Hello community, here is the log from the commit of package libx86emu for openSUSE:Factory checked in at 2020-01-23 16:08:18 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/libx86emu (Old) and /work/SRC/openSUSE:Factory/.libx86emu.new.26092 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libx86emu" Thu Jan 23 16:08:18 2020 rev:29 rq:765278 version:2.6 Changes: -------- --- /work/SRC/openSUSE:Factory/libx86emu/libx86emu.changes 2019-08-24 18:40:52.841789222 +0200 +++ /work/SRC/openSUSE:Factory/.libx86emu.new.26092/libx86emu.changes 2020-01-23 16:08:26.415547883 +0100 @@ -1,0 +2,41 @@ +Fri Jan 17 12:32:27 UTC 2020 - [email protected] + +- merge gh#wfeldt/libx86emu#17 +- Introduce LDFLAGS variable in Makefiles +- test: Link with the development version of the library +- test: Sort tests by name +- Add Travis CI configuration file and a badge in the README +- Travis CI integration +- 2.6 + +-------------------------------------------------------------------- +Fri Jan 17 12:28:09 UTC 2020 - [email protected] + +- merge gh#wfeldt/libx86emu#22 +- decode: Prepare for SSE support +- ops2: Add SSE instructions +- ops2: Add packed SSE ops +- Minimal SSE support + +-------------------------------------------------------------------- +Fri Jan 17 12:26:51 UTC 2020 - [email protected] + +- merge gh#wfeldt/libx86emu#21 +- prim_ops: Fix compiler warning + +-------------------------------------------------------------------- +Fri Jan 17 12:24:59 UTC 2020 - [email protected] + +- merge gh#wfeldt/libx86emu#24 +- ops2: Add cpuid support using a new handler +- ops2: Introduce a callback function for MSR access +- Push cpuid msr callback + +-------------------------------------------------------------------- +Thu Jan 16 15:45:23 UTC 2020 - [email protected] + +- merge gh#wfeldt/libx86emu#26 +- add '--32' option to demo program to start in 32-bit mode +- 2.5 + +-------------------------------------------------------------------- Old: ---- libx86emu-2.4.tar.xz New: ---- libx86emu-2.6.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libx86emu.spec ++++++ --- /var/tmp/diff_new_pack.Zxqosk/_old 2020-01-23 16:08:27.051548260 +0100 +++ /var/tmp/diff_new_pack.Zxqosk/_new 2020-01-23 16:08:27.051548260 +0100 @@ -22,7 +22,7 @@ Summary: An x86 emulation library License: BSD-3-Clause Group: Development/Libraries/C and C++ -Version: 2.4 +Version: 2.6 Release: 0 Source: %{name}-%{version}.tar.xz Url: https://github.com/wfeldt/libx86emu ++++++ libx86emu-2.4.tar.xz -> libx86emu-2.6.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libx86emu-2.4/.travis.yml new/libx86emu-2.6/.travis.yml --- old/libx86emu-2.4/.travis.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/libx86emu-2.6/.travis.yml 2020-01-17 13:32:27.000000000 +0100 @@ -0,0 +1,9 @@ +language: c + +before_install: +- sudo apt-get update -qq +- sudo apt-get install -qq nasm + +script: +- make +- make -C test diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libx86emu-2.4/Makefile new/libx86emu-2.6/Makefile --- old/libx86emu-2.4/Makefile 2019-08-20 16:23:47.000000000 +0200 +++ new/libx86emu-2.6/Makefile 2020-01-17 13:32:27.000000000 +0100 @@ -13,6 +13,7 @@ CC = gcc CFLAGS = -g -O2 -fPIC -fvisibility=hidden -fomit-frame-pointer -Wall +LDFLAGS = LIBDIR = /usr/lib$(shell ldd /bin/sh | grep -q /lib64/ && echo 64) LIBX86 = libx86emu @@ -42,7 +43,7 @@ install -m 644 -D include/x86emu.h $(DESTDIR)/usr/include/x86emu.h $(LIB_NAME): .depend $(OBJS) - $(CC) -shared -Wl,-soname,$(LIB_SONAME) $(OBJS) -o $(LIB_NAME) + $(CC) -shared -Wl,-soname,$(LIB_SONAME) $(OBJS) -o $(LIB_NAME) $(LDFLAGS) @ln -snf $(LIB_NAME) $(LIB_SONAME) @ln -snf $(LIB_SONAME) $(LIBX86).so diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libx86emu-2.4/README.md new/libx86emu-2.6/README.md --- old/libx86emu-2.4/README.md 2019-08-20 16:23:47.000000000 +0200 +++ new/libx86emu-2.6/README.md 2020-01-17 13:32:27.000000000 +0100 @@ -1,5 +1,7 @@ # x86 emulation library +[](https://travis-ci.org/wfeldt/libx86emu) + libx86emu is a small library to emulate x86 instructions. The focus here is not a complete emulation (go for qemu for this) but to cover enough for typical firmware blobs. At the moment 'regular' 32-bit instructions are covered together with basic protected mode support. @@ -256,6 +258,54 @@ Returns old function. +### x86emu_set_cpuid_handler + +Execution hook + + x86emu_cpuid_handler_t x86emu_set_cpuid_handler(x86emu_t *emu, x86emu_cpuid_handler_t handler); + typedef void (* x86emu_cpuid_handler_t)(x86emu_t *emu); + +Set a callback function that handles the CPUID instruction. +Allows the user to use the host's CPUID or provide a custom implementation +to emulate a specific CPU. + +Returns old function. + +There's no default implementation. Without the handler installed the programm +will raise an #UD exception. + +### x86emu_set_rdmsr_handler + +Execution hook + + x86emu_rdmsr_handler_t x86emu_set_rdmsr_handler(x86emu_t *emu, x86emu_rdmsr_handler_t handler); + typedef void (* x86emu_rdmsr_handler_t)(struct x86emu_s *); + +Set alternative callback function that handles the RDMSR instruction. +Allows the user to use the host's MSR or provide a custom implementation +to emulate a specific platform. + +Returns old function. + +The default callback function uses the *msr* array in the *x86emu_t* structure +to read MSRs from and updates the *msr_perm* array. + +### x86emu_set_wrmsr_handler + +Execution hook + + x86emu_wrmsr_handler_t x86emu_set_wrmsr_handler(x86emu_t *emu, x86emu_wrmsr_handler_t handler); + typedef void (* x86emu_wrmsr_handler_t)(struct x86emu_s *); + +Set alternative callback function that handles the WRMSR instruction. +Allows the user to use the host's MSR or provide a custom implementation +to emulate a specific platform. + +Returns old function. + +The default callback function uses the *msr* array in the *x86emu_t* structure +to write MSRs to and updates the *msr_perm* array. + ### x86emu_intr_raise Raise an interrupt diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libx86emu-2.4/VERSION new/libx86emu-2.6/VERSION --- old/libx86emu-2.4/VERSION 2019-08-20 16:23:47.000000000 +0200 +++ new/libx86emu-2.6/VERSION 2020-01-17 13:32:27.000000000 +0100 @@ -1 +1 @@ -2.4 +2.6 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libx86emu-2.4/api.c new/libx86emu-2.6/api.c --- old/libx86emu-2.4/api.c 2019-08-20 16:23:47.000000000 +0200 +++ new/libx86emu-2.6/api.c 2020-01-17 13:32:27.000000000 +0100 @@ -36,6 +36,22 @@ #define LINE_LEN 16 +static void x86emu_rdmsr(x86emu_t *emu) +{ + unsigned u = emu->x86.R_ECX; + + emu->x86.R_EDX = emu->x86.msr[u] >> 32; + emu->x86.R_EAX = emu->x86.msr[u]; + emu->x86.msr_perm[u] |= X86EMU_ACC_R; +} + +static void x86emu_wrmsr(x86emu_t *emu) +{ + unsigned u = emu->x86.R_ECX; + + emu->x86.msr[u] = ((u64) emu->x86.R_EDX << 32) + emu->x86.R_EAX; + emu->x86.msr_perm[u] |= X86EMU_ACC_W; +} API_SYM x86emu_t *x86emu_new(unsigned def_mem_perm, unsigned def_io_perm) { @@ -50,6 +66,8 @@ if(def_io_perm) x86emu_set_io_perm(emu, 0, X86EMU_IO_PORTS - 1, def_io_perm); x86emu_set_memio_handler(emu, vm_memio); + x86emu_set_rdmsr_handler(emu, x86emu_rdmsr); + x86emu_set_wrmsr_handler(emu, x86emu_wrmsr); x86emu_reset(emu); @@ -179,6 +197,41 @@ return old; } +API_SYM x86emu_cpuid_handler_t x86emu_set_cpuid_handler(x86emu_t *emu, x86emu_cpuid_handler_t handler) +{ + x86emu_cpuid_handler_t old = NULL; + + if(emu) { + old = emu->cpuid; + emu->cpuid = handler; + } + + return old; +} + +API_SYM x86emu_wrmsr_handler_t x86emu_set_wrmsr_handler(x86emu_t *emu, x86emu_wrmsr_handler_t handler) +{ + x86emu_wrmsr_handler_t old = NULL; + + if(emu) { + old = emu->wrmsr; + emu->wrmsr = handler; + } + + return old; +} + +API_SYM x86emu_rdmsr_handler_t x86emu_set_rdmsr_handler(x86emu_t *emu, x86emu_rdmsr_handler_t handler) +{ + x86emu_rdmsr_handler_t old = NULL; + + if(emu) { + old = emu->rdmsr; + emu->rdmsr = handler; + } + + return old; +} API_SYM unsigned x86emu_read_byte(x86emu_t *emu, unsigned addr) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libx86emu-2.4/changelog new/libx86emu-2.6/changelog --- old/libx86emu-2.4/changelog 2019-08-20 16:23:47.000000000 +0200 +++ new/libx86emu-2.6/changelog 2020-01-17 13:32:27.000000000 +0100 @@ -1,3 +1,23 @@ +2020-01-17: 2.6 + - merge gh#wfeldt/libx86emu#24 + - ops2: Add cpuid support using a new handler + - ops2: Introduce a callback function for MSR access + - merge gh#wfeldt/libx86emu#21 + - prim_ops: Fix compiler warning + - merge gh#wfeldt/libx86emu#22 + - decode: Prepare for SSE support + - ops2: Add SSE instructions + - ops2: Add packed SSE ops + - merge gh#wfeldt/libx86emu#17 + - Introduce LDFLAGS variable in Makefiles + - test: Link with the development version of the library + - test: Sort tests by name + - Add Travis CI configuration file and a badge in the README + +2020-01-16: 2.5 + - merge gh#wfeldt/libx86emu#26 + - add '--32' option to demo program to start in 32-bit mode + 2019-08-20: 2.4 - merge gh#wfeldt/libx86emu#19 - decode: Fix compiler warning diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libx86emu-2.4/decode.c new/libx86emu-2.6/decode.c --- old/libx86emu-2.4/decode.c 2019-08-20 16:23:47.000000000 +0200 +++ new/libx86emu-2.6/decode.c 2020-01-17 13:32:27.000000000 +0100 @@ -531,6 +531,22 @@ /**************************************************************************** PARAMETERS: +offset - Offset to load data from + +RETURNS: +Quad long value read from the absolute memory location. +****************************************************************************/ +I128_reg_t fetch_data_qlong(x86emu_t *emu, u32 ofs) +{ + I128_reg_t ret; + for (int i = 0; i < sizeof(I128_reg_t); i++) { + ret.reg[i] = fetch_data_byte(emu, ofs + i); + } + return ret; +} + +/**************************************************************************** +PARAMETERS: segment - Segment to load data from offset - Offset to load data from @@ -630,6 +646,22 @@ /**************************************************************************** PARAMETERS: +offset - Offset to store data at +val - Value to store + +REMARKS: +Writes a qlong value to an segmented memory location. The segment used is +the current 'default' segment, which may have been overridden. +****************************************************************************/ +void store_data_qlong(x86emu_t *emu, u32 ofs, I128_reg_t val) +{ + for (int i = 0; i < sizeof(I128_reg_t); i++) { + store_data_word_abs(emu, get_data_segment(emu), ofs, val.reg[i]); + } +} + +/**************************************************************************** +PARAMETERS: segment - Segment to store data at offset - Offset to store data at val - Value to store @@ -885,6 +917,56 @@ /**************************************************************************** PARAMETERS: +reg - SSE register to decode + +RETURNS: +Pointer to the appropriate register + +REMARKS: +Return a pointer to the register given by the R/RM field of the +modrm byte, for dword operands. Also enables the decoding of instructions. +****************************************************************************/ +I128_reg_t* decode_rm_sse_register(x86emu_t *emu, int reg) +{ + switch(reg) { + case 0: + OP_DECODE("xmm0"); + return &emu->x86.R_XMM0; + + case 1: + OP_DECODE("xmm1"); + return &emu->x86.R_XMM1; + + case 2: + OP_DECODE("xmm2"); + return &emu->x86.R_XMM2; + + case 3: + OP_DECODE("xmm3"); + return &emu->x86.R_XMM3; + + case 4: + OP_DECODE("xmm4"); + return &emu->x86.R_XMM4; + + case 5: + OP_DECODE("xmm5"); + return &emu->x86.R_XMM5; + + case 6: + OP_DECODE("xmm6"); + return &emu->x86.R_XMM6; + + case 7: + OP_DECODE("xmm7"); + return &emu->x86.R_XMM7; + } + + return NULL; /* NOTREACHED OR REACHED ON ERROR */ +} + +/**************************************************************************** +PARAMETERS: reg - Register to decode RETURNS: @@ -997,6 +1079,11 @@ decode_hex4(emu, p, ofs & 0xffff); } +void decode_hex32(x86emu_t *emu, char **p, I128_reg_t ofs) +{ + for (int i = sizeof(ofs.reg) - 1; i >= 0; i--) + decode_hex2(emu, p, ofs.reg[i]); +} void decode_hex_addr(x86emu_t *emu, char **p, u32 ofs) { @@ -1726,6 +1813,25 @@ if(ACCESS_FLAG(F_PF)) LOG_STR(" pf"); if(ACCESS_FLAG(F_CF)) LOG_STR(" cf"); + if (emu->x86.R_CR4 & CR4_OSFXSR) { + LOG_STR("\nxmm0 "); + decode_hex32(emu, p, emu->x86.R_XMM0); + LOG_STR("\nxmm1 "); + decode_hex32(emu, p, emu->x86.R_XMM1); + LOG_STR("\nxmm2 "); + decode_hex32(emu, p, emu->x86.R_XMM2); + LOG_STR("\nxmm3 "); + decode_hex32(emu, p, emu->x86.R_XMM3); + LOG_STR("\nxmm4 "); + decode_hex32(emu, p, emu->x86.R_XMM4); + LOG_STR("\nxmm5 "); + decode_hex32(emu, p, emu->x86.R_XMM5); + LOG_STR("\nxmm6 "); + decode_hex32(emu, p, emu->x86.R_XMM6); + LOG_STR("\nxmm7 "); + decode_hex32(emu, p, emu->x86.R_XMM7); + LOG_STR("\n"); + } LOG_STR("\n"); **p = 0; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libx86emu-2.4/demo/x86emu-demo.c new/libx86emu-2.6/demo/x86emu-demo.c --- old/libx86emu-2.4/demo/x86emu-demo.c 2019-08-20 16:23:47.000000000 +0200 +++ new/libx86emu-2.6/demo/x86emu-demo.c 2020-01-17 13:32:27.000000000 +0100 @@ -22,6 +22,7 @@ { "load", 1, NULL, 'l' }, { "start", 1, NULL, 's' }, { "max", 1, NULL, 'm' }, + { "32", 0, NULL, 1001 }, { } }; @@ -33,6 +34,7 @@ } start; unsigned load; unsigned max_instructions; + unsigned bits_32:1; char *file; } opt; @@ -69,6 +71,10 @@ } break; + case 1001: + opt.bits_32 = 1; + break; + default: help(); return i == 'h' ? 0 : 1; @@ -100,16 +106,13 @@ "Load FILE and run x86 emulation.\n" "\n" "Options:\n" - " -l, --load ADDRESS\n" - " load FILE at ADDRESS into memory (default: 0x7c00).\n" - " -s, --start ADDRESS\n" - " start emulation at ADDRESS (default 0:0x7c00).\n" - " Note: ADDRESS may contain a colon (':') to separate segment and offset values;\n" - " if not, segment = 0 is assumed.\n" - " -m, --max N\n" - " stop after emulating N instructions.\n" - " -h, --help\n" - " show this text\n" + " -l, --load ADDRESS Load FILE at ADDRESS into memory (default 0x7c00).\n" + " -s, --start ADDRESS Start emulation at ADDRESS (default 0:0x7c00).\n" + " ADDRESS may contain a colon (':') to separate segment and\n" + " offset values. Without colon, segment 0 is assumed.\n" + " -m, --max N Stop after emulating N instructions.\n" + " --32 Start in 32-bit mode (default 16-bit mode).\n" + " -h, --help Show this text\n" ); } @@ -154,6 +157,18 @@ x86emu_set_seg_register(emu, emu->x86.R_CS_SEL, opt.start.segment); emu->x86.R_EIP = opt.start.offset; + if(opt.bits_32) { + /* set default data/address size to 32 bit */ + emu->x86.R_CS_ACC |= (1 << 10); + + /* maximize descriptor limits */ + emu->x86.R_CS_LIMIT = + emu->x86.R_DS_LIMIT = + emu->x86.R_ES_LIMIT = + emu->x86.R_FS_LIMIT = + emu->x86.R_GS_LIMIT = + emu->x86.R_SS_LIMIT = ~0; + } if(!(f = fopen(file, "r"))) return 0; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libx86emu-2.4/include/decode.h new/libx86emu-2.6/include/decode.h --- old/libx86emu-2.4/include/decode.h 2019-08-20 16:23:47.000000000 +0200 +++ new/libx86emu-2.6/include/decode.h 2020-01-17 13:32:27.000000000 +0100 @@ -75,12 +75,14 @@ u16 fetch_data_word_abs(x86emu_t *emu, sel_t *seg, u32 offset); u32 fetch_data_long(x86emu_t *emu, u32 offset); u32 fetch_data_long_abs(x86emu_t *emu, sel_t *seg, u32 offset); +I128_reg_t fetch_data_qlong(x86emu_t *emu, u32 ofs); void store_data_byte(x86emu_t *emu, u32 offset, u8 val); void store_data_byte_abs(x86emu_t *emu, sel_t *seg, u32 offset, u8 val); void store_data_word(x86emu_t *emu, u32 offset, u16 val); void store_data_word_abs(x86emu_t *emu, sel_t *seg, u32 offset, u16 val); void store_data_long(x86emu_t *emu, u32 offset, u32 val); void store_data_long_abs(x86emu_t *emu, sel_t *seg, u32 offset, u32 val); +void store_data_qlong(x86emu_t *emu, u32 ofs, I128_reg_t val); u8 fetch_io_byte(x86emu_t *emu, u32 offset); u16 fetch_io_word(x86emu_t *emu, u32 offset); u32 fetch_io_long(x86emu_t *emu, u32 offset); @@ -91,6 +93,7 @@ u16* decode_rm_word_register(x86emu_t *emu, int reg); u32* decode_rm_long_register(x86emu_t *emu, int reg); sel_t *decode_rm_seg_register(x86emu_t *emu, int reg); +I128_reg_t* decode_rm_sse_register(x86emu_t *emu, int reg); u32 decode_rm00_address(x86emu_t *emu, int rm); u32 decode_rm01_address(x86emu_t *emu, int rm); u32 decode_rm10_address(x86emu_t *emu, int rm); @@ -102,6 +105,7 @@ void decode_hex2(x86emu_t *emu, char **p, u32 ofs); void decode_hex4(x86emu_t *emu, char **p, u32 ofs); void decode_hex8(x86emu_t *emu, char **p, u32 ofs); +void decode_hex32(x86emu_t *emu, char **p, I128_reg_t ofs); void decode_hex_addr(x86emu_t *emu, char **p, u32 ofs); void decode_hex2s(x86emu_t *emu, char **p, s32 ofs); void decode_hex4s(x86emu_t *emu, char **p, s32 ofs); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libx86emu-2.4/include/x86emu.h new/libx86emu-2.6/include/x86emu.h --- old/libx86emu-2.4/include/x86emu.h 2019-08-20 16:23:47.000000000 +0200 +++ new/libx86emu-2.6/include/x86emu.h 2020-01-17 13:32:27.000000000 +0100 @@ -58,6 +58,8 @@ #define s32 int32_t #define s64 int64_t +#define FP_SP_SIZE 4 +#define FP_DP_SIZE 8 /* * General EAX, EBX, ECX, EDX type registers. Note that for @@ -77,6 +79,10 @@ #ifdef __BIG_ENDIAN__ typedef struct { + u8 reg[16]; +} I128_reg_t; + +typedef struct { u32 e_reg; } I32_reg_t; @@ -91,6 +97,10 @@ #else /* !__BIG_ENDIAN__ */ typedef struct { + u8 reg[16]; +} I128_reg_t; + +typedef struct { u32 e_reg; } I32_reg_t; @@ -119,6 +129,9 @@ u32 FLAGS; }; +struct i386_see_regs { + I128_reg_t XMM[8]; +}; typedef struct { union { @@ -216,6 +229,16 @@ #define R_EIP spc.IP.I32_reg.e_reg #define R_EFLG spc.FLAGS +/* SSE registers */ +#define R_XMM0 sse.XMM[0] +#define R_XMM1 sse.XMM[1] +#define R_XMM2 sse.XMM[2] +#define R_XMM3 sse.XMM[3] +#define R_XMM4 sse.XMM[4] +#define R_XMM5 sse.XMM[5] +#define R_XMM6 sse.XMM[6] +#define R_XMM7 sse.XMM[7] + /* segment registers */ #define R_ES_INDEX 0 #define R_CS_INDEX 1 @@ -304,15 +327,16 @@ #define R_REAL_TSC msr[0x12] /* flag conditions */ -#define FB_CF 0x0001 /* CARRY flag */ -#define FB_PF 0x0004 /* PARITY flag */ -#define FB_AF 0x0010 /* AUX flag */ -#define FB_ZF 0x0040 /* ZERO flag */ -#define FB_SF 0x0080 /* SIGN flag */ -#define FB_TF 0x0100 /* TRAP flag */ -#define FB_IF 0x0200 /* INTERRUPT ENABLE flag */ -#define FB_DF 0x0400 /* DIR flag */ -#define FB_OF 0x0800 /* OVERFLOW flag */ +#define FB_CF 0x000001 /* CARRY flag */ +#define FB_PF 0x000004 /* PARITY flag */ +#define FB_AF 0x000010 /* AUX flag */ +#define FB_ZF 0x000040 /* ZERO flag */ +#define FB_SF 0x000080 /* SIGN flag */ +#define FB_TF 0x000100 /* TRAP flag */ +#define FB_IF 0x000200 /* INTERRUPT ENABLE flag */ +#define FB_DF 0x000400 /* DIR flag */ +#define FB_OF 0x000800 /* OVERFLOW flag */ +#define FB_ID 0x200000 /* ID flag */ /* 80286 and above always have bit#1 set */ #define F_ALWAYS_ON (0x0002) /* flag bits always on */ @@ -335,6 +359,11 @@ #define F_DF 0x0400 /* DIR flag */ #define F_OF 0x0800 /* OVERFLOW flag */ +#define CR0_MP (1 << 1) +#define CR0_EM (1 << 2) +#define CR4_OSFXSR (1 << 9) +#define CR4_OSXMMEXCPT (1 << 10) + #define X86EMU_TOGGLE_FLAG(emu, flag) (emu->x86.R_FLG ^= (flag)) #define X86EMU_SET_FLAG(emu, flag) (emu->x86.R_FLG |= (flag)) #define X86EMU_CLEAR_FLAG(emu, flag) (emu->x86.R_FLG &= ~(flag)) @@ -380,11 +409,15 @@ typedef unsigned (* x86emu_memio_handler_t)(struct x86emu_s *, u32 addr, u32 *val, unsigned type); typedef int (* x86emu_intr_handler_t)(struct x86emu_s *, u8 num, unsigned type); typedef int (* x86emu_code_handler_t)(struct x86emu_s *); +typedef void (* x86emu_cpuid_handler_t)(struct x86emu_s *); +typedef void (* x86emu_wrmsr_handler_t)(struct x86emu_s *); +typedef void (* x86emu_rdmsr_handler_t)(struct x86emu_s *); typedef void (* x86emu_flush_func_t)(struct x86emu_s *, char *buf, unsigned size); typedef struct { struct i386_general_regs gen; struct i386_special_regs spc; + struct i386_see_regs sse; sel_t seg[8]; sel_t ldt; sel_t tr; @@ -486,8 +519,11 @@ typedef struct x86emu_s { x86emu_regs_t x86; x86emu_code_handler_t code_check; + x86emu_cpuid_handler_t cpuid; x86emu_memio_handler_t memio; x86emu_intr_handler_t intr; + x86emu_wrmsr_handler_t wrmsr; + x86emu_wrmsr_handler_t rdmsr; x86emu_mem_t *mem; struct { unsigned char *map; @@ -532,6 +568,9 @@ void x86emu_set_page(x86emu_t *emu, unsigned page, void *address); void x86emu_reset_access_stats(x86emu_t *emu); +x86emu_rdmsr_handler_t x86emu_set_rdmsr_handler(x86emu_t *emu, x86emu_rdmsr_handler_t handler); +x86emu_wrmsr_handler_t x86emu_set_wrmsr_handler(x86emu_t *emu, x86emu_wrmsr_handler_t handler); +x86emu_cpuid_handler_t x86emu_set_cpuid_handler(x86emu_t *emu, x86emu_cpuid_handler_t handler); x86emu_code_handler_t x86emu_set_code_handler(x86emu_t *emu, x86emu_code_handler_t handler); x86emu_intr_handler_t x86emu_set_intr_handler(x86emu_t *emu, x86emu_intr_handler_t handler); x86emu_memio_handler_t x86emu_set_memio_handler(x86emu_t *emu, x86emu_memio_handler_t handler); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libx86emu-2.4/ops.c new/libx86emu-2.6/ops.c --- old/libx86emu-2.4/ops.c 2019-08-20 16:23:47.000000000 +0200 +++ new/libx86emu-2.6/ops.c 2020-01-17 13:32:27.000000000 +0100 @@ -2386,9 +2386,15 @@ static void x86emuOp_pushf_word(x86emu_t *emu, u8 op1) { u32 flags; + u32 mask = F_MSK; + + if(emu->cpuid) { + /* Advertise CPUID support */ + mask |= FB_ID; + } /* clear out *all* bits not representing flags, and turn on real bits */ - flags = (emu->x86.R_EFLG & F_MSK) | F_ALWAYS_ON; + flags = (emu->x86.R_EFLG & mask) | F_ALWAYS_ON; if(MODE_DATA32) { OP_DECODE("pushfd"); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libx86emu-2.4/ops2.c new/libx86emu-2.6/ops2.c --- old/libx86emu-2.4/ops2.c 2019-08-20 16:23:47.000000000 +0200 +++ new/libx86emu-2.6/ops2.c 2020-01-17 13:32:27.000000000 +0100 @@ -280,6 +280,209 @@ OP_DECODE("wbinvd"); } +static void x86emuOp2_sse_enabled_check(x86emu_t *emu) +{ + if (emu->x86.R_CR0 & CR0_EM || !(emu->x86.R_CR0 & CR0_MP)) + INTR_RAISE_UD(emu); + if (!(emu->x86.R_CR4 & CR4_OSFXSR)) + INTR_RAISE_UD(emu); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x0f,0x10-0x11 0xf,0x28-0x29 0xf,0x2b-0x2c +****************************************************************************/ +static void x86emuOp2_SSEmovops(x86emu_t *emu, u8 op2) +{ + int mod, rl, rh; + I128_reg_t *src, *dst, tmp; + u32 addr = 0; + + switch(op2 & 0xfe) { + case 0x10: + OP_DECODE("movups "); + break; + case 0x28: + OP_DECODE("movaps "); + break; + case 0x2b: + OP_DECODE("movntps "); + break; + } + + x86emuOp2_sse_enabled_check(emu); + + fetch_decode_modrm(emu, &mod, &rh, &rl); + + if(mod == 3) { + dst = decode_rm_sse_register(emu, rh); + OP_DECODE(","); + src = decode_rm_sse_register(emu, rl); + memcpy(dst, src, sizeof(*dst)); + } + else { + if(!(op2 & 1)) { + dst = decode_rm_sse_register(emu, rh); + OP_DECODE(","); + addr = decode_rm_address(emu, mod, rl); + tmp = fetch_data_qlong(emu, addr); + /* check memory alignment if not movups */ + if (((op2 & 0xfe) != 0x10) && (addr & 0xf)) { + INTR_RAISE_GP(emu, 0); + return; + } + memcpy(dst, &tmp, sizeof(*dst)); + } else { + addr = decode_rm_address(emu, mod, rh); + OP_DECODE(","); + src = decode_rm_sse_register(emu, rl); + /* check memory alignment if not movups */ + if(((op2 & 0xfe) != 0x10) && (addr & 0xf)) { + INTR_RAISE_GP(emu, 0); + return; + } + memcpy(&tmp, src, sizeof(tmp)); + store_data_qlong(emu, addr, tmp); + } + } +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x0f,0x12-0x13 0x0f,0x16-0x17 +****************************************************************************/ +static void x86emuOp2_SSEmovpackedops(x86emu_t *emu, u8 op2) +{ + int mod, rl, rh; + I128_reg_t *src, *dst; + u32 addr; + + fetch_decode_modrm(emu, &mod, &rh, &rl); + + switch(op2) { + case 0x12: + if (mod == 3) + OP_DECODE("movhlps "); + else + OP_DECODE("movlps "); + break; + case 0x13: + OP_DECODE("movlps "); + break; + case 0x16: + if (mod == 3) + OP_DECODE("movhlps "); + else + OP_DECODE("movhps "); + break; + case 0x17: + OP_DECODE("movhps "); + break; + default: + INTR_RAISE_UD(emu); + break; + } + + x86emuOp2_sse_enabled_check(emu); + + if(mod == 3) { + dst = decode_rm_sse_register(emu, rh); + OP_DECODE(","); + src = decode_rm_sse_register(emu, rl); + for(int i = 0; i < FP_SP_SIZE * 2; i++) { + if (op2 == 0x12) { + dst->reg[i] = src->reg[i + FP_SP_SIZE * 2]; + } else if (op2 == 0x16) { + dst->reg[i+ FP_SP_SIZE * 2] = src->reg[i]; + } + } + }else{ + if (op2 & 1) { + addr = decode_rm_address(emu, mod, rl); + OP_DECODE(","); + src = decode_rm_sse_register(emu, rh); + + for(int i = 0; i < FP_SP_SIZE * 2; i++) { + if (op2 == 0x13) { + store_data_byte(emu, addr + i, src->reg[i]); + } else if (op2 == 0x17) { + store_data_byte(emu, addr + i, src->reg[i+FP_SP_SIZE*2]); + } + } + } else { + dst = decode_rm_sse_register(emu, rh); + OP_DECODE(","); + addr = decode_rm_address(emu, mod, rl); + + for(int i = 0; i < FP_SP_SIZE * 2; i++) { + if (op2 == 0x12) { + dst->reg[i] = fetch_data_byte(emu, addr + i); + } else if (op2 == 0x16) { + dst->reg[i+FP_SP_SIZE*2] = fetch_data_byte(emu, addr + i); + } + } + } + } +} + + +/**************************************************************************** +REMARKS: +Handles opcode 0x0f,0x14-0x15 +****************************************************************************/ +static void x86emuOp2_SSEpackops(x86emu_t *emu, u8 op2) +{ + int mod, rl, rh, off; + I128_reg_t *src, *dst, tmp, arith; + u32 addr; + + switch(op2) { + case 0x14: + OP_DECODE("unpcklps "); + break; + case 0x15: + OP_DECODE("unpckhps "); + break; + default: + INTR_RAISE_UD(emu); + break; + } + + x86emuOp2_sse_enabled_check(emu); + + fetch_decode_modrm(emu, &mod, &rh, &rl); + + if(mod == 3) { + dst = decode_rm_sse_register(emu, rh); + OP_DECODE(","); + src = decode_rm_sse_register(emu, rl); + } else { + dst = decode_rm_sse_register(emu, rh); + OP_DECODE(","); + addr = decode_rm_address(emu, mod, rl); + tmp = fetch_data_qlong(emu, addr); + src = &tmp; + } + + if(op2 == 0x14) { + off = 0; + } else { + off = 2; + } + + arith.reg[0] = dst->reg[off + 0]; + arith.reg[1] = src->reg[off + 0]; + arith.reg[2] = dst->reg[off + 1]; + arith.reg[3] = src->reg[off + 1]; + arith.reg[4] = dst->reg[off + 4]; + arith.reg[5] = src->reg[off + 4]; + arith.reg[6] = dst->reg[off + 5]; + arith.reg[7] = src->reg[off + 5]; + + for(int i = 0; i < FP_SP_SIZE; i++) { + dst->reg[i] = arith.reg[i]; + } +} /**************************************************************************** REMARKS: @@ -389,8 +592,9 @@ INTR_RAISE_UD(emu); } else { - emu->x86.msr[u] = ((u64) emu->x86.R_EDX << 32) + emu->x86.R_EAX; - emu->x86.msr_perm[u] |= X86EMU_ACC_W; + if(emu->wrmsr) { + emu->wrmsr(emu); + } } } @@ -421,14 +625,13 @@ OP_DECODE("rdmsr"); u = emu->x86.R_ECX; - if(u >= X86EMU_MSRS) { INTR_RAISE_UD(emu); } else { - emu->x86.R_EDX = emu->x86.msr[u] >> 32; - emu->x86.R_EAX = emu->x86.msr[u]; - emu->x86.msr_perm[u] |= X86EMU_ACC_R; + if(emu->rdmsr) { + emu->rdmsr(emu); + } } } @@ -597,6 +800,68 @@ /**************************************************************************** REMARKS: +Handles opcode 0x0f,0x54-57 +****************************************************************************/ +static void x86emuOp2_SSElogicalops(x86emu_t *emu, u8 op2) +{ + int mod, rl, rh; + I128_reg_t *src, *dst, tmp; + u32 addr; + + switch(op2) { + case 0x54: + OP_DECODE("andps "); + break; + case 0x55: + OP_DECODE("andnps "); + break; + case 0x56: + OP_DECODE("orps "); + break; + case 0x57: + OP_DECODE("xorps "); + break; + default: + INTR_RAISE_UD(emu); + break; + } + + x86emuOp2_sse_enabled_check(emu); + + fetch_decode_modrm(emu, &mod, &rh, &rl); + + if(mod == 3) { + dst = decode_rm_sse_register(emu, rh); + OP_DECODE(","); + src = decode_rm_sse_register(emu, rl); + } + else { + dst = decode_rm_sse_register(emu, rh); + OP_DECODE(","); + addr = decode_rm_address(emu, mod, rl); + tmp = fetch_data_qlong(emu, addr); + src = &tmp; + } + for(int i = 0; i < sizeof(dst->reg); i++) { + switch(op2) { + case 0x54: + dst->reg[i] &= src->reg[i]; + break; + case 0x55: + dst->reg[i] &= ~src->reg[i]; + break; + case 0x56: + dst->reg[i] |= src->reg[i]; + break; + case 0x57: + dst->reg[i] ^= src->reg[i]; + break; + } + } +} + +/**************************************************************************** +REMARKS: Handles opcode 0x0f,0x80-0x8F ****************************************************************************/ static void x86emuOp2_long_jump(x86emu_t *emu, u8 op2) @@ -679,6 +944,21 @@ x86emu_set_seg_register(emu, emu->x86.R_FS_SEL, MODE_DATA32 ? pop_long(emu) : pop_word(emu)); } +/**************************************************************************** +REMARKS: +Handles opcode 0x0f,0xa2 +****************************************************************************/ +static void x86emuOp2_cpuid(x86emu_t *emu, u8 op2) +{ + OP_DECODE("cpuid "); + + if(emu->cpuid) { + emu->cpuid(emu); + } + else { + INTR_RAISE_UD(emu); + } +} /**************************************************************************** REMARKS: @@ -1781,14 +2061,14 @@ /* 0x0e */ x86emuOp2_illegal_op, /* 0x0f */ x86emuOp2_illegal_op, - /* 0x10 */ x86emuOp2_illegal_op, - /* 0x11 */ x86emuOp2_illegal_op, - /* 0x12 */ x86emuOp2_illegal_op, - /* 0x13 */ x86emuOp2_illegal_op, - /* 0x14 */ x86emuOp2_illegal_op, - /* 0x15 */ x86emuOp2_illegal_op, - /* 0x16 */ x86emuOp2_illegal_op, - /* 0x17 */ x86emuOp2_illegal_op, + /* 0x10 */ x86emuOp2_SSEmovops, + /* 0x11 */ x86emuOp2_SSEmovops, + /* 0x12 */ x86emuOp2_SSEmovpackedops, + /* 0x13 */ x86emuOp2_SSEmovpackedops, + /* 0x14 */ x86emuOp2_SSEpackops, + /* 0x15 */ x86emuOp2_SSEpackops, + /* 0x16 */ x86emuOp2_SSEmovpackedops, + /* 0x17 */ x86emuOp2_SSEmovpackedops, /* 0x18 */ x86emuOp2_illegal_op, /* 0x19 */ x86emuOp2_illegal_op, /* 0x1a */ x86emuOp2_illegal_op, @@ -1806,11 +2086,11 @@ /* 0x25 */ x86emuOp2_illegal_op, /* 0x26 */ x86emuOp2_illegal_op, /* mov treg,reg32 (ring 0 PM) */ /* 0x27 */ x86emuOp2_illegal_op, - /* 0x28 */ x86emuOp2_illegal_op, - /* 0x29 */ x86emuOp2_illegal_op, + /* 0x28 */ x86emuOp2_SSEmovops, + /* 0x29 */ x86emuOp2_SSEmovops, /* 0x2a */ x86emuOp2_illegal_op, - /* 0x2b */ x86emuOp2_illegal_op, - /* 0x2c */ x86emuOp2_illegal_op, + /* 0x2b */ x86emuOp2_SSEmovops, + /* 0x2c */ x86emuOp2_SSEmovops, /* 0x2d */ x86emuOp2_illegal_op, /* 0x2e */ x86emuOp2_illegal_op, /* 0x2f */ x86emuOp2_illegal_op, @@ -1853,10 +2133,10 @@ /* 0x51 */ x86emuOp2_illegal_op, /* 0x52 */ x86emuOp2_illegal_op, /* 0x53 */ x86emuOp2_illegal_op, - /* 0x54 */ x86emuOp2_illegal_op, - /* 0x55 */ x86emuOp2_illegal_op, - /* 0x56 */ x86emuOp2_illegal_op, - /* 0x57 */ x86emuOp2_illegal_op, + /* 0x54 */ x86emuOp2_SSElogicalops, + /* 0x55 */ x86emuOp2_SSElogicalops, + /* 0x56 */ x86emuOp2_SSElogicalops, + /* 0x57 */ x86emuOp2_SSElogicalops, /* 0x58 */ x86emuOp2_illegal_op, /* 0x59 */ x86emuOp2_illegal_op, /* 0x5a */ x86emuOp2_illegal_op, @@ -1936,7 +2216,7 @@ /* 0xa0 */ x86emuOp2_push_FS, /* 0xa1 */ x86emuOp2_pop_FS, - /* 0xa2 */ x86emuOp2_illegal_op, + /* 0xa2 */ x86emuOp2_cpuid, /* 0xa3 */ x86emuOp2_bt_R, /* 0xa4 */ x86emuOp2_shld_IMM, /* 0xa5 */ x86emuOp2_shld_CL, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libx86emu-2.4/prim_ops.c new/libx86emu-2.6/prim_ops.c --- old/libx86emu-2.4/prim_ops.c 2019-08-20 16:23:47.000000000 +0200 +++ new/libx86emu-2.6/prim_ops.c 2020-01-17 13:32:27.000000000 +0100 @@ -2684,6 +2684,7 @@ case 3: /* BE */ cond = (flags & F_CF) != 0; + /* fallthrough */ case 2: /* Z */ cond |= (flags & F_ZF) != 0; @@ -2699,6 +2700,7 @@ case 7: /* LE */ cond = (flags & F_ZF) != 0; + /* fallthrough */ case 6: /* L */ cond |= ((flags & F_SF) != 0) ^ ((flags & F_OF) != 0); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libx86emu-2.4/test/Makefile new/libx86emu-2.6/test/Makefile --- old/libx86emu-2.4/test/Makefile 2019-08-20 16:23:47.000000000 +0200 +++ new/libx86emu-2.6/test/Makefile 2020-01-17 13:32:27.000000000 +0100 @@ -1,8 +1,9 @@ CC = gcc CFLAGS = -g -Wall -fomit-frame-pointer -O2 -TST_FILES = $(wildcard *.tst) +LDFLAGS = +TST_FILES = $(sort $(wildcard *.tst)) INIT_FILES = $(addsuffix .init,$(basename $(wildcard *.tst))) -RES_FILES = $(addsuffix .result,$(basename $(wildcard *.tst))) +RES_FILES = $(sort $(addsuffix .result,$(basename $(wildcard *.tst)))) TEST_OPTS = --verbose --show code,regs,data,acc,io,ints,attr,time export LD_LIBRARY_PATH=.. @@ -17,7 +18,7 @@ @./x86test $(TEST_OPTS) *.init x86test: x86test.c - $(CC) $(CFLAGS) $< -lx86emu -o $@ + $(CC) $(CFLAGS) $< -I ../include -L .. -lx86emu -o $@ $(LDFLAGS) %.result: %.init @./x86test $(TEST_OPTS) $<
