106
106
(* Output a reference to the lower 8, 16 or 32 bits of a register *)
108
108
let reg_low_8_name =
109
[| "al"; "bl"; "dil"; "sil"; "dl"; "cl"; "r8b"; "r9b";
109
[| "al"; "bl"; "dil"; "sil"; "dl"; "cl"; "r8b"; "r9b";
110
110
"r10b"; "r11b"; "bpl"; "r12b"; "r13b" |]
111
111
let reg_low_16_name =
112
[| "ax"; "bx"; "di"; "si"; "dx"; "cx"; "r8w"; "r9w";
112
[| "ax"; "bx"; "di"; "si"; "dx"; "cx"; "r8w"; "r9w";
113
113
"r10w"; "r11w"; "bp"; "r12w"; "r13w" |]
114
114
let reg_low_32_name =
115
[| "eax"; "ebx"; "edi"; "esi"; "edx"; "ecx"; "r8d"; "r9d";
115
[| "eax"; "ebx"; "edi"; "esi"; "edx"; "ecx"; "r8d"; "r9d";
116
116
"r10d"; "r11d"; "ebp"; "r12d"; "r13d" |]
118
118
let emit_subreg tbl pref r =
264
264
(* Output a floating-point compare and branch *)
266
266
let emit_float_test cmp neg arg lbl =
268
| Ceq | Cne -> ` ucomisd `
271
`{emit_reg arg.(0)}, {emit_reg arg.(1)}\n`;
272
let (branch_opcode, need_jp) =
273
match (cmp, neg) with
274
(Ceq, false) -> ("je", true)
275
| (Ceq, true) -> ("jne", true)
276
| (Cne, false) -> ("jne", true)
277
| (Cne, true) -> ("je", true)
278
| (Clt, false) -> ("jb", true)
279
| (Clt, true) -> ("jae", true)
280
| (Cle, false) -> ("jbe", true)
281
| (Cle, true) -> ("ja", true)
282
| (Cgt, false) -> ("ja", false)
283
| (Cgt, true) -> ("jbe", false)
284
| (Cge, false) -> ("jae", true)
285
| (Cge, true) -> ("jb", false) in
286
let branch_if_not_comparable =
287
if cmp = Cne then not neg else neg in
289
if branch_if_not_comparable then begin
290
` jp {emit_label lbl}\n`;
291
` {emit_string branch_opcode} {emit_label lbl}\n`
267
(* Effect of comisd on flags and conditional branches:
268
ZF PF CF cond. branches taken
269
unordered 1 1 1 je, jb, jbe, jp
272
= 1 0 0 je, jae, jbe.
273
If FP traps are on (they are off by default),
274
comisd traps on QNaN and SNaN but ucomisd traps on SNaN only.
276
match (cmp, neg) with
277
| (Ceq, false) | (Cne, true) ->
293
278
let next = new_label() in
294
` jp {emit_label next}\n`;
295
` {emit_string branch_opcode} {emit_label lbl}\n`;
279
` ucomisd {emit_reg arg.(0)}, {emit_reg arg.(1)}\n`;
280
` jp {emit_label next}\n`; (* skip if unordered *)
281
` je {emit_label lbl}\n`; (* branch taken if x=y *)
296
282
`{emit_label next}:\n`
299
` {emit_string branch_opcode} {emit_label lbl}\n`
283
| (Cne, false) | (Ceq, true) ->
284
` ucomisd {emit_reg arg.(0)}, {emit_reg arg.(1)}\n`;
285
` jp {emit_label lbl}\n`; (* branch taken if unordered *)
286
` jne {emit_label lbl}\n` (* branch taken if x<y or x>y *)
288
` comisd {emit_reg arg.(1)}, {emit_reg arg.(0)}\n`; (* swap compare *)
290
` ja {emit_label lbl}\n` (* branch taken if y>x i.e. x<y *)
292
` jbe {emit_label lbl}\n` (* taken if unordered or y<=x i.e. !(x<y) *)
294
` comisd {emit_reg arg.(1)}, {emit_reg arg.(0)}\n`; (* swap compare *)
296
` jae {emit_label lbl}\n` (* branch taken if y>=x i.e. x<=y *)
298
` jb {emit_label lbl}\n` (* taken if unordered or y<x i.e. !(x<=y) *)
300
` comisd {emit_reg arg.(0)}, {emit_reg arg.(1)}\n`;
302
` ja {emit_label lbl}\n` (* branch taken if x>y *)
304
` jbe {emit_label lbl}\n` (* taken if unordered or x<=y i.e. !(x>y) *)
306
` comisd {emit_reg arg.(0)}, {emit_reg arg.(1)}\n`; (* swap compare *)
308
` jae {emit_label lbl}\n` (* branch taken if x>=y *)
310
` jb {emit_label lbl}\n` (* taken if unordered or x<y i.e. !(x>=y) *)
302
312
(* Deallocate the stack frame before a return or tail call *)