#ifndef _DEVPROFILE_H
#define _DEVPROFILE_H

/* Including this header is not sufficient. You must also define PROFILE */

#define PFDESCENDANTSx

/* badma.c */
#define PFbadma                 0
#define PFsweCloseLocalPkt          0+PFbadma
#define PFsweOpenLocalPkt           1+PFbadma
#define PFsweGarbageCollectChain        2+PFbadma
#define PFsweDumpChain              3+PFbadma
#define PFsweHandler                4+PFbadma
#define PFsweVSYNCHandler           5+PFbadma
#define PFsweTim1Handler            6+PFbadma
#define PF_sweOpen              7+PFbadma
#define PF_sweClose             8+PFbadma
#define PF_sweFlush             9+PFbadma
#define PF_sweFlushHid              10+PFbadma
#define PF_sweReqFlip               12+PFbadma
#define PF_sweWaitFlip              13+PFbadma
#define PF_sweAddPkt                14+PFbadma
#define PF_sweAppendPktToDispatchList       15+PFbadma
#define PF_sweAppendToChain         16+PFbadma
#define PF_sweAddCont               17+PFbadma
#define PF_sweAddPrim               18+PFbadma
#define PF_sweReadTimer             19+PFbadma
#define PF_sweFinaliseOpenLocalPkt      20+PFbadma
#define PF_sweProcrastinatedAddURef     21+PFbadma
#define PF_rwSkyWorldOverloadPipeline       22+PFbadma
#define PFsweFlushPURef             23+PFbadma

/* basky.c */
#define PFbasky                 24+PFbadma
#define PFinit_config_system            0+PFbasky
#define PF_rwSkyCamDevUVFromInst        1+PFbasky
#define PF_rwSkyDupeVertex          2+PFbasky
#define PF_rwSkyCamDevUVFromInstPolygon     3+PFbasky
#define PF_rwSkyCamDevColorFromInstPolygon  4+PFbasky
#define PF_rwSkyCamDevUVColorFromInstPolygon    5+PFbasky
#define PF_rwSkyPipeSetOverload         6+PFbasky
#define PFreplyBufferedAlphaPolys       7+PFbasky
#define PF_rwSkySetRenderState          8+PFbasky
#define PF_rwSkyGetRenderState          9+PFbasky
#define PF_rwSkyIm2DRenderLine          10+PFbasky
#define PF_rwSkyIm2DRenderTriangle      11+PFbasky
#define PF_rwSkyIm2DRenderPrimitive     12+PFbasky
#define PF_rwSkyIm2DRenderIndexedPrimitive  13+PFbasky
#define PF_rwSkyCull2DPerspTriangle     14+PFbasky
#define PF_rwSkySetClipAndCull          15+PFbasky
#define PF_rwSkyCameraBeginUpdate       16+PFbasky
#define PF_rwSkyCameraEndUpdate         17+PFbasky
#define PF_rwSkyCameraClear         18+PFbasky
#define PF_rwSkyRasterShowRaster        19+PFbasky
#define PF_rwSkyRGBToPixel          20+PFbasky
#define PF_rwSkyPixelToRGB          21+PFbasky
#define PF_rwSkyTextureSetRaster        22+PFbasky
#define PF_rwSkyFindMSB             23+PFbasky
#define PF_rwSkyGetRasterFormat         24+PFbasky
#define PF_rwSkyImageFindFormat         25+PFbasky
#define PF_rwSkyImageFindRasterFormat       26+PFbasky
#define PF_rwSkyRasterCreate            27+PFbasky
#define PF_rwSkyRasterSubRaster         28+PFbasky
#define PF_rwSkyRasterDestroy           29+PFbasky
#define PF_rwSkyRasterLock          30+PFbasky
#define PF_rwSkyRasterUnlock            31+PFbasky
#define PF_rwSkyRasterLockPalette       32+PFbasky
#define PF_rwSkyRasterUnlockPalette     33+PFbasky
#define PF_rwSkyImageGetRaster          34+PFbasky
#define PF_rwSkyRasterSetImage          35+PFbasky
#define PF_rwSkyHintRenderFront2Back        36+PFbasky
#define PF_rwSkyNoStandard          37+PFbasky
#define PF_rwSkySetStandards            38+PFbasky
#define PF_rwRenderPipelineInitDefaults     39+PFbasky
#define PFsetInitialRenderState         40+PFbasky
#define PF_rwSkySystem              41+PFbasky
#define PF_rwDeviceGetHandle            42+PFbasky
#define PF_rwSkyRasterSetImageNormal        43+PFbasky
#define PF_rwSkyRasterSetImageMipmap        44+PFbasky

/* baskycache.c */
#define PFbaskycache                45+PFbasky
#define PF_rwSkyMemoryInitialise        0+PFbaskycache
#define PF_rwSkyMemoryRelease           1+PFbaskycache
#define PF_rwSkyInsertIntoFreeList      2+PFbaskycache
#define PF_rwSkyMemoryUseMemBlock       3+PFbaskycache
#define PF_rwSkyMemoryAlloc         4+PFbaskycache
#define PF_rwSkyMemoryFree          5+PFbaskycache
#define PF_rwSkyCacheInitialise         6+PFbaskycache
#define PF_rwSkyCacheRelease            7+PFbaskycache
#define PF_rwSkyCacheUploadRaster       8+PFbaskycache
#define PF_rwSkyTexCacheAccessRaster        9+PFbaskycache
#define PF_rwSkyCacheReleaseCacheEntry      10+PFbaskycache
#define PF_rwSkyTexCacheReleaseRaster       11+PFbaskycache
#define PF_rwSkyFlushTexCache           12+PFbaskycache
#define PF_rwSkyTexCacheOpen            13+PFbaskycache
#define PF_rwSkyTexCacheClose           14+PFbaskycache
#define PF_rwSkyTexCacheFlush           15+PFbaskycache

/* baskyfs.c */
#define PFbaskyfs               16+PFbaskycache
#define PFskyTransMode              0+PFbaskyfs
#define PFtrySkyFopen               1+PFbaskyfs
#define PFskyFopen              2+PFbaskyfs
#define PFskyFclose             3+PFbaskyfs
#define PFskyFexist             4+PFbaskyfs
#define PFskyFread              5+PFbaskyfs
#define PFskyFwrite             6+PFbaskyfs
#define PFskyFseek              7+PFbaskyfs
#define PFskyFgets              8+PFbaskyfs
#define PFskyFputs              9+PFbaskyfs
#define PFskyFeof               10+PFbaskyfs
#define PFskyFflush             11+PFbaskyfs
#define PF_rwSkyFSOpen              12+PFbaskyfs
#define PF_rwSkyFSClose             13+PFbaskyfs
#define PFRwSkyInstallFileSystem        14+PFbaskyfs

/* dmaalloc.c */
#define PFdmaalloc              15+PFbaskyfs
#define PFlogAlloc              0+PFdmaalloc
#define PFunlogAlloc                1+PFdmaalloc
#define PFcreateNewBlock            2+PFdmaalloc
#define PFcircularAllocatorExtend       3+PFdmaalloc
#define PFcircularMalloc            4+PFdmaalloc
#define PFcircularRealloc           5+PFdmaalloc
#define PFcircularFree              6+PFdmaalloc
#define PFcircularAllocOpen         7+PFdmaalloc
#define PFcircularAllocClose            8+PFdmaalloc

/* skyblit.c */
#define PFskyblit               9+PFdmaalloc
#define PF_rwSkyRasterClearRect         0+PFskyblit
#define PF_rwSkyRasterClear         1+PFskyblit
#define PF_rwSkyRasterRender            2+PFskyblit
#define PF_rwSkyRasterRenderScaled      3+PFskyblit
#define PF_rwSkyRasterRenderFast        4+PFskyblit
#define PF_rwSkyRasterSetContext        5+PFskyblit

/* texcache.c */
#define PFtexcache              6+PFskyblit
#define PFskyUploadRaster           0+PFtexcache
#define PF_SkyMemoryInitialise          1+PFtexcache
#define PF_SkyMemoryRelease         2+PFtexcache
#define PF_SkyInsertIntoFreeList        3+PFtexcache
#define PF_SkyMemoryUseMemBlock         4+PFtexcache
#define PF_SkyMemoryAlloc           5+PFtexcache
#define PF_SkyMemoryFree            6+PFtexcache
#define PF_SkyCacheInitialise           7+PFtexcache
#define PF_SkyCacheUploadRaster         8+PFtexcache
#define PFskyTexCacheAccessRaster       9+PFtexcache
#define PF_SkyCacheReleaseCacheEntry        10+PFtexcache
#define PFskyTexCacheReleaseRaster      11+PFtexcache
#define PFskyTexCacheOpenCache          12+PFtexcache
#define PFskyTexCacheCloseCache         13+PFtexcache
#define PFskyTexCacheFlush          14+PFtexcache
#define PFupLoadRectangle           15+PFtexcache

/* baskytrans.c */
#define PFbaskytrans                16+PFtexcache
#define PF_rwSkyPerspectiveTransform        0+PFbaskytrans
#define PF_rwSkyPassThroughTransform        1+PFbaskytrans
#define PFmatrixASMMult             2+PFbaskytrans
#define PFvectorASMMultPoint            3+PFbaskytrans
#define PFvectorASMMultVector           4+PFbaskytrans

/* skywrins.c */
#define PFskywrins              5+PFbaskytrans
#define PF_rwSkyAtomicInstanceAnimation     0+PFskywrins
#define PF_rwSkyAtomicInstance          1+PFskywrins
#define PF_rwSkyWorldSectorInstance     2+PFskywrins
#define PF_rwSkyWorldNULLTransform      3+PFskywrins
#define PF_rwSkyWorldPreLight           4+PFskywrins
#define PF_rwSkyWorldLight          5+PFskywrins
#define PF_rwSkyWorldApplyLight         6+PFskywrins
#define PF_rwSkyWorldPostLight          7+PFskywrins
#define PFinitVu1DispatchStuff          8+PFskywrins
#define PFaddRefVU1Tris             9+PFskywrins
#define PF_rwSkyWorldRender         10+PFskywrins
#define PFopenVU1Pkt                11+PFskywrins
#define PFcloseAndDispatchVU1Packet     12+PFskywrins
#define PFcreateAndInitCopyLinePacket       13+PFskywrins
#define PFcreateAndInitCopyTriPacket        14+PFskywrins
#define PFaddCopyVU1Line            15+PFskywrins
#define PFaddCopyVU1Triangle            16+PFskywrins
#define PFaddCopyVU1Prim            17+PFskywrins
#define PFaddCopyVU1IndPrim         18+PFskywrins
#define PFopenVU1SetupPkt           19+PFskywrins
#define PF_rwSkyTSAtomicInstanceAnimation   20+PFskywrins
#define PF_rwSkyTSAtomicInstance        21+PFskywrins
#define PF_rwSkyInstanceDestroyCallback     22+PFskywrins
#define PF_rwSkyAtomicSelectInstance        23+PFskywrins
#define PFskipTriStripMesh          24+PFskywrins
#define PFskipTriListMesh           25+PFskywrins
#define PF_rwSkyWorldUnOverloadPipeline     26+PFskywrins
#define PFRwSkyInitWorldPipeline        27+PFskywrins

/* skyinst.c */
#define PFskyinst               28+PFskywrins
#define PF_rwSkyIm3DNULLTransform       0+PFskyinst
#define PF_rwSkyIm3DNULLPreLight        1+PFskyinst
#define PF_rwSkyIm3DNULLLight           2+PFskyinst
#define PF_rwSkyIm3DNULLPostLight       3+PFskyinst
#define PF_rwSkyIm3DNULLApplyLight      4+PFskyinst
#define PF_rwSkyIm3DRender          5+PFskyinst
#define PF_rwSkyOverloadPipelines       6+PFskyinst
#define PF_rwSkyIm3DRenderLine          7+PFskyinst
#define PF_rwSkyIm3DRenderTriangle      8+PFskyinst
#define PF_rwSkyIm3DRenderPrimitive     9+PFskyinst
#define PF_rwSkyIm3DRenderIndexedPrimitive  10+PFskyinst
#define PFopen2DVU1Pkt              11+PFskyinst
#define PFopen3DVU1Pkt              12+PFskyinst
#define PF_rwSkyIm3DInstance            13+PFskyinst
#define PF_rwSkyPipeSetupForCamera      14+PFskyinst

/* Total time */
#define PFtotalTime             15+PFskyinst

#ifdef PROFILE

/* The macros that actually do the work */
/* Following the least impact directive, we don't use a local for the "current"
   function, but instead insist that the correct constant is passed in each
   time */

#ifdef PFDESCENDANTS

/* Bulk time in top 64 bits, unencumbered time in the lower 64 */
#define PFENTRY(A)              \
do                      \
{                       \
    unsigned long savevi;           \
    unsigned long tmp2;             \
    unsigned long high0;            \
    unsigned long high1;            \
    unsigned long low0;             \
    unsigned long low1;             \
    unsigned long savevf; /* lie */     \
    unsigned long savedi;           \
__asm volatile ("               \
    nop                     \n\
    nop                     \n\
    nop                     \n\
    nop                     \n\
    nop                     \n\
    mfc0    %7, $12             \n\
    di                      \n\
    lui     %1, 1               \n\
    cfc2    %0, $vi1            \n\
    and     %7, %7, %1          \n\
    addiu   %1, $0, 0xff            \n\
    ctc2    %1, $vi1            \n\
    qmfc2   %6, $vf1            \n\
    li      %1, 0x10000800          \n\
    vlqi.xy $vf1, ($vi1++)          \n\
    qmfc2   %2, $vf1            \n\
    lwu     %4, 0(%1)           \n\
    lwu     %3, 0x10(%1)            \n\
    andi    %3, %3, 0x800           \n\
    dsll    %3, %3, 5           \n\
    daddu   %3, %3, %2          \n\
    lwu     %5, 0(%1)           \n\
.set noreorder                  \n\
.set    nomacro                 \n\
    beq     $2, %3, 0f          \n\
    daddu   %4, %4, %2          \n\
.set    macro                   \n\
.set    reorder                 \n\
    daddu   %4, %5, %3          \n\
0:                      \n\
.set noreorder                  \n\
.set    nomacro                 \n\
    beq     %7, $0, 0f          \n\
    ctc2    %8, $vi1            \n\
.set    macro                   \n\
.set    reorder                 \n\
    ei                      \n\
0:                      \n\
    vlqi.xyzw   $vf1, ($vi1++)          \n\
    qmfc2   %2, $vf1            \n\
    pcpyud      %3, %2, %2          \n\
    dsubu   %2, %2, %4          \n\
    dsubu   %3, %3, %4          \n\
    pcpyld      %2, %3, %2          \n\
    qmtc2       %2, $vf1            \n\
    vsqd.xyzw   $vf1, (--$vi1)          \n\
    qmtc2       %6, $vf1            \n\
    ctc2        %0, $vi1 "          \
    : "=r&" (savevi),               \
      "=r&" (tmp2),             \
      "=r&" (high0),                \
      "=r&" (high1),                \
      "=r&" (low0),             \
      "=r&" (low1),             \
      "=r&" (savevf),               \
      "=r&" (savedi)                \
    : "r" (A));                 \
}                       \
while(0)

#define PFEXIT(A)   \
do                      \
{                       \
    unsigned long savevi;           \
    unsigned long tmp2;             \
    unsigned long high0;            \
    unsigned long high1;            \
    unsigned long low0;             \
    unsigned long low1;             \
    unsigned long savevf; /* lie */     \
    unsigned long savedi;           \
__asm volatile ("               \
    nop                     \n\
    nop                     \n\
    nop                     \n\
    nop                     \n\
    nop                     \n\
    mfc0    %7, $12             \n\
    di                      \n\
    lui     %1, 1               \n\
    cfc2    %0, $vi1            \n\
    and     %7, %7, %1          \n\
    addiu   %1, $0, 0xff            \n\
    ctc2    %1, $vi1            \n\
    qmfc2   %6, $vf1            \n\
    li      %1, 0x10000800          \n\
    vlqi.xy $vf1, ($vi1++)          \n\
    qmfc2   %2, $vf1            \n\
    lwu     %4, 0(%1)           \n\
    lwu     %3, 0x10(%1)            \n\
    andi    %3, %3, 0x800           \n\
    dsll    %3, %3, 5           \n\
    daddu   %3, %3, %2          \n\
    lwu     %5, 0(%1)           \n\
.set noreorder                  \n\
.set    nomacro                 \n\
    beq     $2, %3, 0f          \n\
    daddu   %4, %4, %2          \n\
.set    macro                   \n\
.set    reorder                 \n\
    daddu   %4, %5, %3          \n\
0:                      \n\
.set noreorder                  \n\
.set    nomacro                 \n\
    beq     %7, $0, 0f          \n\
    ctc2    %8, $vi1            \n\
.set    macro                   \n\
.set    reorder                 \n\
    ei                      \n\
0:                      \n\
    vlqi.xyzw   $vf1, ($vi1++)          \n\
    qmfc2   %2, $vf1            \n\
    pcpyud      %3, %2, %2          \n\
    daddu   %2, %2, %4          \n\
    daddu   %3, %3, %4          \n\
    pcpyld      %2, %3, %2          \n\
    qmtc2       %2, $vf1            \n\
    vsqd.xyzw   $vf1, (--$vi1)          \n\
    qmtc2       %6, $vf1            \n\
    ctc2        %0, $vi1 "          \
    : "=r&" (savevi),               \
      "=r&" (tmp2),             \
      "=r&" (high0),                \
      "=r&" (high1),                \
      "=r&" (low0),             \
      "=r&" (low1),             \
      "=r&" (savevf),               \
      "=r&" (savedi)                \
    : "r" (A));                 \
}                       \
while(0)

#else /* PFDESCENDANTS */

/* bulk time in top 64, descentants field is being used for call count */
#define PFENTRY(A)              \
do                      \
{                       \
    unsigned long savevi;           \
    unsigned long tmp2;             \
    unsigned long high0;            \
    unsigned long high1;            \
    unsigned long low0;             \
    unsigned long low1;             \
    unsigned long savevf; /* lie */     \
    unsigned long savedi;           \
__asm volatile ("               \
    nop                     \n\
    nop                     \n\
    nop                     \n\
    nop                     \n\
    nop                     \n\
    mfc0    %7, $12             \n\
    di                      \n\
    lui     %1, 1               \n\
    cfc2    %0, $vi1            \n\
    and     %7, %7, %1          \n\
    addiu   %1, $0, 0xff            \n\
    ctc2    %1, $vi1            \n\
    qmfc2   %6, $vf1            \n\
    li      %1, 0x10000800          \n\
    vlqi.xy $vf1, ($vi1++)          \n\
    qmfc2   %2, $vf1            \n\
    lwu     %4, 0(%1)           \n\
    lwu     %3, 0x10(%1)            \n\
    andi    %3, %3, 0x800           \n\
    dsll    %3, %3, 5           \n\
    daddu   %3, %3, %2          \n\
    lwu     %5, 0(%1)           \n\
.set noreorder                  \n\
.set    nomacro                 \n\
    beq     $2, %3, 0f          \n\
    daddu   %4, %4, %2          \n\
.set    macro                   \n\
.set    reorder                 \n\
    daddu   %4, %5, %3          \n\
0:                      \n\
.set noreorder                  \n\
.set    nomacro                 \n\
    beq     %7, $0, 0f          \n\
    ctc2    %8, $vi1            \n\
.set    macro                   \n\
.set    reorder                 \n\
    ei                      \n\
0:                      \n\
    vlqi.xyzw   $vf1, ($vi1++)          \n\
    qmfc2   %2, $vf1            \n\
    pcpyud      %3, %2, %2          \n\
    daddiu  %2, %2, 1           \n\
    dsubu   %3, %3, %4          \n\
    pcpyld      %2, %3, %2          \n\
    qmtc2       %2, $vf1            \n\
    vsqd.xyzw   $vf1, (--$vi1)          \n\
    qmtc2       %6, $vf1            \n\
    ctc2        %0, $vi1 "          \
    : "=r&" (savevi),               \
      "=r&" (tmp2),             \
      "=r&" (high0),                \
      "=r&" (high1),                \
      "=r&" (low0),             \
      "=r&" (low1),             \
      "=r&" (savevf),               \
      "=r&" (savedi)                \
    : "r" (A));                 \
}                       \
while(0)

#define PFEXIT(A)   \
do                      \
{                       \
    unsigned long savevi;           \
    unsigned long tmp2;             \
    unsigned long high0;            \
    unsigned long high1;            \
    unsigned long low0;             \
    unsigned long low1;             \
    unsigned long savevf; /* lie */     \
    unsigned long savedi;           \
__asm volatile ("               \
    nop                     \n\
    nop                     \n\
    nop                     \n\
    nop                     \n\
    nop                     \n\
    mfc0    %7, $12             \n\
    di                      \n\
    lui     %1, 1               \n\
    cfc2    %0, $vi1            \n\
    and     %7, %7, %1          \n\
    addiu   %1, $0, 0xff            \n\
    ctc2    %1, $vi1            \n\
    qmfc2   %6, $vf1            \n\
    li      %1, 0x10000800          \n\
    vlqi.xy $vf1, ($vi1++)          \n\
    qmfc2   %2, $vf1            \n\
    lwu     %4, 0(%1)           \n\
    lwu     %3, 0x10(%1)            \n\
    andi    %3, %3, 0x800           \n\
    dsll    %3, %3, 5           \n\
    daddu   %3, %3, %2          \n\
    lwu     %5, 0(%1)           \n\
.set noreorder                  \n\
.set    nomacro                 \n\
    beq     $2, %3, 0f          \n\
    daddu   %4, %4, %2          \n\
.set    macro                   \n\
.set    reorder                 \n\
    daddu   %4, %5, %3          \n\
0:                      \n\
.set noreorder                  \n\
.set    nomacro                 \n\
    beq     %7, $0, 0f          \n\
    ctc2    %8, $vi1            \n\
.set    macro                   \n\
.set    reorder                 \n\
    ei                      \n\
0:                      \n\
    vlqi.xyzw   $vf1, ($vi1++)          \n\
    qmfc2   %2, $vf1            \n\
    pcpyud      %3, %2, %2          \n\
    daddu   %3, %3, %4          \n\
    pcpyld      %2, %3, %2          \n\
    qmtc2       %2, $vf1            \n\
    vsqd.xyzw   $vf1, (--$vi1)          \n\
    qmtc2       %6, $vf1            \n\
    ctc2        %0, $vi1 "          \
    : "=r&" (savevi),               \
      "=r&" (tmp2),             \
      "=r&" (high0),                \
      "=r&" (high1),                \
      "=r&" (low0),             \
      "=r&" (low1),             \
      "=r&" (savevf),               \
      "=r&" (savedi)                \
    : "r" (A));                 \
}                       \
while(0)

#endif /* PFDESCENDANTS */

#ifdef PFDESCENDANTS

/* We want to be able to distinguish the time spent in children so we bracket
   all calls to children. Gcc's optimisation may mess this up? */
#define PFCALL(A)   \
do                      \
{                       \
    unsigned long savevi;           \
    unsigned long tmp2;             \
    unsigned long high0;            \
    unsigned long high1;            \
    unsigned long low0;             \
    unsigned long low1;             \
    unsigned long savevf; /* lie */     \
    unsigned long savedi;           \
__asm volatile ("               \
    nop                     \n\
    nop                     \n\
    nop                     \n\
    nop                     \n\
    nop                     \n\
    mfc0    %7, $12             \n\
    di                      \n\
    lui     %1, 1               \n\
    cfc2    %0, $vi1            \n\
    and     %7, %7, %1          \n\
    addiu   %1, $0, 0xff            \n\
    ctc2    %1, $vi1            \n\
    qmfc2   %6, $vf1            \n\
    li      %1, 0x10000800          \n\
    vlqi.xy $vf1, ($vi1++)          \n\
    qmfc2   %2, $vf1            \n\
    lwu     %4, 0(%1)           \n\
    lwu     %3, 0x10(%1)            \n\
    andi    %3, %3, 0x800           \n\
    dsll    %3, %3, 5           \n\
    daddu   %3, %3, %2          \n\
    lwu     %5, 0(%1)           \n\
.set noreorder                  \n\
.set    nomacro                 \n\
    beq     $2, %3, 0f          \n\
    daddu   %4, %4, %2          \n\
.set    macro                   \n\
.set    reorder                 \n\
    daddu   %4, %5, %3          \n\
0:                      \n\
.set noreorder                  \n\
.set    nomacro                 \n\
    beq     %7, $0, 0f          \n\
    ctc2    %8, $vi1            \n\
.set    macro                   \n\
.set    reorder                 \n\
    ei                      \n\
0:                      \n\
    vlqi.xy $vf1, ($vi1++)          \n\
    qmfc2   %2, $vf1            \n\
    daddu   %2, %2, %4          \n\
    qmtc2       %2, $vf1            \n\
    vsqd.xy     $vf1, (--$vi1)          \n\
    qmtc2       %6, $vf1            \n\
    ctc2        %0, $vi1 "          \
    : "=r&" (savevi),               \
      "=r&" (tmp2),             \
      "=r&" (high0),                \
      "=r&" (high1),                \
      "=r&" (low0),             \
      "=r&" (low1),             \
      "=r&" (savevf),               \
      "=r&" (savedi)                \
    : "r" (A));                 \
}                       \
while(0)

#define PFRET(A)    \
do                      \
{                       \
    unsigned long savevi;           \
    unsigned long tmp2;             \
    unsigned long high0;            \
    unsigned long high1;            \
    unsigned long low0;             \
    unsigned long low1;             \
    unsigned long savevf; /* lie */     \
    unsigned long savedi;           \
__asm volatile ("               \
    nop                     \n\
    nop                     \n\
    nop                     \n\
    nop                     \n\
    nop                     \n\
    mfc0    %7, $12             \n\
    di                      \n\
    lui     %1, 1               \n\
    cfc2    %0, $vi1            \n\
    and     %7, %7, %1          \n\
    addiu   %1, $0, 0xff            \n\
    ctc2    %1, $vi1            \n\
    qmfc2   %6, $vf1            \n\
    li      %1, 0x10000800          \n\
    vlqi.xy $vf1, ($vi1++)          \n\
    qmfc2   %2, $vf1            \n\
    lwu     %4, 0(%1)           \n\
    lwu     %3, 0x10(%1)            \n\
    andi    %3, %3, 0x800           \n\
    dsll    %3, %3, 5           \n\
    daddu   %3, %3, %2          \n\
    lwu     %5, 0(%1)           \n\
.set noreorder                  \n\
.set    nomacro                 \n\
    beq     $2, %3, 0f          \n\
    daddu   %4, %4, %2          \n\
.set    macro                   \n\
.set    reorder                 \n\
    daddu   %4, %5, %3          \n\
0:                      \n\
.set noreorder                  \n\
.set    nomacro                 \n\
    beq     %7, $0, 0f          \n\
    ctc2    %8, $vi1            \n\
.set    macro                   \n\
.set    reorder                 \n\
    ei                      \n\
0:                      \n\
    vlqi.xy $vf1, ($vi1++)          \n\
    qmfc2   %2, $vf1            \n\
    dsubu   %2, %2, %4          \n\
    qmtc2       %2, $vf1            \n\
    vsqd.xy     $vf1, (--$vi1)          \n\
    qmtc2       %6, $vf1            \n\
    ctc2        %0, $vi1 "          \
    : "=r&" (savevi),               \
      "=r&" (tmp2),             \
      "=r&" (high0),                \
      "=r&" (high1),                \
      "=r&" (low0),             \
      "=r&" (low1),             \
      "=r&" (savevf),               \
      "=r&" (savedi)                \
    : "r" (A));                 \
}                       \
while(0)

#else /* PFDESCENDANTS */

/* descentants field is being used for call count */
#define PFCALL(A)
#define PFRET(A)

#endif /* PFDESCENDANTS */

#define PFGET(A, TOTAL, UNEN)           \
do                      \
{                       \
    unsigned long savevi;           \
    unsigned long savevf; /* lie */     \
    unsigned long _pf_total;            \
    unsigned long _pf_unen;         \
__asm volatile ("               \
    cfc2    %0, $vi1            \n\
    qmfc2   %1, $vf1            \n\
    ctc2    %4, $vi1            \n\
    vlqi.xyzw   $vf1, ($vi1++)          \n\
    qmfc2   %3, $vf1            \n\
    qmtc2   %1, $vf1            \n\
    ctc2    %0, $vi1            \n\
    pcpyud  %2, %3, %3 "            \
    : "=r&" (savevi),               \
      "=r&" (savevf),               \
      "=r" (_pf_total),             \
      "=r" (_pf_unen)               \
    : "r" (A));                 \
    (TOTAL) = _pf_total;            \
    (UNEN) = _pf_unen;              \
}                       \
while(0)

#define PFRESET(A)              \
do                      \
{                       \
    unsigned long savevi;           \
    unsigned long savevf; /* lie */     \
__asm volatile ("               \
    cfc2    %0, $vi1            \n\
    ctc2    %2, $vi1            \n\
    qmfc2   %1, $vf1            \n\
    vsub.xyzw   $vf1, $vf1, $vf1        \n\
    vsqi.xyzw   $vf1, ($vi1++)          \n\
    qmtc2   %1, $vf1            \n\
    ctc2    %0, $vi1"           \
    : "=r&" (savevi),               \
      "=r" (savevf)                 \
    : "r" (A));                 \
}                       \
while(0)

#else /* PROFILE */

/* NULL versions of the above */
#define PFENTRY(A)
#define PFEXIT(A)
#define PFCALL(A)
#define PFRET(A)
#define PFGET(A, TOTAL, UNEN)
#define PFRESET(A)

#endif /* PROFILE */

#endif /* !_DEVPROFILE_H */
