|
|
/*++
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; }
|