GitLab will be upgraded on June 2nd 2020 at 2.00 pm (AEDT) to 3.00 pm (AEDT) due to Critical Security Patch Availability. During the update, GitLab and Mattermost services will not be available. If you have any concerns with this, please talk to local Gitlab admin team.

Commit 19a2f273 authored by Kunshan Wang's avatar Kunshan Wang

Support int<128>

parent edf705a1
......@@ -351,7 +351,12 @@ object MemoryOperations {
case 16 => memorySupport.loadShort(loc, !ptr)
case 32 => memorySupport.loadInt(loc, !ptr)
case 64 => memorySupport.loadLong(loc, !ptr)
case _ => throw new UnimplementedOprationException("Loading int of length %d is not supported".format(l))
case 128 => {
val lowWord = memorySupport.loadLong(loc, !ptr)
val highWord = memorySupport.loadLong(loc + 8, !ptr)
(BigInt(highWord) << 64) + lowWord
}
case _ => throw new UnimplementedOprationException("Loading int of length %d is not supported".format(l))
}
br.asInstanceOf[BoxInt].value = OpHelper.unprepare(bi, l)
case _: TypeFloat =>
......@@ -414,7 +419,11 @@ object MemoryOperations {
case 16 => memorySupport.storeShort(loc, bi.shortValue, !ptr)
case 32 => memorySupport.storeInt(loc, bi.intValue, !ptr)
case 64 => memorySupport.storeLong(loc, bi.longValue, !ptr)
case _ => throw new UnimplementedOprationException("Storing int of length %d is not supported".format(l))
case 128 => {
memorySupport.storeLong(loc, (bi & 0xffffffffffffffffL).longValue, !ptr)
memorySupport.storeLong(loc + 8, (bi >> 64).longValue, !ptr)
}
case _ => throw new UnimplementedOprationException("Storing int of length %d is not supported".format(l))
}
case _: TypeFloat =>
val fv = nvb.asInstanceOf[BoxFloat].value
......
package uvm.refimpl.itpr
import org.scalatest._
import ch.qos.logback.classic.Level._
import uvm._
import uvm.refimpl._
import uvm.refimpl.HowToResume.PassValues
import uvm.refimpl.TrapHandlerResult.Rebind
import uvm.refimpl.itpr._
import uvm.ssavariables.AtomicRMWOptr._
import uvm.ssavariables.MemoryOrder._
class UvmInterpreterInt128Test extends UvmBundleTesterBase {
setLogLevels(
ROOT_LOGGER_NAME -> INFO,
//"uvm.refimpl.mem.simpleimmix.SimpleImmixCollector$" -> DEBUG,
"uvm.refimpl.itpr" -> DEBUG)
override def makeMicroVM = MicroVM()
preloadBundles("tests/uvm-refimpl-test/primitives.uir",
"tests/uvm-refimpl-test/int128-test.uir")
"The constant pool" should "contain appropriate constant values" in {
val ctx = microVM.newContext()
def constInt(id: Int): MuIntValue = ctx.handleFromConst(id).asInstanceOf[MuIntValue]
def valueOfConstInt(id: Int): BigInt = ctx.handleToUInt(constInt(id))
valueOfConstInt("@I128_0") shouldEqual 0
valueOfConstInt("@I128_1") shouldEqual 1
valueOfConstInt("@I128_big") shouldEqual theBig
ctx.closeContext()
}
val mask128 = (BigInt(1)<<128) - 1
val theBig = BigInt("fedcba9876543210123456789abcdef0", 16)
val big0 = BigInt("fedcba98765432100123456789abcdef", 16)
val big1 = BigInt("123456789abcdef0fedcba9876543210", 16)
val big0n = big0 | ~mask128
"Binary operations" should "work on int<128>" in {
val ctx = microVM.newContext()
val func = ctx.handleFromFunc("@binops128")
val arg0 = ctx.handleFromInt(big0, 128)
val arg1 = ctx.handleFromInt(big1, 128)
testFunc(ctx, func, Seq(arg0, arg1)) { (ctx, th, st, wp) =>
val kas = ctx.dumpKeepalives(st, 0)
val Seq(add, sub, mul, udiv, sdiv, urem, srem, shl, lshr, ashr, and, or, xor) = kas
def valueOfInt(h: MuValue): BigInt = ctx.handleToInt(h.asInstanceOf[MuIntValue], false)
def to128(bi: BigInt): BigInt = bi & mask128
valueOfInt(add) shouldEqual to128(big0+big1)
valueOfInt(sub) shouldEqual to128(big0-big1)
valueOfInt(mul) shouldEqual to128(big0*big1)
valueOfInt(udiv) shouldEqual to128(big0/big1)
valueOfInt(sdiv) shouldEqual to128(big0n/big1)
valueOfInt(urem) shouldEqual to128(big0%big1)
valueOfInt(srem) shouldEqual to128(big0n%big1)
valueOfInt(shl) shouldEqual to128(big0<<(big1 % 128).toInt)
valueOfInt(lshr) shouldEqual to128(big0>>(big1 % 128).toInt)
valueOfInt(ashr) shouldEqual to128(big0n>>(big1 % 128).toInt)
valueOfInt(and) shouldEqual to128(big0 & big1)
valueOfInt(or) shouldEqual to128(big0 | big1)
valueOfInt(xor) shouldEqual to128(big0 ^ big1)
Rebind(st, PassValues(Seq()))
}
ctx.closeContext()
}
"Comparing operations" should "work on int<128>" in {
val ctx = microVM.newContext()
val func = ctx.handleFromFunc("@cmp128")
val arg0 = ctx.handleFromInt(big0, 128)
val arg1 = ctx.handleFromInt(big1, 128)
testFunc(ctx, func, Seq(arg0, arg1)) { (ctx, th, st, wp) =>
val kas = ctx.dumpKeepalives(st, 0)
val Seq(eq, ne, ult, ule, ugt, uge, slt, sle, sgt, sge) = kas
def valueOfBool(h: MuValue): Boolean = ctx.handleToInt(h.asInstanceOf[MuIntValue], false) != 0
valueOfBool(eq) shouldEqual (big0 == big1)
valueOfBool(ne) shouldEqual (big0 != big1)
valueOfBool(ult) shouldEqual (big0 < big1)
valueOfBool(ule) shouldEqual (big0 <= big1)
valueOfBool(ugt) shouldEqual (big0 > big1)
valueOfBool(uge) shouldEqual (big0 >= big1)
valueOfBool(slt) shouldEqual (big0n < big1)
valueOfBool(sle) shouldEqual (big0n <= big1)
valueOfBool(sgt) shouldEqual (big0n > big1)
valueOfBool(sge) shouldEqual (big0n >= big1)
Rebind(st, PassValues(Seq()))
}
ctx.closeContext()
}
"LOAD and STORE" should "work with int<128>" in {
val ctx = microVM.newContext()
val func = ctx.handleFromFunc("@memAccessing128")
testFunc(ctx, func, Seq()) { (ctx, th, st, wp) =>
val Seq(l0, l1) = ctx.dumpKeepalives(st, 0)
def valueOfInt(h: MuValue): BigInt = ctx.handleToInt(h.asInstanceOf[MuIntValue], false)
valueOfInt(l0) shouldEqual 0
valueOfInt(l1) shouldEqual theBig
Rebind(st, PassValues(Seq()))
}
ctx.closeContext()
}
"Object layout of int<128>" should "be as defined" in {
val ctx = microVM.newContext()
val hobj = ctx.newFixed("@sbig")
val hir = ctx.getIRef(hobj)
val hf0 = ctx.getFieldIRef(hir, 0)
val hf1 = ctx.getFieldIRef(hir, 1)
val hf2 = ctx.getFieldIRef(hir, 2)
val a0 = hf0.vb.asIRefAddr
val a1 = hf1.vb.asIRefAddr
val a2 = hf2.vb.asIRefAddr
(a1-a0) shouldBe 16
(a2-a0) shouldBe 32
val hbig0 = ctx.handleFromInt(big0, 128)
val hsmall0 = ctx.handleFromInt(0xff, 8)
ctx.store(NOT_ATOMIC, hf1, hbig0)
ctx.store(NOT_ATOMIC, hf0, hsmall0)
ctx.store(NOT_ATOMIC, hf2, hsmall0)
val hbig1 = ctx.load(NOT_ATOMIC, hf1).asInstanceOf[MuIntValue]
val hbig1v = ctx.handleToUInt(hbig1)
hbig1v shouldEqual big0
ctx.closeContext()
}
}
\ No newline at end of file
.typedef @i128 = int<128>
.const @I128_0 <@i128> = 0
.const @I128_1 <@i128> = 1
.const @I128_10 <@i128> = 10
.const @I128_big <@i128> = 0xfedcba9876543210123456789abcdef0
.funcsig @binops128_sig = (@i128 @i128) -> ()
.funcdef @binops128 VERSION %v1 <@binops128_sig> {
%entry(<@i128> %p0 <@i128> %p1):
%add = ADD <@i128> %p0 %p1
%sub = SUB <@i128> %p0 %p1
%mul = MUL <@i128> %p0 %p1
%udiv = UDIV <@i128> %p0 %p1
%sdiv = SDIV <@i128> %p0 %p1
%urem = UREM <@i128> %p0 %p1
%srem = SREM <@i128> %p0 %p1
%shl = SHL <@i128> %p0 %p1
%lshr = LSHR <@i128> %p0 %p1
%ashr = ASHR <@i128> %p0 %p1
%and = AND <@i128> %p0 %p1
%or = OR <@i128> %p0 %p1
%xor = XOR <@i128> %p0 %p1
[%trap] TRAP <> KEEPALIVE (
%add %sub %mul %udiv %sdiv %urem %srem
%shl %lshr %ashr %and %or %xor
)
COMMINST @uvm.thread_exit
}
.funcsig @cmp128_sig = (@i128 @i128) -> ()
.funcdef @cmp128 VERSION %v1 <@cmp128_sig> {
%entry(<@i128> %p0 <@i128> %p1):
%eq = EQ <@i128> %p0 %p1
%ne = NE <@i128> %p0 %p1
%ult = ULT <@i128> %p0 %p1
%ule = ULE <@i128> %p0 %p1
%ugt = UGT <@i128> %p0 %p1
%uge = UGE <@i128> %p0 %p1
%slt = SLT <@i128> %p0 %p1
%sle = SLE <@i128> %p0 %p1
%sgt = SGT <@i128> %p0 %p1
%sge = SGE <@i128> %p0 %p1
[%trap] TRAP <> KEEPALIVE (
%eq %ne %ult %ule %ugt %uge %slt %sle %sgt %sge
)
COMMINST @uvm.thread_exit
}
.global @g_i128 <@i128>
.funcdef @memAccessing128 VERSION %v1 <@v_v> {
%entry():
%l0 = LOAD <@i128> @g_i128
STORE <@i128> @g_i128 @I128_big
%l1 = LOAD <@i128> @g_i128
[%trap] TRAP <> KEEPALIVE (%l0 %l1)
COMMINST @uvm.thread_exit
}
.typedef @sbig = struct <@i8 @i128 @i8>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment