//This is the software interrupt num
//we will use.  See Software Int's for
//picking a num.  Nums are subject to change.

#define I_F_UNARY_MINUS I_USER

asm {

//This changes the sign of the floating
//point val in RAX
F_UNARY_MINUS_INT::
                PUSH        RAX
                FLD         U64 [RSP]
                FCHS
                FSTP        U64 [RSP]
                POP         RAX
                IRET

//This does the same thing, but not as
//an interrupt.
F_UNARY_MINUS_CALL::
                PUSH        RAX
                FLD         U64 [RSP]
                FCHS
                FSTP        U64 [RSP]
                POP         RAX
                RET

//This invokes the interrupt version
//with a C callable function.
_F_UM_INT::
                PUSH        RBP
                MOV         RBP, RSP
                MOV         RAX, SF_ARG1[RBP]
                INT         I_F_UNARY_MINUS
                POP         RBP
                RET1        8

//This invokes the call version
//with a C callable function.
_F_UM_CALL::
                PUSH        RBP
                MOV         RBP, RSP
                MOV         RAX, SF_ARG1[RBP]
                CALL        F_UNARY_MINUS_CALL
                POP         RBP
                RET1        8
}

_extern _F_UM_INT  F64 UnaryMinusInt(F64 d);
_extern _F_UM_CALL F64 UnaryMinusCall(F64 d);

#define SAMPLE_SIZE         1000000
U0 TimeIns()
{
    I64 start, end;
    I64 i, old_irq;

    CPURep;
    old_irq = IntEntrySet(I_F_UNARY_MINUS, F_UNARY_MINUS_INT, IDTET_TRAP);

    //Measure interrupt time
    start = TSCGet;
    for (i = 0; i < SAMPLE_SIZE; i++)
        UnaryMinusInt(pi);
    end = TSCGet;
    "Interrupt Cycles: %10.5f\n", ToF64(end - start) / SAMPLE_SIZE;

    //Measure call time
    start = TSCGet;
    for (i = 0; i < SAMPLE_SIZE; i++)
        UnaryMinusCall(pi);
    end = TSCGet;
    "Call      Cycles: %10.5f\n", ToF64(end - start) / SAMPLE_SIZE;

    IntEntrySet(I_F_UNARY_MINUS, old_irq, IDTET_IRQ);
}

TimeIns;

/*  Program Output
6 Cores 3.395GHz
Interrupt Cycles:  573.98543
Call            Cycles:      9.74349
*/