thumb: add execution of instructions

also arm: fix some instructions

Signed-off-by: Amneesh Singh <natto@weirdnatto.in>
This commit is contained in:
2023-09-30 01:31:09 +05:30
parent 03dbb7052f
commit 36d71a4ee2
19 changed files with 1632 additions and 157 deletions

View File

@@ -307,6 +307,7 @@ Instruction::exec(CpuImpl& cpu) {
}
}
// TODO: clean this shit
// account for decrement
if (!data.up)
address -= (n_regs - 1) * alignment;
@@ -419,44 +420,6 @@ Instruction::exec(CpuImpl& cpu) {
bool overflow = cpu.cpsr.v();
bool carry = cpu.cpsr.c();
auto sub = [&carry, &overflow](uint32_t a, uint32_t b) -> uint32_t {
bool s1 = get_bit(a, 31);
bool s2 = get_bit(b, 31);
uint32_t result = a - b;
carry = b <= a;
overflow = s1 != s2 && s2 == get_bit(result, 31);
return result;
};
auto add = [&carry, &overflow](
uint32_t a, uint32_t b, bool c = 0) -> uint32_t {
bool s1 = get_bit(a, 31);
bool s2 = get_bit(b, 31);
// 33 bits
uint64_t result_ = a + b + c;
uint32_t result = result_ & 0xFFFFFFFF;
carry = get_bit(result_, 32);
overflow = s1 == s2 && s2 != get_bit(result, 31);
return result;
};
auto sbc = [&carry,
&overflow](uint32_t a, uint32_t b, bool c) -> uint32_t {
bool s1 = get_bit(a, 31);
bool s2 = get_bit(b, 31);
uint64_t result_ = a - b + c - 1;
uint32_t result = result_ & 0xFFFFFFFF;
carry = get_bit(result_, 32);
overflow = s1 != s2 && s2 == get_bit(result, 31);
return result;
};
switch (data.opcode) {
case OpCode::AND:
case OpCode::TST:
@@ -469,23 +432,23 @@ Instruction::exec(CpuImpl& cpu) {
break;
case OpCode::SUB:
case OpCode::CMP:
result = sub(op_1, op_2);
result = sub(op_1, op_2, carry, overflow);
break;
case OpCode::RSB:
result = sub(op_2, op_1);
result = sub(op_2, op_1, carry, overflow);
break;
case OpCode::ADD:
case OpCode::CMN:
result = add(op_1, op_2);
result = add(op_1, op_2, carry, overflow);
break;
case OpCode::ADC:
result = add(op_1, op_2, carry);
result = add(op_1, op_2, carry, overflow, carry);
break;
case OpCode::SBC:
result = sbc(op_1, op_2, carry);
result = sbc(op_1, op_2, carry, overflow, carry);
break;
case OpCode::RSC:
result = sbc(op_2, op_1, carry);
result = sbc(op_2, op_1, carry, overflow, carry);
break;
case OpCode::ORR:
result = op_1 | op_2;