1 #pragma once
2 
3 #include "Jitter_CodeGen_x86.h"
4 #include <deque>
5 
6 namespace Jitter
7 {
8 	class CCodeGen_x86_32 : public CCodeGen_x86
9 	{
10 	public:
11 											CCodeGen_x86_32();
12 		virtual								~CCodeGen_x86_32() = default;
13 
14 		void								SetImplicitRetValueParamFixUpRequired(bool);
15 
16 		unsigned int						GetAvailableRegisterCount() const override;
17 		unsigned int						GetAvailableMdRegisterCount() const override;
18 		bool								CanHold128BitsReturnValueInRegisters() const override;
19 		uint32								GetPointerSize() const override;
20 
21 	protected:
22 		enum SHIFTRIGHT_TYPE
23 		{
24 			SHIFTRIGHT_LOGICAL,
25 			SHIFTRIGHT_ARITHMETIC
26 		};
27 
28 		void								Emit_Prolog(const StatementList&, unsigned int) override;
29 		void								Emit_Epilog() override;
30 
31 		CX86Assembler::CAddress				MakeConstant128Address(const LITERAL128&) override;
32 
33 		//PARAM
34 		void								Emit_Param_Ctx(const STATEMENT&);
35 		void								Emit_Param_Reg(const STATEMENT&);
36 		void								Emit_Param_Mem(const STATEMENT&);
37 		void								Emit_Param_Cst(const STATEMENT&);
38 		void								Emit_Param_Mem64(const STATEMENT&);
39 		void								Emit_Param_Cst64(const STATEMENT&);
40 		void								Emit_Param_Reg128(const STATEMENT&);
41 		void								Emit_Param_Mem128(const STATEMENT&);
42 
43 		//PARAM_RET
44 		void								Emit_ParamRet_Mem128(const STATEMENT&);
45 
46 		//CALL
47 		void								Emit_Call(const STATEMENT&);
48 
49 		//RETURNVALUE
50 		void								Emit_RetVal_Tmp(const STATEMENT&);
51 		void								Emit_RetVal_Reg(const STATEMENT&);
52 		void								Emit_RetVal_Mem64(const STATEMENT&);
53 
54 		//EXTERNJMP
55 		void								Emit_ExternJmp(const STATEMENT&);
56 
57 		//MOV
58 		void								Emit_Mov_Mem64Mem64(const STATEMENT&);
59 		void								Emit_Mov_Mem64Cst64(const STATEMENT&);
60 		void								Emit_Mov_RegRefMemRef(const STATEMENT&);
61 
62 		//ADD64
63 		void								Emit_Add64_MemMemMem(const STATEMENT&);
64 		void								Emit_Add64_MemMemCst(const STATEMENT&);
65 
66 		//SUB64
67 		void								Emit_Sub64_MemMemMem(const STATEMENT&);
68 		void								Emit_Sub64_MemMemCst(const STATEMENT&);
69 		void								Emit_Sub64_MemCstMem(const STATEMENT&);
70 
71 		//AND64
72 		void								Emit_And64_MemMemMem(const STATEMENT&);
73 
74 		//SR64
75 		void								Emit_Sr64Var_MemMem(CSymbol*, CSymbol*, CX86Assembler::REGISTER, SHIFTRIGHT_TYPE);
76 		void								Emit_Sr64Cst_MemMem(CSymbol*, CSymbol*, uint32, SHIFTRIGHT_TYPE);
77 
78 		//SRL64
79 		void								Emit_Srl64_MemMemReg(const STATEMENT&);
80 		void								Emit_Srl64_MemMemMem(const STATEMENT&);
81 		void								Emit_Srl64_MemMemCst(const STATEMENT&);
82 
83 		//SRA64
84 		void								Emit_Sra64_MemMemReg(const STATEMENT&);
85 		void								Emit_Sra64_MemMemMem(const STATEMENT&);
86 		void								Emit_Sra64_MemMemCst(const STATEMENT&);
87 
88 		//SLL64
89 		void								Emit_Sll64_MemMemVar(const STATEMENT&, CX86Assembler::REGISTER);
90 		void								Emit_Sll64_MemMemReg(const STATEMENT&);
91 		void								Emit_Sll64_MemMemMem(const STATEMENT&);
92 		void								Emit_Sll64_MemMemCst(const STATEMENT&);
93 
94 		//CMP
95 		void								Emit_Cmp_VarVarVar(const STATEMENT&);
96 		void								Emit_Cmp_VarVarCst(const STATEMENT&);
97 
98 		//CMP64
99 		void								Cmp64_Equal(const STATEMENT&);
100 		template <typename> void			Cmp64_Order(const STATEMENT&);
101 		void								Cmp64_GenericRel(const STATEMENT&);
102 		void								Emit_Cmp64_RegRelRel(const STATEMENT&);
103 		void								Emit_Cmp64_RelRelRel(const STATEMENT&);
104 		void								Emit_Cmp64_RegRelCst(const STATEMENT&);
105 		void								Emit_Cmp64_RelRelCst(const STATEMENT&);
106 		void								Emit_Cmp64_TmpRelRoc(const STATEMENT&);
107 
108 		//RELTOREF
109 		void								Emit_RelToRef_VarCst(const STATEMENT&);
110 
111 		//ADDREF
112 		void								Emit_AddRef_VarVarVar(const STATEMENT&);
113 		void								Emit_AddRef_VarVarCst(const STATEMENT&);
114 
115 		//ISREFNULL
116 		void								Emit_IsRefNull_VarVar(const STATEMENT&);
117 
118 		//LOADFROMREF
119 		void								Emit_LoadFromRef_64_MemVar(const STATEMENT&);
120 		void								Emit_LoadFromRef_Ref_VarVar(const STATEMENT&);
121 
122 		//STOREATREF
123 		void								Emit_StoreAtRef_64_VarMem(const STATEMENT&);
124 		void								Emit_StoreAtRef_64_VarCst(const STATEMENT&);
125 
126 		//STORE8ATREF
127 		void								Emit_Store8AtRef_VarVar(const STATEMENT&);
128 
129 		//CONDJMP
130 		void								Emit_CondJmp_Ref_VarCst(const STATEMENT&);
131 
132 	private:
133 		struct CALL_STATE
134 		{
135 			uint32	paramOffset = 0;
136 			uint32	paramSpillOffset = 0;
137 		};
138 
139 		typedef std::function<void (CALL_STATE&)> ParamEmitterFunction;
140 		typedef std::deque<ParamEmitterFunction> ParamStack;
141 
142 		typedef void (CCodeGen_x86_32::*ConstCodeEmitterType)(const STATEMENT&);
143 
144 		struct CONSTMATCHER
145 		{
146 			OPERATION				op;
147 			MATCHTYPE				dstType;
148 			MATCHTYPE				src1Type;
149 			MATCHTYPE				src2Type;
150 			ConstCodeEmitterType	emitter;
151 		};
152 
153 		enum MAX_REGISTERS
154 		{
155 			MAX_REGISTERS = 3,
156 			MAX_MDREGISTERS = 4,
157 		};
158 
159 		CX86Assembler::REGISTER				PrepareRefSymbolRegisterDef(CSymbol*, CX86Assembler::REGISTER);
160 		CX86Assembler::REGISTER				PrepareRefSymbolRegisterUse(CSymbol*, CX86Assembler::REGISTER) override;
161 		void								CommitRefSymbolRegister(CSymbol*, CX86Assembler::REGISTER);
162 
163 		static CONSTMATCHER					g_constMatchers[];
164 		static CX86Assembler::REGISTER		g_registers[MAX_REGISTERS];
165 		static CX86Assembler::XMMREGISTER	g_mdRegisters[MAX_MDREGISTERS];
166 
167 		ParamStack							m_params;
168 		uint32								m_paramSpillBase = 0;
169 		uint32								m_totalStackAlloc = 0;
170 		uint32								m_literalStackAlloc = 0;
171 		uint32								m_literalBase = 0;
172 		int32								m_mdMakeSzConstantOffset = -1;
173 		bool								m_hasImplicitRetValueParam = false;
174 		bool								m_implicitRetValueParamFixUpRequired = false;
175 	};
176 }
177