mirror of https://github.com/bsnes-emu/bsnes.git
136 lines
4.7 KiB
C++
136 lines
4.7 KiB
C++
auto ARM::pipeline_step() -> void {
|
|
pipeline.execute = pipeline.decode;
|
|
pipeline.decode = pipeline.fetch;
|
|
|
|
unsigned sequential = Sequential;
|
|
if(pipeline.nonsequential) {
|
|
pipeline.nonsequential = false;
|
|
sequential = Nonsequential;
|
|
}
|
|
|
|
if(cpsr().t == 0) {
|
|
r(15).data += 4;
|
|
pipeline.fetch.address = r(15) & ~3;
|
|
pipeline.fetch.instruction = read(Prefetch | Word | sequential, pipeline.fetch.address);
|
|
} else {
|
|
r(15).data += 2;
|
|
pipeline.fetch.address = r(15) & ~1;
|
|
pipeline.fetch.instruction = read(Prefetch | Half | sequential, pipeline.fetch.address);
|
|
}
|
|
}
|
|
|
|
auto ARM::arm_step() -> void {
|
|
if(pipeline.reload) {
|
|
pipeline.reload = false;
|
|
r(15).data &= ~3;
|
|
|
|
pipeline.fetch.address = r(15) & ~3;
|
|
pipeline.fetch.instruction = read(Prefetch | Word | Nonsequential, pipeline.fetch.address);
|
|
|
|
pipeline_step();
|
|
}
|
|
|
|
pipeline_step();
|
|
|
|
if(processor.irqline && cpsr().i == 0) {
|
|
vector(0x00000018, Processor::Mode::IRQ);
|
|
return;
|
|
}
|
|
|
|
instructions++;
|
|
if(trace) {
|
|
print(disassemble_registers(), "\n");
|
|
print(disassemble_arm_instruction(pipeline.execute.address), "\n");
|
|
usleep(100000);
|
|
}
|
|
|
|
if(condition(instruction() >> 28) == false) return;
|
|
|
|
#define decode(pattern, execute) if( \
|
|
(instruction() & std::integral_constant<uint32, bit::mask(pattern)>::value) \
|
|
== std::integral_constant<uint32, bit::test(pattern)>::value \
|
|
) return arm_op_ ## execute()
|
|
|
|
decode("???? 0001 0010 ++++ ++++ ++++ 0001 ????", branch_exchange_register);
|
|
decode("???? 0000 00?? ???? ???? ???? 1001 ????", multiply);
|
|
decode("???? 0000 1??? ???? ???? ???? 1001 ????", multiply_long);
|
|
decode("???? 0001 0?00 ++++ ???? ---- 0000 ----", move_to_register_from_status);
|
|
decode("???? 0001 0?00 ???? ???? ---- 1001 ????", memory_swap);
|
|
decode("???? 0001 0?10 ???? ++++ ---- 0000 ????", move_to_status_from_register);
|
|
decode("???? 0011 0?10 ???? ++++ ???? ???? ????", move_to_status_from_immediate);
|
|
decode("???? 000? ?0?1 ???? ???? ---- 11?1 ????", load_register);
|
|
decode("???? 000? ?1?1 ???? ???? ???? 11?1 ????", load_immediate);
|
|
decode("???? 000? ?0?? ???? ???? ---- 1011 ????", move_half_register);
|
|
decode("???? 000? ?1?? ???? ???? ???? 1011 ????", move_half_immediate);
|
|
decode("???? 000? ???? ???? ???? ???? ???0 ????", data_immediate_shift);
|
|
decode("???? 000? ???? ???? ???? ???? 0??1 ????", data_register_shift);
|
|
decode("???? 001? ???? ???? ???? ???? ???? ????", data_immediate);
|
|
decode("???? 010? ???? ???? ???? ???? ???? ????", move_immediate_offset);
|
|
decode("???? 011? ???? ???? ???? ???? ???0 ????", move_register_offset);
|
|
decode("???? 100? ???? ???? ???? ???? ???? ????", move_multiple);
|
|
decode("???? 101? ???? ???? ???? ???? ???? ????", branch);
|
|
decode("???? 1111 ???? ???? ???? ???? ???? ????", software_interrupt);
|
|
|
|
#undef decode
|
|
|
|
crash = true;
|
|
}
|
|
|
|
auto ARM::thumb_step() -> void {
|
|
if(pipeline.reload) {
|
|
pipeline.reload = false;
|
|
r(15).data &= ~1;
|
|
|
|
pipeline.fetch.address = r(15) & ~1;
|
|
pipeline.fetch.instruction = read(Prefetch | Half | Nonsequential, pipeline.fetch.address);
|
|
|
|
pipeline_step();
|
|
}
|
|
|
|
pipeline_step();
|
|
|
|
if(processor.irqline && cpsr().i == 0) {
|
|
vector(0x00000018, Processor::Mode::IRQ);
|
|
r(14) += 2;
|
|
return;
|
|
}
|
|
|
|
instructions++;
|
|
if(trace) {
|
|
print(disassemble_registers(), "\n");
|
|
print(disassemble_thumb_instruction(pipeline.execute.address), "\n");
|
|
}
|
|
|
|
#define decode(pattern, execute) if( \
|
|
(instruction() & std::integral_constant<uint32, bit::mask(pattern)>::value) \
|
|
== std::integral_constant<uint32, bit::test(pattern)>::value \
|
|
) return thumb_op_ ## execute()
|
|
|
|
decode("0001 10?? ???? ????", adjust_register);
|
|
decode("0001 11?? ???? ????", adjust_immediate);
|
|
decode("000? ???? ???? ????", shift_immediate);
|
|
decode("001? ???? ???? ????", immediate);
|
|
decode("0100 00?? ???? ????", alu);
|
|
decode("0100 0111 0??? ?---", branch_exchange);
|
|
decode("0100 01?? ???? ????", alu_hi);
|
|
decode("0100 1??? ???? ????", load_literal);
|
|
decode("0101 ???? ???? ????", move_register_offset);
|
|
decode("0110 ???? ???? ????", move_word_immediate);
|
|
decode("0111 ???? ???? ????", move_byte_immediate);
|
|
decode("1000 ???? ???? ????", move_half_immediate);
|
|
decode("1001 ???? ???? ????", move_stack);
|
|
decode("1010 ???? ???? ????", add_register_hi);
|
|
decode("1011 0000 ???? ????", adjust_stack);
|
|
decode("1011 ?10? ???? ????", stack_multiple);
|
|
decode("1100 ???? ???? ????", move_multiple);
|
|
decode("1101 1111 ???? ????", software_interrupt);
|
|
decode("1101 ???? ???? ????", branch_conditional);
|
|
decode("1110 0??? ???? ????", branch_short);
|
|
decode("1111 0??? ???? ????", branch_long_prefix);
|
|
decode("1111 1??? ???? ????", branch_long_suffix);
|
|
|
|
#undef decode
|
|
|
|
crash = true;
|
|
}
|