(**************************************************************************) (* *) (* OCaml *) (* *) (* Fabrice Le Fessant, projet Gallium, INRIA Rocquencourt *) (* *) (* Copyright 1996 Institut National de Recherche en Informatique et *) (* en Automatique. *) (* *) (* All rights reserved. This file is distributed under the terms of *) (* the GNU Lesser General Public License version 2.1, with the *) (* special exception on linking described in the file LICENSE. *) (* *) (**************************************************************************) (** Helpers for Intel code generators *) (* The DSL* modules expose functions to emit x86/x86_64 instructions using a syntax close to AT&T (in particular, arguments are reversed compared to the official Intel syntax). Some notes: - Unary floating point instructions such as fadd/fmul/fstp/fld/etc. come with a single version supporting both the single and double precision instructions. (As with Intel syntax.) - A legacy bug in GAS: https://sourceware.org/binutils/docs-2.22/as/i386_002dBugs.html#i386_002dBugs is not replicated here. It is managed by X86_gas. *) open X86_ast open X86_proc let sym s = Sym s let nat n = Imm (Int64.of_nativeint n) let int n = Imm (Int64.of_int n) let const_32 n = Const (Int64.of_int32 n) let const_nat n = Const (Int64.of_nativeint n) let const n = Const (Int64.of_int n) let al = Reg8L RAX let ah = Reg8H AH let cl = Reg8L RCX let ax = Reg16 RAX let rax = Reg64 RAX let r10 = Reg64 R10 let r11 = Reg64 R11 let r13 = Reg64 R13 let r14 = Reg64 R14 let r15 = Reg64 R15 let rsp = Reg64 RSP let rbp = Reg64 RBP let xmm15 = Regf (XMM 15) let eax = Reg32 RAX let ebx = Reg32 RBX let ecx = Reg32 RCX let edx = Reg32 RDX let ebp = Reg32 RBP let esp = Reg32 RSP let st0 = Regf (ST 0) let st1 = Regf (ST 1) let mem32 typ ?(scale = 1) ?base ?sym displ idx = assert(scale >= 0); Mem {arch = X86; typ; idx; scale; base; sym; displ} let mem64 typ ?(scale = 1) ?base ?sym displ idx = assert(scale > 0); Mem {arch = X64; typ; idx; scale; base; sym; displ} let mem64_rip typ ?(ofs = 0) s = Mem64_RIP (typ, s, ofs) module D = struct let section segment flags args = directive (Section (segment, flags, args)) let align n = directive (Align (false, n)) let byte n = directive (Byte n) let bytes s = directive (Bytes s) let cfi_adjust_cfa_offset n = directive (Cfi_adjust_cfa_offset n) let cfi_endproc () = directive Cfi_endproc let cfi_startproc () = directive Cfi_startproc let comment s = directive (Comment s) let data () = section [ ".data" ] None [] let extrn s ptr = directive (External (s, ptr)) let file ~file_num ~file_name = directive (File (file_num, file_name)) let global s = directive (Global s) let indirect_symbol s = directive (Indirect_symbol s) let label ?(typ = NONE) s = directive (NewLabel (s, typ)) let loc ~file_num ~line ~col = directive (Loc (file_num, line, col)) let long cst = directive (Long cst) let mode386 () = directive Mode386 let model name = directive (Model name) let private_extern s = directive (Private_extern s) let qword cst = directive (Quad cst) let setvar (x, y) = directive (Set (x, y)) let size name cst = directive (Size (name, cst)) let space n = directive (Space n) let text () = section [ ".text" ] None [] let type_ name typ = directive (Type (name, typ)) let word cst = directive (Word cst) end module I = struct let add x y = emit (ADD (x, y)) let addsd x y = emit (ADDSD (x, y)) let and_ x y= emit (AND (x, y)) let andpd x y = emit (ANDPD (x, y)) let bswap x = emit (BSWAP x) let call x = emit (CALL x) let cdq () = emit CDQ let cmp x y = emit (CMP (x, y)) let comisd x y = emit (COMISD (x, y)) let cqo () = emit CQO let cvtsd2ss x y = emit (CVTSD2SS (x, y)) let cvtsi2sd x y = emit (CVTSI2SD (x, y)) let cvtss2sd x y = emit (CVTSS2SD (x, y)) let cvttsd2si x y = emit (CVTTSD2SI (x, y)) let dec x = emit (DEC x) let divsd x y = emit (DIVSD (x, y)) let fabs () = emit FABS let fadd x = emit (FADD x) let faddp x y = emit (FADDP (x, y)) let fchs () = emit FCHS let fcomp x = emit (FCOMP x) let fcompp () = emit FCOMPP let fcos () = emit FCOS let fdiv x = emit (FDIV x) let fdivp x y = emit (FDIVP (x, y)) let fdivr x = emit (FDIVR x) let fdivrp x y = emit (FDIVRP (x, y)) let fild x = emit (FILD x) let fistp x = emit (FISTP x) let fld x = emit (FLD x) let fld1 () = emit FLD1 let fldcw x = emit (FLDCW x) let fldlg2 () = emit FLDLG2 let fldln2 () = emit FLDLN2 let fldz () = emit FLDZ let fmul x = emit (FMUL x) let fmulp x y = emit (FMULP (x, y)) let fnstcw x = emit (FNSTCW x) let fnstsw x = emit (FNSTSW x) let fpatan () = emit FPATAN let fptan () = emit FPTAN let fsin () = emit FSIN let fsqrt () = emit FSQRT let fstp x = emit (FSTP x) let fsub x = emit (FSUB x) let fsubp x y = emit (FSUBP (x, y)) let fsubr x = emit (FSUBR x) let fsubrp x y = emit (FSUBRP (x, y)) let fxch x = emit (FXCH x) let fyl2x () = emit FYL2X let hlt () = emit HLT let idiv x = emit (IDIV x) let imul x y = emit (IMUL (x, y)) let inc x = emit (INC x) let j cond x = emit (J (cond, x)) let ja = j A let jae = j AE let jb = j B let jbe = j BE let je = j E let jg = j G let jmp x = emit (JMP x) let jne = j NE let jp = j P let lea x y = emit (LEA (x, y)) let mov x y = emit (MOV (x, y)) let movapd x y = emit (MOVAPD (x, y)) let movsd x y = emit (MOVSD (x, y)) let movss x y = emit (MOVSS (x, y)) let movsx x y = emit (MOVSX (x, y)) let movsxd x y = emit (MOVSXD (x, y)) let movzx x y = emit (MOVZX (x, y)) let mulsd x y = emit (MULSD (x, y)) let nop () = emit NOP let or_ x y = emit (OR (x, y)) let pop x = emit (POP x) let push x = emit (PUSH x) let ret () = emit RET let sal x y = emit (SAL (x, y)) let sar x y = emit (SAR (x, y)) let set cond x = emit (SET (cond, x)) let shr x y = emit (SHR (x, y)) let sqrtsd x y = emit (SQRTSD (x, y)) let sub x y = emit (SUB (x, y)) let subsd x y = emit (SUBSD (x, y)) let test x y= emit (TEST (x, y)) let ucomisd x y = emit (UCOMISD (x, y)) let xchg x y = emit (XCHG (x, y)) let xor x y= emit (XOR (x, y)) let xorpd x y = emit (XORPD (x, y)) end