<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE rfc SYSTEM "rfc2629.dtd" [
  <!ENTITY RFC2119 SYSTEM "https://www.rfc-editor.org/refs/bibxml/reference.RFC.2119.xml">
  <!ENTITY RFC8174 SYSTEM "https://www.rfc-editor.org/refs/bibxml/reference.RFC.8174.xml">
  <!ENTITY RFC8126 SYSTEM "https://www.rfc-editor.org/refs/bibxml/reference.RFC.8126.xml">
  <!ENTITY RFC8200 SYSTEM "https://www.rfc-editor.org/refs/bibxml/reference.RFC.8200.xml">
  <!ENTITY RFC9000 SYSTEM "https://www.rfc-editor.org/refs/bibxml/reference.RFC.9000.xml">
  <!ENTITY RFC9669 SYSTEM "https://www.rfc-editor.org/refs/bibxml/reference.RFC.9669.xml">
]>

<rfc docName="draft-bellis-unheaded-mbc-isa-00" category="exp" ipr="trust200902" submissionType="independent">
<front>
<title>MBC Instruction Set Architecture for the Unheaded Protocol Computer</title>

<author fullname="Stevie Bellis" initials="S." surname="Bellis">
  <organization>Unheaded</organization>
  <address>
    <postal>
      <country>US</country>
    </postal>
    <email>stevie@bellis.tech</email>
  </address>
</author>

<date year="2026" month="March" day="19"/>

<area>General</area>
<workgroup>Independent Submission</workgroup>

<keyword>MBC</keyword>
<keyword>bytecode</keyword>
<keyword>eBPF</keyword>
<keyword>ISA</keyword>
<keyword>Unheaded</keyword>
<keyword>XDP</keyword>

<abstract>
<t>This document defines the MBC (Monad Bytecode) Instruction Set Architecture for the Unheaded Protocol Computer (UPC). MBC is a 48-opcode, 32-bit fixed-width instruction set designed for execution within eBPF XDP programs. It provides computational capabilities for distributed packet processing using the Monad wire format, enabling deterministic network packet classification and transformation at the network edge.</t>
</abstract>

<note title="Status of This Memo">
<t>This document specifies an Experimental Internet Protocol for the Internet community.  This document is a product of the Independent Submission stream.  It represents the work and views of its author, who is responsible for its contents.  It does not represent a consensus view of the Internet community.  Readers interested in this topic should note that the content of this document may change based on deployment experience and feedback from the Internet at large.  Publication of this document does not imply adoption by the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts.  The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.</t>

<t>This Internet-Draft will expire on September 18, 2026.</t>
</note>

<note title="Copyright Notice">
<t>Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved.</t>

<t>This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info/) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and must provide the Revised BSD License, as described in Section 4.e of the Trust Legal Provisions (https://trustee.ietf.org/license-info/).</t>
</note>

</front>

<middle>

<section anchor="introduction" title="Introduction">
<t>The Unheaded Protocol Computer (UPC) is a computational engine embedded within eBPF XDP programs, executing at the network edge to provide deterministic packet processing for infrastructure automation. The MBC Instruction Set Architecture defines the low-level computation model for the UPC.</t>

<t>MBC is optimized for execution within eBPF verifier constraints—specifically the 256-instruction limit per eBPF program execution. This constraint drives several design decisions: fixed-width 32-bit instructions for efficient decoding, a compact 16-register set for minimal memory usage, and a carefully tuned opcode allocation that balances feature completeness with code density.</t>

<t>The primary use cases for MBC include:
<list style="symbols">
<t>Packet classification based on Monad wire format headers</t>
<t>Dynamic packet transformation and header rewriting</t>
<t>Per-packet telemetry and flow tracking</t>
<t>Distributed policy enforcement in multi-hop environments</t>
</list>
</t>

<t>MBC is part of the Foundation (Monad wire format specification), which defines the Monad packet header structure and flow semantics. The Monad wire format provides a 20-byte fixed header with 12 IANA-registered extensions, frozen at version 0x01. MBC executes on packets carrying Monad headers, allowing per-packet computation to be distributed across the network infrastructure.</t>

<t>Complementary to MBC are two other Unheaded specifications:
<list style="symbols">
<t>Wotan: The message bus and ring buffer protocol for event distribution within the UPC ecosystem</t>
<t>Sophia: The dictionary service and knowledge graph for stateful computation and policy storage</t>
</list>
</t>

<t>This document specifies the complete MBC ISA, including instruction encoding, register model, opcode definitions, memory addressing, interrupt handling, and BPF verifier compliance.</t>
</section>

<section anchor="keywords" title="Requirements Language">
<t>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/>.</t>
</section>

<section anchor="encoding" title="Instruction Encoding">
<t>MBC uses a 32-bit fixed-width instruction format. All instructions are aligned on 4-byte boundaries and follow a uniform structure.</t>

<section anchor="encoding-format" title="Instruction Format">
<t>The 32-bit instruction is laid out as follows:</t>


<artwork type="ascii-art">
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|   Opcode      |  Destination  |      Source       |Immediate |
|   [31:24]     |    [23:20]    |      [19:16]      | [15:0]   |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
</artwork>

<t>
<list style="hanging">
<t hangText="Opcode [31:24]:">8-bit opcode identifier, ranging from 0x00 to 0xFF. Opcodes 0x00 and 0xFE are reserved.</t>
<t hangText="Destination [23:20]:">4-bit register index (r0-r15) for the result of the operation, or flags register for compare operations.</t>
<t hangText="Source [19:16]:">4-bit register index (r0-r15) for the first operand, or flags for conditional branches.</t>
<t hangText="Immediate [15:0]:">16-bit signed immediate value, used for offsets, constants, or as part of extended operands.</t>
</list>
</t>

<t>All instructions are stored in little-endian byte order in memory. When an MBC program is loaded, the instruction stream MUST be byte-swapped from the storage format to the native CPU byte order before execution begins.</t>

<t>Field extraction follows standard C bitfield semantics: opcode is the high byte, destination is bits 23-20, source is bits 19-16, and immediate is the low 16 bits. All shifts and masks are performed in the native CPU word size (32-bit or larger).</t>
</section>

<section anchor="encoding-variants" title="Instruction Encoding Variants">
<t>Several instruction families use non-standard field mappings:</t>

<t><list style="hanging">
<t hangText="Arithmetic (ADD, SUB, MUL, DIV, MOD, NEG):">Destination (dst) and Source (src) both reference GPRs. Immediate field is unused (MUST be 0).</t>

<t hangText="Extended Immediate (LOAD_IMM32, ADDI):">Destination is GPR. Immediate is signed 16-bit value, sign-extended to 32 bits. Immediate field is the low 16 bits of the constant for LOAD_IMM32.</t>

<t hangText="Memory Operations (LD, ST, LDB, STB, LDH, STH):">Destination is GPR (for loads) or ignored (for stores). Source is base address GPR. Immediate is signed byte/word offset.</t>

<t hangText="Branch Operations (JZ, JNZ, JN, JP, JC, JNC):">Source field encodes flags to test. Immediate is signed 16-bit word offset from next instruction.</t>

<t hangText="Atomic Operations (XCHG, CAS):">Destination and Source are both GPRs. Immediate specifies additional parameters.</t>
</list>
</t>
</section>

</section>

<section anchor="registers" title="Register Model">
<t>MBC provides a 16-register computational model with a separate flags register.</t>

<section anchor="registers-gpr" title="General-Purpose Registers">
<t>MBC defines 16 general-purpose registers, each 32 bits wide:</t>


<artwork type="ascii-art">
Register | Mnemonic | Convention
---------|----------|---------------------------------------------
   0     |   r0     | Return value
   1     |   r1     | Argument 1, scratch
   2     |   r2     | Argument 2, scratch
   3     |   r3     | Argument 3, scratch
   4     |   r4     | Argument 4, scratch
   5     |   r5     | Argument 5, scratch
   6     |   r6     | Callee-saved
   7     |   r7     | Callee-saved
   8     |   r8     | Callee-saved
   9     |   r9     | Callee-saved
  10     |   r10    | Callee-saved
  11     |   r11    | Scratch
  12     |   r12    | Scratch
  13     |   r13    | Scratch
  14     |   r14    | Scratch
  15     |   r15    | Stack pointer (SP) convention
</artwork>

<t>All registers are 32-bit unsigned values. Signed arithmetic uses two's complement representation internally; the signedness is determined by the instruction semantics, not register width.</t>

<t>The stack pointer (SP) convention uses r15. The stack grows downward (toward lower addresses). Stack operations are not directly supported by MBC instructions (PUSH and POP are memory operations); management of the stack is the responsibility of the MBC program.</t>
</section>

<section anchor="registers-flags" title="Flags Register">
<t>MBC maintains an 8-bit flags register with the following bit assignments:</t>


<artwork type="ascii-art">
Bit | Mnemonic | Meaning
----|----------|----------------------------------------------------
 7  | IF       | Interrupt Enable (1 = interrupts enabled)
 6  | Reserved | Must be zero
 5  | Reserved | Must be zero
 4  | Reserved | Must be zero
 3  | Reserved | Must be zero
 2  | C        | Carry flag (set by arithmetic, test by branch)
 1  | N        | Negative/Sign flag (set by arithmetic)
 0  | Z        | Zero flag (set by arithmetic, test by branch)
</artwork>

<t>Flags are set by arithmetic operations (ADD, SUB, MUL, DIV, MOD, NEG) and by comparison (CMP). Flags are tested by conditional branch instructions (JZ, JNZ, JN, JP, JC, JNC) and by the interrupt control instructions (INT, CLI, STI).</t>

<t>The Interrupt Enable (IF) flag controls whether INT instructions will actually trigger interrupt handlers (see <xref target="interrupts"/> for details).</t>
</section>

<section anchor="registers-pc" title="Program Counter">
<t>The Program Counter (PC) is a 32-bit register that holds the byte address of the currently executing instruction. The PC is automatically incremented after each instruction execution. Branch and jump instructions modify the PC directly.</t>

<t>For the purposes of immediate field interpretation in branch instructions, the immediate value is treated as a signed 16-bit word offset (i.e., it is multiplied by 4 bytes before being added to PC). This allows branch targets to reach +/- 128 KB from the current instruction.</t>
</section>

<section anchor="registers-state" title="CPU State Structure">
<t>The MBC CPU state is organized as a single 128-byte structure:</t>


<artwork type="ascii-art">
Offset | Field       | Size  | Description
-------|-------------|-------|----------------------------------
  0-3  | r0          | 4     | General-purpose register 0
  4-7  | r1          | 4     | General-purpose register 1
  ...  | ...         | ...   | ...
 56-59 | r14         | 4     | General-purpose register 14
 60-63 | r15         | 4     | Stack pointer (SP)
 64    | flags       | 1     | Z, N, C, IF flags
 65-67 | reserved    | 3     | Reserved for alignment
 68-71 | PC          | 4     | Program counter
 72-127| reserved    | 56    | Reserved for future use
</artwork>

<t>Total size: 128 bytes. This structure is the working memory for each MBC execution context.</t>
</section>

</section>

<section anchor="instruction-set" title="Instruction Set">
<t>MBC provides 48 distinct opcodes, organized by functional category.</t>

<section anchor="arithmetic" title="Arithmetic Instructions">
<t>Arithmetic instructions operate on two 32-bit operands (src, dst) and update the flags register.</t>

<section anchor="add" title="ADD - Addition">

<artwork type="ascii-art">
Opcode: 0x01
Encoding: [0x01][dst:r0-r15][src:r0-r15][imm:unused]

Operation: dst = dst + src
Flags: Z, N, C set according to result
</artwork>
<t>Adds the value in src register to dst register, storing the result in dst. Carry flag is set if unsigned overflow occurs. Negative flag is set if result is negative (bit 31 set). Zero flag is set if result is zero.</t>
</section>

<section anchor="sub" title="SUB - Subtraction">

<artwork type="ascii-art">
Opcode: 0x02
Encoding: [0x02][dst:r0-r15][src:r0-r15][imm:unused]

Operation: dst = dst - src
Flags: Z, N, C set according to result
</artwork>
<t>Subtracts the value in src from dst, storing the result in dst. Carry flag is set if unsigned underflow occurs (borrow). Negative and Zero flags set as in ADD.</t>
</section>

<section anchor="mul" title="MUL - Multiplication (Low 32 Bits)">

<artwork type="ascii-art">
Opcode: 0x03
Encoding: [0x03][dst:r0-r15][src:r0-r15][imm:unused]

Operation: dst = (dst * src) &amp; 0xFFFFFFFF
Flags: Z, N set; C set if high 32 bits are non-zero
</artwork>
<t>Multiplies dst by src, storing the low 32 bits in dst. The Carry flag indicates whether the result overflowed 32 bits. This instruction performs 32-bit multiply returning 32-bit result.</t>
</section>

<section anchor="div" title="DIV - Integer Division">

<artwork type="ascii-art">
Opcode: 0x04
Encoding: [0x04][dst:r0-r15][src:r0-r15][imm:unused]

Operation: dst = dst / src
Flags: Z, N set; trap if src == 0
</artwork>
<t>Divides dst by src, storing the quotient in dst. If src is zero, execution traps (see Security Considerations). Division is unsigned 32-bit arithmetic. Remainder is discarded.</t>
</section>

<section anchor="mod" title="MOD - Integer Modulo">

<artwork type="ascii-art">
Opcode: 0x05
Encoding: [0x05][dst:r0-r15][src:r0-r15][imm:unused]

Operation: dst = dst % src
Flags: Z, N set; trap if src == 0
</artwork>
<t>Computes dst modulo src, storing the remainder in dst. Traps on divide by zero. Modulo is unsigned 32-bit arithmetic.</t>
</section>

<section anchor="neg" title="NEG - Arithmetic Negation">

<artwork type="ascii-art">
Opcode: 0x06
Encoding: [0x06][dst:r0-r15][src:unused][imm:unused]

Operation: dst = -dst (two's complement)
Flags: Z, N, C set according to result
</artwork>
<t>Computes the two's complement negation of dst. Equivalent to SUB with dst=0 and src=dst. Carry flag is set if result overflows (i.e., if dst was 0x80000000).</t>
</section>

</section>

<section anchor="logic-bitwise" title="Logic and Bitwise Instructions">
<t>Logical and bitwise instructions operate on 32-bit values and update flags.</t>

<section anchor="and" title="AND - Bitwise AND">

<artwork type="ascii-art">
Opcode: 0x07
Encoding: [0x07][dst:r0-r15][src:r0-r15][imm:unused]

Operation: dst = dst &amp; src
Flags: Z, N set
</artwork>
<t>Performs bitwise AND of dst and src, storing result in dst. Carry flag is not modified.</t>
</section>

<section anchor="or" title="OR - Bitwise OR">

<artwork type="ascii-art">
Opcode: 0x08
Encoding: [0x08][dst:r0-r15][src:r0-r15][imm:unused]

Operation: dst = dst | src
Flags: Z, N set
</artwork>
<t>Performs bitwise OR of dst and src, storing result in dst.</t>
</section>

<section anchor="xor" title="XOR - Bitwise Exclusive OR">

<artwork type="ascii-art">
Opcode: 0x09
Encoding: [0x09][dst:r0-r15][src:r0-r15][imm:unused]

Operation: dst = dst ^ src
Flags: Z, N set
</artwork>
<t>Performs bitwise XOR of dst and src, storing result in dst.</t>
</section>

<section anchor="not" title="NOT - Bitwise NOT">

<artwork type="ascii-art">
Opcode: 0x0A
Encoding: [0x0A][dst:r0-r15][src:unused][imm:unused]

Operation: dst = ~dst
Flags: Z, N set
</artwork>
<t>Performs bitwise NOT (one's complement) of dst, storing result in dst.</t>
</section>

<section anchor="shl" title="SHL - Shift Left (Immediate)">

<artwork type="ascii-art">
Opcode: 0x0B
Encoding: [0x0B][dst:r0-r15][src:unused][imm:shift amount 0-31]

Operation: dst = dst &amp;lt;&amp;lt; (imm &amp; 0x1F)
Flags: Z, N set; C set to last shifted-out bit
</artwork>
<t>Shifts dst left by the amount specified in the immediate field (0-31 bits). Vacated bits are zero-filled. Carry flag is set to the last bit shifted out.</t>
</section>

<section anchor="shr" title="SHR - Shift Right Logical (Immediate)">

<artwork type="ascii-art">
Opcode: 0x0C
Encoding: [0x0C][dst:r0-r15][src:unused][imm:shift amount 0-31]

Operation: dst = dst &amp;gt;&amp;gt; (imm &amp; 0x1F)
Flags: Z, N set; C set to last shifted-out bit
</artwork>
<t>Shifts dst right logically by the amount in the immediate field. Vacated bits are zero-filled (unsigned shift).</t>
</section>

<section anchor="sar" title="SAR - Shift Right Arithmetic (Immediate)">

<artwork type="ascii-art">
Opcode: 0x0D
Encoding: [0x0D][dst:r0-r15][src:unused][imm:shift amount 0-31]

Operation: dst = ((int32_t)dst) &amp;gt;&amp;gt; (imm &amp; 0x1F)
Flags: Z, N set; C set to last shifted-out bit
</artwork>
<t>Shifts dst right arithmetically by the amount in the immediate field. Vacated bits are filled with the sign bit (bit 31). This preserves the sign of negative numbers.</t>
</section>

</section>

<section anchor="data-movement" title="Data Movement Instructions">

<section anchor="mov" title="MOV - Move Register">

<artwork type="ascii-art">
Opcode: 0x0E
Encoding: [0x0E][dst:r0-r15][src:r0-r15][imm:unused]

Operation: dst = src
Flags: Z, N set
</artwork>
<t>Copies the value from src to dst. Flags are set based on the copied value.</t>
</section>

<section anchor="movi" title="MOVI - Move Immediate">

<artwork type="ascii-art">
Opcode: 0x0F
Encoding: [0x0F][dst:r0-r15][src:unused][imm:signed 16-bit]

Operation: dst = sign_extend(imm)
Flags: Z, N set
</artwork>
<t>Loads a sign-extended 16-bit immediate value into dst. The immediate is sign-extended to 32 bits before being stored in dst.</t>
</section>

</section>

<section anchor="comparison" title="Comparison Instruction">

<section anchor="cmp" title="CMP - Compare">

<artwork type="ascii-art">
Opcode: 0x10
Encoding: [0x10][dst:r0-r15][src:r0-r15][imm:unused]

Operation: Compute (dst - src), update flags, discard result
Flags: Z, N, C set according to subtraction
</artwork>
<t>Compares two values by computing dst - src and setting flags accordingly, without storing the result. The Carry flag is set if unsigned underflow occurs (src > dst in unsigned comparison). This instruction is used to prepare for conditional branches.</t>
</section>

</section>

<section anchor="extended-immediate" title="Extended Immediate Instructions">

<section anchor="load-imm32" title="LOAD_IMM32 - Load 32-bit Immediate">

<artwork type="ascii-art">
Opcode: 0x1C
Encoding: [0x1C][dst:r0-r15][upper:4-bit upper word][imm:16-bit lower word]

Operation: dst = (upper &lt;&lt; 16) | imm
Flags: Z, N set
</artwork>
<t>Loads a full 32-bit immediate into dst. The upper 4 bits come from the source field, the lower 16 bits from the immediate field. The middle 12 bits are zero-filled. This allows loading of arbitrary 20-bit immediates. For full 32-bit constants, two consecutive instructions are required.</t>
</section>

<section anchor="addi" title="ADDI - Add Immediate">

<artwork type="ascii-art">
Opcode: 0x1D
Encoding: [0x1D][dst:r0-r15][src:unused][imm:signed 16-bit]

Operation: dst = dst + sign_extend(imm)
Flags: Z, N, C set according to result
</artwork>
<t>Adds a sign-extended 16-bit immediate to dst, storing the result in dst. Flags are updated as in ADD.</t>
</section>

</section>

<section anchor="interrupts" title="Interrupt Instructions">

<section anchor="int" title="INT - Trigger Interrupt">

<artwork type="ascii-art">
Opcode: 0x17
Encoding: [0x17][vector:r0-r15][src:unused][imm:unused]

Operation: If IF flag set, jump to IVT[vector]; save return address
Flags: IF cleared upon entry to handler
</artwork>
<t>Triggers the interrupt handler at IVT entry specified by the value in the vector register. The PC+1 (next instruction address) is pushed onto the stack (via SP--). The Interrupt Enable flag is cleared upon entry to the handler, preventing nested interrupts. If IF is already clear, INT is a no-op.</t>
</section>

<section anchor="iret" title="IRET - Return from Interrupt">

<artwork type="ascii-art">
Opcode: 0x18
Encoding: [0x18][dst:unused][src:unused][imm:unused]

Operation: PC = pop from stack; IF = 1
Flags: IF set
</artwork>
<t>Returns from an interrupt handler. Restores the saved PC from the stack and sets the Interrupt Enable flag. The stack pointer (r15) is incremented by 4.</t>
</section>

</section>

<section anchor="stack" title="Stack Operations">

<section anchor="push" title="PUSH - Push to Stack">

<artwork type="ascii-art">
Opcode: 0x1A
Encoding: [0x1A][src:r0-r15][dst:unused][imm:unused]

Operation: *(--SP) = src; (SP -= 4)
Flags: None
</artwork>
<t>Pushes the value in src onto the stack (using r15 as SP). The stack grows downward (toward lower addresses). SP is decremented by 4 bytes before the write.</t>
</section>

<section anchor="pop" title="POP - Pop from Stack">

<artwork type="ascii-art">
Opcode: 0x1B
Encoding: [0x1B][dst:r0-r15][src:unused][imm:unused]

Operation: dst = *(SP); (SP += 4)
Flags: None
</artwork>
<t>Pops a value from the stack into dst. SP is incremented by 4 bytes after the read.</t>
</section>

</section>

<section anchor="branch-jump" title="Branch and Jump Instructions">

<section anchor="jmp" title="JMP - Unconditional Jump">

<artwork type="ascii-art">
Opcode: 0x20
Encoding: [0x20][dst:unused][src:unused][imm:signed 16-bit word offset]

Operation: PC = PC + (sign_extend(imm) * 4)
Flags: None
</artwork>
<t>Unconditionally jumps to the target address specified by the sign-extended immediate. The immediate is multiplied by 4 to convert from word offset to byte offset. This allows jumps to +/- 128 KB from the current instruction.</t>
</section>

<section anchor="jz" title="JZ - Jump if Zero">

<artwork type="ascii-art">
Opcode: 0x21
Encoding: [0x21][dst:unused][src:flags field][imm:signed 16-bit word offset]

Operation: If Z flag set, PC = PC + (sign_extend(imm) * 4)
Flags: None
</artwork>
<t>Jumps if the Zero flag is set. Typically used after a CMP or arithmetic instruction. Source field encodes which flag to test (currently only Z is supported in src=0x0).</t>
</section>

<section anchor="jnz" title="JNZ - Jump if Not Zero">

<artwork type="ascii-art">
Opcode: 0x22
Encoding: [0x22][dst:unused][src:flags field][imm:signed 16-bit word offset]

Operation: If Z flag clear, PC = PC + (sign_extend(imm) * 4)
Flags: None
</artwork>
<t>Jumps if the Zero flag is clear (i.e., result was non-zero).</t>
</section>

<section anchor="jn" title="JN - Jump if Negative">

<artwork type="ascii-art">
Opcode: 0x23
Encoding: [0x23][dst:unused][src:flags field][imm:signed 16-bit word offset]

Operation: If N flag set, PC = PC + (sign_extend(imm) * 4)
Flags: None
</artwork>
<t>Jumps if the Negative flag is set (result bit 31 is 1).</t>
</section>

<section anchor="jp" title="JP - Jump if Positive">

<artwork type="ascii-art">
Opcode: 0x24
Encoding: [0x24][dst:unused][src:flags field][imm:signed 16-bit word offset]

Operation: If N flag clear, PC = PC + (sign_extend(imm) * 4)
Flags: None
</artwork>
<t>Jumps if the Negative flag is clear (result is positive or zero).</t>
</section>

<section anchor="jc" title="JC - Jump if Carry">

<artwork type="ascii-art">
Opcode: 0x25
Encoding: [0x25][dst:unused][src:flags field][imm:signed 16-bit word offset]

Operation: If C flag set, PC = PC + (sign_extend(imm) * 4)
Flags: None
</artwork>
<t>Jumps if the Carry flag is set. Used for unsigned overflow detection.</t>
</section>

<section anchor="jnc" title="JNC - Jump if No Carry">

<artwork type="ascii-art">
Opcode: 0x26
Encoding: [0x26][dst:unused][src:flags field][imm:signed 16-bit word offset]

Operation: If C flag clear, PC = PC + (sign_extend(imm) * 4)
Flags: None
</artwork>
<t>Jumps if the Carry flag is clear.</t>
</section>

</section>

<section anchor="call-return" title="Call and Return Instructions">

<section anchor="call" title="CALL - Call Subroutine">

<artwork type="ascii-art">
Opcode: 0x27
Encoding: [0x27][dst:unused][src:unused][imm:signed 16-bit word offset]

Operation: *(--SP) = PC + 1; PC = PC + (sign_extend(imm) * 4)
Flags: None
</artwork>
<t>Calls a subroutine at the address specified by the offset. The return address (PC+1) is pushed onto the stack before jumping. Used with RET to implement subroutine calls.</t>
</section>

<section anchor="ret" title="RET - Return from Subroutine">

<artwork type="ascii-art">
Opcode: 0x28
Encoding: [0x28][dst:unused][src:unused][imm:unused]

Operation: PC = *(SP); SP += 4
Flags: None
</artwork>
<t>Returns from a subroutine by popping the return address from the stack and jumping to it. Complements CALL.</t>
</section>

<section anchor="jmpr" title="JMPR - Jump Register">

<artwork type="ascii-art">
Opcode: 0x29
Encoding: [0x29][dst:unused][src:r0-r15][imm:unused]

Operation: PC = src_register_value
Flags: None
</artwork>
<t>Performs an indirect jump to the address contained in the src register. No return address is saved.</t>
</section>

<section anchor="callr" title="CALLR - Call Register">

<artwork type="ascii-art">
Opcode: 0x2A
Encoding: [0x2A][dst:unused][src:r0-r15][imm:unused]

Operation: *(--SP) = PC + 1; PC = src_register_value
Flags: None
</artwork>
<t>Performs an indirect call to the address in the src register. The return address (PC+1) is pushed onto the stack.</t>
</section>

</section>

<section anchor="memory-load-store" title="Memory Load and Store Instructions">
<t>All memory operations use indexed addressing: effective_address = base_register + sign_extend(imm). The immediate field is a signed byte offset (for byte load/store) or word offset (for word load/store).</t>

<section anchor="ld" title="LD - Load Word (32-bit)">

<artwork type="ascii-art">
Opcode: 0x30
Encoding: [0x30][dst:r0-r15][src:r0-r15][imm:signed 16-bit offset]

Operation: dst = *(base + sign_extend(imm))
Flags: Z, N set
</artwork>
<t>Loads a 32-bit word from memory at address (src + sign_extend(imm)) into dst. The immediate is treated as a byte offset. Unaligned access behavior is undefined.</t>
</section>

<section anchor="st" title="ST - Store Word (32-bit)">

<artwork type="ascii-art">
Opcode: 0x31
Encoding: [0x31][src:r0-r15 (data)][base:r0-r15][imm:signed 16-bit offset]

Operation: *(base + sign_extend(imm)) = src
Flags: None
</artwork>
<t>Stores a 32-bit word from src into memory at address (base + sign_extend(imm)). The destination field is used to specify the base register. The source field specifies the data register.</t>
</section>

<section anchor="ldb" title="LDB - Load Byte (8-bit)">

<artwork type="ascii-art">
Opcode: 0x32
Encoding: [0x32][dst:r0-r15][src:r0-r15][imm:signed 16-bit offset]

Operation: dst = *(uint8_t*)(base + sign_extend(imm)); zero-extend to 32 bits
Flags: Z, N set
</artwork>
<t>Loads an 8-bit byte from memory, zero-extends it to 32 bits, and stores it in dst.</t>
</section>

<section anchor="stb" title="STB - Store Byte (8-bit)">

<artwork type="ascii-art">
Opcode: 0x33
Encoding: [0x33][src:r0-r15 (data, low byte used)][base:r0-r15][imm:signed 16-bit offset]

Operation: *(uint8_t*)(base + sign_extend(imm)) = (uint8_t)src
Flags: None
</artwork>
<t>Stores the low byte of src into memory at address (base + sign_extend(imm)).</t>
</section>

<section anchor="ldh" title="LDH - Load Half-word (16-bit)">

<artwork type="ascii-art">
Opcode: 0x34
Encoding: [0x34][dst:r0-r15][src:r0-r15][imm:signed 16-bit offset]

Operation: dst = *(uint16_t*)(base + sign_extend(imm)); zero-extend to 32 bits
Flags: Z, N set
</artwork>
<t>Loads a 16-bit half-word from memory, zero-extends it to 32 bits, and stores it in dst.</t>
</section>

<section anchor="sth" title="STH - Store Half-word (16-bit)">

<artwork type="ascii-art">
Opcode: 0x35
Encoding: [0x35][src:r0-r15 (data, low half-word used)][base:r0-r15][imm:signed 16-bit offset]

Operation: *(uint16_t*)(base + sign_extend(imm)) = (uint16_t)src
Flags: None
</artwork>
<t>Stores the low 16 bits of src into memory at address (base + sign_extend(imm)).</t>
</section>

</section>

<section anchor="register-shifts" title="Register-Based Shifts and Extended Arithmetic">

<section anchor="shlr" title="SHLR - Shift Left Register">

<artwork type="ascii-art">
Opcode: 0x36
Encoding: [0x36][dst:r0-r15][src:r0-r15 (shift count)][imm:unused]

Operation: dst = dst &amp;lt;&amp;lt; (src &amp; 0x1F)
Flags: Z, N set; C set to last shifted-out bit
</artwork>
<t>Shifts dst left by the amount specified in src (masked to 5 bits). Unlike SHL, the shift amount comes from a register, allowing dynamic shift amounts.</t>
</section>

<section anchor="shrr" title="SHRR - Shift Right Logical Register">

<artwork type="ascii-art">
Opcode: 0x37
Encoding: [0x37][dst:r0-r15][src:r0-r15 (shift count)][imm:unused]

Operation: dst = dst &amp;gt;&amp;gt; (src &amp; 0x1F)
Flags: Z, N set; C set to last shifted-out bit
</artwork>
<t>Shifts dst right logically by the amount in src (masked to 5 bits). Vacated bits are zero-filled.</t>
</section>

<section anchor="sarr" title="SARR - Shift Right Arithmetic Register">

<artwork type="ascii-art">
Opcode: 0x38
Encoding: [0x38][dst:r0-r15][src:r0-r15 (shift count)][imm:unused]

Operation: dst = ((int32_t)dst) &amp;gt;&amp;gt; (src &amp; 0x1F)
Flags: Z, N set; C set to last shifted-out bit
</artwork>
<t>Shifts dst right arithmetically by the amount in src (masked to 5 bits). Vacated bits are filled with the sign bit.</t>
</section>

<section anchor="mulh" title="MULH - Multiply High (Signed)">

<artwork type="ascii-art">
Opcode: 0x39
Encoding: [0x39][dst:r0-r15][src:r0-r15][imm:unused]

Operation: dst = (((int64_t)(int32_t)dst) * ((int64_t)(int32_t)src)) &gt;&gt; 32
Flags: Z, N set
</artwork>
<t>Performs a signed 32x32->64 bit multiply and returns the high 32 bits. Both operands are sign-extended from 32 bits to 64 bits before multiplication. Useful for scaling and fixed-point arithmetic.</t>
</section>

</section>

<section anchor="mulhu" title="Extended Multiply">

<section anchor="mulhu-instr" title="MULHU - Multiply High Unsigned">

<artwork type="ascii-art">
Opcode: 0x3A
Encoding: [0x3A][dst:r0-r15][src:r0-r15][imm:unused]

Operation: dst = (((uint64_t)dst) * ((uint64_t)src)) &gt;&gt; 32
Flags: Z, N set
</artwork>
<t>Performs an unsigned 32x32->64 bit multiply and returns the high 32 bits. Both operands are treated as unsigned 32-bit values.</t>
</section>

</section>

<section anchor="atomic" title="Atomic Operations">

<section anchor="cli" title="CLI - Clear Interrupt Enable">

<artwork type="ascii-art">
Opcode: 0x3B
Encoding: [0x3B][dst:unused][src:unused][imm:unused]

Operation: IF = 0
Flags: IF cleared
</artwork>
<t>Clears the Interrupt Enable flag, disabling interrupt processing. All INT instructions become no-ops while IF is clear. Used to protect critical sections from interrupt preemption.</t>
</section>

<section anchor="sti" title="STI - Set Interrupt Enable">

<artwork type="ascii-art">
Opcode: 0x3C
Encoding: [0x3C][dst:unused][src:unused][imm:unused]

Operation: IF = 1
Flags: IF set
</artwork>
<t>Sets the Interrupt Enable flag, re-enabling interrupt processing. Typically used after a CLI to re-enable interrupts at the end of a critical section.</t>
</section>

<section anchor="xchg" title="XCHG - Atomic Exchange">

<artwork type="ascii-art">
Opcode: 0x3D
Encoding: [0x3D][dst:r0-r15 (address)][src:r0-r15 (new value)][imm:offset]

Operation: old = *dst; *dst = src; dst = old
Flags: Z, N set based on old value
</artwork>
<t>Atomically exchanges the value at the memory address in dst with the value in src. The old value is returned in dst. The immediate field specifies an optional offset to add to the address. This operation is atomic with respect to interrupts (guaranteed to complete without interruption even if IF is set).</t>
</section>

<section anchor="cas" title="CAS - Compare and Swap">

<artwork type="ascii-art">
Opcode: 0x3E
Encoding: [0x3E][dst:r0-r15 (address)][src:r0-r15 (new value)][imm:compare value high 16 bits]

Operation: if (*dst == compare_value) { *dst = src; Z=1 } else { Z=0 }
Flags: Z set if swap succeeded, clear if failed
</artwork>
<t>Atomically compares the value at address dst with a compare value (32-bit, specified via immediate and additional register). If equal, stores the new value from src and sets Z flag. If not equal, leaves memory unchanged and clears Z flag. Used for lock-free synchronization. The full 32-bit compare value is formed from the immediate field (lower 16 bits) and a second immediate encoded in the src field (upper 16 bits).</t>
</section>

</section>

<section anchor="system" title="System Instructions">

<section anchor="syscall" title="SYSCALL - System Call">

<artwork type="ascii-art">
Opcode: 0x40
Encoding: [0x40][syscall_num:r0-r15][src:unused][imm:unused]

Operation: Invoke system call (syscall number in dst register)
Flags: Depends on syscall
</artwork>
<t>Invokes a system call. The syscall number is specified in the dst register. System calls provide access to eBPF helper functions and privileged operations. Not all syscalls are available in XDP context; availability depends on the eBPF verifier and kernel version.</t>
</section>

<section anchor="halt" title="HALT - Halt Execution">

<artwork type="ascii-art">
Opcode: 0xFF
Encoding: [0xFF][exit_code:r0-r15][src:unused][imm:unused]

Operation: Stop execution; return exit_code to caller
Flags: None (execution halts)
</artwork>
<t>Terminates execution of the MBC program. The value in the dst register is returned as the exit code to the caller. This is used to signal completion or error conditions back to the eBPF XDP program.</t>
</section>

</section>

</section>

<section anchor="memory-addressing" title="Memory Addressing">
<t>MBC uses a single addressing mode: indexed addressing.</t>

<section anchor="indexed-mode" title="Indexed Addressing Mode">
<t>Effective Address = Base Register + Signed Offset</t>

<t>For load/store instructions, the effective address is computed by adding the sign-extended immediate field to a base register. The immediate field width determines the range:
<list style="symbols">
<t>Byte instructions (LDB, STB): 16-bit signed offset = -32768 to +32767 bytes</t>
<t>Half-word instructions (LDH, STH): 16-bit signed offset = -32768 to +32767 bytes (each byte)</t>
<t>Word instructions (LD, ST): 16-bit signed offset = -32768 to +32767 bytes (each byte)</t>
</list>
</t>

<t>All memory accesses use byte offsets in the immediate field. The eBPF verifier enforces that all memory accesses are within bounds of allocated eBPF maps or kernel memory buffers.</t>
</section>

<section anchor="alignment" title="Alignment Requirements">
<t>MBC does not require strict alignment for memory accesses, but performance is improved for naturally-aligned accesses (4-byte words should be 4-byte aligned, etc.). Unaligned access behavior is defined by the underlying eBPF map type and kernel architecture.</t>
</section>

<section anchor="address-space" title="Address Space Layout">
<t>MBC address space is not directly visible to MBC programs. All memory access goes through eBPF map keys, and the base register values are validated by the eBPF verifier. Typical layout in an eBPF program:
<list style="symbols">
<t>0x00000000 - 0x0FFFFFFF: Stack memory (provided by eBPF runtime, typically 512 bytes per context)</t>
<t>0x10000000+: eBPF map memory (accessed via helper functions, validated by verifier)</t>
</list>
</t>
</section>

</section>

<section anchor="bpf-verifier" title="BPF Verifier Compliance">
<t>MBC execution must comply with eBPF verifier constraints to be JIT-compiled for high performance.</t>

<section anchor="instruction-limit" title="Instruction Limit">
<t>An MBC program MUST NOT exceed 256 instructions per eBPF program unit ("per tick" of the XDP handler). This is the eBPF verifier's limit on linear instruction sequences without loops. Loops within MBC programs must follow bounded iteration patterns (see below).</t>
</section>

<section anchor="bounded-loops" title="Bounded Loop Pattern">
<t>MBC programs that use loops (via jump instructions) must ensure loops terminate in bounded time. The standard pattern is:
<list style="numbers">
<t>Initialize a loop counter (e.g., r1 = 0)</t>
<t>Increment counter in loop body (e.g., r1 = r1 + 1)</t>
<t>Test counter against limit (e.g., CMP r1, 256)</t>
<t>Conditional branch back to loop start (e.g., JC loop_start)</t>
</list>
</t>

<t>The eBPF verifier performs static analysis to verify that the loop counter is bounded and the loop will terminate. If a loop is unbounded, the program will fail verifier validation and will not be loaded.</t>
</section>

<section anchor="map-access-checks" title="Map Access Null Checks">
<t>Any access to eBPF map data via LD/ST instructions MUST be preceded by a bounds check or the eBPF verifier will reject the program. In practice, this means:
<list style="symbols">
<t>The base register for a memory access must either be the stack pointer (r15) or a validated map data pointer</t>
<t>The offset must be within the known bounds of the allocated region</t>
<t>If accessing map data, the map lookup MUST have been performed immediately before the access</t>
</list>
</t>

<t>The eBPF verifier tracks data flow to ensure these properties are maintained.</t>
</section>

<section anchor="memory-safety" title="Memory Safety Guarantees">
<t>The eBPF verifier enforces memory safety:
<list style="symbols">
<t>All memory addresses are validated before access</t>
<t>Stack accesses are bounds-checked</t>
<t>Map accesses are validated against allocated map size</t>
<t>Uninitialized reads are prevented by data-flow analysis</t>
<t>Out-of-bounds writes are prevented by bounds checking</t>
</list>
</t>

<t>These guarantees are inherent to the eBPF execution model and are not specific to MBC. However, MBC programs must be structured to respect these constraints.</t>
</section>

</section>

<section anchor="interrupt-model" title="Interrupt Model">
<t>MBC provides a simple interrupt mechanism for synchronous events and inter-process communication.</t>

<section anchor="interrupt-vector-table" title="Interrupt Vector Table (IVT)">
<t>The IVT is a 256-entry table of interrupt handler addresses, located at fixed word addresses 0x00 to 0xFF. Each entry is a 32-bit word address (4 bytes apart). The total IVT size is 1024 bytes (256 entries × 4 bytes).</t>


<artwork type="ascii-art">
Address | Vector | Purpose
--------|--------|------------------------------------------
0x000   | 0x00   | Reserved (division by zero trap)
0x004   | 0x01   | Reserved
...     | ...    | ...
0x080   | 0x20   | Timer interrupt
0x084   | 0x21   | Keyboard interrupt
...     | ...    | ...
0x200   | 0x80   | System call (SYSCALL instruction)
...     | ...    | (Reserved for user-defined handlers)
</artwork>

<t>The IVT is initialized by the MBC loader before program execution begins. Entries not filled by the loader contain zero (trap on execution).</t>
</section>

<section anchor="interrupt-sequence" title="Interrupt Handling Sequence">
<t>When an interrupt is triggered (via INT instruction or external hardware event):
<list style="numbers">
<t>The CPU saves the current PC+1 (return address) onto the stack (at SP-4, then decrements SP)</t>
<t>The Interrupt Enable (IF) flag is cleared</t>
<t>The PC is loaded with the value from IVT[vector_number]</t>
<t>Execution continues at the interrupt handler</t>
<t>The handler executes IRET to return: restores PC from stack, sets IF flag</t>
</list>
</t>

<t>Interrupt handlers run with IF clear, preventing nested interrupts (re-entrancy).</t>
</section>

<section anchor="interrupt-sources" title="Standard Interrupt Sources">
<t>
<list style="hanging">
<t hangText="0x20 (Timer):">Periodic timer interrupt, used for time-based scheduling and watchdog timers.</t>
<t hangText="0x21 (Keyboard):">Keyboard input interrupt. Not typically used in XDP context.</t>
<t hangText="0x80 (Syscall):">Invoked by the SYSCALL instruction, used to access privileged operations.</t>
</list>
</t>

<t>Vector 0x00 is reserved for division-by-zero exceptions. Additional vectors are reserved for user-defined purposes.</t>
</section>

</section>

<section anchor="safety-constraints" title="Safety Constraints">

<section anchor="opcode-whitelist" title="Opcode Whitelist">
<t>Only the 48 defined opcodes are valid in MBC programs. Opcodes 0x00, 0xFE are reserved and MUST NOT be used. All other opcode values are undefined and will cause a trap if executed. An MBC loader MUST validate that all instructions in a program use only defined opcodes before loading.</t>
</section>

<section anchor="division-by-zero" title="Division by Zero Behavior">
<t>If a DIV or MOD instruction is executed with src = 0, the execution traps (i.e., the eBPF program is terminated and an error is returned to the kernel). This is consistent with hardware division-by-zero behavior. The trap raises an exception that is caught by the eBPF verifier.</t>
</section>

<section anchor="stack-bounds" title="Stack Bounds">
<t>The stack pointer (r15) starts at a predetermined address (typically the end of the eBPF stack frame, around 0x1000 in most implementations). The MBC program is responsible for managing stack bounds. If SP underflows or overflows the allocated stack space, memory corruption results. The eBPF verifier does not automatically check stack bounds for MBC programs; this is the responsibility of the programmer.</t>
</section>

<section anchor="privilege-model" title="Privilege Model">
<t>MBC has a flat privilege model with no distinction between user and kernel mode. All instructions execute with the same privilege level. The eBPF verifier is the trust boundary; any MBC program that passes verification is assumed safe to execute.</t>
</section>

</section>

<section anchor="iana" title="IANA Considerations">
<t>This document requests the creation of a new IANA registry for MBC Opcodes.</t>

<section anchor="iana-registry" title="MBC Opcode Registry">
<t>Registry Name: MBC Instruction Set Architecture Opcode Values</t>

<t>Registry Range: 0x00 - 0xFF (256 values)</t>

<t>Registration Procedure: Standards Action [RFC8126]</t>

<t>Initial Assignments:
<list style="symbols">
<t>0x00: RESERVED</t>
<t>0x01: ADD - Addition</t>
<t>0x02: SUB - Subtraction</t>
<t>0x03: MUL - Multiply (low 32 bits)</t>
<t>0x04: DIV - Integer Division</t>
<t>0x05: MOD - Integer Modulo</t>
<t>0x06: NEG - Negate</t>
<t>0x07: AND - Bitwise AND</t>
<t>0x08: OR - Bitwise OR</t>
<t>0x09: XOR - Bitwise XOR</t>
<t>0x0A: NOT - Bitwise NOT</t>
<t>0x0B: SHL - Shift Left (Immediate)</t>
<t>0x0C: SHR - Shift Right Logical (Immediate)</t>
<t>0x0D: SAR - Shift Right Arithmetic (Immediate)</t>
<t>0x0E: MOV - Move Register</t>
<t>0x0F: MOVI - Move Immediate (16-bit sign-extended)</t>
<t>0x10: CMP - Compare</t>
<t>0x11-0x1B: RESERVED</t>
<t>0x1C: LOAD_IMM32 - Load 32-bit Immediate</t>
<t>0x1D: ADDI - Add Immediate (16-bit sign-extended)</t>
<t>0x1E-0x1F: RESERVED</t>
<t>0x17: INT - Trigger Interrupt</t>
<t>0x18: IRET - Return from Interrupt</t>
<t>0x19: RESERVED</t>
<t>0x1A: PUSH - Push to Stack</t>
<t>0x1B: POP - Pop from Stack</t>
<t>0x20: JMP - Unconditional Jump</t>
<t>0x21: JZ - Jump if Zero</t>
<t>0x22: JNZ - Jump if Not Zero</t>
<t>0x23: JN - Jump if Negative</t>
<t>0x24: JP - Jump if Positive</t>
<t>0x25: JC - Jump if Carry</t>
<t>0x26: JNC - Jump if No Carry</t>
<t>0x27: CALL - Call Subroutine</t>
<t>0x28: RET - Return from Subroutine</t>
<t>0x29: JMPR - Jump Register</t>
<t>0x2A: CALLR - Call Register</t>
<t>0x2B-0x2F: RESERVED</t>
<t>0x30: LD - Load Word (32-bit)</t>
<t>0x31: ST - Store Word (32-bit)</t>
<t>0x32: LDB - Load Byte (8-bit)</t>
<t>0x33: STB - Store Byte (8-bit)</t>
<t>0x34: LDH - Load Half-word (16-bit)</t>
<t>0x35: STH - Store Half-word (16-bit)</t>
<t>0x36: SHLR - Shift Left Register</t>
<t>0x37: SHRR - Shift Right Logical Register</t>
<t>0x38: SARR - Shift Right Arithmetic Register</t>
<t>0x39: MULH - Multiply High (Signed)</t>
<t>0x3A: MULHU - Multiply High Unsigned</t>
<t>0x3B: CLI - Clear Interrupt Enable</t>
<t>0x3C: STI - Set Interrupt Enable</t>
<t>0x3D: XCHG - Atomic Exchange</t>
<t>0x3E: CAS - Compare and Swap</t>
<t>0x3F: RESERVED</t>
<t>0x40: SYSCALL - System Call</t>
<t>0x41-0xFD: RESERVED for future standardization</t>
<t>0xFE: RESERVED</t>
<t>0xFF: HALT - Halt Execution</t>
</list>
</t>

<t>Reserved ranges are allocated for future expansion. Any assignment of previously reserved opcodes requires standards action through the IETF.</t>
</section>

</section>

<section anchor="security" title="Security Considerations">

<section anchor="security-bpf-boundary" title="BPF Verifier as Trust Boundary">
<t>MBC security relies entirely on the eBPF verifier. An MBC program that fails verifier checks will not be loaded. The verifier ensures memory safety, bounds checking, and termination. An attacker cannot directly execute unverified MBC bytecode; all MBC programs must pass the eBPF verifier before execution.</t>
</section>

<section anchor="security-instruction-limit" title="Instruction Limit Prevents Infinite Loops">
<t>The 256-instruction limit per eBPF program guarantees that no single MBC execution can consume arbitrary CPU time. Loops must be bounded, enforced by verifier static analysis. This prevents denial-of-service attacks based on infinite loops within an MBC program.</t>
</section>

<section anchor="security-no-privilege" title="No Privilege Separation">
<t>MBC has no user/kernel mode distinction. All MBC instructions execute at the same privilege level. This simplifies the ISA but means that any MBC code can access any memory location accessible to the eBPF program itself. Isolation between different tenants must be provided by the eBPF XDP program and kernel, not by MBC itself.</t>
</section>

<section anchor="security-cas-atomicity" title="CAS Atomicity Limitations">
<t>The CAS (Compare and Swap) instruction is atomic with respect to eBPF interrupts on a single core. However, it does not provide atomicity across multiple cores or sockets. For multicore scenarios, external synchronization (e.g., distributed locks) is required. MBC programs MUST NOT assume that CAS provides multicore atomicity.</t>
</section>

<section anchor="security-memory-bounds" title="Memory Bounds Enforced by eBPF Maps">
<t>All memory access in MBC programs is validated by the eBPF verifier against allocated eBPF map sizes. Out-of-bounds accesses are prevented by the verifier. This guarantee is inherited from the eBPF execution model and does not require additional MBC-level validation.</t>
</section>

<section anchor="security-crc-validation" title="CRC Validation Before MBC Execution">
<t>Before executing an MBC program on a Monad-framed packet, the eBPF XDP program MUST verify the packet's CRC (if present in the Monad header). Execution of MBC bytecode on corrupted packets can result in undefined behavior. The CRC check MUST occur before the first MBC instruction is executed.</t>
</section>

</section>

</middle>

<back>

<displayreference target="RFC2119" to="RFC2119"/>
<displayreference target="RFC8174" to="RFC8174"/>
<displayreference target="RFC8126" to="RFC8126"/>
<displayreference target="RFC8200" to="RFC8200"/>
<displayreference target="RFC9669" to="RFC9669"/>

<references anchor="normative-refs" title="Normative References">

<reference anchor="RFC2119" target="https://www.rfc-editor.org/info/rfc2119">
<front>
<title>Key words for use in RFCs to Indicate Requirement Levels</title>
<author initials="S." surname="Bradner" fullname="Scott Bradner"><organization/></author>
<date year="1997" month="3"/>
</front>
<seriesInfo name="BCP" value="14"/>
<seriesInfo name="RFC" value="2119"/>
</reference>

<reference anchor="RFC8174" target="https://www.rfc-editor.org/info/rfc8174">
<front>
<title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
<author initials="B." surname="Leiba" fullname="Barry Leiba"><organization/></author>
<date year="2017" month="5"/>
</front>
<seriesInfo name="BCP" value="14"/>
<seriesInfo name="RFC" value="8174"/>
</reference>

<reference anchor="RFC8126" target="https://www.rfc-editor.org/info/rfc8126">
<front>
<title>Guidelines for Writing an IANA Considerations Section in RFCs</title>
<author initials="M." surname="Cotton" fullname="Michelle Cotton"><organization/></author>
<author initials="B." surname="Leiba" fullname="Barry Leiba"><organization/></author>
<author initials="T." surname="Narten" fullname="Thomas Narten"><organization/></author>
<date year="2017" month="6"/>
</front>
<seriesInfo name="BCP" value="26"/>
<seriesInfo name="RFC" value="8126"/>
</reference>

<reference anchor="RFC8200" target="https://www.rfc-editor.org/info/rfc8200">
<front>
<title>Internet Protocol, Version 6 (IPv6) Specification</title>
<author initials="S." surname="Deering" fullname="Stephen Deering"><organization/></author>
<author initials="R." surname="Hinden" fullname="Robert Hinden"><organization/></author>
<date year="2017" month="7"/>
</front>
<seriesInfo name="STD" value="86"/>
<seriesInfo name="RFC" value="8200"/>
</reference>

<reference anchor="RFC9669">
  <front>
    <title>BPF Instruction Set Architecture (ISA)</title>
    <author fullname="D. Thaler" initials="D." role="editor" surname="Thaler"/>
    <date month="October" year="2024"/>
    <abstract>
      <t>eBPF (which is no longer an acronym for anything), also commonly referred to as BPF, is a technology with origins in the Linux kernel that can run untrusted programs in a privileged context such as an operating system kernel. This document specifies the BPF instruction set architecture (ISA).</t>
    </abstract>
  </front>
  <seriesInfo name="RFC" value="9669"/>
  <seriesInfo name="DOI" value="10.17487/RFC9669"/>
</reference>

<reference anchor="FOUNDATION" target="https://github.com/unheaded/unheaded">
<front>
<title>The Monad Protocol Foundation Specification</title>
<author initials="S." surname="Bellis" fullname="Stevie Bellis"><organization>Unheaded</organization></author>
<date year="2026" month="3"/>
</front>
<seriesInfo name="Internet-Draft" value="draft-bellis-unheaded-protocol-foundation-00"/>
</reference>

<reference anchor="WOTAN" target="https://github.com/unheaded/wotan">
<front>
<title>Wotan: The Unheaded Message Bus Protocol</title>
<author initials="S." surname="Bellis" fullname="Stevie Bellis"><organization>Unheaded</organization></author>
<date year="2026" month="3"/>
</front>
<seriesInfo name="Internet-Draft" value="draft-bellis-unheaded-wotan-memory-00"/>
</reference>

</references>

<references anchor="informative-refs" title="Informative References">

<reference anchor="RFC9000" target="https://www.rfc-editor.org/info/rfc9000">
<front>
<title>QUIC: A UDP-Based Multiplexed and Secure Transport</title>
<author initials="J." surname="Iyengar" fullname="Jana Iyengar"><organization/></author>
<author initials="M." surname="Thomson" fullname="Martin Thomson"><organization/></author>
<date year="2021" month="5"/>
</front>
<seriesInfo name="RFC" value="9000"/>
</reference>

<reference anchor="SOPHIA" target="https://github.com/unheaded/unheaded">
<front>
<title>Sophia: The Unheaded Dictionary and Knowledge Graph Service</title>
<author initials="S." surname="Bellis" fullname="Stevie Bellis"><organization>Unheaded</organization></author>
<date year="2026" month="3"/>
</front>
<seriesInfo name="Internet-Draft" value="draft-bellis-unheaded-sophia-dictionary-00"/>
</reference>

<reference anchor="EBPF-IO" target="https://ebpf.io/">
<front>
<title>eBPF: Introduction and Overview</title>
<author><organization>eBPF Foundation</organization></author>
</front>
</reference>

</references>

</back>

</rfc>
