twoapple-reboot/test/d6502/opcodes.d

327 lines
8.5 KiB
D

module test.d6502.opcodes;
import test.d6502.cpu;
// 2-cycle opcodes which neither read nor write.
template REG_OPS(T)
if (isCpu!T)
{
static if (isNMOS!T)
enum REG_OPS = cast(ubyte[])
x"0A 18 1A 2A 38 3A 4A 58 5A 6A 78 7A 88 8A 98 9A
A8 AA B8 BA C8 CA D8 DA E8 EA F8 FA";
else
enum REG_OPS = cast(ubyte[])
x"0A 18 1A 2A 38 3A 4A 58 6A 78 88 8A 98 9A A8 AA
B8 BA C8 CA D8 E8 EA F8";
}
// Opcodes which push to the stack.
template PUSH_OPS(T)
if (isCpu!T)
{
static if (isNMOS!T)
enum PUSH_OPS = cast(ubyte[])x"08 48";
else
enum PUSH_OPS = cast(ubyte[])x"08 48 5A DA";
}
// Opcodes which pull from the stack.
template PULL_OPS(T)
if (isCpu!T)
{
static if (isNMOS!T)
enum PULL_OPS = cast(ubyte[])x"28 68";
else
enum PULL_OPS = cast(ubyte[])x"28 68 7A FA";
}
// Relative branch opcodes.
template BRANCH_OPS(T)
if (isCpu!T)
{
static if (isNMOS!T)
enum BRANCH_OPS = cast(ubyte[])x"10 30 50 70 90 B0 D0 F0";
else
enum BRANCH_OPS = cast(ubyte[])x"10 30 50 70 80 90 B0 D0 F0";
}
// Write-only opcodes.
template WRITE_OPS(T)
if (isCpu!T)
{
static if (isNMOS!T)
enum WRITE_OPS = cast(ubyte[])x"81 83 84 85 86 87 8C 8D 8E 8F
91 93 94 95 96 97 99 9B 9C 9D 9E 9F";
else
enum WRITE_OPS = cast(ubyte[])x"64 74 81 84 85 86 8C 8D 8E
91 92 94 95 96 99 9C 9D 9E";
}
// Read-only opcodes (excluding ADC/SBC).
template READ_OPS(T)
if (isCpu!T)
{
static if (isNMOS!T)
enum READ_OPS = cast(ubyte[])
x"01 04 05 09 0B 0C 0D 11 14 15 19 1C 1D
21 24 25 29 2B 2C 2D 31 34 35 39 3C 3D
41 44 45 49 4B 4D 51 54 55 59 5C 5D
64 6B 74 7C 82 89 8B
A0 A1 A2 A3 A4 A5 A6 A7 A9 AB AC AD AE AF
B1 B3 B4 B5 B6 B7 B9 BB BC BD BE BF
C0 C1 C2 C4 C5 C9 CB CC CD D1 D4 D5 D9 DC DD
E0 E2 E4 EC F4 FC";
else
enum READ_OPS = cast(ubyte[])
x"01 02 05 09 0D 11 12 15 19 1D
21 22 24 25 29 2C 2D 31 32 34 35 39 3C 3D
41 42 44 45 49 4D 51 52 54 55 59 5D 62 82 89
A0 A1 A2 A4 A5 A6 A9 AC AD AE
B2 B1 B4 B5 B6 B9 BC BD BE
C0 C1 C2 C4 C5 C9 CC CD D1 D2 D4 D5 D9 DC DD
E0 E2 E4 EC F4 FC";
}
// Opcodes affected by decimal mode (ADC/SBC).
template BCD_OPS(T)
if (isCpu!T)
{
static if (isNMOS!T)
enum BCD_OPS = cast(ubyte[])x"61 65 69 6B 6D 71 75 79 7D
E1 E5 E9 EB ED F1 F5 F9 FD";
else
enum BCD_OPS = cast(ubyte[])x"61 65 69 6D 71 72 75 79 7D
E1 E5 E9 ED F1 F2 F5 F9 FD";
}
// Opcodes which both read and write.
template RMW_OPS(T)
if (isCpu!T)
{
static if (isNMOS!T)
enum RMW_OPS = cast(ubyte[])
x"03 06 07 0E 0F 13 16 17 1B 1E 1F
23 26 27 2E 2F 33 36 37 3B 3E 3F
43 46 47 4E 4F 53 56 57 5B 5E 5F
63 66 67 6E 6F 73 76 77 7B 7E 7F
C3 C6 C7 CE CF D3 D6 D7 DB DE DF
E3 E6 E7 EE EF F3 F6 F7 FB FE FF";
else
enum RMW_OPS = cast(ubyte[])
x"04 06 0C 0E 14 16 1C 1E 26 2E 36 3E 46 4E 56 5E
66 6E 76 7E C6 CE D6 DE E6 EE F6 FE";
}
// Opcodes with immediate address mode.
template IMM_OPS(T)
if (isCpu!T)
{
static if (isNMOS!T)
enum IMM_OPS = cast(ubyte[])x"09 0B 29 2B 49 4B 69 6B
80 82 89 8B A0 A2 A9 AB
C0 C2 C9 CB E0 E2 E9 EB";
else
enum IMM_OPS = cast(ubyte[])x"02 09 22 29 42 49 62 69 82
89 A0 A2 A9 C0 C2 C9 E0 E2 E9";
}
// Opcodes with zeropage address mode.
template ZPG_OPS(T)
if (isCpu!T)
{
static if (isNMOS!T)
enum ZPG_OPS = cast(ubyte[])x"04 05 06 07 24 25 26 27
44 45 46 47 64 65 66 67
84 85 86 87 A4 A5 A6 A7
C4 C5 C6 C7 E4 E5 E6 E7";
else
enum ZPG_OPS = cast(ubyte[])x"04 05 06 14 24 25 26 44 45 46 64 65 66
84 85 86 A4 A5 A6 C4 C5 C6 E4 E5 E6";
}
// Opcodes with zeropage,x address mode.
template ZPX_OPS(T)
if (isCpu!T)
{
static if (isNMOS!T)
enum ZPX_OPS = cast(ubyte[])x"14 15 16 17 34 35 36 37
54 55 56 57 74 75 76 77
94 95 B4 B5 D4 D5 D6 D7
F4 F5 F6 F7";
else
enum ZPX_OPS = cast(ubyte[])x"15 16 34 35 36 54 55 56 74 75 76
94 95 B4 B5 D4 D5 D6 F4 F5 F6";
}
// Opcodes with zeropage,y address mode.
template ZPY_OPS(T)
if (isCpu!T)
{
static if (isNMOS!T)
enum ZPY_OPS = cast(ubyte[])x"96 97 B6 B7";
else
enum ZPY_OPS = cast(ubyte[])x"96 B6";
}
// Opcodes with absolute address mode.
template ABS_OPS(T)
if (isCpu!T)
{
static if (isNMOS!T)
enum ABS_OPS = cast(ubyte[])x"0C 0D 0E 0F 2C 2D 2E 2F
4C 4D 4E 4F 6D 6E 6F
8C 8D 8E 8F AC AD AE AF
CC CD CE CF EC ED EE EF";
else
enum ABS_OPS = cast(ubyte[])x"0C 0D 0E 1C 2C 2D 2E 4C 4D 4E 6D 6E
8C 8D 8E 9C AC AD AE CC CD CE EC ED EE";
}
// Opcodes with absolute,x address mode.
template ABX_OPS(T)
if (isCpu!T)
{
static if (isNMOS!T)
enum ABX_OPS = cast(ubyte[])x"1C 1D 1E 1F 3C 3D 3E 3F
5C 5D 5E 5F 7C 7D 7E 7F
9C 9D BC BD DC DD DE DF
FC FD FE FF";
else
enum ABX_OPS = cast(ubyte[])x"1D 1E 3C 3D 3E 5D 5E 7D 7E
9D 9E BC BD DC DD DE FC FD FE";
}
// Opcodes with absolute,y address mode.
template ABY_OPS(T)
if (isCpu!T)
{
static if (isNMOS!T)
enum ABY_OPS = cast(ubyte[])x"19 1B 39 3B 59 5B 79 7B
99 9B 9E 9F B9 BB BE BF
D9 DB F9 FB";
else
enum ABY_OPS = cast(ubyte[])x"19 39 59 79 99 B9 BE D9 F9";
}
// Opcodes with indirect zeropage,x address mode.
template IZX_OPS(T)
if (isCpu!T)
{
static if (isNMOS!T)
enum IZX_OPS = cast(ubyte[])x"01 03 21 23 41 43 61 63
81 83 A1 A3 C1 C3 E1 E3";
else
enum IZX_OPS = cast(ubyte[])x"01 21 41 61 81 A1 C1 E1";
}
// Opcodes with indirect zeropage,y address mode.
template IZY_OPS(T)
if (isCpu!T)
{
static if (isNMOS!T)
enum IZY_OPS = cast(ubyte[])x"11 13 31 33 51 53 71 73
91 93 B1 B3 D1 D3 F1 F3";
else
enum IZY_OPS = cast(ubyte[])x"11 31 51 71 91 B1 D1 F1";
}
// Opcodes with indirect zeropage address mode.
template ZPI_OPS(T)
if (isCpu!T && isCMOS!T)
{
enum ZPI_OPS = cast(ubyte[])x"12 32 52 72 92 B2 D2 F2";
}
// 1-cycle NOPS.
template NOP1_OPS(T)
if (isCpu!T && isCMOS!T)
{
enum NOP1_OPS = cast(ubyte[])
x"03 13 23 33 43 53 63 73 83 93 A3 B3 C3 D3 E3 F3
07 17 27 37 47 57 67 77 87 97 A7 B7 C7 D7 E7 F7
0B 1B 2B 3B 4B 5B 6B 7B 8B 9B AB BB CB DB EB FB
0F 1F 2F 3F 4F 5F 6F 7F 8F 9F AF BF CF DF EF FF";
}
// NMOS HLT opcodes.
template HLT_OPS(T)
if (isCpu!T && isNMOS!T)
{
enum HLT_OPS = cast(ubyte[])x"02 12 22 32 42 52 62 72 92 B2 D2 F2";
}
// Opcodes which decrement a register.
template OPS_DEC_REG(T)
if (isCpu!T)
{
static if (isNMOS!T)
enum OPS_DEC_REG = cast(ubyte[])x"88 CA";
else
enum OPS_DEC_REG = cast(ubyte[])x"3A 88 CA";
}
// Opcodes which increment a register.
template OPS_INC_REG(T)
if (isCpu!T)
{
static if (isNMOS!T)
enum OPS_INC_REG = cast(ubyte[])x"C8 E8";
else
enum OPS_INC_REG = cast(ubyte[])x"1A C8 E8";
}
// Opcodes which decrement a memory location.
template OPS_DEC(T)
if (isCpu!T)
{
enum OPS_DEC = cast(ubyte[])x"C6 CE D6 DE";
}
// Opcodes which increment a memory location.
template OPS_INC(T)
if (isCpu!T)
{
enum OPS_INC = cast(ubyte[])x"E6 EE F6 FE";
}
// Opcodes which rotate a value left.
template OPS_ROL(T)
if (isCpu!T)
{
enum OPS_ROL = cast(ubyte[])x"26 2A 2E 36 3E";
}
// Opcodes which shift a value left.
template OPS_ASL(T)
if (isCpu!T)
{
enum OPS_ASL = cast(ubyte[])x"06 0A 0E 16 1E";
}