Statistics
| Branch: | Revision:

root / target-i386 / helper_template.h @ a88790a1

History | View | Annotate | Download (8.6 kB)

1
/*
2
 *  i386 helpers
3
 *
4
 *  Copyright (c) 2008 Fabrice Bellard
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18
 */
19
#define DATA_BITS (1 << (3 + SHIFT))
20
#define SHIFT_MASK (DATA_BITS - 1)
21
#define SIGN_MASK (((target_ulong)1) << (DATA_BITS - 1))
22
#if DATA_BITS <= 32
23
#define SHIFT1_MASK 0x1f
24
#else
25
#define SHIFT1_MASK 0x3f
26
#endif
27

    
28
#if DATA_BITS == 8
29
#define SUFFIX b
30
#define DATA_TYPE uint8_t
31
#define DATA_STYPE int8_t
32
#define DATA_MASK 0xff
33
#elif DATA_BITS == 16
34
#define SUFFIX w
35
#define DATA_TYPE uint16_t
36
#define DATA_STYPE int16_t
37
#define DATA_MASK 0xffff
38
#elif DATA_BITS == 32
39
#define SUFFIX l
40
#define DATA_TYPE uint32_t
41
#define DATA_STYPE int32_t
42
#define DATA_MASK 0xffffffff
43
#elif DATA_BITS == 64
44
#define SUFFIX q
45
#define DATA_TYPE uint64_t
46
#define DATA_STYPE int64_t
47
#define DATA_MASK 0xffffffffffffffffULL
48
#else
49
#error unhandled operand size
50
#endif
51

    
52
/* dynamic flags computation */
53

    
54
static int glue(compute_all_add, SUFFIX)(void)
55
{
56
    int cf, pf, af, zf, sf, of;
57
    target_long src1, src2;
58
    src1 = CC_SRC;
59
    src2 = CC_DST - CC_SRC;
60
    cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1;
61
    pf = parity_table[(uint8_t)CC_DST];
62
    af = (CC_DST ^ src1 ^ src2) & 0x10;
63
    zf = ((DATA_TYPE)CC_DST == 0) << 6;
64
    sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
65
    of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
66
    return cf | pf | af | zf | sf | of;
67
}
68

    
69
static int glue(compute_c_add, SUFFIX)(void)
70
{
71
    int cf;
72
    target_long src1;
73
    src1 = CC_SRC;
74
    cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1;
75
    return cf;
76
}
77

    
78
static int glue(compute_all_adc, SUFFIX)(void)
79
{
80
    int cf, pf, af, zf, sf, of;
81
    target_long src1, src2;
82
    src1 = CC_SRC;
83
    src2 = CC_DST - CC_SRC - 1;
84
    cf = (DATA_TYPE)CC_DST <= (DATA_TYPE)src1;
85
    pf = parity_table[(uint8_t)CC_DST];
86
    af = (CC_DST ^ src1 ^ src2) & 0x10;
87
    zf = ((DATA_TYPE)CC_DST == 0) << 6;
88
    sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
89
    of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
90
    return cf | pf | af | zf | sf | of;
91
}
92

    
93
static int glue(compute_c_adc, SUFFIX)(void)
94
{
95
    int cf;
96
    target_long src1;
97
    src1 = CC_SRC;
98
    cf = (DATA_TYPE)CC_DST <= (DATA_TYPE)src1;
99
    return cf;
100
}
101

    
102
static int glue(compute_all_sub, SUFFIX)(void)
103
{
104
    int cf, pf, af, zf, sf, of;
105
    target_long src1, src2;
106
    src1 = CC_DST + CC_SRC;
107
    src2 = CC_SRC;
108
    cf = (DATA_TYPE)src1 < (DATA_TYPE)src2;
109
    pf = parity_table[(uint8_t)CC_DST];
110
    af = (CC_DST ^ src1 ^ src2) & 0x10;
111
    zf = ((DATA_TYPE)CC_DST == 0) << 6;
112
    sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
113
    of = lshift((src1 ^ src2) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
114
    return cf | pf | af | zf | sf | of;
115
}
116

    
117
static int glue(compute_c_sub, SUFFIX)(void)
118
{
119
    int cf;
120
    target_long src1, src2;
121
    src1 = CC_DST + CC_SRC;
122
    src2 = CC_SRC;
123
    cf = (DATA_TYPE)src1 < (DATA_TYPE)src2;
124
    return cf;
125
}
126

    
127
static int glue(compute_all_sbb, SUFFIX)(void)
128
{
129
    int cf, pf, af, zf, sf, of;
130
    target_long src1, src2;
131
    src1 = CC_DST + CC_SRC + 1;
132
    src2 = CC_SRC;
133
    cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2;
134
    pf = parity_table[(uint8_t)CC_DST];
135
    af = (CC_DST ^ src1 ^ src2) & 0x10;
136
    zf = ((DATA_TYPE)CC_DST == 0) << 6;
137
    sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
138
    of = lshift((src1 ^ src2) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
139
    return cf | pf | af | zf | sf | of;
140
}
141

    
142
static int glue(compute_c_sbb, SUFFIX)(void)
143
{
144
    int cf;
145
    target_long src1, src2;
146
    src1 = CC_DST + CC_SRC + 1;
147
    src2 = CC_SRC;
148
    cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2;
149
    return cf;
150
}
151

    
152
static int glue(compute_all_logic, SUFFIX)(void)
153
{
154
    int cf, pf, af, zf, sf, of;
155
    cf = 0;
156
    pf = parity_table[(uint8_t)CC_DST];
157
    af = 0;
158
    zf = ((DATA_TYPE)CC_DST == 0) << 6;
159
    sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
160
    of = 0;
161
    return cf | pf | af | zf | sf | of;
162
}
163

    
164
static int glue(compute_c_logic, SUFFIX)(void)
165
{
166
    return 0;
167
}
168

    
169
static int glue(compute_all_inc, SUFFIX)(void)
170
{
171
    int cf, pf, af, zf, sf, of;
172
    target_long src1, src2;
173
    src1 = CC_DST - 1;
174
    src2 = 1;
175
    cf = CC_SRC;
176
    pf = parity_table[(uint8_t)CC_DST];
177
    af = (CC_DST ^ src1 ^ src2) & 0x10;
178
    zf = ((DATA_TYPE)CC_DST == 0) << 6;
179
    sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
180
    of = ((CC_DST & DATA_MASK) == SIGN_MASK) << 11;
181
    return cf | pf | af | zf | sf | of;
182
}
183

    
184
#if DATA_BITS == 32
185
static int glue(compute_c_inc, SUFFIX)(void)
186
{
187
    return CC_SRC;
188
}
189
#endif
190

    
191
static int glue(compute_all_dec, SUFFIX)(void)
192
{
193
    int cf, pf, af, zf, sf, of;
194
    target_long src1, src2;
195
    src1 = CC_DST + 1;
196
    src2 = 1;
197
    cf = CC_SRC;
198
    pf = parity_table[(uint8_t)CC_DST];
199
    af = (CC_DST ^ src1 ^ src2) & 0x10;
200
    zf = ((DATA_TYPE)CC_DST == 0) << 6;
201
    sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
202
    of = ((CC_DST & DATA_MASK) == ((target_ulong)SIGN_MASK - 1)) << 11;
203
    return cf | pf | af | zf | sf | of;
204
}
205

    
206
static int glue(compute_all_shl, SUFFIX)(void)
207
{
208
    int cf, pf, af, zf, sf, of;
209
    cf = (CC_SRC >> (DATA_BITS - 1)) & CC_C;
210
    pf = parity_table[(uint8_t)CC_DST];
211
    af = 0; /* undefined */
212
    zf = ((DATA_TYPE)CC_DST == 0) << 6;
213
    sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
214
    /* of is defined if shift count == 1 */
215
    of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_O;
216
    return cf | pf | af | zf | sf | of;
217
}
218

    
219
static int glue(compute_c_shl, SUFFIX)(void)
220
{
221
    return (CC_SRC >> (DATA_BITS - 1)) & CC_C;
222
}
223

    
224
#if DATA_BITS == 32
225
static int glue(compute_c_sar, SUFFIX)(void)
226
{
227
    return CC_SRC & 1;
228
}
229
#endif
230

    
231
static int glue(compute_all_sar, SUFFIX)(void)
232
{
233
    int cf, pf, af, zf, sf, of;
234
    cf = CC_SRC & 1;
235
    pf = parity_table[(uint8_t)CC_DST];
236
    af = 0; /* undefined */
237
    zf = ((DATA_TYPE)CC_DST == 0) << 6;
238
    sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
239
    /* of is defined if shift count == 1 */
240
    of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_O;
241
    return cf | pf | af | zf | sf | of;
242
}
243

    
244
#if DATA_BITS == 32
245
static int glue(compute_c_mul, SUFFIX)(void)
246
{
247
    int cf;
248
    cf = (CC_SRC != 0);
249
    return cf;
250
}
251
#endif
252

    
253
/* NOTE: we compute the flags like the P4. On olders CPUs, only OF and
254
   CF are modified and it is slower to do that. */
255
static int glue(compute_all_mul, SUFFIX)(void)
256
{
257
    int cf, pf, af, zf, sf, of;
258
    cf = (CC_SRC != 0);
259
    pf = parity_table[(uint8_t)CC_DST];
260
    af = 0; /* undefined */
261
    zf = ((DATA_TYPE)CC_DST == 0) << 6;
262
    sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
263
    of = cf << 11;
264
    return cf | pf | af | zf | sf | of;
265
}
266

    
267
/* shifts */
268

    
269
target_ulong glue(helper_rcl, SUFFIX)(target_ulong t0, target_ulong t1)
270
{
271
    int count, eflags;
272
    target_ulong src;
273
    target_long res;
274

    
275
    count = t1 & SHIFT1_MASK;
276
#if DATA_BITS == 16
277
    count = rclw_table[count];
278
#elif DATA_BITS == 8
279
    count = rclb_table[count];
280
#endif
281
    if (count) {
282
        eflags = helper_cc_compute_all(CC_OP);
283
        t0 &= DATA_MASK;
284
        src = t0;
285
        res = (t0 << count) | ((target_ulong)(eflags & CC_C) << (count - 1));
286
        if (count > 1)
287
            res |= t0 >> (DATA_BITS + 1 - count);
288
        t0 = res;
289
        env->cc_tmp = (eflags & ~(CC_C | CC_O)) |
290
            (lshift(src ^ t0, 11 - (DATA_BITS - 1)) & CC_O) |
291
            ((src >> (DATA_BITS - count)) & CC_C);
292
    } else {
293
        env->cc_tmp = -1;
294
    }
295
    return t0;
296
}
297

    
298
target_ulong glue(helper_rcr, SUFFIX)(target_ulong t0, target_ulong t1)
299
{
300
    int count, eflags;
301
    target_ulong src;
302
    target_long res;
303

    
304
    count = t1 & SHIFT1_MASK;
305
#if DATA_BITS == 16
306
    count = rclw_table[count];
307
#elif DATA_BITS == 8
308
    count = rclb_table[count];
309
#endif
310
    if (count) {
311
        eflags = helper_cc_compute_all(CC_OP);
312
        t0 &= DATA_MASK;
313
        src = t0;
314
        res = (t0 >> count) | ((target_ulong)(eflags & CC_C) << (DATA_BITS - count));
315
        if (count > 1)
316
            res |= t0 << (DATA_BITS + 1 - count);
317
        t0 = res;
318
        env->cc_tmp = (eflags & ~(CC_C | CC_O)) |
319
            (lshift(src ^ t0, 11 - (DATA_BITS - 1)) & CC_O) |
320
            ((src >> (count - 1)) & CC_C);
321
    } else {
322
        env->cc_tmp = -1;
323
    }
324
    return t0;
325
}
326

    
327
#undef DATA_BITS
328
#undef SHIFT_MASK
329
#undef SHIFT1_MASK
330
#undef SIGN_MASK
331
#undef DATA_TYPE
332
#undef DATA_STYPE
333
#undef DATA_MASK
334
#undef SUFFIX