Skip to content

Commit 4f580e8

Browse files
committed
implement BX instruction
1 parent 33f43fa commit 4f580e8

File tree

6 files changed

+72
-25
lines changed

6 files changed

+72
-25
lines changed

.github/workflows/gba.yaml

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -66,17 +66,18 @@ jobs:
6666
fail-fast: true
6767
matrix:
6868
test:
69-
- data_proc_immediate
70-
- data_proc_immediate_shift
71-
- data_proc_register_shift
72-
- ldm_stm
73-
- ldr_str_immediate_offset
74-
- ldr_str_register_offset
75-
- ldrh_strh
76-
- ldrsb_ldrsh
77-
- b_bl
78-
- swi
79-
- mul_mla
69+
- arm_data_proc_immediate
70+
- arm_data_proc_immediate_shift
71+
- arm_data_proc_register_shift
72+
- arm_ldm_stm
73+
- arm_ldr_str_immediate_offset
74+
- arm_ldr_str_register_offset
75+
- arm_ldrh_strh
76+
- arm_ldrsb_ldrsh
77+
- arm_b_bl
78+
- arm_bx
79+
- arm_swi
80+
- arm_mul_mla
8081

8182
steps:
8283
- uses: actions/checkout@v4
@@ -89,4 +90,4 @@ jobs:
8990

9091
- name: Run GBA tests
9192
run: |
92-
.\test_gba.exe --gtest_filter=*arm_${{ matrix.test }}_json --test-dir=${{ github.workspace }}/tests/
93+
.\test_gba.exe --gtest_filter=*${{ matrix.test }}_json --test-dir=${{ github.workspace }}/tests/

cores/gba/rtl/cpu/CPU.sv

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ module ARM7TMDI (
2929
/// Data that has been latched from the read bus
3030
word_t read_data;
3131

32+
execution_mode_t execution_mode;
33+
assign execution_mode = execution_mode_t'(regs.CPSR[5]);
34+
3235
always_comb begin
3336
if (control_signals.exception != EXCEPTION_NONE) begin
3437
// TODO: think about combining with `update_cspr_mode`
@@ -378,11 +381,20 @@ module ARM7TMDI (
378381
$display("Setting flush_req_pending to ensure flush on next cycle.");
379382
end
380383
end else if (control_signals.incrementer_writeback) begin
381-
// PC = PC + 4
384+
unique case (execution_mode)
385+
MODE_ARM: begin
386+
// PC = PC + 4
382387

383-
`WRITE_REG(regs, cpu_mode, 15, read_reg(regs, cpu_mode, 15) + 32'd4)
384-
$display("Incrementing PC to: %0d", read_reg(regs, cpu_mode, 15) + 32'd4);
385-
$fflush();
388+
`WRITE_REG(regs, cpu_mode, 15, read_reg(regs, cpu_mode, 15) + 32'd4)
389+
$display("Incrementing PC to: %0d", read_reg(regs, cpu_mode, 15) + 32'd4);
390+
$fflush();
391+
end
392+
MODE_THUMB: begin
393+
`WRITE_REG(regs, cpu_mode, 15, read_reg(regs, cpu_mode, 15) + 32'd2)
394+
$display("Incrementing PC to: %0d", read_reg(regs, cpu_mode, 15) + 32'd2);
395+
$fflush();
396+
end
397+
endcase
386398
end
387399

388400
$display("[CPU] Checking ALU flags writeback. ALU_set_flags=%b, restore_cpsr_from_spsr=%b",
@@ -393,6 +405,13 @@ module ARM7TMDI (
393405
$display("Restoring CPSR from SPSR_%0d: 0x%08x", cpu_mode, read_spsr(regs, cpu_mode));
394406
end
395407

408+
if (control_signals.set_thumb_mode) begin
409+
regs.CPSR[5] <= B_bus[0];
410+
`WRITE_REG(regs, cpu_mode, 4'd15, B_bus & 32'hFFFFFFFE)
411+
flush_req <= 1'b1;
412+
$display("Setting Thumb mode bit in CPSR");
413+
end
414+
396415
if (control_signals.ALU_set_flags && control_signals.pipeline_advance) begin
397416

398417
if ((decoder_bus.word.Rd == 4'd15) && mode_has_spsr(
@@ -452,7 +471,6 @@ module ARM7TMDI (
452471
`WRITE_REG(regs, control_signals.force_user_mode ? CPU_MODE_USR : cpu_mode,
453472
decoder_bus.word.Rn, alu_bus.result)
454473
end
455-
ALU_WB_REG_14: `WRITE_REG(regs, cpu_mode, 14, alu_bus.result)
456474
ALU_WB_REG_RP: begin
457475
`WRITE_REG(regs, control_signals.force_user_mode ? CPU_MODE_USR : cpu_mode,
458476
control_signals.Rp_imm, alu_bus.result)
@@ -486,7 +504,15 @@ module ARM7TMDI (
486504
end
487505

488506
ADDR_SRC_INCR: begin
489-
bus.addr <= bus.addr + 32'd4;
507+
unique case (execution_mode)
508+
MODE_ARM: begin
509+
bus.addr <= bus.addr + 32'd4;
510+
end
511+
MODE_THUMB: begin
512+
bus.addr <= bus.addr + 32'd2;
513+
$display("Incrementing address bus for Thumb mode: new addr=%0d", bus.addr);
514+
end
515+
endcase
490516
end
491517
endcase
492518
end

cores/gba/rtl/cpu/ControlUnit.sv

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1016,7 +1016,7 @@ module ControlUnit (
10161016
end
10171017

10181018
// ============================
1019-
// Branch & Branch with Link
1019+
// Branch
10201020
// ============================
10211021

10221022
ARM_INSTR_BRANCH: begin
@@ -1075,6 +1075,22 @@ module ControlUnit (
10751075
end
10761076
end
10771077

1078+
ARM_INSTR_BRANCH_EX: begin
1079+
if (cycle == 8'd0) begin
1080+
control_signals.ALU_op = ALU_OP_MOV;
1081+
control_signals.addr_bus_src = ADDR_SRC_ALU;
1082+
1083+
// control_signals.ALU_writeback = ALU_WB_REG_RP;
1084+
// control_signals.Rp_imm = 4'd15;
1085+
1086+
control_signals.B_bus_source = B_BUS_SRC_REG_RN;
1087+
1088+
control_signals.set_thumb_mode = 1'b1;
1089+
1090+
control_signals.pipeline_advance = 1'b1;
1091+
end
1092+
end
1093+
10781094
ARM_INSTR_SWI: begin
10791095
if (cycle == 8'd0) begin
10801096
// Rd should be R14 (LR)

cores/gba/rtl/cpu/Decoder.sv

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ module GBA_Decoder (
4444
priority casez (IR)
4545
/// Branch and Branch Exchange
4646
32'b????_0001_0010_1111_1111_1111_0001_????: begin
47+
bus.word.instr_type = ARM_INSTR_BRANCH_EX;
48+
bus.word.Rn = IR[3:0];
4749
$display("[GBA_Decoder] Detected BX instruction with IR=0x%08x", IR);
4850
end
4951

cores/gba/rtl/cpu/control_types.sv

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,7 @@ package gba_control_types_pkg;
8282
ALU_WB_REG_RN,
8383

8484
/// If set, we need also need to set `Rp_imm`
85-
ALU_WB_REG_RP,
86-
87-
/// Write back to register 14
88-
ALU_WB_REG_14
85+
ALU_WB_REG_RP
8986
} alu_writeback_source_t;
9087

9188
typedef struct packed {
@@ -114,6 +111,8 @@ package gba_control_types_pkg;
114111

115112
exception_t exception;
116113

114+
logic set_thumb_mode;
115+
117116
// ======================================================
118117
// A Bus
119118
// ======================================================
@@ -127,8 +126,6 @@ package gba_control_types_pkg;
127126
// B Bus
128127
// ======================================================
129128

130-
/// Hello
131-
/// There
132129
B_bus_source_t B_bus_source;
133130

134131
/// Immediate value to place on the B bus, if selected in `B_bus_source`

cores/gba/rtl/cpu/types.sv

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,11 @@ package gba_cpu_types_pkg;
114114

115115
} cpu_regs_t;
116116

117+
typedef enum logic {
118+
MODE_ARM = 1'b0,
119+
MODE_THUMB = 1'b1
120+
} execution_mode_t;
121+
117122
// TODO: figure out priority
118123
typedef enum logic [2:0] {
119124
/// No exception

0 commit comments

Comments
 (0)