You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

225 lines
5.6 KiB

; Copyright 2002-2019 Intel Corporation.
;
; This software is provided to you as Sample Source Code as defined in the accompanying
; End User License Agreement for the Intel(R) Software Development Products ("Agreement")
; section 1.L.
;
; This software and the related documents are provided as is, with no express or implied
; warranties, other than those that are expressly stated in the License.
PUBLIC ChangeRegsWrapper
PUBLIC ChangeRegs
PUBLIC SaveRegsToMem
.686
.XMM
.model flat, c
extern gprval:dword
extern agprval:dword
extern stval:real10
extern astval:real10
extern xmmval:xmmword
extern axmmval:xmmword
IFDEF CONTEXT_USING_AVX
extern ymmval:ymmword
extern aymmval:ymmword
ENDIF
IFDEF CONTEXT_USING_AVX512F
extern zmmval:ymmword ; We don't care much about the size we just need reference to the variable.
extern azmmval:ymmword ; since there is no support yet for zmmword this is good enough
extern opmaskval:qword
extern aopmaskval:qword
ENDIF
extern fpSaveArea:dword
.code
; void ChangeRegsWrapper();
; This wrapper saves and restores the registers used by ChangeRegs.
; This is done in the wrapper since we want ChangeRegs to actually
; change the register values but not to affect the application itself.
; The tool may intercept ChangeRegs and replace it with its own function.
;
; Register usage:
; eax - used (implicitly) by xsave
; ebx - used for testing the gpr values
; ecx - used for holding a pointer to the fp save area (used by fxsave)
; edx - used (implicitly) by xsave
; st0 - used (implicitly) for loading a value to the FPU stack
; st2 - used for testing the FPU values
; xmm0 - used for testing the sse (xmm) values
; ymm1 - used for testing the avx (ymm) values
; zmm5 - used for testing the avx512 (zmm) values
; k3 - used for testing the opmask register values
ChangeRegsWrapper PROC
; Save the necessary GPRs
push eax
push ebx
push ecx
push edx
IFDEF CONTEXT_USING_AVX512F
; Save the necessary mask registers
; kmovw eax, k3
BYTE 0c5h
BYTE 0f8h
BYTE 093h
BYTE 0c3h
push eax
ENDIF
; Allign the fpSaveArea
lea ecx, fpSaveArea
add ecx, 40H
and ecx, 0ffffffc0H
; Save the floating-point state
IFDEF CONTEXT_USING_AVX
push edx
xor edx, edx
mov eax, 7
xsave [ecx]
ELSE
fxsave [ecx]
ENDIF
; Now call ChangeRegs - do the actual test.
; The tool may intercept this function and modify the register values itself.
call ChangeRegs
; Placeholder for PIN_ExecuteAt
call ExecuteAt
; Save the modified values to memory so the tool can ispect them.
; This is relevant only when the tool modifies the values.
call SaveRegsToMem
; Restore the floating-point state
IFDEF CONTEXT_USING_AVX
mov eax, 7
xrstor [ecx]
pop edx
ELSE
fxrstor [ecx]
ENDIF
IFDEF CONTEXT_USING_AVX512F
; Restore the mask registers
pop eax
;kmovw k3, eax
BYTE 0c5h
BYTE 0f8h
BYTE 092h
BYTE 0d8h
ENDIF
; Restore the GPRs
pop edx
pop ecx
pop ebx
pop eax
ret
ChangeRegsWrapper ENDP
; void ChangeRegs();
; For register usage see ChangeRegsWrapper above.
ChangeRegs PROC
; TEST: load the new value to ebx
mov ebx, gprval
; prepare the test value at the top of the FPU stack
fld real10 ptr stval
; TEST: load the new value to st2
fst st(2)
; TEST: load the new value to xmm0
movdqu xmm0, xmmword ptr xmmval
IFDEF CONTEXT_USING_AVX
; TEST: load the new value to ymm1
vmovdqu ymm1, ymmword ptr ymmval
ENDIF
IFDEF CONTEXT_USING_AVX512F
; TEST: load the new value to zmm5
;instead of simple:
; vmovdqu32 zmm5, zmmword ptr zmmval
;do:
; lea eax, zmmval
; vmovdqu32 zmm5,[eax]
; encode the avx512 instruction in bytes
; since we cannot insert relocation as assembler can we need this split of lea followed by move
push eax
lea eax, zmmval
BYTE 062h
BYTE 0f1h
BYTE 0feh
BYTE 048h
BYTE 06fh
BYTE 028h
; TEST: load the new value to k3
; instead of:
; kmovw k3, opmaskval
; do:
; lea rax opmaskval
; kmovw k3, [rax] (encoded in bytes)
lea eax, opmaskval
BYTE 0c5h
BYTE 0f8h
BYTE 090h
BYTE 018h
pop eax
ENDIF
ret
ChangeRegs ENDP
; void ExecuteAt();
ExecuteAt PROC
ret
ExecuteAt ENDP
; void SaveRegsToMem();
; Save the necessary registers to memory.
; The tool will then compare the value stored in memory to the ones it expects to find.
; For register usage see ChangeRegsWrapper above.
SaveRegsToMem PROC
; TEST: store the new value of ebx
mov agprval, ebx
; prepare the test value at the top of the FPU stack
fld st(2)
; TEST: store the new value of st2
fstp real10 ptr astval
; TEST: store the new value of xmm0
movdqu xmmword ptr axmmval, xmm0
IFDEF CONTEXT_USING_AVX
; TEST: store the new value of ymm1
vmovdqu ymmword ptr aymmval, ymm1
ENDIF
IFDEF CONTEXT_USING_AVX512F
; TEST: store the new value of zmm5
;instead of simple:
; vmovdqu64 zmmword ptr azmmval, zmm5
;do:
; lea eax, azmmval
; vmovdqu64 [eax], zmm5
;encode the avx512 instruction in bytes
push eax
lea eax, azmmval
BYTE 062h
BYTE 0f1h
BYTE 0feh
BYTE 048h
BYTE 07fh
BYTE 028h
; TEST: store the new value of k3
; instead of kmovw k3, opmaskval
;do:
; lea rax aopmaskval
; kmovw [eax], k3 (encoded in bytes)
lea eax, aopmaskval
BYTE 0c5h
BYTE 0f8h
BYTE 091h
BYTE 018h
pop eax
ENDIF
ret
SaveRegsToMem ENDP
end