Re: [Qemu-devel] [PATCH 3/3] target-mips:Support for Cavium specific instructions

2011-08-13 Thread Khansa Butt
On Thu, Aug 4, 2011 at 4:22 PM, Peter Maydell wrote:

> On 5 July 2011 10:19,   wrote:
> > ---
> >  host-utils.c|1 +
> >  target-mips/cpu.h   |7 +
> >  target-mips/helper.h|5 +
> >  target-mips/op_helper.c |   67 +++
> >  target-mips/translate.c |  443
> ++-
> >  5 files changed, 514 insertions(+), 9 deletions(-)
>
> Don't you also need to add support for the new instructions
> to the disassembler in mips-dis.c ?
>
>

The ISA for Cavium Networks Octeon Processor consist of MIPS64r2+Cavium
specific instructions. These are 27 usermode instructions which we
implemented. some of its instructions have some conflicts with mips and
LoongSon instructions. for example Branch on bit clear/set instructions
(these are 4 instructions)  consumes major opcodes of MIPS COP2 instructions
(e.g, LWC2 etc). and V3MULU, VMM0 have same opcode and function fields as
two of Loongson 's Instructions. To detect correct instruction in
disassembling process can I add a CPU specific Flag in DisasContext so that
I can pass this to log_target_disas()/disas.c and set some of top 16 bits in
disassemble_info 's flags. On the basis of which I can pick  correct
instruction in print_insn_mips()/mips-dis.c. In future this Flag can be used
for other vendor specific instruction as well.

Please guide me in this regard. If I make a separate print function for
Cavium, this will not suitable for me as Cavium includes all instructions in
MIPS64r2 so there will be lot of repetition.

Thanks.


Re: [Qemu-devel] [PATCH 3/3] target-mips:Support for Cavium specific instructions

2011-08-04 Thread Peter Maydell
On 5 July 2011 10:19,   wrote:
> ---
>  host-utils.c            |    1 +
>  target-mips/cpu.h       |    7 +
>  target-mips/helper.h    |    5 +
>  target-mips/op_helper.c |   67 +++
>  target-mips/translate.c |  443 
> ++-
>  5 files changed, 514 insertions(+), 9 deletions(-)

Don't you also need to add support for the new instructions
to the disassembler in mips-dis.c ?

> diff --git a/host-utils.c b/host-utils.c
> index dc96123..1128698 100644
> --- a/host-utils.c
> +++ b/host-utils.c
> @@ -102,4 +102,5 @@ void muls64 (uint64_t *plow, uint64_t *phigh, int64_t a, 
> int64_t b)
>            a, b, *phigh, *plow);
>  #endif
>  }
> +
>  #endif /* !defined(__x86_64__) */

Stray random whitespace change to an unrelated file:
please drop this from the patch.

> diff --git a/target-mips/cpu.h b/target-mips/cpu.h
> index b0ac4da..8e75e9b 100644
> --- a/target-mips/cpu.h
> +++ b/target-mips/cpu.h
> @@ -171,6 +171,13 @@ struct TCState {
>     target_ulong CP0_TCSchedule;
>     target_ulong CP0_TCScheFBack;
>     int32_t CP0_Debug_tcstatus;
> +    /* Multiplier registers for Octeon */
> +    target_ulong MPL0;
> +    target_ulong MPL1;
> +    target_ulong MPL2;
> +    target_ulong P0;
> +    target_ulong P1;
> +    target_ulong P2;
>  };

If you add new fields to the CPU struct then you must also
add code to save/restore them in target-mips/machine.c.

> diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
> index 6b966b1..a1893d1 100644
> --- a/target-mips/op_helper.c
> +++ b/target-mips/op_helper.c
> @@ -266,7 +266,74 @@ void helper_dmultu (target_ulong arg1, target_ulong arg2)
>  {
>     mulu64(&(env->active_tc.LO[0]), &(env->active_tc.HI[0]), arg1, arg2);
>  }
> +static void addc(uint64_t res[], uint64_t a, int i)

Can you leave blank lines between function definitions, please?
(here and also in a few places below)

> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index eb108bc..b480665 100644
> --- a/target-mips/translate.c
> +++ b/target-mips/translate.c
> @@ -69,6 +69,11 @@ enum {
>     OPC_JAL      = (0x03 << 26),
>     OPC_JALS     = OPC_JAL | 0x5,
>     OPC_BEQ      = (0x04 << 26),  /* Unconditional if rs = rt = 0 (B) */
> +    /* Cavium Specific */
> +    OPC_BBIT1    = (0x3a << 26),  /* jump on bit set, cavium specific */
> +    OPC_BBIT132  = (0x3e << 26),  /* jump on bit set(for upper 32 bits) */

Space before the '(' in the comment, please.

> +    OPC_BBIT0    = (0x32 << 26),  /* jump on bit clear, cavium specific */
> +    OPC_BBIT032  = (0x36 << 26),  /* jump on bit clear(for upper 32 bits) */

Ditto.

> @@ -482,7 +512,7 @@ enum {
>  static TCGv_ptr cpu_env;
>  static TCGv cpu_gpr[32], cpu_PC;
>  static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], 
> cpu_ACX[MIPS_DSP_ACC];
> -static TCGv cpu_dspctrl, btarget, bcond;
> +static TCGv cpu_dspctrl, btarget, bcond, mpl0, mpl1, mpl2, p0, p1, p2;

p0/p1/p2 are awful names for global variables -- far too short.
mpl0/mpl1/mpl2 aren't a great deal better.

Also it looks like at least some of these aren't really used very
often -- you should consider just doing loads/stores to env+offset
the way we do for most other cpu fields.

> +/* set on equal/not equal immidiate */
> +static void gen_set_imm(CPUState *env, uint32_t opc,
> +                        int rt, int rs, int16_t imm)
> +{
> +    target_ulong uimm = (target_long)imm;
> +    TCGv t0;
> +    const char *opn = "imm set";
> +    if (rt == 0) {
> +        /* If no destination, treat it as a NOP. */
> +        MIPS_DEBUG("NOP");
> +        return;
> +    }
> +    t0 = tcg_temp_new();
> +    gen_load_gpr(t0, rs);
> +    switch (opc) {
> +    case OPC_SEQI:
> +        tcg_gen_xori_tl(t0, t0, uimm);
> +        tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, 1);
> +        opn = "seqi";
> +        break;
> +    case OPC_SNEI:
> +        tcg_gen_xori_tl(t0, t0, uimm);
> +        tcg_gen_setcondi_tl(TCG_COND_GT, cpu_gpr[rt], t0, 0);
> +        opn = "snei";
> +        break;
> +    }
> +    tcg_temp_free(t0);
> +}

The tcg_gen_xori_tl() is the same in both cases of the switch, you
could pull it out of the switch.

> @@ -1636,6 +1881,30 @@ static void gen_arith (CPUState *env, DisasContext 
> *ctx, uint32_t opc,
>         }
>         opn = "addu";
>         break;
> +    case OPC_BADDU:
> +        {
> +            TCGv t0 = tcg_temp_new();
> +            TCGv t1 = tcg_temp_new();
> +            gen_load_gpr(t0, rs);
> +            gen_load_gpr(t1, rt);
> +            tcg_gen_add_tl(t0, t1, t0);
> +            tcg_gen_ext8u_tl(t0, t0);
> +            gen_store_gpr(t0, rd);
> +            tcg_temp_free(t0);
> +            tcg_temp_free(t1);
> +        }
> +       opn = "baddu";
> +       break;

These should go inside the braces, please [ditto for other cases below]

> +    case OPC_DMUL:
> +        {
> +            TCGv t0 = tcg_temp_new();
> +            TCGv t1 = tcg_temp_new();
> +            gen_load_gpr(t0, rs);
> +           

[Qemu-devel] [PATCH 3/3] target-mips:Support for Cavium specific instructions

2011-07-05 Thread khansa
From: Ehsan-ul-Haq, Abdul Qadeer, Abdul Waheed, Khansa Butt 


Signed-off-by: Khansa Butt 
---
 host-utils.c|1 +
 target-mips/cpu.h   |7 +
 target-mips/helper.h|5 +
 target-mips/op_helper.c |   67 +++
 target-mips/translate.c |  443 ++-
 5 files changed, 514 insertions(+), 9 deletions(-)

diff --git a/host-utils.c b/host-utils.c
index dc96123..1128698 100644
--- a/host-utils.c
+++ b/host-utils.c
@@ -102,4 +102,5 @@ void muls64 (uint64_t *plow, uint64_t *phigh, int64_t a, 
int64_t b)
a, b, *phigh, *plow);
 #endif
 }
+
 #endif /* !defined(__x86_64__) */
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index b0ac4da..8e75e9b 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -171,6 +171,13 @@ struct TCState {
 target_ulong CP0_TCSchedule;
 target_ulong CP0_TCScheFBack;
 int32_t CP0_Debug_tcstatus;
+/* Multiplier registers for Octeon */
+target_ulong MPL0;
+target_ulong MPL1;
+target_ulong MPL2;
+target_ulong P0;
+target_ulong P1;
+target_ulong P2;
 };
 
 typedef struct CPUMIPSState CPUMIPSState;
diff --git a/target-mips/helper.h b/target-mips/helper.h
index 297ab64..e892d39 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -8,7 +8,12 @@ DEF_HELPER_3(ldl, tl, tl, tl, int)
 DEF_HELPER_3(ldr, tl, tl, tl, int)
 DEF_HELPER_3(sdl, void, tl, tl, int)
 DEF_HELPER_3(sdr, void, tl, tl, int)
+DEF_HELPER_2(v3mulu, tl, tl, tl)
+DEF_HELPER_2(vmulu, tl, tl, tl)
+DEF_HELPER_1(dpop, tl, tl)
 #endif
+DEF_HELPER_1(pop, tl, tl);
+
 DEF_HELPER_3(lwl, tl, tl, tl, int)
 DEF_HELPER_3(lwr, tl, tl, tl, int)
 DEF_HELPER_3(swl, void, tl, tl, int)
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 6b966b1..a1893d1 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -266,7 +266,74 @@ void helper_dmultu (target_ulong arg1, target_ulong arg2)
 {
 mulu64(&(env->active_tc.LO[0]), &(env->active_tc.HI[0]), arg1, arg2);
 }
+static void addc(uint64_t res[], uint64_t a, int i)
+{
+uint64_t c = res[i];
+for (; i < 4; i++) {
+res[i] = c + a;
+if (res[i] < a) {
+c = 1;
+a = res[i+1];
+} else
+  break;
+}
+}
+target_ulong helper_v3mulu(target_ulong arg1, target_ulong arg2)
+{
+uint64_t hi, lo, res[4];
+int i;
+for (i = 0; i < 4; i++) {
+res[i] = 0;
+}
+mulu64(&res[0], &res[1], env->active_tc.MPL0, arg1);
+mulu64(&lo, &hi, env->active_tc.MPL1, arg1);
+res[1] = res[1] + lo;
+if (res[1] < lo) {
+res[2]++;
+}
+res[2] = res[2] + hi;
+if (res[2] < hi) {
+res[3]++;
+}
+mulu64(&lo, &hi, env->active_tc.MPL2, arg1);
+res[2] = res[2] + lo;
+if (res[2] < lo) {
+res[3]++;
+}
+res[3] = res[3] + hi;
+addc(res, arg2, 0);
+addc(res, env->active_tc.P0, 0);
+addc(res, env->active_tc.P1, 1);
+addc(res, env->active_tc.P2, 2);
+env->active_tc.P0 = res[1];
+env->active_tc.P1 = res[2];
+env->active_tc.P2 = res[3];
+return res[0];
+}
+target_ulong helper_vmulu(target_ulong arg1, target_ulong arg2)
+{
+uint64_t hi, lo;
+mulu64(&lo, &hi, env->active_tc.MPL0, arg1);
+lo = lo + arg2;
+if (lo < arg2) {
+hi++;
+}
+lo = lo + env->active_tc.P0;
+if (lo < env->active_tc.P0) {
+hi++;
+}
+env->active_tc.P0 = hi;
+return lo;
+}
+target_ulong helper_dpop(target_ulong arg)
+{
+return ctpop64(arg);
+}
 #endif
+target_ulong helper_pop(target_ulong arg)
+{
+return ctpop32((uint32_t)arg);
+}
 
 #ifndef CONFIG_USER_ONLY
 
diff --git a/target-mips/translate.c b/target-mips/translate.c
index eb108bc..b480665 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -69,6 +69,11 @@ enum {
 OPC_JAL  = (0x03 << 26),
 OPC_JALS = OPC_JAL | 0x5,
 OPC_BEQ  = (0x04 << 26),  /* Unconditional if rs = rt = 0 (B) */
+/* Cavium Specific */
+OPC_BBIT1= (0x3a << 26),  /* jump on bit set, cavium specific */
+OPC_BBIT132  = (0x3e << 26),  /* jump on bit set(for upper 32 bits) */
+OPC_BBIT0= (0x32 << 26),  /* jump on bit clear, cavium specific */
+OPC_BBIT032  = (0x36 << 26),  /* jump on bit clear(for upper 32 bits) */
 OPC_BEQL = (0x14 << 26),
 OPC_BNE  = (0x05 << 26),
 OPC_BNEL = (0x15 << 26),
@@ -264,6 +269,31 @@ enum {
 OPC_MADD = 0x00 | OPC_SPECIAL2,
 OPC_MADDU= 0x01 | OPC_SPECIAL2,
 OPC_MUL  = 0x02 | OPC_SPECIAL2,
+/* Cavium Specific Instructions */
+OPC_BADDU= 0x28 | OPC_SPECIAL2,
+OPC_DMUL = 0x03 | OPC_SPECIAL2,
+OPC_EXTS = 0x3a | OPC_SPECIAL2,
+OPC_EXTS32   = 0x3b | OPC_SPECIAL2,
+OPC_CINS = 0x32 | OPC_SPECIAL2,
+OPC_CINS32   = 0x33 | OPC_SPECIAL2,
+OPC_SEQI = 0x2e | OPC_SPECIAL2,
+OPC_SNEI = 0x2f | OPC_SPECIAL2,
+OPC_MTM0 = 0x08 | OPC_SPECIAL2,
+OPC_MTM1 = 0x0c | OP