Revision d36cd60e
b/target-i386/cpu.h | ||
---|---|---|
184 | 184 |
enum { |
185 | 185 |
CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */ |
186 | 186 |
CC_OP_EFLAGS, /* all cc are explicitely computed, CC_SRC = flags */ |
187 |
CC_OP_MUL, /* modify all flags, C, O = (CC_SRC != 0) */ |
|
187 |
|
|
188 |
CC_OP_MULB, /* modify all flags, C, O = (CC_SRC != 0) */ |
|
189 |
CC_OP_MULW, |
|
190 |
CC_OP_MULL, |
|
188 | 191 |
|
189 | 192 |
CC_OP_ADDB, /* modify all flags, CC_DST = res, CC_SRC = src1 */ |
190 | 193 |
CC_OP_ADDW, |
b/target-i386/op.c | ||
---|---|---|
169 | 169 |
} |
170 | 170 |
|
171 | 171 |
/* multiply/divide */ |
172 |
|
|
173 |
/* XXX: add eflags optimizations */ |
|
174 |
/* XXX: add non P4 style flags */ |
|
175 |
|
|
172 | 176 |
void OPPROTO op_mulb_AL_T0(void) |
173 | 177 |
{ |
174 | 178 |
unsigned int res; |
175 | 179 |
res = (uint8_t)EAX * (uint8_t)T0; |
176 | 180 |
EAX = (EAX & 0xffff0000) | res; |
181 |
CC_DST = res; |
|
177 | 182 |
CC_SRC = (res & 0xff00); |
178 | 183 |
} |
179 | 184 |
|
... | ... | |
182 | 187 |
int res; |
183 | 188 |
res = (int8_t)EAX * (int8_t)T0; |
184 | 189 |
EAX = (EAX & 0xffff0000) | (res & 0xffff); |
190 |
CC_DST = res; |
|
185 | 191 |
CC_SRC = (res != (int8_t)res); |
186 | 192 |
} |
187 | 193 |
|
... | ... | |
191 | 197 |
res = (uint16_t)EAX * (uint16_t)T0; |
192 | 198 |
EAX = (EAX & 0xffff0000) | (res & 0xffff); |
193 | 199 |
EDX = (EDX & 0xffff0000) | ((res >> 16) & 0xffff); |
200 |
CC_DST = res; |
|
194 | 201 |
CC_SRC = res >> 16; |
195 | 202 |
} |
196 | 203 |
|
... | ... | |
200 | 207 |
res = (int16_t)EAX * (int16_t)T0; |
201 | 208 |
EAX = (EAX & 0xffff0000) | (res & 0xffff); |
202 | 209 |
EDX = (EDX & 0xffff0000) | ((res >> 16) & 0xffff); |
210 |
CC_DST = res; |
|
203 | 211 |
CC_SRC = (res != (int16_t)res); |
204 | 212 |
} |
205 | 213 |
|
... | ... | |
209 | 217 |
res = (uint64_t)((uint32_t)EAX) * (uint64_t)((uint32_t)T0); |
210 | 218 |
EAX = res; |
211 | 219 |
EDX = res >> 32; |
220 |
CC_DST = res; |
|
212 | 221 |
CC_SRC = res >> 32; |
213 | 222 |
} |
214 | 223 |
|
... | ... | |
218 | 227 |
res = (int64_t)((int32_t)EAX) * (int64_t)((int32_t)T0); |
219 | 228 |
EAX = res; |
220 | 229 |
EDX = res >> 32; |
230 |
CC_DST = res; |
|
221 | 231 |
CC_SRC = (res != (int32_t)res); |
222 | 232 |
} |
223 | 233 |
|
... | ... | |
226 | 236 |
int res; |
227 | 237 |
res = (int16_t)T0 * (int16_t)T1; |
228 | 238 |
T0 = res; |
239 |
CC_DST = res; |
|
229 | 240 |
CC_SRC = (res != (int16_t)res); |
230 | 241 |
} |
231 | 242 |
|
... | ... | |
234 | 245 |
int64_t res; |
235 | 246 |
res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1); |
236 | 247 |
T0 = res; |
248 |
CC_DST = res; |
|
237 | 249 |
CC_SRC = (res != (int32_t)res); |
238 | 250 |
} |
239 | 251 |
|
... | ... | |
1293 | 1305 |
return CC_SRC & CC_C; |
1294 | 1306 |
} |
1295 | 1307 |
|
1296 |
static int compute_c_mul(void) |
|
1297 |
{ |
|
1298 |
int cf; |
|
1299 |
cf = (CC_SRC != 0); |
|
1300 |
return cf; |
|
1301 |
} |
|
1302 |
|
|
1303 |
static int compute_all_mul(void) |
|
1304 |
{ |
|
1305 |
int cf, pf, af, zf, sf, of; |
|
1306 |
cf = (CC_SRC != 0); |
|
1307 |
pf = 0; /* undefined */ |
|
1308 |
af = 0; /* undefined */ |
|
1309 |
zf = 0; /* undefined */ |
|
1310 |
sf = 0; /* undefined */ |
|
1311 |
of = cf << 11; |
|
1312 |
return cf | pf | af | zf | sf | of; |
|
1313 |
} |
|
1314 |
|
|
1315 | 1308 |
CCTable cc_table[CC_OP_NB] = { |
1316 | 1309 |
[CC_OP_DYNAMIC] = { /* should never happen */ }, |
1317 | 1310 |
|
1318 | 1311 |
[CC_OP_EFLAGS] = { compute_all_eflags, compute_c_eflags }, |
1319 | 1312 |
|
1320 |
[CC_OP_MUL] = { compute_all_mul, compute_c_mul }, |
|
1313 |
[CC_OP_MULB] = { compute_all_mulb, compute_c_mull }, |
|
1314 |
[CC_OP_MULW] = { compute_all_mulw, compute_c_mull }, |
|
1315 |
[CC_OP_MULL] = { compute_all_mull, compute_c_mull }, |
|
1321 | 1316 |
|
1322 | 1317 |
[CC_OP_ADDB] = { compute_all_addb, compute_c_addb }, |
1323 | 1318 |
[CC_OP_ADDW] = { compute_all_addw, compute_c_addw }, |
b/target-i386/ops_template.h | ||
---|---|---|
229 | 229 |
return cf | pf | af | zf | sf | of; |
230 | 230 |
} |
231 | 231 |
|
232 |
#if DATA_BITS == 32 |
|
233 |
static int glue(compute_c_mul, SUFFIX)(void) |
|
234 |
{ |
|
235 |
int cf; |
|
236 |
cf = (CC_SRC != 0); |
|
237 |
return cf; |
|
238 |
} |
|
239 |
#endif |
|
240 |
|
|
241 |
/* NOTE: we compute the flags like the P4. On olders CPUs, only OF and |
|
242 |
CF are modified and it is slower to do that. */ |
|
243 |
static int glue(compute_all_mul, SUFFIX)(void) |
|
244 |
{ |
|
245 |
int cf, pf, af, zf, sf, of; |
|
246 |
cf = (CC_SRC != 0); |
|
247 |
pf = parity_table[(uint8_t)CC_DST]; |
|
248 |
af = 0; /* undefined */ |
|
249 |
zf = ((DATA_TYPE)CC_DST == 0) << 6; |
|
250 |
sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; |
|
251 |
of = cf << 11; |
|
252 |
return cf | pf | af | zf | sf | of; |
|
253 |
} |
|
254 |
|
|
232 | 255 |
/* various optimized jumps cases */ |
233 | 256 |
|
234 | 257 |
void OPPROTO glue(op_jb_sub, SUFFIX)(void) |
b/target-i386/translate.c | ||
---|---|---|
2016 | 2016 |
switch(ot) { |
2017 | 2017 |
case OT_BYTE: |
2018 | 2018 |
gen_op_mulb_AL_T0(); |
2019 |
s->cc_op = CC_OP_MULB; |
|
2019 | 2020 |
break; |
2020 | 2021 |
case OT_WORD: |
2021 | 2022 |
gen_op_mulw_AX_T0(); |
2023 |
s->cc_op = CC_OP_MULW; |
|
2022 | 2024 |
break; |
2023 | 2025 |
default: |
2024 | 2026 |
case OT_LONG: |
2025 | 2027 |
gen_op_mull_EAX_T0(); |
2028 |
s->cc_op = CC_OP_MULL; |
|
2026 | 2029 |
break; |
2027 | 2030 |
} |
2028 |
s->cc_op = CC_OP_MUL; |
|
2029 | 2031 |
break; |
2030 | 2032 |
case 5: /* imul */ |
2031 | 2033 |
switch(ot) { |
2032 | 2034 |
case OT_BYTE: |
2033 | 2035 |
gen_op_imulb_AL_T0(); |
2036 |
s->cc_op = CC_OP_MULB; |
|
2034 | 2037 |
break; |
2035 | 2038 |
case OT_WORD: |
2036 | 2039 |
gen_op_imulw_AX_T0(); |
2040 |
s->cc_op = CC_OP_MULW; |
|
2037 | 2041 |
break; |
2038 | 2042 |
default: |
2039 | 2043 |
case OT_LONG: |
2040 | 2044 |
gen_op_imull_EAX_T0(); |
2045 |
s->cc_op = CC_OP_MULL; |
|
2041 | 2046 |
break; |
2042 | 2047 |
} |
2043 |
s->cc_op = CC_OP_MUL; |
|
2044 | 2048 |
break; |
2045 | 2049 |
case 6: /* div */ |
2046 | 2050 |
switch(ot) { |
... | ... | |
2235 | 2239 |
gen_op_imulw_T0_T1(); |
2236 | 2240 |
} |
2237 | 2241 |
gen_op_mov_reg_T0[ot][reg](); |
2238 |
s->cc_op = CC_OP_MUL; |
|
2242 |
s->cc_op = CC_OP_MULB + ot;
|
|
2239 | 2243 |
break; |
2240 | 2244 |
case 0x1c0: |
2241 | 2245 |
case 0x1c1: /* xadd Ev, Gv */ |
Also available in: Unified diff