From: James Hogan <james.hogan@imgtec.com>
To: Leon Alrae <leon.alrae@imgtec.com>, qemu-devel@nongnu.org
Cc: aurelien@aurel32.net
Subject: Re: [Qemu-devel] [PATCH 4/7] target-mips: add MTHC0 and MFHC0 instructions
Date: Tue, 28 Apr 2015 16:52:19 +0100 [thread overview]
Message-ID: <553FACB3.2030603@imgtec.com> (raw)
In-Reply-To: <1430224874-18513-5-git-send-email-leon.alrae@imgtec.com>
[-- Attachment #1: Type: text/plain, Size: 11290 bytes --]
Hi Leon,
On 28/04/15 13:41, Leon Alrae wrote:
> Implement MTHC0 and MFHC0 instructions. In MIPS32 they allow to access
> upper word of extended to 64-bits CP0 registers.
>
> In MIPS64, when CP0 destination register specified is the EntryLo0 or
> EntryLo1, bits 1:0 of the GPR appear at bits 31:30 of EntryLo0 or
> EntryLo1. This is to compensate for RI and XI, which were shifted to bits
> 63:62 by MTC0 to EntryLo0 or EntryLo1. Therefore creating separate
> functions generating for EntryLo0 and EntryLo1.
>
> Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
> ---
> disas/mips.c | 2 +
> target-mips/cpu.h | 1 +
> target-mips/translate.c | 216 ++++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 219 insertions(+)
>
> diff --git a/disas/mips.c b/disas/mips.c
> index 1afe0c5..c236495 100644
> --- a/disas/mips.c
> +++ b/disas/mips.c
> @@ -2238,6 +2238,8 @@ const struct mips_opcode mips_builtin_opcodes[] =
> {"ceil.l.s", "D,S", 0x4600000a, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I3|I33 },
> {"ceil.w.d", "D,S", 0x4620000e, 0xffff003f, WR_D|RD_S|FP_S|FP_D, 0, I2 },
> {"ceil.w.s", "D,S", 0x4600000e, 0xffff003f, WR_D|RD_S|FP_S, 0, I2 },
> +{"mfhc0", "t,G,H", 0x40400000, 0xffe007f8, LCD|WR_t|RD_C0, 0, I33 },
> +{"mthc0", "t,G,H", 0x40c00000, 0xffe007f8, COD|RD_t|WR_C0|WR_CC, 0, I33 },
whitespace appears to be inconsistent here (the context uses tabs).
> {"cfc0", "t,G", 0x40400000, 0xffe007ff, LCD|WR_t|RD_C0, 0, I1 },
> {"cfc1", "t,G", 0x44400000, 0xffe007ff, LCD|WR_t|RD_C1|FP_S, 0, I1 },
> {"cfc1", "t,S", 0x44400000, 0xffe007ff, LCD|WR_t|RD_C1|FP_S, 0, I1 },
> diff --git a/target-mips/cpu.h b/target-mips/cpu.h
> index bcd1e2b..cfc6ac7 100644
> --- a/target-mips/cpu.h
> +++ b/target-mips/cpu.h
> @@ -473,6 +473,7 @@ struct CPUMIPSState {
> #define CP0C5_UFE 9
> #define CP0C5_FRE 8
> #define CP0C5_SBRI 6
> +#define CP0C5_MVH 5
> #define CP0C5_UFR 2
> #define CP0C5_NFExists 0
> int32_t CP0_Config6;
> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index bb219ea..f95b655 100644
> --- a/target-mips/translate.c
> +++ b/target-mips/translate.c
> @@ -868,8 +868,10 @@ enum {
> enum {
> OPC_MFC0 = (0x00 << 21) | OPC_CP0,
> OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
> + OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
> OPC_MTC0 = (0x04 << 21) | OPC_CP0,
> OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
> + OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
> OPC_MFTR = (0x08 << 21) | OPC_CP0,
> OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
> OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
> @@ -1423,6 +1425,8 @@ typedef struct DisasContext {
> int ie;
> bool bi;
> bool bp;
> + uint64_t PAMask;
> + bool mvh;
> } DisasContext;
>
> enum {
> @@ -1769,6 +1773,13 @@ static inline void check_cp1_registers(DisasContext *ctx, int regs)
> This is enabled by CP0 Status register MX(24) bit.
> */
>
> +static inline void check_mvh(DisasContext *ctx)
> +{
> + if (unlikely(!(ctx->mvh))) {
superfluous brackets around ctx->mvh.
> + generate_exception(ctx, EXCP_RI);
> + }
> +}
> +
> static inline void check_dsp(DisasContext *ctx)
> {
> if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
> @@ -4820,6 +4831,60 @@ static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
>
> #ifndef CONFIG_USER_ONLY
> /* CP0 (MMU and control) */
> +static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
> +{
> + TCGv_i64 t0 = tcg_temp_new_i64();
> + TCGv_i64 t1 = tcg_temp_new_i64();
> +
> + tcg_gen_ext_tl_i64(t0, arg);
> + tcg_gen_ld_i64(t1, cpu_env, off);
> +#if defined(TARGET_MIPS64)
> + tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
> +#else
> + tcg_gen_concat32_i64(t1, t1, t0);
I don't get what this case is about. what's wrong with the above case
for MIPS64 and MIPS32?
> +#endif
> + tcg_gen_st_i64(t1, cpu_env, off);
> + tcg_temp_free_i64(t1);
> + tcg_temp_free_i64(t0);
> +}
> +
> +static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
> +{
> + TCGv_i64 t0 = tcg_temp_new_i64();
> + TCGv_i64 t1 = tcg_temp_new_i64();
> +
> + tcg_gen_ext_tl_i64(t0, arg);
> + tcg_gen_ld_i64(t1, cpu_env, off);
> + tcg_gen_concat32_i64(t1, t1, t0);
> + tcg_gen_st_i64(t1, cpu_env, off);
> + tcg_temp_free_i64(t1);
> + tcg_temp_free_i64(t0);
simpler to just store a 32-bit value (st32_tl) to the appropriate half,
depending on host endianness? (i.e. +4 if little endian)
> +}
> +
> +static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
> +{
> + TCGv_i64 t0 = tcg_temp_new_i64();
> +
> + tcg_gen_ld_i64(t0, cpu_env, off);
> +#if defined(TARGET_MIPS64)
> + tcg_gen_shri_i64(t0, t0, 30);
need to mask off the xi/ri bits?
> +#else
> + tcg_gen_shri_i64(t0, t0, 32);
Again, I'm not convinced MIPS32 needs special handling here.
> +#endif
> + tcg_gen_trunc_i64_tl(arg, t0);
> + tcg_temp_free_i64(t0);
> +}
> +
> +static inline void gen_mfhc0_load64(TCGv arg, target_ulong off)
> +{
> + TCGv_i64 t0 = tcg_temp_new_i64();
> +
> + tcg_gen_ld_i64(t0, cpu_env, off);
> + tcg_gen_shri_i64(t0, t0, 32);
simpler to just load a signed 32-bit value (ld32s_tl) from the
appropriate half, depending on host endianness? (i.e. +4 if little endian)
> + tcg_gen_trunc_i64_tl(arg, t0);
> + tcg_temp_free_i64(t0);
> +}
> +
> static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
> {
> TCGv_i32 t0 = tcg_temp_new_i32();
> @@ -4850,6 +4915,134 @@ static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
> tcg_gen_st_tl(arg, cpu_env, off);
> }
>
> +static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
> +{
> + const char *rn = "invalid";
> +
> + if (!(ctx->hflags & MIPS_HFLAG_ELPA)) {
worth reusing the CP0_CHECK stuff?
> + goto mfhc0_read_zero;
> + }
> +
> + switch (reg) {
> + case 2:
> + switch (sel) {
> + case 0:
> + gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
> + rn = "EntryLo0";
> + break;
> + default:
> + goto mfhc0_read_zero;
> + }
> + break;
> + case 3:
> + switch (sel) {
> + case 0:
> + gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
> + rn = "EntryLo1";
> + break;
> + default:
> + goto mfhc0_read_zero;
> + }
> + break;
> + case 17:
> + switch (sel) {
> + case 0:
> + gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr));
> + rn = "LLAddr";
> + break;
> + default:
> + goto mfhc0_read_zero;
> + }
> + break;
> + case 28:
> + switch (sel) {
> + case 0:
> + case 2:
> + case 4:
> + case 6:
> + gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo));
> + rn = "TagLo";
> + break;
> + default:
> + goto mfhc0_read_zero;
> + }
> + break;
> + default:
> + goto mfhc0_read_zero;
> + }
> +
> + (void)rn; /* avoid a compiler warning */
> + LOG_DISAS("mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
> + return;
> +
> +mfhc0_read_zero:
> + LOG_DISAS("mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
> + tcg_gen_movi_tl(arg, 0);
> +}
> +
> +static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
> +{
> + const char *rn = "invalid";
> +
> + if (!(ctx->hflags & MIPS_HFLAG_ELPA)) {
> + goto mthc0_nop;
> + }
> +
> + tcg_gen_andi_tl(arg, arg, ctx->PAMask >> 36);
Shouldn't this depend on the register? LLAddr shift varies per core
(CP0_LLAddr_shift), but EntryLo shift will be the same for each core.
Cheers
James
> +
> + switch (reg) {
> + case 2:
> + switch (sel) {
> + case 0:
> + gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
> + rn = "EntryLo0";
> + break;
> + default:
> + goto mthc0_nop;
> + }
> + break;
> + case 3:
> + switch (sel) {
> + case 0:
> + gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
> + rn = "EntryLo1";
> + break;
> + default:
> + goto mthc0_nop;
> + }
> + break;
> + case 17:
> + switch (sel) {
> + case 0:
> + gen_mthc0_store64(arg, offsetof(CPUMIPSState, lladdr));
> + rn = "LLAddr";
> + break;
> + default:
> + goto mthc0_nop;
> + }
> + break;
> + case 28:
> + switch (sel) {
> + case 0:
> + case 2:
> + case 4:
> + case 6:
> + gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
> + rn = "TagLo";
> + break;
> + default:
> + goto mthc0_nop;
> + }
> + break;
> + default:
> + goto mthc0_nop;
> + }
> +
> + (void)rn; /* avoid a compiler warning */
> +mthc0_nop:
> + LOG_DISAS("mthc0 %s (reg %d sel %d)\n", rn, reg, sel);
> +}
> +
> static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
> {
> if (ctx->insn_flags & ISA_MIPS32R6) {
> @@ -7847,6 +8040,25 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt,
> opn = "dmtc0";
> break;
> #endif
> + case OPC_MFHC0:
> + check_mvh(ctx);
> + if (rt == 0) {
> + /* Treat as NOP. */
> + return;
> + }
> + gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
> + opn = "mfhc0";
> + break;
> + case OPC_MTHC0:
> + check_mvh(ctx);
> + {
> + TCGv t0 = tcg_temp_new();
> + gen_load_gpr(t0, rt);
> + gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
> + tcg_temp_free(t0);
> + }
> + opn = "mthc0";
> + break;
> case OPC_MFTR:
> check_insn(ctx, ASE_MT);
> if (rd == 0) {
> @@ -18571,6 +18783,8 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
> case OPC_MTC0:
> case OPC_MFTR:
> case OPC_MTTR:
> + case OPC_MFHC0:
> + case OPC_MTHC0:
> #if defined(TARGET_MIPS64)
> case OPC_DMFC0:
> case OPC_DMTC0:
> @@ -19141,6 +19355,8 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
> ctx.ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
> ctx.bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
> ctx.bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
> + ctx.mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
> + ctx.PAMask = env->PAMask;
> /* Restore delay slot state from the tb context. */
> ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
> ctx.ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
>
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
next prev parent reply other threads:[~2015-04-28 15:52 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-04-28 12:41 [Qemu-devel] [PATCH 0/7] target-mips: add support for large physical addresses Leon Alrae
2015-04-28 12:41 ` [Qemu-devel] [PATCH 1/7] target-mips: extend selected CP0 registers to 64-bits in MIPS32 Leon Alrae
2015-04-28 12:41 ` [Qemu-devel] [PATCH 2/7] target-mips: support Page Frame Number Extension field Leon Alrae
2015-04-28 13:35 ` James Hogan
2015-04-28 13:47 ` James Hogan
2015-04-28 15:59 ` Leon Alrae
2015-04-28 21:39 ` James Hogan
2015-04-29 15:31 ` Leon Alrae
2015-04-28 12:41 ` [Qemu-devel] [PATCH 3/7] target-mips: add CP0.PageGrain.ELPA support Leon Alrae
2015-04-28 15:08 ` James Hogan
2015-04-29 11:35 ` Leon Alrae
2015-04-28 12:41 ` [Qemu-devel] [PATCH 4/7] target-mips: add MTHC0 and MFHC0 instructions Leon Alrae
2015-04-28 15:52 ` James Hogan [this message]
2015-04-29 14:26 ` Leon Alrae
2015-04-28 12:41 ` [Qemu-devel] [PATCH 5/7] target-mips: correct MFC0 for CP0.EntryLo in MIPS64 Leon Alrae
2015-04-28 12:41 ` [Qemu-devel] [PATCH 6/7] target-mips: remove invalid comments in translate_init.c Leon Alrae
2015-04-28 21:50 ` James Hogan
2015-04-28 12:41 ` [Qemu-devel] [PATCH 7/7] target-mips: enable XPA and LPA features Leon Alrae
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=553FACB3.2030603@imgtec.com \
--to=james.hogan@imgtec.com \
--cc=aurelien@aurel32.net \
--cc=leon.alrae@imgtec.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.