[Modified] change the way we decode and exec
This commit is contained in:
@@ -10,7 +10,7 @@
|
|||||||
#define COMMON_H__
|
#define COMMON_H__
|
||||||
|
|
||||||
#ifdef DEBUG_MODE
|
#ifdef DEBUG_MODE
|
||||||
#define Log(fmt, ...) printf("[%s@%d %ld] " fmt "\n", __FILE__, __LINE__, clock(), ## __VA_ARGS__)
|
#define Log(fmt, ...) printf("[%s:%d %ld] " fmt "\n", __FILE__, __LINE__, clock(), ## __VA_ARGS__)
|
||||||
|
|
||||||
#define panic(x) do { \
|
#define panic(x) do { \
|
||||||
Log(x); \
|
Log(x); \
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#define DEVADDR_H__
|
#define DEVADDR_H__
|
||||||
|
|
||||||
#define RAM_ADDR 0x0000'0000
|
#define RAM_ADDR 0x0000'0000
|
||||||
#define IMG_ADDR 0x0000'8000
|
#define IMG_ADDR 0x0001'04d8
|
||||||
#define STK_ADDR 0x2000'0000
|
#define STK_ADDR 0x2000'0000
|
||||||
|
|
||||||
#define DEVICE_BASE 0xa0000000
|
#define DEVICE_BASE 0xa0000000
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ CC := $(LA_BIN_PATH)/$(LA_PREFIX)gcc
|
|||||||
CXX := $(LA_BIN_PATH)/$(LA_PREFIX)g++
|
CXX := $(LA_BIN_PATH)/$(LA_PREFIX)g++
|
||||||
OD := $(LA_BIN_PATH)/$(LA_PREFIX)objdump
|
OD := $(LA_BIN_PATH)/$(LA_PREFIX)objdump
|
||||||
OC := $(LA_BIN_PATH)/$(LA_PREFIX)objcopy
|
OC := $(LA_BIN_PATH)/$(LA_PREFIX)objcopy
|
||||||
|
RE := $(LA_BIN_PATH)/$(LA_PREFIX)readelf
|
||||||
|
|
||||||
CMAKE := cmake
|
CMAKE := cmake
|
||||||
|
|
||||||
@@ -19,8 +20,10 @@ FILES := $(shell find src -name *.c)
|
|||||||
.PHONY: build clean
|
.PHONY: build clean
|
||||||
|
|
||||||
build:
|
build:
|
||||||
$(CC) $(FILES) -o $(BUILD_DIR)/$(BIN)
|
$(CC) $(FILES) -static --no-pic -march=loongarch32r -o $(BUILD_DIR)/$(BIN)
|
||||||
$(OD) -D $(BUILD_DIR)/$(BIN) > $(BUILD_DIR)/$(BIN).dump
|
$(OD) -D $(BUILD_DIR)/$(BIN) > $(BUILD_DIR)/$(BIN).dump
|
||||||
|
$(RE) -a $(BUILD_DIR)/$(BIN) > $(BUILD_DIR)/$(BIN).info
|
||||||
|
$(OC) $(BUILD_DIR)/$(BIN) -O binary $(BUILD_DIR)/$(BIN).bin
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(BUILD_DIR)
|
rm -rf $(BUILD_DIR)
|
||||||
200
lasim/la32r.cc
200
lasim/la32r.cc
@@ -1,4 +1,5 @@
|
|||||||
#include <common.h>
|
#include <common.h>
|
||||||
|
#include <devaddr.h>
|
||||||
#include <la32r.hh>
|
#include <la32r.hh>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@@ -72,25 +73,199 @@ public:
|
|||||||
}
|
}
|
||||||
} Regs ;
|
} Regs ;
|
||||||
|
|
||||||
constexpr u32 getbits(u32 hi, u32 lo, u32 data) {
|
constexpr u32 gb(u32 hi, u32 lo, u32 data) {
|
||||||
|
panicifnot(hi >= lo);
|
||||||
|
|
||||||
data = data >> lo;
|
data = data >> lo;
|
||||||
u32 mask = ((u64) 0x1 << (hi + 1)) - 1;
|
u32 width = hi - lo + 1;
|
||||||
|
u32 mask = (u32)(~0) >> (32 - width);
|
||||||
return data & mask;
|
return data & mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
void decode_and_exec(u32 inst) {
|
constexpr u32 sext(u32 data, u32 width) {
|
||||||
|
u32 upper = 32 - width;
|
||||||
|
u32 result = (i32)(data << upper) >> upper;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
if (getbits(31, 15, inst) == 0b00000000000100000) {
|
bool check(const char *instfmt, u32 inst) {
|
||||||
u32 rd = getbits( 4, 0, inst);
|
size_t len = strlen(instfmt);
|
||||||
u32 rj = getbits( 9, 5, inst);
|
panicifnot(len >= 32);
|
||||||
u32 rk = getbits(14, 10, inst);
|
|
||||||
|
|
||||||
u32 tmp = Regs[rj] + Regs[rk];
|
u32 hit = 0;
|
||||||
Regs[rd] = getbits(31, 0, tmp);
|
|
||||||
return;
|
// alert ! i should gt 0 not geq 0
|
||||||
|
for (size_t i = len; i > 0; --i) {
|
||||||
|
auto idx = i - 1;
|
||||||
|
|
||||||
|
if (std::tolower(instfmt[idx]) == 'x') {
|
||||||
|
inst >>= 1;
|
||||||
|
hit += 1;
|
||||||
|
continue;
|
||||||
|
} else if (instfmt[idx] == '0' && (inst & 0x1) == 0x0) {
|
||||||
|
inst >>= 1;
|
||||||
|
hit += 1;
|
||||||
|
continue;
|
||||||
|
} else if (instfmt[idx] == '1' && (inst & 0x1) == 0x1) {
|
||||||
|
inst >>= 1;
|
||||||
|
hit += 1;
|
||||||
|
continue;
|
||||||
|
} else if (strchr("'., ", instfmt[idx])) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
panic("Invalid operation or have not implemented yet.");
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hit == 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 SLL(u32 data, u32 sa) {
|
||||||
|
if (sa == 0)
|
||||||
|
return data;
|
||||||
|
|
||||||
|
return data << sa;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 SRL(u32 data, u32 sa) {
|
||||||
|
if (sa == 0)
|
||||||
|
return data;
|
||||||
|
|
||||||
|
return data >> sa;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 SRA(u32 data, u32 sa) {
|
||||||
|
if (sa == 0)
|
||||||
|
return data;
|
||||||
|
|
||||||
|
return (i32)data >> sa;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BEGIN_CHECK() if (false) {}
|
||||||
|
|
||||||
|
#define INST(str, instname, extracond, ...) \
|
||||||
|
else if (check((str), (inst)) && (extracond)) { \
|
||||||
|
curinst = #instname; \
|
||||||
|
__VA_ARGS__; \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void decode_and_exec(u32 inst) {
|
||||||
|
|
||||||
|
// These decode is fixed
|
||||||
|
u32 rd = gb( 4, 0, inst);
|
||||||
|
u32 rj = gb( 9, 5, inst);
|
||||||
|
u32 cj = gb( 7, 5, inst);
|
||||||
|
u32 rk = gb(14, 10, inst);
|
||||||
|
|
||||||
|
|
||||||
|
u32 ui5 = rk;
|
||||||
|
u32 ui12 = gb(21, 10, inst);
|
||||||
|
u32 si12 = sext(ui12, 12);
|
||||||
|
u32 si14 = sext(gb(23, 10, inst), 14);
|
||||||
|
u32 si20 = sext(gb(24, 5, inst), 20);
|
||||||
|
|
||||||
|
u32 csr = gb(23, 10, inst);
|
||||||
|
|
||||||
|
u32 offs_15_00 = gb(25, 10, inst);
|
||||||
|
u32 offs_20_16 = gb( 4, 0, inst);
|
||||||
|
u32 offs_25_16 = gb( 9, 0, inst);
|
||||||
|
|
||||||
|
u32 code = rd << 0 | rj << 5 | rk << 10;
|
||||||
|
u32 level = code;
|
||||||
|
u32 hint = code;
|
||||||
|
|
||||||
|
u32 code5 = rd;
|
||||||
|
u32 hint5 = code5;
|
||||||
|
u32 op = code5;
|
||||||
|
|
||||||
|
const char *curinst = nullptr;
|
||||||
|
|
||||||
|
BEGIN_CHECK()
|
||||||
|
INST("00000000000000000'1100'0'xxxxx'00000", RDCNTID.W, gb(4, 0, inst) == 0)
|
||||||
|
INST("00000000000000000'1100'0'00000'xxxxx", RDCNTVL.W, gb(9, 5, inst) == 0)
|
||||||
|
INST("00000000000000000'1100'1'00000'xxxxx", RDCNTVH.W, gb(9, 5, inst) == 0)
|
||||||
|
|
||||||
|
INST("00000000000'100000'xxxxx'xxxxx'xxxxx", ADD.W, true, Regs[rd] = Regs[rj] + Regs[rk])
|
||||||
|
INST("00000000000'100010'xxxxx'xxxxx'xxxxx", SUB.W, true, Regs[rd] = Regs[rj] - Regs[rk])
|
||||||
|
INST("00000000000'100100'xxxxx'xxxxx'xxxxx", SLT, true, Regs[rd] = (i32)Regs[rj] < (i32)Regs[rk])
|
||||||
|
INST("00000000000'100101'xxxxx'xxxxx'xxxxx", SLTU, true, Regs[rd] = Regs[rj] < Regs[rk])
|
||||||
|
INST("00000000000'101000'xxxxx'xxxxx'xxxxx", NOR, true, Regs[rd] = ~(Regs[rj] | Regs[rk]))
|
||||||
|
INST("00000000000'101001'xxxxx'xxxxx'xxxxx", AND, true, Regs[rd] = Regs[rj] & Regs[rk])
|
||||||
|
INST("00000000000'101010'xxxxx'xxxxx'xxxxx", OR, true, Regs[rd] = Regs[rj] | Regs[rk])
|
||||||
|
INST("00000000000'101011'xxxxx'xxxxx'xxxxx", XOR, true, Regs[rd] = Regs[rj] ^ Regs[rk])
|
||||||
|
INST("00000000000'101110'xxxxx'xxxxx'xxxxx", SLL.W, true, Regs[rd] = SLL(Regs[rj], gb(4, 0, Regs[rk])))
|
||||||
|
INST("00000000000'101111'xxxxx'xxxxx'xxxxx", SRL.W, true, Regs[rd] = SRL(Regs[rj], gb(4, 0, Regs[rk])))
|
||||||
|
INST("00000000000'110000'xxxxx'xxxxx'xxxxx", SRA.W, true, Regs[rd] = SRA(Regs[rj], gb(4, 0, Regs[rk])))
|
||||||
|
INST("00000000000'111000'xxxxx'xxxxx'xxxxx", MUL.W, true, Regs[rd] = Regs[rj] * Regs[rk])
|
||||||
|
INST("00000000000'111001'xxxxx'xxxxx'xxxxx", MULH.W, true, Regs[rd] = (u32)(((i64)(i32)Regs[rj] * (i64)(i32)Regs[rk]) >> 32))
|
||||||
|
INST("00000000000'111010'xxxxx'xxxxx'xxxxx", MULH.WU, true, Regs[rd] = (u32)(((u64)Regs[rj] * (u64)Regs[rk]) >> 32))
|
||||||
|
INST("0000000000'1000000'xxxxx'xxxxx'xxxxx", DIV.W, true, Regs[rd] = (i32)Regs[rj] / (i32)Regs[rk])
|
||||||
|
INST("0000000000'1000001'xxxxx'xxxxx'xxxxx", MOD.W, true, Regs[rd] = (i32)Regs[rj] % (i32)Regs[rk])
|
||||||
|
INST("0000000000'1000010'xxxxx'xxxxx'xxxxx", DIV.WU, true, Regs[rd] = Regs[rj] / Regs[rk])
|
||||||
|
INST("0000000000'1000011'xxxxx'xxxxx'xxxxx", MOD.WU, true, Regs[rd] = Regs[rj] % Regs[rk])
|
||||||
|
|
||||||
|
INST("0000000000'1010100'xxxxx xxxxx xxxxx", BREAK, true, )
|
||||||
|
INST("0000000000'1010110'xxxxx xxxxx xxxxx", SYSCALL, true, )
|
||||||
|
|
||||||
|
INST("000000000'10000'000'xxxxx'xxxxx'xxxxx", SLLI.W, true, Regs[rd] = SLL(Regs[rj], ui5))
|
||||||
|
INST("000000000'10000'001'xxxxx'xxxxx'xxxxx", SRLI.W, true, Regs[rd] = SRL(Regs[rj], ui5))
|
||||||
|
INST("000000000'10000'010'xxxxx'xxxxx'xxxxx", SRAI.W, true, Regs[rd] = SRA(Regs[rj], ui5))
|
||||||
|
|
||||||
|
INST("000000'1000'xxxxxxx xxxxx'xxxxx'xxxxx", SLTI, true, Regs[rd] = (i32)Regs[rj] < (i32)si12)
|
||||||
|
INST("000000'1001'xxxxxxx xxxxx'xxxxx'xxxxx", SLTUI, true, Regs[rd] = Regs[rj] < si12)
|
||||||
|
INST("000000'1010'xxxxxxx xxxxx'xxxxx'xxxxx", ADDI.W, true, Regs[rd] = Regs[rj] + si12)
|
||||||
|
INST("000000'1101'xxxxxxx xxxxx'xxxxx'xxxxx", ANDI, true, Regs[rd] = Regs[rj] & ui12)
|
||||||
|
INST("000000'1110'xxxxxxx xxxxx'xxxxx'xxxxx", ORI, true, Regs[rd] = Regs[rj] | ui12)
|
||||||
|
INST("000000'1111'xxxxxxx xxxxx'xxxxx'xxxxx", XORI, true, Regs[rd] = Regs[rj] ^ ui12)
|
||||||
|
|
||||||
|
INST("00000'100'xxxxxxxxxxxxxx'00000'xxxxx", CSRRD, gb(9, 5, inst) == 0, )
|
||||||
|
INST("00000'100'xxxxxxxxxxxxxx'00001'xxxxx", CSRWR, gb(9, 5, inst) == 1, )
|
||||||
|
INST("00000'100'xxxxxxxxxxxxxx'xxxxx'xxxxx", CSRXCHG, gb(9, 5, inst) > 1, )
|
||||||
|
|
||||||
|
INST("00000'11000'xxxxxxxxxxxx'xxxxx'xxxxx", CACOP, true, )
|
||||||
|
|
||||||
|
INST("00000'1100'1001000001'010'00000'00000", TLBSRCH, true, )
|
||||||
|
INST("00000'1100'1001000001'011'00000'00000", TLBRD, true, )
|
||||||
|
INST("00000'1100'1001000001'100'00000'00000", TLBWR, true, )
|
||||||
|
INST("00000'1100'1001000001'101'00000'00000", TLBFILL, true, )
|
||||||
|
INST("00000'1100'1001000001'110'00000'00000", ERTN, true, )
|
||||||
|
|
||||||
|
INST("00000'1100'1001'0001'xxxxx xxxxx xxxxx", IDLE, true, )
|
||||||
|
INST("00000'1100'1001'0011'xxxxx'xxxxx'xxxxx", INVTLB, true, )
|
||||||
|
|
||||||
|
INST("000'1010'xxxxxxxxxxxxxxxxxxxx'xxxxx", LU12I.W, true, )
|
||||||
|
INST("000'1110'xxxxxxxxxxxxxxxxxxxx'xxxxx", PCADDU12I, true, )
|
||||||
|
|
||||||
|
INST("00'100000'xxxxxxxxxxxxxx'xxxxx'xxxxx", LL.W, true, )
|
||||||
|
INST("00'100001'xxxxxxxxxxxxxx'xxxxx'xxxxx", SC.W, true, )
|
||||||
|
|
||||||
|
INST("00'10100000'xxxxxxxxxxxx'xxxxx'xxxxx", LD.B, true, )
|
||||||
|
INST("00'10100001'xxxxxxxxxxxx'xxxxx'xxxxx", LD.H, true, )
|
||||||
|
INST("00'10100010'xxxxxxxxxxxx'xxxxx'xxxxx", LD.W, true, )
|
||||||
|
INST("00'10100100'xxxxxxxxxxxx'xxxxx'xxxxx", ST.B, true, )
|
||||||
|
INST("00'10100101'xxxxxxxxxxxx'xxxxx'xxxxx", ST.H, true, )
|
||||||
|
INST("00'10100110'xxxxxxxxxxxx'xxxxx'xxxxx", ST.W, true, )
|
||||||
|
INST("00'10101000'xxxxxxxxxxxx'xxxxx'xxxxx", LD.BU, true, )
|
||||||
|
INST("00'10101001'xxxxxxxxxxxx'xxxxx'xxxxx", LD.HU, true, )
|
||||||
|
INST("00'10101011'xxxxxxxxxxxx'xxxxx'xxxxx", PRELD, true, )
|
||||||
|
|
||||||
|
INST("00'111000011100100'xxxxx xxxxx xxxxx", DBAR, true, )
|
||||||
|
INST("00'111000011100101'xxxxx xxxxx xxxxx", IBAR, true, )
|
||||||
|
|
||||||
|
INST("0'10010'xxxxxxxxxxxxxxxx'00xxx'xxxxx", BCEQZ, gb(9, 8, inst) == 0, )
|
||||||
|
INST("0'10010'xxxxxxxxxxxxxxxx'01xxx'xxxxx", BCNEZ, gb(9, 8, inst) == 1, )
|
||||||
|
INST("0'10011'xxxxxxxxxxxxxxxx'xxxxx'xxxxx", JIRL, true, )
|
||||||
|
INST("0'10100'xxxxxxxxxxxxxxxx'xxxxx xxxxx", B, true, )
|
||||||
|
INST("0'10101'xxxxxxxxxxxxxxxx'xxxxx xxxxx", BL, true, )
|
||||||
|
INST("0'10110'xxxxxxxxxxxxxxxx'xxxxx'xxxxx", BEQ, true, )
|
||||||
|
INST("0'10111'xxxxxxxxxxxxxxxx'xxxxx'xxxxx", BNE, true, )
|
||||||
|
INST("0'11000'xxxxxxxxxxxxxxxx'xxxxx'xxxxx", BLT, true, )
|
||||||
|
INST("0'11001'xxxxxxxxxxxxxxxx'xxxxx'xxxxx", BGE, true, )
|
||||||
|
INST("0'11010'xxxxxxxxxxxxxxxx'xxxxx'xxxxx", BLTU, true, )
|
||||||
|
INST("0'11011'xxxxxxxxxxxxxxxx'xxxxx'xxxxx", BGEU, true, )
|
||||||
|
|
||||||
|
printf("%08x: %s\n", inst, curinst);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 fetch() {
|
u32 fetch() {
|
||||||
@@ -101,11 +276,10 @@ u32 fetch() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LA32R::LA32R(SystemBus *bus) {
|
LA32R::LA32R(SystemBus *bus) {
|
||||||
sysbus = bus;
|
sysbus = bus;
|
||||||
|
|
||||||
Regs[PC] = 0x0000'0000;
|
Regs[PC] = IMG_ADDR;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LA32R::Step(unsigned in) {
|
void LA32R::Step(unsigned in) {
|
||||||
|
|||||||
@@ -8,18 +8,18 @@
|
|||||||
#include <devaddr.h>
|
#include <devaddr.h>
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
if (argc < 2) {
|
// if (argc < 2) {
|
||||||
std::cout << "Usage: sim <bin>";
|
// std::cout << "Usage: sim <bin>";
|
||||||
return 0;
|
// return 0;
|
||||||
}
|
// }
|
||||||
|
|
||||||
SystemBus bus;
|
SystemBus bus;
|
||||||
Memory ram(2 * 1024 * 1024);
|
Memory ram(2 * 1024 * 1024);
|
||||||
Memory stk(256 * 1024);
|
Memory stk(256 * 1024);
|
||||||
|
|
||||||
Memory flash(1024 * 1024);
|
Memory flash(1024 * 1024);
|
||||||
flash.load(argv[1]);
|
flash.load("../laos/build/neula-os");
|
||||||
ram.load(&flash, IMG_ADDR, flash.size());
|
ram.load(&flash, 0x0, flash.size());
|
||||||
|
|
||||||
bus.regdev(&ram, RAM_ADDR);
|
bus.regdev(&ram, RAM_ADDR);
|
||||||
bus.regdev(&stk, STK_ADDR);
|
bus.regdev(&stk, STK_ADDR);
|
||||||
|
|||||||
Reference in New Issue
Block a user