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