1/*
2 * Copyright (c) 2011 The Native Client Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
6
7/*
8 * Full-blown decoder for amd64 case.  Can be used to decode instruction
9 * sequence and process it, but right now is only used in tests.
10 *
11 * The code is in [hand-written] "parse_instruction.rl" and in [auto-generated]
12 * "decoder_x86_64_instruction.rl" file.  This file only includes tiny amount
13 * of the glue code.
14 */
15
16#include <assert.h>
17#include <stddef.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21
22#include "native_client/src/include/elf32.h"
23#include "native_client/src/shared/utils/types.h"
24#include "native_client/src/trusted/validator_ragel/decoder_internal.h"
25
26#define GET_REX_PREFIX() instruction.prefix.rex
27#define SET_REX_PREFIX(PREFIX_BYTE) instruction.prefix.rex = (PREFIX_BYTE)
28#define GET_VEX_PREFIX2() vex_prefix2
29#define SET_VEX_PREFIX2(PREFIX_BYTE) vex_prefix2 = (PREFIX_BYTE)
30#define CLEAR_SPURIOUS_REX_B() \
31  instruction.prefix.rex_b_spurious = FALSE
32#define SET_SPURIOUS_REX_B() \
33  if (GET_REX_PREFIX() & REX_B) instruction.prefix.rex_b_spurious = TRUE
34#define CLEAR_SPURIOUS_REX_X() \
35  instruction.prefix.rex_x_spurious = FALSE
36#define SET_SPURIOUS_REX_X() \
37  if (GET_REX_PREFIX() & REX_X) instruction.prefix.rex_x_spurious = TRUE
38#define CLEAR_SPURIOUS_REX_R() \
39  instruction.prefix.rex_r_spurious = FALSE
40#define SET_SPURIOUS_REX_R() \
41  if (GET_REX_PREFIX() & REX_R) instruction.prefix.rex_r_spurious = TRUE
42#define CLEAR_SPURIOUS_REX_W() \
43  instruction.prefix.rex_w_spurious = FALSE
44#define SET_SPURIOUS_REX_W() \
45  if (GET_REX_PREFIX() & REX_W) instruction.prefix.rex_w_spurious = TRUE
46
47%%{
48  machine x86_64_decoder;
49  alphtype unsigned char;
50  variable p current_position;
51  variable pe end_position;
52  variable eof end_position;
53  variable cs current_state;
54
55  include byte_machine "byte_machines.rl";
56
57  include prefixes_parsing_decoder
58    "native_client/src/trusted/validator_ragel/parse_instruction.rl";
59  include rex_actions
60    "native_client/src/trusted/validator_ragel/parse_instruction.rl";
61  include rex_parsing
62    "native_client/src/trusted/validator_ragel/parse_instruction.rl";
63  include vex_actions_amd64
64    "native_client/src/trusted/validator_ragel/parse_instruction.rl";
65  include vex_parsing_amd64
66    "native_client/src/trusted/validator_ragel/parse_instruction.rl";
67  include att_suffix_actions
68    "native_client/src/trusted/validator_ragel/parse_instruction.rl";
69  include set_spurious_prefixes
70    "native_client/src/trusted/validator_ragel/parse_instruction.rl";
71  include displacement_fields_parsing
72    "native_client/src/trusted/validator_ragel/parse_instruction.rl";
73  include modrm_actions_amd64
74    "native_client/src/trusted/validator_ragel/parse_instruction.rl";
75  include modrm_parsing
76    "native_client/src/trusted/validator_ragel/parse_instruction.rl";
77  include operand_format_actions
78    "native_client/src/trusted/validator_ragel/parse_instruction.rl";
79  include operand_source_actions_amd64_decoder
80    "native_client/src/trusted/validator_ragel/parse_instruction.rl";
81  include immediate_fields_parsing
82    "native_client/src/trusted/validator_ragel/parse_instruction.rl";
83  include relative_fields_decoder_actions
84    "native_client/src/trusted/validator_ragel/parse_instruction.rl";
85  include relative_fields_parsing
86    "native_client/src/trusted/validator_ragel/parse_instruction.rl";
87  include cpuid_actions
88    "native_client/src/trusted/validator_ragel/parse_instruction.rl";
89
90  include decode_x86_64 "decoder_x86_64_instruction.rl";
91
92  action end_of_instruction_cleanup {
93    process_instruction(instruction_begin, current_position + 1, &instruction,
94                        userdata);
95    instruction_begin = current_position + 1;
96    SET_DISPLACEMENT_FORMAT(DISPNONE);
97    SET_IMMEDIATE_FORMAT(IMMNONE);
98    SET_SECOND_IMMEDIATE_FORMAT(IMMNONE);
99    SET_REX_PREFIX(FALSE);
100    SET_DATA16_PREFIX(FALSE);
101    SET_LOCK_PREFIX(FALSE);
102    SET_REPNZ_PREFIX(FALSE);
103    SET_REPZ_PREFIX(FALSE);
104    SET_BRANCH_NOT_TAKEN(FALSE);
105    SET_BRANCH_TAKEN(FALSE);
106    /*
107     * Top three bits of VEX2 are inverted: see AMD/Intel manual.
108     * Pass VEX2 prefix value that corresponds to zero bits.
109     */
110    SET_VEX_PREFIX2(VEX_R | VEX_X | VEX_B);
111    SET_VEX_PREFIX3(0x00);
112    SET_ATT_INSTRUCTION_SUFFIX(NULL);
113    CLEAR_SPURIOUS_REX_B();
114    CLEAR_SPURIOUS_REX_X();
115    CLEAR_SPURIOUS_REX_R();
116    CLEAR_SPURIOUS_REX_W();
117  }
118
119  action report_fatal_error {
120    process_error(current_position, userdata);
121    result = FALSE;
122    goto error_detected;
123  }
124
125  decoder := (one_instruction @end_of_instruction_cleanup)*
126             $!report_fatal_error;
127}%%
128
129/*
130 * The "write data" statement causes Ragel to emit the constant static data
131 * needed by the ragel machine.
132 */
133%% write data;
134
135int DecodeChunkAMD64(const uint8_t *data, size_t size,
136                     ProcessInstructionFunc process_instruction,
137                     ProcessDecodingErrorFunc process_error,
138                     void *userdata) {
139  const uint8_t *current_position = data;
140  const uint8_t *end_position = data + size;
141  const uint8_t *instruction_begin = current_position;
142  /*
143   * Top three bits of VEX2 are inverted: see AMD/Intel manual.
144   * Start with VEX2 prefix value that corresponds to zero bits.
145   */
146  uint8_t vex_prefix2 = VEX_R | VEX_X | VEX_B;
147  uint8_t vex_prefix3 = 0x00;
148  enum ImmediateMode imm_operand = IMMNONE;
149  enum ImmediateMode imm2_operand = IMMNONE;
150  struct Instruction instruction;
151  int result = TRUE;
152
153  int current_state;
154
155  memset(&instruction, 0, sizeof instruction);
156
157  /*
158   * The "write init" statement causes Ragel to emit initialization code.
159   * This should be executed once before the ragel machine is started.
160   */
161  %% write init;
162  /*
163   * The "write exec" statement causes Ragel to emit the ragel machine's
164   * execution code.
165   */
166  %% write exec;
167
168error_detected:
169  return result;
170}
171