diff mbox

[v2,13/15] target-mips: microMIPS32 R6 Major instructions

Message ID 1434731138-4918-14-git-send-email-yongbok.kim@imgtec.com
State New
Headers show

Commit Message

Yongbok Kim June 19, 2015, 4:25 p.m. UTC
add new microMIPS32 Release 6 Major opcode instructions

Signed-off-by: Yongbok Kim <yongbok.kim@imgtec.com>
---
 target-mips/translate.c |   62 ++++++++++++++++++++++++++++++++++-------------
 1 files changed, 45 insertions(+), 17 deletions(-)

Comments

Leon Alrae June 22, 2015, 12:19 p.m. UTC | #1
On 19/06/2015 17:25, Yongbok Kim wrote:
> @@ -14958,8 +14966,28 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
>      do_cop1:
>          gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
>          break;
> -    case ADDIUPC:
> -        {
> +    case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
> +        if (ctx->insn_flags & ISA_MIPS32R6) {
> +            /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
> +            switch ((ctx->opcode >> 16) & 0x1f) {
> +            case ADDIUPC_00 ... ADDIUPC_07:
> +                gen_pcrel(ctx, OPC_ADDIUPC, ctx->pc & ~0x3, rt);
> +                break;
> +            case AUIPC:
> +                gen_pcrel(ctx, OPC_AUIPC, ctx->pc, rt);

According to the manual you should pass "ctx->pc & ~0x3" here. Otherwise the
patch looks good to me.

Leon
Yongbok Kim June 23, 2015, 9:08 a.m. UTC | #2
On 22/06/2015 13:19, Leon Alrae wrote:
> On 19/06/2015 17:25, Yongbok Kim wrote:
>> @@ -14958,8 +14966,28 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
>>      do_cop1:
>>          gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
>>          break;
>> -    case ADDIUPC:
>> -        {
>> +    case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
>> +        if (ctx->insn_flags & ISA_MIPS32R6) {
>> +            /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
>> +            switch ((ctx->opcode >> 16) & 0x1f) {
>> +            case ADDIUPC_00 ... ADDIUPC_07:
>> +                gen_pcrel(ctx, OPC_ADDIUPC, ctx->pc & ~0x3, rt);
>> +                break;
>> +            case AUIPC:
>> +                gen_pcrel(ctx, OPC_AUIPC, ctx->pc, rt);
> 
> According to the manual you should pass "ctx->pc & ~0x3" here. Otherwise the
> patch looks good to me.
> 
> Leon
> 

That's weird to see that in the doc. I've checked the instruction and it
has been confirmed that the instruction is *not* clearing the bottom 2 bits
of the PC. This issue will be corrected in the next doc release.

Regards,
Yongbok
diff mbox

Patch

diff --git a/target-mips/translate.c b/target-mips/translate.c
index 54c14b6..9483d31 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -3208,45 +3208,46 @@  static inline void gen_r6_ld(target_long addr, int reg, int memidx,
     tcg_temp_free(t0);
 }
 
-static inline void gen_pcrel(DisasContext *ctx, int rs, int16_t imm)
+static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
+                             int rs)
 {
     target_long offset;
     target_long addr;
 
-    switch (MASK_OPC_PCREL_TOP2BITS(ctx->opcode)) {
+    switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
     case OPC_ADDIUPC:
         if (rs != 0) {
             offset = sextract32(ctx->opcode << 2, 0, 21);
-            addr = addr_add(ctx, ctx->pc, offset);
+            addr = addr_add(ctx, pc, offset);
             tcg_gen_movi_tl(cpu_gpr[rs], addr);
         }
         break;
     case R6_OPC_LWPC:
         offset = sextract32(ctx->opcode << 2, 0, 21);
-        addr = addr_add(ctx, ctx->pc, offset);
+        addr = addr_add(ctx, pc, offset);
         gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
         break;
 #if defined(TARGET_MIPS64)
     case OPC_LWUPC:
         check_mips_64(ctx);
         offset = sextract32(ctx->opcode << 2, 0, 21);
-        addr = addr_add(ctx, ctx->pc, offset);
+        addr = addr_add(ctx, pc, offset);
         gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
         break;
 #endif
     default:
-        switch (MASK_OPC_PCREL_TOP5BITS(ctx->opcode)) {
+        switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
         case OPC_AUIPC:
             if (rs != 0) {
-                offset = imm << 16;
-                addr = addr_add(ctx, ctx->pc, offset);
+                offset = sextract32(ctx->opcode, 0, 16) << 16;
+                addr = addr_add(ctx, pc, offset);
                 tcg_gen_movi_tl(cpu_gpr[rs], addr);
             }
             break;
         case OPC_ALUIPC:
             if (rs != 0) {
-                offset = imm << 16;
-                addr = ~0xFFFF & addr_add(ctx, ctx->pc, offset);
+                offset = sextract32(ctx->opcode, 0, 16) << 16;
+                addr = ~0xFFFF & addr_add(ctx, pc, offset);
                 tcg_gen_movi_tl(cpu_gpr[rs], addr);
             }
             break;
@@ -3257,7 +3258,7 @@  static inline void gen_pcrel(DisasContext *ctx, int rs, int16_t imm)
         case R6_OPC_LDPC + (3 << 16):
             check_mips_64(ctx);
             offset = sextract32(ctx->opcode << 3, 0, 21);
-            addr = addr_add(ctx, (ctx->pc & ~0x7), offset);
+            addr = addr_add(ctx, (pc & ~0x7), offset);
             gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
             break;
 #endif
@@ -14827,9 +14828,16 @@  static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
             break;
         }
         break;
-    case ADDI32:
-        mips32_op = OPC_ADDI;
-        goto do_addi;
+    case ADDI32: /* AUI, LUI */
+        if (ctx->insn_flags & ISA_MIPS32R6) {
+            /* AUI, LUI */
+            gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
+        } else {
+            /* ADDI32 */
+            mips32_op = OPC_ADDI;
+            goto do_addi;
+        }
+        break;
     case ADDIU32:
         mips32_op = OPC_ADDIU;
     do_addi:
@@ -14958,8 +14966,28 @@  static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
     do_cop1:
         gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
         break;
-    case ADDIUPC:
-        {
+    case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
+        if (ctx->insn_flags & ISA_MIPS32R6) {
+            /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
+            switch ((ctx->opcode >> 16) & 0x1f) {
+            case ADDIUPC_00 ... ADDIUPC_07:
+                gen_pcrel(ctx, OPC_ADDIUPC, ctx->pc & ~0x3, rt);
+                break;
+            case AUIPC:
+                gen_pcrel(ctx, OPC_AUIPC, ctx->pc, rt);
+                break;
+            case ALUIPC:
+                gen_pcrel(ctx, OPC_ALUIPC, ctx->pc, rt);
+                break;
+            case LWPC_08 ... LWPC_0F:
+                gen_pcrel(ctx, R6_OPC_LWPC, ctx->pc & ~0x3, rt);
+                break;
+            default:
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+        } else {
+            /* ADDIUPC */
             int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
             int offset = SIMM(ctx->opcode, 0, 23) << 2;
 
@@ -19976,7 +20004,7 @@  static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
         break;
     case OPC_PCREL:
         check_insn(ctx, ISA_MIPS32R6);
-        gen_pcrel(ctx, rs, imm);
+        gen_pcrel(ctx, ctx->opcode, ctx->pc, rs);
         break;
     default:            /* Invalid */
         MIPS_INVAL("major opcode");