Commit 0176c94b authored by Kunshan Wang's avatar Kunshan Wang

Fixed, documented, tested tagref64.

Fixed some problem left in the operations for tagref64 which are caused
by porting from microvm-p2, the legacy Python-based Micro VM
implementation.

Added documentation and test cases for tagref64-related operations.
parent 6d42793c
...@@ -120,50 +120,119 @@ object OpHelper { ...@@ -120,50 +120,119 @@ object OpHelper {
} }
} }
/**
* Test if opnd, a tagref64 value, represents an integer.
*
* A tagref64 represents integer if it has the bit pattern ?111 1111 1111 ???? ???? ... ???? ???1,
* that is, a NaN with the lowest bit of the fraction being 1.
*/
def tr64IsInt(opnd: Long): Boolean = { def tr64IsInt(opnd: Long): Boolean = {
(opnd & 0x7ff0000000000001L) == 0x7ff0000000000001L (opnd & 0x7ff0000000000001L) == 0x7ff0000000000001L
} }
/**
* Test if opnd, a tagref64 value, represents an IEEE754 double-precision floating point number (double).
*
* A tagref64 represents a double if it is neither a ref nor an integer.
*/
def tr64IsFP(opnd: Long): Boolean = { def tr64IsFP(opnd: Long): Boolean = {
(opnd & 0x7ff0000000000001L) != 0x7ff0000000000001L && !tr64IsInt(opnd) && !tr64IsRef(opnd)
(opnd & 0x7ff0000000000003L) != 0x7ff0000000000002L
} }
/**
* Test if opnd, a tagref64 value, represents a reference.
*
* A tagref64 represents a ref if the bit pattern is ?111 1111 1111 ???? ???? .... ???? ??10,
* that is, a NaN with the 2 lowest bits of the fraction being 10.
*/
def tr64IsRef(opnd: Long): Boolean = { def tr64IsRef(opnd: Long): Boolean = {
(opnd & 0x7ff0000000000003L) == 0x7ff0000000000002L (opnd & 0x7ff0000000000003L) == 0x7ff0000000000002L
} }
/**
* Converts a 52-bit integer into a tagref64.
*
* Int: abbb bbbb bbbb bbbb bbbb bbbb bbbb bbbb bbbb bbbb bbbb bbbb bbbb
*
* tagref64: a111 1111 1111 bbbb bbbb bbbb bbbb bbbb bbbb bbbb bbbb bbbb bbbb bbbb bbbb bbb1
*/
def intToTr64(opnd: Long): Long = { def intToTr64(opnd: Long): Long = {
(0x7ff0000000000001L | ((opnd & 0x7ffffffffffffL) << 1) | (0x7ff0000000000001L | ((opnd & 0x7ffffffffffffL) << 1) |
((opnd & 0x8000000000000L) << 12)) ((opnd & 0x8000000000000L) << 12))
} }
/**
* Converts a double into a tagref64
*
* If it is not a NaN, return as is; otherwise return one of the four "canonical" NaN values:
*
* s111 1111 1111 1q00 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0100
*
* where s (sign bit) and q (quiet/signalling) are preserved.
*/
def fpToTr64(opnd: Double): Long = { def fpToTr64(opnd: Double): Long = {
var bits = java.lang.Double.doubleToRawLongBits(opnd) val doubleBits = java.lang.Double.doubleToRawLongBits(opnd)
if (java.lang.Double.isNaN(opnd)) { val resultBits = if (java.lang.Double.isNaN(opnd)) {
bits = bits & 0xfff8000000000000L | 0x0000000000000008L doubleBits & 0xfff8000000000000L | 0x0000000000000008L
} else {
doubleBits
} }
bits resultBits
} }
/**
* Converts a ref and a tag into a tagref64.
*
* NOTE: All objects are 8-byte aligned. The current Mu spec's design only
* allows 48-bit effective address. which x86_64 currently implements.
*
* ref: ssss ssss ssss ssss srrr rrrr rrrr rrrr rrrr rrrr rrrr rrrr rrrr rrrr rrrr r000
* where s is either 1 or 0
*
* tag: aaaaab
*
* tagref64: s111 1111 1111 aaaa arrr rrrr rrrr rrrr rrrr rrrr rrrr rrrr rrrr rrrr rrrr rb10
*/
def refToTr64(opnd: Long, tag: Long): Long = { def refToTr64(opnd: Long, tag: Long): Long = {
(0x7ff0000000000002L | (opnd & 0x7ffffffffff8L) | ((opnd & 0x800000000000L) << 16) | (0x7ff0000000000002L | (opnd & 0x7ffffffffff8L) | ((opnd & 0x800000000000L) << 16) |
((tag & 0x3eL) << 46) | ((tag & 0x3eL) << 46) |
((tag & 0x1) << 2)) ((tag & 0x1) << 2))
} }
/**
* Assume the tagref64 opnd represents an integer, and extract that integer.
*/
def tr64ToInt(opnd: Long): Long = { def tr64ToInt(opnd: Long): Long = {
(((opnd & 0xffffffffffffeL) >> 1) | ((opnd & 0x8000000000000000L) >> 12) & (1L << 51)) (((opnd & 0xffffffffffffeL) >>> 1) |
((opnd & 0x8000000000000000L) >>> 12))
} }
/**
* Assume the tagref64 opnd represents a double, and extract that double.
*
* Non-NaN doubles are represented as is. NaNs are canonicalized, but are still NaNs.
*/
def tr64ToFP(opnd: Long): Double = java.lang.Double.longBitsToDouble(opnd) def tr64ToFP(opnd: Long): Double = java.lang.Double.longBitsToDouble(opnd)
/**
* Assume the tagref64 opnd represents a ref and a tag, and extract the ref.
*
* tagref64: s??? ???? ???? ???? ?rrr rrrr rrrr rrrr rrrr rrrr rrrr rrrr rrrr rrrr rrrr r???
*
* ref: ssss ssss ssss ssss srrr rrrr rrrr rrrr rrrr rrrr rrrr rrrr rrrr rrrr rrrr r000
*/
def tr64ToRef(opnd: Long): Long = { def tr64ToRef(opnd: Long): Long = {
((opnd & 0x7ffffffffff8L) | ((opnd & 0x7ffffffffff8L) |
(((~(((opnd & 0x8000000000000000L) << 1) - 1)) >> 17) & ((opnd & 0x8000000000000000L) >> 16))
0xffff800000000000L))
} }
/**
* Assume the tagref64 opnd represents a ref and a tag, and extract the tag.
*
* tagref64: ???? ???? ???? aaaa a??? ???? ???? ???? ???? ???? ???? ???? ???? ???? ???? ?b??
*
* tag: aaaaab
*/
def tr64ToTag(opnd: Long): Long = { def tr64ToTag(opnd: Long): Long = {
(((opnd & 0x000f800000000000L) >> 46) | ((opnd & 0x4) >> 2)) (((opnd & 0x000f800000000000L) >> 46) | ((opnd & 0x4) >> 2))
} }
......
package uvm.refimpl.itpr
import java.lang.Double.{ doubleToRawLongBits, isNaN, longBitsToDouble }
import org.scalatest._
import uvm.UvmTestBase
import uvm.refimpl.itpr._
class UvmTagRef64OperationSpec extends UvmTestBase {
behavior of "TagRef64 operations"
it should "treat a NaN with suffix 1 as an integer." in {
OpHelper.tr64IsInt(0x7ff0000000000001L) shouldBe true
OpHelper.tr64IsInt(0xfff0000000000001L) shouldBe true
OpHelper.tr64IsInt(0xffffffffffffffffL) shouldBe true
}
it should "treat a NaN with suffix 10 as a double." in {
OpHelper.tr64IsRef(0x7ff0000000000002L) shouldBe true
OpHelper.tr64IsRef(0xfff0000000000002L) shouldBe true
OpHelper.tr64IsRef(0xfffffffffffffffeL) shouldBe true
}
it should "treat other bit patterns as double" in {
OpHelper.tr64IsFP(0x0L) shouldBe true
OpHelper.tr64IsFP(0x123456789abcdef0L) shouldBe true
OpHelper.tr64IsFP(0x7ff123456789abccL) shouldBe true
OpHelper.tr64IsFP(0xfffffffffffffffcL) shouldBe true
OpHelper.tr64IsFP(doubleToRawLongBits(3.1415927)) shouldBe true
}
it should "encode integers" in {
OpHelper.intToTr64(0x0000000000000L) shouldBe 0x7ff0000000000001L
OpHelper.intToTr64(0xfffffffffffffL) shouldBe 0xffffffffffffffffL
OpHelper.intToTr64(0x5555555555555L) shouldBe 0x7ffaaaaaaaaaaaabL
OpHelper.intToTr64(0xaaaaaaaaaaaaaL) shouldBe 0xfff5555555555555L
}
it should "encode double" in {
OpHelper.fpToTr64(3.14) shouldBe java.lang.Double.doubleToRawLongBits(3.14)
OpHelper.fpToTr64(-3.14) shouldBe java.lang.Double.doubleToRawLongBits(-3.14)
OpHelper.fpToTr64(java.lang.Double.POSITIVE_INFINITY) shouldBe 0x7ff0000000000000L
OpHelper.fpToTr64(longBitsToDouble(0x7ff123456789abcdL)) shouldBe 0x7ff0000000000008L
isNaN(longBitsToDouble(OpHelper.fpToTr64(longBitsToDouble(0x7ff123456789abcdL)))) shouldBe true
}
it should "encode ref and tag" in {
OpHelper.refToTr64(0x000000000000L, 0x00L) shouldBe 0x7ff0000000000002L
OpHelper.refToTr64(0x7ffffffffff8L, 0x00L) shouldBe 0x7ff07ffffffffffaL
OpHelper.refToTr64(0xfffffffffffffff8L, 0x00L) shouldBe 0xfff07ffffffffffaL
OpHelper.refToTr64(0x000000000000L, 0x3fL) shouldBe 0x7fff800000000006L
}
it should "decode integer" in {
OpHelper.tr64ToInt(0x7ff0000000000001L) shouldBe 0
OpHelper.tr64ToInt(0xfff0000000000001L) shouldBe 0x8000000000000L
OpHelper.tr64ToInt(0xfff5555555555555L) shouldBe 0xaaaaaaaaaaaaaL
OpHelper.tr64ToInt(0x7ffaaaaaaaaaaaabL) shouldBe 0x5555555555555L
}
it should "decode double" in {
OpHelper.tr64ToFP(0x0000000000000000L) shouldBe +0.0
OpHelper.tr64ToFP(0x8000000000000000L) shouldBe -0.0
OpHelper.tr64ToFP(0x3ff0000000000000L) shouldBe 1.0
isNaN(OpHelper.tr64ToFP(0x7ff0000000000008L)) shouldBe true
}
it should "decodde ref and tag" in {
OpHelper.tr64ToRef(0x7ff0555555555552L) shouldBe 0x555555555550L
OpHelper.tr64ToRef(0xfff02aaaaaaaaaaaL) shouldBe 0xffffaaaaaaaaaaa8L
OpHelper.tr64ToTag(0x7ff0555555555552L) shouldBe 0
OpHelper.tr64ToTag(0x7fff800000000006L) shouldBe 0x3f
OpHelper.tr64ToTag(0x7ffa800000000002L) shouldBe 0x2a
OpHelper.tr64ToTag(0x7ff5000000000006L) shouldBe 0x15
}
}
\ 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