using System; using System.Diagnostics; namespace BizHawk.Emulation.CPUs.ARM { partial class ARM { //A8.6.4 ADD uint ExecuteCore_ADD_immediate_thumb(Encoding encoding, uint n, uint d, bool setflags, uint imm32) { if (disassemble) if (disopt.showExplicitAccumulateRegisters || n != d) return DISNEW("ADD", ", , #", setflags, false, d, n, imm32); else return DISNEW("ADD", ", #", setflags, false, d, imm32); _AddWithCarry32(r[n], imm32, 0); r[d] = alu_result_32; if (setflags) { APSR.N = _.BIT31(alu_result_32); APSR.Z = _IsZeroBit(alu_result_32); APSR.C = alu_carry_out; APSR.V = alu_overflow; } return 1; } //A8.6.5 ADD (immediate, ARM) uint ExecuteCore_ADD_immediate_arm(Encoding encoding, bool setflags, uint n, uint d, uint imm32) { if (disassemble) if (disopt.showExplicitAccumulateRegisters || n != d) return DISNEW("ADD", ", , #", setflags, d, n, imm32); else return DISNEW("ADD", ", #", setflags, d, imm32); _AddWithCarry32(r[n], imm32, 0); if (d == 15) _ALUWritePC(alu_result_32); //"setflags is always FALSE here" else { r[d] = alu_result_32; if (setflags) { APSR.N = _.BIT31(alu_result_32); APSR.Z = _IsZeroBit(alu_result_32); APSR.C = alu_carry_out; APSR.V = alu_overflow; } } return 1; } //A8.6.6 ADD (register) uint ExecuteCore_ADD_register(Encoding encoding, uint m, uint d, uint n, bool setflags, SRType shift_t, int shift_n) { if (disassemble) return DISNEW("ADD", ", , <{, shift}>", setflags, d, n, m, shift_t, shift_n); uint shifted = _Shift(r[m], shift_t, shift_n, APSR.C); _AddWithCarry32(r[n], shifted, 0); if (d == 15) _ALUWritePC(alu_result_32); else { r[d] = alu_result_32; if (setflags) { APSR.N = _.BIT31(alu_result_32); APSR.Z = _IsZeroBit(alu_result_32); APSR.C = alu_carry_out; APSR.V = alu_overflow; } } return 0; } //A8.6.8 ADD (SP plus immediate) uint ExecuteCore_ADD_SP_plus_immedate(Encoding encoding, uint d, bool setflags, uint imm32) { if (disassemble) return DISNEW("ADD", ", , #", setflags, d, imm32); if (setflags && d == 15) throw new NotImplementedException("see SUBS PC, LR and related instruction on page B6-25"); //addendum about !s && d==PC is correctly handled already by writing pseudocode _AddWithCarry32(SP, imm32, 0); if (d == 15) { Debug.Assert(!setflags); _ALUWritePC(alu_result_32); //"can only occur for ARM encoding. setflags is always FALSE here" } else { r[d] = alu_result_32; if (setflags) { APSR.N = _.BIT31(alu_result_32); APSR.Z = _IsZeroBit(alu_result_32); APSR.C = alu_carry_out; APSR.V = alu_overflow; } } return 1; } //A8.6.10 ADR uint ExecuteCore_ADR(Encoding encoding, uint d, uint imm32, bool add) { uint result; if (add) result = _Align(PC, 4) + imm32; else result = _Align(PC, 4) - imm32; if (disassemble) if (nstyle) return DIS("ADD", "/r0/,pc,/imm8_1/ ; maybe MOV rX,pc", d, imm32); else return DIS("ADR", "/r0/, /label1/ ; maybe MOV rX,pc", d, result); if (d == 15) _ALUWritePC(result); else r[d] = result; return 1; } //A8.6.14 ASR (immediate) uint ExecuteCore_ASR_immediate(Encoding encoding, uint d, uint m, bool setflags, int shift_n) { if (disassemble) return DISNEW("ASR", "<{rd!~rm, }>, #", setflags, d, m, m, shift_n); uint result; Bit carry; _Shift_C(r[m], SRType.ASR, shift_n, APSR.C, out result, out carry); if (d == 15) _ALUWritePC(result); else { r[d] = result; if (setflags) { APSR.N = _.BIT31(result); APSR.Z = _IsZeroBit(result); APSR.C = carry; //APSR.V unchanged } } return 0; } //A8.6.16 B uint ExecuteCore_B(Encoding encoding, int imm32) { uint label = (uint)((int)PC + imm32); if (disassemble) return DISNEW("B", "