Skip to content

Commit 138cc9b

Browse files
committed
emulation fixes and added difftest with unicorn engine
1 parent 0fbdc8c commit 138cc9b

25 files changed

Lines changed: 480 additions & 70 deletions

File tree

llarm-emu/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,10 @@ write_basic_package_version_file(
135135
)
136136

137137

138+
# maybe not needed, might remove later
139+
add_subdirectory(tests/diff)
140+
141+
138142
# installations
139143
install(TARGETS ${TARGET_BIN} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
140144
install(FILES llarm/llarm-emu.hpp DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/llarm)

llarm-emu/llarm/llarm-emu.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,18 @@ namespace llarm::emu {
147147
void next_instruction() {
148148
cpu.core.continue_cycle = true;
149149
}
150+
151+
// Call after next_instruction() to block until the next instruction finishes executing.
152+
// Uses a two-phase wait on execution_done to avoid races with the cycle boundary.
153+
void wait_for_execution() const {
154+
while ( cpu.core.execution_done.load(std::memory_order_acquire)) {}
155+
while (!cpu.core.execution_done.load(std::memory_order_acquire)) {}
156+
}
157+
158+
// Block until the first instruction has finished executing after run().
159+
void wait_for_first_execution() const {
160+
while (!cpu.core.execution_done.load(std::memory_order_acquire)) {}
161+
}
150162
};
151163

152164
struct cpu_headless {

llarm-emu/src/cpu/coprocessor/cp15.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,7 +1164,7 @@ void CP15::setup_R0_processor_id() {
11641164
case id::product_family::UNKNOWN: llarm::out::error("Cannot configure R0_ID coprocessor register for unknown processor");
11651165
}
11661166

1167-
write(id::cp15::R0_ID_REVISION, settings.revision);
1167+
force_write(id::cp15::R0_ID_REVISION, settings.revision);
11681168

11691169
if (pre_arm7) {
11701170
switch (settings.processor) {
@@ -1179,8 +1179,8 @@ void CP15::setup_R0_processor_id() {
11791179
} else {
11801180
// https://developer.arm.com/documentation/ddi0406/b/Appendices/ARMv4-and-ARMv5-Differences/System-Control-coprocessor--CP15--support/c0--ID-support?lang=en#CHDGAGJH
11811181

1182-
const u8 upper_ppn = static_cast<u8>(settings.ppn);
1183-
1182+
const u8 ppn_top = static_cast<u8>(settings.ppn >> 8);
1183+
11841184
if (arm7) {
11851185
// variant (ARM7 specific)
11861186
force_write(id::cp15::R0_ID_7_VARIANT, settings.variant);
@@ -1195,7 +1195,7 @@ void CP15::setup_R0_processor_id() {
11951195
}
11961196

11971197
// ppn
1198-
if (upper_ppn != 0x7) {
1198+
if (ppn_top != 0x7) {
11991199
llarm::out::error("PPN upper 4 bits must be 0x7 for ARM7 family");
12001200
}
12011201
} else if (post_arm7) {
@@ -1216,13 +1216,13 @@ void CP15::setup_R0_processor_id() {
12161216
force_write(id::cp15::R0_ID_POST7_VARIANT, settings.variant);
12171217

12181218
// ppn
1219-
if (upper_ppn == 0x7 || upper_ppn == 0x0) {
1219+
if (ppn_top == 0x7 || ppn_top == 0x0) {
12201220
llarm::out::error("PPN upper 4 bits must not be 0x7 or 0x0 for post-ARM7 family");
12211221
}
12221222
}
12231223

1224-
// PPN (primary part number)
1225-
force_write(id::cp15::R0_ID_PPN, upper_ppn);
1224+
// PPN (primary part number) — full 12-bit value
1225+
force_write(id::cp15::R0_ID_PPN, settings.ppn);
12261226

12271227
// implementor
12281228
// source: https://developer.arm.com/documentation/ddi0406/b/System-Level-Architecture/Virtual-Memory-System-Architecture--VMSA-/CP15-registers-for-a-VMSA-implementation/c0--Main-ID-Register--MIDR-?lang=en
@@ -1539,6 +1539,9 @@ void CP15::setup_R1_control() {
15391539

15401540
// L4
15411541
force_write(id::cp15::R1_L4, settings.is_L4_bit_enabled_cp15);
1542+
1543+
// implementation-defined SBO (Should Be One) bits
1544+
R1 |= settings.r1_sbo_mask;
15421545
}
15431546

15441547

llarm-emu/src/cpu/core/core.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ inline void CORE::arm_cycle_headless() {
3434

3535
inline void CORE::arm_cycle_step() {
3636
continue_cycle = false;
37+
execution_done = false;
3738
current_pc = reg.force_read(id::reg::R15);
3839

3940
const arm_fetch_struct arm_code_access = fetch.arm_fetch();
@@ -42,17 +43,16 @@ inline void CORE::arm_cycle_step() {
4243
return;
4344
}
4445

45-
//std::cout << "inst : " << arm_code_access.code << "\n";
4646
current_arm_code = arm_code_access.code;
4747

4848
const arm_decode_struct instruction = decode.arm_decode(arm_code_access.code);
4949

50-
//std::cout << "inst_id : " << llarm::as::arm_id_to_string(instruction.id) << "\n";
51-
5250
current_arm_id = instruction.id;
5351

5452
execute.arm_execute(instruction);
5553

54+
execution_done = true;
55+
5656
while (!continue_cycle.load()) {
5757
// wait till continue_cycle variable is true
5858
}
@@ -76,6 +76,7 @@ inline void CORE::arm_cycle_step() {
7676

7777
inline void CORE::thumb_cycle_step() {
7878
continue_cycle = false;
79+
execution_done = false;
7980
current_pc = reg.force_read(id::reg::R15);
8081

8182
const thumb_fetch_struct thumb_code_access = fetch.thumb_fetch();
@@ -91,6 +92,8 @@ inline void CORE::thumb_cycle_step() {
9192

9293
execute.thumb_execute(instruction);
9394

95+
execution_done = true;
96+
9497
while (true) {
9598
if (continue_cycle == true) {
9699
break;

llarm-emu/src/cpu/core/core.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ struct CORE {
8484
u16 current_thumb_code = 0;
8585
u32 current_pc = 0;
8686
std::atomic<bool> continue_cycle{false};
87+
std::atomic<bool> execution_done{false};
8788

8889
CORE(const SETTINGS& init_settings, RAM &ram, VIC& vic, UART& uart, TIMER& timer) :
8990
settings(init_settings),

llarm-emu/src/cpu/core/cycle/execute.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ void EXECUTE::arm_execute(const arm_decode_struct &instruction) {
162162
case arm_id::FTOUID: instructions.arm.vfp.FTOUID(code); return;
163163
case arm_id::FUITOD: instructions.arm.vfp.FUITOD(code); return;
164164
case arm_id::CPS: // TODO
165-
case arm_id::CPY: // TODO
165+
case arm_id::CPY: instructions.arm.movement.CPY(code); return;
166166
case arm_id::LDREX: // TODO
167167
case arm_id::MCRR2: // TODO
168168
case arm_id::MRRC2: // TODO

llarm-emu/src/cpu/core/registers.cpp

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -205,18 +205,25 @@ void REGISTERS::write(const id::reg register_id, const u32 value) {
205205
case id::mode::FIQ:
206206
case id::mode::FIQ_26:
207207
switch (register_id) {
208+
case id::reg::R8:
208209
case id::reg::R8_fiq: R8_fiq = value; return;
210+
case id::reg::R9:
209211
case id::reg::R9_fiq: R9_fiq = value; return;
212+
case id::reg::R10:
210213
case id::reg::R10_fiq: R10_fiq = value; return;
214+
case id::reg::R11:
211215
case id::reg::R11_fiq: R11_fiq = value; return;
216+
case id::reg::R12:
212217
case id::reg::R12_fiq: R12_fiq = value; return;
218+
case id::reg::R13:
213219
case id::reg::R13_fiq: R13_fiq = value; return;
220+
case id::reg::R14:
214221
case id::reg::R14_fiq: R14_fiq = value; return;
215222
case id::reg::SPSR_fiq: SPSR_fiq = value; return;
216223
default: break;
217224
}
218225
break;
219-
226+
220227
case id::mode::IRQ:
221228
case id::mode::IRQ_26:
222229
switch (register_id) {
@@ -225,9 +232,11 @@ void REGISTERS::write(const id::reg register_id, const u32 value) {
225232
case id::reg::R10: R10 = value; return;
226233
case id::reg::R11: R11 = value; return;
227234
case id::reg::R12: R12 = value; return;
235+
case id::reg::R13:
228236
case id::reg::R13_irq: R13_irq = value; return;
237+
case id::reg::R14:
229238
case id::reg::R14_irq: R14_irq = value; return;
230-
case id::reg::SPSR_irq: SPSR_irq = value; return;
239+
case id::reg::SPSR_irq: SPSR_irq = value; return;
231240
default: break;
232241
}
233242
break;
@@ -240,9 +249,11 @@ void REGISTERS::write(const id::reg register_id, const u32 value) {
240249
case id::reg::R10: R10 = value; return;
241250
case id::reg::R11: R11 = value; return;
242251
case id::reg::R12: R12 = value; return;
252+
case id::reg::R13:
243253
case id::reg::R13_svc: R13_svc = value; return;
254+
case id::reg::R14:
244255
case id::reg::R14_svc: R14_svc = value; return;
245-
case id::reg::SPSR_svc: SPSR_svc = value; return;
256+
case id::reg::SPSR_svc: SPSR_svc = value; return;
246257
default: break;
247258
}
248259
break;
@@ -254,9 +265,11 @@ void REGISTERS::write(const id::reg register_id, const u32 value) {
254265
case id::reg::R10: R10 = value; return;
255266
case id::reg::R11: R11 = value; return;
256267
case id::reg::R12: R12 = value; return;
268+
case id::reg::R13:
257269
case id::reg::R13_abt: R13_abt = value; return;
270+
case id::reg::R14:
258271
case id::reg::R14_abt: R14_abt = value; return;
259-
case id::reg::SPSR_abt: SPSR_abt = value; return;
272+
case id::reg::SPSR_abt: SPSR_abt = value; return;
260273
default: break;
261274
}
262275
break;
@@ -268,9 +281,11 @@ void REGISTERS::write(const id::reg register_id, const u32 value) {
268281
case id::reg::R10: R10 = value; return;
269282
case id::reg::R11: R11 = value; return;
270283
case id::reg::R12: R12 = value; return;
284+
case id::reg::R13:
271285
case id::reg::R13_und: R13_und = value; return;
286+
case id::reg::R14:
272287
case id::reg::R14_und: R14_und = value; return;
273-
case id::reg::SPSR_und: SPSR_und = value; return;
288+
case id::reg::SPSR_und: SPSR_und = value; return;
274289
default: break;
275290
}
276291
break;
@@ -459,18 +474,25 @@ u32 REGISTERS::read(const id::reg reg_id) const {
459474
case id::mode::FIQ:
460475
case id::mode::FIQ_26:
461476
switch (reg_id) {
477+
case id::reg::R8:
462478
case id::reg::R8_fiq: return R8_fiq;
479+
case id::reg::R9:
463480
case id::reg::R9_fiq: return R9_fiq;
481+
case id::reg::R10:
464482
case id::reg::R10_fiq: return R10_fiq;
483+
case id::reg::R11:
465484
case id::reg::R11_fiq: return R11_fiq;
485+
case id::reg::R12:
466486
case id::reg::R12_fiq: return R12_fiq;
487+
case id::reg::R13:
467488
case id::reg::R13_fiq: return R13_fiq;
489+
case id::reg::R14:
468490
case id::reg::R14_fiq: return R14_fiq;
469491
case id::reg::SPSR_fiq: return SPSR_fiq;
470492
default: break;
471493
}
472494
break;
473-
495+
474496
case id::mode::IRQ:
475497
case id::mode::IRQ_26:
476498
switch (reg_id) {
@@ -479,9 +501,11 @@ u32 REGISTERS::read(const id::reg reg_id) const {
479501
case id::reg::R10: return R10;
480502
case id::reg::R11: return R11;
481503
case id::reg::R12: return R12;
504+
case id::reg::R13:
482505
case id::reg::R13_irq: return R13_irq;
506+
case id::reg::R14:
483507
case id::reg::R14_irq: return R14_irq;
484-
case id::reg::SPSR_irq: return SPSR_irq;
508+
case id::reg::SPSR_irq: return SPSR_irq;
485509
default: break;
486510
}
487511
break;
@@ -494,9 +518,11 @@ u32 REGISTERS::read(const id::reg reg_id) const {
494518
case id::reg::R10: return R10;
495519
case id::reg::R11: return R11;
496520
case id::reg::R12: return R12;
521+
case id::reg::R13:
497522
case id::reg::R13_svc: return R13_svc;
523+
case id::reg::R14:
498524
case id::reg::R14_svc: return R14_svc;
499-
case id::reg::SPSR_svc: return SPSR_svc;
525+
case id::reg::SPSR_svc: return SPSR_svc;
500526
default: break;
501527
}
502528
break;
@@ -508,9 +534,11 @@ u32 REGISTERS::read(const id::reg reg_id) const {
508534
case id::reg::R10: return R10;
509535
case id::reg::R11: return R11;
510536
case id::reg::R12: return R12;
537+
case id::reg::R13:
511538
case id::reg::R13_abt: return R13_abt;
539+
case id::reg::R14:
512540
case id::reg::R14_abt: return R14_abt;
513-
case id::reg::SPSR_abt: return SPSR_abt;
541+
case id::reg::SPSR_abt: return SPSR_abt;
514542
default: break;
515543
}
516544
break;
@@ -522,9 +550,11 @@ u32 REGISTERS::read(const id::reg reg_id) const {
522550
case id::reg::R10: return R10;
523551
case id::reg::R11: return R11;
524552
case id::reg::R12: return R12;
553+
case id::reg::R13:
525554
case id::reg::R13_und: return R13_und;
555+
case id::reg::R14:
526556
case id::reg::R14_und: return R14_und;
527-
case id::reg::SPSR_und: return SPSR_und;
557+
case id::reg::SPSR_und: return SPSR_und;
528558
default: break;
529559
}
530560
break;

llarm-emu/src/cpu/instructions/arm/addressing_modes/load_store_multiple.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ address_struct ADDRESSING_MODE::ls_mul_inc_after(const u32 code) {
3232
const id::reg Rn_id = reg.fetch_reg_id(code, 16, 19);
3333

3434
const u32 start_address = reg.read(Rn_id);
35-
const u32 end_address = static_cast<u32>((llarm::util::popcount(list) * 4) - 4);
35+
const u32 end_address = start_address + static_cast<u32>((llarm::util::popcount(list) * 4) - 4);
3636

3737
if (reg.is_cond_valid(code) && llarm::util::bit_fetch(code, 21)) {
3838
reg.write(Rn_id, (reg.read(Rn_id) + (llarm::util::popcount(list) * 4)));
@@ -81,7 +81,7 @@ address_struct ADDRESSING_MODE::ls_mul_dec_after(const u32 code) {
8181

8282
const id::reg Rn_id = reg.fetch_reg_id(code, 16, 19);
8383

84-
const u32 start_address = reg.read(Rn_id) - static_cast<u32>((llarm::util::popcount(list) * 4) + 4);
84+
const u32 start_address = reg.read(Rn_id) - static_cast<u32>(llarm::util::popcount(list) * 4) + 4;
8585
const u32 end_address = reg.read(Rn_id);
8686

8787
if (reg.is_cond_valid(code) && llarm::util::bit_fetch(code, 21)) {

llarm-emu/src/cpu/instructions/arm/branching.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ void INSTRUCTIONS::arm::branching::BL(const u32 code) {
4242
* T Flag = Rm[0]
4343
* PC = Rm AND 0xFFFFFFFE
4444
*/
45-
// TODO
4645
void INSTRUCTIONS::arm::branching::BX(const u32 code) {
4746
const u32 Rm = reg.read(code, 0, 3);
4847

@@ -53,10 +52,12 @@ void INSTRUCTIONS::arm::branching::BX(const u32 code) {
5352

5453

5554
void INSTRUCTIONS::arm::branching::BLX1(/* const u32 code */) {
55+
llarm::out::warning("BLX1 is unimplemented");
5656
// TODO
5757
}
5858

5959

6060
void INSTRUCTIONS::arm::branching::BLX2(/* const u32 code */) {
61+
llarm::out::warning("BLX2 is unimplemented");
6162
// TODO
6263
}

llarm-emu/src/cpu/instructions/arm/coprocessor.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
* Coprocessor[cp_num]-dependent operation
1010
*/
1111
void INSTRUCTIONS::arm::coproc::CDP(/* const u32 code */) {
12+
llarm::out::warning("CDP is unimplemented");
1213
// TODO
1314
}
1415

@@ -23,6 +24,7 @@ void INSTRUCTIONS::arm::coproc::CDP(/* const u32 code */) {
2324
* assert address == end_address
2425
*/
2526
void INSTRUCTIONS::arm::coproc::LDC(/*const u32 code*/) {
27+
llarm::out::warning("LDC is unimplemented");
2628
// const address_struct addresses = address_mode.load_store_coprocessor(code);
2729
//
2830
// u32 address = addresses.start;
@@ -96,19 +98,20 @@ void INSTRUCTIONS::arm::coproc::MRC(const u32 code) {
9698
* Memory[address,4] = value from Coprocessor[cp_num]
9799
* assert address == end_address
98100
*/
99-
void INSTRUCTIONS::arm::coproc::STC(/* const u32 code */) { // TODO
101+
void INSTRUCTIONS::arm::coproc::STC(/* const u32 code */) {
102+
llarm::out::warning("STC is unimplemented");
100103
//const address_struct addresses = address_mode.load_store_coprocessor(code);
101104
// TODO
102105
}
103106

104107

105-
void INSTRUCTIONS::arm::coproc::CDP2(/* const u32 code */) { // TODO
106-
CDP(/*code*/); // TODO
108+
void INSTRUCTIONS::arm::coproc::CDP2(/* const u32 code */) {
109+
CDP(/*code*/);
107110
}
108111

109112

110-
void INSTRUCTIONS::arm::coproc::LDC2(/* const u32 code */) { // TODO
111-
LDC(/*code*/); // TODO
113+
void INSTRUCTIONS::arm::coproc::LDC2(/* const u32 code */) {
114+
LDC(/*code*/);
112115
}
113116

114117

0 commit comments

Comments
 (0)