mirror of https://github.com/bsnes-emu/bsnes.git
Update to v086r10 release.
byuu says: More ARM work. ARM core now begins to act upon initial 0xf1 command, but hangs.
This commit is contained in:
parent
3ed42af8a1
commit
11d6f09359
|
@ -1,7 +1,7 @@
|
|||
#ifndef BASE_HPP
|
||||
#define BASE_HPP
|
||||
|
||||
const char Version[] = "086.09";
|
||||
const char Version[] = "086.10";
|
||||
|
||||
#include <nall/platform.hpp>
|
||||
#include <nall/algorithm.hpp>
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#define ARMDSP_CPP
|
||||
namespace SNES {
|
||||
|
||||
static bool trace = 0;
|
||||
|
||||
#include "opcodes.cpp"
|
||||
#include "memory.cpp"
|
||||
#include "disassembler.cpp"
|
||||
|
@ -42,12 +44,17 @@ void ArmDSP::enter() {
|
|||
pipeline.prefetch.opcode = bus_read<4>(r[15]);
|
||||
r[15].step();
|
||||
|
||||
//print("\n", disassemble_registers(), "\n");
|
||||
//print(disassemble_opcode(pipeline.instruction.address), "\n");
|
||||
//if(pipeline.instruction.address == 0x00000208) trace = 1;
|
||||
if(trace) {
|
||||
print("\n", disassemble_registers(), "\n");
|
||||
print(disassemble_opcode(pipeline.instruction.address), "\n");
|
||||
usleep(200000);
|
||||
}
|
||||
|
||||
instruction = pipeline.instruction.opcode;
|
||||
if((instruction & 0x0fb000f0) == 0x01200000) { op_move_status_register_to_register(); continue; }
|
||||
if((instruction & 0x0e000010) == 0x00000000) { op_data_immediate_shift(); continue; }
|
||||
if((instruction & 0x0e000090) == 0x00000010) { op_data_register_shift(); continue; }
|
||||
if((instruction & 0x0e000000) == 0x02000000) { op_data_immediate(); continue; }
|
||||
if((instruction & 0x0e000000) == 0x04000000) { op_move_immediate_offset(); continue; }
|
||||
if((instruction & 0x0e000000) == 0x08000000) { op_move_multiple(); continue; }
|
||||
|
@ -58,21 +65,27 @@ void ArmDSP::enter() {
|
|||
}
|
||||
|
||||
uint8 ArmDSP::mmio_read(unsigned addr) {
|
||||
addr &= 0xffff;
|
||||
if(addr == 0x3800) return armport[0];
|
||||
if(addr == 0x3802) return armport[1];
|
||||
if(addr == 0x3804) return armport[3];
|
||||
uint8 data = 0x00;
|
||||
switch(addr & 0xffff) {
|
||||
case 0x3800: data = w40000000; break;
|
||||
case 0x3802: data = r3802; break;
|
||||
case 0x3804: data = r3804; break;
|
||||
}
|
||||
|
||||
print("* r", hex<4>(addr), "\n");
|
||||
return 0x00;
|
||||
print("* r", hex<6>(addr), " = ", hex<2>(data), "\n");
|
||||
usleep(200000);
|
||||
return data;
|
||||
}
|
||||
|
||||
void ArmDSP::mmio_write(unsigned addr, uint8 data) {
|
||||
addr &= 0xffff;
|
||||
if(addr == 0x3802) cpuport[1] = data;
|
||||
if(addr == 0x3804) cpuport[0] = data;
|
||||
print("* w", hex<6>(addr), " = ", hex<2>(data), "\n");
|
||||
usleep(200000);
|
||||
|
||||
print("* w", hex<4>(addr), "w = ", hex<2>(data), "\n");
|
||||
switch(addr & 0xffff) {
|
||||
case 0x3800: w3800 = data; break;
|
||||
case 0x3802: w3802 = data; trace = 0; cputoarm = true; break;
|
||||
case 0x3804: w3804 = data; break;
|
||||
}
|
||||
}
|
||||
|
||||
void ArmDSP::init() {
|
||||
|
@ -96,6 +109,13 @@ void ArmDSP::reset() {
|
|||
pipeline.reload = true;
|
||||
|
||||
r[15].write = [&] { pipeline.reload = true; };
|
||||
|
||||
r3800=r3802=r3804=0;
|
||||
w3800=w3802=w3804=0;
|
||||
r40000000=r40000010=r40000020=r40000024=r40000028=r4000002c=0;
|
||||
w40000000=w40000010=w40000020=w40000024=w40000028=w4000002c=0;
|
||||
cputoarm=0;
|
||||
armtocpu=0;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,8 +6,17 @@ struct ArmDSP : public Coprocessor {
|
|||
|
||||
#include "registers.hpp"
|
||||
|
||||
uint8 cpuport[4];
|
||||
uint8 armport[4];
|
||||
//CPU
|
||||
uint8 r3800, r3802, r3804;
|
||||
uint8 w3800, w3802, w3804;
|
||||
|
||||
//ARM
|
||||
uint32 r40000000, r40000010, r40000020, r40000024, r40000028, r4000002c;
|
||||
uint32 w40000000, w40000010, w40000020, w40000024, w40000028, w4000002c;
|
||||
|
||||
//Status
|
||||
bool cputoarm;
|
||||
bool armtocpu;
|
||||
|
||||
static void Enter();
|
||||
void enter();
|
||||
|
@ -24,11 +33,11 @@ struct ArmDSP : public Coprocessor {
|
|||
//opcodes.cpp
|
||||
bool condition();
|
||||
void opcode(uint32 data);
|
||||
void flags(uint32 rd);
|
||||
|
||||
void op_branch();
|
||||
void op_data_immediate();
|
||||
void op_data_immediate_shift();
|
||||
void op_data_register_shift();
|
||||
void op_move_immediate_offset();
|
||||
void op_move_status_register_to_register();
|
||||
void op_move_multiple();
|
||||
|
|
|
@ -6,6 +6,10 @@ string ArmDSP::disassemble_opcode(uint32 pc) {
|
|||
static string registers[] = { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc" };
|
||||
static string indices[] = { "da", "ia", "db", "ib" };
|
||||
|
||||
static auto is_move = [](uint4 opcode) { return opcode == 13 || opcode == 15; };
|
||||
static auto is_comp = [](uint4 opcode) { return opcode >= 8 && opcode <= 11; };
|
||||
static auto is_math = [](uint4 opcode) { return opcode < 8 || opcode == 12 || opcode == 14; };
|
||||
|
||||
string output{hex<8>(pc), " "};
|
||||
|
||||
uint32 instruction = bus_read<4>(pc);
|
||||
|
@ -31,45 +35,65 @@ string ArmDSP::disassemble_opcode(uint32 pc) {
|
|||
}
|
||||
|
||||
//data immediate shift
|
||||
//{opcode}{condition}{s} rd,rm {shift} #immediate
|
||||
//{opcode}{condition} rn,rm {shift} #immediate
|
||||
//{opcode}{condition}{s} rd,rn,rm {shift} #immediate
|
||||
if((instruction & 0x0e000000) == 0x00000000) {
|
||||
uint4 condition = instruction >> 28;
|
||||
uint4 opcode = instruction >> 21;
|
||||
uint1 save = instruction >> 20;
|
||||
uint4 rd = instruction >> 16;
|
||||
uint4 rn = instruction >> 12;
|
||||
uint8 rm = instruction;
|
||||
uint4 rn = instruction >> 16;
|
||||
uint4 rd = instruction >> 12;
|
||||
uint5 shift = instruction >> 7;
|
||||
uint2 op = instruction >> 2;
|
||||
uint2 op = instruction >> 5;
|
||||
uint4 rm = instruction;
|
||||
|
||||
output.append(opcodes[opcode], conditions[condition], save ? "s " : " ");
|
||||
output.append(registers[rd], ",");
|
||||
output.append(registers[rn], ",");
|
||||
output.append(registers[rm], " ");
|
||||
if(op == 0) output.append("lsl #", shift);
|
||||
if(op == 1) output.append("lsr #", 1 + shift);
|
||||
if(op == 2) output.append("asr #", 1 + shift);
|
||||
if(op == 3 && shift != 0) output.append("ror #", shift);
|
||||
if(op == 3 && shift == 0) output.append("rrx");
|
||||
output.append(opcodes[opcode], conditions[condition]);
|
||||
if(is_move(opcode)) output.append(save ? "s " : " ", registers[rd]);
|
||||
if(is_comp(opcode)) output.append(" ", registers[rn]);
|
||||
if(is_math(opcode)) output.append(save ? "s " : " ", registers[rd], ",", registers[rn]);
|
||||
output.append(",", registers[rm]);
|
||||
if(op == 0 && shift != 0) output.append(" lsl #", shift);
|
||||
if(op == 1) output.append(" lsr #", shift == 0 ? 32u : (unsigned)shift);
|
||||
if(op == 2) output.append(" asr #", shift == 0 ? 32u : (unsigned)shift);
|
||||
if(op == 3 && shift != 0) output.append(" ror #", shift);
|
||||
if(op == 3 && shift == 0) output.append(" rrx");
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
//data immediate
|
||||
//{opcode}{condition}{s} rd,#immediate
|
||||
//{opcode}{condition} rn,#immediate
|
||||
//{opcode}{condition}{s} rd,rn,#immediate
|
||||
if((instruction & 0x0e000000) == 0x02000000) {
|
||||
uint5 rotate = 2 * (uint4)(instruction >> 8);
|
||||
uint32 immediate = (uint8)instruction;
|
||||
immediate = (immediate >> rotate) | (immediate << (32 - rotate));
|
||||
output.append(opcodes[opcode], " ", registers[rd], ",#0x", hex<8>(immediate));
|
||||
uint4 condition = instruction >> 28;
|
||||
uint4 opcode = instruction >> 21;
|
||||
uint1 save = instruction >> 20;
|
||||
uint4 rn = instruction >> 16;
|
||||
uint4 rd = instruction >> 12;
|
||||
uint4 rotate = instruction >> 8;
|
||||
uint8 immediate = instruction;
|
||||
|
||||
uint32 shifter = (immediate >> (rotate << 1)) | (immediate << (32 - (rotate << 1)));
|
||||
output.append(opcodes[opcode], conditions[condition]);
|
||||
if(is_move(opcode)) output.append(save ? "s " : " ", registers[rd]);
|
||||
if(is_comp(opcode)) output.append(" ", registers[rn]);
|
||||
if(is_math(opcode)) output.append(save ? "s " : " ", registers[rd], ",", registers[rn]);
|
||||
output.append(",#0x", hex<8>(shifter));
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
//move immediate offset
|
||||
//(ldr,str){condition}{b} rd,[rn{+offset}]
|
||||
//todo: support W flag
|
||||
if((instruction & 0x0e000000) == 0x04000000) {
|
||||
uint1 u = instruction >> 23;
|
||||
uint1 load = instruction >> 20;
|
||||
uint12 immediate = instruction;
|
||||
output.append(load ? "ldr" : "str", conditions[condition]);
|
||||
if(instruction & 0x00400000) output.append("b");
|
||||
output.append(" ", registers[rd], ",[", registers[rn]);
|
||||
if(immediate) output.append(u ? "+" : "-", "0x", hex<3>((uint12)instruction));
|
||||
output.append("]");
|
||||
|
@ -77,6 +101,7 @@ string ArmDSP::disassemble_opcode(uint32 pc) {
|
|||
}
|
||||
|
||||
//move multiple
|
||||
//(ldm,stm){condition}{mode} rn{!},{r...}
|
||||
if((instruction & 0x0e000000) == 0x08000000) {
|
||||
output.append(instruction & 0x00100000 ? "ldm" : "stm", conditions[condition], indices[(uint2)(instruction >> 23)]);
|
||||
output.append(" ", registers[rn], instruction & 0x00200000 ? "!" : "", ",{");
|
||||
|
@ -87,6 +112,7 @@ string ArmDSP::disassemble_opcode(uint32 pc) {
|
|||
}
|
||||
|
||||
//branch
|
||||
//b{l}{condition} address
|
||||
if((instruction & 0x0e000000) == 0x0a000000) {
|
||||
uint1 l = instruction >> 24;
|
||||
output.append("b", l ? "l" : "", conditions[condition]);
|
||||
|
|
|
@ -5,52 +5,70 @@ uint8 ArmDSP::bus_iread(uint32 addr) {
|
|||
return programROM[addr & 0x0001ffff];
|
||||
}
|
||||
|
||||
if(addr >= 0x40000020 && addr <= 0x4000002f) {
|
||||
if(addr == 0x40000020) return cpuport[0];
|
||||
if(addr == 0x40000024) return cpuport[1];
|
||||
if(addr == 0x40000028) return cpuport[2];
|
||||
if(addr == 0x4000002c) return cpuport[3];
|
||||
if(addr >= 0x40000000 && addr <= 0x400000ff) {
|
||||
if(addr == 0x40000000) { return r40000000; }
|
||||
if(addr == 0x40000010) { return w3802; }
|
||||
if(addr == 0x40000020) { return (cputoarm << 3); }
|
||||
if(addr == 0x40000024) { return r40000024; }
|
||||
if(addr == 0x40000028) { return r40000028; }
|
||||
if(addr == 0x4000002c) { return r4000002c; }
|
||||
}
|
||||
|
||||
if(addr >= 0xe0000000 && addr <= 0xe0003fff) {
|
||||
return programRAM[addr & 0x00003fff];
|
||||
}
|
||||
|
||||
//print("* ARM r", hex<8>(addr), "\n");
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
void ArmDSP::bus_iwrite(uint32 addr, uint8 data) {
|
||||
if(addr >= 0x40000020 && addr <= 0x4000002f) {
|
||||
if(addr == 0x40000020) armport[0] = data;
|
||||
if(addr == 0x40000024) armport[1] = data;
|
||||
if(addr == 0x40000028) armport[2] = data;
|
||||
if(addr == 0x4000002c) armport[3] = data;
|
||||
if(data) print("* ARM w", hex<8>(addr), " = ", hex<2>(data), "\n");
|
||||
if(addr >= 0x40000000 && addr <= 0x400000ff) {
|
||||
if(addr == 0x40000000) { w40000000 = data; }
|
||||
if(addr == 0x40000020) { w40000020 = data; }
|
||||
if(addr == 0x40000024) { w40000024 = data; }
|
||||
if(addr == 0x40000028) { w40000028 = data; }
|
||||
if(addr == 0x4000002c) { w4000002c = data; if(data & 2) r3804 = 0x80; }
|
||||
}
|
||||
|
||||
if(addr >= 0xe0000000 && addr <= 0xe0003fff) {
|
||||
programRAM[addr & 0x00003fff] = data;
|
||||
return;
|
||||
}
|
||||
|
||||
//print("* ARM w", hex<8>(addr), " = ", hex<2>(data), "\n");
|
||||
}
|
||||
|
||||
template<unsigned size>
|
||||
uint32 ArmDSP::bus_read(uint32 addr) {
|
||||
uint32 result = 0;
|
||||
result |= bus_iread(addr + 0) << 0;
|
||||
result |= bus_iread(addr + 1) << 8;
|
||||
result |= bus_iread(addr + 2) << 16;
|
||||
result |= bus_iread(addr + 3) << 24;
|
||||
if(size == 1) return result & 0xff;
|
||||
if(size == 2) return result & 0xffff;
|
||||
return result;
|
||||
uint32 data = 0;
|
||||
data |= bus_iread(addr + 0) << 0;
|
||||
data |= bus_iread(addr + 1) << 8;
|
||||
data |= bus_iread(addr + 2) << 16;
|
||||
data |= bus_iread(addr + 3) << 24;
|
||||
|
||||
if(addr >= 0x40000000 && addr <= 0x400000ff) {
|
||||
if(data) {
|
||||
if(size == 1) print("* ARM r", hex<8>(addr), " = ", hex<2>(data), "\n");
|
||||
if(size == 2) print("* ARM r", hex<8>(addr), " = ", hex<4>(data), "\n");
|
||||
if(size == 4) print("* ARM r", hex<8>(addr), " = ", hex<8>(data), "\n");
|
||||
usleep(20000);
|
||||
}
|
||||
}
|
||||
|
||||
if(size == 1) return data & 0xff;
|
||||
if(size == 2) return data & 0xffff;
|
||||
return data;
|
||||
}
|
||||
|
||||
template<unsigned size>
|
||||
void ArmDSP::bus_write(uint32 addr, uint32 data) {
|
||||
if(addr >= 0x40000000 && addr <= 0x400000ff) {
|
||||
if(0||data) {
|
||||
if(size == 1) print("* ARM w", hex<8>(addr), " = ", hex<2>(data), "\n");
|
||||
if(size == 2) print("* ARM w", hex<8>(addr), " = ", hex<4>(data), "\n");
|
||||
if(size == 4) print("* ARM w", hex<8>(addr), " = ", hex<8>(data), "\n");
|
||||
usleep(20000);
|
||||
}
|
||||
}
|
||||
|
||||
if(size == 1) data = (bus_read<1>(addr) & 0xffffff00) | (data & 0x000000ff);
|
||||
if(size == 2) data = (bus_read<2>(addr) & 0xffff0000) | (data & 0x0000ffff);
|
||||
bus_iwrite(addr + 0, data >> 0);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifdef ARMDSP_CPP
|
||||
|
||||
bool ArmDSP::condition() {
|
||||
switch((uint4)(instruction >> 28)) { default:
|
||||
switch((uint4)(instruction >> 28)) {
|
||||
case 0: return cpsr.z == 1; //EQ (equal)
|
||||
case 1: return cpsr.z == 0; //NE (not equal)
|
||||
case 2: return cpsr.c == 1; //CS (carry set)
|
||||
|
@ -53,15 +53,15 @@ void ArmDSP::opcode(uint32 rm) {
|
|||
switch(opcode) {
|
||||
case 0: rd = rn & rm; nz(rd); break; //AND (logical and)
|
||||
case 1: rd = rn ^ rm; nz(rd); break; //EOR (logical exclusive or)
|
||||
case 2: rd = rn +~rm; nzcv(rd); break; //SUB (subtract)
|
||||
case 3: rd = rm +~rn; nzcv(rd); break; //RSB (reverse subtract)
|
||||
case 2: rd = rn +~rm + 1; nzcv(rd); break; //SUB (subtract)
|
||||
case 3: rd = rm +~rn + 1; nzcv(rd); break; //RSB (reverse subtract)
|
||||
case 4: rd = rn + rm; nzcv(rd); break; //ADD (add)
|
||||
case 5: rd = rn + rm + cpsr.c; nzcv(rd); break; //ADC (add with carry)
|
||||
case 6: rd = rn +~rm + cpsr.c; nzcv(rd); break; //SBC (subtract with carry)
|
||||
case 7: rd = rm +~rn + cpsr.c; nzcv(rd); break; //RSC (reverse subtract with carry)
|
||||
case 8: ro = rn & rm; nz(ro); break; //TST (test)
|
||||
case 9: ro = rn ^ rm; nz(ro); break; //TEQ (test equivalence)
|
||||
case 10: ro = rn +~rm; nzcv(ro); break; //CMP (compare)
|
||||
case 10: ro = rn +~rm + 1; nzcv(ro); break; //CMP (compare)
|
||||
case 11: ro = rn + rm; nzcv(ro); break; //CMN (compare negated)
|
||||
case 12: rd = rn | rm; nz(rd); break; //ORR (logical inclusive or)
|
||||
case 13: rd = rm; nz(rd); break; //MOV (move)
|
||||
|
@ -70,11 +70,6 @@ void ArmDSP::opcode(uint32 rm) {
|
|||
}
|
||||
}
|
||||
|
||||
void ArmDSP::flags(uint32 rd) {
|
||||
cpsr.n = rd & 0x80000000;
|
||||
cpsr.z = rd == 0;
|
||||
}
|
||||
|
||||
//CCCC 101L DDDD DDDD DDDD DDDD DDDD DDDD
|
||||
//C = condition
|
||||
//L = link
|
||||
|
@ -89,6 +84,9 @@ void ArmDSP::op_branch() {
|
|||
r[15] += displacement * 4;
|
||||
}
|
||||
|
||||
//{opcode}{condition}{s} rd,#immediate
|
||||
//{opcode}{condition} rn,#immediate
|
||||
//{opcode}{condition}{s} rd,rn,#immediate
|
||||
//CCCC 001O OOOS NNNN DDDD RRRR IIII IIII
|
||||
//C = condition
|
||||
//O = opcode
|
||||
|
@ -100,16 +98,18 @@ void ArmDSP::op_branch() {
|
|||
void ArmDSP::op_data_immediate() {
|
||||
if(!condition()) return;
|
||||
|
||||
uint4 rotate = instruction >> 8;
|
||||
uint8 immediate = instruction >> 0;
|
||||
uint4 shift = instruction >> 8;
|
||||
uint8 immediate = instruction;
|
||||
|
||||
opcode(
|
||||
(immediate >> (rotate << 1)) | (immediate << (32 - (rotate << 1)))
|
||||
);
|
||||
uint32 rs = shift << 1;
|
||||
uint32 rm = (immediate >> rs) | (immediate << (32 - rs));
|
||||
|
||||
//todo: set carry for non-add/sub opcodes here
|
||||
opcode(rm);
|
||||
}
|
||||
|
||||
//{opcode}{condition}{s} rd,rm {shift} #immediate
|
||||
//{opcode}{condition} rn,rm {shift} #immediate
|
||||
//{opcode}{condition}{s} rd,rn,rm {shift} #immediate
|
||||
//CCCC 000O OOOS NNNN DDDD LLLL LSS0 MMMM
|
||||
//C = condition
|
||||
//O = opcode
|
||||
|
@ -123,34 +123,66 @@ void ArmDSP::op_data_immediate_shift() {
|
|||
if(!condition()) return;
|
||||
|
||||
uint5 shift = instruction >> 7;
|
||||
uint2 op = instruction >> 5;
|
||||
uint32 rm = r[(uint4)instruction];
|
||||
uint2 mode = instruction >> 5;
|
||||
uint4 m = instruction;
|
||||
|
||||
if(op == 0) { //LSL (logical shift left)
|
||||
rm = rm << shift;
|
||||
}
|
||||
uint32 rs = shift;
|
||||
uint32 rm = r[m];
|
||||
|
||||
if(op == 1) { //LSR (logical shift right)
|
||||
rm = rm >> (1 + shift);
|
||||
}
|
||||
switch(mode) {
|
||||
case 0: //LSL
|
||||
rm = rm << rs;
|
||||
break;
|
||||
|
||||
if(op == 2) { //ASR (arithmetic shift right)
|
||||
rm = (int32)rm >> (1 + shift);
|
||||
}
|
||||
case 1: //LSR
|
||||
if(rs == 0) rs = 32;
|
||||
rm = rm >> rs;
|
||||
break;
|
||||
|
||||
if(op == 3) { //ROR (rotate right)
|
||||
if(shift == 0) { //RRX (rorate right with extend)
|
||||
rm = (cpsr.c << 31) | (rm >> 1);
|
||||
} else {
|
||||
rm = (rm >> shift) + (rm << (32 - shift));
|
||||
}
|
||||
case 2: //ASR
|
||||
if(rs == 0) rs = 32;
|
||||
rm = (int32)rm >> rs;
|
||||
break;
|
||||
|
||||
case 3: //ROR + RRX
|
||||
if(rs == 0) rm = (cpsr.c << 31) | (rm >> 1); //RRX
|
||||
if(rs != 0) rm = (rm >> rs) + (rm << (32 - rs)); //ROR
|
||||
break;
|
||||
}
|
||||
|
||||
opcode(rm);
|
||||
|
||||
//todo: set carry
|
||||
}
|
||||
|
||||
//cccc 000o ooos nnnn dddd ssss 0ss1 mmmm
|
||||
//c = condition
|
||||
//o = opcode
|
||||
//s = save flags
|
||||
//n = rn
|
||||
//d = rd
|
||||
//s = rs
|
||||
//s = shift
|
||||
//m = rm
|
||||
void ArmDSP::op_data_register_shift() {
|
||||
if(!condition()) return;
|
||||
|
||||
uint4 s = instruction >> 8;
|
||||
uint2 mode = instruction >> 5;
|
||||
uint4 m = instruction >> 0;
|
||||
|
||||
uint32 rs = r[s];
|
||||
uint32 rm = r[m];
|
||||
|
||||
switch(mode) {
|
||||
case 0: rm = rm << rs; break; //LSL
|
||||
case 1: rm = rm >> rs; break; //LSR
|
||||
case 2: rm = (int32)rm >> rs; break; //ASR
|
||||
case 3: rm = (rm >> rs) + (rm << (32 - rs)); break; //ROR
|
||||
}
|
||||
|
||||
opcode(rm);
|
||||
}
|
||||
|
||||
//(ldr,str){condition}{b} rd,[rn{+offset}]
|
||||
//CCCC 010P UBWL NNNN DDDD IIII IIII IIII
|
||||
//C = condition
|
||||
//P = pre (0 = post-indexed addressing)
|
||||
|
@ -256,6 +288,8 @@ void ArmDSP::op_move_multiple() {
|
|||
if(u == 1) r[n] = r[n] + bit::count(list) * 4; //IA, IB
|
||||
if(u == 0) r[n] = r[n] - bit::count(list) * 4; //DA, DB
|
||||
}
|
||||
|
||||
//if(l)exception=true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue