support vector 4 (#803)

This commit is contained in:
water111 2021-09-01 10:02:20 -04:00 committed by GitHub
parent c74520398b
commit b58d9ec65d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 152 additions and 36 deletions

View file

@ -304,6 +304,8 @@ std::string get_simple_expression_op_name(SimpleExpression::Kind kind) {
return "subu-s7";
case SimpleExpression::Kind::VECTOR_3_DOT:
return "vec3dot";
case SimpleExpression::Kind::VECTOR_4_DOT:
return "vec4dot";
default:
assert(false);
return {};
@ -363,6 +365,7 @@ int get_simple_expression_arg_count(SimpleExpression::Kind kind) {
case SimpleExpression::Kind::SUBU_L32_S7:
return 1;
case SimpleExpression::Kind::VECTOR_3_DOT:
case SimpleExpression::Kind::VECTOR_4_DOT:
return 2;
default:
assert(false);

View file

@ -235,6 +235,7 @@ class SimpleExpression {
VECTOR_CROSS,
SUBU_L32_S7, // use SUBU X, src0, s7 to check if lower 32-bits are s7.
VECTOR_3_DOT,
VECTOR_4_DOT
};
// how many arguments?

View file

@ -228,6 +228,7 @@ TP_Type SimpleExpression::get_type(const TypeState& input,
case Kind::SUBU_L32_S7:
return TP_Type::make_from_ts("int");
case Kind::VECTOR_3_DOT:
case Kind::VECTOR_4_DOT:
return TP_Type::make_from_ts("float");
default:
throw std::runtime_error("Simple expression cannot get_type: " +

View file

@ -1828,6 +1828,8 @@ std::string fixed_operator_to_string(FixedOperatorKind kind) {
return "l32-false-check";
case FixedOperatorKind::VECTOR_3_DOT:
return "vector-dot";
case FixedOperatorKind::VECTOR_4_DOT:
return "vector4-dot";
case FixedOperatorKind::PROCESS_TO_PPOINTER:
return "process->ppointer";
case FixedOperatorKind::PPOINTER_TO_HANDLE:

View file

@ -224,11 +224,12 @@ class SimpleExpressionElement : public FormElement {
FormStack& stack,
std::vector<FormElement*>* result,
bool allow_side_effects);
void update_from_stack_vector_3_dot(const Env& env,
FormPool& pool,
FormStack& stack,
std::vector<FormElement*>* result,
bool allow_side_effects);
void update_from_stack_vector_dot(FixedOperatorKind kind,
const Env& env,
FormPool& pool,
FormStack& stack,
std::vector<FormElement*>* result,
bool allow_side_effects);
const SimpleExpression& expr() const { return m_expr; }

View file

@ -1321,11 +1321,12 @@ void SimpleExpressionElement::update_from_stack_vector_float_product(
result->push_back(new_form);
}
void SimpleExpressionElement::update_from_stack_vector_3_dot(const Env& env,
FormPool& pool,
FormStack& stack,
std::vector<FormElement*>* result,
bool allow_side_effects) {
void SimpleExpressionElement::update_from_stack_vector_dot(FixedOperatorKind kind,
const Env& env,
FormPool& pool,
FormStack& stack,
std::vector<FormElement*>* result,
bool allow_side_effects) {
std::vector<Form*> popped_args = pop_to_forms({m_expr.get_arg(0).var(), m_expr.get_arg(1).var()},
env, pool, stack, allow_side_effects);
@ -1337,8 +1338,7 @@ void SimpleExpressionElement::update_from_stack_vector_3_dot(const Env& env,
}
auto new_form = pool.alloc_element<GenericElement>(
GenericOperator::make_fixed(FixedOperatorKind::VECTOR_3_DOT),
std::vector<Form*>{popped_args.at(0), popped_args.at(1)});
GenericOperator::make_fixed(kind), std::vector<Form*>{popped_args.at(0), popped_args.at(1)});
result->push_back(new_form);
}
@ -2116,7 +2116,12 @@ void SimpleExpressionElement::update_from_stack(const Env& env,
update_from_stack_subu_l32_s7(env, pool, stack, result, allow_side_effects);
break;
case SimpleExpression::Kind::VECTOR_3_DOT:
update_from_stack_vector_3_dot(env, pool, stack, result, allow_side_effects);
update_from_stack_vector_dot(FixedOperatorKind::VECTOR_3_DOT, env, pool, stack, result,
allow_side_effects);
break;
case SimpleExpression::Kind::VECTOR_4_DOT:
update_from_stack_vector_dot(FixedOperatorKind::VECTOR_4_DOT, env, pool, stack, result,
allow_side_effects);
break;
default:
throw std::runtime_error(
@ -4290,8 +4295,9 @@ void push_asm_srl_to_stack(const AsmOp* op,
stack.push_value_to_reg(*dst, pool.alloc_single_form(nullptr, other), true,
env.get_variable_type(*dst, true));
} else {
throw std::runtime_error(fmt::format("Got invalid bitfield manip for srl: {} type was {}",
src_var->to_string(env), arg0_type.print()));
throw std::runtime_error(
fmt::format("Got invalid bitfield manip for srl at op {}: {} type was {}", op->op_id(),
src_var->to_string(env), arg0_type.print()));
}
}
}

View file

@ -164,6 +164,7 @@ enum class FixedOperatorKind {
PPOINTER_TO_HANDLE,
PROCESS_TO_HANDLE,
PPOINTER_TO_PROCESS,
VECTOR_4_DOT,
INVALID
};

View file

@ -1888,6 +1888,110 @@ std::unique_ptr<AtomicOp> convert_vector3_dot(const Instruction* instrs, int idx
idx);
}
// 12 instructions
std::unique_ptr<AtomicOp> convert_vector4_dot(const Instruction* instrs, int idx) {
// lwc1 f0, 0(a0)
if (!is_lwc(instrs[0], 0)) {
return nullptr;
}
auto t0 = instrs[0].get_dst(0).get_reg();
// lwc1 f1, 4(a0)
if (!is_lwc(instrs[1], 4)) {
return nullptr;
}
auto t1 = instrs[1].get_dst(0).get_reg();
// lwc1 f2, 8(a0)
if (!is_lwc(instrs[2], 8)) {
return nullptr;
}
auto t2 = instrs[2].get_dst(0).get_reg();
// lwc1 f3, 12(a0)
if (!is_lwc(instrs[3], 12)) {
return nullptr;
}
auto t3 = instrs[3].get_dst(0).get_reg();
// lwc1 f3, 0(v1)
if (!is_lwc(instrs[4], 0)) {
return nullptr;
}
auto t4 = instrs[4].get_dst(0).get_reg();
// lwc1 f5, 4(v1)
if (!is_lwc(instrs[5], 4)) {
return nullptr;
}
auto t5 = instrs[5].get_dst(0).get_reg();
// lwc1 f5, 8(v1)
if (!is_lwc(instrs[6], 8)) {
return nullptr;
}
auto t6 = instrs[6].get_dst(0).get_reg();
// lwc1 f5, 12(v1)
if (!is_lwc(instrs[7], 12)) {
return nullptr;
}
auto t7 = instrs[7].get_dst(0).get_reg();
auto src0 = instrs[0].get_src(1).get_reg();
auto src1 = instrs[4].get_src(1).get_reg();
if (instrs[1].get_src(1).get_reg() != src0) {
return nullptr;
}
if (instrs[2].get_src(1).get_reg() != src0) {
return nullptr;
}
if (instrs[3].get_src(1).get_reg() != src0) {
return nullptr;
}
if (instrs[5].get_src(1).get_reg() != src1) {
return nullptr;
}
if (instrs[6].get_src(1).get_reg() != src1) {
return nullptr;
}
if (instrs[7].get_src(1).get_reg() != src1) {
return nullptr;
}
// mula.s f0, f4
if (instrs[8].kind != InstructionKind::MULAS || instrs[8].get_src(0).get_reg() != t0 ||
instrs[8].get_src(1).get_reg() != t4) {
return nullptr;
}
// madda.s f1, f5
if (instrs[9].kind != InstructionKind::MADDAS || instrs[9].get_src(0).get_reg() != t1 ||
instrs[9].get_src(1).get_reg() != t5) {
return nullptr;
}
// madda.s f2, f6
if (instrs[10].kind != InstructionKind::MADDAS || instrs[10].get_src(0).get_reg() != t2 ||
instrs[10].get_src(1).get_reg() != t6) {
return nullptr;
}
// madd.s f0, f3, f7
if (instrs[11].kind != InstructionKind::MADDS || instrs[11].get_src(0).get_reg() != t3 ||
instrs[11].get_src(1).get_reg() != t7) {
return nullptr;
}
auto dst = instrs[11].get_dst(0).get_reg();
return std::make_unique<SetVarOp>(
make_dst_var(dst, idx),
SimpleExpression(SimpleExpression::Kind::VECTOR_4_DOT, make_src_atom(src0, idx),
make_src_atom(src1, idx)),
idx);
}
std::unique_ptr<AtomicOp> convert_9(const Instruction* instrs, int idx) {
auto as_vector3_dot = convert_vector3_dot(instrs, idx);
if (as_vector3_dot) {
@ -1896,6 +2000,14 @@ std::unique_ptr<AtomicOp> convert_9(const Instruction* instrs, int idx) {
return nullptr;
}
std::unique_ptr<AtomicOp> convert_12(const Instruction* instrs, int idx) {
auto as_vector4_dot = convert_vector4_dot(instrs, idx);
if (as_vector4_dot) {
return as_vector4_dot;
}
return nullptr;
}
} // namespace
/*!
@ -1929,7 +2041,15 @@ int convert_block_to_atomic_ops(int begin_idx,
warnings.warn_sq_lq();
}
if (n_instr >= 9) {
if (!converted && n_instr >= 12) {
op = convert_12(&instr[0], op_idx);
if (op) {
converted = true;
length = 12;
}
}
if (!converted && n_instr >= 9) {
op = convert_9(&instr[0], op_idx);
if (op) {
converted = true;

View file

@ -826,27 +826,8 @@
)
;; definition for function vector4-dot
;; WARN: Unsupported inline assembly instruction kind - [mula.s f0, f4]
;; WARN: Unsupported inline assembly instruction kind - [madda.s f1, f5]
;; WARN: Unsupported inline assembly instruction kind - [madda.s f2, f6]
;; WARN: Unsupported inline assembly instruction kind - [madd.s f0, f3, f7]
(defun vector4-dot ((arg0 vector) (arg1 vector))
(local-vars (f0-1 float))
(let ((f0-0 (-> arg0 x))
(f1-0 (-> arg0 y))
(f2-0 (-> arg0 z))
(f3-0 (-> arg0 w))
(f4-0 (-> arg1 x))
(f5-0 (-> arg1 y))
(f6-0 (-> arg1 z))
(f7-0 (-> arg1 w))
)
(.mula.s f0-0 f4-0)
(.madda.s f1-0 f5-0)
(.madda.s f2-0 f6-0)
(.madd.s f0-1 f3-0 f7-0)
)
f0-1
(vector4-dot arg0 arg1)
)
;; definition for function vector4-dot-vu