yaze 0.2.0
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
cpu_test.cc
Go to the documentation of this file.
1#include "app/emu/cpu/cpu.h"
2
3#include <gmock/gmock.h>
4#include <gtest/gtest.h>
5
6#include "app/emu/cpu/clock.h"
11
12namespace yaze {
13namespace test {
14namespace emu {
15
21
25class CpuTest : public ::testing::Test {
26 public:
27 void SetUp() override {
29 EXPECT_CALL(mock_memory, ClearMemory()).Times(::testing::AtLeast(1));
31 }
32
38};
39
40using ::testing::_;
41using ::testing::Return;
42
43// ============================================================================
44// Infrastructure
45// ============================================================================
46
47TEST_F(CpuTest, AsmParserTokenizerOk) {
48 AsmParser asm_parser;
49 std::string instruction = R"(
50 ADC.b #$01
51 LDA.b #$FF
52 STA.w $2000
53 )";
54
55 std::vector<std::string> tokens = asm_parser.Tokenize(instruction);
56
57 std::vector<std::string> expected_tokens = {"ADC", ".b", "#", "$", "01",
58 "LDA", ".b", "#", "$", "FF",
59 "STA", ".w", "$", "2000"};
60 EXPECT_THAT(tokens, ::testing::ContainerEq(expected_tokens));
61}
62
63TEST_F(CpuTest, AsmParserSingleInstructionOk) {
64 AsmParser asm_parser;
65 std::string instruction = "ADC.b #$01";
66 std::vector<std::string> tokens = asm_parser.Tokenize(instruction);
67
68 std::vector<std::string> expected_tokens = {"ADC", ".b", "#", "$", "01"};
69 EXPECT_THAT(tokens, ::testing::ContainerEq(expected_tokens));
70
71 auto opcode = asm_parser.Parse(instruction);
72 EXPECT_EQ(opcode[0], 0x69);
73}
74
75TEST_F(CpuTest, CheckMemoryContents) {
76 MockMemory memory;
77 std::vector<uint8_t> data = {0x00, 0x01, 0x02, 0x03, 0x04};
78 memory.SetMemoryContents(data);
79
80 EXPECT_CALL(memory, ReadByte(0)).WillOnce(Return(0x00));
81 EXPECT_CALL(memory, ReadByte(1)).WillOnce(Return(0x01));
82 EXPECT_CALL(memory, ReadByte(2)).WillOnce(Return(0x02));
83 EXPECT_CALL(memory, ReadByte(3)).WillOnce(Return(0x03));
84 EXPECT_CALL(memory, ReadByte(4)).WillOnce(Return(0x04));
85 EXPECT_CALL(memory, ReadByte(63999)).WillOnce(Return(0x00));
86
87 EXPECT_EQ(memory.ReadByte(0), 0x00);
88 EXPECT_EQ(memory.ReadByte(1), 0x01);
89 EXPECT_EQ(memory.ReadByte(2), 0x02);
90 EXPECT_EQ(memory.ReadByte(3), 0x03);
91 EXPECT_EQ(memory.ReadByte(4), 0x04);
92 EXPECT_EQ(memory.ReadByte(63999), 0x00);
93}
94
95// ============================================================================
96// ADC - Add with Carry
97
98TEST_F(CpuTest, ADC_CheckCarryFlag) {
99 cpu.A = 0xFF;
100 cpu.SetAccumulatorSize(true);
101 std::vector<uint8_t> data = {0x69, 0x15, 0x01}; // Operand at address 0x15
102 mock_memory.SetMemoryContents(data);
103
104 cpu.ExecuteInstruction(cpu.ReadOpcode()); // ADC Immediate
105
106 EXPECT_EQ(cpu.A, 0x00);
107 EXPECT_TRUE(cpu.GetCarryFlag());
108}
109
110TEST_F(CpuTest, ADC_DirectPageIndexedIndirectX) {
111 cpu.A = 0x03;
112 cpu.D = 0x2000; // Setting Direct Page register to 0x2000
113 std::vector<uint8_t> data = {0x61, 0x10}; // ADC (dp, X)
114 mock_memory.SetMemoryContents(data);
115 mock_memory.InsertMemory(0x2012, {0x00, 0x30}); // [0x2012] = 0x3000
116 mock_memory.InsertMemory(0x3000, {0x06}); // [0x3000] = 0x06
117
118 cpu.X = 0x02; // X register
119 EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(Return(0x10));
120 EXPECT_CALL(mock_memory, ReadWord(0x2012)).WillOnce(Return(0x3000));
121 EXPECT_CALL(mock_memory, ReadByte(0x3000)).WillOnce(Return(0x06));
122
123 cpu.ExecuteInstruction(0x61); // ADC (dp, X)
124 EXPECT_EQ(cpu.A, 0x09); // 0x03 + 0x06 = 0x09
125}
126
127TEST_F(CpuTest, ADC_StackRelative) {
128 cpu.A = 0x03;
129 std::vector<uint8_t> data = {0x63, 0x02}; // ADC sr
130 mock_memory.SetMemoryContents(data);
131 mock_memory.InsertMemory(0x0201, {0x06}); // [0x0201] = 0x06
132
133 EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(Return(0x02)); // Operand
134 EXPECT_CALL(mock_memory, ReadByte(0x0201))
135 .WillOnce(Return(0x06)); // Memory value
136
137 cpu.ExecuteInstruction(0x63); // ADC Stack Relative
138 EXPECT_EQ(cpu.A, 0x09); // 0x03 + 0x06 = 0x09
139}
140
141TEST_F(CpuTest, ADC_DirectPage) {
142 cpu.A = 0x01;
143 cpu.D = 0x2000; // Setting Direct Page register to 0x2000
144 std::vector<uint8_t> data = {0x65, 0x10}; // ADC dp
145 mock_memory.SetMemoryContents(data);
146 mock_memory.InsertMemory(0x2010, {0x05}); // [0x2010] = 0x05
147
148 EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(Return(0x10));
149 EXPECT_CALL(mock_memory, ReadByte(0x2010)).WillOnce(Return(0x05));
150
151 cpu.ExecuteInstruction(0x65); // ADC Direct Page
152 EXPECT_EQ(cpu.A, 0x06);
153}
154
155TEST_F(CpuTest, ADC_DirectPageIndirectLong) {
156 cpu.A = 0x03;
157 cpu.D = 0x2000;
158 std::vector<uint8_t> data = {0x67, 0x10};
159 mock_memory.SetMemoryContents(data);
160 mock_memory.InsertMemory(0x2010, {0x05, 0x00, 0x30});
161 mock_memory.InsertMemory(0x030005, {0x06});
162
163 EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(Return(0x10));
164 EXPECT_CALL(mock_memory, ReadWordLong(0x2010)).WillOnce(Return(0x300005));
165 EXPECT_CALL(mock_memory, ReadWord(0x300005)).WillOnce(Return(0x06));
166
167 cpu.ExecuteInstruction(0x67); // ADC Direct Page Indirect Long
168 EXPECT_EQ(cpu.A, 0x09);
169}
170
171TEST_F(CpuTest, ADC_Immediate_TwoPositiveNumbers) {
172 cpu.A = 0x01;
173 cpu.SetAccumulatorSize(true);
174 std::vector<uint8_t> data = {0x01};
175 mock_memory.SetMemoryContents(data);
176
177 EXPECT_CALL(mock_memory, ReadByte(_)).WillOnce(Return(0x01));
178
179 cpu.ExecuteInstruction(0x69); // ADC Immediate
180 EXPECT_EQ(cpu.A, 0x02);
181}
182
183TEST_F(CpuTest, ADC_Immediate_PositiveAndNegativeNumbers) {
184 cpu.A = 10;
185 cpu.SetAccumulatorSize(true);
186 std::vector<uint8_t> data = {0x69, static_cast<uint8_t>(-20)};
187 mock_memory.SetMemoryContents(data);
188
189 EXPECT_CALL(mock_memory, ReadByte(_)).WillOnce(Return(-20));
190
191 cpu.ExecuteInstruction(0x69); // ADC Immediate
192 EXPECT_EQ(cpu.A, static_cast<uint8_t>(-10));
193}
194
195TEST_F(CpuTest, ADC_Absolute) {
196 cpu.A = 0x01;
197 cpu.status = 0x00; // 16-bit mode
198 std::vector<uint8_t> data = {0x6D, 0x03, 0x00, 0x05, 0x00};
199 mock_memory.SetMemoryContents(data);
200
201 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x0003));
202
203 EXPECT_CALL(mock_memory, ReadWord(0x0003)).WillOnce(Return(0x0005));
204
205 cpu.ExecuteInstruction(0x6D); // ADC Absolute
206 EXPECT_EQ(cpu.A, 0x06);
207}
208
209TEST_F(CpuTest, ADC_AbsoluteLong) {
210 cpu.A = 0x01;
211 cpu.SetAccumulatorSize(false); // 16-bit mode
212 cpu.SetCarryFlag(false);
213 std::vector<uint8_t> data = {0x6F, 0x04, 0x00, 0x00, 0x05, 0x00};
214 mock_memory.SetMemoryContents(data);
215
216 EXPECT_CALL(mock_memory, ReadWordLong(0x0001)).WillOnce(Return(0x0004));
217 EXPECT_CALL(mock_memory, ReadWord(0x0004)).WillOnce(Return(0x0005));
218
219 cpu.ExecuteInstruction(0x6F); // ADC Absolute Long
220 EXPECT_EQ(cpu.A, 0x06);
221}
222
223TEST_F(CpuTest, ADC_DirectPageIndirectIndexedY) {
224 cpu.A = 0x03;
225 cpu.Y = 0x02;
226 cpu.D = 0x2000;
227 std::vector<uint8_t> data = {0x71, 0x10};
228 mock_memory.SetMemoryContents(data);
229 mock_memory.InsertMemory(0x2010, {0x00, 0x30}); // [0x2010] = 0x3000
230 mock_memory.InsertMemory(0x3002, {0x06}); // [0x3002] = 0x06
231
232 EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(Return(0x10));
233 EXPECT_CALL(mock_memory, ReadWord(0x2010)).WillOnce(Return(0x3000));
234 EXPECT_CALL(mock_memory, ReadByte(0x3002)).WillOnce(Return(0x06));
235
236 cpu.ExecuteInstruction(0x71); // ADC Direct Page Indirect Indexed, Y
237 EXPECT_EQ(cpu.A, 0x09); // 0x03 + 0x06 = 0x09
238}
239
240TEST_F(CpuTest, ADC_DirectPageIndirect) {
241 cpu.A = 0x02;
242 cpu.D = 0x2000; // Setting Direct Page register to 0x2000
243 std::vector<uint8_t> data = {0x72, 0x10}; // ADC (dp)
244 mock_memory.SetMemoryContents(data);
245 mock_memory.InsertMemory(0x2010, {0x00, 0x30}); // [0x2010] = 0x3000
246 mock_memory.InsertMemory(0x3000, {0x05}); // [0x3000] = 0x05
247
248 EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(Return(0x10));
249 EXPECT_CALL(mock_memory, ReadWord(0x2010)).WillOnce(Return(0x3000));
250 EXPECT_CALL(mock_memory, ReadByte(0x3000)).WillOnce(Return(0x05));
251
252 cpu.ExecuteInstruction(0x72); // ADC (dp)
253 EXPECT_EQ(cpu.A, 0x07); // 0x02 + 0x05 = 0x07
254}
255
256TEST_F(CpuTest, ADC_StackRelativeIndirectIndexedY) {
257 cpu.A = 0x03; // A register
258 cpu.Y = 0x02; // Y register
259 cpu.DB = 0x10; // Setting Data Bank register to 0x20
260 std::vector<uint8_t> data = {0x73, 0x02}; // ADC sr, Y
261 mock_memory.SetMemoryContents(data);
262 mock_memory.InsertMemory(0x0201, {0x00, 0x30}); // [0x0201] = 0x3000
263 mock_memory.InsertMemory(0x103002, {0x06}); // [0x3002] = 0x06
264
265 EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(Return(0x02));
266 EXPECT_CALL(mock_memory, ReadWord(0x0201)).WillOnce(Return(0x3000));
267 EXPECT_CALL(mock_memory, ReadByte(0x103002)).WillOnce(Return(0x06));
268
269 cpu.ExecuteInstruction(0x73); // ADC Stack Relative Indexed Y
270 EXPECT_EQ(cpu.A, 0x09); // 0x03 + 0x06 = 0x09
271}
272
273TEST_F(CpuTest, ADC_DirectPageIndexedX) {
274 cpu.A = 0x03;
275 cpu.X = 0x02;
276 cpu.D = 0x2000;
277 std::vector<uint8_t> data = {0x75, 0x10};
278 mock_memory.SetMemoryContents(data);
279 mock_memory.InsertMemory(0x2012, {0x06}); // [0x2012] = 0x3000
280
281 EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(Return(0x10));
282 EXPECT_CALL(mock_memory, ReadByte(0x2012)).WillOnce(Return(0x06));
283
284 cpu.ExecuteInstruction(0x75); // ADC Direct Page Indexed, X
285 EXPECT_EQ(cpu.A, 0x09); // 0x03 + 0x06 = 0x09
286}
287
288TEST_F(CpuTest, ADC_DirectPageIndirectLongIndexedY) {
289 cpu.A = 0x03;
290 cpu.Y = 0x02;
291 cpu.D = 0x2000;
292 cpu.status = 0x00;
293 std::vector<uint8_t> data = {0x77, 0x10};
294 mock_memory.SetMemoryContents(data);
295 mock_memory.InsertMemory(0x2010, {0x05, 0x00, 0x01});
296 mock_memory.InsertMemory(0x010007, {0x06});
297
298 EXPECT_CALL(mock_memory, ReadWordLong(0x2010)).WillOnce(Return(0x010005));
299 EXPECT_CALL(mock_memory, ReadWord(0x010007)).WillOnce(Return(0x06));
300
301 cpu.ExecuteInstruction(0x77); // ADC DP Indirect Long Indexed, Y
302 EXPECT_EQ(cpu.A, 0x09);
303}
304
305TEST_F(CpuTest, ADC_AbsoluteIndexedY) {
306 cpu.A = 0x03;
307 cpu.Y = 0x02; // Y register
308 cpu.DB = 0x20; // Setting Data Bank register to 0x20
309 std::vector<uint8_t> data = {0x79, 0x03, 0x00, 0x00, 0x05, 0x00};
310 mock_memory.SetMemoryContents(data);
311
312 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x0003));
313 EXPECT_CALL(mock_memory, ReadWord(0x200005)).WillOnce(Return(0x0005));
314
315 mock_memory.InsertMemory(0x200005, {0x05});
316
317 cpu.ExecuteInstruction(0x79); // ADC Absolute Indexed Y
318 EXPECT_EQ(cpu.A, 0x08);
319}
320
321TEST_F(CpuTest, ADC_AbsoluteIndexedX) {
322 cpu.A = 0x03;
323 cpu.X = 0x02; // X register
324 cpu.DB = 0x20; // Setting Data Bank register to 0x20
325 cpu.SetCarryFlag(false);
326 cpu.SetAccumulatorSize(false); // 16-bit mode
327 std::vector<uint8_t> data = {0x7D, 0x03, 0x00};
328 mock_memory.SetMemoryContents(data);
329
330 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x0003));
331 EXPECT_CALL(mock_memory, ReadWord(0x200005)).WillOnce(Return(0x0005));
332
333 mock_memory.InsertMemory(0x200005, {0x05}); // Inserting memory at 0x2005
334
335 cpu.ExecuteInstruction(0x7D); // ADC Absolute Indexed X
336 EXPECT_EQ(cpu.A, 0x08);
337}
338
339TEST_F(CpuTest, ADC_AbsoluteLongIndexedX) {
340 cpu.A = 0x03;
341 cpu.X = 0x02; // X register
342 cpu.SetCarryFlag(false);
343 cpu.SetAccumulatorSize(false); // 16-bit mode
344 std::vector<uint8_t> data = {0x7F, 0x00, 0x00, 0x01};
345 mock_memory.SetMemoryContents(data);
346 mock_memory.InsertMemory(0x010000, {0x03, 0x05});
347
348 EXPECT_CALL(mock_memory, ReadWordLong(0x0001)).WillOnce(Return(0x010000));
349 EXPECT_CALL(mock_memory, ReadWord(0x010002)).WillOnce(Return(0x0005));
350
351 cpu.ExecuteInstruction(0x7F); // ADC Absolute Long Indexed X
352 EXPECT_EQ(cpu.A, 0x08);
353}
354
355// ============================================================================
356// AND - Logical AND
357
358TEST_F(CpuTest, AND_DirectPageIndexedIndirectX) {
359 cpu.A = 0b11110000; // A register
360 cpu.D = 0x2000; // Setting Direct Page register to 0x2000
361 cpu.X = 0x02; // X register
362 cpu.status = 0xFF; // 8-bit mode
363 std::vector<uint8_t> data = {0x21, 0x10};
364 mock_memory.SetMemoryContents(data);
365 mock_memory.InsertMemory(0x2012, {0x00, 0x30}); // [0x2012] = 0x3000
366 mock_memory.InsertMemory(0x3000, {0b10101010}); // [0x3000] = 0b10101010
367
368 // Get the operand
369 EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(Return(0x10));
370
371 // Get the value at the operand
372 EXPECT_CALL(mock_memory, ReadWord(0x2012)).WillOnce(Return(0x3000));
373
374 // Get the value at the operand
375 EXPECT_CALL(mock_memory, ReadByte(0x3000)).WillOnce(Return(0b10101010));
376
377 cpu.ExecuteInstruction(0x21); // AND Direct Page Indexed Indirect X
378
379 EXPECT_EQ(cpu.A, 0b10100000); // A register should now be 0b10100000
380}
381
382TEST_F(CpuTest, AND_StackRelative) {
383 cpu.A = 0b11110000; // A register
384 cpu.status = 0xFF; // 8-bit mode
385 std::vector<uint8_t> data = {0x23, 0x02};
386 mock_memory.SetMemoryContents(data);
387 mock_memory.InsertMemory(0x0201, {0b10101010}); // [0x0201] = 0b10101010
388
389 EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(Return(0x02));
390
391 // Get the value at the operand
392 EXPECT_CALL(mock_memory, ReadByte(0x0201)).WillOnce(Return(0b10101010));
393
394 cpu.ExecuteInstruction(0x23); // AND Stack Relative
395
396 EXPECT_EQ(cpu.A, 0b10100000); // A register should now be 0b10100000
397}
398
399TEST_F(CpuTest, AND_DirectPage) {
400 cpu.A = 0b11110000; // A register
401 cpu.D = 0x2000; // Setting Direct Page register to 0x2000
402 std::vector<uint8_t> data = {0x25, 0x10};
403 mock_memory.SetMemoryContents(data);
404 mock_memory.InsertMemory(0x2010, {0b10101010}); // [0x2010] = 0b10101010
405
406 // Get the operand
407 EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(Return(0x10));
408
409 // Get the value at the operand
410 EXPECT_CALL(mock_memory, ReadByte(0x2010)).WillOnce(Return(0b10101010));
411
412 cpu.ExecuteInstruction(0x25); // AND Direct Page
413
414 EXPECT_EQ(cpu.A, 0b10100000); // A register should now be 0b10100000
415}
416
417TEST_F(CpuTest, AND_DirectPageIndirectLong) {
418 cpu.A = 0b11110000; // A register
419 cpu.D = 0x2000; // Setting Direct Page register to 0x2000
420 cpu.status = 0xFF; // 8-bit mode
421 std::vector<uint8_t> data = {0x27, 0x10};
422 mock_memory.SetMemoryContents(data);
423 mock_memory.InsertMemory(0x2010, {0x05, 0x00, 0x30});
424 mock_memory.InsertMemory(0x300005, {0b10101010});
425
426 // Get the operand
427 EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(Return(0x10));
428
429 // Get the value at the operand
430 EXPECT_CALL(mock_memory, ReadWordLong(0x2010)).WillOnce(Return(0x300005));
431
432 // Get the value at the operand
433 EXPECT_CALL(mock_memory, ReadByte(0x300005)).WillOnce(Return(0b10101010));
434
435 cpu.ExecuteInstruction(0x27); // AND Direct Page Indirect Long
436
437 EXPECT_EQ(cpu.A, 0b10100000); // A register should now be 0b10100000
438}
439
440TEST_F(CpuTest, AND_Immediate) {
441 cpu.A = 0b11110000; // A register
442 std::vector<uint8_t> data = {0x29, 0b10101010}; // AND #0b10101010
443 mock_memory.SetMemoryContents(data);
444
445 cpu.ExecuteInstruction(0x29); // AND Immediate
446 EXPECT_EQ(cpu.A, 0b10100000); // A register should now be 0b10100000
447}
448
449TEST_F(CpuTest, AND_Absolute_16BitMode) {
450 cpu.A = 0b11111111; // A register
451 cpu.E = 0; // 16-bit mode
452 cpu.status = 0x00; // Clear status flags
453 std::vector<uint8_t> data = {0x2D, 0x03, 0x00, 0b10101010, 0x01, 0x02};
454 mock_memory.SetMemoryContents(data);
455
456 // Get the absolute address
457 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x0003));
458
459 // Get the value at the absolute address
460 EXPECT_CALL(mock_memory, ReadWord(0x0003)).WillOnce(Return(0b10101010));
461
462 cpu.ExecuteInstruction(0x2D); // AND Absolute
463
464 EXPECT_THAT(cpu.PC, testing::Eq(0x03));
465 EXPECT_EQ(cpu.A, 0b10101010); // A register should now be 0b10101010
466}
467
468TEST_F(CpuTest, AND_AbsoluteLong) {
469 cpu.A = 0x01;
470 cpu.status = 0x00; // 16-bit mode
471 std::vector<uint8_t> data = {0x2F, 0x04, 0x00, 0x00, 0x05, 0x00};
472
473 mock_memory.SetMemoryContents(data);
474 EXPECT_CALL(mock_memory, ReadWordLong(0x0001)).WillOnce(Return(0x000004));
475
476 EXPECT_CALL(mock_memory, ReadWordLong(0x0004)).WillOnce(Return(0x000005));
477
478 cpu.ExecuteInstruction(0x2F); // ADC Absolute Long
479 EXPECT_EQ(cpu.A, 0x01);
480}
481
482TEST_F(CpuTest, AND_DirectPageIndirectIndexedY) {
483 cpu.A = 0b11110000; // A register
484 cpu.D = 0x2000; // Setting Direct Page register to 0x2000
485 cpu.Y = 0x02; // Y register
486 std::vector<uint8_t> data = {0x31, 0x10};
487 mock_memory.SetMemoryContents(data);
488 mock_memory.InsertMemory(0x2010, {0x00, 0x30}); // [0x2010] = 0x3000
489 mock_memory.InsertMemory(0x3002, {0b10101010}); // [0x3002] = 0b10101010
490
491 // Get the value at the operand
492 EXPECT_CALL(mock_memory, ReadWord(0x2010)).WillOnce(Return(0x3000));
493
494 cpu.ExecuteInstruction(0x31); // AND Direct Page Indirect Indexed Y
495
496 EXPECT_EQ(cpu.A, 0b10100000); // A register should now be 0b10100000
497}
498
499TEST_F(CpuTest, AND_DirectPageIndirect) {
500 cpu.A = 0b11110000; // A register
501 cpu.D = 0x2000; // Setting Direct Page register to 0x2000
502 std::vector<uint8_t> data = {0x32, 0x10};
503 mock_memory.SetMemoryContents(data);
504 mock_memory.InsertMemory(0x2010, {0x00, 0x30}); // [0x2010] = 0x3000
505 mock_memory.InsertMemory(0x3000, {0b10101010}); // [0x3000] = 0b10101010
506
507 // Get the value at the operand
508 EXPECT_CALL(mock_memory, ReadWord(0x2010)).WillOnce(Return(0x3000));
509
510 cpu.ExecuteInstruction(0x32); // AND Direct Page Indirect
511
512 EXPECT_EQ(cpu.A, 0b10100000); // A register should now be 0b10100000
513}
514
515TEST_F(CpuTest, AND_StackRelativeIndirectIndexedY) {
516 cpu.A = 0b11110000; // A register
517 cpu.Y = 0x02; // Y register
518 cpu.DB = 0x10; // Setting Data Bank register to 0x20
519 mock_memory.SetSP(0x01FF); // Setting Stack Pointer to 0x01FF
520 std::vector<uint8_t> data = {0x33, 0x02};
521 mock_memory.SetMemoryContents(data);
522 mock_memory.InsertMemory(0x0201, {0x00, 0x30}); // [0x0201] = 0x3000
523 mock_memory.InsertMemory(0x103002, {0b10101010}); // [0x3002] = 0b10101010
524
525 EXPECT_CALL(mock_memory, SP()).WillRepeatedly(Return(0x01FF));
526 EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(Return(0x02));
527 EXPECT_CALL(mock_memory, ReadWord(0x0201)).WillOnce(Return(0x3000));
528 EXPECT_CALL(mock_memory, ReadByte(0x103002)).WillOnce(Return(0b10101010));
529 cpu.ExecuteInstruction(0x33); // AND Stack Relative Indirect Indexed Y
530
531 EXPECT_EQ(cpu.A, 0b10100000); // A register should now be 0b10100000
532}
533
534TEST_F(CpuTest, AND_DirectPageIndexedX) {
535 cpu.A = 0b11110000; // A register
536 cpu.D = 0x2000; // Setting Direct Page register to 0x2000
537 cpu.X = 0x02; // X register
538 std::vector<uint8_t> data = {0x35, 0x10};
539 mock_memory.SetMemoryContents(data);
540 mock_memory.InsertMemory(0x2012, {0b10101010}); // [0x2012] = 0b10101010
541
542 // Get the value at the operand
543 EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(Return(0x10));
544 EXPECT_CALL(mock_memory, ReadByte(0x2012)).WillOnce(Return(0b10101010));
545
546 cpu.ExecuteInstruction(0x35); // AND Direct Page Indexed X
547
548 EXPECT_EQ(cpu.A, 0b10100000); // A register should now be 0b10100000
549}
550
551TEST_F(CpuTest, AND_DirectPageIndirectLongIndexedY) {
552 cpu.A = 0b11110000; // A register
553 cpu.D = 0x2000; // Setting Direct Page register to 0x2000
554 cpu.Y = 0x02; // Y register
555 std::vector<uint8_t> data = {0x37, 0x10};
556 mock_memory.SetMemoryContents(data);
557 mock_memory.InsertMemory(0x2010, {0x05, 0x00, 0x30});
558 mock_memory.InsertMemory(0x300005, {0b10101010});
559
560 EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(Return(0x10));
561 EXPECT_CALL(mock_memory, ReadWordLong(0x2010)).WillOnce(Return(0x300005));
562 EXPECT_CALL(mock_memory, ReadByte(0x300007)).WillOnce(Return(0b10101010));
563
564 cpu.ExecuteInstruction(0x37); // AND Direct Page Indirect Long Indexed Y
565
566 EXPECT_EQ(cpu.A, 0b10100000); // A register should now be 0b10100000
567}
568
569TEST_F(CpuTest, AND_AbsoluteIndexedY) {
570 cpu.A = 0b11110000; // A register
571 cpu.Y = 0x02; // Y register
572 std::vector<uint8_t> data = {0x39, 0x03, 0x00,
573 0b00000000, 0b10101010, 0b01010101};
574 mock_memory.SetMemoryContents(data);
575
576 // Get the absolute address
577 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x0003));
578
579 // Add the offset from the Y register to the absolute address
580 uint16_t address = 0x0003 + cpu.Y;
581
582 // Get the value at the absolute address + Y
583 EXPECT_CALL(mock_memory, ReadByte(address)).WillOnce(Return(0b10101010));
584
585 cpu.ExecuteInstruction(0x39); // AND Absolute, Y
586
587 EXPECT_THAT(cpu.PC, testing::Eq(0x03));
588 EXPECT_EQ(cpu.A, 0b10100000); // A register should now be 0b10100000
589}
590
591TEST_F(CpuTest, AND_AbsoluteIndexedX) {
592 cpu.A = 0b11110000; // A register
593 cpu.X = 0x02; // X register
594 std::vector<uint8_t> data = {0x3D, 0x03, 0x00,
595 0b00000000, 0b10101010, 0b01010101};
596 mock_memory.SetMemoryContents(data);
597 mock_memory.InsertMemory(0x200005, {0b10101010});
598
599 // Get the absolute address
600 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x0003));
601
602 // Add the offset from the X register to the absolute address
603 uint16_t address = 0x0003 + static_cast<uint16_t>(cpu.X & 0xFF);
604
605 // Get the value at the absolute address + X
606 EXPECT_CALL(mock_memory, ReadByte(address)).WillOnce(Return(0b10101010));
607
608 cpu.ExecuteInstruction(0x3D); // AND Absolute, X
609
610 // EXPECT_THAT(cpu.PC, testing::Eq(0x03));
611 EXPECT_EQ(cpu.A, 0b10100000); // A register should now be 0b10100000
612}
613
614TEST_F(CpuTest, AND_AbsoluteLongIndexedX) {
615 cpu.A = 0b11110000; // A register
616 cpu.X = 0x02; // X register
617 cpu.status = 0xFF; // 8-bit mode
618 std::vector<uint8_t> data = {0x3F, 0x03, 0x00, 0x00,
619 0b00000000, 0b10101010, 0b01010101};
620 mock_memory.SetMemoryContents(data);
621
622 // Get the absolute address
623 EXPECT_CALL(mock_memory, ReadWordLong(0x0001)).WillOnce(Return(0x0003));
624
625 // Add the offset from the X register to the absolute address
626 uint16_t address = 0x0003 + static_cast<uint16_t>(cpu.X & 0xFF);
627
628 // Get the value at the absolute address + X
629 EXPECT_CALL(mock_memory, ReadByte(address)).WillOnce(Return(0b10101010));
630
631 cpu.ExecuteInstruction(0x3F); // AND Absolute Long, X
632
633 EXPECT_THAT(cpu.PC, testing::Eq(0x04));
634 EXPECT_EQ(cpu.A, 0b10100000); // A register should now be 0b10100000
635}
636
637// ============================================================================
638// ASL - Arithmetic Shift Left
639
640TEST_F(CpuTest, ASL_DirectPage) {
641 cpu.D = 0x1000; // Setting Direct Page register to 0x1000
642 cpu.PC = 0x1000;
643 std::vector<uint8_t> data = {0x06, 0x10}; // ASL dp
644 mock_memory.SetMemoryContents(data);
645 mock_memory.InsertMemory(0x1010, {0x40}); // [0x1010] = 0x40
646
647 cpu.ExecuteInstruction(0x06); // ASL Direct Page
648 EXPECT_TRUE(cpu.GetCarryFlag());
649 EXPECT_FALSE(cpu.GetZeroFlag());
650 EXPECT_TRUE(cpu.GetNegativeFlag());
651}
652
653TEST_F(CpuTest, ASL_Accumulator) {
654 cpu.status = 0xFF; // 8-bit mode
655 cpu.A = 0x40;
656 std::vector<uint8_t> data = {0x0A}; // ASL A
657 mock_memory.SetMemoryContents(data);
658
659 cpu.ExecuteInstruction(0x0A); // ASL Accumulator
660 EXPECT_EQ(cpu.A, 0x80);
661 EXPECT_TRUE(cpu.GetCarryFlag());
662 EXPECT_FALSE(cpu.GetZeroFlag());
663 EXPECT_TRUE(cpu.GetNegativeFlag());
664}
665
666TEST_F(CpuTest, ASL_Absolute) {
667 std::vector<uint8_t> data = {0x0E, 0x10, 0x20}; // ASL abs
668 mock_memory.SetMemoryContents(data);
669 mock_memory.InsertMemory(0x2010, {0x40}); // [0x2010] = 0x40
670
671 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x2010));
672 EXPECT_CALL(mock_memory, ReadByte(0x2010)).WillOnce(Return(0x40));
673
674 cpu.ExecuteInstruction(0x0E); // ASL Absolute
675 EXPECT_TRUE(cpu.GetCarryFlag());
676 EXPECT_TRUE(cpu.GetZeroFlag());
677 EXPECT_FALSE(cpu.GetNegativeFlag());
678}
679
680TEST_F(CpuTest, ASL_DirectPageIndexedX) {
681 cpu.D = 0x1000; // Setting Direct Page register to 0x1000
682 cpu.X = 0x02; // Setting X register to 0x02
683 std::vector<uint8_t> data = {0x16, 0x10}; // ASL dp,X
684 mock_memory.SetMemoryContents(data);
685 mock_memory.InsertMemory(0x1012, {0x40}); // [0x1012] = 0x40
686
687 cpu.ExecuteInstruction(0x16); // ASL DP Indexed, X
688 EXPECT_TRUE(cpu.GetCarryFlag());
689 EXPECT_FALSE(cpu.GetZeroFlag());
690 EXPECT_TRUE(cpu.GetNegativeFlag());
691}
692
693TEST_F(CpuTest, ASL_AbsoluteIndexedX) {
694 cpu.X = 0x02; // Setting X register to 0x02
695 std::vector<uint8_t> data = {0x1E, 0x10, 0x20}; // ASL abs,X
696 mock_memory.SetMemoryContents(data);
697 mock_memory.InsertMemory(0x2012, {0x40}); // [0x2012] = 0x40
698
699 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x2010));
700 EXPECT_CALL(mock_memory, ReadByte(0x2012)).WillOnce(Return(0x40));
701
702 cpu.ExecuteInstruction(0x1E); // ASL Absolute, X
703 EXPECT_TRUE(cpu.GetCarryFlag());
704 EXPECT_TRUE(cpu.GetZeroFlag());
705 EXPECT_FALSE(cpu.GetNegativeFlag());
706}
707
708// ============================================================================
709// BCC - Branch if Carry Clear
710
711TEST_F(CpuTest, BCC_WhenCarryFlagClear) {
712 cpu.SetCarryFlag(false);
713 std::vector<uint8_t> data = {0x90, 0x05, 0x01}; // Operand at address 0x1001
714 mock_memory.SetMemoryContents(data);
715
716 EXPECT_CALL(mock_memory, ReadByte(_)).WillOnce(Return(5));
717
718 cpu.ExecuteInstruction(0x90); // BCC
719 EXPECT_EQ(cpu.PC, 0x05);
720}
721
722TEST_F(CpuTest, BCC_WhenCarryFlagSet) {
723 cpu.SetCarryFlag(true);
724 std::vector<uint8_t> data = {0x90, 0x02, 0x01};
725 mock_memory.SetMemoryContents(data);
726
727 EXPECT_CALL(mock_memory, ReadByte(_)).WillOnce(Return(2));
728
729 cpu.ExecuteInstruction(0x90); // BCC
730
731 EXPECT_EQ(cpu.PC, 2);
732}
733
734// ============================================================================
735// BCS - Branch if Carry Set
736
737TEST_F(CpuTest, BCS_WhenCarryFlagSet) {
738 cpu.SetCarryFlag(true);
739 std::vector<uint8_t> data = {0xB0, 0x07, 0x02}; // Operand at address 0x1001
740 mock_memory.SetMemoryContents(data);
741
742 EXPECT_CALL(mock_memory, ReadByte(_)).WillOnce(Return(0x07));
743
744 cpu.ExecuteInstruction(0xB0); // BCS
745 EXPECT_EQ(cpu.PC, 0x07);
746}
747
748TEST_F(CpuTest, BCS_WhenCarryFlagClear) {
749 cpu.SetCarryFlag(false);
750 std::vector<uint8_t> data = {0x10, 0x02, 0x01};
751 mock_memory.SetMemoryContents(data);
752 EXPECT_CALL(mock_memory, ReadByte(_)).WillOnce(Return(2));
753 cpu.ExecuteInstruction(0xB0); // BCS
754 EXPECT_EQ(cpu.PC, 2);
755}
756
757// ============================================================================
758// BEQ - Branch if Equal
759
760TEST_F(CpuTest, BEQ_Immediate_ZeroFlagSet) {
761 cpu.PB = 0x00;
762 cpu.SetZeroFlag(true);
763 std::vector<uint8_t> data = {0xF0, 0x09}; // Operand at address 0x1001
764 mock_memory.SetMemoryContents(data);
765
766 cpu.ExecuteInstruction(0xF0); // BEQ
767
768 EXPECT_EQ(cpu.PC, 0x09);
769}
770
771TEST_F(CpuTest, BEQ_Immediate_ZeroFlagClear) {
772 cpu.SetZeroFlag(false);
773 std::vector<uint8_t> data = {0xF0, 0x03}; // Operand at address 0x1001
774 mock_memory.SetMemoryContents(data);
775
776 EXPECT_CALL(mock_memory, ReadByte(_)).WillOnce(Return(0x03));
777
778 cpu.ExecuteInstruction(0xF0); // BEQ
779
780 EXPECT_EQ(cpu.PC, 0x02);
781}
782
783TEST_F(CpuTest, BEQ_Immediate_ZeroFlagSet_OverflowFlagSet) {
784 cpu.SetZeroFlag(true);
785 cpu.SetOverflowFlag(true);
786 std::vector<uint8_t> data = {0xF0, 0x03}; // Operand at address 0x1001
787 mock_memory.SetMemoryContents(data);
788
789 EXPECT_CALL(mock_memory, ReadByte(_)).WillOnce(Return(0x03));
790
791 cpu.ExecuteInstruction(0xF0); // BEQ
792
793 EXPECT_EQ(cpu.PC, 0x03);
794}
795
796TEST_F(CpuTest, BEQ_Immediate_ZeroFlagClear_OverflowFlagSet) {
797 cpu.SetZeroFlag(false);
798 cpu.SetOverflowFlag(true);
799 std::vector<uint8_t> data = {0xF0, 0x03, 0x02}; // Operand at address 0x1001
800 mock_memory.SetMemoryContents(data);
801
802 EXPECT_CALL(mock_memory, ReadByte(_)).WillOnce(Return(0x03));
803
804 cpu.ExecuteInstruction(0xF0); // BEQ
805
806 EXPECT_EQ(cpu.PC, 0x02);
807}
808
809// ============================================================================
810// BIT - Bit Test
811
812TEST_F(CpuTest, BIT_DirectPage) {
813 cpu.A = 0x01;
814 cpu.D = 0x1000; // Setting Direct Page register to 0x1000
815 cpu.status = 0xFF;
816 std::vector<uint8_t> data = {0x24, 0x10}; // BIT
817 mock_memory.SetMemoryContents(data);
818 mock_memory.InsertMemory(0x1010, {0x81}); // [0x1010] = 0x81
819
820 // Read the operand
821 EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(Return(0x10));
822
823 // Read the value at the address of the operand
824 EXPECT_CALL(mock_memory, ReadByte(0x1010)).WillOnce(Return(0x81));
825
826 cpu.ExecuteInstruction(0x24); // BIT
827 EXPECT_TRUE(cpu.GetNegativeFlag());
828 EXPECT_FALSE(cpu.GetOverflowFlag());
829 EXPECT_FALSE(cpu.GetZeroFlag());
830}
831
832TEST_F(CpuTest, BIT_Absolute) {
833 cpu.A = 0x01;
834 cpu.status = 0xFF;
835 std::vector<uint8_t> data = {0x00, 0x10}; // BIT
836 mock_memory.SetMemoryContents(data);
837 mock_memory.InsertMemory(0x0010, {0x81}); // [0x0010] = 0x81
838
839 // Read the operand
840 EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(Return(0x10));
841
842 // Read the value at the address of the operand
843 EXPECT_CALL(mock_memory, ReadByte(0x0010)).WillOnce(Return(0x81));
844
845 cpu.ExecuteInstruction(0x24); // BIT
846 EXPECT_TRUE(cpu.GetNegativeFlag());
847 EXPECT_FALSE(cpu.GetOverflowFlag());
848 EXPECT_FALSE(cpu.GetZeroFlag());
849}
850
851TEST_F(CpuTest, BIT_DirectPageIndexedX) {
852 cpu.A = 0x01;
853 cpu.X = 0x02;
854 cpu.D = 0x1000; // Setting Direct Page register to 0x1000
855 cpu.status = 0xFF;
856 std::vector<uint8_t> data = {0x34, 0x10}; // BIT
857 mock_memory.SetMemoryContents(data);
858 mock_memory.InsertMemory(0x1012, {0x81}); // [0x1010] = 0x81
859
860 // Read the operand
861 EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(Return(0x10));
862
863 // Read the value at the address of the operand
864 EXPECT_CALL(mock_memory, ReadByte(0x1012)).WillOnce(Return(0x81));
865
866 cpu.ExecuteInstruction(0x34); // BIT
867 EXPECT_TRUE(cpu.GetNegativeFlag());
868 EXPECT_FALSE(cpu.GetOverflowFlag());
869 EXPECT_FALSE(cpu.GetZeroFlag());
870}
871
872TEST_F(CpuTest, BIT_AbsoluteIndexedX) {
873 cpu.A = 0x01;
874 cpu.X = 0x02;
875 cpu.status = 0xFF;
876 std::vector<uint8_t> data = {0x00, 0x10}; // BIT
877 mock_memory.SetMemoryContents(data);
878 mock_memory.InsertMemory(0x0012, {0x81}); // [0x0010] = 0x81
879
880 // Read the operand
881 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x10));
882
883 // Read the value at the address of the operand
884 EXPECT_CALL(mock_memory, ReadByte(0x0012)).WillOnce(Return(0x81));
885
886 cpu.ExecuteInstruction(0x3C); // BIT
887 EXPECT_TRUE(cpu.GetNegativeFlag());
888 EXPECT_FALSE(cpu.GetOverflowFlag());
889 EXPECT_FALSE(cpu.GetZeroFlag());
890}
891
892TEST_F(CpuTest, BIT_Immediate) {
893 cpu.A = 0x01;
894 cpu.status = 0xFF;
895 std::vector<uint8_t> data = {0x24, 0x00, 0x10}; // BIT
896 mock_memory.SetMemoryContents(data);
897 mock_memory.InsertMemory(0x0010, {0x81}); // [0x0010] = 0x81
898
899 // Read the operand
900 EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(Return(0x10));
901
902 // Read the value at the address of the operand
903 EXPECT_CALL(mock_memory, ReadByte(0x0010)).WillOnce(Return(0x81));
904
905 cpu.ExecuteInstruction(0x24); // BIT
906 EXPECT_TRUE(cpu.GetNegativeFlag());
907 EXPECT_FALSE(cpu.GetOverflowFlag());
908 EXPECT_FALSE(cpu.GetZeroFlag());
909}
910
911// ============================================================================
912// BMI - Branch if Minus
913
914TEST_F(CpuTest, BMI_BranchTaken) {
915 cpu.SetNegativeFlag(true);
916 std::vector<uint8_t> data = {0x30, 0x05}; // BMI
917 mock_memory.SetMemoryContents(data);
918
919 cpu.ExecuteInstruction(0x30); // BMI
920 EXPECT_EQ(cpu.PC, 0x0005);
921}
922
923TEST_F(CpuTest, BMI_BranchNotTaken) {
924 cpu.SetNegativeFlag(false);
925 std::vector<uint8_t> data = {0x30, 0x02}; // BMI
926 mock_memory.SetMemoryContents(data);
927
928 cpu.ExecuteInstruction(0x30); // BMI
929 EXPECT_EQ(cpu.PC, 0x0002);
930}
931
932// ============================================================================
933// BNE - Branch if Not Equal
934
935TEST_F(CpuTest, BNE_BranchTaken) {
936 cpu.SetZeroFlag(false);
937 std::vector<uint8_t> data = {0xD0, 0x05}; // BNE
938 mock_memory.SetMemoryContents(data);
939
940 cpu.ExecuteInstruction(0xD0); // BNE
941 EXPECT_EQ(cpu.PC, 0x0007);
942}
943
944TEST_F(CpuTest, BNE_BranchNotTaken) {
945 cpu.SetZeroFlag(true);
946 std::vector<uint8_t> data = {0xD0, 0x05}; // BNE
947 mock_memory.SetMemoryContents(data);
948
949 cpu.ExecuteInstruction(0xD0); // BNE
950 EXPECT_EQ(cpu.PC, 0x0002);
951}
952
953// ============================================================================
954// BPL - Branch if Positive
955
956TEST_F(CpuTest, BPL_BranchTaken) {
957 cpu.SetNegativeFlag(false);
958 std::vector<uint8_t> data = {0x10, 0x07}; // BPL
959 mock_memory.SetMemoryContents(data);
960
961 cpu.ExecuteInstruction(0x10); // BPL
962 EXPECT_EQ(cpu.PC, 0x0007);
963}
964
965TEST_F(CpuTest, BPL_BranchNotTaken) {
966 cpu.SetNegativeFlag(true);
967 std::vector<uint8_t> data = {0x10, 0x02}; // BPL
968 mock_memory.SetMemoryContents(data);
969
970 cpu.ExecuteInstruction(0x10); // BPL
971 EXPECT_EQ(cpu.PC, 0x0002);
972}
973
974// ============================================================================
975// BRA - Branch Always
976
978 std::vector<uint8_t> data = {0x80, 0x02}; // BRA
979 mock_memory.SetMemoryContents(data);
980
981 cpu.ExecuteInstruction(0x80); // BRA
982 EXPECT_EQ(cpu.PC, 0x0004);
983}
984
985// ============================================================================
986
988 std::vector<uint8_t> data = {0x00}; // BRK
989 mock_memory.SetMemoryContents(data);
990 mock_memory.InsertMemory(0xFFFE, {0x10, 0x20}); // [0xFFFE] = 0x2010
991
992 EXPECT_CALL(mock_memory, ReadWord(0xFFFE)).WillOnce(Return(0x2010));
993
994 cpu.ExecuteInstruction(0x00); // BRK
995 EXPECT_EQ(cpu.PC, 0x2010);
996 EXPECT_TRUE(cpu.GetInterruptFlag());
997}
998
999// ============================================================================
1000// BRL - Branch Long
1001
1003 std::vector<uint8_t> data = {0x82, 0x10, 0x20}; // BRL
1004 mock_memory.SetMemoryContents(data);
1005
1006 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x2010));
1007
1008 cpu.ExecuteInstruction(0x82); // BRL
1009 EXPECT_EQ(cpu.PC, 0x2010);
1010}
1011
1012// ============================================================================
1013// BVC - Branch if Overflow Clear
1014
1015TEST_F(CpuTest, BVC_BranchTaken) {
1016 cpu.SetOverflowFlag(false);
1017 std::vector<uint8_t> data = {0x50, 0x02}; // BVC
1018 mock_memory.SetMemoryContents(data);
1019
1020 cpu.ExecuteInstruction(0x50); // BVC
1021 EXPECT_EQ(cpu.PC, 0x0002);
1022}
1023
1024// ============================================================================
1025// BVS - Branch if Overflow Set
1026
1027TEST_F(CpuTest, BVS_BranchTaken) {
1028 cpu.SetOverflowFlag(true);
1029 std::vector<uint8_t> data = {0x70, 0x02}; // BVS
1030 mock_memory.SetMemoryContents(data);
1031
1032 cpu.ExecuteInstruction(0x70); // BVS
1033 EXPECT_EQ(cpu.PC, 0x0002);
1034}
1035
1036// ============================================================================
1037// CLC - Clear Carry Flag
1038
1040 cpu.SetCarryFlag(true);
1041 cpu.PC = 0x0000;
1042 std::vector<uint8_t> data = {0x18}; // CLC
1043 mock_memory.SetMemoryContents(data);
1044
1045 cpu.ExecuteInstruction(0x18); // CLC
1046 EXPECT_FALSE(cpu.GetCarryFlag());
1047}
1048
1049// ============================================================================
1050// CLD - Clear Decimal Mode Flag
1051
1053 cpu.SetDecimalFlag(true);
1054 cpu.PC = 0x0000;
1055 std::vector<uint8_t> data = {0xD8}; // CLD
1056 mock_memory.SetMemoryContents(data);
1057
1058 cpu.ExecuteInstruction(0xD8); // CLD
1059 EXPECT_FALSE(cpu.GetDecimalFlag());
1060}
1061
1062// ============================================================================
1063// CLI - Clear Interrupt Disable Flag
1064
1066 cpu.SetInterruptFlag(true);
1067 cpu.PC = 0x0000;
1068 std::vector<uint8_t> data = {0x58}; // CLI
1069 mock_memory.SetMemoryContents(data);
1070
1071 cpu.ExecuteInstruction(0x58); // CLI
1072 EXPECT_FALSE(cpu.GetInterruptFlag());
1073}
1074
1075// ============================================================================
1076// CLV - Clear Overflow Flag
1077
1079 cpu.SetOverflowFlag(true);
1080 cpu.PC = 0x0000;
1081 std::vector<uint8_t> data = {0xB8}; // CLV
1082 mock_memory.SetMemoryContents(data);
1083
1084 cpu.ExecuteInstruction(0xB8); // CLV
1085 EXPECT_FALSE(cpu.GetOverflowFlag());
1086}
1087
1088// ============================================================================
1089// CMP - Compare Accumulator
1090
1091TEST_F(CpuTest, CMP_DirectPageIndexedIndirectX) {
1092 cpu.status = 0x00;
1093 cpu.SetAccumulatorSize(true);
1094 cpu.A = 0x80;
1095 cpu.X = 0x02;
1096 cpu.D = 0x1000;
1097 cpu.DB = 0x01;
1098 std::vector<uint8_t> data = {0xC1, 0x10};
1099 mock_memory.SetMemoryContents(data);
1100 mock_memory.InsertMemory(0x1012, {0x00, 0x30}); // [0x1012] = 0x3000
1101 mock_memory.InsertMemory(0x013000, {0x40}); // [0x3000] = 0x40
1102
1103 cpu.ExecuteInstruction(0xC1);
1104
1105 EXPECT_TRUE(cpu.GetCarryFlag());
1106 EXPECT_FALSE(cpu.GetZeroFlag());
1107 EXPECT_TRUE(cpu.GetNegativeFlag());
1108}
1109
1110TEST_F(CpuTest, CMP_StackRelative) {
1111 cpu.A = 0x80;
1112 mock_memory.SetSP(0x01FF);
1113 std::vector<uint8_t> data = {0xC3, 0x02};
1114 mock_memory.SetMemoryContents(data);
1115 mock_memory.InsertMemory(0x0201, {0x40, 0x9F});
1116
1117 EXPECT_CALL(mock_memory, SP()).WillRepeatedly(Return(0x01FF));
1118 EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(Return(0x02));
1119 EXPECT_CALL(mock_memory, ReadByte(0x0201)).WillOnce(Return(0x30));
1120
1121 // Execute the CMP Stack Relative instruction
1122 cpu.ExecuteInstruction(0xC3);
1123
1124 EXPECT_TRUE(cpu.GetCarryFlag());
1125 EXPECT_FALSE(cpu.GetZeroFlag());
1126 EXPECT_FALSE(cpu.GetNegativeFlag());
1127
1128 mock_memory.InsertMemory(0x0002, {0xC3, 0x03});
1129
1130 EXPECT_CALL(mock_memory, SP()).WillRepeatedly(Return(0x01FF));
1131 EXPECT_CALL(mock_memory, ReadByte(0x0003)).WillOnce(Return(0x03));
1132 EXPECT_CALL(mock_memory, ReadByte(0x0202)).WillOnce(Return(0x9F));
1133
1134 cpu.status = 0b00110000;
1135 cpu.ExecuteInstruction(0xC3);
1136
1137 EXPECT_TRUE(cpu.GetCarryFlag());
1138 EXPECT_FALSE(cpu.GetZeroFlag());
1139 EXPECT_TRUE(cpu.GetNegativeFlag());
1140}
1141
1142TEST_F(CpuTest, CMP_DirectPage) {
1143 // Set the accumulator to 8-bit mode
1144 cpu.status = 0x00;
1145 cpu.SetAccumulatorSize(true);
1146 cpu.A = 0x80; // Set the accumulator to 0x80
1147 mock_memory.InsertMemory(0x0000, {0xC5});
1148
1149 // Execute the CMP Direct Page instruction
1150 cpu.ExecuteInstruction(0xC5);
1151
1152 // Check the status flags
1153 EXPECT_TRUE(cpu.GetCarryFlag()); // Carry flag should be set
1154 EXPECT_FALSE(cpu.GetZeroFlag()); // Zero flag should not be set
1155 EXPECT_TRUE(cpu.GetNegativeFlag()); // Negative flag should be set
1156}
1157
1158TEST_F(CpuTest, CMP_DirectPageIndirectLong) {
1159 // Set the accumulator to 8-bit mode
1160 cpu.status = 0x00;
1161 cpu.SetAccumulatorSize(true);
1162 cpu.A = 0x80; // Set the accumulator to 0x80
1163
1164 // Set up the instruction and operand
1165 mock_memory.InsertMemory(0x0000, {0xC7, 0x02});
1166
1167 cpu.D = 0x1000; // Set the Direct Page register to 0x1000
1168
1169 mock_memory.InsertMemory(0x1002, {0x00, 0x00, 0x01});
1170 mock_memory.InsertMemory(0x010000, {0x40}); // [0x010000] = 0x40
1171
1172 // Execute the CMP Direct Page Indirect Long instruction
1173 cpu.ExecuteInstruction(0xC7);
1174
1175 // Check the status flags
1176 EXPECT_TRUE(cpu.GetCarryFlag()); // Carry flag should be set
1177 EXPECT_FALSE(cpu.GetZeroFlag()); // Zero flag should not be set
1178 EXPECT_FALSE(cpu.GetNegativeFlag()); // Negative flag should be set
1179}
1180
1181TEST_F(CpuTest, CMP_Immediate_8Bit) {
1182 // Set the accumulator to 8-bit mode
1183 cpu.status = 0x00;
1184 cpu.SetAccumulatorSize(true);
1185 cpu.A = 0x80; // Set the accumulator to 0x80
1186 mock_memory.InsertMemory(0x0000, {0x40});
1187
1188 // Set up the memory to return 0x40 when the Immediate addressing mode is used
1189 EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(::testing::Return(0x40));
1190
1191 // Execute the CMP Immediate instruction
1192 cpu.ExecuteInstruction(0xC9);
1193
1194 // Check the status flags
1195 EXPECT_TRUE(cpu.GetCarryFlag()); // Carry flag should be set
1196 EXPECT_FALSE(cpu.GetZeroFlag()); // Zero flag should not be set
1197 EXPECT_FALSE(cpu.GetNegativeFlag()); // Negative flag should be set
1198}
1199
1200TEST_F(CpuTest, CMP_Absolute_16Bit) {
1201 // Set the accumulator to 16-bit mode
1202 cpu.SetAccumulatorSize(false);
1203 cpu.A = 0x8000; // Set the accumulator to 0x8000
1204 mock_memory.InsertMemory(0x0000, {0x34, 0x12});
1205
1206 // Execute the CMP Absolute instruction
1207 cpu.ExecuteInstruction(0xCD);
1208
1209 // Check the status flags
1210 EXPECT_TRUE(cpu.GetCarryFlag()); // Carry flag should be set
1211 EXPECT_FALSE(cpu.GetZeroFlag()); // Zero flag should not be set
1212 EXPECT_TRUE(cpu.GetNegativeFlag()); // Negative flag should be set
1213}
1214
1215TEST_F(CpuTest, CMP_AbsoluteLong) {
1216 cpu.A = 0x01;
1217 cpu.status = 0b00000001; // 16-bit mode
1218 std::vector<uint8_t> data = {0xCF, 0x04, 0x00, 0x00, 0x05, 0x00};
1219
1220 mock_memory.SetMemoryContents(data);
1221 EXPECT_CALL(mock_memory, ReadWordLong(0x0001)).WillOnce(Return(0x000004));
1222
1223 EXPECT_CALL(mock_memory, ReadWord(0x0004)).WillOnce(Return(0x000005));
1224
1225 cpu.ExecuteInstruction(0xCF); // ADC Absolute Long
1226
1227 EXPECT_FALSE(cpu.GetCarryFlag());
1228 EXPECT_FALSE(cpu.GetZeroFlag());
1229 EXPECT_TRUE(cpu.GetNegativeFlag());
1230}
1231
1232TEST_F(CpuTest, CMP_DirectPageIndirect) {
1233 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
1234 cpu.D = 0x0200;
1235 std::vector<uint8_t> data = {0xD1, 0x3C};
1236 mock_memory.SetMemoryContents(data);
1237 mock_memory.InsertMemory(0x00023C, {0x00, 0x10});
1238
1239 EXPECT_CALL(mock_memory, ReadByte(0x000001)).WillOnce(Return(0x3C));
1240 EXPECT_CALL(mock_memory, ReadWord(0x00023C)).WillOnce(Return(0x1000));
1241
1242 EXPECT_CALL(mock_memory, ReadByte(0x1000)).WillOnce(Return(0x7F));
1243
1244 // Execute the CMP Direct Page Indirect instruction
1245 cpu.ExecuteInstruction(0xD1);
1246
1247 // Check the status flags
1248 EXPECT_TRUE(cpu.GetCarryFlag()); // Carry flag should be set
1249 EXPECT_FALSE(cpu.GetZeroFlag()); // Zero flag should not be set
1250 EXPECT_TRUE(cpu.GetNegativeFlag()); // Negative flag should be set
1251}
1252
1253TEST_F(CpuTest, CMP_StackRelativeIndirectIndexedY) {
1254 cpu.A = 0x03; // A register
1255 cpu.Y = 0x02; // Y register
1256 cpu.DB = 0x10; // Setting Data Bank register to 0x20
1257 mock_memory.SetSP(0x01FF); // Setting Stack Pointer to 0x01FF
1258 std::vector<uint8_t> data = {0xD3, 0x02}; // ADC sr, Y
1259 mock_memory.SetMemoryContents(data);
1260 mock_memory.InsertMemory(0x0201, {0x00, 0x30}); // [0x0201] = 0x3000
1261 mock_memory.InsertMemory(0x103002, {0x06}); // [0x3002] = 0x06
1262
1263 EXPECT_CALL(mock_memory, SP()).WillRepeatedly(Return(0x01FF));
1264 EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(Return(0x02));
1265 EXPECT_CALL(mock_memory, ReadWord(0x0201)).WillOnce(Return(0x3000));
1266 EXPECT_CALL(mock_memory, ReadByte(0x103002)).WillOnce(Return(0x06));
1267
1268 // Execute the CMP Stack Relative Indirect Indexed Y instruction
1269 cpu.ExecuteInstruction(0xD3);
1270
1271 // Check the status flags
1272 EXPECT_TRUE(cpu.GetCarryFlag()); // Carry flag should be set
1273 EXPECT_FALSE(cpu.GetZeroFlag()); // Zero flag should not be set
1274 EXPECT_TRUE(cpu.GetNegativeFlag()); // Negative flag should be set
1275}
1276
1277TEST_F(CpuTest, CMP_DirectPageIndexedX) {
1278 // Set the accumulator to 8-bit mode
1279 cpu.status = 0x00;
1280 cpu.SetAccumulatorSize(true);
1281 cpu.A = 0x80; // Set the accumulator to 0x80
1282 cpu.X = 0x02; // Set the X register to 0x02
1283 mock_memory.InsertMemory(0x0000, {0xD5});
1284
1285 // Set up the memory to return 0x40 when the Direct Page Indexed X addressing
1286 // mode is used
1287 EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(::testing::Return(0x40));
1288 EXPECT_CALL(mock_memory, ReadByte(0x0042)).WillOnce(::testing::Return(0x40));
1289
1290 // Execute the CMP Direct Page Indexed X instruction
1291 cpu.ExecuteInstruction(0xD5);
1292
1293 // Check the status flags
1294 EXPECT_TRUE(cpu.GetCarryFlag()); // Carry flag should be set
1295 EXPECT_FALSE(cpu.GetZeroFlag()); // Zero flag should not be set
1296 EXPECT_FALSE(cpu.GetNegativeFlag()); // Negative flag should be set
1297}
1298
1299TEST_F(CpuTest, CMP_DirectPageIndirectLongIndexedY) {
1300 cpu.A = 0b11110000; // A register
1301 cpu.D = 0x2000; // Setting Direct Page register to 0x2000
1302 cpu.Y = 0x02; // Y register
1303 std::vector<uint8_t> data = {0xD7, 0x10};
1304 mock_memory.SetMemoryContents(data);
1305 mock_memory.InsertMemory(0x2010, {0x05, 0x00, 0x30});
1306 mock_memory.InsertMemory(0x300005, {0b10101010});
1307
1308 EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(Return(0x10));
1309 EXPECT_CALL(mock_memory, ReadWordLong(0x2010)).WillOnce(Return(0x300005));
1310 EXPECT_CALL(mock_memory, ReadByte(0x300007)).WillOnce(Return(0b10101010));
1311
1312 // Execute the CMP Direct Page Indirect Long Indexed Y instruction
1313 cpu.ExecuteInstruction(0xD7);
1314
1315 // Check the status flags
1316 EXPECT_TRUE(cpu.GetCarryFlag()); // Carry flag should be set
1317 EXPECT_FALSE(cpu.GetZeroFlag()); // Zero flag should not be set
1318 EXPECT_FALSE(cpu.GetNegativeFlag()); // Negative flag should be set
1319}
1320
1321TEST_F(CpuTest, CMP_AbsoluteIndexedY) {
1322 // Set the accumulator to 16-bit mode
1323 cpu.SetAccumulatorSize(false);
1324 cpu.A = 0x8000; // Set the accumulator to 0x8000
1325 cpu.Y = 0x02; // Set the Y register to 0x02
1326 mock_memory.InsertMemory(0x0000, {0xD9});
1327
1328 // Execute the CMP Absolute Indexed Y instruction
1329 cpu.ExecuteInstruction(0xD9);
1330
1331 // Check the status flags
1332 EXPECT_TRUE(cpu.GetCarryFlag()); // Carry flag should be set
1333 EXPECT_FALSE(cpu.GetZeroFlag()); // Zero flag should not be set
1334 EXPECT_TRUE(cpu.GetNegativeFlag()); // Negative flag should be set
1335}
1336
1337TEST_F(CpuTest, CMP_AbsoluteIndexedX) {
1338 // Set the accumulator to 16-bit mode
1339 cpu.SetAccumulatorSize(false);
1340 cpu.A = 0x8000; // Set the accumulator to 0x8000
1341 cpu.X = 0x02; // Set the X register to 0x02
1342 mock_memory.InsertMemory(0x0000, {0xDD});
1343
1344 // Execute the CMP Absolute Indexed X instruction
1345 cpu.ExecuteInstruction(0xDD);
1346
1347 // Check the status flags
1348 EXPECT_TRUE(cpu.GetCarryFlag()); // Carry flag should be set
1349 EXPECT_FALSE(cpu.GetZeroFlag()); // Zero flag should not be set
1350 EXPECT_TRUE(cpu.GetNegativeFlag()); // Negative flag should be set
1351}
1352
1353TEST_F(CpuTest, CMP_AbsoluteLongIndexedX) {
1354 // Set the accumulator to 16-bit mode
1355 cpu.SetAccumulatorSize(false);
1356 cpu.A = 0x8000; // Set the accumulator to 0x8000
1357 cpu.X = 0x02; // Set the X register to 0x02
1358 mock_memory.InsertMemory(0x0000, {0xDF});
1359
1360 // Execute the CMP Absolute Long Indexed X instruction
1361 cpu.ExecuteInstruction(0xDF);
1362
1363 // Check the status flags
1364 EXPECT_TRUE(cpu.GetCarryFlag()); // Carry flag should be set
1365 EXPECT_FALSE(cpu.GetZeroFlag()); // Zero flag should not be set
1366 EXPECT_TRUE(cpu.GetNegativeFlag()); // Negative flag should be set
1367}
1368
1369// ============================================================================
1370
1371// TODO: FIX COP TEST
1373 // mock_memory.SetSP(0x01FF);
1374 // std::vector<uint8_t> data = {0x02}; // COP
1375 // mock_memory.SetMemoryContents(data);
1376 // mock_memory.InsertMemory(0xFFF4, {0x10, 0x20}); // [0xFFFE] = 0x2010
1377
1378 // ON_CALL(mock_memory, SetSP(_)).WillByDefault(::testing::Return());
1379 // EXPECT_CALL(mock_memory, PushWord(0x0002));
1380 // EXPECT_CALL(mock_memory, PushByte(0x30));
1381 // EXPECT_CALL(mock_memory, ReadWord(0xFFF4)).WillOnce(Return(0x2010));
1382
1383 // cpu.ExecuteInstruction(0x02); // COP
1384 // EXPECT_TRUE(cpu.GetInterruptFlag());
1385 // EXPECT_FALSE(cpu.GetDecimalFlag());
1386}
1387
1388// ============================================================================
1389// Test for CPX instruction
1390
1391TEST_F(CpuTest, CPX_Immediate_ZeroFlagSet) {
1392 cpu.SetIndexSize(false); // Set X register to 16-bit mode
1393 cpu.SetAccumulatorSize(false);
1394 cpu.X = 0x1234;
1395 std::vector<uint8_t> data = {0xE0, 0x34, 0x12}; // CPX #0x1234
1396 mock_memory.SetMemoryContents(data);
1397 cpu.ExecuteInstruction(0xE0); // Immediate CPX
1398 ASSERT_TRUE(cpu.GetZeroFlag()); // Zero flag should be set
1399}
1400
1401TEST_F(CpuTest, CPX_Immediate_NegativeFlagSet) {
1402 cpu.SetIndexSize(false); // Set X register to 16-bit mode
1403 cpu.PC = 0;
1404 cpu.X = 0x9000;
1405 std::vector<uint8_t> data = {0xE0, 0xFF, 0xFF}; // CPX #0x8001
1406 mock_memory.SetMemoryContents(data);
1407 cpu.ExecuteInstruction(0xE0); // Immediate CPX
1408 ASSERT_TRUE(cpu.GetNegativeFlag()); // Negative flag should be set
1409}
1410
1411// Test for CPX instruction
1412TEST_F(CpuTest, CPX_DirectPage) {
1413 cpu.SetIndexSize(false); // Set Y register to 16-bit mode
1414 cpu.PC = 0;
1415 cpu.X = 0x1234;
1416 std::vector<uint8_t> data = {0xE4, 0x34, 0x12}; // CPY #0x1234
1417 mock_memory.SetMemoryContents(data);
1418 cpu.ExecuteInstruction(0xE4); // Immediate CPY
1419 ASSERT_TRUE(cpu.GetCarryFlag()); // Carry flag should be set
1420}
1421
1422TEST_F(CpuTest, CPX_Absolute) {
1423 cpu.SetIndexSize(false); // Set Y register to 16-bit mode
1424 cpu.PC = 0;
1425 cpu.X = 0x1234;
1426 std::vector<uint8_t> data = {0xEC, 0x34, 0x12}; // CPY #0x1234
1427 mock_memory.SetMemoryContents(data);
1428 cpu.ExecuteInstruction(0xEC); // Immediate CPY
1429 ASSERT_TRUE(cpu.GetCarryFlag()); // Carry flag should be set
1430}
1431
1432TEST_F(CpuTest, CPY_Immediate_ZeroFlagSet) {
1433 cpu.SetIndexSize(false); // Set Y register to 16-bit mode
1434 cpu.SetAccumulatorSize(false);
1435 cpu.Y = 0x5678;
1436 std::vector<uint8_t> data = {0xC0, 0x78, 0x56}; // CPY #0x5678
1437 mock_memory.SetMemoryContents(data);
1438 cpu.ExecuteInstruction(0xC0); // Immediate CPY
1439 ASSERT_TRUE(cpu.GetZeroFlag()); // Zero flag should be set
1440}
1441
1442TEST_F(CpuTest, CPY_Immediate_NegativeFlagSet) {
1443 cpu.SetIndexSize(false); // Set Y register to 16-bit mode
1444 cpu.PC = 0;
1445 cpu.Y = 0x9000;
1446 std::vector<uint8_t> data = {0xC0, 0x01, 0x80}; // CPY #0x8001
1447 mock_memory.SetMemoryContents(data);
1448 cpu.ExecuteInstruction(0xC0); // Immediate CPY
1449 ASSERT_TRUE(cpu.GetNegativeFlag()); // Negative flag should be set
1450}
1451
1452// Test for CPY instruction
1453TEST_F(CpuTest, CPY_DirectPage) {
1454 cpu.SetIndexSize(false); // Set Y register to 16-bit mode
1455 cpu.PC = 0;
1456 cpu.Y = 0x1234;
1457 std::vector<uint8_t> data = {0xC4, 0x34, 0x12}; // CPY #0x1234
1458 mock_memory.SetMemoryContents(data);
1459 cpu.ExecuteInstruction(0xC4); // Immediate CPY
1460 ASSERT_TRUE(cpu.GetCarryFlag()); // Carry flag should be set
1461}
1462
1463TEST_F(CpuTest, CPY_Absolute) {
1464 cpu.SetIndexSize(false); // Set Y register to 16-bit mode
1465 cpu.PC = 0;
1466 cpu.Y = 0x1234;
1467 std::vector<uint8_t> data = {0xCC, 0x34, 0x12}; // CPY #0x1234
1468 mock_memory.SetMemoryContents(data);
1469 cpu.ExecuteInstruction(0xCC); // Immediate CPY
1470 ASSERT_TRUE(cpu.GetCarryFlag()); // Carry flag should be set
1471}
1472
1473// ============================================================================
1474// DEC - Decrement Memory
1475
1476TEST_F(CpuTest, DEC_Accumulator) {
1477 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
1478 cpu.A = 0x02; // Set A register to 2
1479 cpu.ExecuteInstruction(0x3A); // Execute DEC instruction
1480 EXPECT_EQ(0x01, cpu.A); // Expected value of A register after decrementing
1481
1482 cpu.A = 0x00; // Set A register to 0
1483 cpu.ExecuteInstruction(0x3A); // Execute DEC instruction
1484 EXPECT_EQ(0xFF, cpu.A); // Expected value of A register after decrementing
1485
1486 cpu.A = 0x80; // Set A register to 128
1487 cpu.ExecuteInstruction(0x3A); // Execute DEC instruction
1488 EXPECT_EQ(0x7F, cpu.A); // Expected value of A register after decrementing
1489}
1490
1491TEST_F(CpuTest, DEC_DirectPage) {
1492 cpu.status = 0xFF; // Set A register to 8-bit mode
1493 cpu.D = 0x1000; // Set Direct Page register to 0x1000
1494 std::vector<uint8_t> data = {0xC6, 0x7F};
1495 mock_memory.SetMemoryContents(data);
1496 mock_memory.InsertMemory(0x107F, {0x02}); // [0x107F] = 0x02
1497
1498 cpu.ExecuteInstruction(0xC6); // Execute DEC instruction
1499 EXPECT_EQ(0x01, mock_memory.ReadByte(0x107F)); // Expected value of memory
1500 // location after decrementing
1501}
1502
1503TEST_F(CpuTest, DEC_Absolute) {
1504 cpu.status = 0xFF; // Set A register to 8-bit mode
1505 std::vector<uint8_t> data = {0xCE, 0x00, 0x10};
1506 mock_memory.SetMemoryContents(data);
1507 mock_memory.InsertMemory(0x1000, {0x02}); // [0x1000] = 0x02
1508
1509 cpu.ExecuteInstruction(0xCE); // Execute DEC instruction
1510 EXPECT_EQ(0x01, mock_memory.ReadByte(0x1000)); // Expected value of memory
1511 // location after decrementing
1512}
1513
1514TEST_F(CpuTest, DEC_DirectPageIndexedX) {
1515 cpu.status = 0xFF; // Set A register to 8-bit mode
1516 cpu.D = 0x1000; // Set Direct Page register to 0x1000
1517 cpu.X = 0x02; // Set X register to 0x02
1518 std::vector<uint8_t> data = {0xD6, 0x7F};
1519 mock_memory.SetMemoryContents(data);
1520 mock_memory.InsertMemory(0x1081, {0x02}); // [0x1081] = 0x02
1521
1522 cpu.ExecuteInstruction(0xD6); // Execute DEC instruction
1523 EXPECT_EQ(0x01, mock_memory.ReadByte(0x1081)); // Expected value of memory
1524 // location after decrementing
1525}
1526
1527TEST_F(CpuTest, DEC_AbsoluteIndexedX) {
1528 cpu.status = 0xFF; // Set A register to 8-bit mode
1529 cpu.X = 0x02; // Set X register to 0x02
1530 std::vector<uint8_t> data = {0xDE, 0x00, 0x10};
1531 mock_memory.SetMemoryContents(data);
1532 mock_memory.InsertMemory(0x1002, {0x02}); // [0x1002] = 0x02
1533
1534 cpu.ExecuteInstruction(0xDE); // Execute DEC instruction
1535 EXPECT_EQ(0x01, mock_memory.ReadByte(0x1002)); // Expected value of memory
1536 // location after decrementing
1537}
1538
1539// ============================================================================
1540// Test for DEX instruction
1541
1543 cpu.SetIndexSize(true); // Set X register to 8-bit mode
1544 cpu.X = 0x02; // Set X register to 2
1545 cpu.ExecuteInstruction(0xCA); // Execute DEX instruction
1546 EXPECT_EQ(0x01, cpu.X); // Expected value of X register after decrementing
1547
1548 cpu.X = 0x00; // Set X register to 0
1549 cpu.ExecuteInstruction(0xCA); // Execute DEX instruction
1550 EXPECT_EQ(0xFF, cpu.X); // Expected value of X register after decrementing
1551
1552 cpu.X = 0x80; // Set X register to 128
1553 cpu.ExecuteInstruction(0xCA); // Execute DEX instruction
1554 EXPECT_EQ(0x7F, cpu.X); // Expected value of X register after decrementing
1555}
1556
1557// ============================================================================
1558// Test for DEY instruction
1559
1561 cpu.SetIndexSize(true); // Set Y register to 8-bit mode
1562 cpu.Y = 0x02; // Set Y register to 2
1563 cpu.ExecuteInstruction(0x88); // Execute DEY instruction
1564 EXPECT_EQ(0x01, cpu.Y); // Expected value of Y register after decrementing
1565
1566 cpu.Y = 0x00; // Set Y register to 0
1567 cpu.ExecuteInstruction(0x88); // Execute DEY instruction
1568 EXPECT_EQ(0xFF, cpu.Y); // Expected value of Y register after decrementing
1569
1570 cpu.Y = 0x80; // Set Y register to 128
1571 cpu.ExecuteInstruction(0x88); // Execute DEY instruction
1572 EXPECT_EQ(0x7F, cpu.Y); // Expected value of Y register after decrementing
1573}
1574
1575// ============================================================================
1576// EOR
1577
1578TEST_F(CpuTest, EOR_DirectPageIndexedIndirectX) {
1579 cpu.A = 0b10101010; // A register
1580 cpu.X = 0x02; // X register
1581 cpu.status = 0xFF; // 8-bit mode
1582 std::vector<uint8_t> data = {0x41, 0x7E};
1583 mock_memory.SetMemoryContents(data);
1584 mock_memory.InsertMemory(0x0080, {0x00, 0x10}); // [0x0080] = 0x1000
1585 mock_memory.InsertMemory(0x1000, {0b01010101}); // [0x1000] = 0b01010101
1586
1587 cpu.ExecuteInstruction(0x41); // EOR DP Indexed Indirect, X
1588 EXPECT_EQ(cpu.A, 0b11111111); // A register should now be 0b11111111
1589}
1590
1591TEST_F(CpuTest, EOR_StackRelative) {
1592 cpu.A = 0b10101010; // A register
1593 cpu.status = 0xFF; // 8-bit mode
1594 mock_memory.SetSP(0x01FF); // Set Stack Pointer to 0x01FF
1595 std::vector<uint8_t> data = {0x43, 0x02};
1596 mock_memory.SetMemoryContents(data);
1597 mock_memory.InsertMemory(0x0201, {0b01010101}); // [0x0201] = 0b01010101
1598
1599 EXPECT_CALL(mock_memory, SP()).WillRepeatedly(Return(0x01FF));
1600 EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(Return(0x02));
1601 EXPECT_CALL(mock_memory, ReadByte(0x0201)).WillOnce(Return(0b01010101));
1602
1603 cpu.ExecuteInstruction(0x43); // EOR Stack Relative
1604 EXPECT_EQ(cpu.A, 0b11111111); // A register should now be 0b11111111
1605}
1606
1607TEST_F(CpuTest, EOR_DirectPage) {
1608 cpu.A = 0b10101010; // A register
1609 cpu.status = 0xFF; // 8-bit mode
1610 std::vector<uint8_t> data = {0x45, 0x7F};
1611 mock_memory.SetMemoryContents(data);
1612 mock_memory.InsertMemory(0x007F, {0b01010101}); // [0x007F] = 0b01010101
1613
1614 cpu.ExecuteInstruction(0x45); // EOR Direct Page
1615 EXPECT_EQ(cpu.A, 0b11111111); // A register should now be 0b11111111
1616}
1617
1618TEST_F(CpuTest, EOR_DirectPageIndirectLong) {
1619 cpu.A = 0b10101010; // A register
1620 cpu.status = 0xFF; // 8-bit mode
1621 std::vector<uint8_t> data = {0x47, 0x7F};
1622 mock_memory.SetMemoryContents(data);
1623 mock_memory.InsertMemory(0x007F, {0x00, 0x10, 0x00}); // [0x007F] = 0x1000
1624 mock_memory.InsertMemory(0x1000, {0b01010101}); // [0x1000] = 0b01010101
1625
1626 cpu.ExecuteInstruction(0x47); // EOR Direct Page Indirect Long
1627 EXPECT_EQ(cpu.A, 0b11111111); // A register should now be 0b11111111
1628}
1629
1630TEST_F(CpuTest, EOR_Immediate_8bit) {
1631 cpu.A = 0b10101010; // A register
1632 cpu.status = 0xFF; // 8-bit mode
1633 std::vector<uint8_t> data = {0x49, 0b01010101};
1634 mock_memory.SetMemoryContents(data);
1635
1636 cpu.ExecuteInstruction(0x49); // EOR Immediate
1637 EXPECT_EQ(cpu.A, 0b11111111); // A register should now be 0b11111111
1638}
1639
1640TEST_F(CpuTest, EOR_Absolute) {
1641 cpu.A = 0b10101010; // A register
1642 cpu.status = 0xFF; // 8-bit mode
1643 std::vector<uint8_t> data = {0x4D, 0x00, 0x10};
1644 mock_memory.SetMemoryContents(data);
1645 mock_memory.InsertMemory(0x1000, {0b01010101}); // [0x1000] = 0b01010101
1646
1647 cpu.ExecuteInstruction(0x4D); // EOR Absolute
1648 EXPECT_EQ(cpu.A, 0b11111111); // A register should now be 0b11111111
1649}
1650
1651TEST_F(CpuTest, EOR_AbsoluteLong) {
1652 cpu.A = 0b10101010; // A register
1653 cpu.status = 0xFF; // 8-bit mode
1654 std::vector<uint8_t> data = {0x4F, 0x00, 0x10, 0x00};
1655 mock_memory.SetMemoryContents(data);
1656 mock_memory.InsertMemory(0x1000, {0b01010101}); // [0x1000] = 0b01010101
1657
1658 cpu.ExecuteInstruction(0x4F); // EOR Absolute Long
1659 EXPECT_EQ(cpu.A, 0b11111111); // A register should now be 0b11111111
1660}
1661
1662TEST_F(CpuTest, EOR_DirectPageIndirectIndexedY) {
1663 cpu.A = 0b10101010; // A register
1664 cpu.Y = 0x02; // Y register
1665 cpu.status = 0xFF; // 8-bit mode
1666 std::vector<uint8_t> data = {0x51, 0x7E};
1667 mock_memory.SetMemoryContents(data);
1668 mock_memory.InsertMemory(0x007E, {0x00, 0x10}); // [0x007E] = 0x1000
1669 mock_memory.InsertMemory(0x1002, {0b01010101}); // [0x1002] = 0b01010101
1670
1671 cpu.ExecuteInstruction(0x51); // EOR DP Indirect Indexed, Y
1672 EXPECT_EQ(cpu.A, 0b11111111); // A register should now be 0b11111111
1673}
1674
1675TEST_F(CpuTest, EOR_DirectPageIndirect) {
1676 cpu.A = 0b10101010; // A register
1677 cpu.status = 0xFF; // 8-bit mode
1678 std::vector<uint8_t> data = {0x52, 0x7E};
1679 mock_memory.SetMemoryContents(data);
1680 mock_memory.InsertMemory(0x007E, {0x00, 0x10}); // [0x007E] = 0x1000
1681 mock_memory.InsertMemory(0x1000, {0b01010101}); // [0x1000] = 0b01010101
1682
1683 cpu.ExecuteInstruction(0x52); // EOR DP Indirect
1684 EXPECT_EQ(cpu.A, 0b11111111); // A register should now be 0b11111111
1685}
1686
1687TEST_F(CpuTest, EOR_StackRelativeIndirectIndexedY) {
1688 cpu.A = 0b10101010; // A register
1689 cpu.Y = 0x02; // Y register
1690 cpu.status = 0xFF; // 8-bit mode
1691 std::vector<uint8_t> data = {0x53, 0x02};
1692 mock_memory.SetMemoryContents(data);
1693 mock_memory.InsertMemory(0x0201, {0x00, 0x10}); // [0x0201] = 0x1000
1694 mock_memory.InsertMemory(0x1002, {0b01010101}); // [0x1002] = 0b01010101
1695
1696 EXPECT_CALL(mock_memory, SP()).WillRepeatedly(Return(0x01FF));
1697 EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(Return(0x02));
1698 EXPECT_CALL(mock_memory, ReadWord(0x0201)).WillOnce(Return(0x1000));
1699 EXPECT_CALL(mock_memory, ReadByte(0x1002)).WillOnce(Return(0b01010101));
1700
1701 cpu.ExecuteInstruction(0x53); // EOR Stack Relative Indirect Indexed, Y
1702 EXPECT_EQ(cpu.A, 0b11111111); // A register should now be 0b11111111
1703}
1704
1705TEST_F(CpuTest, EOR_DirectPageIndexedX) {
1706 cpu.A = 0b10101010; // A register
1707 cpu.X = 0x02; // X register
1708 cpu.status = 0xFF; // 8-bit mode
1709 std::vector<uint8_t> data = {0x55, 0x7E};
1710 mock_memory.SetMemoryContents(data);
1711 mock_memory.InsertMemory(0x0080, {0b01010101}); // [0x0080] = 0b01010101
1712
1713 cpu.ExecuteInstruction(0x55); // EOR DP Indexed, X
1714 EXPECT_EQ(cpu.A, 0b11111111); // A register should now be 0b11111111
1715}
1716
1717TEST_F(CpuTest, EOR_DirectPageIndirectLongIndexedY) {
1718 cpu.A = 0b10101010; // A register
1719 cpu.Y = 0x02; // Y register
1720 cpu.status = 0xFF; // 8-bit mode
1721 std::vector<uint8_t> data = {0x51, 0x7E};
1722 mock_memory.SetMemoryContents(data);
1723 mock_memory.InsertMemory(0x007E, {0x00, 0x10, 0x00}); // [0x007E] = 0x1000
1724 mock_memory.InsertMemory(0x1002, {0b01010101}); // [0x1002] = 0b01010101
1725
1726 cpu.ExecuteInstruction(0x51); // EOR DP Indirect Long Indexed, Y
1727 EXPECT_EQ(cpu.A, 0b11111111); // A register should now be 0b11111111
1728}
1729
1730TEST_F(CpuTest, EOR_AbsoluteIndexedY) {
1731 cpu.A = 0b10101010; // A register
1732 cpu.Y = 0x02; // Y register
1733 cpu.status = 0xFF; // 8-bit mode
1734 // PC register
1735 std::vector<uint8_t> data = {0x59, 0x7C, 0x00};
1736 mock_memory.SetMemoryContents(data);
1737 mock_memory.InsertMemory(0x007E, {0b01010101}); // [0x007E] = 0b01010101
1738
1739 cpu.ExecuteInstruction(0x59); // EOR Absolute Indexed, Y
1740 EXPECT_EQ(cpu.A, 0b11111111); // A register should now be 0b11111111
1741}
1742
1743TEST_F(CpuTest, EOR_AbsoluteIndexedX) {
1744 cpu.A = 0b10101010; // A register
1745 cpu.X = 0x02; // X register
1746 cpu.status = 0xFF; // 8-bit mode
1747 // PC register
1748 std::vector<uint8_t> data = {0x5D, 0x7C, 0x00};
1749 mock_memory.SetMemoryContents(data);
1750 mock_memory.InsertMemory(0x007E, {0b01010101}); // [0x007E] = 0b01010101
1751
1752 cpu.ExecuteInstruction(0x5D); // EOR Absolute Indexed, X
1753 EXPECT_EQ(cpu.A, 0b11111111); // A register should now be 0b11111111
1754}
1755
1756TEST_F(CpuTest, EOR_AbsoluteLongIndexedX) {
1757 cpu.A = 0b10101010; // A register
1758 cpu.X = 0x02; // X register
1759 cpu.status = 0xFF; // 8-bit mode
1760 // PC register
1761 std::vector<uint8_t> data = {0x5F, 0x7C, 0x00, 0x00};
1762 mock_memory.SetMemoryContents(data);
1763 mock_memory.InsertMemory(0x007E, {0b01010101}); // [0x007E] = 0b01010101
1764
1765 cpu.ExecuteInstruction(0x5F); // EOR Absolute Long Indexed, X
1766 EXPECT_EQ(cpu.A, 0b11111111); // A register should now be 0b11111111
1767}
1768
1769// ============================================================================
1770// INC - Increment Memory
1771
1772TEST_F(CpuTest, INC_Accumulator) {
1773 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
1774 cpu.A = 0x02; // Set A register to 2
1775 cpu.ExecuteInstruction(0x1A); // Execute INC instruction
1776 EXPECT_EQ(0x03, cpu.A); // Expected value of A register after incrementing
1777
1778 cpu.A = 0xFF; // Set A register to 0xFF
1779 cpu.ExecuteInstruction(0x1A); // Execute INC instruction
1780 EXPECT_EQ(0x00, cpu.A); // Expected value of A register after incrementing
1781
1782 cpu.A = 0x7F; // Set A register to 127
1783 cpu.ExecuteInstruction(0x1A); // Execute INC instruction
1784 EXPECT_EQ(0x80, cpu.A); // Expected value of A register after incrementing
1785}
1786
1787TEST_F(CpuTest, INC_DirectPage_8bit) {
1788 cpu.SetAccumulatorSize(true);
1789 cpu.D = 0x0200; // Setting Direct Page register to 0x0200
1790 std::vector<uint8_t> data = {0xE6, 0x20};
1791 mock_memory.SetMemoryContents(data);
1792 mock_memory.InsertMemory(0x0220, {0x40}); // [0x0220] = 0x40
1793
1794 EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(Return(0x20));
1795 EXPECT_CALL(mock_memory, ReadByte(0x0220)).WillOnce(Return(0x40));
1796
1797 cpu.ExecuteInstruction(0xE6); // INC Direct Page
1798 EXPECT_EQ(mock_memory[0x0220], 0x41);
1799 EXPECT_FALSE(cpu.GetNegativeFlag());
1800 EXPECT_FALSE(cpu.GetZeroFlag());
1801}
1802
1803TEST_F(CpuTest, INC_Absolute_16bit) {
1804 std::vector<uint8_t> data = {0xEE, 0x00, 0x10};
1805 mock_memory.SetMemoryContents(data);
1806 mock_memory.InsertMemory(0x1000, {0x40}); // [0x1000] = 0x40
1807
1808 cpu.SetAccumulatorSize(false);
1809 cpu.ExecuteInstruction(0xEE); // INC Absolute
1810 EXPECT_EQ(mock_memory[0x1000], 0x41);
1811 EXPECT_FALSE(cpu.GetNegativeFlag());
1812 EXPECT_FALSE(cpu.GetZeroFlag());
1813}
1814
1815TEST_F(CpuTest, INC_DirectPage_ZeroResult_8bit) {
1816 cpu.D = 0x0200; // Setting Direct Page register to 0x0200
1817 std::vector<uint8_t> data = {0xE6, 0x20};
1818 mock_memory.SetMemoryContents(data);
1819 mock_memory.InsertMemory(0x0220, {0xFF}); // [0x0220] = 0xFF
1820
1821 cpu.SetAccumulatorSize(true);
1822 cpu.ExecuteInstruction(0xE6); // INC Direct Page
1823 EXPECT_FALSE(cpu.GetNegativeFlag());
1824 EXPECT_TRUE(cpu.GetZeroFlag());
1825}
1826
1827TEST_F(CpuTest, INC_Absolute_ZeroResult_16bit) {
1828 std::vector<uint8_t> data = {0xEE, 0x00, 0x10};
1829 mock_memory.SetMemoryContents(data);
1830 mock_memory.InsertMemory(0x1000, {0xFF}); // [0x1000] = 0xFF
1831
1832 cpu.SetAccumulatorSize(false);
1833 cpu.ExecuteInstruction(0xEE); // INC Absolute
1834 EXPECT_FALSE(cpu.GetNegativeFlag());
1835 EXPECT_FALSE(cpu.GetZeroFlag());
1836}
1837
1838TEST_F(CpuTest, INC_DirectPage_8bit_Overflow) {
1839 std::vector<uint8_t> data = {0xE6, 0x80};
1840 mock_memory.SetMemoryContents(data);
1841
1842 cpu.SetAccumulatorSize(true);
1843 cpu.ExecuteInstruction(0xE6); // INC Direct Page
1844 EXPECT_FALSE(cpu.GetNegativeFlag());
1845 EXPECT_FALSE(cpu.GetZeroFlag());
1846}
1847
1848TEST_F(CpuTest, INC_DirectPageIndexedX_8bit) {
1849 cpu.X = 0x01;
1850 cpu.D = 0x0200; // Setting Direct Page register to 0x0200
1851 std::vector<uint8_t> data = {0xF6, 0x20};
1852 mock_memory.SetMemoryContents(data);
1853 mock_memory.InsertMemory(0x0221, {0x40}); // [0x0221] = 0x40
1854
1855 EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(Return(0x20));
1856 EXPECT_CALL(mock_memory, ReadByte(0x0221)).WillOnce(Return(0x40));
1857
1858 cpu.ExecuteInstruction(0xF6); // INC Direct Page Indexed, X
1859 EXPECT_EQ(mock_memory[0x0221], 0x41);
1860 EXPECT_FALSE(cpu.GetNegativeFlag());
1861 EXPECT_FALSE(cpu.GetZeroFlag());
1862}
1863
1864TEST_F(CpuTest, INC_AbsoluteIndexedX_16bit) {
1865 cpu.X = 0x01;
1866 std::vector<uint8_t> data = {0xFE, 0x00, 0x10};
1867 mock_memory.SetMemoryContents(data);
1868 mock_memory.InsertMemory(0x1001, {0x40}); // [0x1001] = 0x40
1869
1870 cpu.SetAccumulatorSize(false);
1871 cpu.ExecuteInstruction(0xFE); // INC Absolute Indexed, X
1872 EXPECT_EQ(mock_memory[0x1001], 0x41);
1873 EXPECT_FALSE(cpu.GetNegativeFlag());
1874 EXPECT_FALSE(cpu.GetZeroFlag());
1875}
1877 cpu.SetIndexSize(true); // Set X register to 8-bit mode
1878 cpu.X = 0x7F;
1879 // cpu.INX();
1880 EXPECT_EQ(cpu.X, 0x80);
1881 EXPECT_TRUE(cpu.GetNegativeFlag());
1882 EXPECT_FALSE(cpu.GetZeroFlag());
1883
1884 cpu.X = 0xFF;
1885 // cpu.INX();
1886 EXPECT_EQ(cpu.X, 0x00);
1887 EXPECT_FALSE(cpu.GetNegativeFlag());
1888 EXPECT_TRUE(cpu.GetZeroFlag());
1889}
1890
1892 cpu.SetIndexSize(true); // Set Y register to 8-bit mode
1893 cpu.Y = 0x7F;
1894 // cpu.INY();
1895 EXPECT_EQ(cpu.Y, 0x80);
1896 EXPECT_TRUE(cpu.GetNegativeFlag());
1897 EXPECT_FALSE(cpu.GetZeroFlag());
1898
1899 cpu.Y = 0xFF;
1900 // cpu.INY();
1901 EXPECT_EQ(cpu.Y, 0x00);
1902 EXPECT_FALSE(cpu.GetNegativeFlag());
1903 EXPECT_TRUE(cpu.GetZeroFlag());
1904}
1905
1906// ============================================================================
1907// JMP - Jump to new location
1908
1909TEST_F(CpuTest, JMP_Absolute) {
1910 std::vector<uint8_t> data = {0x4C, 0x05, 0x20}; // JMP $2005
1911 mock_memory.SetMemoryContents(data);
1912
1913 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x2005));
1914
1915 cpu.ExecuteInstruction(0x4C); // JMP Absolute
1916 cpu.ExecuteInstruction(0xEA); // NOP
1917
1918 EXPECT_EQ(cpu.PC, 0x2006);
1919}
1920
1921TEST_F(CpuTest, JMP_Indirect) {
1922 std::vector<uint8_t> data = {0x6C, 0x03, 0x20, 0x05, 0x30}; // JMP ($2003)
1923 mock_memory.SetMemoryContents(data);
1924
1925 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x2003));
1926 EXPECT_CALL(mock_memory, ReadWord(0x2003)).WillOnce(Return(0x3005));
1927
1928 cpu.ExecuteInstruction(0x6C); // JMP Indirect
1929 EXPECT_EQ(cpu.PC, 0x3005);
1930}
1931
1932// ============================================================================
1933// JML - Jump Long
1934
1935TEST_F(CpuTest, JML_AbsoluteLong) {
1936 cpu.E = 0;
1937
1938 std::vector<uint8_t> data = {0x5C, 0x05, 0x00, 0x03}; // JML $030005
1939 mock_memory.SetMemoryContents(data);
1940 mock_memory.InsertMemory(0x030005, {0x00, 0x20, 0x00});
1941
1942 EXPECT_CALL(mock_memory, ReadWordLong(0x0001)).WillOnce(Return(0x030005));
1943
1944 cpu.ExecuteInstruction(0x5C); // JML Absolute Long
1945 EXPECT_EQ(cpu.PC, 0x0005);
1946 EXPECT_EQ(cpu.PB, 0x03); // The PBR should be updated to 0x03
1947}
1948
1949TEST_F(CpuTest, JMP_AbsoluteIndexedIndirectX) {
1950 cpu.X = 0x02;
1951 std::vector<uint8_t> data = {0x7C, 0x05, 0x20, 0x00}; // JMP ($2005, X)
1952 mock_memory.SetMemoryContents(data);
1953 mock_memory.InsertMemory(0x2007, {0x30, 0x05}); // [0x2007] = 0x0530
1954
1955 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x2005));
1956 EXPECT_CALL(mock_memory, ReadWord(0x2007)).WillOnce(Return(0x3005));
1957
1958 cpu.ExecuteInstruction(0x7C); // JMP Absolute Indexed Indirect
1959 EXPECT_EQ(cpu.PC, 0x3005);
1960}
1961
1962TEST_F(CpuTest, JMP_AbsoluteIndirectLong) {
1963 std::vector<uint8_t> data = {0xDC, 0x05, 0x20, 0x00}; // JMP [$2005]
1964 mock_memory.SetMemoryContents(data);
1965 mock_memory.InsertMemory(0x2005, {0x01, 0x30, 0x05}); // [0x2005] = 0x0530
1966
1967 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x2005));
1968 EXPECT_CALL(mock_memory, ReadWordLong(0x2005)).WillOnce(Return(0x013005));
1969
1970 cpu.ExecuteInstruction(0xDC); // JMP Absolute Indirect Long
1971 EXPECT_EQ(cpu.PC, 0x3005);
1972 EXPECT_EQ(cpu.PB, 0x01);
1973}
1974
1975// ============================================================================
1976// JSR - Jump to Subroutine
1977
1978TEST_F(CpuTest, JSR_Absolute) {
1979 std::vector<uint8_t> data = {0x20, 0x05, 0x20}; // JSR $2005
1980 mock_memory.SetMemoryContents(data);
1981
1982 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x2005));
1983 EXPECT_CALL(mock_memory, PushWord(0x0000)).Times(1);
1984
1985 cpu.ExecuteInstruction(0x20); // JSR Absolute
1986 EXPECT_EQ(cpu.PC, 0x2005);
1987
1988 // Continue executing some code
1989 cpu.ExecuteInstruction(0x60); // RTS
1990 EXPECT_EQ(cpu.PC, 0x0003);
1991}
1992
1993// ============================================================================
1994// JSL - Jump to Subroutine Long
1995
1996TEST_F(CpuTest, JSL_AbsoluteLong) {
1997 std::vector<uint8_t> data = {0x22, 0x05, 0x20, 0x00}; // JSL $002005
1998 mock_memory.SetMemoryContents(data);
1999
2000 EXPECT_CALL(mock_memory, ReadWordLong(0x0001)).WillOnce(Return(0x002005));
2001 EXPECT_CALL(mock_memory, PushLong(0x0000)).Times(1);
2002
2003 cpu.ExecuteInstruction(0x22); // JSL Absolute Long
2004 EXPECT_EQ(cpu.PC, 0x002005);
2005}
2006
2007TEST_F(CpuTest, JSL_AbsoluteIndexedIndirect) {
2008 cpu.X = 0x02;
2009 std::vector<uint8_t> data = {0xFC, 0x05, 0x20, 0x00}; // JSL $002005
2010 mock_memory.SetMemoryContents(data);
2011 mock_memory.InsertMemory(0x2007, {0x00, 0x20, 0x00});
2012
2013 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x2005));
2014 EXPECT_CALL(mock_memory, ReadWord(0x2007)).WillOnce(Return(0x002000));
2015
2016 cpu.ExecuteInstruction(0xFC); // JSL Absolute Long
2017 EXPECT_EQ(cpu.PC, 0x2000);
2018}
2019
2020// ============================================================================
2021// LDA - Load Accumulator
2022
2023TEST_F(CpuTest, LDA_DirectPageIndexedIndirectX) {
2024 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2025 cpu.X = 0x02; // Set X register to 0x02
2026 cpu.D = 0x0200; // Set Direct Page register to 0x0200
2027 std::vector<uint8_t> data = {0xA1, 0x3C};
2028 mock_memory.SetMemoryContents(data);
2029 mock_memory.InsertMemory(0x00023E, {0x00, 0x10});
2030
2031 EXPECT_CALL(mock_memory, ReadByte(0x000001)).WillOnce(Return(0x3C));
2032 EXPECT_CALL(mock_memory, ReadWord(0x00023E)).WillOnce(Return(0x1000));
2033
2034 EXPECT_CALL(mock_memory, ReadByte(0x1000)).WillOnce(Return(0x80));
2035
2036 cpu.ExecuteInstruction(0xA1); // LDA Direct Page Indexed Indirect, X
2037 EXPECT_EQ(cpu.A, 0x80);
2038 EXPECT_TRUE(cpu.GetNegativeFlag());
2039 EXPECT_FALSE(cpu.GetZeroFlag());
2040}
2041
2042TEST_F(CpuTest, LDA_StackRelative) {
2043 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2044 cpu.status = 0xFF; // 8-bit mode
2045 mock_memory.SetSP(0x01FF); // Set Stack Pointer to 0x01FF
2046 std::vector<uint8_t> data = {0xA3, 0x02};
2047 mock_memory.SetMemoryContents(data);
2048 mock_memory.InsertMemory(0x0201, {0x7F});
2049
2050 EXPECT_CALL(mock_memory, SP()).WillRepeatedly(Return(0x01FF));
2051 EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(Return(0x02));
2052 EXPECT_CALL(mock_memory, ReadByte(0x0201)).WillOnce(Return(0x7F));
2053
2054 cpu.ExecuteInstruction(0xA3); // LDA Stack Relative
2055 EXPECT_EQ(cpu.A, 0x7F);
2056 EXPECT_FALSE(cpu.GetNegativeFlag());
2057 EXPECT_FALSE(cpu.GetZeroFlag());
2058}
2059
2060TEST_F(CpuTest, LDA_DirectPage) {
2061 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2062 cpu.D = 0x0200;
2063 std::vector<uint8_t> data = {0xA5, 0x3C, 0x00};
2064 mock_memory.SetMemoryContents(data);
2065 mock_memory.InsertMemory(0x00023C, {0x80});
2066
2067 EXPECT_CALL(mock_memory, ReadByte(0x000001)).WillOnce(Return(0x3C));
2068 EXPECT_CALL(mock_memory, ReadByte(0x00023C)).WillOnce(Return(0x80));
2069
2070 cpu.ExecuteInstruction(0xA5); // LDA Direct Page
2071 EXPECT_EQ(cpu.A, 0x80);
2072 EXPECT_TRUE(cpu.GetNegativeFlag());
2073 EXPECT_FALSE(cpu.GetZeroFlag());
2074}
2075
2076TEST_F(CpuTest, LDA_DirectPageIndirectLong) {
2077 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2078 cpu.D = 0x0200;
2079 std::vector<uint8_t> data = {0xA7, 0x3C, 0x00};
2080 mock_memory.SetMemoryContents(data);
2081 mock_memory.InsertMemory(0x00023C, {0x00, 0x10, 0x00});
2082
2083 EXPECT_CALL(mock_memory, ReadByte(0x000001)).WillOnce(Return(0x3C));
2084 EXPECT_CALL(mock_memory, ReadWordLong(0x00023C)).WillOnce(Return(0x1000));
2085
2086 EXPECT_CALL(mock_memory, ReadByte(0x1000)).WillOnce(Return(0x80));
2087
2088 cpu.ExecuteInstruction(0xA7); // LDA Direct Page Indirect Long
2089 EXPECT_EQ(cpu.A, 0x80);
2090 EXPECT_TRUE(cpu.GetNegativeFlag());
2091 EXPECT_FALSE(cpu.GetZeroFlag());
2092}
2093
2094TEST_F(CpuTest, LDA_Immediate_8bit) {
2095 cpu.SetAccumulatorSize(true);
2096 std::vector<uint8_t> data = {0xA9, 0xFF};
2097 mock_memory.SetMemoryContents(data);
2098
2099 cpu.ExecuteInstruction(0xA9); // LDA Immediate
2100 EXPECT_EQ(cpu.A, 0xFF);
2101 EXPECT_TRUE(cpu.GetNegativeFlag());
2102 EXPECT_FALSE(cpu.GetZeroFlag());
2103}
2104
2105TEST_F(CpuTest, LDA_Immediate_16bit) {
2106 std::vector<uint8_t> data = {0xA9, 0x7F, 0xFF};
2107 mock_memory.SetMemoryContents(data);
2108
2109 cpu.SetAccumulatorSize(false);
2110 cpu.ExecuteInstruction(0xA9); // LDA Immediate
2111 EXPECT_EQ(cpu.A, 0xFF7F);
2112 EXPECT_TRUE(cpu.GetNegativeFlag());
2113 EXPECT_FALSE(cpu.GetZeroFlag());
2114}
2115
2116TEST_F(CpuTest, LDA_Absolute) {
2117 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2118 std::vector<uint8_t> data = {0xAD, 0x7F, 0xFF};
2119 mock_memory.SetMemoryContents(data);
2120 mock_memory.InsertMemory(0x7FFF, {0x7F});
2121
2122 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x7FFF));
2123
2124 EXPECT_CALL(mock_memory, ReadByte(0x7FFF)).WillOnce(Return(0x7F));
2125
2126 cpu.SetAccumulatorSize(true);
2127 cpu.ExecuteInstruction(0xAD); // LDA Absolute
2128 EXPECT_EQ(cpu.A, 0x7F);
2129 EXPECT_FALSE(cpu.GetZeroFlag());
2130}
2131
2132TEST_F(CpuTest, LDA_AbsoluteLong) {
2133 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2134 std::vector<uint8_t> data = {0xAF, 0x7F, 0xFF, 0x00};
2135 mock_memory.SetMemoryContents(data);
2136 mock_memory.InsertMemory(0x7FFF, {0x7F});
2137
2138 EXPECT_CALL(mock_memory, ReadWordLong(0x0001)).WillOnce(Return(0x7FFF));
2139
2140 EXPECT_CALL(mock_memory, ReadByte(0x7FFF)).WillOnce(Return(0x7F));
2141
2142 cpu.SetAccumulatorSize(true);
2143 cpu.ExecuteInstruction(0xAF); // LDA Absolute Long
2144 EXPECT_EQ(cpu.A, 0x7F);
2145 EXPECT_FALSE(cpu.GetZeroFlag());
2146}
2147
2148TEST_F(CpuTest, LDA_DirectPageIndirectIndexedY) {
2149 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2150 cpu.Y = 0x02; // Set Y register to 0x02
2151 cpu.D = 0x0200; // Set Direct Page register to 0x0200
2152 std::vector<uint8_t> data = {0xB1, 0x3C};
2153 mock_memory.SetMemoryContents(data);
2154 mock_memory.InsertMemory(0x00023C, {0x00, 0x10});
2155 mock_memory.InsertMemory(0x1002, {0x80});
2156
2157 EXPECT_CALL(mock_memory, ReadByte(0x000001)).WillOnce(Return(0x3C));
2158 EXPECT_CALL(mock_memory, ReadWord(0x00023C)).WillOnce(Return(0x1000));
2159
2160 EXPECT_CALL(mock_memory, ReadByte(0x1002)).WillOnce(Return(0x80));
2161
2162 cpu.ExecuteInstruction(0xB1); // LDA Direct Page Indirect Indexed, Y
2163 EXPECT_EQ(cpu.A, 0x80);
2164 EXPECT_TRUE(cpu.GetNegativeFlag());
2165 EXPECT_FALSE(cpu.GetZeroFlag());
2166}
2167
2168TEST_F(CpuTest, LDA_DirectPageIndirect) {
2169 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2170 cpu.D = 0x0200;
2171 std::vector<uint8_t> data = {0xA1, 0x3C};
2172 mock_memory.SetMemoryContents(data);
2173 mock_memory.InsertMemory(0x00023C, {0x00, 0x10});
2174
2175 EXPECT_CALL(mock_memory, ReadByte(0x000001)).WillOnce(Return(0x3C));
2176 EXPECT_CALL(mock_memory, ReadWord(0x00023C)).WillOnce(Return(0x1000));
2177
2178 EXPECT_CALL(mock_memory, ReadByte(0x1000)).WillOnce(Return(0x7F));
2179
2180 cpu.ExecuteInstruction(0xB2); // LDA Direct Page Indirect
2181 EXPECT_EQ(cpu.A, 0x7F);
2182 EXPECT_FALSE(cpu.GetZeroFlag());
2183}
2184
2185TEST_F(CpuTest, LDA_StackRelativeIndirectIndexedY) {
2186 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2187 cpu.Y = 0x02; // Set Y register to 0x02
2188 cpu.status = 0xFF; // 8-bit mode
2189 std::vector<uint8_t> data = {0xB3, 0x02};
2190 mock_memory.SetMemoryContents(data);
2191 mock_memory.InsertMemory(0x0201, {0x00, 0x10});
2192
2193 EXPECT_CALL(mock_memory, SP()).WillRepeatedly(Return(0x01FF));
2194 EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(Return(0x02));
2195 EXPECT_CALL(mock_memory, ReadWord(0x0201)).WillOnce(Return(0x1000));
2196
2197 EXPECT_CALL(mock_memory, ReadByte(0x1002)).WillOnce(Return(0x80));
2198
2199 cpu.ExecuteInstruction(0xB3); // LDA Stack Relative Indirect Indexed, Y
2200 EXPECT_EQ(cpu.A, 0x80);
2201 EXPECT_TRUE(cpu.GetNegativeFlag());
2202 EXPECT_FALSE(cpu.GetZeroFlag());
2203}
2204
2205TEST_F(CpuTest, LDA_DirectPageIndexedX) {
2206 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2207 cpu.X = 0x02; // Set X register to 0x02
2208 cpu.D = 0x0200; // Set Direct Page register to 0x0200
2209 std::vector<uint8_t> data = {0xB5, 0x3C};
2210 mock_memory.SetMemoryContents(data);
2211 mock_memory.InsertMemory(0x00023E, {0x7F});
2212
2213 EXPECT_CALL(mock_memory, ReadByte(0x000001)).WillOnce(Return(0x3C));
2214 EXPECT_CALL(mock_memory, ReadByte(0x00023E)).WillOnce(Return(0x80));
2215
2216 cpu.ExecuteInstruction(0xB5); // LDA Direct Page Indexed, X
2217 EXPECT_EQ(cpu.A, 0x80);
2218 EXPECT_TRUE(cpu.GetNegativeFlag());
2219 EXPECT_FALSE(cpu.GetZeroFlag());
2220}
2221
2222TEST_F(CpuTest, LDA_DirectPageIndirectLongIndexedY) {
2223 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2224 cpu.Y = 0x02; // Set Y register to 0x02
2225 cpu.D = 0x0200; // Set Direct Page register to 0x0200
2226 std::vector<uint8_t> data = {0xB7, 0x3C};
2227 mock_memory.SetMemoryContents(data);
2228 mock_memory.InsertMemory(0x00023C, {0x00, 0x10, 0x00});
2229
2230 EXPECT_CALL(mock_memory, ReadByte(0x000001)).WillOnce(Return(0x3C));
2231 EXPECT_CALL(mock_memory, ReadWordLong(0x00023C)).WillOnce(Return(0x1000));
2232
2233 EXPECT_CALL(mock_memory, ReadByte(0x1002)).WillOnce(Return(0x80));
2234
2235 cpu.ExecuteInstruction(0xB7); // LDA Direct Page Indirect Long Indexed, Y
2236 EXPECT_EQ(cpu.A, 0x80);
2237 EXPECT_TRUE(cpu.GetNegativeFlag());
2238 EXPECT_FALSE(cpu.GetZeroFlag());
2239}
2240
2241TEST_F(CpuTest, LDA_AbsoluteIndexedY) {
2242 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2243 cpu.Y = 0x02; // Set Y register to 0x02
2244 std::vector<uint8_t> data = {0xB9, 0x7F, 0xFF};
2245 mock_memory.SetMemoryContents(data);
2246 mock_memory.InsertMemory(0x8001, {0x80});
2247
2248 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x7FFF));
2249
2250 EXPECT_CALL(mock_memory, ReadByte(0x8001)).WillOnce(Return(0x80));
2251
2252 cpu.ExecuteInstruction(0xB9); // LDA Absolute Indexed, Y
2253 EXPECT_EQ(cpu.A, 0x80);
2254 EXPECT_FALSE(cpu.GetZeroFlag());
2255}
2256
2257TEST_F(CpuTest, LDA_AbsoluteIndexedX) {
2258 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2259 cpu.X = 0x02; // Set X register to 0x02
2260 std::vector<uint8_t> data = {0xBD, 0x7F, 0xFF};
2261 mock_memory.SetMemoryContents(data);
2262 mock_memory.InsertMemory(0x8001, {0x80});
2263
2264 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x7FFF));
2265
2266 EXPECT_CALL(mock_memory, ReadByte(0x8001)).WillOnce(Return(0x80));
2267
2268 cpu.ExecuteInstruction(0xBD); // LDA Absolute Indexed, X
2269 EXPECT_EQ(cpu.A, 0x80);
2270 EXPECT_FALSE(cpu.GetZeroFlag());
2271}
2272
2273TEST_F(CpuTest, LDA_AbsoluteLongIndexedX) {
2274 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2275 cpu.X = 0x02; // Set X register to 0x02
2276 std::vector<uint8_t> data = {0xBF, 0x7F, 0xFF, 0x00};
2277 mock_memory.SetMemoryContents(data);
2278 mock_memory.InsertMemory(0x8001, {0x80});
2279
2280 EXPECT_CALL(mock_memory, ReadWordLong(0x0001)).WillOnce(Return(0x7FFF));
2281
2282 EXPECT_CALL(mock_memory, ReadByte(0x8001)).WillOnce(Return(0x80));
2283
2284 cpu.ExecuteInstruction(0xBF); // LDA Absolute Long Indexed, X
2285 EXPECT_EQ(cpu.A, 0x80);
2286 EXPECT_FALSE(cpu.GetZeroFlag());
2287}
2288
2289// ============================================================================
2290
2291TEST_F(CpuTest, LDX_Immediate) {
2292 cpu.SetIndexSize(true); // Set X register to 8-bit mode
2293 std::vector<uint8_t> data = {0xA2, 0x42};
2294 mock_memory.SetMemoryContents(data);
2295
2296 cpu.ExecuteInstruction(0xA2); // LDX Immediate
2297 EXPECT_EQ(cpu.X, 0x42);
2298 EXPECT_FALSE(cpu.GetZeroFlag());
2299}
2300
2301TEST_F(CpuTest, LDX_DirectPage) {
2302 cpu.SetIndexSize(true); // Set X register to 8-bit mode
2303 std::vector<uint8_t> data = {0xA6, 0x80};
2304 mock_memory.SetMemoryContents(data);
2305 mock_memory.InsertMemory(0x0080, {0x42});
2306
2307 cpu.ExecuteInstruction(0xA6); // LDX Direct Page
2308 EXPECT_EQ(cpu.X, 0x42);
2309 EXPECT_FALSE(cpu.GetZeroFlag());
2310}
2311
2312TEST_F(CpuTest, LDX_Absolute) {
2313 cpu.SetIndexSize(true); // Set X register to 8-bit mode
2314 std::vector<uint8_t> data = {0xAE, 0x7F, 0xFF};
2315 mock_memory.SetMemoryContents(data);
2316 mock_memory.InsertMemory(0x7FFF, {0x42});
2317
2318 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x7FFF));
2319
2320 cpu.ExecuteInstruction(0xAE); // LDX Absolute
2321 EXPECT_EQ(cpu.X, 0x42);
2322 EXPECT_FALSE(cpu.GetZeroFlag());
2323}
2324
2325TEST_F(CpuTest, LDX_DirectPageIndexedY) {
2326 cpu.SetIndexSize(true); // Set X register to 8-bit mode
2327 cpu.Y = 0x02; // Set Y register to 0x02
2328 std::vector<uint8_t> data = {0xB6, 0x80};
2329 mock_memory.SetMemoryContents(data);
2330 mock_memory.InsertMemory(0x0082, {0x42});
2331
2332 cpu.ExecuteInstruction(0xB6); // LDX Direct Page Indexed, Y
2333 EXPECT_EQ(cpu.X, 0x42);
2334 EXPECT_FALSE(cpu.GetZeroFlag());
2335}
2336
2337TEST_F(CpuTest, LDX_AbsoluteIndexedY) {
2338 cpu.SetIndexSize(true); // Set X register to 8-bit mode
2339 cpu.Y = 0x02; // Set Y register to 0x02
2340 std::vector<uint8_t> data = {0xBE, 0x7F, 0xFF};
2341 mock_memory.SetMemoryContents(data);
2342 mock_memory.InsertMemory(0x8001, {0x42});
2343
2344 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x7FFF));
2345
2346 cpu.ExecuteInstruction(0xBE); // LDX Absolute Indexed, Y
2347 EXPECT_EQ(cpu.X, 0x42);
2348 EXPECT_FALSE(cpu.GetZeroFlag());
2349}
2350
2351// ============================================================================
2352
2353TEST_F(CpuTest, LDY_Immediate) {
2354 cpu.SetIndexSize(true); // Set Y register to 8-bit mode
2355 std::vector<uint8_t> data = {0xA0, 0x42};
2356 mock_memory.SetMemoryContents(data);
2357
2358 cpu.ExecuteInstruction(0xA0); // LDY Immediate
2359 EXPECT_EQ(cpu.Y, 0x42);
2360 EXPECT_FALSE(cpu.GetZeroFlag());
2361}
2362
2363TEST_F(CpuTest, LDY_DirectPage) {
2364 cpu.SetIndexSize(true); // Set Y register to 8-bit mode
2365 std::vector<uint8_t> data = {0xA4, 0x80};
2366 mock_memory.SetMemoryContents(data);
2367 mock_memory.InsertMemory(0x0080, {0x42});
2368
2369 cpu.ExecuteInstruction(0xA4); // LDY Direct Page
2370 EXPECT_EQ(cpu.Y, 0x42);
2371 EXPECT_FALSE(cpu.GetZeroFlag());
2372}
2373
2374TEST_F(CpuTest, LDY_Absolute) {
2375 cpu.SetIndexSize(true); // Set Y register to 8-bit mode
2376 std::vector<uint8_t> data = {0xAC, 0x7F, 0xFF};
2377 mock_memory.SetMemoryContents(data);
2378 mock_memory.InsertMemory(0x7FFF, {0x42});
2379
2380 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x7FFF));
2381
2382 cpu.ExecuteInstruction(0xAC); // LDY Absolute
2383 EXPECT_EQ(cpu.Y, 0x42);
2384 EXPECT_FALSE(cpu.GetZeroFlag());
2385}
2386
2387TEST_F(CpuTest, LDY_DirectPageIndexedX) {
2388 cpu.SetIndexSize(true); // Set Y register to 8-bit mode
2389 cpu.X = 0x02; // Set X register to 0x02
2390 std::vector<uint8_t> data = {0xB4, 0x80};
2391 mock_memory.SetMemoryContents(data);
2392 mock_memory.InsertMemory(0x0082, {0x42});
2393
2394 cpu.ExecuteInstruction(0xB4); // LDY Direct Page Indexed, X
2395 EXPECT_EQ(cpu.Y, 0x42);
2396 EXPECT_FALSE(cpu.GetZeroFlag());
2397}
2398
2399TEST_F(CpuTest, LDY_AbsoluteIndexedX) {
2400 cpu.SetIndexSize(true); // Set Y register to 8-bit mode
2401 cpu.X = 0x02; // Set X register to 0x02
2402 std::vector<uint8_t> data = {0xBC, 0x7F, 0xFF};
2403 mock_memory.SetMemoryContents(data);
2404 mock_memory.InsertMemory(0x8001, {0x42});
2405
2406 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x7FFF));
2407
2408 cpu.ExecuteInstruction(0xBC); // LDY Absolute Indexed, X
2409 EXPECT_EQ(cpu.Y, 0x42);
2410 EXPECT_FALSE(cpu.GetZeroFlag());
2411}
2412
2413// ============================================================================
2414
2415TEST_F(CpuTest, LSR_DirectPage) {
2416 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2417 std::vector<uint8_t> data = {0x46, 0x80};
2418 mock_memory.SetMemoryContents(data);
2419 mock_memory.InsertMemory(0x0080, {0x42});
2420
2421 cpu.ExecuteInstruction(0x46); // LSR Direct Page
2422 EXPECT_EQ(mock_memory[0x0080], 0x21);
2423 EXPECT_FALSE(cpu.GetNegativeFlag());
2424 EXPECT_FALSE(cpu.GetZeroFlag());
2425}
2426
2427TEST_F(CpuTest, LSR_Accumulator) {
2428 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2429 cpu.A = 0x42;
2430 cpu.ExecuteInstruction(0x4A); // LSR Accumulator
2431 EXPECT_EQ(cpu.A, 0x21);
2432 EXPECT_FALSE(cpu.GetNegativeFlag());
2433 EXPECT_FALSE(cpu.GetZeroFlag());
2434}
2435
2436TEST_F(CpuTest, LSR_Absolute) {
2437 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2438 std::vector<uint8_t> data = {0x4E, 0x7F, 0xFF};
2439 mock_memory.SetMemoryContents(data);
2440 mock_memory.InsertMemory(0x7FFF, {0x42});
2441
2442 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x7FFF));
2443
2444 cpu.ExecuteInstruction(0x4E); // LSR Absolute
2445 EXPECT_EQ(mock_memory[0x7FFF], 0x21);
2446 EXPECT_FALSE(cpu.GetNegativeFlag());
2447 EXPECT_FALSE(cpu.GetZeroFlag());
2448}
2449
2450TEST_F(CpuTest, LSR_DirectPageIndexedX) {
2451 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2452 cpu.X = 0x02; // Set X register to 0x02
2453 std::vector<uint8_t> data = {0x56, 0x80};
2454 mock_memory.SetMemoryContents(data);
2455 mock_memory.InsertMemory(0x0082, {0x42});
2456
2457 cpu.ExecuteInstruction(0x56); // LSR Direct Page Indexed, X
2458 EXPECT_EQ(mock_memory[0x0082], 0x21);
2459 EXPECT_FALSE(cpu.GetNegativeFlag());
2460 EXPECT_FALSE(cpu.GetZeroFlag());
2461}
2462
2463TEST_F(CpuTest, LSR_AbsoluteIndexedX) {
2464 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2465 cpu.X = 0x02; // Set X register to 0x02
2466 std::vector<uint8_t> data = {0x5E, 0x7F, 0xFF};
2467 mock_memory.SetMemoryContents(data);
2468 mock_memory.InsertMemory(0x8001, {0x42});
2469
2470 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x7FFF));
2471
2472 cpu.ExecuteInstruction(0x5E); // LSR Absolute Indexed, X
2473 EXPECT_EQ(mock_memory[0x8001], 0x21);
2474 EXPECT_FALSE(cpu.GetNegativeFlag());
2475 EXPECT_FALSE(cpu.GetZeroFlag());
2476}
2477
2478// ============================================================================
2479// Stack Tests
2480
2481TEST_F(CpuTest, ORA_DirectPageIndexedIndirectX) {
2482 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2483 cpu.X = 0x02; // Set X register to 0x02
2484 cpu.D = 0x0200; // Set Direct Page register to 0x0200
2485 std::vector<uint8_t> data = {0x01, 0x3C};
2486 mock_memory.SetMemoryContents(data);
2487 mock_memory.InsertMemory(0x00023E, {0x00, 0x10});
2488
2489 EXPECT_CALL(mock_memory, ReadByte(0x000001)).WillOnce(Return(0x3C));
2490 EXPECT_CALL(mock_memory, ReadWord(0x00023E)).WillOnce(Return(0x1000));
2491
2492 EXPECT_CALL(mock_memory, ReadByte(0x1000)).WillOnce(Return(0x80));
2493
2494 cpu.ExecuteInstruction(0x01); // ORA Direct Page Indexed Indirect, X
2495 EXPECT_EQ(cpu.A, 0x80);
2496 EXPECT_TRUE(cpu.GetNegativeFlag());
2497 EXPECT_FALSE(cpu.GetZeroFlag());
2498}
2499
2500TEST_F(CpuTest, ORA_StackRelative) {
2501 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2502 cpu.status = 0xFF; // 8-bit mode
2503 mock_memory.SetSP(0x01FF); // Set Stack Pointer to 0x01FF
2504 std::vector<uint8_t> data = {0x03, 0x02};
2505 mock_memory.SetMemoryContents(data);
2506 mock_memory.InsertMemory(0x0201, {0x7F});
2507
2508 EXPECT_CALL(mock_memory, SP()).WillRepeatedly(Return(0x01FF));
2509 EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(Return(0x02));
2510 EXPECT_CALL(mock_memory, ReadByte(0x0201)).WillOnce(Return(0x7F));
2511
2512 cpu.ExecuteInstruction(0x03); // ORA Stack Relative
2513 EXPECT_EQ(cpu.A, 0x7F);
2514 EXPECT_FALSE(cpu.GetNegativeFlag());
2515 EXPECT_FALSE(cpu.GetZeroFlag());
2516}
2517
2518TEST_F(CpuTest, ORA_DirectPage) {
2519 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2520 cpu.D = 0x0200;
2521 std::vector<uint8_t> data = {0x05, 0x3C, 0x00};
2522 mock_memory.SetMemoryContents(data);
2523 mock_memory.InsertMemory(0x00023C, {0x80});
2524
2525 EXPECT_CALL(mock_memory, ReadByte(0x000001)).WillOnce(Return(0x3C));
2526 EXPECT_CALL(mock_memory, ReadByte(0x00023C)).WillOnce(Return(0x80));
2527
2528 cpu.ExecuteInstruction(0x05); // ORA Direct Page
2529 EXPECT_EQ(cpu.A, 0x80);
2530 EXPECT_TRUE(cpu.GetNegativeFlag());
2531 EXPECT_FALSE(cpu.GetZeroFlag());
2532}
2533
2534TEST_F(CpuTest, ORA_DirectPageIndirectLong) {
2535 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2536 cpu.D = 0x0200;
2537 std::vector<uint8_t> data = {0x07, 0x3C, 0x00};
2538 mock_memory.SetMemoryContents(data);
2539 mock_memory.InsertMemory(0x00023C, {0x00, 0x10, 0x00});
2540
2541 EXPECT_CALL(mock_memory, ReadByte(0x000001)).WillOnce(Return(0x3C));
2542 EXPECT_CALL(mock_memory, ReadWordLong(0x00023C)).WillOnce(Return(0x1000));
2543
2544 EXPECT_CALL(mock_memory, ReadByte(0x1000)).WillOnce(Return(0x80));
2545
2546 cpu.ExecuteInstruction(0x07); // ORA Direct Page Indirect Long
2547 EXPECT_EQ(cpu.A, 0x80);
2548 EXPECT_TRUE(cpu.GetNegativeFlag());
2549 EXPECT_FALSE(cpu.GetZeroFlag());
2550}
2551
2552TEST_F(CpuTest, ORA_Immediate) {
2553 cpu.SetAccumulatorSize(true);
2554 std::vector<uint8_t> data = {0x09, 0xFF};
2555 mock_memory.SetMemoryContents(data);
2556
2557 cpu.ExecuteInstruction(0x09); // ORA Immediate
2558 EXPECT_EQ(cpu.A, 0xFF);
2559 EXPECT_TRUE(cpu.GetNegativeFlag());
2560 EXPECT_FALSE(cpu.GetZeroFlag());
2561}
2562
2563TEST_F(CpuTest, ORA_Absolute) {
2564 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2565 std::vector<uint8_t> data = {0x0D, 0x7F, 0xFF};
2566 mock_memory.SetMemoryContents(data);
2567 mock_memory.InsertMemory(0x7FFF, {0x7F});
2568
2569 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x7FFF));
2570
2571 EXPECT_CALL(mock_memory, ReadByte(0x7FFF)).WillOnce(Return(0x7F));
2572
2573 cpu.SetAccumulatorSize(true);
2574 cpu.ExecuteInstruction(0x0D); // ORA Absolute
2575 EXPECT_EQ(cpu.A, 0x7F);
2576 EXPECT_FALSE(cpu.GetZeroFlag());
2577}
2578
2579TEST_F(CpuTest, ORA_AbsoluteLong) {
2580 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2581 std::vector<uint8_t> data = {0x0F, 0x7F, 0xFF, 0x00};
2582 mock_memory.SetMemoryContents(data);
2583 mock_memory.InsertMemory(0x7FFF, {0x7F});
2584
2585 EXPECT_CALL(mock_memory, ReadWordLong(0x0001)).WillOnce(Return(0x7FFF));
2586
2587 EXPECT_CALL(mock_memory, ReadByte(0x7FFF)).WillOnce(Return(0x7F));
2588
2589 cpu.SetAccumulatorSize(true);
2590 cpu.ExecuteInstruction(0x0F); // ORA Absolute Long
2591 EXPECT_EQ(cpu.A, 0x7F);
2592 EXPECT_FALSE(cpu.GetZeroFlag());
2593}
2594
2595TEST_F(CpuTest, ORA_DirectPageIndirectIndexedY) {
2596 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2597 cpu.Y = 0x02; // Set Y register to 0x02
2598 cpu.D = 0x0200; // Set Direct Page register to 0x0200
2599 std::vector<uint8_t> data = {0x11, 0x3C};
2600 mock_memory.SetMemoryContents(data);
2601 mock_memory.InsertMemory(0x00023C, {0x00, 0x10});
2602 mock_memory.InsertMemory(0x1002, {0x80});
2603
2604 EXPECT_CALL(mock_memory, ReadByte(0x000001)).WillOnce(Return(0x3C));
2605 EXPECT_CALL(mock_memory, ReadWord(0x00023C)).WillOnce(Return(0x1000));
2606
2607 EXPECT_CALL(mock_memory, ReadByte(0x1002)).WillOnce(Return(0x80));
2608
2609 cpu.ExecuteInstruction(0x11); // ORA Direct Page Indirect Indexed, Y
2610 EXPECT_EQ(cpu.A, 0x80);
2611 EXPECT_TRUE(cpu.GetNegativeFlag());
2612 EXPECT_FALSE(cpu.GetZeroFlag());
2613}
2614
2615TEST_F(CpuTest, ORA_DirectPageIndirect) {
2616 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2617 cpu.D = 0x0200;
2618 std::vector<uint8_t> data = {0x12, 0x3C};
2619 mock_memory.SetMemoryContents(data);
2620 mock_memory.InsertMemory(0x00023C, {0x00, 0x10});
2621
2622 EXPECT_CALL(mock_memory, ReadByte(0x000001)).WillOnce(Return(0x3C));
2623 EXPECT_CALL(mock_memory, ReadWord(0x00023C)).WillOnce(Return(0x1000));
2624
2625 EXPECT_CALL(mock_memory, ReadByte(0x1000)).WillOnce(Return(0x7F));
2626
2627 cpu.ExecuteInstruction(0x12); // ORA Direct Page Indirect
2628 EXPECT_EQ(cpu.A, 0x7F);
2629 EXPECT_FALSE(cpu.GetZeroFlag());
2630}
2631
2632TEST_F(CpuTest, ORA_StackRelativeIndirectIndexedY) {
2633 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2634 cpu.Y = 0x02; // Set Y register to 0x02
2635 cpu.status = 0xFF; // 8-bit mode
2636 std::vector<uint8_t> data = {0x13, 0x02};
2637 mock_memory.SetMemoryContents(data);
2638 mock_memory.InsertMemory(0x0201, {0x00, 0x10});
2639
2640 EXPECT_CALL(mock_memory, SP()).WillRepeatedly(Return(0x01FF));
2641 EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(Return(0x02));
2642 EXPECT_CALL(mock_memory, ReadWord(0x0201)).WillOnce(Return(0x1000));
2643
2644 EXPECT_CALL(mock_memory, ReadByte(0x1002)).WillOnce(Return(0x80));
2645
2646 cpu.ExecuteInstruction(0x13); // ORA Stack Relative Indirect Indexed, Y
2647 EXPECT_EQ(cpu.A, 0x80);
2648 EXPECT_TRUE(cpu.GetNegativeFlag());
2649 EXPECT_FALSE(cpu.GetZeroFlag());
2650}
2651
2652TEST_F(CpuTest, ORA_DirectPageIndexedX) {
2653 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2654 cpu.X = 0x02; // Set X register to 0x02
2655 cpu.D = 0x0200; // Set Direct Page register to 0x0200
2656 std::vector<uint8_t> data = {0x15, 0x3C};
2657 mock_memory.SetMemoryContents(data);
2658 mock_memory.InsertMemory(0x00023E, {0x80});
2659
2660 EXPECT_CALL(mock_memory, ReadByte(0x000001)).WillOnce(Return(0x3C));
2661 EXPECT_CALL(mock_memory, ReadByte(0x00023E)).WillOnce(Return(0x80));
2662
2663 cpu.ExecuteInstruction(0x15); // ORA Direct Page Indexed, X
2664 EXPECT_EQ(cpu.A, 0x80);
2665 EXPECT_TRUE(cpu.GetNegativeFlag());
2666 EXPECT_FALSE(cpu.GetZeroFlag());
2667}
2668
2669TEST_F(CpuTest, ORA_DirectPageIndirectLongIndexedY) {
2670 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2671 cpu.Y = 0x02; // Set Y register to 0x02
2672 cpu.D = 0x0200; // Set Direct Page register to 0x0200
2673 std::vector<uint8_t> data = {0x17, 0x3C};
2674 mock_memory.SetMemoryContents(data);
2675 mock_memory.InsertMemory(0x00023C, {0x00, 0x10, 0x00});
2676
2677 EXPECT_CALL(mock_memory, ReadByte(0x000001)).WillOnce(Return(0x3C));
2678 EXPECT_CALL(mock_memory, ReadWordLong(0x00023C)).WillOnce(Return(0x1000));
2679
2680 EXPECT_CALL(mock_memory, ReadByte(0x1002)).WillOnce(Return(0x80));
2681
2682 cpu.ExecuteInstruction(0x17); // ORA Direct Page Indirect Long Indexed, Y
2683 EXPECT_EQ(cpu.A, 0x80);
2684 EXPECT_TRUE(cpu.GetNegativeFlag());
2685 EXPECT_FALSE(cpu.GetZeroFlag());
2686}
2687
2688TEST_F(CpuTest, ORA_AbsoluteIndexedY) {
2689 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2690 cpu.Y = 0x02; // Set Y register to 0x02
2691 std::vector<uint8_t> data = {0x19, 0x7F, 0xFF};
2692 mock_memory.SetMemoryContents(data);
2693 mock_memory.InsertMemory(0x8001, {0x7F});
2694
2695 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x7FFF));
2696
2697 EXPECT_CALL(mock_memory, ReadByte(0x8001)).WillOnce(Return(0x7F));
2698
2699 cpu.ExecuteInstruction(0x19); // ORA Absolute Indexed, Y
2700 EXPECT_EQ(cpu.A, 0x7F);
2701 EXPECT_FALSE(cpu.GetZeroFlag());
2702}
2703
2704TEST_F(CpuTest, ORA_AbsoluteIndexedX) {
2705 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2706 cpu.X = 0x02; // Set X register to 0x02
2707 std::vector<uint8_t> data = {0x1D, 0x7F, 0xFF};
2708 mock_memory.SetMemoryContents(data);
2709 mock_memory.InsertMemory(0x8001, {0x7F});
2710
2711 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x7FFF));
2712
2713 EXPECT_CALL(mock_memory, ReadByte(0x8001)).WillOnce(Return(0x7F));
2714
2715 cpu.ExecuteInstruction(0x1D); // ORA Absolute Indexed, X
2716 EXPECT_EQ(cpu.A, 0x7F);
2717 EXPECT_FALSE(cpu.GetZeroFlag());
2718}
2719
2720TEST_F(CpuTest, ORA_AbsoluteLongIndexedX) {
2721 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2722 cpu.X = 0x02; // Set X register to 0x02
2723 std::vector<uint8_t> data = {0x1F, 0x7F, 0xFF, 0x00};
2724 mock_memory.SetMemoryContents(data);
2725 mock_memory.InsertMemory(0x8001, {0x7F});
2726
2727 EXPECT_CALL(mock_memory, ReadWordLong(0x0001)).WillOnce(Return(0x7FFF));
2728
2729 EXPECT_CALL(mock_memory, ReadByte(0x8001)).WillOnce(Return(0x7F));
2730
2731 cpu.ExecuteInstruction(0x1F); // ORA Absolute Long Indexed, X
2732 EXPECT_EQ(cpu.A, 0x7F);
2733 EXPECT_FALSE(cpu.GetZeroFlag());
2734}
2735
2736// ============================================================================
2737
2739 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2740 std::vector<uint8_t> data = {0xF4, 0x7F, 0xFF};
2741 mock_memory.SetMemoryContents(data);
2742
2743 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x7FFF));
2744 EXPECT_CALL(mock_memory, PushWord(0x7FFF));
2745
2746 cpu.ExecuteInstruction(0xF4); // PEA
2747}
2748
2750 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2751 std::vector<uint8_t> data = {0xD4, 0x3C, 0x00};
2752 mock_memory.SetMemoryContents(data);
2753 mock_memory.InsertMemory(0x00003C, {0x00, 0x10});
2754
2755 EXPECT_CALL(mock_memory, ReadWord(0x000001)).WillOnce(Return(0x3C));
2756 EXPECT_CALL(mock_memory, ReadWord(0x00003C)).WillOnce(Return(0x1000));
2757
2758 EXPECT_CALL(mock_memory, PushWord(0x1000));
2759
2760 cpu.ExecuteInstruction(0xD4); // PEI
2761}
2762
2764 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2765 std::vector<uint8_t> data = {0x62, 0x7F, 0xFF};
2766 mock_memory.SetMemoryContents(data);
2767
2768 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x7FFF));
2769 EXPECT_CALL(mock_memory, PushWord(0x7FFF));
2770
2771 cpu.ExecuteInstruction(0x62); // PER
2772}
2773
2775 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2776 cpu.D = 0x7FFF;
2777 std::vector<uint8_t> data = {0x0B};
2778 mock_memory.SetMemoryContents(data);
2779
2780 EXPECT_CALL(mock_memory, PushWord(0x7FFF));
2781
2782 cpu.ExecuteInstruction(0x0B); // PHD
2783}
2784
2786 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2787 cpu.PB = 0x7F;
2788 std::vector<uint8_t> data = {0x4B};
2789 mock_memory.SetMemoryContents(data);
2790
2791 EXPECT_CALL(mock_memory, PushByte(0x7F));
2792
2793 cpu.ExecuteInstruction(0x4B); // PHK
2794}
2795
2797 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2798 cpu.status = 0x7F;
2799 std::vector<uint8_t> data = {0x08};
2800 mock_memory.SetMemoryContents(data);
2801
2802 EXPECT_CALL(mock_memory, PushByte(0x7F));
2803
2804 cpu.ExecuteInstruction(0x08); // PHP
2805}
2806
2808 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2809 cpu.X = 0x7F;
2810 std::vector<uint8_t> data = {0xDA};
2811 mock_memory.SetMemoryContents(data);
2812
2813 EXPECT_CALL(mock_memory, PushByte(0x7F));
2814
2815 cpu.ExecuteInstruction(0xDA); // PHX
2816}
2817
2819 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2820 cpu.Y = 0x7F;
2821 std::vector<uint8_t> data = {0x5A};
2822 mock_memory.SetMemoryContents(data);
2823
2824 EXPECT_CALL(mock_memory, PushByte(0x7F));
2825
2826 cpu.ExecuteInstruction(0x5A); // PHY
2827}
2828
2830 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2831 cpu.DB = 0x7F;
2832 std::vector<uint8_t> data = {0x8B};
2833 mock_memory.SetMemoryContents(data);
2834
2835 EXPECT_CALL(mock_memory, PushByte(0x7F));
2836
2837 cpu.ExecuteInstruction(0x8B); // PHB
2838}
2839
2841 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2842 cpu.A = 0x7F;
2843 std::vector<uint8_t> data = {0x48};
2844 mock_memory.SetMemoryContents(data);
2845
2846 EXPECT_CALL(mock_memory, PushByte(0x7F));
2847
2848 cpu.ExecuteInstruction(0x48); // PHA
2849}
2850
2851TEST_F(CpuTest, PHA_16Bit) {
2852 cpu.SetAccumulatorSize(false); // Set A register to 16-bit mode
2853 cpu.A = 0x7FFF;
2854 std::vector<uint8_t> data = {0x48};
2855 mock_memory.SetMemoryContents(data);
2856
2857 EXPECT_CALL(mock_memory, PushWord(0x7FFF));
2858
2859 cpu.ExecuteInstruction(0x48); // PHA
2860}
2861
2863 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2864 cpu.A = 0x00;
2865 std::vector<uint8_t> data = {0x68};
2866 mock_memory.SetMemoryContents(data);
2867 mock_memory.InsertMemory(0x0001, {0x7F});
2868
2869 EXPECT_CALL(mock_memory, PopByte()).WillOnce(Return(0x7F));
2870
2871 cpu.ExecuteInstruction(0x68); // PLA
2872 EXPECT_EQ(cpu.A, 0x7F);
2873}
2874
2875TEST_F(CpuTest, PLA_16Bit) {
2876 cpu.SetAccumulatorSize(false); // Set A register to 16-bit mode
2877 cpu.A = 0x0000;
2878 std::vector<uint8_t> data = {0x68};
2879 mock_memory.SetMemoryContents(data);
2880 mock_memory.InsertMemory(0x0001, {0x7F, 0xFF});
2881
2882 EXPECT_CALL(mock_memory, PopWord()).WillOnce(Return(0x7FFF));
2883
2884 cpu.ExecuteInstruction(0x68); // PLA
2885 EXPECT_EQ(cpu.A, 0x7FFF);
2886}
2887
2889 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2890 cpu.DB = 0x00;
2891 std::vector<uint8_t> data = {0xAB};
2892 mock_memory.SetMemoryContents(data);
2893 mock_memory.InsertMemory(0x0001, {0x7F});
2894
2895 EXPECT_CALL(mock_memory, PopByte()).WillOnce(Return(0x7F));
2896
2897 cpu.ExecuteInstruction(0xAB); // PLB
2898 EXPECT_EQ(cpu.DB, 0x7F);
2899}
2900
2902 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2903 cpu.D = 0x0000;
2904 std::vector<uint8_t> data = {0x2B};
2905 mock_memory.SetMemoryContents(data);
2906 mock_memory.InsertMemory(0x0001, {0x7F, 0xFF});
2907
2908 EXPECT_CALL(mock_memory, PopWord()).WillOnce(Return(0x7FFF));
2909
2910 cpu.ExecuteInstruction(0x2B); // PLD
2911 EXPECT_EQ(cpu.D, 0x7FFF);
2912}
2913
2915 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2916 cpu.status = 0x00;
2917 std::vector<uint8_t> data = {0x28};
2918 mock_memory.SetMemoryContents(data);
2919 mock_memory.InsertMemory(0x0001, {0x7F});
2920
2921 EXPECT_CALL(mock_memory, PopByte()).WillOnce(Return(0x7F));
2922
2923 cpu.ExecuteInstruction(0x28); // PLP
2924 EXPECT_EQ(cpu.status, 0x7F);
2925}
2926
2928 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
2929 cpu.X = 0x00;
2930 std::vector<uint8_t> data = {0xFA};
2931 mock_memory.SetMemoryContents(data);
2932 mock_memory.InsertMemory(0x0001, {0x7F});
2933
2934 EXPECT_CALL(mock_memory, PopByte()).WillOnce(Return(0x7F));
2935
2936 cpu.ExecuteInstruction(0xFA); // PLX
2937 EXPECT_EQ(cpu.X, 0x7F);
2938}
2939
2940TEST_F(CpuTest, PLX_16Bit) {
2941 cpu.SetIndexSize(false); // Set A register to 16-bit mode
2942 cpu.X = 0x0000;
2943
2944 std::vector<uint8_t> data = {0xFA};
2945 mock_memory.SetMemoryContents(data);
2946 mock_memory.InsertMemory(0x01FF, {0x7F, 0xFF});
2947
2948 EXPECT_CALL(mock_memory, PopWord()).WillOnce(Return(0x7FFF));
2949
2950 cpu.ExecuteInstruction(0xFA); // PLX
2951 EXPECT_EQ(cpu.X, 0x7FFF);
2952}
2953
2955 cpu.SetIndexSize(true); // Set A register to 8-bit mode
2956 cpu.Y = 0x00;
2957 std::vector<uint8_t> data = {0x7A};
2958 mock_memory.SetMemoryContents(data);
2959 mock_memory.InsertMemory(0x0001, {0x7F});
2960
2961 EXPECT_CALL(mock_memory, PopByte()).WillOnce(Return(0x7F));
2962
2963 cpu.ExecuteInstruction(0x7A); // PLY
2964 EXPECT_EQ(cpu.Y, 0x7F);
2965}
2966
2967TEST_F(CpuTest, PLY_16Bit) {
2968 cpu.SetIndexSize(false); // Set A register to 16-bit mode
2969 cpu.Y = 0x0000;
2970 std::vector<uint8_t> data = {0x7A};
2971 mock_memory.SetMemoryContents(data);
2972 mock_memory.InsertMemory(0x0001, {0x7F, 0xFF});
2973
2974 EXPECT_CALL(mock_memory, PopWord()).WillOnce(Return(0x7FFF));
2975
2976 cpu.ExecuteInstruction(0x7A); // PLY
2977 EXPECT_EQ(cpu.Y, 0x7FFF);
2978}
2979
2980// ============================================================================
2981// REP - Reset Processor Status Bits
2982
2984 cpu.status = 0xFF;
2985 std::vector<uint8_t> data = {0xC2, 0x30};
2986 mock_memory.SetMemoryContents(data);
2987
2988 cpu.ExecuteInstruction(0xC2); // REP
2989 EXPECT_EQ(cpu.status, 0xCF); // 11001111
2990}
2991
2992TEST_F(CpuTest, REP_16Bit) {
2993 cpu.status = 0xFF;
2994 std::vector<uint8_t> data = {0xC2, 0x30};
2995 mock_memory.SetMemoryContents(data);
2996
2997 cpu.ExecuteInstruction(0xC2); // REP
2998 EXPECT_EQ(cpu.status, 0xCF); // 00111111
2999}
3000
3001TEST_F(CpuTest, PHA_PLA_Ok) {
3002 cpu.A = 0x42;
3003 EXPECT_CALL(mock_memory, PushByte(0x42)).WillOnce(Return());
3004 // cpu.Pha();
3005 cpu.A = 0x00;
3006 EXPECT_CALL(mock_memory, PopByte()).WillOnce(Return(0x42));
3007 // cpu.Pla();
3008 EXPECT_EQ(cpu.A, 0x42);
3009}
3010
3011TEST_F(CpuTest, PHP_PLP_Ok) {
3012 // Set some status flags
3013 cpu.status = 0;
3014 cpu.SetNegativeFlag(true);
3015 cpu.SetZeroFlag(false);
3016 EXPECT_TRUE(cpu.GetNegativeFlag());
3017 EXPECT_FALSE(cpu.GetZeroFlag());
3018
3019 EXPECT_CALL(mock_memory, PushByte(0x80)).WillOnce(Return());
3020 // cpu.Php();
3021
3022 // Clear status flags
3023 cpu.SetNegativeFlag(false);
3024 cpu.SetZeroFlag(true);
3025 EXPECT_FALSE(cpu.GetNegativeFlag());
3026 EXPECT_TRUE(cpu.GetZeroFlag());
3027
3028 EXPECT_CALL(mock_memory, PopByte()).WillOnce(Return(0x80));
3029 // cpu.Plp();
3030
3031 EXPECT_TRUE(cpu.GetNegativeFlag());
3032 EXPECT_FALSE(cpu.GetZeroFlag());
3033}
3034
3035// ============================================================================
3036// PHA, PHP, PHX, PHY, PHB, PHD, PHK
3037// ============================================================================
3038
3039TEST_F(CpuTest, PHA_PushAccumulator) {
3040 cpu.A = 0x12;
3041 EXPECT_CALL(mock_memory, PushByte(0x12));
3042 cpu.ExecuteInstruction(0x48); // PHA
3043}
3044
3045TEST_F(CpuTest, PHP_PushProcessorStatusRegister) {
3046 cpu.status = 0x34;
3047 EXPECT_CALL(mock_memory, PushByte(0x34));
3048 cpu.ExecuteInstruction(0x08); // PHP
3049}
3050
3051TEST_F(CpuTest, PHX_PushXRegister) {
3052 cpu.X = 0x56;
3053 EXPECT_CALL(mock_memory, PushByte(0x56));
3054 cpu.ExecuteInstruction(0xDA); // PHX
3055}
3056
3057TEST_F(CpuTest, PHY_PushYRegister) {
3058 cpu.Y = 0x78;
3059 EXPECT_CALL(mock_memory, PushByte(0x78));
3060 cpu.ExecuteInstruction(0x5A); // PHY
3061}
3062
3063TEST_F(CpuTest, PHB_PushDataBankRegister) {
3064 cpu.DB = 0x9A;
3065 EXPECT_CALL(mock_memory, PushByte(0x9A));
3066 cpu.ExecuteInstruction(0x8B); // PHB
3067}
3068
3069TEST_F(CpuTest, PHD_PushDirectPageRegister) {
3070 cpu.D = 0xBC;
3071 EXPECT_CALL(mock_memory, PushWord(0xBC));
3072 cpu.ExecuteInstruction(0x0B); // PHD
3073}
3074
3075TEST_F(CpuTest, PHK_PushProgramBankRegister) {
3076 cpu.PB = 0xDE;
3077 EXPECT_CALL(mock_memory, PushByte(0xDE));
3078 cpu.ExecuteInstruction(0x4B); // PHK
3079}
3080
3081// ============================================================================
3082// PLA, PLP, PLX, PLY, PLB, PLD
3083// ============================================================================
3084
3085TEST_F(CpuTest, PLA_PullAccumulator) {
3086 EXPECT_CALL(mock_memory, PopByte()).WillOnce(Return(0x12));
3087 cpu.ExecuteInstruction(0x68); // PLA
3088 EXPECT_EQ(cpu.A, 0x12);
3089}
3090
3091TEST_F(CpuTest, PLP_PullProcessorStatusRegister) {
3092 EXPECT_CALL(mock_memory, PopByte()).WillOnce(Return(0x34));
3093 cpu.ExecuteInstruction(0x28); // PLP
3094 EXPECT_EQ(cpu.status, 0x34);
3095}
3096
3097TEST_F(CpuTest, PLX_PullXRegister) {
3098 EXPECT_CALL(mock_memory, PopByte()).WillOnce(Return(0x56));
3099 cpu.ExecuteInstruction(0xFA); // PLX
3100 EXPECT_EQ(cpu.X, 0x56);
3101}
3102
3103TEST_F(CpuTest, PLY_PullYRegister) {
3104 EXPECT_CALL(mock_memory, PopByte()).WillOnce(Return(0x78));
3105 cpu.ExecuteInstruction(0x7A); // PLY
3106 EXPECT_EQ(cpu.Y, 0x78);
3107}
3108
3109TEST_F(CpuTest, PLB_PullDataBankRegister) {
3110 EXPECT_CALL(mock_memory, PopByte()).WillOnce(Return(0x9A));
3111 cpu.ExecuteInstruction(0xAB); // PLB
3112 EXPECT_EQ(cpu.DB, 0x9A);
3113}
3114
3115TEST_F(CpuTest, PLD_PullDirectPageRegister) {
3116 EXPECT_CALL(mock_memory, PopWord()).WillOnce(Return(0xBC));
3117 cpu.ExecuteInstruction(0x2B); // PLD
3118 EXPECT_EQ(cpu.D, 0xBC);
3119}
3120
3121// ============================================================================
3122// SEP - Set Processor Status Bits
3123
3125 cpu.status = 0x00; // All flags cleared
3126 std::vector<uint8_t> data = {0xE2, 0x30,
3127 0x00}; // SEP #0x30 (set N & Z flags)
3128 mock_memory.SetMemoryContents(data);
3129
3130 cpu.ExecuteInstruction(0xE2); // SEP
3131 EXPECT_EQ(cpu.status, 0x30); // 00110000
3132}
3133
3134// ============================================================================
3135
3136TEST_F(CpuTest, ROL_DirectPage) {
3137 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3138 std::vector<uint8_t> data = {0x26, 0x80};
3139 mock_memory.SetMemoryContents(data);
3140 mock_memory.InsertMemory(0x0080, {0x42});
3141
3142 cpu.ExecuteInstruction(0x26); // ROL Direct Page
3143 EXPECT_EQ(mock_memory[0x0080], 0x84);
3144 EXPECT_TRUE(cpu.GetNegativeFlag());
3145 EXPECT_FALSE(cpu.GetZeroFlag());
3146}
3147
3148TEST_F(CpuTest, ROL_Accumulator) {
3149 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3150 cpu.A = 0x42;
3151 cpu.ExecuteInstruction(0x2A); // ROL Accumulator
3152 EXPECT_EQ(cpu.A, 0x84);
3153 EXPECT_TRUE(cpu.GetNegativeFlag());
3154 EXPECT_FALSE(cpu.GetZeroFlag());
3155}
3156
3157TEST_F(CpuTest, ROL_Absolute) {
3158 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3159 std::vector<uint8_t> data = {0x2E, 0x7F, 0xFF};
3160 mock_memory.SetMemoryContents(data);
3161 mock_memory.InsertMemory(0x7FFF, {0x42});
3162
3163 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x7FFF));
3164
3165 cpu.ExecuteInstruction(0x2E); // ROL Absolute
3166 EXPECT_EQ(mock_memory[0x7FFF], 0x84);
3167 EXPECT_TRUE(cpu.GetNegativeFlag());
3168 EXPECT_FALSE(cpu.GetZeroFlag());
3169}
3170
3171TEST_F(CpuTest, ROL_DirectPageIndexedX) {
3172 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3173 cpu.X = 0x02; // Set X register to 0x02
3174 std::vector<uint8_t> data = {0x36, 0x80};
3175 mock_memory.SetMemoryContents(data);
3176 mock_memory.InsertMemory(0x0082, {0x42});
3177
3178 cpu.ExecuteInstruction(0x36); // ROL Direct Page Indexed, X
3179 EXPECT_EQ(mock_memory[0x0082], 0x84);
3180 EXPECT_TRUE(cpu.GetNegativeFlag());
3181 EXPECT_FALSE(cpu.GetZeroFlag());
3182}
3183
3184TEST_F(CpuTest, ROL_AbsoluteIndexedX) {
3185 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3186 cpu.X = 0x02; // Set X register to 0x02
3187 std::vector<uint8_t> data = {0x3E, 0x7F, 0xFF};
3188 mock_memory.SetMemoryContents(data);
3189 mock_memory.InsertMemory(0x8001, {0x42});
3190
3191 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x7FFF));
3192
3193 cpu.ExecuteInstruction(0x3E); // ROL Absolute Indexed, X
3194 EXPECT_EQ(mock_memory[0x8001], 0x84);
3195 EXPECT_TRUE(cpu.GetNegativeFlag());
3196 EXPECT_FALSE(cpu.GetZeroFlag());
3197}
3198
3199// ============================================================================
3200
3201TEST_F(CpuTest, ROR_DirectPage) {
3202 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3203 std::vector<uint8_t> data = {0x66, 0x80};
3204 mock_memory.SetMemoryContents(data);
3205 mock_memory.InsertMemory(0x0080, {0x42});
3206
3207 cpu.ExecuteInstruction(0x66); // ROR Direct Page
3208 EXPECT_EQ(mock_memory[0x0080], 0x21);
3209 EXPECT_FALSE(cpu.GetNegativeFlag());
3210 EXPECT_FALSE(cpu.GetZeroFlag());
3211}
3212
3213TEST_F(CpuTest, ROR_Accumulator) {
3214 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3215 cpu.A = 0x42;
3216 cpu.ExecuteInstruction(0x6A); // ROR Accumulator
3217 EXPECT_EQ(cpu.A, 0x21);
3218 EXPECT_FALSE(cpu.GetNegativeFlag());
3219 EXPECT_FALSE(cpu.GetZeroFlag());
3220}
3221
3222TEST_F(CpuTest, ROR_Absolute) {
3223 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3224 std::vector<uint8_t> data = {0x6E, 0x7F, 0xFF};
3225 mock_memory.SetMemoryContents(data);
3226 mock_memory.InsertMemory(0x7FFF, {0x42});
3227
3228 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x7FFF));
3229
3230 cpu.ExecuteInstruction(0x6E); // ROR Absolute
3231 EXPECT_EQ(mock_memory[0x7FFF], 0x21);
3232 EXPECT_FALSE(cpu.GetNegativeFlag());
3233 EXPECT_FALSE(cpu.GetZeroFlag());
3234}
3235
3236TEST_F(CpuTest, ROR_DirectPageIndexedX) {
3237 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3238 cpu.X = 0x02; // Set X register to 0x02
3239 std::vector<uint8_t> data = {0x76, 0x80};
3240 mock_memory.SetMemoryContents(data);
3241 mock_memory.InsertMemory(0x0082, {0x42});
3242
3243 cpu.ExecuteInstruction(0x76); // ROR Direct Page Indexed, X
3244 EXPECT_EQ(mock_memory[0x0082], 0x21);
3245 EXPECT_FALSE(cpu.GetNegativeFlag());
3246 EXPECT_FALSE(cpu.GetZeroFlag());
3247}
3248
3249TEST_F(CpuTest, ROR_AbsoluteIndexedX) {
3250 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3251 cpu.X = 0x02; // Set X register to 0x02
3252 std::vector<uint8_t> data = {0x7E, 0x7F, 0xFF};
3253 mock_memory.SetMemoryContents(data);
3254 mock_memory.InsertMemory(0x8001, {0x42});
3255
3256 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x7FFF));
3257
3258 cpu.ExecuteInstruction(0x7E); // ROR Absolute Indexed, X
3259 EXPECT_EQ(mock_memory[0x8001], 0x21);
3260 EXPECT_FALSE(cpu.GetNegativeFlag());
3261 EXPECT_FALSE(cpu.GetZeroFlag());
3262}
3263
3264// ============================================================================
3265
3267 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3268 cpu.status = 0x00;
3269 std::vector<uint8_t> data = {0x40};
3270 mock_memory.SetMemoryContents(data);
3271 mock_memory.InsertMemory(0x0001, {0x7F});
3272
3273 EXPECT_CALL(mock_memory, PopByte()).WillOnce(Return(0x7F));
3274
3275 cpu.ExecuteInstruction(0x40); // RTI
3276 EXPECT_EQ(cpu.status, 0x7F);
3277}
3278
3279// ============================================================================
3280
3282 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3283 cpu.PC = 0x0000;
3284 std::vector<uint8_t> data = {0x6B};
3285 mock_memory.SetMemoryContents(data);
3286 mock_memory.InsertMemory(0x0001, {0x7F, 0xFF});
3287
3288 EXPECT_CALL(mock_memory, PopWord()).WillOnce(Return(0x7FFF));
3289
3290 cpu.ExecuteInstruction(0x6B); // RTL
3291 EXPECT_EQ(cpu.PC, 0x7FFF);
3292}
3293
3294// ============================================================================
3295
3297 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3298 cpu.PC = 0x0000;
3299 std::vector<uint8_t> data = {0x60};
3300 mock_memory.SetMemoryContents(data);
3301 mock_memory.InsertMemory(0x0001, {0x7F, 0xFF});
3302
3303 EXPECT_CALL(mock_memory, PopWord()).WillOnce(Return(0x7FFF));
3304
3305 cpu.ExecuteInstruction(0x60); // RTS
3306 EXPECT_EQ(cpu.PC, 0x7FFF + 3);
3307}
3308
3309// ============================================================================
3310
3311TEST_F(CpuTest, SBC_DirectPageIndexedIndirectX) {
3312 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3313 cpu.X = 0x02; // Set X register to 0x02
3314 cpu.D = 0x0200; // Set Direct Page register to 0x0200
3315 cpu.A = 0x10; // Set A register to 0x80
3316 cpu.status = 0xFF; // 8-bit mode
3317 std::vector<uint8_t> data = {0xE1, 0x3C};
3318 mock_memory.SetMemoryContents(data);
3319 mock_memory.InsertMemory(0x00023E, {0x80});
3320 mock_memory.InsertMemory(0x0080, {0x80});
3321
3322 EXPECT_CALL(mock_memory, ReadByte(0x000001)).WillOnce(Return(0x3C));
3323 EXPECT_CALL(mock_memory, ReadWord(0x00023E)).WillOnce(Return(0x80));
3324 EXPECT_CALL(mock_memory, ReadByte(0x0080)).WillOnce(Return(0x80));
3325
3326 cpu.ExecuteInstruction(0xE1); // SBC Direct Page Indexed Indirect, X
3327 EXPECT_EQ(cpu.A, 0x90);
3328 EXPECT_TRUE(cpu.GetNegativeFlag());
3329 EXPECT_FALSE(cpu.GetZeroFlag());
3330}
3331
3332TEST_F(CpuTest, SBC_StackRelative) {
3333 std::vector<uint8_t> data = {0xE3, 0x3C};
3334 mock_memory.SetMemoryContents(data);
3335 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3336 cpu.status = 0xFF; // 8-bit mode
3337 mock_memory.SetSP(0x01FF); // Set Stack Pointer to 0x01FF
3338 mock_memory.InsertMemory(0x00003E, {0x02});
3339 mock_memory.InsertMemory(0x2002, {0x80});
3340
3341 EXPECT_CALL(mock_memory, SP()).WillRepeatedly(Return(0x01FF));
3342 // EXPECT_CALL(mock_memory, ReadByte(_)).WillOnce(Return(0x3C));
3343
3344 cpu.ExecuteInstruction(0xE3); // SBC Stack Relative
3345 EXPECT_EQ(cpu.A, 0x00);
3346 EXPECT_FALSE(cpu.GetNegativeFlag());
3347 EXPECT_TRUE(cpu.GetZeroFlag());
3348}
3349
3350TEST_F(CpuTest, SBC_DirectPage) {
3351 std::vector<uint8_t> data = {0xE5, 0x80};
3352 mock_memory.SetMemoryContents(data);
3353 cpu.D = 0x0100; // Set Direct Page register to 0x0100
3354
3355 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3356 cpu.status = 0xFF; // 8-bit mode
3357 cpu.A = 0x42; // Set A register to 0x42
3358
3359 mock_memory.InsertMemory(0x0180, {0x01});
3360
3361 cpu.ExecuteInstruction(0xE5); // SBC Direct Page
3362 EXPECT_EQ(cpu.A, 0x41);
3363 EXPECT_FALSE(cpu.GetNegativeFlag());
3364 EXPECT_FALSE(cpu.GetZeroFlag());
3365}
3366
3367TEST_F(CpuTest, SBC_DirectPageIndirectLong) {
3368 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3369 cpu.status = 0xFF; // 8-bit mode
3370 cpu.A = 0x80; // Set A register to 0x80
3371 std::vector<uint8_t> data = {0xE7, 0x3C};
3372 mock_memory.SetMemoryContents(data);
3373 mock_memory.InsertMemory(0x00003C, {0x00, 0x10, 0x00});
3374 mock_memory.InsertMemory(0x1000, {0x8F});
3375
3376 EXPECT_CALL(mock_memory, ReadByte(0x000001)).WillOnce(Return(0x3C));
3377 EXPECT_CALL(mock_memory, ReadWordLong(0x00003C)).WillOnce(Return(0x1000));
3378
3379 EXPECT_CALL(mock_memory, ReadByte(0x1000)).WillOnce(Return(0x8F));
3380
3381 cpu.ExecuteInstruction(0xE7); // SBC Direct Page Indirect Long
3382 EXPECT_EQ(cpu.A, 0xF1);
3383 EXPECT_TRUE(cpu.GetNegativeFlag());
3384 EXPECT_FALSE(cpu.GetZeroFlag());
3385}
3386
3387TEST_F(CpuTest, SBC_Immediate) {
3388 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3389 cpu.status = 0xFF; // 8-bit mode
3390 cpu.A = 0x80; // Set A register to 0x80
3391 std::vector<uint8_t> data = {0xE9, 0x80};
3392 mock_memory.SetMemoryContents(data);
3393
3394 cpu.ExecuteInstruction(0xE9); // SBC Immediate
3395 EXPECT_EQ(cpu.A, 0x00);
3396 EXPECT_FALSE(cpu.GetNegativeFlag());
3397 EXPECT_TRUE(cpu.GetZeroFlag());
3398}
3399
3400TEST_F(CpuTest, SBC_Absolute) {
3401 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3402 cpu.status = 0xFF; // 8-bit mode
3403 cpu.A = 0xFF; // Set A register to 0x80
3404 std::vector<uint8_t> data = {0xED, 0x7F, 0xFF};
3405 mock_memory.SetMemoryContents(data);
3406 mock_memory.InsertMemory(0x7FFF, {0x80});
3407
3408 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x7FFF));
3409
3410 cpu.ExecuteInstruction(0xED); // SBC Absolute
3411 EXPECT_EQ(cpu.A, 0x7F);
3412 EXPECT_FALSE(cpu.GetNegativeFlag());
3413 EXPECT_FALSE(cpu.GetZeroFlag());
3414}
3415
3416TEST_F(CpuTest, SBC_AbsoluteLong) {
3417 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3418 cpu.status = 0xFF; // 8-bit mode
3419 cpu.A = 0xFF; // Set A register to 0x80
3420 std::vector<uint8_t> data = {0xEF, 0x7F, 0xFF, 0xFF, 0xFF};
3421 mock_memory.SetMemoryContents(data);
3422 mock_memory.InsertMemory(0x7FFFFF, {0x80});
3423
3424 EXPECT_CALL(mock_memory, ReadWordLong(0x0001)).WillOnce(Return(0x7FFFFF));
3425
3426 cpu.ExecuteInstruction(0xEF); // SBC Absolute Long
3427 EXPECT_EQ(cpu.A, 0x7F);
3428 EXPECT_FALSE(cpu.GetNegativeFlag());
3429 EXPECT_FALSE(cpu.GetZeroFlag());
3430}
3431
3432TEST_F(CpuTest, SBC_DirectPageIndirectIndexedY) {
3433 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3434 cpu.Y = 0x02; // Set Y register to 0x02
3435 cpu.A = 0xFF; // Set A register to 0x80
3436 cpu.status = 0xFF; // 8-bit mode
3437 std::vector<uint8_t> data = {0xF1, 0x3C};
3438 mock_memory.SetMemoryContents(data);
3439 mock_memory.InsertMemory(0x00003E, {0x00, 0x10});
3440
3441 EXPECT_CALL(mock_memory, ReadByte(0x000001)).WillOnce(Return(0x3C));
3442 EXPECT_CALL(mock_memory, ReadWord(0x00003C)).WillOnce(Return(0x1000));
3443
3444 EXPECT_CALL(mock_memory, ReadByte(0x1002)).WillOnce(Return(0x80));
3445
3446 cpu.ExecuteInstruction(0xF1); // SBC Direct Page Indirect Indexed, Y
3447 EXPECT_EQ(cpu.A, 0x7F);
3448 EXPECT_FALSE(cpu.GetNegativeFlag());
3449 EXPECT_FALSE(cpu.GetZeroFlag());
3450}
3451
3452TEST_F(CpuTest, SBC_DirectPageIndirect) {
3453 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3454 cpu.status = 0xFF; // 8-bit mode
3455 cpu.D = 0x0200; // Set Direct Page register to 0x0200
3456 cpu.A = 0x10; // Set A register to 0x80
3457 std::vector<uint8_t> data = {0xF2, 0x3C};
3458 mock_memory.SetMemoryContents(data);
3459 mock_memory.InsertMemory(0x00023C, {0x00, 0x10});
3460 mock_memory.InsertMemory(0x1000, {0x80});
3461
3462 EXPECT_CALL(mock_memory, ReadByte(0x000001)).WillOnce(Return(0x3C));
3463
3464 EXPECT_CALL(mock_memory, ReadWord(0x00023C)).WillOnce(Return(0x1000));
3465
3466 EXPECT_CALL(mock_memory, ReadByte(0x1000)).WillOnce(Return(0x80));
3467
3468 cpu.ExecuteInstruction(0xF2); // SBC Direct Page Indirect
3469 EXPECT_EQ(cpu.A, 0x90);
3470 EXPECT_TRUE(cpu.GetNegativeFlag());
3471 EXPECT_FALSE(cpu.GetZeroFlag());
3472}
3473
3474TEST_F(CpuTest, SBC_StackRelativeIndirectIndexedY) {
3475 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3476 cpu.Y = 0x02; // Set Y register to 0x02
3477 cpu.A = 0xFF; // Set A register to 0x80
3478 cpu.status = 0xFF; // 8-bit mode
3479 mock_memory.SetSP(0x01FF); // Set Stack Pointer to 0x01FF
3480 std::vector<uint8_t> data = {0xF3, 0x02};
3481 mock_memory.SetMemoryContents(data);
3482 mock_memory.InsertMemory(0x0201, {0x00, 0x30});
3483 mock_memory.InsertMemory(0x3002, {0x80});
3484
3485 EXPECT_CALL(mock_memory, SP()).WillRepeatedly(Return(0x01FF));
3486 EXPECT_CALL(mock_memory, ReadByte(0x000001)).WillOnce(Return(0x02));
3487 EXPECT_CALL(mock_memory, ReadWord(0x0201)).WillOnce(Return(0x3000));
3488 EXPECT_CALL(mock_memory, ReadByte(0x3002)).WillOnce(Return(0x80));
3489
3490 cpu.ExecuteInstruction(0xF3); // SBC Stack Relative Indirect Indexed, Y
3491 EXPECT_EQ(cpu.A, 0x7F);
3492 EXPECT_FALSE(cpu.GetNegativeFlag());
3493 EXPECT_FALSE(cpu.GetZeroFlag());
3494}
3495
3496TEST_F(CpuTest, SBC_DirectPageIndexedX) {
3497 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3498 cpu.X = 0x02; // Set X register to 0x02
3499 cpu.A = 0x01;
3500 std::vector<uint8_t> data = {0xF5, 0x80};
3501 mock_memory.SetMemoryContents(data);
3502 mock_memory.InsertMemory(0x0082, {0x01});
3503
3504 cpu.ExecuteInstruction(0xF5); // SBC Direct Page Indexed, X
3505 EXPECT_EQ(cpu.A, 0xFF);
3506 EXPECT_TRUE(cpu.GetNegativeFlag());
3507 EXPECT_FALSE(cpu.GetZeroFlag());
3508}
3509
3510TEST_F(CpuTest, SBC_DirectPageIndirectLongIndexedY) {
3511 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3512 cpu.Y = 0x02; // Set Y register to 0x02
3513 cpu.status = 0xFF; // 8-bit mode
3514 cpu.A = 0xFF;
3515 std::vector<uint8_t> data = {0xF7, 0x3C};
3516 mock_memory.SetMemoryContents(data);
3517 mock_memory.InsertMemory(0x00003C, {0x00, 0x10, 0x00});
3518
3519 EXPECT_CALL(mock_memory, ReadByte(0x000001)).WillOnce(Return(0x3C));
3520 EXPECT_CALL(mock_memory, ReadWordLong(0x00003C)).WillOnce(Return(0x1000));
3521
3522 EXPECT_CALL(mock_memory, ReadByte(0x1002)).WillOnce(Return(0x80));
3523
3524 cpu.ExecuteInstruction(0xF7); // SBC Direct Page Indirect Long Indexed, Y
3525 EXPECT_EQ(cpu.A, 0x7F);
3526 EXPECT_FALSE(cpu.GetNegativeFlag());
3527 EXPECT_FALSE(cpu.GetZeroFlag());
3528}
3529
3530TEST_F(CpuTest, SBC_AbsoluteIndexedY) {
3531 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3532 cpu.Y = 0x02; // Set Y register to 0x02
3533 cpu.status = 0xFF; // 8-bit mode
3534 cpu.A = 0xFF;
3535 std::vector<uint8_t> data = {0xF9, 0x7F, 0xFF};
3536 mock_memory.SetMemoryContents(data);
3537 mock_memory.InsertMemory(0x8001, {0x80});
3538
3539 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x7FFF));
3540
3541 cpu.ExecuteInstruction(0xF9); // SBC Absolute Indexed, Y
3542 EXPECT_EQ(cpu.A, 0x7F);
3543 EXPECT_FALSE(cpu.GetNegativeFlag());
3544 EXPECT_FALSE(cpu.GetZeroFlag());
3545}
3546
3547TEST_F(CpuTest, SBC_AbsoluteIndexedX) {
3548 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3549 cpu.X = 0x02; // Set X register to 0x02
3550 cpu.status = 0xFF; // 8-bit mode
3551 cpu.A = 0xFF;
3552 std::vector<uint8_t> data = {0xFD, 0x7F, 0xFF};
3553 mock_memory.SetMemoryContents(data);
3554 mock_memory.InsertMemory(0x8001, {0x80});
3555
3556 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x7FFF));
3557
3558 cpu.ExecuteInstruction(0xFD); // SBC Absolute Indexed, X
3559 EXPECT_EQ(cpu.A, 0x7F);
3560 EXPECT_FALSE(cpu.GetNegativeFlag());
3561 EXPECT_FALSE(cpu.GetZeroFlag());
3562}
3563
3564TEST_F(CpuTest, SBC_AbsoluteLongIndexedX) {
3565 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3566 cpu.X = 0x02; // Set X register to 0x02
3567 cpu.A = 0xFF;
3568 cpu.status = 0xFF; // 8-bit mode
3569 std::vector<uint8_t> data = {0xFF, 0x7F, 0xFF, 0xFF, 0xFF};
3570 mock_memory.SetMemoryContents(data);
3571 mock_memory.InsertMemory(0x800001, {0x80});
3572
3573 EXPECT_CALL(mock_memory, ReadWordLong(0x0001)).WillOnce(Return(0x7FFFFF));
3574
3575 cpu.ExecuteInstruction(0xFF); // SBC Absolute Long Indexed, X
3576 EXPECT_EQ(cpu.A, 0x7F);
3577 EXPECT_FALSE(cpu.GetNegativeFlag());
3578 EXPECT_FALSE(cpu.GetZeroFlag());
3579}
3580
3581// ============================================================================
3582
3584 cpu.ExecuteInstruction(0x38); // SEC
3585 EXPECT_TRUE(cpu.GetCarryFlag());
3586}
3587
3588// ============================================================================
3589
3591 cpu.ExecuteInstruction(0xF8); // SED
3592 EXPECT_TRUE(cpu.GetDecimalFlag());
3593}
3594
3595// ============================================================================
3596
3597// SEI - Set Interrupt Disable Status Flag
3598
3600 cpu.ExecuteInstruction(0x78); // SEI
3601 // EXPECT_TRUE(cpu.GetInterruptDisableFlag());
3602}
3603
3604// ============================================================================
3605
3606TEST_F(CpuTest, SEP_8Bit) {
3607 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3608 cpu.status = 0x00;
3609 std::vector<uint8_t> data = {0xE2, 0x30};
3610 mock_memory.SetMemoryContents(data);
3611
3612 cpu.ExecuteInstruction(0xE2); // SEP
3613 EXPECT_EQ(cpu.status, 0x30); // 00110000
3614}
3615
3616TEST_F(CpuTest, SEP_16Bit) {
3617 cpu.SetAccumulatorSize(false); // Set A register to 16-bit mode
3618 cpu.status = 0x00;
3619 std::vector<uint8_t> data = {0xE2, 0x30};
3620 mock_memory.SetMemoryContents(data);
3621
3622 cpu.ExecuteInstruction(0xE2); // SEP
3623 EXPECT_EQ(cpu.status, 0x30); // 00110000
3624}
3625
3626// ============================================================================
3627
3628TEST_F(CpuTest, STA_DirectPageIndexedIndirectX) {
3629 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3630 cpu.A = 0x42;
3631 cpu.X = 0x02; // Set X register to 0x02
3632 std::vector<uint8_t> data = {0x81, 0x3C};
3633 mock_memory.SetMemoryContents(data);
3634 mock_memory.InsertMemory(0x00003E, {0x00, 0x10});
3635
3636 EXPECT_CALL(mock_memory, ReadByte(0x000001)).WillOnce(Return(0x3C));
3637 EXPECT_CALL(mock_memory, ReadWord(0x00003E)).WillOnce(Return(0x1000));
3638
3639 EXPECT_CALL(mock_memory, WriteByte(0x1000, 0x42));
3640
3641 cpu.ExecuteInstruction(0x81); // STA Direct Page Indexed Indirect, X
3642 EXPECT_EQ(cpu.A, 0x42);
3643}
3644
3645TEST_F(CpuTest, STA_StackRelative) {
3646 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3647 cpu.A = 0x42;
3648 mock_memory.SetSP(0x01FF); // Set Stack Pointer to 0x01FF
3649 std::vector<uint8_t> data = {0x83, 0x3C};
3650 mock_memory.SetMemoryContents(data);
3651
3652 EXPECT_CALL(mock_memory, ReadByte(0x000001)).WillOnce(Return(0x3C));
3653
3654 EXPECT_CALL(mock_memory, WriteByte(0x023B, 0x42));
3655
3656 cpu.ExecuteInstruction(0x83); // STA Stack Relative
3657}
3658
3659TEST_F(CpuTest, STA_DirectPage) {
3660 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3661 cpu.A = 0x42;
3662 std::vector<uint8_t> data = {0x85, 0x80};
3663 mock_memory.SetMemoryContents(data);
3664
3665 EXPECT_CALL(mock_memory, WriteByte(0x0080, 0x42));
3666
3667 cpu.ExecuteInstruction(0x85); // STA Direct Page
3668}
3669
3670TEST_F(CpuTest, STA_DirectPageIndirectLong) {
3671 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3672 cpu.A = 0x42;
3673 std::vector<uint8_t> data = {0x87, 0x3C};
3674 mock_memory.SetMemoryContents(data);
3675 mock_memory.InsertMemory(0x00003C, {0x00, 0x10, 0x00});
3676
3677 EXPECT_CALL(mock_memory, ReadByte(0x000001)).WillOnce(Return(0x3C));
3678 EXPECT_CALL(mock_memory, ReadWordLong(0x00003C)).WillOnce(Return(0x1000));
3679
3680 EXPECT_CALL(mock_memory, WriteByte(0x1000, 0x42));
3681
3682 cpu.ExecuteInstruction(0x87); // STA Direct Page Indirect Long
3683}
3684
3685TEST_F(CpuTest, STA_Absolute) {
3686 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3687 cpu.A = 0x42;
3688 std::vector<uint8_t> data = {0x8D, 0xFF, 0x7F};
3689 mock_memory.SetMemoryContents(data);
3690
3691 EXPECT_CALL(mock_memory, WriteByte(0x7FFF, 0x42));
3692
3693 cpu.ExecuteInstruction(0x8D); // STA Absolute
3694}
3695
3696TEST_F(CpuTest, STA_AbsoluteLong) {
3697 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3698 cpu.A = 0x42;
3699 std::vector<uint8_t> data = {0x8F, 0xFF, 0x7F};
3700 mock_memory.SetMemoryContents(data);
3701
3702 EXPECT_CALL(mock_memory, WriteByte(0x7FFF, 0x42));
3703
3704 cpu.ExecuteInstruction(0x8F); // STA Absolute Long
3705}
3706
3707TEST_F(CpuTest, STA_DirectPageIndirectIndexedY) {
3708 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3709 cpu.A = 0x42;
3710 cpu.Y = 0x02; // Set Y register to 0x02
3711 std::vector<uint8_t> data = {0x91, 0x3C};
3712 mock_memory.SetMemoryContents(data);
3713 mock_memory.InsertMemory(0x00003E, {0x00, 0x10});
3714
3715 EXPECT_CALL(mock_memory, ReadByte(0x000001)).WillOnce(Return(0x3C));
3716 EXPECT_CALL(mock_memory, ReadWord(0x00003C)).WillOnce(Return(0x1000));
3717
3718 EXPECT_CALL(mock_memory, WriteByte(0x1002, 0x42));
3719
3720 cpu.ExecuteInstruction(0x91); // STA Direct Page Indirect Indexed, Y
3721}
3722
3723TEST_F(CpuTest, STA_DirectPageIndirect) {
3724 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3725 cpu.A = 0x42;
3726 cpu.Y = 0x02; // Set Y register to 0x02
3727 std::vector<uint8_t> data = {0x92, 0x3C};
3728 mock_memory.SetMemoryContents(data);
3729 mock_memory.InsertMemory(0x00003C, {0x00, 0x10});
3730
3731 EXPECT_CALL(mock_memory, ReadByte(0x000001)).WillOnce(Return(0x3C));
3732 EXPECT_CALL(mock_memory, ReadWord(0x00003C)).WillOnce(Return(0x1000));
3733
3734 EXPECT_CALL(mock_memory, WriteByte(0x1000, 0x42));
3735
3736 cpu.ExecuteInstruction(0x92); // STA Direct Page Indirect
3737}
3738
3739TEST_F(CpuTest, STA_StackRelativeIndirectIndexedY) {
3740 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3741 cpu.A = 0x42;
3742 cpu.Y = 0x02; // Set Y register to 0x02
3743 mock_memory.SetSP(0x01FF); // Set Stack Pointer to 0x01FF
3744 std::vector<uint8_t> data = {0x93, 0x3C};
3745 mock_memory.SetMemoryContents(data);
3746 mock_memory.InsertMemory(0x00023B, {0x00, 0x10});
3747
3748 EXPECT_CALL(mock_memory, ReadByte(0x000001)).WillOnce(Return(0x3C));
3749 EXPECT_CALL(mock_memory, ReadWord(0x00023B)).WillOnce(Return(0x1000));
3750
3751 EXPECT_CALL(mock_memory, WriteByte(0x1002, 0x42));
3752
3753 cpu.ExecuteInstruction(0x93); // STA Stack Relative Indirect Indexed, Y
3754}
3755
3756TEST_F(CpuTest, STA_DirectPageIndexedX) {
3757 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3758 cpu.A = 0x42;
3759 cpu.X = 0x02; // Set X register to 0x02
3760 std::vector<uint8_t> data = {0x95, 0x80};
3761 mock_memory.SetMemoryContents(data);
3762
3763 EXPECT_CALL(mock_memory, WriteByte(0x0082, 0x42));
3764
3765 cpu.ExecuteInstruction(0x95); // STA Direct Page Indexed, X
3766}
3767
3768TEST_F(CpuTest, STA_DirectPageIndirectLongIndexedY) {
3769 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3770 cpu.A = 0x42;
3771 cpu.Y = 0x02; // Set Y register to 0x02
3772 std::vector<uint8_t> data = {0x97, 0x3C};
3773 mock_memory.SetMemoryContents(data);
3774 mock_memory.InsertMemory(0x00003C, {0x00, 0x10, 0x00});
3775
3776 EXPECT_CALL(mock_memory, ReadByte(0x000001)).WillOnce(Return(0x3C));
3777 EXPECT_CALL(mock_memory, ReadWordLong(0x00003C)).WillOnce(Return(0x1000));
3778
3779 EXPECT_CALL(mock_memory, WriteByte(0x1002, 0x42));
3780
3781 cpu.ExecuteInstruction(0x97); // STA Direct Page Indirect Long Indexed, Y
3782}
3783
3784TEST_F(CpuTest, STA_AbsoluteIndexedY) {
3785 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3786 cpu.A = 0x42;
3787 cpu.Y = 0x02; // Set Y register to 0x02
3788 std::vector<uint8_t> data = {0x99, 0x7F, 0xFF};
3789 mock_memory.SetMemoryContents(data);
3790
3791 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x7FFF));
3792 EXPECT_CALL(mock_memory, WriteByte(0x8001, 0x42));
3793
3794 cpu.ExecuteInstruction(0x99); // STA Absolute Indexed, Y
3795}
3796
3797TEST_F(CpuTest, STA_AbsoluteIndexedX) {
3798 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3799 cpu.A = 0x42;
3800 cpu.X = 0x02; // Set X register to 0x02
3801 std::vector<uint8_t> data = {0x9D, 0x7F, 0xFF};
3802 mock_memory.SetMemoryContents(data);
3803
3804 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x7FFF));
3805 EXPECT_CALL(mock_memory, WriteByte(0x8001, 0x42));
3806
3807 cpu.ExecuteInstruction(0x9D); // STA Absolute Indexed, X
3808}
3809
3810TEST_F(CpuTest, STA_AbsoluteLongIndexedX) {
3811 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3812 cpu.A = 0x42;
3813 cpu.X = 0x02; // Set X register to 0x02
3814 std::vector<uint8_t> data = {0x9F, 0xFF, 0xFF, 0x7F};
3815 mock_memory.SetMemoryContents(data);
3816
3817 EXPECT_CALL(mock_memory, ReadWordLong(0x0001)).WillOnce(Return(0x7FFFFF));
3818 EXPECT_CALL(mock_memory, WriteByte(0x800001, 0x42));
3819
3820 cpu.ExecuteInstruction(0x9F); // STA Absolute Long Indexed, X
3821}
3822
3823// ============================================================================
3824
3826 cpu.ExecuteInstruction(0xDB); // STP
3827 // EXPECT_TRUE(cpu.GetStoppedFlag());
3828}
3829
3830// ============================================================================
3831
3832TEST_F(CpuTest, STX_DirectPage) {
3833 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3834 cpu.X = 0x42;
3835 std::vector<uint8_t> data = {0x86, 0x80};
3836 mock_memory.SetMemoryContents(data);
3837
3838 EXPECT_CALL(mock_memory, WriteByte(0x0080, 0x42));
3839
3840 cpu.ExecuteInstruction(0x86); // STX Direct Page
3841}
3842
3843TEST_F(CpuTest, STX_Absolute) {
3844 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3845 cpu.X = 0x42;
3846 std::vector<uint8_t> data = {0x8E, 0x7F, 0xFF};
3847 mock_memory.SetMemoryContents(data);
3848
3849 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x7FFF));
3850 EXPECT_CALL(mock_memory, WriteByte(0x7FFF, 0x42));
3851
3852 cpu.ExecuteInstruction(0x8E); // STX Absolute
3853}
3854
3855TEST_F(CpuTest, STX_DirectPageIndexedY) {
3856 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3857 cpu.X = 0x42;
3858 cpu.Y = 0x02; // Set Y register to 0x02
3859 std::vector<uint8_t> data = {0x96, 0x80};
3860 mock_memory.SetMemoryContents(data);
3861
3862 EXPECT_CALL(mock_memory, WriteByte(0x0082, 0x42));
3863
3864 cpu.ExecuteInstruction(0x96); // STX Direct Page Indexed, Y
3865}
3866
3867// ============================================================================
3868
3869TEST_F(CpuTest, STY_DirectPage) {
3870 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3871 cpu.Y = 0x42;
3872 std::vector<uint8_t> data = {0x84, 0x80};
3873 mock_memory.SetMemoryContents(data);
3874
3875 EXPECT_CALL(mock_memory, WriteByte(0x0080, 0x42));
3876
3877 cpu.ExecuteInstruction(0x84); // STY Direct Page
3878}
3879
3880TEST_F(CpuTest, STY_Absolute) {
3881 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3882 cpu.Y = 0x42;
3883 std::vector<uint8_t> data = {0x8C, 0x7F, 0xFF};
3884 mock_memory.SetMemoryContents(data);
3885
3886 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x7FFF));
3887 EXPECT_CALL(mock_memory, WriteByte(0x7FFF, 0x42));
3888
3889 cpu.ExecuteInstruction(0x8C); // STY Absolute
3890}
3891
3892TEST_F(CpuTest, STY_DirectPageIndexedX) {
3893 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3894 cpu.Y = 0x42;
3895 cpu.X = 0x02; // Set X register to 0x02
3896 std::vector<uint8_t> data = {0x94, 0x80};
3897 mock_memory.SetMemoryContents(data);
3898
3899 EXPECT_CALL(mock_memory, WriteByte(0x0082, 0x42));
3900
3901 cpu.ExecuteInstruction(0x94); // STY Direct Page Indexed, X
3902}
3903
3904// ============================================================================
3905
3906TEST_F(CpuTest, STZ_DirectPage) {
3907 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3908 std::vector<uint8_t> data = {0x64, 0x80};
3909 mock_memory.SetMemoryContents(data);
3910
3911 EXPECT_CALL(mock_memory, WriteByte(0x0080, 0x00));
3912
3913 cpu.ExecuteInstruction(0x64); // STZ Direct Page
3914}
3915
3916TEST_F(CpuTest, STZ_DirectPageIndexedX) {
3917 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3918 cpu.X = 0x02; // Set X register to 0x02
3919 std::vector<uint8_t> data = {0x74, 0x80};
3920 mock_memory.SetMemoryContents(data);
3921
3922 EXPECT_CALL(mock_memory, WriteByte(0x0082, 0x00));
3923
3924 cpu.ExecuteInstruction(0x74); // STZ Direct Page Indexed, X
3925}
3926
3927TEST_F(CpuTest, STZ_Absolute) {
3928 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3929 std::vector<uint8_t> data = {0x9C, 0x7F, 0xFF};
3930 mock_memory.SetMemoryContents(data);
3931
3932 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x7FFF));
3933 EXPECT_CALL(mock_memory, WriteByte(0x7FFF, 0x00));
3934
3935 cpu.ExecuteInstruction(0x9C); // STZ Absolute
3936}
3937
3938// ============================================================================
3939// TAX - Transfer Accumulator to Index X
3940
3942 cpu.A = 0xBC; // A register
3943 std::vector<uint8_t> data = {0xAA}; // TAX
3944 mock_memory.SetMemoryContents(data);
3945
3946 cpu.ExecuteInstruction(0xAA); // TAX
3947 EXPECT_EQ(cpu.X, 0xBC); // X register should now be equal to A
3948}
3949
3950// ============================================================================
3951// TAY - Transfer Accumulator to Index Y
3952
3954 cpu.A = 0xDE; // A register
3955 std::vector<uint8_t> data = {0xA8}; // TAY
3956 mock_memory.SetMemoryContents(data);
3957
3958 cpu.ExecuteInstruction(0xA8); // TAY
3959 EXPECT_EQ(cpu.Y, 0xDE); // Y register should now be equal to A
3960}
3961
3962// ============================================================================
3963
3965 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3966 cpu.A = 0x42;
3967 std::vector<uint8_t> data = {0x5B};
3968 mock_memory.SetMemoryContents(data);
3969
3970 cpu.ExecuteInstruction(0x5B); // TCD
3971 EXPECT_EQ(cpu.D, 0x42);
3972}
3973
3974// ============================================================================
3975
3977 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3978 cpu.A = 0x42;
3979 std::vector<uint8_t> data = {0x1B};
3980 mock_memory.SetMemoryContents(data);
3981
3982 EXPECT_CALL(mock_memory, SetSP(0x42));
3983
3984 cpu.ExecuteInstruction(0x1B); // TCS
3985 EXPECT_EQ(mock_memory.SP(), 0x42);
3986}
3987
3988// ============================================================================
3989
3991 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
3992 cpu.D = 0x42;
3993 std::vector<uint8_t> data = {0x7B};
3994 mock_memory.SetMemoryContents(data);
3995
3996 cpu.ExecuteInstruction(0x7B); // TDC
3997 EXPECT_EQ(cpu.A, 0x42);
3998}
3999
4000// ============================================================================
4001
4002TEST_F(CpuTest, TRB_DirectPage) {
4003 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
4004 cpu.A = 0x42;
4005 std::vector<uint8_t> data = {0x14, 0x80};
4006 mock_memory.SetMemoryContents(data);
4007 mock_memory.InsertMemory(0x0080, {0x00});
4008
4009 EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(Return(0x0080));
4010 EXPECT_CALL(mock_memory, ReadByte(0x0080)).WillOnce(Return(0x00));
4011 EXPECT_CALL(mock_memory, WriteByte(0x0080, 0x00));
4012
4013 cpu.ExecuteInstruction(0x14); // TRB Direct Page
4014}
4015
4016TEST_F(CpuTest, TRB_Absolute) {
4017 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
4018 cpu.A = 0x42;
4019 std::vector<uint8_t> data = {0x1C, 0xFF, 0x7F};
4020 mock_memory.SetMemoryContents(data);
4021 mock_memory.InsertMemory(0x7FFF, {0x00});
4022
4023 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x7FFF));
4024 EXPECT_CALL(mock_memory, ReadByte(0x7FFF)).WillOnce(Return(0x00));
4025 EXPECT_CALL(mock_memory, WriteByte(0x7FFF, 0x00));
4026
4027 cpu.ExecuteInstruction(0x1C); // TRB Absolute
4028}
4029
4030// ============================================================================
4031
4032TEST_F(CpuTest, TSB_DirectPage) {
4033 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
4034 cpu.A = 0x00;
4035 std::vector<uint8_t> data = {0x04, 0x80};
4036 mock_memory.SetMemoryContents(data);
4037 mock_memory.InsertMemory(0x0080, {0x42});
4038
4039 EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(Return(0x0080));
4040 EXPECT_CALL(mock_memory, ReadByte(0x0080)).WillOnce(Return(0x42));
4041 EXPECT_CALL(mock_memory, WriteByte(0x0080, 0x42));
4042
4043 cpu.ExecuteInstruction(0x04); // TSB Direct Page
4044}
4045
4046TEST_F(CpuTest, TSB_Absolute) {
4047 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
4048 cpu.A = 0x00;
4049 std::vector<uint8_t> data = {0x0C, 0xFF, 0x7F};
4050 mock_memory.SetMemoryContents(data);
4051 mock_memory.InsertMemory(0x7FFF, {0x42});
4052
4053 EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x7FFF));
4054 EXPECT_CALL(mock_memory, ReadByte(0x7FFF)).WillOnce(Return(0x42));
4055 EXPECT_CALL(mock_memory, WriteByte(0x7FFF, 0x42));
4056
4057 cpu.ExecuteInstruction(0x0C); // TSB Absolute
4058}
4059
4060// ============================================================================
4061
4063 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
4064 mock_memory.SetSP(0x42);
4065 std::vector<uint8_t> data = {0x3B};
4066 mock_memory.SetMemoryContents(data);
4067
4068 cpu.ExecuteInstruction(0x3B); // TSC
4069 EXPECT_EQ(cpu.A, 0x42);
4070}
4071
4072// ============================================================================
4073
4075 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
4076 mock_memory.SetSP(0x42);
4077 std::vector<uint8_t> data = {0xBA};
4078 mock_memory.SetMemoryContents(data);
4079
4080 cpu.ExecuteInstruction(0xBA); // TSX
4081 EXPECT_EQ(cpu.X, 0x42);
4082}
4083
4084// ============================================================================
4085// TXA - Transfer Index X to Accumulator
4086
4088 cpu.X = 0xAB; // X register
4089 std::vector<uint8_t> data = {0x8A}; // TXA
4090 mock_memory.SetMemoryContents(data);
4091
4092 cpu.ExecuteInstruction(0x8A); // TXA
4093 EXPECT_EQ(cpu.A, 0xAB); // A register should now be equal to X
4094}
4095
4096// ============================================================================
4097
4099 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
4100 cpu.X = 0x42;
4101 std::vector<uint8_t> data = {0x9A};
4102 mock_memory.SetMemoryContents(data);
4103
4104 cpu.ExecuteInstruction(0x9A); // TXS
4105 EXPECT_EQ(mock_memory.SP(), 0x42);
4106}
4107
4108// ============================================================================
4109
4111 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
4112 cpu.X = 0x42;
4113 std::vector<uint8_t> data = {0x9B};
4114 mock_memory.SetMemoryContents(data);
4115
4116 cpu.ExecuteInstruction(0x9B); // TXY
4117 EXPECT_EQ(cpu.Y, 0x42);
4118}
4119
4120// ============================================================================
4121// TYA - Transfer Index Y to Accumulator
4122
4124 cpu.Y = 0xCD; // Y register
4125 std::vector<uint8_t> data = {0x98}; // TYA
4126 mock_memory.SetMemoryContents(data);
4127
4128 cpu.ExecuteInstruction(0x98); // TYA
4129 EXPECT_EQ(cpu.A, 0xCD); // A register should now be equal to Y
4130}
4131
4132// ============================================================================
4133// TYX - Transfer Index Y to Index X
4134
4136 cpu.Y = 0xCD; // Y register
4137 std::vector<uint8_t> data = {0xBB}; // TYX
4138 mock_memory.SetMemoryContents(data);
4139
4140 cpu.ExecuteInstruction(0xBB); // TYX
4141 EXPECT_EQ(cpu.X, 0xCD); // X register should now be equal to Y
4142}
4143
4144// ============================================================================
4145
4147 cpu.ExecuteInstruction(0xCB); // WAI
4148 // EXPECT_TRUE(cpu.GetWaitingFlag());
4149}
4150
4151// ============================================================================
4152
4154 std::vector<uint8_t> data = {0x42};
4155 mock_memory.SetMemoryContents(data);
4156
4157 cpu.ExecuteInstruction(0x42); // WDM
4158}
4159
4160// ============================================================================
4161
4163 cpu.SetAccumulatorSize(true); // Set A register to 8-bit mode
4164 cpu.A = 0x4002;
4165 std::vector<uint8_t> data = {0xEB};
4166 mock_memory.SetMemoryContents(data);
4167
4168 cpu.ExecuteInstruction(0xEB); // XBA
4169 EXPECT_EQ(cpu.A, 0x0240);
4170}
4171
4172// ============================================================================
4173// XCE - Exchange Carry and Emulation Flags
4174
4175TEST_F(CpuTest, XCESwitchToNativeMode) {
4176 cpu.ExecuteInstruction(0x18); // Clear carry flag
4177 cpu.ExecuteInstruction(0xFB); // Switch to native mode
4178 EXPECT_FALSE(cpu.E); // Emulation mode flag should be cleared
4179}
4180
4181TEST_F(CpuTest, XCESwitchToEmulationMode) {
4182 cpu.ExecuteInstruction(0x38); // Set carry flag
4183 cpu.ExecuteInstruction(0xFB); // Switch to emulation mode
4184 EXPECT_TRUE(cpu.E); // Emulation mode flag should be set
4185}
4186
4187TEST_F(CpuTest, XCESwitchBackAndForth) {
4188 cpu.ExecuteInstruction(0x18); // Clear carry flag
4189 cpu.ExecuteInstruction(0xFB); // Switch to native mode
4190 EXPECT_FALSE(cpu.E); // Emulation mode flag should be cleared
4191
4192 cpu.ExecuteInstruction(0x38); // Set carry flag
4193 cpu.ExecuteInstruction(0xFB); // Switch to emulation mode
4194 EXPECT_TRUE(cpu.E); // Emulation mode flag should be set
4195
4196 cpu.ExecuteInstruction(0x18); // Clear carry flag
4197 cpu.ExecuteInstruction(0xFB); // Switch to native mode
4198 EXPECT_FALSE(cpu.E); // Emulation mode flag should be cleared
4199}
4200
4201} // namespace emu
4202} // namespace test
4203} // namespace yaze
std::vector< std::string > Tokenize(const std::string &instruction)
Definition asm_parser.h:139
std::vector< uint8_t > Parse(const std::string &instruction)
Definition asm_parser.h:70
virtual uint8_t ReadByte(uint32_t address) const =0
Mock CPU class for testing.
Definition mock_memory.h:19
A mock implementation of the Memory class.
Definition mock_memory.h:45
void SetMemoryContents(const std::vector< uint8_t > &data)
Definition mock_memory.h:90
CpuCallbacks cpu_callbacks
Definition cpu_test.cc:36
void SetUp() override
Definition cpu_test.cc:27
TEST_F(CpuTest, AsmParserTokenizerOk)
Definition cpu_test.cc:47
Definition common.cc:22