ps2toolchain
ps2toolchain copied to clipboard
Assembler - Instructions div/divu expand into macros without means of disabling them
When compiling assembly .s files which contain division instructions (div/divu), these instructions expand into multiple instructions which check if the divisor is 0, or (for div) if the divisor is -1 and the dividend is INT_MIN.
There seems to be no means of disabling this macro if unwanted, however. Command line arguments -mno-check-zero-division, --no-break, --no-trap, appear to have no effect on the compiled output.
I'll need a little more information to be able to help and reproduce the issue. Can you provide:
- example code (few lines)
- commands used to compile
- commands used to decompile
- expected result
- received result
Hints:
- Are you using .S or .s ?
- Are you using gcc or as ?
I am using .s files and using ee-gcc to assemble. The issue can be replicated with an input file containing text such as
.text
.global main
.set noreorder
.set noat
main:
div $v0, $v0
jr $ra
nop
When assembled with
ee-gcc input.s -mno-check-zero-division
I expect the main subroutine to compile into
main:
div $v0, $v0
jr $ra
nop
While the actual result is:
main:
bnez $v0, L1
div $v0, $v0
break 7
L1:
dli $at, -1
bne $v0, $at, L2
lui $at, 0x8000
bne $v0, $at, L2
nop
break 6
L2:
mflo $v0
jr $ra
nop
The behaviour is strage, but there's a solution. The ps2's DIV instruction has only 2 operands and places the result in the HI/LO register. However, binutils will always want to see 3 operands, so we have to use $0 as the third operand.
You'll have to get the result out of the LO register with mflo $2.
So:
main:
div $0, $v0, $v0
mflo $2
jr $ra
Should work. Don't add the NOP so binutils can optimize the branch delay slot, so the end result woll look like:
main:
div $0, $v0, $v0
jr $ra
mflo $2
That does work as a workaround to the issue, thank you. Certainly a lot easier than writing it out using a .byte directive.
I think it's also worth nothing that this behavior does not apply to div1 and divu1; checking division arguments and mflo only occurs for div/divu.