Commit d36cd60e6c8c66e0279bad4b17e2d23833eb20b9
1 parent
5e809a80
P4 style multiplication eflags
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@481 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
49 additions
and
24 deletions
target-i386/cpu.h
... | ... | @@ -184,7 +184,10 @@ |
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, | ... | ... |
target-i386/op.c
... | ... | @@ -169,11 +169,16 @@ void OPPROTO op_bswapl_T0(void) |
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,6 +187,7 @@ void OPPROTO op_imulb_AL_T0(void) |
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,6 +197,7 @@ void OPPROTO op_mulw_AX_T0(void) |
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,6 +207,7 @@ void OPPROTO op_imulw_AX_T0(void) |
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,6 +217,7 @@ void OPPROTO op_mull_EAX_T0(void) |
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,6 +227,7 @@ void OPPROTO op_imull_EAX_T0(void) |
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,6 +236,7 @@ void OPPROTO op_imulw_T0_T1(void) |
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,6 +245,7 @@ void OPPROTO op_imull_T0_T1(void) |
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,31 +1305,14 @@ static int compute_c_eflags(void) |
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 }, | ... | ... |
target-i386/ops_template.h
... | ... | @@ -229,6 +229,29 @@ static int glue(compute_all_sar, SUFFIX)(void) |
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) | ... | ... |
target-i386/translate.c
... | ... | @@ -2016,31 +2016,35 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
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,7 +2239,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
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 */ | ... | ... |