Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MIPS delay slot codegen issue #91442

Closed
sajattack opened this issue Dec 2, 2021 · 5 comments
Closed

MIPS delay slot codegen issue #91442

sajattack opened this issue Dec 2, 2021 · 5 comments
Labels
A-codegen Area: Code generation C-bug Category: This is a bug. O-MIPS Target: MIPS processors

Comments

@sajattack
Copy link
Contributor

sajattack commented Dec 2, 2021

I tried this code:

#![no_std]
#![no_main]

#![feature(bench_black_box)]

psp::module!("crash-test",1,0);


fn psp_main() {
    psp::enable_home_button();
    let start_x = core::hint::black_box(942.0);
    let end_x = core::hint::black_box(942.0);
    let start_y = core::hint::black_box(1121.0);
    let end_y = core::hint::black_box(1127.0);
    let dx = end_x - start_x;
    let dy = end_y - start_y;
    let tdx = if dx == 0.0 {
        core::f32::MAX
    } else {
        1.0 / dx
    };
    let tdy = 1.0 / dy;
    psp::dprintln!("{}, {}", tdx, tdy);
}

and compiled with the official tier 3 target, mipsel-sony-psp, the psp crate, and the cargo-psp crate. This should compile for any other mips target by renaming psp_main to main, removing #[no_main], removing psp::enable_home_button, removing psp::module! and replacing psp::dprintln!with println!. I suspect the problem would be the same on other MIPS targets, PSP is MIPS2 ISA.

I expected to see this happen: The if statement should prevent the case of divide by zero

Instead, this happened: The division instruction is scheduled in the delay slot of the jump (2b0), rendering the if statement useless. This leads to a floating point exception for dividing by zero.

000001f0 <_ZN10crash_test8psp_main17hbe49ea7b35c4c2efE>:
     1f0:	27bdffa8 	addiu	sp,sp,-88
     1f4:	e7b50054 	swc1	$f21,84(sp)
     1f8:	e7b40050 	swc1	$f20,80(sp)
     1fc:	afbf004c 	sw	ra,76(sp)
     200:	0c006627 	jal	1989c <_ZN3psp18enable_home_button17h2bfc525e5943e058E>
     204:	00000000 	nop
     208:	3c01446b 	lui	at,0x446b
     20c:	27a20030 	addiu	v0,sp,48
     210:	3c034091 	lui	v1,0x4091
     214:	34218000 	ori	at,at,0x8000
     218:	34648400 	ori	a0,v1,0x8400
     21c:	34639c00 	ori	v1,v1,0x9c00
     220:	afa10030 	sw	at,48(sp)
     224:	c7b40030 	lwc1	$f20,48(sp)
     228:	afa10030 	sw	at,48(sp)
     22c:	afa40034 	sw	a0,52(sp)
     230:	c7b50030 	lwc1	$f21,48(sp)
     234:	afa00030 	sw	zero,48(sp)
     238:	8fa70034 	lw	a3,52(sp)
     23c:	8fa60030 	lw	a2,48(sp)
     240:	afa30034 	sw	v1,52(sp)
     244:	afa00030 	sw	zero,48(sp)
     248:	8fa40030 	lw	a0,48(sp)
     24c:	0c01afad 	jal	6beb4 <__subdf3>
     250:	8fa50034 	lw	a1,52(sp)
     254:	00403025 	move	a2,v0
     258:	00603825 	move	a3,v1
     25c:	24040000 	li	a0,0
     260:	0c01ae9d 	jal	6ba74 <__divdf3>
     264:	3c053ff0 	lui	a1,0x3ff0
     268:	4614a801 	sub.s	$f0,$f21,$f20
     26c:	44800800 	mtc1	zero,$f1
     270:	3c050006 	lui	a1,0x6
     274:	3c010009 	lui	at,0x9
     278:	3c040006 	lui	a0,0x6
     27c:	27a70014 	addiu	a3,sp,20
     280:	27a90018 	addiu	t1,sp,24
     284:	27aa0020 	addiu	t2,sp,32
     288:	240b0002 	li	t3,2
     28c:	2486592c 	addiu	a2,a0,22828
     290:	24a556e8 	addiu	a1,a1,22248
     294:	24285c54 	addiu	t0,at,23636
     298:	46010032 	c.eq.s	$f0,$f1
     29c:	45010005 	bc1t	2b4 <_ZN10crash_test8psp_main17hbe49ea7b35c4c2efE+0xc4>
     2a0:	27a40030 	addiu	a0,sp,48
     2a4:	3c010009 	lui	at,0x9
     2a8:	c4215b00 	lwc1	$f1,23296(at)
     2ac:	080000af 	j	2bc <_ZN10crash_test8psp_main17hbe49ea7b35c4c2efE+0xcc>
     2b0:	46000803 	div.s	$f0,$f1,$f0
     2b4:	3c010009 	lui	at,0x9
     2b8:	c4205bbc 	lwc1	$f0,23484(at)
     2bc:	afab0044 	sw	t3,68(sp)
     2c0:	afaa0040 	sw	t2,64(sp)
     2c4:	afab0034 	sw	t3,52(sp)
     2c8:	afa80030 	sw	t0,48(sp)
     2cc:	afa6002c 	sw	a2,44(sp)
     2d0:	afa90028 	sw	t1,40(sp)
     2d4:	afa50024 	sw	a1,36(sp)
     2d8:	e7a00014 	swc1	$f0,20(sp)
     2dc:	afa3001c 	sw	v1,28(sp)
     2e0:	afa20018 	sw	v0,24(sp)
     2e4:	afa70020 	sw	a3,32(sp)
     2e8:	0c0062ac 	jal	18ab0 <_ZN3psp5debug10print_args17ha66f43044fc9cba7E>
     2ec:	afa00038 	sw	zero,56(sp)
     2f0:	3c010009 	lui	at,0x9
     2f4:	3c020009 	lui	v0,0x9
     2f8:	27a40030 	addiu	a0,sp,48
     2fc:	24030001 	li	v1,1
     300:	24215c50 	addiu	at,at,23632
     304:	24425c68 	addiu	v0,v0,23656
     308:	afa10040 	sw	at,64(sp)
     30c:	afa30034 	sw	v1,52(sp)
     310:	afa20030 	sw	v0,48(sp)
     314:	afa00044 	sw	zero,68(sp)
     318:	0c0062ac 	jal	18ab0 <_ZN3psp5debug10print_args17ha66f43044fc9cba7E>
     31c:	afa00038 	sw	zero,56(sp)
     320:	8fbf004c 	lw	ra,76(sp)
     324:	c7b40050 	lwc1	$f20,80(sp)
     328:	c7b50054 	lwc1	$f21,84(sp)
     32c:	03e00008 	jr	ra
     330:	27bd0058 	addiu	sp,sp,88
     334:	04170001 	0x4170001
     338:	04170001 	0x4170001
     33c:	04170001 	0x4170001

Meta

rustc --version --verbose:

rustc 1.58.0-nightly (936238a92 2021-11-11)
binary: rustc
commit-hash: 936238a92b2f9d6e7afe7dda69b4afd903f96399
commit-date: 2021-11-11
host: x86_64-unknown-linux-gnu
release: 1.58.0-nightly
LLVM version: 13.0.0

I used gdb for backtrace since I can't run RUST_BACKTRACE=1 on PSP.

Backtrace

(gdb) continue
Continuing.

Program received signal SIGFPE, Arithmetic exception.
[Switching to Thread 71772003]
0x0881050c in psp_main () at src/main.rs:17
17	src/main.rs: No such file or directory.
(gdb) bt
#0  0x0881050c in psp_main () at src/main.rs:17
#1  {closure#0} () at /home/paul/.cargo/registry/src/git.luolix.top-1ecc6299db9ec823/psp-0.1.6/src/lib.rs:168
#2  do_call<crash_test::__psp_module::module_start::main_thread::{closure#0}, ()> (data=<optimized out>)
    at /home/paul/.cargo/registry/src/git.luolix.top-1ecc6299db9ec823/psp-0.1.6/src/panic.rs:190
#3  psp::panic::catch_unwind::hd7cc0a6d600ad95e (f=...) at /home/paul/.cargo/registry/src/git.luolix.top-1ecc6299db9ec823/psp-0.1.6/src/panic.rs:170
#4  0x0881061c in crash_test::__psp_module::module_start::main_thread::ha12ba2af7e504b63 (_argc=<optimized out>, _argv=<optimized out>)
    at /home/paul/.cargo/registry/src/git.luolix.top-1ecc6299db9ec823/psp-0.1.6/src/lib.rs:167
#5  0x0bebfec0 in ?? ()
Exception - FPU Exception (UZ)
Load/Start host0:/crash-test.prx UID: 0x0449B23F Name: crash-test
Thread ID - 0x0447734B
host0:/> Th Name   - main_thread
Module ID - 0x0449B23F
Mod Name  - crash-test
EPC       - 0x0881050C
Cause     - 0x9000003C
BadVAddr  - 0xBE261F31
Status    - 0x20088613
Address   - 0x0000050C
zr:0x00000000 at:0x088A0000 v0:0x55555555 v1:0x3FC55555
a0:0x0BEBFE78 a1:0x088756E8 a2:0x0887592C a3:0x0BEBFE60
t0:0x088A5C54 t1:0x0BEBFE5C t2:0x0BEBFE68 t3:0x00000002
t4:0x00000000 t5:0x55400000 t6:0x55555555 t7:0x00155555
s0:0xDEADBEEF s1:0xDEADBEEF s2:0xDEADBEEF s3:0xDEADBEEF
s4:0xDEADBEEF s5:0xDEADBEEF s6:0xDEADBEEF s7:0xDEADBEEF
t8:0x00000000 t9:0x00000000 k0:0x0BEBFF00 k1:0x00000000
gp:0x00155555 sp:0x0BEBFE48 fp:0x0BEBFEC0 ra:0x088104C8
0x0881050C: 0x0A204147 'GA .' - j          0x0881051C

@sajattack sajattack added the C-bug Category: This is a bug. label Dec 2, 2021
@sajattack
Copy link
Contributor Author

@rustbot label: +O-mips

@rustbot rustbot added the O-MIPS Target: MIPS processors label Dec 2, 2021
@sajattack
Copy link
Contributor Author

@rustbot label: +A-codegen

@rustbot rustbot added the A-codegen Area: Code generation label Dec 2, 2021
@sajattack
Copy link
Contributor Author

Simplified example:

#![no_std]
#![no_main]

#![feature(bench_black_box)]

psp::module!("crash-test",1,0);


fn psp_main() {
    let dx = core::hint::black_box(0.0); 
    let tdx = do_calc(dx);
    psp::dprintln!("{}", tdx);
}

#[no_mangle]
#[inline(never)]
fn do_calc(dx: f32) -> f32 {
    if dx == 0.0 {
        core::f32::MAX
    } else {
        1.0 / dx
    }
}
000001cc <do_calc>:
     1cc:       44800000        mtc1    zero,$f0
     1d0:       46006032        c.eq.s  $f12,$f0
     1d4:       45010005        bc1t    1ec <do_calc+0x20>
     1d8:       00000000        nop
     1dc:       3c010009        lui     at,0x9
     1e0:       c42058f0        lwc1    $f0,22768(at)
     1e4:       03e00008        jr      ra
     1e8:       460c0003        div.s   $f0,$f0,$f12
     1ec:       3c010009        lui     at,0x9
     1f0:       c42059ac        lwc1    $f0,22956(at)
     1f4:       03e00008        jr      ra
     1f8:       00000000        nop
     1fc:       04170001        0x4170001

@sajattack
Copy link
Contributor Author

Nevermind, this appears to be a possible problem with the FPU of the PSP doing the comparison to 0, combined with my dodgy understanding of MIPS assembly.

@sajattack
Copy link
Contributor Author

sajattack commented Dec 3, 2021

Followup: The real problem is that MIPS revs <=3 have delay slots for floating point comparison instructions, (such as c.eq.s), and LLVM does not appear to have accounted for this.

Sources:
https://gcc.gnu.org/legacy-ml/gcc-patches/2003-05/msg01601.html
https://gcc.gnu.org/legacy-ml/gcc-patches/2003-05/msg01605.html
https://github.com/gcc-mirror/gcc/blob/16e2427f50c208dfe07d07f18009969502c25dc8/gcc/config/mips/mips.h#L1282
See MIPS Run Textbook:
2021-12-02-201241_332x62_scrot
MIPS R4000 Manual:
2021-12-02-202302_854x497_scrot

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-codegen Area: Code generation C-bug Category: This is a bug. O-MIPS Target: MIPS processors
Projects
None yet
Development

No branches or pull requests

2 participants