1 /* jit/i386/codegen.h - code generation macros and definitions for i386
3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4 R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5 M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6 P. Tomsich, J. Wenninger
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Andreas Krall
30 $Id: codegen.h 766 2003-12-13 22:52:32Z twisti $
42 /* define x86 register numbers */
53 /* preallocated registers *****************************************************/
55 /* integer registers */
57 #define REG_RESULT EAX /* to deliver method results */
58 #define REG_RESULT2 EDX /* to deliver long method results */
60 #define REG_ITMP1 EAX /* temporary register */
61 #define REG_ITMP2 ECX /* temporary register */
62 #define REG_ITMP3 EDX /* temporary register */
64 #define REG_NULL -1 /* used for reg_of_var where d is not needed */
66 #define REG_ITMP1_XPTR EAX /* exception pointer = temporary register 1 */
67 #define REG_ITMP2_XPC ECX /* exception pc = temporary register 2 */
69 #define REG_SP ESP /* stack pointer */
71 /* floating point registers */
73 #define REG_FRESULT 0 /* to deliver floating point method results */
74 #define REG_FTMP1 6 /* temporary floating point register */
75 #define REG_FTMP2 7 /* temporary floating point register */
76 #define REG_FTMP3 7 /* temporary floating point register */
79 static u1 fpu_in_24bit_mode = 0;
81 static u2 fpu_ctrlwrd_24bit = 0x007f; /* Round to nearest, 24-bit mode, exceptions masked */
82 static u2 fpu_ctrlwrd_53bit = 0x027f; /* Round to nearest, 53-bit mode, exceptions masked */
84 static u4 subnormal_bias1[3] = { 0x00000000, 0x80000000, 0x03ff }; /* 2^(-15360) */
85 static u4 subnormal_bias2[3] = { 0x00000000, 0x80000000, 0x7bff }; /* 2^(+15360) */
88 /* macros to create code ******************************************************/
103 /* opcodes for alu instructions */
131 I386_CC_B = 2, I386_CC_C = 2, I386_CC_NAE = 2,
132 I386_CC_BE = 6, I386_CC_NA = 6,
133 I386_CC_AE = 3, I386_CC_NB = 3, I386_CC_NC = 3,
134 I386_CC_E = 4, I386_CC_Z = 4,
135 I386_CC_NE = 5, I386_CC_NZ = 5,
136 I386_CC_A = 7, I386_CC_NBE = 7,
137 I386_CC_S = 8, I386_CC_LZ = 8,
138 I386_CC_NS = 9, I386_CC_GEZ = 9,
139 I386_CC_P = 0x0a, I386_CC_PE = 0x0a,
140 I386_CC_NP = 0x0b, I386_CC_PO = 0x0b,
141 I386_CC_L = 0x0c, I386_CC_NGE = 0x0c,
142 I386_CC_GE = 0x0d, I386_CC_NL = 0x0d,
143 I386_CC_LE = 0x0e, I386_CC_NG = 0x0e,
144 I386_CC_G = 0x0f, I386_CC_NLE = 0x0f,
149 /* modrm and stuff */
151 #define i386_address_byte(mod, reg, rm) \
152 *(mcodeptr++) = ((((mod) & 0x03) << 6) | (((reg) & 0x07) << 3) | (((rm) & 0x07)));
155 #define i386_emit_reg(reg,rm) \
156 i386_address_byte(3,(reg),(rm));
159 #define i386_is_imm8(imm) \
160 (((int)(imm) >= -128 && (int)(imm) <= 127))
163 #define i386_emit_imm8(imm) \
164 *(mcodeptr++) = (u1) ((imm) & 0xff);
167 #define i386_emit_imm16(imm) \
170 imb.i = (int) (imm); \
171 *(mcodeptr++) = imb.b[0]; \
172 *(mcodeptr++) = imb.b[1]; \
176 #define i386_emit_imm32(imm) \
179 imb.i = (int) (imm); \
180 *(mcodeptr++) = imb.b[0]; \
181 *(mcodeptr++) = imb.b[1]; \
182 *(mcodeptr++) = imb.b[2]; \
183 *(mcodeptr++) = imb.b[3]; \
187 #define i386_emit_mem(r,disp) \
189 i386_address_byte(0,(r),5); \
190 i386_emit_imm32((disp)); \
194 #define i386_emit_membase(basereg,disp,dreg) \
196 if ((basereg) == ESP) { \
198 i386_address_byte(0, (dreg), ESP); \
199 i386_address_byte(0, ESP, ESP); \
200 } else if (i386_is_imm8((disp))) { \
201 i386_address_byte(1, (dreg), ESP); \
202 i386_address_byte(0, ESP, ESP); \
203 i386_emit_imm8((disp)); \
205 i386_address_byte(2, (dreg), ESP); \
206 i386_address_byte(0, ESP, ESP); \
207 i386_emit_imm32((disp)); \
212 if ((disp) == 0 && (basereg) != EBP) { \
213 i386_address_byte(0, (dreg), (basereg)); \
217 if (i386_is_imm8((disp))) { \
218 i386_address_byte(1, (dreg), (basereg)); \
219 i386_emit_imm8((disp)); \
221 i386_address_byte(2, (dreg), (basereg)); \
222 i386_emit_imm32((disp)); \
227 #define i386_emit_memindex(reg,disp,basereg,indexreg,scale) \
229 if ((basereg) == -1) { \
230 i386_address_byte(0, (reg), 4); \
231 i386_address_byte((scale), (indexreg), 5); \
232 i386_emit_imm32((disp)); \
234 } else if ((disp) == 0 && (basereg) != EBP) { \
235 i386_address_byte(0, (reg), 4); \
236 i386_address_byte((scale), (indexreg), (basereg)); \
238 } else if (i386_is_imm8((disp))) { \
239 i386_address_byte(1, (reg), 4); \
240 i386_address_byte((scale), (indexreg), (basereg)); \
241 i386_emit_imm8 ((disp)); \
244 i386_address_byte(2, (reg), 4); \
245 i386_address_byte((scale), (indexreg), (basereg)); \
246 i386_emit_imm32((disp)); \
251 /* code generation prototypes */
253 void i386_emit_ialu(s4 alu_op, stackptr src, instruction *iptr);
254 void i386_emit_ialuconst(s4 alu_op, stackptr src, instruction *iptr);
255 void i386_emit_lalu(s4 alu_op, stackptr src, instruction *iptr);
256 void i386_emit_laluconst(s4 alu_op, stackptr src, instruction *iptr);
257 void i386_emit_ishift(s4 shift_op, stackptr src, instruction *iptr);
258 void i386_emit_ishiftconst(s4 shift_op, stackptr src, instruction *iptr);
259 void i386_emit_ifcc_iconst(s4 if_op, stackptr src, instruction *iptr);
262 /* integer instructions */
264 void i386_mov_reg_reg(s4 reg, s4 dreg);
265 void i386_mov_imm_reg(s4 imm, s4 dreg);
266 void i386_movb_imm_reg(s4 imm, s4 dreg);
267 void i386_mov_membase_reg(s4 basereg, s4 disp, s4 reg);
268 void i386_mov_membase32_reg(s4 basereg, s4 disp, s4 reg);
269 void i386_mov_reg_membase(s4 reg, s4 basereg, s4 disp);
270 void i386_mov_memindex_reg(s4 disp, s4 basereg, s4 indexreg, s4 scale, s4 reg);
271 void i386_mov_reg_memindex(s4 reg, s4 disp, s4 basereg, s4 indexreg, s4 scale);
272 void i386_movw_reg_memindex(s4 reg, s4 disp, s4 basereg, s4 indexreg, s4 scale);
273 void i386_movb_reg_memindex(s4 reg, s4 disp, s4 basereg, s4 indexreg, s4 scale);
274 void i386_mov_imm_membase(s4 imm, s4 basereg, s4 disp);
275 void i386_movsbl_memindex_reg(s4 disp, s4 basereg, s4 indexreg, s4 scale, s4 reg);
276 void i386_movswl_memindex_reg(s4 disp, s4 basereg, s4 indexreg, s4 scale, s4 reg);
277 void i386_movzwl_memindex_reg(s4 disp, s4 basereg, s4 indexreg, s4 scale, s4 reg);
278 void i386_alu_reg_reg(s4 opc, s4 reg, s4 dreg);
279 void i386_alu_reg_membase(s4 opc, s4 reg, s4 basereg, s4 disp);
280 void i386_alu_membase_reg(s4 opc, s4 basereg, s4 disp, s4 reg);
281 void i386_alu_imm_reg(s4 opc, s4 imm, s4 reg);
282 void i386_alu_imm_membase(s4 opc, s4 imm, s4 basereg, s4 disp);
283 void i386_test_reg_reg(s4 reg, s4 dreg);
284 void i386_test_imm_reg(s4 imm, s4 dreg);
285 void i386_inc_reg(s4 reg);
286 void i386_inc_membase(s4 basereg, s4 disp);
287 void i386_dec_reg(s4 reg);
288 void i386_dec_membase(s4 basereg, s4 disp);
290 void i386_imul_reg_reg(s4 reg, s4 dreg);
291 void i386_imul_membase_reg(s4 basereg, s4 disp, s4 dreg);
292 void i386_imul_imm_reg(s4 imm, s4 reg);
293 void i386_imul_imm_reg_reg(s4 imm, s4 reg, s4 dreg);
294 void i386_imul_imm_membase_reg(s4 imm, s4 basereg, s4 disp, s4 dreg);
295 void i386_mul_membase(s4 basereg, s4 disp);
296 void i386_idiv_reg(s4 reg);
298 void i386_shift_reg(s4 opc, s4 reg);
299 void i386_shift_membase(s4 opc, s4 basereg, s4 disp);
300 void i386_shift_imm_reg(s4 opc, s4 imm, s4 reg);
301 void i386_shift_imm_membase(s4 opc, s4 imm, s4 basereg, s4 disp);
302 void i386_shld_reg_reg(s4 reg, s4 dreg);
303 void i386_shld_imm_reg_reg(s4 imm, s4 reg, s4 dreg);
304 void i386_shld_reg_membase(s4 reg, s4 basereg, s4 disp);
305 void i386_shrd_reg_reg(s4 reg, s4 dreg);
306 void i386_shrd_imm_reg_reg(s4 imm, s4 reg, s4 dreg);
307 void i386_shrd_reg_membase(s4 reg, s4 basereg, s4 disp);
308 void i386_jmp_imm(s4 imm);
309 void i386_jmp_reg(s4 reg);
310 void i386_jcc(s4 opc, s4 imm);
311 void i386_setcc_reg(s4 opc, s4 reg);
312 void i386_setcc_membase(s4 opc, s4 basereg, s4 disp);
313 void i386_neg_reg(s4 reg);
314 void i386_neg_membase(s4 basereg, s4 disp);
315 void i386_push_imm(s4 imm);
316 void i386_pop_reg(s4 reg);
318 void i386_call_reg(s4 reg);
319 void i386_call_imm(s4 imm);
322 /* floating point instructions */
326 void i386_fld_reg(s4 reg);
327 void i386_flds_membase(s4 basereg, s4 disp);
328 void i386_fldl_membase(s4 basereg, s4 disp);
329 void i386_fldt_membase(s4 basereg, s4 disp);
330 void i386_flds_memindex(s4 disp, s4 basereg, s4 indexreg, s4 scale);
331 void i386_fldl_memindex(s4 disp, s4 basereg, s4 indexreg, s4 scale);
332 void i386_fildl_membase(s4 basereg, s4 disp);
333 void i386_fildll_membase(s4 basereg, s4 disp);
334 void i386_fst_reg(s4 reg);
335 void i386_fsts_membase(s4 basereg, s4 disp);
336 void i386_fstl_membase(s4 basereg, s4 disp);
337 void i386_fsts_memindex(s4 disp, s4 basereg, s4 indexreg, s4 scale);
338 void i386_fstl_memindex(s4 disp, s4 basereg, s4 indexreg, s4 scale);
339 void i386_fstp_reg(s4 reg);
340 void i386_fstps_membase(s4 basereg, s4 disp);
341 void i386_fstpl_membase(s4 basereg, s4 disp);
342 void i386_fstpt_membase(s4 basereg, s4 disp);
343 void i386_fstps_memindex(s4 disp, s4 basereg, s4 indexreg, s4 scale);
344 void i386_fstpl_memindex(s4 disp, s4 basereg, s4 indexreg, s4 scale);
345 void i386_fistl_membase(s4 basereg, s4 disp);
346 void i386_fistpl_membase(s4 basereg, s4 disp);
347 void i386_fistpll_membase(s4 basereg, s4 disp);
350 void i386_fadd_reg_st(s4 reg);
351 void i386_fadd_st_reg(s4 reg);
352 void i386_faddp_st_reg(s4 reg);
353 void i386_fadds_membase(s4 basereg, s4 disp);
354 void i386_faddl_membase(s4 basereg, s4 disp);
355 void i386_fsub_reg_st(s4 reg);
356 void i386_fsub_st_reg(s4 reg);
357 void i386_fsubp_st_reg(s4 reg);
359 void i386_fsubs_membase(s4 basereg, s4 disp);
360 void i386_fsubl_membase(s4 basereg, s4 disp);
361 void i386_fmul_reg_st(s4 reg);
362 void i386_fmul_st_reg(s4 reg);
364 void i386_fmulp_st_reg(s4 reg);
365 void i386_fmuls_membase(s4 basereg, s4 disp);
366 void i386_fmull_membase(s4 basereg, s4 disp);
367 void i386_fdiv_reg_st(s4 reg);
368 void i386_fdiv_st_reg(s4 reg);
370 void i386_fdivp_st_reg(s4 reg);
372 void i386_fxch_reg(s4 reg);
376 void i386_fucom_reg(s4 reg);
377 void i386_fucomp_reg(s4 reg);
382 void i386_fldcw_mem(s4 mem);
383 void i386_fldcw_membase(s4 basereg, s4 disp);
385 void i386_ffree_reg(s4 reg);
390 /* function gen_resolvebranch **************************************************
392 backpatches a branch instruction
394 parameters: ip ... pointer to instruction after branch (void*)
395 so ... offset of instruction after branch (s4)
396 to ... offset of branch target (s4)
398 *******************************************************************************/
400 #define gen_resolvebranch(ip,so,to) \
401 *((void **) ((ip) - 4)) = (void **) ((to) - (so));
404 /* function prototypes */
407 void init_exceptions();
409 void codegen_close();
410 void dseg_display(s4 *s4ptr);
412 #endif /* _CODEGEN_H */
416 * These are local overrides for various environment variables in Emacs.
417 * Please do not remove this and leave it at the end of the file, where
418 * Emacs will automagically detect them.
419 * ---------------------------------------------------------------------
422 * indent-tabs-mode: t