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