diff mbox

[v14,22/33] target-tilegx: Implement system and memory management instructions

Message ID 1440433079-14458-23-git-send-email-rth@twiddle.net
State New
Headers show

Commit Message

Richard Henderson Aug. 24, 2015, 4:17 p.m. UTC
Most of which are either nops or exceptions.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-tilegx/translate.c | 94 ++++++++++++++++++++++++++++++++++-------------
 1 file changed, 68 insertions(+), 26 deletions(-)

Comments

Peter Maydell Aug. 29, 2015, 9:21 p.m. UTC | #1
On 24 August 2015 at 17:17, Richard Henderson <rth@twiddle.net> wrote:
> Most of which are either nops or exceptions.
>
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
>  target-tilegx/translate.c | 94 ++++++++++++++++++++++++++++++++++-------------
>  1 file changed, 68 insertions(+), 26 deletions(-)
>
> diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c
> index ea68902..5bdc8be 100644
> --- a/target-tilegx/translate.c
> +++ b/target-tilegx/translate.c
> @@ -241,27 +241,82 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext,
>      TCGv tdest, tsrca;
>      const char *mnemonic;
>      TCGMemOp memop;
> +    TileExcp ret = TILEGX_EXCP_NONE;
>
> -    /* Eliminate nops and jumps before doing anything else.  */
> +    /* Eliminate instructions with no output before doing anything else.  */
>      switch (opext) {
>      case OE_RR_Y0(NOP):
>      case OE_RR_Y1(NOP):
>      case OE_RR_X0(NOP):
>      case OE_RR_X1(NOP):
>          mnemonic = "nop";
> -        goto do_nop;
> +        goto done0;
>      case OE_RR_Y0(FNOP):
>      case OE_RR_Y1(FNOP):
>      case OE_RR_X0(FNOP):
>      case OE_RR_X1(FNOP):
>          mnemonic = "fnop";
> -    do_nop:
> -        if (srca || dest) {
> -            return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
> +        goto done0;
> +    case OE_RR_X1(DRAIN):
> +        mnemonic = "drain";
> +        goto done0;
> +    case OE_RR_X1(FLUSHWB):
> +        mnemonic = "flushwb";
> +        goto done0;
> +    case OE_RR_X1(ILL):
> +    case OE_RR_Y1(ILL):
> +        ret = TILEGX_EXCP_OPCODE_UNKNOWN;
> +        mnemonic = (dest == 0x1c && srca == 0x25 ? "bpt" : "ill");
> +        goto done0;
> +    case OE_RR_X1(MF):
> +        mnemonic = "mf";
> +        goto done0;
> +    case OE_RR_X1(NAP):
> +        /* ??? This should yield, especially in system mode.  */
> +        mnemonic = "nap";
> +        goto done0;
> +    case OE_RR_X1(SWINT0):
> +        ret = TILEGX_EXCP_OPCODE_UNKNOWN;
> +        mnemonic = "swint0";
> +        goto done0;
> +    case OE_RR_X1(SWINT1):
> +        ret = TILEGX_EXCP_SYSCALL;
> +        mnemonic = "swint1";
> +        goto done0;
> +    case OE_RR_X1(SWINT2):
> +        ret = TILEGX_EXCP_OPCODE_UNKNOWN;
> +        mnemonic = "swint2";
> +        goto done0;
> +    case OE_RR_X1(SWINT3):
> +        ret = TILEGX_EXCP_OPCODE_UNKNOWN;
> +        mnemonic = "swint3";
> +        goto done0;
> +    done0:

goto to immediately following label ?

> +        if ((srca || dest) && ret == TILEGX_EXCP_NONE) {
> +            ret = TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
>          }
>          qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s", mnemonic);
> -        return TILEGX_EXCP_NONE;
> +        return ret;
>
> +    case OE_RR_X1(DTLBPR):
> +        ret = TILEGX_EXCP_OPCODE_UNKNOWN;
> +        mnemonic = "dtlbpr";
> +        goto done1;
> +    case OE_RR_X1(FINV):
> +        mnemonic = "finv";
> +        goto done1;
> +    case OE_RR_X1(FLUSH):
> +        mnemonic = "flush";
> +        goto done1;
> +    case OE_RR_X1(ICOH):
> +        mnemonic = "icoh";
> +        goto done1;
> +    case OE_RR_X1(INV):
> +        mnemonic = "inv";
> +        goto done1;
> +    case OE_RR_X1(WH64):
> +        mnemonic = "wh64";
> +        goto done1;
>      case OE_RR_X1(JRP):
>      case OE_RR_Y1(JRP):
>          mnemonic = "jrp";
> @@ -284,8 +339,12 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext,
>          dc->jmp.cond = TCG_COND_ALWAYS;
>          dc->jmp.dest = tcg_temp_new();
>          tcg_gen_andi_tl(dc->jmp.dest, load_gr(dc, srca), ~7);

Should this really fall through into the added check ?

> +    done1:
> +        if (dest && ret == TILEGX_EXCP_NONE) {
> +            ret = TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
> +        }
>          qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s", mnemonic, reg_names[srca]);
> -        return TILEGX_EXCP_NONE;
> +        return ret;
>      }
>
>      tdest = dest_gr(dc, dest);
> @@ -302,17 +361,8 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext,
>          gen_helper_cnttz(tdest, tsrca);
>          mnemonic = "cnttz";
>          break;
> -    case OE_RR_X1(DRAIN):
> -    case OE_RR_X1(DTLBPR):
> -    case OE_RR_X1(FINV):
> -    case OE_RR_X1(FLUSHWB):
> -    case OE_RR_X1(FLUSH):
>      case OE_RR_X0(FSINGLE_PACK1):
>      case OE_RR_Y0(FSINGLE_PACK1):
> -    case OE_RR_X1(ICOH):
> -    case OE_RR_X1(ILL):
> -    case OE_RR_Y1(ILL):
> -    case OE_RR_X1(INV):
>      case OE_RR_X1(IRET):
>          return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
>      case OE_RR_X1(LD1S):
> @@ -381,14 +431,11 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext,
>      case OE_RR_X1(LNK):
>      case OE_RR_Y1(LNK):
>          if (srca) {
> -            return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
> +            ret = TILEGX_EXCP_OPCODE_UNIMPLEMENTED;

This code change seems unrelated to the rest of the patch?
Also we'll end up printing the disassembly as "lnk" rather
than whatever we should print for undefined instructions.

>          }
>          tcg_gen_movi_tl(tdest, dc->pc + TILEGX_BUNDLE_SIZE_IN_BYTES);
>          mnemonic = "lnk";
>          break;
> -    case OE_RR_X1(MF):
> -    case OE_RR_X1(NAP):
> -        return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
>      case OE_RR_X0(PCNT):
>      case OE_RR_Y0(PCNT):
>          gen_helper_pcnt(tdest, tsrca);
> @@ -404,10 +451,6 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext,
>          tcg_gen_bswap64_tl(tdest, tsrca);
>          mnemonic = "revbytes";
>          break;
> -    case OE_RR_X1(SWINT0):
> -    case OE_RR_X1(SWINT1):
> -    case OE_RR_X1(SWINT2):
> -    case OE_RR_X1(SWINT3):
>      case OE_RR_X0(TBLIDXB0):
>      case OE_RR_Y0(TBLIDXB0):
>      case OE_RR_X0(TBLIDXB1):
> @@ -416,14 +459,13 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext,
>      case OE_RR_Y0(TBLIDXB2):
>      case OE_RR_X0(TBLIDXB3):
>      case OE_RR_Y0(TBLIDXB3):
> -    case OE_RR_X1(WH64):
>      default:
>          return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
>      }
>
>      qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s, %s", mnemonic,
>                    reg_names[dest], reg_names[srca]);
> -    return TILEGX_EXCP_NONE;
> +    return ret;
>  }
>
>  static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext,

thanks
-- PMM
Richard Henderson Sept. 1, 2015, 5:16 a.m. UTC | #2
On 08/29/2015 02:21 PM, Peter Maydell wrote:
>> +    case OE_RR_X1(SWINT3):
>> +        ret = TILEGX_EXCP_OPCODE_UNKNOWN;
>> +        mnemonic = "swint3";
>> +        goto done0;
>> +    done0:
>
> goto to immediately following label ?

Sometimes nicer than fallthrough when future patches might interpose extra code.

>> @@ -284,8 +339,12 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext,
>>           dc->jmp.cond = TCG_COND_ALWAYS;
>>           dc->jmp.dest = tcg_temp_new();
>>           tcg_gen_andi_tl(dc->jmp.dest, load_gr(dc, srca), ~7);
>
> Should this really fall through into the added check ?
>
>> +    done1:
>> +        if (dest && ret == TILEGX_EXCP_NONE) {
>> +            ret = TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
>> +        }
...
>>       case OE_RR_X1(LNK):
>>       case OE_RR_Y1(LNK):
>>           if (srca) {
>> -            return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
>> +            ret = TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
>
> This code change seems unrelated to the rest of the patch?
> Also we'll end up printing the disassembly as "lnk" rather
> than whatever we should print for undefined instructions.

I'm not really sure what to do with reserved operand fields on this 
architecture.  Raising an exception is what Chen started with, but the encoding 
for brk suggests that they're ignored.

Suggestions?


r~
Peter Maydell Sept. 1, 2015, 8:23 a.m. UTC | #3
On 1 September 2015 at 06:16, Richard Henderson <rth@twiddle.net> wrote:
> I'm not really sure what to do with reserved operand fields on this
> architecture.  Raising an exception is what Chen started with, but the
> encoding for brk suggests that they're ignored.

The ISA says "Implementations are permitted, but not required, to take
an Illegal Instruction interrupt when detecting a nonzero value in an
unused instruction field.".

Raising an exception seems like the best option to me.

The description of 'bpt' suggests that it's just "a particular
pattern we guarantee will always generate an illegal instruction
interrupt", and then the kernel figures out that it was a bpt
in particular by looking at the instruction:

http://lxr.free-electrons.com/source/arch/tile/kernel/traps.c#L212

Similarly for 'raise', handled a little further up in that file.

In QEMU, we probably want to deal with this by having the insns
generate an illegal instruction exception in translate.c and
then examine the instruction at PC in the linux-user/main.c
loop to see if it should be special-cased as 'bpt', etc.

thanks
-- PMM
diff mbox

Patch

diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c
index ea68902..5bdc8be 100644
--- a/target-tilegx/translate.c
+++ b/target-tilegx/translate.c
@@ -241,27 +241,82 @@  static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext,
     TCGv tdest, tsrca;
     const char *mnemonic;
     TCGMemOp memop;
+    TileExcp ret = TILEGX_EXCP_NONE;
 
-    /* Eliminate nops and jumps before doing anything else.  */
+    /* Eliminate instructions with no output before doing anything else.  */
     switch (opext) {
     case OE_RR_Y0(NOP):
     case OE_RR_Y1(NOP):
     case OE_RR_X0(NOP):
     case OE_RR_X1(NOP):
         mnemonic = "nop";
-        goto do_nop;
+        goto done0;
     case OE_RR_Y0(FNOP):
     case OE_RR_Y1(FNOP):
     case OE_RR_X0(FNOP):
     case OE_RR_X1(FNOP):
         mnemonic = "fnop";
-    do_nop:
-        if (srca || dest) {
-            return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
+        goto done0;
+    case OE_RR_X1(DRAIN):
+        mnemonic = "drain";
+        goto done0;
+    case OE_RR_X1(FLUSHWB):
+        mnemonic = "flushwb";
+        goto done0;
+    case OE_RR_X1(ILL):
+    case OE_RR_Y1(ILL):
+        ret = TILEGX_EXCP_OPCODE_UNKNOWN;
+        mnemonic = (dest == 0x1c && srca == 0x25 ? "bpt" : "ill");
+        goto done0;
+    case OE_RR_X1(MF):
+        mnemonic = "mf";
+        goto done0;
+    case OE_RR_X1(NAP):
+        /* ??? This should yield, especially in system mode.  */
+        mnemonic = "nap";
+        goto done0;
+    case OE_RR_X1(SWINT0):
+        ret = TILEGX_EXCP_OPCODE_UNKNOWN;
+        mnemonic = "swint0";
+        goto done0;
+    case OE_RR_X1(SWINT1):
+        ret = TILEGX_EXCP_SYSCALL;
+        mnemonic = "swint1";
+        goto done0;
+    case OE_RR_X1(SWINT2):
+        ret = TILEGX_EXCP_OPCODE_UNKNOWN;
+        mnemonic = "swint2";
+        goto done0;
+    case OE_RR_X1(SWINT3):
+        ret = TILEGX_EXCP_OPCODE_UNKNOWN;
+        mnemonic = "swint3";
+        goto done0;
+    done0:
+        if ((srca || dest) && ret == TILEGX_EXCP_NONE) {
+            ret = TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
         }
         qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s", mnemonic);
-        return TILEGX_EXCP_NONE;
+        return ret;
 
+    case OE_RR_X1(DTLBPR):
+        ret = TILEGX_EXCP_OPCODE_UNKNOWN;
+        mnemonic = "dtlbpr";
+        goto done1;
+    case OE_RR_X1(FINV):
+        mnemonic = "finv";
+        goto done1;
+    case OE_RR_X1(FLUSH):
+        mnemonic = "flush";
+        goto done1;
+    case OE_RR_X1(ICOH):
+        mnemonic = "icoh";
+        goto done1;
+    case OE_RR_X1(INV):
+        mnemonic = "inv";
+        goto done1;
+    case OE_RR_X1(WH64):
+        mnemonic = "wh64";
+        goto done1;
     case OE_RR_X1(JRP):
     case OE_RR_Y1(JRP):
         mnemonic = "jrp";
@@ -284,8 +339,12 @@  static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext,
         dc->jmp.cond = TCG_COND_ALWAYS;
         dc->jmp.dest = tcg_temp_new();
         tcg_gen_andi_tl(dc->jmp.dest, load_gr(dc, srca), ~7);
+    done1:
+        if (dest && ret == TILEGX_EXCP_NONE) {
+            ret = TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
+        }
         qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s", mnemonic, reg_names[srca]);
-        return TILEGX_EXCP_NONE;
+        return ret;
     }
 
     tdest = dest_gr(dc, dest);
@@ -302,17 +361,8 @@  static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext,
         gen_helper_cnttz(tdest, tsrca);
         mnemonic = "cnttz";
         break;
-    case OE_RR_X1(DRAIN):
-    case OE_RR_X1(DTLBPR):
-    case OE_RR_X1(FINV):
-    case OE_RR_X1(FLUSHWB):
-    case OE_RR_X1(FLUSH):
     case OE_RR_X0(FSINGLE_PACK1):
     case OE_RR_Y0(FSINGLE_PACK1):
-    case OE_RR_X1(ICOH):
-    case OE_RR_X1(ILL):
-    case OE_RR_Y1(ILL):
-    case OE_RR_X1(INV):
     case OE_RR_X1(IRET):
         return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
     case OE_RR_X1(LD1S):
@@ -381,14 +431,11 @@  static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext,
     case OE_RR_X1(LNK):
     case OE_RR_Y1(LNK):
         if (srca) {
-            return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
+            ret = TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
         }
         tcg_gen_movi_tl(tdest, dc->pc + TILEGX_BUNDLE_SIZE_IN_BYTES);
         mnemonic = "lnk";
         break;
-    case OE_RR_X1(MF):
-    case OE_RR_X1(NAP):
-        return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
     case OE_RR_X0(PCNT):
     case OE_RR_Y0(PCNT):
         gen_helper_pcnt(tdest, tsrca);
@@ -404,10 +451,6 @@  static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext,
         tcg_gen_bswap64_tl(tdest, tsrca);
         mnemonic = "revbytes";
         break;
-    case OE_RR_X1(SWINT0):
-    case OE_RR_X1(SWINT1):
-    case OE_RR_X1(SWINT2):
-    case OE_RR_X1(SWINT3):
     case OE_RR_X0(TBLIDXB0):
     case OE_RR_Y0(TBLIDXB0):
     case OE_RR_X0(TBLIDXB1):
@@ -416,14 +459,13 @@  static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext,
     case OE_RR_Y0(TBLIDXB2):
     case OE_RR_X0(TBLIDXB3):
     case OE_RR_Y0(TBLIDXB3):
-    case OE_RR_X1(WH64):
     default:
         return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
     }
 
     qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s, %s", mnemonic,
                   reg_names[dest], reg_names[srca]);
-    return TILEGX_EXCP_NONE;
+    return ret;
 }
 
 static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext,