bnd: Drop bnd prefix for relaxed short jmp instructions
[platform/upstream/nasm.git] / disp8.c
1 /* ----------------------------------------------------------------------- *
2  *
3  *   Copyright 1996-2013 The NASM Authors - All Rights Reserved
4  *   See the file AUTHORS included with the NASM distribution for
5  *   the specific copyright holders.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following
9  *   conditions are met:
10  *
11  *   * Redistributions of source code must retain the above copyright
12  *     notice, this list of conditions and the following disclaimer.
13  *   * Redistributions in binary form must reproduce the above
14  *     copyright notice, this list of conditions and the following
15  *     disclaimer in the documentation and/or other materials provided
16  *     with the distribution.
17  *
18  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19  *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20  *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21  *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23  *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * ----------------------------------------------------------------------- */
33
34 /*
35  * disp8.c   : Contains a common logic for EVEX compressed displacement
36  */
37
38 #include "disp8.h"
39
40 /*
41  * Find N value for compressed displacement (disp8 * N)
42  */
43 uint8_t get_disp8N(insn *ins)
44 {
45     const uint8_t fv_n[2][2][VLMAX] = {{{16, 32, 64}, {4, 4, 4}},
46                                        {{16, 32, 64}, {8, 8, 8}}};
47     const uint8_t hv_n[2][VLMAX]    =  {{8, 16, 32}, {4, 4, 4}};
48     const uint8_t dup_n[VLMAX]      =   {8, 32, 64};
49
50     bool evex_b           = (ins->evex_p[2] & EVEX_P2B) >> 4;
51     enum ttypes   tuple   = ins->evex_tuple;
52     enum vectlens vectlen = (ins->evex_p[2] & EVEX_P2LL) >> 5;
53     bool evex_w           = (ins->evex_p[1] & EVEX_P1W) >> 7;
54     uint8_t n = 0;
55
56     switch(tuple) {
57     case FV:
58         n = fv_n[evex_w][evex_b][vectlen];
59         break;
60     case HV:
61         n = hv_n[evex_b][vectlen];
62         break;
63
64     case FVM:
65         /* 16, 32, 64 for VL 128, 256, 512 respectively*/
66         n = 1 << (vectlen + 4);
67         break;
68     case T1S8:  /* N = 1 */
69     case T1S16: /* N = 2 */
70         n = tuple - T1S8 + 1;
71         break;
72     case T1S:
73         /* N = 4 for 32bit, 8 for 64bit */
74         n = evex_w ? 8 : 4;
75         break;
76     case T1F32:
77     case T1F64:
78         /* N = 4 for 32bit, 8 for 64bit */
79         n = (tuple == T1F32 ? 4 : 8);
80         break;
81     case T2:
82     case T4:
83     case T8:
84         if (vectlen + 7 <= (evex_w + 5) + (tuple - T2 + 1))
85             n = 0;
86         else
87             n = 1 << (tuple - T2 + evex_w + 3);
88         break;
89     case HVM:
90     case QVM:
91     case OVM:
92         n = 1 << (OVM - tuple + vectlen + 1);
93         break;
94     case M128:
95         n = 16;
96         break;
97     case DUP:
98         n = dup_n[vectlen];
99         break;
100
101     default:
102         break;
103     }
104
105     return n;
106 }
107
108 /*
109  * Check if offset is a multiple of N with corresponding tuple type
110  * if Disp8*N is available, compressed displacement is stored in compdisp
111  */
112 bool is_disp8n(operand *input, insn *ins, int8_t *compdisp)
113 {
114     int32_t off           = input->offset;
115     uint8_t n;
116     int32_t disp8;
117
118     n = get_disp8N(ins);
119
120     if (n && !(off & (n - 1))) {
121         disp8 = off / n;
122         /* if it fits in Disp8 */
123         if (disp8 >= -128 && disp8 <= 127) {
124             *compdisp = disp8;
125             return true;
126         }
127     }
128
129     *compdisp = 0;
130     return false;
131 }