summaryrefslogtreecommitdiff
path: root/orc/orcx86.h
blob: 62b4743133a27e8b498013502d62d16447525cd7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231

#ifndef _ORC_X86_H_
#define _ORC_X86_H_

#include <orc/orcprogram.h>
#include <orc/orcx86insn.h>

ORC_BEGIN_DECLS

#ifdef ORC_ENABLE_UNSTABLE_API

typedef struct _OrcX86Target
{
  /* Same as OrcTarget */
  const char *name;
  unsigned int (*get_default_flags)(void);
  const char * (*get_flag_name)(int shift);
  int (*is_executable)(void);

  /* X86 specific */
  void (*validate_registers)(int *regs, int is_64bit);
  void (*saveable_registers)(int *regs, int is_64bit);
  int (*is_64bit)(int flags);
  int (*use_frame_pointer)(int flags);
  int (*use_long_jumps)(int flags);
  int (*loop_shift)(int max_var_size);
  void (*init_accumulator)(OrcCompiler *c, OrcVariable *var);
  void (*reduce_accumulator)(OrcCompiler *c, int i, OrcVariable *var);
  void (*load_constant)(OrcCompiler *c, int reg, int size, orc_uint64 value);
  void (*load_constant_long)(OrcCompiler *c, int reg, OrcConstant *constant);
  void (*move_register_to_memoffset)(OrcCompiler *compiler, int size, int reg1, int offset, int reg2, int aligned, int uncached);
  void (*move_memoffset_to_register)(OrcCompiler *compiler, int size, int offset, int reg1, int reg2, int is_aligned);
  int (*get_shift)(int size);
  void (*set_mxcsr)(OrcCompiler *c);
  void (*restore_mxcsr)(OrcCompiler *c);
  int register_size;
  int register_start;
  int n_registers;
  int label_step_up;
} OrcX86Target;

enum {
  X86_EAX = ORC_GP_REG_BASE,
  X86_ECX,
  X86_EDX,
  X86_EBX,
  X86_ESP,
  X86_EBP,
  X86_ESI,
  X86_EDI,
  X86_R8,
  X86_R9,
  X86_R10,
  X86_R11,
  X86_R12,
  X86_R13,
  X86_R14,
  X86_R15
};

enum {
  ORC_X86_UNKNOWN,
  ORC_X86_P6,
  ORC_X86_NETBURST,
  ORC_X86_CORE,
  ORC_X86_PENRYN,
  ORC_X86_NEHALEM,
  ORC_X86_BONNELL,
  ORC_X86_WESTMERE,
  ORC_X86_SANDY_BRIDGE,
  ORC_X86_K5,
  ORC_X86_K6,
  ORC_X86_K7,
  ORC_X86_K8,
  ORC_X86_K10
};

ORC_API const char * orc_x86_get_regname(int i);
ORC_API int          orc_x86_get_regnum(int i);
ORC_API const char * orc_x86_get_regname_8(int i);
ORC_API const char * orc_x86_get_regname_16(int i);
ORC_API const char * orc_x86_get_regname_64(int i);
ORC_API const char * orc_x86_get_regname_ptr(OrcCompiler *compiler, int i);
ORC_API const char * orc_x86_get_regname_size(int i, int size);

ORC_API void orc_x86_emit_push (OrcCompiler *compiler, int size, int reg);
ORC_API void orc_x86_emit_pop (OrcCompiler *compiler, int size, int reg);

#define orc_x86_emit_mov_imm_reg(p,size,value,reg) \
  orc_x86_emit_cpuinsn_imm_reg (p, ORC_X86_mov_imm32_r, size, value, reg)
#define orc_x86_emit_mov_reg_reg(p,size,src,dest) \
  orc_x86_emit_cpuinsn_size (p, ORC_X86_mov_r_rm, size, src, dest)
#define orc_x86_emit_test_reg_reg(p,size,src,dest) \
  orc_x86_emit_cpuinsn_size (p, ORC_X86_test, size, src, dest)
#define orc_x86_emit_sar_imm_reg(p,size,value,reg) do { \
    if (value == 1) { \
      orc_x86_emit_cpuinsn_imm_reg (p, ORC_X86_sar, size, value, reg); \
    } else if (value > 1) { \
      orc_x86_emit_cpuinsn_imm_reg (p, ORC_X86_sar_imm, size, value, reg); \
    } \
  } while (0)
#define orc_x86_emit_and_imm_memoffset(p,size,value,offset,reg) \
  orc_x86_emit_cpuinsn_imm_memoffset (p, (value >= -128 && value < 128) ? \
      ORC_X86_and_imm8_rm : ORC_X86_and_imm32_rm, size, value, offset, reg)
#define orc_x86_emit_and_imm_reg(p,size,value,reg) do { \
  if ((value) >= -128 && (value) < 128) { \
    orc_x86_emit_cpuinsn_imm_reg (p, ORC_X86_and_imm8_rm, size, value, reg); \
  } else { \
    if ((reg) == X86_EAX) { \
      orc_x86_emit_cpuinsn_imm_reg (p, ORC_X86_and_imm32_a, size, value, reg); \
    } else { \
      orc_x86_emit_cpuinsn_imm_reg (p, ORC_X86_and_imm32_rm, size, value, reg); \
    } \
  } \
} while (0)
#define orc_x86_emit_add_imm_memoffset(p,size,value,offset,reg) \
  orc_x86_emit_cpuinsn_imm_memoffset (p, (value >= -128 && value < 128) ? \
      ORC_X86_add_imm8_rm : ORC_X86_add_imm32_rm, size, value, offset, reg)
#define orc_x86_emit_add_reg_memoffset(p,size,src,offset,dest) \
  orc_x86_emit_cpuinsn_reg_memoffset_s(p, ORC_X86_add_r_rm, size, src, offset, dest)
#define orc_x86_emit_add_reg_reg(p,size,src,dest) \
  orc_x86_emit_cpuinsn_size(p, ORC_X86_add_r_rm, size, src, dest)
#define orc_x86_emit_add_memoffset_reg(p,size,offset,src,dest) \
  orc_x86_emit_cpuinsn_memoffset_reg(p, ORC_X86_add_rm_r, size, offset, src, dest)
#define orc_x86_emit_sub_reg_reg(p,size,src,dest) \
  orc_x86_emit_cpuinsn_size(p, ORC_X86_sub_r_rm, size, src, dest)
#define orc_x86_emit_sub_memoffset_reg(p,size,offset,src,dest) \
  orc_x86_emit_cpuinsn_memoffset_reg(p, ORC_X86_sub_rm_r, size, offset, src, dest)
#define orc_x86_emit_imul_memoffset_reg(p,size,offset,src,dest) \
  orc_x86_emit_cpuinsn_memoffset_reg(p, ORC_X86_imul_rm_r, size, offset, src, dest)

#define orc_x86_emit_cmp_reg_memoffset(p,size,src,offset,dest) \
  orc_x86_emit_cpuinsn_reg_memoffset_s(p, ORC_X86_cmp_r_rm, size, src, offset, dest)

#define orc_x86_emit_jmp(p,label) \
  orc_x86_emit_cpuinsn_branch (p, ORC_X86_jmp, label)
#define orc_x86_emit_jg(p,label) \
  orc_x86_emit_cpuinsn_branch (p, ORC_X86_jg, label)
#define orc_x86_emit_jle(p,label) \
  orc_x86_emit_cpuinsn_branch (p, ORC_X86_jle, label)
#define orc_x86_emit_je(p,label) \
  orc_x86_emit_cpuinsn_branch (p, ORC_X86_jz, label)
#define orc_x86_emit_jne(p,label) \
  orc_x86_emit_cpuinsn_branch (p, ORC_X86_jnz, label)

#define orc_x86_emit_align(p,align_shift) \
  orc_x86_emit_cpuinsn_align (p, ORC_X86_ALIGN, align_shift)
#define orc_x86_emit_label(p,label) \
  orc_x86_emit_cpuinsn_label (p, ORC_X86_LABEL, label)

#define orc_x86_emit_emms(p) \
  orc_x86_emit_cpuinsn_none (p, ORC_X86_emms)
#define orc_x86_emit_rdtsc(p) \
  orc_x86_emit_cpuinsn_none (p, ORC_X86_rdtsc)
#define orc_x86_emit_ret(p) \
  orc_x86_emit_cpuinsn_none (p, ((p)->is_64bit) ? ORC_X86_retq : ORC_X86_ret)

#define orc_x86_emit_test_imm_memoffset(p,size,value,offset,dest) \
  orc_x86_emit_cpuinsn_imm_memoffset (p, ORC_X86_test_imm, size, value, \
      offset, dest)

ORC_API void orc_x86_emit_mov_memoffset_reg (OrcCompiler *compiler, int size, int offset, int reg1, int reg2);
ORC_API void orc_x86_emit_mov_reg_memoffset (OrcCompiler *compiler, int size, int reg1, int offset, int reg2);
ORC_API void orc_x86_emit_dec_memoffset (OrcCompiler *compiler, int size, int offset, int reg);
ORC_API void orc_x86_emit_add_imm_reg (OrcCompiler *compiler, int size, int value, int reg, orc_bool record);
ORC_API void orc_x86_emit_add_reg_reg_shift (OrcCompiler *compiler, int size, int reg1, int reg2, int shift);
ORC_API void orc_x86_emit_cmp_imm_memoffset (OrcCompiler *compiler, int size, int value, int offset, int reg);
ORC_API void orc_x86_emit_cmp_imm_reg (OrcCompiler *compiler, int size, int value, int reg);
ORC_API void orc_x86_emit_rep_movs (OrcCompiler *compiler, int size);
ORC_API void orc_x86_emit_prologue (OrcCompiler *compiler);
ORC_API void orc_x86_emit_epilogue (OrcCompiler *compiler);

ORC_API void orc_x86_emit_rex (OrcCompiler *compiler, int size, int reg1, int reg2, int reg3);
ORC_API void orc_x86_emit_modrm_memoffset_old (OrcCompiler *compiler, int reg1, int offset, int reg2);
ORC_API void orc_x86_emit_modrm_memoffset (OrcCompiler *compiler, int offset, int reg1, int reg2);
ORC_API void orc_x86_emit_modrm_reg (OrcCompiler *compiler, int reg1, int reg2);
ORC_API void orc_x86_emit_modrm_memindex (OrcCompiler *compiler, int reg1, int offset,
    int reg2, int regindex, int shift);
ORC_API void orc_x86_emit_modrm_memindex2 (OrcCompiler *compiler, int offset,
    int src, int src_index, int shift, int dest);

/* FIXME: remove from public header, these were never exported */
void x86_add_fixup (OrcCompiler *compiler, unsigned char *ptr, int label, int type);
void x86_add_label (OrcCompiler *compiler, unsigned char *ptr, int label);
void x86_add_label2 (OrcCompiler *compiler, int index, int label);

ORC_API void orc_x86_do_fixups (OrcCompiler *compiler);

ORC_API int  orc_x86_assemble_copy_check (OrcCompiler *compiler);
ORC_API void orc_x86_assemble_copy (OrcCompiler *compiler);

ORC_API void orc_x86_emit_cpuinsn_size (OrcCompiler *p, int opcode, int size,
    int src, int dest);
ORC_API void orc_x86_emit_cpuinsn_imm (OrcCompiler *p, int opcode, int imm,
    int src, int dest);
ORC_API void orc_x86_emit_cpuinsn_load_memoffset (OrcCompiler *p, int index, int size,
    int imm, int offset, int src, int dest);
ORC_API void orc_x86_emit_cpuinsn_store_memoffset (OrcCompiler *p, int size, int index,
    int imm, int offset, int src, int dest);
ORC_API void orc_x86_emit_cpuinsn_load_memindex (OrcCompiler *p, int index, int size,
    int imm, int offset, int src, int src_index, int shift, int dest);
ORC_API void orc_x86_emit_cpuinsn_load_register (OrcCompiler *p, int index, int imm,
    int src, int dest);
ORC_API void orc_x86_emit_cpuinsn_imm_reg (OrcCompiler *p, int index, int size, int imm,
    int dest);
ORC_API void orc_x86_emit_cpuinsn_imm_memoffset (OrcCompiler *p, int index, int size,
    int imm, int offset, int dest);
ORC_API void orc_x86_emit_cpuinsn_reg_memoffset (OrcCompiler *p, int index, int src,
    int offset, int dest);
ORC_API void orc_x86_emit_cpuinsn_reg_memoffset_8 (OrcCompiler *p, int index, int src,
    int offset, int dest);
ORC_API void orc_x86_emit_cpuinsn_reg_memoffset_s (OrcCompiler *p, int index, int size,
    int src, int offset, int dest);
ORC_API void orc_x86_emit_cpuinsn_memoffset_reg (OrcCompiler *p, int index, int size,
    int offset, int src, int dest);
ORC_API void orc_x86_emit_cpuinsn_memoffset (OrcCompiler *p, int index, int size,
    int offset, int srcdest);
ORC_API void orc_x86_emit_cpuinsn_branch (OrcCompiler *p, int index, int label);
ORC_API void orc_x86_emit_cpuinsn_label (OrcCompiler *p, int index, int label);
ORC_API void orc_x86_emit_cpuinsn_none (OrcCompiler *p, int index);
ORC_API void orc_x86_emit_cpuinsn_align (OrcCompiler *p, int index, int align_shift);

ORC_API OrcTarget * orc_x86_register_target (OrcX86Target *x86t);

#endif

ORC_END_DECLS


#endif