Skip to content

Commit c94fb70

Browse files
committed
Support Z80-specific main opcodes and ED-prefixed opcodes.
1 parent 4912348 commit c94fb70

9 files changed

+170
-24
lines changed

Archs/Z80/CZ80Instruction.cpp

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ bool CZ80Instruction::Validate(const ValidateState& state)
1919

2020
Vars.Length = Opcode.length;
2121
Vars.Encoding = Opcode.encoding;
22-
Vars.WritePrefix = Opcode.flags & Z80_PREFIX_CB;
2322
Vars.WriteImmediate8 = false;
2423
Vars.WriteImmediate16 = false;
2524

@@ -52,32 +51,34 @@ bool CZ80Instruction::Validate(const ValidateState& state)
5251

5352
int64_t min = INT64_MIN;
5453
int64_t max = INT64_MAX;
55-
if (Opcode.flags & Z80_IMMEDIATE_U3)
54+
Vars.WriteImmediate8 = false;
55+
Vars.WriteImmediate16 = false;
56+
if (Opcode.flags & Z80_INTERRUPT_MODE)
57+
{
58+
min = 0;
59+
max = 2;
60+
}
61+
else if (Opcode.flags & Z80_IMMEDIATE_U3)
5662
{
5763
min = 0;
5864
max = 8;
59-
Vars.WriteImmediate8 = false;
60-
Vars.WriteImmediate16 = false;
6165
}
62-
if (Opcode.flags & Z80_IMMEDIATE_U8)
66+
else if (Opcode.flags & Z80_IMMEDIATE_U8)
6367
{
6468
min = 0;
6569
max = 255;
6670
Vars.WriteImmediate8 = true;
67-
Vars.WriteImmediate16 = false;
6871
}
6972
else if (Opcode.flags & Z80_IMMEDIATE_S8)
7073
{
7174
min = -128;
7275
max = 127;
7376
Vars.WriteImmediate8 = true;
74-
Vars.WriteImmediate16 = false;
7577
}
7678
else if (Opcode.flags & Z80_IMMEDIATE_U16)
7779
{
7880
min = 0;
7981
max = 65535;
80-
Vars.WriteImmediate8 = false;
8182
Vars.WriteImmediate16 = true;
8283
}
8384

@@ -93,7 +94,7 @@ bool CZ80Instruction::Validate(const ValidateState& state)
9394
Vars.Immediate = -Vars.Immediate;
9495
}
9596

96-
if (Z80.GetVersion() == ZARCH_GAMEBOY)
97+
if (Z80.GetVersion() == Z80ArchType::Gameboy)
9798
{
9899
// Special loads in range 0xFF00 - 0xFFFF
99100
if (Vars.RightParam.num == Z80_REG8_A && Vars.Immediate >= 0xFF00 && !(Opcode.flags & Z80_IMMEDIATE_U3))
@@ -124,12 +125,17 @@ bool CZ80Instruction::Validate(const ValidateState& state)
124125
{
125126
Logger::queueError(Logger::Error, L"Jump target %04X out of range", Vars.Immediate);
126127
}
128+
else if (Opcode.flags & Z80_INTERRUPT_MODE)
129+
{
130+
Logger::queueError(Logger::Error, L"Interrupt mode %i out of range", Vars.Immediate);
131+
}
127132
else
128133
{
129134
Logger::queueError(Logger::Error, L"Immediate %i out of range", Vars.Immediate);
130135
}
131136
return false;
132137
}
138+
133139
if (Opcode.flags & Z80_RST)
134140
{
135141
if (Vars.Immediate >= 0x00 && Vars.Immediate <= 0x7)
@@ -152,6 +158,11 @@ bool CZ80Instruction::Validate(const ValidateState& state)
152158
Vars.LeftParam.name = L"imm";
153159
Vars.LeftParam.num = Vars.Immediate;
154160
}
161+
else if (Opcode.flags & Z80_INTERRUPT_MODE)
162+
{
163+
Vars.LeftParam.name = L"imm";
164+
Vars.LeftParam.num = Vars.Immediate + (Vars.Immediate != 0 ? 1 : 0);
165+
}
155166
}
156167

157168
g_fileManager->advanceMemory(Vars.Length);
@@ -163,10 +174,14 @@ void CZ80Instruction::Encode() const
163174
{
164175
unsigned char encoding = Vars.Encoding;
165176

166-
if (Vars.WritePrefix)
177+
if (Opcode.flags & Z80_PREFIX_CB)
167178
{
168179
g_fileManager->writeU8(0xCB);
169180
}
181+
if (Opcode.flags & Z80_PREFIX_ED)
182+
{
183+
g_fileManager->writeU8(0xED);
184+
}
170185

171186
if (Opcode.lhs && Opcode.lhsShift >= 0)
172187
{

Archs/Z80/CZ80Instruction.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ struct Z80OpcodeVariables
1313
unsigned char Length;
1414
unsigned char Encoding;
1515
bool IsNegative : 1;
16-
bool WritePrefix : 1;
1716
bool WriteImmediate8 : 1;
1817
bool WriteImmediate16 : 1;
1918
};

Archs/Z80/Z80.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#include "Core/ELF/ElfRelocator.h"
55
#include "Core/Expression.h"
66

7-
enum Z80ArchType { ZARCH_Z80 = 0, ZARCH_GAMEBOY, ZARCH_INVALID };
7+
enum class Z80ArchType { Z80 = 0, Gameboy, Invalid };
88

99
struct Z80RegisterValue
1010
{
@@ -26,6 +26,15 @@ class CZ80Architecture: public CArchitecture
2626
virtual Endianness getEndianness() { return Endianness::Little; };
2727
void SetVersion(Z80ArchType v) { Version = v; };
2828
Z80ArchType GetVersion() { return Version; };
29+
const std::wstring GetName() {
30+
switch (Version)
31+
{
32+
case Z80ArchType::Gameboy:
33+
return L"Gameboy";
34+
default:
35+
return L"Z80";
36+
}
37+
}
2938
private:
3039
Z80ArchType Version;
3140
};

Archs/Z80/Z80Opcodes.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,20 @@ const tZ80Opcode Z80Opcodes[] = {
1414
{ L"ld", 1, 0x22, Z80_PARAM_HLI_HLD, Z80_PARAM_A, 4, -1, Z80_GAMEBOY },
1515
{ L"ld", 1, 0x2A, Z80_PARAM_A, Z80_PARAM_HLI_HLD, -1, 4, Z80_GAMEBOY },
1616
{ L"ld", 1, 0xE2, Z80_PARAM_FF00_C, Z80_PARAM_A, -1, -1, Z80_GAMEBOY },
17+
{ L"ld", 2, 0x57, Z80_PARAM_A, Z80_PARAM_IR, -1, 3, Z80_Z80 | Z80_PREFIX_ED },
1718
{ L"ld", 1, 0xF2, Z80_PARAM_A, Z80_PARAM_FF00_C, -1, -1, Z80_GAMEBOY },
1819
{ L"ld", 1, 0xF9, Z80_PARAM_SP, Z80_PARAM_HL, -1, -1, 0 },
1920
{ L"ld", 2, 0xF8, Z80_PARAM_HL, Z80_PARAM_SP_IMM, -1, -1, Z80_IMMEDIATE_S8 | Z80_GAMEBOY },
21+
{ L"ld", 3, 0x2A, Z80_PARAM_HL, Z80_PARAM_MEMIMMEDIATE, -1, -1, Z80_IMMEDIATE_U16 | Z80_Z80 },
22+
{ L"ld", 4, 0x4B, Z80_PARAM_REG16_SP, Z80_PARAM_MEMIMMEDIATE, 4, -1, Z80_IMMEDIATE_U16 | Z80_Z80 | Z80_PREFIX_ED },
23+
{ L"ld", 3, 0x3A, Z80_PARAM_A, Z80_PARAM_MEMIMMEDIATE, -1, -1, Z80_IMMEDIATE_U16 | Z80_Z80 },
2024
{ L"ld", 3, 0xFA, Z80_PARAM_A, Z80_PARAM_MEMIMMEDIATE, -1, -1, Z80_IMMEDIATE_U16 | Z80_GAMEBOY },
2125
{ L"ld", 2, 0x06, Z80_PARAM_REG8_MEMHL, Z80_PARAM_IMMEDIATE, 3, -1, Z80_IMMEDIATE_U8 },
2226
{ L"ld", 3, 0x01, Z80_PARAM_REG16_SP, Z80_PARAM_IMMEDIATE, 4, -1, Z80_IMMEDIATE_U16 },
27+
{ L"ld", 2, 0x47, Z80_PARAM_IR, Z80_PARAM_A, 3, -1, Z80_Z80 | Z80_PREFIX_ED },
28+
{ L"ld", 3, 0x22, Z80_PARAM_MEMIMMEDIATE, Z80_PARAM_HL, -1, -1, Z80_IMMEDIATE_U16 | Z80_Z80 },
29+
{ L"ld", 4, 0x43, Z80_PARAM_MEMIMMEDIATE, Z80_PARAM_REG16_SP, -1, 4, Z80_IMMEDIATE_U16 | Z80_Z80 | Z80_PREFIX_ED },
30+
{ L"ld", 3, 0x32, Z80_PARAM_MEMIMMEDIATE, Z80_PARAM_A, -1, -1, Z80_IMMEDIATE_U16 | Z80_Z80 },
2331
{ L"ld", 3, 0x08, Z80_PARAM_MEMIMMEDIATE, Z80_PARAM_SP, -1, -1, Z80_IMMEDIATE_U16 | Z80_GAMEBOY },
2432
{ L"ld", 3, 0xEA, Z80_PARAM_MEMIMMEDIATE, Z80_PARAM_A, -1, -1, Z80_IMMEDIATE_U16 | Z80_GAMEBOY },
2533
{ L"ldi", 1, 0x22, Z80_PARAM_MEMHL, Z80_PARAM_A, -1, -1, Z80_GAMEBOY },
@@ -37,11 +45,13 @@ const tZ80Opcode Z80Opcodes[] = {
3745
{ L"add", 2, 0xE8, Z80_PARAM_SP, Z80_PARAM_IMMEDIATE, -1, -1, Z80_IMMEDIATE_S8 | Z80_GAMEBOY },
3846
{ L"adc", 1, 0x88, Z80_PARAM_A, Z80_PARAM_REG8_MEMHL, -1, 0, 0 },
3947
{ L"adc", 2, 0xCE, Z80_PARAM_A, Z80_PARAM_IMMEDIATE, -1, -1, Z80_IMMEDIATE_U8 | Z80_ADD_SUB_IMMEDIATE },
48+
{ L"adc", 2, 0x4A, Z80_PARAM_HL, Z80_PARAM_REG16_SP, -1, 4, Z80_Z80 | Z80_PREFIX_ED },
4049
{ L"sub", 1, 0x90, Z80_PARAM_A, Z80_PARAM_REG8_MEMHL, -1, 0, 0 },
4150
{ L"sub", 2, 0xD6, Z80_PARAM_A, Z80_PARAM_IMMEDIATE, -1, -1, Z80_IMMEDIATE_U8 | Z80_ADD_SUB_IMMEDIATE },
4251
{ L"sub", 2, 0xE8, Z80_PARAM_SP, Z80_PARAM_IMMEDIATE, -1, -1, Z80_IMMEDIATE_S8 | Z80_NEGATE_IMM | Z80_GAMEBOY },
4352
{ L"sbc", 1, 0x98, Z80_PARAM_A, Z80_PARAM_REG8_MEMHL, -1, 0, 0 },
4453
{ L"sbc", 2, 0xDE, Z80_PARAM_A, Z80_PARAM_IMMEDIATE, -1, -1, Z80_IMMEDIATE_U8 | Z80_ADD_SUB_IMMEDIATE },
54+
{ L"sbc", 2, 0x42, Z80_PARAM_HL, Z80_PARAM_REG16_SP, -1, 4, Z80_Z80 | Z80_PREFIX_ED },
4555
{ L"and", 1, 0xA0, Z80_PARAM_A, Z80_PARAM_REG8_MEMHL, -1, 0, 0 },
4656
{ L"and", 2, 0xE6, Z80_PARAM_A, Z80_PARAM_IMMEDIATE, -1, -1, Z80_IMMEDIATE_U8 },
4757
{ L"xor", 1, 0xA8, Z80_PARAM_A, Z80_PARAM_REG8_MEMHL, -1, 0, 0 },
@@ -88,5 +98,35 @@ const tZ80Opcode Z80Opcodes[] = {
8898
{ L"ret", 1, 0xC9, Z80_PARAM_NONE, Z80_PARAM_NONE, -1, -1, 0 },
8999
{ L"reti", 1, 0xD9, Z80_PARAM_NONE, Z80_PARAM_NONE, -1, -1, Z80_GAMEBOY },
90100
{ L"rst", 1, 0xC7, Z80_PARAM_IMMEDIATE, Z80_PARAM_NONE, 0, -1, Z80_RST },
101+
{ L"ex", 1, 0x08, Z80_PARAM_AF, Z80_PARAM_AF_PRIME, -1, -1, Z80_Z80 },
102+
{ L"ex", 1, 0xE3, Z80_PARAM_MEMSP, Z80_PARAM_HL, -1, -1, Z80_Z80 },
103+
{ L"ex", 1, 0xEB, Z80_PARAM_DE, Z80_PARAM_HL, -1, -1, Z80_Z80 },
104+
{ L"exx", 1, 0xD9, Z80_PARAM_NONE, Z80_PARAM_NONE, -1, -1, Z80_Z80 },
105+
{ L"djnz", 2, 0x10, Z80_PARAM_IMMEDIATE, Z80_PARAM_NONE, -1, -1, Z80_Z80 | Z80_IMMEDIATE_S8 | Z80_JUMP_RELATIVE },
106+
{ L"out", 2, 0x41, Z80_PARAM_MEMC, Z80_PARAM_REG8, -1, 3, Z80_Z80 | Z80_PREFIX_ED },
107+
{ L"out", 2, 0xD3, Z80_PARAM_MEMIMMEDIATE, Z80_PARAM_A, -1, -1, Z80_Z80 | Z80_IMMEDIATE_U8 },
108+
{ L"in", 2, 0x40, Z80_PARAM_REG8, Z80_PARAM_MEMC, 3, -1, Z80_Z80 | Z80_PREFIX_ED },
109+
{ L"in", 2, 0xDB, Z80_PARAM_A, Z80_PARAM_MEMIMMEDIATE, -1, -1, Z80_Z80 | Z80_IMMEDIATE_U8 },
110+
{ L"neg", 2, 0x44, Z80_PARAM_NONE, Z80_PARAM_NONE, -1, -1, Z80_Z80 | Z80_PREFIX_ED },
111+
{ L"retn", 2, 0x45, Z80_PARAM_NONE, Z80_PARAM_NONE, -1, -1, Z80_Z80 | Z80_PREFIX_ED },
112+
{ L"im", 2, 0x46, Z80_PARAM_IMMEDIATE, Z80_PARAM_NONE, 3, -1, Z80_Z80 | Z80_PREFIX_ED | Z80_INTERRUPT_MODE },
113+
{ L"rrd", 2, 0x67, Z80_PARAM_NONE, Z80_PARAM_NONE, -1, -1, Z80_Z80 | Z80_PREFIX_ED },
114+
{ L"rld", 2, 0x6F, Z80_PARAM_NONE, Z80_PARAM_NONE, -1, -1, Z80_Z80 | Z80_PREFIX_ED },
115+
{ L"ldi", 2, 0xA0, Z80_PARAM_NONE, Z80_PARAM_NONE, -1, -1, Z80_Z80 | Z80_PREFIX_ED },
116+
{ L"cpi", 2, 0xA1, Z80_PARAM_NONE, Z80_PARAM_NONE, -1, -1, Z80_Z80 | Z80_PREFIX_ED },
117+
{ L"ini", 2, 0xA2, Z80_PARAM_NONE, Z80_PARAM_NONE, -1, -1, Z80_Z80 | Z80_PREFIX_ED },
118+
{ L"outi", 2, 0xA3, Z80_PARAM_NONE, Z80_PARAM_NONE, -1, -1, Z80_Z80 | Z80_PREFIX_ED },
119+
{ L"ldd", 2, 0xA8, Z80_PARAM_NONE, Z80_PARAM_NONE, -1, -1, Z80_Z80 | Z80_PREFIX_ED },
120+
{ L"cpd", 2, 0xA9, Z80_PARAM_NONE, Z80_PARAM_NONE, -1, -1, Z80_Z80 | Z80_PREFIX_ED },
121+
{ L"ind", 2, 0xAA, Z80_PARAM_NONE, Z80_PARAM_NONE, -1, -1, Z80_Z80 | Z80_PREFIX_ED },
122+
{ L"outd", 2, 0xAB, Z80_PARAM_NONE, Z80_PARAM_NONE, -1, -1, Z80_Z80 | Z80_PREFIX_ED },
123+
{ L"ldir", 2, 0xB0, Z80_PARAM_NONE, Z80_PARAM_NONE, -1, -1, Z80_Z80 | Z80_PREFIX_ED },
124+
{ L"cpir", 2, 0xB1, Z80_PARAM_NONE, Z80_PARAM_NONE, -1, -1, Z80_Z80 | Z80_PREFIX_ED },
125+
{ L"inir", 2, 0xB2, Z80_PARAM_NONE, Z80_PARAM_NONE, -1, -1, Z80_Z80 | Z80_PREFIX_ED },
126+
{ L"otir", 2, 0xB3, Z80_PARAM_NONE, Z80_PARAM_NONE, -1, -1, Z80_Z80 | Z80_PREFIX_ED },
127+
{ L"lddr", 2, 0xB8, Z80_PARAM_NONE, Z80_PARAM_NONE, -1, -1, Z80_Z80 | Z80_PREFIX_ED },
128+
{ L"cpdr", 2, 0xB9, Z80_PARAM_NONE, Z80_PARAM_NONE, -1, -1, Z80_Z80 | Z80_PREFIX_ED },
129+
{ L"indr", 2, 0xBA, Z80_PARAM_NONE, Z80_PARAM_NONE, -1, -1, Z80_Z80 | Z80_PREFIX_ED },
130+
{ L"otdr", 2, 0xBB, Z80_PARAM_NONE, Z80_PARAM_NONE, -1, -1, Z80_Z80 | Z80_PREFIX_ED },
91131
{ nullptr, 0, 0x00, Z80_PARAM_NONE, Z80_PARAM_NONE, -1, -1, 0 },
92132
};

Archs/Z80/Z80Opcodes.h

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@
1515
#define Z80_PARAM_FF00_C 0x0C // (0xFF00+c)
1616
#define Z80_PARAM_SP_IMM 0x0D // sp+s8
1717
#define Z80_PARAM_CONDITION 0x0E // nz, z, nc, c
18+
#define Z80_PARAM_AF 0x0F // af
19+
#define Z80_PARAM_AF_PRIME 0x10 // af'
20+
#define Z80_PARAM_MEMSP 0x11 // (sp)
21+
#define Z80_PARAM_DE 0x12 // de
22+
#define Z80_PARAM_REG8 0x13 // b, c, d, e, h, l, a
23+
#define Z80_PARAM_MEMC 0x14 // (c)
24+
#define Z80_PARAM_BC_DE_SP 0x15 // bc, de, sp
25+
#define Z80_PARAM_IR 0x16 // i, r
1826

1927
#define Z80_REG8_B 0x00 // b
2028
#define Z80_REG8_C 0x01 // c
@@ -42,6 +50,20 @@
4250
#define Z80_COND_Z 0x01 // z
4351
#define Z80_COND_NC 0x02 // nc
4452
#define Z80_COND_C 0x03 // c
53+
#define Z80_COND_PO 0x04 // po
54+
#define Z80_COND_PE 0x05 // pe
55+
#define Z80_COND_P 0x06 // p
56+
#define Z80_COND_M 0x07 // m
57+
#define Z80_COND_BIT_ALL ( Z80_REG_BIT(Z80_COND_NZ) | Z80_REG_BIT(Z80_COND_Z) \
58+
| Z80_REG_BIT(Z80_COND_NC) | Z80_REG_BIT(Z80_COND_C) \
59+
| Z80_REG_BIT(Z80_COND_PO) | Z80_REG_BIT(Z80_COND_PE) \
60+
| Z80_REG_BIT(Z80_COND_P) | Z80_REG_BIT(Z80_COND_M) )
61+
#define Z80_COND_BIT_GB ( Z80_REG_BIT(Z80_COND_NZ) | Z80_REG_BIT(Z80_COND_Z) \
62+
| Z80_REG_BIT(Z80_COND_NC) | Z80_REG_BIT(Z80_COND_C) )
63+
64+
#define Z80_REG_I 0x00 // i
65+
#define Z80_REG_R 0x01 // r
66+
#define Z80_REG_IR_ALL ( Z80_REG_BIT(Z80_REG_I) | Z80_REG_BIT(Z80_REG_R) )
4567

4668
#define Z80_REG_BIT_ALL 0xFFFFFFFF
4769

@@ -57,9 +79,13 @@
5779
#define Z80_NEGATE_IMM 0x00000200
5880
#define Z80_JUMP_RELATIVE 0x00000400
5981
#define Z80_GAMEBOY 0x00000800
82+
#define Z80_Z80 0x00001000
83+
#define Z80_PREFIX_ED 0x00002000
84+
#define Z80_INTERRUPT_MODE 0x00004000
6085

6186
#define Z80_HAS_IMMEDIATE ( Z80_IMMEDIATE_U3 | Z80_IMMEDIATE_U8 | Z80_IMMEDIATE_S8 \
62-
| Z80_IMMEDIATE_U16 | Z80_RST | Z80_JUMP_RELATIVE )
87+
| Z80_IMMEDIATE_U16 | Z80_RST | Z80_JUMP_RELATIVE \
88+
| Z80_INTERRUPT_MODE )
6389

6490
#define Z80_REG_BIT(reg) (1 << reg)
6591

@@ -68,8 +94,8 @@ struct tZ80Opcode
6894
const wchar_t* name;
6995
unsigned char length;
7096
unsigned char encoding;
71-
unsigned char lhs : 4;
72-
unsigned char rhs : 4;
97+
unsigned char lhs;
98+
unsigned char rhs;
7399
char lhsShift : 4;
74100
char rhsShift : 4;
75101
int flags;

Archs/Z80/Z80Parser.cpp

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,14 @@ const Z80RegisterDescriptor Z80HLIncDec16[] = {
3030
};
3131

3232
const Z80RegisterDescriptor Z80Conds[] = {
33-
{ L"nz", Z80_COND_NZ }, { L"z", Z80_COND_Z },
34-
{ L"nc", Z80_COND_NC }, { L"c", Z80_COND_C },
33+
{ L"nz", Z80_COND_NZ }, { L"z", Z80_COND_Z },
34+
{ L"nc", Z80_COND_NC }, { L"c", Z80_COND_C },
35+
{ L"po", Z80_COND_PO }, { L"pe", Z80_COND_PE },
36+
{ L"p", Z80_COND_P }, { L"m", Z80_COND_M },
37+
};
38+
39+
const Z80RegisterDescriptor Z80RegsIR[] = {
40+
{ L"i", Z80_REG_I }, { L"r", Z80_REG_R },
3541
};
3642

3743
const DirectiveMap Z80Directives = { };
@@ -76,9 +82,29 @@ bool Z80Parser::parseRegister16AF(Parser& parser, Z80RegisterValue& dest, int al
7682
return parseRegisterTable(parser, dest, Z80Regs16AF, std::size(Z80Regs16AF), allowed);
7783
}
7884

85+
bool Z80Parser::parseRegisterIR(Parser& parser, Z80RegisterValue& dest)
86+
{
87+
return parseRegisterTable(parser, dest, Z80RegsIR, std::size(Z80RegsIR), Z80_REG_IR_ALL);
88+
}
89+
90+
bool Z80Parser::parseAFPrime(Parser& parser)
91+
{
92+
const Token &token = parser.nextToken();
93+
CHECK(token.type == TokenType::Identifier);
94+
CHECK(token.getStringValue() == L"af'");
95+
96+
return true;
97+
}
98+
7999
bool Z80Parser::parseCondition(Parser& parser, Z80RegisterValue& dest)
80100
{
81-
return parseRegisterTable(parser, dest, Z80Conds, std::size(Z80Conds), Z80_REG_BIT_ALL);
101+
int allowed = Z80_COND_BIT_ALL;
102+
if (Z80.GetVersion() == Z80ArchType::Gameboy)
103+
{
104+
allowed = Z80_COND_BIT_GB;
105+
}
106+
107+
return parseRegisterTable(parser, dest, Z80Conds, std::size(Z80Conds), allowed);
82108
}
83109

84110
bool Z80Parser::parseHLIncDec(Parser& parser, Z80RegisterValue& dest)
@@ -114,6 +140,15 @@ bool Z80Parser::parseHLIncDec(Parser& parser, Z80RegisterValue& dest)
114140
return true;
115141
}
116142

143+
bool Z80Parser::parseMemoryRegister8(Parser& parser, Z80RegisterValue& dest, int allowed)
144+
{
145+
CHECK(parser.matchToken(TokenType::LParen));
146+
CHECK(parseRegister8(parser, dest, allowed));
147+
CHECK(parser.matchToken(TokenType::RParen));
148+
149+
return true;
150+
}
151+
117152
bool Z80Parser::parseMemoryRegister16(Parser& parser, Z80RegisterValue& dest, int allowed)
118153
{
119154
CHECK(parser.matchToken(TokenType::LParen));
@@ -193,22 +228,38 @@ bool Z80Parser::parseOpcodeParameter(Parser& parser, unsigned char paramType, Z8
193228
return true;
194229
}
195230
return false;
231+
case Z80_PARAM_REG8:
232+
return parseRegister8(parser, destReg, Z80_REG8_BIT_ALL);
196233
case Z80_PARAM_REG16_SP:
197234
return parseRegister16SP(parser, destReg, Z80_REG16_BIT_ALL);
198235
case Z80_PARAM_REG16_AF:
199236
return parseRegister16AF(parser, destReg, Z80_REG16_BIT_ALL);
200237
case Z80_PARAM_A:
201238
return parseRegister8(parser, destReg, Z80_REG_BIT(Z80_REG8_A));
239+
case Z80_PARAM_MEMC:
240+
return parseMemoryRegister8(parser, destReg, Z80_REG_BIT(Z80_REG8_C));
202241
case Z80_PARAM_MEMBC_MEMDE:
203242
return parseMemoryRegister16(parser, destReg, Z80_REG_BIT(Z80_REG16_BC) | Z80_REG_BIT(Z80_REG16_DE));
204243
case Z80_PARAM_HL:
205244
return parseRegister16SP(parser, destReg, Z80_REG_BIT(Z80_REG16_HL));
206245
case Z80_PARAM_MEMHL:
207246
return parseMemoryRegister16(parser, destReg, Z80_REG_BIT(Z80_REG16_HL));
247+
case Z80_PARAM_MEMSP:
248+
return parseMemoryRegister16(parser, destReg, Z80_REG_BIT(Z80_REG16_SP));
208249
case Z80_PARAM_HLI_HLD:
209250
return parseHLIncDec(parser, destReg);
251+
case Z80_PARAM_DE:
252+
return parseRegister16AF(parser, destReg, Z80_REG_BIT(Z80_REG16_DE));
210253
case Z80_PARAM_SP:
211254
return parseRegister16SP(parser, destReg, Z80_REG_BIT(Z80_REG16_SP));
255+
case Z80_PARAM_AF:
256+
return parseRegister16AF(parser, destReg, Z80_REG_BIT(Z80_REG16_AF));
257+
case Z80_PARAM_BC_DE_SP:
258+
return parseRegister16SP(parser, destReg, Z80_REG_BIT(Z80_REG16_BC) | Z80_REG_BIT(Z80_REG16_DE) | Z80_REG_BIT(Z80_REG16_SP));
259+
case Z80_PARAM_IR:
260+
return parseRegisterIR(parser, destReg);
261+
case Z80_PARAM_AF_PRIME:
262+
return parseAFPrime(parser);
212263
case Z80_PARAM_IMMEDIATE:
213264
destImm = parser.parseExpression();
214265
return destImm.isLoaded();
@@ -255,7 +306,9 @@ std::unique_ptr<CZ80Instruction> Z80Parser::parseOpcode(Parser& parser)
255306
const std::wstring stringValue = token.getStringValue();
256307
for (int z = 0; Z80Opcodes[z].name != nullptr; z++)
257308
{
258-
if ((Z80Opcodes[z].flags & Z80_GAMEBOY) && Z80.GetVersion() != ZARCH_GAMEBOY)
309+
if ((Z80Opcodes[z].flags & Z80_Z80) && Z80.GetVersion() != Z80ArchType::Z80)
310+
continue;
311+
if ((Z80Opcodes[z].flags & Z80_GAMEBOY) && Z80.GetVersion() != Z80ArchType::Gameboy)
259312
continue;
260313

261314
if (stringValue == Z80Opcodes[z].name)
@@ -274,9 +327,9 @@ std::unique_ptr<CZ80Instruction> Z80Parser::parseOpcode(Parser& parser)
274327
}
275328

276329
if (paramFail)
277-
parser.printError(token, L"Z80 parameter failure in %S", stringValue);
330+
parser.printError(token, L"%s parameter failure in %S", Z80.GetName(), stringValue);
278331
else
279-
parser.printError(token, L"Invalid Z80 opcode: %S", stringValue);
332+
parser.printError(token, L"Invalid %s opcode: %S", Z80.GetName(), stringValue);
280333

281334
return nullptr;
282335
}

0 commit comments

Comments
 (0)