-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmegayume_lower.spin2
8256 lines (7067 loc) · 275 KB
/
megayume_lower.spin2
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
CON ' Header
'' _______ _______ _______ _______ _______ _______
'' ( | ____ ( ____ ( ___ )\ /|\ /( | ____ \
'' | () () | ( \/ ( \/ ( ) ( \ / ) ) ( | () () | ( \/
'' | || || | (__ | | | (___) |\ (_) /| | | | || || | (__
'' | |(_)| | __) | | ____| ___ | \ / | | | | |(_)| | __)
'' | | | | ( | | \_ ) ( ) | ) ( | | | | | | | (
'' | ) ( | (____/\ (___) | ) ( | | | | (___) | ) ( | (____/\
'' |/ \(_______(_______)/ \| \_/ (_______)/ \(_______/
''
'' -= SEGA MEGA DRIVE EMULATOR =-
''
'' Note: this sucks. not as much.
'' Perhaps more important note: use the included build.sh.
#include "config.spin2"
CON ' Configuration constants (UNUSED WITH CURRENT UPPER CODE)
'' Console region to be reported.
'' Note that a 60Hz system is always emulated,
'' this only affects the version register
USE_REGION = REGION_OVERSEAS_60HZ
REGION_OVERSEAS_60HZ = %10 '' Americas
REGION_DOMESTIC_60HZ = %00 '' Japan
REGION_OVERSEAS_50HZ = %11 '' Europe, Australia
REGION_DOMESTIC_50HZ = %01 '' Narnia, Gensokyo, Oz, Bielefeld
#0,IOMODE_3BUTTON,IOMODE_6BUTTON,IOMODE_MULTITAP,IOMODE_MULTITAP_3BUTTON
#0,PAD_NONE,PAD_6BUTTON,PAD_3BUTTON
CON ' Common constants
_CLKFREQ = 327_600_000 ' Ignore this unless you're debugging - clock is set by video driver
'DEBUG_BAUD = 115_200*2
'DEBUG_BAUD = 1_000_000
ROM_LOCK = 7
HINT_LOCK = 8
VINT_LOCK = 9
ZINT_LOCK = 10 ' Z80 VBlank IRQ is sorta independent
STATIC_LOCKS = decod ROM_LOCK | decod HINT_LOCK | decod VINT_LOCK | decod ZINT_LOCK
UPPER_LOAD = $5_0000
DAT ' startup code & zero page
org
' reboot into upper
coginit #0,##UPPER_LOAD
'coginit #HUBEXEC,##mk_init
orgh $14
_clkf long 0
_clkm long 0
_mk_init_ptr long @mk_init ' < $1C
_vdp_outbuffer_ptr long @outbuffer_loc ' < $20
_vdpr_load_ptr long @vdpr_entry ' < $24
_vdpc_load_ptr long @vdpc_entry ' < $28
_zk_init_ptr long @zk_init ' < $2C
_opn_init_ptr long @opn_init ' < $30
_cram32_ptr long @vdp_cram32 ' < $34
_vsram_ptr long @vdp_cram + $120 ' < $38
_vram_ptr long @vdp_ram ' < $3C
orgh $40
' control bit format is %MXYZ_SACB_RLDU
io_pl1_padw long 0 ' < $40 (populated by upper code)
io_pl2_padw long 0 ' < $44 (populated by upper code)
io_pl3_padw long 0 ' < $48 (populated by upper code)
io_pl4_padw long 0 ' < $4C (populated by upper code)
io_mode byte IOMODE_6BUTTON ' < $50
io_pl1_dir byte 0
io_pl1_out byte 0
io_pl1_state byte 0
io_pl2_dir byte 0
io_pl2_out byte 0
io_pl2_state byte 0
alignl
io_6btn_timeout long 0 ' Timeout for 6 button state machine
io_multitap_data long 0,0,0
zbus_request byte $00 ' \/ These two can be read as a word
z80_reset byte $01 ' Reset is inverted polarity (low = run)
zbus_status byte $01
psg_register byte $08 ' selected PSG register + 8
opn_register word $000 ' selected OPN2 register
opn_timerAflag byte 0
opn_timerBflag byte 0
orgh $70
' registers loaded into render cog
vdp_registers
vdp_forceSPRreload long 0
vdp_flags long 1<<VDPFLAG_H40 ' < $64
vdp_planeAbase long $C000
vdp_planeBbase long $E000
vdp_windowbase long $A000
vdp_spritebase long $F800
vdp_HScrollbase long $FC00
vdp_planewidth long 1+6' basically what to shl the line count with (1+6 -> 64)
vdp_planeheight long 4' basically what to zerox the thing with (4->32)
vdp_columnScroll long 0 ' 1 or 0
vdp_HScrollMode long 3 ' 0 or 2 or 3 (1 is invalid in HW, too)
vdp_windowColumn long 0
vdp_windowRow long 0*8 ' pre-chewed to pixels?
vdp_bgcolor long $00
' I/O related regs. These are arranged as such for a reason
vdp_io_address_w word 0
vdp_autoinc_b byte 0
vdp_iomode_b byte 3 '%W0FH_00CS where W is write flag, C is CRAM flag and S is VSRAM flag. both set -> no access in progress.
' H is set when awaiting second half of command. F is set if fill is pending
vdp_dmasrc_l long 0 ' bit 23 is set for fill/copy, bit 22 then selects which
vdp_dmalen_w word 0
vdp_dma_enable_b byte 0
vdp_hint_interval_b byte 0
vdp_linestartct_l long 0 ' timestamp of current line render start
vdp_cyc2hcnt_w word 0 ' reciporal of cycles-per-pixel
word 0 ' padding
orgh $E0
' More stuff set by upper code
rom_zerox byte 22 ' < $E0 - number of valid bits in ROM address - 1 (22 -> 8MB)
machine_version byte USE_REGION<<6 ' < $E1: version register value
atn_command byte 0 ' < $E2: 68k COGATN command.
sram_bankreg byte %10 ' < $E3: $A130F1 reg value. bit0 enables SRAM banking, bit 1 *locks* SRAM (zero unlocks)
sram_write_tstamp long 0 ' $E4: last write time stamp (|1 so as to never be zero)
sram_map_start long -1 ' < $E8: SRAM start address
sram_map_end long -1 ' < $EC: SRAM end address
orgh $F8
video_line_ctr long 0
video_frame_ctr long 0
CON ' Memory constants
#ifdef USE_PSRAM16
PSRAM_PAGESIZE = 0 addbits 9
PSRAM_ASHIFT = 0
#endif
#ifdef USE_PSRAM8
PSRAM_PAGESIZE = 0 addbits 8
PSRAM_ASHIFT = 1
#endif
#ifdef USE_PSRAM4
PSRAM_PAGESIZE = 0 addbits 7
PSRAM_ASHIFT = 2
#endif
#ifdef USE_PSRAM_SLOW
PSRAM_CLKDIV = 3
PSRAM_CYSHL = 0
#else
PSRAM_CLKDIV = 2
PSRAM_CYSHL = 1
#endif
CON ' MotoKore 68000 constants
#0,MK_CARRY_BIT,MK_OVER_BIT,MK_ZERO_BIT,MK_NEG_BIT,MK_EXT_BIT
MK_SUPER_BIT = 13
MK_TRACE_BIT = 15
MK_CARRY_MASK = 1<<MK_CARRY_BIT
MK_OVER_MASK = 1<<MK_OVER_BIT
MK_ZERO_MASK = 1<<MK_ZERO_BIT
MK_NEG_MASK = 1<<MK_NEG_BIT
MK_EXT_MASK = 1<<MK_EXT_BIT
MK_SUPER_MASK = 1<<MK_SUPER_BIT
MK_TRACE_MASK = 1<<MK_TRACE_BIT
MK_ROMQUE_SIZE = 16 ' words
DMA_BLOCK_SIZE = 32 ' longs
DAT ' MotoKore 68000 cog resident code
org
mk_cogbase
mk_d0 long 0
mk_d1 long 0
mk_d2 long 0
mk_d3 long 0
mk_d4 long 0
mk_d5 long 0
mk_d6 long 0
mk_d7 long 0
mk_a0 long 0
mk_a1 long 0
mk_a2 long 0
mk_a3 long 0
mk_a4 long 0
mk_a5 long 0
mk_a6 long 0
mk_a7 long 0
mk_othersp long 0
mk_sr long 0
mk_nibble_impl_tbl
long mk_nibble_0 ' 0 (immediate ops)
long mk_nibble_1 ' 1 (MOVE BYTE)
long mk_nibble_2 ' 2 (MOVE LONG)
long mk_nibble_3 ' 3 (MOVE WORD)
long mk_nibble_4 ' 4 (weird stuff idk)
long mk_nibble_5 ' 5 (ADDQ/SUBQ and also Scc/DBcc)
long mk_nibble_6 ' 6 (branches)
long mk_nibble_7 ' 7 (MOVEQ)
long mk_nibble_8 ' 8 (OR and stuffs)
long mk_nibble_9 ' 9 (subtracts)
long mk_nibble_A ' A (LINE A EMULATOR TRAP)
long mk_nibble_B ' B (CMP and EOR)
long mk_nibble_C ' C (AND or stuffs)
long mk_nibble_D ' D (adds)
long mk_nibble_E ' E (Bit shifts)
long mk_nibble_F ' F (LINE F EMULATOR TRAP)
mk_nextop
'debug("registers: ",ubin_word(mk_sr),13,uhex_reg_array(#mk_d0,#8),13,uhex_reg_array(#mk_a0,#8))
'debug("last 16 RAM bytes: ",uhex_byte_array(#main_ram + $FFF0,#16))
'tjnz mk_debug_ctr,#mk_nextop_nohook
jatn mk_cogatnptr
mk_ihook1 nop
mk_ihook2 nop
mk_nextop_nohook
'cmp mk_virtualpc,mk_debug_tripwire wz
'if_z drvh #38
'if_z mov mk_debug_tripwire,#0
'if_z mov mk_debug_ctr,#1
'debug("getting op with ",uhex_long(mk_virtualpc))
'debug(uhex_long_(mk_virtualpc))
'debug(uhex_word_array(#@fake_rom+$200,#4))
call mk_getopf
'debug("got op: ",uhex_word(mk_opword))
'debug("got op: ",uhex_word(mk_opword)," before ",uhex_long(mk_virtualpc))
'tjnz mk_debug_tripwire,#.no_trace
'tjz mk_debug_ctr,#.no_trace
'sub mk_debug_ctr,#1
'cmp mk_debug_tripwire,mk_virtualpc wz
'if_nz jmp #.no_trace
'debug("tripwired' ",uhex_byte_array(#@zbus_status,#1),uhex_long(mk_virtualpc))
'call #mk_check_core_integrity
'debug("got: ",uhex_word_(mk_opword)," before ",uhex_long_(mk_virtualpc),uhex_long(mk_d2,mk_a0,mk_a1))
'debug("registers: ",ubin_word(mk_sr),13,uhex_reg_array(#mk_d0,#8),13,uhex_reg_array(#mk_a0,#8))
'debug("got op: ",uhex_word(mk_opword)," before ",uhex_long(mk_virtualpc),uhex_long(mk_a3))
'waitx ##174_00
.no_trace
push #mk_nextop
getnib mk_memtmp0,mk_opword,#3
altd mk_memtmp0,#mk_nibble_impl_tbl
jmp 0-0
mk_irq4ptr long @mk_hub_irq4
mk_irq6ptr long @mk_hub_irq6
mk_cogatnptr long @mk_hub_cogatn
mk_write_second_reg_or_ea '' for ops that have two directional modes
testb mk_opword,#8 wc
if_c jmp mk_writef
mk_write_second_reg
neg pb,#1
shr pb,mk_shiftit
setq pb
and mk_opword,mk_dreg_mask ' assume we don't need it anymore
alti mk_opword,#%000_100_000
_ret_ muxq 0-0,mk_memvalue
mk_nibble_0 ' Immediate ops (decode headache!)
testb mk_opword,#8 wc
test mk_opword,#%110_000 wz
testb mk_opword,#3 andz
if_c_and_z jmp #mk_hub_movep
if_c jmp #.register_bitop ' not actually an immediate op...
getnib mk_optmp2,mk_opword,#2
cmp mk_optmp2,#%1000 wz
if_z jmp #.imm_bitop
' ok, we know it's a sized ***I type op
mov pb,mk_opword
call #mk_getopimm_auto
'debug("xxxI type op... imm is ",uhex_long(mk_optmp1))
mov pb,mk_opword
and pb,#%111_111
cmp pb,#%111_100 wz ' <- if Z, is op to SR/CCR
if_z mov mk_readf,#mk_rd_sr
if_z mov mk_shiftit,#16
if_z testb mk_opword,#6 wc
if_z_and_c mov mk_writef,#mk_wr_sr
if_z_and_nc mov mk_writef,#mk_wr_ccr
if_nz callpb mk_opword,#mk_setup_operand_auto
call mk_readf
cmp mk_optmp2,#%1100 wz
if_z jmp #mk_cmp_swapped ' CMPI (doesn't write)
push mk_writef ' setup write return
cmp mk_optmp2,#%0110 wz
if_z jmp #mk_add_common ' ADDI
cmp mk_optmp2,#%0100 wz
if_z jmp #mk_sub_common ' SUBI
' ok, only logic ops left
setr mk_thelogicop,#%0101000_01 ' P2 AND WZ opcode (assume this if no other logic op)
cmp mk_optmp2,#%0000 wz
if_z setr mk_thelogicop,#%0101010_01 ' P2 OR WZ opcode
cmp mk_optmp2,#%1010 wz
if_z setr mk_thelogicop,#%0101011_01 ' P2 XOR WZ opcode
jmp #mk_multilogic_common
.imm_bitop
push #.bitop_common
jmp #mk_getopimm8
.register_bitop
mov pb,mk_opword
shr pb,#9
and pb,#7
alts pb,#mk_d0
mov mk_optmp1,0-0
.bitop_common
test mk_opword,#%110_000 wz ' Register op?
mov pb,mk_opword
if_z call #mk_setup_reg32
if_nz and mk_optmp1,#7
if_nz call #mk_setup_operand8_move
call mk_readf
'debug("doing bitop with ",uhex_byte(mk_optmp1),uhex_long(mk_memvalue))
testbn mk_memvalue,mk_optmp1 wc
bitc mk_sr,#MK_ZERO_BIT
testb mk_opword,#6 wz
testb mk_opword,#7 wc
if_00 ret ' BTST
and mk_optmp1,#31 ' bitfield-sensitive ops ahead
if_01 bitnot mk_memvalue,mk_optmp1 ' BCHG
if_1x bitz mk_memvalue,mk_optmp1 ' BCLR/BSET
'debug("bitop result ",uhex_long(mk_memvalue))
jmp mk_writef
mk_move_shoot_the_shit ' handle all the common MOVE stuff
' Doing MOVEA?
test mk_opword,#%110_000_000 wz
testb mk_opword,#6 andz
if_z jmp #.movea
signx mk_memvalue,pa wcz
bitc mk_sr,#MK_NEG_BIT
bitz mk_sr,#MK_ZERO_BIT
andn mk_sr,#MK_OVER_MASK|MK_CARRY_MASK
.mangle_ea2 ' format for second operand is stupid
setnib mk_opword,#0,#3
mov pa,mk_opword
and pa,#%111_000_000
shl pa,#6
or mk_opword,pa
_ret_ shr mk_opword,#9
.movea
shr mk_opword,#9
and mk_opword,#7
altr mk_opword,#mk_a0
signx mk_memvalue,pa
jmp #mk_nextop ' don't need the rest of the op
mk_nibble_1 ' MOVE (byte)
callpb mk_opword,#mk_setup_operand8_move
call mk_readf
callpa #7,#mk_move_shoot_the_shit
callpb mk_opword,#mk_setup_operand8_move
'debug("in move.b, writing ",uhex_byte(mk_memvalue)," to ",uhex_long(mk_effaddr))
jmp mk_writef
mk_nibble_3 ' MOVE (word)
'debug("in move.w")
callpb mk_opword,#mk_setup_operand16_move
call mk_readf
callpa #15,#mk_move_shoot_the_shit
callpb mk_opword,#mk_setup_operand16_move
'debug("in move.w, writing ",uhex_word(mk_memvalue)," to ",uhex_long(mk_effaddr))
jmp mk_writef
mk_nibble_2 ' MOVE (long)
callpb mk_opword,#mk_setup_operand32_move
call mk_readf
callpa #31,#mk_move_shoot_the_shit
callpb mk_opword,#mk_setup_operand32_move
jmp mk_writef
mk_nibble_5 ' ADDQ/SUBQ/Scc/DBcc
test mk_opword,#%11_000_000 wcz
if_00 jmp #mk_nibble_5_not_addsub
' get operand
mov mk_optmp1,mk_opword
shr mk_optmp1,#9 wc ' C = SUBQ, NC = ADDQ
and mk_optmp1,#7 wz
if_z mov mk_optmp1,#8
' Check if An reg
test mk_opword,#%110_000 wz
testb mk_opword,#3 andz
if_z jmp #.addsubq_areg
callpb mk_opword,#mk_setup_operand_auto
call mk_readf
push mk_writef
if_c jmp #mk_sub_common
jmp #mk_add_common
.addsubq_areg
and mk_opword,#7
altd mk_opword,#mk_a0
_ret_ sumc 0-0,mk_optmp1
mk_nibble_5_not_addsub
' Check if DBCC
test mk_opword,#%110_000 wz
testb mk_opword,#3 andz
if_z jmp #mk_dbcc
' got SCC
callpb mk_opword,#mk_setup_operand8_move
call mk_readf ' <- yes, this is stupid but accurate
getnib pb,mk_opword,#2
shr pb,#1 wc
altd pb,#mk_condition_truth_table
testb 0-0,mk_sr xorc
muxc mk_memvalue,#255
jmp mk_writef
mk_cmp
callpb mk_opword,#mk_setup_operand_auto
call mk_readf
push #mk_cmp_common
jmp #mk_get_second_reg
mk_cmpa
testb mk_opword,#8 wc ' long sized?
if_nc callpb mk_opword,#mk_setup_operand16_move
if_c callpb mk_opword,#mk_setup_operand32_move
call mk_readf
if_nc signx mk_memvalue,#15
shr mk_opword,#9
and mk_opword,#7
skipf #%11_111_00 ' Skip swap and shift
alts mk_opword,#mk_a0
mov mk_optmp1,0-0
mk_cmp_swapped
xor mk_memvalue,mk_optmp1
xor mk_optmp1,mk_memvalue
xor mk_memvalue,mk_optmp1
mk_cmp_common
'debug("in mk_cmp_common ",uhex_long(mk_d0),uhex_long(mk_memvalue),uhex_long(mk_optmp1),udec(mk_shiftit))
shl mk_memvalue,mk_shiftit
shl mk_optmp1,mk_shiftit
' NOTE: the operands are swapped compared to sub_common
' generate stupid overflow flag
mov mk_optmp0,mk_optmp1
subs mk_optmp0,mk_memvalue wc
testb mk_optmp0,#31 xorc
bitc mk_sr,#MK_OVER_BIT
' do actual sub
sub mk_optmp1,mk_memvalue wcz
bitc mk_sr,#MK_CARRY_BIT
bitz mk_sr,#MK_ZERO_BIT
testb mk_optmp0,#31 wc
_ret_ bitc mk_sr,#MK_NEG_BIT
mk_nibble_9
mk_nibble_D
' ADD/SUB (X/A)
' check for ADDA/SUBA
test mk_opword,#%11_000_000 wcz
if_00 jmp #mk_addsuba
' check for ADDX/SUBX
test mk_opword,#%110_000 wz
testb mk_opword,#8 andz
if_z jmp #mk_hub_addsubx
' Okay, normal ADD/SUB
callpb mk_opword,#mk_setup_operand_auto
call mk_readf
call #mk_get_second_reg
push #mk_write_second_reg_or_ea
testb mk_opword,#14 wc ' C = ADD,NC = SUB ?
if_nc jmp #mk_sub_withdir
' fall through
mk_add_common
shl mk_memvalue,mk_shiftit
shl mk_optmp1,mk_shiftit
' generate stupid overflow flag
mov mk_optmp0,mk_optmp1
adds mk_optmp0,mk_memvalue wc
testb mk_optmp0,#31 xorc
bitc mk_sr,#MK_OVER_BIT
' do actual add
add mk_memvalue,mk_optmp1 wcz
muxc mk_sr,#MK_CARRY_MASK|MK_EXT_MASK
bitz mk_sr,#MK_ZERO_BIT
testb mk_optmp0,#31 wc
bitc mk_sr,#MK_NEG_BIT
_ret_ shr mk_memvalue,mk_shiftit
mk_sub_withdir
' if dir bit clear, swap operands
testb mk_opword,#8 wc
if_nc xor mk_memvalue,mk_optmp1
if_nc xor mk_optmp1,mk_memvalue
if_nc xor mk_memvalue,mk_optmp1
mk_sub_common
'debug("in mk_sub_common ",uhex_long(mk_d0),uhex_long(mk_memvalue),uhex_long(mk_optmp1),udec(mk_shiftit))
shl mk_memvalue,mk_shiftit
shl mk_optmp1,mk_shiftit
' generate stupid overflow flag
mov mk_optmp0,mk_memvalue
subs mk_optmp0,mk_optmp1 wc
testb mk_optmp0,#31 xorc
bitc mk_sr,#MK_OVER_BIT
' do actual sub
sub mk_memvalue,mk_optmp1 wcz
muxc mk_sr,#MK_CARRY_MASK|MK_EXT_MASK
bitz mk_sr,#MK_ZERO_BIT
testb mk_optmp0,#31 wc
bitc mk_sr,#MK_NEG_BIT
_ret_ shr mk_memvalue,mk_shiftit
mk_addsuba
setq mk_dreg_mask
muxq .adda_op,mk_opword
testb mk_opword,#8 wc ' long sized?
if_nc callpb mk_opword,#mk_setup_operand16_move
if_c callpb mk_opword,#mk_setup_operand32_move
call mk_readf
'debug("in mk_adda: ",uhex_long(mk_memvalue))
if_nc signx mk_memvalue,#15
testb mk_opword,#14 wc ' C = ADDA,NC = SUBA ?
.adda_op _ret_ sumnc mk_a0,mk_memvalue
' Memory R/W primitives
mk_setup_operand_auto ' with ea-supplying op in pb
' make sure size field is not %11 (will be treated as 16bit)
testb pb,#6 wc
if_c jmp #mk_setup_operand16
testb pb,#7 wc
if_c jmp #mk_setup_operand32
' Fall through!
mk_setup_operand8
'debug("in mk_setup_operand8 ",ubin(pb))
mov mk_shiftit,#24
mk_setup_operand8_move
test pb,#%110_000 wz
if_z jmp #mk_setup_reg8
and pb,#%00_111_111
cmp pb,#%00_111_100 wc
if_ae jmp #mk_setup_imm8
call #mk_compute_ea
mk_setup_ea8
'debug("in mk_setup_ea8 ",uhex_long(mk_effaddr))
mov pb,mk_effaddr
zerox pb,#23
cmp pb,mk_ram_begin wc
if_ae jmp #mk_setup_ram8
cmp pb,mk_rom_stop wc
if_ae jmp #mk_setup_io8
' fall through
mk_setup_rom8
mov mk_readf,#mk_rd8_rom
mov mk_writef,#mk_wrrom
mov mk_eacache,mk_romio_area_ptr
ret wcz
mk_setup_operand16
'debug("in mk_setup_operand16 ",ubin(pb))
mov mk_shiftit,#16
mk_setup_operand16_move
test pb,#%110_000 wz
if_z jmp #mk_setup_reg16
and pb,#%00_111_111
cmp pb,#%00_111_100 wc
if_ae jmp #mk_setup_imm16
or pb,#%01_000_000
call #mk_compute_ea
mk_setup_ea16
testb mk_effaddr,#0 wc
if_c jmp #mk_address_error
mov pb,mk_effaddr
zerox pb,#23
cmp pb,mk_ram_begin wc
if_ae jmp #mk_setup_ram16
cmp pb,mk_rom_stop wc
if_ae jmp #mk_setup_io16
' fall through
mk_setup_rom16
mov mk_readf,#mk_rd16_rom
mov mk_writef,#mk_wrrom
mov mk_eacache,mk_romio_area_ptr
ret wcz
mk_setup_operand32
mov mk_shiftit,#0
mk_setup_operand32_move
test pb,#%110_000 wz
if_z jmp #mk_setup_reg32
and pb,#%00_111_111
cmp pb,#%00_111_100 wc
if_ae jmp #mk_setup_imm32
or pb,#%10_000_000
call #mk_compute_ea
mk_setup_ea32
testb mk_effaddr,#0 wc
if_c jmp #mk_address_error
mov pb,mk_effaddr
zerox pb,#23
cmp pb,mk_ram_begin wc
if_ae jmp #mk_setup_ram32
cmp pb,mk_rom_stop wc
if_ae jmp #mk_setup_io32
' fall through
mk_setup_rom32
mov mk_readf,#mk_rd32_rom
mov mk_writef,#mk_wrrom
mov mk_eacache,mk_romio_area_ptr
ret wcz
mk_setup_reg32
and pb,#%1_111
sets mk_rd32_reg,pb
setd mk_wr32_reg,pb
mov mk_readf,#mk_rd32_reg
mov mk_writef,#mk_wr32_reg
ret wcz
mk_ea_impl_tbl
long mk_ea_direct
long mk_ea_postinc
long mk_ea_predec
long mk_ea_displace
long mk_ea_index
long mk_ea_headache
mk_rd8_reg
_ret_ getbyte mk_memvalue,0-0,#0
mk_wr8_reg
_ret_ setbyte 0-0,mk_memvalue,#0
mk_rd16_reg
_ret_ getword mk_memvalue,0-0,#0
mk_wr16_reg
_ret_ setword 0-0,mk_memvalue,#0
mk_rd32_reg
_ret_ mov mk_memvalue,0-0
mk_wr32_reg
_ret_ mov 0-0,mk_memvalue
mk_rd8_rom call #mk_readrom_ea
mk_rd8_ram
_ret_ rdbyte mk_memvalue,mk_eacache
mk_wr8_ram
'call #mk_debug_wrchk8
_ret_ wrbyte mk_memvalue,mk_eacache
mk_rd16_rom call #mk_readrom_ea
mk_rd16_ram
rdword mk_memvalue,mk_eacache
_ret_ movbyts mk_memvalue,#%%3201
mk_wr16_ram
'call #mk_debug_wrchk16
movbyts mk_memvalue,#%%3201
_ret_ wrword mk_memvalue,mk_eacache
mk_rd32_rom call #mk_readrom_ea32
mk_rd32_ram
rdlong mk_memvalue,mk_eacache
_ret_ movbyts mk_memvalue,#%%0123
mk_wr32_ram
'call #mk_debug_wrchk32
movbyts mk_memvalue,#%%0123
_ret_ wrlong mk_memvalue,mk_eacache
mk_wrrom ret ' obviously nothing
mk_rdimm
_ret_ mov mk_memvalue,mk_eacache
mk_longio_tmp long 0
mk_rd32_io
call #mk_rd16_io
getword mk_longio_tmp,mk_memvalue,#0
add mk_eacache,#2
call #mk_rd16_io
_ret_ setword mk_memvalue,mk_longio_tmp,#1
mk_wr32_io
mov mk_longio_tmp,mk_memvalue
shr mk_memvalue,#16
call #mk_wr16_io
add mk_eacache,#2
getword mk_memvalue,mk_longio_tmp,#0
' fall through
mk_wr16_io
'debug("mk_wr16_io ",uhex(mk_effaddr),uhex_long($7f))
cmp mk_eacache,mk_vdp_begin wc
if_ae jmp #vdpio_write16
cmp mk_eacache,mk_iog_begin wc
if_ae jmp #iog_write16
cmp mk_eacache,mk_sram_begin wc
if_ae cmpr mk_eacache,mk_sram_stop wc
if_ae jmp #sram_write16
debug("undecoded IO WORD WRITE: ",uhex_(mk_effaddr),uhex_long(mk_virtualpc))
ret wcz ' undecoded IO?
mk_rd16_io
cmp mk_eacache,mk_vdp_begin wc
if_ae jmp #vdpio_read16
cmp mk_eacache,mk_iog_begin wc
if_ae jmp #iog_read16
cmp mk_eacache,mk_sram_begin wc
if_ae cmpr mk_eacache,mk_sram_stop wc
if_ae jmp #sram_read16
debug("undecoded IO WORD READ: ",uhex(mk_effaddr))
ret wcz ' undecoded IO?
mk_rd8_io
cmp mk_eacache,mk_vdp_begin wc
if_ae jmp #vdpio_read8
cmp mk_eacache,mk_iog_begin wc
if_ae jmp #iog_read8
cmp mk_eacache,mk_sram_begin wc
if_ae cmpr mk_eacache,mk_sram_stop wc
if_ae jmp #sram_read8
mov mk_memvalue,#0 ' TODO
ret wcz
mk_wr8_io
'debug("mk_wr8_io ",uhex(mk_effaddr))
cmp mk_eacache,mk_vdp_begin wc
if_ae jmp #vdpio_write8
cmp mk_eacache,mk_iog_begin wc
if_ae jmp #iog_write8
cmp mk_eacache,mk_sram_begin wc
if_ae cmpr mk_eacache,mk_sram_stop wc
if_ae jmp #sram_write8
mov mk_memvalue,#0 ' TODO
ret wcz
mk_wr_sr
xor mk_memvalue,mk_sr
testn mk_memvalue,#255 wz
xor mk_memvalue,mk_sr
testb mk_sr,#MK_SUPER_BIT wc
if_nz_or_nc jmp #mk_hub_wr_sr
mk_wr_ccr
setq #%11111
muxq mk_sr,mk_memvalue
ret wcz
mk_rd_sr
_ret_ mov mk_memvalue,mk_sr
mk_multilogic
call #mk_get_second_reg
callpb mk_opword,#mk_setup_operand_auto
call mk_readf
push #mk_write_second_reg_or_ea
mk_multilogic_common
shl mk_memvalue,mk_shiftit
shl mk_optmp1,mk_shiftit
mk_thelogicop and mk_memvalue,mk_optmp1 wz
bitz mk_sr,#MK_ZERO_BIT
testb mk_memvalue,#31 wz
bitz mk_sr,#MK_NEG_BIT
andn mk_sr,#MK_CARRY_MASK|MK_OVER_MASK
_ret_ shr mk_memvalue,mk_shiftit
mk_illegal
debug("ILLEGAL INSTRUCTION ",uhex_word(mk_opword))
'drvh #38
mov pb,#$10
jmp #mk_hub_trapit
mk_getop_ram
mov mk_memtmp0,mk_virtualpc
add mk_virtualpc,#2
setword mk_memtmp0,#@main_ram>>16,#1
rdword mk_opword,mk_memtmp0
_ret_ movbyts mk_opword,#%%3201
mk_romque_refill
mov mk_romio_target,mk_romque_area_ptr
mov mk_romio_length,#MK_ROMQUE_SIZE/2
mov mk_romque_left,#MK_ROMQUE_SIZE
mov ptra,mk_romque_area_ptr
mov pa,mk_virtualpc
' Handle not long-aligned access (must logically be word aligned though!)
rczr pa wcz
zerox pa,#20 ' Limit to 8 MB range
if_c sub mk_romio_target,#2
if_c add mk_romio_length,#1
call #mk_readrom
mk_getop_rom
'debug("in getop_rom with ",udec(mk_romque_left))
djf mk_romque_left,#mk_romque_refill
add mk_virtualpc,#2
rdword mk_opword,ptra++
movbyts mk_opword,#%%3201
ret wcz
mk_romque_left long 0
mk_condition_truth_table
'' Remember, status register is %XNZVC
long $10001 * %1111_1111_1111_1111 '' %0000 : True
'long $10001 * %0000_0000_0000_0000 '' %0001 : False
long $10001 * %0000_0101_0000_0101 '' %0010 : High
'long $10001 * %1111_1010_1111_1010 '' %0011 : Low or same
long $10001 * %0101_0101_0101_0101 '' %0100 : carry clear
'long $10001 * %1010_1010_1010_1010 '' %0101 : carry set
long $10001 * %0000_1111_0000_1111 '' %0110 : not equal
'long $10001 * %1111_0000_1111_0000 '' %0111 : equal
long $10001 * %0011_0011_0011_0011 '' %1000 : overflow clear
'long $10001 * %1100_1100_1100_1100 '' %1001 : overflow set
long $10001 * %0000_0000_1111_1111 '' %1010 : plus
'long $10001 * %1111_1111_0000_0000 '' %1011 : minus
long $10001 * %1100_1100_0011_0011 '' %1100 : greater or equal (N==V)
'long $10001 * %0011_0011_1100_1100 '' %1101 : less than (N!=V)
long $10001 * %0000_1100_0000_0011 '' %1110 : greater than (N==V)&!Z (???)
'long $10001 * %1111_0011_1111_1100 '' %1111 : less or equal (N!=V)|Z (???)
mk_shift_impl_tbl
long mk_do_asr
long mk_do_asl
long mk_do_lsr
long mk_do_lsl
long mk_do_roxr
long mk_do_roxl
long mk_do_ror
long mk_do_rol
mk_flowop_impl_tbl
long mk_hub_reset
long mk_hub_nop
long mk_hub_stop
long mk_hub_rte
long mk_illegal
long mk_hub_rts
long mk_hub_trapv
long mk_hub_rtr
mk_iog_begin long $00_A00000
mk_vdp_begin long $00_C00000
mk_ram_begin long $00_E00000
mk_romio_area_ptr long @mk_romio_area
mk_romque_area_ptr long @mk_romque_area
mk_dreg_mask long %111_000_000_000
mk_bit31 long negx
#ifdef USE_PSRAM16
mk_psram_pinfield long PSRAM_BASE addpins 15
mk_psram_addr_cmd long (PSRAM_BASE<<17)|X_PINS_ON | X_IMM_8X4_LUT + 8
mk_psram_read_cmd long (PSRAM_BASE<<17)|X_WRITE_ON| X_16P_2DAC8_WFWORD
#endif
#ifdef USE_PSRAM8
mk_psram_pinfield long PSRAM_BASE addpins 7
mk_psram_addr_cmd long (PSRAM_BASE<<17)|X_PINS_ON | X_IMM_8X4_LUT + 8
mk_psram_read_cmd long (PSRAM_BASE<<17)|X_WRITE_ON| X_8P_1DAC8_WFBYTE
#endif
#ifdef USE_PSRAM4
mk_psram_pinfield long PSRAM_BASE addpins 3
mk_psram_addr_cmd long (PSRAM_BASE<<17)|X_PINS_ON | X_IMM_8X4_4DAC1 + 8
mk_psram_read_cmd long (PSRAM_BASE<<17)|X_WRITE_ON| X_4P_4DAC1_WFBYTE
#endif
#ifdef USE_HYPER
mk_hyper_addr_cmd1 long (HYPER_BASE<<17)|X_PINS_ON | X_IMM_4X8_1DAC8 + 4
mk_hyper_addr_cmd2 long (HYPER_BASE<<17)|X_PINS_ON | X_IMM_4X8_1DAC8 + 2
mk_hyper_read_cmd long (HYPER_BASE<<17)|X_WRITE_ON| X_8P_1DAC8_WFBYTE
#endif
mk_nco_fast long $8000_0000
#ifdef USE_PSRAM_EITHER
#ifdef USE_PSRAM_SLOW
mk_nco_slow long $2AAA_AAAB
#else
mk_nco_slow long $4000_0000
#endif
#else
mk_nco_slow long $4000_0000
#endif
mk_cogvar_start
mk_debug_tripwire long $00173E
mk_debug_ctr long 0
mk_rom_stop res 1
mk_sram_begin res 1
mk_sram_stop res 1
mk_virtualpc res 1 ' PC in virtual space
mk_effaddr res 1 ' calculated effective address
mk_shiftit res 1 ' operand MSB shift
mk_branchdisplace res 1 ' branch target
mk_opword res 1 ' opcode
mk_readf res 1 ' operand read pointer
mk_writef res 1 ' operand write pointer
mk_getopf res 1 ' opword get pointer
mk_optmp0 res 1
mk_optmp1 res 1
mk_optmp2 res 1
mk_eatmp0 res 1
mk_eatmp1 res 1
mk_romio_length res 1
mk_romio_target res 1
mk_romio_tmp1 res 1
mk_romio_tmp2 res 1
mk_romio_zerox res 1
fit $1F0
org $1F0
mk_memtmp0 res 1
mk_memtmp1 res 1
mk_memtmp2 res 1
mk_memtmp3 res 1
mk_memvalue res 1 ' memory read/write value
mk_eacache res 1 ' remapped EA
fit $1F6
DAT ' MotoKore 68000 LUT resident code
mk_lutbase
org 512
#ifdef USE_PSRAM16
long $0000
long $1111
long $2222
long $3333
long $4444
long $5555
long $6666
long $7777
long $8888
long $9999
long $AAAA
long $BBBB
long $CCCC
long $DDDD
long $EEEE
long $FFFF
#elseifdef USE_PSRAM8
long $00
long $11
long $22
long $33
long $44
long $55
long $66
long $77
long $88