新增 ISA 验证资产:迷你汇编器 + 指令测试程序
tools/rv_asm.py - 极简 RISC-V 汇编器(Python 3,无第三方依赖),支持 add/sub/and/or/xor/sll/srl/sra/slt/sltu、mul/mulh/mulhsu/mulhu、 addi/slti/sltiu/xori/ori/andi、slli/srli/srai、lw/sw、 beq/bne/blt/bge/bltu/bgeu、lui、jal/jalr、ecall、标签与 # 注释; - 提供 print / halt 两条双字伪指令(分别等价于 addi a7,zero,34 + ecall、 addi a7,zero,10 + ecall); - I 型与访存立即数做 12 位有符号范围检查,越界直接报错,避免静默截断; - 除 hex 外同时输出 .lst 编码清单,便于与 .asm 逐行核对。 testbench/programs/isa_test.asm + isa_test.expected - 指令扩展验证程序:sltiu(两个方向)、xor/sll/srl/sra、mul/mulh/mulhu/mulhsu、 bltu/bge/bgeu 的有符号与无符号区分,以及 bge/bgeu/bltu 三个循环, 共 24 项 LED 输出,期望值逐行保存在 isa_test.expected。 testbench/programs/lui_test.asm - LUI 验证程序:0x12345 / 0xfffff / 0x80000 与 lui+addi 组合,共 4 项输出。 另外包含编辑器/格式化工具对 cpu21_riscv_alu.v、cpu21_riscv_branch_unit.v、 cpu21_riscv_decoder.v 的重排(纯格式,语义等价)。 验证(xsim + testbench/tb_no_intr.v,按提交后的正式路径生成 hex) - isa_test:24 项 LED 输出与 isa_test.expected 逐项一致,143 周期后 halt 停机; - lui_test:12345000 / fffff000 / 80000000 / 12345678,21 周期后停机; - 重新编译无 error / warning。
This commit is contained in:
+6
-4
@@ -32,8 +32,8 @@ module cpu21_riscv_alu (
|
||||
localparam ALU_MULHSU = 4'd14;
|
||||
localparam ALU_PASSB = 4'd15; // 直接输出 B 端(供 LUI 使用)
|
||||
reg [63:0] mult_result; // 无符号 32x32 乘积
|
||||
reg signed [63:0] mult_ss; // 有符号 x 有符号
|
||||
reg signed [63:0] mult_su; // 有符号 x 无符号
|
||||
reg signed [63:0] mult_ss; // 有符号 x 有符号
|
||||
reg signed [63:0] mult_su; // 有符号 x 无符号
|
||||
|
||||
always @* begin
|
||||
mult_result = a * b;
|
||||
@@ -57,8 +57,10 @@ module cpu21_riscv_alu (
|
||||
ALU_AND: result = a & b;
|
||||
ALU_OR: result = a | b;
|
||||
ALU_XOR: result = a ^ b;
|
||||
ALU_NOR: result = ~(a | b); ALU_MULH: result = mult_ss[63:32];
|
||||
ALU_MULHSU: result = mult_su[63:32]; ALU_SLT: result = ($signed(a) < $signed(b)) ? 32'd1 : 32'd0;
|
||||
ALU_NOR: result = ~(a | b);
|
||||
ALU_MULH: result = mult_ss[63:32];
|
||||
ALU_MULHSU: result = mult_su[63:32];
|
||||
ALU_SLT: result = ($signed(a) < $signed(b)) ? 32'd1 : 32'd0;
|
||||
ALU_SLTU: result = (a < b) ? 32'd1 : 32'd0;
|
||||
ALU_PASSB: result = b;
|
||||
default: result = 32'b0;
|
||||
|
||||
@@ -34,9 +34,9 @@ module cpu21_riscv_branch_unit (
|
||||
output wire [31:0] redirect_pc_o
|
||||
);
|
||||
// 比较结果预先算好,避免表达式过长被自动换行拆散。
|
||||
wire lt_signed = $signed(src1_i) < $signed(src2_i);
|
||||
wire ge_signed = $signed(src1_i) >= $signed(src2_i);
|
||||
wire lt_unsigned = src1_i < src2_i;
|
||||
wire lt_signed = $signed(src1_i) < $signed(src2_i);
|
||||
wire ge_signed = $signed(src1_i) >= $signed(src2_i);
|
||||
wire lt_unsigned = src1_i < src2_i;
|
||||
wire ge_unsigned = src1_i >= src2_i;
|
||||
|
||||
// 条件分支裁决:beq 相等、bne 不等、blt/bge 有符号比较、bltu/bgeu 无符号比较。
|
||||
|
||||
@@ -115,14 +115,14 @@ module cpu21_riscv_decoder (
|
||||
// (funct3=111 形式)。mulhu 与 remu 都取 ALU 的 result2(wb_sel=3)。
|
||||
if (funct7 == 7'b0000001) begin
|
||||
case (funct3)
|
||||
3'b000: alu_op_o = ALU_MUL; // mul:无符号乘积低 32 位
|
||||
3'b001: alu_op_o = ALU_MULH; // mulh:有符号乘积高 32 位
|
||||
3'b000: alu_op_o = ALU_MUL; // mul:无符号乘积低 32 位
|
||||
3'b001: alu_op_o = ALU_MULH; // mulh:有符号乘积高 32 位
|
||||
3'b010: alu_op_o = ALU_MULHSU; // mulhsu:有符号 x 无符号高 32 位
|
||||
3'b011: begin // mulhu:无符号乘积高 32 位
|
||||
3'b011: begin // mulhu:无符号乘积高 32 位
|
||||
alu_op_o = ALU_MUL;
|
||||
wb_sel_o = 3'd3;
|
||||
end
|
||||
3'b111: begin // remu(课程约定):取余数
|
||||
3'b111: begin // remu(课程约定):取余数
|
||||
alu_op_o = ALU_DIVU;
|
||||
wb_sel_o = 3'd3;
|
||||
end
|
||||
@@ -213,8 +213,7 @@ module cpu21_riscv_decoder (
|
||||
bgeu_o = (funct3 == 3'b111);
|
||||
// 有符号比较用 ALU_SLT、无符号比较用 ALU_SLTU,相等/不等用减法;
|
||||
// 分支是否成立由 EX 级的分支裁决单元决定,这里只与真值表保持一致。
|
||||
alu_op_o = (blt_o || bge_o) ? ALU_SLT :
|
||||
((bltu_o || bgeu_o) ? ALU_SLTU : ALU_SUB);
|
||||
alu_op_o = (blt_o || bge_o) ? ALU_SLT : ((bltu_o || bgeu_o) ? ALU_SLTU : ALU_SUB);
|
||||
imm_o = {{19{ir_i[31]}}, ir_i[31], ir_i[7], ir_i[30:25], ir_i[11:8], 1'b0};
|
||||
end
|
||||
end
|
||||
|
||||
@@ -27,18 +27,18 @@
|
||||
表中的 `opcode` 是控制器使用的五位字段 `IR[6:2]`,不是包含最低两位的 7 位原始 opcode。
|
||||
因此它与标准 RISC-V 指令的低 7 位 opcode 相差右移两位。
|
||||
|
||||
| 指令类别 | opcode | 说明 |
|
||||
| ------------------------------ | -----: | --------------------------------------- |
|
||||
| R 型 | `0x0c` | add/sub/and/or/xor/slt/sltu/sll/srl/sra |
|
||||
| M 扩展(R 型) | `0x0c` | `funct7=0000001`:mul/mulh/mulhsu/mulhu(另有课程约定的 remu,`funct3=111`) |
|
||||
| I 型 ALU | `0x04` | addi/andi/ori/xori/slti/sltiu/slli/srli/srai |
|
||||
| `lui`(扩展) | `0x0d` | 加载高位立即数,`rd = imm[31:12] << 12` |
|
||||
| `lw` | `0x00` | `funct3=010` |
|
||||
| `sw` / `sb` | `0x08` | `funct3=010` / `000` |
|
||||
| `beq` / `bne` / `blt` / `bge` / `bltu` / `bgeu` | `0x18` | `funct3=000` / `001` / `100` / `101` / `110` / `111` |
|
||||
| `jal` | `0x1b` | J 型立即数 |
|
||||
| `jalr` | `0x19` | `funct3=000` |
|
||||
| 系统类 | `0x1c` | `ecall`、`URET`、CSRRSI、CSRRCI |
|
||||
| 指令类别 | opcode | 说明 |
|
||||
| ----------------------------------------------- | -----: | ---------------------------------------------------------------------------- |
|
||||
| R 型 | `0x0c` | add/sub/and/or/xor/slt/sltu/sll/srl/sra |
|
||||
| M 扩展(R 型) | `0x0c` | `funct7=0000001`:mul/mulh/mulhsu/mulhu(另有课程约定的 remu,`funct3=111`) |
|
||||
| I 型 ALU | `0x04` | addi/andi/ori/xori/slti/sltiu/slli/srli/srai |
|
||||
| `lui`(扩展) | `0x0d` | 加载高位立即数,`rd = imm[31:12] << 12` |
|
||||
| `lw` | `0x00` | `funct3=010` |
|
||||
| `sw` / `sb` | `0x08` | `funct3=010` / `000` |
|
||||
| `beq` / `bne` / `blt` / `bge` / `bltu` / `bgeu` | `0x18` | `funct3=000` / `001` / `100` / `101` / `110` / `111` |
|
||||
| `jal` | `0x1b` | J 型立即数 |
|
||||
| `jalr` | `0x19` | `funct3=000` |
|
||||
| 系统类 | `0x1c` | `ecall`、`URET`、CSRRSI、CSRRCI |
|
||||
|
||||
`ecall` 和 `URET` 都是 `opcode=0x1c、funct3=0`,由 `IR[21]` 区分:
|
||||
`IR[21]=0` 是 `ecall`,`IR[21]=1` 是 `URET`。这一点来自原控制器中的 `IR21` 分支逻辑。
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
# 指令扩展验证程序:每条被测指令的结果都通过 ecall(a7=34) 输出,最后用 halt 停机。
|
||||
# 期望输出顺序见每行注释(共 24 次输出),同时保存在同目录 isa_test.expected(每行一项 LED 值)。
|
||||
#
|
||||
# 用法(在仓库根目录执行):
|
||||
# python tools/rv_asm.py testbench/programs/isa_test.asm <仿真工作目录>/risc-v-benchmark_ccab.hex
|
||||
# 再用 testbench/tb_no_intr.v 仿真;hex 命名为 risc-v-benchmark_ccab.hex 时会被测试
|
||||
# 平台优先从仿真工作目录载入(参见 tb_no_intr.v 的 ROM 探测顺序)。
|
||||
# print / halt 是 tools/rv_asm.py 提供的双字伪指令:
|
||||
# print = addi a7,zero,34 + ecall;halt = addi a7,zero,10 + ecall。
|
||||
|
||||
# ---- sltiu:立即数符号扩展后做无符号比较 ----
|
||||
addi t0, zero, 1
|
||||
addi t1, zero, -1 # t1 = 0xffffffff
|
||||
sltiu a0, t0, -1 # 1 <u 0xffffffff -> 00000001
|
||||
print
|
||||
sltiu a0, t1, 1 # 0xffffffff <u 1 -> 00000000
|
||||
print
|
||||
|
||||
# ---- xor / sll / srl / sra(原有指令回归)----
|
||||
addi t0, zero, 0xff
|
||||
addi t1, zero, -1
|
||||
xor a0, t0, t1 # 0xff ^ 0xffffffff -> ffffff00
|
||||
print
|
||||
|
||||
addi t0, zero, 1
|
||||
addi t1, zero, 31
|
||||
sll a0, t0, t1 # 1 << 31 -> 80000000
|
||||
print
|
||||
|
||||
addi t0, zero, -1
|
||||
addi t1, zero, 28
|
||||
srl a0, t0, t1 # 逻辑右移 -> 0000000f
|
||||
print
|
||||
sra a0, t0, t1 # 算术右移 -> ffffffff
|
||||
print
|
||||
|
||||
# ---- mul:无符号乘积低 32 位 ----
|
||||
addi t0, zero, 1234
|
||||
addi t1, zero, 567
|
||||
mul a0, t0, t1 # 1234*567 = 0x000aad1e
|
||||
print
|
||||
|
||||
# ---- mulh / mulhu / mulhsu:64 位乘积的高 32 位 ----
|
||||
addi t0, zero, -1 # 有符号 -1 / 无符号 0xffffffff
|
||||
addi t1, zero, -1
|
||||
mulh a0, t0, t1 # (-1)*(-1)=1 -> 00000000
|
||||
print
|
||||
mulhu a0, t0, t1 # 0xffffffff^2 -> fffffffe
|
||||
print
|
||||
addi t0, zero, -1
|
||||
addi t1, zero, 2
|
||||
mulhsu a0, t0, t1 # (-1)*2=-2 -> ffffffff
|
||||
print
|
||||
|
||||
# ---- bltu:0 <u 0xffffffff 成立(按有符号比较则不成立)----
|
||||
addi t0, zero, -1
|
||||
bltu zero, t0, bltu_ok
|
||||
addi a0, zero, 0x101 # 不应执行
|
||||
print
|
||||
bltu_ok:
|
||||
addi a0, zero, 0x601 # 00000601
|
||||
print
|
||||
|
||||
# ---- bge:有符号 >= ,(-1) >= 0 不成立,应走 fall-through ----
|
||||
addi t0, zero, -1
|
||||
bge t0, zero, bge_bad
|
||||
addi a0, zero, 0x602 # 00000602
|
||||
print
|
||||
jal zero, bge_done
|
||||
bge_bad:
|
||||
addi a0, zero, 0x102 # 不应执行
|
||||
print
|
||||
bge_done:
|
||||
|
||||
# ---- bgeu:无符号 >= ,0xffffffff >=u 0 成立 ----
|
||||
addi t0, zero, -1
|
||||
bgeu t0, zero, bgeu_ok
|
||||
addi a0, zero, 0x103 # 不应执行
|
||||
print
|
||||
bgeu_ok:
|
||||
addi a0, zero, 0x603 # 00000603
|
||||
print
|
||||
|
||||
# ---- bge 循环:从 -3 递增到 0(共 4 次输出)----
|
||||
addi s1, zero, -3
|
||||
bge_loop:
|
||||
add a0, zero, s1
|
||||
print # fffffffd / fffffffe / ffffffff / 00000000
|
||||
addi s1, s1, 1
|
||||
bge zero, s1, bge_loop
|
||||
|
||||
# ---- bgeu 循环:3 -> 1(共 3 次输出)----
|
||||
addi t0, zero, 3
|
||||
bgeu_loop:
|
||||
add a0, zero, t0
|
||||
print # 00000003 / 00000002 / 00000001
|
||||
addi t0, t0, -1
|
||||
addi t2, zero, 1
|
||||
bgeu t0, t2, bgeu_loop
|
||||
|
||||
# ---- bltu 循环:4 -> 1(共 4 次输出)----
|
||||
addi s1, zero, 4
|
||||
bltu_loop:
|
||||
add a0, zero, s1
|
||||
print # 00000004 / 00000003 / 00000002 / 00000001
|
||||
addi s1, s1, -1
|
||||
bltu zero, s1, bltu_loop
|
||||
|
||||
halt
|
||||
@@ -0,0 +1,24 @@
|
||||
00000001
|
||||
00000000
|
||||
ffffff00
|
||||
80000000
|
||||
0000000f
|
||||
ffffffff
|
||||
000aad1e
|
||||
00000000
|
||||
fffffffe
|
||||
ffffffff
|
||||
00000601
|
||||
00000602
|
||||
00000603
|
||||
fffffffd
|
||||
fffffffe
|
||||
ffffffff
|
||||
00000000
|
||||
00000003
|
||||
00000002
|
||||
00000001
|
||||
00000004
|
||||
00000003
|
||||
00000002
|
||||
00000001
|
||||
@@ -0,0 +1,26 @@
|
||||
# LUI 指令测试:依次打印 lui 的结果,最后停机。
|
||||
# 期望输出:12345000 / fffff000 / 80000000 / 12345678,随后停机(halted=1)。
|
||||
# 用法:python tools/rv_asm.py testbench/programs/lui_test.asm <仿真工作目录>/risc-v-benchmark_ccab.hex
|
||||
lui t0, 0x12345 # t0 = 0x12345000
|
||||
add a0, zero, t0
|
||||
addi a7, zero, 34
|
||||
ecall
|
||||
|
||||
lui t0, 0xfffff # t0 = 0xfffff000
|
||||
add a0, zero, t0
|
||||
addi a7, zero, 34
|
||||
ecall
|
||||
|
||||
lui t0, 0x80000 # t0 = 0x80000000
|
||||
add a0, zero, t0
|
||||
addi a7, zero, 34
|
||||
ecall
|
||||
|
||||
lui t0, 0x12345 # 常见用法 lui+addi:0x12345678
|
||||
addi t0, t0, 0x678
|
||||
add a0, zero, t0
|
||||
addi a7, zero, 34
|
||||
ecall
|
||||
|
||||
addi a7, zero, 10 # a7=10 -> 停机
|
||||
ecall
|
||||
+220
@@ -0,0 +1,220 @@
|
||||
#!/usr/bin/env python3
|
||||
"""极简 RISC-V 汇编器:仅支持本项目测试所需的指令子集。
|
||||
|
||||
用法: python tools/rv_asm.py <input.asm> <output.hex>
|
||||
同时生成 <output.hex>.lst 反汇编/编码清单,便于核对。
|
||||
支持:add/sub/and/or/xor/sll/srl/sra/slt/sltu、
|
||||
mul/mulh/mulhsu/mulhu、
|
||||
addi/slti/sltiu/xori/ori/andi、slli/srli/srai、
|
||||
lw/sw、beq/bne/blt/bge/bltu/bgeu、lui、jal/jalr、ecall、标签、# 注释
|
||||
伪指令:print(= addi a7,zero,34 + ecall)、halt(= addi a7,zero,10 + ecall),各占两个字。
|
||||
示例:python tools/rv_asm.py testbench/programs/isa_test.asm out.hex
|
||||
"""
|
||||
|
||||
import re
|
||||
import sys
|
||||
|
||||
REGS = {
|
||||
"zero": 0,
|
||||
"ra": 1,
|
||||
"sp": 2,
|
||||
"gp": 3,
|
||||
"tp": 4,
|
||||
"t0": 5,
|
||||
"t1": 6,
|
||||
"t2": 7,
|
||||
"s0": 8,
|
||||
"s1": 9,
|
||||
"a0": 10,
|
||||
"a1": 11,
|
||||
"a2": 12,
|
||||
"a3": 13,
|
||||
"a4": 14,
|
||||
"a5": 15,
|
||||
"a6": 16,
|
||||
"a7": 17,
|
||||
"s2": 18,
|
||||
"s3": 19,
|
||||
"s4": 20,
|
||||
"s5": 21,
|
||||
"s6": 22,
|
||||
"s7": 23,
|
||||
"s8": 24,
|
||||
"s9": 25,
|
||||
"s10": 26,
|
||||
"s11": 27,
|
||||
"t3": 28,
|
||||
"t4": 29,
|
||||
"t5": 30,
|
||||
"t6": 31,
|
||||
}
|
||||
|
||||
|
||||
def reg(t):
|
||||
t = t.strip()
|
||||
if t in REGS:
|
||||
return REGS[t]
|
||||
m = re.fullmatch(r"x(\d+)", t)
|
||||
if m:
|
||||
return int(m.group(1))
|
||||
raise SystemExit("未知寄存器: " + t)
|
||||
|
||||
|
||||
def num(t):
|
||||
return int(t.strip(), 0)
|
||||
|
||||
|
||||
def enc_r(f7, rs2, rs1, f3, rd):
|
||||
return (f7 << 25) | (rs2 << 20) | (rs1 << 15) | (f3 << 12) | (rd << 7) | 0x33
|
||||
|
||||
|
||||
def enc_i(imm, rs1, f3, rd, op=0x13):
|
||||
return ((imm & 0xFFF) << 20) | (rs1 << 15) | (f3 << 12) | (rd << 7) | op
|
||||
|
||||
|
||||
def enc_s(imm, rs2, rs1, f3):
|
||||
imm &= 0xFFF
|
||||
return (
|
||||
((imm >> 5) << 25)
|
||||
| (rs2 << 20)
|
||||
| (rs1 << 15)
|
||||
| (f3 << 12)
|
||||
| ((imm & 0x1F) << 7)
|
||||
| 0x23
|
||||
)
|
||||
|
||||
|
||||
def enc_b(imm, rs2, rs1, f3):
|
||||
imm &= 0x1FFF
|
||||
return (
|
||||
(((imm >> 12) & 1) << 31)
|
||||
| (((imm >> 5) & 0x3F) << 25)
|
||||
| (rs2 << 20)
|
||||
| (rs1 << 15)
|
||||
| (f3 << 12)
|
||||
| (((imm >> 1) & 0xF) << 8)
|
||||
| (((imm >> 11) & 1) << 7)
|
||||
| 0x63
|
||||
)
|
||||
|
||||
|
||||
def enc_u(imm, rd):
|
||||
return ((imm & 0xFFFFF) << 12) | (rd << 7) | 0x37
|
||||
|
||||
|
||||
def enc_j(imm, rd):
|
||||
imm &= 0x1FFFFF
|
||||
return (
|
||||
(((imm >> 20) & 1) << 31)
|
||||
| (((imm >> 1) & 0x3FF) << 21)
|
||||
| (((imm >> 11) & 1) << 20)
|
||||
| (((imm >> 12) & 0xFF) << 12)
|
||||
| (rd << 7)
|
||||
| 0x6F
|
||||
)
|
||||
|
||||
|
||||
RTYPE = {
|
||||
"add": (0x00, 0),
|
||||
"sub": (0x20, 0),
|
||||
"sll": (0x00, 1),
|
||||
"slt": (0x00, 2),
|
||||
"sltu": (0x00, 3),
|
||||
"xor": (0x00, 4),
|
||||
"srl": (0x00, 5),
|
||||
"sra": (0x20, 5),
|
||||
"or": (0x00, 6),
|
||||
"and": (0x00, 7),
|
||||
"mul": (0x01, 0),
|
||||
"mulh": (0x01, 1),
|
||||
"mulhsu": (0x01, 2),
|
||||
"mulhu": (0x01, 3),
|
||||
}
|
||||
ITYPE = {"addi": 0, "slti": 2, "sltiu": 3, "xori": 4, "ori": 6, "andi": 7}
|
||||
SHIFT = {"slli": 1, "srli": 5, "srai": 5}
|
||||
BTYPE = {"beq": 0, "bne": 1, "blt": 4, "bge": 5, "bltu": 6, "bgeu": 7}
|
||||
# 双字伪指令:print = addi a7,zero,34 + ecall;halt = addi a7,zero,10 + ecall
|
||||
PSEUDO_SIZE = {"print": 2, "halt": 2}
|
||||
|
||||
|
||||
def assemble(lines):
|
||||
labels, items, addr = {}, [], 0
|
||||
for raw in lines:
|
||||
line = raw.split("#")[0].strip()
|
||||
if not line:
|
||||
continue
|
||||
while True:
|
||||
m = re.match(r"^([A-Za-z_.$][\w.$]*)\s*:\s*(.*)$", line)
|
||||
if not m:
|
||||
break
|
||||
labels[m.group(1)] = addr
|
||||
line = m.group(2).strip()
|
||||
if not line:
|
||||
break
|
||||
if not line:
|
||||
continue
|
||||
items.append((addr, line))
|
||||
addr += 4 * PSEUDO_SIZE.get(line.split()[0].lower(), 1)
|
||||
|
||||
out = []
|
||||
for addr, line in items:
|
||||
parts = re.split(r"[\s,]+", line)
|
||||
mn, a = parts[0].lower(), parts[1:]
|
||||
if mn in RTYPE:
|
||||
f7, f3 = RTYPE[mn]
|
||||
w = enc_r(f7, reg(a[2]), reg(a[1]), f3, reg(a[0]))
|
||||
elif mn in ITYPE:
|
||||
im = num(a[2])
|
||||
if not (-2048 <= im <= 2047):
|
||||
raise SystemExit("I 型立即数超出 12 位有符号范围: " + line)
|
||||
w = enc_i(im, reg(a[1]), ITYPE[mn], reg(a[0]))
|
||||
elif mn in SHIFT:
|
||||
w = enc_i(num(a[2]) & 0x1F, reg(a[1]), SHIFT[mn], reg(a[0]))
|
||||
elif mn == "lui":
|
||||
w = enc_u(num(a[1]), reg(a[0]))
|
||||
elif mn in ("lw", "sw"):
|
||||
m = re.fullmatch(r"(-?\w+)\((\w+)\)", a[1])
|
||||
if not m:
|
||||
raise SystemExit("内存操作数格式应为 imm(rs1): " + line)
|
||||
im = num(m.group(1))
|
||||
if not (-2048 <= im <= 2047):
|
||||
raise SystemExit("访存偏移超出 12 位有符号范围: " + line)
|
||||
if mn == "lw":
|
||||
w = enc_i(im, reg(m.group(2)), 2, reg(a[0]), 0x03)
|
||||
else:
|
||||
w = enc_s(im, reg(a[0]), reg(m.group(2)), 2)
|
||||
elif mn in BTYPE:
|
||||
tgt = labels[a[2]] if a[2] in labels else num(a[2])
|
||||
w = enc_b(tgt - addr, reg(a[1]), reg(a[0]), BTYPE[mn])
|
||||
elif mn == "jal":
|
||||
tgt = labels[a[1]] if a[1] in labels else num(a[1])
|
||||
w = enc_j(tgt - addr, reg(a[0]))
|
||||
elif mn == "jalr":
|
||||
w = enc_i(num(a[2]), reg(a[1]), 0, reg(a[0]), 0x67)
|
||||
elif mn == "ecall":
|
||||
w = 0x00000073
|
||||
elif mn == "print":
|
||||
w = [enc_i(34, 0, 0, 17), 0x00000073]
|
||||
elif mn == "halt":
|
||||
w = [enc_i(10, 0, 0, 17), 0x00000073]
|
||||
else:
|
||||
raise SystemExit("未知助记符: " + mn)
|
||||
out.append((addr, line, w if isinstance(w, list) else [w]))
|
||||
return out
|
||||
|
||||
|
||||
def main():
|
||||
src, dst = sys.argv[1], sys.argv[2]
|
||||
with open(src, encoding="utf-8") as f:
|
||||
prog = assemble(f.readlines())
|
||||
with open(dst, "w", encoding="ascii") as f:
|
||||
for _, _, ws in prog:
|
||||
for w in ws:
|
||||
f.write("%08X\n" % w)
|
||||
with open(dst + ".lst", "w", encoding="utf-8") as f:
|
||||
for addr, line, ws in prog:
|
||||
f.write("%04X: %s %s\n" % (addr, " ".join("%08X" % w for w in ws), line))
|
||||
print("已生成 %s(%d 个字)" % (dst, sum(len(ws) for _, _, ws in prog)))
|
||||
|
||||
|
||||
main()
|
||||
Reference in New Issue
Block a user