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