2025.01.06-2025.01.12 学习内容

1 minute read

Published:

添加对类似”q1”的向量寄存器之支持。同时补充会引起sandbox报错的指令。

1、支持q寄存器

1.1 Antlr语法

添加即可。

// 添加q
fragment REG_VEC_NAME: ('b' | 'h' | 's' | 'd' | 'v' | 'q') ('0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '10' | '11' | '12' | '13' | '14' | '15' | '16' | '17' | '18' | '19' | '20' | '21' | '22' | '23' | '24' | '25' | '26' | '27' | '28' | '29' | '30');

1.2 语义分析

参见asmjit文档:asmjit::a64::Vec Class Reference

只有b、d、s、h、v,并没有q,所以这里的处理办法是将q完全等价于v处理。

reg_map中添加一行处理q的代码:

const unordered_map<string, Reg> reg_map = []() {
    unordered_map<string, Reg> m;
    for (int i = 0; i < 32; ++i) {
        m["w" + to_string(i)] = GpW(i);
        // m["r" + to_string(i)] = GpW(i); // 'r' 其实是 AArch32
        // 里面的,这里我们就不支持了
        m["x" + to_string(i)] = GpX(i);

        // SIMD寄存器
        m["b" + to_string(i)] = VecB(i);
        m["h" + to_string(i)] = VecH(i);
        m["s" + to_string(i)] = VecS(i);
        m["d" + to_string(i)] = VecD(i);
        m["v" + to_string(i)] = VecV(i);
        // 添加这一行
        m["q" + to_string(i)] = VecV(i);
    }
    m["wzr"] = wzr;
    m["xzr"] = xzr;
    m["sp"] = sp;
    return m;
}();

2、引起报错的指令

部分指令会引起沙箱报错,结合之前工作进行了测试,这些指令的一些例子罗列如下:

ld1 {v0.8b}, [x0]
ld2 {v0.8b, v1.8b}, [x0]
ld3 {v0.8b, v1.8b, v2.8b}, [x0]
ld4 {v0.8b, v1.8b, v2.8b, v3.8b}, [x0]

ld1r {v0.8b}, [x0]
ld2r {v0.8b, v1.8b}, [x0]
ld3r {v0.8b, v1.8b, v2.8b}, [x0]
ld4r {v0.8b, v1.8b, v2.8b, v3.8b}, [x0]

st1 {v0.8b}, [x0]
st2 {v0.8b, v1.8b}, [x0]
st3 {v0.8b, v1.8b, v2.8b}, [x0]
st4 {v0.8b, v1.8b, v2.8b, v3.8b}, [x0]

目前可以确定的是,有且只有这些指令会引起报错,其他指令均不会报错。这些指令的特点是只能作为向量指令使用;其他不会引起报错的指令,如ldp,既可以作为标量指令(此时对应asmjit中InstId为”kIdLdp”),也可以作为向量指令(此时对应asmjit中InstId为”kIdLdp_v”)使用。

故补充test_excutor函数如下:

TEST_F(ExecutorTestFixture, St1)
{
  /* 目前可以确定的是,只有 ld1..ld4/ld1r...ld4r/st1..st4 这12条指令会引起报错,这些指令的特点是只能作为向量指令使用。
   * 其他不会引起报错的指令,如ldp,既可以作为标量指令(此时对应asmjit中InstId为"kIdLdp")使用,也可以作为向量指令(此时对应asmjit中InstId为"kIdLdp_v")使用。
   */
  Config *config = Config::getInstance();
  config->def_in_registers.insert({x0, v0});
  config->live_out_registers.insert({x0, v0});
  config->available_registers.insert({x0, v0});
  /*
    st1 {v0.8b}, [x0]
    将 v0 寄存器的 8 个字节元素存储到 `x0` 指向的内存中的位置。
  */
  BasicBlock bb1({
      TInstNodeHandler(Inst::kIdSt1_v, { VecV(0).b8(), Mem(GpX(0))}),
  });
  Program p;
  p.addBlock(make_shared<BasicBlock>(bb1));
  // 生成输入测例
  CPUState input = gen_rand_ptr();
  cout << "Input: " << input << endl;
  auto [exit_code, res] = run(p, input);
  ASSERT_TRUE(exit_code == NORMAL);
}