Upstream version 11.39.266.0
[platform/framework/web/crosswalk.git] / src / native_client / src / trusted / validator / x86 / ncval_reg_sfi / ncvalidate_utils.c
1 /*
2  * Copyright (c) 2012 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 /* Some useful utilities for validator patterns. */
8
9 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_utils.h"
10
11 #include "native_client/src/include/portability_io.h"
12 #include "native_client/src/shared/platform/nacl_log.h"
13 #include "native_client/src/trusted/validator/x86/decoder/nc_decode_tables.h"
14 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_iter.h"
15 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_state_internal.h"
16 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_trans.h"
17 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_iter.h"
18 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_iter_internal.h"
19
20 /* To turn on debugging of instruction decoding, change value of
21  * DEBUGGING to 1.
22  */
23 #define DEBUGGING 0
24
25 #include "native_client/src/shared/utils/debugging.h"
26
27 #include "native_client/src/trusted/validator/x86/decoder/ncopcode_desc_inl.c"
28 #include "native_client/src/trusted/validator/x86/decoder/ncop_exps_inl.c"
29 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_iter_inl.c"
30
31 const NaClOpFlags NaClOpSetOrUse = NACL_OPFLAG(OpSet) | NACL_OPFLAG(OpUse);
32
33 Bool NaClIsBinaryUsingRegisters(const NaClInst* inst,
34                                 NaClMnemonic name,
35                                 NaClExpVector* vector,
36                                 NaClOpKind reg_1,
37                                 NaClOpKind reg_2) {
38   return name == inst->name &&
39       2 == NaClGetInstNumberOperandsInline(inst) &&
40       /* Note: Since the vector contains a list of operand expressions, the
41        * first operand reference is always at index zero, and its first child
42        * (where the register would be defined) is at index 1.
43        */
44       ExprRegister == vector->node[1].kind &&
45       reg_1 == NaClGetExpRegisterInline(&vector->node[1]) &&
46       /* Note: Since the first subtree is a register operand, it uses
47        * nodes 0 and 1 in the vector (node 0 is the operand reference, and
48        * node 1 is its child defining a register value). The second operand
49        * reference therefore lies at node 2, and if the operand is defined by
50        * a register, it is the first kid of node 2, which is node 3.
51        */
52       ExprRegister == vector->node[3].kind &&
53       reg_2 == NaClGetExpRegisterInline(&vector->node[3]);
54 }
55
56 Bool NaClIsMovUsingRegisters(const NaClDecodeTables* tables,
57                              const NaClInst* inst,
58                              NaClExpVector* vector,
59                              NaClOpKind reg_set,
60                              NaClOpKind reg_use) {
61   return NaClIsBinaryUsingRegisters(inst, InstMov, vector, reg_set, reg_use) &&
62       NACL_OPFLAG(OpSet) ==
63       (NaClGetInstOperandInline(tables, inst, 0)->flags & NaClOpSetOrUse) &&
64       NACL_OPFLAG(OpUse) ==
65       (NaClGetInstOperandInline(tables, inst, 1)->flags & NaClOpSetOrUse);
66 }
67
68 Bool NaClIsBinarySetUsingRegisters(const NaClDecodeTables* tables,
69                                    const NaClInst* inst,
70                                    NaClMnemonic name,
71                                    NaClExpVector* vector,
72                                    NaClOpKind reg_1,
73                                    NaClOpKind reg_2) {
74   return NaClIsBinaryUsingRegisters(inst, name, vector, reg_1, reg_2) &&
75       NaClOpSetOrUse ==
76       (NaClGetInstOperandInline(tables, inst, 0)->flags & NaClOpSetOrUse) &&
77       NACL_OPFLAG(OpUse) ==
78       (NaClGetInstOperandInline(tables, inst, 1)->flags & NaClOpSetOrUse);
79 }
80
81 Bool NaClOperandOneIsRegisterSet(NaClInstState* inst,
82                                  NaClOpKind reg_name) {
83   /* Note: Since the vector contains a list of operand expressions, the
84    * first operand reference is always at index zero, and its first child
85    * (where the register would be defined) is at index 1.
86    */
87   Bool result = FALSE;
88   NaClExpVector* vector = NaClInstStateExpVector(inst);
89   DEBUG(NaClLog(LOG_INFO,
90                 "->NaClOperandOneIsRegisterSet %s\n",
91                 NaClOpKindName(reg_name)));
92   DEBUG(NaClExpVectorPrint(NaClLogGetGio(), inst));
93   if (vector->number_expr_nodes >= 2) {
94     NaClExp* op_reg = &vector->node[1];
95     result = (ExprRegister == op_reg->kind &&
96               reg_name == NaClGetExpRegisterInline(op_reg) &&
97               (op_reg->flags & NACL_EFLAG(ExprSet)));
98   }
99   DEBUG(NaClLog(LOG_INFO,
100                 "<-NaClOperandOneIsRegisterSet = %"NACL_PRIdBool"\n", result));
101   return result;
102 }
103
104 Bool NaClOperandOneZeroExtends(NaClInstState* state) {
105   Bool result = FALSE;
106   const NaClInst* inst = NaClInstStateInst(state);
107   DEBUG(NaClLog(LOG_INFO, "->NaClOperandOneZeroExtends\n"));
108   DEBUG_OR_ERASE(NaClInstPrint(NaClLogGetGio(), state->decoder_tables, inst));
109   result = (1 <= NaClGetInstNumberOperandsInline(inst) &&
110             (NaClGetInstOperandInline(state->decoder_tables, inst, 0)->flags &
111              NACL_OPFLAG(OperandZeroExtends_v)) &&
112             4 == NaClInstStateOperandSize(state));
113   DEBUG(NaClLog(LOG_INFO,
114                 "<-NcOPerandOneZeroExtends = %"NACL_PRIdBool"\n", result));
115   return result;
116 }
117
118 static INLINE Bool NaClAssignsRegisterWithZeroExtends(NaClInstState* state,
119                                         NaClOpKind reg_name) {
120   return NaClOperandOneIsRegisterSet(state, reg_name) &&
121       NaClOperandOneZeroExtends(state);
122 }
123
124 Bool NaClAssignsRegisterWithZeroExtends32(
125     struct NaClValidatorState* state,
126     size_t distance,
127     NaClOpKind reg32) {
128   Bool result = FALSE;
129   DEBUG(NaClLog(LOG_INFO, "zero extend precond? %s %u\n",
130                 NaClOpKindName(reg32), (unsigned) distance));
131 #ifdef NCVAL_TESTING
132   /* Assume we match previous instructions when generating pre/post
133    * conditions.
134    */
135   if (distance > 0) return TRUE;
136 #endif
137
138   if (NaClInstIterHasLookbackStateInline(state->cur_iter, distance)) {
139     result = NaClAssignsRegisterWithZeroExtends(
140         NaClInstIterGetLookbackStateInline(state->cur_iter, distance), reg32);
141   }
142
143   DEBUG(if (result)
144           NaClValidatorMessage(
145               LOG_INFO, state, "zero extends = %d\n", result));
146   return result;
147 }
148
149 Bool NaClAssignsRegisterWithZeroExtends64(
150     struct NaClValidatorState* state,
151     size_t distance,
152     NaClOpKind reg64) {
153   NaClOpKind reg32 = NaClGet32For64BitReg(reg64);
154   return (RegUnknown != reg32) &&
155       NaClAssignsRegisterWithZeroExtends32(state, distance, reg32);
156 }