mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	Merge pull request #3788 from wwylele/shader-jit-breakc
shader/jit: implement breakc
This commit is contained in:
		
						commit
						2dac1a9590
					
				
					 2 changed files with 81 additions and 64 deletions
				
			
		|  | @ -33,70 +33,70 @@ namespace Shader { | |||
| typedef void (JitShader::*JitFunction)(Instruction instr); | ||||
| 
 | ||||
| const JitFunction instr_table[64] = { | ||||
|     &JitShader::Compile_ADD,   // add
 | ||||
|     &JitShader::Compile_DP3,   // dp3
 | ||||
|     &JitShader::Compile_DP4,   // dp4
 | ||||
|     &JitShader::Compile_DPH,   // dph
 | ||||
|     nullptr,                   // unknown
 | ||||
|     &JitShader::Compile_EX2,   // ex2
 | ||||
|     &JitShader::Compile_LG2,   // lg2
 | ||||
|     nullptr,                   // unknown
 | ||||
|     &JitShader::Compile_MUL,   // mul
 | ||||
|     &JitShader::Compile_SGE,   // sge
 | ||||
|     &JitShader::Compile_SLT,   // slt
 | ||||
|     &JitShader::Compile_FLR,   // flr
 | ||||
|     &JitShader::Compile_MAX,   // max
 | ||||
|     &JitShader::Compile_MIN,   // min
 | ||||
|     &JitShader::Compile_RCP,   // rcp
 | ||||
|     &JitShader::Compile_RSQ,   // rsq
 | ||||
|     nullptr,                   // unknown
 | ||||
|     nullptr,                   // unknown
 | ||||
|     &JitShader::Compile_MOVA,  // mova
 | ||||
|     &JitShader::Compile_MOV,   // mov
 | ||||
|     nullptr,                   // unknown
 | ||||
|     nullptr,                   // unknown
 | ||||
|     nullptr,                   // unknown
 | ||||
|     nullptr,                   // unknown
 | ||||
|     &JitShader::Compile_DPH,   // dphi
 | ||||
|     nullptr,                   // unknown
 | ||||
|     &JitShader::Compile_SGE,   // sgei
 | ||||
|     &JitShader::Compile_SLT,   // slti
 | ||||
|     nullptr,                   // unknown
 | ||||
|     nullptr,                   // unknown
 | ||||
|     nullptr,                   // unknown
 | ||||
|     nullptr,                   // unknown
 | ||||
|     nullptr,                   // unknown
 | ||||
|     &JitShader::Compile_NOP,   // nop
 | ||||
|     &JitShader::Compile_END,   // end
 | ||||
|     nullptr,                   // break
 | ||||
|     &JitShader::Compile_CALL,  // call
 | ||||
|     &JitShader::Compile_CALLC, // callc
 | ||||
|     &JitShader::Compile_CALLU, // callu
 | ||||
|     &JitShader::Compile_IF,    // ifu
 | ||||
|     &JitShader::Compile_IF,    // ifc
 | ||||
|     &JitShader::Compile_LOOP,  // loop
 | ||||
|     &JitShader::Compile_EMIT,  // emit
 | ||||
|     &JitShader::Compile_SETE,  // sete
 | ||||
|     &JitShader::Compile_JMP,   // jmpc
 | ||||
|     &JitShader::Compile_JMP,   // jmpu
 | ||||
|     &JitShader::Compile_CMP,   // cmp
 | ||||
|     &JitShader::Compile_CMP,   // cmp
 | ||||
|     &JitShader::Compile_MAD,   // madi
 | ||||
|     &JitShader::Compile_MAD,   // madi
 | ||||
|     &JitShader::Compile_MAD,   // madi
 | ||||
|     &JitShader::Compile_MAD,   // madi
 | ||||
|     &JitShader::Compile_MAD,   // madi
 | ||||
|     &JitShader::Compile_MAD,   // madi
 | ||||
|     &JitShader::Compile_MAD,   // madi
 | ||||
|     &JitShader::Compile_MAD,   // madi
 | ||||
|     &JitShader::Compile_MAD,   // mad
 | ||||
|     &JitShader::Compile_MAD,   // mad
 | ||||
|     &JitShader::Compile_MAD,   // mad
 | ||||
|     &JitShader::Compile_MAD,   // mad
 | ||||
|     &JitShader::Compile_MAD,   // mad
 | ||||
|     &JitShader::Compile_MAD,   // mad
 | ||||
|     &JitShader::Compile_MAD,   // mad
 | ||||
|     &JitShader::Compile_MAD,   // mad
 | ||||
|     &JitShader::Compile_ADD,    // add
 | ||||
|     &JitShader::Compile_DP3,    // dp3
 | ||||
|     &JitShader::Compile_DP4,    // dp4
 | ||||
|     &JitShader::Compile_DPH,    // dph
 | ||||
|     nullptr,                    // unknown
 | ||||
|     &JitShader::Compile_EX2,    // ex2
 | ||||
|     &JitShader::Compile_LG2,    // lg2
 | ||||
|     nullptr,                    // unknown
 | ||||
|     &JitShader::Compile_MUL,    // mul
 | ||||
|     &JitShader::Compile_SGE,    // sge
 | ||||
|     &JitShader::Compile_SLT,    // slt
 | ||||
|     &JitShader::Compile_FLR,    // flr
 | ||||
|     &JitShader::Compile_MAX,    // max
 | ||||
|     &JitShader::Compile_MIN,    // min
 | ||||
|     &JitShader::Compile_RCP,    // rcp
 | ||||
|     &JitShader::Compile_RSQ,    // rsq
 | ||||
|     nullptr,                    // unknown
 | ||||
|     nullptr,                    // unknown
 | ||||
|     &JitShader::Compile_MOVA,   // mova
 | ||||
|     &JitShader::Compile_MOV,    // mov
 | ||||
|     nullptr,                    // unknown
 | ||||
|     nullptr,                    // unknown
 | ||||
|     nullptr,                    // unknown
 | ||||
|     nullptr,                    // unknown
 | ||||
|     &JitShader::Compile_DPH,    // dphi
 | ||||
|     nullptr,                    // unknown
 | ||||
|     &JitShader::Compile_SGE,    // sgei
 | ||||
|     &JitShader::Compile_SLT,    // slti
 | ||||
|     nullptr,                    // unknown
 | ||||
|     nullptr,                    // unknown
 | ||||
|     nullptr,                    // unknown
 | ||||
|     nullptr,                    // unknown
 | ||||
|     nullptr,                    // unknown
 | ||||
|     &JitShader::Compile_NOP,    // nop
 | ||||
|     &JitShader::Compile_END,    // end
 | ||||
|     &JitShader::Compile_BREAKC, // breakc
 | ||||
|     &JitShader::Compile_CALL,   // call
 | ||||
|     &JitShader::Compile_CALLC,  // callc
 | ||||
|     &JitShader::Compile_CALLU,  // callu
 | ||||
|     &JitShader::Compile_IF,     // ifu
 | ||||
|     &JitShader::Compile_IF,     // ifc
 | ||||
|     &JitShader::Compile_LOOP,   // loop
 | ||||
|     &JitShader::Compile_EMIT,   // emit
 | ||||
|     &JitShader::Compile_SETE,   // sete
 | ||||
|     &JitShader::Compile_JMP,    // jmpc
 | ||||
|     &JitShader::Compile_JMP,    // jmpu
 | ||||
|     &JitShader::Compile_CMP,    // cmp
 | ||||
|     &JitShader::Compile_CMP,    // cmp
 | ||||
|     &JitShader::Compile_MAD,    // madi
 | ||||
|     &JitShader::Compile_MAD,    // madi
 | ||||
|     &JitShader::Compile_MAD,    // madi
 | ||||
|     &JitShader::Compile_MAD,    // madi
 | ||||
|     &JitShader::Compile_MAD,    // madi
 | ||||
|     &JitShader::Compile_MAD,    // madi
 | ||||
|     &JitShader::Compile_MAD,    // madi
 | ||||
|     &JitShader::Compile_MAD,    // madi
 | ||||
|     &JitShader::Compile_MAD,    // mad
 | ||||
|     &JitShader::Compile_MAD,    // mad
 | ||||
|     &JitShader::Compile_MAD,    // mad
 | ||||
|     &JitShader::Compile_MAD,    // mad
 | ||||
|     &JitShader::Compile_MAD,    // mad
 | ||||
|     &JitShader::Compile_MAD,    // mad
 | ||||
|     &JitShader::Compile_MAD,    // mad
 | ||||
|     &JitShader::Compile_MAD,    // mad
 | ||||
| }; | ||||
| 
 | ||||
| // The following is used to alias some commonly used registers. Generally, RAX-RDX and XMM0-XMM3 can
 | ||||
|  | @ -584,6 +584,14 @@ void JitShader::Compile_END(Instruction instr) { | |||
|     ret(); | ||||
| } | ||||
| 
 | ||||
| void JitShader::Compile_BREAKC(Instruction instr) { | ||||
|     Compile_Assert(looping, "BREAKC must be inside a LOOP"); | ||||
|     if (looping) { | ||||
|         Compile_EvaluateCondition(instr); | ||||
|         jnz(*loop_break_label); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void JitShader::Compile_CALL(Instruction instr) { | ||||
|     // Push offset of the return
 | ||||
|     push(qword, (instr.flow_control.dest_offset + instr.flow_control.num_instructions)); | ||||
|  | @ -727,11 +735,14 @@ void JitShader::Compile_LOOP(Instruction instr) { | |||
|     Label l_loop_start; | ||||
|     L(l_loop_start); | ||||
| 
 | ||||
|     loop_break_label = Xbyak::Label(); | ||||
|     Compile_Block(instr.flow_control.dest_offset + 1); | ||||
| 
 | ||||
|     add(LOOPCOUNT_REG, LOOPINC); // Increment LOOPCOUNT_REG by Z-component
 | ||||
|     sub(LOOPCOUNT, 1);           // Increment loop count by 1
 | ||||
|     jnz(l_loop_start);           // Loop if not equal
 | ||||
|     L(*loop_break_label); | ||||
|     loop_break_label = boost::none; | ||||
| 
 | ||||
|     looping = false; | ||||
| } | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ | |||
| #include <cstddef> | ||||
| #include <utility> | ||||
| #include <vector> | ||||
| #include <boost/optional.hpp> | ||||
| #include <nihstro/shader_bytecode.h> | ||||
| #include <xbyak.h> | ||||
| #include "common/bit_set.h" | ||||
|  | @ -58,6 +59,7 @@ public: | |||
|     void Compile_MOV(Instruction instr); | ||||
|     void Compile_NOP(Instruction instr); | ||||
|     void Compile_END(Instruction instr); | ||||
|     void Compile_BREAKC(Instruction instr); | ||||
|     void Compile_CALL(Instruction instr); | ||||
|     void Compile_CALLC(Instruction instr); | ||||
|     void Compile_CALLU(Instruction instr); | ||||
|  | @ -119,6 +121,10 @@ private: | |||
|     /// Mapping of Pica VS instructions to pointers in the emitted code
 | ||||
|     std::array<Xbyak::Label, MAX_PROGRAM_CODE_LENGTH> instruction_labels; | ||||
| 
 | ||||
|     /// Label pointing to the end of the current LOOP block. Used by the BREAKC instruction to break
 | ||||
|     /// out of the loop.
 | ||||
|     boost::optional<Xbyak::Label> loop_break_label; | ||||
| 
 | ||||
|     /// Offsets in code where a return needs to be inserted
 | ||||
|     std::vector<unsigned> return_offsets; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue