]>
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 | ||
7923057b BS |
44 | target_ulong glue(helper_rcl, SUFFIX)(CPUX86State *env, target_ulong t0, |
45 | target_ulong t1) | |
38de4c46 BS |
46 | { |
47 | int count, eflags; | |
48 | target_ulong src; | |
49 | target_long res; | |
50 | ||
51 | count = t1 & SHIFT1_MASK; | |
52 | #if DATA_BITS == 16 | |
53 | count = rclw_table[count]; | |
54 | #elif DATA_BITS == 8 | |
55 | count = rclb_table[count]; | |
56 | #endif | |
57 | if (count) { | |
f5847c91 | 58 | eflags = env->cc_src; |
38de4c46 BS |
59 | t0 &= DATA_MASK; |
60 | src = t0; | |
61 | res = (t0 << count) | ((target_ulong)(eflags & CC_C) << (count - 1)); | |
62 | if (count > 1) { | |
63 | res |= t0 >> (DATA_BITS + 1 - count); | |
64 | } | |
65 | t0 = res; | |
f5847c91 | 66 | env->cc_src = (eflags & ~(CC_C | CC_O)) | |
38de4c46 BS |
67 | (lshift(src ^ t0, 11 - (DATA_BITS - 1)) & CC_O) | |
68 | ((src >> (DATA_BITS - count)) & CC_C); | |
38de4c46 BS |
69 | } |
70 | return t0; | |
71 | } | |
72 | ||
7923057b BS |
73 | target_ulong glue(helper_rcr, SUFFIX)(CPUX86State *env, target_ulong t0, |
74 | target_ulong t1) | |
38de4c46 BS |
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) { | |
f5847c91 | 87 | eflags = env->cc_src; |
38de4c46 BS |
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; | |
f5847c91 | 96 | env->cc_src = (eflags & ~(CC_C | CC_O)) | |
38de4c46 BS |
97 | (lshift(src ^ t0, 11 - (DATA_BITS - 1)) & CC_O) | |
98 | ((src >> (count - 1)) & CC_C); | |
38de4c46 BS |
99 | } |
100 | return t0; | |
101 | } | |
102 | ||
103 | #undef DATA_BITS | |
104 | #undef SHIFT_MASK | |
105 | #undef SHIFT1_MASK | |
106 | #undef DATA_TYPE | |
107 | #undef DATA_MASK | |
108 | #undef SUFFIX |