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:
parent
2d2bfae611
commit
c787b70613
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue