verilog单周期CPU(简化指令)

模块设计

整体视图:

1. GRF(寄存器堆)

端口名 输入\输出 位宽 功能
clk Input 1 时钟信号
reset Input 1 复位信号
WE Input 1 使能信号
PC Input 31:0 pc
A1 Input 4:0 输入寄存器地址端口1
A2 Input 4:0 输入寄存器地址端口2
A3 Input 4:0 输入寄存器地址端口3,写寄存器地址
WD Input 31:0 数据输入端口,输入一个32位数据,存入编码为A3的寄存器中
RD1 Output 31:0 输出编码为A1中输入的寄存器中的值
RD2 Output 31:0 输出编码为A2中输入的寄存器中的值

初始化!!

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
module GRF(
input clk,
input reset,
input WE,
input [31:0] PC,
input [4:0] A1,
input [4:0] A2,
input [4:0] A3,
input [31:0] WD,
output [31:0] RD1,
output [31:0] RD2

);

reg [31:0] registers [31:0];
integer i;
assign RD1 = (A1 == 5'b0) ? 32'b0 : registers[A1];
assign RD2 = (A2 == 5'b0) ? 32'b0 : registers[A2];

initial begin
for(i=0;i<32;i=i+1) begin
registers[i]=32'b0;
end
end


always @(posedge clk ) begin
if(reset) begin
for(i=0;i<32;i=i+1) begin
registers[i]<= 32'b0;
end
end
else begin
if(WE) begin
$display("@%h: $%d <= %h", PC, A3, WD);
registers[A3]<=WD;
end
end
end

2. DM

端口名 输入\输出 位宽 功能
clk Input 1 时钟信号
reset Input 1 复位信号
PC Input 31:0 pc
memwrite Input 1 内存写使能
memaddr Input 31:0 内存地址
memdata Input 31:0 写入的内存数据
outdata Output 31:0 输出的内存数据

使用寄存器数组实现。初始化!!

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
module DM (
input clk,
input reset,
input [31:0] PC,
input memwrite,
input [31:0] memaddr,
input [31:0] memdata,
output [31:0] outdata
);
reg [31:0] mem[4095:0];
integer i;

assign outdata = mem[memaddr[13:2]];

initial begin
for (i = 0; i < 4096; i = i + 1) begin
mem[i] = 32'b0;
end
end
always @(posedge clk) begin
if (reset) begin
for (i = 0; i < 4096; i = i + 1) begin
mem[i] <= 32'b0;
end
end else begin
if (memwrite) begin
$display("@%h: *%h <= %h", PC, {22'b0,memaddr[11:0]}, memdata);
mem[memaddr[13:2]] <= memdata;
end
end
end
endmodule

DM中一个字是一个地址,按字节为14位(16K),按字为12位地址(32bit*4096),端口应该连接ALU输出端的2~13位。

3. NPC

端口名 输入\输出 位宽 功能
clk Input 1 时钟信号
reset Input 1 复位信号
beq_if Input 1 beq指令pc选择
zero Input 1 beq指令相等判断
j_if Input 1 j指令pc选择
jr_if Input 1 jr指令pc选择
jal_if Input 1 jal指令pc选择
imm Input 31:0 位扩展后的立即数
j_addr Input 25:0 j指令跳转地址
jr_addr Input 31:0 jr指令跳转地址
NPC Output 31:0 输出的真实pc值
NPC_4 Output 31:0 pc+4(用于jal指令写入$ra)

外部引入两个对应位置的寄存器通过ALU的减法结果zero,通过与beq_if(判断指令是否为beq)连接,实现beq(if$[rs]==$[rt]): PC=PC+offest+4。

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

module NPC (
input clk,
input reset,
input beq_if,
input j_if,
input jr_if,
input jal_if,
input zero,
input [31:0] imm,//afterext
input [25:0] j_addr,
input [31:0] jr_addr,
output reg [31:0] NPC,
output [31:0] NPC_4 //pc+4
);
assign NPC_4 = (NPC + 4);
initial begin
NPC = 32'h0000_3000;
end

always @(posedge clk) begin
if (reset) begin
NPC <= 32'h00003000;
end
else if (j_if == 1'b1||jal_if == 1'b1) begin
NPC <= {NPC[31 : 28], j_addr, 2'b00};
end
else if (jr_if == 1'b1) begin
NPC <= jr_addr;
end
else if (beq_if == 1'b1&&zero== 1'b1) begin
NPC <= ((imm << 2) + NPC + 4);
end
else begin
NPC <= NPC_4;
end

end


endmodule

4.IM:

通过ROM元件存储和读入指令代码,PC在内部为0x00000000起始,而外部为0x00003000,需要减去一个偏移量

ROM中一个字是一个地址,按字为12位地址端口应该连接ALU输出端的2~13位。

端口名 输入\输出 位宽 功能
pc Input 31:0 pc
inster Output 31:0 指令机器码
Opcode Output 5:0 高六位opcode
rs Output 4:0 rs寄存器序号
rt Output 4:0 rt寄存器序号
rd Output 4:0 rd寄存器序号
s Output 4:0 输出6-10位
func Output 5:0 输出func码
imm Output 15:0 输出低16位立即数imm
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
module IM(
input [31:0] pc,
output [31:0] instr,
output [5:0] opcode,
output [4:0] rs,
output [4:0] rt,
output [4:0] rd,
output [4:0] s,
output [5:0] func,
output [15:0] imm
);
reg [31:0] mem[4095:0];
wire [31:0] fakepc;
assign fakepc = pc-32'h0000_3000;
assign instr = mem[fakepc[13:2]];
assign opcode = instr[31:26];
assign rs = instr[25:21];
assign rt = instr[20:16];
assign rd = instr[15:11];
assign s = instr[10:6];
assign func = instr[5:0];
assign imm = instr[15:0];


initial begin
$readmemh("code.txt", mem);
end
endmodule

使用**$readmemh(“code.txt”, mem)**指令读取文件,初始化im。

5.ALU

端口名 输入\输出 位宽 功能
ALUOp Input 3:0 ALU功能选择
A Input 31:0 待处理数字1
B Input 31:0 待处理数字2
result Output 31:0 计算结果
zero Output 1 计算结果为零
overflow Output 1 溢出判断
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
`define ADD 4'b0000
`define SUB 4'b0001
`define MUL 4'b0010
`define DIV 4'b0011
`define AND 4'b0100
`define OR 4'b0101
`define SLL 4'b0110
`define SRL 4'b0111
module ALU(
input [3:0] aluop,
input [31:0] A,
input [31:0] B,

output [31:0] result,
output zero,
output overflow
);
reg [32:0] bit_33;

assign overflow = bit_33[32];
assign result = bit_33[31:0];
assign zero = (result==32'h00000000)? 1:0;

always @(*) begin
case(aluop)
`ADD: bit_33 = A + B;
`SUB: bit_33 = A - B;
`MUL: bit_33 = A * B;
`DIV: bit_33 = A / B;
`AND: bit_33 = A & B;
`OR: bit_33 = A | B;
`SLL: bit_33 = (A << B[4:0]);
`SRL: bit_33 = (A >> B[4:0]);
default: begin
bit_33 =33'b0;
end
endcase
end
endmodule

ALUOp:(留一位给剩下的)

0000 0001 0010 0011 0100 0101 0110 0111
add sub mul div and or sll srl

6.EXT

端口名 输入\输出 位宽 功能
imm Input 15:0 16位立即数
extp Input 1 位扩展选择功能
extresult Output 31:0 位扩展计算结果
1
2
3
4
5
6
7
8
9
module EXT (
input [1:0] extop,
input [15:0] imm,
output [31:0] extresult
);
assign extresult = (extop == 2'b00) ? {16'h0000, imm} :
(extop == 2'b01) ? {{16{imm[15]}}, imm} :
(extop == 2'b10) ? {imm, 16'h0000} : {16'h0000, imm};
endmodule
EXTOp: 00 01 10 11
功能 0扩展 符号扩展 高位加载 空余

7.CTRL

端口名 输入\输出 位宽 功能
opcode Input 5:0 高六位opcode
func Input 5:0 低六位opcode
instr Input 31:0 指令码
regwrite Output 1 reg写使能
regwritedst Output 1:0 寄存器写选择
alusrc Output 1 alu选择imm入B口
memwrite Output 1 mem写使能
memtoreg Output 1 mem写入reg选择
jr_if Output 1 jr判断
j_if Output 1 j判断
jal_if Output 1 jal判断
sll_if Output 1 sll判断
srl_if Output 1 srl判断
beq_if Output 1 beq判断
extop Output 1:0 ext功能选择
aluop Output 3:0 alu功能选择

通过输入的指令码各部分,进行操作状态输出。

*** sll指令未实现***

执行指令
信号名 add sub andi lui ori j jal jr beq sw lw nop sll srl
opcode 000000 000000 001100 001111 001101 000010 000011 000000 000100 101011 100011 000000 000000 000000
func 100000 100010 001000 000000 000000 000010
regwrite 1 1 1 1 1 0 1 0 0 0 1 0 1 1
regwritedst(2) 01(rd) 01 00 00 00(rt) 00 10($ra) 00 00 00 00 01 01 01
alusrc(imm) 0 0 1 1 1 0 0 0 0 1 1 0 0 0
memwrite 0 0 0 0 0 0 0 0 0 1 0 0 0 0
memtoreg 0 0 0 0 0 0 0 0 0 0 1 0 0 0
extop(2) 00 00 00 10 00 00 00 00 01 01 01 00 00 00
beq_if 0 0 0 0 0 0 0 0 1 0 0 0 0 0
j_if 0 0 0 0 0 1 0 0 0 0 0 0 0 0
jal_if 0 0 0 0 0 0 1 0 0 0 0 0 0 0
jr_if 0 0 0 0 0 0 0 1 0 0 0 0 0 0
sll_if 0 0 0 0 0 0 0 0 0 0 0 0 1 0
srl_if 0 0 0 0 0 0 0 0 0 0 0 0 0 1
ALU_ctr3 0 0 1 0(add$0) 1 0 0 0 0 0 0 0 1 1
ALU_ctr2 0 0 0 0 0 0 0 0 0 0 0 0 1 1
ALU_ctr1 0 1 0 0 1 0 0 0 1(sub验证) 0 0 0 0 1
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

`define OPCODE0 6'b000000
`define ADD 6'b100000
`define SUB 6'b100010
`define ANDI 6'b001100
`define ORI 6'b001101
`define LUI 6'b001111
`define J 6'b000010
`define JAL 6'b000011
`define JR 6'b001000
`define SW 6'b101011
`define LW 6'b100011
`define BEQ 6'b000100
`define FUNC0 6'b000000
`define SLL 6'b000000
`define SRL 6'b000010
`define NOP 6'b000000
module CTRL (
input [5:0] opcode,
input [5:0] func,
input [31:0] instr,
output regwrite,
output [1:0] regwritedst,
output alusrc,
output memwrite,
output memtoreg,
output beq_if,
output j_if,
output jr_if,
output jal_if,
output sll_if,
output srl_if,
output [1:0] extop,
output [3:0] aluop
);
assign {regwrite,regwritedst,alusrc,memwrite,memtoreg,extop,beq_if,j_if,jal_if,jr_if,sll_if,srl_if,aluop} =
(instr==32'b0)?{18'b0_00_0_00_00_000000_0000}:
(opcode==`OPCODE0&&func==`ADD)?{18'b1_01_0_00_00_000000_0000}:
(opcode==`OPCODE0&&func==`SUB)?{18'b1_01_0_00_00_000000_0001}:
(opcode==`ANDI)?{18'b1_00_1_00_00_000000_0100}:

(opcode==`LUI)?{18'b1_00_1_00_10_000000_0000}:

(opcode==`ORI)?{18'b1_00_1_00_00_000000_0101}:

(opcode==`J)?{18'b0_00_0_00_00_010000_0000}:
(opcode==`JAL)?{18'b1_10_0_00_00_001000_0000}:
(opcode==`OPCODE0&&func==`JR)?{18'b0_00_0_00_00_000100_0000}:
(opcode==`BEQ)?{18'b0_00_0_00_01_100000_0001}:
(opcode==`SW)?{18'b0_00_1_10_01_000000_0000}:
(opcode==`LW)?{18'b1_00_1_01_01_000000_0000}:
(opcode==`OPCODE0&&func==`SLL)?{18'b1_01_0_00_00_000010_0110}:
(opcode==`OPCODE0&&func==`SRL)?{18'b1_01_0_00_00_000001_0111}:{18'b0_00_0_00_00_000000_0000};
endmodule

各信号注意点:

  • add、sub、jr指令需要先判断opcode再判断func。

8.MUX

名称/信号|输出 00 01 10 11
mem_or_alu alu计算结果 mem数据
normal_or_ra(grfdatain) mem_or_alu jal_ra(PC+4)
grfwrite rt rd 0x1f($31/$ra)
aluAin rs rt
grf_or_imm GRF_2(rt) extresult(扩展后的imm)
aluBin grf_or_imm s

MUX均为32bit两位选择器,多余端口空余待未来使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

module MUX(
input [1:0]sel,
input [31:0] sel0,
input [31:0] sel1,
input [31:0] sel2,
input [31:0] sel3,
output [31:0] out

);
assign out = (sel==2'b00)?sel0:
(sel==2'b01)?sel1:
(sel==2'b10)?sel2:sel3;


endmodule

9.mips(顶层模块)

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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181


module mips (
input clk,
input reset
);
//im
wire [31:0] pc;
wire [31:0] jal_ra;
wire [5:0] opcode;
wire [5:0] func;
//ctrl
wire regwrite;
wire [1:0] regwritedst;
wire alusrc;
//dm
wire memwrite;
wire memtoreg;
wire [31:0] memoutdata;
//ctrl
wire beq_if;
wire j_if;
wire jr_if;
wire jal_if;
wire sll_if;
wire srl_if;
wire [1:0] extop;
wire [3:0] aluop;
//alu
wire [31:0] aluA;
wire [31:0] aluB;
wire zero;
wire overflow;
wire [31:0] aluresult;
//im
wire [31:0] instr;
wire [4:0] rs;
wire [4:0] rt;
wire [4:0] rd;
wire [4:0] s;
wire [15:0] imm;
//ext
wire [31:0] extresult;
//grf
wire [31:0] grf_1;
wire [31:0] grf_2;
wire [31:0] grfwriteaddr;
wire [31:0] grfdatain;
//muxfor
wire [31:0] mem_or_alu_out;
wire [31:0] grf_2_or_imm;

CTRL ctrl ( //
.instr(instr),
.opcode(opcode),
.func(func),
.regwrite(regwrite),
.regwritedst(regwritedst),
.alusrc(alusrc),
.memwrite(memwrite),
.memtoreg(memtoreg),
.beq_if(beq_if),
.j_if(j_if),
.jr_if(jr_if),
.jal_if(jal_if),
.sll_if(sll_if),
.srl_if(srl_if),
.extop(extop),
.aluop(aluop)
);
MUX mem_or_alu (
.sel({1'b0, memtoreg}),
.sel0(aluresult), //
.sel1(memoutdata), //
.sel2(32'h00000000), //
.sel3(32'h00000000), //
.out(mem_or_alu_out) //
);
MUX normal_or_ra (
.sel({1'b0, jal_if}),//grf写入寄存器选择
.sel0(mem_or_alu_out), //
.sel1(jal_ra), //
.sel2(32'h00000000), //
.sel3(32'h00000000), //
.out(grfdatain) //
);
GRF grf (
.clk(clk), //
.reset(reset), //
.PC(pc), //
.WE(regwrite), //
.A1(rs), //
.A2(rt), //
.A3(grfwriteaddr[4:0]), //
.WD(grfdatain), //
.RD1(grf_1), //
.RD2(grf_2) //
);
IM im (
.pc(pc), //
.instr(instr), //
.opcode(opcode), //
.rs(rs), //
.rt(rt), //
.rd(rd), //
.s(s), //
.func(func), //
.imm(imm) //
);
EXT ext (
.extop(extop), //
.imm(imm), //
.extresult(extresult) //
);
wire s_if;
assign s_if=sll_if|srl_if;
MUX grf_or_imm (
.sel({1'b0, alusrc}),
.sel0(grf_2), //
.sel1(extresult),
.sel2(32'h00000000),
.sel3(32'h00000000),
.out(grf_2_or_imm) //
);
MUX aluBin (
.sel({1'b0, s_if}),
.sel0(grf_2_or_imm), //
.sel1({27'b0,s}),
.sel2(32'h00000000),
.sel3(32'h00000000),
.out(aluB) //
);
MUX aluAin (
.sel({1'b0, s_if}),
.sel0(grf_1), //
.sel1(grf_2),
.sel2(32'h00000000),
.sel3(32'h00000000),
.out(aluA) //
);
ALU alu (
.aluop(aluop), //
.A(aluA), //
.B(aluB), //
.result(aluresult), //
.zero(zero), //
.overflow(overflow) //
);
MUX grfwrite (
.sel(regwritedst), //
.sel0({27'b0, rt}), //
.sel1({27'b0, rd}), //
.sel2(32'b11111), //
.sel3(32'h00000000), //
.out(grfwriteaddr) //
);
NPC npc (
.clk(clk), //
.reset(reset), //
.beq_if(beq_if), //
.j_if(j_if), //
.jr_if(jr_if),
.jal_if(jal_if), //
.zero(zero), //
.imm(extresult), //
.j_addr(instr[25:0]), //
.jr_addr(grf_1), //
.NPC(pc), //
.NPC_4(jal_ra) //
);
DM dm (
.clk(clk), //
.reset(reset), //
.PC(pc), //
.memwrite(memwrite), //
.memaddr(aluresult), //
.memdata(grf_2), //
.outdata(memoutdata) //
);
endmodule

测试方案

通过mars编写汇编程序,编写相关测试代码,将mars生成的机器码通过文件导入到verilog,通过向输出中间数据,和mars进行对拍,以此验证各代码是否运行正确。

思考题

1.

addr信号来自于ALU的结果,地址信号 addr 位数为什么是 [11:2] 而不是 [9:0]是因为DM是按照字存储的,需要除以4,同时低两位用于其他作用,不可使用。

2.

如果采用控制信号每种取值所对应的指令

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
assign regwrite = ((opcode==`OPCODE0&&(func==`ADD||func==`SUB))||opcode==`ANDI||opcode==`ORI||opcode==`LUI||opcode==`JAL||opcode==`LW)?1'b1:1'b0;
assign regwritedst = (opcode==`OPCODE0&&(func==`ADD||func==`SUB||func==`SLL))?2'b01:
(opcode==`JAL)?2'b10:2'b00;
assign alusrc = (opcode==`ANDI||opcode==`ORI||opcode==`LUI||opcode==`SW||opcode==`LW)?1'b1:1'b0;
assign memwrite = (opcode==`SW)?1'b1:1'b0;
assign memtoreg = (opcode==`LW)?1'b1:1'b0;
assign extop = (opcode==`SW||opcode==`LW||opcode==`BEQ)?2'b01:
(opcode==`LUI)?2'b10:2'b00;
assign beq_if = (opcode==`BEQ)?1'b1:1'b0;
assign j_if = (opcode==`J)?1'b1:1'b0;
assign jal_if = (opcode==`JAL)?1'b1:1'b0;
assign jr_if = (opcode==`OPCODE0&&func==`JR)?1'b1:1'b0;
assign aluop =
(opcode==`OPCODE0&&func==`ADD)?4'b0000:
(opcode==`OPCODE0&&func==`SUB)?4'b0001:
(opcode==`ANDI)?4'b0100:
(opcode==`ORI)?4'b0101:
(opcode==`LUI)?4'b0000:
(opcode==`J)?4'b0000:
(opcode==`JAL)?4'b0000:
(opcode==`OPCODE0&&func==`JR)?4'b0000:
(opcode==`BEQ)?4'b0001:
(opcode==`SW)?4'b0000:
(opcode==`LW)?4'b0000:
(opcode==`OPCODE0&&func==`SLL)?4'b0000:4'b0000;

这种做法是可以方便地管理不同信号的控制,如果新添加信号只需要更改对应信号控制即可,但是如果要添加的指令过多可能存在修改过多信号的问题,而且不便于管理同类命令。

如果采用指令对应的控制信号如何取值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
assign {regwrite,regwritedst,alusrc,memwrite,memtoreg,extop,beq_if,j_if,jal_if,jr_if,aluop} = 
(opcode==`OPCODE0&&func==`ADD)?{16'b1_01_0_00_00_0000_0000}:
(opcode==`OPCODE0&&func==`SUB)?{16'b1_01_0_00_00_0000_0001}:
(opcode==`ANDI)?{16'b1_00_1_00_00_0000_0100}:

(opcode==`LUI)?{16'b1_00_1_00_10_0000_0000}:

(opcode==`ORI)?{16'b1_00_1_00_00_0000_0101}:

(opcode==`J)?{16'b0_00_0_00_00_0100_0000}:
(opcode==`JAL)?{16'b1_10_0_00_00_0010_0000}:
(opcode==`OPCODE0&&func==`JR)?{16'b0_00_0_00_00_0001_0000}:
(opcode==`BEQ)?{16'b0_00_0_00_01_1000_0001}:
(opcode==`SW)?{16'b0_00_1_10_01_0000_0000}:
(opcode==`LW)?{16'b1_00_1_01_01_0000_0000}:
(opcode==`OPCODE0&&func==`SLL)?{16'b0_01_0_00_00_0000_0000}:{16'b0_00_0_00_00_0000_0000};

这种优点是可以分类管理不同的命令,如果要新添加命令就只需要添加对应命令的所有信号输出即可,不会影响其他命令,缺点是如果新添加的命令有新的信号,剩下的所有命令也需要更改输出信号格式。

3.

同步复位:只有clk处于上升沿时,reset为高电平才能复位,所有元器件同步在时钟上升沿复位。

异步复位:只要reset为上升沿,元器件就会复位,与clk信号无关,是异步的。

4.

add和addu,addi 与 addiu,本质上只是是否考虑溢出的问题,MIPS本身都是对其进行无符号运算,如果不考虑溢出自然是相同的。

附录:

题目测试代码翻译:

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
0x0000000000003000: 34 1C 00 00 ori $gp, $zero, 0 
0x0000000000003004: 34 1D 00 00 ori $sp, $zero, 0
0x0000000000003008: 34 01 34 56 ori $at, $zero, 0x3456
0x000000000000300c: 00 21 08 20 add $at, $at, $at
0x0000000000003010: 8C 01 00 04 lw $at, 4($zero)
0x0000000000003014: AC 01 00 04 sw $at, 4($zero)
0x0000000000003018: 3C 02 78 78 lui $v0, 0x7878
0x000000000000301c: 00 41 18 22 sub $v1, $v0, $at
0x0000000000003020: 3C 05 12 34 lui $a1, 0x1234
0x0000000000003024: 34 04 00 05 ori $a0, $zero, 5
0x0000000000003028: 00 00 00 00 nop
0x000000000000302c: AC 85 FF FF sw $a1, -1($a0)
0x0000000000003030: 8C 83 FF FF lw $v1, -1($a0)
0x0000000000003034: 10 65 00 03 beq $v1, $a1, 0x44
0x0000000000003038: 00 00 00 00 nop
0x000000000000303c: 10 00 00 11 b 0x84
0x0000000000003040: 00 00 00 00 nop
0x0000000000003044: 34 67 04 04 ori $a3, $v1, 0x404
0x0000000000003048: 10 E3 00 0E beq $a3, $v1, 0x84
0x000000000000304c: 00 00 00 00 nop
0x0000000000003050: 3C 08 77 77 lui $t0, 0x7777
0x0000000000003054: 35 08 FF FF ori $t0, $t0, 0xffff
0x0000000000003058: 00 08 00 22 neg $zero, $t0
0x000000000000305c: 34 00 11 00 ori $zero, $zero, 0x1100
0x0000000000003060: 00 E6 50 20 add $t2, $a3, $a2
0x0000000000003064: 34 08 00 00 ori $t0, $zero, 0
0x0000000000003068: 34 09 00 01 ori $t1, $zero, 1
0x000000000000306c: 34 0A 00 01 ori $t2, $zero, 1
0x0000000000003070: 01 0A 40 20 add $t0, $t0, $t2
0x0000000000003074: 11 09 FF FE beq $t0, $t1, 0x70
0x0000000000003078: 0C 00 0C 22 jal 0x3088
0x000000000000307c: 00 00 00 00 nop
0x0000000000003080: 01 4A 50 20 add $t2, $t2, $t2
0x0000000000003084: 10 00 FF FF b 0x84
0x0000000000003088: 01 4A 50 20 add $t2, $t2, $t2
0x000000000000308c: 03 E0 00 08 jr $ra
0x0000000000003090: 00 00 00 00 nop
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
@00003000: $28 <= 00000000
@00003004: $29 <= 00000000
@00003008: $ 1 <= 00003456
@0000300c: $ 1 <= 000068ac
@00003010: $ 1 <= 00000000
@00003014: *00000004 <= 00000000
@00003018: $ 2 <= 78780000
@0000301c: $ 3 <= 78780000
@00003020: $ 5 <= 12340000
@00003024: $ 4 <= 00000005
@0000302c: *00000004 <= 12340000
@00003030: $ 3 <= 12340000
@00003044: $ 7 <= 12340404
@00003050: $ 8 <= 77770000
@00003054: $ 8 <= 7777ffff
@00003058: $ 0 <= 88880001
@0000305c: $ 0 <= 00001100
@00003060: $10 <= 12340404
@00003064: $ 8 <= 00000000
@00003068: $ 9 <= 00000001
@0000306c: $10 <= 00000001
@00003070: $ 8 <= 00000001
@00003070: $ 8 <= 00000002
@00003078: $31 <= 0000307c
@00003088: $10 <= 00000002
@00003080: $10 <= 00000004

所涉及的指令的手册解释

image-20241030110149128image-20241030110215113