Skip to content

Latest commit

 

History

History
732 lines (657 loc) · 17 KB

isa.md

File metadata and controls

732 lines (657 loc) · 17 KB

ISA

Conventions

The following conventions are used in asm commands and encodings.

Types

  • n - none type (no dst or src)
  • r - register (dst register generally encoded in last nibble of instruction)
    • f - the alu flags register (not one fo the general purpose registers)
  • i - immediate constants (encoded in word after instruction)
  • m - a fixed location in memory (pc relative)
    • mb - an unsigned byte in memory
    • mbs - a signed byte in memory
    • mw - a word in memory (signed or unsigned, no sign extension needed)
  • p - a memory location pointed to by a register (not pc relative)
    • pb - an unsigned byte in memory
    • pbs - a signed byte in memory
    • pw - a word in memory
  • off - an addressing offset (stored in word after instruction)
  • j - a pc-relative jump address
  • ra - a pc relative address to be converted to a non pc-relative address (for loading pointer initial values)
  • c - a condition code (see below)
  • sp - a register used as a stack pointer
  • p - an io port number
  • i - an interrupt vector entry (one of 8 ints)
  • ipc - the interrupt pc reg (pc copied to ipc reg on interrupt)

Registers

Registers are the program counter (pc), flags register (f), and registers r0-rf. By convention only, r0 is used as the stack pointer and r1 as the frame pointer. The hardware can use any register as a stack pointer, or have multiple stacks.

Extended register are formed by two registers next to each other starting on an even reg number. Extended registers are (e0, e2, e4, ... ec, ee)

Register Usage Conventions:

Reg Extended VBCC Usage
r0 e0 low GPR
r1 e0 high GPR
r2 e2 low GPR
r3 e2 high GPR
r4 e4 low GPR
r5 e4 high GPR
r6 e6 low GPR
r7 e6 high GPR
r8 e8 low GPR
r9 e8 high GPR
ra ea low GPR
rb ea high GPR
rc ec low Backend Temp
rd ec high Backend Temp
re ee low FP
rf ee high SP

ALU ops

There are 16 possible alu operations, stored as 4-bit alu opcodes. They are:

0 - | (bitwise or)
1 - ^ (bitwise xor)
2 - & (bitwise and)
3 - << (left shift)
4 - >> (unsigned right shift)
5 - >> (signed right shift)
6 - + (addition)
7 - - (subtraction)
8 - * (multiplication)
9 - ~ (bitwise complement) (of first operand)
a - - (unary minus) (of first operand)
b -
c -
d -
e -
f -

Condition Codes

Condition codes in the flag register are set by the cmp instruction. They are five bit values, encoded as follows:

4 3 2 1 0
signed greater than signed less than unsigned greater than unsigned less than equal to

A conditional is a five bit value. It is or'd with the flags register, so multiple conditions can be combined. Thus, the following are all the posibilities for unsigned numbers:

000 - false
001 - ==
010 - <
011 - <=
100 - >
101 - >=
110 - !=
111 - true

NOTE: the flags register starts with the value 1 loaded so that an uncoditional jump always works.

Encoding Shorthands

  • s/u - signedness of the value. 0=unsigned, 1=signed
  • b/w - width of the value. 0=word, 1=byte

PC Relative Instructions

All instructions that deal with immediate addresses are pc-relative. Pointer loads are not pc relative - real adresses for initilizing pointers should be loaded with ld.r.ra.

PC relative addresses are found by taking the address of (inst_addr + mem_addr + 2), where instr_addr is the address where the first word of the instruction is written, and mem_addr is the pc-relative addr. The +2 is because the pc will already be incremented past the instruction by the time it executes.

Instruction System

SCP has 8 interrupt priority levels, ranging from int0 (highest priority) to int7 (lowest priority).

SCP has two privilege levels, 0 (system privilege), and 1 (user privilege). Interrupts can only occur in user privilege. An interrupts raises the privilege level to system privilege, and jumps to the interrupt vector. Because the privilege was raised to system, the page table base register is not used for page table calculations. This means that the interrupt vector that is jumped to will be in the system memory (ptb 0).

If an interrupt occurs and scp is in system privilege, the interrupts will wait till the privilege level goes back to user to take effect.

NOTE: because interrupts can only occur in user privilage and interrupts switch privilage to system priority, interrupts can't be interrupted by higher priority interrupts. Thus, interrupt priority only comes into play if there are two interrupts waiting to happen at the same time.

Interrupts can be triggered by an external event, or by the int.i.n instruction. An interrupt is the only way to raise the privilage level from user privilage, and are used for system calls, etc. The interrupt instruction can trigger any interrupt, even if it is also wired to an external device.

Interrupt Vectors

Interrupt vectors start at 0x0010 in the system memory, and the address of each increases by 0x0004 (enough space for one unconditional jump instruction). They are fixed address and can't be configured. Thus, the vectors are:

int vector
int0 0x0010
int1 0x0014
int2 0x0018
int3 0x001b
int4 0x001d
int5 0x0020
int6 0x0024
int7 0x0028
int8 0x002b

Opcode Encodings

Instr opcode
nop.n.n 000000
mov.r.r 000001
cmp.r.f 000010
jmp.c.r 000011
alu.r.r 0001__
ld.r.p.(b/bs/w) 010000
st.r.p.(b/bs/w) 010001
push.r.sp 010011
pop.r.sp 010100
call.r.sp 010101
ret.n.sp 010110
int.i.n 010111
reti.ipc.n 100000
mov.r.ipc 100001
mov.ipc.r 100010
ptb.r.n 110000
mmu.r.r 110001
ld.r.ra 001000
alu.r.i 0011__
ld.r.i 011000
ld.r.m.(b/bs/w) 011001
ld.r.p.off.(b/bs/w) 011010
st.r.m.(b/bs/w) 011011
st.r.p.off.(b/bs/w) 011100
jmp.c.j 011101
call.j.sp 011110
out.r.p 111000
in.r.p 111001

Nop Instructions

nop

Do nothing

nop
; nothing
fedcba9876543210
opcode ----

Move Instructions

mov.r.r

Copy one register to another.

mov.r.r dst src
; dst = src
fedcba9876543210
opcode ---- srcreg dst reg

ALU Instructions

alu.r.r

Perform an alu operation on two registers, and stores the result in the first register.

alu.r.r op dst src
; dst = dst op src
fedcba9876543210
opcode alu op src reg dst reg

alu.r.i

Perform an alu operation on a register and an immediate, and stores the result in the register.

alu.r.r op dst imd
; dst = dst op imd
fedcba9876543210val16
opcode alu op ---- dst reg immediate value

cmp.r.f

Compare two registers, and set alu flags based on comparison.

cmp.r.f reg1 reg2
; flags = reg1 cmp reg2
fedcba9876543210
opcode ---- reg2 reg1

Load Instructions

ld.r.i

Load an immediate into a register.

ld.r.i dst imd
; dst = imd
fedcba9876543210val16
opcode ---- dst reg immediate value

ld.r.m.(b/bs/w)

Load a value from memory into a register, sign extend if needed.

ld.r.m.b/bs/w dst mem
; dst = (pc + mem)
fedcba9876543210val16
opcode b/w s/u ---- dst reg memory address

ld.r.p.(b/bs/w)

Load a value pointed to by a register into a register, sign extend if needed.

ld.r.p.b/bs/w dst src
; dst = (src)
fedcba9876543210
opcode b/w s/u src reg dst reg

ld.r.p.off.(b/bs/w)

Load a value pointed to by a register plus offset into a register, sign extend if needed.

ld.r.p.off.b/bs/w dst src off
; dst = (src + off)
fedcba9876543210val16
opcode b/w s/u src reg dst reg address offset

ld.r.ra

Load a not pc-relative adress from a pc-relative adress immediate into a register.

ld.r.ra dst addr
; dst = pc + addr
fedcba9876543210val16
opcode ----- dst reg address

Store Instructions

NOTE: Store instructions with b and bs modes do the same thing, as we can't un sign extend

st.r.m.(b/bs/w)

Store a value from a register into memory.

st.r.m.b/bs/w src mem
; (pc + mem) = src
fedcba9876543210val16
opcode b/w - ---- src reg memory address

st.r.p.(b/bs/w)

Store a value from a register into the memory addr pointed to by a register.

st.r.p.b/bs/w src dst
; (dst) = src
fedcba9876543210
opcode b/w - dst reg src reg

st.r.p.off.(b/bs/w)

Store a value from a register into the memory addr pointed to by a register plus an offset.

st.r.p.p.off.b/bs/w src dst off
; (dst + off) = src
fedcba9876543210val16
opcode b/w - dst reg src reg address offset

Jump Instructions

jmp.c.j

Perform a conditional jump to a fixed addr.

jmp.c.j cond addr
; if flags | cond then pc = pc + addr

Note - an unconditional jump can be performed by using 0b11111 as the condition code.

fedcba9876543210val16
opcode - cond --- address

jmp.c.r

Perform a conditional jump to a non pc-relative addr in a register.

jmp.c.r cond reg
; if flags | cond then pc = reg

Note - an unconditional jump can be performed by using 0b11111 as the condition code.

fedcba9876543210
opcode - cond reg

Stack instructions

push.r.sp

Push a register onto a stack.

push.r.sp reg sp
; sp = sp - 2
; (sp) = reg

Note - The register used as a stack pointer must be aligned on word boundries.

fedcba9876543210
opcode --- sp reg

pop.r.sp

Pop a value off a stack into a register.

pop.r.sp reg sp
; sp = sp + 2
; reg = (sp - 2)

Note - The register used as a stack pointer must be aligned on word boundries.

fedcba9876543210
opcode --- sp reg

call.j.sp

Perform a function call to a pc relative adress.

call.i.sp sp addr
; sp = sp - 2
; (sp) = pc + 2
; pc = pc + addr
fedcba9876543210val16
opcode --- sp --- function address

call.r.sp

Perform a function call to a non pc-relative address in a register.

call.r.sp reg sp
; sp = sp - 2
; (sp) = pc
; pc = reg
fedcba9876543210
opcode --- sp reg

ret.n.sp

Return from a function call, given a return adress on the top of the stack.

ret.n.sp sp
; sp = sp + 2
; pc = (sp - 2)
fedcba9876543210
opcode --- sp ---

IO Instructions

out.r.p

Output a register to the specified io port number.

out.r.p reg port_num
; io[port_num] = reg
fedcba9876543210val16
opcode --- reg port_num

in.r.p

Read a value from the specified io port into a register.

in.r.p reg port_num
; reg = io[port_num]
fedcba9876543210val16
opcode --- reg port_num

Interrupt Instructions

int.i.n

Perform an interrupt to the specified interrupt vector.

int.i.n vector
; pc_cpy = pc
; pc = int_vectors[vector]
; priv_lv = 0
fedcba9876543210
opcode --- vector

reti.ipc.n

Return from an interrupt. Copies ipc to pc, and sets priv_lv to 1 (usr).

reti.ipc.n
; pc = ipc
; priv_lv = 1
fedcba9876543210
opcode ---

mov.r.ipc

Copy the value in a register into the ipc reg.

mov.r.ipc reg
; ipc = reg
fedcba9876543210
opcode --- reg

mov.ipc.r

Copy the value in the ipc reg to a reg.

mov.ipc.r reg
; reg = ipc
fedcba9876543210
opcode --- reg

MMU Instructions

mmu.r.r

Set the mmu entry pointed to by (reg2>>11) + ptb to the low byte of reg1. priv_lv must be sys(0) going into the instruction. It will be sys(0) coming out of it.

mmu.r.r reg2 reg1
; priv_lv = 0
; page_table[ptb + (reg2 >> 11)] = reg1;
fedcba9876543210
opcode --- reg2 reg1

ptb.r.n

Set the ptb to the value in reg. priv_lv should be sys(0) going into instruction. Calling in sys(1) will cause a strange jump and likely crash.

ptb.r.n reg
; ptb = reg
fedcba9876543210
opcode --- reg

Pipeline

Three stages: EX (Execute), MEM (Memory Access), RW (Register Writeback)

- EX MEM RW
Memory Access Instr Register Word 1 Memory Instruction Instr Register Word 2
Alu Offset Add Alu instructions -
Register Write - sp increment/deincrement Main Write Back

Clocks

CLK0 - Earlier Clock - MMU clk, alu op, reg write back

CLK1 - Delayed Clock - RAM clk, microcode clk