-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.s
More file actions
1174 lines (1104 loc) · 23.6 KB
/
main.s
File metadata and controls
1174 lines (1104 loc) · 23.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
global _start
extern malloc
extern free
extern printf
extern signal
SIGINT equ 2
struc _6502_CPUREGS
.PC resw 1
.F resb 1
.A resb 1
.X resb 1
.Y resb 1
.S resb 1
endstruc
_FLAG_N equ 0x80
_FLAG_V equ 0x40
_FLAG_B equ 0x10
_FLAG_D equ 0x08
_FLAG_I equ 0x04
_FLAG_Z equ 0x02
_FLAG_C equ 0x01
%macro TRANSFLAGS_ZSC 1
pushf
pop ax
mov bl, al
and al, 0x80+%1 ; keep S flag only, which is N on 6502 and C flag is optional
xor cl, cl
rcl bl, 2 ; rotate Z into carry (bit 6 -> C)
rcl cl, 2 ; rotate carry into Z (C -> bit 1)
or al, cl ; al contains Z and N flag
and byte [sregs + _6502_CPUREGS.F], ~(_FLAG_Z | _FLAG_N | _FLAG_C*%1 )
or byte [sregs + _6502_CPUREGS.F], al
%endmacro
%macro TRANSFLAGS_ZSCO 0
pushf
pop ax
mov dl, ah
mov bl, al
and al, 0x81 ; keep N and C flags
xor cl, cl
rcl bl, 2 ; rotate Z into carry (bit 6 -> C)
rcl cl, 2 ; rotate carry into Z (C -> bit 1)
or al, cl ; al contains Z and N flag
and byte [sregs + _6502_CPUREGS.F], ~(_FLAG_Z | _FLAG_N | _FLAG_C | _FLAG_V)
or byte [sregs + _6502_CPUREGS.F], al
rcr dl, 4 ; rotate overflow flag into carry
xor al, al
rcr al, 2 ; rotate overflwo flag into V flag position
or byte [sregs + _6502_CPUREGS.F], al
%endmacro
%macro PUSH6_AL 0
xor rbx, rbx
mov rcx, qword [procmem]
mov bl, byte [sregs + _6502_CPUREGS.S]
mov byte [rcx + rbx + 0x100], al
dec byte [sregs + _6502_CPUREGS.S]
%endmacro
%macro LOAD_STACK_TO_RSI 0
xor rbx, rbx
mov rsi, qword [procmem]
mov bl, byte [sregs + _6502_CPUREGS.S]
add rsi, rbx
add rsi, 0x100
%endmacro
%macro POP6_AL 0
xor rbx, rbx
mov rcx, qword [procmem]
mov bl, byte [sregs + _6502_CPUREGS.S]
mov al, byte [rcx + rbx + 0x100]
inc byte [sregs + _6502_CPUREGS.S]
%endmacro
%macro JMPREL 1
; al contains signed byte to be added to PC
cbw ; sign extend to ax
test ax, ax
js %1_offset_neg
add word [sregs + _6502_CPUREGS.PC], ax
jmp %1_jmprelcont
%1_offset_neg:
neg ax
sub word [sregs + _6502_CPUREGS.PC], ax
%1_jmprelcont:
%endmacro
section .text
_6502_RAMSIZE equ 65536
_sigint_handler:
mov byte [done], 1
ret
_sigint_restorer:
mov rax, 15
syscall
ret
fwait:
; fetch the current terminal settings
mov rax, 16 ; __NR_ioctl
mov rdi, 0 ; fd: stdin
mov rsi, 21505 ; cmd: TCGETS
mov rdx, orig ; arg: the buffer, orig
syscall
; again, but this time for the 'new' buffer
mov rax, 16
mov rdi, 0
mov rsi, 21505
mov rdx, new
syscall
; change settings
and dword [new+0], -1516 ; ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON)
and dword [new+4], -2 ; ~OPOST
and dword [new+12], -32844 ; ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN)
and dword [new+8], -305 ; ~(CSIZE | PARENB)
or dword [new+8], 48 ; CS8
; set settings (with ioctl again)
mov rax, 16 ; __NR_ioctl
mov rdi, 0 ; fd: stdin
mov rsi, 21506 ; cmd: TCSETS
mov rdx, new ; arg: the buffer, new
syscall
; read a character
mov rax, 0 ; __NR_read
mov rdi, 0 ; fd: stdin
mov rsi, char ; buf: the temporary buffer, char
mov rdx, 1 ; count: the length of the buffer, 1
syscall
; reset settings (with ioctl again)
mov rax, 16 ; __NR_ioctl
mov rdi, 0 ; fd: stdin
mov rsi, 21506 ; cmd: TCSETS
mov rdx, orig ; arg: the buffer, orig
syscall
ret
_print:
mov rax, 1
mov rdi, 1
mov rdx, 13
syscall
ret
_init_6502_memory:
mov rdi, _6502_RAMSIZE
call malloc
test rax, rax
jz _init_6502_memory_error
mov [procmem], rax
ret
_init_6502_memory_error:
mov rsi, mem_init_err_msg
call _print
ret
_cleanup:
sub rsp, 8
mov rdi, [procmem]
call free
add rsp, 8
ret
_step_cpu:
; LOAD BYTE FROM 6502 MEMORY
xor rax, rax
mov ax, word [sregs + _6502_CPUREGS.PC]
mov rsi, [procmem]
add rsi, rax
xor rax, rax
lodsb
inc word [sregs + _6502_CPUREGS.PC]
ror al, 2 ; rotate byte to align opcode table
mov rbx, rax ; save copy
mov rcx, rax
and al, 0xF8 ; mask adress mode
and bl, 0x03 ; mask opcode type
cmp al, 0x38
jbe nosetup_src_dest
call setup_src_dest
nosetup_src_dest:
call [machinecode + rax]
ret
_init_sigint_handler:
sub rsp, 8
mov rsi, _sigint_handler
mov rdi, SIGINT
call signal
add rsp, 8
ret
_start:
mov rsi, message
call _print
call _init_6502_memory
;call fwait
call _init_sigint_handler
mov rdi, message2
call printf
_mainloop:
call _step_cpu
test byte [done], 1
loopz _mainloop
mov rdi, message3
call printf
call _cleanup
mov rax, 60
xor rdi, rdi
syscall
setup_src_dest:
xor rax, rax
cmp bl, 1 ; zpg
jne lsd0
lodsb ; al = zeropage offset
mov qword [inst_operand], rax
inc word [sregs + _6502_CPUREGS.PC]
ret
lsd0:
cmp bl, 5 ; zpg, X
jne lsd1
lodsb
and cl, 0xF0
cmp cl, 0xA0 ; for opcode 0xA0 (STX) and 0xA8 (LDX)
je _A0_use_Y ; use zpg,Y instead of zpg,X
add al, byte [sregs + _6502_CPUREGS.X]
jmp _A0_cont
_A0_use_Y:
add al, byte [sregs + _6502_CPUREGS.Y]
_A0_cont:
add rax, procmem
mov qword [inst_operand], rax
inc word [sregs + _6502_CPUREGS.PC]
ret
lsd1:
cmp bl, 3 ; abs
jne lsd2
lodsb
xchg al, ah
lodsb
xchg al, ah
add rax, procmem
mov qword [inst_operand], rax
inc word [sregs + _6502_CPUREGS.PC]
inc word [sregs + _6502_CPUREGS.PC]
ret
lsd2:
cmp bl, 7 ; abs, X
jne lsd3
lodsb
xchg al, ah
lodsb
xchg al, ah
cmp cl, 0xA8
jne _nomodify_7_A8
add al, byte [sregs + _6502_CPUREGS.Y]
jmp _cont_7_A8
_nomodify_7_A8:
add al, byte [sregs + _6502_CPUREGS.X]
_cont_7_A8:
adc ah, 0
add rax, procmem
mov qword [inst_operand], rax
inc word [sregs + _6502_CPUREGS.PC]
inc word [sregs + _6502_CPUREGS.PC]
ret
lsd3:
cmp bl, 6 ; abs, Y
jne lsd4
and cl, 0xF0
cmp cl, 0xA0 ; for opcode 0xA0 (TXS) and 0xA8 (TSX)
je _A0_store_to_S
lodsb
xchg al, ah
lodsb
xchg al, ah
add al, byte [sregs + _6502_CPUREGS.Y]
adc ah, 0
add rax, procmem
mov qword [inst_operand], rax
inc word [sregs + _6502_CPUREGS.PC]
inc word [sregs + _6502_CPUREGS.PC]
ret
_A0_store_to_S:
mov rax, sregs + _6502_CPUREGS.S
mov qword [inst_operand], rax
ret
lsd4:
cmp bl, 0 ; X, ind
jne lsd5
lodsb
add al, byte [sregs + _6502_CPUREGS.X]
add rax, procmem
mov ax, word [rax]
add rax, procmem
mov qword [inst_operand], rax
inc word [sregs + _6502_CPUREGS.PC]
ret
lsd5:
cmp bl, 4 ; ind, Y
jne lsd6
lodsb
add rax, procmem
mov ax, word [rax]
add al, byte [sregs + _6502_CPUREGS.Y]
adc ah, 0
test byte [sregs + _6502_CPUREGS.F], _FLAG_C
jz lsd_nocarry5
inc word [sregs + _6502_CPUREGS.PC]
inc ax
lsd_nocarry5:
add rax, procmem
mov qword [inst_operand], rax
ret
lsd6:
cmp bl, 2 ; A or X
jne lsd7
cmp cl, 0xB0
je _DEX
mov rax, sregs + _6502_CPUREGS.A
mov qword [inst_operand], rax
ret
_DEX:
mov rax, sregs + _6502_CPUREGS.X
mov qword [inst_operand], rax
lsd7:
ret
_interpret_line00:
cmp bl, 0
jnz l00n1
; BRK
xor rax, rax
mov ax, word [sregs + _6502_CPUREGS.PC]
inc ax ; already was incremented before
xchg al, ah
PUSH6_AL ; store PC(hi)
xchg al, ah
PUSH6_AL ; store PC(lo)
mov al, byte [sregs + _6502_CPUREGS.F]
or al, _FLAG_B ; set B flag
PUSH6_AL ; store FLAGS
mov rsi, qword [procmem]
add rsi, 0xFFFE
lodsw ; fetch PC(lo), then fetch PC(hi)
mov word [sregs + _6502_CPUREGS.PC], ax
ret
l00n1:
cmp bl, 2
jnz l00n2
; PHP
mov al, byte [sregs + _6502_CPUREGS.F]
PUSH6_AL
ret
l00n2:
cmp bl, 4
jnz l00n3
; BPL rel
test byte [sregs + _6502_CPUREGS.F], _FLAG_N
jnz nobpl
lodsb
JMPREL bpl
ret
nobpl:
inc word [sregs + _6502_CPUREGS.PC]
ret
l00n3:
cmp bl, 6
jnz l00n4
; CLC
and byte [sregs + _6502_CPUREGS.F], ~_FLAG_C
ret
l00n4:
ret
_interpret_line08:
cmp bl, 0
jnz l08n1
; JSR abs
; PUSH PC+2
; (PC+1) -> PCL
; (PC+2) -> PCH
mov dx, word [rsi] ; LOAD new PC
mov ax, word [sregs + _6502_CPUREGS.PC]
inc ax ; we already had PC+1 before
xchg al, ah
PUSH6_AL ; store PC(hi)
xchg al, ah
PUSH6_AL ; store PC(lo)
mov word [sregs + _6502_CPUREGS.PC], dx
ret
l08n1:
cmp bl, 1
jnz l08n1b
; BIT zpg
xor rax, rax
lodsb
add rax, qword [procmem]
mov al, byte [rax]
test al, byte [sregs + _6502_CPUREGS.A]
jz bit_setz
and byte [sregs + _6502_CPUREGS.F], ~_FLAG_Z
jmp bit_cont
bit_setz:
or byte [sregs + _6502_CPUREGS.F], _FLAG_Z
bit_cont:
and al, 0xC0
and byte [sregs + _6502_CPUREGS.F], 0x3F
or byte [sregs + _6502_CPUREGS.F], al
inc word [sregs + _6502_CPUREGS.PC]
ret
l08n1b:
cmp bl, 2
jnz l08n2
; PLP
POP6_AL
mov byte [sregs + _6502_CPUREGS.F], al
ret
l08n2:
cmp bl, 3
jnz l08n2b
; BIT abs
xor rax, rax
lodsw
add rax, qword [procmem]
mov al, byte [rax]
test al, byte [sregs + _6502_CPUREGS.A]
jz bita_setz
and byte [sregs + _6502_CPUREGS.F], ~_FLAG_Z
jmp bita_cont
bita_setz:
or byte [sregs + _6502_CPUREGS.F], _FLAG_Z
bita_cont:
and al, 0xC0
and byte [sregs + _6502_CPUREGS.F], 0x3F
or byte [sregs + _6502_CPUREGS.F], al
inc word [sregs + _6502_CPUREGS.PC]
inc word [sregs + _6502_CPUREGS.PC]
ret
l08n2b:
cmp bl, 4
jnz l08n3
; BMI rel
test byte [sregs + _6502_CPUREGS.F], _FLAG_N
jz nobmi
lodsb
JMPREL bmi
ret
nobmi:
inc word [sregs + _6502_CPUREGS.PC]
ret
l08n3:
cmp bl, 6
jnz l08n4
; SEC
or byte [sregs + _6502_CPUREGS.F], _FLAG_C
ret
l08n4:
ret
_interpret_line10:
cmp bl, 0
jnz l10n1
; RTI
POP6_AL
mov byte [sregs + _6502_CPUREGS.F], al
POP6_AL
xchg al, ah
POP6_AL
xchg al, ah
inc ax ; TODO is this correct?
mov word [sregs + _6502_CPUREGS.PC], ax
ret
l10n1:
cmp bl, 2
jnz l10n2
; PHA
mov al, byte [sregs + _6502_CPUREGS.A]
PUSH6_AL
ret
l10n2:
cmp bl, 3
jnz l10n2b
; JMP abs
lodsw
mov word [sregs + _6502_CPUREGS.PC], ax
ret
l10n2b:
cmp bl, 4
jnz l10n3
; BVC rel
test byte [sregs + _6502_CPUREGS.F], _FLAG_V
jnz nobvc
lodsb
JMPREL bvc
ret
nobvc:
inc word [sregs + _6502_CPUREGS.PC]
ret
l10n3:
cmp bl, 6
jnz l10n4
; CLI
and byte [sregs + _6502_CPUREGS.F], ~_FLAG_I
ret
l10n4:
ret
_interpret_line18:
cmp bl, 0
jnz l18n1
; RTS
POP6_AL
xchg al, ah
POP6_AL
xchg al, ah
inc ax
mov word [sregs + _6502_CPUREGS.PC], ax
ret
l18n1:
cmp bl, 2
jnz l18n2
; PLA
POP6_AL
mov byte [sregs + _6502_CPUREGS.A], al
TRANSFLAGS_ZSC 1
ret
l18n2:
cmp bl, 3
jnz l18n2b
; JMP ind
xor rax, rax
lodsw
add rax, qword [procmem]
mov ax, word [rax]
mov word [sregs + _6502_CPUREGS.PC], ax
ret
l18n2b:
cmp bl, 4
jnz l18n3
; BVS rel
test byte [sregs + _6502_CPUREGS.F], _FLAG_V
jz nobvs
lodsb
JMPREL bvs
ret
nobvs:
inc word [sregs + _6502_CPUREGS.PC]
ret
l18n3:
cmp bl, 6
jnz l18n4
; SEI
or byte [sregs + _6502_CPUREGS.F], _FLAG_I
ret
l18n4:
ret
_interpret_line20:
cmp bl, 1
jnz l20n1
; STY zpg
xor rax, rax
lodsb
add rax, qword [procmem]
mov bl, byte [sregs + _6502_CPUREGS.Y]
mov byte [rax], bl
inc word [sregs + _6502_CPUREGS.PC]
ret
l20n1:
cmp bl, 2
jnz l20n2
; DEY
dec byte [sregs + _6502_CPUREGS.Y]
jns l20n1_nosign
pushf
or byte [sregs + _6502_CPUREGS.F], _FLAG_N
popf
l20n1_nosign:
pushf
and byte [sregs + _6502_CPUREGS.F], ~_FLAG_N
popf
jnz l20n1_nozero
or byte [sregs + _6502_CPUREGS.F], _FLAG_Z
l20n1_nozero:
and byte [sregs + _6502_CPUREGS.F], ~_FLAG_Z
ret
l20n2:
cmp bl, 3
jnz l20n2b
; STY abs
xor rax, rax
lodsw
add rax, qword [procmem]
mov bl, byte [sregs + _6502_CPUREGS.Y]
mov byte [rax], bl
inc word [sregs + _6502_CPUREGS.PC]
inc word [sregs + _6502_CPUREGS.PC]
ret
l20n2b:
cmp bl, 4
jnz l20n3
; BCC rel
test byte [sregs + _6502_CPUREGS.F], _FLAG_C
jnz nobcc
lodsb
JMPREL bcc
ret
nobcc:
inc word [sregs + _6502_CPUREGS.PC]
ret
l20n3:
cmp bl, 5
jnz l20n3b
; STY zpg, X
xor rax, rax
lodsb
add al, byte [sregs + _6502_CPUREGS.X]
add rax, qword [procmem]
mov bl, byte [sregs + _6502_CPUREGS.Y]
mov byte [rax], bl
inc word [sregs + _6502_CPUREGS.PC]
ret
l20n3b:
cmp bl, 6
jnz l20n4
; TYA
mov al, byte [sregs + _6502_CPUREGS.Y]
mov byte [sregs + _6502_CPUREGS.A], al
ret
l20n4:
ret
_interpret_line28:
cmp bl, 0
jnz l28n0
; LDY #
lodsb
mov byte [sregs + _6502_CPUREGS.Y], al
inc word [sregs + _6502_CPUREGS.PC]
ret
l28n0:
cmp bl, 1
jnz l28n1
; LDY zpg
xor rax, rax
lodsb
add rax, qword [procmem]
mov al, byte [rax]
mov byte [sregs + _6502_CPUREGS.Y], al
inc word [sregs + _6502_CPUREGS.PC]
ret
l28n1:
cmp bl, 2
jnz l28n2
; TAY
mov al, byte [sregs + _6502_CPUREGS.A]
mov byte [sregs + _6502_CPUREGS.Y], al
ret
l28n2:
cmp bl, 3
jnz l28n2b
; LDY abs
xor rax, rax
lodsw
add rax, qword [procmem]
mov byte al, [rax]
mov byte [sregs + _6502_CPUREGS.Y], al
inc word [sregs + _6502_CPUREGS.PC]
inc word [sregs + _6502_CPUREGS.PC]
ret
l28n2b:
cmp bl, 4
jnz l28n3
; BCS rel
test byte [sregs + _6502_CPUREGS.F], _FLAG_C
jz nobcs
lodsb
JMPREL bcs
ret
nobcs:
inc word [sregs + _6502_CPUREGS.PC]
ret
l28n3:
cmp bl, 5
jnz l28n3b
; LDY zpg, x
xor rax, rax
lodsb
add al, byte [sregs + _6502_CPUREGS.X]
add rax, qword [procmem]
mov al, byte [rax]
mov byte [sregs + _6502_CPUREGS.Y], al
inc word [sregs + _6502_CPUREGS.PC]
ret
l28n3b:
cmp bl, 6
jnz l28n4
; CLV
and byte [sregs + _6502_CPUREGS.F], ~_FLAG_V
ret
l28n4:
; LDY abs, X
xor rax, rax
lodsw
add al, byte [sregs + _6502_CPUREGS.X]
adc ah, 1
add rax, qword [procmem]
mov al, byte [rax]
mov byte [sregs + _6502_CPUREGS.Y], al
inc word [sregs + _6502_CPUREGS.PC]
inc word [sregs + _6502_CPUREGS.PC]
ret
_interpret_line30:
cmp bl, 0
jnz l30n1
; CPY #
lodsb
mov bl, byte [sregs +_6502_CPUREGS.Y]
sub bl, al
TRANSFLAGS_ZSC 1
inc word [sregs + _6502_CPUREGS.PC]
ret
l30n1:
cmp bl, 1
jnz l30n2
; CPY zpg
xor rax, rax
lodsb
add rax, qword [procmem]
mov al, byte [rax]
mov bl, byte [sregs + _6502_CPUREGS.Y]
sub bl, al
TRANSFLAGS_ZSC 1
inc word [sregs + _6502_CPUREGS.PC]
ret
l30n2:
cmp bl, 2
jnz l30n2b
; INY
inc byte [sregs + _6502_CPUREGS.Y]
jns l30n2_nosign
pushf
or byte [sregs + _6502_CPUREGS.F], _FLAG_N
popf
l30n2_nosign:
pushf
and byte [sregs + _6502_CPUREGS.F], ~_FLAG_N
popf
jnz l30n2_nozero
or byte [sregs + _6502_CPUREGS.F], _FLAG_Z
l30n2_nozero:
and byte [sregs + _6502_CPUREGS.F], ~_FLAG_Z
ret
l30n2b:
cmp bl, 3
jnz l30n3
; CPY abs
xor rax, rax
lodsw
add rax, qword [procmem]
mov al, byte [rax]
mov bl, byte [sregs + _6502_CPUREGS.Y]
sub bl, al
TRANSFLAGS_ZSC 1
inc word [sregs + _6502_CPUREGS.PC]
inc word [sregs + _6502_CPUREGS.PC]
ret
l30n3:
cmp bl, 4
jnz l30n3b
; BNE rel
test byte [sregs + _6502_CPUREGS.F], _FLAG_Z
jnz nobne
lodsb
JMPREL bne
ret
nobne:
inc word [sregs + _6502_CPUREGS.PC]
ret
l30n3b:
cmp bl, 6
jnz l30n4
; CLD
and byte [sregs + _6502_CPUREGS.F], ~_FLAG_D
ret
l30n4:
ret
_interpret_line38:
cmp bl, 0
jnz l38n1
; CPX #
lodsb
mov bl, byte [sregs +_6502_CPUREGS.X]
sub bl, al
TRANSFLAGS_ZSC 1
inc word [sregs + _6502_CPUREGS.PC]
ret
l38n1:
cmp bl, 1
jnz l38n2
; CPX zpg
xor rax, rax
lodsb
add rax, qword [procmem]
mov al, byte [rax]
mov bl, byte [sregs + _6502_CPUREGS.X]
sub bl, al
TRANSFLAGS_ZSC 1
inc word [sregs + _6502_CPUREGS.PC]
ret
l38n2:
cmp bl, 2
jnz l38n2b
; INX
inc byte [sregs + _6502_CPUREGS.X]
jns l38n2_nosign
pushf
or byte [sregs + _6502_CPUREGS.F], _FLAG_N
popf
l38n2_nosign:
pushf
and byte [sregs + _6502_CPUREGS.F], ~_FLAG_N
popf
jnz l38n2_nozero
or byte [sregs + _6502_CPUREGS.F], _FLAG_Z
l38n2_nozero:
and byte [sregs + _6502_CPUREGS.F], ~_FLAG_Z
ret
l38n2b:
cmp bl, 3
jnz l38n3
; CPX abs
xor rax, rax
lodsw
add rax, qword [procmem]
mov al, byte [rax]
mov bl, byte [sregs + _6502_CPUREGS.X]
sub bl, al
TRANSFLAGS_ZSC 1
inc word [sregs + _6502_CPUREGS.PC]
inc word [sregs + _6502_CPUREGS.PC]
ret
l38n3:
cmp bl, 4
jnz l38n3b
; BEQ rel
test byte [sregs + _6502_CPUREGS.F], _FLAG_Z
jz nobeq
lodsb
JMPREL beq
ret
nobeq:
inc word [sregs + _6502_CPUREGS.PC]
ret
l38n3b:
cmp bl, 6
jnz l38n4
; SED
or byte [sregs + _6502_CPUREGS.F], _FLAG_D
ret
l38n4:
ret
_do_ORA:
mov rax, qword [inst_operand]
mov al, byte [rax]
cmp bl, 2
jne _do_ORAb
lodsb ; use immediate data instead of A
_do_ORAb:
or [sregs + _6502_CPUREGS.A], al
TRANSFLAGS_ZSC 0
ret
_do_AND:
mov rax, qword [inst_operand]
mov al, byte [rax]
cmp bl, 2
jne _do_ANDb
lodsb ; use immediate data instead of A
_do_ANDb:
and [sregs + _6502_CPUREGS.A], al
TRANSFLAGS_ZSC 0
ret
_do_EOR:
mov rax, qword [inst_operand]
mov al, byte [rax]
cmp bl, 2
jne _do_EORb
lodsb ; use immediate data instead of A
_do_EORb:
xor [sregs + _6502_CPUREGS.A], al
TRANSFLAGS_ZSC 0
ret
_do_ADC:
; trick was to use the add with bcd support of the x86 :)
; but the "daa" instruction is not available in x86_64 mode
; SHIT !!!!!
xor rbx, rbx
mov rax, qword [inst_operand]
mov bl, byte [rax]
_ADC_from_SBC:
mov al, byte [sregs + _6502_CPUREGS.A]
push rax
push rbx
test byte [sregs + _6502_CPUREGS.F], _FLAG_D
jnz _do_ADC_bcd
; Add in binary mode
; Set carry if set on 6502
test byte [sregs + _6502_CPUREGS.F], _FLAG_C
jz ADC_clc
stc
jmp ADC_cont
ADC_clc:
clc
ADC_cont:
adc al, bl
TRANSFLAGS_ZSCO
pop rbx
pop rax
ret
_do_ADC_bcd:
; Add in BCD mode
; Set carry if set on 6502
test byte [sregs + _6502_CPUREGS.F], _FLAG_C
jz ADC2_clc
stc
jmp ADC2_cont
ADC2_clc:
clc
ADC2_cont:
mov cl, al
mov dl, bl
and cl, 0x0F
and dl, 0x0F
adc cl, dl
cmp cl, 0x0A
jb no_daa1
add cl, 6
no_daa1:
; now, the high nibble can be non-zero
; the carry flag must be zero now
and al, 0xF0
and bl, 0xF0
add cl, al ; here, carry is impossible
add cl, bl ; here carry can occur
jnc daa_nc1
mov dl, _FLAG_C
daa_nc1:
cmp cl, 0x99
jb no_daa2
add cl, 0x60 ; here, carry can occur
jnc daa_nc2
mov dl, _FLAG_C
daa_nc2:
no_daa2:
mov byte [sregs + _6502_CPUREGS.A], cl ;store result
pop rbx ; restore original operands
pop rax
mov cl, al
and al, 0x80
and bl, 0x80
xor al, bl
; if both signs are different, xor gives non-zero and
; overflow is not possible
jnz bcd_no_overflow
; here, highest bit is 0
xor al, [sregs + _6502_CPUREGS.A]
test al, 0x80