68000: implement EORI, ROXL, ROXR. Fix bugs on ADDI.L and SUBI.L. Complete MOVA timings. Work on An/PC Indexed addressing modes.

This commit is contained in:
beirich 2011-10-09 19:15:31 +00:00
parent 2d2bfae611
commit c787b70613
6 changed files with 286 additions and 51 deletions

View File

@ -34,11 +34,14 @@ namespace BizHawk.Emulation.CPUs.M68000
else if (Opcodes[op] == PEA) PEA_Disasm(info);
else if (Opcodes[op] == ANDI) ANDI_Disasm(info);
else if (Opcodes[op] == EORI) EORI_Disasm(info);
else if (Opcodes[op] == ORI) ORI_Disasm(info);
else if (Opcodes[op] == LSLd) LSLd_Disasm(info);
else if (Opcodes[op] == LSRd) LSRd_Disasm(info);
else if (Opcodes[op] == ASLd) ASLd_Disasm(info);
else if (Opcodes[op] == ASRd) ASRd_Disasm(info);
else if (Opcodes[op] == LSLd) LSLd_Disasm(info);
else if (Opcodes[op] == LSRd) LSRd_Disasm(info);
else if (Opcodes[op] == ROXLd) ROXLd_Disasm(info);
else if (Opcodes[op] == ROXRd) ROXRd_Disasm(info);
else if (Opcodes[op] == ROLd) ROLd_Disasm(info);
else if (Opcodes[op] == RORd) RORd_Disasm(info);
else if (Opcodes[op] == SWAP) SWAP_Disasm(info);

View File

@ -74,9 +74,7 @@ namespace BizHawk.Emulation.CPUs.M68000
V = false;
C = false;
throw new NotTestedException();
switch (size)
{
case 0: // Byte
@ -299,6 +297,85 @@ namespace BizHawk.Emulation.CPUs.M68000
info.Length = pc - info.PC;
}
void EORI()
{
int size = (op >> 6) & 3;
int mode = (op >> 3) & 7;
int reg = (op >> 0) & 7;
V = false;
C = false;
switch (size)
{
case 0: // byte
{
sbyte immed = (sbyte) ReadWord(PC); PC += 2;
sbyte value = (sbyte) (PeekValueB(mode, reg) ^ immed);
WriteValueB(mode, reg, value);
N = (value & 0x80) != 0;
Z = value == 0;
PendingCycles -= mode == 0 ? 8 : 12 + EACyclesBW[mode, reg];
return;
}
case 1: // word
{
short immed = ReadWord(PC); PC += 2;
short value = (short)(PeekValueW(mode, reg) ^ immed);
WriteValueW(mode, reg, value);
N = (value & 0x8000) != 0;
Z = value == 0;
PendingCycles -= mode == 0 ? 8 : 12 + EACyclesBW[mode, reg];
return;
}
case 2: // long
{
int immed = ReadLong(PC); PC += 4;
int value = PeekValueL(mode, reg) ^ immed;
WriteValueL(mode, reg, value);
N = (value & 0x80000000) != 0;
Z = value == 0;
PendingCycles -= mode == 0 ? 16 : 20 + EACyclesL[mode, reg];
return;
}
}
}
void EORI_Disasm(DisassemblyInfo info)
{
int pc = info.PC + 2;
int size = (op >> 6) & 3;
int mode = (op >> 3) & 7;
int reg = (op >> 0) & 7;
switch (size)
{
case 0: // byte
{
info.Mnemonic = "eori.b";
sbyte immed = (sbyte) ReadWord(pc); pc += 2;
info.Args = String.Format("${0:X}, {1}", immed, DisassembleValue(mode, reg, 1, ref pc));
break;
}
case 1: // word
{
info.Mnemonic = "eori.w";
short immed = ReadWord(pc); pc += 2;
info.Args = String.Format("${0:X}, {1}", immed, DisassembleValue(mode, reg, 2, ref pc));
break;
}
case 2: // long
{
info.Mnemonic = "eori.l";
int immed = ReadLong(pc); pc += 4;
info.Args = String.Format("${0:X}, {1}", immed, DisassembleValue(mode, reg, 4, ref pc));
break;
}
}
info.Length = pc - info.PC;
}
void OR0() // OR <ea>, Dn
{
int dstReg = (op >> 9) & 0x07;
@ -1003,6 +1080,152 @@ namespace BizHawk.Emulation.CPUs.M68000
info.Length = pc - info.PC;
}
void ROXLd()
{
int rot = (op >> 9) & 7;
int size = (op >> 6) & 3;
int m = (op >> 5) & 1;
int reg = op & 7;
if (m == 0 && rot == 0) rot = 8;
else if (m == 1) rot = D[rot].s32 & 63;
C = X;
V = false;
switch (size)
{
case 0: // byte
for (int i = 0; i < rot; i++)
{
C = (D[reg].u8 & 0x80) != 0;
D[reg].u8 = (byte)((D[reg].u8 << 1) | (X ? 1 : 0));
X = C;
}
N = (D[reg].s8 & 0x80) != 0;
Z = D[reg].s8 == 0;
PendingCycles -= 6 + (rot * 2);
return;
case 1: // word
for (int i = 0; i < rot; i++)
{
C = (D[reg].u16 & 0x8000) != 0;
D[reg].u16 = (ushort)((D[reg].u16 << 1) | (X ? 1 : 0));
X = C;
}
N = (D[reg].s16 & 0x8000) != 0;
Z = D[reg].s16 == 0;
PendingCycles -= 6 + (rot * 2);
return;
case 2: // long
for (int i = 0; i < rot; i++)
{
C = (D[reg].s32 & 0x80000000) != 0;
D[reg].s32 = ((D[reg].s32 << 1) | (X ? 1 : 0));
X = C;
}
N = (D[reg].s32 & 0x80000000) != 0;
Z = D[reg].s32 == 0;
PendingCycles -= 8 + (rot * 2);
return;
}
}
void ROXLd_Disasm(DisassemblyInfo info)
{
int pc = info.PC + 2;
int rot = (op >> 9) & 7;
int size = (op >> 6) & 3;
int m = (op >> 5) & 1;
int reg = op & 7;
if (m == 0 && rot == 0) rot = 8;
switch (size)
{
case 0: info.Mnemonic = "roxl.b"; break;
case 1: info.Mnemonic = "roxl.w"; break;
case 2: info.Mnemonic = "roxl.l"; break;
}
if (m == 0) info.Args = rot + ", D" + reg;
else info.Args = "D" + rot + ", D" + reg;
info.Length = pc - info.PC;
}
void ROXRd()
{
int rot = (op >> 9) & 7;
int size = (op >> 6) & 3;
int m = (op >> 5) & 1;
int reg = op & 7;
if (m == 0 && rot == 0) rot = 8;
else if (m == 1) rot = D[rot].s32 & 63;
C = X;
V = false;
switch (size)
{
case 0: // byte
for (int i = 0; i < rot; i++)
{
C = (D[reg].u8 & 1) != 0;
D[reg].u8 = (byte)((D[reg].u8 >> 1) | (X ? 0x80 : 0));
X = C;
}
N = (D[reg].s8 & 0x80) != 0;
Z = D[reg].s8 == 0;
PendingCycles -= 6 + (rot * 2);
return;
case 1: // word
for (int i = 0; i < rot; i++)
{
C = (D[reg].u16 & 1) != 0;
D[reg].u16 = (ushort)((D[reg].u16 >> 1) | (X ? 0x8000 : 0));
X = C;
}
N = (D[reg].s16 & 0x8000) != 0;
Z = D[reg].s16 == 0;
PendingCycles -= 6 + (rot * 2);
return;
case 2: // long
for (int i = 0; i < rot; i++)
{
C = (D[reg].s32 & 1) != 0;
D[reg].u32 = ((D[reg].u32 >> 1) | (X ? 0x80000000 : 0));
X = C;
}
N = (D[reg].s32 & 0x80000000) != 0;
Z = D[reg].s32 == 0;
PendingCycles -= 8 + (rot * 2);
return;
}
}
void ROXRd_Disasm(DisassemblyInfo info)
{
int pc = info.PC + 2;
int rot = (op >> 9) & 7;
int size = (op >> 6) & 3;
int m = (op >> 5) & 1;
int reg = op & 7;
if (m == 0 && rot == 0) rot = 8;
switch (size)
{
case 0: info.Mnemonic = "roxr.b"; break;
case 1: info.Mnemonic = "roxr.w"; break;
case 2: info.Mnemonic = "roxr.l"; break;
}
if (m == 0) info.Args = rot + ", D" + reg;
else info.Args = "D" + rot + ", D" + reg;
info.Length = pc - info.PC;
}
void SWAP()
{
int reg = op & 7;

View File

@ -90,16 +90,19 @@ namespace BizHawk.Emulation.CPUs.M68000
case 2: PendingCycles -= 8; break;
case 3: PendingCycles -= 8; break;
case 4: PendingCycles -= 10; break;
case 5: PendingCycles -= 12; break;
case 6: PendingCycles -= 14; break;
case 7:
switch (srcReg)
{
case 0: PendingCycles -= 12; break;
case 1: PendingCycles -= 16; break;
case 2: PendingCycles -= 12; break;
case 3: PendingCycles -= 14; break;
case 4: PendingCycles -= 8; break;
default: throw new NotImplementedException();
default: throw new InvalidOperationException();
}
break;
default: throw new NotImplementedException();
}
} else { // Long
A[dstReg].s32 = ReadValueL(srcMode, srcReg);
@ -110,16 +113,19 @@ namespace BizHawk.Emulation.CPUs.M68000
case 2: PendingCycles -= 12; break;
case 3: PendingCycles -= 12; break;
case 4: PendingCycles -= 14; break;
case 5: PendingCycles -= 16; break;
case 6: PendingCycles -= 18; break;
case 7:
switch (srcReg)
{
case 0: PendingCycles -= 16; break;
case 1: PendingCycles -= 20; break;
case 2: PendingCycles -= 16; break;
case 3: PendingCycles -= 18; break;
case 4: PendingCycles -= 12; break;
default: throw new NotImplementedException();
default: throw new InvalidOperationException();
}
break;
default: throw new NotImplementedException();
}
}
}

View File

@ -169,7 +169,7 @@ namespace BizHawk.Emulation.CPUs.M68000
}
case 2: // long
{
int immed = ReadLong(PC); PC += 2;
int immed = ReadLong(PC); PC += 4;
int value = PeekValueL(mode, reg);
long result = value + immed;
long uresult = (uint)value + (uint)immed;
@ -492,7 +492,7 @@ namespace BizHawk.Emulation.CPUs.M68000
}
case 2: // long
{
int immed = ReadLong(PC); PC += 2;
int immed = ReadLong(PC); PC += 4;
int value = PeekValueL(mode, reg);
long result = value - immed;
long uresult = (uint)value - (uint)immed;

View File

@ -302,10 +302,7 @@ namespace BizHawk.Emulation.CPUs.M68000
case 2: return A[reg].s32; // (An)
case 3: return A[reg].s32; // (An)+
case 4: return A[reg].s32; // -(An)
case 5: // (d16,An)
addr = A[reg].s32 + ReadWord(PC);
PC += 2;
return addr;
case 5: addr = A[reg].s32 + ReadWord(PC); PC += 2; return addr; // (d16,An)
case 6: return A[reg].s32 + GetIndex(); // (d8,An,Xn)
case 7:
switch (reg)
@ -324,6 +321,7 @@ namespace BizHawk.Emulation.CPUs.M68000
string DisassembleValue(int mode, int reg, int size, ref int pc)
{
string value;
int addr;
switch (mode)
{
case 0: return "D"+reg; // Dn
@ -331,33 +329,15 @@ namespace BizHawk.Emulation.CPUs.M68000
case 2: return "(A"+reg+")"; // (An)
case 3: return "(A"+reg+")+"; // (An)+
case 4: return "-(A"+reg+")"; // -(An)
case 5: // (d16,An)
// TODO need to figure out how to print signed-hex
value = string.Format("(${0:X},A{1})", ReadWord(pc), reg);
pc += 2;
return value;
case 6: return "NOT IMPLEMENTED"; // (d8,An,Xn)
//return ReadByte(A[reg].Long + GetIndex());
case 5: value = string.Format("(${0:X},A{1})", ReadWord(pc), reg); pc += 2; return value; // (d16,An)
case 6: addr = ReadWord(pc); pc += 2; return DisassembleIndex("A" + reg, (short) addr); // (d8,An,Xn)
case 7:
switch (reg)
{
case 0: // (imm).W
value = String.Format("(${0:X})", ReadWord(pc));
pc += 2;
return value;
case 1: // (imm).L
value = String.Format("(${0:X})", ReadLong(pc));
pc += 4;
return value;
case 2: // (d16,PC)
value = String.Format("(${0:X})", pc + ReadWord(pc));
pc += 2;
return value;
case 3: // (d8,PC,Xn)
return "NOT IMPLEMENTED";
/* uint _pc = PC;
value = ReadByte((_pc + GetIndex()));
return value;*/
case 0: value = String.Format("(${0:X})", ReadWord(pc)); pc += 2; return value; // (imm).W
case 1: value = String.Format("(${0:X})", ReadLong(pc)); pc += 4; return value; // (imm).L
case 2: value = String.Format("(${0:X})", pc + ReadWord(pc)); pc += 2; return value; // (d16,PC)
case 3: addr = ReadWord(pc); pc += 2; return DisassembleIndex("PC", (short)addr); // (d8,PC,Xn)
case 4:
switch (size)
{
@ -400,18 +380,15 @@ namespace BizHawk.Emulation.CPUs.M68000
case 2: return "(A"+reg+")"; // (An)
case 3: return "(A"+reg+")+"; // (An)+
case 4: return "-(A"+reg+")"; // -(An)
case 5: // (d16,An)
addr = ReadWord(pc);
pc += 2;
return String.Format("({0},A{1})", addr, reg);
case 6: return "NOT IMPLEMENTED"; // (d8,An,Xn)
case 5: addr = ReadWord(pc); pc += 2; return String.Format("({0},A{1})", addr, reg); // (d16,An)
case 6: addr = ReadWord(pc); pc += 2; return DisassembleIndex("A" + reg, (short)addr); // (d8,An,Xn)
case 7:
switch (reg)
{
case 0: addr = ReadWord(pc); pc += 2; return String.Format("${0:X}.w",addr); // (imm).w
case 1: addr = ReadLong(pc); pc += 4; return String.Format("${0:X}.l",addr); // (imm).l
case 2: addr = ReadWord(pc); pc += 2; return String.Format("(${0:X},PC)",addr); // (d16,PC)
case 3: return "NOT IMPLEMENTED"; // (d8,PC,Xn)
case 3: addr = ReadWord(pc); pc += 2; return DisassembleIndex("PC", (short)addr); // (d8,PC,Xn)
case 4: return "INVALID"; // immediate
}
break;
@ -573,9 +550,9 @@ namespace BizHawk.Emulation.CPUs.M68000
short extension = ReadWord(PC); PC += 2;
int da = (extension >> 15) & 0x1;
int reg = (extension >> 12) & 0x7;
int size = (extension >> 11) & 0x1;
int da = (extension >> 15) & 0x1;
int reg = (extension >> 12) & 0x7;
int size = (extension >> 11) & 0x1;
int scale = (extension >> 9) & 0x3;
sbyte displacement = (sbyte)extension;
@ -622,5 +599,28 @@ namespace BizHawk.Emulation.CPUs.M68000
return displacement + indexReg;
}
string DisassembleIndex(string baseRegister, short extension)
{
int d_a = (extension >> 15) & 0x1;
int reg = (extension >> 12) & 0x7;
int size = (extension >> 11) & 0x1;
int scale = (extension >> 9) & 0x3;
sbyte displacement = (sbyte)extension;
string scaleFactor;
switch (scale)
{
case 0: scaleFactor = ""; break;
case 1: scaleFactor = "2"; break;
case 2: scaleFactor = "4"; break;
default: scaleFactor = "8"; break;
}
string offsetRegister = (d_a == 0) ? "D" : "A";
string sizeStr = size == 0 ? ".w" : ".l";
string displacementStr = displacement == 0 ? "" : ("," + displacement);
return string.Format("({0},{1}{2}{3}{4}{5})", baseRegister, scaleFactor, offsetRegister, reg, sizeStr, displacementStr);
}
}
}

View File

@ -21,11 +21,14 @@ namespace BizHawk.Emulation.CPUs.M68000
Assign("pea", PEA, "0100100001", "AmXn");
Assign("andi", ANDI, "00000010", "Size2_1", "AmXn");
Assign("eori", EORI, "00001010", "Size2_1", "AmXn");
Assign("ori", ORI, "00000000", "Size2_1", "AmXn");
Assign("lsl", LSLd, "1110", "Data3", "1", "Size2_1", "Data1", "01", "Xn");
Assign("lsr", LSRd, "1110", "Data3", "0", "Size2_1", "Data1", "01", "Xn");
Assign("asl", ASLd, "1110", "Data3", "1", "Size2_1", "Data1", "00", "Xn");
Assign("asr", ASRd, "1110", "Data3", "0", "Size2_1", "Data1", "00", "Xn");
Assign("lsl", LSLd, "1110", "Data3", "1", "Size2_1", "Data1", "01", "Xn");
Assign("lsr", LSRd, "1110", "Data3", "0", "Size2_1", "Data1", "01", "Xn");
Assign("roxl", ROXLd, "1110", "Data3", "1", "Size2_1", "Data1", "10", "Xn");
Assign("roxr", ROXRd, "1110", "Data3", "0", "Size2_1", "Data1", "10", "Xn");
Assign("rol", ROLd, "1110", "Data3", "1", "Size2_1", "Data1", "11", "Xn");
Assign("ror", RORd, "1110", "Data3", "0", "Size2_1", "Data1", "11", "Xn");
Assign("swap", SWAP, "0100100001000","Xn");
@ -107,7 +110,7 @@ namespace BizHawk.Emulation.CPUs.M68000
foreach (var opcode in opList)
{
int opc = Convert.ToInt32(opcode, 2);
if (Opcodes[opc] != null && instr.NotIn("movea","andi2sr","ori2sr","ext","dbcc","swap"))
if (Opcodes[opc] != null && instr.NotIn("movea","andi2sr","eori2sr","ori2sr","ext","dbcc","swap"))
Console.WriteLine("Setting opcode for {0}, a handler is already set. overwriting. {1:X4}", instr, opc);
Opcodes[opc] = exec;
}