forked from hperaza/Debug280
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdebug280.mac
1170 lines (1045 loc) · 21.9 KB
/
debug280.mac
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
;**********************************************************************;
; ;
; Simple Z280 standalone debug monitor for the Z280RC board. ;
; Copyright (C) 2020, Hector Peraza. ;
; ;
; This program is free software; you can redistribute it and/or ;
; modify it under the terms of the GNU General Public License as ;
; published by the Free Software Foundation; either version 2 of ;
; the License, or (at your option) any later version. ;
; ;
; This program is distributed in the hope that it will be useful, ;
; but WITHOUT ANY WARRANTY; without even the implied warranty of ;
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;
; GNU General Public License for more details. ;
; ;
; You should have received a copy of the GNU General Public License ;
; along with this program; if not, write to the Free Software ;
; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ;
; ;
;**********************************************************************;
.Z280
include Z280.INC
CR equ 0Dh
LF equ 0Ah
TAB equ 09h
FALSE equ 0
TRUE equ NOT FALSE
MAXBP equ 8 ; max number of breakpoints
cseg
public GETB,GETAB,GETW,GETADR,PUTCH,AHEX,HLHEX
extrn DIS280
;-----------------------------------------------------------------------
; Main entry point
DEBUG:: di
ld sp,mon_stack ; setup local stack
call init
cmd_loop:
ld sp,mon_stack ; restore local stack
ld hl,prompt
call print ; output prompt
call getln ; get command
push cmd_loop ; push return address
ld hl,lnbuf
call skipbl ; skip blanks and get command char
or a
ret z ; ignore empty lines
inc hl
ld (lnptr),hl
call ucase ; convert command char to uppercase
cp 'X' ; show regs?
jp z,showregs
push af
call get_args ; parse command and get arguments
ld bc,(arg3) ; load arguments into registers
ld de,(arg2)
ld hl,(arg1)
pop af
cp 'D' ; dump?
jp z,dump
cp 'F' ; fill?
jp z,fill
cp 'S' ; search?
jp z,search
cp 'E' ; examine?
jp z,exam
cp 'B' ; set breakpoint?
jp z,addbrk
cp 'C' ; clear breakpoint?
jp z,clrbrk
cp 'G' ; go?
jp z,run
cp 'T' ; trace (single-step)?
jp z,trace
cp 'I' ; input?
jp z,inport
cp 'O' ; output?
jp z,outport
cp 'W' ; word?
jp z,word
cp 'L' ; list?
jp z,disasm
error: call cr_lf
ld a,'?' ; unknown command
call mon_putch
jr cmd_loop
prompt: db CR,LF,"Z280>",0
; init MMU, setup ITVT, etc.
init: ld hl,$ITBL
ld de,0
ld bc,28*4
ldir ; copy ITVT to page zero
ld hl,0 ; note: assuming Z80-mode!
ld c,ITV
ldctl (c),hl ; set interrupt/trap table pointer
ld c,ISR
;; ld hl,0
ldctl (c),hl ; disable vectored external ints
im 3
;; ld hl,0
ldctl usp,hl
ld de,0
dec hl
dec hl
ldw (hl),de
dec hl
dec hl
ldw (hl),de
ld (pgm_sp),hl
ld hl,DEBUG
ld (lastz),hl
ld (lastd),hl
ret
; get command line
getln: ld hl,lnbuf ; HL = start of command buffer
ld b,1
get: call mon_getch ; get char
cp CR
jr z,eol ; CR ends command
cp 8
jr z,bkspc ; del and backspace erase prev char
cp 7Fh
jr z,bkspc
cp 3
jr z,ctrlc ; ^C restarts
cp ' '
jr c,get ; ignore any other control chars
ld c,a
ld a,b
cp 40-1 ; max length reached?
jr nc,get ; ignore extra input if yes
ld a,c
call mon_putch ; echo char
ld (hl),a ; store in buffer
inc hl ; advance pointer
inc b ; and counter
jr get ; loop
bkspc: dec b
jr z,getln
ld a,8
call mon_putch ; erase prev char from the screen
call space
ld a,8
call mon_putch
dec hl
jr get
eol: ld (hl),0 ; end of input, append null char
call mon_putch
ret
ctrlc: ld hl,ctlcm
call print
jp cmd_loop
ctlcm: db "^C",CR,LF,0
; convert char to uppercase
ucase: cp 'a'
ret c
cp 'z'+1
ret nc
and 5Fh
ret
; output string
print: ld a,(hl)
or a
ret z
call mon_putch
inc hl
jr print
; skip blanks
skip: inc hl
skipbl: ld a,(hl)
or a
ret z
cp ' '
jr z,skip
cp TAB
jr z,skip
ret
; get command line arguments
get_args:
ld hl,0
ld (arg1),hl ; unspecified args default to zero
ld (arg2),hl
ld (arg3),hl
xor a
ld (argset),a
ld de,(lnptr)
ld c,01h
call gethex ; get first arg
ld (arg1),hl
ld (arg2),hl
ret c
ld c,02h
call gethex ; get second arg
ld (arg2),hl
ret c
ld c,04h
call gethex ; get third arg
ld (arg3),hl
ret c
jp error ; error if more args
; get hexadecimal value from command line
gethex: ld hl,0
gh1: ld a,(de)
or a ; end of command line?
scf ; return with CY set if yes
ret z
inc de
cp ' ' ; ignore blanks
jr z,gh1
cp ',' ; comma separates arguments
ret z
call tohex
jp c,error
call adddig
jp c,error
ld a,(argset)
or c ; set bit if argument present
ld (argset),a
jr gh1
adddig: add hl,hl
ret c
add hl,hl
ret c
add hl,hl
ret c
add hl,hl
ret c
add hl,a
ret
tohex: call ucase
sub '0'
ret c
cp 10
ccf
ret nc
cp 11h
ret c
cp 17h
ccf
ret c
sub 7
ret
; compare addresses and return one level higher if they match
next: call ?stop ; check for ^C abort
cpw hl,de ; end address reached?
jr z,cmp_eq ; return one level higher if yes
inc hl ; else increment HL and return
ret
cmp_eq: inc sp
inc sp
ret
; check for ^C abort or XON/XOFF
?stop: call mon_status
or a
ret z
call mon_getch
cp 3 ; ^C aborts
jp z,ctrlc
cp 13h ; ^S suspends output
ret nz
call mon_getch
cp 3
jp z,ctrlc
ret
; D addr1,addr2[,bank]
; Dump region addr1...addr2
dump: push hl
push bc
iopage MMUP
xor a
out (PDR),a
pop hl
ld a,(argset)
bit 2,a ; bank specified?
jr nz,dmp0 ; branch if yes
ld hl,(mmu_pdr+32) ; else use saved user bank
jr dmp3
dmp0: add hl,hl
add hl,hl
add hl,hl
add hl,hl
dmp3: set 3,l
ld c,BMP
ld b,16
ld a,10h
dmp1: outw (c),hl ; setup MMU for LDUP command
add hl,a
djnz dmp1
pop hl
ld a,(argset)
bit 0,a ; start address specified?
jr nz,dmp4 ; use it if yes
ld hl,(lastd) ; else continue from where we stopped before
dmp4: bit 1,a ; end address specified?
jr nz,dmp2 ; use it if yes
ld e,l
ld d,h
inc d
dec de ; else display one 256-byte page
dmp2: call out_addr ; output address
push hl
dmph: ldup a,(hl) ; get byte
call outbyte ; output it as hexadecimal
call ?stop ; check for ^C abort
cpw hl,de
jr z,enddmp ; exit loop when done
inc hl ; advance pointer
ld a,l
and 0Fh ; max 16 bytes per line
jr nz,dmph
pop hl
call dmpa ; dump ASCII as well
jr dmp2
enddmp: inc hl
ld (lastd),hl ; remember where we stopped
pop hl
dmpa: ldup a,(hl) ; get byte
cp ' ' ; printable?
jr c,outdot
cp 7Fh
jr c,char
outdot: ld a,'.' ; output a dot if not
char: call mon_putch
call ?stop ; check for ^C abort
cpw hl,de
ret z ; return when done
inc hl
ld a,l
and 0Fh ; max 16 chars per line
jr nz,dmpa
ret
; F addr1,addr2,byte
; Fill region addr1...addr2 with byte
fill: ld (hl),c
call next
jr fill
; S addr1,addr2,byte
; Search region addr1...addr2 for byte
search: ld a,c
cp (hl) ; byte matches?
jr nz,scont ; branch if not
call out_addr ; else output address
dec hl
ld a,(hl)
call outbyte ; output prev byte
ld a,'('
call mon_putch
inc hl
ld a,(hl)
call ahex ; output matching byte
ld a,')'
call mon_putch
call space
inc hl
ld a,(hl)
call outbyte ; output following byte
dec hl
scont: call next
jr search
; E addr[,bank]
; Examine and modify memory starting at addr
exam: call out_addr ; output address
ld a,(hl)
call outbyte ; output old contents
push hl
call getln ; read line
pop de
ld hl,lnbuf
call skipbl ; skip blanks
ex de,hl
or a
jr z,cont ; empty line keeps old value
cp '.'
ret z ; dot (or ^C in getln) ends operation
push hl
call gethex ; get new value
ex de,hl ; into DE
pop hl
ld (hl),e ; store it
cont: inc hl
jr exam ; loop
; I port[,iopage][,wflag] wflag = 0 for byte else word
; Input from port
inport: call cr_lf
ld a,l
call ahex ; output port address
ld a,'='
call mon_putch
ex de,hl
push bc
ld c,IOP
ldctl (c),hl ; select I/O page
ex de,hl
pop bc
ld a,b
or c ; word read?
ld c,l
ld b,0
jr z,iw ; branch if not
in hl,(c) ; read
jp hlhex ; and output word
iw: in a,(c) ; read
jp ahex ; and output byte
; O port,byte[,iopage]
; Output to port
outport:push hl
ld l,c
ld l,b
ld c,IOP
ldctl (c),hl ; select I/O page
pop bc
;ld b,0
ld a,e
out (c),a ; output byte
ret
; W addr
; display Word at addr
word: call out_addr ; output address
ld hl,(hl)
jp hlhex ; output contents
; B
; display current Breakpoints
; B addr
; set Breakpoint at addr.
addbrk: ld ix,bptbl ; get breakpoint table address into IX
ld a,(argset)
and 01h ; argument given?
jr nz,setb ; set breakpoint if yes
ld a,(numbp)
or a ; any breakpoints set?
ret z ; return if not
ld b,a
ld de,3
dispbp: ld hl,(ix)
call cr_lf
call hlhex ; display breakpoint address
add ix,de
djnz dispbp ; loop to process next
ret
setb: ld a,(numbp)
cp MAXBP ; maximum already reached?
jp nc,error ; error if yes
or a ; table empty?
jr z,sb2 ; branch if yes
ld b,a
ld de,3
sb1: cpw hl,(ix) ; breakpoint already exists?
jp z,error ; error if yes
add ix,de
djnz sb1 ; else loop to check next entry
sb2: ldw (ix),hl ; store breakpoint address
ld hl,numbp
inc (hl) ; new breakpoint address
ret
; C addr
; Clear breakpoint at addr.
clrbrk: ld a,(argset)
and 01h
jp z,error ; argument is mandatory
ld ix,bptbl ; get breakpoint table address into IX
ld a,(numbp)
or a ; any breakpoints set?
jp z,error ; error if not
ld b,a
ld de,3
cb1: cpw hl,(ix) ; breakpoint found?
jr z,cb2 ; exit loop if yes
add ix,de
djnz cb1 ; loop to process next entry
jp error ; breakpoint not found
cb2: ld hl,numbp
dec (hl) ; decrement breakpoint count
dec b ; last used entry?
ret z ; return if yes
cb3: ldw hl,(ix+3)
ldw (ix),hl ; else shuffle entries down
add ix,de
djnz cb3
ret
; L addr,num
; List (disassemble) num instructions starting from addr
disasm: ld a,(argset)
bit 0,a ; address given?
jr nz,dis1 ; use it if yes
ld hl,(lastz) ; else continue from where we ended last time
ld (arg1),hl
dis1: bit 1,a ; count given?
jr nz,dis2 ; use it if yes
ld de,16 ; else default to 16
ld (arg2),de
dis2: ld a,d
or e
jr z,dis3
ld hl,(arg1)
call out_addr ; output address
ld a,TAB
call mon_putch ; output TAB separator
call DIS280 ; output mnemonic
call ?stop ; check for ^C abort
ld hl,(arg2)
dec hl ; decrement count
ld (arg2),hl
ex de,hl
jr dis2 ; and loop
dis3: ld hl,(arg1)
ld (lastz),hl ; remember where we stopped
ret
; routines called by the disassembler module:
GETB: push hl
ld hl,(arg1)
ld a,(hl) ; return next opcode byte
inc hl
ld (arg1),hl
pop hl
ret
GETAB: ld a,(hl) ; return opcode at address HL
ret
GETW: call GETB ; return next word
ld l,a
call GETB
ld h,a
ret
GETADR: ld hl,(arg1) ; return current address
ret
PUTCH: ld a,c ; output char
jp mon_putch
; G addr
; Go (execute) program at addr.
run: ld ix,(pgm_sp)
ld a,(argset)
and 01h ; an address was given?
jr nz,r1 ; yes, use it
ld hl,(pgm_pc) ; else continue from saved PC
r1: ldw (ix+2),hl ; store PC on return stack
res 0,(ix+1) ; clear SS bit of MSR
res 1,(ix+1) ; clear SSP bit of MSR
set 4,(ix+1) ; set BH bit of MSR
call setbp ; set breakpoints in place
jp continue
; place breakpoints prior to executing user code
setbp: ld ix,bptbl
ld a,(numbp)
or a ; any breakpoints defined?
ret z ; return if not
ld b,a
ld de,(pgm_pc)
set1: ld hl,(ix) ; get breakpoint address
ld a,(hl)
ld (ix+2),a ; remember original memory contents
cpw hl,de
ld (hl),76h ; store halt instruction (breakpoint-on-halt mode)
inc ix
inc ix
inc ix
djnz set1
ret
; remove breakpoints from user code so they will not appear in the
; disassembler listing and will not interfere with single-stepping
rembp: ld ix,bptbl
ld a,(numbp)
or a ; any breakpoints defined?
ret z ; return if not
ld b,a
ld de,3
rem1: ld hl,(ix) ; get breakpoint address
ld a,(ix+2)
ld (hl),a ; restore original memory contents
add ix,de
djnz rem1
ret
; T
; Trace single instruction
; T num
; Trace num instructions
trace: ld a,h
or l
jr nz,tr1
ld hl,1 ; no argument or zero count defaults to 1
tr1: ld (tcount),hl
trnext: ld ix,(pgm_sp)
ld hl,(pgm_pc) ; store PC on return stack
ldw (ix+2),hl ; in case user changed it
set 0,(ix+1) ; set SS bit of MSR
res 1,(ix+1) ; clear SSP bit of MSR
set 4,(ix+1) ; set BH bit of MSR
jp continue
; display 16-bit address followed by a colon and a space
out_addr:
call cr_lf
call hlhex
ld a,':'
call mon_putch
jr space
; display 8-bit value followed by a space
outbyte:
call ahex
space: ld a,' '
jp mon_putch
; display 16-bit hexadecimal value
hlhex: ld a,h
call ahex
ld a,l
ahex: push af
rrca
rrca
rrca
rrca
call nhex
pop af
nhex: and 0Fh
add a,90h
daa
adc a,40h
daa
jp mon_putch
; display newline
cr_lf: push af
ld a,CR
call mon_putch
ld a,LF
call mon_putch
pop af
ret
; trap entry point: saves all registers and current MMU status, and then
; jumps to the command loop.
debug_trap:
ld (pgm_sp),sp
ld sp,reg_stack
push af ; push main reg bank
push bc
push de
push hl
ex af,af'
push af ; push alternate reg bank
ex af,af'
exx
push bc
push de
push hl
exx
push ix ; push index regs
push iy
ldctl hl,usp
push hl ; push user SP
ld c,IOP
ldctl hl,(c)
push hl ; push user I/O page
ld sp,mon_stack
call savmmu ; save user MMU state
ld ix,(pgm_sp)
ldw de,(ix)
ld (pgm_msr),de ; save user MSR
ldw de,(ix+2)
ld (pgm_pc),de ; save user PC
ld (lastz),de ; use as default for L command
ld a,(reason)
dec a ; single-stepping?
call nz,rembp ; remove breakpoints if not
call pr_reason ; display trap reason
call shregs ; display register contents
ld hl,(pgm_pc)
ld (arg1),hl
call out_addr
ld a,TAB
call mon_putch
call DIS280 ; display next instruction
call cr_lf
ld a,(reason)
dec a ; single-stepping?
jr nz,dbg2 ; branch if not
ld hl,(tcount)
dec hl
ld (tcount),hl
ld a,h
or l ; trace count reached zero?
jp nz,trnext ; trace next instruction if not
dbg2: ld hl,(pgm_hl)
ld (lastd),hl ; use HL value as default for D command
jp cmd_loop
; display trap reason
pr_reason:
ld a,(reason)
or a
ld hl,brk_msg
jr z,pr1
dec a
ret z ; don't print anything if single-stepping
dec a
ld hl,div_msg
jr z,pr1
dec a
ld hl,acv_msg
jr z,pr1
dec a
ld hl,prv_msg
jr z,pr1
dec a
ld hl,ext_msg
ret nz
pr1: call print
ld hl,atpc_msg
call print ; display reason
ld hl,(pgm_pc)
jp hlhex ; display trap address
brk_msg:
db CR,LF,"Break",0
div_msg:
db CR,LF,"Divide exception",0
acv_msg:
db CR,LF,"Access violation",0
prv_msg:
db CR,LF,"Privileged instruction",0
ext_msg:
db CR,LF,"Extended instruction",0
atpc_msg:
db " at PC=",0
; continue execution from last breakpoint or single-step operation
continue:
call rstmmu ; restore user MMU state
ld sp,pgm_iop
pop hl
ld c,IOP
ldctl (c),hl ; restore user I/O page
pop hl
ldctl usp,hl ; restore user SP
pop iy ; restore index regs
pop ix
exx
pop hl ; restore alternate reg bank
pop de
pop bc
exx
ex af,af'
pop af
ex af,af'
pop hl ; restore main reg bank
pop de
pop bc
pop af
ld sp,(pgm_sp) ; prepare to return from trap
retil
; X
; show CPU register contents
; XM
; show MMU state
; Xrr
; display/modify CPU register
showregs:
ld hl,(lnptr)
call skipbl
or a ; anything follows command?
jp z,shregs ; no, display all regs
call ucase
cp 'M' ; M?
jp z,showmmu ; yes, display MMU status
ld (lnptr),hl
ld hl,regdat
chrg1: ldw de,(hl) ; get pointer to reg value into DE
ld a,d
or e ; end of list?
jp z,error ; error if yes, reg name not found
inc hl
inc hl ; point to string
push de
call rmatch ; register name matches?
pop de
jr z,chrg3 ; branch if yes
chrg2: ld a,(hl) ; else skip this entry
inc hl
or a
jr nz,chrg2
jr chrg1
chrg3: call cr_lf
call print ; output register name
dec hl
ld a,'='
cp (hl)
call nz,mon_putch ; follow alt regs with '='
ex de,hl
push hl
ldw hl,(hl)
call hlhex ; output reg value
ld a,' '
call mon_putch
call getln ; read line
pop de
ld hl,lnbuf
call skipbl ; skip blanks
ld (lnptr),hl
or a
ret z ; empty line keeps old value
cp '.'
ret z ; as does dot
push de
ld de,(lnptr)
call gethex ; get new value
ex de,hl ; into DE
pop hl
ldw (hl),de ; store it
ret
rmatch: ld a,(hl)
inc hl
cp ' ' ; skip blanks
jr z,rmatch
cp CR ; CR
jr z,rmatch
cp LF ; and LF
jr z,rmatch
dec hl
push hl ; remember start of reg name
ld de,(lnptr)
rm1: ld a,(hl)
or a ; end of name?
jr z,rm4 ; return Z if yes
cp '='
jr z,rm2
ld c,a
ld a,(de)
call ucase
cp c ; name matches?
jr nz,rm4 ; return NZ if not
inc hl
inc de
jr rm1 ; loop
rm2: ld a,(de)
cp "'"
jr z,rm3
xor a
rm3: or a
rm4: pop hl
ret
shregs: ld hl,regdat
srg1: ldw de,(hl) ; get pointer to register value into DE
ld a,d
or e ; end of list?
ret z ; return if yes
inc hl
inc hl ; point to start of string
ex de,hl
ldw bc,(hl) ; get register value into BC
push bc
ex de,hl
call print ; output register name
ex (sp),hl
call hlhex ; output value
pop hl
inc hl
jr srg1
regdat: dw pgm_af
db CR,LF,"AF=",0
dw pgm_bc
db " BC=",0
dw pgm_de
db " DE=",0
dw pgm_hl
db " HL=",0
dw pgm_ix
db " IX=",0
dw pgm_iy
db " IY=",0
dw pgm_iop
db " IOP=",0
dw pgm_af1
db CR,LF,"AF'",0
dw pgm_bc1
db " BC'",0
dw pgm_de1
db " DE'",0
dw pgm_hl1
db " HL'",0
dw pgm_pc
db " PC=",0
dw pgm_sp
db " SP=",0
dw pgm_usp
db " USP=",0
dw 0
showmmu:
ld hl,mmsg1
call print
iopage MMUP
ld c,MMCR
inw hl,(c)
call hlhex
ld ix,mmu_pdr ; point to saved MMU registers
ld hl,mmsg2
call print
call sm3
call cr_lf
call sm1
ld hl,mmsg3
call print
call sm3
call cr_lf
sm1: ld b,8
sm2: call space
djnz sm2
sm3: ld b,8
sm4: ldw hl,(ix)
call hlhex
call space
inc ix
inc ix
djnz sm4
ret
mmsg1: db CR,LF,'MMCR=',0
mmsg2: db CR,LF,'Usr PDR ',0