bsnes/higan/processor/arm/step.cpp

136 lines
4.7 KiB
C++

auto ARM::stepPipeline() -> void {
pipeline.execute = pipeline.decode;
pipeline.decode = pipeline.fetch;
uint 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::stepARM() -> 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);
stepPipeline();
}
stepPipeline();
if(processor.irqline && cpsr().i == 0) {
interrupt(Processor::Mode::IRQ, 0x18);
return;
}
instructions++;
if(trace) {
print(disassembleRegisters(), "\n");
print(disassembleInstructionARM(pipeline.execute.address), "\n");
usleep(100000);
}
if(condition(instruction() >> 28) == false) return;
#define decode(pattern, execute) if( \
(instruction() & std::integral_constant<uint32_t, bit::mask(pattern)>::value) \
== std::integral_constant<uint32_t, 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::stepTHUMB() -> 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);
stepPipeline();
}
stepPipeline();
if(processor.irqline && cpsr().i == 0) {
interrupt(Processor::Mode::IRQ, 0x18);
r(14).data += 2;
return;
}
instructions++;
if(trace) {
print(disassembleRegisters(), "\n");
print(disassembleInstructionTHUMB(pipeline.execute.address), "\n");
}
#define decode(pattern, execute) if( \
(instruction() & std::integral_constant<uint32_t, bit::mask(pattern)>::value) \
== std::integral_constant<uint32_t, 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;
}