mirror of
https://github.com/daniel5151/ANESE.git
synced 2025-04-02 10:32:00 -04:00
331 lines
7.6 KiB
ArmAsm
331 lines
7.6 KiB
ArmAsm
; Tests instruction timing for all except the 8 branches and 12 halts
|
|
;
|
|
; Times each instruction by putting it in a loop that counts iterations
|
|
; and waits for APU length counter to expire.
|
|
|
|
CUSTOM_IRQ=1
|
|
.include "shell.inc"
|
|
|
|
zp_byte nothing_failed
|
|
zp_byte test_index
|
|
zp_byte type_mask
|
|
zp_byte saved_sp
|
|
stack_copy = $600 ; stack is copied here during instruction test
|
|
test_opcode = $705 ; test loop is copied here
|
|
irq = test_opcode+2
|
|
|
|
main:
|
|
print_str "Instruction timing test",{newline,newline}
|
|
print_str "Takes about 25 seconds. "
|
|
print_str "Doesn't time the 8 branches "
|
|
print_str "and 12 illegal instructions.",{newline,newline}
|
|
|
|
set_test 5,"Timing of APU length period, INC zp, LDA abs, AND #imm, or BNE (taken) is wrong."
|
|
lda #$29
|
|
sta test_index
|
|
jsr time_instr
|
|
cmp #2
|
|
jne test_failed
|
|
|
|
set_test 0
|
|
|
|
print_str "Official instructions...",newline
|
|
lda #0
|
|
jsr test_instrs
|
|
bne :+
|
|
set_test 2,"Official instruction timing is wrong"
|
|
:
|
|
print_str {newline,"NOPs and alternate SBC...",newline}
|
|
lda #$80
|
|
jsr test_instrs
|
|
bne :+
|
|
set_test 3,"NOPs and alternate SBC timing is wrong"
|
|
:
|
|
print_str {newline,"Unofficial instructions...",newline}
|
|
lda #$40
|
|
jsr test_instrs
|
|
bne :+
|
|
set_test 4,"Unofficial instruction timing is wrong"
|
|
:
|
|
jmp tests_done
|
|
|
|
|
|
; A -> Type to test
|
|
test_instrs:
|
|
sta type_mask
|
|
setb nothing_failed,1
|
|
|
|
setb test_index,0
|
|
@loop: ldx test_index
|
|
lda instr_types,x
|
|
and #$F0
|
|
cmp type_mask
|
|
bne :+
|
|
jsr avoid_silent_nsf
|
|
jsr @test_instr
|
|
: inc test_index
|
|
bne @loop
|
|
|
|
lda nothing_failed
|
|
ora test_code
|
|
rts
|
|
|
|
|
|
; Tests current instruction in normal and page cross cases
|
|
@test_instr:
|
|
; No page crossing
|
|
lda #2
|
|
jsr time_instr
|
|
ldy test_index
|
|
eor instr_times,y
|
|
beq :+
|
|
|
|
jsr print_failed_instr
|
|
jsr print_newline
|
|
|
|
lda instr_times,y
|
|
cmp instr_times_cross,y
|
|
bne :+ ; test again only if page crossing time is different
|
|
rts
|
|
|
|
; Page crossing
|
|
: lda #3
|
|
jsr time_instr
|
|
ldy test_index
|
|
eor instr_times_cross,y
|
|
beq :+
|
|
|
|
jsr print_failed_instr
|
|
print_str " (cross)",newline
|
|
: rts
|
|
|
|
|
|
; Prints failed instruction times
|
|
; A -> Actual XOR correct
|
|
; X -> Actual
|
|
; Preserved: Y
|
|
print_failed_instr:
|
|
pha
|
|
lda test_index
|
|
jsr print_hex
|
|
jsr play_byte
|
|
print_str " was "
|
|
txa
|
|
jsr print_dec
|
|
pla
|
|
print_str ", should be "
|
|
stx temp
|
|
eor temp
|
|
jsr print_dec
|
|
setb nothing_failed,0
|
|
rts
|
|
|
|
|
|
; Times a single instruction
|
|
; test_index -> Opcode of instruction
|
|
; A -> Byte to load into X and Y before running instruction
|
|
; X, A <- Cycles instruction took
|
|
.align 256
|
|
time_instr:
|
|
sta temp
|
|
ldy test_index
|
|
sty test_opcode
|
|
|
|
; Copy test_opcode to RAM
|
|
lda instr_types,y
|
|
and #$07
|
|
asl a
|
|
tay
|
|
lda test_addrs-2,y
|
|
sta addr
|
|
lda test_addrs-1,y
|
|
sta addr+1
|
|
ldy #1
|
|
: lda (addr),y
|
|
sta test_opcode,y
|
|
iny
|
|
cpy #16
|
|
bne :-
|
|
|
|
; Save copy of stack
|
|
tsx
|
|
stx saved_sp
|
|
: lda $100,x
|
|
sta stack_copy,x
|
|
inx
|
|
bne :-
|
|
|
|
; Set zero-page values so the addressing modes use the following
|
|
; when X and Y = $02/$03
|
|
; zp $FD
|
|
; zp,x $FF/$00
|
|
; abs $03FD
|
|
; abs,x/y $03FF/$0400
|
|
; (ind,x) $02FD/$0302
|
|
; (ind),y $02FF/$0300
|
|
; JMP (ind) test_opcode+3
|
|
setb <$00,$02
|
|
setb <$01,$03
|
|
setb <$FD,$FD
|
|
setb <$FE,$02
|
|
setb <$FF,$FD
|
|
lda temp ; $A3 LAX (ab,X) will load X from these two
|
|
sta $02FD
|
|
sta $0302
|
|
setw $03FD,test_opcode+3 ; JMP ($03FD) will use this address
|
|
|
|
; Fill stack for RTS/RTI test
|
|
ldx #$FF
|
|
txs
|
|
inx
|
|
lda #>test_opcode
|
|
: pha
|
|
inx
|
|
bne :-
|
|
|
|
; Setup registers
|
|
lda temp
|
|
tay
|
|
tax
|
|
setb temp,0
|
|
|
|
; Synchronize with APU length counter
|
|
setb SNDMODE,$40
|
|
setb SNDCHN,$01
|
|
setb $4000,$10
|
|
setb $4001,$7F
|
|
setb $4002,$FF
|
|
setb $4003,$18
|
|
lda #$01
|
|
: and SNDCHN
|
|
bne :-
|
|
|
|
; Setup length counter
|
|
setb $4003,$18
|
|
|
|
; ~26323 delay, so length counter will be ~3500 cycles from expiring
|
|
setb temp3,-13
|
|
setb temp2,-207
|
|
: inc temp2
|
|
bne :-
|
|
inc temp3
|
|
bne :-
|
|
|
|
; Run instruction
|
|
jmp test_opcode
|
|
|
|
raw_to_cycles: ; entry i is lowest value that qualifies for i cycles
|
|
.byte 241, 226, 212, 200, 189, 179, 171, 163, 156, 149, 0
|
|
|
|
; Jumps here when instruction has been timed
|
|
instr_done:
|
|
; Restore things in case instruction affected them
|
|
sei
|
|
cld
|
|
|
|
; Convert iteration count to cycle count
|
|
lda temp
|
|
ldy #-1
|
|
: iny
|
|
cmp raw_to_cycles,y
|
|
blt :-
|
|
|
|
; Convert 10+ to 0
|
|
cpy #10
|
|
blt :+
|
|
ldy #0
|
|
:
|
|
; Restore stack
|
|
ldx saved_sp
|
|
txs
|
|
: lda stack_copy,x
|
|
sta $100,x
|
|
inx
|
|
bne :-
|
|
|
|
tya
|
|
tax
|
|
|
|
rts
|
|
|
|
.macro instr_template instr
|
|
: instr
|
|
inc temp
|
|
lda SNDCHN
|
|
and #$01
|
|
bne :-
|
|
jmp instr_done
|
|
.endmacro
|
|
|
|
test_1: instr_template nop
|
|
test_2: instr_template sta <$FD
|
|
test_3: instr_template sta $03FD
|
|
test_4: instr_template jmp test_opcode+3
|
|
|
|
test_addrs:
|
|
.word test_1, test_2, test_3, test_4
|
|
|
|
; $8n = unofficial NOPs and $EB equivalent of SBC #imm
|
|
; $4n = all other unofficial opcodes
|
|
; $0n = official opcodes
|
|
; -1 = not tested
|
|
; n = instruction length
|
|
instr_types:
|
|
; 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
.byte 2, 2, -1,$42,$82, 2, 2,$42, 1, 2, 1,$42,$83, 3, 3,$43 ; 0
|
|
.byte -1, 2, -1,$42,$82, 2, 2,$42, 1, 3,$81,$43,$83, 3, 3,$43 ; 1
|
|
.byte 4, 2, -1,$42, 2, 2, 2,$42, 1, 2, 1,$42, 3, 3, 3,$43 ; 2
|
|
.byte -1, 2, -1,$42,$82, 2, 2,$42, 1, 3,$81,$43,$83, 3, 3,$43 ; 3
|
|
.byte 2, 2, -1,$42,$82, 2, 2,$42, 1, 2, 1,$42, 4, 3, 3,$43 ; 4
|
|
.byte -1, 2, -1,$42,$82, 2, 2,$42, 1, 3,$81,$43,$83, 3, 3,$43 ; 5
|
|
.byte 3, 2, -1,$42,$82, 2, 2,$42, 1, 2, 1,$42, 3, 3, 3,$43 ; 6
|
|
.byte -1, 2, -1,$42,$82, 2, 2,$42, 1, 3,$81,$43,$83, 3, 3,$43 ; 7
|
|
.byte $82, 2,$82,$42, 2, 2, 2,$42, 1,$82, 1,$42, 3, 3, 3,$43 ; 8
|
|
.byte -1, 2, -1,$42, 2, 2, 2,$42, 1, 3, 1,$43,$43, 3,$43,$43 ; 9
|
|
.byte 2, 2, 2,$42, 2, 2, 2,$42, 1, 2, 1,$42, 3, 3, 3,$43 ; A
|
|
.byte -1, 2, -1,$42, 2, 2, 2,$42, 1, 3, 1,$43, 3, 3, 3,$43 ; B
|
|
.byte 2, 2,$82,$42, 2, 2, 2,$42, 1, 2, 1,$42, 3, 3, 3,$43 ; C
|
|
.byte -1, 2, -1,$42,$82, 2, 2,$42, 1, 3,$81,$43,$83, 3, 3,$43 ; D
|
|
.byte 2, 2,$82,$42, 2, 2, 2,$42, 1, 2, 1,$82, 3, 3, 3,$43 ; E
|
|
.byte -1, 2, -1,$42,$82, 2, 2,$42, 1, 3,$81,$43,$83, 3, 3,$43 ; F
|
|
; Bxx HLT
|
|
|
|
; Clocks when no page crossing occurs
|
|
instr_times:
|
|
; 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
.byte 7,6,0,8,3,3,5,5,3,2,2,2,4,4,6,6 ; 0
|
|
.byte 0,5,0,8,4,4,6,6,2,4,2,7,4,4,7,7 ; 1
|
|
.byte 6,6,0,8,3,3,5,5,4,2,2,2,4,4,6,6 ; 2
|
|
.byte 0,5,0,8,4,4,6,6,2,4,2,7,4,4,7,7 ; 3
|
|
.byte 6,6,0,8,3,3,5,5,3,2,2,2,3,4,6,6 ; 4
|
|
.byte 0,5,0,8,4,4,6,6,2,4,2,7,4,4,7,7 ; 5
|
|
.byte 6,6,0,8,3,3,5,5,4,2,2,2,5,4,6,6 ; 6
|
|
.byte 0,5,0,8,4,4,6,6,2,4,2,7,4,4,7,7 ; 7
|
|
.byte 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4 ; 8
|
|
.byte 0,6,0,6,4,4,4,4,2,5,2,5,5,5,5,5 ; 9
|
|
.byte 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4 ; A
|
|
.byte 0,5,0,5,4,4,4,4,2,4,2,4,4,4,4,4 ; B
|
|
.byte 2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6 ; C
|
|
.byte 0,5,0,8,4,4,6,6,2,4,2,7,4,4,7,7 ; D
|
|
.byte 2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6 ; E
|
|
.byte 0,5,0,8,4,4,6,6,2,4,2,7,4,4,7,7 ; F
|
|
|
|
; Clocks when page crossing occurs
|
|
instr_times_cross:
|
|
; 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
.byte 7,6,0,8,3,3,5,5,3,2,2,2,4,4,6,6 ; 0
|
|
.byte 0,6,0,8,4,4,6,6,2,5,2,7,5,5,7,7 ; 1
|
|
.byte 6,6,0,8,3,3,5,5,4,2,2,2,4,4,6,6 ; 2
|
|
.byte 0,6,0,8,4,4,6,6,2,5,2,7,5,5,7,7 ; 3
|
|
.byte 6,6,0,8,3,3,5,5,3,2,2,2,3,4,6,6 ; 4
|
|
.byte 0,6,0,8,4,4,6,6,2,5,2,7,5,5,7,7 ; 5
|
|
.byte 6,6,0,8,3,3,5,5,4,2,2,2,5,4,6,6 ; 6
|
|
.byte 0,6,0,8,4,4,6,6,2,5,2,7,5,5,7,7 ; 7
|
|
.byte 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4 ; 8
|
|
.byte 0,6,0,6,4,4,4,4,2,5,2,5,5,5,5,5 ; 9
|
|
.byte 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4 ; A
|
|
.byte 0,6,0,6,4,4,4,4,2,5,2,5,5,5,5,5 ; B
|
|
.byte 2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6 ; C
|
|
.byte 0,6,0,8,4,4,6,6,2,5,2,7,5,5,7,7 ; D
|
|
.byte 2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6 ; E
|
|
.byte 0,6,0,8,4,4,6,6,2,5,2,7,5,5,7,7 ; F
|