compiler: Support the majority of the remaining VU VF instructions (#258)

* compiler: Support the majority of the remaining VU VF instructions

- VWAIT
- VMADD variants
- VMSUB variants
- VSQRT
- VDIV
- outer product (VOPMULA + VOPMSUB)

* compiler: Fix some bugs / optimize some instructions

* tests/compiler: Add test coverage for new instructions

* docs: Add documentation for new inline assembly functions

* lint: Formatting / fix failing test

* Remove my comment about ftf/fsf encoding, it's been fixed

* address review feedback

* correct VSQRTPS implementation
This commit is contained in:
Tyler Wilding
2021-02-16 18:41:33 -08:00
committed by GitHub
parent f1a93886e7
commit cdce4d9612
15 changed files with 1546 additions and 514 deletions
+88
View File
@@ -1099,6 +1099,27 @@ void IR_AsmFNop::do_codegen(emitter::ObjectGenerator* gen,
gen->add_instr(IGen::nop_vf(), irec);
}
///////////////////////
// AsmFWait
///////////////////////
IR_AsmFWait::IR_AsmFWait() : IR_Asm(false) {}
std::string IR_AsmFWait::print() {
return ".wait.vf";
}
RegAllocInstr IR_AsmFWait::to_rai() {
return {};
}
void IR_AsmFWait::do_codegen(emitter::ObjectGenerator* gen,
const AllocationResult& allocs,
emitter::IR_Record irec) {
(void)allocs;
gen->add_instr(IGen::wait_vf(), irec);
}
///////////////////////
// AsmPush
///////////////////////
@@ -1343,6 +1364,9 @@ std::string IR_VFMath3Asm::print() {
case Kind::MIN:
function = ".min.vf";
break;
case Kind::DIV:
function = ".div.vf";
break;
default:
assert(false);
}
@@ -1386,11 +1410,16 @@ void IR_VFMath3Asm::do_codegen(emitter::ObjectGenerator* gen,
case Kind::MIN:
gen->add_instr(IGen::min_vf(dst, src1, src2), irec);
break;
case Kind::DIV:
gen->add_instr(IGen::div_vf(dst, src1, src2), irec);
break;
default:
assert(false);
}
}
// ---- Blend VF
IR_BlendVF::IR_BlendVF(bool use_color,
const RegVal* dst,
const RegVal* src1,
@@ -1422,6 +1451,8 @@ void IR_BlendVF::do_codegen(emitter::ObjectGenerator* gen,
gen->add_instr(IGen::blend_vf(dst, src1, src2, m_mask), irec);
}
// ----- Splat VF
IR_SplatVF::IR_SplatVF(bool use_color,
const RegVal* dst,
const RegVal* src,
@@ -1449,3 +1480,60 @@ void IR_SplatVF::do_codegen(emitter::ObjectGenerator* gen,
auto src = get_reg_asm(m_src, allocs, irec, m_use_coloring);
gen->add_instr(IGen::splat_vf(dst, src, m_element), irec);
}
// ---- Swizzle VF
IR_SwizzleVF::IR_SwizzleVF(bool use_color,
const RegVal* dst,
const RegVal* src,
const u8 controlBytes)
: IR_Asm(use_color), m_dst(dst), m_src(src), m_controlBytes(controlBytes) {}
std::string IR_SwizzleVF::print() {
return fmt::format(".swizzle.vf{} {}, {}, {}", get_color_suffix_string(), m_dst->print(),
m_src->print(), m_controlBytes);
}
RegAllocInstr IR_SwizzleVF::to_rai() {
RegAllocInstr rai;
if (m_use_coloring) {
rai.write.push_back(m_dst->ireg());
rai.read.push_back(m_src->ireg());
}
return rai;
}
void IR_SwizzleVF::do_codegen(emitter::ObjectGenerator* gen,
const AllocationResult& allocs,
emitter::IR_Record irec) {
auto dst = get_reg_asm(m_dst, allocs, irec, m_use_coloring);
auto src = get_reg_asm(m_src, allocs, irec, m_use_coloring);
gen->add_instr(IGen::swizzle_vf(dst, src, m_controlBytes), irec);
}
// ---- Square Root VF
IR_SqrtVF::IR_SqrtVF(bool use_color, const RegVal* dst, const RegVal* src)
: IR_Asm(use_color), m_dst(dst), m_src(src) {}
std::string IR_SqrtVF::print() {
return fmt::format(".sqrt.vf{} {}, {}", get_color_suffix_string(), m_dst->print(),
m_src->print());
}
RegAllocInstr IR_SqrtVF::to_rai() {
RegAllocInstr rai;
if (m_use_coloring) {
rai.write.push_back(m_dst->ireg());
rai.read.push_back(m_src->ireg());
}
return rai;
}
void IR_SqrtVF::do_codegen(emitter::ObjectGenerator* gen,
const AllocationResult& allocs,
emitter::IR_Record irec) {
auto dst = get_reg_asm(m_dst, allocs, irec, m_use_coloring);
auto src = get_reg_asm(m_src, allocs, irec, m_use_coloring);
gen->add_instr(IGen::sqrt_vf(dst, src), irec);
}