yaze 0.2.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
spc700_test.cc
Go to the documentation of this file.
2
3#include <gmock/gmock-nice-strict.h>
4#include <gmock/gmock.h>
5#include <gtest/gtest.h>
6
7namespace yaze {
8namespace test {
9
10using testing::_;
11using testing::Return;
13using yaze::emu::AudioRam;
14using yaze::emu::Spc700;
15
19class MockAudioRam : public AudioRam {
20 public:
21 MOCK_METHOD(void, reset, (), (override));
22 MOCK_METHOD(uint8_t, read, (uint16_t address), (const, override));
23 MOCK_METHOD(uint8_t&, mutable_read, (uint16_t address), (override));
24 MOCK_METHOD(void, write, (uint16_t address, uint8_t value), (override));
25
26 void SetupMemory(uint16_t address, const std::vector<uint8_t>& values) {
27 if (address > internal_audio_ram_.size()) {
28 internal_audio_ram_.resize(address + values.size());
29 }
30 int i = 0;
31 for (const auto& each : values) {
32 internal_audio_ram_[address + i] = each;
33 i++;
34 }
35 }
36
37 void SetUp() {
38 // internal_audio_ram_.resize(0x10000); // 64 K (0x10000)
39 // std::fill(internal_audio_ram_.begin(), internal_audio_ram_.end(), 0);
40 ON_CALL(*this, read(_)).WillByDefault([this](uint16_t address) {
41 return internal_audio_ram_[address];
42 });
43 ON_CALL(*this, mutable_read(_))
44 .WillByDefault([this](uint16_t address) -> uint8_t& {
45 return internal_audio_ram_[address];
46 });
47 ON_CALL(*this, write(_, _))
48 .WillByDefault([this](uint16_t address, uint8_t value) {
49 internal_audio_ram_[address] = value;
50 });
51 ON_CALL(*this, reset()).WillByDefault([this]() {
52 std::fill(internal_audio_ram_.begin(), internal_audio_ram_.end(), 0);
53 });
54 }
55
56 std::vector<uint8_t> internal_audio_ram_ = std::vector<uint8_t>(0x10000, 0);
57};
58
62class Spc700Test : public ::testing::Test {
63 public:
64 Spc700Test() = default;
65 void SetUp() override {
66 // Set up the mock
67 audioRAM.SetUp();
68
69 // Set the Spc700 to bank 01
70 spc700.PC = 0x0100;
71 }
72
73 testing::StrictMock<MockAudioRam> audioRAM;
76};
77
78// ========================================================
79// 8-bit Move Memory to Register
80
81TEST_F(Spc700Test, MOV_A_Immediate) {
82 // MOV A, imm
83 uint8_t opcode = 0xE8;
84 uint8_t immediate_value = 0x5A;
85 audioRAM.SetupMemory(0x0100, {opcode, immediate_value});
86
87 EXPECT_CALL(audioRAM, read(_)).WillOnce(Return(immediate_value));
88
89 spc700.ExecuteInstructions(opcode);
90
91 EXPECT_EQ(spc700.A, immediate_value);
92 EXPECT_EQ(spc700.PSW.Z, 0);
93 EXPECT_EQ(spc700.PSW.N, 0);
94}
95
96TEST_F(Spc700Test, MOV_A_X) {
97 // MOV A, X
98 uint8_t opcode = 0x7D;
99 spc700.X = 0x5A;
100
101 spc700.ExecuteInstructions(opcode);
102
103 EXPECT_EQ(spc700.A, spc700.X);
104 EXPECT_EQ(spc700.PSW.Z, 0);
105 EXPECT_EQ(spc700.PSW.N, 0);
106}
107
109 // MOV A, Y
110 uint8_t opcode = 0xDD;
111 spc700.Y = 0x5A;
112
113 spc700.ExecuteInstructions(opcode);
114
115 EXPECT_EQ(spc700.A, spc700.Y);
116 EXPECT_EQ(spc700.PSW.Z, 0);
117 EXPECT_EQ(spc700.PSW.N, 0);
118}
119
120TEST_F(Spc700Test, MOV_A_dp) {
121 // MOV A, dp
122 uint8_t opcode = 0xE4;
123 uint8_t dp_value = 0x5A;
124 audioRAM.SetupMemory(0x005A, {0x42});
125 audioRAM.SetupMemory(0x0100, {opcode, dp_value});
126
127 EXPECT_CALL(audioRAM, read(_))
128 .WillOnce(Return(dp_value))
129 .WillOnce(Return(0x42));
130
131 spc700.ExecuteInstructions(opcode);
132
133 EXPECT_EQ(spc700.A, 0x42);
134 EXPECT_EQ(spc700.PSW.Z, 0);
135 EXPECT_EQ(spc700.PSW.N, 0);
136}
137
138TEST_F(Spc700Test, MOV_A_dp_plus_x) {
139 // MOV A, dp+X
140 uint8_t opcode = 0xF4;
141 uint8_t dp_value = 0x5A;
142 spc700.X = 0x01;
143 audioRAM.SetupMemory(0x005B, {0x42});
144 audioRAM.SetupMemory(0x0100, {opcode, dp_value});
145
146 EXPECT_CALL(audioRAM, read(_))
147 .WillOnce(Return(dp_value + spc700.X))
148 .WillOnce(Return(0x42));
149
150 spc700.ExecuteInstructions(opcode);
151
152 EXPECT_EQ(spc700.A, 0x42);
153 EXPECT_EQ(spc700.PSW.Z, 0);
154 EXPECT_EQ(spc700.PSW.N, 0);
155}
156
157TEST_F(Spc700Test, MOV_A_dp_indirect_plus_y) {
158 // MOV A, [dp]+Y
159 uint8_t opcode = 0xF7;
160 uint8_t dp_value = 0x5A;
161 spc700.Y = 0x01;
162 audioRAM.SetupMemory(0x005A, {0x00, 0x42});
163 audioRAM.SetupMemory(0x0100, {opcode, dp_value});
164 audioRAM.SetupMemory(0x4201, {0x69});
165
166 EXPECT_CALL(audioRAM, read(_))
167 .WillOnce(Return(dp_value))
168 .WillOnce(Return(0x4200))
169 .WillOnce(Return(0x69));
170
171 spc700.ExecuteInstructions(opcode);
172
173 EXPECT_EQ(spc700.A, 0x69);
174 EXPECT_EQ(spc700.PSW.Z, 0);
175 EXPECT_EQ(spc700.PSW.N, 0);
176}
177
178TEST_F(Spc700Test, MOV_A_dp_plus_x_indirect) {
179 // MOV A, [dp+X]
180 uint8_t opcode = 0xE7;
181 uint8_t dp_value = 0x5A;
182 spc700.X = 0x01;
183 audioRAM.SetupMemory(0x005B, {0x00, 0x42});
184 audioRAM.SetupMemory(0x0100, {opcode, dp_value});
185 audioRAM.SetupMemory(0x4200, {0x69});
186
187 EXPECT_CALL(audioRAM, read(_))
188 .WillOnce(Return(dp_value + 1))
189 .WillOnce(Return(0x4200))
190 .WillOnce(Return(0x69));
191
192 spc700.ExecuteInstructions(opcode);
193
194 EXPECT_EQ(spc700.A, 0x69);
195 EXPECT_EQ(spc700.PSW.Z, 0);
196 EXPECT_EQ(spc700.PSW.N, 0);
197}
198
199TEST_F(Spc700Test, MOV_A_abs) {
200 // MOV A, !abs
201 uint8_t opcode = 0xE5;
202 uint16_t abs_addr = 0x1234;
203 uint8_t abs_value = 0x5A;
204
205 EXPECT_CALL(audioRAM, read(_))
206 .WillOnce(Return(abs_addr & 0xFF)) // Low byte
207 .WillOnce(Return(abs_addr >> 8)); // High byte
208
209 EXPECT_CALL(audioRAM, read(abs_addr)).WillOnce(Return(abs_value));
210
211 spc700.ExecuteInstructions(opcode);
212
213 EXPECT_EQ(spc700.A, abs_value);
214 EXPECT_EQ(spc700.PSW.Z, 0);
215 EXPECT_EQ(spc700.PSW.N, 0);
216}
217
218// ============================================================================
219// 8-bit Move Register to Memory
220
221TEST_F(Spc700Test, MOV_Immediate) {
222 // MOV A, imm
223 uint8_t opcode = 0xE8;
224 uint8_t immediate_value = 0x5A;
225
226 EXPECT_CALL(audioRAM, read(_)).WillOnce(Return(immediate_value));
227
228 spc700.ExecuteInstructions(opcode);
229
230 EXPECT_EQ(spc700.A, immediate_value);
231 EXPECT_EQ(spc700.PSW.Z, 0);
232 EXPECT_EQ(spc700.PSW.N, 0);
233}
234
235// ============================================================================
236
237TEST_F(Spc700Test, NOP_DoesNothing) {
238 // NOP opcode
239 uint8_t opcode = 0x00;
240
241 uint16_t initialPC = spc700.PC;
242 spc700.ExecuteInstructions(opcode);
243
244 // PC should increment by 1, no other changes
245 EXPECT_EQ(spc700.PC, initialPC + 1);
246 // Add checks for other registers if needed
247}
248
249TEST_F(Spc700Test, ADC_A_Immediate) {
250 // ADC A, #imm
251 uint8_t opcode = 0x88;
252 uint8_t immediate_value = 0x10;
253 spc700.A = 0x01;
254 spc700.PSW.C = 1; // Assume carry is set
255
256 EXPECT_CALL(audioRAM, read(_)).WillOnce(Return(immediate_value));
257
258 spc700.ExecuteInstructions(opcode);
259
260 // Verify A, and flags
261 EXPECT_EQ(spc700.A, 0x12); // 0x01 + 0x10 + 1 (carry)
262 // Check for other flags (Z, C, etc.) based on the result
263}
264
265TEST_F(Spc700Test, BEQ_BranchesIfZeroFlagSet) {
266 // BEQ rel
267 uint8_t opcode = 0xF0;
268 int8_t offset = 0x05;
269 spc700.PSW.Z = 1; // Set Zero flag
270
271 EXPECT_CALL(audioRAM, read(_)).WillOnce(Return(offset));
272
273 uint16_t initialPC = spc700.PC + 1;
274 spc700.ExecuteInstructions(opcode);
275
276 EXPECT_EQ(spc700.PC, initialPC + offset);
277}
278
279TEST_F(Spc700Test, STA_Absolute) {
280 // STA !abs
281 uint8_t opcode = 0x85;
282 uint16_t abs_addr = 0x1234;
283 spc700.A = 0x80;
284
285 // Set up the mock to return the address for the absolute addressing
286 EXPECT_CALL(audioRAM, read(_))
287 .WillOnce(Return(abs_addr & 0xFF)) // Low byte
288 .WillOnce(Return(abs_addr >> 8)); // High byte
289
290 spc700.ExecuteInstructions(opcode);
291}
292
293TEST_F(Spc700Test, ExecuteADCWithImmediate) {
294 // ADC A, imm
295 uint8_t opcode = 0x88; // Replace with opcode for ADC A, imm
296 uint8_t immediate_value = 0x10;
297 spc700.A = 0x15;
298
299 EXPECT_CALL(audioRAM, read(_)).WillOnce(Return(immediate_value));
300
301 spc700.ExecuteInstructions(opcode);
302
303 EXPECT_EQ(spc700.A, 0x25); // 0x15 + 0x10
304 EXPECT_EQ(spc700.PSW.Z, 0);
305 EXPECT_EQ(spc700.PSW.N, 0);
306 EXPECT_EQ(spc700.PSW.C, 0);
307}
308
309TEST_F(Spc700Test, ExecuteBRA) {
310 // BRA
311 uint8_t opcode = 0x2F;
312 int8_t offset = 0x05;
313
314 EXPECT_CALL(audioRAM, read(_)).WillOnce(Return(offset));
315
316 // rel() moves the PC forward one after read
317 uint16_t initialPC = spc700.PC + 1;
318 spc700.ExecuteInstructions(opcode);
319
320 EXPECT_EQ(spc700.PC, initialPC + offset);
321}
322
323TEST_F(Spc700Test, ReadFromAudioRAM) {
324 uint16_t address = 0x1234;
325 uint8_t expected_value = 0x5A;
326
327 EXPECT_CALL(audioRAM, read(address)).WillOnce(Return(expected_value));
328
329 uint8_t value = spc700.read(address);
330 EXPECT_EQ(value, expected_value);
331}
332
333TEST_F(Spc700Test, WriteToAudioRAM) {
334 uint16_t address = 0x1234;
335 uint8_t value = 0x5A;
336
337 EXPECT_CALL(audioRAM, write(address, value));
338
339 spc700.write(address, value);
340}
341
342TEST_F(Spc700Test, ExecuteANDWithImmediate) {
343 // AND A, imm
344 uint8_t opcode = 0x28;
345 uint8_t immediate_value = 0x0F;
346 spc700.A = 0x5A; // 0101 1010
347
348 EXPECT_CALL(audioRAM, read(_)).WillOnce(Return(immediate_value));
349
350 spc700.ExecuteInstructions(opcode);
351
352 EXPECT_EQ(spc700.A, 0x0A); // 0101 1010 & 0000 1111 = 0000 1010
353 EXPECT_EQ(spc700.PSW.Z, 0);
354 EXPECT_EQ(spc700.PSW.N, 0);
355}
356
357TEST_F(Spc700Test, ExecuteORWithImmediate) {
358 // OR A, imm
359 uint8_t opcode = 0x08;
360 uint8_t immediate_value = 0x0F;
361 spc700.A = 0xA0; // 1010 0000
362
363 EXPECT_CALL(audioRAM, read(_)).WillOnce(Return(immediate_value));
364
365 spc700.ExecuteInstructions(opcode);
366
367 EXPECT_EQ(spc700.A, 0xAF); // 1010 0000 | 0000 1111 = 1010 1111
368 EXPECT_EQ(spc700.PSW.Z, 0);
369 // EXPECT_EQ(spc700.PSW.N, 1);
370}
371
372TEST_F(Spc700Test, ExecuteEORWithImmediate) {
373 // EOR A, imm
374 uint8_t opcode = 0x48;
375 uint8_t immediate_value = 0x5A;
376 spc700.A = 0x5A; // 0101 1010
377
378 EXPECT_CALL(audioRAM, read(_)).WillOnce(Return(immediate_value));
379
380 spc700.ExecuteInstructions(opcode);
381
382 EXPECT_EQ(spc700.A, 0x00); // 0101 1010 ^ 0101 1010 = 0000 0000
383 EXPECT_EQ(spc700.PSW.Z, 1);
384 EXPECT_EQ(spc700.PSW.N, 0);
385}
386
387TEST_F(Spc700Test, ExecuteINC) {
388 // INC A
389 uint8_t opcode = 0xBC;
390 spc700.A = 0xFF;
391
392 spc700.ExecuteInstructions(opcode);
393
394 EXPECT_EQ(spc700.A, 0x00);
395 EXPECT_EQ(spc700.PSW.Z, 1);
396 EXPECT_EQ(spc700.PSW.N, 0);
397}
398
399TEST_F(Spc700Test, ExecuteDEC) {
400 // DEC A
401 uint8_t opcode = 0x9C;
402 spc700.A = 0x01;
403
404 spc700.ExecuteInstructions(opcode);
405
406 EXPECT_EQ(spc700.A, 0x00);
407 EXPECT_EQ(spc700.PSW.Z, 1);
408 EXPECT_EQ(spc700.PSW.N, 0);
409}
410
411TEST_F(Spc700Test, ExecuteBNEWhenNotEqual) {
412 // BNE
413 uint8_t opcode = 0xD0;
414 int8_t offset = 0x05;
415 spc700.PSW.Z = 0;
416
417 EXPECT_CALL(audioRAM, read(_)).WillOnce(Return(offset));
418
419 uint16_t initialPC = spc700.PC + 1;
420 spc700.ExecuteInstructions(opcode);
421
422 EXPECT_EQ(spc700.PC, initialPC + offset);
423}
424
425TEST_F(Spc700Test, ExecuteBNEWhenEqual) {
426 // BNE
427 uint8_t opcode = 0xD0;
428 int8_t offset = 0x05;
429 spc700.PSW.Z = 1;
430
431 EXPECT_CALL(audioRAM, read(_)).WillOnce(Return(offset));
432
433 uint16_t initialPC = spc700.PC;
434 spc700.ExecuteInstructions(opcode);
435
436 EXPECT_EQ(spc700.PC, initialPC + 1); // +1 because of reading the offset
437}
438
439TEST_F(Spc700Test, ExecuteBEQWhenEqual) {
440 // BEQ
441 uint8_t opcode = 0xF0;
442 int8_t offset = 0x05;
443 spc700.PSW.Z = 1;
444
445 EXPECT_CALL(audioRAM, read(_)).WillOnce(Return(offset));
446
447 uint16_t initialPC = spc700.PC + 1;
448 spc700.ExecuteInstructions(opcode);
449
450 EXPECT_EQ(spc700.PC, initialPC + offset);
451}
452
453TEST_F(Spc700Test, ExecuteBEQWhenNotEqual) {
454 // BEQ
455 uint8_t opcode = 0xF0;
456 int8_t offset = 0x05;
457 spc700.PSW.Z = 0;
458
459 EXPECT_CALL(audioRAM, read(_)).WillOnce(Return(offset));
460
461 uint16_t initialPC = spc700.PC;
462 spc700.ExecuteInstructions(opcode);
463
464 EXPECT_EQ(spc700.PC, initialPC + 1); // +1 because of reading the offset
465}
466
467TEST_F(Spc700Test, BootIplRomOk) {
468 // Boot the IPL ROM
469 // spc700.BootIplRom();
470 // EXPECT_EQ(spc700.PC, 0xFFC1 + 0x3F);
471}
472
473} // namespace test
474} // namespace yaze
AudioRam is an interface for the Audio RAM used by the SPC700.
Definition spc700.h:15
virtual void reset()=0
virtual void write(uint16_t address, uint8_t value)=0
virtual uint8_t & mutable_read(uint16_t address)=0
virtual uint8_t read(uint16_t address) const =0
The Spc700 class represents the SPC700 processor.
Definition spc700.h:69
MockAudioRam is a mock class for the AudioRam class.
MOCK_METHOD(uint8_t &, mutable_read,(uint16_t address),(override))
std::vector< uint8_t > internal_audio_ram_
MOCK_METHOD(uint8_t, read,(uint16_t address),(const, override))
MOCK_METHOD(void, reset,(),(override))
void SetupMemory(uint16_t address, const std::vector< uint8_t > &values)
MOCK_METHOD(void, write,(uint16_t address, uint8_t value),(override))
ApuCallbacks callbacks_
testing::StrictMock< MockAudioRam > audioRAM
void SetUp() override
struct yaze::emu::ApuCallbacks ApuCallbacks
TEST_F(CpuTest, AsmParserTokenizerOk)
Definition cpu_test.cc:44
Main namespace for the application.
Definition controller.cc:18