- most important: exchanged REG_ITMP2 and REG_ITMP3, because we try to use
[cacao.git] / src / vm / jit / i386 / codegen.h
1 /* jit/i386/codegen.h - code generation macros and definitions for i386
2
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
7
8    This file is part of CACAO.
9
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.
14
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.
19
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
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Andreas Krall
28             Christian Thalinger
29
30    $Id: codegen.h 766 2003-12-13 22:52:32Z twisti $
31
32 */
33
34
35 #ifndef _CODEGEN_H
36 #define _CODEGEN_H
37
38 #include "global.h"
39 #include "jit.h"
40
41
42 /* define x86 register numbers */
43 #define EAX    0
44 #define ECX    1
45 #define EDX    2
46 #define EBX    3
47 #define ESP    4
48 #define EBP    5
49 #define ESI    6
50 #define EDI    7
51
52
53 /* preallocated registers *****************************************************/
54
55 /* integer registers */
56   
57 #define REG_RESULT      EAX      /* to deliver method results                 */
58 #define REG_RESULT2     EDX      /* to deliver long method results            */
59
60 #define REG_ITMP1       EAX      /* temporary register                        */
61 #define REG_ITMP2       ECX      /* temporary register                        */
62 #define REG_ITMP3       EDX      /* temporary register                        */
63
64 #define REG_NULL        -1       /* used for reg_of_var where d is not needed */
65
66 #define REG_ITMP1_XPTR  EAX      /* exception pointer = temporary register 1  */
67 #define REG_ITMP2_XPC   ECX      /* exception pc = temporary register 2       */
68
69 #define REG_SP          ESP      /* stack pointer                             */
70
71 /* floating point registers */
72
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             */
77
78
79 static u1 fpu_in_24bit_mode = 0;
80
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 */
83
84 static u4 subnormal_bias1[3] = { 0x00000000, 0x80000000, 0x03ff };    /* 2^(-15360) */
85 static u4 subnormal_bias2[3] = { 0x00000000, 0x80000000, 0x7bff };    /* 2^(+15360) */
86
87
88 /* macros to create code ******************************************************/
89
90 typedef enum {
91     I386_AL = 0,
92     I386_CL = 1,
93     I386_DL = 2,
94     I386_BL = 3,
95     I386_AH = 4,
96     I386_CH = 5,
97     I386_DH = 6,
98     I386_BH = 7,
99     I386_NREGB
100 } I386_RegB_No;
101
102
103 /* opcodes for alu instructions */
104
105 typedef enum {
106     I386_ADD = 0,
107     I386_OR  = 1,
108     I386_ADC = 2,
109     I386_SBB = 3,
110     I386_AND = 4,
111     I386_SUB = 5,
112     I386_XOR = 6,
113     I386_CMP = 7,
114     I386_NALU
115 } I386_ALU_Opcode;
116
117 typedef enum {
118     I386_ROL = 0,
119     I386_ROR = 1,
120     I386_RCL = 2,
121     I386_RCR = 3,
122     I386_SHL = 4,
123     I386_SHR = 5,
124     I386_SAR = 7,
125     I386_NSHIFT = 8
126 } I386_Shift_Opcode;
127
128 typedef enum {
129     I386_CC_O = 0,
130     I386_CC_NO = 1,
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,
145     I386_NCC
146 } I386_CC;
147
148
149 /* modrm and stuff */
150
151 #define i386_address_byte(mod, reg, rm) \
152     *(mcodeptr++) = ((((mod) & 0x03) << 6) | (((reg) & 0x07) << 3) | (((rm) & 0x07)));
153
154
155 #define i386_emit_reg(reg,rm) \
156     i386_address_byte(3,(reg),(rm));
157
158
159 #define i386_is_imm8(imm) \
160     (((int)(imm) >= -128 && (int)(imm) <= 127))
161
162
163 #define i386_emit_imm8(imm) \
164     *(mcodeptr++) = (u1) ((imm) & 0xff);
165
166
167 #define i386_emit_imm16(imm) \
168     do { \
169         imm_union imb; \
170         imb.i = (int) (imm); \
171         *(mcodeptr++) = imb.b[0]; \
172         *(mcodeptr++) = imb.b[1]; \
173     } while (0)
174
175
176 #define i386_emit_imm32(imm) \
177     do { \
178         imm_union imb; \
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]; \
184     } while (0)
185
186
187 #define i386_emit_mem(r,disp) \
188     do { \
189         i386_address_byte(0,(r),5); \
190         i386_emit_imm32((disp)); \
191     } while (0)
192
193
194 #define i386_emit_membase(basereg,disp,dreg) \
195     do { \
196         if ((basereg) == ESP) { \
197             if ((disp) == 0) { \
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)); \
204             } else { \
205                 i386_address_byte(2, (dreg), ESP); \
206                 i386_address_byte(0, ESP, ESP); \
207                 i386_emit_imm32((disp)); \
208             } \
209             break; \
210         } \
211         \
212         if ((disp) == 0 && (basereg) != EBP) { \
213             i386_address_byte(0, (dreg), (basereg)); \
214             break; \
215         } \
216         \
217         if (i386_is_imm8((disp))) { \
218             i386_address_byte(1, (dreg), (basereg)); \
219             i386_emit_imm8((disp)); \
220         } else { \
221             i386_address_byte(2, (dreg), (basereg)); \
222             i386_emit_imm32((disp)); \
223         } \
224     } while (0)
225
226
227 #define i386_emit_memindex(reg,disp,basereg,indexreg,scale) \
228     do { \
229         if ((basereg) == -1) { \
230             i386_address_byte(0, (reg), 4); \
231             i386_address_byte((scale), (indexreg), 5); \
232             i386_emit_imm32((disp)); \
233         \
234         } else if ((disp) == 0 && (basereg) != EBP) { \
235             i386_address_byte(0, (reg), 4); \
236             i386_address_byte((scale), (indexreg), (basereg)); \
237         \
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)); \
242         \
243         } else { \
244             i386_address_byte(2, (reg), 4); \
245             i386_address_byte((scale), (indexreg), (basereg)); \
246             i386_emit_imm32((disp)); \
247         }    \
248      } while (0)
249
250
251 /* code generation prototypes */
252
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);
260
261
262 /* integer instructions */
263
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);
289 void i386_cltd();
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);
297 void i386_ret();
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);
317 void i386_nop();
318 void i386_call_reg(s4 reg);
319 void i386_call_imm(s4 imm);
320
321
322 /* floating point instructions */
323
324 void i386_fld1();
325 void i386_fldz();
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);
348 void i386_fchs();
349 void i386_faddp();
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);
358 void i386_fsubp();
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);
363 void i386_fmulp();
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);
369 void i386_fdivp();
370 void i386_fdivp_st_reg(s4 reg);
371 void i386_fxch();
372 void i386_fxch_reg(s4 reg);
373 void i386_fprem();
374 void i386_fprem1();
375 void i386_fucom();
376 void i386_fucom_reg(s4 reg);
377 void i386_fucomp_reg(s4 reg);
378 void i386_fucompp();
379 void i386_fnstsw();
380 void i386_sahf();
381 void i386_finit();
382 void i386_fldcw_mem(s4 mem);
383 void i386_fldcw_membase(s4 basereg, s4 disp);
384 void i386_wait();
385 void i386_ffree_reg(s4 reg);
386 void i386_fdecstp();
387 void i386_fincstp();
388
389
390 /* function gen_resolvebranch **************************************************
391
392     backpatches a branch instruction
393
394     parameters: ip ... pointer to instruction after branch (void*)
395                 so ... offset of instruction after branch  (s4)
396                 to ... offset of branch target             (s4)
397
398 *******************************************************************************/
399
400 #define gen_resolvebranch(ip,so,to) \
401     *((void **) ((ip) - 4)) = (void **) ((to) - (so));
402
403
404 /* function prototypes */
405
406 void codegen_init();
407 void init_exceptions();
408 void codegen();
409 void codegen_close();
410 void dseg_display(s4 *s4ptr);
411
412 #endif /* _CODEGEN_H */
413
414
415 /*
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  * ---------------------------------------------------------------------
420  * Local variables:
421  * mode: c
422  * indent-tabs-mode: t
423  * c-basic-offset: 4
424  * tab-width: 4
425  * End:
426  */