Initial snarf.
[shack.git] / arch / x86 / as / x86_as_code.ml
blob43e5338d4c7ce01e675d7fae63cfb3d161a136c1
1 (*
2 * Assemble the code.
4 * ----------------------------------------------------------------
6 * @begin[license]
7 * Copyright (C) 2001 Jason Hickey, Caltech
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * Author: Jason Hickey
24 * @email{jyh@cs.caltech.edu}
25 * @end[license]
27 open Format
29 open Debug
30 open Symbol
32 open Bfd
34 open Frame_type
36 open Mir_arity_map
38 open X86_inst_type
39 open X86_frame_type
40 open X86_frame
41 open X86_exn
42 open X86_pos
44 open X86_as_bfd
45 open X86_as_bfd.Bfd
46 open X86_as_bfd.Buf
47 open X86_as_opcodes
48 open X86_as_util
49 open X86_as_opcode
50 open X86_as_modrm
51 open X86_as_empty
52 open X86_as_unary
53 open X86_as_binary
54 open X86_as_shift
55 open X86_as_special
56 open X86_as_float
57 open X86_as_mmx
58 open X86_as_section
60 module Pos = MakePos (struct let name = "X86_as_code" end)
61 open Pos
64 * Assemble the instructon.
66 let assem_inst buf pos inst =
67 let pos = inst_pos inst pos in
68 let next = new_symbol_string "inst" in
69 let () =
70 match inst with
71 (* Nops *)
72 CommentString _
73 | CommentInst _
74 | CommentMIR _
75 | CommentFIR _
76 | FJMP _ ->
78 | NOP ->
79 as_print_empty_inst buf nop_opcodes
81 (* Copy *)
82 | MOV (pre, op1, op2) ->
83 as_print_binary_int_inst buf mov_opcodes pos pre op1 op2 next
84 | MOVS (pre, op1, op2) ->
85 as_print_binary_int_inst buf movs_opcodes pos pre op1 op2 next
86 | MOVZ (pre, op1, op2) ->
87 as_print_binary_int_inst buf movz_opcodes pos pre op1 op2 next
88 | RMOVS pre ->
89 as_print_empty_pre_inst buf rmovs_opcodes pre
91 (* Arithmetic *)
92 | NOT (pre, op) ->
93 as_print_unary_int_inst buf not_opcodes pos pre op next
94 | NEG (pre, op) ->
95 as_print_unary_int_inst buf neg_opcodes pos pre op next
96 | INC (pre, op) ->
97 as_print_unary_int_inst buf inc_opcodes pos pre op next
98 | DEC (pre, op) ->
99 as_print_unary_int_inst buf dec_opcodes pos pre op next
100 | LEA (pre, op1, op2) ->
101 as_print_binary_int_inst buf lea_opcodes pos pre op1 op2 next
102 | ADD (pre, op1, op2) ->
103 as_print_binary_int_inst buf add_opcodes pos pre op1 op2 next
104 | ADC (pre, op1, op2) ->
105 as_print_binary_int_inst buf adc_opcodes pos pre op1 op2 next
106 | SUB (pre, op1, op2) ->
107 as_print_binary_int_inst buf sub_opcodes pos pre op1 op2 next
108 | SBB (pre, op1, op2) ->
109 as_print_binary_int_inst buf sbb_opcodes pos pre op1 op2 next
110 | MUL (pre, op) ->
111 as_print_unary_int_inst buf mul_opcodes pos pre op next
112 | IMUL (pre, op1, op2) ->
113 as_print_imul_inst buf pos pre op1 op2 next
114 | DIV (pre, op) ->
115 as_print_unary_int_inst buf div_opcodes pos pre op next
116 | IDIV (pre, op) ->
117 as_print_unary_int_inst buf idiv_opcodes pos pre op next
118 | CLTD ->
119 as_print_empty_inst buf cltd_opcodes
120 | AND (pre, op1, op2) ->
121 as_print_binary_int_inst buf and_opcodes pos pre op1 op2 next
122 | OR (pre, op1, op2) ->
123 as_print_binary_int_inst buf or_opcodes pos pre op1 op2 next
124 | XOR (pre, op1, op2) ->
125 as_print_binary_int_inst buf xor_opcodes pos pre op1 op2 next
126 | SAL (pre, op1, op2) ->
127 as_print_shift_inst buf sal_opcodes pos pre op1 op2
128 | SAR (pre, op1, op2) ->
129 as_print_shift_inst buf sar_opcodes pos pre op1 op2
130 | SHL (pre, op1, op2) ->
131 as_print_shift_inst buf shl_opcodes pos pre op1 op2
132 | SHR (pre, op1, op2) ->
133 as_print_shift_inst buf shr_opcodes pos pre op1 op2
134 | SHLD (pre, op1, op2, op3) ->
135 as_print_shiftd_inst buf shld_opcodes pos pre op1 op2 op3
136 | SHRD (pre, op1, op2, op3) ->
137 as_print_shiftd_inst buf shrd_opcodes pos pre op1 op2 op3
139 | PUSH (pre, op) ->
140 as_print_unary_int_inst buf push_opcodes pos pre op next
141 | POP (pre, op) ->
142 as_print_unary_int_inst buf pop_opcodes pos pre op next
143 | CALL op
144 | FCALL op ->
145 as_print_unary_int_inst buf call_opcodes pos IL op next
146 | RET ->
147 as_print_empty_inst buf ret_opcodes
149 | CMP (pre, op1, op2) ->
150 as_print_binary_int_inst buf cmp_opcodes pos pre op1 op2 next
151 | TEST (pre, op1, op2) ->
152 as_print_binary_int_inst buf test_opcodes pos pre op1 op2 next
154 | JMP op
155 | IJMP (_, op) ->
156 as_print_jmp_inst buf pos op next
157 | JCC (cc, op) ->
158 as_print_jcc_inst buf pos cc op next
159 | SET (cc, op) ->
160 as_print_setcc_inst buf pos cc op
162 (* MMX *)
163 | MOVD (op1, op2) ->
164 as_print_binary_mmx_inst buf movd_opcodes pos op1 op2 next
165 | MOVQ (op1, op2) ->
166 as_print_binary_mmx_inst buf movq_opcodes pos op1 op2 next
168 (* Floating point *)
169 | FINIT ->
170 as_print_empty_float_inst buf finit_opcodes
171 | FSTCW op ->
172 as_print_unary_float_inst buf fstcw_opcodes pos FS op
173 | FLDCW op ->
174 as_print_unary_float_inst buf fldcw_opcodes pos FS op
175 | FLD (pre, op) ->
176 as_print_unary_float_inst buf fld_opcodes pos pre op
177 | FILD op ->
178 as_print_unary_float_inst buf fild_opcodes pos FS op
179 | FILD64 op ->
180 as_print_unary_float_inst buf fild_opcodes pos FL op
181 | FST (pre, op) ->
182 as_print_unary_float_inst buf fst_opcodes pos pre op
183 | FSTP (pre, op) ->
184 as_print_unary_float_inst buf fstp_opcodes pos pre op
185 | FIST op ->
186 as_print_unary_float_inst buf fist_opcodes pos FS op
187 | FISTP op ->
188 as_print_unary_float_inst buf fistp_opcodes pos FS op
189 | FISTP64 op ->
190 as_print_unary_float_inst buf fistp_opcodes pos FL op
191 | FXCH op ->
192 as_print_unary_float_inst buf fxch_opcodes pos FT op
193 | FCHS ->
194 as_print_empty_float_inst buf fchs_opcodes
195 | FADDP ->
196 as_print_unary_float_inst buf faddp_opcodes pos FT st1
197 | FSUBP ->
198 as_print_unary_float_inst buf fsubp_opcodes pos FT st1
199 | FMULP ->
200 as_print_unary_float_inst buf fmulp_opcodes pos FT st1
201 | FDIVP ->
202 as_print_unary_float_inst buf fdivp_opcodes pos FT st1
203 | FSUBRP ->
204 as_print_unary_float_inst buf fsubrp_opcodes pos FT st1
205 | FDIVRP ->
206 as_print_unary_float_inst buf fdivrp_opcodes pos FT st1
207 | FPREM ->
208 as_print_empty_float_inst buf fprem_opcodes
209 | FSIN ->
210 as_print_empty_float_inst buf fsin_opcodes
211 | FCOS ->
212 as_print_empty_float_inst buf fcos_opcodes
213 | FPATAN ->
214 as_print_empty_float_inst buf fpatan_opcodes
215 | FSQRT ->
216 as_print_empty_float_inst buf fsqrt_opcodes
217 | FUCOM ->
218 as_print_unary_float_inst buf fucom_opcodes pos FT st1
219 | FUCOMP ->
220 as_print_unary_float_inst buf fucomp_opcodes pos FT st1
221 | FUCOMPP ->
222 as_print_empty_float_inst buf fucompp_opcodes
223 | FSTSW ->
224 as_print_empty_float_inst buf fstsw_opcodes
225 | FADD (op1, op2) ->
226 as_print_binary_float_inst buf fadd_opcodes pos FL op1 op2
227 | FSUB (op1, op2) ->
228 as_print_binary_float_inst buf fsub_opcodes pos FL op1 op2
229 | FMUL (op1, op2) ->
230 as_print_binary_float_inst buf fmul_opcodes pos FL op1 op2
231 | FDIV (op1, op2) ->
232 as_print_binary_float_inst buf fdiv_opcodes pos FL op1 op2
233 | FSUBR (op1, op2) ->
234 as_print_binary_float_inst buf fsubr_opcodes pos FL op1 op2
235 | FDIVR (op1, op2) ->
236 as_print_binary_float_inst buf fdivr_opcodes pos FL op1 op2
237 | FMOV (pre1, op1, pre2, op2) ->
238 as_print_unary_float_inst buf fld_opcodes pos pre2 op2;
239 as_print_unary_float_inst buf fst_opcodes pos pre1 op1
240 | FMOVP (pre1, op1, pre2, op2) ->
241 as_print_unary_float_inst buf fld_opcodes pos pre2 op2;
242 as_print_unary_float_inst buf fstp_opcodes pos pre1 op1
244 (* Special instructions *)
245 | RES (label, _, mem, ptr) ->
246 as_print_unary_int_inst buf push_opcodes pos IL label next;
247 as_print_unary_int_inst buf push_opcodes pos IL mem next;
248 as_print_unary_int_inst buf push_opcodes pos IL ptr next;
249 as_print_unary_int_inst buf call_opcodes pos IL (ImmediateLabel gc_label) next;
250 as_print_binary_int_inst buf add_opcodes pos IL (Register esp) (ImmediateNumber (OffNumber (Int32.of_int 12))) next
251 | COW (label, _, mem, ptr, copy_ptr) ->
252 as_print_unary_int_inst buf push_opcodes pos IL copy_ptr next;
253 as_print_unary_int_inst buf push_opcodes pos IL label next;
254 as_print_unary_int_inst buf push_opcodes pos IL mem next;
255 as_print_unary_int_inst buf push_opcodes pos IL ptr next;
256 as_print_unary_int_inst buf call_opcodes pos IL (ImmediateLabel copy_on_write_label) next;
257 as_print_binary_int_inst buf add_opcodes pos IL (Register esp) (ImmediateNumber (OffNumber (Int32.of_int 16))) next
258 | RESP (label, _) ->
259 as_print_unary_int_inst buf push_opcodes pos IL label next;
260 as_print_unary_int_inst buf push_opcodes pos IL (ImmediateNumber (OffNumber (Int32.of_int 0))) next;
261 as_print_unary_int_inst buf push_opcodes pos IL (ImmediateNumber (OffNumber (Int32.of_int 0))) next;
262 as_print_unary_int_inst buf push_opcodes pos IL (ImmediateNumber (OffNumber (Int32.of_int 0))) next;
263 as_print_unary_int_inst buf push_opcodes pos IL (Register ebp) next;
264 as_print_unary_int_inst buf push_opcodes pos IL (Register edi) next;
265 as_print_unary_int_inst buf push_opcodes pos IL (Register esi) next;
266 as_print_unary_int_inst buf push_opcodes pos IL (Register edx) next;
267 as_print_unary_int_inst buf push_opcodes pos IL (Register ecx) next;
268 as_print_unary_int_inst buf push_opcodes pos IL (Register ebx) next;
269 as_print_unary_int_inst buf push_opcodes pos IL (Register eax) next;
270 as_print_unary_int_inst buf push_opcodes pos IL (Register esp) next
273 bfd_print_label buf SymTemp next;
277 * Assemble a block.
279 let assem_block buf export block =
280 let { block_label = label;
281 block_code = insts;
282 block_index = index_flag;
283 block_align = align_flag;
284 block_arity = arity_tag;
285 } = block
287 let pos = var_exp_pos label in
288 let pos = string_pos "assem_block" pos in
289 (* Align if necessary *)
290 if align_flag then
291 bfd_align buf align_block
292 else
293 bfd_align buf 4;
295 (* If the index is set, then add space and the index *)
296 (match index_flag, arity_tag with
297 Some index, Some arity ->
298 (* Add the index to the function index table.
299 See arch/x86/runtime/x86_runtime.h for format. *)
300 bfd_skip buf index_skip 0x90; (* NOP *)
301 (* Function header begins here *)
302 as_print_imm32 buf (OffLabel arity);
303 bfd_print_int32 buf Int32.zero;
304 as_print_imm32 buf (OffOr (OffLabel index, OffNumber X86_runtime.aggr_shift_mask32));
305 | None, None ->
307 | _ ->
308 raise (X86Exception (pos, StringError "block_index and block_arity must be both set or both cleared")));
310 (* If there is a global binding, add it at this point *)
311 (try
312 let { export_name = s } = SymbolTable.find export label in
313 bfd_print_label buf SymGlobal (Symbol.add s)
314 with
315 Not_found ->
316 ());
318 (* Add the label at this program point *)
319 bfd_print_label buf SymLocal label;
321 (* Print all the instructons *)
322 ignore (List.fold_left (assem_inst buf) pos insts)
325 * Assemble a list.of blocks.
327 let assem_blocks buf export blocks =
328 List.iter (assem_block buf export) blocks
331 * Assemble all the block's text.
332 * We'll sweep for data separately.
334 let as_print_code buf blocks export =
335 let sect = text_section buf in
336 let buf = section_buf sect in
337 bfd_print_label buf SymLocal X86_stab.text_sym;
338 Trace.iter (assem_block buf export) blocks;
339 bfd_align buf align_block
342 * Assemble the code and print the function table info.
344 let assem_code buf info blocks =
345 let { bfd_export = export } = info in
346 as_print_code buf blocks export
349 * Print the arity tag table.
351 let as_print_arity_table buf arity =
352 let lookup_arity name =
354 snd (ArityTable.find arity name)
355 with
356 Not_found ->
357 Int32.zero
359 let sect = absolute_section buf in
360 let buf = section_buf sect in
361 let tag_exit = lookup_arity exit_arity_tag in
362 let tag_uncaught_exception = lookup_arity uncaught_exception_arity_tag in
363 ArityTable.iter (fun _ (label, index) ->
364 as_print_equ_int32 buf SymLocal label index) arity;
365 as_print_equ_int32 buf SymGlobal exit_arity_label tag_exit;
366 as_print_equ_int32 buf SymGlobal uncaught_exception_arity_label tag_uncaught_exception
369 * Print the function table.
371 let as_print_function_label buf (label, _) =
372 as_print_abs32 buf label
374 let as_print_function_table buf funs =
375 let sect = data_section buf in
376 let buf = section_buf sect in
377 bfd_align buf 4;
378 bfd_print_label buf SymGlobal function_base_label;
379 as_print_abs32 buf exit_label;
380 as_print_abs32 buf uncaught_exception_label;
381 List.iter (as_print_function_label buf) funs;
382 bfd_print_label buf SymGlobal function_limit_label
385 * Print the function tags.
387 let as_print_function_tag buf off (_, tag) =
388 as_print_equ_int buf SymLocal tag off;
389 off + 4
391 let as_print_function_tag_table buf funs =
392 let sect = absolute_section buf in
393 let buf = section_buf sect in
394 as_print_equ_int buf SymGlobal exit_tag_label 0;
395 as_print_equ_int buf SymGlobal uncaught_exception_tag_label 4;
396 let size = List.fold_left (as_print_function_tag buf) 8 funs in
397 as_print_equ_int buf SymGlobal function_size_label size
399 let assem_fun_table buf info =
400 let { bfd_fun_tags = funs;
401 bfd_arity_tags = arity;
402 } = info
404 as_print_function_table buf funs;
405 as_print_function_tag_table buf funs;
406 as_print_arity_table buf arity
409 * Collect all the blocks with index labels.
411 let get_block_tag funs block =
412 let { block_label = label;
413 block_index = index
414 } = block
416 match index with
417 Some tag ->
418 (label, tag) :: funs
419 | None ->
420 funs
422 let get_fun_tags blocks =
423 List.rev (Trace.fold get_block_tag [] blocks)
426 * @docoff
428 * -*-
429 * Local Variables:
430 * Caml-master: "compile"
431 * End:
432 * -*-