1; Verifies timing of branch instructions
2;
3; Runs branch instruction in loop that counts iterations
4; until APU length counter expires. Moves the loop around
5; in memory to trigger page cross/no cross cases.
6
7.include "shell.inc"
8
9zp_byte opcode
10zp_byte flags
11zp_byte time_ptr
12bss_res times,8
13
14main:
15	set_test 0
16	for_loop test_opcode,$10,$F0,$20
17	jmp tests_done
18
19log_time:
20	ldx time_ptr
21	sta times,x
22	inc time_ptr
23	rts
24
25test_opcode:
26	sta opcode
27
28	; Not taken
29	ldx #$FF
30	and #$20
31	beq :+
32	inx
33:       stx flags
34	setb time_ptr,0
35	jsr test_addrs
36
37	; Taken
38	lda flags
39	eor #$FF
40	sta flags
41	jsr test_addrs
42
43	; Verify times
44	ldx #8 - 1
45:       lda times,x
46	cmp @correct_times,x
47	bne @error
48	dex
49	bpl :-
50
51	rts
52
53@correct_times:
54	.byte 2,2,2,2,3,3,4,4
55
56@error: lda opcode
57	jsr print_a
58	jsr play_byte
59	ldy #0
60:       lda times,y
61	jsr print_dec
62	jsr print_space
63	iny
64	cpy #8
65	bne :-
66	jsr print_newline
67	set_test 1
68	rts
69
70; Tests instruction with page cross/no cross cases
71test_addrs:
72	setw addr,$6EA
73	jsr test_forward
74
75	setw addr,$700
76	jsr test_reverse
77
78	setw addr,$6EB
79	jsr test_forward
80
81	setw addr,$6FF
82	jsr test_reverse
83
84	rts
85
86; Times code at addr
87time_code:
88	pha
89
90	; Synchronize with APU length counter
91	setb SNDMODE,$40
92	setb SNDCHN,$01
93	setb $4000,$10
94	setb $4001,$7F
95	setb $4002,$FF
96	setb $4003,$18
97	lda #$01
98:       and SNDCHN
99	bne :-
100
101	; Setup length counter
102	setb $4003,$18
103
104	delay 29830-7120
105
106	; Run instruction
107	setb temp,0
108	pla
109	jmp (addr)
110
111raw_to_cycles: ; entry i is lowest value that qualifies for i cycles
112	.byte 250, 241, 233, 226, 219, 213, 206, 201, 195, 190, 0
113
114; Jumps here when instruction has been timed
115instr_done:
116	; Convert iteration count to cycle count
117	lda temp
118	ldy #-1
119:       iny
120	cmp raw_to_cycles,y
121	blt :-
122
123	; Convert 10+ to 0
124	cpy #10
125	blt :+
126	ldy #0
127:
128	tya
129	jsr log_time
130
131	rts
132
133.macro test_dir
134	; Copy code
135	ldy #40
136:       lda @code,y
137	sta (addr),y
138	dey
139	bpl :-
140
141	; Patch branch opcode
142	ldy #@branch - @code
143	lda opcode
144	sta (addr),y
145
146	; Calculate address of @loop
147	lda addr
148	clc
149	adc #@loop - @code
150	sta addr
151	lda addr+1
152	adc #0
153	sta addr+1
154
155	jmp time_code
156@code:
157.endmacro
158
159.macro instr_loop
160	inc temp
161	lda SNDCHN
162	and #$01
163	beq *+5
164	jmp (addr)
165	jmp instr_done
166.endmacro
167
168test_reverse:
169	test_dir
170:       instr_loop
171@loop:  lda flags
172	pha
173	plp
174@branch:
175	bmi :-
176	instr_loop
177
178test_forward:
179	test_dir
180@loop:  lda flags
181	pha
182	plp
183@branch:
184	bmi :+
185	instr_loop
186:       instr_loop
187