[t][TT #1119] Convert t/op/bitwise.t to PIR
[parrot.git] / src / frame_builder.h
blob8825ff9198db76e2ca698c4b5e33dbb628ccef37
1 /*
2 * Copyright (C) 2002-2009, Parrot Foundation.
3 */
5 /*
6 * frame_builder.h
8 * i386
10 * $Id$
13 #ifndef PARROT_I386_JIT_EMIT_H_GUARD
14 #define PARROT_I386_JIT_EMIT_H_GUARD
16 #if defined(__cplusplus)
17 # define EXTERN extern "C"
18 #else
19 # define EXTERN
20 #endif
22 #include <assert.h>
23 #include "parrot/parrot.h"
24 #include "parrot/hash.h"
25 #include "parrot/oplib/ops.h"
28 * NCI interface
30 void *
31 Parrot_jit_build_call_func(Interp *, PMC *, STRING *, int *);
33 /* custom pmc callback functions */
34 void
35 Parrot_jit_free_buffer(PARROT_INTERP, void *ptr, void *priv);
37 PMC*
38 Parrot_jit_clone_buffer(PARROT_INTERP, PMC *pmc, void *priv);
40 struct jit_buffer_private_data {
41 int size;
44 /* Scale factor values */
45 #define emit_Scale(scale) ((scale) << 6)
46 #define emit_Scale_1 emit_Scale(0)
47 #define emit_Scale_2 emit_Scale(1)
48 #define emit_Scale_4 emit_Scale(2)
49 #define emit_Scale_8 emit_Scale(3)
51 /* ESIB byte */
52 #define emit_reg_Index(x) (((x)-1) << 3)
53 #define emit_reg_Base(x) ((x)-1)
54 #define emit_Index_None ((emit_b100) << 3)
57 * helper funcs - get argument n
61 * if we have a delegated method like typeof_i_p, that returns an INTVAL
62 * and that is all in a sequence of JITted opcodes, and when these INTVAL
63 * is MAPped, we got a problem. So the EXT_CALL flag is disabled - mapped
64 * registers are saved/restored around vtable calls.
66 #define JIT_VTABLE_OPS 1
68 /* EXEC_SHARED generates code to be used with libparrot.so
69 * It grabs the real address of cgp_core from the gcc generated code
70 * x/1i cgp_code
71 * jmp *0xXXXX
72 * x/1wx 0xXXXX
73 * real address of cpg_core
74 * s. exec_emit_end
75 * XXX This should be a command line option.
77 #undef EXEC_SHARED
79 extern UINTVAL ld(UINTVAL);
81 #define NEG_MINUS_ZERO
82 /* #define NEG_ZERO_SUB */
84 /* Register codes */
85 #define emit_None 0
87 /* These are + 1 the real values */
88 #define emit_EAX 1
89 #define emit_ECX 2
90 #define emit_EDX 3
91 #define emit_EBX 4
92 #define emit_ESP 5
93 #define emit_EBP 6
94 #define emit_ESI 7
95 #define emit_EDI 8
97 /* Scratch register. */
99 #define ISR1 emit_EAX
100 #define FSR1 0
102 #define emit_b00 0
103 #define emit_b01 1
104 #define emit_b10 2
105 #define emit_b11 3
107 #define emit_b000 0
108 #define emit_b001 1
109 #define emit_b010 2
110 #define emit_b011 3
111 #define emit_b100 4
112 #define emit_b101 5
113 #define emit_b110 6
114 #define emit_b111 7
116 /* Mod R/M byte */
117 #define emit_reg(x) ((x) << 3)
118 #define emit_Mod(Mod) ((Mod) << 6)
119 #define emit_reg_rm(x) ((x)-1)
121 /* Mod values for Mod R/M Byte */
122 #define emit_Mod_b00 emit_Mod(emit_b00)
123 #define emit_Mod_b01 emit_Mod(emit_b01)
124 #define emit_Mod_b10 emit_Mod(emit_b10)
126 /* special R/M values */
127 #define emit_rm_b101 emit_b101
128 #define emit_rm_b100 emit_b100
130 #define emit_r_m(interp, pc, reg1, b, i, s, d) \
131 emit_r_X((interp), (pc), emit_reg((reg1)-1), (b), (i), (s), (d))
133 #define emit_alu_X_r(X, reg) ((emit_b11 << 6) | ((X) << 3) | ((reg) - 1))
135 #define emit_alu_r_r(reg1, reg2) emit_alu_X_r(((reg1) - 1), (reg2))
137 int emit_is8bit(long disp);
139 char * emit_disp8_32(char *pc, int disp);
141 void emit_sib(PARROT_INTERP, char *pc, int scale, int i, int base);
143 char * emit_r_X(PARROT_INTERP, char *pc, int reg_opcode, int base, int i,
144 int scale, long disp);
146 char * emit_shift_i_r(PARROT_INTERP, char *pc, int opcode, int imm, int reg);
148 char * emit_shift_i_m(PARROT_INTERP, char *pc, int opcode, int imm,
149 int base, int i, int scale, long disp);
151 char * emit_shift_r_r(PARROT_INTERP, char *pc, int opcode, int reg1, int reg2);
153 char * emit_shift_r_m(PARROT_INTERP, char *pc, int opcode, int reg,
154 int base, int i, int scale, long disp);
156 /* CDQ - need this to do multiply */
157 #define emitm_cdq(pc) *((pc)++) = (char) 0x99
159 /* RET */
160 #define emitm_ret(pc) *((pc)++) = (char) 0xc3
162 /* NOP */
163 #define emit_nop(pc) *((pc)++) = (char) 0x90
165 /* PUSHes */
167 #define emitm_pushl_r(pc, reg) \
168 *((pc)++) = (char) 0x50 | ((reg) - 1)
170 #define emitm_pushl_i(pc, imm) { \
171 *((pc)++) = (char) 0x68; \
172 *(long *)(pc) = (long)(imm); \
173 (pc) += 4; }
175 #define emitm_pushl_m(pc, mem) { \
176 *((pc)++) = (char) 0xff; \
177 *((pc)++) = (char) 0x35; \
178 *(long *)(pc) = (long)(mem); \
179 (pc) += 4; }
181 char * emit_pushl_m(PARROT_INTERP, char *pc, int base, int i, int scale,
182 long disp);
184 /* POPs */
186 char * emit_popl_r(char *pc, int reg);
188 # define emitm_popl_r(pc, reg) \
189 (pc) = emit_popl_r((pc), (reg))
191 char * emit_popl_m(PARROT_INTERP, char *pc, int base, int i, int scale,
192 long disp);
194 /* MOVes */
196 char * emit_movb_r_r(char *pc, int reg1, int reg2);
198 # define jit_emit_mov_rr_i(pc, reg2, reg1) if ((reg1) != (reg2)) { \
199 *((pc)++) = (char) 0x89; \
200 *((pc)++) = (char) emit_alu_r_r((reg1), (reg2)); }
202 # define jit_emit_mov_ri_i(interp, pc, reg, imm) { \
203 *((pc)++) = (char)(0xb8 | ((reg) - 1)); \
204 *(long *)(pc) = (long)(imm); (pc) += 4; }
206 # define emitm_movX_Y_Z(interp, op, pc, reg1, b, i, s, d) { \
207 *((pc)++) = (char) (op); \
208 (pc) = emit_r_m((interp), (pc), (reg1), (b), (i), (s), (long)(d)); }
210 # define emitm_movb_r_m(interp, pc, reg1, b, i, s, d) \
211 emitm_movX_Y_Z((interp), 0x88, (pc), (reg1), (b), (i), (s), (d))
213 # define emitm_movl_r_m(interp, pc, reg1, b, i, s, d) \
214 emitm_movX_Y_Z((interp), 0x89, (pc), (reg1), (b), (i), (s), (d))
216 /* move byte/word with sign extension */
217 # define emitm_movsbl_r_m(interp, pc, reg1, b, i, s, d) { \
218 *((pc)++) = (char) 0x0f; \
219 emitm_movX_Y_Z((interp), 0xBE, (pc), (reg1), (b), (i), (s), (d)); \
222 # define emitm_movswl_r_m(interp, pc, reg1, b, i, s, d) { \
223 *((pc)++) = (char) 0x0f; \
224 emitm_movX_Y_Z((interp), 0xBF, (pc), (reg1), (b), (i), (s), (d)); \
227 # define emitm_movsbl_r_r(pc, reg1, reg2) { \
228 *((pc)++) = (char) 0x0f; \
229 *((pc)++) = (char) 0xbe; \
230 *((pc)++) = (char) emit_alu_r_r((reg1), (reg2)); \
233 # define emitm_movswl_r_r(pc, reg1, reg2) { \
234 *((pc)++) = (char) 0x0f; \
235 *((pc)++) = (char) 0xbf; \
236 *((pc)++) = (char) emit_alu_r_r((reg1), (reg2)); \
239 # define emitm_movb_m_r(interp, pc, reg1, b, i, s, d) \
240 emitm_movX_Y_Z((interp), 0x8a, (pc), (reg1), (b), (i), (s), (d))
242 # define emitm_movl_m_r(interp, pc, reg1, b, i, s, d) \
243 emitm_movX_Y_Z((interp), 0x8b, (pc), (reg1), (b), (i), (s), (d))
245 # define emitm_lea_m_r(interp, pc, reg1, b, i, s, d) \
246 emitm_movX_Y_Z((interp), 0x8d, (pc), (reg1), (b), (i), (s), (d))
248 char * emit_movb_i_m(PARROT_INTERP, char *pc, char imm, int base, int i,
249 int scale, long disp);
251 # define emitm_movl_i_m(pc, imm, b, i, s, d) { \
252 *((pc)++) = (char) 0xc7; \
253 (pc) = emit_r_X((interp), (pc), emit_reg(emit_b000), (b), (i), (s), (long)(d)); \
254 *(long *)(pc) = (long)(imm); (pc) += 4; }
256 /* Various ALU formats */
258 # define emitm_alul_r_r(pc, op, reg1, reg2) { \
259 *((pc)++) = (char) (op); *((pc)++) = (char) emit_alu_r_r((reg1), (reg2)); }
261 # define emitm_alub_i_r(pc, op1, op2, imm, reg) { \
262 *((pc)++) = (char) (op1); *((pc)++) = (char) emit_alu_X_r((op2), (reg)); *((pc)++) = (char)(imm); }
264 # define emitm_alul_i_r(pc, op1, op2, imm, reg) { \
265 *((pc)++) = (char) (op1); \
266 *((pc)++) = (char) emit_alu_X_r((op2), (reg)); \
267 *(long *)((pc)) = (long)(imm); (pc) += 4; }
269 # define emitm_alul_i_m(pc, op1, op2, imm, b, i, s, d) { \
270 *((pc)++) = (char) (op1); \
271 (pc) = emit_r_X((interp), (pc), emit_reg(op2), (b), (i), (s), (d)); \
272 *(long *)(pc) = (long)(imm); (pc) += 4; }
274 # define emitm_alul_r_m(pc, op, reg, b, i, s, d) { \
275 *((pc)++) = (char) (op); \
276 (pc) = emit_r_X((interp), (pc), emit_reg((reg)-1), (b), (i), (s), (long)(d)); }
278 /* ADDs */
280 # define emitm_addb_r_r(pc, reg1, reg2) \
281 emitm_alul_r_r((pc), 0x00, (reg1), (reg2))
283 # define emitm_addb_i_r(pc, imm, reg) \
284 emitm_alub_i_r((pc), 0x83, emit_b000, (imm), (reg))
286 # define jit_emit_add_rr_i(interp, pc, reg1, reg2) \
287 emitm_alul_r_r((pc), 0x01, (reg2), (reg1))
289 # define jit_emit_add_ri_i(interp, pc, reg, imm) \
290 emitm_alul_i_r((pc), 0x81, emit_b000, (imm), (reg))
292 # define emitm_addl_i_r(pc, imm, reg) \
293 emitm_alul_i_r((pc), 0x81, emit_b000, (imm), (reg))
295 # define emitm_addl_i_m(pc, imm, b, i, s, d) \
296 emitm_alul_i_m((pc), 0x81, emit_b000, (imm), (b), (i), (s), (d))
298 # define emitm_addl_r_m(pc, reg, b, i, s, d) \
299 emitm_alul_r_m((pc), 0x01, (reg), (b), (i), (s), (d))
301 # define emitm_addl_m_r(pc, reg, b, i, s, d) \
302 emitm_alul_r_m((pc), 0x03, (reg), (b), (i), (s), (d))
304 /* SUBs */
306 # define jit_emit_sub_rr_i(interp, pc, reg1, reg2) \
307 emitm_alul_r_r((pc), 0x29, (reg2), (reg1))
309 # define emitm_subl_i_r(pc, imm, reg) \
310 emitm_alul_i_r((pc), 0x81, emit_b101, (imm), (reg))
312 # define jit_emit_sub_ri_i(interp, pc, r, i) emitm_subl_i_r((pc), (i), (r))
314 # define emitm_subl_r_m(pc, reg, b, i, s, d) \
315 emitm_alul_r_m((pc), 0x29, (reg), (b), (i), (s), (d))
317 # define emitm_subl_m_r(pc, reg, b, i, s, d) \
318 emitm_alul_r_m((pc), 0x2b, (reg), (b), (i), (s), (d))
320 # define emitm_subl_i_m(pc, imm, b, i, s, d) \
321 emitm_alul_i_m((pc), 0x81, emit_b101, (imm), (b), (i), (s), (d))
323 /* These are used by both signed and unsigned EDIV, but only unsigned MUL */
324 # define emitm_alu_imp_r(pc, op, reg) { \
325 *((pc)++) = (char) 0xf7; \
326 *((pc)++) = (char) emit_alu_X_r((op), (reg)); }
328 # define emitm_alu_imp_m(pc, op, b, i, s, d) { \
329 *((pc)++) = (char) 0xf7; \
330 (pc) = emit_r_X((interp), (pc), emit_reg(op), (b), (i), (s), (d)); }
332 /* Unsigned MUL and EDIV */
333 /* EAX implicit destination in multiply and divide */
335 # define emitm_umull_r(pc, reg2) emitm_alu_imp_r((pc), emit_b100, (reg2))
337 # define emitm_udivl_r(pc, reg2) emitm_alu_imp_r((pc), emit_b110, (reg2))
339 # define emitm_umull_m(pc, b, i, s, d) \
340 emitm_alu_imp_m((pc), emit_b100, (b), (i), (s), (d))
342 # define emitm_udivl_m(pc, b, i, s, d) \
343 emitm_alu_imp_m((pc), emit_b110, (b), (i), (s), (d))
345 /* Signed MUL and EDIV */
347 # define emitm_sdivl_r(pc, reg2) emitm_alu_imp_r((pc), emit_b111, (reg2))
349 # define emitm_sdivl_m(pc, b, i, s, d) \
350 emitm_alu_imp_m((pc), emit_b111, (b), (i), (s), (d))
352 # define jit_emit_cdq(pc) *(pc)++ = 0x99
354 /* TEST for zero */
355 # define jit_emit_test_r_i(pc, reg1) emitm_alul_r_r((pc), 0x85, (reg1), (reg1))
357 # define emitm_smull_r(pc, reg2) emitm_alu_imp_r((pc), emit_b101, (reg2))
359 # define jit_emit_mul_rr_i(interp, pc, reg1, reg2) { \
360 *(pc)++ = 0xf; \
361 emitm_alul_r_r((pc), 0xaf, (reg1), (reg2)); }
363 # define emitm_smull_r_m(pc, reg1, b, i, s, d) { \
364 *(pc)++ = 0xf; \
365 emitm_alul_r_m((pc), 0xaf, (reg1), (b), (i), (s), (d)); }
367 char * opt_mul(PARROT_INTERP, char *pc, int dest, INTVAL imm, int src);
369 # define jit_emit_mul_rir_i(pc, dest, imm, src) \
370 (pc) = opt_mul(interp, (pc), (dest), (imm), (src))
373 # define jit_emit_mul_ri_i(pc, r, imm) jit_emit_mul_rir_i((pc), (r), (imm), (r))
375 # define jit_emit_mul_RIM_ii(pc, reg, imm, ofs) \
376 emitm_alul_r_m((pc), 0x69, (reg), emit_EBX, emit_None, 1, (ofs)); \
377 *(long *)(pc) = (long)(imm); \
378 (pc) += 4;
380 /* NEG */
382 # define jit_emit_neg_r_i(pc, reg) emitm_alu_imp_r((pc), emit_b011, (reg))
384 # define emitm_negl_m(pc, b, i, s, d) \
385 emitm_alu_imp_m((pc), emit_b011, (b), (i), (s), (d))
387 /* AND */
389 # define emit_andl_r_r(pc, reg1, reg2) emitm_alul_r_r((pc), 0x21, (reg1), (reg2))
390 # define jit_emit_band_rr_i(interp, pc, r1, r2) emit_andl_r_r((pc), (r2), (r1))
392 # define jit_emit_band_ri_i(interp, pc, reg, imm) \
393 emitm_alul_i_r((pc), 0x81, emit_b100, (imm), (reg))
395 # define emitm_andl_r_m(pc, reg, b, i, s, d) \
396 emitm_alul_r_m((pc), 0x21, (reg), (b), (i), (s), (d))
398 # define emitm_andl_m_r(pc, reg, b, i, s, d) \
399 emitm_alul_r_m((pc), 0x23, (reg), (b), (i), (s), (d))
401 # define emitm_andl_i_m(pc, imm, b, i, s, d) \
402 emitm_alul_i_m((pc), 0x81, emit_b100, (imm), (b), (i), (s), (d))
404 /* TEST op */
405 # define jit_emit_test_rr_i(pc, r1, r2) emitm_alul_r_r((pc), 0x85, (r1), (r2))
407 # define jit_emit_test_ri_i(pc, r, im) \
408 emitm_alul_i_r((pc), 0xF7, emit_b000, (im), (r))
410 # define jit_emit_test_RM_i(pc, r, offs) \
411 emitm_alul_r_m((pc), 0x85, (r), emit_EBX, 0, 1, (offs))
413 /* OR */
415 # define jit_emit_bor_rr_i(interp, pc, reg1, reg2) emitm_alul_r_r((pc), 0x9, (reg2), (reg1))
417 # define jit_emit_bor_ri_i(interp, pc, reg, imm) \
418 emitm_alul_i_r((pc), 0x81, emit_b001, (imm), (reg))
420 # define emitm_orl_r_m(pc, reg, b, i, s, d) \
421 emitm_alul_r_m((pc), 0x09, (reg), (b), (i), (s), (d))
423 # define emitm_orl_m_r(pc, reg, b, i, s, d) \
424 emitm_alul_r_m((pc), 0x0b, (reg), (b), (i), (s), (d))
426 # define emitm_orl_i_m(pc, imm, b, i, s, d) \
427 emitm_alul_i_m((pc), 0x81, emit_b001, (imm), (b), (i), (s), (d))
429 /* XOR */
431 # define jit_emit_bxor_rr_i(interp, pc, reg1, reg2) \
432 emitm_alul_r_r((pc), 0x31, (reg2), (reg1))
434 # define jit_emit_bxor_ri_i(intepr, pc, reg, imm) \
435 emitm_alul_i_r((pc), 0x81, emit_b110, (imm), (reg))
437 # define emitm_xorl_r_m(pc, reg, b, i, s, d) \
438 emitm_alul_r_m((pc), 0x31, (reg), (b), (i), (s), (d))
440 # define emitm_xorl_m_r(pc, reg, b, i, s, d) \
441 emitm_alul_r_m((pc), 0x33, (reg), (b), (i), (s), (d))
443 # define emitm_xorl_i_m(pc, imm, b, i, s, d) \
444 emitm_alul_i_m((pc), 0x81, emit_b110, (imm), (b), (i), (s), (d))
446 /* NOT */
448 # define jit_emit_not_r_i(pc, reg) emitm_alu_imp_r((pc), emit_b010, (reg))
449 # define emitm_notl_m(pc, b, i, s, d) \
450 emitm_alu_imp_m((pc), emit_b010, (b), (i), (s), (d))
452 # define jit_emit_not_M_i(interp, pc, offs) emitm_notl_m((pc), emit_EBX, 0, 1, (offs))
454 /* XCHG */
455 # define jit_emit_xchg_rr_i(interp, pc, r1, r2) { \
456 if ((r1) != (r2)) { \
457 *((pc)++) = (char) 0x87; \
458 *((pc)++) = (char) emit_alu_r_r((r1), (r2)); \
462 # define jit_emit_xchg_rm_i(pc, r, m) { \
463 emitm_alul_r_m((pc), 0x87, (r), emit_None, emit_None, emit_None, (m)) \
465 # define jit_emit_xchg_RM_i(interp, pc, r, offs) { \
466 emitm_alul_r_m((pc), 0x87, (r), emit_EBX, emit_None, 1, (offs)) \
468 # define jit_emit_xchg_MR_i(interp, pc, offs, r) jit_emit_xchg_RM_i((interp), (pc), (r), (offs))
470 /* SHL */
472 # define jit_emit_shl_ri_i(interp, pc, reg, imm) \
473 { (pc) = emit_shift_i_r((interp), (pc), emit_b100, (imm), (reg)); }
475 # define emitm_shll_i_m(pc, imm, b, i, s, d) \
476 { (pc) = emit_shift_i_m((pc), emit_b100, (imm), (b), (i), (s), (d)); }
478 # define emitm_shll_r_r(interp, pc, reg1, reg2) \
479 { (pc) = emit_shift_r_r((interp), (pc), emit_b100, (reg1), (reg2)); }
481 # define emitm_shll_r_m(pc, reg, b, i, s, d) \
482 { (pc) = emit_shift_r_m((pc), emit_b100, (reg), (b), (i), (s), (d)); }
484 /* SHR */
486 # define jit_emit_lsr_ri_i(interp, pc, reg, imm) \
487 { (pc) = emit_shift_i_r((interp), (pc), emit_b101, (imm), (reg)); }
489 # define emitm_shrl_i_m(pc, imm, b, i, s, d) \
490 { (pc) = emit_shift_i_m((pc), emit_b101, (imm), (b), (i), (s), (d)); }
492 # define emitm_shrl_r_r(interp, pc, reg1, reg2) \
493 { (pc) = emit_shift_r_r((interp), (pc), emit_b101, (reg1), (reg2)); }
495 # define emitm_shrl_r_m(pc, reg, b, i, s, d) \
496 { (pc) = emit_shift_r_m((pc), emit_b101, (reg), (b), (i), (s), (d)); }
498 /* SAL */
500 # define emitm_sall_i_r(interp, pc, imm, reg) \
501 { (pc) = emit_shift_i_r((interp), (pc), emit_b100, (imm), (reg)); }
503 # define emitm_sall_i_m(pc, imm, b, i, s, d) \
504 { (pc) = emit_shift_i_m((pc), emit_b100, (imm), (b), (i), (s), (d)); }
506 # define emitm_sall_r_r(interp, pc, reg1, reg2) \
507 { (pc) = emit_shift_r_r((interp), (pc), emit_b100, (reg1), (reg2)); }
509 # define emitm_sall_r_m(pc, reg, b, i, s, d) \
510 { (pc) = emit_shift_r_m((pc), emit_b100, (reg), (b), (i), (s), (d)); }
512 /* SAR */
514 # define jit_emit_shr_ri_i(interp, pc, reg, imm) \
515 { (pc) = emit_shift_i_r((interp), (pc), emit_b111, (imm), (reg)); }
518 # define emitm_sarl_i_m(pc, imm, b, i, s, d) \
519 { (pc) = emit_shift_i_m((pc), emit_b111, (imm), (b), (i), (s), (d)); }
521 # define emitm_sarl_r_r(interp, pc, reg1, reg2) \
522 { (pc) = emit_shift_r_r((interp), (pc), emit_b111, (reg1), (reg2)); }
524 # define emitm_sarl_r_m(pc, reg, b, i, s, d) \
525 { (pc) = emit_shift_r_m((pc), emit_b111, (reg), (b), (i), (s), (d)); }
527 /* rotate */
529 # define jit_emit_rol_ri_i(interp, pc, reg, imm) \
530 { (pc) = emit_shift_i_r((interp), (pc), emit_b000, (imm), (reg)); }
532 # define jit_emit_ror_ri_i(interp, pc, reg, imm) \
533 { (pc) = emit_shift_i_r((interp), (pc), emit_b001, (imm), (reg)); }
535 /* interface, shift r1 by r2 bits */
537 # define jit_emit_shl_rr_i(interp, pc, r1, r2) \
538 (pc) = opt_shift_rr((interp), jit_info, (r1), (r2), emit_b100)
540 # define jit_emit_shl_RM_i(interp, pc, r1, offs) \
541 (pc) = opt_shift_rm((interp), jit_info, (r1), (offs), emit_b100)
543 /* shr seems to be the arithmetic shift */
544 # define jit_emit_shr_rr_i(interp, pc, r1, r2) \
545 (pc) = opt_shift_rr((interp), jit_info, (r1), (r2), emit_b111)
547 # define jit_emit_shr_RM_i(interp, pc, r1, offs) \
548 (pc) = opt_shift_rm((interp), jit_info, (r1), (offs), emit_b111)
550 # define jit_emit_lsr_rr_i(interp, pc, r1, r2) \
551 (pc) = opt_shift_rr((interp), jit_info, (r1), (r2), emit_b101)
553 # define jit_emit_lsr_RM_i(interp, pc, r1, offs) \
554 (pc) = opt_shift_rm((interp), jit_info, (r1), (offs), emit_b101)
556 /* MOV (reg), reg */
557 # define emit_movm_r_r(pc, src, dest) \
558 *((pc)++) = (char) 0x8b; \
559 *((pc)++) = (char) (src) | (dest) << 3
561 /* MOV X(reg), reg */
562 # define emit_movb_i_r_r(pc, imm, src, dest) \
563 *((pc)++) = (char)(0x8b); \
564 *((p)c++) = (char)(0x40 | ((src) - 1) | ((dest) - 1) << 3); \
565 *((pc)++) = (imm)
567 /* INC / DEC */
568 # define jit_emit_inc_r_i(pc, reg) *((pc)++) = (char)(0x40 | ((reg) - 1))
569 # define jit_emit_dec_r_i(pc, reg) *((pc)++) = (char)(0x48 | ((reg) - 1))
571 /* Floating point ops */
573 # define emitm_floatop 0xd8 /* 11011000 */
574 # define jit_emit_dec_fsp(pc) { *((pc)++) = (char) 0xD9; *((pc)++) = (char) 0xF6; }
575 # define jit_emit_inc_fsp(pc) { *((pc)++) = (char) 0xD9; *((pc)++) = (char) 0xF7; }
577 # define emitm_fl_2(interp, pc, mf, opa, opb, b, i, s, d) { \
578 *((pc)++) = (char)(emitm_floatop | ((mf) << 1) | (opa)); \
579 (pc) = emit_r_X((interp), (pc), emit_reg(opb), (b), (i), (s), (long)(d)); }
581 # define emitm_fl_3(pc, d_p_opa, opb_r, sti) { \
582 *((pc)++) = (char)(emitm_floatop | (d_p_opa)); \
583 *((pc)++) = (char)(0xc0 | ((opb_r) << 3) | (sti)); }
585 # define emitm_fl_4(pc, op) { \
586 *((pc)++) = (char)(emitm_floatop | emit_b001); \
587 *((pc)++) = (char)(0xe0 | (op)); }
589 /* Integer loads and stores */
590 # define emitm_fildl(interp, pc, b, i, s, d) \
591 emitm_fl_2((interp), (pc), emit_b01, 1, emit_b000, (b), (i), (s), (d))
593 # define emitm_fistpl(interp, pc, b, i, s, d) \
594 emitm_fl_2((interp), (pc), emit_b01, 1, emit_b011, (b), (i), (s), (d))
596 # define emitm_fistl(interp, pc, b, i, s, d) \
597 emitm_fl_2((interp), (pc), emit_b01, 1, emit_b010, (b), (i), (s), (d))
599 /* long long integer load/store */
600 # define emitm_fildll(interp, pc, b, i, s, d) \
601 emitm_fl_2((interp), (pc), emit_b11, 1, emit_b101, (b), (i), (s), (d))
603 # define emitm_fistpll(interp, pc, b, i, s, d) \
604 emitm_fl_2((interp), (pc), emit_b11, 1, emit_b111, (b), (i), (s), (d))
606 /* Double loads and stores */
607 # define emitm_fldl(interp, pc, b, i, s, d) \
608 emitm_fl_2((interp), (pc), emit_b10, 1, emit_b000, (b), (i), (s), (d))
610 # define emitm_fstpl(interp, pc, b, i, s, d) \
611 emitm_fl_2((interp), (pc), emit_b10, 1, emit_b011, (b), (i), (s), (d))
613 # define emitm_fstl(interp, pc, b, i, s, d) \
614 emitm_fl_2((interp), (pc), emit_b10, 1, emit_b010, (b), (i), (s), (d))
616 /* long double load / store */
617 # define emitm_fldt(interp, pc, b, i, s, d) \
618 emitm_fl_2((interp), (pc), emit_b01, 1, emit_b101, (b), (i), (s), (d))
620 # define emitm_fstpt(interp, pc, b, i, s, d) \
621 emitm_fl_2((interp), (pc), emit_b01, 1, emit_b111, (b), (i), (s), (d))
623 /* short float load / store */
624 # define emitm_flds(interp, pc, b, i, s, d) \
625 emitm_fl_2((interp), (pc), emit_b00, 1, emit_b000, (b), (i), (s), (d))
627 # define emitm_fstps(interp, pc, b, i, s, d) \
628 emitm_fl_2((interp), (pc), emit_b00, 1, emit_b010, (b), (i), (s), (d))
630 #if NUMVAL_SIZE == 8
632 # define jit_emit_fload_m_n(interp, pc, address) \
633 emitm_fldl((interp), (pc), emit_None, emit_None, emit_None, (address))
635 # define jit_emit_fload_mb_n(interp, pc, base, offs) \
636 emitm_fldl((interp), (pc), (base), emit_None, 1, (offs))
638 # define jit_emit_fstore_m_n(interp, pc, address) \
639 emitm_fstpl((interp), (pc), emit_None, emit_None, emit_None, (address))
641 # define jit_emit_fstore_mb_n(interp, pc, base, offs) \
642 emitm_fstpl((interp), (pc), (base), emit_None, 1, (offs))
644 # define jit_emit_fst_mb_n(interp, pc, base, offs) \
645 emitm_fstl((interp), (pc), (base), emit_None, 1, (offs))
647 #else /* NUMVAL_SIZE */
649 # define jit_emit_fload_m_n(interp, pc, address) \
650 emitm_fldt((pc), emit_None, emit_None, emit_None, (address))
652 # define jit_emit_fload_mb_n(interp, pc, base, offs) \
653 emitm_fldt((pc), (base), emit_None, 1, (offs))
655 # define jit_emit_fstore_m_n(pc, address) \
656 emitm_fstpt((pc), emit_None, emit_None, emit_None, (address))
658 # define jit_emit_fstore_mb_n(interp, pc, base, offs) \
659 emitm_fstpt((pc), (base), emit_None, 1, (offs))
661 # define jit_emit_fst_mb_n(interp, pc, base, offs) \
662 emitm_fstt((pc), (base), emit_None, 1, (offs))
664 #endif /* NUMVAL_SIZE */
666 #if INTVAL_SIZE == 4
668 # define jit_emit_fload_m_i(interp, pc, address) \
669 emitm_fildl((interp), (pc), emit_None, emit_None, emit_None, (address))
670 # define jit_emit_fload_mb_i(interp, pc, offs) \
671 emitm_fildl((interp), (pc), emit_EBX, emit_None, 1, (offs))
672 # define jit_emit_fstore_m_i(pc, m) \
673 emitm_fistpl((pc), emit_None, emit_None, emit_None, (m))
675 #else /* INTVAL_SIZE */
677 # define jit_emit_fload_m_i(interp, pc, address) \
678 emitm_fildll((interp), (pc), emit_None, emit_None, emit_None, (address))
679 # define jit_emit_fload_mb_i(interp, pc, offs) \
680 emitm_fildll((interp), (pc), emit_EBX, emit_None, 1, (offs))
681 # define jit_emit_fstore_m_i(pc, m) \
682 emitm_fistpll((pc), emit_None, emit_None, emit_None, (m))
684 #endif /* INTVAL_SIZE */
686 /* 0xD8 ops */
687 # define emitm_fadd(pc, sti) emitm_fl_3((pc), emit_b000, emit_b000, (sti))
688 # define emitm_fmul(pc, sti) emitm_fl_3((pc), emit_b000, emit_b001, (sti))
689 # define emitm_fsub(pc, sti) emitm_fl_3((pc), emit_b000, emit_b100, (sti))
690 # define emitm_fdiv(pc, sti) emitm_fl_3((pc), emit_b000, emit_b110, (sti))
692 /* 0xD9 ops */
693 # define emitm_fldz(pc) { *((pc)++) = (char) 0xd9; *((pc)++) = (char) 0xee; }
694 # define emitm_fld1(pc) { *((pc)++) = (char) 0xd9; *((pc)++) = (char) 0xe8; }
695 # define emitm_fsqrt(pc) { *((pc)++) = (char) 0xd9; *((pc)++) = (char) 0xfa; }
696 # define emitm_fsin(pc) { *((pc)++) = (char) 0xd9; *((pc)++) = (char) 0xfe; }
697 # define emitm_fcos(pc) { *((pc)++) = (char) 0xd9; *((pc)++) = (char) 0xff; }
698 # define emitm_fxam(pc) { *((pc)++) = (char) 0xd9; *((pc)++) = (char) 0xe5; }
700 /* FXCH ST, ST(i) , optimize 2 consecutive fxch with same reg */
701 # define emitm_fxch(pc, sti) { \
702 emitm_fl_3((pc), emit_b001, emit_b001, (sti)); \
705 /* FLD ST, ST(i), optimized FSTP(N+1);FLD(N) => FST(N+1) */
706 extern unsigned char *lastpc;
707 # define emitm_fld(pc, sti) do { \
708 if ((unsigned char *)(pc) == (lastpc + 2) && \
709 (int)(*lastpc) == (int)0xDD && \
710 (int)lastpc[1] == (int)(0xD8+(sti)+1)) \
711 lastpc[1] = 0xD0+(sti)+1; \
712 else \
713 emitm_fl_3((pc), emit_b001, emit_b000, (sti)); \
714 } while (0)
716 /* 0xDA, 0xDB ops */
717 /* FCMOV*, FCOMI PPRO */
719 /* 0xDC like 0xD8 with reversed operands */
720 # define emitm_faddr(pc, sti) emitm_fl_3((pc), emit_b100, emit_b000, (sti))
721 # define emitm_fmulr(pc, sti) emitm_fl_3((pc), emit_b100, emit_b001, (sti))
722 # define emitm_fsubr(pc, sti) emitm_fl_3((pc), emit_b100, emit_b100, (sti))
724 /* 0xDD ops */
725 /* FFree ST(i) */
726 # define emitm_ffree(pc, sti) emitm_fl_3((pc), emit_b101, emit_b000, (sti))
728 /* FST ST(i) = ST */
729 # define emitm_fst(pc, sti) emitm_fl_3((pc), emit_b101, emit_b010, (sti))
731 /* FSTP ST(i) = ST, POP */
732 # define emitm_fstp(pc, sti) { \
733 lastpc = (unsigned char*) (pc); \
734 emitm_fl_3((pc), emit_b101, emit_b011, (sti)); \
737 /* FUCOM ST(i) <=> ST unordered compares */
738 # define emitm_fucom(pc, sti) emitm_fl_3((pc), emit_b101, emit_b100, (sti))
740 /* FUCOMP ST(i) <=> ST, POP */
741 # define emitm_fucomp(pc, sti) emitm_fl_3((pc), emit_b101, emit_b101, (sti))
743 /* 0xDE ops */
744 /* FADDP Add ST(i) = ST + ST(i); POP */
745 # define emitm_faddp(pc, sti) emitm_fl_3((pc), emit_b110, emit_b000, (sti))
747 /* FMULP Mul ST(i) = ST * ST(i); POP */
748 # define emitm_fmulp(pc, sti) emitm_fl_3((pc), emit_b110, emit_b001, (sti))
750 /* FSUB ST = ST - ST(i) */
752 /* FSUBRP SubR ST(i) = ST - ST(i); POP */
753 # define emitm_fsubrp(pc, sti) emitm_fl_3((pc), emit_b110, emit_b100, (sti))
755 /* FSUBP Sub ST(i) = ST(i) - ST; POP */
756 # define emitm_fsubp(pc, sti) emitm_fl_3((pc), emit_b110, emit_b101, (sti))
758 /* FDIVRP DivR ST(i) = ST(i) / ST(0); POP */
759 # define emitm_fdivrp(pc, sti) emitm_fl_3((pc), emit_b110, emit_b110, (sti))
761 /* FDIVP Div ST(i) = ST(0) / ST(i); POP ST(0) */
762 # define emitm_fdivp(pc, sti) emitm_fl_3((pc), emit_b110, emit_b111, (sti))
764 /* 0xDF OPS: FCOMIP, FUCOMIP PPRO */
766 /* Negate - called change sign */
767 # define emitm_fchs(pc) emitm_fl_4((pc), 0)
769 /* ABS - ST(0) = ABS(ST(0)) */
770 # define emitm_fabs(pc) emitm_fl_4((pc), 1)
772 /* Comparisons */
774 # define emitm_fcom(pc, sti) emitm_fl_3((pc), emit_b000, emit_b010, (sti))
776 # define emitm_fcomp(pc, sti) emitm_fl_3((pc), emit_b000, emit_b011, (sti))
778 #ifdef PARROT_HAS_JIT_FCOMIP
779 # define emitm_fcomip(pc, sti) emitm_fl_3((pc), emit_b111, emit_b110, (sti))
780 # define emitm_fcomi(pc, sti) emitm_fl_3((pc), emit_b011, emit_b110, (sti))
781 #else
782 # define emitm_fcomip(pc, sti) do { \
783 emitm_fcomp((pc), (sti)); \
784 emitm_fstw(pc); \
785 emitm_sahf(pc); \
786 } while (0)
787 # define emitm_fcomi(pc, sti) do { \
788 emitm_fcom((pc), (sti)); \
789 emitm_fstw(pc); \
790 emitm_sahf(pc); \
791 } while (0)
792 #endif
794 # define emitm_fcompp(pc) { *((pc)++) = (char) 0xde; *((pc)++) = (char) 0xd9; }
796 # define emitm_fcom_m(interp, pc, b, i, s, d) \
797 emitm_fl_2((interp), (pc), emit_b10, 0, emit_b010, (b), (i), (s), (d))
799 # define emitm_fcomp_m(interp, pc, b, i, s, d) \
800 emitm_fl_2((interp), (pc), emit_b10, 0, emit_b011, (b), (i), (s), (d))
802 /* ST -= real64 */
803 # define emitm_fsub_m(interp, pc, b, i, s, d) \
804 emitm_fl_2((interp), (pc), emit_b10, 0, emit_b100, (b), (i), (s), (d))
806 /* ST -= int32_mem */
807 # define emitm_fisub_m(interp, pc, b, i, s, d) \
808 emitm_fl_2((interp), (pc), emit_b01, 0, emit_b100, (b), (i), (s), (d))
810 # define emitm_fadd_m(interp, pc, b, i, s, d) \
811 emitm_fl_2((interp), (pc), emit_b10, 0, emit_b000, (b), (i), (s), (d))
813 /* ST += int32_mem */
814 # define emitm_fiadd_m(interp, pc, b, i, s, d) \
815 emitm_fl_2((interp), (pc), emit_b01, 0, emit_b000, (b), (i), (s), (d))
817 /* ST *= real64 */
818 # define emitm_fmul_m(interp, pc, b, i, s, d) \
819 emitm_fl_2((interp), (pc), emit_b10, 0, emit_b001, (b), (i), (s), (d))
821 /* ST *= int32_mem */
822 # define emitm_fimul_m(interp, pc, b, i, s, d) \
823 emitm_fl_2((interp), (pc), emit_b01, 0, emit_b001, (b), (i), (s), (d))
825 /* ST /= real64 */
826 # define emitm_fdiv_m(interp, pc, b, i, s, d) \
827 emitm_fl_2((interp), (pc), emit_b10, 0, emit_b110, (b), (i), (s), (d))
829 /* ST /= int32_mem */
830 # define emitm_fidiv_m(interp, pc, b, i, s, d) \
831 emitm_fl_2((interp), (pc), emit_b01, 0, emit_b110, (b), (i), (s), (d))
833 /* Ops Needed to support loading EFLAGs for conditional branches */
834 # define emitm_fstw(pc) emitm_fl_3((pc), emit_b111, emit_b100, emit_b000)
836 # define emitm_sahf(pc) *((pc)++) = (char) 0x9e
838 /* misc float */
839 # define emitm_ftst(pc) { *(pc)++ = 0xd9; *(pc)++ = 0xE4; }
840 # define emitm_fprem(pc) { *(pc)++ = 0xd9; *(pc)++ = 0xF8; }
841 # define emitm_fprem1(pc) { *(pc)++ = 0xd9; *(pc)++ = 0xF5; }
843 # define emitm_fldcw(interp, pc, mem) \
844 emitm_fl_2((interp), (pc), emit_b00, 1, emit_b101, 0, 0, 0, (mem))
846 #if defined(NEG_MINUS_ZERO)
847 # define jit_emit_neg_r_n(pc, r) { \
848 if (r) { \
849 emitm_fld((pc), (r)); \
851 emitm_fchs(pc); \
852 if (r) { \
853 emitm_fstp((pc), ((r)+1)); \
857 # define jit_emit_neg_M_n(interp, pc, mem) { \
858 jit_emit_fload_mb_n((interp), (pc), emit_EBX, (mem)); \
859 emitm_fchs(pc); \
860 jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (mem)); \
863 #elif defined(NEG_ZERO_SUB)
865 # define jit_emit_neg_r_n(pc, r) { \
866 emitm_fldz(pc); \
867 emitm_fsubrp((pc), ((r)+1)); \
870 # define jit_emit_neg_M_n(interp, pc, mem) { \
871 jit_emit_fload_mb_n((interp), (pc), emit_EBX, (mem)); \
872 emitm_fldz(pc); \
873 emitm_fsubrp((pc), 1); \
874 jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (mem)); \
876 #else
878 # define jit_emit_neg_r_n(pc, r) { \
879 if (r) { \
880 emitm_fld((pc), (r)); \
882 emitm_ftst(pc); \
883 emitm_fstw(pc); \
884 emitm_sahf(pc); \
885 emitm_jxs((pc), emitm_jz, 2); \
886 emitm_fchs(pc); \
887 if (r) { \
888 emitm_fstp((pc), ((r)+1)); \
892 # define jit_emit_neg_M_n(interp, pc, mem) { \
893 jit_emit_fload_mb_n((interp), (pc), emit_EBX, (mem)); \
894 emitm_ftst(pc); \
895 emitm_fstw(pc); \
896 emitm_sahf(pc); \
897 emitm_jxs((pc), emitm_jz, 2); \
898 emitm_fchs(pc); \
899 jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (mem)); \
901 #endif
903 # define jit_emit_sin_r_n(pc, r) \
904 if (r) { \
905 emitm_fld((pc), (r)); \
907 emitm_fsin(pc); \
908 if (r) { \
909 emitm_fstp((pc), ((r)+1)); \
912 # define jit_emit_cos_r_n(pc, r) \
913 if (r) { \
914 emitm_fld((pc), (r)); \
916 emitm_fcos(pc); \
917 if (r) { \
918 emitm_fstp((pc), ((r)+1)); \
921 # define jit_emit_sqrt_r_n(pc, r) \
922 if (r) { \
923 emitm_fld((pc), (r)); \
925 emitm_fsqrt(pc); \
926 if (r) { \
927 emitm_fstp((pc), ((r)+1)); \
930 # define jit_emit_abs_r_n(pc, r) { \
931 if (r) { \
932 emitm_fld((pc), (r)); \
934 emitm_fabs(pc); \
935 if (r) { \
936 emitm_fstp((pc), ((r)+1)); \
940 # define jit_emit_abs_r_i(pc, r) { \
941 jit_emit_test_r_i((pc), (r)); \
942 emitm_jxs((pc), emitm_jns, 3); \
943 jit_emit_not_r_i((pc), (r)); \
944 jit_emit_inc_r_i((pc), (r)); \
947 # define jit_emit_abs_m_n(interp, pc, mem) { \
948 jit_emit_fload_m_n((interp), (pc), (mem)); \
949 emitm_fabs(pc); \
950 jit_emit_fstore_m_n((pc), (mem)); \
953 /* Integer comparisons */
954 # define jit_emit_cmp_rr(pc, reg1, reg2) \
955 emitm_alul_r_r((pc), 0x39, (reg2), (reg1))
956 # define jit_emit_cmp_rr_i(pc, r1, r2) jit_emit_cmp_rr((pc), (r1), (r2))
958 # define emitm_cmpl_r_m(pc, reg, b, i, s, d) \
959 emitm_alul_r_m((pc), 0x3b, (reg), (b), (i), (s), (d))
961 # define emitm_cmpl_m_r(pc, reg, b, i, s, d) \
962 emitm_alul_r_m((pc), 0x39, (reg), (b), (i), (s), (d))
964 # define jit_emit_cmp_ri_i(interp, pc, reg, imm) \
965 emitm_alul_i_r((pc), 0x81, emit_b111, (imm), (reg))
967 /* Unconditional Jump/Call */
969 # define emitm_call_cfunc(pc, func) emitm_calll((pc), (char *)(func) - (pc) - 4)
971 # define emitm_calll(pc, disp) { \
972 *((pc)++) = (char) 0xe8; \
973 *(long *)(pc) = (disp); (pc) += 4; }
975 # define emitm_callr(pc, reg) { \
976 *((pc)++) = (char) 0xff; \
977 *((pc)++) = (char) 0xd0 | ((reg) - 1); }
979 # define emitm_callm(pc, b, i, s, d) { \
980 *((pc)++) = (char) 0xff; \
981 (pc) = emit_r_X((interp), (pc), emit_reg(emit_b010), (b), (i), (s), (d)); }
983 # define emitm_jumps(pc, disp) { \
984 *((pc)++) = (char) 0xeb; \
985 *((pc)++) = (disp); }
987 # define emitm_jumpl(pc, disp) { \
988 *((pc)++) = (char) 0xe9; \
989 *(long *)(pc) = (disp); (pc) += 4; }
991 # define emitm_jumpr(pc, reg) { \
992 *((pc)++) = (char) 0xff; \
993 *((pc)++) = (char)(0xe0 | ((reg) - 1)); }
995 # define emitm_jumpm(pc, b, i, s, d) { \
996 *((pc)++) = (char) 0xff; \
997 (pc) = emit_r_X((interp), (pc), emit_reg(emit_b100), (b), (i), (s), (d)); }
999 /* Conditional jumps */
1001 /* Short jump - 8 bit disp */
1002 # define emitm_jxs(pc, code, disp) { \
1003 *((pc)++) = (char)(0x70 | (code)); \
1004 *((pc)++) = (char)(disp); }
1006 /* Long jump - 32 bit disp */
1007 # define emitm_jxl(pc, code, disp) { \
1008 *((pc)++) = (char) 0x0f; \
1009 *((pc)++) = (char)(0x80 | (code)); \
1010 *(long *)(pc) = (disp); (pc) += 4; }
1012 # define emitm_jo 0
1013 # define emitm_jno 1
1014 # define emitm_jb 2
1015 # define emitm_jnb 3
1016 # define emitm_jz 4
1017 # define emitm_je emitm_jz
1018 # define emitm_jnz 5
1019 # define emitm_jne emitm_jnz
1020 # define emitm_jbe 6
1021 # define emitm_ja 7
1022 # define emitm_js 8
1023 # define emitm_jns 9
1024 # define emitm_jp 10
1025 # define emitm_jnp 11
1026 # define emitm_jl 12
1027 # define emitm_jnl 13
1028 # define emitm_jle 14
1029 # define emitm_jg 15
1031 /* set byte conditional */
1032 # define jit_emit_setcc_r(pc, cc, r) \
1033 *(pc)++ = 0x0f; \
1034 *(pc)++ = 0x90 + (cc); \
1035 *(pc)++ = (char) emit_alu_X_r(0, (r))
1038 * core.jit interface
1040 * The new offset based versions have uppercase RM or MR inside
1041 * That's probably only during transition time
1044 # define jit_emit_mov_mi_i(pc, dest, immediate) \
1045 emitm_movl_i_m((pc), (immediate), emit_None, emit_None, emit_None, (dest))
1047 # define jit_emit_mov_MI_i(interp, pc, offs, immediate) \
1048 emitm_movl_i_m((pc), (immediate), emit_EBX, emit_None, 1, (offs))
1050 # define jit_emit_mov_rm_i(interp, pc, reg, address) \
1051 emitm_movl_m_r((interp), (pc), (reg), emit_None, emit_None, emit_None, (address))
1053 # define jit_emit_mov_RM_i(interp, pc, reg, offs) \
1054 emitm_movl_m_r((interp), (pc), (reg), emit_EBX, emit_None, 1, (offs))
1056 # define jit_emit_mov_mr_i(interp, pc, address, reg) \
1057 emitm_movl_r_m((interp), (pc), (reg), emit_None, emit_None, emit_None, (address))
1059 # define jit_emit_mov_MR_i(interp, pc, offs, reg) \
1060 emitm_movl_r_m((interp), (pc), (reg), emit_EBX, emit_None, 1, (offs))
1062 # define jit_emit_mul_RM_i(interp, pc, reg, offs) \
1063 emitm_smull_r_m((pc), (reg), emit_EBX, emit_None, 1, (offs))
1065 # define jit_emit_sub_RM_i(interp, pc, reg, offs) \
1066 emitm_subl_m_r((pc), (reg), emit_EBX, emit_None, 1, (offs))
1068 # define jit_emit_sub_MR_i(interp, pc, offs, reg) \
1069 emitm_subl_r_m((pc), (reg), emit_EBX, emit_None, 1, (offs))
1071 # define jit_emit_sub_MI_i(pc, offs, imm) \
1072 emitm_subl_i_m((pc), (imm), emit_EBX, emit_None, 1, (offs))
1074 # define jit_emit_add_RM_i(interp, pc, reg, offs) \
1075 emitm_addl_m_r((pc), (reg), emit_EBX, emit_None, 1, (offs))
1077 # define jit_emit_add_MR_i(interp, pc, offs, reg) \
1078 emitm_addl_r_m((pc), (reg), emit_EBX, emit_None, 1, (offs))
1080 # define jit_emit_add_MI_i(pc, offs, imm) \
1081 emitm_addl_i_m((pc), (imm), emit_EBX, emit_None, 1, (offs))
1083 # define jit_emit_cmp_rm_i(pc, reg, address) \
1084 emitm_cmpl_r_m((pc), (reg), emit_None, emit_None, emit_None, (address))
1086 # define jit_emit_cmp_RM_i(interp, pc, reg, offs) \
1087 emitm_cmpl_r_m((pc), (reg), emit_EBX, emit_None, 1, (offs))
1089 # define jit_emit_cmp_MR_i(interp, pc, offs, reg) \
1090 emitm_cmpl_m_r((pc), (reg), emit_EBX, emit_None, 1, (offs))
1092 /* high level routines, behave like real 2 register FP */
1094 /* mapped float registers numbers are ST(1)-ST(4).
1095 * scratch register is ST(0)
1098 /* ST(i) <- numvar */
1099 # define jit_emit_mov_RM_n(interp, pc, r, d) { \
1100 jit_emit_fload_mb_n((interp), (pc), emit_EBX, (d)); \
1101 emitm_fstp((pc), ((r)+1)); \
1104 /* ST(i) <= NUM_CONST */
1105 # define jit_emit_mov_ri_n(interp, pc, r, i) { \
1106 jit_emit_fload_m_n((interp), (pc), (i)); \
1107 emitm_fstp((pc), ((r)+1)); \
1110 /* ST(i) <= &INT_CONST */
1111 # define jit_emit_mov_ri_ni(interp, pc, r, i) { \
1112 jit_emit_fload_m_i((interp), (pc), (i)); \
1113 emitm_fstp((pc), ((r)+1)); \
1116 /* ST(i) <= INT_REG */
1117 # define jit_emit_mov_RM_ni(interp, pc, r, i) { \
1118 jit_emit_fload_mb_i((interp), (pc), (i)); \
1119 emitm_fstp((pc), ((r)+1)); \
1122 /* NUM_REG(i) <= &INT_CONST
1123 * the int const i is loaded from the code memory
1125 # define jit_emit_mov_MI_ni(interp, pc, offs, i) { \
1126 jit_emit_fload_m_i((interp), (pc), (i)); \
1127 jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (offs)); \
1130 /* INT_REG <= ST(i) */
1131 # define jit_emit_mov_mr_in(pc, mem, r) { \
1132 emitm_fld((pc), (r)); \
1133 jit_emit_fstore_m_i((pc), (mem)); \
1136 /* numvar <- ST(i) */
1137 # define jit_emit_mov_mr_n(pc, d, r) { \
1138 emitm_fld((pc), (r)); \
1139 jit_emit_fstore_m_n((pc), (d)); \
1142 # define jit_emit_mov_MR_n(interp, pc, d, r) { \
1143 if (r) { \
1144 emitm_fld((pc), (r)); \
1145 jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (d)); \
1147 else { \
1148 jit_emit_fst_mb_n((interp), (pc), emit_EBX, (d)); \
1152 /* ST(r1) <= ST(r2) */
1153 # define jit_emit_mov_rr_n(pc, r1, r2) { \
1154 if ((r1) != (r2)) { \
1155 if (r2) { \
1156 emitm_fld((pc), (r2)); \
1157 emitm_fstp((pc), ((r1)+1)); \
1159 else { \
1160 emitm_fst((pc), (r1)); \
1165 /* ST(r1) xchg ST(r2) */
1166 # define jit_emit_xchg_rr_n(interp, pc, r1, r2) { \
1167 if ((r1) != (r2)) { \
1168 emitm_fld((pc), (r1)); \
1169 emitm_fld((pc), ((r2)+1)); \
1170 emitm_fstp((pc), ((r1)+2)); \
1171 emitm_fstp((pc), ((r2)+1)); \
1175 # define jit_emit_xchg_RM_n(interp, pc, r, offs) { \
1176 emitm_fld((pc), (r)); \
1177 jit_emit_fload_mb_n((interp), (pc), emit_EBX, (offs)); \
1178 emitm_fstp((pc), ((r)+2)); \
1179 jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (offs)); \
1182 # define jit_emit_xchg_MR_n(interp, pc, offs, r) { \
1183 emitm_fld((pc), (r)); \
1184 jit_emit_fload_mb_n((interp), (pc), emit_EBX, (offs)); \
1185 emitm_fstp((pc), ((r)+2)); \
1186 jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (offs)); \
1189 # define jit_emit_finit(pc) { *((pc)++) = (char) 0xdb; *((pc)++) = (char) 0xe3; }
1191 /* ST(i) op= MEM */
1193 # define jit_emit_xxx_rm_n(interp, op, pc, r, m) { \
1194 jit_emit_fload_m_n((interp), (pc), (m)); \
1195 emitm_f ## op ## p((pc), ((r)+1)); \
1198 # define jit_emit_xxx_RM_n(interp, op, pc, r, offs) { \
1199 jit_emit_fload_mb_n((interp), (pc), emit_EBX, (offs)); \
1200 emitm_f ## op ## p((pc), ((r)+1)); \
1204 * float ops in two flavors: abs memory for constants, offsets for regs
1207 # define jit_emit_add_ri_n(interp, pc, r, m) jit_emit_xxx_rm_n((interp), add, (pc), (r), (m))
1208 # define jit_emit_sub_ri_n(interp, pc, r, m) jit_emit_xxx_rm_n((interp), sub, (pc), (r), (m))
1209 # define jit_emit_mul_ri_n(interp, pc, r, m) jit_emit_xxx_rm_n((interp), mul, (pc), (r), (m))
1211 # define jit_emit_add_RM_n(interp, pc, r, o) jit_emit_xxx_RM_n((interp), add, (pc), (r), (o))
1212 # define jit_emit_sub_RM_n(interp, pc, r, o) jit_emit_xxx_RM_n((interp), sub, (pc), (r), (o))
1213 # define jit_emit_mul_RM_n(interp, pc, r, o) jit_emit_xxx_RM_n((interp), mul, (pc), (r), (o))
1215 /* ST(r1) += ST(r2) */
1216 /* r1 == 0: ST(0) <- ST(0) + ST(i)
1217 * r2 == 0: ST(i) <- ST(0) + ST(i)
1219 # define jit_emit_add_rr_n(interp, pc, r1, r2) do { \
1220 if (!(r1)) { \
1221 emitm_fadd((pc), (r2)); \
1223 else if (!(r2)) { \
1224 emitm_faddr((pc), (r1)); \
1226 else { \
1227 emitm_fld((pc), (r2)); \
1228 emitm_faddp((pc), ((r1)+1)); \
1231 while (0)
1233 * ST(r) += INT_REG
1235 # define jit_emit_add_RM_ni(pc, r, offs) { \
1236 emitm_fld((pc), (r)); \
1237 emitm_fiadd_m((pc), emit_EBX, 0, 1, (offs)); \
1238 emitm_fstp((pc), ((r)+1)); \
1241 /* ST(r1) -= ST(r2) */
1242 /* r1 == 0: ST(0) <- ST(0) - ST(i)
1243 * r2 == 0: ST(i) <- ST(i) - ST(0)
1245 # define jit_emit_sub_rr_n(interp, pc, r1, r2) do { \
1246 if (!(r1)) { \
1247 emitm_fsub((pc), (r2)); \
1249 else if (!(r2)) { \
1250 emitm_fsubr((pc), (r1)); \
1252 else { \
1253 emitm_fld((pc), (r2)); \
1254 emitm_fsubp((pc), ((r1)+1)); \
1257 while (0)
1260 * ST(r) -= INT_REG
1262 # define jit_emit_sub_RM_ni(pc, r, offs) { \
1263 emitm_fld((pc), (r)); \
1264 emitm_fisub_m((pc), emit_EBX, 0, 1, (offs)); \
1265 emitm_fstp((pc), ((r)+1)); \
1268 # define jit_emit_inc_r_n(pc, r) { \
1269 emitm_fld1(pc); \
1270 emitm_faddp((pc), ((r)+1)); \
1273 # define jit_emit_dec_r_n(pc, r) { \
1274 emitm_fld1(pc); \
1275 emitm_fsubp((pc), ((r)+1)); \
1278 /* ST(r1) *= ST(r2) */
1279 /* r1 == 0: ST(0) <- ST(0) * ST(i)
1280 * r2 == 0: ST(i) <- ST(0) * ST(i)
1282 # define jit_emit_mul_rr_n(interp, pc, r1, r2) do { \
1283 if (!(r1)) { \
1284 emitm_fmul((pc), (r2)); \
1286 else if (!(r2)) { \
1287 emitm_fmulr((pc), (r1)); \
1289 else { \
1290 emitm_fld((pc), (r2)); \
1291 emitm_fmulp((pc), ((r1)+1)); \
1294 while (0)
1297 * ST(r) *= INT_REG
1299 # define jit_emit_mul_RM_ni(pc, r, offs) { \
1300 emitm_fld((pc), (r)); \
1301 emitm_fimul_m((pc), emit_EBX, 0, 1, (offs)); \
1302 emitm_fstp((pc), ((r)+1)); \
1306 * ST(r) /= INT_REG
1308 # define jit_emit_div_RM_ni(pc, r, offs) { \
1309 emitm_fld((pc), (r)); \
1310 emitm_fidiv_m((pc), emit_EBX, 0, 1, (offs)); \
1311 emitm_fstp((pc), ((r)+1)); \
1314 /* test r for zero */
1315 # define jit_emit_test_r_n(pc, r) { \
1316 if (r) { \
1317 emitm_fxch((pc), (r)); \
1319 emitm_fxam(pc); \
1320 emitm_fstw(pc); \
1321 emitm_sahf(pc); \
1322 if (r) { \
1323 emitm_fxch((pc), (r)); \
1327 enum { JIT_X86BRANCH, JIT_X86JUMP, JIT_X86CALL };
1329 # define jit_emit_stack_frame_enter(pc) do { \
1330 emitm_pushl_r((pc), emit_EBP); \
1331 jit_emit_mov_rr_i((pc), emit_EBP, emit_ESP); \
1332 } while (0)
1334 # define jit_emit_stack_frame_leave(pc) do { \
1335 jit_emit_mov_rr_i((pc), emit_ESP, emit_EBP); \
1336 emitm_popl_r((pc), emit_EBP); \
1337 } while (0)
1339 # define jit_emit_end(pc) { \
1340 jit_emit_add_ri_i((interp), (pc), emit_ESP, 4); \
1341 emitm_popl_r((pc), emit_EDI); \
1342 emitm_popl_r((pc), emit_ESI); \
1343 emitm_popl_r((pc), emit_EBX); \
1344 emitm_popl_r((pc), emit_EBP); \
1345 emitm_ret(pc); \
1348 size_t calc_signature_needs(const char *sig, int *strings);
1350 void * Parrot_jit_build_call_func(PARROT_INTERP, PMC *pmc_nci,
1351 STRING *signature, int *sizeptr);
1354 * register usage
1355 * %edi, %esi ... mapped, preserved
1356 * %edx, %ecx ... mapped, not preserved
1357 * %ebx ... base pointer for register access, preserved
1358 * %eax ... scratch, return value register
1361 #endif /* PARROT_I386_JIT_EMIT_H_GUARD */
1364 * Local variables:
1365 * c-file-style: "parrot"
1366 * End:
1367 * vim: expandtab shiftwidth=4: