diff --git a/avm-transpiler/src/bit_traits.rs b/avm-transpiler/src/bit_traits.rs index 77a0b7eb2f6d..ff54ef23df5d 100644 --- a/avm-transpiler/src/bit_traits.rs +++ b/avm-transpiler/src/bit_traits.rs @@ -50,6 +50,12 @@ impl BitsQueryable for u128 { } } +impl BitsQueryable for usize { + fn num_bits(&self) -> usize { + get_msb(*self as u128) + } +} + pub fn bits_needed_for(val: &T) -> usize { let num_bits = val.num_bits(); if num_bits < 8 { diff --git a/avm-transpiler/src/opcodes.rs b/avm-transpiler/src/opcodes.rs index 86537a38c88f..94a52cf5d265 100644 --- a/avm-transpiler/src/opcodes.rs +++ b/avm-transpiler/src/opcodes.rs @@ -36,8 +36,8 @@ pub enum AvmOpcode { L2GASLEFT, DAGASLEFT, // Control flow - JUMP, - JUMPI, + JUMP_16, + JUMPI_16, INTERNALCALL, INTERNALRETURN, // Memory @@ -129,8 +129,8 @@ impl AvmOpcode { AvmOpcode::L2GASLEFT => "L2GASLEFT", AvmOpcode::DAGASLEFT => "DAGASLEFT", // Machine State - Internal Control Flow - AvmOpcode::JUMP => "JUMP", - AvmOpcode::JUMPI => "JUMPI", + AvmOpcode::JUMP_16 => "JUMP_16", + AvmOpcode::JUMPI_16 => "JUMPI_16", AvmOpcode::INTERNALCALL => "INTERNALCALL", AvmOpcode::INTERNALRETURN => "INTERNALRETURN", // Machine State - Memory diff --git a/avm-transpiler/src/transpile.rs b/avm-transpiler/src/transpile.rs index c4800a2c5522..25a64479120b 100644 --- a/avm-transpiler/src/transpile.rs +++ b/avm-transpiler/src/transpile.rs @@ -101,20 +101,17 @@ pub fn brillig_to_avm( BrilligOpcode::Jump { location } => { let avm_loc = brillig_pcs_to_avm_pcs[*location]; avm_instrs.push(AvmInstruction { - opcode: AvmOpcode::JUMP, - operands: vec![AvmOperand::U32 { value: avm_loc as u32 }], + opcode: AvmOpcode::JUMP_16, + operands: vec![make_operand(16, &avm_loc)], ..Default::default() }); } BrilligOpcode::JumpIf { condition, location } => { let avm_loc = brillig_pcs_to_avm_pcs[*location]; avm_instrs.push(AvmInstruction { - opcode: AvmOpcode::JUMPI, + opcode: AvmOpcode::JUMPI_16, indirect: Some(ALL_DIRECT), - operands: vec![ - AvmOperand::U32 { value: avm_loc as u32 }, - AvmOperand::U32 { value: condition.to_usize() as u32 }, - ], + operands: vec![make_operand(16, &avm_loc), make_operand(16, &condition.0)], ..Default::default() }); } diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp index 268c42e7e851..cc3d58323634 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp @@ -403,7 +403,6 @@ TEST_F(AvmExecutionTests, nestedInternalCalls) // 0 1 2 3 4 TEST_F(AvmExecutionTests, jumpAndCalldatacopy) { - GTEST_SKIP(); std::string bytecode_hex = to_hex(OpCode::SET_8) + // opcode SET "00" // Indirect flag "03" // U32 @@ -419,8 +418,8 @@ TEST_F(AvmExecutionTests, jumpAndCalldatacopy) "00000000" // cd_offset "00000001" // copy_size "0000000A" // dst_offset // M[10] = 13, M[11] = 156 - + to_hex(OpCode::JUMP) + // opcode JUMP - "00000005" // jmp_dest (FDIV located at 3) + + to_hex(OpCode::JUMP_16) + // opcode JUMP + "0005" // jmp_dest (FDIV located at 3) + to_hex(OpCode::SUB) + // opcode SUB "00" // Indirect flag "06" // FF @@ -456,14 +455,16 @@ TEST_F(AvmExecutionTests, jumpAndCalldatacopy) // JUMP EXPECT_THAT(instructions.at(3), - AllOf(Field(&Instruction::op_code, OpCode::JUMP), - Field(&Instruction::operands, ElementsAre(VariantWith(3))))); + AllOf(Field(&Instruction::op_code, OpCode::JUMP_16), + Field(&Instruction::operands, ElementsAre(VariantWith(5))))); std::vector returndata; auto trace = Execution::gen_trace(instructions, returndata, std::vector{ 13, 156 }, public_inputs_vec); // Expected sequence of PCs during execution - std::vector pc_sequence{ 0, 1, 3, 4 }; + std::vector pc_sequence{ + 0, 1, 2, 3, 4, 6, + }; for (size_t i = 0; i < 4; i++) { EXPECT_EQ(trace.at(i + 1).main_pc, pc_sequence.at(i)); @@ -492,61 +493,70 @@ TEST_F(AvmExecutionTests, jumpAndCalldatacopy) // We test this bytecode with two calldatacopy values: 9873123 and 0. TEST_F(AvmExecutionTests, jumpiAndCalldatacopy) { - GTEST_SKIP(); - std::string bytecode_hex = to_hex(OpCode::CALLDATACOPY) + // opcode CALLDATACOPY (no in tag) - "00" // Indirect flag - "00000000" // cd_offset - "00000001" // copy_size - "0000000A" // dst_offset 10 - + to_hex(OpCode::SET_16) + // opcode SET - "00" // Indirect flag - "02" // U16 - "0014" // val 20 - "0065" // dst_offset 101 - + to_hex(OpCode::JUMPI) + // opcode JUMPI - "00" // Indirect flag - "00000004" // jmp_dest (MUL located at 4) - "0000000A" // cond_offset 10 - + to_hex(OpCode::ADD) + // opcode ADD - "00" // Indirect flag - "02" // U16 - "00000065" // addr 101 - "00000065" // addr 101 - "00000065" // output addr 101 - + to_hex(OpCode::MUL) + // opcode MUL - "00" // Indirect flag - "02" // U16 - "00000065" // addr 101 - "00000065" // addr 101 - "00000066" // output of MUL addr 102 - + to_hex(OpCode::RETURN) + // opcode RETURN - "00" // Indirect flag - "00000000" // ret offset 0 - "00000000" // ret size 0 + std::string bytecode_hex = to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + "03" // U32 + "00" // val + "00" // dst_offset + + to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + "03" // U32 + "01" // val + "01" // dst_offset + + to_hex(OpCode::CALLDATACOPY) + // opcode CALLDATACOPY (no in tag) + "00" // Indirect flag + "00000000" // cd_offset + "00000001" // copy_size + "0000000A" // dst_offset 10 + + to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + "02" // U16 + "14" // val 20 + "65" // dst_offset 101 + + to_hex(OpCode::JUMPI_16) + // opcode JUMPI + "00" // Indirect flag + "0006" // jmp_dest (MUL located at 6) + "000A" // cond_offset 10 + + to_hex(OpCode::ADD) + // opcode ADD + "00" // Indirect flag + "02" // U16 + "00000065" // addr 101 + "00000065" // addr 101 + "00000065" // output addr 101 + + to_hex(OpCode::MUL) + // opcode MUL + "00" // Indirect flag + "02" // U16 + "00000065" // addr 101 + "00000065" // addr 101 + "00000066" // output of MUL addr 102 + + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "00000000" // ret offset 0 + "00000000" // ret size 0 ; auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse(bytecode); - ASSERT_THAT(instructions, SizeIs(6)); + ASSERT_THAT(instructions, SizeIs(8)); // We test parsing of JUMPI. // JUMPI EXPECT_THAT( - instructions.at(2), - AllOf(Field(&Instruction::op_code, OpCode::JUMPI), + instructions.at(4), + AllOf(Field(&Instruction::op_code, OpCode::JUMPI_16), Field(&Instruction::operands, - ElementsAre(VariantWith(0), VariantWith(4), VariantWith(10))))); + ElementsAre(VariantWith(0), VariantWith(6), VariantWith(10))))); - std::vector returndata{}; + std::vector returndata; auto trace_jump = Execution::gen_trace(instructions, returndata, std::vector{ 9873123 }, public_inputs_vec); auto trace_no_jump = Execution::gen_trace(instructions, returndata, std::vector{ 0 }, public_inputs_vec); // Expected sequence of PCs during execution with jump - std::vector pc_sequence_jump{ 0, 1, 2, 4, 5 }; + std::vector pc_sequence_jump{ 0, 1, 2, 3, 4, 6, 7 }; // Expected sequence of PCs during execution without jump - std::vector pc_sequence_no_jump{ 0, 1, 2, 3, 4, 5 }; + std::vector pc_sequence_no_jump{ 0, 1, 2, 3, 4, 5, 6, 7 }; for (size_t i = 0; i < 5; i++) { EXPECT_EQ(trace_jump.at(i + 1).main_pc, pc_sequence_jump.at(i)); @@ -556,22 +566,6 @@ TEST_F(AvmExecutionTests, jumpiAndCalldatacopy) EXPECT_EQ(trace_no_jump.at(i + 1).main_pc, pc_sequence_no_jump.at(i)); } - // JUMP CASE - // Find the first row enabling the MUL opcode - auto row = std::ranges::find_if(trace_jump.begin(), trace_jump.end(), [](Row r) { return r.main_sel_op_mul == 1; }); - EXPECT_EQ(row->main_ic, 400); // 400 = 20 * 20 - - // Find the first row enabling the addition selector. - row = std::ranges::find_if(trace_jump.begin(), trace_jump.end(), [](Row r) { return r.main_sel_op_add == 1; }); - // It must have failed as addition was "jumped over". - EXPECT_EQ(row, trace_jump.end()); - - // NO JUMP CASE - // Find the first row enabling the MUL opcode - row = - std::ranges::find_if(trace_no_jump.begin(), trace_no_jump.end(), [](Row r) { return r.main_sel_op_mul == 1; }); - EXPECT_EQ(row->main_ic, 1600); // 800 = (20 + 20) * (20 + 20) - // traces validation validate_trace(std::move(trace_jump), public_inputs, { 9873123 }); validate_trace(std::move(trace_no_jump), public_inputs, { 0 }); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/deserialization.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/deserialization.cpp index 799ce6219ae5..190a908adf0d 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/deserialization.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/deserialization.cpp @@ -81,8 +81,8 @@ const std::unordered_map> OPCODE_WIRE_FORMAT = { OpCode::DAGASLEFT, getter_format }, // Machine State - Internal Control Flow - { OpCode::JUMP, { OperandType::UINT32 } }, - { OpCode::JUMPI, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32 } }, + { OpCode::JUMP_16, { OperandType::UINT16 } }, + { OpCode::JUMPI_16, { OperandType::INDIRECT, OperandType::UINT16, OperandType::UINT16 } }, { OpCode::INTERNALCALL, { OperandType::UINT32 } }, { OpCode::INTERNALRETURN, {} }, diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp index 133e8484d088..892a414337c5 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp @@ -573,13 +573,13 @@ std::vector Execution::gen_trace(std::vector const& instructio break; // Machine State - Internal Control Flow - case OpCode::JUMP: - trace_builder.op_jump(std::get(inst.operands.at(0))); + case OpCode::JUMP_16: + trace_builder.op_jump(std::get(inst.operands.at(0))); break; - case OpCode::JUMPI: + case OpCode::JUMPI_16: trace_builder.op_jumpi(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2))); + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2))); break; case OpCode::INTERNALCALL: trace_builder.op_internal_call(std::get(inst.operands.at(0))); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/fixed_gas.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/fixed_gas.cpp index 76f472d64004..5f4cbed17cb1 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/fixed_gas.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/fixed_gas.cpp @@ -47,8 +47,8 @@ const std::unordered_map GAS_COST_TABLE = { { OpCode::CALLDATACOPY, make_cost(AVM_CALLDATACOPY_BASE_L2_GAS, 0, AVM_CALLDATACOPY_DYN_L2_GAS, 0) }, { OpCode::L2GASLEFT, make_cost(AVM_L2GASLEFT_BASE_L2_GAS, 0, AVM_L2GASLEFT_DYN_L2_GAS, 0) }, { OpCode::DAGASLEFT, make_cost(AVM_DAGASLEFT_BASE_L2_GAS, 0, AVM_DAGASLEFT_DYN_L2_GAS, 0) }, - { OpCode::JUMP, make_cost(AVM_JUMP_BASE_L2_GAS, 0, AVM_JUMP_DYN_L2_GAS, 0) }, - { OpCode::JUMPI, make_cost(AVM_JUMPI_BASE_L2_GAS, 0, AVM_JUMPI_DYN_L2_GAS, 0) }, + { OpCode::JUMP_16, make_cost(AVM_JUMP_BASE_L2_GAS, 0, AVM_JUMP_DYN_L2_GAS, 0) }, + { OpCode::JUMPI_16, make_cost(AVM_JUMPI_BASE_L2_GAS, 0, AVM_JUMPI_DYN_L2_GAS, 0) }, { OpCode::INTERNALCALL, make_cost(AVM_INTERNALCALL_BASE_L2_GAS, 0, AVM_INTERNALCALL_DYN_L2_GAS, 0) }, { OpCode::INTERNALRETURN, make_cost(AVM_INTERNALRETURN_BASE_L2_GAS, 0, AVM_INTERNALRETURN_DYN_L2_GAS, 0) }, { OpCode::SET_8, make_cost(AVM_SET_BASE_L2_GAS, 0, AVM_SET_DYN_L2_GAS, 0) }, diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/opcode.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/opcode.cpp index 5c9721a25ebc..2b310b5d5ea4 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/opcode.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/opcode.cpp @@ -93,10 +93,10 @@ std::string to_string(OpCode opcode) case OpCode::DAGASLEFT: return "DAGASLEFT"; // Machine State - Internal Control Flow - case OpCode::JUMP: - return "JUMP"; - case OpCode::JUMPI: - return "JUMPI"; + case OpCode::JUMP_16: + return "JUMP_16"; + case OpCode::JUMPI_16: + return "JUMPI_16"; case OpCode::INTERNALCALL: return "INTERNALCALL"; case OpCode::INTERNALRETURN: diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/opcode.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/opcode.hpp index 711376e6e09d..a4e8f0cc167f 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/opcode.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/opcode.hpp @@ -62,8 +62,8 @@ enum class OpCode : uint8_t { L2GASLEFT, DAGASLEFT, // Machine State - Internal Control Flow - JUMP, - JUMPI, + JUMP_16, + JUMPI_16, INTERNALCALL, INTERNALRETURN, // Machine State - Memory diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp index cc3a48260d9a..260dcaff259d 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp @@ -1563,7 +1563,7 @@ void AvmTraceBuilder::op_jump(uint32_t jmp_dest) auto clk = static_cast(main_trace.size()) + 1; // Constrain gas cost - gas_trace_builder.constrain_gas(clk, OpCode::JUMP); + gas_trace_builder.constrain_gas(clk, OpCode::JUMP_16); main_trace.push_back(Row{ .main_clk = clk, @@ -1612,7 +1612,7 @@ void AvmTraceBuilder::op_jumpi(uint8_t indirect, uint32_t jmp_dest, uint32_t con uint32_t next_pc = !id_zero ? jmp_dest : pc + 1; // Constrain gas cost - gas_trace_builder.constrain_gas(clk, OpCode::JUMPI); + gas_trace_builder.constrain_gas(clk, OpCode::JUMPI_16); main_trace.push_back(Row{ .main_clk = clk, diff --git a/yarn-project/simulator/src/avm/avm_gas.ts b/yarn-project/simulator/src/avm/avm_gas.ts index 598c5d58e65a..486e58d5a3ec 100644 --- a/yarn-project/simulator/src/avm/avm_gas.ts +++ b/yarn-project/simulator/src/avm/avm_gas.ts @@ -86,8 +86,8 @@ const BaseGasCosts: Record = { [Opcode.CALLDATACOPY]: makeCost(c.AVM_CALLDATACOPY_BASE_L2_GAS, 0), [Opcode.L2GASLEFT]: makeCost(c.AVM_L2GASLEFT_BASE_L2_GAS, 0), [Opcode.DAGASLEFT]: makeCost(c.AVM_DAGASLEFT_BASE_L2_GAS, 0), - [Opcode.JUMP]: makeCost(c.AVM_JUMP_BASE_L2_GAS, 0), - [Opcode.JUMPI]: makeCost(c.AVM_JUMPI_BASE_L2_GAS, 0), + [Opcode.JUMP_16]: makeCost(c.AVM_JUMP_BASE_L2_GAS, 0), + [Opcode.JUMPI_16]: makeCost(c.AVM_JUMPI_BASE_L2_GAS, 0), [Opcode.INTERNALCALL]: makeCost(c.AVM_INTERNALCALL_BASE_L2_GAS, 0), [Opcode.INTERNALRETURN]: makeCost(c.AVM_INTERNALRETURN_BASE_L2_GAS, 0), [Opcode.SET_8]: makeCost(c.AVM_SET_BASE_L2_GAS, 0), @@ -157,8 +157,8 @@ const DynamicGasCosts: Record = { [Opcode.CALLDATACOPY]: makeCost(c.AVM_CALLDATACOPY_DYN_L2_GAS, 0), [Opcode.L2GASLEFT]: makeCost(c.AVM_L2GASLEFT_DYN_L2_GAS, 0), [Opcode.DAGASLEFT]: makeCost(c.AVM_DAGASLEFT_DYN_L2_GAS, 0), - [Opcode.JUMP]: makeCost(c.AVM_JUMP_DYN_L2_GAS, 0), - [Opcode.JUMPI]: makeCost(c.AVM_JUMPI_DYN_L2_GAS, 0), + [Opcode.JUMP_16]: makeCost(c.AVM_JUMP_DYN_L2_GAS, 0), + [Opcode.JUMPI_16]: makeCost(c.AVM_JUMPI_DYN_L2_GAS, 0), [Opcode.INTERNALCALL]: makeCost(c.AVM_INTERNALCALL_DYN_L2_GAS, 0), [Opcode.INTERNALRETURN]: makeCost(c.AVM_INTERNALRETURN_DYN_L2_GAS, 0), [Opcode.SET_8]: makeCost(c.AVM_SET_DYN_L2_GAS, 0), diff --git a/yarn-project/simulator/src/avm/opcodes/control_flow.test.ts b/yarn-project/simulator/src/avm/opcodes/control_flow.test.ts index abd6ea2958f2..6c4996a488e1 100644 --- a/yarn-project/simulator/src/avm/opcodes/control_flow.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/control_flow.test.ts @@ -15,9 +15,9 @@ describe('Control Flow Opcodes', () => { it('Should (de)serialize correctly', () => { const buf = Buffer.from([ Jump.opcode, // opcode - ...Buffer.from('12345678', 'hex'), // loc + ...Buffer.from('1234', 'hex'), // loc ]); - const inst = new Jump(/*loc=*/ 0x12345678); + const inst = new Jump(/*loc=*/ 0x1234); expect(Jump.deserialize(buf)).toEqual(inst); expect(inst.serialize()).toEqual(buf); @@ -39,10 +39,10 @@ describe('Control Flow Opcodes', () => { const buf = Buffer.from([ JumpI.opcode, // opcode 0x01, // indirect - ...Buffer.from('12345678', 'hex'), // loc - ...Buffer.from('a2345678', 'hex'), // condOffset + ...Buffer.from('1234', 'hex'), // loc + ...Buffer.from('a234', 'hex'), // condOffset ]); - const inst = new JumpI(/*indirect=*/ 1, /*loc=*/ 0x12345678, /*condOffset=*/ 0xa2345678); + const inst = new JumpI(/*indirect=*/ 1, /*loc=*/ 0x1234, /*condOffset=*/ 0xa234); expect(JumpI.deserialize(buf)).toEqual(inst); expect(inst.serialize()).toEqual(buf); diff --git a/yarn-project/simulator/src/avm/opcodes/control_flow.ts b/yarn-project/simulator/src/avm/opcodes/control_flow.ts index 635430d6b836..e601bb3ad1a4 100644 --- a/yarn-project/simulator/src/avm/opcodes/control_flow.ts +++ b/yarn-project/simulator/src/avm/opcodes/control_flow.ts @@ -7,9 +7,9 @@ import { Instruction } from './instruction.js'; export class Jump extends Instruction { static type: string = 'JUMP'; - static readonly opcode: Opcode = Opcode.JUMP; + static readonly opcode: Opcode = Opcode.JUMP_16; // Informs (de)serialization. See Instruction.deserialize. - static readonly wireFormat: OperandType[] = [OperandType.UINT8, OperandType.UINT32]; + static readonly wireFormat: OperandType[] = [OperandType.UINT8, OperandType.UINT16]; constructor(private jumpOffset: number) { super(); @@ -26,14 +26,14 @@ export class Jump extends Instruction { export class JumpI extends Instruction { static type: string = 'JUMPI'; - static readonly opcode: Opcode = Opcode.JUMPI; + static readonly opcode: Opcode = Opcode.JUMPI_16; // Instruction wire format with opcode. static readonly wireFormat: OperandType[] = [ OperandType.UINT8, OperandType.UINT8, - OperandType.UINT32, - OperandType.UINT32, + OperandType.UINT16, + OperandType.UINT16, ]; constructor(private indirect: number, private loc: number, private condOffset: number) { diff --git a/yarn-project/simulator/src/avm/serialization/instruction_serialization.ts b/yarn-project/simulator/src/avm/serialization/instruction_serialization.ts index cdc1b463bbfa..81564454e4dd 100644 --- a/yarn-project/simulator/src/avm/serialization/instruction_serialization.ts +++ b/yarn-project/simulator/src/avm/serialization/instruction_serialization.ts @@ -40,8 +40,8 @@ export enum Opcode { L2GASLEFT, DAGASLEFT, // Control flow - JUMP, - JUMPI, + JUMP_16, + JUMPI_16, INTERNALCALL, INTERNALRETURN, // Memory