master
inc 213 lines 5.54 KB
Raw
1 /*
2 * x86 condition code helpers for AF/CF/OF
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.1 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
22 #if DATA_BITS == 8
23 #define SUFFIX b
24 #define DATA_TYPE uint8_t
25 #define WIDER_TYPE uint32_t
26 #elif DATA_BITS == 16
27 #define SUFFIX w
28 #define DATA_TYPE uint16_t
29 #define WIDER_TYPE uint32_t
30 #elif DATA_BITS == 32
31 #define SUFFIX l
32 #define DATA_TYPE uint32_t
33 #if HOST_LONG_BITS >= 64
34 #define WIDER_TYPE uint64_t
35 #endif
36 #elif DATA_BITS == 64
37 #define SUFFIX q
38 #define DATA_TYPE uint64_t
39 #else
40 #error unhandled operand size
41 #endif
42
43 #define SIGN_MASK (((DATA_TYPE)1) << (DATA_BITS - 1))
44
45 /* dynamic flags computation */
46
47 static uint32_t glue(compute_aco_cout, SUFFIX)(DATA_TYPE carries)
48 {
49 uint32_t af_cf, of;
50
51 /*
52 * AF, CF, OF computed from carry out vector. To compute AF and CF, rotate it
53 * left by one so cout(DATA_BITS - 1) is in bit 0 and cout(3) in bit 4.
54 *
55 * To compute OF, place the highest two carry bits into OF and the bit
56 * immediately to the right of it; then, adding CC_O / 2 XORs them.
57 */
58 af_cf = ((carries << 1) | (carries >> (DATA_BITS - 1))) & (CC_A | CC_C);
59 of = (lshift(carries, 12 - DATA_BITS) + CC_O / 2) & CC_O;
60 return af_cf + of;
61 }
62
63 static uint32_t glue(compute_aco_add, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
64 {
65 DATA_TYPE src2 = dst - src1;
66 DATA_TYPE carries = ADD_COUT_VEC(src1, src2, dst);
67 return glue(compute_aco_cout, SUFFIX)(carries);
68 }
69
70 static int glue(compute_c_add, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
71 {
72 return dst < src1;
73 }
74
75 static uint32_t glue(compute_aco_adc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1,
76 DATA_TYPE src3)
77 {
78 DATA_TYPE src2 = dst - src1 - src3;
79 DATA_TYPE carries = ADD_COUT_VEC(src1, src2, dst);
80 return glue(compute_aco_cout, SUFFIX)(carries);
81 }
82
83 static int glue(compute_c_adc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1,
84 DATA_TYPE src3)
85 {
86 #ifdef WIDER_TYPE
87 WIDER_TYPE src13 = (WIDER_TYPE) src1 + (WIDER_TYPE) src3;
88
89 return dst < src13;
90 #else
91 return src3 ? dst <= src1 : dst < src1;
92 #endif
93 }
94
95 static uint32_t glue(compute_aco_sub, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2)
96 {
97 DATA_TYPE src1 = dst + src2;
98 DATA_TYPE carries = SUB_COUT_VEC(src1, src2, dst);
99 return glue(compute_aco_cout, SUFFIX)(carries);
100 }
101
102 static int glue(compute_c_sub, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2)
103 {
104 DATA_TYPE src1 = dst + src2;
105
106 return src1 < src2;
107 }
108
109 static uint32_t glue(compute_aco_sbb, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2,
110 DATA_TYPE src3)
111 {
112 DATA_TYPE src1 = dst + src2 + src3;
113 DATA_TYPE carries = SUB_COUT_VEC(src1, src2, dst);
114 return glue(compute_aco_cout, SUFFIX)(carries);
115 }
116
117 static int glue(compute_c_sbb, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2,
118 DATA_TYPE src3)
119 {
120 #ifdef WIDER_TYPE
121 WIDER_TYPE src23 = (WIDER_TYPE) src2 + (WIDER_TYPE) src3;
122 DATA_TYPE src1 = dst + src23;
123
124 return src1 < src23;
125 #else
126 DATA_TYPE src1 = dst + src2 + src3;
127
128 return (src3 ? src1 <= src2 : src1 < src2);
129 #endif
130 }
131
132 static uint32_t glue(compute_aco_inc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
133 {
134 uint32_t cf, af, of;
135
136 cf = src1;
137 af = (dst ^ (dst - 1)) & CC_A; /* bits 0..3 are all clear */
138 of = (dst == SIGN_MASK) * CC_O;
139 return cf + af + of;
140 }
141
142 static uint32_t glue(compute_aco_dec, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
143 {
144 uint32_t cf, af, of;
145
146 cf = src1;
147 af = (dst ^ (dst + 1)) & CC_A; /* bits 0..3 are all set */
148 of = (dst == SIGN_MASK - 1) * CC_O;
149 return cf + af + of;
150 }
151
152 static uint32_t glue(compute_aco_shl, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
153 {
154 uint32_t cf, af, of;
155
156 cf = (src1 >> (DATA_BITS - 1)) & CC_C;
157 af = 0; /* undefined */
158 /* of is defined iff shift count == 1 */
159 of = lshift(src1 ^ dst, 12 - DATA_BITS) & CC_O;
160 return cf + af + of;
161 }
162
163 static int glue(compute_c_shl, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
164 {
165 return (src1 >> (DATA_BITS - 1)) & CC_C;
166 }
167
168 static uint32_t glue(compute_aco_sar, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
169 {
170 uint32_t cf, af, of;
171
172 cf = src1 & 1;
173 af = 0; /* undefined */
174 /* of is defined iff shift count == 1 */
175 of = lshift(src1 ^ dst, 12 - DATA_BITS) & CC_O;
176 return cf + af + of;
177 }
178
179 static uint32_t glue(compute_aco_bmilg, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
180 {
181 uint32_t cf, af, of;
182
183 cf = (src1 == 0);
184 af = 0; /* undefined */
185 of = 0;
186 return cf + af + of;
187 }
188
189 static int glue(compute_c_bmilg, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
190 {
191 return src1 == 0;
192 }
193
194 static int glue(compute_aco_blsi, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
195 {
196 uint32_t cf, af, of;
197
198 cf = (src1 != 0);
199 af = 0; /* undefined */
200 of = 0;
201 return cf + af + of;
202 }
203
204 static int glue(compute_c_blsi, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
205 {
206 return src1 != 0;
207 }
208
209 #undef DATA_BITS
210 #undef SIGN_MASK
211 #undef DATA_TYPE
212 #undef SUFFIX
213 #undef WIDER_TYPE