I am not sure if I should post this here or on bugzilla. 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 Devel@XFree86.Org http://XFree86.Org/mailman/listinfo/devel