module Harpy.X86CodeGen(
X86_SSE_PFX,
x86_dword_size,
x86_qword_size,
x86_max_instruction_bytes,
x86_eax, x86_ecx, x86_edx, x86_ebx, x86_esp, x86_ebp, x86_esi, x86_edi,
x86_nobasereg,
x86_eax_mask, x86_ecx_mask, x86_edx_mask, x86_ebx_mask,
x86_esi_mask, x86_edi_mask, x86_ebp_mask,
x86_callee_regs, x86_caller_regs, x86_byte_regs,
x86_add, x86_or, x86_adc, x86_sbb, x86_and, x86_sub, x86_xor, x86_cmp,
x86_rol, x86_ror, x86_rcl, x86_rcr, x86_shl,
x86_shr, x86_sar, x86_shld, x86_shlr,
x86_fadd, x86_fmul, x86_fcom, x86_fcomp, x86_fsub, x86_fsubr,
x86_fdiv, x86_fdivr,
x86_fp_c0, x86_fp_c1, x86_fp_c2, x86_fp_c3, x86_fp_cc_mask,
x86_fpcw_invopex_mask, x86_fpcw_denopex_mask, x86_fpcw_zerodiv_mask,
x86_fpcw_ovfex_mask, x86_fpcw_undfex_mask, x86_fpcw_precex_mask,
x86_fpcw_precc_mask, x86_fpcw_roundc_mask,
x86_fpcw_prec_single, x86_fpcw_prec_double,
x86_fpcw_prec_extended,
x86_fpcw_round_nearest, x86_fpcw_round_down, x86_fpcw_round_up,
x86_fpcw_round_tozero,
x86_cc_eq, x86_cc_e, x86_cc_z,
x86_cc_ne, x86_cc_nz,
x86_cc_lt, x86_cc_b, x86_cc_c, x86_cc_nae, x86_cc_le, x86_cc_be,
x86_cc_na, x86_cc_gt, x86_cc_a, x86_cc_nbe, x86_cc_ge, x86_cc_ae,
x86_cc_nb, x86_cc_nc, x86_cc_lz, x86_cc_s, x86_cc_gez, x86_cc_ns,
x86_cc_p, x86_cc_np, x86_cc_pe, x86_cc_po, x86_cc_o, x86_cc_no,
x86_lock_prefix, x86_repnz_prefix, x86_repz_prefix, x86_rep_prefix,
x86_cs_prefix, x86_ss_prefix, x86_ds_prefix, x86_es_prefix,
x86_fs_prefix, x86_gs_prefix, x86_unlikely_prefix,
x86_likely_prefix, x86_operand_prefix, x86_address_prefix,
x86_is_scratch, x86_is_callee,
x86_imm_emit16, x86_imm_emit8, x86_imm_emit32,
x86_membase_emit, x86_alu_reg_imm,
x86_call_hs, x86_call_membase, x86_call_mem, x86_call_reg, x86_call_code,
x86_call_imm,
x86_prolog, x86_epilog, x86_enter, x86_leave,
x86_ret, x86_ret_imm,
x86_jecxz, x86_branch, x86_branch32, x86_branch8,
x86_jump_membase, x86_jump_mem, x86_jump_reg,
x86_jump32, x86_jump8,
x86_loopne, x86_loope, x86_loop,
x86_push_reg, x86_push_regp, x86_push_mem, x86_push_membase,
x86_push_imm, x86_push_imm_template, x86_push_memindex,
x86_pop_membase, x86_pop_mem, x86_pop_reg,
x86_popfd, x86_pushfd, x86_popad, x86_pushad,
x86_mov_reg_reg, x86_mov_reg_imm, x86_mov_mem_imm, x86_mov_membase_imm,
x86_mov_memindex_imm, x86_mov_mem_reg, x86_mov_reg_mem,
x86_mov_regp_reg, x86_mov_reg_regp, x86_mov_membase_reg,
x86_mov_reg_membase, x86_mov_memindex_reg, x86_mov_reg_memindex,
x86_xadd_reg_reg, x86_xadd_mem_reg, x86_xadd_membase_reg,
x86_inc_mem, x86_inc_membase, x86_inc_reg,
x86_dec_mem, x86_dec_membase, x86_dec_reg,
x86_not_mem, x86_not_membase, x86_not_reg,
x86_neg_mem, x86_neg_membase, x86_neg_reg,
x86_alu_mem_imm, x86_alu_membase_imm, x86_alu_membase8_imm,
x86_alu_mem_reg, x86_alu_membase_reg, x86_alu_reg_reg,
x86_alu_reg8_reg8, x86_alu_reg_mem, x86_alu_reg_membase,
x86_mul_reg, x86_mul_mem, x86_mul_membase,
x86_imul_reg_reg, x86_imul_reg_membase, x86_imul_reg_reg_imm,
x86_imul_reg_mem,
x86_imul_reg_mem_imm, x86_imul_reg_membase_imm,
x86_div_reg, x86_div_mem, x86_div_membase,
x86_test_reg_imm, x86_test_mem_imm, x86_test_membase_imm,
x86_test_reg_reg, x86_test_mem_reg, x86_test_membase_reg,
x86_cmpxchg_reg_reg, x86_cmpxchg_mem_reg, x86_cmpxchg_membase_reg,
x86_xchg_reg_reg, x86_xchg_mem_reg, x86_xchg_membase_reg,
x86_stosb, x86_stosl, x86_stosd, x86_movsb, x86_movsl, x86_movsd,
x86_shift_reg_imm, x86_shift_mem_imm, x86_shift_membase_imm,
x86_shift_reg, x86_shift_mem, x86_shift_membase,
x86_shrd_reg, x86_shrd_reg_imm, x86_shld_reg, x86_shld_reg_imm,
x86_cmov_membase, x86_cmov_mem, x86_cmov_reg,
x86_set_membase, x86_set_mem, x86_set_reg,
x86_lea_mem, x86_lea_membase, x86_lea_memindex,
x86_cdq,x86_widen_memindex, x86_widen_membase, x86_widen_mem,
x86_widen_reg,
x86_fp_op_mem, x86_fp_op_membase, x86_fp_op, x86_fp_op_reg,
x86_fp_int_op_membase, x86_fstp, x86_fcompp, x86_fucompp,
x86_fnstsw, x86_fnstcw, x86_fnstcw_membase,
x86_fldcw, x86_fldcw_membase, x86_fchs,
x86_frem, x86_fxch, x86_fcomi, x86_fcomip, x86_fucomi, x86_fucomip,
x86_fld, x86_fld_membase, x86_fld80_mem, x86_fld80_membase,
x86_fld_reg, x86_fldz, x86_fld1, x86_fldpi,
x86_fst, x86_fst_membase, x86_fst80_mem, x86_fst80_membase,
x86_fist_pop, x86_fist_pop_membase, x86_fstsw,
x86_fist_membase, x86_fild, x86_fild_membase,
x86_fsin, x86_fcos, x86_fabs, x86_ftst, x86_fxam, x86_fpatan,
x86_fprem, x86_fprem1, x86_frndint, x86_fsqrt, x86_fptan,
x86_sse_ps, x86_sse_pd, x86_sse_ss, x86_sse_sd,
x86_add_sse_reg_reg, x86_add_sse_reg_mem, x86_add_sse_reg_membase,
x86_sub_sse_reg_reg, x86_sub_sse_reg_mem, x86_sub_sse_reg_membase,
x86_mul_sse_reg_reg, x86_mul_sse_reg_mem, x86_mul_sse_reg_membase,
x86_div_sse_reg_reg, x86_div_sse_reg_mem, x86_div_sse_reg_membase,
x86_max_sse_reg_reg, x86_max_sse_reg_mem, x86_max_sse_reg_membase,
x86_min_sse_reg_reg, x86_min_sse_reg_mem, x86_min_sse_reg_membase,
x86_sqrt_sse_reg_reg, x86_sqrt_sse_reg_mem, x86_sqrt_sse_reg_membase,
x86_mov_sse_reg_reg, x86_mov_sse_reg_mem, x86_mov_sse_reg_membase, x86_mov_sse_mem_reg ,x86_mov_sse_membase_reg,
x86_ucomisd_reg_reg, x86_ucomisd_reg_mem, x86_ucomisd_reg_membase,
x86_ucomiss_reg_reg, x86_ucomiss_reg_mem, x86_ucomiss_reg_membase,
x86_comisd_reg_reg, x86_comisd_reg_mem, x86_comisd_reg_membase,
x86_comiss_reg_reg, x86_comiss_reg_mem, x86_comiss_reg_membase,
x86_sahf, x86_wait, x86_nop, x86_breakpoint, x86_rdtsc, x86_cld,
x86_prefix, x86_padding,
negateCC
) where
import qualified Text.PrettyPrint.HughesPJ as PP
import Data.Word
import Data.Bits
import Foreign.Ptr
import Harpy.CodeGenMonad
x86_max_instruction_bytes :: Int
x86_max_instruction_bytes = 16
x86_dword_size, x86_qword_size :: Int
x86_dword_size = 4
x86_qword_size = 8
x86_eax, x86_ecx, x86_edx, x86_ebx, x86_esp, x86_ebp, x86_esi,
x86_edi :: Word8
x86_eax = 0
x86_ecx = 1
x86_edx = 2
x86_ebx = 3
x86_esp = 4
x86_ebp = 5
x86_esi = 6
x86_edi = 7
x86_cmp, x86_or, x86_adc, x86_sbb, x86_and, x86_sub, x86_xor,
x86_add :: Word8
x86_add = 0
x86_or = 1
x86_adc = 2
x86_sbb = 3
x86_and = 4
x86_sub = 5
x86_xor = 6
x86_cmp = 7
x86_sar, x86_shld, x86_shlr, x86_rol, x86_ror, x86_rcl, x86_rcr,
x86_shl, x86_shr :: Word8
x86_shld = 0
x86_shlr = 1
x86_rol = 0
x86_ror = 1
x86_rcl = 2
x86_rcr = 3
x86_shl = 4
x86_shr = 5
x86_sar = 7
x86_fadd, x86_fmul, x86_fcom, x86_fcomp, x86_fsub, x86_fsubr :: Word8
x86_fdiv, x86_fdivr :: Word8
x86_fadd = 0
x86_fmul = 1
x86_fcom = 2
x86_fcomp = 3
x86_fsub = 4
x86_fsubr = 5
x86_fdiv = 6
x86_fdivr = 7
x86_cc_no, x86_cc_eq, x86_cc_e, x86_cc_z, x86_cc_ne, x86_cc_nz, x86_cc_lt :: Int
x86_cc_b, x86_cc_c, x86_cc_nae, x86_cc_le, x86_cc_be, x86_cc_na :: Int
x86_cc_gt :: Int
x86_cc_a, x86_cc_nbe, x86_cc_ge, x86_cc_ae, x86_cc_nb, x86_cc_nc :: Int
x86_cc_lz, x86_cc_s, x86_cc_gez, x86_cc_ns, x86_cc_p, x86_cc_pe :: Int
x86_cc_np, x86_cc_po, x86_cc_o :: Int
x86_cc_eq = 0
x86_cc_e = 0
x86_cc_z = 0
x86_cc_ne = 1
x86_cc_nz = 1
x86_cc_lt = 2
x86_cc_b = 2
x86_cc_c = 2
x86_cc_nae = 2
x86_cc_le = 3
x86_cc_be = 3
x86_cc_na = 3
x86_cc_gt = 4
x86_cc_a = 4
x86_cc_nbe = 4
x86_cc_ge = 5
x86_cc_ae = 5
x86_cc_nb = 5
x86_cc_nc = 5
x86_cc_lz = 6
x86_cc_s = 6
x86_cc_gez = 7
x86_cc_ns = 7
x86_cc_p = 8
x86_cc_pe = 8
x86_cc_np = 9
x86_cc_po = 9
x86_cc_o = 10
x86_cc_no = 11
x86_fp_c0, x86_fp_c1, x86_fp_c2, x86_fp_c3, x86_fp_cc_mask :: Word32
x86_fp_c0 = 0x100
x86_fp_c1 = 0x200
x86_fp_c2 = 0x400
x86_fp_c3 = 0x4000
x86_fp_cc_mask = 0x4500
x86_fpcw_invopex_mask, x86_fpcw_denopex_mask, x86_fpcw_zerodiv_mask,
x86_fpcw_ovfex_mask, x86_fpcw_undfex_mask, x86_fpcw_precex_mask,
x86_fpcw_precc_mask, x86_fpcw_roundc_mask :: Word32
x86_fpcw_invopex_mask = 0x1
x86_fpcw_denopex_mask = 0x2
x86_fpcw_zerodiv_mask = 0x4
x86_fpcw_ovfex_mask = 0x8
x86_fpcw_undfex_mask = 0x10
x86_fpcw_precex_mask = 0x20
x86_fpcw_precc_mask = 0x300
x86_fpcw_roundc_mask = 0xc00
x86_fpcw_prec_single, x86_fpcw_prec_double,
x86_fpcw_prec_extended :: Word32
x86_fpcw_prec_single = 0
x86_fpcw_prec_double = 0x200
x86_fpcw_prec_extended = 0x300
x86_fpcw_round_nearest, x86_fpcw_round_down, x86_fpcw_round_up,
x86_fpcw_round_tozero :: Word32
x86_fpcw_round_nearest = 0
x86_fpcw_round_down = 0x400
x86_fpcw_round_up = 0x800
x86_fpcw_round_tozero = 0xc00
x86_lock_prefix, x86_repnz_prefix, x86_repz_prefix, x86_rep_prefix,
x86_cs_prefix, x86_ss_prefix, x86_ds_prefix, x86_es_prefix,
x86_fs_prefix, x86_gs_prefix, x86_unlikely_prefix,
x86_likely_prefix, x86_operand_prefix, x86_address_prefix :: Word8
x86_lock_prefix = 0xf0
x86_repnz_prefix = 0xf2
x86_repz_prefix = 0xf3
x86_rep_prefix = 0xf3
x86_cs_prefix = 0x2e
x86_ss_prefix = 0x36
x86_ds_prefix = 0x3e
x86_es_prefix = 0x26
x86_fs_prefix = 0x64
x86_gs_prefix = 0x65
x86_unlikely_prefix = 0x2e
x86_likely_prefix = 0x3e
x86_operand_prefix = 0x66
x86_address_prefix = 0x67
x86_cc_unsigned_map :: [Word8]
x86_cc_unsigned_map = [
0x74,
0x75,
0x72,
0x76,
0x77,
0x73,
0x78,
0x79,
0x7a,
0x7b,
0x70,
0x71
]
x86_cc_signed_map :: [Word8]
x86_cc_signed_map = [
0x74,
0x75,
0x7c,
0x7e,
0x7f,
0x7d,
0x78,
0x79,
0x7a,
0x7b,
0x70,
0x71
]
x86_cc_negate :: [(Int, Int)]
x86_cc_negate = [
(x86_cc_eq, x86_cc_ne),
(x86_cc_ne, x86_cc_eq),
(x86_cc_lt, x86_cc_ge),
(x86_cc_le, x86_cc_gt),
(x86_cc_gt, x86_cc_le),
(x86_cc_ge, x86_cc_lt),
(x86_cc_lz, x86_cc_gez),
(x86_cc_gez, x86_cc_lz),
(x86_cc_p, x86_cc_np),
(x86_cc_np, x86_cc_p),
(x86_cc_o, x86_cc_no),
(x86_cc_no, x86_cc_o)
]
negateCC :: Int -> Int
negateCC cc =
case lookup cc x86_cc_negate of
Just cc' -> cc'
Nothing -> error ("unhandled case in negateCC" ++ show cc)
x86_nobasereg :: Word8
x86_nobasereg = (1)
x86_edi_mask, x86_esi_mask, x86_ebx_mask, x86_ebp_mask,
x86_eax_mask, x86_ecx_mask, x86_edx_mask:: Int
x86_esi_mask = (1 `shiftL` (fromIntegral x86_esi))
x86_edi_mask = (1 `shiftL` (fromIntegral x86_edi))
x86_ebx_mask = (1 `shiftL` (fromIntegral x86_ebx))
x86_ebp_mask = (1 `shiftL` (fromIntegral x86_ebp))
x86_eax_mask = (1 `shiftL` (fromIntegral x86_eax))
x86_ecx_mask = (1 `shiftL` (fromIntegral x86_ecx))
x86_edx_mask = (1 `shiftL` (fromIntegral x86_edx))
x86_callee_regs :: Int
x86_callee_regs = ((1 `shiftL` (fromIntegral x86_eax)) .|.
(1 `shiftL` (fromIntegral x86_ecx)) .|.
(1 `shiftL` (fromIntegral x86_edx)))
x86_caller_regs :: Int
x86_caller_regs = ((1 `shiftL` (fromIntegral x86_ebx)) .|.
(1 `shiftL` (fromIntegral x86_ebp)) .|.
(1 `shiftL` (fromIntegral x86_esi)) .|.
(1 `shiftL` (fromIntegral x86_edi)))
x86_byte_regs :: Int
x86_byte_regs = ((1 `shiftL` (fromIntegral x86_eax)) .|.
(1 `shiftL` (fromIntegral x86_ecx)) .|.
(1 `shiftL` (fromIntegral x86_edx)) .|.
(1 `shiftL` (fromIntegral x86_ebx)))
x86_is_scratch :: Int -> Bool
x86_is_scratch reg = (x86_caller_regs .&. (1 `shiftL` (reg))) /= 0
x86_is_callee :: Int -> Bool
x86_is_callee reg = (x86_callee_regs .&. (1 `shiftL` (reg))) /= 0
x86_is_byte_reg :: (Num a, Ord a) => a -> Bool
x86_is_byte_reg reg = ((reg) < 4)
x86_address_byte :: Word8 -> Word8 -> Word8 -> CodeGen e s ()
x86_address_byte m o r = emit8 ((((m) .&. 0x03) `shiftL` 6) .|.
(((o) .&. 0x07) `shiftL` 3) .|.
(((r) .&. 0x07)))
x86_imm_emit32 :: Word32 -> CodeGen e s ()
x86_imm_emit32 imm = emit32 imm
x86_imm_emit16 :: Word16 -> CodeGen e s ()
x86_imm_emit16 imm =
let b0 = (imm .&. 0xff)
b1 = ((imm `shiftR` 8) .&. 0xff)
in do emit8 (fromIntegral b0)
emit8 (fromIntegral b1)
x86_imm_emit8 :: Word8 -> CodeGen e s ()
x86_imm_emit8 imm =
emit8 (imm .&. 0xff)
x86_is_imm8 :: Integral a => a -> Bool
x86_is_imm8 imm = (((fromIntegral imm :: Integer) >= 128) && ((fromIntegral imm :: Integer) <= 127))
x86_reg_emit :: Word8 -> Word8 -> CodeGen e s ()
x86_reg_emit r regno = x86_address_byte 3 r regno
x86_reg8_emit :: Word8 -> Word8 -> Bool -> Bool -> CodeGen e s ()
x86_reg8_emit r regno is_rh is_rnoh =
x86_address_byte 3 (if is_rh then (r .|. 4) else r)
(if is_rnoh then regno .|. 4 else regno)
x86_regp_emit :: Word8 -> Word8 -> CodeGen e s ()
x86_regp_emit r regno = x86_address_byte 0 r regno
x86_mem_emit :: Word8 -> Word32 -> CodeGen e s ()
x86_mem_emit r disp = do x86_address_byte 0 r 5
x86_imm_emit32 disp
x86_membase_emit :: Word8 -> Word8 -> Word32 -> CodeGen e s ()
x86_membase_emit r basereg disp =
if basereg == x86_esp
then if disp == 0
then do x86_address_byte 0 r x86_esp
x86_address_byte 0 x86_esp x86_esp
else if x86_is_imm8 disp
then do x86_address_byte 1 r x86_esp
x86_address_byte 0 x86_esp x86_esp
x86_imm_emit8 (fromIntegral disp)
else do x86_address_byte 2 r x86_esp
x86_address_byte 0 x86_esp x86_esp
x86_imm_emit32 (fromIntegral disp)
else do if (disp == 0 && (toInteger basereg) /= (toInteger x86_ebp))
then x86_address_byte 0 r basereg
else if x86_is_imm8 (fromIntegral disp :: Word32)
then do x86_address_byte 1 r basereg
x86_imm_emit8 (fromIntegral disp)
else do x86_address_byte 2 r basereg
x86_imm_emit32 (fromIntegral disp)
x86_memindex_emit :: Word8 -> Word8 -> Word32 -> Word8 -> Word8 -> CodeGen e s ()
x86_memindex_emit r basereg disp indexreg shft =
if (basereg == x86_nobasereg)
then do x86_address_byte 0 r 4
x86_address_byte shft indexreg 5
x86_imm_emit32 disp
else if ((disp) == 0 && (basereg) /= x86_ebp)
then do x86_address_byte 0 r 4
x86_address_byte shft indexreg (fromIntegral basereg)
else if x86_is_imm8 disp
then do x86_address_byte 1 r 4
x86_address_byte shft indexreg
(fromIntegral basereg)
x86_imm_emit8 (fromIntegral disp)
else do x86_address_byte 2 r 4
x86_address_byte shft indexreg 5
x86_imm_emit32 disp
x86_breakpoint, x86_cld, x86_stosb, x86_stosl, x86_stosd, x86_movsb,
x86_movsl, x86_movsd :: CodeGen s e ()
x86_breakpoint = emit8 0xcc
x86_cld = emit8 0xfc
x86_stosb = emit8 0xaa
x86_stosl = emit8 0xab
x86_stosd = x86_stosl
x86_movsb = emit8 0xa4
x86_movsl = emit8 0xa5
x86_movsd = x86_movsl
x86_prefix :: Word8 -> CodeGen s e ()
x86_prefix p = emit8 p
x86_rdtsc :: CodeGen s e ()
x86_rdtsc = emit8 0x0f >> emit8 0x31
x86_cmpxchg_reg_reg :: Word8 -> Word8 -> CodeGen e s ()
x86_cmpxchg_reg_reg dreg reg =
emit8 0x0f >> emit8 0xb1 >> x86_reg_emit reg dreg
x86_cmpxchg_mem_reg :: Word32 -> Word8 -> CodeGen e s ()
x86_cmpxchg_mem_reg mem reg = emit8 0x0f >> emit8 0xb1 >> x86_mem_emit reg mem
x86_cmpxchg_membase_reg :: Word8 -> Word32 -> Word8 -> CodeGen e s ()
x86_cmpxchg_membase_reg basereg disp reg =
emit8 0x0f >> emit8 0xb1 >> x86_membase_emit reg basereg disp
x86_xchg :: Num a => a -> CodeGen e s ()
x86_xchg size = if size == 1 then emit8 0x86 else emit8 0x87
x86_xchg_reg_reg dreg reg size =
do x86_xchg size ; x86_reg_emit reg dreg
x86_xchg_mem_reg mem reg size =
do x86_xchg size ; x86_mem_emit reg mem
x86_xchg_membase_reg basereg disp reg size =
do x86_xchg size ; x86_membase_emit reg basereg disp
x86_xadd :: Num a => a -> CodeGen e s ()
x86_xadd size = do emit8 0x0f ; if size == 1 then emit8 0xc0 else emit8 0xc1
x86_xadd_reg_reg dreg reg size = x86_xadd size >> x86_reg_emit reg dreg
x86_xadd_mem_reg mem reg size = x86_xadd size >> x86_mem_emit reg mem
x86_xadd_membase_reg basereg disp reg size =
x86_xadd size >> x86_membase_emit reg basereg disp
x86_inc_mem mem = emit8 0xff >> x86_mem_emit 0 mem
x86_inc_membase basereg disp = emit8 0xff >> x86_membase_emit 0 basereg disp
x86_inc_reg reg = emit8 (0x40 + reg)
x86_dec_mem mem = emit8 0xff >> x86_mem_emit 1 mem
x86_dec_membase basereg disp = emit8 0xff >> x86_membase_emit 1 basereg disp
x86_dec_reg reg = emit8 (0x48 + reg)
x86_not_mem mem = emit8 0xf7 >> x86_mem_emit 2 mem
x86_not_membase basereg disp = emit8 0xf7 >> x86_membase_emit 2 basereg disp
x86_not_reg reg = emit8 0xf7 >> x86_reg_emit 2 reg
x86_neg_mem mem = emit8 0xf7 >> x86_mem_emit 3 mem
x86_neg_membase basereg disp = emit8 0xf7 >> x86_membase_emit 3 basereg disp
x86_neg_reg reg = emit8 0xf7 >> x86_reg_emit 3 reg
x86_nop :: CodeGen s e ()
x86_nop = emit8 0x90
x86_alu_reg_imm :: Word8 -> Word8 -> Int -> CodeGen e s ()
x86_alu_reg_imm opc reg imm =
do if reg == x86_eax
then emit8 (fromIntegral (((opc) `shiftL` 3) + 5)) >> x86_imm_emit32 (fromIntegral imm)
else if x86_is_imm8 imm
then do emit8 0x83
x86_reg_emit (fromIntegral opc) (fromIntegral reg)
x86_imm_emit8 (fromIntegral imm)
else do emit8 0x81
x86_reg_emit (fromIntegral opc) (fromIntegral reg)
x86_imm_emit32 (fromIntegral imm)
x86_alu_mem_imm opc mem imm =
if x86_is_imm8 imm
then do emit8 0x83
x86_mem_emit opc mem
x86_imm_emit8 (fromIntegral imm)
else do emit8 0x81
x86_mem_emit opc mem
x86_imm_emit32 imm
x86_alu_membase_imm opc basereg disp imm =
if x86_is_imm8 imm
then do emit8 0x83
x86_membase_emit opc basereg disp
x86_imm_emit8 (fromIntegral imm)
else do emit8 0x81
x86_membase_emit opc basereg disp
x86_imm_emit32 imm
x86_alu_membase8_imm opc basereg disp imm =
do emit8 0x80
x86_membase_emit opc basereg disp
x86_imm_emit8 imm
x86_alu_mem_reg opc mem reg =
do emit8 ((opc `shiftL` 3) + 1)
x86_mem_emit reg mem
x86_alu_membase_reg opc basereg disp reg =
do emit8 ((opc `shiftL` 3) + 1)
x86_membase_emit reg basereg disp
x86_alu_reg_reg opc dreg reg =
do emit8 ((opc `shiftL` 3) + 3)
x86_reg_emit dreg reg
<