Message ID | 20180126045742.5487-14-richard.henderson@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | tcg: generic vector operations | expand |
Richard Henderson <richard.henderson@linaro.org> writes: > Reviewed-by: Peter Maydell <peter.maydell@linaro.org> > Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Alex Bennée <alex.bennee@linaro.org> > --- > target/arm/translate-a64.c | 42 ++++++++++++++++++++++++++++++++++++------ > 1 file changed, 36 insertions(+), 6 deletions(-) > > diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c > index 5a4e62ae0f..11310f1a7a 100644 > --- a/target/arm/translate-a64.c > +++ b/target/arm/translate-a64.c > @@ -86,6 +86,7 @@ typedef void CryptoThreeOpIntFn(TCGv_ptr, TCGv_ptr, TCGv_i32); > typedef void CryptoThreeOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr); > > /* Note that the gvec expanders operate on offsets + sizes. */ > +typedef void GVecGen2Fn(unsigned, uint32_t, uint32_t, uint32_t, uint32_t); > typedef void GVecGen3Fn(unsigned, uint32_t, uint32_t, > uint32_t, uint32_t, uint32_t); > > @@ -631,6 +632,14 @@ static TCGv_ptr get_fpstatus_ptr(void) > return statusptr; > } > > +/* Expand a 2-operand AdvSIMD vector operation using an expander function. */ > +static void gen_gvec_fn2(DisasContext *s, bool is_q, int rd, int rn, > + GVecGen2Fn *gvec_fn, int vece) > +{ > + gvec_fn(vece, vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn), > + is_q ? 16 : 8, vec_full_reg_size(s)); > +} > + > /* Expand a 3-operand AdvSIMD vector operation using an expander function. */ > static void gen_gvec_fn3(DisasContext *s, bool is_q, int rd, int rn, int rm, > GVecGen3Fn *gvec_fn, int vece) > @@ -4596,14 +4605,17 @@ static void handle_fp_1src_double(DisasContext *s, int opcode, int rd, int rn) > TCGv_i64 tcg_op; > TCGv_i64 tcg_res; > > + switch (opcode) { > + case 0x0: /* FMOV */ > + gen_gvec_fn2(s, false, rd, rn, tcg_gen_gvec_mov, 0); > + return; > + } > + > fpst = get_fpstatus_ptr(); > tcg_op = read_fp_dreg(s, rn); > tcg_res = tcg_temp_new_i64(); > > switch (opcode) { > - case 0x0: /* FMOV */ > - tcg_gen_mov_i64(tcg_res, tcg_op); > - break; > case 0x1: /* FABS */ > gen_helper_vfp_absd(tcg_res, tcg_op); > break; > @@ -9185,7 +9197,11 @@ static void disas_simd_3same_logic(DisasContext *s, uint32_t insn) > gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_andc, 0); > return; > case 2: /* ORR */ > - gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_or, 0); > + if (rn == rm) { /* MOV */ > + gen_gvec_fn2(s, is_q, rd, rn, tcg_gen_gvec_mov, 0); > + } else { > + gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_or, 0); > + } > return; > case 3: /* ORN */ > gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_orc, 0); > @@ -10059,8 +10075,7 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn) > return; > case 0x5: /* CNT, NOT, RBIT */ > if (u && size == 0) { > - /* NOT: adjust size so we can use the 64-bits-at-a-time loop. */ > - size = 3; > + /* NOT */ > break; > } else if (u && size == 1) { > /* RBIT */ > @@ -10312,6 +10327,21 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn) > tcg_rmode = NULL; > } > > + switch (opcode) { > + case 0x5: > + if (u && size == 0) { /* NOT */ > + gen_gvec_fn2(s, is_q, rd, rn, tcg_gen_gvec_not, 0); > + return; > + } > + break; > + case 0xb: > + if (u) { /* NEG */ > + gen_gvec_fn2(s, is_q, rd, rn, tcg_gen_gvec_neg, size); > + return; > + } > + break; > + } > + > if (size == 3) { > /* All 64-bit element operations can be shared with scalar 2misc */ > int pass; -- Alex Bennée
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index 5a4e62ae0f..11310f1a7a 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -86,6 +86,7 @@ typedef void CryptoThreeOpIntFn(TCGv_ptr, TCGv_ptr, TCGv_i32); typedef void CryptoThreeOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr); /* Note that the gvec expanders operate on offsets + sizes. */ +typedef void GVecGen2Fn(unsigned, uint32_t, uint32_t, uint32_t, uint32_t); typedef void GVecGen3Fn(unsigned, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t); @@ -631,6 +632,14 @@ static TCGv_ptr get_fpstatus_ptr(void) return statusptr; } +/* Expand a 2-operand AdvSIMD vector operation using an expander function. */ +static void gen_gvec_fn2(DisasContext *s, bool is_q, int rd, int rn, + GVecGen2Fn *gvec_fn, int vece) +{ + gvec_fn(vece, vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn), + is_q ? 16 : 8, vec_full_reg_size(s)); +} + /* Expand a 3-operand AdvSIMD vector operation using an expander function. */ static void gen_gvec_fn3(DisasContext *s, bool is_q, int rd, int rn, int rm, GVecGen3Fn *gvec_fn, int vece) @@ -4596,14 +4605,17 @@ static void handle_fp_1src_double(DisasContext *s, int opcode, int rd, int rn) TCGv_i64 tcg_op; TCGv_i64 tcg_res; + switch (opcode) { + case 0x0: /* FMOV */ + gen_gvec_fn2(s, false, rd, rn, tcg_gen_gvec_mov, 0); + return; + } + fpst = get_fpstatus_ptr(); tcg_op = read_fp_dreg(s, rn); tcg_res = tcg_temp_new_i64(); switch (opcode) { - case 0x0: /* FMOV */ - tcg_gen_mov_i64(tcg_res, tcg_op); - break; case 0x1: /* FABS */ gen_helper_vfp_absd(tcg_res, tcg_op); break; @@ -9185,7 +9197,11 @@ static void disas_simd_3same_logic(DisasContext *s, uint32_t insn) gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_andc, 0); return; case 2: /* ORR */ - gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_or, 0); + if (rn == rm) { /* MOV */ + gen_gvec_fn2(s, is_q, rd, rn, tcg_gen_gvec_mov, 0); + } else { + gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_or, 0); + } return; case 3: /* ORN */ gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_orc, 0); @@ -10059,8 +10075,7 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn) return; case 0x5: /* CNT, NOT, RBIT */ if (u && size == 0) { - /* NOT: adjust size so we can use the 64-bits-at-a-time loop. */ - size = 3; + /* NOT */ break; } else if (u && size == 1) { /* RBIT */ @@ -10312,6 +10327,21 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn) tcg_rmode = NULL; } + switch (opcode) { + case 0x5: + if (u && size == 0) { /* NOT */ + gen_gvec_fn2(s, is_q, rd, rn, tcg_gen_gvec_not, 0); + return; + } + break; + case 0xb: + if (u) { /* NEG */ + gen_gvec_fn2(s, is_q, rd, rn, tcg_gen_gvec_neg, size); + return; + } + break; + } + if (size == 3) { /* All 64-bit element operations can be shared with scalar 2misc */ int pass;