Skip to content

Commit

Permalink
Merge pull request qemu#48 from yongbok/i6400-mips64r6-PRIP4
Browse files Browse the repository at this point in the history
target-mips: R6 Multi-threading

Updates qemu#17

Signed-off-by: Yongbok Kim yongbok.kim@imgtec.com
  • Loading branch information
yongbok committed Mar 3, 2015
2 parents e5c038d + d63062b commit 7e9e1db
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 1 deletion.
4 changes: 4 additions & 0 deletions disas/mips.c
Original file line number Diff line number Diff line change
Expand Up @@ -1404,6 +1404,10 @@ const struct mips_opcode mips_builtin_opcodes[] =
{"cmp.sor.d", "D,S,T", 0x46a00019, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6},
{"cmp.sune.d", "D,S,T", 0x46a0001a, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6},
{"cmp.sne.d", "D,S,T", 0x46a0001b, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6},
{"dvp", "", 0x41600024, 0xffffffff, TRAP, 0, I32R6},
{"dvp", "t", 0x41600024, 0xffe0ffff, TRAP|WR_t, 0, I32R6},
{"evp", "", 0x41600004, 0xffffffff, TRAP, 0, I32R6},
{"evp", "t", 0x41600004, 0xffe0ffff, TRAP|WR_t, 0, I32R6},

/* MSA */
{"sll.b", "+d,+e,+f", 0x7800000d, 0xffe0003f, WR_VD|RD_VS|RD_VT, 0, MSA},
Expand Down
8 changes: 8 additions & 0 deletions target-mips/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,14 @@ static bool mips_cpu_has_work(CPUState *cs)
has_work = false;
}
}
if (env->CP0_Config5 & (1 << CP0C5_VP)) {
if (cs->interrupt_request & CPU_INTERRUPT_WAKE) {
has_work = true;
}
if (!mips_vp_active(env)) {
has_work = false;
}
}
return has_work;
}

Expand Down
19 changes: 19 additions & 0 deletions target-mips/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,8 @@ struct CPUMIPSState {

int32_t CP0_Index;
/* CP0_MVP* are per MVP registers. */
int32_t CP0_VPControl;
#define CP0VPCtl_DIS 0
int32_t CP0_Random;
int32_t CP0_VPEControl;
#define CP0VPECo_YSI 21
Expand Down Expand Up @@ -298,6 +300,8 @@ struct CPUMIPSState {
# define CP0EnLo_RI 31
# define CP0EnLo_XI 30
#endif
int32_t CP0_GlobalNumer;
#define CP0GN_VPId 0
target_ulong CP0_Context;
target_ulong CP0_KScratch[MIPS_KSCRATCH_NUM];
int32_t CP0_PageMask;
Expand Down Expand Up @@ -502,6 +506,7 @@ struct CPUMIPSState {
#define CP0C5_MSAEn 27
#define CP0C5_UFE 9
#define CP0C5_FRE 8
#define CP0C5_VP 7
#define CP0C5_SBRI 6
#define CP0C5_MVH 5
#define CP0C5_LLB 4
Expand Down Expand Up @@ -879,6 +884,20 @@ static inline int mips_vpe_active(CPUMIPSState *env)
return active;
}

static inline int mips_vp_active(CPUMIPSState *env)
{
CPUState *other_cs = first_cpu;

CPU_FOREACH(other_cs) {
MIPSCPU *other_cpu = MIPS_CPU(other_cs);
if ((&other_cpu->env != env) &&
((other_cpu->env.CP0_VPControl >> CP0VPCtl_DIS) &1)) {
return 0;
}
}
return 1;
}

#include "exec/exec-all.h"

static inline void compute_hflags(CPUMIPSState *env)
Expand Down
4 changes: 4 additions & 0 deletions target-mips/helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,10 @@ DEF_HELPER_0(dmt, tl)
DEF_HELPER_0(emt, tl)
DEF_HELPER_1(dvpe, tl, env)
DEF_HELPER_1(evpe, tl, env)

/* R6 Multi-threading */
DEF_HELPER_1(dvp, tl, env)
DEF_HELPER_1(evp, tl, env)
#endif /* !CONFIG_USER_ONLY */

/* microMIPS functions */
Expand Down
47 changes: 47 additions & 0 deletions target-mips/op_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,14 @@ static bool mips_vpe_is_wfi(MIPSCPU *c)
return cpu->halted && mips_vpe_active(env);
}

static bool mips_vp_is_wfi(MIPSCPU *c)
{
CPUState *cpu = CPU(c);
CPUMIPSState *env = &c->env;

return cpu->halted && mips_vp_active(env);
}

static inline void mips_vpe_wake(MIPSCPU *c)
{
/* Dont set ->halted = 0 directly, let it be done via cpu_has_work
Expand Down Expand Up @@ -1940,6 +1948,45 @@ target_ulong helper_evpe(CPUMIPSState *env)
}
return prev;
}

target_ulong helper_dvp(CPUMIPSState *env)
{
CPUState *other_cs = first_cpu;
target_ulong prev = env->CP0_VPControl;

if (!((env->CP0_VPControl >> CP0VPCtl_DIS) &1)) {
CPU_FOREACH(other_cs) {
MIPSCPU *other_cpu = MIPS_CPU(other_cs);
/* Turn off all VPs except the one executing the dvp. */
if (&other_cpu->env != env) {
mips_vpe_sleep(other_cpu);
}
}
env->CP0_VPControl |= (1 << CP0VPCtl_DIS);
}
return prev;
}

target_ulong helper_evp(CPUMIPSState *env)
{
CPUState *other_cs = first_cpu;
target_ulong prev = env->CP0_VPControl;

if (((env->CP0_VPControl >> CP0VPCtl_DIS) &1)) {
CPU_FOREACH(other_cs) {
MIPSCPU *other_cpu = MIPS_CPU(other_cs);

if (&other_cpu->env != env
/* If the VP is WFI, don't disturb its sleep. */
&& !mips_vp_is_wfi(other_cpu)) {
/* Enable the VP. */
mips_vpe_wake(other_cpu); /* And wake it up. */
}
}
env->CP0_VPControl &= ~(1 << CP0VPCtl_DIS);
}
return prev;
}
#endif /* !CONFIG_USER_ONLY */

void helper_fork(target_ulong arg1, target_ulong arg2)
Expand Down
59 changes: 59 additions & 0 deletions target-mips/translate.c
Original file line number Diff line number Diff line change
Expand Up @@ -893,6 +893,8 @@ enum {
OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
};

/* Coprocessor 0 (with rs == C0) */
Expand Down Expand Up @@ -1431,6 +1433,7 @@ typedef struct DisasContext {
bool pw;
bool llb;
bool ps;
bool vp;
} DisasContext;

enum {
Expand Down Expand Up @@ -5146,6 +5149,11 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
gen_helper_mfc0_mvpconf1(arg, cpu_env);
rn = "MVPConf1";
break;
case 4:
CP0_CHECK(ctx->vp);
gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
rn = "VPcontrol";
break;
default:
goto cp0_unimplemented;
}
Expand Down Expand Up @@ -5267,6 +5275,11 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
tcg_gen_ext32s_tl(arg, arg);
rn = "EntryLo1";
break;
case 1:
CP0_CHECK(ctx->vp);
gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumer));
rn = "GlobalNumber";
break;
default:
goto cp0_unimplemented;
}
Expand Down Expand Up @@ -5808,6 +5821,11 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
/* ignored */
rn = "MVPConf1";
break;
case 4:
CP0_CHECK(ctx->vp);
/* ignored */
rn = "VPControl";
break;
default:
goto cp0_unimplemented;
}
Expand Down Expand Up @@ -5908,6 +5926,11 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
gen_helper_mtc0_entrylo1(cpu_env, arg);
rn = "EntryLo1";
break;
case 1:
CP0_CHECK(ctx->vp);
/* ignored */
rn = "GlobalNumber";
break;
default:
goto cp0_unimplemented;
}
Expand Down Expand Up @@ -6472,6 +6495,11 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
gen_helper_mfc0_mvpconf1(arg, cpu_env);
rn = "MVPConf1";
break;
case 4:
CP0_CHECK(ctx->vp);
gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
rn = "VPcontrol";
break;
default:
goto cp0_unimplemented;
}
Expand Down Expand Up @@ -6573,6 +6601,11 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
rn = "EntryLo1";
break;
case 1:
CP0_CHECK(ctx->vp);
gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumer));
rn = "GlobalNumber";
break;
default:
goto cp0_unimplemented;
}
Expand Down Expand Up @@ -7105,6 +7138,11 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
/* ignored */
rn = "MVPConf1";
break;
case 4:
CP0_CHECK(ctx->vp);
/* ignored */
rn = "VPcontrol";
break;
default:
goto cp0_unimplemented;
}
Expand Down Expand Up @@ -7205,6 +7243,11 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
gen_helper_dmtc0_entrylo1(cpu_env, arg);
rn = "EntryLo1";
break;
case 1:
CP0_CHECK(ctx->vp);
/* ignored */
rn = "GlobalNumber";
break;
default:
goto cp0_unimplemented;
}
Expand Down Expand Up @@ -19030,6 +19073,20 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
gen_helper_evpe(t0, cpu_env);
gen_store_gpr(t0, rt);
break;
case OPC_DVP:
check_insn(ctx, ISA_MIPS32R6);
if (ctx->vp) {
gen_helper_dvp(t0, cpu_env);
gen_store_gpr(t0, rt);
}
break;
case OPC_EVP:
check_insn(ctx, ISA_MIPS32R6);
if (ctx->vp) {
gen_helper_evp(t0, cpu_env);
gen_store_gpr(t0, rt);
}
break;
case OPC_DI:
check_insn(ctx, ISA_MIPS32R2);
save_cpu_state(ctx, 1);
Expand Down Expand Up @@ -19563,6 +19620,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
ctx.ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
ctx.ps = (env->active_fpu.fcr0 >> FCR0_PS) & 1;
ctx.vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
restore_cpu_state(env, &ctx);
#ifdef CONFIG_USER_ONLY
ctx.mem_idx = MIPS_HFLAG_UM;
Expand Down Expand Up @@ -20001,6 +20059,7 @@ void cpu_state_reset(CPUMIPSState *env)
env->CP0_Random = env->tlb->nb_tlb - 1;
env->tlb->tlb_in_use = env->tlb->nb_tlb;
env->CP0_Wired = 0;
env->CP0_GlobalNumer = (cs->cpu_index & 0x0F) << CP0GN_VPId;
env->CP0_EBase = (cs->cpu_index & 0x3FF);
if (kvm_enabled()) {
env->CP0_EBase |= 0x40000000;
Expand Down
2 changes: 1 addition & 1 deletion target-mips/translate_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,7 @@ static const mips_def_t mips_defs[] =
(1 << CP0C3_RXI) | (1 << CP0C3_LPA),
.CP0_Config4 = MIPS_CONFIG4 | (0xfc << CP0C4_KScrExist) |
(3 << CP0C4_IE) | (1U << CP0C4_M),
.CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_LLB),
.CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_VP) | (1 << CP0C5_LLB),
.CP0_Config5_rw_bitmask = (1 << CP0C5_MSAEn) | (1 << CP0C5_SBRI) |
(1 << CP0C5_FRE) | (1 << CP0C5_UFE),
.CP0_LLAddr_rw_bitmask = 0,
Expand Down

0 comments on commit 7e9e1db

Please sign in to comment.