提交 b973f41a 编写于 作者: Z Zihao Yu

mips32: add tlb

上级 191c4883
......@@ -51,3 +51,6 @@ make_EHelper(syscall);
make_EHelper(eret);
make_EHelper(mfc0);
make_EHelper(mtc0);
make_EHelper(tlbwr);
make_EHelper(tlbwi);
make_EHelper(tlbp);
#include "cpu/exec.h"
#include "all-instr.h"
#include <setjmp.h>
static OpcodeEntry special_table [64] = {
/* b000 */ IDEX(shift, sll), EMPTY, IDEX(shift, srl), IDEX(shift, sra), IDEX(R, sll), EMPTY, IDEX(R, srl), IDEX(R, sra),
......@@ -48,8 +49,8 @@ static OpcodeEntry cop0_table [16] = {
};
static OpcodeEntry cop0co_table [64] = {
/* b000 */ EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
/* b001 */ EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
/* b000 */ EMPTY, EMPTY, EX(tlbwi), EMPTY, EMPTY, EMPTY, EX(tlbwr), EMPTY,
/* b001 */ EX(tlbp), EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
/* b010 */ EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
/* b011 */ EX(eret), EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
/* b100 */ EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
......@@ -79,6 +80,15 @@ static OpcodeEntry opcode_table [64] = {
};
make_EHelper(isa) {
extern jmp_buf intr_buf;
int setjmp_ret;
if ((setjmp_ret = setjmp(intr_buf)) != 0) {
// exception
int exce_code = setjmp_ret - 1;
void raise_intr(uint8_t, vaddr_t);
raise_intr(exce_code, cpu.pc);
return;
}
decinfo.isa.instr.val = instr_fetch(eip, 4);
decinfo.width = opcode_table[decinfo.isa.instr.opcode].width;
idex(eip, &opcode_table[decinfo.isa.instr.opcode]);
......
#include "cpu/exec.h"
#include "isa/intr.h"
void raise_intr(uint8_t, vaddr_t);
#define EX_SYSCALL 8
make_EHelper(syscall) {
#if defined(DIFF_TEST)
......@@ -27,6 +27,8 @@ make_EHelper(mfc0) {
uint32_t val;
switch (id_dest->reg) {
case 0: val = cpu.index; print_asm("mfc0 %s, index", id_src2->str); break;
case 10: val = cpu.entryhi.val; print_asm("mfc0 %s, entryhi", id_src2->str); break;
case 12: val = cpu.status; print_asm("mfc0 %s, status", id_src2->str); break;
case 13: val = cpu.cause; print_asm("mfc0 %s, cause", id_src2->str); break;
case 14: val = cpu.epc; print_asm("mfc0 %s, epc", id_src2->str); break;
......@@ -39,9 +41,28 @@ make_EHelper(mfc0) {
make_EHelper(mtc0) {
switch (id_dest->reg) {
case 0: cpu.index = id_src2->val; print_asm("mtc0 %s, index", id_src2->str); break;
case 2: cpu.entrylo0 = id_src2->val; print_asm("mtc0 %s, entrylo0", id_src2->str); break;
case 3: cpu.entrylo1 = id_src2->val; print_asm("mtc0 %s, entrylo1", id_src2->str); break;
case 10: cpu.entryhi.val = id_src2->val; print_asm("mtc0 %s, entryhi", id_src2->str); break;
case 12: cpu.status = id_src2->val; print_asm("mtc0 %s, status", id_src2->str); break;
case 13: cpu.cause = id_src2->val; print_asm("mtc0 %s, cause", id_src2->str); break;
case 14: cpu.epc = id_src2->val; print_asm("mtc0 %s, epc", id_src2->str); break;
default: assert(0);
}
}
make_EHelper(tlbwr) {
extern void tlbwr(void);
tlbwr();
}
make_EHelper(tlbwi) {
extern void tlbwi(void);
tlbwi();
}
make_EHelper(tlbp) {
extern void tlbp(void);
tlbp();
}
#include "reg.h"
#define EX_SYSCALL 8
#define EX_TLB_LD 2
#define EX_TLB_ST 3
#define TLB_REFILL 0x80
static inline bool isa_istatus(void) {
return false;
}
......@@ -20,6 +20,17 @@ typedef struct {
vaddr_t pc;
uint32_t epc;
union {
struct {
uint32_t ASID: 8;
uint32_t pad : 5;
uint32_t VPN2:19;
};
uint32_t val;
} entryhi;
uint32_t entrylo0, entrylo1;
uint32_t index;
bool INTR;
} CPU_state;
......
#include "cpu/rtl.h"
#include "isa/intr.h"
#include <setjmp.h>
#define EX_ENTRY 0x80000180
......@@ -8,8 +10,16 @@ void raise_intr(uint8_t NO, vaddr_t epc) {
*/
//TODO();
vaddr_t target = (NO & TLB_REFILL) ? 0x80000000 : EX_ENTRY;
NO &= ~TLB_REFILL;
cpu.cause = NO << 2;
cpu.epc = epc;
rtl_j(EX_ENTRY);
rtl_j(target);
}
jmp_buf intr_buf;
void longjmp_raise_intr(uint8_t NO) {
longjmp(intr_buf, NO + 1);
}
#include "nemu.h"
#include "memory/memory.h"
#include "isa/intr.h"
#include <stdlib.h>
#include <time.h>
#define NR_TLB 128
typedef union {
struct {
uint32_t ASID: 8;
uint32_t pad : 5;
uint32_t VPN2:19;
};
uint32_t val;
} EntryHi;
typedef union {
struct {
uint32_t G : 1;
uint32_t V : 1;
uint32_t D : 1;
uint32_t C : 3;
uint32_t PFN :24;
uint32_t pad : 2;
};
uint32_t val;
} EntryLo;
struct {
EntryHi hi;
EntryLo lo[2];
} tlb [NR_TLB];
void init_mmu(void) {
int i;
for (i = 0; i < NR_TLB; i ++) {
tlb[i].lo[0].V = tlb[i].lo[1].V = 0;
}
srand(time(0));
}
void update_tlb(int idx) {
tlb[idx].hi.val = cpu.entryhi.val;
tlb[idx].lo[0].val = cpu.entrylo0;
tlb[idx].lo[1].val = cpu.entrylo1;
}
void tlbwr(void) {
update_tlb(rand() % NR_TLB);
}
void tlbwi(void) {
update_tlb(cpu.index % NR_TLB);
}
void tlbp(void) {
int i;
for (i = 0; i < NR_TLB; i ++) {
if (tlb[i].hi.VPN2 == cpu.entryhi.VPN2) {
Log("match, i = %d", i);
cpu.index = i;
return;
}
}
cpu.index = -1;
}
extern void longjmp_raise_intr(uint8_t NO);
static inline int32_t search_ppn(vaddr_t addr, bool write) {
union {
struct {
uint32_t offset :12;
uint32_t lo_idx : 1;
uint32_t vpn :19;
};
uint32_t val;
} a;
a.val = addr;
int i;
for (i = 0; i < NR_TLB; i ++) {
if (tlb[i].hi.VPN2 == a.vpn) {
if (!tlb[i].lo[a.lo_idx].V) {
cpu.entryhi.VPN2 = a.vpn;
// Log("tlb[%d] invalid at cpu.pc = 0x%08x, badaddr = 0x%08x", i, cpu.pc, addr);
longjmp_raise_intr(write ? EX_TLB_ST : EX_TLB_LD);
return -1;
}
//Assert(tlb[i].lo[a.lo_idx].V, "cpu.pc = 0x%08x, addr = 0x%08x, lo0 = 0x%08x, lo1 = 0x%08x",
// cpu.pc, addr, tlb[i].lo[0].val, tlb[i].lo[1].val);
return tlb[i].lo[a.lo_idx].PFN;
}
}
cpu.entryhi.VPN2 = a.vpn;
// Log("tlb refill at cpu.pc = 0x%08x, badaddr = 0x%08x", cpu.pc, addr);
longjmp_raise_intr(TLB_REFILL | (write ? EX_TLB_ST : EX_TLB_LD));
return -1;
}
static inline paddr_t va2pa(vaddr_t addr, bool write) {
if ((addr & 0xa0000000u) == 0xa0000000u) {
return addr & ~0xa0000000u;
}
if ((addr & 0x80000000u) == 0) {
int32_t ppn = search_ppn(addr, write);
addr = (addr & 0xfff) | (ppn << 12);
}
static inline paddr_t va2pa(vaddr_t addr) {
return addr & ~0x80000000u;
}
uint32_t isa_vaddr_read(vaddr_t addr, int len) {
return paddr_read(va2pa(addr), len);
return paddr_read(va2pa(addr, false), len);
}
void isa_vaddr_write(vaddr_t addr, uint32_t data, int len) {
paddr_write(va2pa(addr), data, len);
paddr_write(va2pa(addr, true), data, len);
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册