68000: add MULU, MULS, DIVU, DIVS, MOVE to CCR

Some genesis source reorganization
This commit is contained in:
beirich 2011-10-11 03:52:44 +00:00
parent c787b70613
commit 5b5c7c2890
18 changed files with 242 additions and 70 deletions

View File

@ -163,6 +163,7 @@
<Compile Include="Consoles\PC Engine\MemoryMap.Populous.cs" />
<Compile Include="Consoles\PC Engine\ScsiCDBus.cs" />
<Compile Include="Consoles\PC Engine\TurboCD.cs" />
<Compile Include="Consoles\Sega\Genesis\Input.cs" />
<Compile Include="Consoles\Sega\SMS\MemoryMap.CodeMasters.cs" />
<Compile Include="Consoles\Sega\SMS\MemoryMap.Sega.cs" />
<Compile Include="Consoles\Sega\SMS\VDP.ModeTMS.cs" />
@ -174,7 +175,7 @@
<Compile Include="CPUs\68000\Instructions\IntegerMath.cs" />
<Compile Include="CPUs\68000\Instructions\ProgramFlow.cs" />
<Compile Include="CPUs\68000\Instructions\Supervisor.cs" />
<Compile Include="CPUs\68000\M68000.cs" />
<Compile Include="CPUs\68000\MC68000.cs" />
<Compile Include="CPUs\68000\Memory.cs" />
<Compile Include="CPUs\68000\OpcodeTable.cs" />
<Compile Include="CPUs\68000\Tables.cs" />
@ -277,7 +278,6 @@
<Compile Include="Consoles\PC Engine\VPC.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Consoles\Sega\Genesis\Genesis.cs" />
<Compile Include="Consoles\Sega\Genesis\Genesis.Input.cs" />
<Compile Include="Consoles\Sega\Genesis\GenVDP.cs" />
<Compile Include="Consoles\Sega\Genesis\GenVDP.DMA.cs" />
<Compile Include="Consoles\Sega\Genesis\GenVDP.Render.cs" />
@ -300,6 +300,7 @@
<Content Include="Consoles\Nintendo\Docs\notes_for_disch.txt" />
<Content Include="Consoles\Nintendo\Docs\test_status.txt" />
<Content Include="Consoles\PC Engine\Compat.txt" />
<Content Include="Consoles\Sega\Genesis\Compat.txt" />
<Content Include="Consoles\Sega\SMS\Compat.txt" />
<Content Include="ExternalCores\Snippets.txt" />
<Content Include="Notes.txt" />

View File

@ -2,7 +2,7 @@
namespace BizHawk.Emulation.CPUs.M68000
{
public class DisassemblyInfo
public sealed class DisassemblyInfo
{
public int PC;
public string Mnemonic;
@ -88,6 +88,10 @@ namespace BizHawk.Emulation.CPUs.M68000
else if (Opcodes[op] == CMP) CMP_Disasm(info);
else if (Opcodes[op] == CMPA) CMPA_Disasm(info);
else if (Opcodes[op] == CMPI) CMPI_Disasm(info);
else if (Opcodes[op] == MULU) MULU_Disasm(info);
else if (Opcodes[op] == MULS) MULS_Disasm(info);
else if (Opcodes[op] == DIVU) DIVU_Disasm(info);
else if (Opcodes[op] == DIVS) DIVS_Disasm(info);
else if (Opcodes[op] == MOVEtSR) MOVEtSR_Disasm(info);
else if (Opcodes[op] == MOVEfSR) MOVEfSR_Disasm(info);
@ -95,6 +99,7 @@ namespace BizHawk.Emulation.CPUs.M68000
else if (Opcodes[op] == ANDI_SR) ANDI_SR_Disasm(info);
else if (Opcodes[op] == EORI_SR) EORI_SR_Disasm(info);
else if (Opcodes[op] == ORI_SR) ORI_SR_Disasm(info);
else if (Opcodes[op] == MOVECCR) MOVECCR_Disasm(info);
else if (Opcodes[op] == TRAP) TRAP_Disasm(info);
var sb = new StringBuilder();

View File

@ -4,6 +4,7 @@ namespace BizHawk.Emulation.CPUs.M68000
{
partial class MC68000
{
// TODO, the timing on AND variants is wrong. IE, and.w w/ immediate should be 8 cycles, but I cant figure out how that should work.
void AND0() // AND <ea>, Dn
{
int dstReg = (op >> 9) & 0x07;

View File

@ -439,8 +439,8 @@ namespace BizHawk.Emulation.CPUs.M68000
int reg = (op >> 0) & 7;
int pc = info.PC + 2;
ushort registers = (ushort)ReadWord(pc); pc += 2;
string address = DisassembleAddress(mode, reg, ref pc);
ushort registers = (ushort) ReadWord(pc); pc += 2;
info.Mnemonic = size == 0 ? "movem.w" : "movem.l";
info.Args = DisassembleRegisterList0(registers) + ", " + address;
@ -454,9 +454,9 @@ namespace BizHawk.Emulation.CPUs.M68000
int reg = (op >> 0) & 7;
int pc = info.PC + 2;
string address = DisassembleAddress(mode, reg, ref pc);
ushort registers = (ushort)ReadWord(pc); pc += 2;
string address = DisassembleAddress(mode, reg, ref pc);
info.Mnemonic = size == 0 ? "movem.w" : "movem.l";
info.Args = address + ", " + DisassembleRegisterList1(registers);
info.Length = pc - info.PC;

View File

@ -307,8 +307,11 @@ namespace BizHawk.Emulation.CPUs.M68000
PendingCycles -= 8 + EACyclesBW[mode, reg];
} else { // long
int value = ReadValueL(mode, reg);
A[aReg].s32 -= value;
PendingCycles += 6 + EACyclesL[mode, reg];
A[aReg].s32 += value;
if (mode == 0 || mode == 1 || (mode == 7 && reg == 4))
PendingCycles -= 8 + EACyclesL[mode, reg];
else
PendingCycles -= 6 + EACyclesL[mode, reg];
}
}
@ -631,7 +634,10 @@ namespace BizHawk.Emulation.CPUs.M68000
} else { // long
int value = ReadValueL(mode, reg);
A[aReg].s32 -= value;
PendingCycles -= 6 + EACyclesL[mode, reg];
if (mode == 0 || mode == 1 || (mode == 7 && reg == 4))
PendingCycles -= 8 + EACyclesL[mode, reg];
else
PendingCycles -= 6 + EACyclesL[mode, reg];
}
}
@ -951,5 +957,135 @@ namespace BizHawk.Emulation.CPUs.M68000
}
info.Length = pc - info.PC;
}
void MULU()
{
int dreg = (op >> 9) & 3;
int mode = (op >> 3) & 7;
int reg = (op >> 0) & 7;
uint result = (uint) (D[dreg].u16 * (ushort)ReadValueW(mode, reg));
D[dreg].u32 = result;
V = false;
C = false;
N = (result & 0x80000000) != 0;
Z = result == 0;
PendingCycles -= 70 + EACyclesBW[mode, reg];
}
void MULU_Disasm(DisassemblyInfo info)
{
int dreg = (op >> 9) & 3;
int mode = (op >> 3) & 7;
int reg = (op >> 0) & 7;
int pc = info.PC;
info.Mnemonic = "mulu";
info.Args = String.Format("{0}, D{1}", DisassembleValue(mode, reg, 2, ref pc), dreg);
info.Length = pc - info.PC;
}
void MULS()
{
int dreg = (op >> 9) & 3;
int mode = (op >> 3) & 7;
int reg = (op >> 0) & 7;
int result = D[dreg].s16 * ReadValueW(mode, reg);
D[dreg].s32 = result;
V = false;
C = false;
N = (result & 0x80000000) != 0;
Z = result == 0;
PendingCycles -= 70 + EACyclesBW[mode, reg];
}
void MULS_Disasm(DisassemblyInfo info)
{
int dreg = (op >> 9) & 3;
int mode = (op >> 3) & 7;
int reg = (op >> 0) & 7;
int pc = info.PC;
info.Mnemonic = "muls";
info.Args = String.Format("{0}, D{1}", DisassembleValue(mode, reg, 2, ref pc), dreg);
info.Length = pc - info.PC;
}
void DIVU()
{
int dreg = (op >> 9) & 3;
int mode = (op >> 3) & 7;
int reg = (op >> 0) & 7;
uint source = (ushort) ReadValueW(mode, reg);
uint dest = D[dreg].u32;
if (source == 0)
throw new Exception("divide by zero");
uint quotient = dest / source;
uint remainder = dest % source;
V = ((int) quotient < short.MinValue || (int) quotient > short.MaxValue);
N = (quotient & 0x8000) != 0;
Z = quotient == 0;
C = false;
D[dreg].u32 = (quotient & 0xFFFF) | (remainder << 16);
PendingCycles -= 140 + EACyclesBW[mode, reg]; // this is basically a rough approximation at best.
}
void DIVU_Disasm(DisassemblyInfo info)
{
int dreg = (op >> 9) & 3;
int mode = (op >> 3) & 7;
int reg = (op >> 0) & 7;
int pc = info.PC;
info.Mnemonic = "divu";
info.Args = String.Format("{0}, D{1}", DisassembleValue(mode, reg, 2, ref pc), dreg);
info.Length = pc - info.PC;
}
void DIVS()
{
int dreg = (op >> 9) & 3;
int mode = (op >> 3) & 7;
int reg = (op >> 0) & 7;
int source = ReadValueW(mode, reg);
int dest = D[dreg].s32;
if (source == 0)
throw new Exception("divide by zero");
int quotient = dest / source;
int remainder = dest % source;
V = ((int)quotient < short.MinValue || (int)quotient > short.MaxValue);
N = (quotient & 0x8000) != 0;
Z = quotient == 0;
C = false;
D[dreg].s32 = (quotient & 0xFFFF) | (remainder << 16);
PendingCycles -= 140 + EACyclesBW[mode, reg];
}
void DIVS_Disasm(DisassemblyInfo info)
{
int dreg = (op >> 9) & 3;
int mode = (op >> 3) & 7;
int reg = (op >> 0) & 7;
int pc = info.PC;
info.Mnemonic = "divs";
info.Args = String.Format("{0}, D{1}", DisassembleValue(mode, reg, 2, ref pc), dreg);
info.Length = pc - info.PC;
}
}
}

View File

@ -628,7 +628,8 @@ namespace BizHawk.Emulation.CPUs.M68000
A[7].s32 -= 4;
short offset = ReadWord(PC); PC += 2;
WriteLong(A[7].s32, A[reg].s32);
A[reg].s32 = A[7].s32 + offset;
A[reg].s32 = A[7].s32;
A[7].s32 += offset;
PendingCycles -= 16;
}

View File

@ -12,7 +12,7 @@ namespace BizHawk.Emulation.CPUs.M68000
int mode = (op >> 3) & 7;
int reg = (op >> 0) & 7;
SR = ReadValueW(mode, reg);
PendingCycles -= (mode == 0) ? 12 : 12 + EACyclesBW[mode, reg];
PendingCycles -= 12 + EACyclesBW[mode, reg];
}
void MOVEtSR_Disasm(DisassemblyInfo info)
@ -115,6 +115,27 @@ namespace BizHawk.Emulation.CPUs.M68000
info.Length = pc - info.PC;
}
void MOVECCR()
{
int mode = (op >> 3) & 7;
int reg = (op >> 0) & 7;
ushort sr = (ushort) (SR & 0xFF00);
sr |= (byte)ReadValueB(mode, reg);
SR = (short)sr;
PendingCycles -= 12 + EACyclesBW[mode, reg];
}
void MOVECCR_Disasm(DisassemblyInfo info)
{
int pc = info.PC + 2;
int mode = (op >> 3) & 7;
int reg = (op >> 0) & 7;
info.Mnemonic = "move";
info.Args = DisassembleValue(mode, reg, 2, ref pc) + ", CCR";
info.Length = pc - info.PC;
}
void TRAP()
{
int vector = 32 + (op & 0x0F);

View File

@ -144,6 +144,7 @@ namespace BizHawk.Emulation.CPUs.M68000
int prevCycles = PendingCycles;
Log.Note("CPU", State());
op = (ushort)ReadWord(PC);
if (Opcodes[op] == null) throw new Exception(string.Format("unhandled opcode at pc={0:X6}",PC));
PC += 2;
Opcodes[op]();
int delta = prevCycles - PendingCycles;

View File

@ -173,7 +173,7 @@ namespace BizHawk.Emulation.CPUs.M68000
value = ReadByte((A[reg].s32 + ReadWord(PC)));
return value;
case 6: // (d8,An,Xn)
return ReadByte(A[reg].s32 + GetIndex());
return ReadByte(A[reg].s32 + PeekIndex());
case 7:
switch (reg)
{
@ -545,7 +545,7 @@ namespace BizHawk.Emulation.CPUs.M68000
int GetIndex()
{
Console.WriteLine("IN INDEX PORTION - NOT VERIFIED!!!");
//Console.WriteLine("IN INDEX PORTION - NOT VERIFIED!!!");
// TODO kid chameleon triggers this in startup sequence
short extension = ReadWord(PC); PC += 2;
@ -574,7 +574,7 @@ namespace BizHawk.Emulation.CPUs.M68000
int PeekIndex()
{
Console.WriteLine("IN INDEX PORTION - NOT VERIFIED!!!");
//Console.WriteLine("IN INDEX PORTION - NOT VERIFIED!!!");
short extension = ReadWord(PC);

View File

@ -75,6 +75,10 @@ namespace BizHawk.Emulation.CPUs.M68000
Assign("cmp", CMP, "1011", "Xn", "0", "Size2_1", "AmXn");
Assign("cmpa", CMPA, "1011", "Xn", "Size1", "11", "AmXn");
Assign("cmpi", CMPI, "00001100", "Size2_1", "AmXn");
Assign("mulu", MULU, "1100", "Xn", "011", "AmXn"); // TODO accurate timing
Assign("muls", MULS, "1100", "Xn", "111", "AmXn"); // TODO accurate timing
Assign("divu", DIVU, "1000", "Xn", "011", "AmXn"); // TODO accurate timing
Assign("divs", DIVS, "1000", "Xn", "111", "AmXn"); // TODO accurate timing
Assign("move2sr", MOVEtSR, "0100011011", "AmXn");
Assign("movefsr", MOVEfSR, "0100000011", "AmXn");
@ -82,6 +86,7 @@ namespace BizHawk.Emulation.CPUs.M68000
Assign("andi2sr", ANDI_SR, "0000001001111100");
Assign("eori2sr", EORI_SR, "0000101001111100");
Assign("ori2sr", ORI_SR, "0000000001111100");
Assign("moveccr", MOVECCR, "0100010011", "AmXn");
Assign("trap", TRAP, "010011100100", "Data4");
}

View File

@ -34,28 +34,28 @@
{ 12, 12, 20, 20, 20, 24, 26, 24, 28 }
};
static readonly int[,] EACyclesBW = new int[8, 9]
static readonly int[,] EACyclesBW = new int[8, 8]
{
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 4, 4, 4, 4, 4, 4, 4, 4, 4 },
{ 4, 4, 4, 4, 4, 4, 4, 4, 4 },
{ 6, 6, 6, 6, 6, 6, 6, 6, 6 },
{ 8, 8, 8, 8, 8, 8, 8, 8, 8 },
{ 10, 10, 10, 10, 10, 10, 10, 10, 10 },
{ 8, 12, 8, 10, 4, 99, 99, 99, 99 }
{ 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 },
{ 4, 4, 4, 4, 4, 4, 4, 4 },
{ 4, 4, 4, 4, 4, 4, 4, 4 },
{ 6, 6, 6, 6, 6, 6, 6, 6 },
{ 8, 8, 8, 8, 8, 8, 8, 8 },
{ 10, 10, 10, 10, 10, 10, 10, 10 },
{ 8, 12, 8, 10, 4, 99, 99, 99 }
};
static readonly int[,] EACyclesL = new int[8, 9]
static readonly int[,] EACyclesL = new int[8, 8]
{
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 8, 8, 8, 8, 8, 8, 8, 8, 8 },
{ 8, 8, 8, 8, 8, 8, 8, 8, 8 },
{ 10, 10, 10, 10, 10, 10, 10, 10, 10 },
{ 12, 12, 12, 12, 12, 12, 12, 12, 12 },
{ 14, 14, 14, 14, 14, 14, 14, 14, 14 },
{ 12, 16, 12, 14, 8, 99, 99, 99, 99 }
{ 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 },
{ 8, 8, 8, 8, 8, 8, 8, 8 },
{ 8, 8, 8, 8, 8, 8, 8, 8 },
{ 10, 10, 10, 10, 10, 10, 10, 10 },
{ 12, 12, 12, 12, 12, 12, 12, 12 },
{ 14, 14, 14, 14, 14, 14, 14, 14 },
{ 12, 16, 12, 14, 8, 99, 99, 99 }
};
}
}

View File

@ -0,0 +1,8 @@
68000:
Timings:
- MULU/MULS/DIVU/DIVS have funky timings.
- How many cycles does TRAP take to execute?
- How many cycles does it take to accept an interrupt?
- AND has some funky timings when it comes to immediates?

View File

@ -7,7 +7,8 @@ using BizHawk.Emulation.Sound;
namespace BizHawk.Emulation.Consoles.Sega
{
public sealed partial class Genesis : IEmulator
[CoreVersion("0.0.0.1", FriendlyName = "MegaHawk")]
public sealed partial class Genesis : IEmulator
{
// ROM
public byte[] RomData;
@ -61,15 +62,15 @@ namespace BizHawk.Emulation.Consoles.Sega
YM2612 = new YM2612();
PSG = new SN76489();
VDP = new GenVDP();
VDP.DmaReadFrom68000 = ReadW;
VDP.DmaReadFrom68000 = ReadWord;
SoundMixer = new SoundMixer(YM2612, PSG);
MainCPU.ReadByte = ReadB;
MainCPU.ReadWord = ReadW;
MainCPU.ReadLong = ReadL;
MainCPU.WriteByte = WriteB;
MainCPU.WriteWord = WriteW;
MainCPU.WriteLong = WriteL;
MainCPU.ReadByte = ReadByte;
MainCPU.ReadWord = ReadWord;
MainCPU.ReadLong = ReadLong;
MainCPU.WriteByte = WriteByte;
MainCPU.WriteWord = WriteWord;
MainCPU.WriteLong = WriteLong;
SoundCPU.ReadMemory = ReadMemoryZ80;
SoundCPU.WriteMemory = WriteMemoryZ80;
@ -94,7 +95,7 @@ namespace BizHawk.Emulation.Consoles.Sega
if (VDP.ScanLine < 224)
VDP.RenderLine();
MainCPU.ExecuteCycles(487); // 488??
if (Z80Runnable)
{

View File

@ -1,17 +1,17 @@
namespace BizHawk.Emulation.Consoles.Sega
{
public partial class Genesis
partial class Genesis
{
// todo ???????
public bool SegaCD = false;
public int ReadIO(int offset)
public byte ReadIO(int offset)
{
int value;
offset &= 3;
byte value;
switch (offset)
{
case 0: // version
value = SegaCD ? 0x00 : 0x20;
value = (byte) (SegaCD ? 0x00 : 0x20);
switch((char)RomData[0x01F0])
{
case 'J': value |= 0x00; break;
@ -21,7 +21,7 @@
case '4': value |= 0x80; break;
default: value |= 0x80; break;
}
value |= 1; // US
//value |= 1; // US
return value;
}
return 0xFF;

View File

@ -1,6 +1,6 @@
namespace BizHawk.Emulation.Consoles.Sega
{
public partial class Genesis
partial class Genesis
{
public static readonly ControllerDefinition GenesisController = new ControllerDefinition
{

View File

@ -2,17 +2,9 @@
namespace BizHawk.Emulation.Consoles.Sega
{
public partial class Genesis
partial class Genesis
{
private byte ReadByte(uint address) { return (byte) ReadB((int)address); }
private ushort ReadWord(uint address) { return (ushort) ReadW((int)address); }
private uint ReadLong(uint address) { return (uint) ReadL((int)address); }
private void WriteByte(uint address, byte value) { WriteB((int)address, (sbyte)value); }
private void WriteWord(uint address, ushort value) { WriteW((int)address, (short)value); }
private void WriteLong(uint address, uint value) { WriteL((int)address, (int) value); }
public sbyte ReadB(int address)
public sbyte ReadByte(int address)
{
address &= 0x00FFFFFF;
@ -47,7 +39,7 @@ namespace BizHawk.Emulation.Consoles.Sega
return 0x7D;
}
public short ReadW(int address)
public short ReadWord(int address)
{
address &= 0x00FFFFFF;
@ -70,7 +62,7 @@ namespace BizHawk.Emulation.Consoles.Sega
return 0x7DCD;
}
public int ReadL(int address)
public int ReadLong(int address)
{
address &= 0x00FFFFFF;
@ -90,13 +82,13 @@ namespace BizHawk.Emulation.Consoles.Sega
return 0x7DCDCDCD;
}
public void WriteB(int address, sbyte value)
public void WriteByte(int address, sbyte value)
{
address &= 0x00FFFFFF;
if (address >= 0xE00000) // Work RAM
{
Console.WriteLine("MEM[{0:X4}] change from {1:X2} to {2:X2}", address & 0xFFFF, Ram[address & 0xFFFF], value);
//Console.WriteLine("MEM[{0:X4}] change from {1:X2} to {2:X2}", address & 0xFFFF, Ram[address & 0xFFFF], value);
Ram[address & 0xFFFF] = (byte)value;
return;
}
@ -145,7 +137,7 @@ namespace BizHawk.Emulation.Consoles.Sega
Console.WriteLine("UNHANDLED WRITEB {0:X6}:{1:X2}", address, value);
}
public void WriteW(int address, short value)
public void WriteWord(int address, short value)
{
address &= 0x00FFFFFF;
@ -187,7 +179,7 @@ namespace BizHawk.Emulation.Consoles.Sega
Console.WriteLine("UNHANDLED WRITEW {0:X6}:{1:X4}", address, value);
}
public void WriteL(int address, int value)
public void WriteLong(int address, int value)
{
address &= 0x00FFFFFF;
@ -202,8 +194,8 @@ namespace BizHawk.Emulation.Consoles.Sega
}
if (address >= 0xC00000)
{
WriteW(address, (short)(value >> 16));
WriteW(address, (short)value);
WriteWord(address, (short)(value >> 16));
WriteWord(address, (short)value);
return;
}

View File

@ -2,7 +2,7 @@
namespace BizHawk.Emulation.Consoles.Sega
{
public partial class Genesis
partial class Genesis
{
private int BankRegion;
@ -21,7 +21,7 @@ namespace BizHawk.Emulation.Consoles.Sega
if (address >= 0x8000)
{
// 68000 Bank region
return (byte) ReadB(BankRegion | (address & 0x7FFF));
return (byte) ReadByte(BankRegion | (address & 0x7FFF));
}
Console.WriteLine("UNHANDLED Z80 READ {0:X4}",address);
return 0xCD;
@ -51,7 +51,7 @@ namespace BizHawk.Emulation.Consoles.Sega
}
if (address >= 0x8000)
{
WriteB(BankRegion | (address & 0x7FFF), (sbyte) value);
WriteByte(BankRegion | (address & 0x7FFF), (sbyte) value);
return;
}
Console.WriteLine("UNHANDLED Z80 WRITE {0:X4}:{1:X2}", address, value);

View File

@ -10,7 +10,7 @@
public void Write(int addr, byte value)
{
System.Console.WriteLine("YM2612: {0:X2} -> {1:X2}", addr, value);
//System.Console.WriteLine("YM2612: {0:X2} -> {1:X2}", addr, value);
}
public void Reset()