Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
folium-app
GitHub Repository: folium-app/Folium
Path: blob/a-new-beginning/Cherry/Core/include/Processor_inline.h
2 views
1
/*
2
* Gearcoleco - ColecoVision Emulator
3
* Copyright (C) 2021 Ignacio Sanchez
4
5
* This program is free software: you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation, either version 3 of the License, or
8
* any later version.
9
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
14
15
* You should have received a copy of the GNU General Public License
16
* along with this program. If not, see http://www.gnu.org/licenses/
17
*
18
*/
19
20
#ifndef PROCESSOR_INLINE_H
21
#define PROCESSOR_INLINE_H
22
23
#include "definitions.h"
24
#include "SixteenBitRegister.h"
25
#include "Processor.h"
26
#include "IOPorts.h"
27
28
inline u8 Processor::FetchOPCode()
29
{
30
u8 opcode = m_pMemory->Read(PC.GetValue());
31
PC.Increment();
32
return opcode;
33
}
34
35
inline u16 Processor::FetchArg16()
36
{
37
u16 pc = PC.GetValue();
38
u8 l = m_pMemory->Read(pc);
39
u8 h = m_pMemory->Read(pc + 1);
40
PC.SetValue(pc + 2);
41
return (h << 8) | l;
42
}
43
44
inline void Processor::LeaveHalt()
45
{
46
if (m_bHalt)
47
{
48
m_bHalt = false;
49
PC.Increment();
50
}
51
}
52
53
inline void Processor::ClearAllFlags()
54
{
55
SetFlag(FLAG_NONE);
56
}
57
58
inline void Processor::ToggleZeroFlagFromResult(u16 result)
59
{
60
if (result == 0)
61
ToggleFlag(FLAG_ZERO);
62
else
63
ClearFlag(FLAG_ZERO);
64
}
65
66
inline void Processor::ToggleSignFlagFromResult(u8 result)
67
{
68
if ((result & 0x80) != 0)
69
ToggleFlag(FLAG_SIGN);
70
else
71
ClearFlag(FLAG_SIGN);
72
}
73
74
inline void Processor::ToggleXYFlagsFromResult(u8 result)
75
{
76
if ((result & 0x08) != 0)
77
ToggleFlag(FLAG_X);
78
else
79
ClearFlag(FLAG_X);
80
if ((result & 0x20) != 0)
81
ToggleFlag(FLAG_Y);
82
else
83
ClearFlag(FLAG_Y);
84
}
85
86
inline void Processor::ToggleParityFlagFromResult(u8 result)
87
{
88
if (kZ80ParityTable[result])
89
ToggleFlag(FLAG_PARITY);
90
else
91
ClearFlag(FLAG_PARITY);
92
}
93
94
inline void Processor::SetFlag(u8 flag)
95
{
96
AF.SetLow(flag);
97
}
98
99
inline void Processor::FlipFlag(u8 flag)
100
{
101
AF.SetLow(AF.GetLow() ^ flag);
102
}
103
104
inline void Processor::ToggleFlag(u8 flag)
105
{
106
AF.SetLow(AF.GetLow() | flag);
107
}
108
109
inline void Processor::ClearFlag(u8 flag)
110
{
111
AF.SetLow(AF.GetLow() & (~flag));
112
}
113
114
inline bool Processor::IsSetFlag(u8 flag)
115
{
116
return (AF.GetLow() & flag) != 0;
117
}
118
119
inline void Processor::StackPush(SixteenBitRegister* reg)
120
{
121
SP.Decrement();
122
m_pMemory->Write(SP.GetValue(), reg->GetHigh());
123
SP.Decrement();
124
m_pMemory->Write(SP.GetValue(), reg->GetLow());
125
}
126
127
inline void Processor::StackPop(SixteenBitRegister* reg)
128
{
129
reg->SetLow(m_pMemory->Read(SP.GetValue()));
130
SP.Increment();
131
reg->SetHigh(m_pMemory->Read(SP.GetValue()));
132
SP.Increment();
133
}
134
135
inline void Processor::SetInterruptMode(int mode)
136
{
137
if (mode == 1)
138
{
139
m_iInterruptMode = mode;
140
}
141
else
142
{
143
Debug("--> ** Attempting to set interrupt mode %d", mode);
144
}
145
}
146
147
inline SixteenBitRegister* Processor::GetPrefixedRegister()
148
{
149
switch (m_CurrentPrefix)
150
{
151
case 0xDD:
152
return &IX;
153
case 0xFD:
154
return &IY;
155
default:
156
return &HL;
157
}
158
}
159
160
inline u16 Processor::GetEffectiveAddress()
161
{
162
switch (m_CurrentPrefix)
163
{
164
case 0xDD:
165
{
166
u16 address = IX.GetValue();
167
if (m_bPrefixedCBOpcode)
168
{
169
address += static_cast<s8> (m_PrefixedCBValue);
170
}
171
else
172
{
173
address += static_cast<s8> (m_pMemory->Read(PC.GetValue()));
174
PC.Increment();
175
WZ.SetValue(address);
176
}
177
return address;
178
}
179
case 0xFD:
180
{
181
u16 address = IY.GetValue();
182
if (m_bPrefixedCBOpcode)
183
{
184
address += static_cast<s8> (m_PrefixedCBValue);
185
}
186
else
187
{
188
address += static_cast<s8> (m_pMemory->Read(PC.GetValue()));
189
PC.Increment();
190
WZ.SetValue(address);
191
}
192
return address;
193
}
194
default:
195
return HL.GetValue();
196
}
197
}
198
199
inline bool Processor::IsPrefixedInstruction()
200
{
201
return (m_CurrentPrefix == 0xDD) || (m_CurrentPrefix == 0xFD);
202
}
203
204
inline void Processor::IncreaseR()
205
{
206
u8 r = R;
207
R = ((r + 1) & 0x7F) | (r & 0x80);
208
m_iTStates++; // M1 1 cycle wait
209
}
210
211
inline void Processor::OPCodes_LD(u8* reg1, u8 value)
212
{
213
*reg1 = value;
214
}
215
216
inline void Processor::OPCodes_LD(u8* reg, u16 address)
217
{
218
*reg = m_pMemory->Read(address);
219
}
220
221
inline void Processor::OPCodes_LD(u16 address, u8 reg)
222
{
223
m_pMemory->Write(address, reg);
224
}
225
226
inline void Processor::OPCodes_LD_dd_nn(SixteenBitRegister* reg)
227
{
228
u16 address = FetchArg16();
229
reg->SetLow(m_pMemory->Read(address));
230
address++;
231
reg->SetHigh(m_pMemory->Read(address));
232
WZ.SetValue(address);
233
}
234
235
inline void Processor::OPCodes_LD_nn_dd(SixteenBitRegister* reg)
236
{
237
u16 address = FetchArg16();
238
m_pMemory->Write(address, reg->GetLow());
239
address++;
240
m_pMemory->Write(address, reg->GetHigh());
241
WZ.SetValue(address);
242
}
243
244
inline void Processor::OPCodes_LDI()
245
{
246
u8 result = m_pMemory->Read(HL.GetValue());
247
m_pMemory->Write(DE.GetValue(), result);
248
DE.Increment();
249
HL.Increment();
250
BC.Decrement();
251
ClearFlag(FLAG_NEGATIVE);
252
ClearFlag(FLAG_HALF);
253
if (BC.GetValue() != 0)
254
ToggleFlag(FLAG_PARITY);
255
else
256
ClearFlag(FLAG_PARITY);
257
u16 n = AF.GetHigh() + result;
258
if ((n & 0x08) != 0)
259
ToggleFlag(FLAG_X);
260
else
261
ClearFlag(FLAG_X);
262
if ((n & 0x02) != 0)
263
ToggleFlag(FLAG_Y);
264
else
265
ClearFlag(FLAG_Y);
266
}
267
268
inline void Processor::OPCodes_LDD()
269
{
270
u8 result = m_pMemory->Read(HL.GetValue());
271
m_pMemory->Write(DE.GetValue(), result);
272
DE.Decrement();
273
HL.Decrement();
274
BC.Decrement();
275
ClearFlag(FLAG_NEGATIVE);
276
ClearFlag(FLAG_HALF);
277
if (BC.GetValue() != 0)
278
ToggleFlag(FLAG_PARITY);
279
else
280
ClearFlag(FLAG_PARITY);
281
u16 n = AF.GetHigh() + result;
282
if ((n & 0x08) != 0)
283
ToggleFlag(FLAG_X);
284
else
285
ClearFlag(FLAG_X);
286
if ((n & 0x02) != 0)
287
ToggleFlag(FLAG_Y);
288
else
289
ClearFlag(FLAG_Y);
290
}
291
292
inline void Processor::OPCodes_RST(u16 address)
293
{
294
StackPush(&PC);
295
PC.SetValue(address);
296
WZ.SetValue(address);
297
}
298
299
inline void Processor::OPCodes_CALL_nn()
300
{
301
u16 address = FetchArg16();
302
StackPush(&PC);
303
PC.SetValue(address);
304
WZ.SetValue(address);
305
}
306
307
inline void Processor::OPCodes_CALL_nn_Conditional(bool condition)
308
{
309
u16 address = FetchArg16();
310
if (condition)
311
{
312
StackPush(&PC);
313
PC.SetValue(address);
314
m_bBranchTaken = true;
315
}
316
WZ.SetValue(address);
317
}
318
319
inline void Processor::OPCodes_JP_nn()
320
{
321
u8 l = m_pMemory->Read(PC.GetValue());
322
u8 h = m_pMemory->Read(PC.GetValue() + 1);
323
u16 address = (h << 8) | l;
324
PC.SetValue(address);
325
WZ.SetValue(address);
326
}
327
328
inline void Processor::OPCodes_JP_nn_Conditional(bool condition)
329
{
330
u8 l = m_pMemory->Read(PC.GetValue());
331
u8 h = m_pMemory->Read(PC.GetValue() + 1);
332
u16 address = (h << 8) | l;
333
if (condition)
334
{
335
PC.SetValue(address);
336
m_bBranchTaken = true;
337
}
338
else
339
{
340
PC.Increment();
341
PC.Increment();
342
}
343
WZ.SetValue(address);
344
}
345
346
inline void Processor::OPCodes_JR_n()
347
{
348
u16 pc = PC.GetValue();
349
PC.SetValue(pc + 1 + (static_cast<s8> (m_pMemory->Read(pc))));
350
}
351
352
inline void Processor::OPCodes_JR_n_conditional(bool condition)
353
{
354
if (condition)
355
{
356
OPCodes_JR_n();
357
m_bBranchTaken = true;
358
}
359
else
360
PC.Increment();
361
}
362
363
inline void Processor::OPCodes_RET()
364
{
365
StackPop(&PC);
366
WZ.SetValue(PC.GetValue());
367
}
368
369
inline void Processor::OPCodes_RET_Conditional(bool condition)
370
{
371
if (condition)
372
{
373
OPCodes_RET();
374
m_bBranchTaken = true;
375
}
376
}
377
378
inline void Processor::OPCodes_IN_C(u8* reg)
379
{
380
u8 result = m_pIOPorts->In(BC.GetLow());
381
if (IsValidPointer(reg))
382
*reg = result;
383
IsSetFlag(FLAG_CARRY) ? SetFlag(FLAG_CARRY) : ClearAllFlags();
384
ToggleZeroFlagFromResult(result);
385
ToggleSignFlagFromResult(result);
386
ToggleParityFlagFromResult(result);
387
ToggleXYFlagsFromResult(result);
388
}
389
390
inline void Processor::OPCodes_INI()
391
{
392
WZ.SetValue(BC.GetValue() + 1);
393
u8 result = m_pIOPorts->In(BC.GetLow());
394
m_pMemory->Write(HL.GetValue(), result);
395
OPCodes_DEC(BC.GetHighRegister());
396
HL.Increment();
397
if ((result & 0x80) != 0)
398
ToggleFlag(FLAG_NEGATIVE);
399
else
400
ClearFlag(FLAG_NEGATIVE);
401
if ((result + ((BC.GetLow() + 1) & 0xFF)) > 0xFF)
402
{
403
ToggleFlag(FLAG_CARRY);
404
ToggleFlag(FLAG_HALF);
405
}
406
else
407
{
408
ClearFlag(FLAG_CARRY);
409
ClearFlag(FLAG_HALF);
410
}
411
if (((result + ((BC.GetLow() + 1) & 0xFF)) & 0x07) ^ BC.GetHigh())
412
ToggleFlag(FLAG_PARITY);
413
else
414
ClearFlag(FLAG_PARITY);
415
}
416
417
inline void Processor::OPCodes_IND()
418
{
419
WZ.SetValue(BC.GetValue() - 1);
420
u8 result = m_pIOPorts->In(BC.GetLow());
421
m_pMemory->Write(HL.GetValue(), result);
422
OPCodes_DEC(BC.GetHighRegister());
423
HL.Decrement();
424
if ((result & 0x80) != 0)
425
ToggleFlag(FLAG_NEGATIVE);
426
else
427
ClearFlag(FLAG_NEGATIVE);
428
if ((result + ((BC.GetLow() - 1) & 0xFF)) > 0xFF)
429
{
430
ToggleFlag(FLAG_CARRY);
431
ToggleFlag(FLAG_HALF);
432
}
433
else
434
{
435
ClearFlag(FLAG_CARRY);
436
ClearFlag(FLAG_HALF);
437
}
438
if (((result + ((BC.GetLow() + 1) & 0xFF)) & 0x07) ^ BC.GetHigh())
439
ToggleFlag(FLAG_PARITY);
440
else
441
ClearFlag(FLAG_PARITY);
442
}
443
444
inline void Processor::OPCodes_OUT_C(u8* reg)
445
{
446
m_pIOPorts->Out(BC.GetLow(), *reg);
447
}
448
449
inline void Processor::OPCodes_OUTI()
450
{
451
u8 result = m_pMemory->Read(HL.GetValue());
452
m_pIOPorts->Out(BC.GetLow(), result);
453
OPCodes_DEC(BC.GetHighRegister());
454
WZ.SetValue(BC.GetValue() + 1);
455
HL.Increment();
456
if ((result & 0x80) != 0)
457
ToggleFlag(FLAG_NEGATIVE);
458
else
459
ClearFlag(FLAG_NEGATIVE);
460
if ((HL.GetLow() + result) > 0xFF)
461
{
462
ToggleFlag(FLAG_CARRY);
463
ToggleFlag(FLAG_HALF);
464
}
465
else
466
{
467
ClearFlag(FLAG_CARRY);
468
ClearFlag(FLAG_HALF);
469
}
470
if (((HL.GetLow() + result) & 0x07) ^ BC.GetHigh())
471
ToggleFlag(FLAG_PARITY);
472
else
473
ClearFlag(FLAG_PARITY);
474
}
475
476
inline void Processor::OPCodes_OUTD()
477
{
478
u8 result = m_pMemory->Read(HL.GetValue());
479
m_pIOPorts->Out(BC.GetLow(), result);
480
OPCodes_DEC(BC.GetHighRegister());
481
WZ.SetValue(BC.GetValue() - 1);
482
HL.Decrement();
483
if ((result & 0x80) != 0)
484
ToggleFlag(FLAG_NEGATIVE);
485
else
486
ClearFlag(FLAG_NEGATIVE);
487
if ((HL.GetLow() + result) > 0xFF)
488
{
489
ToggleFlag(FLAG_CARRY);
490
ToggleFlag(FLAG_HALF);
491
}
492
else
493
{
494
ClearFlag(FLAG_CARRY);
495
ClearFlag(FLAG_HALF);
496
}
497
if (((HL.GetLow() + result) & 0x07) ^ BC.GetHigh())
498
ToggleFlag(FLAG_PARITY);
499
else
500
ClearFlag(FLAG_PARITY);
501
}
502
503
inline void Processor::OPCodes_EX(SixteenBitRegister* reg1, SixteenBitRegister* reg2)
504
{
505
u16 tmp = reg1->GetValue();
506
reg1->SetValue(reg2->GetValue());
507
reg2->SetValue(tmp);
508
}
509
510
inline void Processor::OPCodes_OR(u8 number)
511
{
512
u8 result = AF.GetHigh() | number;
513
AF.SetHigh(result);
514
ClearAllFlags();
515
ToggleZeroFlagFromResult(result);
516
ToggleSignFlagFromResult(result);
517
ToggleXYFlagsFromResult(result);
518
ToggleParityFlagFromResult(result);
519
}
520
521
inline void Processor::OPCodes_XOR(u8 number)
522
{
523
u8 result = AF.GetHigh() ^ number;
524
AF.SetHigh(result);
525
ClearAllFlags();
526
ToggleZeroFlagFromResult(result);
527
ToggleSignFlagFromResult(result);
528
ToggleXYFlagsFromResult(result);
529
ToggleParityFlagFromResult(result);
530
}
531
532
inline void Processor::OPCodes_AND(u8 number)
533
{
534
u8 result = AF.GetHigh() & number;
535
AF.SetHigh(result);
536
SetFlag(FLAG_HALF);
537
ToggleZeroFlagFromResult(result);
538
ToggleSignFlagFromResult(result);
539
ToggleXYFlagsFromResult(result);
540
ToggleParityFlagFromResult(result);
541
}
542
543
inline void Processor::OPCodes_CP(u8 number)
544
{
545
int result = AF.GetHigh() - number;
546
int carrybits = AF.GetHigh() ^ number ^ result;
547
u8 final_result = static_cast<u8> (result);
548
SetFlag(FLAG_NEGATIVE);
549
ToggleZeroFlagFromResult(final_result);
550
ToggleSignFlagFromResult(final_result);
551
ToggleXYFlagsFromResult(number);
552
if ((carrybits & 0x100) != 0)
553
ToggleFlag(FLAG_CARRY);
554
if ((carrybits & 0x10) != 0)
555
ToggleFlag(FLAG_HALF);
556
if ((((carrybits << 1) ^ carrybits) & 0x100) != 0)
557
ToggleFlag(FLAG_PARITY);
558
}
559
560
inline void Processor::OPCodes_CPI()
561
{
562
u8 number = m_pMemory->Read(HL.GetValue());
563
int result = AF.GetHigh() - number;
564
int carrybits = AF.GetHigh() ^ number ^ result;
565
u8 final_result = static_cast<u8> (result);
566
ToggleFlag(FLAG_NEGATIVE);
567
ToggleZeroFlagFromResult(final_result);
568
ToggleSignFlagFromResult(final_result);
569
if ((carrybits & 0x10) != 0)
570
ToggleFlag(FLAG_HALF);
571
else
572
ClearFlag(FLAG_HALF);
573
HL.Increment();
574
BC.Decrement();
575
if (BC.GetValue() != 0)
576
ToggleFlag(FLAG_PARITY);
577
else
578
ClearFlag(FLAG_PARITY);
579
int n = AF.GetHigh() - number - (IsSetFlag(FLAG_HALF) ? 1 : 0);
580
if ((n & 0x08) != 0)
581
ToggleFlag(FLAG_X);
582
else
583
ClearFlag(FLAG_X);
584
if ((n & 0x02) != 0)
585
ToggleFlag(FLAG_Y);
586
else
587
ClearFlag(FLAG_Y);
588
WZ.Increment();
589
}
590
591
inline void Processor::OPCodes_CPD()
592
{
593
u8 number = m_pMemory->Read(HL.GetValue());
594
int result = AF.GetHigh() - number;
595
int carrybits = AF.GetHigh() ^ number ^ result;
596
u8 final_result = static_cast<u8> (result);
597
ToggleFlag(FLAG_NEGATIVE);
598
ToggleZeroFlagFromResult(final_result);
599
ToggleSignFlagFromResult(final_result);
600
if ((carrybits & 0x10) != 0)
601
ToggleFlag(FLAG_HALF);
602
else
603
ClearFlag(FLAG_HALF);
604
HL.Decrement();
605
BC.Decrement();
606
if (BC.GetValue() != 0)
607
ToggleFlag(FLAG_PARITY);
608
else
609
ClearFlag(FLAG_PARITY);
610
int n = AF.GetHigh() - number - (IsSetFlag(FLAG_HALF) ? 1 : 0);
611
if ((n & 0x08) != 0)
612
ToggleFlag(FLAG_X);
613
else
614
ClearFlag(FLAG_X);
615
if ((n & 0x02) != 0)
616
ToggleFlag(FLAG_Y);
617
else
618
ClearFlag(FLAG_Y);
619
WZ.Decrement();
620
}
621
622
inline void Processor::OPCodes_INC(u8* reg)
623
{
624
u8 result = *reg + 1;
625
*reg = result;
626
IsSetFlag(FLAG_CARRY) ? SetFlag(FLAG_CARRY) : ClearAllFlags();
627
ToggleZeroFlagFromResult(result);
628
ToggleSignFlagFromResult(result);
629
ToggleXYFlagsFromResult(result);
630
if ((result & 0x0F) == 0x00)
631
ToggleFlag(FLAG_HALF);
632
if (result == 0x80)
633
ToggleFlag(FLAG_PARITY);
634
}
635
636
inline void Processor::OPCodes_INC_HL()
637
{
638
u16 address = GetEffectiveAddress();
639
u8 result = m_pMemory->Read(address) + 1;
640
m_pMemory->Write(address, result);
641
IsSetFlag(FLAG_CARRY) ? SetFlag(FLAG_CARRY) : ClearAllFlags();
642
ToggleZeroFlagFromResult(result);
643
ToggleSignFlagFromResult(result);
644
ToggleXYFlagsFromResult(result);
645
if ((result & 0x0F) == 0x00)
646
ToggleFlag(FLAG_HALF);
647
if (result == 0x80)
648
ToggleFlag(FLAG_PARITY);
649
}
650
651
inline void Processor::OPCodes_DEC(u8* reg)
652
{
653
u8 result = *reg - 1;
654
*reg = result;
655
IsSetFlag(FLAG_CARRY) ? SetFlag(FLAG_CARRY) : ClearAllFlags();
656
ToggleFlag(FLAG_NEGATIVE);
657
ToggleZeroFlagFromResult(result);
658
ToggleSignFlagFromResult(result);
659
ToggleXYFlagsFromResult(result);
660
if ((result & 0x0F) == 0x0F)
661
ToggleFlag(FLAG_HALF);
662
if (result == 0x7F)
663
ToggleFlag(FLAG_PARITY);
664
}
665
666
inline void Processor::OPCodes_DEC_HL()
667
{
668
u16 address = GetEffectiveAddress();
669
u8 result = m_pMemory->Read(address) - 1;
670
m_pMemory->Write(address, result);
671
IsSetFlag(FLAG_CARRY) ? SetFlag(FLAG_CARRY) : ClearAllFlags();
672
ToggleFlag(FLAG_NEGATIVE);
673
ToggleZeroFlagFromResult(result);
674
ToggleSignFlagFromResult(result);
675
ToggleXYFlagsFromResult(result);
676
if ((result & 0x0F) == 0x0F)
677
ToggleFlag(FLAG_HALF);
678
if (result == 0x7F)
679
ToggleFlag(FLAG_PARITY);
680
}
681
682
inline void Processor::OPCodes_ADD(u8 number)
683
{
684
int result = AF.GetHigh() + number;
685
int carrybits = AF.GetHigh() ^ number ^ result;
686
u8 final_result = static_cast<u8> (result);
687
AF.SetHigh(final_result);
688
ClearAllFlags();
689
ToggleZeroFlagFromResult(final_result);
690
ToggleSignFlagFromResult(final_result);
691
ToggleXYFlagsFromResult(final_result);
692
if ((carrybits & 0x100) != 0)
693
ToggleFlag(FLAG_CARRY);
694
if ((carrybits & 0x10) != 0)
695
ToggleFlag(FLAG_HALF);
696
if ((((carrybits << 1) ^ carrybits) & 0x100) != 0)
697
ToggleFlag(FLAG_PARITY);
698
}
699
700
inline void Processor::OPCodes_ADC(u8 number)
701
{
702
int result = AF.GetHigh() + number + (IsSetFlag(FLAG_CARRY) ? 1 : 0);
703
int carrybits = AF.GetHigh() ^ number ^ result;
704
u8 final_result = static_cast<u8> (result);
705
AF.SetHigh(final_result);
706
ClearAllFlags();
707
ToggleZeroFlagFromResult(final_result);
708
ToggleSignFlagFromResult(final_result);
709
ToggleXYFlagsFromResult(final_result);
710
if ((carrybits & 0x100) != 0)
711
ToggleFlag(FLAG_CARRY);
712
if ((carrybits & 0x10) != 0)
713
ToggleFlag(FLAG_HALF);
714
if ((((carrybits << 1) ^ carrybits) & 0x100) != 0)
715
ToggleFlag(FLAG_PARITY);
716
}
717
718
inline void Processor::OPCodes_SUB(u8 number)
719
{
720
int result = AF.GetHigh() - number;
721
int carrybits = AF.GetHigh() ^ number ^ result;
722
u8 final_result = static_cast<u8> (result);
723
AF.SetHigh(final_result);
724
SetFlag(FLAG_NEGATIVE);
725
ToggleZeroFlagFromResult(final_result);
726
ToggleSignFlagFromResult(final_result);
727
ToggleXYFlagsFromResult(final_result);
728
if ((carrybits & 0x100) != 0)
729
ToggleFlag(FLAG_CARRY);
730
if ((carrybits & 0x10) != 0)
731
ToggleFlag(FLAG_HALF);
732
if ((((carrybits << 1) ^ carrybits) & 0x100) != 0)
733
ToggleFlag(FLAG_PARITY);
734
}
735
736
inline void Processor::OPCodes_SBC(u8 number)
737
{
738
int result = AF.GetHigh() - number - (IsSetFlag(FLAG_CARRY) ? 1 : 0);
739
int carrybits = AF.GetHigh() ^ number ^ result;
740
u8 final_result = static_cast<u8> (result);
741
AF.SetHigh(final_result);
742
SetFlag(FLAG_NEGATIVE);
743
ToggleZeroFlagFromResult(final_result);
744
ToggleSignFlagFromResult(final_result);
745
ToggleXYFlagsFromResult(final_result);
746
if ((carrybits & 0x100) != 0)
747
ToggleFlag(FLAG_CARRY);
748
if ((carrybits & 0x10) != 0)
749
ToggleFlag(FLAG_HALF);
750
if ((((carrybits << 1) ^ carrybits) & 0x100) != 0)
751
ToggleFlag(FLAG_PARITY);
752
}
753
754
inline void Processor::OPCodes_ADD_HL(u16 number)
755
{
756
SixteenBitRegister* reg = GetPrefixedRegister();
757
WZ.SetValue(reg->GetValue() + 1);
758
int result = reg->GetValue() + number;
759
int carrybits = reg->GetValue() ^ number ^ result;
760
reg->SetValue(static_cast<u16> (result));
761
ClearFlag(FLAG_NEGATIVE);
762
ToggleXYFlagsFromResult(reg->GetHigh());
763
if ((carrybits & 0x10000) != 0)
764
ToggleFlag(FLAG_CARRY);
765
else
766
ClearFlag(FLAG_CARRY);
767
if ((carrybits & 0x1000) != 0)
768
ToggleFlag(FLAG_HALF);
769
else
770
ClearFlag(FLAG_HALF);
771
}
772
773
inline void Processor::OPCodes_ADC_HL(u16 number)
774
{
775
WZ.SetValue(HL.GetValue() + 1);
776
int result = HL.GetValue() + number + (IsSetFlag(FLAG_CARRY) ? 1 : 0);
777
int carrybits = HL.GetValue() ^ number ^ result;
778
u16 final_result = static_cast<u16> (result);
779
HL.SetValue(final_result);
780
ClearAllFlags();
781
ToggleXYFlagsFromResult(HL.GetHigh());
782
ToggleSignFlagFromResult(HL.GetHigh());
783
ToggleZeroFlagFromResult(final_result);
784
if ((carrybits & 0x10000) != 0)
785
ToggleFlag(FLAG_CARRY);
786
if ((carrybits & 0x1000) != 0)
787
ToggleFlag(FLAG_HALF);
788
if ((((carrybits << 1) ^ carrybits) & 0x10000) != 0)
789
ToggleFlag(FLAG_PARITY);
790
}
791
792
inline void Processor::OPCodes_SBC_HL(u16 number)
793
{
794
WZ.SetValue(HL.GetValue() + 1);
795
int result = HL.GetValue() - number - (IsSetFlag(FLAG_CARRY) ? 1 : 0);
796
int carrybits = HL.GetValue() ^ number ^ result;
797
u16 final_result = static_cast<u16> (result);
798
HL.SetValue(final_result);
799
SetFlag(FLAG_NEGATIVE);
800
ToggleXYFlagsFromResult(HL.GetHigh());
801
ToggleSignFlagFromResult(HL.GetHigh());
802
ToggleZeroFlagFromResult(final_result);
803
if ((carrybits & 0x10000) != 0)
804
ToggleFlag(FLAG_CARRY);
805
if ((carrybits & 0x1000) != 0)
806
ToggleFlag(FLAG_HALF);
807
if ((((carrybits << 1) ^ carrybits) & 0x10000) != 0)
808
ToggleFlag(FLAG_PARITY);
809
}
810
811
inline void Processor::OPCodes_SLL(u8* reg)
812
{
813
u16 address = 0x0000;
814
if (IsPrefixedInstruction())
815
{
816
address = GetEffectiveAddress();
817
*reg = m_pMemory->Read(address);
818
}
819
(*reg & 0x80) != 0 ? SetFlag(FLAG_CARRY) : ClearAllFlags();
820
u8 result = (*reg << 1) | 0x01;
821
*reg = result;
822
if (IsPrefixedInstruction())
823
m_pMemory->Write(address, *reg);
824
ToggleZeroFlagFromResult(result);
825
ToggleSignFlagFromResult(result);
826
ToggleParityFlagFromResult(result);
827
ToggleXYFlagsFromResult(result);
828
}
829
830
inline void Processor::OPCodes_SLL_HL()
831
{
832
u16 address = GetEffectiveAddress();
833
u8 result = m_pMemory->Read(address);
834
(result & 0x80) != 0 ? SetFlag(FLAG_CARRY) : ClearAllFlags();
835
result = (result << 1) | 0x01;
836
m_pMemory->Write(address, result);
837
ToggleZeroFlagFromResult(result);
838
ToggleSignFlagFromResult(result);
839
ToggleParityFlagFromResult(result);
840
ToggleXYFlagsFromResult(result);
841
}
842
843
inline void Processor::OPCodes_SLA(u8* reg)
844
{
845
u16 address = 0x0000;
846
if (IsPrefixedInstruction())
847
{
848
address = GetEffectiveAddress();
849
*reg = m_pMemory->Read(address);
850
}
851
(*reg & 0x80) != 0 ? SetFlag(FLAG_CARRY) : ClearAllFlags();
852
u8 result = *reg << 1;
853
*reg = result;
854
if (IsPrefixedInstruction())
855
m_pMemory->Write(address, *reg);
856
ToggleZeroFlagFromResult(result);
857
ToggleSignFlagFromResult(result);
858
ToggleParityFlagFromResult(result);
859
ToggleXYFlagsFromResult(result);
860
}
861
862
inline void Processor::OPCodes_SLA_HL()
863
{
864
u16 address = GetEffectiveAddress();
865
u8 result = m_pMemory->Read(address);
866
(result & 0x80) != 0 ? SetFlag(FLAG_CARRY) : ClearAllFlags();
867
result <<= 1;
868
m_pMemory->Write(address, result);
869
ToggleZeroFlagFromResult(result);
870
ToggleSignFlagFromResult(result);
871
ToggleParityFlagFromResult(result);
872
ToggleXYFlagsFromResult(result);
873
}
874
875
inline void Processor::OPCodes_SRA(u8* reg)
876
{
877
u16 address = 0x0000;
878
if (IsPrefixedInstruction())
879
{
880
address = GetEffectiveAddress();
881
*reg = m_pMemory->Read(address);
882
}
883
u8 result = *reg;
884
(result & 0x01) != 0 ? SetFlag(FLAG_CARRY) : ClearAllFlags();
885
if ((result & 0x80) != 0)
886
{
887
result >>= 1;
888
result |= 0x80;
889
}
890
else
891
result >>= 1;
892
*reg = result;
893
if (IsPrefixedInstruction())
894
m_pMemory->Write(address, *reg);
895
ToggleZeroFlagFromResult(result);
896
ToggleSignFlagFromResult(result);
897
ToggleParityFlagFromResult(result);
898
ToggleXYFlagsFromResult(result);
899
}
900
901
inline void Processor::OPCodes_SRA_HL()
902
{
903
u16 address = GetEffectiveAddress();
904
u8 result = m_pMemory->Read(address);
905
(result & 0x01) != 0 ? SetFlag(FLAG_CARRY) : ClearAllFlags();
906
if ((result & 0x80) != 0)
907
{
908
result >>= 1;
909
result |= 0x80;
910
}
911
else
912
result >>= 1;
913
m_pMemory->Write(address, result);
914
ToggleZeroFlagFromResult(result);
915
ToggleSignFlagFromResult(result);
916
ToggleParityFlagFromResult(result);
917
ToggleXYFlagsFromResult(result);
918
}
919
920
inline void Processor::OPCodes_SRL(u8* reg)
921
{
922
u16 address = 0x0000;
923
if (IsPrefixedInstruction())
924
{
925
address = GetEffectiveAddress();
926
*reg = m_pMemory->Read(address);
927
}
928
u8 result = *reg;
929
(result & 0x01) != 0 ? SetFlag(FLAG_CARRY) : ClearAllFlags();
930
result >>= 1;
931
*reg = result;
932
if (IsPrefixedInstruction())
933
m_pMemory->Write(address, *reg);
934
ToggleZeroFlagFromResult(result);
935
ToggleSignFlagFromResult(result);
936
ToggleParityFlagFromResult(result);
937
ToggleXYFlagsFromResult(result);
938
}
939
940
inline void Processor::OPCodes_SRL_HL()
941
{
942
u16 address = GetEffectiveAddress();
943
u8 result = m_pMemory->Read(address);
944
(result & 0x01) != 0 ? SetFlag(FLAG_CARRY) : ClearAllFlags();
945
result >>= 1;
946
m_pMemory->Write(address, result);
947
ToggleZeroFlagFromResult(result);
948
ToggleSignFlagFromResult(result);
949
ToggleParityFlagFromResult(result);
950
ToggleXYFlagsFromResult(result);
951
}
952
953
inline void Processor::OPCodes_RLC(u8* reg, bool isRegisterA)
954
{
955
u16 address = 0x0000;
956
if (!isRegisterA && IsPrefixedInstruction())
957
{
958
address = GetEffectiveAddress();
959
*reg = m_pMemory->Read(address);
960
}
961
u8 result = *reg;
962
if ((result & 0x80) != 0)
963
{
964
ToggleFlag(FLAG_CARRY);
965
result <<= 1;
966
result |= 0x1;
967
}
968
else
969
{
970
ClearFlag(FLAG_CARRY);
971
result <<= 1;
972
}
973
*reg = result;
974
if (!isRegisterA && IsPrefixedInstruction())
975
m_pMemory->Write(address, *reg);
976
ClearFlag(FLAG_HALF);
977
ClearFlag(FLAG_NEGATIVE);
978
ToggleXYFlagsFromResult(result);
979
if (!isRegisterA)
980
{
981
ToggleZeroFlagFromResult(result);
982
ToggleSignFlagFromResult(result);
983
ToggleParityFlagFromResult(result);
984
}
985
}
986
987
inline void Processor::OPCodes_RLC_HL()
988
{
989
u16 address = GetEffectiveAddress();
990
u8 result = m_pMemory->Read(address);
991
if ((result & 0x80) != 0)
992
{
993
SetFlag(FLAG_CARRY);
994
result <<= 1;
995
result |= 0x1;
996
}
997
else
998
{
999
ClearAllFlags();
1000
result <<= 1;
1001
}
1002
m_pMemory->Write(address, result);
1003
ToggleZeroFlagFromResult(result);
1004
ToggleSignFlagFromResult(result);
1005
ToggleParityFlagFromResult(result);
1006
ToggleXYFlagsFromResult(result);
1007
}
1008
1009
inline void Processor::OPCodes_RL(u8* reg, bool isRegisterA)
1010
{
1011
u16 address = 0x0000;
1012
if (!isRegisterA && IsPrefixedInstruction())
1013
{
1014
address = GetEffectiveAddress();
1015
*reg = m_pMemory->Read(address);
1016
}
1017
u8 carry = IsSetFlag(FLAG_CARRY) ? 1 : 0;
1018
u8 result = *reg;
1019
((result & 0x80) != 0) ? ToggleFlag(FLAG_CARRY) : ClearFlag(FLAG_CARRY);
1020
result <<= 1;
1021
result |= carry;
1022
*reg = result;
1023
if (!isRegisterA && IsPrefixedInstruction())
1024
m_pMemory->Write(address, *reg);
1025
ClearFlag(FLAG_HALF);
1026
ClearFlag(FLAG_NEGATIVE);
1027
ToggleXYFlagsFromResult(result);
1028
if (!isRegisterA)
1029
{
1030
ToggleZeroFlagFromResult(result);
1031
ToggleSignFlagFromResult(result);
1032
ToggleParityFlagFromResult(result);
1033
}
1034
}
1035
1036
inline void Processor::OPCodes_RL_HL()
1037
{
1038
u16 address = GetEffectiveAddress();
1039
u8 carry = IsSetFlag(FLAG_CARRY) ? 1 : 0;
1040
u8 result = m_pMemory->Read(address);
1041
((result & 0x80) != 0) ? SetFlag(FLAG_CARRY) : ClearAllFlags();
1042
result <<= 1;
1043
result |= carry;
1044
m_pMemory->Write(address, result);
1045
ToggleZeroFlagFromResult(result);
1046
ToggleSignFlagFromResult(result);
1047
ToggleParityFlagFromResult(result);
1048
ToggleXYFlagsFromResult(result);
1049
}
1050
1051
inline void Processor::OPCodes_RRC(u8* reg, bool isRegisterA)
1052
{
1053
u16 address = 0x0000;
1054
if (!isRegisterA && IsPrefixedInstruction())
1055
{
1056
address = GetEffectiveAddress();
1057
*reg = m_pMemory->Read(address);
1058
}
1059
u8 result = *reg;
1060
if ((result & 0x01) != 0)
1061
{
1062
ToggleFlag(FLAG_CARRY);
1063
result >>= 1;
1064
result |= 0x80;
1065
}
1066
else
1067
{
1068
ClearFlag(FLAG_CARRY);
1069
result >>= 1;
1070
}
1071
*reg = result;
1072
if (!isRegisterA && IsPrefixedInstruction())
1073
m_pMemory->Write(address, *reg);
1074
ClearFlag(FLAG_HALF);
1075
ClearFlag(FLAG_NEGATIVE);
1076
ToggleXYFlagsFromResult(result);
1077
if (!isRegisterA)
1078
{
1079
ToggleZeroFlagFromResult(result);
1080
ToggleSignFlagFromResult(result);
1081
ToggleParityFlagFromResult(result);
1082
}
1083
}
1084
1085
inline void Processor::OPCodes_RRC_HL()
1086
{
1087
u16 address = GetEffectiveAddress();
1088
u8 result = m_pMemory->Read(address);
1089
if ((result & 0x01) != 0)
1090
{
1091
SetFlag(FLAG_CARRY);
1092
result >>= 1;
1093
result |= 0x80;
1094
}
1095
else
1096
{
1097
ClearAllFlags();
1098
result >>= 1;
1099
}
1100
m_pMemory->Write(address, result);
1101
ToggleZeroFlagFromResult(result);
1102
ToggleSignFlagFromResult(result);
1103
ToggleParityFlagFromResult(result);
1104
ToggleXYFlagsFromResult(result);
1105
}
1106
1107
inline void Processor::OPCodes_RR(u8* reg, bool isRegisterA)
1108
{
1109
u16 address = 0x0000;
1110
if (!isRegisterA && IsPrefixedInstruction())
1111
{
1112
address = GetEffectiveAddress();
1113
*reg = m_pMemory->Read(address);
1114
}
1115
u8 carry = IsSetFlag(FLAG_CARRY) ? 0x80 : 0x00;
1116
u8 result = *reg;
1117
((result & 0x01) != 0) ? ToggleFlag(FLAG_CARRY) : ClearFlag(FLAG_CARRY);
1118
result >>= 1;
1119
result |= carry;
1120
*reg = result;
1121
if (!isRegisterA && IsPrefixedInstruction())
1122
m_pMemory->Write(address, *reg);
1123
ClearFlag(FLAG_HALF);
1124
ClearFlag(FLAG_NEGATIVE);
1125
ToggleXYFlagsFromResult(result);
1126
if (!isRegisterA)
1127
{
1128
ToggleZeroFlagFromResult(result);
1129
ToggleSignFlagFromResult(result);
1130
ToggleParityFlagFromResult(result);
1131
}
1132
}
1133
1134
inline void Processor::OPCodes_RR_HL()
1135
{
1136
u16 address = GetEffectiveAddress();
1137
u8 carry = IsSetFlag(FLAG_CARRY) ? 0x80 : 0x00;
1138
u8 result = m_pMemory->Read(address);
1139
((result & 0x01) != 0) ? SetFlag(FLAG_CARRY) : ClearAllFlags();
1140
result >>= 1;
1141
result |= carry;
1142
m_pMemory->Write(address, result);
1143
ToggleZeroFlagFromResult(result);
1144
ToggleSignFlagFromResult(result);
1145
ToggleParityFlagFromResult(result);
1146
ToggleXYFlagsFromResult(result);
1147
}
1148
1149
inline void Processor::OPCodes_BIT(u8* reg, int bit)
1150
{
1151
IsSetFlag(FLAG_CARRY) ? SetFlag(FLAG_CARRY) : ClearAllFlags();
1152
u8 value = *reg;
1153
if (IsPrefixedInstruction())
1154
value = m_pMemory->Read(GetEffectiveAddress());
1155
if (!IsSetBit(value, bit))
1156
{
1157
ToggleFlag(FLAG_ZERO);
1158
ToggleFlag(FLAG_PARITY);
1159
}
1160
else if (bit == 7)
1161
ToggleFlag(FLAG_SIGN);
1162
if (IsSetBit(value, 3))
1163
ToggleFlag(FLAG_X);
1164
if (IsSetBit(value, 5))
1165
ToggleFlag(FLAG_Y);
1166
ToggleFlag(FLAG_HALF);
1167
}
1168
1169
inline void Processor::OPCodes_BIT_HL(int bit)
1170
{
1171
IsSetFlag(FLAG_CARRY) ? SetFlag(FLAG_CARRY) : ClearAllFlags();
1172
u16 address = GetEffectiveAddress();
1173
if (!IsSetBit(m_pMemory->Read(address), bit))
1174
{
1175
ToggleFlag(FLAG_ZERO);
1176
ToggleFlag(FLAG_PARITY);
1177
}
1178
else if (bit == 7)
1179
ToggleFlag(FLAG_SIGN);
1180
u8 xy = IsPrefixedInstruction() ? ((address >> 8) & 0xFF) : WZ.GetHigh();
1181
if (IsSetBit(xy, 3))
1182
ToggleFlag(FLAG_X);
1183
if (IsSetBit(xy, 5))
1184
ToggleFlag(FLAG_Y);
1185
ToggleFlag(FLAG_HALF);
1186
}
1187
1188
inline void Processor::OPCodes_SET(u8* reg, int bit)
1189
{
1190
u16 address = 0x0000;
1191
if (IsPrefixedInstruction())
1192
{
1193
address = GetEffectiveAddress();
1194
*reg = m_pMemory->Read(address);
1195
}
1196
*reg = *reg | (0x1 << bit);
1197
if (IsPrefixedInstruction())
1198
m_pMemory->Write(address, *reg);
1199
}
1200
1201
inline void Processor::OPCodes_SET_HL(int bit)
1202
{
1203
u16 address = GetEffectiveAddress();
1204
u8 result = m_pMemory->Read(address);
1205
result |= (0x1 << bit);
1206
m_pMemory->Write(address, result);
1207
}
1208
1209
inline void Processor::OPCodes_RES(u8* reg, int bit)
1210
{
1211
u16 address = 0x0000;
1212
if (IsPrefixedInstruction())
1213
{
1214
address = GetEffectiveAddress();
1215
*reg = m_pMemory->Read(address);
1216
}
1217
*reg = *reg & (~(0x1 << bit));
1218
if (IsPrefixedInstruction())
1219
m_pMemory->Write(address, *reg);
1220
}
1221
1222
inline void Processor::OPCodes_RES_HL(int bit)
1223
{
1224
u16 address = GetEffectiveAddress();
1225
u8 result = m_pMemory->Read(address);
1226
result &= ~(0x1 << bit);
1227
m_pMemory->Write(address, result);
1228
}
1229
1230
#endif /* PROCESSOR_INLINE_H */
1231
1232
1233