Update to v103r29 release.

byuu says:

Changelog:

  - processor/arm7tdmi: implementation all nine remaining ARM
    instructions
  - processor/arm7tdmi: implemented five more THUMB instructions
    (sixteen remain)
This commit is contained in:
Tim Allen 2017-08-08 21:51:41 +10:00
parent a72ff8b7fa
commit 559eeccc89
9 changed files with 578 additions and 50 deletions

View File

@ -12,7 +12,7 @@ using namespace nall;
namespace Emulator {
static const string Name = "higan";
static const string Version = "103.28";
static const string Version = "103.29";
static const string Author = "byuu";
static const string License = "GPLv3";
static const string Website = "http://byuu.org/";

View File

@ -301,7 +301,7 @@ auto ARM::disassembleInstructionARM(uint32 pc) -> string {
output.append(opcodes[opcode], conditions[condition]);
if(isMove(opcode)) output.append(save ? "s " : " ", registers[rd], ",");
if(isComp(opcode)) output.append(registers[rn], ",");
if(isComp(opcode)) output.append(" ", registers[rn], ",");
if(isMath(opcode)) output.append(save ? "s " : " ", registers[rd], ",", registers[rn], ",");
output.append(registers[rm]);
if(mode == 0) output.append(" lsl ");
@ -357,7 +357,7 @@ auto ARM::disassembleInstructionARM(uint32 pc) -> string {
if(pre == 1) output.append("]");
if(pre == 0 || writeback == 1) output.append("!");
if(rn == 15) output.append(" =0x", hex(read((byte ? Byte : Word) | Nonsequential, pc + 8 + (up ? +immediate : -immediate)), 8L));
if(rn == 15) output.append(" =0x", hex(read((byte ? Byte : Word) | Nonsequential, pc + 8 + (up ? +immediate : -immediate)), byte ? 2L : 4L));
return output;
}

View File

@ -496,7 +496,6 @@ auto ARM::arm_op_move_register_offset() {
uint32 rd = r(d);
uint32 rs = immediate;
uint32 rm = r(m);
bool c = cpsr().c;
if(mode == 0) rm = lsl(rm, rs);
if(mode == 1) rm = lsr(rm, rs ? rs : (uint32)32);

View File

@ -31,7 +31,6 @@ struct ARM7TDMI {
struct GPR;
struct PSR;
inline auto r(uint4) -> GPR&;
inline auto u(uint4) -> GPR&;
inline auto cpsr() -> PSR&;
inline auto spsr() -> PSR&;
inline auto privileged() const -> bool;
@ -67,22 +66,33 @@ struct ARM7TDMI {
auto armALU(uint4 mode, uint4 target, uint4 source, uint32 data) -> void;
auto armMoveToStatus(uint4 field, uint1 source, uint32 data) -> void;
auto armInstructionBranch(int24, uint1) -> void;
auto armInstructionBranchExchangeRegister(uint4) -> void;
auto armInstructionDataImmediate(uint8, uint4, uint4, uint4, uint1, uint4) -> void;
auto armInstructionDataImmediateShift(uint4, uint2, uint5, uint4, uint4, uint1, uint4) -> void;
auto armInstructionDataRegisterShift(uint4, uint2, uint4, uint4, uint4, uint1, uint4) -> void;
auto armInstructionLoadImmediate(uint8, uint1, uint4, uint4, uint1, uint1, uint1) -> void;
auto armInstructionLoadRegister(uint4, uint1, uint4, uint4, uint1, uint1, uint1) -> void;
auto armInstructionMemorySwap(uint4, uint4, uint4, uint1) -> void;
auto armInstructionMoveHalfImmediate(uint8, uint4, uint4, uint1, uint1, uint1, uint1) -> void;
auto armInstructionMoveHalfRegister(uint4, uint4, uint4, uint1, uint1, uint1, uint1) -> void;
auto armInstructionMoveImmediateOffset(uint12, uint4, uint4, uint1, uint1, uint1, uint1, uint1) -> void;
auto armInstructionMoveMultiple(uint16, uint4, uint1, uint1, uint1, uint1, uint1) -> void;
auto armInstructionMoveRegisterOffset(uint4, uint2, uint5, uint4, uint4, uint1, uint1, uint1, uint1, uint1) -> void;
auto armInstructionMoveToRegisterFromStatus(uint4, uint1) -> void;
auto armInstructionMoveToStatusFromImmediate(uint8, uint4, uint4, uint1) -> void;
auto armInstructionMoveToStatusFromRegister(uint4, uint4, uint1) -> void;
auto armInstructionMultiply(uint4, uint4, uint4, uint4, uint1, uint1) -> void;
auto armInstructionMultiplyLong(uint4, uint4, uint4, uint4, uint1, uint1, uint1) -> void;
auto armInstructionSoftwareInterrupt(uint24 immediate) -> void;
//instructions-thumb.cpp
auto thumbALU(uint4 mode, uint4 target, uint4 source) -> void;
auto thumbInstructionALU(uint3, uint3, uint4) -> void;
auto thumbInstructionAdjustImmediate(uint3, uint3, uint3, uint1) -> void;
auto thumbInstructionAdjustRegister(uint3, uint3, uint3, uint1) -> void;
auto thumbInstructionBranchExchange(uint4) -> void;
auto thumbInstructionImmediate(uint8, uint3, uint2) -> void;
auto thumbInstructionShiftImmediate(uint3, uint3, uint5, uint2) -> void;
//serialization.cpp
auto serialize(serializer&) -> void;
@ -210,19 +220,32 @@ struct ARM7TDMI {
function<string ()> thumbDisassemble[65536];
//disassembler.cpp
auto armDisassembleBranch(int24, uint1) -> string;
auto armDisassembleBranchExchangeRegister(uint4) -> string;
auto armDisassembleDataImmediate(uint8, uint4, uint4, uint4, uint1, uint4) -> string;
auto armDisassembleDataImmediateShift(uint4, uint2, uint5, uint4, uint4, uint1, uint4) -> string;
auto armDisassembleDataRegisterShift(uint4, uint2, uint4, uint4, uint4, uint1, uint4) -> string;
auto armDisassembleLoadImmediate(uint8, uint1, uint4, uint4, uint1, uint1, uint1) -> string;
auto armDisassembleLoadRegister(uint4, uint1, uint4, uint4, uint1, uint1, uint1) -> string;
auto armDisassembleMemorySwap(uint4, uint4, uint4, uint1) -> string;
auto armDisassembleMoveHalfImmediate(uint8, uint4, uint4, uint1, uint1, uint1, uint1) -> string;
auto armDisassembleMoveHalfRegister(uint4, uint4, uint4, uint1, uint1, uint1, uint1) -> string;
auto armDisassembleMoveImmediateOffset(uint12, uint4, uint4, uint1, uint1, uint1, uint1, uint1) -> string;
auto armDisassembleMoveMultiple(uint16, uint4, uint1, uint1, uint1, uint1, uint1) -> string;
auto armDisassembleMoveRegisterOffset(uint4, uint2, uint5, uint4, uint4, uint1, uint1, uint1, uint1, uint1) -> string;
auto armDisassembleMoveToRegisterFromStatus(uint4, uint1) -> string;
auto armDisassembleMoveToStatusFromImmediate(uint8, uint4, uint4, uint1) -> string;
auto armDisassembleMoveToStatusFromRegister(uint4, uint4, uint1) -> string;
auto armDisassembleMultiply(uint4, uint4, uint4, uint4, uint1, uint1) -> string;
auto armDisassembleMultiplyLong(uint4, uint4, uint4, uint4, uint1, uint1, uint1) -> string;
auto armDisassembleSoftwareInterrupt(uint24) -> string;
auto thumbDisassembleALU(uint3, uint3, uint4) -> string;
auto thumbDisassembleAdjustImmediate(uint3, uint3, uint3, uint1) -> string;
auto thumbDisassembleAdjustRegister(uint3, uint3, uint3, uint1) -> string;
auto thumbDisassembleBranchExchange(uint4) -> string;
auto thumbDisassembleImmediate(uint8, uint3, uint2) -> string;
auto thumbDisassembleShiftImmediate(uint3, uint3, uint5, uint2) -> string;
};
}

View File

@ -1,22 +1,81 @@
static uint32 _pc;
static string _c;
static string _r[16] = {
static const string _r[] = {
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
"r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc"
};
#define _s save ? "s" : ""
#define isMove(mode) (mode == 13 || mode == 15)
#define isComp(mode) (mode >= 8 && mode <= 11)
#define isMath(mode) (mode <= 7 || mode == 12 || mode == 14)
auto ARM7TDMI::disassemble(uint32 pc) -> string {
return "";
}
//
auto ARM7TDMI::armDisassembleBranch
(int24 displacement, uint1 link) -> string {
return {"b", link ? "l" : "", _c, " 0x", hex(_pc + 8 + displacement * 4, 8L)};
}
auto ARM7TDMI::armDisassembleBranchExchangeRegister
(uint4 m) -> string {
return {"bx", _c, " ", _r[m]};
}
auto ARM7TDMI::armDisassembleDataImmediate
(uint8 immediate, uint4 shift, uint4 d, uint4 n, uint1 save, uint4 mode) -> string {
static const string opcode[] = {
"and", "eor", "sub", "rsb", "add", "adc", "sbc", "rsc",
"tst", "teq", "cmp", "cmn", "orr", "mov", "bic", "mvn",
};
uint32 data = immediate >> (shift << 1) | immediate << 32 - (shift << 1);
return {opcode[mode], _c,
isMove(mode) ? string{_s, " ", _r[d]} : string{},
isComp(mode) ? string{" ", _r[n]} : string{},
isMath(mode) ? string{_s, " ", _r[d], ",", _r[n]} : string{},
",#0x", hex(data, 8L)};
}
auto ARM7TDMI::armDisassembleDataImmediateShift
(uint4 m, uint2 type, uint5 shift, uint4 d, uint4 n, uint1 save, uint4 mode) -> string {
static const string opcode[] = {
"and", "eor", "sub", "rsb", "add", "adc", "sbc", "rsc",
"tst", "teq", "cmp", "cmn", "orr", "mov", "bic", "mvn",
};
return {opcode[mode], _c,
isMove(mode) ? string{_s, " ", _r[d]} : string{},
isComp(mode) ? string{" ", _r[n]} : string{},
isMath(mode) ? string{_s, " ", _r[d], ",", _r[n]} : string{},
",", _r[m],
type == 0 && shift ? string{" lsl #", shift} : string{},
type == 1 ? string{" lsr #", shift ? (uint)shift : 32} : string{},
type == 2 ? string{" asr #", shift ? (uint)shift : 32} : string{},
type == 3 && shift ? string{" ror #", shift} : string{},
type == 3 && !shift ? " rrx" : ""};
}
auto ARM7TDMI::armDisassembleDataRegisterShift
(uint4 m, uint2 type, uint4 s, uint4 d, uint4 n, uint1 save, uint4 mode) -> string {
static const string opcode[] = {
"and", "eor", "sub", "rsb", "add", "adc", "sbc", "rsc",
"tst", "teq", "cmp", "cmn", "orr", "mov", "bic", "mvn",
};
return {opcode[mode], _c,
isMove(mode) ? string{_s, " ", _r[d]} : string{},
isComp(mode) ? string{" ", _r[n]} : string{},
isMath(mode) ? string{_s, " ", _r[d], ",", _r[n]} : string{},
",", _r[m], " ",
type == 0 ? "lsl" : "",
type == 1 ? "lsr" : "",
type == 2 ? "asr" : "",
type == 3 ? "ror" : "",
" ", _r[s]};
}
auto ARM7TDMI::armDisassembleLoadImmediate
(uint8 immediate, uint1 half, uint4 d, uint4 n, uint1 writeback, uint1 up, uint1 pre) -> string {
string data;
@ -69,6 +128,48 @@ auto ARM7TDMI::armDisassembleMoveHalfRegister
pre == 0 || writeback ? "!" : ""};
}
auto ARM7TDMI::armDisassembleMoveImmediateOffset
(uint12 immediate, uint4 d, uint4 n, uint1 mode, uint1 writeback, uint1 byte, uint1 up, uint1 pre) -> string {
string data;
if(n == 15) data = {" =0x", hex(read((byte ? Byte : Word) | Nonsequential,
_pc + 8 + (up ? +immediate : -immediate)), byte ? 2L : 4L)};
return {mode ? "ldr" : "str", _c, byte ? "b" : "", " ", _r[d], ",[", _r[n],
pre == 0 ? "]" : "",
immediate ? string{",", up ? "+" : "-", "0x", hex(immediate, 3L)} : string{},
pre == 1 ? "]" : "",
pre == 0 || writeback ? "!" : "", data};
}
auto ARM7TDMI::armDisassembleMoveMultiple
(uint16 list, uint4 n, uint1 mode, uint1 writeback, uint1 type, uint1 up, uint1 pre) -> string {
string registers;
for(auto index : range(16)) {
if(list.bit(index)) registers.append(_r[index], ",");
}
registers.trimRight(",", 1L);
return {mode ? "ldm" : "stm",
up == 0 && pre == 0 ? "da" : "",
up == 0 && pre == 1 ? "db" : "",
up == 1 && pre == 0 ? "ia" : "",
up == 1 && pre == 1 ? "ib" : "",
" ", _r[n], writeback ? "!" : "",
",{", registers, "}", type ? "^" : ""};
}
auto ARM7TDMI::armDisassembleMoveRegisterOffset
(uint4 m, uint2 type, uint5 shift, uint4 d, uint4 n, uint1 mode, uint1 writeback, uint1 byte, uint1 up, uint1 pre) -> string {
return {mode ? "ldr" : "str", _c, byte ? "b" : "", " ", _r[d], ",[", _r[n],
pre == 0 ? "]" : "",
",", up ? "+" : "-", _r[m],
type == 0 && shift ? string{" lsl #", shift} : string{},
type == 1 ? string{" lsr #", shift ? (uint)shift : 32} : string{},
type == 2 ? string{" asr #", shift ? (uint)shift : 32} : string{},
type == 3 && shift ? string{" ror #", shift} : string{},
type == 3 && !shift ? " rrx" : "",
pre == 1 ? "]" : "",
pre == 0 || writeback ? "!" : ""};
}
auto ARM7TDMI::armDisassembleMoveToRegisterFromStatus
(uint4 d, uint1 mode) -> string {
return {"mrs", _c, " ", _r[d], ",", mode ? "spsr" : "cpsr"};
@ -110,9 +211,77 @@ auto ARM7TDMI::armDisassembleMultiplyLong
_r[l], ",", _r[h], ",", _r[m], ",", _r[s]};
}
auto ARM7TDMI::armDisassembleSoftwareInterrupt
(uint24 immediate) -> string {
return {"swi #0x", hex(immediate, 6L)};
}
//
auto ARM7TDMI::thumbDisassembleALU
(uint3 d, uint3 m, uint4 mode) -> string {
static const string opcode[] = {
"and", "eor", "lsl", "lsr", "asr", "adc", "sbc", "ror",
"tst", "neg", "cmp", "cmn", "orr", "mul", "bic", "mvn",
};
return {opcode[mode], " ", _r[d], ",", _r[m]};
}
auto ARM7TDMI::thumbDisassembleAdjustImmediate
(uint3 d, uint3 n, uint3 immediate, uint1 mode) -> string {
return {!mode ? "add" : "sub", " ", _r[d], ",", _r[n], ",#", immediate};
}
auto ARM7TDMI::thumbDisassembleAdjustRegister
(uint3 d, uint3 n, uint3 m, uint1 mode) -> string {
return {!mode ? "add" : "sub", " ", _r[d], ",", _r[n], ",", _r[m]};
}
auto ARM7TDMI::thumbDisassembleBranchExchange
(uint4 m) -> string {
return {"bx ", _r[m]};
}
auto ARM7TDMI::thumbDisassembleImmediate
(uint8 immediate, uint3 d, uint2 mode) -> string {
static const string opcode[] = {"mov", "cmp", "add", "sub"};
return {opcode[mode], " ", _r[d], ",#0x", hex(immediate, 2L)};
}
auto ARM7TDMI::thumbDisassembleShiftImmediate
(uint3 d, uint3 m, uint5 immediate, uint2 mode) -> string {
static const string opcode[] = {"lsl", "lsr", "asr"};
return {opcode[mode], " ", _r[d], ",", _r[m], ",#", immediate};
}

View File

@ -66,6 +66,18 @@ auto ARM7TDMI::armInitialize() -> void {
#define pattern(s) \
std::integral_constant<uint32_t, bit::test(s)>::value
#define arguments \
opcode.bits( 0,23), /* displacement */ \
opcode.bit (24) /* link */
for(uint4 displacementLo : range(16))
for(uint4 displacementHi : range(16))
for(uint1 link : range(2)) {
auto opcode = pattern(".... 101? ???? ???? ???? ???? ???? ????")
| displacementLo << 4 | displacementHi << 20 | link << 24;
bind(opcode, Branch);
}
#undef arguments
#define arguments \
opcode.bits( 0, 3) /* m */
{
@ -74,6 +86,57 @@ auto ARM7TDMI::armInitialize() -> void {
}
#undef arguments
#define arguments \
opcode.bits( 0, 7), /* immediate */ \
opcode.bits( 8,11), /* shift */ \
opcode.bits(12,15), /* d */ \
opcode.bits(16,19), /* n */ \
opcode.bit (20), /* save */ \
opcode.bits(21,24) /* mode */
for(uint4 shiftHi : range(16))
for(uint1 save : range(2))
for(uint4 mode : range(16)) {
if(mode >= 8 && mode <= 11 && !save) continue; //TST, TEQ, CMP, CMN
auto opcode = pattern(".... 001? ???? ???? ???? ???? ???? ????") | shiftHi << 4 | save << 20 | mode << 21;
bind(opcode, DataImmediate);
}
#undef arguments
#define arguments \
opcode.bits( 0, 3), /* m */ \
opcode.bits( 5, 6), /* type */ \
opcode.bits( 7,11), /* shift */ \
opcode.bits(12,15), /* d */ \
opcode.bits(16,19), /* n */ \
opcode.bit (20), /* save */ \
opcode.bits(21,24) /* mode */
for(uint2 type : range(4))
for(uint1 shiftLo : range(2))
for(uint1 save : range(2))
for(uint4 mode : range(16)) {
if(mode >= 8 && mode <= 11 && !save) continue; //TST, TEQ, CMP, CMN
auto opcode = pattern(".... 000? ???? ???? ???? ???? ???0 ????") | type << 5 | shiftLo << 7 | save << 20 | mode << 21;
bind(opcode, DataImmediateShift);
}
#undef arguments
#define arguments \
opcode.bits( 0, 3), /* m */ \
opcode.bits( 5, 6), /* type */ \
opcode.bits( 8,11), /* s */ \
opcode.bits(12,15), /* d */ \
opcode.bits(16,19), /* n */ \
opcode.bit (20), /* save */ \
opcode.bits(21,24) /* mode */
for(uint2 type : range(4))
for(uint1 save : range(2))
for(uint4 mode : range(16)) {
if(mode >= 8 && mode <= 11 && !save) continue; //TST, TEQ, CMP, CMN
auto opcode = pattern(".... 000? ???? ???? ???? ???? 0??1 ????") | type << 5 | save << 20 | mode << 21;
bind(opcode, DataRegisterShift);
}
#undef arguments
#define arguments \
opcode.bits( 0, 3) << 0 | opcode.bits( 8,11) << 4, /* immediate */ \
opcode.bit ( 5), /* half */ \
@ -153,6 +216,71 @@ auto ARM7TDMI::armInitialize() -> void {
}
#undef arguments
#define arguments \
opcode.bits( 0,11), /* immediate */ \
opcode.bits(12,15), /* d */ \
opcode.bits(16,19), /* n */ \
opcode.bit (20), /* mode */ \
opcode.bit (21), /* writeback */ \
opcode.bit (22), /* byte */ \
opcode.bit (23), /* up */ \
opcode.bit (24) /* pre */
for(uint4 immediatePart : range(16))
for(uint1 mode : range(2))
for(uint1 writeback : range(2))
for(uint1 byte : range(2))
for(uint1 up : range(2))
for(uint1 pre : range(2)) {
auto opcode = pattern(".... 010? ???? ???? ???? ???? ???? ????")
| immediatePart << 4 | mode << 20 | writeback << 21 | byte << 22 | up << 23 | pre << 24;
bind(opcode, MoveImmediateOffset);
}
#undef arguments
#define arguments \
opcode.bits( 0,15), /* list */ \
opcode.bits(16,19), /* n */ \
opcode.bit (20), /* mode */ \
opcode.bit (21), /* writeback */ \
opcode.bit (22), /* type */ \
opcode.bit (23), /* up */ \
opcode.bit (24) /* pre */
for(uint4 listPart : range(16))
for(uint1 mode : range(2))
for(uint1 writeback : range(2))
for(uint1 type : range(2))
for(uint1 up : range(2))
for(uint1 pre : range(2)) {
auto opcode = pattern(".... 100? ???? ???? ???? ???? ???? ????")
| listPart << 4 | mode << 20 | writeback << 21 | type << 22 | up << 23 | pre << 24;
bind(opcode, MoveMultiple);
}
#undef arguments
#define arguments \
opcode.bits( 0, 3), /* m */ \
opcode.bits( 5, 6), /* type */ \
opcode.bits( 7,11), /* shift */ \
opcode.bits(12,15), /* d */ \
opcode.bits(16,19), /* n */ \
opcode.bit (20), /* mode */ \
opcode.bit (21), /* writeback */ \
opcode.bit (22), /* byte */ \
opcode.bit (23), /* up */ \
opcode.bit (24) /* pre */
for(uint2 type : range(4))
for(uint1 shiftLo : range(2))
for(uint1 mode : range(2))
for(uint1 writeback : range(2))
for(uint1 byte : range(2))
for(uint1 up : range(2))
for(uint1 pre : range(2)) {
auto opcode = pattern(".... 011? ???? ???? ???? ???? ???0 ????")
| type << 5 | shiftLo << 7 | mode << 20 | writeback << 21 | byte << 22 | up << 23 | pre << 24;
bind(opcode, MoveRegisterOffset);
}
#undef arguments
#define arguments \
opcode.bits( 0, 3), /* d */ \
opcode.bit (22) /* mode */
@ -214,6 +342,15 @@ auto ARM7TDMI::armInitialize() -> void {
}
#undef arguments
#define arguments \
opcode.bits( 0,23) /* immediate */
for(uint4 immediateLo : range(16))
for(uint4 immediateHi : range(16)) {
auto opcode = pattern(".... 1111 ???? ???? ???? ???? ???? ????") | immediateLo << 4 | immediateHi << 20;
bind(opcode, SoftwareInterrupt);
}
#undef arguments
#undef bind
#undef pattern
}
@ -228,6 +365,21 @@ auto ARM7TDMI::thumbInitialize() -> void {
#define pattern(s) \
std::integral_constant<uint16_t, bit::test(s)>::value
for(uint3 d : range(8))
for(uint3 m : range(8))
for(uint4 mode : range(16)) {
auto opcode = pattern("0100 00?? ???? ????") | d << 0 | m << 3 | mode << 6;
bind(opcode, ALU, d, m, mode);
}
for(uint3 d : range(8))
for(uint3 n : range(8))
for(uint3 immediate : range(8))
for(uint1 mode : range(2)) {
auto opcode = pattern("0001 11?? ???? ????") | d << 0 | n << 3 | immediate << 6 | mode << 9;
bind(opcode, AdjustImmediate, d, n, immediate, mode);
}
for(uint3 d : range(8))
for(uint3 n : range(8))
for(uint3 m : range(8))
@ -236,6 +388,49 @@ auto ARM7TDMI::thumbInitialize() -> void {
bind(opcode, AdjustRegister, d, n, m, mode);
}
for(uint3 _ : range(8))
for(uint4 m : range(16)) {
auto opcode = pattern("0100 0111 0??? ?---") | _ << 0 | m << 3;
bind(opcode, BranchExchange, m);
}
for(uint8 immediate : range(256))
for(uint3 d : range(8))
for(uint2 mode : range(4)) {
auto opcode = pattern("001? ???? ???? ????") | immediate << 0 | d << 8 | mode << 11;
bind(opcode, Immediate, immediate, d, mode);
}
for(uint3 d : range(8))
for(uint3 m : range(8))
for(uint5 immediate : range(32))
for(uint2 mode : range(4)) {
if(mode == 3) continue;
auto opcode = pattern("000? ???? ???? ????") | d << 0 | m << 3 | immediate << 6 | mode << 11;
bind(opcode, ShiftImmediate, d, m, immediate, mode);
}
#undef bind
#undef pattern
}

View File

@ -46,6 +46,12 @@ auto ARM7TDMI::armMoveToStatus(uint4 field, uint1 mode, uint32 data) -> void {
//
auto ARM7TDMI::armInstructionBranch
(int24 displacement, uint1 link) -> void {
if(link) r(14) = r(15) - 4;
r(15) = r(15) + displacement * 4;
}
auto ARM7TDMI::armInstructionBranchExchangeRegister
(uint4 m) -> void {
uint32 address = r(m);
@ -53,6 +59,45 @@ auto ARM7TDMI::armInstructionBranchExchangeRegister
r(15) = address;
}
auto ARM7TDMI::armInstructionDataImmediate
(uint8 immediate, uint4 shift, uint4 d, uint4 n, uint1 save, uint4 mode) -> void {
uint32 data = immediate;
carry = cpsr().c;
if(shift) data = ROR(data, shift << 1);
armALU(mode, d, n, data);
}
auto ARM7TDMI::armInstructionDataImmediateShift
(uint4 m, uint2 type, uint5 shift, uint4 d, uint4 n, uint1 save, uint4 mode) -> void {
uint32 rm = r(m);
carry = cpsr().c;
switch(type) {
case 0: rm = LSL(rm, shift); break;
case 1: rm = LSR(rm, shift ? (uint)shift : 32); break;
case 2: rm = ASR(rm, shift ? (uint)shift : 32); break;
case 3: rm = shift ? ROR(rm, shift) : RRX(rm); break;
}
armALU(mode, d, n, rm);
}
auto ARM7TDMI::armInstructionDataRegisterShift
(uint4 m, uint2 type, uint4 s, uint4 d, uint4 n, uint1 save, uint4 mode) -> void {
uint8 rs = r(s) + (s == 15 ? 4 : 0);
uint32 rm = r(m) + (m == 15 ? 4 : 0);
carry = cpsr().c;
switch(type) {
case 0: rm = LSL(rm, rs < 33 ? rs : (uint8)33); break;
case 1: rm = LSR(rm, rs < 33 ? rs : (uint8)33); break;
case 2: rm = ASR(rm, rs < 32 ? rs : (uint8)32); break;
case 3: if(rs) rm = ROR(rm, rs & 31 ? rs & 31 : 32); break;
}
armALU(mode, d, n, rm);
}
auto ARM7TDMI::armInstructionLoadImmediate
(uint8 immediate, uint1 half, uint4 d, uint4 n, uint1 writeback, uint1 up, uint1 pre) -> void {
uint32 rn = r(n);
@ -116,6 +161,87 @@ auto ARM7TDMI::armInstructionMoveHalfRegister
if(mode == 1) r(d) = rd;
}
auto ARM7TDMI::armInstructionMoveImmediateOffset
(uint12 immediate, uint4 d, uint4 n, uint1 mode, uint1 writeback, uint1 byte, uint1 up, uint1 pre) -> void {
uint32 rn = r(n);
uint32 rd = r(d);
if(pre == 1) rn = up ? rn + immediate : rn - immediate;
if(mode == 1) rd = load((byte ? Byte : Word) | Nonsequential, rn);
if(mode == 0) store((byte ? Byte : Word) | Nonsequential, rn, rd);
if(pre == 0) rn = up ? rn + immediate : rn - immediate;
if(pre == 0 || writeback) r(n) = rn;
if(mode == 1) r(d) = rd;
}
auto ARM7TDMI::armInstructionMoveMultiple
(uint16 list, uint4 n, uint1 mode, uint1 writeback, uint1 type, uint1 up, uint1 pre) -> void {
uint32 rn = r(n);
if(pre == 0 && up == 1) rn = rn + 0; //IA
if(pre == 1 && up == 1) rn = rn + 4; //IB
if(pre == 1 && up == 0) rn = rn - bit::count(list) * 4 + 0; //DB
if(pre == 0 && up == 0) rn = rn - bit::count(list) * 4 + 4; //DA
if(writeback && mode == 1) {
if(up == 1) r(n) = r(n) + bit::count(list) * 4; //IA,IB
if(up == 0) r(n) = r(n) - bit::count(list) * 4; //DA,DB
}
auto cpsrMode = cpsr().m;
bool usr = false;
if(type && mode == 1 && !list.bit(15)) usr = true;
if(type && mode == 0) usr = true;
if(usr) cpsr().m = PSR::USR;
uint sequential = Nonsequential;
for(uint m : range(16)) {
if(!list.bit(m)) continue;
if(mode == 1) r(m) = read(Word | sequential, rn);
if(mode == 0) write(Word | sequential, rn, r(m));
rn += 4;
sequential = Sequential;
}
if(usr) cpsr().m = cpsrMode;
if(mode) {
idle();
if(type && list.bit(15) && cpsr().m != PSR::USR && cpsr().m != PSR::SYS) {
cpsr() = spsr();
}
} else {
pipeline.nonsequential = true;
}
if(writeback && mode == 0) {
if(up == 1) r(n) = r(n) + bit::count(list) * 4; //IA,IB
if(up == 0) r(n) = r(n) - bit::count(list) * 4; //DA,DB
}
}
auto ARM7TDMI::armInstructionMoveRegisterOffset
(uint4 m, uint2 type, uint5 shift, uint4 d, uint4 n, uint1 mode, uint1 writeback, uint1 byte, uint1 up, uint1 pre) -> void {
uint32 rm = r(m);
uint32 rd = r(d);
uint32 rn = r(n);
switch(type) {
case 0: rm = LSL(rm, shift); break;
case 1: rm = LSR(rm, shift ? (uint)shift : 32); break;
case 2: rm = ASR(rm, shift ? (uint)shift : 32); break;
case 3: rm = shift ? ROR(rm, shift) : RRX(rm); break;
}
if(pre == 1) rn = up ? rn + rm : rn - rm;
if(mode == 1) rd = load((byte ? Byte : Word) | Nonsequential, rn);
if(mode == 0) store((byte ? Byte : Word) | Nonsequential, rn, rd);
if(pre == 0) rn = up ? rn + rm : rn - rm;
if(pre == 0 || writeback) r(n) = rn;
if(mode == 1) r(d) = rd;
}
auto ARM7TDMI::armInstructionMoveToRegisterFromStatus
(uint4 d, uint1 mode) -> void {
if(mode && (cpsr().m == PSR::USR || cpsr().m == PSR::SYS)) return;
@ -172,3 +298,8 @@ auto ARM7TDMI::armInstructionMultiplyLong
cpsr().n = rd.bit(63);
}
}
auto ARM7TDMI::armInstructionSoftwareInterrupt
(uint24 immediate) -> void {
interrupt(PSR::SVC, 0x08);
}

View File

@ -1,30 +1,63 @@
auto ARM7TDMI::thumbALU(uint4 mode, uint4 target, uint4 source) -> void {
auto ARM7TDMI::thumbInstructionALU
(uint3 d, uint3 m, uint4 mode) -> void {
switch(mode) {
case 0: r(target) = BIT(r(target) & r(source)); break; //AND
case 1: r(target) = BIT(r(target) ^ r(source)); break; //EOR
case 2: r(target) = BIT(LSL(r(target), r(source))); break; //LSL
case 3: r(target) = BIT(LSR(r(target), r(source))); break; //LSR
case 4: r(target) = BIT(ASR(r(target), r(source))); break; //ASR
case 5: r(target) = ADD(r(target), r(source), cpsr().c); break; //ADC
case 6: r(target) = SUB(r(target), r(source), cpsr().c); break; //SBC
case 7: r(target) = BIT(ROR(r(target), r(source))); break; //ROR
case 8: BIT(r(target) & r(source)); break; //TST
case 9: r(target) = SUB(0, r(source), 1); break; //NEG
case 10: SUB(r(target), r(source), 1); break; //CMP
case 11: ADD(r(target), r(source), 0); break; //CMN
case 12: r(target) = BIT(r(target) | r(source)); break; //ORR
case 13: r(target) = MUL(0, r(source), r(target)); break; //MUL
case 14: r(target) = BIT(r(target) & ~r(source)); break; //BIC
case 15: r(target) = BIT(~r(source)); break; //MVN
case 0: r(d) = BIT(r(d) & r(m)); break; //AND
case 1: r(d) = BIT(r(d) ^ r(m)); break; //EOR
case 2: r(d) = BIT(LSL(r(d), r(m))); break; //LSL
case 3: r(d) = BIT(LSR(r(d), r(m))); break; //LSR
case 4: r(d) = BIT(ASR(r(d), r(m))); break; //ASR
case 5: r(d) = ADD(r(d), r(m), cpsr().c); break; //ADC
case 6: r(d) = SUB(r(d), r(m), cpsr().c); break; //SBC
case 7: r(d) = BIT(ROR(r(d), r(m))); break; //ROR
case 8: BIT(r(d) & r(m)); break; //TST
case 9: r(d) = SUB(0, r(m), 1); break; //NEG
case 10: SUB(r(d), r(m), 1); break; //CMP
case 11: ADD(r(d), r(m), 0); break; //CMN
case 12: r(d) = BIT(r(d) | r(m)); break; //ORR
case 13: r(d) = MUL(0, r(m), r(d)); break; //MUL
case 14: r(d) = BIT(r(d) & ~r(m)); break; //BIC
case 15: r(d) = BIT(~r(m)); break; //MVN
}
}
//
auto ARM7TDMI::thumbInstructionAdjustImmediate
(uint3 d, uint3 n, uint3 immediate, uint1 mode) -> void {
switch(mode) {
case 0: r(d) = ADD(r(n), immediate, 0); break; //ADD
case 1: r(d) = SUB(r(n), immediate, 1); break; //SUB
}
}
auto ARM7TDMI::thumbInstructionAdjustRegister
(uint3 d, uint3 n, uint3 m, uint1 mode) -> void {
switch(mode) {
case 0: r(d) = ADD(r(n), r(m), 0); break;
case 1: r(d) = SUB(r(n), r(m), 1); break;
case 0: r(d) = ADD(r(n), r(m), 0); break; //ADD
case 1: r(d) = SUB(r(n), r(m), 1); break; //SUB
}
}
auto ARM7TDMI::thumbInstructionBranchExchange
(uint4 m) -> void {
uint32 address = r(m);
cpsr().t = address.bit(0);
r(15) = address;
}
auto ARM7TDMI::thumbInstructionImmediate
(uint8 immediate, uint3 d, uint2 mode) -> void {
switch(mode) {
case 0: r(d) = BIT(immediate); break; //MOV
case 1: SUB(r(d), immediate, 1); break; //CMP
case 2: r(d) = ADD(r(d), immediate, 0); break; //ADD
case 3: r(d) = SUB(r(d), immediate, 1); break; //SUB
}
}
auto ARM7TDMI::thumbInstructionShiftImmediate
(uint3 d, uint3 m, uint5 immediate, uint2 mode) -> void {
switch(mode) {
case 0: r(d) = BIT(LSL(r(m), immediate)); break; //LSL
case 1: r(d) = BIT(LSR(r(m), immediate ? (uint)immediate : 32)); break; //LSR
case 2: r(d) = BIT(ASR(r(m), immediate ? (uint)immediate : 32)); break; //ASR
}
}

View File

@ -34,28 +34,6 @@ auto ARM7TDMI::r(uint4 index) -> GPR& {
unreachable;
}
auto ARM7TDMI::u(uint4 index) -> GPR& {
switch(index) {
case 0: return processor.r0;
case 1: return processor.r1;
case 2: return processor.r2;
case 3: return processor.r3;
case 4: return processor.r4;
case 5: return processor.r5;
case 6: return processor.r6;
case 7: return processor.r7;
case 8: return processor.r8;
case 9: return processor.r9;
case 10: return processor.r10;
case 11: return processor.r11;
case 12: return processor.r12;
case 13: return processor.r13;
case 14: return processor.r14;
case 15: return processor.r15;
}
unreachable;
}
auto ARM7TDMI::cpsr() -> PSR& {
return processor.cpsr;
}