-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuc_test.cc
More file actions
87 lines (69 loc) · 2.64 KB
/
uc_test.cc
File metadata and controls
87 lines (69 loc) · 2.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include <unicorn/sparc.h>
#include <unicorn/unicorn.h>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
// LEON3 内存布局映射
constexpr uint64_t RAM_BASE = 0x40000000;
constexpr size_t RAM_SIZE = 0x100000; // 1 MB
constexpr uint64_t ROM_BASE = 0x00000000;
constexpr size_t ROM_SIZE = 0x2000; // 8 KB
// BM3803 片上外设区域 (AHB I/O)
constexpr uint64_t MMIO1_BASE = 0x80000000;
constexpr size_t MMIO1_SIZE = 0x2000; // 8 KB
constexpr uint64_t MMIO2_BASE = 0x20000000;
constexpr size_t MMIO2_SIZE = 0x20000000; // 512 MB
// 模拟的入口点
constexpr uint64_t BOOT_PC = ROM_BASE;
constexpr uint64_t STACK_TOP = RAM_BASE + RAM_SIZE - 4;
// 错误退出
static void die(const char *msg, uc_err err) {
std::fprintf(stderr, "%s: %u (%s)\n", msg, err, uc_strerror(err));
std::exit(EXIT_FAILURE);
}
// 一个简单的 "boot code",只是一条 NOP (0x01000000 for SPARC)
static const uint32_t boot_code[] = {
0x01000000, // nop
0x91d02000, // ta 0 (trap always) — 会触发中断/陷阱
};
int main(void) {
uc_engine *uc = nullptr;
uc_err err;
// 初始化 SPARC32
err = uc_open(UC_ARCH_SPARC, UC_MODE_SPARC32, &uc);
if (err != UC_ERR_OK) die("uc_open failed", err);
// 分配内存
if ((err = uc_mem_map(uc, RAM_BASE, RAM_SIZE, UC_PROT_ALL)))
die("map ram failed", err);
if ((err = uc_mem_map(uc, ROM_BASE, ROM_SIZE, UC_PROT_READ | UC_PROT_EXEC)))
die("map rom failed", err);
if ((err = uc_mem_map(uc, MMIO1_BASE, MMIO1_SIZE, UC_PROT_ALL)))
die("map periph failed", err);
if ((err = uc_mem_map(uc, MMIO2_BASE, MMIO2_SIZE, UC_PROT_ALL)))
die("map mmio failed", err);
// 写入 boot code 到 ROM
if ((err = uc_mem_write(uc, ROM_BASE, boot_code, sizeof(boot_code))))
die("write rom failed", err);
// 设置寄存器
if ((err = uc_reg_write(uc, UC_SPARC_REG_PC, &BOOT_PC)))
die("set PC failed", err);
if ((err = uc_reg_write(uc, UC_SPARC_REG_nSP, &STACK_TOP))) // 全局栈指针
die("set SP failed", err);
// 运行一点时间
err = uc_emu_start(uc, BOOT_PC, ROM_BASE + sizeof(boot_code), 0 /* timeout */,
10 /* instr count */);
if (err != UC_ERR_OK) die("emu_start failed", err);
// 模拟外部中断
std::puts("Raising external interrupt...");
err = uc_irq_raise(uc, 1); // IRQ 1
if (err != UC_ERR_OK) die("irq_raise failed", err);
// 继续执行
err = uc_emu_start(uc, BOOT_PC, ROM_BASE + sizeof(boot_code), 0, 20);
if (err != UC_ERR_OK) die("emu_start after irq failed", err);
// 清除中断
err = uc_irq_lower(uc, 1);
if (err != UC_ERR_OK) die("irq_lower failed", err);
std::puts("VM finished execution.");
uc_close(uc);
return 0;
}