/[dotgnu-pnet]/pnet/engine/md_amd64.h
ViewVC logotype

Contents of /pnet/engine/md_amd64.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (show annotations) (download)
Tue Oct 4 05:34:57 2005 UTC (18 years, 6 months ago) by t3rmin4t0r
Branch: MAIN
File MIME type: text/plain
AMD64 unroller - first cut

1 /*
2 * md_amd64.h - Machine-dependent definitions for x86_64 (AMD64/EM64T).
3 *
4 * Copyright (C) 2003,2005 Southern Storm Software, Pty Ltd.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #ifndef _ENGINE_MD_AMD64_H
22 #define _ENGINE_MD_AMD64_H
23
24 #include "amd64_codegen.h"
25
26 #ifdef __cplusplus
27 extern "C" {
28 #endif
29
30 /*
31 * Register numbers in the standard register allocation order.
32 * -1 is the list terminator.
33 */
34 #define MD_REG_0 AMD64_RAX
35 #define MD_REG_1 AMD64_RCX
36 #define MD_REG_2 AMD64_RBP
37 #define MD_REG_3 AMD64_RBX
38 #define MD_REG_4 AMD64_RDX
39 #define MD_REG_5 AMD64_RSI
40 #define MD_REG_6 AMD64_RDI
41 #define MD_REG_7 -1
42 #define MD_REG_8 -1
43 #define MD_REG_9 -1
44 #define MD_REG_10 -1
45 #define MD_REG_11 -1
46 #define MD_REG_12 -1
47 #define MD_REG_13 -1
48 #define MD_REG_14 -1
49 #define MD_REG_15 -1
50
51 /*
52 * Mask that indicates a floating-point register.
53 */
54 #define MD_FREG_MASK 0x0010
55
56 /*
57 * Floating point register numbers in the standard allocation order.
58 * -1 is the list terminator. The floating point register numbers
59 * must include the MD_FREG_MASK value.
60 */
61 //#define MD_FREG_0 (MD_FREG_MASK | 0)
62 #define MD_FREG_0 -1 /* TODO: implement FPU support */
63 #define MD_FREG_1 (MD_FREG_MASK | 1)
64 #define MD_FREG_2 (MD_FREG_MASK | 2)
65 #define MD_FREG_3 (MD_FREG_MASK | 3)
66 #define MD_FREG_4 (MD_FREG_MASK | 4)
67 #define MD_FREG_5 (MD_FREG_MASK | 5)
68 #define MD_FREG_6 (MD_FREG_MASK | 6)
69 #define MD_FREG_7 (MD_FREG_MASK | 7)
70 #define MD_FREG_8 -1
71 #define MD_FREG_9 -1
72 #define MD_FREG_10 -1
73 #define MD_FREG_11 -1
74 #define MD_FREG_12 -1
75 #define MD_FREG_13 -1
76 #define MD_FREG_14 -1
77 #define MD_FREG_15 -1
78
79 /*
80 * Set this to a non-zero value if floating-point registers are organised
81 * in a stack (e.g. the x87 FPU).
82 */
83 #define MD_FP_STACK_SIZE 0
84
85 /*
86 * The register that contains the CVM program counter. This may be
87 * present in the standard register allocation order. This can be
88 * set to -1 if MD_STATE_ALREADY_IN_REGS is 0.
89 */
90 #define MD_REG_PC AMD64_R12
91
92 /*
93 * The register that contains the CVM stacktop pointer. This must not
94 * be present in the standard register allocation order.
95 */
96 #define MD_REG_STACK AMD64_R14
97
98 /*
99 * The register that contains the CVM frame pointer. This must not
100 * be present in the standard register allocation order.
101 */
102 #define MD_REG_FRAME AMD64_R15
103
104 /*
105 * Set this to 1 if "pc", "stacktop", and "frame" are already in
106 * the above registers when unrolled code is entered. i.e. the
107 * CVM interpreter has manual assignments of registers to variables
108 * in the file "cvm.c". If the state is not already in registers,
109 * then set this value to zero.
110 */
111 #define MD_STATE_ALREADY_IN_REGS 1
112
113 /*
114 * Registers that must be saved on the system stack prior to their use
115 * in unrolled code for temporary stack values.
116 */
117 #define MD_REGS_TO_BE_SAVED (1 << AMD64_RBP)
118
119 /*
120 * Registers with special meanings (pc, stacktop, frame) that must
121 * be saved if MD_STATE_ALREADY_IN_REGS is 0.
122 */
123 #define MD_SPECIAL_REGS_TO_BE_SAVED 0
124
125 /*
126 * Floating-point register numbers that must be saved.
127 */
128 #define MD_FREGS_TO_BE_SAVED 0
129
130 /*
131 * Set this to 1 if the CPU has integer division operations.
132 * Set it to zero if integer division is too hard to be performed
133 * inline using a simple opcode.
134 */
135 #define MD_HAS_INT_DIVISION 0
136
137 /*
138 * Set to 1 if 64-bit register pairs are stored in little-endian order.
139 */
140 #define MD_LITTLE_ENDIAN_LONGS 0
141
142 /*
143 * Type of the instruction pointer for outputting code.
144 */
145 typedef unsigned char *md_inst_ptr;
146
147 /*
148 * Trap TODO code while executing
149 */
150
151 #define TODO_trap(inst) \
152 do { \
153 amd64_breakpoint_size((inst), 8); \
154 }while(0)
155
156 /*
157 * Push a word register onto the system stack.
158 */
159 #define md_push_reg(inst,reg) amd64_push_reg((inst), (reg))
160
161 /*
162 * Pop a word register from the system stack.
163 */
164 #define md_pop_reg(inst,reg) amd64_pop_reg((inst), (reg))
165
166 /*
167 * Discard the contents of a floating-point register.
168 */
169 #define md_discard_freg(inst,reg) do { ; } while (0)
170
171 /*
172 * Load a 32-bit integer constant into a register. This will sign-extend
173 * if the native word size is larger.
174 */
175 #define md_load_const_32(inst,reg,value) \
176 amd64_mov_reg_imm_size((inst), (reg), (value), 4)
177
178 /*
179 * Load a native integer constant into a register.
180 */
181 #define md_load_const_native(inst,reg,value) \
182 amd64_mov_reg_imm_size((inst), (reg), (value), 8)
183
184 /*
185 * Load a 32-bit floating-point constant into a register. The constant
186 * is at a particular memory location. If the system does not use
187 * floating-point registers, then load onto the top of the stack.
188 */
189 #define md_load_const_float_32(inst,reg,mem) \
190 x86_fld((inst), (int)(mem), 0)
191
192 /*
193 * Load a 64-bit floating-point constant into a register. The constant
194 * is at a particular memory location. If the system does not use
195 * floating-point registers, then load onto the top of the stack.
196 */
197 #define md_load_const_float_64(inst,reg,mem) \
198 x86_fld((inst), (int)(mem), 1)
199
200 /*
201 * Load the 32-bit constant zero into a register. This will zero-extend
202 * if the native word size is larger.
203 */
204 #define md_load_zero_32(inst,reg) \
205 amd64_clear_reg_size((inst), (reg), 4)
206
207 /*
208 * Load the native constant zero into a register.
209 */
210 #define md_load_zero_native(inst,reg) \
211 amd64_clear_reg((inst), (reg))
212
213 /*
214 * Load a 32-bit word register from an offset from a pointer register.
215 * This will sign-extend if the native word size is larger.
216 */
217 #define md_load_membase_word_32(inst,reg,basereg,offset) \
218 amd64_mov_reg_membase((inst), (reg), (basereg), (offset), 4)
219
220 /*
221 * Load a native-sized word register from an offset from a pointer register.
222 */
223 #define md_load_membase_word_native(inst,reg,basereg,offset) \
224 amd64_mov_reg_membase((inst), (reg), (basereg), (offset), 8)
225
226 /*
227 * Load a 64-bit word register from an offset from a pointer register
228 * into a pair of 32-bit registers. Only used on 32-bit systems.
229 */
230 #define md_load_membase_word_64(inst,lreg,hreg,basereg,offset) \
231 do { \
232 TODO_trap(inst);\
233 } while (0)
234
235 /*
236 * Load a byte value from an offset from a pointer register.
237 */
238 #define md_load_membase_byte(inst,reg,basereg,offset) \
239 amd64_widen_membase((inst), (reg), (basereg), (offset), 0, 0)
240
241 /*
242 * Load a signed byte value from an offset from a pointer register.
243 */
244 #define md_load_membase_sbyte(inst,reg,basereg,offset) \
245 amd64_widen_membase((inst), (reg), (basereg), (offset), 1, 0)
246
247 /*
248 * Load a short value from an offset from a pointer register.
249 */
250 #define md_load_membase_short(inst,reg,basereg,offset) \
251 amd64_widen_membase((inst), (reg), (basereg), (offset), 1, 1)
252
253 /*
254 * Load an unsigned short value from an offset from a pointer register.
255 */
256 #define md_load_membase_ushort(inst,reg,basereg,offset) \
257 amd64_widen_membase((inst), (reg), (basereg), (offset), 0, 1)
258
259 /*
260 * Load a floating-point value from an offset from a pointer register.
261 * If the system uses floating-point registers, then the value is
262 * loaded into "reg". Otherwise it is loaded onto the top of the
263 * floating-point stack.
264 */
265 #define md_load_membase_float_32(inst,reg,basereg,offset) \
266 x86_fld_membase((inst), (basereg), (offset), 0)
267 #define md_load_membase_float_64(inst,reg,basereg,offset) \
268 x86_fld_membase((inst), (basereg), (offset), 1)
269 #define md_load_membase_float_native(inst,reg,basereg,offset) \
270 x86_fld80_membase((inst), (basereg), (offset))
271
272 /*
273 * Store a 32-bit word register to an offset from a pointer register.
274 */
275 #define md_store_membase_word_32(inst,reg,basereg,offset) \
276 amd64_mov_membase_reg((inst), (basereg), (offset), (reg), 4)
277
278 /*
279 * Store a native-sized word register to an offset from a pointer register.
280 */
281 #define md_store_membase_word_native(inst,reg,basereg,offset) \
282 amd64_mov_membase_reg((inst), (basereg), (offset), (reg), 8)
283
284 /*
285 * Store a pair of 32-bit word registers to an offset from a pointer
286 * register as a 64-bit value. Only used on 32-bit systems.
287 */
288 #define md_store_membase_word_64(inst,lreg,hreg,basereg,offset) \
289 do { \
290 TODO_trap(inst);\
291 } while (0)
292
293 /*
294 * Store a byte value to an offset from a pointer register.
295 */
296 md_inst_ptr _md_x86_mov_membase_reg_byte
297 (md_inst_ptr inst, int basereg, int offset, int srcreg);
298 #define md_store_membase_byte(inst,reg,basereg,offset) \
299 do { \
300 (inst) = _md_x86_mov_membase_reg_byte \
301 ((inst), (basereg), (int)(offset), (reg)); \
302 } while (0)
303
304 /*
305 * Store a signed byte value to an offset from a pointer register.
306 */
307 #define md_store_membase_sbyte(inst,reg,basereg,offset) \
308 md_store_membase_byte((inst), (reg), (basereg), (offset))
309
310 /*
311 * Store a short value to an offset from a pointer register.
312 */
313 #define md_store_membase_short(inst,reg,basereg,offset) \
314 x86_mov_membase_reg((inst), (basereg), (offset), (reg), 2)
315
316 /*
317 * Store an unsigned short value to an offset from a pointer register.
318 */
319 #define md_store_membase_ushort(inst,reg,basereg,offset) \
320 x86_mov_membase_reg((inst), (basereg), (offset), (reg), 2)
321
322 /*
323 * Store a floating-point value to an offset from a pointer register.
324 * If the system uses floating-point registers, then the value is
325 * stored from "reg". Otherwise it is stored from the top of the
326 * floating-point stack.
327 */
328 #define md_store_membase_float_32(inst,reg,basereg,offset) \
329 x86_fst_membase((inst), (basereg), (offset), 0, 1)
330 #define md_store_membase_float_64(inst,reg,basereg,offset) \
331 x86_fst_membase((inst), (basereg), (offset), 1, 1)
332 #define md_store_membase_float_native(inst,reg,basereg,offset) \
333 x86_fst80_membase((inst), (basereg), (offset))
334
335 /*
336 * Add an immediate value to a register.
337 */
338 #define md_add_reg_imm(inst,reg,imm) \
339 amd64_alu_reg_imm_size((inst), X86_ADD, (reg), (imm), 8)
340
341 /*
342 * Subtract an immediate value from a register.
343 */
344 #define md_sub_reg_imm(inst,reg,imm) \
345 amd64_alu_reg_imm_size((inst), X86_SUB, (reg), (imm), 8)
346
347 /*
348 * Perform arithmetic and logical operations on 32-bit word registers.
349 *
350 * Division is tricky, so it is handled elsewhere for x86.
351 */
352 #define md_add_reg_reg_word_32(inst,reg1,reg2) \
353 amd64_alu_reg_reg_size((inst), X86_ADD, (reg1), (reg2), 4)
354 #define md_sub_reg_reg_word_32(inst,reg1,reg2) \
355 amd64_alu_reg_reg_size((inst), X86_SUB, (reg1), (reg2), 4)
356 #define md_mul_reg_reg_word_32(inst,reg1,reg2) \
357 amd64_imul_reg_reg_size((inst), (reg1), (reg2), 4)
358 extern md_inst_ptr _md_x86_divide(md_inst_ptr inst, int reg1, int reg2,
359 int isSigned, int wantRemainder);
360 #define md_div_reg_reg_word_32(inst,reg1,reg2) \
361 do { ; } while (0)
362 #define md_udiv_reg_reg_word_32(inst,reg1,reg2) \
363 do { ; } while (0)
364 #define md_rem_reg_reg_word_32(inst,reg1,reg2) \
365 do { ; } while (0)
366 #define md_urem_reg_reg_word_32(inst,reg1,reg2) \
367 do { ; } while (0)
368 #define md_neg_reg_word_32(inst,reg) \
369 amd64_neg_reg_size((inst), (reg), 4)
370 #define md_and_reg_reg_word_32(inst,reg1,reg2) \
371 amd64_alu_reg_reg_size((inst), X86_AND, (reg1), (reg2), 4)
372 #define md_xor_reg_reg_word_32(inst,reg1,reg2) \
373 amd64_alu_reg_reg_size((inst), X86_XOR, (reg1), (reg2), 4)
374 #define md_or_reg_reg_word_32(inst,reg1,reg2) \
375 amd64_alu_reg_reg_size((inst), X86_OR, (reg1), (reg2), 4)
376 #define md_not_reg_word_32(inst,reg) \
377 amd64_not_reg_size((inst), (reg), 4)
378 extern md_inst_ptr _md_x86_shift(md_inst_ptr inst, int opc, int reg1, int reg2);
379 #define md_shl_reg_reg_word_32(inst,reg1,reg2) \
380 do { (inst) = _md_x86_shift \
381 ((inst), X86_SHL, (reg1), (reg2)); } while (0)
382 #define md_shr_reg_reg_word_32(inst,reg1,reg2) \
383 do { (inst) = _md_x86_shift \
384 ((inst), X86_SAR, (reg1), (reg2)); } while (0)
385 #define md_ushr_reg_reg_word_32(inst,reg1,reg2) \
386 do { (inst) = _md_x86_shift \
387 ((inst), X86_SHR, (reg1), (reg2)); } while (0)
388 /*
389 * Perform arithmetic on native word values
390 */
391
392 #define md_add_reg_reg_word_native(inst,reg1,reg2) \
393 amd64_alu_reg_reg_size((inst), X86_ADD, (reg1), (reg2), 8)
394 #define md_sub_reg_reg_word_native(inst,reg1,reg2) \
395 amd64_alu_reg_reg_size((inst), X86_SUB, (reg1), (reg2), 8)
396 #define md_neg_reg_word_native(inst,reg) \
397 amd64_neg_reg((inst), (reg))
398 #define md_and_reg_reg_word_native(inst,reg1,reg2) \
399 amd64_alu_reg_reg_size((inst), X86_AND, (reg1), (reg2), 8)
400 #define md_xor_reg_reg_word_native(inst,reg1,reg2) \
401 amd64_alu_reg_reg_size((inst), X86_XOR, (reg1), (reg2), 8)
402 #define md_or_reg_reg_word_native(inst,reg1,reg2) \
403 amd64_alu_reg_reg_size((inst), X86_OR, (reg1), (reg2), 8)
404 #define md_not_reg_word_native(inst,reg) \
405 amd64_not_reg((inst), (reg))
406
407 /*
408 * Perform arithmetic on 64-bit values represented as 32-bit word pairs.
409 */
410 #define md_add_reg_reg_word_64(inst,lreg1,hreg1,lreg2,hreg2) \
411 do { \
412 TODO_trap(inst); \
413 } while (0)
414 #define md_sub_reg_reg_word_64(inst,lreg1,hreg1,lreg2,hreg2) \
415 do { \
416 TODO_trap(inst); \
417 } while (0)
418 #define md_neg_reg_word_64(inst,lreg,hreg) \
419 do { \
420 TODO_trap(inst); \
421 } while (0)
422
423 /*
424 * Perform arithmetic operations on native float values. If the system
425 * uses a floating-point stack, then the register arguments are ignored.
426 *
427 * Note: x86 remainder is handled elsewhere because it is complicated.
428 */
429 #define md_add_reg_reg_float(inst,reg1,reg2) \
430 x86_fp_op_reg((inst), X86_FADD, 1, 1)
431 #define md_sub_reg_reg_float(inst,reg1,reg2) \
432 x86_fp_op_reg((inst), X86_FSUB, 1, 1)
433 #define md_mul_reg_reg_float(inst,reg1,reg2) \
434 x86_fp_op_reg((inst), X86_FMUL, 1, 1)
435 #define md_div_reg_reg_float(inst,reg1,reg2) \
436 x86_fp_op_reg((inst), X86_FDIV, 1, 1)
437 extern md_inst_ptr _md_x86_rem_float
438 (md_inst_ptr inst, int reg1, int reg2, int used);
439 #define md_rem_reg_reg_float(inst,reg1,reg2,used) \
440 do { (inst) = _md_x86_rem_float \
441 ((inst), (reg1), (reg2), (used)); } while (0)
442 #define md_neg_reg_float(inst,reg) \
443 x86_fchs((inst))
444
445 /*
446 * Compare two floating point values and produce a -1, 0, or 1 result.
447 */
448 extern md_inst_ptr _md_x86_cmp_float(md_inst_ptr inst, int dreg, int lessop);
449 #define md_cmp_reg_reg_float(inst, dreg, sreg1, sreg2, lessop) \
450 do { \
451 (inst) = _md_x86_cmp_float((inst), (dreg), (lessop)); \
452 } while (0)
453
454 /*
455 * Convert word registers between various types.
456 */
457 extern md_inst_ptr _md_x86_widen_byte(md_inst_ptr inst, int reg, int isSigned);
458 #define md_reg_to_byte(inst,reg) \
459 do { \
460 (inst) = _md_x86_widen_byte((inst), (reg), 0); \
461 } while (0)
462 #define md_reg_to_sbyte(inst,reg) \
463 do { \
464 (inst) = _md_x86_widen_byte((inst), (reg), 1); \
465 } while (0)
466 #define md_reg_to_short(inst,reg) \
467 amd64_widen_reg((inst), (reg), (reg), 1, 1)
468 #define md_reg_to_ushort(inst,reg) \
469 amd64_widen_reg((inst), (reg), (reg), 0, 1)
470 #define md_reg_to_word_32(inst,reg) \
471 amd64_mov_reg_reg((inst), (reg), (reg), 4)
472 #define md_reg_to_word_native(inst,reg) \
473 amd64_movxsd_reg_reg((inst), (reg), (reg))
474 #define md_reg_to_word_native_un(inst,reg) \
475 amd64_mov_reg_reg_size((inst), (reg), (reg), 4)
476
477 /*
478 * Truncate floating point values to 32-bit or 64-bit.
479 */
480 #define md_reg_to_float_32(inst,reg) \
481 do { \
482 x86_alu_reg_imm((inst), X86_SUB, X86_ESP, 4); \
483 x86_fst_membase((inst), X86_ESP, 0, 0, 1); \
484 x86_fld_membase((inst), X86_ESP, 0, 0); \
485 x86_alu_reg_imm((inst), X86_ADD, X86_ESP, 4); \
486 } while (0)
487 #define md_reg_to_float_64(inst,reg) \
488 do { \
489 x86_alu_reg_imm((inst), X86_SUB, X86_ESP, 8); \
490 x86_fst_membase((inst), X86_ESP, 0, 1, 1); \
491 x86_fld_membase((inst), X86_ESP, 0, 1); \
492 x86_alu_reg_imm((inst), X86_ADD, X86_ESP, 8); \
493 } while (0)
494
495 /*
496 * Swap the top two items on the floating-point stack.
497 */
498 #define md_freg_swap(inst) x86_fxch((inst), 1)
499
500 /*
501 * Jump back into the CVM interpreter to execute the instruction
502 * at "pc". If "label" is non-NULL, then it indicates the address
503 * of the CVM instruction handler to jump directly to.
504 */
505 #define md_jump_to_cvm(inst,pc,label) \
506 do { \
507 amd64_mov_reg_imm_size((inst), MD_REG_PC, (void*)pc, 8); \
508 if((label)) \
509 { \
510 amd64_jump_code((inst), label); \
511 } \
512 else \
513 { \
514 amd64_jump_membase((inst), MD_REG_PC, 0); \
515 } \
516 } while (0)
517
518 /*
519 * Jump to a program counter that is defined by a switch table.
520 */
521 #define md_switch(inst,reg,table) \
522 do { \
523 /* amd64_mov_reg_memindex((inst), MD_REG_PC, X86_NOBASEREG, \
524 (long long)(table), (reg), 2, 4); \
525 amd64_jump_membase((inst), MD_REG_PC, 0); */\
526 TODO_trap(inst);\
527 } while (0)
528
529 /*
530 * Perform a clear operation at a memory base.
531 */
532 #define md_clear_membase_start(inst) do { ; } while (0)
533 #define md_clear_membase(inst,reg,offset) \
534 do { \
535 amd64_mov_membase_imm((inst), (reg), (offset), 0, 8); \
536 } while (0)
537
538 /*
539 * Load the effective address of a memory base into a register.
540 */
541 #define md_lea_membase(inst,reg,basereg,offset) \
542 do { \
543 int __value = (int)(offset); \
544 if(!__value) \
545 { \
546 amd64_mov_reg_reg((inst), (reg), (basereg), 8); \
547 } \
548 else \
549 { \
550 amd64_lea_membase((inst), (reg), (basereg), __value); \
551 } \
552 } while (0)
553
554 /*
555 * Move values between registers.
556 */
557 #define md_mov_reg_reg(inst,dreg,sreg) \
558 amd64_mov_reg_reg((inst), (dreg), (sreg), 4)
559
560 /*
561 * Set a register to a 0 or 1 value based on a condition.
562 */
563 extern md_inst_ptr _md_x86_setcc(md_inst_ptr inst, int reg, int cond);
564 #define md_seteq_reg(inst,reg) \
565 do { (inst) = _md_x86_setcc((inst), (reg), X86_CC_EQ); } while (0)
566 #define md_setne_reg(inst,reg) \
567 do { (inst) = _md_x86_setcc((inst), (reg), X86_CC_NE); } while (0)
568 #define md_setlt_reg(inst,reg) \
569 do { (inst) = _md_x86_setcc((inst), (reg), X86_CC_LT); } while (0)
570 #define md_setle_reg(inst,reg) \
571 do { (inst) = _md_x86_setcc((inst), (reg), X86_CC_LE); } while (0)
572 #define md_setgt_reg(inst,reg) \
573 do { (inst) = _md_x86_setcc((inst), (reg), X86_CC_GT); } while (0)
574 #define md_setge_reg(inst,reg) \
575 do { (inst) = _md_x86_setcc((inst), (reg), X86_CC_GE); } while (0)
576
577 /*
578 * Set a register to -1, 0, or 1 based on comparing two values.
579 */
580 extern md_inst_ptr _md_x86_compare
581 (md_inst_ptr inst, int reg1, int reg2, int isSigned);
582 #define md_cmp_reg_reg_word_32(inst,reg1,reg2) \
583 do { (inst) = _md_x86_compare \
584 ((inst), (reg1), (reg2), 1); } while (0)
585 #define md_ucmp_reg_reg_word_32(inst,reg1,reg2) \
586 do { (inst) = _md_x86_compare \
587 ((inst), (reg1), (reg2), 0); } while (0)
588
589 /*
590 * Set the condition codes based on comparing two values.
591 * The "cond" value indicates the type of condition that we
592 * want to check for.
593 */
594 #define md_cmp_cc_reg_reg_word_32(inst,cond,reg1,reg2) \
595 amd64_alu_reg_reg_size((inst), X86_CMP, (reg1), (reg2), 4)
596 #define md_cmp_cc_reg_reg_word_native(inst,cond,reg1,reg2) \
597 amd64_alu_reg_reg((inst), X86_CMP, (reg1), (reg2))
598
599 /*
600 * Test the contents of a register against NULL and set the
601 * condition codes based on the result.
602 */
603 #define md_reg_is_null(inst,reg) \
604 amd64_alu_reg_reg((inst), X86_OR, (reg), (reg))
605
606 /*
607 * Test the contents of a register against 32-bit zero and set the
608 * condition codes based on the result.
609 */
610 #define md_reg_is_zero(inst,reg) \
611 amd64_alu_reg_reg((inst), X86_OR, (reg), (reg))
612
613 /*
614 * Compare a 32-bit register against an immediate value and set
615 * the condition codes based on the result.
616 */
617 #define md_cmp_reg_imm_word_32(inst,cond,reg,imm) \
618 x86_alu_reg_imm((inst), X86_CMP, (reg), (int)(imm))
619
620 /*
621 * Output a branch to a location based on a condition. The actual
622 * jump offset will be filled in by a later "md_patch" call.
623 */
624 #define md_branch_eq(inst) \
625 amd64_branch32((inst), X86_CC_EQ, 0, 0)
626 #define md_branch_ne(inst) \
627 amd64_branch32((inst), X86_CC_NE, 0, 0)
628 #define md_branch_lt(inst) \
629 amd64_branch32((inst), X86_CC_LT, 0, 1)
630 #define md_branch_le(inst) \
631 amd64_branch32((inst), X86_CC_LE, 0, 1)
632 #define md_branch_gt(inst) \
633 amd64_branch32((inst), X86_CC_GT, 0, 1)
634 #define md_branch_ge(inst) \
635 amd64_branch32((inst), X86_CC_GE, 0, 1)
636 #define md_branch_lt_un(inst) \
637 amd64_branch32((inst), X86_CC_LT, 0, 0)
638 #define md_branch_le_un(inst) \
639 amd64_branch32((inst), X86_CC_LE, 0, 0)
640 #define md_branch_gt_un(inst) \
641 amd64_branch32((inst), X86_CC_GT, 0, 0)
642 #define md_branch_ge_un(inst) \
643 amd64_branch32((inst), X86_CC_GE, 0, 0)
644 #define md_branch_cc(inst,cond) \
645 amd64_branch32((inst), (cond) & 15, 0, ((cond) & 16) != 0)
646
647 /*
648 * Specific condition codes for "md_branch_cc".
649 */
650 #define MD_CC_EQ X86_CC_EQ
651 #define MD_CC_NE X86_CC_NE
652 #define MD_CC_LT (X86_CC_LT | 16)
653 #define MD_CC_LE (X86_CC_LE | 16)
654 #define MD_CC_GT (X86_CC_GT | 16)
655 #define MD_CC_GE (X86_CC_GE | 16)
656 #define MD_CC_LT_UN X86_CC_LT
657 #define MD_CC_LE_UN X86_CC_LE
658 #define MD_CC_GT_UN X86_CC_GT
659 #define MD_CC_GE_UN X86_CC_GE
660
661 /*
662 * Back-patch a branch instruction at "patch" to branch to "inst".
663 */
664 #define md_patch(patch,inst) \
665 amd64_patch((patch), (inst))
666
667 /*
668 * Check an array bounds value. "reg1" points to the array,
669 * and "reg2" is the array index to check.
670 */
671 #define md_bounds_check(inst,reg1,reg2) \
672 x86_alu_reg_membase((inst), X86_CMP, (reg2), (reg1), 0)
673
674 /*
675 * Load a 32-bit word value from an indexed array. "disp" is the offset
676 * to use to skip over the array bounds value. Some platforms may ignore
677 * "disp" if they advance the base pointer in "md_bounds_check".
678 */
679 #define md_load_memindex_word_32(inst,reg,basereg,indexreg,disp) \
680 do { \
681 x86_mov_reg_memindex((inst), (reg), (basereg), \
682 (disp), (indexreg), 2, 4); \
683 } while (0)
684
685 /*
686 * Load a native word value from an indexed array.
687 */
688 #define md_load_memindex_word_native(inst,reg,basereg,indexreg,disp) \
689 do { \
690 x86_mov_reg_memindex((inst), (reg), (basereg), \
691 (disp), (indexreg), 2, 4); \
692 } while (0)
693
694 /*
695 * Load a byte value from an indexed array.
696 */
697 #define md_load_memindex_byte(inst,reg,basereg,indexreg,disp) \
698 do { \
699 x86_widen_memindex((inst), (reg), (basereg), \
700 (disp), (indexreg), 0, 0, 0); \
701 } while (0)
702
703 /*
704 * Load a signed byte value from an indexed array.
705 */
706 #define md_load_memindex_sbyte(inst,reg,basereg,indexreg,disp) \
707 do { \
708 x86_widen_memindex((inst), (reg), (basereg), \
709 (disp), (indexreg), 0, 1, 0); \
710 } while (0)
711
712 /*
713 * Load a short value from an indexed array.
714 */
715 #define md_load_memindex_short(inst,reg,basereg,indexreg,disp) \
716 do { \
717 x86_widen_memindex((inst), (reg), (basereg), \
718 (disp), (indexreg), 1, 1, 1); \
719 } while (0)
720
721 /*
722 * Load an unsigned short value from an indexed array.
723 */
724 #define md_load_memindex_ushort(inst,reg,basereg,indexreg,disp) \
725 do { \
726 x86_widen_memindex((inst), (reg), (basereg), \
727 (disp), (indexreg), 1, 0, 1); \
728 } while (0)
729
730 /*
731 * Store a 32-bit word value into an indexed array.
732 */
733 #define md_store_memindex_word_32(inst,reg,basereg,indexreg,disp) \
734 do { \
735 x86_mov_memindex_reg((inst), (basereg), (disp), (indexreg), \
736 2, (reg), 4); \
737 } while (0)
738
739 /*
740 * Store a native word value into an indexed array.
741 */
742 #define md_store_memindex_word_native(inst,reg,basereg,indexreg,disp) \
743 do { \
744 x86_mov_memindex_reg((inst), (basereg), (disp), (indexreg), \
745 2, (reg), 4); \
746 } while (0)
747
748 /*
749 * Store a byte value into an indexed array.
750 */
751 extern md_inst_ptr _md_x86_mov_memindex_reg_byte
752 (md_inst_ptr inst, int basereg,
753 unsigned offset, int indexreg, int srcreg);
754 #define md_store_memindex_byte(inst,reg,basereg,indexreg,disp) \
755 do { \
756 (inst) = _md_x86_mov_memindex_reg_byte \
757 ((inst), (basereg), (disp), (indexreg), (reg)); \
758 } while (0)
759
760 /*
761 * Store a signed byte value into an indexed array.
762 */
763 #define md_store_memindex_sbyte(inst,reg,basereg,indexreg,disp) \
764 do { \
765 (inst) = _md_x86_mov_memindex_reg_byte \
766 ((inst), (basereg), (disp), (indexreg), (reg)); \
767 } while (0)
768
769 /*
770 * Store a short value into an indexed array.
771 */
772 #define md_store_memindex_short(inst,reg,basereg,indexreg,disp) \
773 do { \
774 x86_mov_memindex_reg((inst), (basereg), (disp), (indexreg), \
775 1, (reg), 2); \
776 } while (0)
777
778 /*
779 * Store an unsigned short value into an indexed array.
780 */
781 #define md_store_memindex_ushort(inst,reg,basereg,indexreg,disp) \
782 do { \
783 x86_mov_memindex_reg((inst), (basereg), (disp), (indexreg), \
784 1, (reg), 2); \
785 } while (0)
786
787 #ifdef __cplusplus
788 };
789 #endif
790
791 #endif /* _ENGINE_MD_X86_H */

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26