Subject: mc_cpuspeed() returns wrong value on gcc3
To: None <port-mips@netbsd.org>
From: Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
List: port-pmax
Date: 04/29/2004 14:58:09
pmax (and maybe some other mips ports) use mc_cpuspeed() and
mips_mcclock_tickloop() in mips_mccloc.c to determine their CPU clock,
but after gcc3 import mips_mcclock_tickloop() returns smaller values
at least on DECstation 5000/125.

In article <031223212041.M0103669@mirage.ceres.dti.ne.jp> on port-pmax
I wrote:

> BTW, I think mc_cpuspeed() in arch/mips/mips/mips_mcclock.c also
> might have some problem with gcc3. Kernels compiled by gcc3
> detect machine clock incorrectly on my 3MIN (5000/125):
> 
> >> NetBSD 1.6ZD (PROUDIA) #29: Sun Oct 26 15:12:26 JST 2003
> >>        tsutsui@mirage:/usr/src/sys/arch/pmax/compile/PROUDIA
> >> DECstation 5000/125 (3MIN)
> >> total memory = 98304 KB
> >> avail memory = 87980 KB
> 
> >> NetBSD 1.6ZE (PROUDIA) #30: Mon Oct 27 02:03:15 JST 2003
> >>        tsutsui@mirage:/usr/src/sys/arch/pmax/compile/PROUDIA
> >> DECstation 5000/120 (3MIN)
> >> total memory = 98304 KB
> >> avail memory = 88068 KB

The following iteration code is used to measure CPU clock
in mips_mcclock_tickloop():
---
	while ((mips_cp0_cause_read() & clockmask) == 0) {
		__asm __volatile ("nop; nop; nop; nop");
		iters++;
	}
---

gcc-2.95.3 generates:
---
	j	2f
	 nop
1:	nop					# __asm __volatile (nop; ...);
	nop
	nop
	nop
	addiu	s0, s0, 1			# iters++;
2:	jal	_C_LABEL(mips_cp0_cause_read)	# v0 = mips_cp0_cause_read();
	 nop
	and	v0, v0, s1			# v0 & clockmask
	beqz	v0, 1b				# if zero then repeat
	 move	v0, s0				# for return (iters);

	j	3f
	 nop
	[...]
3:
---
In this case each iteration contains 10 instructions.

but gcc-3.3.3 generates deferent code:
---
1:	jal	_C_LABEL(mips_cp0_cause_read)	# v0 = mips_cp0_cause_read();
	 nop
	and	v0, v0, s0			# v0 & clockmask
	bnez	v0, 2f				# if !zero then break
	 nop
	nop					# __asm __volatile (nop; ...);
	nop
	nop
	nop
	j	1b
	 addiu	s1, s1, 1			# iters++;
2:	[...]
---
Each loop contains 11 instructions so it returns different iters
from the previous one.

An easy fix is to remove one dummy nop from __asm lines,
but I guess such code should not depend on compiler and
should be written in asm.

Is there anyone to rewrite these code properly?
(sorry, I'm not a mips guy...)
---
Izumi Tsutsui
tsutsui@ceres.dti.ne.jp