| 
									
										
										
										
											2021-05-09 03:11:34 -03:00
										 |  |  | // Copyright 2021 yuzu Emulator Project
 | 
					
						
							|  |  |  | // Licensed under GPLv2 or any later version
 | 
					
						
							|  |  |  | // Refer to the license.txt file included.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "shader_recompiler/backend/glasm/emit_glasm_instructions.h"
 | 
					
						
							| 
									
										
										
										
											2021-12-05 16:42:03 -05:00
										 |  |  | #include "shader_recompiler/backend/glasm/glasm_emit_context.h"
 | 
					
						
							| 
									
										
										
										
											2021-05-09 03:11:34 -03:00
										 |  |  | #include "shader_recompiler/frontend/ir/value.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace Shader::Backend::GLASM { | 
					
						
							|  |  |  | namespace { | 
					
						
							| 
									
										
										
										
											2021-05-09 04:01:17 -03:00
										 |  |  | template <auto read_imm, char type, typename... Values> | 
					
						
							|  |  |  | void CompositeConstruct(EmitContext& ctx, IR::Inst& inst, Values&&... elements) { | 
					
						
							| 
									
										
										
										
											2021-05-09 03:11:34 -03:00
										 |  |  |     const Register ret{ctx.reg_alloc.Define(inst)}; | 
					
						
							|  |  |  |     if (std::ranges::any_of(std::array{elements...}, | 
					
						
							|  |  |  |                             [](const IR::Value& value) { return value.IsImmediate(); })) { | 
					
						
							| 
									
										
										
										
											2021-05-09 04:01:17 -03:00
										 |  |  |         using Type = std::invoke_result_t<decltype(read_imm), IR::Value>; | 
					
						
							|  |  |  |         const std::array<Type, 4> values{(elements.IsImmediate() ? (elements.*read_imm)() : 0)...}; | 
					
						
							|  |  |  |         ctx.Add("MOV.{} {},{{{},{},{},{}}};", type, ret, fmt::to_string(values[0]), | 
					
						
							| 
									
										
										
										
											2021-05-09 03:11:34 -03:00
										 |  |  |                 fmt::to_string(values[1]), fmt::to_string(values[2]), fmt::to_string(values[3])); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     size_t index{}; | 
					
						
							|  |  |  |     for (const IR::Value& element : {elements...}) { | 
					
						
							|  |  |  |         if (!element.IsImmediate()) { | 
					
						
							|  |  |  |             const ScalarU32 value{ctx.reg_alloc.Consume(element)}; | 
					
						
							| 
									
										
										
										
											2021-05-09 04:01:17 -03:00
										 |  |  |             ctx.Add("MOV.{} {}.{},{};", type, ret, "xyzw"[index], value); | 
					
						
							| 
									
										
										
										
											2021-05-09 03:11:34 -03:00
										 |  |  |         } | 
					
						
							|  |  |  |         ++index; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-09 04:01:17 -03:00
										 |  |  | void CompositeExtract(EmitContext& ctx, IR::Inst& inst, Register composite, u32 index, char type) { | 
					
						
							| 
									
										
										
										
											2021-05-09 03:11:34 -03:00
										 |  |  |     const Register ret{ctx.reg_alloc.Define(inst)}; | 
					
						
							|  |  |  |     if (ret == composite && index == 0) { | 
					
						
							|  |  |  |         // No need to do anything here, the source and destination are the same register
 | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-05-09 04:01:17 -03:00
										 |  |  |     ctx.Add("MOV.{} {}.x,{}.{};", type, ret, composite, "xyzw"[index]); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <typename ObjectType> | 
					
						
							|  |  |  | void CompositeInsert(EmitContext& ctx, IR::Inst& inst, Register composite, ObjectType object, | 
					
						
							|  |  |  |                      u32 index, char type) { | 
					
						
							|  |  |  |     const Register ret{ctx.reg_alloc.Define(inst)}; | 
					
						
							| 
									
										
										
										
											2021-05-10 19:20:15 -03:00
										 |  |  |     const char swizzle{"xyzw"[index]}; | 
					
						
							|  |  |  |     if (ret != composite && ret == object) { | 
					
						
							|  |  |  |         // The object is aliased with the return value, so we have to use a temporary to insert
 | 
					
						
							|  |  |  |         ctx.Add("MOV.{} RC,{};" | 
					
						
							|  |  |  |                 "MOV.{} RC.{},{};" | 
					
						
							|  |  |  |                 "MOV.{} {},RC;", | 
					
						
							|  |  |  |                 type, composite, type, swizzle, object, type, ret); | 
					
						
							|  |  |  |     } else if (ret != composite) { | 
					
						
							|  |  |  |         // The input composite is not aliased with the return value so we have to copy it before
 | 
					
						
							|  |  |  |         // hand. But the insert object is not aliased with the return value, so we don't have to
 | 
					
						
							|  |  |  |         // worry about that
 | 
					
						
							| 
									
										
										
										
											2021-05-25 02:22:21 -03:00
										 |  |  |         ctx.Add("MOV.{} {},{};" | 
					
						
							|  |  |  |                 "MOV.{} {}.{},{};", | 
					
						
							|  |  |  |                 type, ret, composite, type, ret, swizzle, object); | 
					
						
							| 
									
										
										
										
											2021-05-10 19:20:15 -03:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         // The return value is alised so we can just insert the object, it doesn't matter if it's
 | 
					
						
							|  |  |  |         // aliased
 | 
					
						
							|  |  |  |         ctx.Add("MOV.{} {}.{},{};", type, ret, swizzle, object); | 
					
						
							| 
									
										
										
										
											2021-05-09 04:01:17 -03:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-05-09 03:11:34 -03:00
										 |  |  | } | 
					
						
							|  |  |  | } // Anonymous namespace
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmitCompositeConstructU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& e1, | 
					
						
							|  |  |  |                                  const IR::Value& e2) { | 
					
						
							| 
									
										
										
										
											2021-05-09 04:01:17 -03:00
										 |  |  |     CompositeConstruct<&IR::Value::U32, 'U'>(ctx, inst, e1, e2); | 
					
						
							| 
									
										
										
										
											2021-05-09 03:11:34 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmitCompositeConstructU32x3(EmitContext& ctx, IR::Inst& inst, const IR::Value& e1, | 
					
						
							|  |  |  |                                  const IR::Value& e2, const IR::Value& e3) { | 
					
						
							| 
									
										
										
										
											2021-05-09 04:01:17 -03:00
										 |  |  |     CompositeConstruct<&IR::Value::U32, 'U'>(ctx, inst, e1, e2, e3); | 
					
						
							| 
									
										
										
										
											2021-05-09 03:11:34 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmitCompositeConstructU32x4(EmitContext& ctx, IR::Inst& inst, const IR::Value& e1, | 
					
						
							|  |  |  |                                  const IR::Value& e2, const IR::Value& e3, const IR::Value& e4) { | 
					
						
							| 
									
										
										
										
											2021-05-09 04:01:17 -03:00
										 |  |  |     CompositeConstruct<&IR::Value::U32, 'U'>(ctx, inst, e1, e2, e3, e4); | 
					
						
							| 
									
										
										
										
											2021-05-09 03:11:34 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmitCompositeExtractU32x2(EmitContext& ctx, IR::Inst& inst, Register composite, u32 index) { | 
					
						
							| 
									
										
										
										
											2021-05-09 04:01:17 -03:00
										 |  |  |     CompositeExtract(ctx, inst, composite, index, 'U'); | 
					
						
							| 
									
										
										
										
											2021-05-09 03:11:34 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmitCompositeExtractU32x3(EmitContext& ctx, IR::Inst& inst, Register composite, u32 index) { | 
					
						
							| 
									
										
										
										
											2021-05-09 04:01:17 -03:00
										 |  |  |     CompositeExtract(ctx, inst, composite, index, 'U'); | 
					
						
							| 
									
										
										
										
											2021-05-09 03:11:34 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmitCompositeExtractU32x4(EmitContext& ctx, IR::Inst& inst, Register composite, u32 index) { | 
					
						
							| 
									
										
										
										
											2021-05-09 04:01:17 -03:00
										 |  |  |     CompositeExtract(ctx, inst, composite, index, 'U'); | 
					
						
							| 
									
										
										
										
											2021-05-09 03:11:34 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmitCompositeInsertU32x2([[maybe_unused]] EmitContext& ctx, | 
					
						
							|  |  |  |                               [[maybe_unused]] Register composite, | 
					
						
							|  |  |  |                               [[maybe_unused]] ScalarU32 object, [[maybe_unused]] u32 index) { | 
					
						
							|  |  |  |     throw NotImplementedException("GLASM instruction"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmitCompositeInsertU32x3([[maybe_unused]] EmitContext& ctx, | 
					
						
							|  |  |  |                               [[maybe_unused]] Register composite, | 
					
						
							|  |  |  |                               [[maybe_unused]] ScalarU32 object, [[maybe_unused]] u32 index) { | 
					
						
							|  |  |  |     throw NotImplementedException("GLASM instruction"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmitCompositeInsertU32x4([[maybe_unused]] EmitContext& ctx, | 
					
						
							|  |  |  |                               [[maybe_unused]] Register composite, | 
					
						
							|  |  |  |                               [[maybe_unused]] ScalarU32 object, [[maybe_unused]] u32 index) { | 
					
						
							|  |  |  |     throw NotImplementedException("GLASM instruction"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmitCompositeConstructF16x2([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register e1, | 
					
						
							|  |  |  |                                  [[maybe_unused]] Register e2) { | 
					
						
							|  |  |  |     throw NotImplementedException("GLASM instruction"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmitCompositeConstructF16x3([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register e1, | 
					
						
							|  |  |  |                                  [[maybe_unused]] Register e2, [[maybe_unused]] Register e3) { | 
					
						
							|  |  |  |     throw NotImplementedException("GLASM instruction"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmitCompositeConstructF16x4([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] Register e1, | 
					
						
							|  |  |  |                                  [[maybe_unused]] Register e2, [[maybe_unused]] Register e3, | 
					
						
							|  |  |  |                                  [[maybe_unused]] Register e4) { | 
					
						
							|  |  |  |     throw NotImplementedException("GLASM instruction"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmitCompositeExtractF16x2([[maybe_unused]] EmitContext& ctx, | 
					
						
							|  |  |  |                                [[maybe_unused]] Register composite, [[maybe_unused]] u32 index) { | 
					
						
							|  |  |  |     throw NotImplementedException("GLASM instruction"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmitCompositeExtractF16x3([[maybe_unused]] EmitContext& ctx, | 
					
						
							|  |  |  |                                [[maybe_unused]] Register composite, [[maybe_unused]] u32 index) { | 
					
						
							|  |  |  |     throw NotImplementedException("GLASM instruction"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmitCompositeExtractF16x4([[maybe_unused]] EmitContext& ctx, | 
					
						
							|  |  |  |                                [[maybe_unused]] Register composite, [[maybe_unused]] u32 index) { | 
					
						
							|  |  |  |     throw NotImplementedException("GLASM instruction"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmitCompositeInsertF16x2([[maybe_unused]] EmitContext& ctx, | 
					
						
							|  |  |  |                               [[maybe_unused]] Register composite, [[maybe_unused]] Register object, | 
					
						
							|  |  |  |                               [[maybe_unused]] u32 index) { | 
					
						
							|  |  |  |     throw NotImplementedException("GLASM instruction"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmitCompositeInsertF16x3([[maybe_unused]] EmitContext& ctx, | 
					
						
							|  |  |  |                               [[maybe_unused]] Register composite, [[maybe_unused]] Register object, | 
					
						
							|  |  |  |                               [[maybe_unused]] u32 index) { | 
					
						
							|  |  |  |     throw NotImplementedException("GLASM instruction"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmitCompositeInsertF16x4([[maybe_unused]] EmitContext& ctx, | 
					
						
							|  |  |  |                               [[maybe_unused]] Register composite, [[maybe_unused]] Register object, | 
					
						
							|  |  |  |                               [[maybe_unused]] u32 index) { | 
					
						
							|  |  |  |     throw NotImplementedException("GLASM instruction"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-09 04:01:17 -03:00
										 |  |  | void EmitCompositeConstructF32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& e1, | 
					
						
							|  |  |  |                                  const IR::Value& e2) { | 
					
						
							|  |  |  |     CompositeConstruct<&IR::Value::F32, 'F'>(ctx, inst, e1, e2); | 
					
						
							| 
									
										
										
										
											2021-05-09 03:11:34 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-09 04:01:17 -03:00
										 |  |  | void EmitCompositeConstructF32x3(EmitContext& ctx, IR::Inst& inst, const IR::Value& e1, | 
					
						
							|  |  |  |                                  const IR::Value& e2, const IR::Value& e3) { | 
					
						
							|  |  |  |     CompositeConstruct<&IR::Value::F32, 'F'>(ctx, inst, e1, e2, e3); | 
					
						
							| 
									
										
										
										
											2021-05-09 03:11:34 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-09 04:01:17 -03:00
										 |  |  | void EmitCompositeConstructF32x4(EmitContext& ctx, IR::Inst& inst, const IR::Value& e1, | 
					
						
							|  |  |  |                                  const IR::Value& e2, const IR::Value& e3, const IR::Value& e4) { | 
					
						
							|  |  |  |     CompositeConstruct<&IR::Value::F32, 'F'>(ctx, inst, e1, e2, e3, e4); | 
					
						
							| 
									
										
										
										
											2021-05-09 03:11:34 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-09 04:01:17 -03:00
										 |  |  | void EmitCompositeExtractF32x2(EmitContext& ctx, IR::Inst& inst, Register composite, u32 index) { | 
					
						
							|  |  |  |     CompositeExtract(ctx, inst, composite, index, 'F'); | 
					
						
							| 
									
										
										
										
											2021-05-09 03:11:34 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-09 04:01:17 -03:00
										 |  |  | void EmitCompositeExtractF32x3(EmitContext& ctx, IR::Inst& inst, Register composite, u32 index) { | 
					
						
							|  |  |  |     CompositeExtract(ctx, inst, composite, index, 'F'); | 
					
						
							| 
									
										
										
										
											2021-05-09 03:11:34 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-09 04:01:17 -03:00
										 |  |  | void EmitCompositeExtractF32x4(EmitContext& ctx, IR::Inst& inst, Register composite, u32 index) { | 
					
						
							|  |  |  |     CompositeExtract(ctx, inst, composite, index, 'F'); | 
					
						
							| 
									
										
										
										
											2021-05-09 03:11:34 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-09 04:01:17 -03:00
										 |  |  | void EmitCompositeInsertF32x2(EmitContext& ctx, IR::Inst& inst, Register composite, | 
					
						
							|  |  |  |                               ScalarF32 object, u32 index) { | 
					
						
							|  |  |  |     CompositeInsert(ctx, inst, composite, object, index, 'F'); | 
					
						
							| 
									
										
										
										
											2021-05-09 03:11:34 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-09 04:01:17 -03:00
										 |  |  | void EmitCompositeInsertF32x3(EmitContext& ctx, IR::Inst& inst, Register composite, | 
					
						
							|  |  |  |                               ScalarF32 object, u32 index) { | 
					
						
							|  |  |  |     CompositeInsert(ctx, inst, composite, object, index, 'F'); | 
					
						
							| 
									
										
										
										
											2021-05-09 03:11:34 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-09 04:01:17 -03:00
										 |  |  | void EmitCompositeInsertF32x4(EmitContext& ctx, IR::Inst& inst, Register composite, | 
					
						
							|  |  |  |                               ScalarF32 object, u32 index) { | 
					
						
							|  |  |  |     CompositeInsert(ctx, inst, composite, object, index, 'F'); | 
					
						
							| 
									
										
										
										
											2021-05-09 03:11:34 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmitCompositeConstructF64x2([[maybe_unused]] EmitContext& ctx) { | 
					
						
							|  |  |  |     throw NotImplementedException("GLASM instruction"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmitCompositeConstructF64x3([[maybe_unused]] EmitContext& ctx) { | 
					
						
							|  |  |  |     throw NotImplementedException("GLASM instruction"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmitCompositeConstructF64x4([[maybe_unused]] EmitContext& ctx) { | 
					
						
							|  |  |  |     throw NotImplementedException("GLASM instruction"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmitCompositeExtractF64x2([[maybe_unused]] EmitContext& ctx) { | 
					
						
							|  |  |  |     throw NotImplementedException("GLASM instruction"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmitCompositeExtractF64x3([[maybe_unused]] EmitContext& ctx) { | 
					
						
							|  |  |  |     throw NotImplementedException("GLASM instruction"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmitCompositeExtractF64x4([[maybe_unused]] EmitContext& ctx) { | 
					
						
							|  |  |  |     throw NotImplementedException("GLASM instruction"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmitCompositeInsertF64x2([[maybe_unused]] EmitContext& ctx, | 
					
						
							|  |  |  |                               [[maybe_unused]] Register composite, [[maybe_unused]] Register object, | 
					
						
							|  |  |  |                               [[maybe_unused]] u32 index) { | 
					
						
							|  |  |  |     throw NotImplementedException("GLASM instruction"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmitCompositeInsertF64x3([[maybe_unused]] EmitContext& ctx, | 
					
						
							|  |  |  |                               [[maybe_unused]] Register composite, [[maybe_unused]] Register object, | 
					
						
							|  |  |  |                               [[maybe_unused]] u32 index) { | 
					
						
							|  |  |  |     throw NotImplementedException("GLASM instruction"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EmitCompositeInsertF64x4([[maybe_unused]] EmitContext& ctx, | 
					
						
							|  |  |  |                               [[maybe_unused]] Register composite, [[maybe_unused]] Register object, | 
					
						
							|  |  |  |                               [[maybe_unused]] u32 index) { | 
					
						
							|  |  |  |     throw NotImplementedException("GLASM instruction"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } // namespace Shader::Backend::GLASM
 |