On 3/14/20 10:15 PM, LIU Zhiwei wrote:
>
>
> On 2020/3/15 10:53, Richard Henderson wrote:
>> On 3/12/20 7:58 AM, LIU Zhiwei wrote:
>>> +static bool trans_vext_x_v(DisasContext *s, arg_r *a)
>>> +{
>>> + if (vext_check_isa_ill(s, RVV)) {
>>> + TCGv_ptr src2;
>>> + TCGv dest, src1;
>>> + gen_helper_vext_x_v fns[4] = {
>>> + gen_helper_vext_x_v_b, gen_helper_vext_x_v_h,
>>> + gen_helper_vext_x_v_w, gen_helper_vext_x_v_d
>>> + };
>>> +
>>> + dest = tcg_temp_new();
>>> + src1 = tcg_temp_new();
>>> + src2 = tcg_temp_new_ptr();
>>> +
>>> + gen_get_gpr(src1, a->rs1);
>>> + tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, a->rs2));
>>> +
>>> + fns[s->sew](dest, src2, src1, cpu_env);
>>> + gen_set_gpr(a->rd, dest);
>>> +
>>> + tcg_temp_free(dest);
>>> + tcg_temp_free(src1);
>>> + tcg_temp_free_ptr(src2);
>>> + return true;
>>> + }
>>> + return false;
>>> +}
>> This entire operation can be performed inline easily.
>>
>> static void extract_element(TCGv dest, TCGv_ptr base,
>> int ofs, int sew)
>> {
>> switch (sew) {
>> case MO_8:
>> tcg_gen_ld8u_tl(dest, base, ofs);
>> break;
>> case MO_16:
>> tcg_gen_ld16u_tl(dest, base, ofs);
>> break;
>> default:
>> tcg_gen_ld32u_tl(dest, base, ofs);
>> break;
>> #if TARGET_LONG_BITS == 64
>> case MO_64:
>> tcg_gen_ld_i64(dest, base, ofs);
>> break;
>> #endif
>> }
>> }
>>
>> static bool trans_vext_x_v(DisasContext *s, arg_r *a)
>> {
>> ...
>> if (a->rs1 == 0) {
>> /* Special case vmv.x.s rd, vs2. */
>> do_extract(dest, cpu_env,
>> vreg_ofs(s, a->rs2), s->sew);
>> } else {
>> int vlen = s->vlen >> (3 + s->sew);
>> TCGv_i32 ofs = tcg_temp_new_i32();
>> TCGv_ptr base = tcg_temp_new_ptr();
>> TCGv t_vlen, t_zero;
>>
>> /* Mask the index to the length so that we do
>> not produce an out-of-range load. */
>> tcg_gen_trunc_tl_i32(ofs, cpu_gpr[a->rs1]);
>> tcg_gen_andi_i32(ofs, ofs, vlen - 1);
>>
>> /* Convert the index to an offset. */
>> tcg_gen_shli_i32(ofs, ofs, s->sew);
>
> In big endianess host, should I convert the index first before this
> statement.
>
> #ifdef HOST_WORDS_BIGENDIAN
> static void convert_idx(TCGv_i32 idx, int sew)
> {
> switch (sew) {
> case MO_8:
> tcg_gen_xori_i32(idx, idx, 7);
> break;
> case MO_16:
> tcg_gen_xori_i32(idx, idx, 3);
> break;
> case MO_32:
> tcg_gen_xori_i32(idx, idx, 1);
> break;
> default:
> break;
> }
> }
> #endif
>
>
> When convert the index to an offset, use this function first
>
> #ifdef HOST_WORDS_BIGENDIAN
> convert_idx(ofs, s->sew)
> #endif
Yes, I forgot about endian adjust.
I would say
static void endian_adjust(TCGv_i32 ofs, int sew)
{
#ifdef HOST_WORDS_BIGENDIAN
tcg_gen_xori_i32(ofs, ofs, 7 >> sew);
#endif
}
so that you don't need the ifdef at the use site.
r~