]>
Commit | Line | Data |
---|---|---|
38de4c46 BS |
1 | /* |
2 | * x86 shift 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 | ||
20 | #define DATA_BITS (1 << (3 + SHIFT)) | |
21 | #define SHIFT_MASK (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_MASK 0xff | |
31 | #elif DATA_BITS == 16 | |
32 | #define SUFFIX w | |
33 | #define DATA_MASK 0xffff | |
34 | #elif DATA_BITS == 32 | |
35 | #define SUFFIX l | |
36 | #define DATA_MASK 0xffffffff | |
37 | #elif DATA_BITS == 64 | |
38 | #define SUFFIX q | |
39 | #define DATA_MASK 0xffffffffffffffffULL | |
40 | #else | |
41 | #error unhandled operand size | |
42 | #endif | |
43 | ||
44 | target_ulong glue(helper_rcl, SUFFIX)(target_ulong t0, target_ulong t1) | |
45 | { | |
46 | int count, eflags; | |
47 | target_ulong src; | |
48 | target_long res; | |
49 | ||
50 | count = t1 & SHIFT1_MASK; | |
51 | #if DATA_BITS == 16 | |
52 | count = rclw_table[count]; | |
53 | #elif DATA_BITS == 8 | |
54 | count = rclb_table[count]; | |
55 | #endif | |
56 | if (count) { | |
57 | eflags = helper_cc_compute_all(CC_OP); | |
58 | t0 &= DATA_MASK; | |
59 | src = t0; | |
60 | res = (t0 << count) | ((target_ulong)(eflags & CC_C) << (count - 1)); | |
61 | if (count > 1) { | |
62 | res |= t0 >> (DATA_BITS + 1 - count); | |
63 | } | |
64 | t0 = res; | |
65 | env->cc_tmp = (eflags & ~(CC_C | CC_O)) | | |
66 | (lshift(src ^ t0, 11 - (DATA_BITS - 1)) & CC_O) | | |
67 | ((src >> (DATA_BITS - count)) & CC_C); | |
68 | } else { | |
69 | env->cc_tmp = -1; | |
70 | } | |
71 | return t0; | |
72 | } | |
73 | ||
74 | target_ulong glue(helper_rcr, SUFFIX)(target_ulong t0, target_ulong t1) | |
75 | { | |
76 | int count, eflags; | |
77 | target_ulong src; | |
78 | target_long res; | |
79 | ||
80 | count = t1 & SHIFT1_MASK; | |
81 | #if DATA_BITS == 16 | |
82 | count = rclw_table[count]; | |
83 | #elif DATA_BITS == 8 | |
84 | count = rclb_table[count]; | |
85 | #endif | |
86 | if (count) { | |
87 | eflags = helper_cc_compute_all(CC_OP); | |
88 | t0 &= DATA_MASK; | |
89 | src = t0; | |
90 | res = (t0 >> count) | | |
91 | ((target_ulong)(eflags & CC_C) << (DATA_BITS - count)); | |
92 | if (count > 1) { | |
93 | res |= t0 << (DATA_BITS + 1 - count); | |
94 | } | |
95 | t0 = res; | |
96 | env->cc_tmp = (eflags & ~(CC_C | CC_O)) | | |
97 | (lshift(src ^ t0, 11 - (DATA_BITS - 1)) & CC_O) | | |
98 | ((src >> (count - 1)) & CC_C); | |
99 | } else { | |
100 | env->cc_tmp = -1; | |
101 | } | |
102 | return t0; | |
103 | } | |
104 | ||
105 | #undef DATA_BITS | |
106 | #undef SHIFT_MASK | |
107 | #undef SHIFT1_MASK | |
108 | #undef DATA_TYPE | |
109 | #undef DATA_MASK | |
110 | #undef SUFFIX |