|
|
@ -3,38 +3,60 @@ |
|
|
|
#include "util.h" |
|
|
|
|
|
|
|
#include <stddef.h> |
|
|
|
#include <stdio.h> |
|
|
|
|
|
|
|
#define TABLE_SIZE 0x34 |
|
|
|
|
|
|
|
static cpu_insn_handler primary_insn_handler[TABLE_SIZE] = {NULL}; |
|
|
|
void insn_lw(cpu_t *cpu, uint32_t insn); |
|
|
|
|
|
|
|
static cpu_insn_handler primary_insn_handler[TABLE_SIZE] = { |
|
|
|
[LW] = insn_lw, |
|
|
|
}; |
|
|
|
|
|
|
|
static cpu_insn_handler secondary_insn_handler[TABLE_SIZE] = {NULL}; |
|
|
|
|
|
|
|
static inline op_primary_t extract_primary_op(uint32_t insn) { |
|
|
|
return (insn >> 26) & 0x3f; |
|
|
|
} |
|
|
|
#define BITS(x, start, len) (((x) >> (start)) & ((1 << (len)) - 1)) |
|
|
|
|
|
|
|
static inline op_secondary_t extract_secondary_op(uint32_t insn) { |
|
|
|
return (insn >> 0) & 0x3f; |
|
|
|
} |
|
|
|
#define OP(insn) BITS(insn, 26, 6) |
|
|
|
#define RS(insn) BITS(insn, 21, 5) |
|
|
|
#define RT(insn) BITS(insn, 16, 5) |
|
|
|
#define RD(insn) BITS(insn, 11, 5) |
|
|
|
#define COMMENT(insn) BITS(insn, 6, 20) |
|
|
|
#define IMM5(insn) BITS(insn, 6, 5) |
|
|
|
#define OP2(insn) BITS(insn, 0, 6) |
|
|
|
#define IMM(insn) BITS(insn, 0, 16) |
|
|
|
|
|
|
|
void insn_execute(cpu_t *cpu, uint32_t raw_insn) { |
|
|
|
const op_primary_t op = extract_primary_op(raw_insn); |
|
|
|
const insn_t insn = *(insn_t *)&raw_insn; |
|
|
|
void insn_execute(cpu_t *cpu, uint32_t insn) |
|
|
|
{ |
|
|
|
const op_primary_t op = OP(insn); |
|
|
|
|
|
|
|
if (op == SPECIAL) { |
|
|
|
const op_secondary_t op2 = extract_secondary_op(raw_insn); |
|
|
|
if (op == SPECIAL) |
|
|
|
{ |
|
|
|
const op_secondary_t op2 = OP2(insn); |
|
|
|
|
|
|
|
if (op2 > TABLE_SIZE || secondary_insn_handler[op2] == NULL) { |
|
|
|
fatal("unsupported instruction: insn=%08x, op=%02x, op2=%02x", raw_insn, |
|
|
|
if (op2 > TABLE_SIZE || secondary_insn_handler[op2] == NULL) |
|
|
|
{ |
|
|
|
fatal("unsupported instruction: insn=%08x, op=%02x, op2=%02x", insn, |
|
|
|
op, op2); |
|
|
|
} |
|
|
|
|
|
|
|
secondary_insn_handler[op2](cpu, insn); |
|
|
|
} |
|
|
|
|
|
|
|
if (op > TABLE_SIZE || primary_insn_handler[op] == NULL) { |
|
|
|
fatal("unsupported instruction: insn=%08x, op=%02x", raw_insn, op); |
|
|
|
if (op > TABLE_SIZE || primary_insn_handler[op] == NULL) |
|
|
|
{ |
|
|
|
fatal("unsupported instruction: insn=%08x, op=%02x", insn, op); |
|
|
|
} |
|
|
|
|
|
|
|
primary_insn_handler[op](cpu, insn); |
|
|
|
} |
|
|
|
|
|
|
|
void insn_lw(cpu_t *cpu, uint32_t insn) |
|
|
|
{ |
|
|
|
const uint8_t rs = RS(insn); |
|
|
|
const uint8_t rt = RT(insn); |
|
|
|
const uint16_t imm = IMM(insn); |
|
|
|
|
|
|
|
printf("LW R%u, [R%u + %x]\n", rt, rs, imm); |
|
|
|
cpu->regs[rt] = cpu_read32(cpu, cpu->regs[rs] + imm); |
|
|
|
} |