xref: /php-src/ext/opcache/jit/ir/ir_x86.h (revision 29a70828)
1 /*
2  * IR - Lightweight JIT Compilation Framework
3  * (x86/x86_64 CPU specific definitions)
4  * Copyright (C) 2022 Zend by Perforce.
5  * Authors: Dmitry Stogov <dmitry@php.net>
6  */
7 
8 #ifndef IR_X86_H
9 #define IR_X86_H
10 
11 #if defined(IR_TARGET_X64)
12 # define IR_GP_REGS(_) \
13 	_(R0,   rax,   eax,   ax,   al, ah) \
14 	_(R1,   rcx,   ecx,   cx,   cl, ch) \
15 	_(R2,   rdx,   edx,   dx,   dl, dh) \
16 	_(R3,   rbx,   ebx,   bx,   bl, bh) \
17 	_(R4,   rsp,   esp,   __,   __, __) \
18 	_(R5,   rbp,   ebp,   bp,  r5b, __) \
19 	_(R6,   rsi,   esi,   si,  r6b, __) \
20 	_(R7,   rdi,   edi,   di,  r7b, __) \
21 	_(R8,   r8,    r8d,  r8w,  r8b, __) \
22 	_(R9,   r9,    r9d,  r9w,  r9b, __) \
23 	_(R10,  r10,  r10d, r10w, r10b, __) \
24 	_(R11,  r11,  r11d, r11w, r11b, __) \
25 	_(R12,  r12,  r12d, r12w, r12b, __) \
26 	_(R13,  r13,  r13d, r13w, r13b, __) \
27 	_(R14,  r14,  r14d, r14w, r14b, __) \
28 	_(R15,  r15,  r15d, r15w, r15b, __) \
29 
30 # define IR_FP_REGS(_) \
31 	_(XMM0,  xmm0) \
32 	_(XMM1,  xmm1) \
33 	_(XMM2,  xmm2) \
34 	_(XMM3,  xmm3) \
35 	_(XMM4,  xmm4) \
36 	_(XMM5,  xmm5) \
37 	_(XMM6,  xmm6) \
38 	_(XMM7,  xmm7) \
39 	_(XMM8,  xmm8) \
40 	_(XMM9,  xmm9) \
41 	_(XMM10, xmm10) \
42 	_(XMM11, xmm11) \
43 	_(XMM12, xmm12) \
44 	_(XMM13, xmm13) \
45 	_(XMM14, xmm14) \
46 	_(XMM15, xmm15) \
47 
48 #elif defined(IR_TARGET_X86)
49 
50 # define IR_GP_REGS(_) \
51 	_(R0,   ___,   eax,   ax,   al, ah) \
52 	_(R1,   ___,   ecx,   cx,   cl, ch) \
53 	_(R2,   ___,   edx,   dx,   dl, dh) \
54 	_(R3,   ___,   ebx,   bx,   bl, bh) \
55 	_(R4,   ___,   esp,   __,   __, __) \
56 	_(R5,   ___,   ebp,   bp,   __, __) \
57 	_(R6,   ___,   esi,   si,   __, __) \
58 	_(R7,   ___,   edi,   di,   __, __) \
59 
60 # define IR_FP_REGS(_) \
61 	_(XMM0,  xmm0) \
62 	_(XMM1,  xmm1) \
63 	_(XMM2,  xmm2) \
64 	_(XMM3,  xmm3) \
65 	_(XMM4,  xmm4) \
66 	_(XMM5,  xmm5) \
67 	_(XMM6,  xmm6) \
68 	_(XMM7,  xmm7) \
69 
70 #else
71 # error "Unsupported target architecture"
72 #endif
73 
74 #define IR_GP_REG_ENUM(code, name64, name32, name16, name8, name8h) \
75 	IR_REG_ ## code,
76 
77 #define IR_FP_REG_ENUM(code, name) \
78 	IR_REG_ ## code,
79 
80 enum _ir_reg {
81 	_IR_REG_NONE = -1,
82 	IR_GP_REGS(IR_GP_REG_ENUM)
83 	IR_FP_REGS(IR_FP_REG_ENUM)
84 	IR_REG_NUM,
85 };
86 
87 #define IR_REG_GP_FIRST IR_REG_R0
88 #define IR_REG_FP_FIRST IR_REG_XMM0
89 #define IR_REG_GP_LAST  (IR_REG_FP_FIRST - 1)
90 #define IR_REG_FP_LAST  (IR_REG_NUM - 1)
91 #define IR_REG_SCRATCH  (IR_REG_NUM)        /* special name for regset */
92 #define IR_REG_ALL      (IR_REG_NUM + 1)    /* special name for regset */
93 
94 #define IR_REGSET_64BIT 0
95 
96 #define IR_REG_STACK_POINTER \
97 	IR_REG_RSP
98 #define IR_REG_FRAME_POINTER \
99 	IR_REG_RBP
100 #define IR_REGSET_FIXED \
101 	(IR_REGSET(IR_REG_RSP))
102 #define IR_REGSET_GP \
103 	IR_REGSET_DIFFERENCE(IR_REGSET_INTERVAL(IR_REG_GP_FIRST, IR_REG_GP_LAST), IR_REGSET_FIXED)
104 #define IR_REGSET_FP \
105 	IR_REGSET_DIFFERENCE(IR_REGSET_INTERVAL(IR_REG_FP_FIRST, IR_REG_FP_LAST), IR_REGSET_FIXED)
106 
107 #define IR_REG_RAX IR_REG_R0
108 #define IR_REG_RCX IR_REG_R1
109 #define IR_REG_RDX IR_REG_R2
110 #define IR_REG_RBX IR_REG_R3
111 #define IR_REG_RSP IR_REG_R4
112 #define IR_REG_RBP IR_REG_R5
113 #define IR_REG_RSI IR_REG_R6
114 #define IR_REG_RDI IR_REG_R7
115 
116 /* Calling Convention */
117 #ifdef _WIN64
118 
119 # define IR_REG_INT_RET1 IR_REG_RAX
120 # define IR_REG_FP_RET1  IR_REG_XMM0
121 # define IR_REG_INT_ARGS 4
122 # define IR_REG_FP_ARGS  4
123 # define IR_REG_INT_ARG1 IR_REG_RCX
124 # define IR_REG_INT_ARG2 IR_REG_RDX
125 # define IR_REG_INT_ARG3 IR_REG_R8
126 # define IR_REG_INT_ARG4 IR_REG_R9
127 # define IR_REG_FP_ARG1  IR_REG_XMM0
128 # define IR_REG_FP_ARG2  IR_REG_XMM1
129 # define IR_REG_FP_ARG3  IR_REG_XMM2
130 # define IR_REG_FP_ARG4  IR_REG_XMM3
131 # define IR_MAX_REG_ARGS 4
132 # define IR_SHADOW_ARGS  32 /* Reserved space in bytes - "home space" or "shadow store" for register arguments */
133 
134 # define IR_REGSET_SCRATCH \
135 	(IR_REGSET_INTERVAL(IR_REG_RAX, IR_REG_RDX) \
136 	| IR_REGSET_INTERVAL(IR_REG_R8, IR_REG_R11) \
137 	| IR_REGSET_INTERVAL(IR_REG_XMM0, IR_REG_XMM5))
138 
139 # define IR_REGSET_PRESERVED \
140 	(IR_REGSET(IR_REG_RBX) \
141 	| IR_REGSET_INTERVAL(IR_REG_RBP, IR_REG_RDI) \
142 	| IR_REGSET_INTERVAL(IR_REG_R12, IR_REG_R15) \
143 	| IR_REGSET_INTERVAL(IR_REG_XMM6, IR_REG_XMM15))
144 
145 #elif defined(IR_TARGET_X64)
146 
147 # define IR_REG_INT_RET1 IR_REG_RAX
148 # define IR_REG_FP_RET1  IR_REG_XMM0
149 # define IR_REG_INT_ARGS 6
150 # define IR_REG_FP_ARGS  8
151 # define IR_REG_INT_ARG1 IR_REG_RDI
152 # define IR_REG_INT_ARG2 IR_REG_RSI
153 # define IR_REG_INT_ARG3 IR_REG_RDX
154 # define IR_REG_INT_ARG4 IR_REG_RCX
155 # define IR_REG_INT_ARG5 IR_REG_R8
156 # define IR_REG_INT_ARG6 IR_REG_R9
157 # define IR_REG_FP_ARG1  IR_REG_XMM0
158 # define IR_REG_FP_ARG2  IR_REG_XMM1
159 # define IR_REG_FP_ARG3  IR_REG_XMM2
160 # define IR_REG_FP_ARG4  IR_REG_XMM3
161 # define IR_REG_FP_ARG5  IR_REG_XMM4
162 # define IR_REG_FP_ARG6  IR_REG_XMM5
163 # define IR_REG_FP_ARG7  IR_REG_XMM6
164 # define IR_REG_FP_ARG8  IR_REG_XMM7
165 # define IR_MAX_REG_ARGS 14
166 # define IR_SHADOW_ARGS  0
167 
168 # define IR_REG_VARARG_FP_REGS IR_REG_RAX /* hidden argument to specify the number of vector registers used */
169 
170 # define IR_REGSET_SCRATCH \
171 	(IR_REGSET_INTERVAL(IR_REG_RAX, IR_REG_RDX) \
172 	| IR_REGSET_INTERVAL(IR_REG_RSI, IR_REG_RDI) \
173 	| IR_REGSET_INTERVAL(IR_REG_R8, IR_REG_R11) \
174 	| IR_REGSET_FP)
175 
176 # define IR_REGSET_PRESERVED \
177 	(IR_REGSET(IR_REG_RBX) \
178 	| IR_REGSET(IR_REG_RBP) \
179 	| IR_REGSET_INTERVAL(IR_REG_R12, IR_REG_R15))
180 
181 typedef struct _ir_va_list {
182 	uint32_t  gp_offset;
183 	uint32_t  fp_offset;
184 	void     *overflow_arg_area;
185 	void     *reg_save_area;
186 } ir_va_list;
187 
188 #elif defined(IR_TARGET_X86)
189 
190 # define IR_REG_INT_RET1   IR_REG_RAX
191 # define IR_REG_INT_RET2   IR_REG_RDX
192 # define IR_REG_INT_ARGS   0
193 # define IR_REG_FP_ARGS    0
194 
195 # define IR_HAVE_FASTCALL  1
196 # define IR_REG_INT_FCARGS 2
197 # define IR_REG_FP_FCARGS  0
198 # define IR_REG_INT_FCARG1 IR_REG_RCX
199 # define IR_REG_INT_FCARG2 IR_REG_RDX
200 # define IR_MAX_REG_ARGS   2
201 # define IR_SHADOW_ARGS    0
202 
203 # define IR_REGSET_SCRATCH \
204 	(IR_REGSET_INTERVAL(IR_REG_RAX, IR_REG_RDX) | IR_REGSET_FP)
205 
206 # define IR_REGSET_PRESERVED \
207 	(IR_REGSET(IR_REG_RBX) \
208 	| IR_REGSET(IR_REG_RBP) \
209 	| IR_REGSET_INTERVAL(IR_REG_RSI, IR_REG_RDI))
210 
211 #else
212 # error "Unsupported target architecture"
213 #endif
214 
215 typedef struct _ir_tmp_reg {
216 	union {
217 		uint8_t num;
218 		int8_t  reg;
219 	};
220 	uint8_t     type;
221 	uint8_t     start;
222 	uint8_t     end;
223 } ir_tmp_reg;
224 
225 struct _ir_target_constraints {
226 	int8_t      def_reg;
227 	uint8_t     tmps_count;
228 	uint8_t     hints_count;
229 	ir_tmp_reg  tmp_regs[3];
230 	int8_t      hints[IR_MAX_REG_ARGS + 3];
231 };
232 
233 #endif /* IR_X86_H */
234