windows-nt/Source/XPSP1/NT/base/wow64/mscpu/fraglib/lock.c
2020-09-26 16:20:57 +08:00

229 lines
4.5 KiB
C

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
lock.c
Abstract:
32bit instructions with the LOCK prefix
Author:
15-Aug-1995 t-orig (Ori Gershony)
Revision History:
24-Aug-1999 [askhalid] copied from 32-bit wx86 directory and make work for 64bit.
20-Sept-1999[barrybo] added FRAG2REF(LockCmpXchg8bFrag32, ULONGLONG)
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <stdio.h>
#include "fragp.h"
#include "lock.h"
// Define a macro which calls the lock helper functions
#define CALLLOCKHELPER0(fn) fn ## LockHelper ()
#define CALLLOCKHELPER1(fn,a1) fn ## LockHelper (a1)
#define CALLLOCKHELPER2(fn,a1,a2) fn ## LockHelper (a1,a2)
#define CALLLOCKHELPER3(fn,a1,a2,a3) fn ## LockHelper (a1,a2,a3)
#define CALLLOCKHELPER4(fn,a1,a2,a3,a4) fn ## LockHelper (a1,a2,a3,a4)
// Now define 32bit MSB
#define MSB 0x80000000
#define SET_FLAGS_ADD SET_FLAGS_ADD32
#define SET_FLAGS_SUB SET_FLAGS_SUB32
#define SET_FLAGS_INC SET_FLAGS_INC32
#define SET_FLAGS_DEC SET_FLAGS_DEC32
FRAG2(LockAddFrag32, ULONG)
{
ULONG result, op1;
result = CALLLOCKHELPER3(Add, &op1, pop1, op2);
SET_FLAGS_ADD(result, op1, op2, MSB);
}
FRAG2(LockOrFrag32, ULONG)
{
ULONG result;
result = CALLLOCKHELPER2(Or, pop1, op2);
SET_PFLAG(result);
SET_ZFLAG(result);
SET_SFLAG(result);
SET_CFLAG_OFF;
SET_OFLAG_OFF;
}
FRAG2(LockAdcFrag32, ULONG)
{
ULONG result, op1;
result = CALLLOCKHELPER4(Adc, &op1, pop1, op2, cpu->flag_cf);
SET_FLAGS_ADD(result, op1, op2, MSB);
}
FRAG2(LockSbbFrag32, ULONG)
{
ULONG result, op1;
result = CALLLOCKHELPER4(Sbb, &op1, pop1, op2, cpu->flag_cf);
SET_FLAGS_SUB(result, op1, op2, MSB);
}
FRAG2(LockAndFrag32, ULONG)
{
ULONG result;
result = CALLLOCKHELPER2(And, pop1, op2);
SET_ZFLAG(result);
SET_PFLAG(result);
SET_SFLAG(result);
SET_CFLAG_OFF;
SET_OFLAG_OFF;
}
FRAG2(LockSubFrag32, ULONG)
{
ULONG result, op1;
result = CALLLOCKHELPER3(Sub, &op1, pop1, op2);
SET_FLAGS_SUB(result, op1, op2, MSB);
}
FRAG2(LockXorFrag32, ULONG)
{
ULONG result;
result = CALLLOCKHELPER2(Xor, pop1, op2);
SET_ZFLAG(result);
SET_PFLAG(result);
SET_SFLAG(result);
SET_CFLAG_OFF;
SET_OFLAG_OFF;
}
FRAG1(LockNotFrag32, ULONG)
{
CALLLOCKHELPER1(Not, pop1);
}
FRAG1(LockNegFrag32, ULONG)
{
ULONG result, op1;
result = CALLLOCKHELPER2(Neg, &op1, pop1);
SET_CFLAG_IND(result == 0);
SET_ZFLAG(result);
SET_PFLAG(result);
SET_SFLAG(result);
SET_OFLAG_IND(op1 & result & MSB);
}
FRAG1(LockIncFrag32, ULONG)
{
ULONG result, op1;
result = CALLLOCKHELPER3(Add, &op1, pop1, 1);
SET_FLAGS_INC(result, op1);
}
FRAG1(LockDecFrag32, ULONG)
{
ULONG result, op1;
result = CALLLOCKHELPER3(Sub, &op1, pop1, 1);
SET_FLAGS_DEC(result, op1);
}
FRAG2(LockBtsMemFrag32, ULONG)
{
ULONG bit = 1<<(op2&0x1f);
pop1 += (op2 >> 5);
SET_CFLAG_IND(CALLLOCKHELPER2(Bts, pop1, bit));
}
FRAG2(LockBtsRegFrag32, ULONG)
{
ULONG bit = 1<<(op2&0x1f);
SET_CFLAG_IND(CALLLOCKHELPER2(Bts, pop1, bit));
}
FRAG2(LockBtrMemFrag32, ULONG)
{
ULONG bit = 1<<(op2&0x1f);
pop1 += (op2 >> 5);
SET_CFLAG_IND(CALLLOCKHELPER2(Btr, pop1, bit));
}
FRAG2(LockBtrRegFrag32, ULONG)
{
ULONG bit = 1<<(op2&0x1f);
SET_CFLAG_IND(CALLLOCKHELPER2(Btr, pop1, bit));
}
FRAG2(LockBtcMemFrag32, ULONG)
{
ULONG bit = 1<<(op2&0x1f);
pop1 += (op2 >> 5);
SET_CFLAG_IND(CALLLOCKHELPER2(Btc, pop1, bit));
}
FRAG2(LockBtcRegFrag32, ULONG)
{
ULONG bit = 1<<(op2&0x1f);
SET_CFLAG_IND(CALLLOCKHELPER2(Btc, pop1, bit));
}
FRAG2REF(LockXchgFrag32, ULONG)
{
CALLLOCKHELPER2(Xchg, pop1, pop2);
}
FRAG2REF(LockXaddFrag32, ULONG)
{
ULONG op1, op2;
op2 = CALLLOCKHELPER3(Xadd, &op1, pop1, pop2);
// op1 has the original value of dest (*pop1)
// op2 has the result of the XADD
// so, op2-op1 is the original value of src
SET_FLAGS_ADD(op2, (op2-op1), op1, MSB);
}
FRAG2REF(LockCmpXchgFrag32, ULONG)
{
ULONG op1;
ULONG Value = eax;
SET_ZFLAG(CALLLOCKHELPER4(CmpXchg, &eax, pop1, pop2, &op1));
SET_FLAGS_SUB(Value-op1, Value, op1, MSB);
}
FRAG2REF(LockCmpXchg8bFrag32, ULONGLONG)
{
ULONGLONG op1;
ULONGLONG EdxEax;
ULONGLONG EcxEbx;
EdxEax = (((ULONGLONG)edx) << 32) | (ULONGLONG)eax;
EcxEbx = (ULONGLONG)ecx << 32 | (ULONGLONG)ebx;
SET_ZFLAG(CALLLOCKHELPER3(CmpXchg8b, &EdxEax, &EcxEbx, pop1));
edx = (ULONG)(EdxEax >> 32);
eax = (ULONG)EdxEax;
}