19682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* File "FastTimes.c" - Original code by Matt Slot <fprefect@ambrosiasw.com> */ 29682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Created 4/24/99 - This file is hereby placed in the public domain */ 39682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Updated 5/21/99 - Calibrate to VIA, add TBR support, renamed functions */ 49682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Updated 10/4/99 - Use AbsoluteToNanoseconds() in case Absolute = double */ 59682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Updated 2/15/00 - Check for native Time Manager, no need to calibrate */ 69682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Updated 2/19/00 - Fixed default value for gScale under native Time Mgr */ 79682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Updated 3/21/00 - Fixed ns conversion, create 2 different scale factors */ 89682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Updated 5/03/00 - Added copyright and placed into PD. No code changes */ 99682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Updated 8/01/00 - Made "Carbon-compatible" by replacing LMGetTicks() */ 109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* This file is Copyright (C) Matt Slot, 1999-2012. It is hereby placed into 129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall the public domain. The author makes no warranty as to fitness or stability */ 139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <Gestalt.h> 159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <LowMem.h> 169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <CodeFragments.h> 179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <DriverServices.h> 189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <Timer.h> 199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "FastTimes.h" 219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef TARGET_CPU_PPC 239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#undef GENERATINGPOWERPC /* stop whining */ 249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define GENERATINGPOWERPC TARGET_CPU_PPC 259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif 269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ 289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ 299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* 309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall On 680x0 machines, we just use Microseconds(). 319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall On PowerPC machines, we try several methods: 339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * DriverServicesLib is available on all PCI PowerMacs, and perhaps 349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall some NuBus PowerMacs. If it is, we use UpTime() : Overhead = 2.1 �sec. 359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * The PowerPC 601 has a built-in "real time clock" RTC, and we fall 369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall back to that, accessing it directly from asm. Overhead = 1.3 �sec. 379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * Later PowerPCs have an accurate "time base register" TBR, and we 389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall fall back to that, access it from PowerPC asm. Overhead = 1.3 �sec. 399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * We can also try Microseconds() which is emulated : Overhead = 36 �sec. 409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall On PowerPC machines, we avoid the following: 429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * OpenTransport is available on all PCI and some NuBus PowerMacs, but it 439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall uses UpTime() if available and falls back to Microseconds() otherwise. 449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * InputSprocket is available on many PowerMacs, but again it uses 459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall UpTime() if available and falls back to Microseconds() otherwise. 469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall Another PowerPC note: certain configurations, especially 3rd party upgrade 489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall cards, may return inaccurate timings for the CPU or memory bus -- causing 499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall skew in various system routines (up to 20% drift!). The VIA chip is very 509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall accurate, and it's the basis for the Time Manager and Microseconds(). 519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall Unfortunately, it's also very slow because the MacOS has to (a) switch to 529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 68K and (b) poll for a VIA event. 539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall We compensate for the drift by calibrating a floating point scale factor 559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall between our fast method and the accurate timer at startup, then convert 569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall each sample quickly on the fly. I'd rather not have the initialization 579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall overhead -- but it's simply necessary for accurate timing. You can drop 589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall it down to 30 ticks if you prefer, but that's as low as I'd recommend. 599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall Under MacOS 9, "new world" Macs (iMacs, B+W G3s and G+W G4s) have a native 619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall Time Manager implementation: UpTime(), Microseconds(), and TickCount() are 629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall all based on the same underlying counter. This makes it silly to calibrate 639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall UpTime() against TickCount(). We now check for this feature using Gestalt(), 649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall and skip the whole calibration step if possible. 659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/ 679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ 689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ 699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define RTCToNano(w) ((double) (w).hi * 1000000000.0 + (double) (w).lo) 719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define WideTo64bit(w) (*(UInt64 *) &(w)) 729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* LMGetTicks() is not in Carbon and TickCount() has a fair bit of overhead, 749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall so for speed we always read lowmem directly. This is a Mac OS X no-no, but 759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall it always work on those systems that don't have a native Time Manager (ie, 769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall anything before MacOS 9) -- regardless whether we are in Carbon or not! */ 779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MyLMGetTicks() (*(volatile UInt32 *) 0x16A) 789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if GENERATINGPOWERPC 809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic asm UnsignedWide PollRTC(void); 829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic asm UnsignedWide PollTBR(void); 839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic Ptr FindFunctionInSharedLib(StringPtr libName, StringPtr funcName); 849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic Boolean gInited = false; 869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic Boolean gNative = false; 879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic Boolean gUseRTC = false; 889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic Boolean gUseTBR = false; 899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic double gScaleUSec = 1.0 / 1000.0; /* 1 / ( nsec / usec) */ 909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic double gScaleMSec = 1.0 / 1000000.0; /* 1 / ( nsec / msec) */ 919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Functions loaded from DriverServicesLib */ 939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Halltypedef AbsoluteTime (*UpTimeProcPtr)(void); 949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Halltypedef Nanoseconds (*A2NSProcPtr)(AbsoluteTime); 959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic UpTimeProcPtr gUpTime = NULL; 969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic A2NSProcPtr gA2NS = NULL; 979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* GENERATINGPOWERPC */ 999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ 1019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ 1029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid FastInitialize() { 1049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall SInt32 result; 1059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall if (!gInited) { 1079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if GENERATINGPOWERPC 1099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* Initialize the feature flags */ 1119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall gNative = gUseRTC = gUseTBR = false; 1129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* We use CFM to find and load needed symbols from shared libraries, so 1149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall the application doesn't have to weak-link them, for convenience. */ 1159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall gUpTime = (UpTimeProcPtr) FindFunctionInSharedLib( 1169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall "\pDriverServicesLib", "\pUpTime"); 1179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall if (gUpTime) gA2NS = (A2NSProcPtr) FindFunctionInSharedLib( 1189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall "\pDriverServicesLib", "\pAbsoluteToNanoseconds"); 1199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall if (!gA2NS) gUpTime = nil; /* Pedantic but necessary */ 1209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall if (gUpTime) { 1229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* If we loaded UpTime(), then we need to know if the system has 1239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall a native implementation of the Time Manager. If so, then it's 1249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall pointless to calculate a scale factor against the missing VIA */ 1259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* gestaltNativeTimeMgr = 4 in some future version of the headers */ 1279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall if (!Gestalt(gestaltTimeMgrVersion, &result) && 1289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall (result > gestaltExtendedTimeMgr)) 1299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall gNative = true; 1309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 1319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall else { 1329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* If no DriverServicesLib, use Gestalt() to get the processor type. 1339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall Only NuBus PowerMacs with old System Software won't have DSL, so 1349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall we know it should either be a 601 or 603. */ 1359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* Use the processor gestalt to determine which register to use */ 1379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall if (!Gestalt(gestaltNativeCPUtype, &result)) { 1389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall if (result == gestaltCPU601) gUseRTC = true; 1399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall else if (result > gestaltCPU601) gUseTBR = true; 1409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 1419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 1429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* Now calculate a scale factor to keep us accurate. */ 1449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall if ((gUpTime && !gNative) || gUseRTC || gUseTBR) { 1459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall UInt64 tick, usec1, usec2; 1469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall UnsignedWide wide; 1479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* Wait for the beginning of the very next tick */ 1499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall for(tick = MyLMGetTicks() + 1; tick > MyLMGetTicks(); ); 1509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* Poll the selected timer and prepare it (since we have time) */ 1529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall wide = (gUpTime) ? (*gA2NS)((*gUpTime)()) : 1539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall ((gUseRTC) ? PollRTC() : PollTBR()); 1549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall usec1 = (gUseRTC) ? RTCToNano(wide) : WideTo64bit(wide); 1559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* Wait for the exact 60th tick to roll over */ 1579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall while(tick + 60 > MyLMGetTicks()); 1589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* Poll the selected timer again and prepare it */ 1609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall wide = (gUpTime) ? (*gA2NS)((*gUpTime)()) : 1619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall ((gUseRTC) ? PollRTC() : PollTBR()); 1629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall usec2 = (gUseRTC) ? RTCToNano(wide) : WideTo64bit(wide); 1639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* Calculate a scale value that will give microseconds per second. 1659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall Remember, there are actually 60.15 ticks in a second, not 60. */ 1669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall gScaleUSec = (60.0 * 1000000.0) / ((usec2 - usec1) * 60.15); 1679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall gScaleMSec = gScaleUSec / 1000.0; 1689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 1699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* GENERATINGPOWERPC */ 1719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* We've initialized our globals */ 1739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall gInited = true; 1749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 1759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 1769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ 1789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ 1799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallUInt64 FastMicroseconds() { 1819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall UnsignedWide wide; 1829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall UInt64 usec; 1839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if GENERATINGPOWERPC 1859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* Initialize globals the first time we are called */ 1869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall if (!gInited) FastInitialize(); 1879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 1889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall if (gNative) { 1899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* Use DriverServices if it's available -- it's fast and compatible */ 1909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall wide = (*gA2NS)((*gUpTime)()); 1919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall usec = (double) WideTo64bit(wide) * gScaleUSec + 0.5; 1929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 1939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall else if (gUpTime) { 1949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* Use DriverServices if it's available -- it's fast and compatible */ 1959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall wide = (*gA2NS)((*gUpTime)()); 1969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall usec = (double) WideTo64bit(wide) * gScaleUSec + 0.5; 1979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 1989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall else if (gUseTBR) { 1999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* On a recent PowerPC, we poll the TBR directly */ 2009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall wide = PollTBR(); 2019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall usec = (double) WideTo64bit(wide) * gScaleUSec + 0.5; 2029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 2039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall else if (gUseRTC) { 2049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* On a 601, we can poll the RTC instead */ 2059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall wide = PollRTC(); 2069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall usec = (double) RTCToNano(wide) * gScaleUSec + 0.5; 2079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 2089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall else 2099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* GENERATINGPOWERPC */ 2109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall { 2119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* If all else fails, suffer the mixed mode overhead */ 2129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall Microseconds(&wide); 2139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall usec = WideTo64bit(wide); 2149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 2159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 2169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall return(usec); 2179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 2189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 2199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ 2209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ 2219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 2229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallUInt64 FastMilliseconds() { 2239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall UnsignedWide wide; 2249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall UInt64 msec; 2259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 2269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if GENERATINGPOWERPC 2279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* Initialize globals the first time we are called */ 2289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall if (!gInited) FastInitialize(); 2299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 2309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall if (gNative) { 2319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* Use DriverServices if it's available -- it's fast and compatible */ 2329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall wide = (*gA2NS)((*gUpTime)()); 2339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall msec = (double) WideTo64bit(wide) * gScaleMSec + 0.5; 2349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 2359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall else if (gUpTime) { 2369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* Use DriverServices if it's available -- it's fast and compatible */ 2379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall wide = (*gA2NS)((*gUpTime)()); 2389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall msec = (double) WideTo64bit(wide) * gScaleMSec + 0.5; 2399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 2409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall else if (gUseTBR) { 2419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* On a recent PowerPC, we poll the TBR directly */ 2429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall wide = PollTBR(); 2439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall msec = (double) WideTo64bit(wide) * gScaleMSec + 0.5; 2449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 2459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall else if (gUseRTC) { 2469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* On a 601, we can poll the RTC instead */ 2479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall wide = PollRTC(); 2489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall msec = (double) RTCToNano(wide) * gScaleMSec + 0.5; 2499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 2509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall else 2519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* GENERATINGPOWERPC */ 2529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall { 2539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* If all else fails, suffer the mixed mode overhead */ 2549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall Microseconds(&wide); 2559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall msec = ((double) WideTo64bit(wide) + 500.0) / 1000.0; 2569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 2579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 2589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall return(msec); 2599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 2609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 2619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ 2629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ 2639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 2649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallStringPtr FastMethod() { 2659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall StringPtr method = "\p<Unknown>"; 2669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 2679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if GENERATINGPOWERPC 2689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* Initialize globals the first time we are called */ 2699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall if (!gInited) FastInitialize(); 2709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 2719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall if (gNative) { 2729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* The Time Manager and UpTime() are entirely native on this machine */ 2739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall method = "\pNative UpTime()"; 2749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 2759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall else if (gUpTime) { 2769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* Use DriverServices if it's available -- it's fast and compatible */ 2779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall method = "\pUpTime()"; 2789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 2799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall else if (gUseTBR) { 2809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* On a recent PowerPC, we poll the TBR directly */ 2819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall method = "\pPowerPC TBR"; 2829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 2839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall else if (gUseRTC) { 2849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* On a 601, we can poll the RTC instead */ 2859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall method = "\pPowerPC RTC"; 2869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 2879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall else 2889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* GENERATINGPOWERPC */ 2899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall { 2909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* If all else fails, suffer the mixed mode overhead */ 2919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall method = "\pMicroseconds()"; 2929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 2939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 2949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall return(method); 2959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 2969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 2979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ 2989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ 2999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#pragma mark - 3009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 3019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if GENERATINGPOWERPC 3029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallasm static UnsignedWide PollRTC_() { 3039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallentry PollRTC /* Avoid CodeWarrior glue */ 3049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall machine 601 3059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall@AGAIN: 3069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall mfrtcu r4 /* RTCU = SPR 4 */ 3079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall mfrtcl r5 /* RTCL = SPR 5 */ 3089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall mfrtcu r6 3099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall cmpw r4,r6 3109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall bne @AGAIN 3119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall stw r4,0(r3) 3129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall stw r5,4(r3) 3139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall blr 3149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 3159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 3169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ 3179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ 3189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 3199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallasm static UnsignedWide PollTBR_() { 3209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallentry PollTBR /* Avoid CodeWarrior glue */ 3219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall machine 604 3229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall@AGAIN: 3239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall mftbu r4 /* TBRU = SPR 268 */ 3249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall mftb r5 /* TBRL = SPR 269 */ 3259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall mftbu r6 3269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall cmpw r4,r6 3279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall bne @AGAIN 3289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall stw r4,0(r3) 3299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall stw r5,4(r3) 3309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall blr 3319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 3329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 3339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ 3349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ 3359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 3369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic Ptr FindFunctionInSharedLib(StringPtr libName, StringPtr funcName) { 3379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall OSErr error = noErr; 3389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall Str255 errorStr; 3399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall Ptr func = NULL; 3409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall Ptr entry = NULL; 3419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall CFragSymbolClass symClass; 3429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall CFragConnectionID connID; 3439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 3449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall /* Find CFM containers for the current archecture -- CFM-PPC or CFM-68K */ 3459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall if (/* error = */ GetSharedLibrary(libName, kCompiledCFragArch, 3469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall kLoadCFrag, &connID, &entry, errorStr)) return(NULL); 3479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall if (/* error = */ FindSymbol(connID, funcName, &func, &symClass)) 3489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall return(NULL); 3499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 3509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall return(func); 3519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 3529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* GENERATINGPOWERPC */ 353