96 lines
3.1 KiB
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)
|