-
Notifications
You must be signed in to change notification settings - Fork 1
/
Handlers.c
85 lines (80 loc) · 2.27 KB
/
Handlers.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include "Driver.h"
#include "Parser.h"
#include "Emulators.h"
/* Main instruction handler */
int __stdcall HandleUndefInstruction(unsigned char** instruction, CALLER_CONTEXT* context)
{
UNREFERENCED_PARAMETER(instruction);
UNREFERENCED_PARAMETER(context);
ParsedInstruction parsedInstruction = parse(*instruction);
EmulatorRoutine routine;
// Choose routine depending on the instruction type returned by parser
switch (parsedInstruction.type)
{
case INSTR_ANDN:
routine = EMULATOR_ROUTINE_PTR(ANDN);
break;
case INSTR_BEXTR:
routine = EMULATOR_ROUTINE_PTR(BEXTR);
break;
case INSTR_BLSI:
routine = EMULATOR_ROUTINE_PTR(BLSI);
break;
case INSTR_BLSMSK:
routine = EMULATOR_ROUTINE_PTR(BLSMSK);
break;
case INSTR_BLSR:
routine = EMULATOR_ROUTINE_PTR(BLSR);
break;
case INSTR_LZCNT:
routine = EMULATOR_ROUTINE_PTR(LZCNT);
break;
case INSTR_POPCNT:
routine = EMULATOR_ROUTINE_PTR(POPCNT);
break;
case INSTR_TZCNT:
routine = EMULATOR_ROUTINE_PTR(TZCNT);
break;
case INSTR_DEBUG:
routine = EMULATOR_ROUTINE_PTR(Example);
break;
default:
// If instruction is unknown for parser: pass handling to O/S
return FALSE;
}
// Call emulator routine.
if (routine(parsedInstruction, context))
{
// On success: move instruction pointer and continue
*instruction += parsedInstruction.length;
return TRUE;
}
else
// On failure: pass handling to O/S
return FALSE;
}
/* Helper functions: context getters/setters */
unsigned int getRegValue(unsigned char src, CALLER_CONTEXT* context)
{
// Get pointer to first register value
UINT32* reg_val = &context->eax;
// Shift pointer to register specified as argument
reg_val -= (src & 0x0F);
// If source is 16b reg: return only 16 lsb
// Otherwise: return whole value
return (src & 0xF0) ? ((*reg_val) & 0xFFFF) : (*reg_val);
}
void setRegValue(unsigned char dst, unsigned int value, CALLER_CONTEXT* context)
{
// Get pointer to first register value
UINT32* reg_val = &context->eax;
// Shift pointer to register specified as argument
reg_val -= (dst & 0x0F);
// If source is 16b reg...
if (dst & 0xF0)
// ... merge 16 msb from origin and 16 lsb from argument
*reg_val = (*reg_val & 0xFFFF0000) | (value & 0xFFFF);
else
// Otherwise: just overwrite register with specified value
*reg_val = value;
}