Arithmetic instructions in Nios II perform integer math on registers. The basics:

  • add, sub — register + register.
  • addi, subi — register + immediate constant.

Plus multiplication (mul, muli), division (div, divu), and various bitwise operations (and, or, xor, nor) following the same patterns. Computer Architecture mostly uses add and subtract.

add dest, src1, src2

Adds two registers, stores the sum in the destination.

add r3, r4, r5      # r3 ← r4 + r5

The destination can be the same as a source — add r3, r3, r4 increments r3 by r4.

Standard signed addition; overflow is silently truncated (the upper bits beyond 32 are lost). The Nios II base ISA doesn’t set status flags; you check for overflow only by explicit comparison if you care.

addi dest, src, imm16

Adds a 16-bit signed immediate to a register, stores the result.

addi r3, r3, 1       # r3 ← r3 + 1   (increment)
addi r2, r2, 4       # r2 ← r2 + 4   (advance pointer to next word)
addi r4, r5, -8      # r4 ← r5 - 8

The immediate is sign-extended to 32 bits before the add. Range: to . For larger constants, you’d movia them into a register first and use add.

addi is the standard incrementer for loops, pointer advance, and small offsets.

sub dest, src1, src2

Subtracts: .

sub r3, r4, r5      # r3 ← r4 - r5

subi dest, src, imm16

Subtracts an immediate.

subi sp, sp, 12     # allocate 12 bytes on the stack
subi r6, r6, 1      # decrement counter

The classic pattern for subi sp, sp, N is to make room on the stack for bytes of local storage. Stack grows downward, so subtracting from the stack pointer “pushes” the boundary.

A typical loop

Counting down from to 0:

    movi r3, 10          # n = 10
loop:
    # ... loop body ...
    subi r3, r3, 1       # n--
    bgt  r3, r0, loop    # while n > 0

r0 is the always-zero register — comparing against it tests “greater than zero.”

What’s missing

Nios II’s base ISA omits some things that other architectures have built in:

  • No condition flags. Branches compare two registers explicitly (bgt r3, r0, loop) rather than testing a flag set by a previous arithmetic instruction. This is the RISC purity choice — every comparison is its own instruction.
  • No memory operands. All arithmetic happens between registers. To add a value in memory, you ldw first, then add. This is the load/store architecture.

For shift, logical, and other arithmetic-adjacent instructions: srli (shift right logical immediate), sll (shift left logical), and, or, xor, nor — they follow the same dest, src, src form.

For control flow that uses these results, see Nios II branch instructions.