The instruction set is designed for somewhat easy assembly language coding. A simulator and disassembler are provided with the development kit; these are released as free software. The reference assembler is still in development.
The existing implementation of the KIPS architecture uses a 16-bit address bus and 16-bit data bus and can address up to 65,536 16-bit words of memory. The other pins include CLK, /RESET, PWR, and GND. The initial processor has no interrupt pull lines.
When the system starts, it jumps to address 0, which generally contains a long jump (lui, or, jr) to the initial program. Future versions may jump to other low-numbered addresses when they receive an interrupt.
A simulator can represent the memory and registers thus:
unsigned short mem[65536]; /* 16-bit address and data bus */ unsigned short reg[8]; /* eight general-purpose registers */
Register | MIPS equivalent | Notes |
---|---|---|
$0 | $at | accumulator; used for expanding macros |
$1 | $t1 | param 1; return value |
$2 | $t2 | param 2; caller saved |
$3 | $t3 | param 3; caller saved |
$4 | $s4 | callee saved |
$5 | $s5 | callee saved |
$6 | $ra | return address |
$7 | $sp | stack/frame pointer |
fedcba9876543210 |||||||||||||||| |||||||+++++++++- Extra fields ||||+++---------- a register ++++------------- opcodeOr, in more detail:
fedc b a 9 8 7 6 5 4 3 2 1 0 Type let 0000 src1... src2....... dest....... ALUfunc R lui 0001 reg.... 0 imm.............................. I lw 0010 reg.... addr....... offset.................. L sw 0011 reg.... addr....... offset.................. L jl 0100 reg.... offset............................... I jr 0101 reg.... (unused) I bnz 0110 reg.... offset............................... I bz 0111 reg.... offset............................... I leti 1func dest... imm.................................. I
The initial implementation uses a multicycle datapath. Cycle-by-cycle descriptions of the initial implementation follow each instruction's description.
Cycle 1: instruction = mem[pc]; pc += 1;
Cycle 2: a = reg[instruction[b..9]]; b = reg[instruction[8..6]]; aluout = pc + sex(instruction[8..0]);
This leaves the branch destination in aluout.
The let family of instructions performs ALU functions on numbers contained in registers, or a register and an immediate value in [-256..255]. The function codes are as follows:
Code | Name | Operation |
---|---|---|
000 | shl | a << b* |
001 | slt | a < b (unsigned) |
010 | sub | a - b |
011 | add | a + b |
100 | xor | a xor b |
101 | or | a or b |
110 | and | a and b |
111 | li | b |
*Initial prototypes do not contain the shl instruction because of the difficulty of modeling a [barrel shifter]? in Capilano DesignWorks?.
Five of these operations (sub through and) have the same function codes as the corresponding operations on the standard 74LS382? ALU.
The let instruction puts the contents of two registers through the ALU and stores the result in another register, which may be the same as one of the source registers. On the other hand, leti instructions always store their result in the source register; this leaves nine bits for the immediate value, allowing both unsigned 8-bit bytes and signed values to be specified in one instruction.
For example, the forms of the add instruction are
add dest, src1, src2 // dest = src1 + src2<br />
add dest, 235 // dest = dest + 235
Other let-family instructions are similar.
// this loads a number between -256 and 255<br />
li reg, 169
So how does a larger value get loaded? The lui instruction loads an immediate value into a register shifted left eight bits; an `or' instruction (see leti) can fill in the low eight bits.
// this loads any number<br />
lui reg, 0x12<br />
or reg, 0x34
An assembler will change an out-of-range li into an lui/or pair.
lw copies a word from memory into a register. sw copies a word from a register into memory. The address in each case is a 6-bit signed offset plus the value of the specified register, allowing stack frames to be up to 32 words in length.
li $1, 0x2080 // expands into lui + or pair<br />
lw $2, 4($1) // copies the value in mem[0x2084] to $2
jl (jump link) jumps to a PC-relative address, storing the return address in the given register (an assembler assumes $6 if none is specified). There is no plain jump instruction; a jl can store the return address in an unused (garbage) register if necessary.
jr (jump register; jump return) jumps to the address in the given register (an assembler assumes $6 if none is specified). Often used to return from a function or to jump farther than 255 words. (load the address using lui/or).
bnz (branch nonzero) jumps to a PC-relative address if the given register contains a nonzero value. bz (branch zero) does the opposite. (Comparing a register to zero instead of to another register frees up three bits for the branch destination.) Assemblers may support macroinstructions (such as bne, beq, blt, bgt, ble, bge) that expand comparisons into an slt/bz pair, an xor/bnz pair, etc. using $0.