add rd,rs1,rs2
[11:15]: rd
[16:20]: rs1
[21:25]: rs2
[26:31]: 0b000000
rd[0:31] = rs1[0:31] + rs2[0:31];
sub rd,rs1,rs2
[11:15]: rd
[16:20]: rs1
[21:25]: rs2
[26:31]: 0b000001
rd[0:31] = rs1[0:31] - rs2[0:31];
and rd,rs1,rs2
[11:15]: rd
[16:20]: rs1
[21:25]: rs2
[26:31]: 0b000010
rd[0:31] = rs1[0:31] & rs2[0:31];
or rd,rs1,rs2
[11:15]: rd
[16:20]: rs1
[21:25]: rs2
[26:31]: 0b000011
rd[0:31] = rs1[0:31] | rs2[0:31];
xor rd,rs1,rs2
[11:15]: rd
[16:20]: rs1
[21:25]: rs2
[26:31]: 0b000100
rd[0:31] = rs1[0:31] ^ rs2[0:31];
sll rd,rs1,rs2
[11:15]: rd
[16:20]: rs1
[21:25]: rs2
[26:31]: 0b000101
rd[0:31] = rs1[0:31] << rs2[0:31];
srl rd,rs1,rs2
[11:15]: rd
[16:20]: rs1
[21:25]: rs2
[26:31]: 0b000110
rd[0:31] = rs1[0:31] >>> rs2[0:31];
sra rd,rs1,rs2
[7:10]: 8
[11:15]: rd
[16:20]: rs1
[21:25]: rs2
[26:31]: 0b000110
rd[0:31] = rs1[0:31] >> rs2[0:31];
slt rd,rs1,rs2
[11:15]: rd
[16:20]: rs1
[21:25]: rs2
[26:31]: 0b000111
rd[0:31] = (rs1[0:31] < rs2[0:31]) ? 1 : 0;
sltu rd,rs1,rs2
[11:15]: rd
[16:20]: rs1
[21:25]: rs2
[26:31]: 0b001000
rd[0:31] = (rs1[0:31] < rs2[0:31]) ? 1 : 0;
mul rd, ru, rs1, rs2
[6:10]: rd
[11:15]: ru
[16:20]: rs1
[21:25]: rs2
[26:31]: 0b001001
rd[0:31] = (rs1[0:31] * rs2[0:31]) & 0xffffffff;
ru[0:31] = (rs1[0:31] * rs2[0:31]) >>> 32;
mulu rd,ru,rs1,rs2
[0:3]: 1
[6:10]: rd
[11:15]: ru
[16:20]: rs1
[21:25]: rs2
[26:31]: 0b001001
rd[0:31] = (rs1[0:31] * rs2[0:31]) & 0xffffffff;
ru[0:31] = (rs1[0:31] * rs2[0:31]) >>> 32;
div rd,ru,rs1,rs2
[6:10]: rd
[11:15]: ru
[16:20]: rs1
[21:25]: rs2
[26:31]: 0b001010
rd[0:31] = rs1[0:31] / rs2[0:31];
ru[0:31] = rs1[0:31] % rs2[0:31];
divu rd,ru,rs1,rs2
[0:3]: 1
[6:10]: rd
[11:15]: ru
[16:20]: rs1
[21:25]: rs2
[26:31]: 0b001010
rd[0:31] = rs1[0:31] / rs2[0:31];
ru[0:31] = rs1[0:31] % rs2[0:31];
addi rd,rs,const
[0:15]: const
[16:20]: rd
[21:25]: rs
[26:31]: 0b010000
rd[0:31] = rs[0:31] + const;
andi rd,rs,const
[0:15]: const
[16:20]: rd
[21:25]: rs
[26:31]: 0b010001
rd[0:31] = rs[0:31] & const;
ori rd,rs,const
[0:15]: const
[16:20]: rd
[21:25]: rs
[26:31]: 0b010010
rd[0:31] = rs[0:31] | const;
xori rd,rs,const
[0:15]: const
[16:20]: rd
[21:25]: rs
[26:31]: 0b010011
rd[0:31] = rs[0:31] ^ const;
slli rd,rs,const
[0:4]: const
[5:15]: 0
[16:20]: rd
[21:25]: rs
[26:31]: 0b010100
rd[0:31] = rs[0:31] << const;
srli rd,rs,const
[0:4]: const
[5:15]: 0
[16:20]: rd
[21:25]: rs
[26:31]: 0b010101
rd[0:31] = rs[0:31] >>> const;
srai rd,rs,const
[0:4]: const
[5:11]: 0
[12:15]: 8
[16:20]: rd
[21:25]: rs
[26:31]: 0b010101
rd[0:31] = rs[0:31] >> const;
slti rd,rs,const
[0:15]: const
[16:20]: rd
[21:25]: rs
[26:31]: 0b010110
rd[0:31] = (rs[0:31] < const) ? 1 : 0;
sltiu rd,rs,const
[0:15]: const
[16:20]: rd
[21:25]: rs
[26:31]: 0b010111
rd[0:31] = (rs[0:31] < const) ? 1 : 0;
lui rd,const
[0:15]: const
[16:20]: rd
[26:31]: 0b011000
rd[0:31] = const << 16
b addr
[0:25]: offset
[26:31] 0b100000
PC[0:31] += offset * 4;
bl addr
[0:25]: offset
[26:31] 0b100001
ra = PC+4;
PC[0:31] += offset * 4;
blr rs, rd
[11:15]: rd
[16:30]: rs
[26:31] 0b100010
rd[0:31] = PC+4;
PC[0:31] = rs[0:31];
beq rs1, rs2, offset
[0:15]: offset
[16:20]: rs1
[21:25]: rs2
[26:31] 0b100011
if(rs1[0:31] == rs2[0:31]) {
PC[0:31] += offset * 4;
}
bne rs1, rs2, offset
[0:15]: offset
[16:20]: rs1
[21:25]: rs2
[26:31] 0b100100
if(rs1[0:31] != rs2[0:31]) {
PC[0:31] += offset * 4;
}
bge rs1, rs2, offset
[0:15]: offset
[16:20]: rs1
[21:25]: rs2
[26:31] 0b100101
if(rs1[0:31] >= rs2[0:31]) {
PC[0:31] += offset * 4;
}
blt rs1, rs2, offset
[0:15]: offset
[16:20]: rs1
[21:25]: rs2
[26:31] 0b100110
if(rs1[0:31] < rs2[0:31]) {
PC[0:31] += offset * 4;
}
bgeu rs1, rs2, offset
[0:15]: offset
[16:20]: rs1
[21:25]: rs2
[26:31] 0b100111
if(rs1[0:31] >= rs2[0:31]) {
PC[0:31] += offset * 4;
}
bltu rs1, rs2, offset
[0:15]: offset
[16:20]: rs1
[21:25]: rs2
[26:31]: 0b101000
if(rs1[0:31] < rs2[0:31]) {
PC[0:31] += offset * 4;
}
lb rd, const(rs)
[0:15]: offset
[16:20]: rs
[21:25]: rd
[26:31]: 0b110000
lbu rd, const(rs)
[0:15]: offset
[16:20]: rs
[21:25]: rd
[26:31]: 0b110001
lh rd, const(rs)
[0:15]: offset
[16:20]: rs
[21:25]: rd
[26:31]: 0b110010
lhb rd, const(rs)
[0:15]: offset
[16:20]: rs
[21:25]: rd
[26:31]: 0b110011
lw rd, const(rs)
[0:15]: offset
[16:20]: rs
[21:25]: rd
[26:31]: 0b110100
sb rd, const(rs)
[0:15]: offset
[16:20]: rs
[21:25]: rd
[26:31]: 0b110101
sh rd, const(rs)
[0:15]: offset
[16:20]: rs
[21:25]: rd
[26:31]: 0b110110
sw rd, const(rs)
[0:15]: offset
[16:20]: rs
[21:25]: rd
[26:31]: 0b110111
tlbri
[0:2]: 0b000
[26:31]: 0b111011
OKAMI_TLB_VALUE_LOW = MMU_TLBLOW[OKAMI_TLB_INDEX];
OKAMI_TLB_VALUE_HIGH = MMU_TLBHIGH[OKAMI_TLB_INDEX];
tlbwi
[0:2]: 0b010
[26:31]: 0b111011
MMU_TLBLOW[OKAMI_TLB_INDEX] = OKAMI_TLB_VALUE_LOW;
MMU_TLBHIGH[OKAMI_TLB_INDEX] = OKAMI_TLB_VALUE_HIGH;
tlbwr
[0:2]: 0b011
[26:31]: 0b111011
MMU_TLBLOW[OKAMI_TLB_RANDOM] = OKAMI_TLB_VALUE_LOW;
MMU_TLBHIGH[OKAMI_TLB_RANDOM] = OKAMI_TLB_VALUE_HIGH;
tlbp
[0:2]: 0b100
[26:31]: 0b111011
for(i=0;i < 64;i++) {
if(MMU_TLBHIGH[i] == OKAMI_TLB_VALUE_HIGH) {
OKAMI_TLB_INDEX = i;
return;
}
}
OKAMI_TLB_INDEX = 0x80000000;
mfex rd, regnum
[0:15]: offset
[21:25]: rd
[26:31]: 0b111100
Move Extended Register to Register
mtex rs, regnum
[0:15]: offset
[16:20]: rs
[26:31]: 0b111101
Move Register Value to Extended Register
coproc
[0:25] Coprocessor Instruction and Arguments
[26:31]: 0b001111
Only available if a coprocessor is externally installed.
This can be used for calculating floating-point numbers.
kcall code
[0:24]: Code (can be any value)
[25]: 0b0
[26:31]: 0b111110
Triggers KCALL Trap
mcall code
[0:24]: Code (can be any value)
[25]: 0b1
[26:31]: 0b111110
Triggers MCALL Trap
This can only be used in kernel mode.
rft
[26:31]: 0b111111
OKAMI_STATUS = ((OKAMI_STATUS & 3) >> 1) | (OKAMI_STATUS & ~3);
PC = OAMKI_TRAP_PC;
0x00000000-0x7fffffff user (MMU Enabled, Caches Enabled)
0x80000000-0x9fffffff kernel1 (MMU Disabled, Caches Enabled)
0xa0000000-0xbfffffff kernel2 (MMU Disabled, Caches Disabled)
0xc0000000-0xffffffff kernel3 (MMU Enabled, Caches Enabled)
r0 - zero: Hardwired Zero
r1-r8 - a0-a7: Arguments/Return Values
r9-r15 - t0-t6: Temporary/Scratchpad Values
r16-r25 - s0-s9: Saved Values
r26-r27 - k0-k1: Kernel Registers (For interrupt handlers)
r28 - gp: Global Pointer
r29 - fp: Frame Pointer
r30 - sp: Stack Pointer
r31 - ra: Return Address
0x00: OKAMI_STATUS
0x1: Current Mode (0: User, 1: Kernel. Set to 1 on reset)
0x2: Current Interrupt Enable
0x4: Previous Mode
0x8: Previous Interrupt Enable
0x10: Old Mode
0x20: Old Interrupt Enable
0x40: Cache Isolate
NOTE: This acts similar to how MIPS-1 does it. It allows the CPU to directly access the L1 Data Cache using the kernel1 segment.
0x80: Cache Swap
NOTE: This acts similar to how MIPS-1 does it. It swaps the L1 Data and L1 Instruction Caches when isolating them.
0x01: OKAMI_TRAP_CAUSE
0: N/A
1: External Trap
2: KCall/MCall
3: TLB Miss
4: TLB Modify
5: TLB Invalid
6: Misaligned Read
7: Misaligned Write
8: Fetch Exception
9: Data Exception
10: Arithmetic Exception (Divide by zero)
11: Permission Exception
12: Unknown Opcode
0x02: OKAMI_TRAP_PC
0x03: OKAMI_TRAP_BAD_VADDR
0x04: OKAMI_TRAP_KERNEL_SCRATCH
0x05: OKAMI_TRAP_VECTOR_OFFSET
0x06: OKAMI_TLB_MISS_VECTOR_OFFSET
NOTE: DO NOT USE THE user SEGMENT or the kernel3 SEGMENT UNTIL THIS HAS BEEN SET!
0x07: OKAMI_MCALL_VECTOR_OFFSET
Intended for interacting with the system firmware
0x10: OKAMI_TLB_INDEX
0x11: OKAMI_TLB_VALUE_LOW
0x12: OKAMI_TLB_VALUE_HIGH
0x13: OKAMI_TLB_RANDOM_INDEX
Starts from 63 and decrements every cpu tick, it wraps around after trying to decrement 8.
Useful if you just want to fill a random TLB entry.
0x14: OKAMI_TLB_ADDRSPACE_ID
0x15: OKAMI_TLB_CONTEXT
0-1: 0
2-20: (OKAMI_TRAP_BAD_VADDR >> 12) << 2
21-31: PTEBase
0x16: OKAMI_TLB_PAGE_DIRECTORY
Intended for storing the root page directory
Useful for nested tlb misses.
63 Valid |
62 Reserved |
61-32 Address |
0-31 Word |
---|
63-44 VirtualAddress |
43-32 AddrSpaceID |
12-31 PhysicalAddress |
4-11 Reserved |
3 Global |
2 Dirty |
1 NonCacheable |
0 Valid |
---|
You might notice that TLB Entries don't have a flag for making pages read-only. This is because the behavior of the Dirty Flag acts as a form of write-protection; Okami can't write if the dirty flag is cleared. However, when it is set, write-access is allowed.