summaryrefslogtreecommitdiff
path: root/lib/mesa/src/gallium/drivers/r600/sfn/sfn_instruction_alu.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/mesa/src/gallium/drivers/r600/sfn/sfn_instruction_alu.cpp')
-rw-r--r--lib/mesa/src/gallium/drivers/r600/sfn/sfn_instruction_alu.cpp183
1 files changed, 183 insertions, 0 deletions
diff --git a/lib/mesa/src/gallium/drivers/r600/sfn/sfn_instruction_alu.cpp b/lib/mesa/src/gallium/drivers/r600/sfn/sfn_instruction_alu.cpp
new file mode 100644
index 000000000..72cf23172
--- /dev/null
+++ b/lib/mesa/src/gallium/drivers/r600/sfn/sfn_instruction_alu.cpp
@@ -0,0 +1,183 @@
+/* -*- mesa-c++ -*-
+ *
+ * Copyright (c) 2018 Collabora LTD
+ *
+ * Author: Gert Wollny <gert.wollny@collabora.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "sfn_instruction_alu.h"
+#include "sfn_valuepool.h"
+
+namespace r600 {
+
+const AluModifiers AluInstruction::src_abs_flags[2] =
+ {alu_src0_abs, alu_src1_abs};
+const AluModifiers AluInstruction::src_neg_flags[3] =
+ {alu_src0_neg, alu_src1_neg, alu_src2_neg};
+const AluModifiers AluInstruction::src_rel_flags[3] =
+ {alu_src0_rel, alu_src1_rel, alu_src2_rel};
+
+AluInstruction::AluInstruction(EAluOp opcode):
+ Instruction (Instruction::alu),
+ m_opcode(opcode),
+ m_src(alu_ops.at(opcode).nsrc),
+ m_bank_swizzle(alu_vec_unknown),
+ m_cf_type(cf_alu)
+{
+ if (alu_ops.at(opcode).nsrc == 3)
+ m_flags.set(alu_op3);
+}
+
+AluInstruction::AluInstruction(EAluOp opcode, PValue dest,
+ std::vector<PValue> src,
+ const std::set<AluModifiers>& flags):
+ Instruction (Instruction::alu),
+ m_opcode(opcode),
+ m_dest(dest),
+ m_bank_swizzle(alu_vec_unknown),
+ m_cf_type(cf_alu)
+{
+ assert(dest);
+ m_src.swap(src);
+ for (auto f : flags)
+ m_flags.set(f);
+
+ if (alu_ops.at(opcode).nsrc == 3)
+ m_flags.set(alu_op3);
+
+ for (auto &s: m_src)
+ add_remappable_src_value(&s);
+
+ add_remappable_dst_value(&m_dest);
+}
+
+AluInstruction::AluInstruction(EAluOp opcode, PValue dest, PValue src0,
+ const std::set<AluModifiers>& flags):
+ AluInstruction(opcode, dest, std::vector<PValue>{src0}, flags)
+{
+}
+
+AluInstruction::AluInstruction(EAluOp opcode, PValue dest,
+ PValue src0, PValue src1,
+ const std::set<AluModifiers> &m_flags):
+ AluInstruction(opcode, dest, {src0, src1}, m_flags)
+{
+}
+
+AluInstruction::AluInstruction(EAluOp opcode, PValue dest, PValue src0,
+ PValue src1, PValue src2,
+ const std::set<AluModifiers> &flags):
+ AluInstruction(opcode, dest, {src0, src1, src2}, flags)
+{
+}
+
+bool AluInstruction::is_equal_to(const Instruction& lhs) const
+{
+ assert(lhs.type() == alu);
+ const auto& oth = static_cast<const AluInstruction&>(lhs);
+
+ if (m_opcode != oth.m_opcode) {
+ return false;
+ }
+
+ if (*m_dest != *oth.m_dest)
+ return false;
+
+ if (m_src.size() != oth.m_src.size())
+ return false;
+
+ for (unsigned i = 0; i < m_src.size(); ++i)
+ if (*m_src[i] != *oth.m_src[i]) {
+ return false;
+ }
+ return (m_flags == oth.m_flags && m_cf_type == oth.m_cf_type);
+}
+
+void AluInstruction::replace_values(const ValueSet& candidates, PValue new_value)
+{
+ for (auto c: candidates) {
+ if (*c == *m_dest)
+ m_dest = new_value;
+
+ for (auto& s: m_src) {
+ if (*c == *s)
+ s = new_value;
+ }
+ }
+}
+
+PValue AluInstruction::remap_one_registers(PValue reg, std::vector<rename_reg_pair>& map,
+ ValueMap &values)
+{
+ auto new_index = map[reg->sel()];
+ if (new_index.valid)
+ reg = values.get_or_inject(new_index.new_reg, reg->chan());
+ map[reg->sel()].used = true;
+ return reg;
+}
+
+
+void AluInstruction::set_flag(AluModifiers flag)
+{
+ m_flags.set(flag);
+}
+
+void AluInstruction::set_bank_swizzle(AluBankSwizzle bswz)
+{
+ m_bank_swizzle = bswz;
+}
+
+unsigned AluInstruction::n_sources() const
+{
+ return m_src.size();
+}
+
+void AluInstruction::do_print(std::ostream& os) const
+{
+ os << "ALU " << alu_ops.at(m_opcode).name;
+ if (m_flags.test(alu_dst_clamp))
+ os << "_CLAMP";
+ if (m_dest)
+ os << ' ' << *m_dest << " : " ;
+
+ for (unsigned i = 0; i < m_src.size(); ++i) {
+ int pflags = 0;
+ if (i)
+ os << ' ';
+ if (m_flags.test(src_neg_flags[i])) pflags |= Value::PrintFlags::has_neg;
+ if (m_flags.test(src_rel_flags[i])) pflags |= Value::PrintFlags::is_rel;
+ if (i < 2)
+ if (m_flags.test(src_abs_flags[i])) pflags |= Value::PrintFlags::has_abs;
+ m_src[i]->print(os, Value::PrintFlags(0, pflags));
+ }
+ os << " {";
+ os << (m_flags.test(alu_write) ? 'W' : ' ');
+ os << (m_flags.test(alu_last_instr) ? 'L' : ' ');
+ os << (m_flags.test(alu_update_exec) ? 'E' : ' ');
+ os << (m_flags.test(alu_update_pred) ? 'P' : ' ');
+ os << "}";
+
+ os << " BS:" << m_bank_swizzle;
+ os << " CF:" << m_cf_type;
+}
+
+}