qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
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 --]

  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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).