NYC
skills/letta-ai/skills/make-mips-interpreter

make-mips-interpreter

SKILL.md

MIPS Interpreter Implementation

Overview

This skill provides guidance for implementing MIPS interpreters/emulators that can load and execute MIPS ELF binaries. The core challenge involves parsing ELF files, decoding MIPS instructions, managing virtual memory, and handling system calls.

Critical Approach: Incremental Development

The most important principle for this task is incremental development over comprehensive analysis. Avoid spending excessive time analyzing before writing code. Instead:

  1. Start with a minimal working skeleton early
  2. Expand functionality iteratively
  3. Test frequently with partial implementations
  4. Debug and refine based on actual execution

Implementation Phases

Phase 1: Minimal ELF Loader

Start with the bare minimum to load an executable:

  1. Parse ELF header to extract:
    • Magic number verification (0x7f, 'E', 'L', 'F')
    • Architecture (MIPS32)
    • Endianness (typically little-endian)
    • Entry point address
  2. Parse program headers to identify loadable segments
  3. Load segments into virtual memory at specified addresses
  4. Set program counter to entry point

Key data structures needed:

  • Memory array/map for virtual address space
  • Registers array (32 general-purpose + PC + HI/LO)

Phase 2: Core Instruction Decoding

Implement instruction decoding for the three MIPS instruction formats:

R-type format (register operations):

  • Bits 31-26: opcode (0x00 for R-type)
  • Bits 25-21: rs (source register 1)
  • Bits 20-16: rt (source register 2)
  • Bits 15-11: rd (destination register)
  • Bits 10-6: shamt (shift amount)
  • Bits 5-0: funct (function code)

I-type format (immediate operations):

  • Bits 31-26: opcode
  • Bits 25-21: rs
  • Bits 20-16: rt
  • Bits 15-0: immediate value

J-type format (jump operations):

  • Bits 31-26: opcode
  • Bits 25-0: target address

Phase 3: Essential Instructions First

Implement instructions in priority order based on typical program needs:

High Priority (implement first):

  • Arithmetic: ADD, ADDU, ADDI, ADDIU, SUB, SUBU
  • Logical: AND, ANDI, OR, ORI, XOR, NOR
  • Shifts: SLL, SRL, SRA, SLLV, SRLV, SRAV
  • Comparison: SLT, SLTI, SLTU, SLTIU
  • Memory: LW, SW, LB, LBU, SB, LH, LHU, SH
  • Branches: BEQ, BNE, BGTZ, BLEZ, BLTZ, BGEZ
  • Jumps: J, JAL, JR, JALR
  • Load: LUI

Medium Priority:

  • Multiply/Divide: MULT, MULTU, DIV, DIVU, MFHI, MFLO, MTHI, MTLO

Lower Priority:

  • Coprocessor instructions (if needed)
  • Floating point (if needed)

Phase 4: Syscall Handler

Implement system call interface based on the target environment:

  1. Detect SYSCALL instruction
  2. Read syscall number from register (typically $v0 or $2)
  3. Read arguments from registers ($a0-$a3 or $4-$7)
  4. Execute syscall and set return value in $v0

Common syscalls to implement:

  • read (file descriptor, buffer, count)
  • write (file descriptor, buffer, count)
  • open (path, flags, mode)
  • close (file descriptor)
  • lseek (file descriptor, offset, whence)
  • exit (status code)

Phase 5: I/O and File System

For programs requiring file access:

  • Implement file descriptor table
  • Handle standard streams (stdin=0, stdout=1, stderr=2)
  • Support opening/reading external files (e.g., data files)
  • Handle output file creation (e.g., frame buffers, results)

Verification Strategies

Incremental Testing

Test after each implementation phase:

  1. ELF loader test: Verify entry point and memory layout match expected values
  2. Instruction test: Create simple test sequences for each instruction group
  3. Syscall test: Test each syscall with known inputs/outputs
  4. Integration test: Run actual target binary

Debugging Techniques

  • Add instruction tracing (PC, instruction, register changes)
  • Log syscall invocations with arguments
  • Verify memory reads/writes at expected addresses
  • Compare register state against expected values at checkpoints

Common Validation Points

  • Entry point address matches ELF header
  • Stack pointer initialized correctly
  • Memory segments loaded at correct addresses
  • Register $0 always reads as zero
  • Signed vs unsigned operations handled correctly
  • Branch delay slots handled (if applicable to target)

Common Pitfalls

Analysis Paralysis

Problem: Spending too much time understanding every detail before writing code. Solution: Start implementation after understanding ELF basics, entry point, and syscall numbers. Iterate and learn through building.

Missing Endianness Handling

Problem: Incorrect byte ordering when loading instructions or data. Solution: Check ELF header for endianness flag and apply consistently when reading multi-byte values.

Register Zero Hardwiring

Problem: Allowing writes to register $0 to persist. Solution: Always return 0 when reading $0, or ignore writes to $0.

Sign Extension Errors

Problem: Incorrect sign extension for immediate values or load operations. Solution: Carefully distinguish signed vs unsigned operations. LB sign-extends, LBU zero-extends.

Branch/Jump Address Calculation

Problem: Incorrect target address computation. Solution:

  • Branches: PC + 4 + (sign-extended offset << 2)
  • Jumps: (PC & 0xF0000000) | (target << 2)

Memory Alignment

Problem: Unaligned memory access causing errors. Solution: Either enforce alignment or handle unaligned access appropriately for the target.

Syscall Return Values

Problem: Not setting error codes or return values correctly. Solution: Set $v0 for return value, handle error cases consistently.

Incomplete Instruction Coverage

Problem: Missing instructions causing silent failures. Solution: Log unimplemented instructions with their encodings for debugging.

Time Management Strategy

For complex interpreter tasks:

  1. First 25% of time: ELF loading + basic instruction loop skeleton
  2. Next 25% of time: Core arithmetic/logic/memory instructions
  3. Next 25% of time: Branches, jumps, and syscalls
  4. Final 25% of time: Testing, debugging, edge cases

Prioritize a running (even incomplete) interpreter over comprehensive analysis. A partial implementation that executes provides more debugging information than complete analysis without code.

Weekly Installs
18
Repository
letta-ai/skills
First Seen
Jan 24, 2026
Installed on
claude-code13
codex12
gemini-cli12
opencode12
antigravity11
cursor9