Skip to content

Commit 9adf4cf

Browse files
committed
part 1 of thumb long branch link
1 parent 731b7b3 commit 9adf4cf

File tree

8 files changed

+538
-448
lines changed

8 files changed

+538
-448
lines changed

.github/workflows/gba.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,11 @@ jobs:
119119
- ldrh_strh_imm_offset
120120
- ldr_str_sp_rel
121121
- add_cmp_mov_hi
122+
- add_sub_sp
122123
- b
123124
- bcc
124125
- bx
125-
- add_sub_sp
126+
- bl_blx_prefix
126127
# - push_pop
127128

128129
steps:

cores/gba/rtl/cpu/ControlUnit.sv

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1149,10 +1149,12 @@ module GBA_ControlUnit (
11491149
// TODO: Currently this instr lasts an extra cycle. We need to overlap the fetch and cycle 2.
11501150
ARM_INSTR_BRANCH_LINK: begin
11511151
if (cycle == 8'd0) begin
1152-
// Rd should be R14 (LR)
1152+
// Rd == R14 (LR)
11531153
control_signals.ALU_writeback = ALU_WB_REG_RD;
11541154

11551155
control_signals.ALU_op = ALU_OP_SUB;
1156+
1157+
// Rn == R15 (PC)
11561158
control_signals.A_bus_source = A_BUS_SRC_RN;
11571159

11581160
control_signals.B_bus_source = B_BUS_SRC_IMM;
@@ -1200,6 +1202,31 @@ module GBA_ControlUnit (
12001202
end
12011203
end
12021204

1205+
ARM_INSTR_THUMB_LONG_BRANCH_LINK_0: begin
1206+
if (cycle == 8'd0) begin
1207+
control_signals.addr_bus_src = ADDR_SRC_INCR;
1208+
control_signals |= fetch_next_instr();
1209+
control_signals.pipeline_advance = 1'b1;
1210+
control_signals.incrementer_writeback = 1'b1;
1211+
1212+
control_signals.ALU_op = ALU_OP_ADD;
1213+
1214+
// Rn == R15 (PC)
1215+
control_signals.A_bus_source = A_BUS_SRC_RN;
1216+
1217+
// Rd == R14 (LR)
1218+
control_signals.ALU_writeback = ALU_WB_REG_RD;
1219+
1220+
control_signals.B_bus_source = B_BUS_SRC_IMM;
1221+
control_signals.B_bus_imm = decoder_bus.word.arm.branch.imm24;
1222+
control_signals.B_bus_sign_extend = 1'b1;
1223+
1224+
control_signals.shift_type = SHIFT_LSL;
1225+
control_signals.shift_amount = 5'd12;
1226+
1227+
end
1228+
end
1229+
12031230
ARM_INSTR_SWI: begin
12041231
if (cycle == 8'd0) begin
12051232
// Rd should be R14 (LR)

cores/gba/rtl/cpu/Decoder.sv

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,17 @@ module GBA_Decoder (
3737
end
3838
end
3939

40+
logic [10:0] thumb_bl_imm11;
41+
42+
always_ff @(posedge clk) begin
43+
if (reset) begin
44+
thumb_bl_imm11 <= 11'b0;
45+
end else if (execution_mode == MODE_THUMB && IR_THUMB[15:11] == 5'b11110) begin
46+
thumb_bl_imm11 <= IR_THUMB[10:0];
47+
$display("[GBA_Decoder] Latched upper half of BL immediate value 0x%03x", IR_THUMB[10:0]);
48+
end
49+
end
50+
4051
always_comb begin
4152
bus.instr_type = ARM_INSTR_UNDEFINED;
4253
bus.condition_pass = 1'b1;
@@ -344,7 +355,20 @@ module GBA_Decoder (
344355

345356
// Long Branch with Link
346357
16'b1111_????_????_????: begin
347-
$display("[Decoder] Detected THUMB BL instruction with IR=0x%08x", IR_THUMB);
358+
if (IR_THUMB[11] == 1'b0) begin
359+
// bus.instr_type = ARM_INSTR_BRANCH_LINK;
360+
361+
bus.instr_type = ARM_INSTR_THUMB_LONG_BRANCH_LINK_0;
362+
363+
// Overwrite Rn and Rd
364+
bus.decoded_regs.Rn = 4'd15;
365+
bus.decoded_regs.Rd = 4'd14;
366+
367+
bus.word.arm.branch.imm24 = {{13{IR_THUMB[10]}}, IR_THUMB[10:0]};
368+
$display("[Decoder] Detected THUMB BL instruction with IR=0x%08x", IR_THUMB);
369+
end else begin
370+
371+
end
348372
end
349373

350374
// Add Offset to Stack Pointer

cores/gba/rtl/cpu/example.sv

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module ExampleModule (
2+
input logic clk,
3+
);
4+
5+
always_ff @(posedge clk) begin
6+
// do stuff here
7+
end

cores/gba/rtl/cpu/types.sv

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,9 @@ package gba_cpu_types_pkg;
295295
/// Branch and exchange (BX)
296296
ARM_INSTR_BRANCH_EX,
297297

298+
/// Thumb Long Branch with Link (BL) - first instruction
299+
ARM_INSTR_THUMB_LONG_BRANCH_LINK_0,
300+
298301
// ======================================================
299302
// Data Processing
300303
// ======================================================
@@ -355,7 +358,11 @@ package gba_cpu_types_pkg;
355358
ARM_INSTR_MRS,
356359

357360
/// MSR (write CPSR/SPSR)
358-
ARM_INSTR_MSR
361+
ARM_INSTR_MSR,
362+
363+
/// This instruction is for the BL instruction in thumb mode which takes
364+
/// 2 instructions to execute.
365+
ARM_INSTR_THUMB_STALL
359366

360367
} arm_instr_t;
361368

cores/gba/tests/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ add_subdirectory(golden/nba/src/nba)
44

55
add_subdirectory(cpu)
66
add_subdirectory(arm.gba)
7+
add_subdirectory(thumb.gba)
78

89
add_executable(test_gba
910
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
@@ -22,6 +23,7 @@ target_link_libraries(test_gba
2223
PRIVATE
2324
test_cpu_adv
2425
test_arm_gba
26+
test_thumb_gba
2527
GTest::gtest
2628
libcommon
2729
)

planning/gba/Branch and Link.md

Lines changed: 464 additions & 442 deletions
Large diffs are not rendered by default.

planning/gba/Branch and Link.svg

Lines changed: 2 additions & 2 deletions
Loading

0 commit comments

Comments
 (0)