From 5aeade32e2fda3a888e39fc471214559a4db0258 Mon Sep 17 00:00:00 2001 From: nicksavers Date: Thu, 6 Nov 2014 00:05:57 +0100 Subject: [PATCH] Add SIGNEXTEND op code --- .../main/java/org/ethereum/vm/DataWord.java | 11 ++- .../src/main/java/org/ethereum/vm/VM.java | 13 +++ .../java/org/ethereum/vm/DataWordTest.java | 82 +++++++++++++++++++ 3 files changed, 105 insertions(+), 1 deletion(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/vm/DataWord.java b/ethereumj-core/src/main/java/org/ethereum/vm/DataWord.java index 517caa12..acceac26 100644 --- a/ethereumj-core/src/main/java/org/ethereum/vm/DataWord.java +++ b/ethereumj-core/src/main/java/org/ethereum/vm/DataWord.java @@ -278,7 +278,7 @@ public class DataWord implements Comparable { return true; } - + @Override public int hashCode() { return java.util.Arrays.hashCode(data); @@ -293,4 +293,13 @@ public class DataWord implements Comparable { // Convert result into -1, 0 or 1 as is the convention return (int) Math.signum(result); } + + public void signExtend(byte k) { + if (k > 31) + throw new IndexOutOfBoundsException(); + byte mask = this.sValue().testBit((k * 8) + 7) ? (byte) 0xff : 0; + for (int i = 31; i > k; i--) { + this.data[31 - i] = mask; + } + } } \ No newline at end of file diff --git a/ethereumj-core/src/main/java/org/ethereum/vm/VM.java b/ethereumj-core/src/main/java/org/ethereum/vm/VM.java index f109c8b4..6389dc2b 100644 --- a/ethereumj-core/src/main/java/org/ethereum/vm/VM.java +++ b/ethereumj-core/src/main/java/org/ethereum/vm/VM.java @@ -280,6 +280,19 @@ public class VM { program.stackPush(word1); program.step(); } break; + case SIGNEXTEND: { + DataWord word1 = program.stackPop(); + BigInteger k = word1.value(); + + if (k.compareTo(_32_) < 0) { + DataWord word2 = program.stackPop(); + if (logger.isInfoEnabled()) + hint = word1 + " " + word2.value(); + word2.signExtend(k.byteValue()); + program.stackPush(word2); + } + program.step(); + } break; case NOT:{ DataWord word1 = program.stackPop(); word1.bnot(); diff --git a/ethereumj-core/src/test/java/org/ethereum/vm/DataWordTest.java b/ethereumj-core/src/test/java/org/ethereum/vm/DataWordTest.java index 0935cf06..5373a0b4 100644 --- a/ethereumj-core/src/test/java/org/ethereum/vm/DataWordTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/vm/DataWordTest.java @@ -134,6 +134,88 @@ public class DataWordTest { System.out.println(result2); } + @Test + public void testSignExtend1() { + + DataWord x = new DataWord(Hex.decode("f2")); + byte k = 0; + String expected = "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2"; + + x.signExtend(k); + System.out.println(x.toString()); + assertEquals(expected, x.toString()); + } + + @Test + public void testSignExtend2() { + DataWord x = new DataWord(Hex.decode("f2")); + byte k = 1; + String expected = "00000000000000000000000000000000000000000000000000000000000000f2"; + + x.signExtend(k); + System.out.println(x.toString()); + assertEquals(expected, x.toString()); + } + + @Test + public void testSignExtend3() { + + byte k = 1; + DataWord x = new DataWord(Hex.decode("0f00ab")); + String expected = "00000000000000000000000000000000000000000000000000000000000000ab"; + + x.signExtend(k); + System.out.println(x.toString()); + assertEquals(expected, x.toString()); + } + + @Test + public void testSignExtend4() { + + byte k = 1; + DataWord x = new DataWord(Hex.decode("ffff")); + String expected = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; + + x.signExtend(k); + System.out.println(x.toString()); + assertEquals(expected, x.toString()); + } + + @Test + public void testSignExtend5() { + + byte k = 3; + DataWord x = new DataWord(Hex.decode("ffffffff")); + String expected = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; + + x.signExtend(k); + System.out.println(x.toString()); + assertEquals(expected, x.toString()); + } + + @Test + public void testSignExtend6() { + + byte k = 3; + DataWord x = new DataWord(Hex.decode("ab02345678")); + String expected = "0000000000000000000000000000000000000000000000000000000002345678"; + + x.signExtend(k); + System.out.println(x.toString()); + assertEquals(expected, x.toString()); + } + + @Test + public void testSignExtend7() { + + byte k = 3; + DataWord x = new DataWord(Hex.decode("ab82345678")); + String expected = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffff82345678"; + + x.signExtend(k); + System.out.println(x.toString()); + assertEquals(expected, x.toString()); + } public static BigInteger pow(BigInteger x, BigInteger y) { if (y.compareTo(BigInteger.ZERO) < 0)