constantine/research/codegen/x86.nim

96 lines
3.1 KiB
Nim

# Constantine
# Copyright (c) 2018-2019 Status Research & Development GmbH
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
./bindings/c_abi,
./llvm, ./ir,
./x86_inlineasm,
../primitives
export x86_inlineasm
# ############################################################
#
# x86 API
#
# ############################################################
proc defMulExt*(asy: Assembler_LLVM, wordSize: int): FnDef =
let procName = if wordSize == 64: cstring"hw_mulExt64"
else: cstring"hw_mulExt32"
let doublePrec_t = if wordSize == 64: asy.i128_t
else: asy.i64_t
let mulExtTy = if wordSize == 64: function_t(doublePrec_t, [asy.i64_t, asy.i64_t])
else: function_t(doublePrec_t, [asy.i32_t, asy.i32_t])
let mulExtKernel = asy.module.addFunction(procName, mulExtTy)
let blck = asy.ctx.appendBasicBlock(mulExtKernel, "mulExtBody")
asy.builder.positionAtEnd(blck)
let bld = asy.builder
let a = bld.zext(mulExtKernel.getParam(0), doublePrec_t)
let b = bld.zext(mulExtKernel.getParam(1), doublePrec_t)
let r = bld.mul(a, b)
bld.ret r
return (mulExtTy, mulExtKernel)
proc defHi*(asy: Assembler_LLVM, wordSize: int): FnDef =
let procName = if wordSize == 64: cstring"hw_hi64"
else: cstring"hw_hi32"
let doublePrec_t = if wordSize == 64: asy.i128_t
else: asy.i64_t
let singlePrec_t = if wordSize == 64: asy.i64_t
else: asy.i32_t
let hiTy = function_t(singlePrec_t, [doublePrec_t])
let hiKernel = asy.module.addFunction(procName, hiTy)
let blck = asy.ctx.appendBasicBlock(hiKernel, "hiBody")
asy.builder.positionAtEnd(blck)
let bld = asy.builder
# %1 = zext i32 64 to i128
let shift = bld.zext(constInt(asy.i32_t, culonglong wordSize, signExtend = LlvmBool(0)), doublePrec_t)
# %hiLarge = lshr i128 %input, %1
let hiLarge = bld.lshr(hiKernel.getParam(0), shift)
# %hi = trunc i128 %hiLarge to i64
let hi = bld.trunc(hiLarge, singlePrec_t)
bld.ret hi
return (hiTy, hiKernel)
proc defLo*(asy: Assembler_LLVM, wordSize: int): FnDef =
let procName = if wordSize == 64: cstring"hw_lo64"
else: cstring"hw_lo32"
let doublePrec_t = if wordSize == 64: asy.i128_t
else: asy.i64_t
let singlePrec_t = if wordSize == 64: asy.i64_t
else: asy.i32_t
let loTy = function_t(singlePrec_t, [doublePrec_t])
let loKernel = asy.module.addFunction(procName, loTy)
let blck = asy.ctx.appendBasicBlock(loKernel, "loBody")
asy.builder.positionAtEnd(blck)
let bld = asy.builder
# %lo = trunc i128 %input to i64
let lo = bld.trunc(loKernel.getParam(0), singlePrec_t)
bld.ret lo
return (loTy, loKernel)