Re: x86 emulator bug
Alex Deucher <[email protected]>
| Newsgroups | gmane.comp.xfree86.devel |
|---|---|
| Message-ID | <[email protected]> |
On Thu, 10 Feb 2005 10:08:20 -0000, Charles Dobson <[email protected]> wrote: > I am not sure if I should post this here or on bugzilla. post your patch in bugzilla. Thanks, Alex > > While trying to get a Silicon Motion SM722 video controller > working with Solaris, I have discovered a problem with the > emulation of the SHLD and SHRD (double precision shift) > instructions of the x86 emulator. > According to the Intel Pentium User Guide Vol 3, these > instructions can shift upto 31 bits with both 16 and 32 > bit operands. The emulator code will only work with shifts > of upto 15 bits for 16 bit operands. > > The file is > xc/extras/x86emu/src/x86emu/prim_ops.c > > I have modified the two functions as below. > I am not positive the flags are set correctly so > would appreciated someone else to check these. > > u16 shld_word (u16 d, u16 fill, u8 s) > { > unsigned int cnt, res, cf; > > if (s < 32) { > cnt = s % 32; > if (cnt > 0) { > if (cnt > 15) { > res = (unsigned int)fill << (cnt - 16); > if (cnt == 16) > cf = d & 0x1; > else > cf = res & 0x10000; > } > else { > res = (d << cnt) | (fill >> (16-cnt)); > cf = d & (1 << (16 - cnt)); > } > CONDITIONAL_SET_FLAG(cf, F_CF); > CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); > CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); > CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); > } else { > res = d; > } > if (cnt == 1) { > CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^ > (ACCESS_FLAG(F_CF) != 0)), F_OF); > } else { > CLEAR_FLAG(F_OF); > } > } else { > res = 0; > CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF); > CLEAR_FLAG(F_OF); > CLEAR_FLAG(F_SF); > SET_FLAG(F_PF); > SET_FLAG(F_ZF); > } > return (u16)res; > } > > u16 shrd_word (u16 d, u16 fill, u8 s) > { > unsigned int cnt, res, cf; > > if (s < 32) { > cnt = s % 32; > if (cnt > 0) { > if (cnt > 15) { > if (cnt == 16) > cf = d & 0x8000; > else > cf = fill & (1 << (cnt - 17)); > res = fill >> (cnt - 16); > } else { > cf = d & (1 << (cnt - 1)); > res = (d >> cnt) | (fill << (16 - cnt)); > } > CONDITIONAL_SET_FLAG(cf, F_CF); > CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); > CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); > CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); > } else { > res = d; > } > > if (cnt == 1) { > CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF); > } else { > CLEAR_FLAG(F_OF); > } > } else { > res = 0; > CLEAR_FLAG(F_CF); > CLEAR_FLAG(F_OF); > SET_FLAG(F_ZF); > CLEAR_FLAG(F_SF); > CLEAR_FLAG(F_PF); > } > return (u16)res; > } > > Charles Dobson. > Concurrent Technologies Plc. > > _______________________________________________ > Devel mailing list > [email protected] > http://XFree86.Org/mailman/listinfo/devel >