aboutsummaryrefslogtreecommitdiffstats
path: root/ia32/TargetPrinter.ml
diff options
context:
space:
mode:
Diffstat (limited to 'ia32/TargetPrinter.ml')
-rw-r--r--ia32/TargetPrinter.ml359
1 files changed, 286 insertions, 73 deletions
diff --git a/ia32/TargetPrinter.ml b/ia32/TargetPrinter.ml
index 18aacebf..a53a8fbd 100644
--- a/ia32/TargetPrinter.ml
+++ b/ia32/TargetPrinter.ml
@@ -348,7 +348,156 @@ module Target(System: SYSTEM):TARGET =
print_annot_stmt preg "%esp" oc txt targs args
end
- (* Handling of varargs *)
+ let print_annot_val oc txt args res =
+ fprintf oc "%s annotation: " comment;
+ print_annot_val preg oc txt args;
+ match args, res with
+ | [IR src], [IR dst] ->
+ if dst <> src then fprintf oc " movl %a, %a\n" ireg src ireg dst
+ | [FR src], [FR dst] ->
+ if dst <> src then fprintf oc " movapd %a, %a\n" freg src freg dst
+ | _, _ -> assert false
+
+(* Handling of memcpy *)
+
+(* Unaligned memory accesses are quite fast on IA32, so use large
+ memory accesses regardless of alignment. *)
+
+ let print_builtin_memcpy_small oc sz al src dst =
+ assert (src = EDX && dst = EAX);
+ let rec copy ofs sz =
+ if sz >= 8 && !Clflags.option_ffpu then begin
+ fprintf oc " movq %d(%a), %a\n" ofs ireg src freg XMM7;
+ fprintf oc " movq %a, %d(%a)\n" freg XMM7 ofs ireg dst;
+ copy (ofs + 8) (sz - 8)
+ end else if sz >= 4 then begin
+ fprintf oc " movl %d(%a), %a\n" ofs ireg src ireg ECX;
+ fprintf oc " movl %a, %d(%a)\n" ireg ECX ofs ireg dst;
+ copy (ofs + 4) (sz - 4)
+ end else if sz >= 2 then begin
+ fprintf oc " movw %d(%a), %a\n" ofs ireg src ireg16 ECX;
+ fprintf oc " movw %a, %d(%a)\n" ireg16 ECX ofs ireg dst;
+ copy (ofs + 2) (sz - 2)
+ end else if sz >= 1 then begin
+ fprintf oc " movb %d(%a), %a\n" ofs ireg src ireg8 ECX;
+ fprintf oc " movb %a, %d(%a)\n" ireg8 ECX ofs ireg dst;
+ copy (ofs + 1) (sz - 1)
+ end in
+ copy 0 sz
+
+ let print_builtin_memcpy_big oc sz al src dst =
+ assert (src = ESI && dst = EDI);
+ fprintf oc " movl $%d, %a\n" (sz / 4) ireg ECX;
+ fprintf oc " rep movsl\n";
+ if sz mod 4 >= 2 then fprintf oc " movsw\n";
+ if sz mod 2 >= 1 then fprintf oc " movsb\n"
+
+ let print_builtin_memcpy oc sz al args =
+ let (dst, src) =
+ match args with [IR d; IR s] -> (d, s) | _ -> assert false in
+ fprintf oc "%s begin builtin __builtin_memcpy_aligned, size = %d, alignment = %d\n"
+ comment sz al;
+ if sz <= 32
+ then print_builtin_memcpy_small oc sz al src dst
+ else print_builtin_memcpy_big oc sz al src dst;
+ fprintf oc "%s end builtin __builtin_memcpy_aligned\n" comment
+
+(* Handling of volatile reads and writes *)
+
+ let offset_addressing (Addrmode(base, ofs, cst)) delta =
+ Addrmode(base, ofs,
+ match cst with
+ | Coq_inl n -> Coq_inl(Integers.Int.add n delta)
+ | Coq_inr(id, n) -> Coq_inr(id, Integers.Int.add n delta))
+
+ let print_builtin_vload_common oc chunk addr res =
+ match chunk, res with
+ | Mint8unsigned, [IR res] ->
+ fprintf oc " movzbl %a, %a\n" addressing addr ireg res
+ | Mint8signed, [IR res] ->
+ fprintf oc " movsbl %a, %a\n" addressing addr ireg res
+ | Mint16unsigned, [IR res] ->
+ fprintf oc " movzwl %a, %a\n" addressing addr ireg res
+ | Mint16signed, [IR res] ->
+ fprintf oc " movswl %a, %a\n" addressing addr ireg res
+ | Mint32, [IR res] ->
+ fprintf oc " movl %a, %a\n" addressing addr ireg res
+ | Mint64, [IR res1; IR res2] ->
+ let addr' = offset_addressing addr (coqint_of_camlint 4l) in
+ if not (Asmgen.addressing_mentions addr res2) then begin
+ fprintf oc " movl %a, %a\n" addressing addr ireg res2;
+ fprintf oc " movl %a, %a\n" addressing addr' ireg res1
+ end else begin
+ fprintf oc " movl %a, %a\n" addressing addr' ireg res1;
+ fprintf oc " movl %a, %a\n" addressing addr ireg res2
+ end
+ | Mfloat32, [FR res] ->
+ fprintf oc " movss %a, %a\n" addressing addr freg res
+ | Mfloat64, [FR res] ->
+ fprintf oc " movsd %a, %a\n" addressing addr freg res
+ | _ ->
+ assert false
+
+ let print_builtin_vload oc chunk args res =
+ fprintf oc "%s begin builtin __builtin_volatile_read\n" comment;
+ begin match args with
+ | [IR addr] ->
+ print_builtin_vload_common oc chunk
+ (Addrmode(Some addr, None, Coq_inl Integers.Int.zero)) res
+ | _ ->
+ assert false
+ end;
+ fprintf oc "%s end builtin __builtin_volatile_read\n" comment
+
+ let print_builtin_vload_global oc chunk id ofs args res =
+ fprintf oc "%s begin builtin __builtin_volatile_read\n" comment;
+ print_builtin_vload_common oc chunk
+ (Addrmode(None, None, Coq_inr(id,ofs))) res;
+ fprintf oc "%s end builtin __builtin_volatile_read\n" comment
+
+ let print_builtin_vstore_common oc chunk addr src tmp =
+ match chunk, src with
+ | (Mint8signed | Mint8unsigned), [IR src] ->
+ if Asmgen.low_ireg src then
+ fprintf oc " movb %a, %a\n" ireg8 src addressing addr
+ else begin
+ fprintf oc " movl %a, %a\n" ireg src ireg tmp;
+ fprintf oc " movb %a, %a\n" ireg8 tmp addressing addr
+ end
+ | (Mint16signed | Mint16unsigned), [IR src] ->
+ fprintf oc " movw %a, %a\n" ireg16 src addressing addr
+ | Mint32, [IR src] ->
+ fprintf oc " movl %a, %a\n" ireg src addressing addr
+ | Mint64, [IR src1; IR src2] ->
+ let addr' = offset_addressing addr (coqint_of_camlint 4l) in
+ fprintf oc " movl %a, %a\n" ireg src2 addressing addr;
+ fprintf oc " movl %a, %a\n" ireg src1 addressing addr'
+ | Mfloat32, [FR src] ->
+ fprintf oc " movss %a, %a\n" freg src addressing addr
+ | Mfloat64, [FR src] ->
+ fprintf oc " movsd %a, %a\n" freg src addressing addr
+ | _ ->
+ assert false
+
+ let print_builtin_vstore oc chunk args =
+ fprintf oc "%s begin builtin __builtin_volatile_write\n" comment;
+ begin match args with
+ | IR addr :: src ->
+ print_builtin_vstore_common oc chunk
+ (Addrmode(Some addr, None, Coq_inl Integers.Int.zero)) src
+ (if addr = EAX then ECX else EAX)
+ | _ ->
+ assert false
+ end;
+ fprintf oc "%s end builtin __builtin_volatile_write\n" comment
+
+ let print_builtin_vstore_global oc chunk id ofs args =
+ fprintf oc "%s begin builtin __builtin_volatile_write\n" comment;
+ print_builtin_vstore_common oc chunk
+ (Addrmode(None, None, Coq_inr(id,ofs))) args EAX;
+ fprintf oc "%s end builtin __builtin_volatile_write\n" comment
+
+(* Handling of varargs *)
let print_builtin_va_start oc r =
if not (!current_function_sig).sig_cc.cc_vararg then
@@ -360,6 +509,117 @@ module Target(System: SYSTEM):TARGET =
fprintf oc " movl %%esp, 0(%a)\n" ireg r;
fprintf oc " addl $%ld, 0(%a)\n" ofs ireg r
+(* Handling of compiler-inlined builtins *)
+
+ let print_builtin_inline oc name args res =
+ fprintf oc "%s begin builtin %s\n" comment name;
+ begin match name, args, res with
+ (* Integer arithmetic *)
+ | ("__builtin_bswap"| "__builtin_bswap32"), [IR a1], [IR res] ->
+ if a1 <> res then
+ fprintf oc " movl %a, %a\n" ireg a1 ireg res;
+ fprintf oc " bswap %a\n" ireg res
+ | "__builtin_bswap16", [IR a1], [IR res] ->
+ if a1 <> res then
+ fprintf oc " movl %a, %a\n" ireg a1 ireg res;
+ fprintf oc " rolw $8, %a\n" ireg16 res
+ | "__builtin_clz", [IR a1], [IR res] ->
+ fprintf oc " bsrl %a, %a\n" ireg a1 ireg res;
+ fprintf oc " xorl $31, %a\n" ireg res
+ | "__builtin_ctz", [IR a1], [IR res] ->
+ fprintf oc " bsfl %a, %a\n" ireg a1 ireg res
+ (* Float arithmetic *)
+ | "__builtin_fabs", [FR a1], [FR res] ->
+ need_masks := true;
+ if a1 <> res then
+ fprintf oc " movapd %a, %a\n" freg a1 freg res;
+ fprintf oc " andpd %a, %a\n" raw_symbol "__absd_mask" freg res
+ | "__builtin_fsqrt", [FR a1], [FR res] ->
+ fprintf oc " sqrtsd %a, %a\n" freg a1 freg res
+ | "__builtin_fmax", [FR a1; FR a2], [FR res] ->
+ if res = a1 then
+ fprintf oc " maxsd %a, %a\n" freg a2 freg res
+ else if res = a2 then
+ fprintf oc " maxsd %a, %a\n" freg a1 freg res
+ else begin
+ fprintf oc " movapd %a, %a\n" freg a1 freg res;
+ fprintf oc " maxsd %a, %a\n" freg a2 freg res
+ end
+ | "__builtin_fmin", [FR a1; FR a2], [FR res] ->
+ if res = a1 then
+ fprintf oc " minsd %a, %a\n" freg a2 freg res
+ else if res = a2 then
+ fprintf oc " minsd %a, %a\n" freg a1 freg res
+ else begin
+ fprintf oc " movapd %a, %a\n" freg a1 freg res;
+ fprintf oc " minsd %a, %a\n" freg a2 freg res
+ end
+ | ("__builtin_fmadd"|"__builtin_fmsub"|"__builtin_fnmadd"|"__builtin_fnmsub"),
+ [FR a1; FR a2; FR a3], [FR res] ->
+ let opcode =
+ match name with
+ | "__builtin_fmadd" -> "vfmadd"
+ | "__builtin_fmsub" -> "vfmsub"
+ | "__builtin_fnmadd" -> "vfnmadd"
+ | "__builtin_fnmsub" -> "vfnmsub"
+ | _ -> assert false in
+ if res = a1 then
+ fprintf oc " %s132sd %a, %a, %a\n" opcode freg a2 freg a3 freg res
+ else if res = a2 then
+ fprintf oc " %s213sd %a, %a, %a\n" opcode freg a3 freg a1 freg res
+ else if res = a3 then
+ fprintf oc " %s231sd %a, %a, %a\n" opcode freg a1 freg a2 freg res
+ else begin
+ fprintf oc " movapd %a, %a\n" freg a3 freg res;
+ fprintf oc " %s231sd %a, %a, %a\n" opcode freg a1 freg a2 freg res
+ end
+ (* 64-bit integer arithmetic *)
+ | "__builtin_negl", [IR ah; IR al], [IR rh; IR rl] ->
+ assert (ah = EDX && al = EAX && rh = EDX && rl = EAX);
+ fprintf oc " negl %a\n" ireg EAX;
+ fprintf oc " adcl $0, %a\n" ireg EDX;
+ fprintf oc " negl %a\n" ireg EDX
+ | "__builtin_addl", [IR ah; IR al; IR bh; IR bl], [IR rh; IR rl] ->
+ assert (ah = EDX && al = EAX && bh = ECX && bl = EBX && rh = EDX && rl = EAX);
+ fprintf oc " addl %a, %a\n" ireg EBX ireg EAX;
+ fprintf oc " adcl %a, %a\n" ireg ECX ireg EDX
+ | "__builtin_subl", [IR ah; IR al; IR bh; IR bl], [IR rh; IR rl] ->
+ assert (ah = EDX && al = EAX && bh = ECX && bl = EBX && rh = EDX && rl = EAX);
+ fprintf oc " subl %a, %a\n" ireg EBX ireg EAX;
+ fprintf oc " sbbl %a, %a\n" ireg ECX ireg EDX
+ | "__builtin_mull", [IR a; IR b], [IR rh; IR rl] ->
+ assert (a = EAX && b = EDX && rh = EDX && rl = EAX);
+ fprintf oc " mull %a\n" ireg EDX
+ (* Memory accesses *)
+ | "__builtin_read16_reversed", [IR a1], [IR res] ->
+ fprintf oc " movzwl 0(%a), %a\n" ireg a1 ireg res;
+ fprintf oc " rolw $8, %a\n" ireg16 res
+ | "__builtin_read32_reversed", [IR a1], [IR res] ->
+ fprintf oc " movl 0(%a), %a\n" ireg a1 ireg res;
+ fprintf oc " bswap %a\n" ireg res
+ | "__builtin_write16_reversed", [IR a1; IR a2], _ ->
+ let tmp = if a1 = ECX then EDX else ECX in
+ if a2 <> tmp then
+ fprintf oc " movl %a, %a\n" ireg a2 ireg tmp;
+ fprintf oc " xchg %a, %a\n" ireg8 tmp high_ireg8 tmp;
+ fprintf oc " movw %a, 0(%a)\n" ireg16 tmp ireg a1
+ | "__builtin_write32_reversed", [IR a1; IR a2], _ ->
+ let tmp = if a1 = ECX then EDX else ECX in
+ if a2 <> tmp then
+ fprintf oc " movl %a, %a\n" ireg a2 ireg tmp;
+ fprintf oc " bswap %a\n" ireg tmp;
+ fprintf oc " movl %a, 0(%a)\n" ireg tmp ireg a1
+ (* Synchronization *)
+ | "__builtin_membar", [], _ ->
+ ()
+ (* Vararg stuff *)
+ | "__builtin_va_start", [IR a], _ ->
+ print_builtin_va_start oc a
+ (* Catch-all *)
+ | _ ->
+ invalid_arg ("unrecognized builtin " ^ name)
+ end;
+ fprintf oc "%s end builtin %s\n" comment name
(* Printing of instructions *)
@@ -581,83 +841,36 @@ module Target(System: SYSTEM):TARGET =
fprintf oc " ret\n"
end
(** Pseudo-instructions *)
- | Padcl_ir (n,res) ->
- fprintf oc " adcl $%ld, %a\n" (camlint_of_coqint n) ireg res;
- | Padcl_rr (a1,res) ->
- fprintf oc " adcl %a, %a\n" ireg a1 ireg res;
- | Paddl (a1,res) ->
- fprintf oc " addl %a, %a\n" ireg a1 ireg res;
- | Paddl_mi (addr,n) ->
- fprintf oc " addl $%ld, %a\n" (camlint_of_coqint n) addressing addr
- | Paddl_ri (res,n) ->
- fprintf oc " addl $%ld, %a\n" (camlint_of_coqint n) ireg res
- | Pbsfl (a1,res) ->
- fprintf oc " bsfl %a, %a\n" ireg a1 ireg res
- | Pbslr (a1,res) ->
- fprintf oc " bsrl %a, %a\n" ireg a1 ireg res
- | Pbswap res ->
- fprintf oc " bswap %a\n" ireg res
- | Pcfi_adjust sz ->
- cfi_adjust oc (camlint_of_coqint sz)
- | Pfmadd132 (a1,a2,res) ->
- fprintf oc " vfmadd132sd %a, %a, %a\n" freg a1 freg a2 freg res
- | Pfmadd213 (a1,a2,res) ->
- fprintf oc " vfmadd213sd %a, %a, %a\n" freg a1 freg a2 freg res
- | Pfmadd231 (a1,a2,res) ->
- fprintf oc " vfmadd231sd %a, %a, %a\n" freg a1 freg a2 freg res
- | Pfmsub132 (a1,a2,res) ->
- fprintf oc " vfmsub132sd %a, %a, %a\n" freg a1 freg a2 freg res
- | Pfmsub213 (a1,a2,res) ->
- fprintf oc " vfmsub213sd %a, %a, %a\n" freg a1 freg a2 freg res
- | Pfmsub231 (a1,a2,res) ->
- fprintf oc " vfmsub231sd %a, %a, %a\n" freg a1 freg a2 freg res
- | Pfnmadd132 (a1,a2,res) ->
- fprintf oc " vfnmadd132sd %a, %a, %a\n" freg a1 freg a2 freg res
- | Pfnmadd213 (a1,a2,res) ->
- fprintf oc " vfnmadd213sd %a, %a, %a\n" freg a1 freg a2 freg res
- | Pfnmadd231 (a1,a2,res) ->
- fprintf oc " vfnmadd231sd %a, %a, %a\n" freg a1 freg a2 freg res
- | Pfnmsub132 (a1,a2,res) ->
- fprintf oc " vfnmsub132sd %a, %a, %a\n" freg a1 freg a2 freg res
- | Pfnmsub213 (a1,a2,res) ->
- fprintf oc " vfnmsub213sd %a, %a, %a\n" freg a1 freg a2 freg res
- | Pfnmsub231 (a1,a2,res) ->
- fprintf oc " vfnmsub231sd %a, %a, %a\n" freg a1 freg a2 freg res
- | Pmaxsd (a1,res) ->
- fprintf oc " maxsd %a, %a\n" freg a1 freg res
- | Pminsd (a1,res) ->
- fprintf oc " minsd %a, %a\n" freg a1 freg res
- | Pmovb_rm (r1,a) ->
- fprintf oc " movb %a, %a\n" addressing a ireg8 r1
- | Pmovq_rm(rd, a) ->
- fprintf oc " movq %a, %a\n" addressing a freg rd
- | Pmovq_mr(a, r1) ->
- fprintf oc " movq %a, %a\n" freg r1 addressing a
- | Pmovsb ->
- fprintf oc " movsb\n";
- | Pmovsw ->
- fprintf oc " movsw\n";
- | Pmovw_rm (r1, a) ->
- fprintf oc " movw %a, %a\n" addressing a ireg16 r1
- | Prep_movsl ->
- fprintf oc " rep movsl\n"
- | Prolw_8 res ->
- fprintf oc " rolw $8, %a\n" ireg16 res
- | Psbbl (a1,res) ->
- fprintf oc " sbbl %a, %a\n" ireg a1 ireg res
- | Psqrtsd (a1,res) ->
- fprintf oc " sqrtsd %a, %a\n" freg a1 freg res
- | Psubl_ri (res,n) ->
- fprintf oc " subl $%ld, %a\n" (camlint_of_coqint n) ireg res;
- | Pxchg (a1,a2) ->
- fprintf oc " xchg %a, %a\n" ireg8 a1 high_ireg8 a2;
| Plabel(l) ->
fprintf oc "%a:\n" label (transl_label l)
- | Pallocframe(sz, ofs_ra, ofs_link)
+ | Pallocframe(sz, ofs_ra, ofs_link) ->
+ let sz = sp_adjustment sz in
+ let ofs_link = camlint_of_coqint ofs_link in
+ fprintf oc " subl $%ld, %%esp\n" sz;
+ cfi_adjust oc sz;
+ fprintf oc " leal %ld(%%esp), %%edx\n" (Int32.add sz 4l);
+ fprintf oc " movl %%edx, %ld(%%esp)\n" ofs_link;
+ current_function_stacksize := sz
| Pfreeframe(sz, ofs_ra, ofs_link) ->
- assert false
+ let sz = sp_adjustment sz in
+ fprintf oc " addl $%ld, %%esp\n" sz
| Pbuiltin(ef, args, res) ->
begin match ef with
+ | EF_builtin(name, sg) ->
+ print_builtin_inline oc (extern_atom name) args res
+ | EF_vload chunk ->
+ print_builtin_vload oc chunk args res
+ | EF_vstore chunk ->
+ print_builtin_vstore oc chunk args
+ | EF_vload_global(chunk, id, ofs) ->
+ print_builtin_vload_global oc chunk id ofs args res
+ | EF_vstore_global(chunk, id, ofs) ->
+ print_builtin_vstore_global oc chunk id ofs args
+ | EF_memcpy(sz, al) ->
+ print_builtin_memcpy oc (Int32.to_int (camlint_of_coqint sz))
+ (Int32.to_int (camlint_of_coqint al)) args
+ | EF_annot_val(txt, targ) ->
+ print_annot_val oc (extern_atom txt) args res
| EF_inline_asm(txt, sg, clob) ->
fprintf oc "%s begin inline assembly\n\t" comment;
print_inline_asm preg oc (extern_atom txt) sg args res;