Line data Source code
1 : /*
2 : ** This file has been pre-processed with DynASM.
3 : ** https://luajit.org/dynasm.html
4 : ** DynASM version 1.5.0, DynASM x64 version 1.5.0
5 : ** DO NOT EDIT! The original file is in "fd_jit_compiler.dasc".
6 : */
7 :
8 : #line 1 "fd_jit_compiler.dasc"
9 : /* WARNING: WORK IN PROGRESS!
10 : This is an experimental version of the Firedancer JIT compiler.
11 : It is disabled in production. There are known security issues in
12 : this code. It is not covered by the Firedancer bug bounty policy.
13 :
14 : ### fd_vm_interp compatibility
15 :
16 : fd_jit aims for exact compatibility with fd_vm_interp unless
17 : otherwise noted.
18 :
19 : ### Optimizations
20 :
21 : The fd_jit transpiler does not implement any optimizations.
22 :
23 : ### Error Handling
24 :
25 : VM faults (e.g. segfault, divide by zero, CU overrun, invalid call
26 : destination, program EOF, syscall error) are detected reliably and
27 : deterministically.
28 :
29 : However, after a fault happens, any VM state becomes unreliable
30 : (non-deterministic or undefined). Unreliable fault state include CU
31 : left, current PC, and the error code.
32 :
33 : A VM fault usually triggers ->longjmp, transitioning back into the
34 : fd_jit_execute call frame. */
35 :
36 : #include "../../../util/fd_util_base.h"
37 :
38 : /* Include dynasm headers. These fail to compile when some strict
39 : checks are enabled. */
40 :
41 : void fd_dasm_grow_check( void * ptr, ulong min_sz );
42 0 : #define DASM_M_GROW(ctx, t, p, sz, need) (fd_dasm_grow_check( (p), (need) ))
43 0 : #define DASM_M_FREE(ctx, p, sz) do{}while(0)
44 :
45 : #pragma GCC diagnostic push
46 : #pragma GCC diagnostic ignored "-Wconversion"
47 : #pragma GCC diagnostic ignored "-Wsign-conversion"
48 : #pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
49 : #include "dasm_proto.h"
50 : #include "dasm_x86.h"
51 : #pragma GCC diagnostic pop
52 :
53 : #include "fd_jit_private.h"
54 : #include "../fd_vm_private.h"
55 :
56 : //| .arch x64
57 : #if DASM_VERSION != 10500
58 : #error "Version mismatch between DynASM and included encoding engine"
59 : #endif
60 : #line 49 "fd_jit_compiler.dasc"
61 : //| .actionlist actions
62 : static const unsigned char actions[1657] = {
63 : 254,0,248,10,100,72,139,4,37,237,72,137,176,233,76,137,152,233,76,137,160,
64 : 233,76,137,168,233,76,137,176,233,76,137,184,233,72,137,152,233,72,137,136,
65 : 233,76,137,128,233,76,137,136,233,76,137,144,233,195,255,248,11,100,72,139,
66 : 4,37,237,72,139,176,233,76,139,152,233,76,139,160,233,76,139,168,233,76,139,
67 : 176,233,76,139,184,233,72,139,152,233,72,139,136,233,76,139,128,233,76,139,
68 : 136,233,76,139,144,233,195,255,248,12,137,252,250,72,193,252,239,32,209,231,
69 : 252,233,244,13,255,248,14,137,252,250,72,193,252,239,32,141,60,125,1,0,0,
70 : 0,255,248,13,255,252,233,244,15,255,252,233,244,16,255,248,15,137,252,250,
71 : 72,193,252,239,32,100,59,60,37,237,15,131,244,17,1,213,15,130,244,17,100,
72 : 59,20,189,237,15,131,244,17,49,252,237,131,252,255,2,184,0,16,0,0,15,68,232,
73 : 33,252,234,15,131,244,17,100,72,3,20,252,253,237,195,255,248,16,100,59,60,
74 : 37,237,15,131,244,17,1,213,15,130,244,17,100,59,20,189,237,15,131,244,17,
75 : 100,72,3,20,252,253,237,195,255,248,17,72,193,231,32,72,9,215,100,72,137,
76 : 60,37,237,72,139,60,36,100,72,137,60,37,237,252,233,244,18,255,248,19,73,
77 : 187,237,237,73,137,155,233,73,137,171,233,77,137,99,16,77,137,107,24,77,137,
78 : 115,32,77,137,123,40,72,141,84,36,8,73,137,83,48,72,139,20,36,73,137,83,56,
79 : 49,192,49,210,195,255,248,20,72,137,252,248,186,1,0,0,0,72,191,237,237,72,
80 : 139,159,233,72,139,175,233,76,139,103,16,76,139,111,24,76,139,119,32,76,139,
81 : 127,40,72,139,103,48,252,255,119,56,195,255,248,21,232,244,10,232,244,10,
82 : 72,137,229,72,131,228,252,240,72,131,252,236,16,100,76,139,28,37,237,100,
83 : 76,139,151,233,76,137,223,72,139,176,233,72,139,144,233,72,139,136,233,76,
84 : 139,128,233,76,139,136,233,76,141,152,233,65,83,65,252,255,210,133,252,255,
85 : 15,133,244,18,72,137,252,236,232,244,11,195,255,248,22,100,72,139,60,37,237,
86 : 72,252,255,135,233,95,83,81,65,80,65,81,73,129,194,0,32,0,0,252,255,231,255,
87 : 248,23,100,72,139,60,37,237,72,252,255,143,233,95,65,89,65,88,89,91,73,129,
88 : 252,234,0,32,0,0,252,255,231,255,248,18,191,237,252,233,244,20,255,248,24,
89 : 255,232,244,19,133,210,15,133,244,247,255,232,244,11,72,131,252,236,32,252,
90 : 255,215,72,137,252,247,232,244,20,248,1,195,255,249,255,64,129,192,240,43,
91 : 239,255,252,233,245,255,72,129,192,240,35,239,255,64,1,192,240,131,240,51,
92 : 255,72,1,192,240,131,240,35,255,64,129,232,240,43,239,255,72,129,252,248,
93 : 240,35,239,255,15,132,245,255,72,129,232,240,35,239,255,64,49,192,240,131,
94 : 240,51,255,72,199,192,240,35,237,255,64,41,192,240,131,240,51,255,72,57,192,
95 : 240,131,240,35,15,132,245,255,72,41,192,240,131,240,35,255,64,105,192,240,
96 : 131,240,51,239,255,72,129,252,248,240,35,239,15,135,245,255,72,105,192,240,
97 : 131,240,35,239,255,64,15,175,192,240,132,240,52,255,72,57,192,240,131,240,
98 : 35,15,135,245,255,72,15,175,192,240,132,240,36,255,64,144,240,42,49,210,191,
99 : 237,252,247,252,247,64,144,240,42,255,72,129,252,248,240,35,239,15,131,245,
100 : 255,72,144,240,34,49,210,72,199,199,237,72,252,247,252,247,72,144,240,34,
101 : 255,64,133,192,240,131,240,51,15,132,244,18,255,64,184,240,42,1,0,0,0,255,
102 : 64,144,240,42,49,210,64,252,247,252,240,240,43,64,144,240,42,255,72,57,192,
103 : 240,131,240,35,15,131,245,255,72,133,192,240,131,240,35,15,132,244,18,255,
104 : 72,144,240,34,49,210,72,252,247,252,240,240,35,72,144,240,34,255,64,129,200,
105 : 240,43,239,255,72,252,247,192,240,35,237,15,133,245,255,72,129,200,240,35,
106 : 239,255,64,9,192,240,131,240,51,255,72,133,192,240,131,240,35,15,133,245,
107 : 255,72,9,192,240,131,240,35,255,64,129,224,240,43,239,255,72,129,252,248,
108 : 240,35,239,15,133,245,255,72,129,224,240,35,239,255,64,33,192,240,131,240,
109 : 51,255,72,57,192,240,131,240,35,15,133,245,255,72,33,192,240,131,240,35,255,
110 : 72,141,184,253,240,3,233,189,3,0,0,0,232,244,12,64,139,2,240,139,255,72,141,
111 : 184,253,240,3,233,189,3,0,0,0,232,244,14,199,2,237,255,72,141,184,253,240,
112 : 3,233,189,3,0,0,0,232,244,14,64,137,2,240,139,255,64,193,224,240,43,235,255,
113 : 72,129,252,248,240,35,239,15,143,245,255,72,193,224,240,35,235,255,72,141,
114 : 184,253,240,3,233,189,1,0,0,0,232,244,12,64,49,192,240,131,240,51,102,64,
115 : 139,2,240,139,255,72,141,184,253,240,3,233,189,1,0,0,0,232,244,14,102,199,
116 : 2,236,255,72,141,184,253,240,3,233,189,1,0,0,0,232,244,14,64,137,2,240,139,
117 : 255,64,136,193,240,131,64,211,224,240,43,255,72,57,192,240,131,240,35,15,
118 : 143,245,255,64,136,193,240,131,72,211,224,240,35,255,72,141,184,253,240,3,
119 : 233,49,252,237,232,244,12,255,64,49,192,240,131,240,51,64,138,2,240,131,255,
120 : 72,141,184,253,240,3,233,49,252,237,232,244,14,198,2,235,255,72,141,184,253,
121 : 240,3,233,49,252,237,232,244,14,64,136,2,240,131,255,64,193,232,240,43,235,
122 : 255,72,129,252,248,240,35,239,15,141,245,255,72,193,232,240,35,235,255,72,
123 : 141,184,253,240,3,233,189,7,0,0,0,232,244,12,72,139,2,240,131,255,72,141,
124 : 184,253,240,3,233,189,7,0,0,0,232,244,14,199,2,237,199,66,4,0,0,0,0,255,72,
125 : 141,184,253,240,3,233,189,7,0,0,0,232,244,14,72,137,2,240,131,255,64,136,
126 : 193,240,131,64,211,232,240,43,255,72,57,192,240,131,240,35,15,141,245,255,
127 : 64,136,193,240,131,72,211,232,240,35,255,64,252,247,216,240,43,255,232,244,
128 : 22,232,245,255,72,199,199,237,232,244,21,255,72,252,247,216,240,35,255,64,
129 : 144,240,42,49,210,191,237,252,247,252,247,64,135,208,240,43,255,232,244,23,
130 : 195,255,64,184,240,42,0,0,0,0,255,64,144,240,42,49,210,64,252,247,252,240,
131 : 240,43,64,135,208,240,43,255,72,144,240,34,49,210,72,252,247,252,240,240,
132 : 35,72,135,208,240,35,255,64,129,252,240,240,43,239,255,72,129,252,248,240,
133 : 35,239,15,130,245,255,72,129,252,240,240,35,239,255,72,57,192,240,131,240,
134 : 35,15,130,245,255,72,49,192,240,131,240,35,255,64,184,240,42,237,255,72,129,
135 : 252,248,240,35,239,15,134,245,255,64,137,192,240,131,240,51,255,72,57,192,
136 : 240,131,240,35,15,134,245,255,72,137,192,240,131,240,35,255,64,193,252,248,
137 : 240,43,235,255,72,129,252,248,240,35,239,15,140,245,255,72,193,252,248,240,
138 : 35,235,255,64,136,193,240,131,64,211,252,248,240,43,255,72,57,192,240,131,
139 : 240,35,15,140,245,255,64,136,193,240,131,72,211,252,248,240,35,255,72,129,
140 : 252,248,240,35,239,15,142,245,255,64,15,183,192,240,132,240,52,102,64,193,
141 : 200,240,43,8,255,64,15,200,240,43,255,72,15,200,240,35,255,72,57,192,240,
142 : 131,240,35,15,142,245,255,248,25,252,233,244,18,255
143 : };
144 :
145 : #line 50 "fd_jit_compiler.dasc"
146 : //| .globals fd_jit_lbl_
147 : enum {
148 : fd_jit_lbl_save_regs,
149 : fd_jit_lbl_restore_regs,
150 : fd_jit_lbl_fd_jit_vm_translate_ro,
151 : fd_jit_lbl_fd_jit_vm_translate,
152 : fd_jit_lbl_fd_jit_vm_translate_rw,
153 : fd_jit_lbl_fd_jit_vm_translate_abiv1,
154 : fd_jit_lbl_fd_jit_vm_translate_abiv2,
155 : fd_jit_lbl_translate_fail,
156 : fd_jit_lbl_vm_fault,
157 : fd_jit_lbl_setjmp,
158 : fd_jit_lbl_longjmp,
159 : fd_jit_lbl_emulate_syscall,
160 : fd_jit_lbl_call_stack_push,
161 : fd_jit_lbl_call_stack_pop,
162 : fd_jit_lbl_entrypoint,
163 : fd_jit_lbl_overrun,
164 : fd_jit_lbl__MAX
165 : };
166 : #line 51 "fd_jit_compiler.dasc"
167 : //| .section code
168 : #define DASM_SECTION_CODE 0
169 3 : #define DASM_MAXSECTION 1
170 : #line 52 "fd_jit_compiler.dasc"
171 :
172 : fd_jit_scratch_layout_t *
173 : fd_jit_scratch_layout( fd_jit_scratch_layout_t * layout,
174 6 : ulong bpf_sz ) {
175 :
176 6 : if( FD_UNLIKELY( bpf_sz > (1UL<<24) ) ) return NULL;
177 6 : ulong text_cnt = bpf_sz / 8UL;
178 :
179 : /* These "magic" values are taken from dasm_x86.h */
180 :
181 6 : ulong dasm_sz = DASM_PSZ( DASM_MAXSECTION ); /* dasm_x86.h(89) */
182 6 : ulong lglabels_sz = (10+fd_jit_lbl__MAX)*sizeof(int); /* dasm_x86.h(119) */
183 6 : ulong pclabels_sz = text_cnt*sizeof(int); /* dasm_x86.h(127) */
184 6 : ulong code_sz = fd_jit_est_code_sz( bpf_sz );
185 :
186 6 : memset( layout, 0, sizeof(fd_jit_scratch_layout_t) );
187 6 : FD_SCRATCH_ALLOC_INIT( l, 0 );
188 6 : layout->dasm_off = (ulong)FD_SCRATCH_ALLOC_APPEND( l, 16UL, dasm_sz );
189 0 : layout->dasm_sz = dasm_sz;
190 6 : layout->lglabels_off = (ulong)FD_SCRATCH_ALLOC_APPEND( l, 16UL, lglabels_sz );
191 0 : layout->lglabels_sz = lglabels_sz;
192 6 : layout->pclabels_off = (ulong)FD_SCRATCH_ALLOC_APPEND( l, 16UL, pclabels_sz );
193 0 : layout->pclabels_sz = pclabels_sz;
194 6 : layout->code_off = (ulong)FD_SCRATCH_ALLOC_APPEND( l, 16UL, code_sz );
195 0 : layout->code_sz = code_sz;
196 6 : layout->sz = (ulong)FD_SCRATCH_ALLOC_FINI( l, 16UL );
197 6 : return layout;
198 6 : }
199 :
200 : dasm_State *
201 : fd_jit_prepare( void * scratch,
202 3 : fd_jit_scratch_layout_t const * layout ) {
203 :
204 : /* Custom dasm_init */
205 3 : dasm_State * d = (void *)( (ulong)scratch + layout->dasm_off );
206 3 : fd_memset( d, 0, layout->dasm_sz );
207 3 : d->psize = layout->dasm_sz;
208 3 : d->maxsection = DASM_MAXSECTION;
209 :
210 : /* Custom dasm_setupglobal */
211 3 : d->globals = fd_jit_labels;
212 3 : d->lglabels = (void *)( (ulong)scratch + layout->lglabels_off );
213 3 : d->lgsize = layout->lglabels_sz;
214 :
215 : /* Custom dasm_growpc */
216 3 : d->pcsize = layout->pclabels_sz;
217 3 : d->pclabels = (void *)( (ulong)scratch + layout->pclabels_off );
218 :
219 : /* Setup encoder. Zeros lglabels and pclabels. */
220 3 : dasm_setup( &d, actions );
221 :
222 : /* Preallocate space for .code section
223 : See dasm_x86.h(172) */
224 3 : dasm_Section * code = d->sections + 0;
225 3 : code->buf = (void *)( (ulong)scratch + layout->code_off );
226 3 : code->bsize = layout->code_sz;
227 3 : code->pos = 0;
228 3 : code->rbuf = code->buf;
229 3 : code->epos = (int)( ((ulong)code->bsize / sizeof(int)) - DASM_MAXSECPOS );
230 3 : code->ofs = 0;
231 :
232 3 : return d;
233 3 : }
234 :
235 : /* Compile time thread locals */
236 :
237 : FD_TL void * fd_jit_labels[ FD_JIT_LABEL_CNT ];
238 : FD_STATIC_ASSERT( sizeof(fd_jit_labels)==fd_jit_lbl__MAX*8, label_cnt );
239 :
240 : /* Mapping between sBPF registers and x86_64 registers *****************
241 :
242 : This mapping is valid just before a translated sBPF instruction is
243 : about to be executed. (At the `=>next_label` token in the code gen
244 : loop)
245 :
246 : BPF | r0 | r1 | r2 | r3 | r4 | r5 | r6 | r7 | r8 | r9 | r10
247 : X86 | rsi | r11 | r12 | r13 | r14 | r15 | rbx | rcx | r8 | r9 | r10
248 :
249 : x86_64 GPRs rax, rdi, rdx, rbp do not map to sBPF registers. Those can
250 : be used as scratch registers for complex opcodes.
251 :
252 : Note that this mapping cannot be trivially changed. Certain x86
253 : instructions (like div) have hardcoded register accesses which the
254 : JIT code works around.
255 :
256 : dynasm macros bpf_r{...} resolve to 64-bit register names.
257 :
258 : reg_bpf2x86 is indexed by sBPF register numbers and resolves to the
259 : x86_64 dynasm register index. */
260 :
261 : static uchar const reg_bpf2x86[11] = {
262 : [ 0] = FD_DASM_RSI,
263 : //| .define bpf_r0, rsi
264 : [ 1] = FD_DASM_R11,
265 : //| .define bpf_r1, r11
266 : [ 2] = FD_DASM_R12,
267 : //| .define bpf_r2, r12
268 : [ 3] = FD_DASM_R13,
269 : //| .define bpf_r3, r13
270 : [ 4] = FD_DASM_R14,
271 : //| .define bpf_r4, r14
272 : [ 5] = FD_DASM_R15,
273 : //| .define bpf_r5, r15
274 : [ 6] = FD_DASM_RBX,
275 : //| .define bpf_r6, rbx
276 : [ 7] = FD_DASM_RCX,
277 : //| .define bpf_r7, rcx
278 : [ 8] = FD_DASM_R8,
279 : //| .define bpf_r8, r8
280 : [ 9] = FD_DASM_R9,
281 : //| .define bpf_r9, r9
282 : [10] = FD_DASM_R10
283 : //| .define bpf_r10, r10
284 : };
285 :
286 :
287 : /* JIT compiler *******************************************************/
288 :
289 : void
290 : fd_jit_compile( struct dasm_State ** Dst,
291 : fd_sbpf_program_t const * prog,
292 0 : fd_sbpf_syscalls_t const * syscalls ) {
293 :
294 0 : int const abiv2 = 0; /* For now, only support ABIv1 */
295 :
296 : //| .code
297 0 : dasm_put(Dst, 0);
298 0 : #line 178 "fd_jit_compiler.dasc"
299 :
300 : /* Derive offsets of thread locals in FS "segment" */
301 :
302 0 : # if defined(__FSGSBASE__)
303 0 : ulong fs_base = __builtin_ia32_rdfsbase64();
304 : # else
305 : ulong fs_base; __asm__( "mov %%fs:0, %0" : "=r"(fs_base) );
306 : # endif
307 0 : # define FS_RELATIVE(ptr) ((uint)( (ulong)(ptr) - fs_base ))
308 0 : uint fd_jit_vm_tpoff = FS_RELATIVE( &fd_jit_vm );
309 0 : uint fd_jit_syscalls_tpoff = FS_RELATIVE( &fd_jit_syscalls );
310 0 : uint fd_jit_segment_cnt_tpoff = FS_RELATIVE( &fd_jit_segment_cnt );
311 0 : uint fd_jit_mem_sz_tpoff = FS_RELATIVE( fd_jit_mem_sz );
312 0 : uint fd_jit_mem_haddr_tpoff = FS_RELATIVE( fd_jit_mem_haddr );
313 0 : uint fd_jit_segfault_vaddr_tpoff = FS_RELATIVE( &fd_jit_segfault_vaddr );
314 0 : uint fd_jit_segfault_rip_tpoff = FS_RELATIVE( &fd_jit_segfault_rip );
315 0 : # undef FD_RELATIVE
316 :
317 : //|->save_regs:
318 : //| fs
319 : //| mov rax, [fd_jit_vm_tpoff]
320 : //| mov [rax + offsetof(fd_vm_t, reg[ 0])], bpf_r0
321 : //| mov [rax + offsetof(fd_vm_t, reg[ 1])], bpf_r1
322 : //| mov [rax + offsetof(fd_vm_t, reg[ 2])], bpf_r2
323 : //| mov [rax + offsetof(fd_vm_t, reg[ 3])], bpf_r3
324 : //| mov [rax + offsetof(fd_vm_t, reg[ 4])], bpf_r4
325 : //| mov [rax + offsetof(fd_vm_t, reg[ 5])], bpf_r5
326 : //| mov [rax + offsetof(fd_vm_t, reg[ 6])], bpf_r6
327 : //| mov [rax + offsetof(fd_vm_t, reg[ 7])], bpf_r7
328 : //| mov [rax + offsetof(fd_vm_t, reg[ 8])], bpf_r8
329 : //| mov [rax + offsetof(fd_vm_t, reg[ 9])], bpf_r9
330 : //| mov [rax + offsetof(fd_vm_t, reg[10])], bpf_r10
331 : //| ret
332 0 : dasm_put(Dst, 2, fd_jit_vm_tpoff, offsetof(fd_vm_t, reg[ 0]), offsetof(fd_vm_t, reg[ 1]), offsetof(fd_vm_t, reg[ 2]), offsetof(fd_vm_t, reg[ 3]), offsetof(fd_vm_t, reg[ 4]), offsetof(fd_vm_t, reg[ 5]), offsetof(fd_vm_t, reg[ 6]), offsetof(fd_vm_t, reg[ 7]), offsetof(fd_vm_t, reg[ 8]), offsetof(fd_vm_t, reg[ 9]), offsetof(fd_vm_t, reg[10]));
333 0 : #line 211 "fd_jit_compiler.dasc"
334 :
335 : //|->restore_regs:
336 : //| fs
337 : //| mov rax, [fd_jit_vm_tpoff]
338 : //| mov bpf_r0, [rax + offsetof(fd_vm_t, reg[ 0])]
339 : //| mov bpf_r1, [rax + offsetof(fd_vm_t, reg[ 1])]
340 : //| mov bpf_r2, [rax + offsetof(fd_vm_t, reg[ 2])]
341 : //| mov bpf_r3, [rax + offsetof(fd_vm_t, reg[ 3])]
342 : //| mov bpf_r4, [rax + offsetof(fd_vm_t, reg[ 4])]
343 : //| mov bpf_r5, [rax + offsetof(fd_vm_t, reg[ 5])]
344 : //| mov bpf_r6, [rax + offsetof(fd_vm_t, reg[ 6])]
345 : //| mov bpf_r7, [rax + offsetof(fd_vm_t, reg[ 7])]
346 : //| mov bpf_r8, [rax + offsetof(fd_vm_t, reg[ 8])]
347 : //| mov bpf_r9, [rax + offsetof(fd_vm_t, reg[ 9])]
348 : //| mov bpf_r10, [rax + offsetof(fd_vm_t, reg[10])]
349 : //| ret
350 0 : dasm_put(Dst, 56, fd_jit_vm_tpoff, offsetof(fd_vm_t, reg[ 0]), offsetof(fd_vm_t, reg[ 1]), offsetof(fd_vm_t, reg[ 2]), offsetof(fd_vm_t, reg[ 3]), offsetof(fd_vm_t, reg[ 4]), offsetof(fd_vm_t, reg[ 5]), offsetof(fd_vm_t, reg[ 6]), offsetof(fd_vm_t, reg[ 7]), offsetof(fd_vm_t, reg[ 8]), offsetof(fd_vm_t, reg[ 9]), offsetof(fd_vm_t, reg[10]));
351 0 : #line 227 "fd_jit_compiler.dasc"
352 :
353 : /* Helper macros for BPF-to-x86 function calls */
354 :
355 : //|.macro enter_x86_frame
356 : //| call ->save_regs
357 : //| mov rbp, rsp
358 : //| and rsp, -16
359 : //|.endmacro
360 :
361 : //|.macro leave_x86_frame
362 : //| mov rsp, rbp
363 : //| call ->restore_regs
364 : //|.endmacro
365 :
366 : /* Address translation macros
367 :
368 : The translate_{rw,ro}_{1,2,4,8} macros perform address translation
369 : and access permission checks for {read-write,read-only} accesses of
370 : {1,2,4,8} bytes. The compiler may inline this macro for each
371 : translated sBPF instruction, so these should be optimized for small
372 : size.
373 :
374 : Prior to the macro, rdi holds an address in the virtual address
375 : space (untrusted in [0,2^64)). If translation and permission
376 : checks succeed, rdx holds the translated address in the host
377 : address space. On failure jumps to sigsegv. Reasons for failure
378 : include access to out-of-bounds memory, unaligned address, access
379 : permission error. */
380 :
381 : //| .define translate_in, rdi
382 : //| .define translate_out, rdx
383 : /* FIXME make output argument rdi instead of rdx */
384 :
385 : //|->fd_jit_vm_translate_ro:
386 : //| mov edx, edi // segment offset
387 : //| shr rdi, 32 // segment index
388 : //| shl edi, 1
389 : //| jmp ->fd_jit_vm_translate
390 0 : dasm_put(Dst, 110);
391 0 : #line 265 "fd_jit_compiler.dasc"
392 :
393 : //|->fd_jit_vm_translate_rw:
394 : //| mov edx, edi // segment offset
395 : //| shr rdi, 32 // segment index
396 : //| lea edi, [edi*2+1]
397 0 : dasm_put(Dst, 127);
398 0 : #line 270 "fd_jit_compiler.dasc"
399 : /* fallthrough */
400 :
401 : //|->fd_jit_vm_translate:
402 0 : dasm_put(Dst, 145);
403 0 : #line 273 "fd_jit_compiler.dasc"
404 0 : if( abiv2 ) {
405 : //| jmp ->fd_jit_vm_translate_abiv1
406 0 : dasm_put(Dst, 148);
407 0 : #line 275 "fd_jit_compiler.dasc"
408 0 : } else {
409 : //| jmp ->fd_jit_vm_translate_abiv2
410 0 : dasm_put(Dst, 153);
411 0 : #line 277 "fd_jit_compiler.dasc"
412 0 : }
413 :
414 : /* ABIv1 virtual memory overview
415 :
416 : - There are 6 pages indexed in [0,6)
417 : - The number of readable bytes in a page is variable in [0,2^31)
418 : - The number of writable bytes in a page is equal to the number of
419 : readable bytes or zero
420 : - The first byte of a page in virtual memory is at (index<<32)
421 : - Page 0 is always empty (all bytes are unaddressable)
422 : - Page 2 is 'striped': Virtual addresses with bit 12 set are not
423 : addressable */
424 :
425 : //|->fd_jit_vm_translate_abiv1:
426 : //| // rdi := virtual address
427 : //| // ebp := size of the access minus 1
428 : //|
429 : //| // edx := segment offset
430 : //| mov edx, edi
431 : //|
432 : //| // edi := segment index
433 : //| shr rdi, 32
434 : //|
435 : //| // segment index in bounds?
436 : //| fs
437 : //| cmp edi, [fd_jit_segment_cnt_tpoff]
438 : //| jae ->translate_fail
439 : //|
440 : //| // no multi segment overlap?
441 : //| add ebp, edx
442 : //| jc ->translate_fail
443 : //|
444 : //| // segment offset in bounds?
445 : //| fs
446 : //| cmp edx, [rdi*4 + fd_jit_mem_sz_tpoff]
447 : //| jae ->translate_fail
448 : //|
449 : //| // stack gap?
450 : //| xor ebp, ebp
451 : //| cmp edi, 2
452 : //| mov eax, 0x1000
453 : //| cmove ebp, eax
454 : //| and edx, ebp
455 : //| jae ->translate_fail
456 : //|
457 : //| // rdx := host address
458 : //| fs
459 : //| add rdx, [rdi*8 + fd_jit_mem_haddr_tpoff]
460 : //| ret
461 0 : dasm_put(Dst, 158, fd_jit_segment_cnt_tpoff, fd_jit_mem_sz_tpoff, fd_jit_mem_haddr_tpoff);
462 0 : #line 326 "fd_jit_compiler.dasc"
463 :
464 : /* ABIv2 virtual memory overview:
465 :
466 : - Virtual memory is described by a page table
467 : - There can be up to 2^16 pages
468 : - Each page is 4 GiB (2^32 byte) aligned in virtual memory
469 : - The number of readable bytes in a page is variable in [0,2^31)
470 : - The number of writable bytes in a page is less or equal to the
471 : number of readable bytes */
472 :
473 : //|->fd_jit_vm_translate_abiv2:
474 : //| // rdi := virtual address
475 : //| // ebp := size of the access minus 1
476 : //|
477 : //| // segment index in bounds?
478 : //| fs
479 : //| cmp edi, [fd_jit_segment_cnt_tpoff]
480 : //| jae ->translate_fail
481 : //|
482 : //| //// aligned access?
483 : //| // FIXME do we need an alignment check?
484 : //| //mov eax, edx
485 : //| //and eax, ebp
486 : //| //test eax, eax
487 : //| //jnz ->translate_fail
488 : //|
489 : //| // no multi segment overlap?
490 : //| add ebp, edx
491 : //| jc ->translate_fail
492 : //|
493 : //| // segment offset in bounds?
494 : //| fs
495 : //| cmp edx, [rdi*4 + fd_jit_mem_sz_tpoff]
496 : //| jae ->translate_fail
497 : //|
498 : //| // rdx := host address
499 : //| fs
500 : //| add rdx, [rdi*8 + fd_jit_mem_haddr_tpoff]
501 : //| ret
502 0 : dasm_put(Dst, 223, fd_jit_segment_cnt_tpoff, fd_jit_mem_sz_tpoff, fd_jit_mem_haddr_tpoff);
503 0 : #line 365 "fd_jit_compiler.dasc"
504 :
505 : //|->translate_fail:
506 : //| shl rdi, 32
507 : //| or rdi, rdx
508 : //| fs
509 : //| mov [fd_jit_segfault_vaddr_tpoff], rdi
510 : //| mov rdi, [rsp]
511 : //| fs
512 : //| mov [fd_jit_segfault_rip_tpoff], rdi
513 : //| jmp ->vm_fault
514 0 : dasm_put(Dst, 258, fd_jit_segfault_vaddr_tpoff, fd_jit_segfault_rip_tpoff);
515 0 : #line 375 "fd_jit_compiler.dasc"
516 :
517 : //|.macro translate_rw_1
518 : //| xor ebp, ebp
519 : //| call ->fd_jit_vm_translate_rw
520 : //|.endmacro
521 :
522 : //|.macro translate_rw_2
523 : //| mov ebp, 1
524 : //| call ->fd_jit_vm_translate_rw
525 : //|.endmacro
526 :
527 : //|.macro translate_rw_4
528 : //| mov ebp, 3
529 : //| call ->fd_jit_vm_translate_rw
530 : //|.endmacro
531 :
532 : //|.macro translate_rw_8
533 : //| mov ebp, 7
534 : //| call ->fd_jit_vm_translate_rw
535 : //|.endmacro
536 :
537 : //|.macro translate_ro_1
538 : //| xor ebp, ebp
539 : //| call ->fd_jit_vm_translate_ro
540 : //|.endmacro
541 :
542 : //|.macro translate_ro_2
543 : //| mov ebp, 1
544 : //| call ->fd_jit_vm_translate_ro
545 : //|.endmacro
546 :
547 : //|.macro translate_ro_4
548 : //| mov ebp, 3
549 : //| call ->fd_jit_vm_translate_ro
550 : //|.endmacro
551 :
552 : //|.macro translate_ro_8
553 : //| mov ebp, 7
554 : //| call ->fd_jit_vm_translate_ro
555 : //|.endmacro
556 :
557 : /* Generate setjmp/longjmp subroutines. These can be called from any
558 : execution state with a valid stack. The JIT uses them to restore a
559 : sane SystemV-ABI context when exiting JIT code.
560 :
561 : These are based on musl libc's setjmp/longjmp implementation.
562 : Copyright 2011-2012 Nicholas J. Kain, licensed under standard MIT license
563 :
564 : setjmp takes no arguments. longjmp takes a 64-bit value in rdi.
565 : When setjmp returns from setjmp, sets rax=0 and rdx=0. When setjmp
566 : returns from longjmp, sets rax to the rdi argument of longjmp, and
567 : sets rdx=1. setjmp preserves rdi. */
568 :
569 : //|->setjmp:
570 : //| mov64 r11, (ulong)fd_jit_jmp_buf
571 : //| mov [r11+ 0], rbx
572 : //| mov [r11+ 8], rbp
573 : //| mov [r11+16], r12
574 : //| mov [r11+24], r13
575 : //| mov [r11+32], r14
576 : //| mov [r11+40], r15
577 : //| // save callee's stack pointer
578 : //| // derived by removing our 8 byte stack frame (only return address)
579 : //| lea rdx, [rsp+8]
580 : //| mov [r11+48], rdx
581 : //| // save return address
582 : //| mov rdx, [rsp]
583 : //| mov [r11+56], rdx
584 : //| // normal return
585 : //| xor eax, eax
586 : //| xor edx, edx
587 : //| ret
588 0 : dasm_put(Dst, 288, (unsigned int)((ulong)fd_jit_jmp_buf), (unsigned int)(((ulong)fd_jit_jmp_buf)>>32), 0, 8);
589 0 : #line 447 "fd_jit_compiler.dasc"
590 :
591 : //|->longjmp:
592 : //| mov rax, rdi // move first argument to first output register
593 : //| mov edx, 1 // set second output register to 1
594 : //| mov64 rdi, (ulong)fd_jit_jmp_buf
595 : //| // restore execution state to callee of setjmp
596 : //| mov rbx, [rdi+ 0]
597 : //| mov rbp, [rdi+ 8]
598 : //| mov r12, [rdi+16]
599 : //| mov r13, [rdi+24]
600 : //| mov r14, [rdi+32]
601 : //| mov r15, [rdi+40]
602 : //| mov rsp, [rdi+48]
603 : //| push qword [rdi+56]
604 : //| ret // retpoline
605 0 : dasm_put(Dst, 341, (unsigned int)((ulong)fd_jit_jmp_buf), (unsigned int)(((ulong)fd_jit_jmp_buf)>>32), 0, 8);
606 0 : #line 462 "fd_jit_compiler.dasc"
607 :
608 : /* The emulate_syscall function switches from a JIT to an interpreter (C)
609 : execution context and invokes a syscall handler. Register edi is
610 : assumed to hold the byte offset into the vm->syscalls table of the
611 : fd_sbpf_syscalls_t entry to invoke.
612 : On syscall return, switches back to the JIT execution context and
613 : resumes execution after the syscall instruction. */
614 :
615 : //|->emulate_syscall:
616 : //| call ->save_regs
617 : //| enter_x86_frame
618 : //| sub rsp, 16
619 : //| fs
620 : //| mov r11, [fd_jit_vm_tpoff]
621 : //| fs
622 : //| mov r10, [rdi + fd_jit_syscalls_tpoff + offsetof(fd_sbpf_syscalls_t, func)]
623 : //| mov rdi, r11
624 : //| // load BPF r1 through r5 into function arguments
625 : //| // FIXME could avoid spill to memory by shuffling registers
626 : //| mov rsi, [rax + offsetof(fd_vm_t, reg[1])]
627 : //| mov rdx, [rax + offsetof(fd_vm_t, reg[2])]
628 : //| mov rcx, [rax + offsetof(fd_vm_t, reg[3])]
629 : //| mov r8, [rax + offsetof(fd_vm_t, reg[4])]
630 : //| mov r9, [rax + offsetof(fd_vm_t, reg[5])]
631 : //| lea r11, [rax + offsetof(fd_vm_t, reg[0])]
632 : //| push r11
633 : //| call r10
634 : //| test edi, edi
635 : //| jnz ->vm_fault
636 : //| leave_x86_frame
637 : //| ret
638 0 : dasm_put(Dst, 390, fd_jit_vm_tpoff, fd_jit_syscalls_tpoff + offsetof(fd_sbpf_syscalls_t, func), offsetof(fd_vm_t, reg[1]), offsetof(fd_vm_t, reg[2]), offsetof(fd_vm_t, reg[3]), offsetof(fd_vm_t, reg[4]), offsetof(fd_vm_t, reg[5]), offsetof(fd_vm_t, reg[0]));
639 0 : #line 493 "fd_jit_compiler.dasc"
640 :
641 : /* The call_stack_push function pushes the current program counter and
642 : eBPF registers r6, r7, r8, r9 to the shadow stack. The frame register
643 : (r10) grows upwards. FIXME implement shadow stack overflow. */
644 :
645 0 : # define REG(n) (offsetof(fd_vm_t, shadow[0].r##n))
646 :
647 : //|->call_stack_push:
648 : //| fs
649 : //| mov rdi, [fd_jit_vm_tpoff]
650 : //| // vm->frame_cnt++
651 : //| inc qword [rdi + offsetof(fd_vm_t, frame_cnt)]
652 : //| // save registers
653 : //| pop rdi
654 : //| push bpf_r6
655 : //| push bpf_r7
656 : //| push bpf_r8
657 : //| push bpf_r9
658 : //| add bpf_r10, 0x2000
659 : //| jmp rdi
660 0 : dasm_put(Dst, 471, fd_jit_vm_tpoff, offsetof(fd_vm_t, frame_cnt));
661 0 : #line 513 "fd_jit_compiler.dasc"
662 :
663 : /* The call_stack_pop function undoes the effects of call_stack_push. */
664 :
665 : //|->call_stack_pop:
666 : //| fs
667 : //| mov rdi, [fd_jit_vm_tpoff]
668 : //| // vm->frame_cnt--
669 : //| dec qword [rdi + offsetof(fd_vm_t, frame_cnt)]
670 : //| // restore registers
671 : //| pop rdi
672 : //| pop bpf_r9
673 : //| pop bpf_r8
674 : //| pop bpf_r7
675 : //| pop bpf_r6
676 : //| sub bpf_r10, 0x2000
677 : //| jmp rdi
678 0 : dasm_put(Dst, 502, fd_jit_vm_tpoff, offsetof(fd_vm_t, frame_cnt));
679 0 : #line 529 "fd_jit_compiler.dasc"
680 :
681 0 : # undef REG
682 : /* Exception handlers */
683 :
684 : //|->vm_fault:
685 : //| mov edi, FD_VM_ERR_ABORT
686 : //| jmp ->longjmp
687 0 : dasm_put(Dst, 534, FD_VM_ERR_ABORT);
688 0 : #line 536 "fd_jit_compiler.dasc"
689 :
690 : /* JIT entrypoint from C code */
691 :
692 : //|->entrypoint:
693 0 : dasm_put(Dst, 543);
694 0 : #line 540 "fd_jit_compiler.dasc"
695 :
696 : /* Create setjmp anchor used to return from JIT */
697 :
698 : //| call ->setjmp // preserves rdi
699 : //| test edx, edx
700 : //| jnz >1
701 0 : dasm_put(Dst, 546);
702 0 : #line 546 "fd_jit_compiler.dasc"
703 :
704 : /* Enter JIT execution context */
705 :
706 : //| call ->restore_regs
707 : //| sub rsp, 0x20 // balance call_stack_push
708 : //| call rdi
709 : //| mov rdi, bpf_r0
710 : //| call ->longjmp
711 : //|1:
712 : //| ret
713 0 : dasm_put(Dst, 556);
714 0 : #line 556 "fd_jit_compiler.dasc"
715 :
716 : /* Start translating user code */
717 :
718 0 : ulong * const text_start = prog->text;
719 0 : ulong * text_end = prog->text + prog->text_cnt;
720 :
721 0 : for( ulong * cur=text_start; cur<text_end; cur++ ) {
722 0 : ulong instr = *cur;
723 :
724 0 : ulong opcode = fd_vm_instr_opcode( instr ); /* in [0,256) even if malformed */
725 0 : ulong dst = fd_vm_instr_dst ( instr ); /* in [0, 16) even if malformed */
726 0 : ulong src = fd_vm_instr_src ( instr ); /* in [0, 16) even if malformed */
727 0 : short offset = fd_vm_instr_offset( instr ); /* in [-2^15,2^15) even if malformed */
728 0 : uint imm = fd_vm_instr_imm ( instr ); /* in [0,2^32) even if malformed */
729 :
730 : /* Macros for translating register accesses */
731 :
732 0 : uint x86_dst = reg_bpf2x86[ dst ];
733 0 : uint x86_src = reg_bpf2x86[ src ];
734 :
735 : //| .define dst64, Rq(x86_dst)
736 : //| .define src64, Rq(x86_src)
737 : //| .define dst32, Rd(x86_dst)
738 : //| .define src32, Rd(x86_src)
739 : //| .define src8, Rb(x86_src)
740 :
741 : /* Macro for translating jumps */
742 :
743 0 : ulong * jmp_dst = cur + 1 + offset; /* may be OOB, FIXME validate */
744 0 : int jmp_dst_lbl = (int)( jmp_dst - text_start );
745 : //int jmp_bounds_ok = jmp_dst>=text_start && jmp<text_end;
746 : /* FIXME do a bounds check */
747 : /* FIXME what happens if the label is not set? */
748 :
749 : /* FIXME CU accounting */
750 :
751 : /* Create a dynamic label for each instruction */
752 :
753 0 : uint cur_pc = (uint)( cur - text_start );
754 0 : int next_label = (int)cur_pc;
755 : //|=>next_label:
756 0 : dasm_put(Dst, 578, next_label);
757 0 : #line 597 "fd_jit_compiler.dasc"
758 :
759 : /* Translate instruction */
760 :
761 0 : switch( opcode ) {
762 :
763 : /* 0x00 - 0x0f ******************************************************/
764 :
765 0 : case 0x04: /* FD_SBPF_OP_ADD_IMM */
766 : //| add dst32, imm
767 0 : dasm_put(Dst, 580, (x86_dst), imm);
768 0 : #line 606 "fd_jit_compiler.dasc"
769 0 : break;
770 :
771 0 : case 0x05: /* FD_SBPF_OP_JA */
772 : //| jmp =>jmp_dst_lbl
773 0 : dasm_put(Dst, 587, jmp_dst_lbl);
774 0 : #line 610 "fd_jit_compiler.dasc"
775 0 : break;
776 :
777 0 : case 0x07: /* FD_SBPF_OP_ADD64_IMM */
778 : //| add dst64, imm
779 0 : dasm_put(Dst, 591, (x86_dst), imm);
780 0 : #line 614 "fd_jit_compiler.dasc"
781 0 : break;
782 :
783 0 : case 0x0c: /* FD_SBPF_OP_ADD_REG */
784 : //| add dst32, src32
785 0 : dasm_put(Dst, 598, (x86_src), (x86_dst));
786 0 : #line 618 "fd_jit_compiler.dasc"
787 0 : break;
788 :
789 0 : case 0x0f: /* FD_SBPF_OP_ADD64_REG */
790 : //| add dst64, src64
791 0 : dasm_put(Dst, 606, (x86_src), (x86_dst));
792 0 : #line 622 "fd_jit_compiler.dasc"
793 0 : break;
794 :
795 : /* 0x10 - 0x1f ******************************************************/
796 :
797 0 : case 0x14: /* FD_SBPF_OP_SUB_IMM */
798 : //| sub dst32, imm
799 0 : dasm_put(Dst, 614, (x86_dst), imm);
800 0 : #line 628 "fd_jit_compiler.dasc"
801 0 : break;
802 :
803 0 : case 0x15: /* FD_SBPF_OP_JEQ_IMM */
804 : //| cmp dst64, imm
805 0 : dasm_put(Dst, 621, (x86_dst), imm);
806 0 : #line 632 "fd_jit_compiler.dasc"
807 : /* pre branch check here ... branchless cu update? */
808 : //| je =>jmp_dst_lbl
809 0 : dasm_put(Dst, 629, jmp_dst_lbl);
810 0 : #line 634 "fd_jit_compiler.dasc"
811 0 : break;
812 :
813 0 : case 0x17: /* FD_SBPF_OP_SUB64_IMM */
814 : //| sub dst64, imm
815 0 : dasm_put(Dst, 633, (x86_dst), imm);
816 0 : #line 638 "fd_jit_compiler.dasc"
817 0 : break;
818 :
819 0 : case 0x18: /* FD_SBPF_OP_LDQ */
820 0 : cur++; {
821 0 : ulong imm64 = (ulong)imm | ( (ulong)fd_vm_instr_imm( *cur ) << 32 );
822 0 : if( imm64==0 ) {
823 : //| xor dst32, dst32
824 0 : dasm_put(Dst, 640, (x86_dst), (x86_dst));
825 0 : #line 645 "fd_jit_compiler.dasc"
826 0 : } else {
827 : //| mov dst64, imm64
828 0 : dasm_put(Dst, 648, (x86_dst), imm64);
829 0 : #line 647 "fd_jit_compiler.dasc"
830 0 : }
831 0 : break;
832 0 : }
833 :
834 0 : case 0x1c: /* FD_SBPF_OP_SUB_REG */
835 : //| sub dst32, src32
836 0 : dasm_put(Dst, 655, (x86_src), (x86_dst));
837 0 : #line 653 "fd_jit_compiler.dasc"
838 0 : break;
839 :
840 0 : case 0x1d: /* FD_SBPF_OP_JEQ_REG */
841 : //| cmp dst64, src64
842 : //| je =>jmp_dst_lbl
843 0 : dasm_put(Dst, 663, (x86_src), (x86_dst), jmp_dst_lbl);
844 0 : #line 658 "fd_jit_compiler.dasc"
845 0 : break;
846 :
847 0 : case 0x1f: /* FD_SBPF_OP_SUB64_REG */
848 : //| sub dst64, src64
849 0 : dasm_put(Dst, 674, (x86_src), (x86_dst));
850 0 : #line 662 "fd_jit_compiler.dasc"
851 0 : break;
852 :
853 : /* 0x20 - 0x2f ******************************************************/
854 :
855 0 : case 0x24: /* FD_SBPF_OP_MUL_IMM */
856 : /* TODO strength reduction? */
857 : //| imul dst32, imm
858 0 : dasm_put(Dst, 682, (x86_dst), (x86_dst), imm);
859 0 : #line 669 "fd_jit_compiler.dasc"
860 0 : break;
861 :
862 0 : case 0x25: /* FD_SBPF_OP_JGT_IMM */
863 : //| cmp dst64, imm
864 : //| ja =>jmp_dst_lbl
865 0 : dasm_put(Dst, 691, (x86_dst), imm, jmp_dst_lbl);
866 0 : #line 674 "fd_jit_compiler.dasc"
867 0 : break;
868 :
869 0 : case 0x27: /* FD_SBPF_OP_MUL64_IMM */
870 : /* TODO strength reduction? */
871 : //| imul dst64, imm
872 0 : dasm_put(Dst, 702, (x86_dst), (x86_dst), imm);
873 0 : #line 679 "fd_jit_compiler.dasc"
874 0 : break;
875 :
876 0 : case 0x2c: /* FD_SBPF_OP_MUL_REG */
877 : //| imul dst32, src32
878 0 : dasm_put(Dst, 711, (x86_dst), (x86_src));
879 0 : #line 683 "fd_jit_compiler.dasc"
880 0 : break;
881 :
882 0 : case 0x2d: /* FD_SBPF_OP_JGT_REG */
883 : //| cmp dst64, src64
884 : //| ja =>jmp_dst_lbl
885 0 : dasm_put(Dst, 720, (x86_src), (x86_dst), jmp_dst_lbl);
886 0 : #line 688 "fd_jit_compiler.dasc"
887 0 : break;
888 :
889 0 : case 0x2f: /* FD_SBPF_OP_MUL64_REG */
890 : //| imul dst64, src64
891 0 : dasm_put(Dst, 731, (x86_dst), (x86_src));
892 0 : #line 692 "fd_jit_compiler.dasc"
893 0 : break;
894 :
895 : /* 0x30 - 0x3f ******************************************************/
896 :
897 0 : case 0x34: /* FD_SBPF_OP_DIV_IMM */
898 0 : if( FD_UNLIKELY( imm==0 ) ) {
899 : //| jmp ->vm_fault
900 0 : dasm_put(Dst, 283);
901 0 : #line 699 "fd_jit_compiler.dasc"
902 0 : break;
903 0 : }
904 : //| xchg eax, dst32
905 : //| xor edx, edx
906 : //| mov edi, imm
907 : //| div edi
908 : //| xchg eax, dst32
909 0 : dasm_put(Dst, 740, (x86_dst), imm, (x86_dst));
910 0 : #line 706 "fd_jit_compiler.dasc"
911 0 : break;
912 :
913 0 : case 0x35: /* FD_SBPF_OP_JGE_IMM */
914 : //| cmp dst64, imm
915 : //| jae =>jmp_dst_lbl
916 0 : dasm_put(Dst, 757, (x86_dst), imm, jmp_dst_lbl);
917 0 : #line 711 "fd_jit_compiler.dasc"
918 0 : break;
919 :
920 0 : case 0x37: /* FD_SBPF_OP_DIV64_IMM */
921 0 : if( FD_UNLIKELY( imm==0 ) ) {
922 : //| jmp ->vm_fault
923 0 : dasm_put(Dst, 283);
924 0 : #line 716 "fd_jit_compiler.dasc"
925 0 : break;
926 0 : }
927 : //| xchg rax, dst64
928 : //| xor edx, edx
929 : //| mov rdi, imm
930 : //| div rdi
931 : //| xchg rax, dst64
932 0 : dasm_put(Dst, 768, (x86_dst), imm, (x86_dst));
933 0 : #line 723 "fd_jit_compiler.dasc"
934 0 : break;
935 :
936 0 : case 0x3c: /* FD_SBPF_OP_DIV_REG */
937 : //| test src32, src32
938 : //| jz ->vm_fault
939 0 : dasm_put(Dst, 788, (x86_src), (x86_src));
940 0 : #line 728 "fd_jit_compiler.dasc"
941 0 : if( x86_dst==x86_src ) {
942 : //| mov dst32, 1
943 0 : dasm_put(Dst, 800, (x86_dst));
944 0 : #line 730 "fd_jit_compiler.dasc"
945 0 : break;
946 0 : }
947 : //| xchg eax, dst32
948 : //| xor edx, edx
949 : //| div src32
950 : //| xchg eax, dst32
951 0 : dasm_put(Dst, 809, (x86_dst), (x86_src), (x86_dst));
952 0 : #line 736 "fd_jit_compiler.dasc"
953 0 : break;
954 :
955 0 : case 0x3d: /* FD_SBPF_OP_JGE_REG */
956 : //| cmp dst64, src64
957 : //| jae =>jmp_dst_lbl
958 0 : dasm_put(Dst, 827, (x86_src), (x86_dst), jmp_dst_lbl);
959 0 : #line 741 "fd_jit_compiler.dasc"
960 0 : break;
961 :
962 0 : case 0x3f: /* FD_SBPF_OP_DIV64_REG */
963 : //| test src64, src64
964 : //| jz ->vm_fault
965 0 : dasm_put(Dst, 838, (x86_src), (x86_src));
966 0 : #line 746 "fd_jit_compiler.dasc"
967 0 : if( x86_dst==x86_src ) {
968 : //| mov dst32, 1
969 0 : dasm_put(Dst, 800, (x86_dst));
970 0 : #line 748 "fd_jit_compiler.dasc"
971 0 : break;
972 0 : }
973 : //| xchg rax, dst64
974 : //| xor edx, edx
975 : //| div src64
976 : //| xchg rax, dst64
977 0 : dasm_put(Dst, 850, (x86_dst), (x86_src), (x86_dst));
978 0 : #line 754 "fd_jit_compiler.dasc"
979 0 : break;
980 :
981 : /* 0x40 - 0x4f ******************************************************/
982 :
983 0 : case 0x44: /* FD_SBPF_OP_OR_IMM */
984 : //| or dst32, imm
985 0 : dasm_put(Dst, 868, (x86_dst), imm);
986 0 : #line 760 "fd_jit_compiler.dasc"
987 0 : break;
988 :
989 0 : case 0x45: /* FD_SBPF_OP_JSET_IMM */
990 : //| test dst64, imm
991 : //| jnz =>jmp_dst_lbl
992 0 : dasm_put(Dst, 875, (x86_dst), imm, jmp_dst_lbl);
993 0 : #line 765 "fd_jit_compiler.dasc"
994 0 : break;
995 :
996 0 : case 0x47: /* FD_SBPF_OP_OR64_IMM */
997 : //| or dst64, imm
998 0 : dasm_put(Dst, 886, (x86_dst), imm);
999 0 : #line 769 "fd_jit_compiler.dasc"
1000 0 : break;
1001 :
1002 0 : case 0x4c: /* FD_SBPF_OP_OR_REG */
1003 : //| or dst32, src32
1004 0 : dasm_put(Dst, 893, (x86_src), (x86_dst));
1005 0 : #line 773 "fd_jit_compiler.dasc"
1006 0 : break;
1007 :
1008 0 : case 0x4d: /* FD_SBPF_OP_JSET_REG */
1009 : //| test dst64, src64
1010 : //| jnz =>jmp_dst_lbl
1011 0 : dasm_put(Dst, 901, (x86_src), (x86_dst), jmp_dst_lbl);
1012 0 : #line 778 "fd_jit_compiler.dasc"
1013 0 : break;
1014 :
1015 0 : case 0x4f: /* FD_SBPF_OP_OR64_REG */
1016 : //| or dst64, src64
1017 0 : dasm_put(Dst, 912, (x86_src), (x86_dst));
1018 0 : #line 782 "fd_jit_compiler.dasc"
1019 0 : break;
1020 :
1021 : /* 0x50 - 0x5f ******************************************************/
1022 :
1023 0 : case 0x54: /* FD_SBPF_OP_AND_IMM */
1024 : //| and dst32, imm
1025 0 : dasm_put(Dst, 920, (x86_dst), imm);
1026 0 : #line 788 "fd_jit_compiler.dasc"
1027 0 : break;
1028 :
1029 0 : case 0x55: /* FD_SBPF_OP_JNE_IMM */
1030 : //| cmp dst64, imm
1031 : //| jne =>jmp_dst_lbl
1032 0 : dasm_put(Dst, 927, (x86_dst), imm, jmp_dst_lbl);
1033 0 : #line 793 "fd_jit_compiler.dasc"
1034 0 : break;
1035 :
1036 0 : case 0x57: /* FD_SBPF_OP_AND64_IMM */
1037 : //| and dst64, imm
1038 0 : dasm_put(Dst, 938, (x86_dst), imm);
1039 0 : #line 797 "fd_jit_compiler.dasc"
1040 0 : break;
1041 :
1042 0 : case 0x5c: /* FD_SBPF_OP_AND_REG */
1043 : //| and dst32, src32
1044 0 : dasm_put(Dst, 945, (x86_src), (x86_dst));
1045 0 : #line 801 "fd_jit_compiler.dasc"
1046 0 : break;
1047 :
1048 0 : case 0x5d: /* FD_SBPF_OP_JNE_REG */
1049 : //| cmp dst64, src64
1050 : //| jne =>jmp_dst_lbl
1051 0 : dasm_put(Dst, 953, (x86_src), (x86_dst), jmp_dst_lbl);
1052 0 : #line 806 "fd_jit_compiler.dasc"
1053 0 : break;
1054 :
1055 0 : case 0x5f: /* FD_SBPF_OP_AND64_REG */
1056 : //| and dst64, src64
1057 0 : dasm_put(Dst, 964, (x86_src), (x86_dst));
1058 0 : #line 810 "fd_jit_compiler.dasc"
1059 0 : break;
1060 :
1061 : /* 0x60 - 0x6f ******************************************************/
1062 :
1063 0 : case 0x61: /* FD_SBPF_OP_LDXW */
1064 : //| lea translate_in, [src64+offset]
1065 : //| translate_ro_4
1066 : //| mov dst32, [translate_out]
1067 0 : dasm_put(Dst, 972, (x86_src), offset, (x86_dst));
1068 0 : #line 818 "fd_jit_compiler.dasc"
1069 0 : break;
1070 :
1071 0 : case 0x62: /* FD_SBPF_OP_STW */
1072 : //| lea translate_in, [dst64+offset]
1073 : //| translate_rw_4
1074 : //| mov dword [translate_out], imm
1075 0 : dasm_put(Dst, 993, (x86_dst), offset, imm);
1076 0 : #line 824 "fd_jit_compiler.dasc"
1077 0 : break;
1078 :
1079 0 : case 0x63: /* FD_SBPF_OP_STXW */
1080 : //| lea translate_in, [dst64+offset]
1081 : //| translate_rw_4
1082 : //| mov [translate_out], src32
1083 0 : dasm_put(Dst, 1012, (x86_dst), offset, (x86_src));
1084 0 : #line 830 "fd_jit_compiler.dasc"
1085 0 : break;
1086 :
1087 0 : case 0x64: /* FD_SBPF_OP_LSH_IMM */
1088 : //| shl dst32, imm
1089 0 : dasm_put(Dst, 1033, (x86_dst), imm);
1090 0 : #line 834 "fd_jit_compiler.dasc"
1091 0 : break;
1092 :
1093 0 : case 0x65: /* FD_SBPF_OP_JSGT_IMM */
1094 : //| cmp dst64, imm
1095 : //| jg =>jmp_dst_lbl
1096 0 : dasm_put(Dst, 1040, (x86_dst), imm, jmp_dst_lbl);
1097 0 : #line 839 "fd_jit_compiler.dasc"
1098 0 : break;
1099 :
1100 0 : case 0x67: /* FD_SBPF_OP_LSH64_IMM */
1101 : //| shl dst64, imm
1102 0 : dasm_put(Dst, 1051, (x86_dst), imm);
1103 0 : #line 843 "fd_jit_compiler.dasc"
1104 0 : break;
1105 :
1106 0 : case 0x69: /* FD_SBPF_OP_LDXH */
1107 : //| lea translate_in, [src64+offset]
1108 : //| translate_ro_2
1109 : //| xor dst32, dst32
1110 : //| mov Rw(x86_dst), [translate_out]
1111 0 : dasm_put(Dst, 1058, (x86_src), offset, (x86_dst), (x86_dst), (x86_dst));
1112 0 : #line 850 "fd_jit_compiler.dasc"
1113 0 : break;
1114 :
1115 0 : case 0x6a: /* FD_SBPF_OP_STH */
1116 : //| lea translate_in, [dst64+offset]
1117 : //| translate_rw_2
1118 : //| mov word [translate_out], imm
1119 0 : dasm_put(Dst, 1087, (x86_dst), offset, imm);
1120 0 : #line 856 "fd_jit_compiler.dasc"
1121 0 : break;
1122 :
1123 0 : case 0x6b: /* FD_SBPF_OP_STXH */
1124 : //| lea translate_in, [dst64+offset]
1125 : //| translate_rw_2
1126 : //| mov [translate_out], src32
1127 0 : dasm_put(Dst, 1107, (x86_dst), offset, (x86_src));
1128 0 : #line 862 "fd_jit_compiler.dasc"
1129 0 : break;
1130 :
1131 0 : case 0x6c: /* FD_SBPF_OP_LSH_REG */
1132 : //| mov cl, src8
1133 : //| shl dst32, cl
1134 0 : dasm_put(Dst, 1128, (x86_src), (x86_dst));
1135 0 : #line 867 "fd_jit_compiler.dasc"
1136 0 : break;
1137 :
1138 0 : case 0x6d: /* FD_SBPF_OP_JSGT_REG */
1139 : //| cmp dst64, src64
1140 : //| jg =>jmp_dst_lbl
1141 0 : dasm_put(Dst, 1139, (x86_src), (x86_dst), jmp_dst_lbl);
1142 0 : #line 872 "fd_jit_compiler.dasc"
1143 0 : break;
1144 :
1145 0 : case 0x6f: /* FD_SBPF_OP_LSH64_REG */
1146 : //| mov cl, src8
1147 : //| shl dst64, cl
1148 0 : dasm_put(Dst, 1150, (x86_src), (x86_dst));
1149 0 : #line 877 "fd_jit_compiler.dasc"
1150 0 : break;
1151 :
1152 : /* 0x70 - 0x7f ******************************************************/
1153 :
1154 0 : case 0x71: /* FD_SBPF_OP_LDXB */
1155 : //| lea translate_in, [src64+offset]
1156 : //| translate_ro_1
1157 0 : dasm_put(Dst, 1161, (x86_src), offset);
1158 0 : #line 884 "fd_jit_compiler.dasc"
1159 : /* TODO is there a better way to zero upper and mov byte? */
1160 : //| xor dst32, dst32
1161 : //| mov Rb(x86_dst), [translate_out]
1162 0 : dasm_put(Dst, 1175, (x86_dst), (x86_dst), (x86_dst));
1163 0 : #line 887 "fd_jit_compiler.dasc"
1164 0 : break;
1165 :
1166 0 : case 0x72: /* FD_SBPF_OP_STB */
1167 : //| lea translate_in, [src64+offset]
1168 : //| translate_rw_1
1169 : //| mov byte [translate_out], imm
1170 0 : dasm_put(Dst, 1188, (x86_src), offset, imm);
1171 0 : #line 893 "fd_jit_compiler.dasc"
1172 0 : break;
1173 :
1174 0 : case 0x73: /* FD_SBPF_OP_STXB */
1175 : //| lea translate_in, [dst64+offset]
1176 : //| translate_rw_1
1177 : //| mov byte [translate_out], Rb(x86_src)
1178 0 : dasm_put(Dst, 1205, (x86_dst), offset, (x86_src));
1179 0 : #line 899 "fd_jit_compiler.dasc"
1180 0 : break;
1181 :
1182 0 : case 0x74: /* FD_SBPF_OP_RSH_IMM */
1183 : //| shr dst32, imm
1184 0 : dasm_put(Dst, 1224, (x86_dst), imm);
1185 0 : #line 903 "fd_jit_compiler.dasc"
1186 0 : break;
1187 :
1188 0 : case 0x75: /* FD_SBPF_OP_JSGE_IMM */
1189 : //| cmp dst64, imm
1190 : //| jge =>jmp_dst_lbl
1191 0 : dasm_put(Dst, 1231, (x86_dst), imm, jmp_dst_lbl);
1192 0 : #line 908 "fd_jit_compiler.dasc"
1193 0 : break;
1194 :
1195 0 : case 0x77: /* FD_SBPF_OP_RSH64_IMM */
1196 : //| shr dst64, imm
1197 0 : dasm_put(Dst, 1242, (x86_dst), imm);
1198 0 : #line 912 "fd_jit_compiler.dasc"
1199 0 : break;
1200 :
1201 0 : case 0x79: /* FD_SBPF_OP_LDXQ */
1202 : //| lea translate_in, [src64+offset]
1203 : //| translate_ro_8
1204 : //| mov dst64, [translate_out]
1205 0 : dasm_put(Dst, 1249, (x86_src), offset, (x86_dst));
1206 0 : #line 918 "fd_jit_compiler.dasc"
1207 0 : break;
1208 :
1209 0 : case 0x7a: /* FD_SBPF_OP_STQ */
1210 : //| lea translate_in, [dst64+offset]
1211 : //| translate_rw_8
1212 : //| mov dword [translate_out], imm
1213 : //| mov dword [translate_out+4], 0
1214 0 : dasm_put(Dst, 1270, (x86_dst), offset, imm);
1215 0 : #line 925 "fd_jit_compiler.dasc"
1216 0 : break;
1217 :
1218 0 : case 0x7b: /* FD_SBPF_OP_STXQ */
1219 : //| lea translate_in, [dst64+offset]
1220 : //| translate_rw_8
1221 : //| mov [translate_out], src64
1222 0 : dasm_put(Dst, 1296, (x86_dst), offset, (x86_src));
1223 0 : #line 931 "fd_jit_compiler.dasc"
1224 0 : break;
1225 :
1226 0 : case 0x7c: /* FD_SBPF_OP_RSH_REG */
1227 : //| mov cl, src8
1228 : //| shr dst32, cl
1229 0 : dasm_put(Dst, 1317, (x86_src), (x86_dst));
1230 0 : #line 936 "fd_jit_compiler.dasc"
1231 0 : break;
1232 :
1233 0 : case 0x7d: /* FD_SBPF_OP_JSGE_REG */
1234 : //| cmp dst64, src64
1235 : //| jge =>jmp_dst_lbl
1236 0 : dasm_put(Dst, 1328, (x86_src), (x86_dst), jmp_dst_lbl);
1237 0 : #line 941 "fd_jit_compiler.dasc"
1238 0 : break;
1239 :
1240 0 : case 0x7f: /* FD_SBPF_OP_RSH64_REG */
1241 : //| mov cl, src8
1242 : //| shr dst64, cl
1243 0 : dasm_put(Dst, 1339, (x86_src), (x86_dst));
1244 0 : #line 946 "fd_jit_compiler.dasc"
1245 0 : break;
1246 :
1247 : /* 0x80-0x8f ********************************************************/
1248 :
1249 0 : case 0x84: /* FD_SBPF_OP_NEG */
1250 : //| neg dst32
1251 0 : dasm_put(Dst, 1350, (x86_dst));
1252 0 : #line 952 "fd_jit_compiler.dasc"
1253 0 : break;
1254 :
1255 0 : case 0x85: { /* FD_SBPF_OP_CALL_IMM */
1256 0 : fd_sbpf_syscalls_t const * syscall = fd_sbpf_syscalls_query_const( syscalls, imm, NULL );
1257 0 : if( !syscall ) {
1258 0 : ulong target_pc = (ulong)fd_pchash_inverse( imm );
1259 : //| call ->call_stack_push
1260 : //| call =>target_pc
1261 0 : dasm_put(Dst, 1357, target_pc);
1262 0 : #line 960 "fd_jit_compiler.dasc"
1263 0 : } else {
1264 : /* Optimize for code footprint: Generate an offset into the
1265 : syscall table (32-bit) instead of the syscall address (64-bit) */
1266 : //| mov rdi, (uint)( (ulong)syscall - (ulong)syscalls );
1267 : //| call ->emulate_syscall
1268 0 : dasm_put(Dst, 1363, (uint)( (ulong)syscall - (ulong)syscalls ));
1269 0 : #line 965 "fd_jit_compiler.dasc"
1270 0 : }
1271 0 : break;
1272 0 : }
1273 :
1274 0 : case 0x87: /* FD_SBPF_OP_NEG64 */
1275 : //| neg dst64
1276 0 : dasm_put(Dst, 1371, (x86_dst));
1277 0 : #line 971 "fd_jit_compiler.dasc"
1278 0 : break;
1279 :
1280 0 : case 0x8d: /* FD_SBPF_OP_CALL_REG */
1281 0 : FD_LOG_WARNING(( "TODO: CALLX" ));
1282 0 : break;
1283 :
1284 : /* 0x90 - 0x9f ******************************************************/
1285 :
1286 0 : case 0x94: /* FD_SBPF_OP_MOD_IMM */
1287 0 : if( FD_UNLIKELY( imm==0 ) ) {
1288 : //| jmp ->vm_fault
1289 0 : dasm_put(Dst, 283);
1290 0 : #line 982 "fd_jit_compiler.dasc"
1291 0 : break;
1292 0 : }
1293 : //| xchg eax, dst32
1294 : //| xor edx, edx
1295 : //| mov edi, imm
1296 : //| div edi
1297 : //| xchg edx, dst32
1298 0 : dasm_put(Dst, 1378, (x86_dst), imm, (x86_dst));
1299 0 : #line 989 "fd_jit_compiler.dasc"
1300 0 : break;
1301 :
1302 0 : case 0x95: /* FD_SBPF_OP_EXIT */
1303 : //| call ->call_stack_pop
1304 : //| ret
1305 0 : dasm_put(Dst, 1396);
1306 0 : #line 994 "fd_jit_compiler.dasc"
1307 0 : break;
1308 :
1309 0 : case 0x97: /* FD_SBPF_OP_MOD64_IMM */
1310 0 : if( FD_UNLIKELY( imm==0 ) ) {
1311 : //| jmp ->vm_fault
1312 0 : dasm_put(Dst, 283);
1313 0 : #line 999 "fd_jit_compiler.dasc"
1314 0 : break;
1315 0 : }
1316 : //| xchg rax, dst64
1317 : //| xor edx, edx
1318 : //| mov rdi, imm
1319 : //| div rdi
1320 : //| xchg rax, dst64
1321 0 : dasm_put(Dst, 768, (x86_dst), imm, (x86_dst));
1322 0 : #line 1006 "fd_jit_compiler.dasc"
1323 0 : break;
1324 :
1325 0 : case 0x9c: /* FD_SBPF_OP_MOD_REG */
1326 : //| test src32, src32
1327 : //| jz ->vm_fault
1328 0 : dasm_put(Dst, 788, (x86_src), (x86_src));
1329 0 : #line 1011 "fd_jit_compiler.dasc"
1330 0 : if( x86_dst==x86_src ) {
1331 : //| mov dst32, 0
1332 0 : dasm_put(Dst, 1401, (x86_dst));
1333 0 : #line 1013 "fd_jit_compiler.dasc"
1334 0 : break;
1335 0 : }
1336 : //| xchg eax, dst32
1337 : //| xor edx, edx
1338 : //| div src32
1339 : //| xchg edx, dst32
1340 0 : dasm_put(Dst, 1410, (x86_dst), (x86_src), (x86_dst));
1341 0 : #line 1019 "fd_jit_compiler.dasc"
1342 0 : break;
1343 :
1344 0 : case 0x9f: /* FD_SBPF_OP_MOD64_REG */
1345 : //| test src64, src64
1346 : //| jz ->vm_fault
1347 0 : dasm_put(Dst, 838, (x86_src), (x86_src));
1348 0 : #line 1024 "fd_jit_compiler.dasc"
1349 0 : if( x86_dst==x86_src ) {
1350 : //| mov dst32, 0
1351 0 : dasm_put(Dst, 1401, (x86_dst));
1352 0 : #line 1026 "fd_jit_compiler.dasc"
1353 0 : break;
1354 0 : }
1355 : //| xchg rax, dst64
1356 : //| xor edx, edx
1357 : //| div src64
1358 : //| xchg rdx, dst64
1359 0 : dasm_put(Dst, 1429, (x86_dst), (x86_src), (x86_dst));
1360 0 : #line 1032 "fd_jit_compiler.dasc"
1361 0 : break;
1362 :
1363 : /* 0xa0 - 0xaf ******************************************************/
1364 :
1365 0 : case 0xa4: /* FD_SBPF_OP_XOR_IMM */
1366 : //| xor dst32, imm
1367 0 : dasm_put(Dst, 1448, (x86_dst), imm);
1368 0 : #line 1038 "fd_jit_compiler.dasc"
1369 0 : break;
1370 :
1371 0 : case 0xa5: /* FD_SBPF_OP_JLT_IMM */
1372 : //| cmp dst64, imm
1373 : //| jb =>jmp_dst_lbl
1374 0 : dasm_put(Dst, 1456, (x86_dst), imm, jmp_dst_lbl);
1375 0 : #line 1043 "fd_jit_compiler.dasc"
1376 0 : break;
1377 :
1378 0 : case 0xa7: /* FD_SBPF_OP_XOR64_IMM */
1379 : // TODO sign extension
1380 : //| xor dst64, imm
1381 0 : dasm_put(Dst, 1467, (x86_dst), imm);
1382 0 : #line 1048 "fd_jit_compiler.dasc"
1383 0 : break;
1384 :
1385 0 : case 0xac: /* FD_SBPF_OP_XOR_REG */
1386 : //| xor dst32, src32
1387 0 : dasm_put(Dst, 640, (x86_src), (x86_dst));
1388 0 : #line 1052 "fd_jit_compiler.dasc"
1389 0 : break;
1390 :
1391 0 : case 0xad: /* FD_SBPF_OP_JLT_REG */
1392 : //| cmp dst64, src64
1393 : //| jb =>jmp_dst_lbl
1394 0 : dasm_put(Dst, 1475, (x86_src), (x86_dst), jmp_dst_lbl);
1395 0 : #line 1057 "fd_jit_compiler.dasc"
1396 0 : break;
1397 :
1398 0 : case 0xaf: /* FD_SBPF_OP_XOR64_REG */
1399 : //| xor dst64, src64
1400 0 : dasm_put(Dst, 1486, (x86_src), (x86_dst));
1401 0 : #line 1061 "fd_jit_compiler.dasc"
1402 0 : break;
1403 :
1404 : /* 0xb0 - 0xbf ******************************************************/
1405 :
1406 0 : case 0xb4: /* FD_SBPF_OP_MOV_IMM */
1407 : //| mov dst32, imm
1408 0 : dasm_put(Dst, 1494, (x86_dst), imm);
1409 0 : #line 1067 "fd_jit_compiler.dasc"
1410 0 : break;
1411 :
1412 0 : case 0xb5: /* FD_SBPF_OP_JLE_IMM */
1413 : //| cmp dst64, imm
1414 : //| jbe =>jmp_dst_lbl
1415 0 : dasm_put(Dst, 1500, (x86_dst), imm, jmp_dst_lbl);
1416 0 : #line 1072 "fd_jit_compiler.dasc"
1417 0 : break;
1418 :
1419 0 : case 0xb7: /* FD_SBPF_OP_MOV64_IMM */
1420 0 : if( imm==0 ) {
1421 : //| xor dst32, dst32
1422 0 : dasm_put(Dst, 640, (x86_dst), (x86_dst));
1423 0 : #line 1077 "fd_jit_compiler.dasc"
1424 0 : } else {
1425 : //| mov dst64, imm
1426 0 : dasm_put(Dst, 648, (x86_dst), imm);
1427 0 : #line 1079 "fd_jit_compiler.dasc"
1428 0 : }
1429 0 : break;
1430 :
1431 0 : case 0xbc: /* FD_SBPF_OP_MOV_REG */
1432 : //| mov dst32, src32
1433 0 : dasm_put(Dst, 1511, (x86_src), (x86_dst));
1434 0 : #line 1084 "fd_jit_compiler.dasc"
1435 0 : break;
1436 :
1437 0 : case 0xbd: /* FD_SBPF_OP_JLE_REG */
1438 : //| cmp dst64, src64
1439 : //| jbe =>jmp_dst_lbl
1440 0 : dasm_put(Dst, 1519, (x86_src), (x86_dst), jmp_dst_lbl);
1441 0 : #line 1089 "fd_jit_compiler.dasc"
1442 0 : break;
1443 :
1444 0 : case 0xbf: /* FD_SBPF_OP_MOV64_REG */
1445 : //| mov dst64, src64
1446 0 : dasm_put(Dst, 1530, (x86_src), (x86_dst));
1447 0 : #line 1093 "fd_jit_compiler.dasc"
1448 0 : break;
1449 :
1450 : /* 0xc0 - 0xcf ******************************************************/
1451 :
1452 0 : case 0xc4: /* FD_SBPF_OP_ARSH_IMM */
1453 : //| sar dst32, imm
1454 0 : dasm_put(Dst, 1538, (x86_dst), imm);
1455 0 : #line 1099 "fd_jit_compiler.dasc"
1456 0 : break;
1457 :
1458 0 : case 0xc5: /* FD_SBPF_OP_JSLT_IMM */
1459 : //| cmp dst64, imm
1460 : //| jl =>jmp_dst_lbl
1461 0 : dasm_put(Dst, 1546, (x86_dst), imm, jmp_dst_lbl);
1462 0 : #line 1104 "fd_jit_compiler.dasc"
1463 0 : break;
1464 :
1465 0 : case 0xc7: /* FD_SBPF_OP_ARSH64_IMM */
1466 : //| sar dst64, imm
1467 0 : dasm_put(Dst, 1557, (x86_dst), imm);
1468 0 : #line 1108 "fd_jit_compiler.dasc"
1469 0 : break;
1470 :
1471 0 : case 0xcc: /* FD_SBPF_OP_ARSH_REG */
1472 : //| mov cl, src8
1473 : //| sar dst32, cl
1474 0 : dasm_put(Dst, 1565, (x86_src), (x86_dst));
1475 0 : #line 1113 "fd_jit_compiler.dasc"
1476 0 : break;
1477 :
1478 0 : case 0xcd: /* FD_SBPF_OP_JSLT_REG */
1479 : //| cmp dst64, src64
1480 : //| jl =>jmp_dst_lbl
1481 0 : dasm_put(Dst, 1577, (x86_src), (x86_dst), jmp_dst_lbl);
1482 0 : #line 1118 "fd_jit_compiler.dasc"
1483 0 : break;
1484 :
1485 0 : case 0xcf: /* FD_SBPF_OP_ARSH64_REG */
1486 : //| mov cl, src8
1487 : //| sar dst64, cl
1488 0 : dasm_put(Dst, 1588, (x86_src), (x86_dst));
1489 0 : #line 1123 "fd_jit_compiler.dasc"
1490 0 : break;
1491 :
1492 : /* 0xd0 - 0xdf ******************************************************/
1493 :
1494 0 : case 0xd4: /* FD_SBPF_OP_END_LE */
1495 : /* nop */
1496 0 : break;
1497 :
1498 0 : case 0xd5: /* FD_SBPF_OP_JSLE_IMM */
1499 : //| cmp dst64, imm
1500 : //| jle =>jmp_dst_lbl
1501 0 : dasm_put(Dst, 1600, (x86_dst), imm, jmp_dst_lbl);
1502 0 : #line 1134 "fd_jit_compiler.dasc"
1503 0 : break;
1504 :
1505 0 : case 0xdc: /* FD_SBPF_OP_END_BE */
1506 0 : switch( imm ) {
1507 0 : case 16U:
1508 : //| movzx dst32, Rw(x86_dst)
1509 : //| ror Rw(x86_dst), 8
1510 0 : dasm_put(Dst, 1611, (x86_dst), (x86_dst), (x86_dst));
1511 0 : #line 1141 "fd_jit_compiler.dasc"
1512 0 : break;
1513 0 : case 32U:
1514 : //| bswap dst32
1515 0 : dasm_put(Dst, 1627, (x86_dst));
1516 0 : #line 1144 "fd_jit_compiler.dasc"
1517 0 : break;
1518 0 : case 64U:
1519 : //| bswap dst64
1520 0 : dasm_put(Dst, 1633, (x86_dst));
1521 0 : #line 1147 "fd_jit_compiler.dasc"
1522 0 : break;
1523 0 : default:
1524 0 : break;
1525 : // TODO sigill
1526 0 : }
1527 0 : break;
1528 :
1529 0 : case 0xdd: /* FD_SBPF_OP_JSLE_REG */
1530 : //| cmp dst64, src64
1531 : //| jle =>jmp_dst_lbl
1532 0 : dasm_put(Dst, 1639, (x86_src), (x86_dst), jmp_dst_lbl);
1533 0 : #line 1157 "fd_jit_compiler.dasc"
1534 0 : break;
1535 :
1536 0 : default:
1537 0 : FD_LOG_WARNING(( "Unsupported opcode %lx", opcode ));
1538 0 : cur = text_end;
1539 0 : break;
1540 :
1541 0 : }
1542 :
1543 0 : }
1544 :
1545 : //|->overrun:
1546 : //| jmp ->vm_fault
1547 0 : dasm_put(Dst, 1650);
1548 0 : #line 1170 "fd_jit_compiler.dasc"
1549 :
1550 0 : }
1551 :
1552 : fd_jit_entrypoint_t
1553 0 : fd_jit_get_entrypoint( void ) {
1554 0 : return (fd_jit_entrypoint_t)(ulong)fd_jit_labels[ fd_jit_lbl_entrypoint ];
1555 0 : }
|