diff --git a/libevm/VM.h b/libevm/VM.h index ce8001bbf..eed1988bb 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -261,6 +261,7 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con case Instruction::OR: case Instruction::XOR: case Instruction::BYTE: + case Instruction::SIGNEXTEND: case Instruction::JUMPI: require(2); break; @@ -420,6 +421,19 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con m_stack.pop_back(); m_stack.pop_back(); break; + case Instruction::SIGNEXTEND: + if (m_stack.back() < 31) + { + unsigned const testBit(m_stack.back() * 8 + 7); + u256& number = m_stack[m_stack.size() - 2]; + u256 mask = ((u256(1) << testBit) - 1); + if (boost::multiprecision::bit_test(number, testBit)) + number |= ~mask; + else + number &= mask; + } + m_stack.pop_back(); + break; case Instruction::SHA3: { unsigned inOff = (unsigned)m_stack.back(); diff --git a/libevmface/Instruction.cpp b/libevmface/Instruction.cpp index 7b253f388..238b21512 100644 --- a/libevmface/Instruction.cpp +++ b/libevmface/Instruction.cpp @@ -52,6 +52,7 @@ const std::map dev::eth::c_instructions = { "BYTE", Instruction::BYTE }, { "ADDMOD", Instruction::ADDMOD }, { "MULMOD", Instruction::MULMOD }, + { "SIGNEXTEND", Instruction::SIGNEXTEND }, { "SHA3", Instruction::SHA3 }, { "ADDRESS", Instruction::ADDRESS }, { "BALANCE", Instruction::BALANCE }, @@ -179,6 +180,7 @@ static const std::map c_instructionInfo = { Instruction::BYTE, { "BYTE", 0, 2, 1 } }, { Instruction::ADDMOD, { "ADDMOD", 0, 3, 1 } }, { Instruction::MULMOD, { "MULMOD", 0, 3, 1 } }, + { Instruction::SIGNEXTEND, { "SIGNEXTEND", 0, 2, 1 } }, { Instruction::SHA3, { "SHA3", 0, 2, 1 } }, { Instruction::ADDRESS, { "ADDRESS", 0, 0, 1 } }, { Instruction::BALANCE, { "BALANCE", 0, 1, 1 } }, diff --git a/libevmface/Instruction.h b/libevmface/Instruction.h index b6aa477b1..ce587dfaf 100644 --- a/libevmface/Instruction.h +++ b/libevmface/Instruction.h @@ -58,6 +58,7 @@ enum class Instruction: uint8_t BYTE, ///< retrieve single byte from word ADDMOD, ///< unsigned modular addition MULMOD, ///< unsigned modular multiplication + SIGNEXTEND, ///< perform sign extension starting at given bit SHA3 = 0x20, ///< compute SHA3-256 hash ADDRESS = 0x30, ///< get address of currently executing account diff --git a/libserpent/opcodes.h b/libserpent/opcodes.h index 552364731..f02a5aa6d 100644 --- a/libserpent/opcodes.h +++ b/libserpent/opcodes.h @@ -42,8 +42,9 @@ Mapping mapping[] = { Mapping("XOR", 0x12, 2, 1), Mapping("BYTE", 0x13, 2, 1), Mapping("ADDMOD", 0x14, 3, 1), - Mapping("MULMOD", 0x15, 3, 1), - Mapping("SHA3", 0x20, 2, 1), + Mapping("MULMOD", 0x15, 3, 1), + Mapping("SIGNEXTEND", 0x16, 2, 1), + Mapping("SHA3", 0x20, 2, 1), Mapping("ADDRESS", 0x30, 0, 1), Mapping("BALANCE", 0x31, 1, 1), Mapping("ORIGIN", 0x32, 0, 1),