diff options
author | Martin Reindl <martin@cvs.openbsd.org> | 2004-11-30 01:44:23 +0000 |
---|---|---|
committer | Martin Reindl <martin@cvs.openbsd.org> | 2004-11-30 01:44:23 +0000 |
commit | 9fb0a99025af567ab4c0b08fae9d1dea2ba98a44 (patch) | |
tree | 4de7d893c72a1615b483393ddb1aabb6323889e2 /sys | |
parent | 3fca817cbc05076038d7e138301275202aed2fc1 (diff) |
provide a more accurate assembly delay() routine
ok miod@
>From: NetBSD
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/mac68k/mac68k/clock.c | 61 | ||||
-rw-r--r-- | sys/arch/mac68k/mac68k/locore.s | 47 |
2 files changed, 57 insertions, 51 deletions
diff --git a/sys/arch/mac68k/mac68k/clock.c b/sys/arch/mac68k/mac68k/clock.c index b8e7eeefeb8..9971328f047 100644 --- a/sys/arch/mac68k/mac68k/clock.c +++ b/sys/arch/mac68k/mac68k/clock.c @@ -1,5 +1,5 @@ -/* $OpenBSD: clock.c,v 1.17 2004/11/26 21:21:28 miod Exp $ */ -/* $NetBSD: clock.c,v 1.36 1997/10/07 03:04:55 scottr Exp $ */ +/* $OpenBSD: clock.c,v 1.18 2004/11/30 01:44:22 martin Exp $ */ +/* $NetBSD: clock.c,v 1.39 1999/11/05 19:14:56 scottr Exp $ */ /* * Copyright (c) 1988 University of Utah. @@ -408,6 +408,8 @@ resettodr() "to the PRAM on this system.\n"); #endif } + + /* * The Macintosh timers decrement once every 1.2766 microseconds. * MGFH2, p. 180 @@ -415,55 +417,11 @@ resettodr() #define CLK_RATE 12766 #define DELAY_CALIBRATE (0xffffff << 7) /* Large value for calibration */ -#define LARGE_DELAY 0x40000 /* About 335 msec */ u_int delay_factor = DELAY_CALIBRATE; volatile int delay_flag = 1; -/* - * delay(usec) - * Delay usec microseconds. - * - * The delay_factor is scaled up by a factor of 128 to avoid loss - * of precision for small delays. As a result of this, note that - * delays larger that LARGE_DELAY will be up to 128 usec too short, - * due to adjustments for calculations involving 32 bit values. - */ -void -delay(usec) - unsigned usec; -{ - volatile unsigned int cycles; - - if (usec > LARGE_DELAY) - cycles = (usec >> 7) * delay_factor; - else - cycles = ((usec > 0 ? usec : 1) * delay_factor) >> 7; - - while ((cycles-- > 0) && delay_flag); -} - -static unsigned dummy_delay(unsigned); -/* - * Dummy delay calibration. Functionally identical to delay(), but - * returns the number of times through the loop. - */ -static unsigned -dummy_delay(usec) - unsigned usec; -{ - volatile unsigned int cycles; - - if (usec > LARGE_DELAY) - cycles = (usec >> 7) * delay_factor; - else - cycles = ((usec > 0 ? usec : 1) * delay_factor) >> 7; - - while ((cycles-- > 0) && delay_flag); - - return ((delay_factor >> 7) - cycles); -} - +int _delay(u_int); static int delay_timer1_irq(void *); static int @@ -480,8 +438,9 @@ delay_timer1_irq(dummy) void mac68k_calibrate_delay() { - int n; - unsigned sum; + u_int sum, n; + + (void)spl0(); /* Disable VIA1 timer 1 interrupts and set up service routine */ via_reg(VIA1, vIER) = V1IF_T1; @@ -501,7 +460,7 @@ mac68k_calibrate_delay() delay_flag = 1; via_reg(VIA1, vT1C) = 0; /* 1024 clock ticks */ via_reg(VIA1, vT1CH) = 4; /* (approx 1.3 msec) */ - sum += dummy_delay(1); + sum += ((delay_factor >> 7) - _delay(1)); } /* Disable timer interrupts and reset service routine */ @@ -533,4 +492,6 @@ mac68k_calibrate_delay() if (clock_debug) printf("mac68k_calibrate_delay(): delay_factor calibrated\n"); #endif + + (void)splhigh(); } diff --git a/sys/arch/mac68k/mac68k/locore.s b/sys/arch/mac68k/mac68k/locore.s index b49530ff836..762c40d819c 100644 --- a/sys/arch/mac68k/mac68k/locore.s +++ b/sys/arch/mac68k/mac68k/locore.s @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.s,v 1.38 2004/11/27 14:26:32 miod Exp $ */ +/* $OpenBSD: locore.s,v 1.39 2004/11/30 01:44:22 martin Exp $ */ /* $NetBSD: locore.s,v 1.103 1998/07/09 06:02:50 scottr Exp $ */ /* @@ -1506,6 +1506,51 @@ Lm68881rdone: rts /* + * delay() - delay for a specified number of microseconds + * _delay() - calibrator helper for delay() + * + * Notice that delay_factor is scaled up by a factor of 128 to avoid loss + * of precision for small delays. As a result of this we need to avoid + * overflow. + * + * The branch target for the loops must be aligned on a half-line (8-byte) + * boundary to minimize cache effects. This guarantees both that there + * will be no prefetch stalls due to cache line burst operations and that + * the loops will run from a single cache half-line. + */ + .align 8 | align to half-line boundary + +ALTENTRY(_delay, _delay) +ENTRY(delay) + movl sp@(4),d0 | get microseconds to delay + cmpl #0x40000,d0 | is it a "large" delay? + bls Ldelayshort | no, normal calculation + movql #0x7f,d1 | adjust for scaled multipler (to + addl d1,d0 | avoid overflow) + lsrl #7,d0 + mulul _C_LABEL(delay_factor),d0 | calculate number of loop iterations + bra Ldelaysetup | go do it! +Ldelayshort: + mulul _C_LABEL(delay_factor),d0 | calculate number of loop iterations + lsrl #7,d0 | adjust for scaled multiplier +Ldelaysetup: + jeq Ldelayexit | bail out if nothing to do + movql #0,d1 | put bits 15-0 in d1 for the + movw d0,d1 | inner loop, and move bits + movw #0,d0 | 31-16 to the low-order word + subql #1,d1 | of d0 for the outer loop + swap d0 +Ldelay: + tstl _C_LABEL(delay_flag) | this never changes for delay()! + dbeq d1,Ldelay | (used only for timing purposes) + dbeq d0,Ldelay + addqw #1,d1 | adjust end count and + swap d0 | return the longword result + orl d1,d0 +Ldelayexit: + rts + +/* * Handle the nitty-gritty of rebooting the machine. * Basically we just turn off the MMU and jump to the appropriate ROM routine. * Note that we must be running in an address range that is mapped one-to-one |