GitLab will continue to be upgraded from 11.4.5-ce.0 on November 25th 2019 at 4.00pm (AEDT) to 5.00pm (AEDT) due to Critical Security Patch Availability. During the update, GitLab and Mattermost services will not be available.

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 {
}
}
/**
* 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 = {
(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 = {
(opnd & 0x7ff0000000000001L) != 0x7ff0000000000001L &&
(opnd & 0x7ff0000000000003L) != 0x7ff0000000000002L
!tr64IsInt(opnd) && !tr64IsRef(opnd)
}
/**
* 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 = {
(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 = {
(0x7ff0000000000001L | ((opnd & 0x7ffffffffffffL) << 1) |
((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 = {
var bits = java.lang.Double.doubleToRawLongBits(opnd)
if (java.lang.Double.isNaN(opnd)) {
bits = bits & 0xfff8000000000000L | 0x0000000000000008L
val doubleBits = java.lang.Double.doubleToRawLongBits(opnd)
val resultBits = if (java.lang.Double.isNaN(opnd)) {
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 = {
(0x7ff0000000000002L | (opnd & 0x7ffffffffff8L) | ((opnd & 0x800000000000L) << 16) |
((tag & 0x3eL) << 46) |
((tag & 0x1) << 2))
}
/**
* Assume the tagref64 opnd represents an integer, and extract that integer.
*/
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)
/**
* 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 = {
((opnd & 0x7ffffffffff8L) |
(((~(((opnd & 0x8000000000000000L) << 1) - 1)) >> 17) &
0xffff800000000000L))
((opnd & 0x8000000000000000L) >> 16))
}
/**
* 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 = {
(((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