Here's the assembly code of my CD command function written in GNU assembler syntax:
Code: Select all
.set IOBASE, 0x1f80
.set CD_REG0, 0x1800
.set CD_REG1, 0x1801
.set CD_REG2, 0x1802
.set CD_REG3, 0x1803
StupidCdControl:
# a0 - Command value
# a1 - Arguments
# a2 - Pointer to result buffer
lui $v1, IOBASE
li $v0, 1 # Clear parameter FIFO
sb $v0, CD_REG0($v1)
li $v0, 0x40
sb $v0, CD_REG3($v1)
.cmd_wait: # Wait for CD to become ready to take commands
lbu $v0, CD_REG0($a1)
nop
andi $v0, 0x80
bnez $v0, .cmd_wait
nop
la $v0, _cd_busy # Set internal values
sw $a0, 0($v0)
la $v0, _cd_result_dest
sw $a2, 0($v0)
beqz $a1, .no_params
nop
beq $a0, 0x02, .setLoc_param
nop
beq $a0, 0x03, .play_param
nop
beq $a0, 0x0e, .setMode_param
nop
beq $a0, 0x14, .getTD_param
nop
b .no_params
nop
.setLoc_param:
b .do_params
li $a3, 0x03
.play_param:
b .do_params
li $a3, 0x01
.setMode_param:
b .do_params
li $a3, 0x02
.getTD_param:
li $a3, 0x01
sb $0 , CD_REG0($v1)
.do_params:
lbu $v0, 0($a1)
addi $a3, -1
sb $v0, CD_REG1($v1)
bgtz $a3, .do_params
addiu $a1, 1
.no_params:
sb $0 , CD_REG0($v1)
sb $a0, CD_REG1($v1)
.param_wait:
lbu $v0, CD_REG0($v1)
nop
and $v0, 0x8
beqz $v0, .param_wait
nop
jr $ra
nop
# Related to IRQ handler but that isn't really relevant to this issue
.comm _cd_busy,4,4
.comm _cd_result_dest,4,4