[Add] software simulator add
This commit is contained in:
@@ -13,6 +13,7 @@ if (${CMAKE_BUILD_TYPE} STREQUAL "Debug")
|
|||||||
add_compile_options(-D DEBUG_MODE)
|
add_compile_options(-D DEBUG_MODE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
include_directories(${CMAKE_SOURCE_DIR}/include)
|
||||||
|
|
||||||
# ----- ----- 构建虚拟外设 ----- -----
|
# ----- ----- 构建虚拟外设 ----- -----
|
||||||
set(LABUS labus)
|
set(LABUS labus)
|
||||||
|
|||||||
36
include/common.h
Normal file
36
include/common.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <ctime>
|
||||||
|
#include <cstring>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#ifndef COMMON_H__
|
||||||
|
#define COMMON_H__
|
||||||
|
|
||||||
|
#ifdef DEBUG_MODE
|
||||||
|
#define Log(fmt, ...) printf("[%s@%d %ld] " fmt "\n", __FILE__, __LINE__, clock(), ## __VA_ARGS__)
|
||||||
|
|
||||||
|
#define panic(x) do { \
|
||||||
|
Log(x); \
|
||||||
|
exit(EXIT_FAILURE); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define panicifnot(cond) do { \
|
||||||
|
if (!(cond)) { \
|
||||||
|
Log(#cond " fail"); \
|
||||||
|
exit(EXIT_FAILURE); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define Log(...)
|
||||||
|
#define panic(x)
|
||||||
|
#define panicifnot(cond)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
22
include/devaddr.h
Normal file
22
include/devaddr.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef DEVADDR_H__
|
||||||
|
#define DEVADDR_H__
|
||||||
|
|
||||||
|
#define RAM_ADDR 0x0000'0000
|
||||||
|
#define IMG_ADDR 0x0000'8000
|
||||||
|
#define STK_ADDR 0x2000'0000
|
||||||
|
|
||||||
|
#define DEVICE_BASE 0xa0000000
|
||||||
|
#define MMIO_BASE 0xa0000000
|
||||||
|
|
||||||
|
#define SERIAL_PORT (DEVICE_BASE + 0x00003f8)
|
||||||
|
#define KBD_ADDR (DEVICE_BASE + 0x0000060)
|
||||||
|
#define RTC_ADDR (DEVICE_BASE + 0x0000048)
|
||||||
|
#define VGACTL_ADDR (DEVICE_BASE + 0x0000100)
|
||||||
|
#define AUDIO_ADDR (DEVICE_BASE + 0x0000200)
|
||||||
|
#define DISK_ADDR (DEVICE_BASE + 0x0000300)
|
||||||
|
#define FB_ADDR (MMIO_BASE + 0x1000000)
|
||||||
|
#define AUDIO_SBUF_ADDR (MMIO_BASE + 0x1200000)
|
||||||
|
|
||||||
|
#endif
|
||||||
1
labus/device.cc
Normal file
1
labus/device.cc
Normal file
@@ -0,0 +1 @@
|
|||||||
|
#include <device.hh>
|
||||||
140
labus/include/device.hh
Normal file
140
labus/include/device.hh
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
class Device {
|
||||||
|
public:
|
||||||
|
Device() = default;
|
||||||
|
|
||||||
|
virtual const size_t &size() const = 0;
|
||||||
|
|
||||||
|
virtual void write(char *buf, size_t addr, size_t len) = 0;
|
||||||
|
virtual void read(char *buf, size_t addr, size_t len) = 0;
|
||||||
|
|
||||||
|
virtual void write64(uint64_t &dword, size_t addr) = 0;
|
||||||
|
virtual void read64(uint64_t &dword, size_t addr) = 0;
|
||||||
|
|
||||||
|
virtual void write32(uint32_t &word, size_t addr) = 0;
|
||||||
|
virtual void read32(uint32_t &word, size_t addr) = 0;
|
||||||
|
|
||||||
|
virtual void write16(uint16_t &hword, size_t addr) = 0;
|
||||||
|
virtual void read16(uint16_t &hword, size_t addr) = 0;
|
||||||
|
|
||||||
|
virtual void write8(uint8_t &byte, size_t addr) = 0;
|
||||||
|
virtual void read8(uint8_t &byte, size_t addr) = 0;
|
||||||
|
|
||||||
|
virtual ~Device() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class WRDevice : public Device{
|
||||||
|
size_t devsiz;
|
||||||
|
public:
|
||||||
|
WRDevice(size_t siz);
|
||||||
|
|
||||||
|
virtual const size_t &size() const;
|
||||||
|
|
||||||
|
virtual void write(char *buf, size_t addr, size_t len);
|
||||||
|
virtual void read(char *buf, size_t addr, size_t len);
|
||||||
|
|
||||||
|
virtual void write64(uint64_t &dword, size_t addr);
|
||||||
|
virtual void read64(uint64_t &dword, size_t addr);
|
||||||
|
|
||||||
|
virtual void write32(uint32_t &word, size_t addr);
|
||||||
|
virtual void read32(uint32_t &word, size_t addr);
|
||||||
|
|
||||||
|
virtual void write16(uint16_t &hword, size_t addr);
|
||||||
|
virtual void read16(uint16_t &hword, size_t addr);
|
||||||
|
|
||||||
|
virtual void write8(uint8_t &byte, size_t addr);
|
||||||
|
virtual void read8(uint8_t &byte, size_t addr);
|
||||||
|
|
||||||
|
virtual ~WRDevice() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
WRDevice<T>::WRDevice(size_t siz) : devsiz(siz) {}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
const size_t &WRDevice<T>::size() const { return devsiz; }
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void WRDevice<T>::write(char *buf, size_t addr, size_t len) {}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void WRDevice<T>::read(char *buf, size_t addr, size_t len) {}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void WRDevice<T>::write64(uint64_t &dword, size_t addr) {
|
||||||
|
uint8_t buf[sizeof(dword)];
|
||||||
|
buf[0] = (dword >> 0) & 0xFF;
|
||||||
|
buf[1] = (dword >> 8) & 0xFF;
|
||||||
|
buf[2] = (dword >> 16) & 0xFF;
|
||||||
|
buf[3] = (dword >> 24) & 0xFF;
|
||||||
|
buf[4] = (dword >> 32) & 0xFF;
|
||||||
|
buf[5] = (dword >> 40) & 0xFF;
|
||||||
|
buf[6] = (dword >> 48) & 0xFF;
|
||||||
|
buf[7] = (dword >> 56) & 0xFF;
|
||||||
|
static_cast<T *>(this)->write((char *)buf, addr, sizeof(dword));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void WRDevice<T>::read64(uint64_t &dword, size_t addr) {
|
||||||
|
uint8_t buf[sizeof(dword)];
|
||||||
|
static_cast<T *>(this)->read((char *)buf, addr, sizeof(dword));
|
||||||
|
dword = (uint64_t) buf[0];
|
||||||
|
dword |= (uint64_t) buf[1] << 8;
|
||||||
|
dword |= (uint64_t) buf[2] << 16;
|
||||||
|
dword |= (uint64_t) buf[3] << 24;
|
||||||
|
dword |= (uint64_t) buf[4] << 32;
|
||||||
|
dword |= (uint64_t) buf[5] << 40;
|
||||||
|
dword |= (uint64_t) buf[6] << 48;
|
||||||
|
dword |= (uint64_t) buf[7] << 56;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void WRDevice<T>::write32(uint32_t &word, size_t addr) {
|
||||||
|
uint8_t buf[sizeof(word)];
|
||||||
|
buf[0] = (word >> 0) & 0xFF;
|
||||||
|
buf[1] = (word >> 8) & 0xFF;
|
||||||
|
buf[2] = (word >> 16) & 0xFF;
|
||||||
|
buf[3] = (word >> 24) & 0xFF;
|
||||||
|
static_cast<T *>(this)->write((char *)buf, addr, sizeof(word));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void WRDevice<T>::read32(uint32_t &word, size_t addr) {
|
||||||
|
uint8_t buf[sizeof(word)];
|
||||||
|
static_cast<T *>(this)->read((char *)buf, addr, sizeof(word));
|
||||||
|
word = (uint32_t) buf[0];
|
||||||
|
word |= (uint32_t) buf[1] << 8;
|
||||||
|
word |= (uint32_t) buf[2] << 16;
|
||||||
|
word |= (uint32_t) buf[3] << 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void WRDevice<T>::write16(uint16_t &hword, size_t addr) {
|
||||||
|
uint8_t buf[sizeof(hword)];
|
||||||
|
buf[0] = (hword >> 0) & 0xFF;
|
||||||
|
buf[1] = (hword >> 8) & 0xFF;
|
||||||
|
static_cast<T *>(this)->write((char *)buf, addr, sizeof(hword));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void WRDevice<T>::read16(uint16_t &hword, size_t addr) {
|
||||||
|
uint8_t buf[sizeof(hword)];
|
||||||
|
static_cast<T *>(this)->read((char *)buf, addr, sizeof(hword));
|
||||||
|
hword = (uint16_t) buf[0];
|
||||||
|
hword |= (uint16_t) buf[1] << 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void WRDevice<T>::write8(uint8_t &byte, size_t addr) {
|
||||||
|
static_cast<T *>(this)->write((char *)&byte, addr, sizeof(byte));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void WRDevice<T>::read8(uint8_t &byte, size_t addr) {
|
||||||
|
static_cast<T *>(this)->read((char *)&byte, addr, sizeof(byte));
|
||||||
|
}
|
||||||
19
labus/include/memory.hh
Normal file
19
labus/include/memory.hh
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <device.hh>
|
||||||
|
|
||||||
|
class Memory : public WRDevice<Memory> {
|
||||||
|
char *data;
|
||||||
|
bool wen;
|
||||||
|
bool ren;
|
||||||
|
bool xen;
|
||||||
|
public:
|
||||||
|
Memory(size_t siz, bool w = true, bool r = true, bool x = true);
|
||||||
|
~Memory();
|
||||||
|
|
||||||
|
void load(const char *path);
|
||||||
|
void load(Memory *mem, size_t addr, size_t len);
|
||||||
|
|
||||||
|
void write(char *buf, size_t addr, size_t len);
|
||||||
|
void read(char *buf, size_t addr, size_t len);
|
||||||
|
};
|
||||||
10
labus/include/serial.hh
Normal file
10
labus/include/serial.hh
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <device.hh>
|
||||||
|
|
||||||
|
class Serial : public WRDevice<Serial> {
|
||||||
|
public:
|
||||||
|
Serial(size_t siz);
|
||||||
|
|
||||||
|
void write(char *buf, size_t addr, size_t len);
|
||||||
|
};
|
||||||
@@ -1 +1,33 @@
|
|||||||
int fetch();
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include <device.hh>
|
||||||
|
|
||||||
|
class SystemBus {
|
||||||
|
std::map<uint64_t, Device *> iomap;
|
||||||
|
|
||||||
|
std::pair<const uint64_t, Device *> &finddev(uint64_t addr);
|
||||||
|
|
||||||
|
public:
|
||||||
|
SystemBus() = default;
|
||||||
|
|
||||||
|
void regdev(Device *dev, uint64_t addr);
|
||||||
|
|
||||||
|
void write(char *buf, size_t addr, size_t len);
|
||||||
|
void read(char *buf, size_t addr, size_t len);
|
||||||
|
|
||||||
|
void write64(uint64_t &dword, size_t addr);
|
||||||
|
void read64(uint64_t &dword, size_t addr);
|
||||||
|
|
||||||
|
void write32(uint32_t &word, size_t addr);
|
||||||
|
void read32(uint32_t &word, size_t addr);
|
||||||
|
|
||||||
|
void write16(uint16_t &hword, size_t addr);
|
||||||
|
void read16(uint16_t &hword, size_t addr);
|
||||||
|
|
||||||
|
void write8(uint8_t &byte, size_t addr);
|
||||||
|
void read8(uint8_t &byte, size_t addr);
|
||||||
|
};
|
||||||
40
labus/memory.cc
Normal file
40
labus/memory.cc
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#include <memory.hh>
|
||||||
|
#include <common.h>
|
||||||
|
|
||||||
|
Memory::Memory(size_t siz, bool w, bool r, bool x)
|
||||||
|
: WRDevice(siz), wen(w), ren(r), xen(x) {
|
||||||
|
data = new char[siz];
|
||||||
|
memset((void *)data, 0, siz);
|
||||||
|
}
|
||||||
|
|
||||||
|
Memory::~Memory() {
|
||||||
|
if (data) {
|
||||||
|
delete [] data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Memory::load(const char *path) {
|
||||||
|
std::fstream ifs(path, std::ios::in | std::ios::binary);
|
||||||
|
panicifnot(ifs);
|
||||||
|
ifs.read(data, this->size());
|
||||||
|
ifs.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Memory::load(Memory *mem, size_t addr, size_t len) {
|
||||||
|
panicifnot(addr + len < this->size());
|
||||||
|
memcpy(&data[addr], mem->data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Memory::write(char *buf, size_t addr, size_t len) {
|
||||||
|
if (!wen)
|
||||||
|
panic("permission denied");
|
||||||
|
size_t actlen = addr + len >= this->size() ? this->size() - addr : len;
|
||||||
|
memcpy(&data[addr], buf, actlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Memory::read(char *buf, size_t addr, size_t len) {
|
||||||
|
if (!ren)
|
||||||
|
panic("permission denied");
|
||||||
|
size_t actlen = addr + len >= this->size() ? this->size() - addr : len;
|
||||||
|
memcpy(buf, &data[addr], actlen);
|
||||||
|
}
|
||||||
10
labus/serial.cc
Normal file
10
labus/serial.cc
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#include <serial.hh>
|
||||||
|
#include <common.h>
|
||||||
|
|
||||||
|
Serial::Serial(size_t siz) : WRDevice(siz) {}
|
||||||
|
|
||||||
|
void Serial::write(char *buf, size_t addr, size_t len) {
|
||||||
|
for (size_t i = 0; i < len; ++i)
|
||||||
|
putc(buf[i], stdout);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
@@ -1,3 +1,66 @@
|
|||||||
int fetch() {
|
#include <sysbus.hh>
|
||||||
return 0;
|
#include <common.h>
|
||||||
|
|
||||||
|
std::pair<const uint64_t, Device *> &SystemBus::finddev(uint64_t addr) {
|
||||||
|
Device *dev = nullptr;
|
||||||
|
auto &&iter = iomap.upper_bound(addr);
|
||||||
|
if (iter == iomap.begin())
|
||||||
|
panic("device not found");
|
||||||
|
iter--;
|
||||||
|
if (iter->first <= addr && iter->first + iter->second->size() > addr)
|
||||||
|
dev = iter->second;
|
||||||
|
panicifnot(dev);
|
||||||
|
return *iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemBus::regdev(Device *dev, uint64_t addr) { iomap.emplace(addr, dev); }
|
||||||
|
|
||||||
|
void SystemBus::write(char *buf, size_t addr, size_t len) {
|
||||||
|
auto &&dev = finddev(addr);
|
||||||
|
dev.second->write(buf, addr - dev.first, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemBus::read(char *buf, size_t addr, size_t len) {
|
||||||
|
auto &&dev = finddev(addr);
|
||||||
|
dev.second->read(buf, addr - dev.first, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemBus::write64(uint64_t &dword, size_t addr) {
|
||||||
|
auto &&dev = finddev(addr);
|
||||||
|
dev.second->write64(dword, addr - dev.first);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemBus::read64(uint64_t &dword, size_t addr) {
|
||||||
|
auto &&dev = finddev(addr);
|
||||||
|
dev.second->read64(dword, addr - dev.first);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemBus::write32(uint32_t &word, size_t addr) {
|
||||||
|
auto &&dev = finddev(addr);
|
||||||
|
dev.second->write32(word, addr - dev.first);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemBus::read32(uint32_t &word, size_t addr) {
|
||||||
|
auto &&dev = finddev(addr);
|
||||||
|
dev.second->read32(word, addr - dev.first);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemBus::write16(uint16_t &hword, size_t addr) {
|
||||||
|
auto &&dev = finddev(addr);
|
||||||
|
dev.second->write16(hword, addr - dev.first);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemBus::read16(uint16_t &hword, size_t addr) {
|
||||||
|
auto &&dev = finddev(addr);
|
||||||
|
dev.second->read16(hword, addr - dev.first);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemBus::write8(uint8_t &byte, size_t addr) {
|
||||||
|
auto &&dev = finddev(addr);
|
||||||
|
dev.second->write8(byte, addr - dev.first);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemBus::read8(uint8_t &byte, size_t addr) {
|
||||||
|
auto &&dev = finddev(addr);
|
||||||
|
dev.second->read8(byte, addr - dev.first);
|
||||||
}
|
}
|
||||||
9
lasim/include/la32r.hh
Normal file
9
lasim/include/la32r.hh
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <sysbus.hh>
|
||||||
|
|
||||||
|
class LA32R {
|
||||||
|
public:
|
||||||
|
LA32R(SystemBus *bus);
|
||||||
|
void Step(unsigned in);
|
||||||
|
};
|
||||||
115
lasim/la32r.cc
Normal file
115
lasim/la32r.cc
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
#include <common.h>
|
||||||
|
#include <la32r.hh>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
using u64 = uint64_t;
|
||||||
|
using i64 = int64_t;
|
||||||
|
|
||||||
|
using u32 = uint32_t;
|
||||||
|
using i32 = int32_t;
|
||||||
|
|
||||||
|
SystemBus *sysbus;
|
||||||
|
|
||||||
|
enum regenum {
|
||||||
|
R0, R1, R2, R3, R4, R5, R6, R7, R8, R9,
|
||||||
|
R10, R11, R12, R13, R14, R15, R16, R17, R18, R19,
|
||||||
|
R20, R21, R22, R23, R24, R25, R26, R27, R28, R29,
|
||||||
|
R30, R31, PC
|
||||||
|
};
|
||||||
|
|
||||||
|
enum PLV {
|
||||||
|
PLV0,
|
||||||
|
// PLV1,
|
||||||
|
// PLV2,
|
||||||
|
PLV3,
|
||||||
|
} PrivilegeLevel ;
|
||||||
|
|
||||||
|
class Registers {
|
||||||
|
private:
|
||||||
|
u32 regs_[32] = {0};
|
||||||
|
u32 pc_ = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Registers() = default;
|
||||||
|
|
||||||
|
u32 get(u32 idx) {
|
||||||
|
panicifnot((0 <= idx && 32 >= idx) || idx == PC);
|
||||||
|
if (idx == PC) {
|
||||||
|
return pc_;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 <= idx && 32 >= idx) {
|
||||||
|
return regs_[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
panic("Unexpected register access");
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(u32 idx, u32 data) {
|
||||||
|
panicifnot((0 <= idx && 32 >= idx) || idx == PC);
|
||||||
|
if (idx == PC) {
|
||||||
|
pc_ = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 <= idx && 32 >= idx) {
|
||||||
|
regs_[idx] = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
panic("Unexpected register access");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 &operator[](u32 idx) {
|
||||||
|
if (idx == PC) {
|
||||||
|
return pc_;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 <= idx && 32 >= idx) {
|
||||||
|
return regs_[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
panic("Unexpected register access");
|
||||||
|
}
|
||||||
|
} Regs ;
|
||||||
|
|
||||||
|
constexpr u32 getbits(u32 hi, u32 lo, u32 data) {
|
||||||
|
data = data >> lo;
|
||||||
|
u32 mask = ((u64) 0x1 << (hi + 1)) - 1;
|
||||||
|
return data & mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
void decode_and_exec(u32 inst) {
|
||||||
|
|
||||||
|
if (getbits(31, 15, inst) == 0b00000000000100000) {
|
||||||
|
u32 rd = getbits( 4, 0, inst);
|
||||||
|
u32 rj = getbits( 9, 5, inst);
|
||||||
|
u32 rk = getbits(14, 10, inst);
|
||||||
|
|
||||||
|
u32 tmp = Regs[rj] + Regs[rk];
|
||||||
|
Regs[rd] = getbits(31, 0, tmp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
panic("Invalid operation or have not implemented yet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 fetch() {
|
||||||
|
u32 inst;
|
||||||
|
sysbus->read32(inst, Regs[PC]);
|
||||||
|
return inst;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LA32R::LA32R(SystemBus *bus) {
|
||||||
|
sysbus = bus;
|
||||||
|
|
||||||
|
Regs[PC] = 0x0000'0000;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LA32R::Step(unsigned in) {
|
||||||
|
u32 inst = fetch();
|
||||||
|
decode_and_exec(inst);
|
||||||
|
Regs[PC] += 4;
|
||||||
|
}
|
||||||
@@ -1,11 +1,38 @@
|
|||||||
#include <sysbus.hh>
|
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
int main() {
|
#include <sysbus.hh>
|
||||||
fetch();
|
#include <memory.hh>
|
||||||
#ifdef DEBUG_MODE
|
#include <serial.hh>
|
||||||
std::cout << "Hello" << std::endl;
|
#include <la32r.hh>
|
||||||
#endif
|
#include <common.h>
|
||||||
|
#include <devaddr.h>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
if (argc < 2) {
|
||||||
|
std::cout << "Usage: sim <bin>";
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SystemBus bus;
|
||||||
|
Memory ram(2 * 1024 * 1024);
|
||||||
|
Memory stk(256 * 1024);
|
||||||
|
|
||||||
|
Memory flash(1024 * 1024);
|
||||||
|
flash.load(argv[1]);
|
||||||
|
ram.load(&flash, IMG_ADDR, flash.size());
|
||||||
|
|
||||||
|
bus.regdev(&ram, RAM_ADDR);
|
||||||
|
bus.regdev(&stk, STK_ADDR);
|
||||||
|
|
||||||
|
Serial bios(1);
|
||||||
|
bus.regdev(&bios, SERIAL_PORT);
|
||||||
|
|
||||||
|
auto cpu = new LA32R(&bus);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
cpu->Step(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete cpu;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user