* [PULL 01/25] scsi-disk: Fix crash for VM configured with USB CDROM after live migration
2024-06-11 14:24 [PULL 00/25] target/i386, SCSI changes for 2024-06-11 Paolo Bonzini
@ 2024-06-11 14:24 ` Paolo Bonzini
2024-06-11 14:25 ` [PULL 02/25] i386/cpu: fixup number of addressable IDs for processor cores in the physical package Paolo Bonzini
` (24 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Paolo Bonzini @ 2024-06-11 14:24 UTC (permalink / raw)
To: qemu-devel; +Cc: Hyman Huang
From: Hyman Huang <yong.huang@smartx.com>
For VMs configured with the USB CDROM device:
-drive file=/path/to/local/file,id=drive-usb-disk0,media=cdrom,readonly=on...
-device usb-storage,drive=drive-usb-disk0,id=usb-disk0...
QEMU process may crash after live migration, to reproduce the issue,
configure VM (Guest OS ubuntu 20.04 or 21.10) with the following XML:
<disk type='file' device='cdrom'>
<driver name='qemu' type='raw'/>
<source file='/path/to/share_fs/cdrom.iso'/>
<target dev='sda' bus='usb'/>
<readonly/>
<address type='usb' bus='0' port='2'/>
</disk>
<controller type='usb' index='0' model='piix3-uhci'/>
Do the live migration repeatedly, crash may happen after live migratoin,
trace log at the source before live migration is as follows:
324808@1711972823.521945:usb_uhci_frame_start nr 319
324808@1711972823.521978:usb_uhci_qh_load qh 0x35cb5400
324808@1711972823.521989:usb_uhci_qh_load qh 0x35cb5480
324808@1711972823.521997:usb_uhci_td_load qh 0x35cb5480, td 0x35cbe000, ctrl 0x0, token 0xffe07f69
324808@1711972823.522010:usb_uhci_td_nextqh qh 0x35cb5480, td 0x35cbe000
324808@1711972823.522022:usb_uhci_qh_load qh 0x35cb5680
324808@1711972823.522030:usb_uhci_td_load qh 0x35cb5680, td 0x75ac5180, ctrl 0x19800000, token 0x3c903e1
324808@1711972823.522045:usb_uhci_packet_add token 0x103e1, td 0x75ac5180
324808@1711972823.522056:usb_packet_state_change bus 0, port 2, ep 2, packet 0x559f9ba14b00, state undef -> setup
324808@1711972823.522079:usb_msd_cmd_submit lun 0, tag 0x472, flags 0x00000080, len 10, data-len 8
324808@1711972823.522107:scsi_req_parsed target 0 lun 0 tag 1138 command 74 dir 1 length 8
324808@1711972823.522124:scsi_req_parsed_lba target 0 lun 0 tag 1138 command 74 lba 4096
324808@1711972823.522139:scsi_req_alloc target 0 lun 0 tag 1138
324808@1711972823.522169:scsi_req_continue target 0 lun 0 tag 1138
324808@1711972823.522181:scsi_req_data target 0 lun 0 tag 1138 len 8
324808@1711972823.522194:usb_packet_state_change bus 0, port 2, ep 2, packet 0x559f9ba14b00, state setup -> complete
324808@1711972823.522209:usb_uhci_packet_complete_success token 0x103e1, td 0x75ac5180
324808@1711972823.522219:usb_uhci_packet_del token 0x103e1, td 0x75ac5180
324808@1711972823.522232:usb_uhci_td_complete qh 0x35cb5680, td 0x75ac5180
trace log at the destination after live migration is as follows:
3286206@1711972823.951646:usb_uhci_frame_start nr 320
3286206@1711972823.951663:usb_uhci_qh_load qh 0x35cb5100
3286206@1711972823.951671:usb_uhci_qh_load qh 0x35cb5480
3286206@1711972823.951680:usb_uhci_td_load qh 0x35cb5480, td 0x35cbe000, ctrl 0x1000000, token 0xffe07f69
3286206@1711972823.951693:usb_uhci_td_nextqh qh 0x35cb5480, td 0x35cbe000
3286206@1711972823.951702:usb_uhci_qh_load qh 0x35cb5700
3286206@1711972823.951709:usb_uhci_td_load qh 0x35cb5700, td 0x75ac5240, ctrl 0x39800000, token 0xe08369
3286206@1711972823.951727:usb_uhci_queue_add token 0x8369
3286206@1711972823.951735:usb_uhci_packet_add token 0x8369, td 0x75ac5240
3286206@1711972823.951746:usb_packet_state_change bus 0, port 2, ep 1, packet 0x56066b2fb5a0, state undef -> setup
3286206@1711972823.951766:usb_msd_data_in 8/8 (scsi 8)
2024-04-01 12:00:24.665+0000: shutting down, reason=crashed
The backtrace reveals the following:
Program terminated with signal SIGSEGV, Segmentation fault.
0 __memmove_sse2_unaligned_erms () at ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:312
312 movq -8(%rsi,%rdx), %rcx
[Current thread is 1 (Thread 0x7f0a9025fc00 (LWP 3286206))]
(gdb) bt
0 __memmove_sse2_unaligned_erms () at ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:312
1 memcpy (__len=8, __src=<optimized out>, __dest=<optimized out>) at /usr/include/bits/string_fortified.h:34
2 iov_from_buf_full (iov=<optimized out>, iov_cnt=<optimized out>, offset=<optimized out>, buf=0x0, bytes=bytes@entry=8) at ../util/iov.c:33
3 iov_from_buf (bytes=8, buf=<optimized out>, offset=<optimized out>, iov_cnt=<optimized out>, iov=<optimized out>)
at /usr/src/debug/qemu-6-6.2.0-75.7.oe1.smartx.git.40.x86_64/include/qemu/iov.h:49
4 usb_packet_copy (p=p@entry=0x56066b2fb5a0, ptr=<optimized out>, bytes=bytes@entry=8) at ../hw/usb/core.c:636
5 usb_msd_copy_data (s=s@entry=0x56066c62c770, p=p@entry=0x56066b2fb5a0) at ../hw/usb/dev-storage.c:186
6 usb_msd_handle_data (dev=0x56066c62c770, p=0x56066b2fb5a0) at ../hw/usb/dev-storage.c:496
7 usb_handle_packet (dev=0x56066c62c770, p=p@entry=0x56066b2fb5a0) at ../hw/usb/core.c:455
8 uhci_handle_td (s=s@entry=0x56066bd5f210, q=0x56066bb7fbd0, q@entry=0x0, qh_addr=qh_addr@entry=902518530, td=td@entry=0x7fffe6e788f0, td_addr=<optimized out>,
int_mask=int_mask@entry=0x7fffe6e788e4) at ../hw/usb/hcd-uhci.c:885
9 uhci_process_frame (s=s@entry=0x56066bd5f210) at ../hw/usb/hcd-uhci.c:1061
10 uhci_frame_timer (opaque=opaque@entry=0x56066bd5f210) at ../hw/usb/hcd-uhci.c:1159
11 timerlist_run_timers (timer_list=0x56066af26bd0) at ../util/qemu-timer.c:642
12 qemu_clock_run_timers (type=QEMU_CLOCK_VIRTUAL) at ../util/qemu-timer.c:656
13 qemu_clock_run_all_timers () at ../util/qemu-timer.c:738
14 main_loop_wait (nonblocking=nonblocking@entry=0) at ../util/main-loop.c:542
15 qemu_main_loop () at ../softmmu/runstate.c:739
16 main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>) at ../softmmu/main.c:52
(gdb) frame 5
(gdb) p ((SCSIDiskReq *)s->req)->iov
$1 = {iov_base = 0x0, iov_len = 0}
(gdb) p/x s->req->tag
$2 = 0x472
When designing the USB mass storage device model, QEMU places SCSI disk
device as the backend of USB mass storage device. In addition, USB mass
device driver in Guest OS conforms to the "Universal Serial Bus Mass
Storage Class Bulk-Only Transport" specification in order to simulate
the transform behavior between a USB controller and a USB mass device.
The following shows the protocol hierarchy:
+----------------+
CDROM driver | scsi command | CDROM
+----------------+
+-----------------------+
USB mass | USB Mass Storage Class| USB mass
storage driver | Bulk-Only Transport | storage device
+-----------------------+
+----------------+
USB Controller | USB Protocol | USB device
+----------------+
In the USB protocol layer, between the USB controller and USB device, at
least two USB packets will be transformed when guest OS send a
read operation to USB mass storage device:
1. The CBW packet, which will be delivered to the USB device's Bulk-Out
endpoint. In order to simulate a read operation, the USB mass storage
device parses the CBW and converts it to a SCSI command, which would be
executed by CDROM(represented as SCSI disk in QEMU internally), and store
the result data of the SCSI command in a buffer.
2. The DATA-IN packet, which will be delivered from the USB device's
Bulk-In endpoint(fetched directly from the preceding buffer) to the USB
controller.
We consider UHCI to be the controller. The two packets mentioned above may
have been processed by UHCI in two separate frame entries of the Frame List
, and also described by two different TDs. Unlike the physical environment,
a virtualized environment requires the QEMU to make sure that the result
data of CBW is not lost and is delivered to the UHCI controller.
Currently, these types of SCSI requests are not migrated, so QEMU cannot
ensure the result data of the IO operation is not lost if there are
inflight emulated SCSI requests during the live migration.
Assume for the moment that the USB mass storage device is processing the
CBW and storing the result data of the read operation to a buffre, live
migration happens and moves the VM to the destination while not migrating
the result data of the read operation.
After migration, when UHCI at the destination issues a DATA-IN request to
the USB mass storage device, a crash happens because USB mass storage device
fetches the result data and get nothing.
The scenario this patch addresses is this one.
Theoretically, any device that uses the SCSI disk as a back-end would be
affected by this issue. In this case, it is the USB CDROM.
To fix it, inflight emulated SCSI request be migrated during live migration,
similar to the DMA SCSI request.
Signed-off-by: Hyman Huang <yong.huang@smartx.com>
Message-ID: <878c8f093f3fc2f584b5c31cb2490d9f6a12131a.1716531409.git.yong.huang@smartx.com>
[Do not bump migration version, introduce compat property instead. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/core/machine.c | 1 +
hw/scsi/scsi-disk.c | 24 +++++++++++++++++++++++-
2 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/hw/core/machine.c b/hw/core/machine.c
index c93d2492443..655d75c21fc 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -36,6 +36,7 @@
GlobalProperty hw_compat_9_0[] = {
{"arm-cpu", "backcompat-cntfrq", "true" },
+ {"scsi-disk-base", "migrate-emulated-scsi-request", "false" },
{"vfio-pci", "skip-vsc-check", "false" },
};
const size_t hw_compat_9_0_len = G_N_ELEMENTS(hw_compat_9_0);
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index 0812d39c023..a67092db6a6 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -114,6 +114,7 @@ struct SCSIDiskState {
* 0xffff - reserved
*/
uint16_t rotation_rate;
+ bool migrate_emulated_scsi_request;
};
static void scsi_free_request(SCSIRequest *req)
@@ -162,6 +163,15 @@ static void scsi_disk_save_request(QEMUFile *f, SCSIRequest *req)
}
}
+static void scsi_disk_emulate_save_request(QEMUFile *f, SCSIRequest *req)
+{
+ SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
+
+ if (s->migrate_emulated_scsi_request) {
+ scsi_disk_save_request(f, req);
+ }
+}
+
static void scsi_disk_load_request(QEMUFile *f, SCSIRequest *req)
{
SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
@@ -185,6 +195,15 @@ static void scsi_disk_load_request(QEMUFile *f, SCSIRequest *req)
qemu_iovec_init_external(&r->qiov, &r->iov, 1);
}
+static void scsi_disk_emulate_load_request(QEMUFile *f, SCSIRequest *req)
+{
+ SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
+
+ if (s->migrate_emulated_scsi_request) {
+ scsi_disk_load_request(f, req);
+ }
+}
+
/*
* scsi_handle_rw_error has two return values. False means that the error
* must be ignored, true means that the error has been processed and the
@@ -2606,6 +2625,8 @@ static const SCSIReqOps scsi_disk_emulate_reqops = {
.read_data = scsi_disk_emulate_read_data,
.write_data = scsi_disk_emulate_write_data,
.get_buf = scsi_get_buf,
+ .load_request = scsi_disk_emulate_load_request,
+ .save_request = scsi_disk_emulate_save_request,
};
static const SCSIReqOps scsi_disk_dma_reqops = {
@@ -3114,7 +3135,8 @@ static const TypeInfo scsi_disk_base_info = {
DEFINE_PROP_STRING("serial", SCSIDiskState, serial), \
DEFINE_PROP_STRING("vendor", SCSIDiskState, vendor), \
DEFINE_PROP_STRING("product", SCSIDiskState, product), \
- DEFINE_PROP_STRING("device_id", SCSIDiskState, device_id)
+ DEFINE_PROP_STRING("device_id", SCSIDiskState, device_id), \
+ DEFINE_PROP_BOOL("migrate-emulated-scsi-request", SCSIDiskState, migrate_emulated_scsi_request, true)
static Property scsi_hd_properties[] = {
--
2.45.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PULL 02/25] i386/cpu: fixup number of addressable IDs for processor cores in the physical package
2024-06-11 14:24 [PULL 00/25] target/i386, SCSI changes for 2024-06-11 Paolo Bonzini
2024-06-11 14:24 ` [PULL 01/25] scsi-disk: Fix crash for VM configured with USB CDROM after live migration Paolo Bonzini
@ 2024-06-11 14:25 ` Paolo Bonzini
2024-06-11 14:25 ` [PULL 03/25] i386/sev: fix unreachable code coverity issue Paolo Bonzini
` (23 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Paolo Bonzini @ 2024-06-11 14:25 UTC (permalink / raw)
To: qemu-devel; +Cc: Chuang Xu, Guixiong Wei, Yipeng Yin, Zhao Liu
From: Chuang Xu <xuchuangxclwt@bytedance.com>
When QEMU is started with:
-cpu host,host-cache-info=on,l3-cache=off \
-smp 2,sockets=1,dies=1,cores=1,threads=2
Guest can't acquire maximum number of addressable IDs for processor cores in
the physical package from CPUID[04H].
When creating a CPU topology of 1 core per package, host-cache-info only
uses the Host's addressable core IDs field (CPUID.04H.EAX[bits 31-26]),
resulting in a conflict (on the multicore Host) between the Guest core
topology information in this field and the Guest's actual cores number.
Fix it by removing the unnecessary condition to cover 1 core per package
case. This is safe because cores_per_pkg will not be 0 and will be at
least 1.
Fixes: d7caf13b5fcf ("x86: cpu: fixup number of addressable IDs for logical processors sharing cache")
Signed-off-by: Guixiong Wei <weiguixiong@bytedance.com>
Signed-off-by: Yipeng Yin <yinyipeng@bytedance.com>
Signed-off-by: Chuang Xu <xuchuangxclwt@bytedance.com>
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Message-ID: <20240611032314.64076-1-xuchuangxclwt@bytedance.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/cpu.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 7466217d5ea..365852cb99e 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -6455,10 +6455,8 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
if (*eax & 31) {
int host_vcpus_per_cache = 1 + ((*eax & 0x3FFC000) >> 14);
- if (cores_per_pkg > 1) {
- *eax &= ~0xFC000000;
- *eax |= max_core_ids_in_package(&topo_info) << 26;
- }
+ *eax &= ~0xFC000000;
+ *eax |= max_core_ids_in_package(&topo_info) << 26;
if (host_vcpus_per_cache > threads_per_pkg) {
*eax &= ~0x3FFC000;
--
2.45.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PULL 03/25] i386/sev: fix unreachable code coverity issue
2024-06-11 14:24 [PULL 00/25] target/i386, SCSI changes for 2024-06-11 Paolo Bonzini
2024-06-11 14:24 ` [PULL 01/25] scsi-disk: Fix crash for VM configured with USB CDROM after live migration Paolo Bonzini
2024-06-11 14:25 ` [PULL 02/25] i386/cpu: fixup number of addressable IDs for processor cores in the physical package Paolo Bonzini
@ 2024-06-11 14:25 ` Paolo Bonzini
2024-06-11 14:25 ` [PULL 04/25] i386/sev: Move SEV_COMMON null check before dereferencing Paolo Bonzini
` (22 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Paolo Bonzini @ 2024-06-11 14:25 UTC (permalink / raw)
To: qemu-devel; +Cc: Pankaj Gupta
From: Pankaj Gupta <pankaj.gupta@amd.com>
Set 'finish->id_block_en' early, so that it is properly reset.
Fixes coverity CID 1546887.
Fixes: 7b34df4426 ("i386/sev: Introduce 'sev-snp-guest' object")
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
Message-ID: <20240607183611.1111100-2-pankaj.gupta@amd.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/sev.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/target/i386/sev.c b/target/i386/sev.c
index 004c667ac14..7c9df621de1 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -2165,6 +2165,7 @@ sev_snp_guest_set_id_block(Object *obj, const char *value, Error **errp)
struct kvm_sev_snp_launch_finish *finish = &sev_snp_guest->kvm_finish_conf;
gsize len;
+ finish->id_block_en = 0;
g_free(sev_snp_guest->id_block);
g_free((guchar *)finish->id_block_uaddr);
@@ -2184,7 +2185,7 @@ sev_snp_guest_set_id_block(Object *obj, const char *value, Error **errp)
return;
}
- finish->id_block_en = (len) ? 1 : 0;
+ finish->id_block_en = 1;
}
static char *
--
2.45.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PULL 04/25] i386/sev: Move SEV_COMMON null check before dereferencing
2024-06-11 14:24 [PULL 00/25] target/i386, SCSI changes for 2024-06-11 Paolo Bonzini
` (2 preceding siblings ...)
2024-06-11 14:25 ` [PULL 03/25] i386/sev: fix unreachable code coverity issue Paolo Bonzini
@ 2024-06-11 14:25 ` Paolo Bonzini
2024-06-11 14:25 ` [PULL 05/25] i386/sev: Return when sev_common is null Paolo Bonzini
` (21 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Paolo Bonzini @ 2024-06-11 14:25 UTC (permalink / raw)
To: qemu-devel; +Cc: Pankaj Gupta
From: Pankaj Gupta <pankaj.gupta@amd.com>
Fixes Coverity CID 1546886.
Fixes: 9861405a8f ("i386/sev: Invoke launch_updata_data() for SEV class")
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
Message-ID: <20240607183611.1111100-3-pankaj.gupta@amd.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/sev.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/target/i386/sev.c b/target/i386/sev.c
index 7c9df621de1..f18432f58e2 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -1529,11 +1529,12 @@ int
sev_encrypt_flash(hwaddr gpa, uint8_t *ptr, uint64_t len, Error **errp)
{
SevCommonState *sev_common = SEV_COMMON(MACHINE(qdev_get_machine())->cgs);
- SevCommonStateClass *klass = SEV_COMMON_GET_CLASS(sev_common);
+ SevCommonStateClass *klass;
if (!sev_common) {
return 0;
}
+ klass = SEV_COMMON_GET_CLASS(sev_common);
/* if SEV is in update state then encrypt the data else do nothing */
if (sev_check_state(sev_common, SEV_STATE_LAUNCH_UPDATE)) {
--
2.45.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PULL 05/25] i386/sev: Return when sev_common is null
2024-06-11 14:24 [PULL 00/25] target/i386, SCSI changes for 2024-06-11 Paolo Bonzini
` (3 preceding siblings ...)
2024-06-11 14:25 ` [PULL 04/25] i386/sev: Move SEV_COMMON null check before dereferencing Paolo Bonzini
@ 2024-06-11 14:25 ` Paolo Bonzini
2024-06-11 14:25 ` [PULL 06/25] target/i386: remove CPUX86State argument from generator functions Paolo Bonzini
` (20 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Paolo Bonzini @ 2024-06-11 14:25 UTC (permalink / raw)
To: qemu-devel; +Cc: Pankaj Gupta
From: Pankaj Gupta <pankaj.gupta@amd.com>
Fixes Coverity CID 1546885.
Fixes: 16dcf200dc ("i386/sev: Introduce "sev-common" type to encapsulate common SEV state")
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
Message-ID: <20240607183611.1111100-4-pankaj.gupta@amd.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/sev.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/target/i386/sev.c b/target/i386/sev.c
index f18432f58e2..c40562dce31 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -587,6 +587,7 @@ static SevCapability *sev_get_capabilities(Error **errp)
sev_common = SEV_COMMON(MACHINE(qdev_get_machine())->cgs);
if (!sev_common) {
error_setg(errp, "SEV is not configured");
+ return NULL;
}
sev_device = object_property_get_str(OBJECT(sev_common), "sev-device",
--
2.45.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PULL 06/25] target/i386: remove CPUX86State argument from generator functions
2024-06-11 14:24 [PULL 00/25] target/i386, SCSI changes for 2024-06-11 Paolo Bonzini
` (4 preceding siblings ...)
2024-06-11 14:25 ` [PULL 05/25] i386/sev: Return when sev_common is null Paolo Bonzini
@ 2024-06-11 14:25 ` Paolo Bonzini
2024-06-11 14:25 ` [PULL 07/25] target/i386: rewrite flags writeback for ADCX/ADOX Paolo Bonzini
` (19 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Paolo Bonzini @ 2024-06-11 14:25 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson
CPUX86State argument would only be used to fetch bytes, but that has to be
done before the generator function is called. So remove it, and all
temptation together with it.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/tcg/decode-new.h | 2 +-
target/i386/tcg/decode-new.c.inc | 4 +-
target/i386/tcg/emit.c.inc | 572 +++++++++++++++----------------
3 files changed, 289 insertions(+), 289 deletions(-)
diff --git a/target/i386/tcg/decode-new.h b/target/i386/tcg/decode-new.h
index 1f90cf96407..f704698575f 100644
--- a/target/i386/tcg/decode-new.h
+++ b/target/i386/tcg/decode-new.h
@@ -245,7 +245,7 @@ typedef struct X86DecodedInsn X86DecodedInsn;
typedef void (*X86DecodeFunc)(DisasContext *s, CPUX86State *env, X86OpEntry *entry, uint8_t *b);
/* Code generation function. */
-typedef void (*X86GenFunc)(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode);
+typedef void (*X86GenFunc)(DisasContext *s, X86DecodedInsn *decode);
struct X86OpEntry {
/* Based on the is_decode flags. */
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index c2d8da8d14e..e7d88020481 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -2590,7 +2590,7 @@ static void disas_insn(DisasContext *s, CPUState *cpu)
}
if (s->prefix & PREFIX_LOCK) {
gen_load(s, &decode, 2, s->T1);
- decode.e.gen(s, env, &decode);
+ decode.e.gen(s, &decode);
} else {
if (decode.op[0].unit == X86_OP_MMX) {
compute_mmx_offset(&decode.op[0]);
@@ -2599,7 +2599,7 @@ static void disas_insn(DisasContext *s, CPUState *cpu)
}
gen_load(s, &decode, 1, s->T0);
gen_load(s, &decode, 2, s->T1);
- decode.e.gen(s, env, &decode);
+ decode.e.gen(s, &decode);
gen_writeback(s, &decode, 0, s->T0);
}
diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
index 4be3d9a6fba..df7597c7e2f 100644
--- a/target/i386/tcg/emit.c.inc
+++ b/target/i386/tcg/emit.c.inc
@@ -60,8 +60,8 @@ typedef void (*SSEFunc_0_eppppii)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
TCGv_ptr reg_c, TCGv_ptr reg_d, TCGv_i32 even,
TCGv_i32 odd);
-static void gen_JMP_m(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode);
-static void gen_JMP(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode);
+static void gen_JMP_m(DisasContext *s, X86DecodedInsn *decode);
+static void gen_JMP(DisasContext *s, X86DecodedInsn *decode);
static inline TCGv_i32 tcg_constant8u_i32(uint8_t val)
{
@@ -446,7 +446,7 @@ static const SSEFunc_0_epp fns_3dnow[] = {
[0xbf] = gen_helper_pavgusb,
};
-static void gen_3dnow(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_3dnow(DisasContext *s, X86DecodedInsn *decode)
{
uint8_t b = decode->immediate;
SSEFunc_0_epp fn = b < ARRAY_SIZE(fns_3dnow) ? fns_3dnow[b] : NULL;
@@ -479,7 +479,7 @@ static void gen_3dnow(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
* f3 = v*ss Vss, Hss, Wps
* f2 = v*sd Vsd, Hsd, Wps
*/
-static inline void gen_unary_fp_sse(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode,
+static inline void gen_unary_fp_sse(DisasContext *s, X86DecodedInsn *decode,
SSEFunc_0_epp pd_xmm, SSEFunc_0_epp ps_xmm,
SSEFunc_0_epp pd_ymm, SSEFunc_0_epp ps_ymm,
SSEFunc_0_eppp sd, SSEFunc_0_eppp ss)
@@ -504,9 +504,9 @@ static inline void gen_unary_fp_sse(DisasContext *s, CPUX86State *env, X86Decode
}
}
#define UNARY_FP_SSE(uname, lname) \
-static void gen_##uname(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) \
+static void gen_##uname(DisasContext *s, X86DecodedInsn *decode) \
{ \
- gen_unary_fp_sse(s, env, decode, \
+ gen_unary_fp_sse(s, decode, \
gen_helper_##lname##pd_xmm, \
gen_helper_##lname##ps_xmm, \
gen_helper_##lname##pd_ymm, \
@@ -522,7 +522,7 @@ UNARY_FP_SSE(VSQRT, sqrt)
* f3 = v*ss Vss, Hss, Wps
* f2 = v*sd Vsd, Hsd, Wps
*/
-static inline void gen_fp_sse(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode,
+static inline void gen_fp_sse(DisasContext *s, X86DecodedInsn *decode,
SSEFunc_0_eppp pd_xmm, SSEFunc_0_eppp ps_xmm,
SSEFunc_0_eppp pd_ymm, SSEFunc_0_eppp ps_ymm,
SSEFunc_0_eppp sd, SSEFunc_0_eppp ss)
@@ -543,9 +543,9 @@ static inline void gen_fp_sse(DisasContext *s, CPUX86State *env, X86DecodedInsn
}
#define FP_SSE(uname, lname) \
-static void gen_##uname(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) \
+static void gen_##uname(DisasContext *s, X86DecodedInsn *decode) \
{ \
- gen_fp_sse(s, env, decode, \
+ gen_fp_sse(s, decode, \
gen_helper_##lname##pd_xmm, \
gen_helper_##lname##ps_xmm, \
gen_helper_##lname##pd_ymm, \
@@ -561,7 +561,7 @@ FP_SSE(VDIV, div)
FP_SSE(VMAX, max)
#define FMA_SSE_PACKED(uname, ptr0, ptr1, ptr2, even, odd) \
-static void gen_##uname##Px(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) \
+static void gen_##uname##Px(DisasContext *s, X86DecodedInsn *decode) \
{ \
SSEFunc_0_eppppii xmm = s->vex_w ? gen_helper_fma4pd_xmm : gen_helper_fma4ps_xmm; \
SSEFunc_0_eppppii ymm = s->vex_w ? gen_helper_fma4pd_ymm : gen_helper_fma4ps_ymm; \
@@ -574,7 +574,7 @@ static void gen_##uname##Px(DisasContext *s, CPUX86State *env, X86DecodedInsn *d
#define FMA_SSE(uname, ptr0, ptr1, ptr2, flags) \
FMA_SSE_PACKED(uname, ptr0, ptr1, ptr2, flags, flags) \
-static void gen_##uname##Sx(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) \
+static void gen_##uname##Sx(DisasContext *s, X86DecodedInsn *decode) \
{ \
SSEFunc_0_eppppi fn = s->vex_w ? gen_helper_fma4sd : gen_helper_fma4ss; \
\
@@ -607,10 +607,10 @@ FMA_SSE_PACKED(VFMSUBADD213, OP_PTR1, OP_PTR0, OP_PTR2, 0, float_muladd_negate_c
FMA_SSE_PACKED(VFMSUBADD132, OP_PTR0, OP_PTR2, OP_PTR1, 0, float_muladd_negate_c)
#define FP_UNPACK_SSE(uname, lname) \
-static void gen_##uname(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) \
+static void gen_##uname(DisasContext *s, X86DecodedInsn *decode) \
{ \
/* PS maps to the DQ integer instruction, PD maps to QDQ. */ \
- gen_fp_sse(s, env, decode, \
+ gen_fp_sse(s, decode, \
gen_helper_##lname##qdq_xmm, \
gen_helper_##lname##dq_xmm, \
gen_helper_##lname##qdq_ymm, \
@@ -624,7 +624,7 @@ FP_UNPACK_SSE(VUNPCKHPx, punpckh)
* 00 = v*ps Vps, Wpd
* f3 = v*ss Vss, Wps
*/
-static inline void gen_unary_fp32_sse(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode,
+static inline void gen_unary_fp32_sse(DisasContext *s, X86DecodedInsn *decode,
SSEFunc_0_epp ps_xmm,
SSEFunc_0_epp ps_ymm,
SSEFunc_0_eppp ss)
@@ -649,9 +649,9 @@ illegal_op:
gen_illegal_opcode(s);
}
#define UNARY_FP32_SSE(uname, lname) \
-static void gen_##uname(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) \
+static void gen_##uname(DisasContext *s, X86DecodedInsn *decode) \
{ \
- gen_unary_fp32_sse(s, env, decode, \
+ gen_unary_fp32_sse(s, decode, \
gen_helper_##lname##ps_xmm, \
gen_helper_##lname##ps_ymm, \
gen_helper_##lname##ss); \
@@ -663,7 +663,7 @@ UNARY_FP32_SSE(VRCP, rcp)
* 66 = v*pd Vpd, Hpd, Wpd
* f2 = v*ps Vps, Hps, Wps
*/
-static inline void gen_horizontal_fp_sse(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode,
+static inline void gen_horizontal_fp_sse(DisasContext *s, X86DecodedInsn *decode,
SSEFunc_0_eppp pd_xmm, SSEFunc_0_eppp ps_xmm,
SSEFunc_0_eppp pd_ymm, SSEFunc_0_eppp ps_ymm)
{
@@ -674,9 +674,9 @@ static inline void gen_horizontal_fp_sse(DisasContext *s, CPUX86State *env, X86D
fn(tcg_env, OP_PTR0, OP_PTR1, OP_PTR2);
}
#define HORIZONTAL_FP_SSE(uname, lname) \
-static void gen_##uname(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) \
+static void gen_##uname(DisasContext *s, X86DecodedInsn *decode) \
{ \
- gen_horizontal_fp_sse(s, env, decode, \
+ gen_horizontal_fp_sse(s, decode, \
gen_helper_##lname##pd_xmm, gen_helper_##lname##ps_xmm, \
gen_helper_##lname##pd_ymm, gen_helper_##lname##ps_ymm); \
}
@@ -684,7 +684,7 @@ HORIZONTAL_FP_SSE(VHADD, hadd)
HORIZONTAL_FP_SSE(VHSUB, hsub)
HORIZONTAL_FP_SSE(VADDSUB, addsub)
-static inline void gen_ternary_sse(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode,
+static inline void gen_ternary_sse(DisasContext *s, X86DecodedInsn *decode,
int op3, SSEFunc_0_epppp xmm, SSEFunc_0_epppp ymm)
{
SSEFunc_0_epppp fn = s->vex_l ? ymm : xmm;
@@ -695,21 +695,21 @@ static inline void gen_ternary_sse(DisasContext *s, CPUX86State *env, X86Decoded
fn(tcg_env, OP_PTR0, OP_PTR1, OP_PTR2, ptr3);
}
#define TERNARY_SSE(uname, uvname, lname) \
-static void gen_##uvname(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) \
+static void gen_##uvname(DisasContext *s, X86DecodedInsn *decode) \
{ \
- gen_ternary_sse(s, env, decode, (uint8_t)decode->immediate >> 4, \
+ gen_ternary_sse(s, decode, (uint8_t)decode->immediate >> 4, \
gen_helper_##lname##_xmm, gen_helper_##lname##_ymm); \
} \
-static void gen_##uname(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) \
+static void gen_##uname(DisasContext *s, X86DecodedInsn *decode) \
{ \
- gen_ternary_sse(s, env, decode, 0, \
+ gen_ternary_sse(s, decode, 0, \
gen_helper_##lname##_xmm, gen_helper_##lname##_ymm); \
}
TERNARY_SSE(BLENDVPS, VBLENDVPS, blendvps)
TERNARY_SSE(BLENDVPD, VBLENDVPD, blendvpd)
TERNARY_SSE(PBLENDVB, VPBLENDVB, pblendvb)
-static inline void gen_binary_imm_sse(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode,
+static inline void gen_binary_imm_sse(DisasContext *s, X86DecodedInsn *decode,
SSEFunc_0_epppi xmm, SSEFunc_0_epppi ymm)
{
TCGv_i32 imm = tcg_constant8u_i32(decode->immediate);
@@ -721,9 +721,9 @@ static inline void gen_binary_imm_sse(DisasContext *s, CPUX86State *env, X86Deco
}
#define BINARY_IMM_SSE(uname, lname) \
-static void gen_##uname(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) \
+static void gen_##uname(DisasContext *s, X86DecodedInsn *decode) \
{ \
- gen_binary_imm_sse(s, env, decode, \
+ gen_binary_imm_sse(s, decode, \
gen_helper_##lname##_xmm, \
gen_helper_##lname##_ymm); \
}
@@ -739,7 +739,7 @@ BINARY_IMM_SSE(PCLMULQDQ, pclmulqdq)
#define UNARY_INT_GVEC(uname, func, ...) \
-static void gen_##uname(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) \
+static void gen_##uname(DisasContext *s, X86DecodedInsn *decode) \
{ \
int vec_len = vector_len(s, decode); \
\
@@ -757,7 +757,7 @@ UNARY_INT_GVEC(VPBROADCASTQ, tcg_gen_gvec_dup_mem, MO_64)
#define BINARY_INT_GVEC(uname, func, ...) \
-static void gen_##uname(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) \
+static void gen_##uname(DisasContext *s, X86DecodedInsn *decode) \
{ \
int vec_len = vector_len(s, decode); \
\
@@ -816,7 +816,7 @@ BINARY_INT_GVEC(PXOR, tcg_gen_gvec_xor, MO_64)
* These are really the same encoding, because 1) V is the same as P when VEX.V
* is not present 2) P and Q are the same as H and W apart from MM/XMM
*/
-static inline void gen_binary_int_sse(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode,
+static inline void gen_binary_int_sse(DisasContext *s, X86DecodedInsn *decode,
SSEFunc_0_eppp mmx, SSEFunc_0_eppp xmm, SSEFunc_0_eppp ymm)
{
assert(!!mmx == !!(decode->e.special == X86_SPECIAL_MMX));
@@ -837,9 +837,9 @@ static inline void gen_binary_int_sse(DisasContext *s, CPUX86State *env, X86Deco
#define BINARY_INT_MMX(uname, lname) \
-static void gen_##uname(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) \
+static void gen_##uname(DisasContext *s, X86DecodedInsn *decode) \
{ \
- gen_binary_int_sse(s, env, decode, \
+ gen_binary_int_sse(s, decode, \
gen_helper_##lname##_mmx, \
gen_helper_##lname##_xmm, \
gen_helper_##lname##_ymm); \
@@ -886,9 +886,9 @@ BINARY_INT_MMX(PMULHRSW, pmulhrsw)
/* Instructions with no MMX equivalent. */
#define BINARY_INT_SSE(uname, lname) \
-static void gen_##uname(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) \
+static void gen_##uname(DisasContext *s, X86DecodedInsn *decode) \
{ \
- gen_binary_int_sse(s, env, decode, \
+ gen_binary_int_sse(s, decode, \
NULL, \
gen_helper_##lname##_xmm, \
gen_helper_##lname##_ymm); \
@@ -911,7 +911,7 @@ BINARY_INT_SSE(VAESENC, aesenc)
BINARY_INT_SSE(VAESENCLAST, aesenclast)
#define UNARY_CMP_SSE(uname, lname) \
-static void gen_##uname(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) \
+static void gen_##uname(DisasContext *s, X86DecodedInsn *decode) \
{ \
if (!s->vex_l) { \
gen_helper_##lname##_xmm(tcg_env, OP_PTR1, OP_PTR2); \
@@ -924,7 +924,7 @@ UNARY_CMP_SSE(VPTEST, ptest)
UNARY_CMP_SSE(VTESTPS, vtestps)
UNARY_CMP_SSE(VTESTPD, vtestpd)
-static inline void gen_unary_int_sse(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode,
+static inline void gen_unary_int_sse(DisasContext *s, X86DecodedInsn *decode,
SSEFunc_0_epp xmm, SSEFunc_0_epp ymm)
{
if (!s->vex_l) {
@@ -935,9 +935,9 @@ static inline void gen_unary_int_sse(DisasContext *s, CPUX86State *env, X86Decod
}
#define UNARY_INT_SSE(uname, lname) \
-static void gen_##uname(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) \
+static void gen_##uname(DisasContext *s, X86DecodedInsn *decode) \
{ \
- gen_unary_int_sse(s, env, decode, \
+ gen_unary_int_sse(s, decode, \
gen_helper_##lname##_xmm, \
gen_helper_##lname##_ymm); \
}
@@ -969,7 +969,7 @@ UNARY_INT_SSE(VCVTTPS2DQ, cvttps2dq)
UNARY_INT_SSE(VCVTPH2PS, cvtph2ps)
-static inline void gen_unary_imm_sse(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode,
+static inline void gen_unary_imm_sse(DisasContext *s, X86DecodedInsn *decode,
SSEFunc_0_ppi xmm, SSEFunc_0_ppi ymm)
{
TCGv_i32 imm = tcg_constant8u_i32(decode->immediate);
@@ -981,9 +981,9 @@ static inline void gen_unary_imm_sse(DisasContext *s, CPUX86State *env, X86Decod
}
#define UNARY_IMM_SSE(uname, lname) \
-static void gen_##uname(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) \
+static void gen_##uname(DisasContext *s, X86DecodedInsn *decode) \
{ \
- gen_unary_imm_sse(s, env, decode, \
+ gen_unary_imm_sse(s, decode, \
gen_helper_##lname##_xmm, \
gen_helper_##lname##_ymm); \
}
@@ -996,7 +996,7 @@ UNARY_IMM_SSE(VPERMQ, vpermq)
UNARY_IMM_SSE(VPERMILPS_i, vpermilps_imm)
UNARY_IMM_SSE(VPERMILPD_i, vpermilpd_imm)
-static inline void gen_unary_imm_fp_sse(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode,
+static inline void gen_unary_imm_fp_sse(DisasContext *s, X86DecodedInsn *decode,
SSEFunc_0_eppi xmm, SSEFunc_0_eppi ymm)
{
TCGv_i32 imm = tcg_constant8u_i32(decode->immediate);
@@ -1008,9 +1008,9 @@ static inline void gen_unary_imm_fp_sse(DisasContext *s, CPUX86State *env, X86De
}
#define UNARY_IMM_FP_SSE(uname, lname) \
-static void gen_##uname(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) \
+static void gen_##uname(DisasContext *s, X86DecodedInsn *decode) \
{ \
- gen_unary_imm_fp_sse(s, env, decode, \
+ gen_unary_imm_fp_sse(s, decode, \
gen_helper_##lname##_xmm, \
gen_helper_##lname##_ymm); \
}
@@ -1018,7 +1018,7 @@ static void gen_##uname(DisasContext *s, CPUX86State *env, X86DecodedInsn *decod
UNARY_IMM_FP_SSE(VROUNDPS, roundps)
UNARY_IMM_FP_SSE(VROUNDPD, roundpd)
-static inline void gen_vexw_avx(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode,
+static inline void gen_vexw_avx(DisasContext *s, X86DecodedInsn *decode,
SSEFunc_0_eppp d_xmm, SSEFunc_0_eppp q_xmm,
SSEFunc_0_eppp d_ymm, SSEFunc_0_eppp q_ymm)
{
@@ -1030,9 +1030,9 @@ static inline void gen_vexw_avx(DisasContext *s, CPUX86State *env, X86DecodedIns
/* VEX.W affects whether to operate on 32- or 64-bit elements. */
#define VEXW_AVX(uname, lname) \
-static void gen_##uname(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) \
+static void gen_##uname(DisasContext *s, X86DecodedInsn *decode) \
{ \
- gen_vexw_avx(s, env, decode, \
+ gen_vexw_avx(s, decode, \
gen_helper_##lname##d_xmm, gen_helper_##lname##q_xmm, \
gen_helper_##lname##d_ymm, gen_helper_##lname##q_ymm); \
}
@@ -1042,7 +1042,7 @@ VEXW_AVX(VPSRAV, vpsrav)
VEXW_AVX(VPMASKMOV, vpmaskmov)
/* Same as above, but with extra arguments to the helper. */
-static inline void gen_vsib_avx(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode,
+static inline void gen_vsib_avx(DisasContext *s, X86DecodedInsn *decode,
SSEFunc_0_epppti d_xmm, SSEFunc_0_epppti q_xmm,
SSEFunc_0_epppti d_ymm, SSEFunc_0_epppti q_ymm)
{
@@ -1066,29 +1066,29 @@ static inline void gen_vsib_avx(DisasContext *s, CPUX86State *env, X86DecodedIns
}
}
#define VSIB_AVX(uname, lname) \
-static void gen_##uname(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode) \
+static void gen_##uname(DisasContext *s, X86DecodedInsn *decode) \
{ \
- gen_vsib_avx(s, env, decode, \
+ gen_vsib_avx(s, decode, \
gen_helper_##lname##d_xmm, gen_helper_##lname##q_xmm, \
gen_helper_##lname##d_ymm, gen_helper_##lname##q_ymm); \
}
VSIB_AVX(VPGATHERD, vpgatherd)
VSIB_AVX(VPGATHERQ, vpgatherq)
-static void gen_AAA(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_AAA(DisasContext *s, X86DecodedInsn *decode)
{
gen_update_cc_op(s);
gen_helper_aaa(tcg_env);
assume_cc_op(s, CC_OP_EFLAGS);
}
-static void gen_AAD(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_AAD(DisasContext *s, X86DecodedInsn *decode)
{
gen_helper_aad(s->T0, s->T0, s->T1);
prepare_update1_cc(decode, s, CC_OP_LOGICB);
}
-static void gen_AAM(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_AAM(DisasContext *s, X86DecodedInsn *decode)
{
if (decode->immediate == 0) {
gen_exception(s, EXCP00_DIVZ);
@@ -1098,14 +1098,14 @@ static void gen_AAM(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
}
}
-static void gen_AAS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_AAS(DisasContext *s, X86DecodedInsn *decode)
{
gen_update_cc_op(s);
gen_helper_aas(tcg_env);
assume_cc_op(s, CC_OP_EFLAGS);
}
-static void gen_ADC(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_ADC(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[1].ot;
TCGv c_in = tcg_temp_new();
@@ -1123,7 +1123,7 @@ static void gen_ADC(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
}
/* ADCX/ADOX do not have memory operands and can use set_cc_op. */
-static void gen_ADCOX(DisasContext *s, CPUX86State *env, MemOp ot, int cc_op)
+static void gen_ADCOX(DisasContext *s, MemOp ot, int cc_op)
{
int opposite_cc_op;
TCGv carry_in = NULL;
@@ -1170,12 +1170,12 @@ static void gen_ADCOX(DisasContext *s, CPUX86State *env, MemOp ot, int cc_op)
}
}
-static void gen_ADCX(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_ADCX(DisasContext *s, X86DecodedInsn *decode)
{
- gen_ADCOX(s, env, decode->op[0].ot, CC_OP_ADCX);
+ gen_ADCOX(s, decode->op[0].ot, CC_OP_ADCX);
}
-static void gen_ADD(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_ADD(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[1].ot;
@@ -1188,12 +1188,12 @@ static void gen_ADD(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
prepare_update2_cc(decode, s, CC_OP_ADDB + ot);
}
-static void gen_ADOX(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_ADOX(DisasContext *s, X86DecodedInsn *decode)
{
- gen_ADCOX(s, env, decode->op[0].ot, CC_OP_ADOX);
+ gen_ADCOX(s, decode->op[0].ot, CC_OP_ADOX);
}
-static void gen_AND(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_AND(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[1].ot;
@@ -1206,7 +1206,7 @@ static void gen_AND(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
prepare_update1_cc(decode, s, CC_OP_LOGICB + ot);
}
-static void gen_ANDN(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_ANDN(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[0].ot;
@@ -1214,7 +1214,7 @@ static void gen_ANDN(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
prepare_update1_cc(decode, s, CC_OP_LOGICB + ot);
}
-static void gen_ARPL(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_ARPL(DisasContext *s, X86DecodedInsn *decode)
{
TCGv zf = tcg_temp_new();
TCGv flags = tcg_temp_new();
@@ -1235,7 +1235,7 @@ static void gen_ARPL(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
decode->cc_op = CC_OP_EFLAGS;
}
-static void gen_BEXTR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_BEXTR(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[0].ot;
TCGv bound = tcg_constant_tl(ot == MO_64 ? 63 : 31);
@@ -1264,7 +1264,7 @@ static void gen_BEXTR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
}
/* BLSI do not have memory operands and can use set_cc_op. */
-static void gen_BLSI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_BLSI(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[0].ot;
@@ -1276,7 +1276,7 @@ static void gen_BLSI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
}
/* BLSMSK do not have memory operands and can use set_cc_op. */
-static void gen_BLSMSK(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_BLSMSK(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[0].ot;
@@ -1288,7 +1288,7 @@ static void gen_BLSMSK(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode
}
/* BLSR do not have memory operands and can use set_cc_op. */
-static void gen_BLSR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_BLSR(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[0].ot;
@@ -1299,7 +1299,7 @@ static void gen_BLSR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
set_cc_op(s, CC_OP_BMILGB + ot);
}
-static void gen_BOUND(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_BOUND(DisasContext *s, X86DecodedInsn *decode)
{
TCGv_i32 op = tcg_temp_new_i32();
tcg_gen_trunc_tl_i32(op, s->T0);
@@ -1310,7 +1310,7 @@ static void gen_BOUND(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
}
}
-static void gen_BSWAP(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_BSWAP(DisasContext *s, X86DecodedInsn *decode)
{
#ifdef TARGET_X86_64
if (s->dflag == MO_64) {
@@ -1321,7 +1321,7 @@ static void gen_BSWAP(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
tcg_gen_bswap32_tl(s->T0, s->T0, TCG_BSWAP_OZ);
}
-static void gen_BZHI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_BZHI(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[0].ot;
TCGv bound = tcg_constant_tl(ot == MO_64 ? 63 : 31);
@@ -1341,24 +1341,24 @@ static void gen_BZHI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
prepare_update2_cc(decode, s, CC_OP_BMILGB + ot);
}
-static void gen_CALL(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_CALL(DisasContext *s, X86DecodedInsn *decode)
{
gen_push_v(s, eip_next_tl(s));
- gen_JMP(s, env, decode);
+ gen_JMP(s, decode);
}
-static void gen_CALL_m(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_CALL_m(DisasContext *s, X86DecodedInsn *decode)
{
gen_push_v(s, eip_next_tl(s));
- gen_JMP_m(s, env, decode);
+ gen_JMP_m(s, decode);
}
-static void gen_CALLF(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_CALLF(DisasContext *s, X86DecodedInsn *decode)
{
gen_far_call(s);
}
-static void gen_CALLF_m(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_CALLF_m(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[2].ot;
@@ -1368,41 +1368,41 @@ static void gen_CALLF_m(DisasContext *s, CPUX86State *env, X86DecodedInsn *decod
gen_far_call(s);
}
-static void gen_CBW(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_CBW(DisasContext *s, X86DecodedInsn *decode)
{
MemOp src_ot = decode->op[0].ot - 1;
tcg_gen_ext_tl(s->T0, s->T0, src_ot | MO_SIGN);
}
-static void gen_CLC(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_CLC(DisasContext *s, X86DecodedInsn *decode)
{
gen_compute_eflags(s);
tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C);
}
-static void gen_CLD(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_CLD(DisasContext *s, X86DecodedInsn *decode)
{
tcg_gen_st_i32(tcg_constant_i32(1), tcg_env, offsetof(CPUX86State, df));
}
-static void gen_CLI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_CLI(DisasContext *s, X86DecodedInsn *decode)
{
gen_reset_eflags(s, IF_MASK);
}
-static void gen_CMC(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_CMC(DisasContext *s, X86DecodedInsn *decode)
{
gen_compute_eflags(s);
tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C);
}
-static void gen_CMOVcc(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_CMOVcc(DisasContext *s, X86DecodedInsn *decode)
{
gen_cmovcc1(s, decode->b & 0xf, s->T0, s->T1);
}
-static void gen_CMPccXADD(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_CMPccXADD(DisasContext *s, X86DecodedInsn *decode)
{
TCGLabel *label_top = gen_new_label();
TCGLabel *label_bottom = gen_new_label();
@@ -1505,7 +1505,7 @@ static void gen_CMPccXADD(DisasContext *s, CPUX86State *env, X86DecodedInsn *dec
decode->cc_op = CC_OP_SUBB + ot;
}
-static void gen_CMPS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_CMPS(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[2].ot;
if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) {
@@ -1515,7 +1515,7 @@ static void gen_CMPS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
}
}
-static void gen_CRC32(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_CRC32(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[2].ot;
@@ -1523,7 +1523,7 @@ static void gen_CRC32(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
gen_helper_crc32(s->T0, s->tmp2_i32, s->T1, tcg_constant_i32(8 << ot));
}
-static void gen_CVTPI2Px(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_CVTPI2Px(DisasContext *s, X86DecodedInsn *decode)
{
gen_helper_enter_mmx(tcg_env);
if (s->prefix & PREFIX_DATA) {
@@ -1533,7 +1533,7 @@ static void gen_CVTPI2Px(DisasContext *s, CPUX86State *env, X86DecodedInsn *deco
}
}
-static void gen_CVTPx2PI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_CVTPx2PI(DisasContext *s, X86DecodedInsn *decode)
{
gen_helper_enter_mmx(tcg_env);
if (s->prefix & PREFIX_DATA) {
@@ -1543,7 +1543,7 @@ static void gen_CVTPx2PI(DisasContext *s, CPUX86State *env, X86DecodedInsn *deco
}
}
-static void gen_CVTTPx2PI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_CVTTPx2PI(DisasContext *s, X86DecodedInsn *decode)
{
gen_helper_enter_mmx(tcg_env);
if (s->prefix & PREFIX_DATA) {
@@ -1553,28 +1553,28 @@ static void gen_CVTTPx2PI(DisasContext *s, CPUX86State *env, X86DecodedInsn *dec
}
}
-static void gen_CWD(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_CWD(DisasContext *s, X86DecodedInsn *decode)
{
int shift = 8 << decode->op[0].ot;
tcg_gen_sextract_tl(s->T0, s->T0, shift - 1, 1);
}
-static void gen_DAA(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_DAA(DisasContext *s, X86DecodedInsn *decode)
{
gen_update_cc_op(s);
gen_helper_daa(tcg_env);
assume_cc_op(s, CC_OP_EFLAGS);
}
-static void gen_DAS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_DAS(DisasContext *s, X86DecodedInsn *decode)
{
gen_update_cc_op(s);
gen_helper_das(tcg_env);
assume_cc_op(s, CC_OP_EFLAGS);
}
-static void gen_DEC(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_DEC(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[1].ot;
@@ -1588,7 +1588,7 @@ static void gen_DEC(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
prepare_update_cc_incdec(decode, s, CC_OP_DECB + ot);
}
-static void gen_DIV(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_DIV(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[2].ot;
@@ -1611,17 +1611,17 @@ static void gen_DIV(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
}
}
-static void gen_EMMS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_EMMS(DisasContext *s, X86DecodedInsn *decode)
{
gen_helper_emms(tcg_env);
}
-static void gen_ENTER(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_ENTER(DisasContext *s, X86DecodedInsn *decode)
{
gen_enter(s, decode->op[1].imm, decode->op[2].imm);
}
-static void gen_EXTRQ_i(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_EXTRQ_i(DisasContext *s, X86DecodedInsn *decode)
{
TCGv_i32 length = tcg_constant_i32(decode->immediate & 63);
TCGv_i32 index = tcg_constant_i32((decode->immediate >> 8) & 63);
@@ -1629,12 +1629,12 @@ static void gen_EXTRQ_i(DisasContext *s, CPUX86State *env, X86DecodedInsn *decod
gen_helper_extrq_i(tcg_env, OP_PTR0, index, length);
}
-static void gen_EXTRQ_r(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_EXTRQ_r(DisasContext *s, X86DecodedInsn *decode)
{
gen_helper_extrq_r(tcg_env, OP_PTR0, OP_PTR2);
}
-static void gen_HLT(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_HLT(DisasContext *s, X86DecodedInsn *decode)
{
#ifdef CONFIG_SYSTEM_ONLY
gen_update_cc_op(s);
@@ -1644,7 +1644,7 @@ static void gen_HLT(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
#endif
}
-static void gen_IDIV(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_IDIV(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[2].ot;
@@ -1667,7 +1667,7 @@ static void gen_IDIV(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
}
}
-static void gen_IMUL3(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_IMUL3(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[0].ot;
TCGv cc_src_rhs;
@@ -1730,7 +1730,7 @@ static void gen_IMUL3(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
prepare_update2_cc(decode, s, CC_OP_MULB + ot);
}
-static void gen_IMUL(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_IMUL(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[1].ot;
TCGv cc_src_rhs;
@@ -1788,7 +1788,7 @@ static void gen_IMUL(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
prepare_update2_cc(decode, s, CC_OP_MULB + ot);
}
-static void gen_IN(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_IN(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[0].ot;
TCGv_i32 port = tcg_temp_new_i32();
@@ -1804,7 +1804,7 @@ static void gen_IN(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
gen_bpt_io(s, port, ot);
}
-static void gen_INC(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_INC(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[1].ot;
@@ -1818,7 +1818,7 @@ static void gen_INC(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
prepare_update_cc_incdec(decode, s, CC_OP_INCB + ot);
}
-static void gen_INS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_INS(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[1].ot;
TCGv_i32 port = tcg_temp_new_i32();
@@ -1838,7 +1838,7 @@ static void gen_INS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
}
}
-static void gen_INSERTQ_i(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_INSERTQ_i(DisasContext *s, X86DecodedInsn *decode)
{
TCGv_i32 length = tcg_constant_i32(decode->immediate & 63);
TCGv_i32 index = tcg_constant_i32((decode->immediate >> 8) & 63);
@@ -1846,17 +1846,17 @@ static void gen_INSERTQ_i(DisasContext *s, CPUX86State *env, X86DecodedInsn *dec
gen_helper_insertq_i(tcg_env, OP_PTR0, OP_PTR1, index, length);
}
-static void gen_INSERTQ_r(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_INSERTQ_r(DisasContext *s, X86DecodedInsn *decode)
{
gen_helper_insertq_r(tcg_env, OP_PTR0, OP_PTR2);
}
-static void gen_INT(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_INT(DisasContext *s, X86DecodedInsn *decode)
{
gen_interrupt(s, decode->immediate);
}
-static void gen_INT1(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_INT1(DisasContext *s, X86DecodedInsn *decode)
{
gen_update_cc_op(s);
gen_update_eip_next(s);
@@ -1864,19 +1864,19 @@ static void gen_INT1(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
s->base.is_jmp = DISAS_NORETURN;
}
-static void gen_INT3(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_INT3(DisasContext *s, X86DecodedInsn *decode)
{
gen_interrupt(s, EXCP03_INT3);
}
-static void gen_INTO(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_INTO(DisasContext *s, X86DecodedInsn *decode)
{
gen_update_cc_op(s);
gen_update_eip_cur(s);
gen_helper_into(tcg_env, cur_insn_len_i32(s));
}
-static void gen_IRET(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_IRET(DisasContext *s, X86DecodedInsn *decode)
{
if (!PE(s) || VM86(s)) {
gen_helper_iret_real(tcg_env, tcg_constant_i32(s->dflag - 1));
@@ -1888,13 +1888,13 @@ static void gen_IRET(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
s->base.is_jmp = DISAS_EOB_ONLY;
}
-static void gen_Jcc(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_Jcc(DisasContext *s, X86DecodedInsn *decode)
{
gen_bnd_jmp(s);
gen_jcc(s, decode->b & 0xf, decode->immediate);
}
-static void gen_JCXZ(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_JCXZ(DisasContext *s, X86DecodedInsn *decode)
{
TCGLabel *taken = gen_new_label();
@@ -1903,25 +1903,25 @@ static void gen_JCXZ(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
gen_conditional_jump_labels(s, decode->immediate, NULL, taken);
}
-static void gen_JMP(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_JMP(DisasContext *s, X86DecodedInsn *decode)
{
gen_update_cc_op(s);
gen_jmp_rel(s, s->dflag, decode->immediate, 0);
}
-static void gen_JMP_m(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_JMP_m(DisasContext *s, X86DecodedInsn *decode)
{
gen_op_jmp_v(s, s->T0);
gen_bnd_jmp(s);
s->base.is_jmp = DISAS_JUMP;
}
-static void gen_JMPF(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_JMPF(DisasContext *s, X86DecodedInsn *decode)
{
gen_far_jmp(s);
}
-static void gen_JMPF_m(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_JMPF_m(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[2].ot;
@@ -1931,7 +1931,7 @@ static void gen_JMPF_m(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode
gen_far_jmp(s);
}
-static void gen_LAHF(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_LAHF(DisasContext *s, X86DecodedInsn *decode)
{
if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM)) {
return gen_illegal_opcode(s);
@@ -1942,13 +1942,13 @@ static void gen_LAHF(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
tcg_gen_deposit_tl(cpu_regs[R_EAX], cpu_regs[R_EAX], s->T0, 8, 8);
}
-static void gen_LDMXCSR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_LDMXCSR(DisasContext *s, X86DecodedInsn *decode)
{
tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T1);
gen_helper_ldmxcsr(tcg_env, s->tmp2_i32);
}
-static void gen_lxx_seg(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode, int seg)
+static void gen_lxx_seg(DisasContext *s, X86DecodedInsn *decode, int seg)
{
MemOp ot = decode->op[0].ot;
@@ -1960,37 +1960,37 @@ static void gen_lxx_seg(DisasContext *s, CPUX86State *env, X86DecodedInsn *decod
gen_movl_seg(s, seg, s->T1);
}
-static void gen_LDS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_LDS(DisasContext *s, X86DecodedInsn *decode)
{
- gen_lxx_seg(s, env, decode, R_DS);
+ gen_lxx_seg(s, decode, R_DS);
}
-static void gen_LEA(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_LEA(DisasContext *s, X86DecodedInsn *decode)
{
tcg_gen_mov_tl(s->T0, s->A0);
}
-static void gen_LEAVE(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_LEAVE(DisasContext *s, X86DecodedInsn *decode)
{
gen_leave(s);
}
-static void gen_LES(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_LES(DisasContext *s, X86DecodedInsn *decode)
{
- gen_lxx_seg(s, env, decode, R_ES);
+ gen_lxx_seg(s, decode, R_ES);
}
-static void gen_LFS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_LFS(DisasContext *s, X86DecodedInsn *decode)
{
- gen_lxx_seg(s, env, decode, R_FS);
+ gen_lxx_seg(s, decode, R_FS);
}
-static void gen_LGS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_LGS(DisasContext *s, X86DecodedInsn *decode)
{
- gen_lxx_seg(s, env, decode, R_GS);
+ gen_lxx_seg(s, decode, R_GS);
}
-static void gen_LODS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_LODS(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[2].ot;
if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) {
@@ -2000,7 +2000,7 @@ static void gen_LODS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
}
}
-static void gen_LOOP(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_LOOP(DisasContext *s, X86DecodedInsn *decode)
{
TCGLabel *taken = gen_new_label();
@@ -2010,7 +2010,7 @@ static void gen_LOOP(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
gen_conditional_jump_labels(s, decode->immediate, NULL, taken);
}
-static void gen_LOOPE(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_LOOPE(DisasContext *s, X86DecodedInsn *decode)
{
TCGLabel *taken = gen_new_label();
TCGLabel *not_taken = gen_new_label();
@@ -2022,7 +2022,7 @@ static void gen_LOOPE(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
gen_conditional_jump_labels(s, decode->immediate, not_taken, taken);
}
-static void gen_LOOPNE(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_LOOPNE(DisasContext *s, X86DecodedInsn *decode)
{
TCGLabel *taken = gen_new_label();
TCGLabel *not_taken = gen_new_label();
@@ -2034,18 +2034,18 @@ static void gen_LOOPNE(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode
gen_conditional_jump_labels(s, decode->immediate, not_taken, taken);
}
-static void gen_LSS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_LSS(DisasContext *s, X86DecodedInsn *decode)
{
- gen_lxx_seg(s, env, decode, R_SS);
+ gen_lxx_seg(s, decode, R_SS);
}
-static void gen_MOV(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_MOV(DisasContext *s, X86DecodedInsn *decode)
{
/* nothing to do! */
}
#define gen_NOP gen_MOV
-static void gen_MASKMOV(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_MASKMOV(DisasContext *s, X86DecodedInsn *decode)
{
gen_lea_v_seg(s, cpu_regs[R_EDI], R_DS, s->override);
@@ -2056,7 +2056,7 @@ static void gen_MASKMOV(DisasContext *s, CPUX86State *env, X86DecodedInsn *decod
}
}
-static void gen_MOVBE(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_MOVBE(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[0].ot;
@@ -2068,7 +2068,7 @@ static void gen_MOVBE(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
}
}
-static void gen_MOVD_from(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_MOVD_from(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[2].ot;
@@ -2086,7 +2086,7 @@ static void gen_MOVD_from(DisasContext *s, CPUX86State *env, X86DecodedInsn *dec
}
}
-static void gen_MOVD_to(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_MOVD_to(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[2].ot;
int vec_len = vector_len(s, decode);
@@ -2108,12 +2108,12 @@ static void gen_MOVD_to(DisasContext *s, CPUX86State *env, X86DecodedInsn *decod
}
}
-static void gen_MOVDQ(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_MOVDQ(DisasContext *s, X86DecodedInsn *decode)
{
gen_store_sse(s, decode, decode->op[2].offset);
}
-static void gen_MOVMSK(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_MOVMSK(DisasContext *s, X86DecodedInsn *decode)
{
typeof(gen_helper_movmskps_ymm) *ps, *pd, *fn;
ps = s->vex_l ? gen_helper_movmskps_ymm : gen_helper_movmskps_xmm;
@@ -2123,7 +2123,7 @@ static void gen_MOVMSK(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode
tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32);
}
-static void gen_MOVQ(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_MOVQ(DisasContext *s, X86DecodedInsn *decode)
{
int vec_len = vector_len(s, decode);
int lo_ofs = vector_elem_offset(&decode->op[0], MO_64, 0);
@@ -2145,14 +2145,14 @@ static void gen_MOVQ(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
}
}
-static void gen_MOVq_dq(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_MOVq_dq(DisasContext *s, X86DecodedInsn *decode)
{
gen_helper_enter_mmx(tcg_env);
/* Otherwise the same as any other movq. */
- return gen_MOVQ(s, env, decode);
+ return gen_MOVQ(s, decode);
}
-static void gen_MOVS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_MOVS(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[2].ot;
if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) {
@@ -2162,7 +2162,7 @@ static void gen_MOVS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
}
}
-static void gen_MUL(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_MUL(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[1].ot;
@@ -2213,7 +2213,7 @@ static void gen_MUL(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
decode->cc_op = CC_OP_MULB + ot;
}
-static void gen_MULX(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_MULX(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[0].ot;
@@ -2239,7 +2239,7 @@ static void gen_MULX(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
}
}
-static void gen_NEG(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_NEG(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[0].ot;
TCGv oldv = tcg_temp_new();
@@ -2266,7 +2266,7 @@ static void gen_NEG(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
decode->cc_op = CC_OP_SUBB + ot;
}
-static void gen_NOT(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_NOT(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[0].ot;
@@ -2279,7 +2279,7 @@ static void gen_NOT(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
}
}
-static void gen_OR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_OR(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[1].ot;
@@ -2292,7 +2292,7 @@ static void gen_OR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
prepare_update1_cc(decode, s, CC_OP_LOGICB + ot);
}
-static void gen_OUT(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_OUT(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[1].ot;
TCGv_i32 port = tcg_temp_new_i32();
@@ -2309,7 +2309,7 @@ static void gen_OUT(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
gen_bpt_io(s, port, ot);
}
-static void gen_OUTS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_OUTS(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[1].ot;
TCGv_i32 port = tcg_temp_new_i32();
@@ -2328,7 +2328,7 @@ static void gen_OUTS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
}
}
-static void gen_PALIGNR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_PALIGNR(DisasContext *s, X86DecodedInsn *decode)
{
TCGv_i32 imm = tcg_constant8u_i32(decode->immediate);
if (!(s->prefix & PREFIX_DATA)) {
@@ -2340,7 +2340,7 @@ static void gen_PALIGNR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decod
}
}
-static void gen_PANDN(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_PANDN(DisasContext *s, X86DecodedInsn *decode)
{
int vec_len = vector_len(s, decode);
@@ -2350,7 +2350,7 @@ static void gen_PANDN(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
decode->op[1].offset, vec_len, vec_len);
}
-static void gen_PAUSE(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_PAUSE(DisasContext *s, X86DecodedInsn *decode)
{
gen_update_cc_op(s);
gen_update_eip_next(s);
@@ -2358,14 +2358,14 @@ static void gen_PAUSE(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
s->base.is_jmp = DISAS_NORETURN;
}
-static void gen_PCMPESTRI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_PCMPESTRI(DisasContext *s, X86DecodedInsn *decode)
{
TCGv_i32 imm = tcg_constant8u_i32(decode->immediate);
gen_helper_pcmpestri_xmm(tcg_env, OP_PTR1, OP_PTR2, imm);
assume_cc_op(s, CC_OP_EFLAGS);
}
-static void gen_PCMPESTRM(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_PCMPESTRM(DisasContext *s, X86DecodedInsn *decode)
{
TCGv_i32 imm = tcg_constant8u_i32(decode->immediate);
gen_helper_pcmpestrm_xmm(tcg_env, OP_PTR1, OP_PTR2, imm);
@@ -2376,14 +2376,14 @@ static void gen_PCMPESTRM(DisasContext *s, CPUX86State *env, X86DecodedInsn *dec
}
}
-static void gen_PCMPISTRI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_PCMPISTRI(DisasContext *s, X86DecodedInsn *decode)
{
TCGv_i32 imm = tcg_constant8u_i32(decode->immediate);
gen_helper_pcmpistri_xmm(tcg_env, OP_PTR1, OP_PTR2, imm);
assume_cc_op(s, CC_OP_EFLAGS);
}
-static void gen_PCMPISTRM(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_PCMPISTRM(DisasContext *s, X86DecodedInsn *decode)
{
TCGv_i32 imm = tcg_constant8u_i32(decode->immediate);
gen_helper_pcmpistrm_xmm(tcg_env, OP_PTR1, OP_PTR2, imm);
@@ -2394,17 +2394,17 @@ static void gen_PCMPISTRM(DisasContext *s, CPUX86State *env, X86DecodedInsn *dec
}
}
-static void gen_PDEP(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_PDEP(DisasContext *s, X86DecodedInsn *decode)
{
gen_helper_pdep(s->T0, s->T0, s->T1);
}
-static void gen_PEXT(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_PEXT(DisasContext *s, X86DecodedInsn *decode)
{
gen_helper_pext(s->T0, s->T0, s->T1);
}
-static inline void gen_pextr(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode, MemOp ot)
+static inline void gen_pextr(DisasContext *s, X86DecodedInsn *decode, MemOp ot)
{
int vec_len = vector_len(s, decode);
int mask = (vec_len >> ot) - 1;
@@ -2430,23 +2430,23 @@ static inline void gen_pextr(DisasContext *s, CPUX86State *env, X86DecodedInsn *
}
}
-static void gen_PEXTRB(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_PEXTRB(DisasContext *s, X86DecodedInsn *decode)
{
- gen_pextr(s, env, decode, MO_8);
+ gen_pextr(s, decode, MO_8);
}
-static void gen_PEXTRW(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_PEXTRW(DisasContext *s, X86DecodedInsn *decode)
{
- gen_pextr(s, env, decode, MO_16);
+ gen_pextr(s, decode, MO_16);
}
-static void gen_PEXTR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_PEXTR(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[0].ot;
- gen_pextr(s, env, decode, ot);
+ gen_pextr(s, decode, ot);
}
-static inline void gen_pinsr(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode, MemOp ot)
+static inline void gen_pinsr(DisasContext *s, X86DecodedInsn *decode, MemOp ot)
{
int vec_len = vector_len(s, decode);
int mask = (vec_len >> ot) - 1;
@@ -2477,19 +2477,19 @@ static inline void gen_pinsr(DisasContext *s, CPUX86State *env, X86DecodedInsn *
}
}
-static void gen_PINSRB(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_PINSRB(DisasContext *s, X86DecodedInsn *decode)
{
- gen_pinsr(s, env, decode, MO_8);
+ gen_pinsr(s, decode, MO_8);
}
-static void gen_PINSRW(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_PINSRW(DisasContext *s, X86DecodedInsn *decode)
{
- gen_pinsr(s, env, decode, MO_16);
+ gen_pinsr(s, decode, MO_16);
}
-static void gen_PINSR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_PINSR(DisasContext *s, X86DecodedInsn *decode)
{
- gen_pinsr(s, env, decode, decode->op[2].ot);
+ gen_pinsr(s, decode, decode->op[2].ot);
}
static void gen_pmovmskb_i64(TCGv_i64 d, TCGv_i64 s)
@@ -2529,7 +2529,7 @@ static void gen_pmovmskb_vec(unsigned vece, TCGv_vec d, TCGv_vec s)
tcg_gen_or_vec(vece, d, d, t);
}
-static void gen_PMOVMSKB(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_PMOVMSKB(DisasContext *s, X86DecodedInsn *decode)
{
static const TCGOpcode vecop_list[] = { INDEX_op_shli_vec, 0 };
static const GVecGen2 g = {
@@ -2573,7 +2573,7 @@ static void gen_PMOVMSKB(DisasContext *s, CPUX86State *env, X86DecodedInsn *deco
}
}
-static void gen_POP(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_POP(DisasContext *s, X86DecodedInsn *decode)
{
X86DecodedOp *op = &decode->op[0];
MemOp ot = gen_pop_T0(s);
@@ -2587,12 +2587,12 @@ static void gen_POP(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
gen_pop_update(s, ot);
}
-static void gen_POPA(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_POPA(DisasContext *s, X86DecodedInsn *decode)
{
gen_popa(s);
}
-static void gen_POPF(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_POPF(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot;
int mask = TF_MASK | AC_MASK | ID_MASK | NT_MASK;
@@ -2614,13 +2614,13 @@ static void gen_POPF(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
s->base.is_jmp = DISAS_EOB_NEXT;
}
-static void gen_PSHUFW(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_PSHUFW(DisasContext *s, X86DecodedInsn *decode)
{
TCGv_i32 imm = tcg_constant8u_i32(decode->immediate);
gen_helper_pshufw_mmx(OP_PTR0, OP_PTR1, imm);
}
-static void gen_PSRLW_i(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_PSRLW_i(DisasContext *s, X86DecodedInsn *decode)
{
int vec_len = vector_len(s, decode);
@@ -2633,7 +2633,7 @@ static void gen_PSRLW_i(DisasContext *s, CPUX86State *env, X86DecodedInsn *decod
}
}
-static void gen_PSLLW_i(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_PSLLW_i(DisasContext *s, X86DecodedInsn *decode)
{
int vec_len = vector_len(s, decode);
@@ -2646,7 +2646,7 @@ static void gen_PSLLW_i(DisasContext *s, CPUX86State *env, X86DecodedInsn *decod
}
}
-static void gen_PSRAW_i(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_PSRAW_i(DisasContext *s, X86DecodedInsn *decode)
{
int vec_len = vector_len(s, decode);
@@ -2658,7 +2658,7 @@ static void gen_PSRAW_i(DisasContext *s, CPUX86State *env, X86DecodedInsn *decod
decode->immediate, vec_len, vec_len);
}
-static void gen_PSRLD_i(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_PSRLD_i(DisasContext *s, X86DecodedInsn *decode)
{
int vec_len = vector_len(s, decode);
@@ -2671,7 +2671,7 @@ static void gen_PSRLD_i(DisasContext *s, CPUX86State *env, X86DecodedInsn *decod
}
}
-static void gen_PSLLD_i(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_PSLLD_i(DisasContext *s, X86DecodedInsn *decode)
{
int vec_len = vector_len(s, decode);
@@ -2684,7 +2684,7 @@ static void gen_PSLLD_i(DisasContext *s, CPUX86State *env, X86DecodedInsn *decod
}
}
-static void gen_PSRAD_i(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_PSRAD_i(DisasContext *s, X86DecodedInsn *decode)
{
int vec_len = vector_len(s, decode);
@@ -2696,7 +2696,7 @@ static void gen_PSRAD_i(DisasContext *s, CPUX86State *env, X86DecodedInsn *decod
decode->immediate, vec_len, vec_len);
}
-static void gen_PSRLQ_i(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_PSRLQ_i(DisasContext *s, X86DecodedInsn *decode)
{
int vec_len = vector_len(s, decode);
@@ -2709,7 +2709,7 @@ static void gen_PSRLQ_i(DisasContext *s, CPUX86State *env, X86DecodedInsn *decod
}
}
-static void gen_PSLLQ_i(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_PSLLQ_i(DisasContext *s, X86DecodedInsn *decode)
{
int vec_len = vector_len(s, decode);
@@ -2736,7 +2736,7 @@ static TCGv_ptr make_imm8u_xmm_vec(uint8_t imm, int vec_len)
return ptr;
}
-static void gen_PSRLDQ_i(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_PSRLDQ_i(DisasContext *s, X86DecodedInsn *decode)
{
int vec_len = vector_len(s, decode);
TCGv_ptr imm_vec = make_imm8u_xmm_vec(decode->immediate, vec_len);
@@ -2748,7 +2748,7 @@ static void gen_PSRLDQ_i(DisasContext *s, CPUX86State *env, X86DecodedInsn *deco
}
}
-static void gen_PSLLDQ_i(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_PSLLDQ_i(DisasContext *s, X86DecodedInsn *decode)
{
int vec_len = vector_len(s, decode);
TCGv_ptr imm_vec = make_imm8u_xmm_vec(decode->immediate, vec_len);
@@ -2760,17 +2760,17 @@ static void gen_PSLLDQ_i(DisasContext *s, CPUX86State *env, X86DecodedInsn *deco
}
}
-static void gen_PUSH(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_PUSH(DisasContext *s, X86DecodedInsn *decode)
{
gen_push_v(s, s->T1);
}
-static void gen_PUSHA(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_PUSHA(DisasContext *s, X86DecodedInsn *decode)
{
gen_pusha(s);
}
-static void gen_PUSHF(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_PUSHF(DisasContext *s, X86DecodedInsn *decode)
{
gen_update_cc_op(s);
gen_helper_read_eflags(s->T0, tcg_env);
@@ -2967,7 +2967,7 @@ static void gen_rotc_mod(MemOp ot, TCGv count)
* length - count, because (length-1) - (count-1) can be computed with
* a XOR, and that is commutative unlike subtraction.
*/
-static void gen_RCL(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_RCL(DisasContext *s, X86DecodedInsn *decode)
{
bool have_1bit_cin, can_be_zero;
TCGv count;
@@ -3019,7 +3019,7 @@ static void gen_RCL(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
}
}
-static void gen_RCR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_RCR(DisasContext *s, X86DecodedInsn *decode)
{
bool have_1bit_cin, can_be_zero;
TCGv count;
@@ -3072,7 +3072,7 @@ static void gen_RCR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
}
}
-static void gen_RET(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_RET(DisasContext *s, X86DecodedInsn *decode)
{
int16_t adjust = decode->e.op2 == X86_TYPE_I ? decode->immediate : 0;
@@ -3083,7 +3083,7 @@ static void gen_RET(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
s->base.is_jmp = DISAS_JUMP;
}
-static void gen_RETF(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_RETF(DisasContext *s, X86DecodedInsn *decode)
{
int16_t adjust = decode->e.op2 == X86_TYPE_I ? decode->immediate : 0;
@@ -3154,7 +3154,7 @@ static void gen_rot_carry(X86DecodedInsn *decode, TCGv result,
}
}
-static void gen_ROL(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_ROL(DisasContext *s, X86DecodedInsn *decode)
{
bool can_be_zero;
TCGv count;
@@ -3182,7 +3182,7 @@ static void gen_ROL(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
gen_rot_overflow(decode, s->T0, old, can_be_zero, count);
}
-static void gen_ROR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_ROR(DisasContext *s, X86DecodedInsn *decode)
{
bool can_be_zero;
TCGv count;
@@ -3211,7 +3211,7 @@ static void gen_ROR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
gen_rot_overflow(decode, s->T0, old, can_be_zero, count);
}
-static void gen_RORX(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_RORX(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[0].ot;
int mask = ot == MO_64 ? 63 : 31;
@@ -3235,7 +3235,7 @@ static void gen_RORX(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
}
}
-static void gen_SAHF(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_SAHF(DisasContext *s, X86DecodedInsn *decode)
{
if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM)) {
return gen_illegal_opcode(s);
@@ -3247,7 +3247,7 @@ static void gen_SAHF(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, s->T0);
}
-static void gen_SALC(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_SALC(DisasContext *s, X86DecodedInsn *decode)
{
gen_compute_eflags_c(s, s->T0);
tcg_gen_neg_tl(s->T0, s->T0);
@@ -3283,7 +3283,7 @@ static void gen_shift_dynamic_flags(DisasContext *s, X86DecodedInsn *decode, TCG
old_cc_op, tcg_constant_i32(cc_op));
}
-static void gen_SAR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_SAR(DisasContext *s, X86DecodedInsn *decode)
{
bool can_be_zero;
TCGv count;
@@ -3305,7 +3305,7 @@ static void gen_SAR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
}
}
-static void gen_SARX(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_SARX(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[0].ot;
int mask;
@@ -3315,7 +3315,7 @@ static void gen_SARX(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
tcg_gen_sar_tl(s->T0, s->T0, s->T1);
}
-static void gen_SBB(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_SBB(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[0].ot;
TCGv c_in = tcg_temp_new();
@@ -3337,7 +3337,7 @@ static void gen_SBB(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
prepare_update3_cc(decode, s, CC_OP_SBBB + ot, c_in);
}
-static void gen_SCAS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_SCAS(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[2].ot;
if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) {
@@ -3347,27 +3347,27 @@ static void gen_SCAS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
}
}
-static void gen_SETcc(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_SETcc(DisasContext *s, X86DecodedInsn *decode)
{
gen_setcc1(s, decode->b & 0xf, s->T0);
}
-static void gen_SHA1NEXTE(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_SHA1NEXTE(DisasContext *s, X86DecodedInsn *decode)
{
gen_helper_sha1nexte(OP_PTR0, OP_PTR1, OP_PTR2);
}
-static void gen_SHA1MSG1(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_SHA1MSG1(DisasContext *s, X86DecodedInsn *decode)
{
gen_helper_sha1msg1(OP_PTR0, OP_PTR1, OP_PTR2);
}
-static void gen_SHA1MSG2(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_SHA1MSG2(DisasContext *s, X86DecodedInsn *decode)
{
gen_helper_sha1msg2(OP_PTR0, OP_PTR1, OP_PTR2);
}
-static void gen_SHA1RNDS4(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_SHA1RNDS4(DisasContext *s, X86DecodedInsn *decode)
{
switch(decode->immediate & 3) {
case 0:
@@ -3385,17 +3385,17 @@ static void gen_SHA1RNDS4(DisasContext *s, CPUX86State *env, X86DecodedInsn *dec
}
}
-static void gen_SHA256MSG1(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_SHA256MSG1(DisasContext *s, X86DecodedInsn *decode)
{
gen_helper_sha256msg1(OP_PTR0, OP_PTR1, OP_PTR2);
}
-static void gen_SHA256MSG2(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_SHA256MSG2(DisasContext *s, X86DecodedInsn *decode)
{
gen_helper_sha256msg2(OP_PTR0, OP_PTR1, OP_PTR2);
}
-static void gen_SHA256RNDS2(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_SHA256RNDS2(DisasContext *s, X86DecodedInsn *decode)
{
TCGv_i32 wk0 = tcg_temp_new_i32();
TCGv_i32 wk1 = tcg_temp_new_i32();
@@ -3406,7 +3406,7 @@ static void gen_SHA256RNDS2(DisasContext *s, CPUX86State *env, X86DecodedInsn *d
gen_helper_sha256rnds2(OP_PTR0, OP_PTR1, OP_PTR2, wk0, wk1);
}
-static void gen_SHL(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_SHL(DisasContext *s, X86DecodedInsn *decode)
{
bool can_be_zero;
TCGv count;
@@ -3428,7 +3428,7 @@ static void gen_SHL(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
}
}
-static void gen_SHLX(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_SHLX(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[0].ot;
int mask;
@@ -3438,7 +3438,7 @@ static void gen_SHLX(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
tcg_gen_shl_tl(s->T0, s->T0, s->T1);
}
-static void gen_SHR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_SHR(DisasContext *s, X86DecodedInsn *decode)
{
bool can_be_zero;
TCGv count;
@@ -3460,7 +3460,7 @@ static void gen_SHR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
}
}
-static void gen_SHRX(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_SHRX(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[0].ot;
int mask;
@@ -3470,37 +3470,37 @@ static void gen_SHRX(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
tcg_gen_shr_tl(s->T0, s->T0, s->T1);
}
-static void gen_STC(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_STC(DisasContext *s, X86DecodedInsn *decode)
{
gen_compute_eflags(s);
tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C);
}
-static void gen_STD(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_STD(DisasContext *s, X86DecodedInsn *decode)
{
tcg_gen_st_i32(tcg_constant_i32(-1), tcg_env, offsetof(CPUX86State, df));
}
-static void gen_STI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_STI(DisasContext *s, X86DecodedInsn *decode)
{
gen_set_eflags(s, IF_MASK);
s->base.is_jmp = DISAS_EOB_INHIBIT_IRQ;
}
-static void gen_VAESKEYGEN(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VAESKEYGEN(DisasContext *s, X86DecodedInsn *decode)
{
TCGv_i32 imm = tcg_constant8u_i32(decode->immediate);
assert(!s->vex_l);
gen_helper_aeskeygenassist_xmm(tcg_env, OP_PTR0, OP_PTR1, imm);
}
-static void gen_STMXCSR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_STMXCSR(DisasContext *s, X86DecodedInsn *decode)
{
gen_helper_update_mxcsr(tcg_env);
tcg_gen_ld32u_tl(s->T0, tcg_env, offsetof(CPUX86State, mxcsr));
}
-static void gen_STOS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_STOS(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[1].ot;
if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) {
@@ -3510,7 +3510,7 @@ static void gen_STOS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
}
}
-static void gen_SUB(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_SUB(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[1].ot;
@@ -3526,12 +3526,12 @@ static void gen_SUB(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
prepare_update2_cc(decode, s, CC_OP_SUBB + ot);
}
-static void gen_UD(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_UD(DisasContext *s, X86DecodedInsn *decode)
{
gen_illegal_opcode(s);
}
-static void gen_VAESIMC(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VAESIMC(DisasContext *s, X86DecodedInsn *decode)
{
assert(!s->vex_l);
gen_helper_aesimc_xmm(tcg_env, OP_PTR0, OP_PTR2);
@@ -3586,7 +3586,7 @@ static const SSEFunc_0_eppp gen_helper_cmp_funcs[32][6] = {
};
#undef SSE_CMP
-static void gen_VCMP(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VCMP(DisasContext *s, X86DecodedInsn *decode)
{
int index = decode->immediate & (s->prefix & PREFIX_VEX ? 31 : 7);
int b =
@@ -3597,7 +3597,7 @@ static void gen_VCMP(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
gen_helper_cmp_funcs[index][b](tcg_env, OP_PTR0, OP_PTR1, OP_PTR2);
}
-static void gen_VCOMI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VCOMI(DisasContext *s, X86DecodedInsn *decode)
{
SSEFunc_0_epp fn;
fn = s->prefix & PREFIX_DATA ? gen_helper_comisd : gen_helper_comiss;
@@ -3605,7 +3605,7 @@ static void gen_VCOMI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
assume_cc_op(s, CC_OP_EFLAGS);
}
-static void gen_VCVTPD2PS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VCVTPD2PS(DisasContext *s, X86DecodedInsn *decode)
{
if (s->vex_l) {
gen_helper_cvtpd2ps_ymm(tcg_env, OP_PTR0, OP_PTR2);
@@ -3614,7 +3614,7 @@ static void gen_VCVTPD2PS(DisasContext *s, CPUX86State *env, X86DecodedInsn *dec
}
}
-static void gen_VCVTPS2PD(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VCVTPS2PD(DisasContext *s, X86DecodedInsn *decode)
{
if (s->vex_l) {
gen_helper_cvtps2pd_ymm(tcg_env, OP_PTR0, OP_PTR2);
@@ -3623,9 +3623,9 @@ static void gen_VCVTPS2PD(DisasContext *s, CPUX86State *env, X86DecodedInsn *dec
}
}
-static void gen_VCVTPS2PH(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VCVTPS2PH(DisasContext *s, X86DecodedInsn *decode)
{
- gen_unary_imm_fp_sse(s, env, decode,
+ gen_unary_imm_fp_sse(s, decode,
gen_helper_cvtps2ph_xmm,
gen_helper_cvtps2ph_ymm);
/*
@@ -3637,17 +3637,17 @@ static void gen_VCVTPS2PH(DisasContext *s, CPUX86State *env, X86DecodedInsn *dec
}
}
-static void gen_VCVTSD2SS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VCVTSD2SS(DisasContext *s, X86DecodedInsn *decode)
{
gen_helper_cvtsd2ss(tcg_env, OP_PTR0, OP_PTR1, OP_PTR2);
}
-static void gen_VCVTSS2SD(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VCVTSS2SD(DisasContext *s, X86DecodedInsn *decode)
{
gen_helper_cvtss2sd(tcg_env, OP_PTR0, OP_PTR1, OP_PTR2);
}
-static void gen_VCVTSI2Sx(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VCVTSI2Sx(DisasContext *s, X86DecodedInsn *decode)
{
int vec_len = vector_len(s, decode);
TCGv_i32 in;
@@ -3677,7 +3677,7 @@ static void gen_VCVTSI2Sx(DisasContext *s, CPUX86State *env, X86DecodedInsn *dec
}
}
-static inline void gen_VCVTtSx2SI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode,
+static inline void gen_VCVTtSx2SI(DisasContext *s, X86DecodedInsn *decode,
SSEFunc_i_ep ss2si, SSEFunc_l_ep ss2sq,
SSEFunc_i_ep sd2si, SSEFunc_l_ep sd2sq)
{
@@ -3715,21 +3715,21 @@ static inline void gen_VCVTtSx2SI(DisasContext *s, CPUX86State *env, X86DecodedI
#define gen_helper_cvttsd2sq NULL
#endif
-static void gen_VCVTSx2SI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VCVTSx2SI(DisasContext *s, X86DecodedInsn *decode)
{
- gen_VCVTtSx2SI(s, env, decode,
+ gen_VCVTtSx2SI(s, decode,
gen_helper_cvtss2si, gen_helper_cvtss2sq,
gen_helper_cvtsd2si, gen_helper_cvtsd2sq);
}
-static void gen_VCVTTSx2SI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VCVTTSx2SI(DisasContext *s, X86DecodedInsn *decode)
{
- gen_VCVTtSx2SI(s, env, decode,
+ gen_VCVTtSx2SI(s, decode,
gen_helper_cvttss2si, gen_helper_cvttss2sq,
gen_helper_cvttsd2si, gen_helper_cvttsd2sq);
}
-static void gen_VEXTRACTx128(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VEXTRACTx128(DisasContext *s, X86DecodedInsn *decode)
{
int mask = decode->immediate & 1;
int src_ofs = vector_elem_offset(&decode->op[1], MO_128, mask);
@@ -3741,12 +3741,12 @@ static void gen_VEXTRACTx128(DisasContext *s, CPUX86State *env, X86DecodedInsn *
}
}
-static void gen_VEXTRACTPS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VEXTRACTPS(DisasContext *s, X86DecodedInsn *decode)
{
- gen_pextr(s, env, decode, MO_32);
+ gen_pextr(s, decode, MO_32);
}
-static void gen_vinsertps(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_vinsertps(DisasContext *s, X86DecodedInsn *decode)
{
int val = decode->immediate;
int dest_word = (val >> 4) & 3;
@@ -3779,21 +3779,21 @@ static void gen_vinsertps(DisasContext *s, CPUX86State *env, X86DecodedInsn *dec
}
}
-static void gen_VINSERTPS_r(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VINSERTPS_r(DisasContext *s, X86DecodedInsn *decode)
{
int val = decode->immediate;
tcg_gen_ld_i32(s->tmp2_i32, tcg_env,
vector_elem_offset(&decode->op[2], MO_32, (val >> 6) & 3));
- gen_vinsertps(s, env, decode);
+ gen_vinsertps(s, decode);
}
-static void gen_VINSERTPS_m(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VINSERTPS_m(DisasContext *s, X86DecodedInsn *decode)
{
tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LEUL);
- gen_vinsertps(s, env, decode);
+ gen_vinsertps(s, decode);
}
-static void gen_VINSERTx128(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VINSERTx128(DisasContext *s, X86DecodedInsn *decode)
{
int mask = decode->immediate & 1;
tcg_gen_gvec_mov(MO_64,
@@ -3804,7 +3804,7 @@ static void gen_VINSERTx128(DisasContext *s, CPUX86State *env, X86DecodedInsn *d
decode->op[1].offset + offsetof(YMMReg, YMM_X(!mask)), 16, 16);
}
-static inline void gen_maskmov(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode,
+static inline void gen_maskmov(DisasContext *s, X86DecodedInsn *decode,
SSEFunc_0_eppt xmm, SSEFunc_0_eppt ymm)
{
if (!s->vex_l) {
@@ -3814,17 +3814,17 @@ static inline void gen_maskmov(DisasContext *s, CPUX86State *env, X86DecodedInsn
}
}
-static void gen_VMASKMOVPD_st(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VMASKMOVPD_st(DisasContext *s, X86DecodedInsn *decode)
{
- gen_maskmov(s, env, decode, gen_helper_vpmaskmovq_st_xmm, gen_helper_vpmaskmovq_st_ymm);
+ gen_maskmov(s, decode, gen_helper_vpmaskmovq_st_xmm, gen_helper_vpmaskmovq_st_ymm);
}
-static void gen_VMASKMOVPS_st(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VMASKMOVPS_st(DisasContext *s, X86DecodedInsn *decode)
{
- gen_maskmov(s, env, decode, gen_helper_vpmaskmovd_st_xmm, gen_helper_vpmaskmovd_st_ymm);
+ gen_maskmov(s, decode, gen_helper_vpmaskmovd_st_xmm, gen_helper_vpmaskmovd_st_ymm);
}
-static void gen_VMOVHPx_ld(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VMOVHPx_ld(DisasContext *s, X86DecodedInsn *decode)
{
gen_ldq_env_A0(s, decode->op[0].offset + offsetof(XMMReg, XMM_Q(1)));
if (decode->op[0].offset != decode->op[1].offset) {
@@ -3833,12 +3833,12 @@ static void gen_VMOVHPx_ld(DisasContext *s, CPUX86State *env, X86DecodedInsn *de
}
}
-static void gen_VMOVHPx_st(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VMOVHPx_st(DisasContext *s, X86DecodedInsn *decode)
{
gen_stq_env_A0(s, decode->op[2].offset + offsetof(XMMReg, XMM_Q(1)));
}
-static void gen_VMOVHPx(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VMOVHPx(DisasContext *s, X86DecodedInsn *decode)
{
if (decode->op[0].offset != decode->op[2].offset) {
tcg_gen_ld_i64(s->tmp1_i64, tcg_env, decode->op[2].offset + offsetof(XMMReg, XMM_Q(1)));
@@ -3850,7 +3850,7 @@ static void gen_VMOVHPx(DisasContext *s, CPUX86State *env, X86DecodedInsn *decod
}
}
-static void gen_VMOVHLPS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VMOVHLPS(DisasContext *s, X86DecodedInsn *decode)
{
tcg_gen_ld_i64(s->tmp1_i64, tcg_env, decode->op[2].offset + offsetof(XMMReg, XMM_Q(1)));
tcg_gen_st_i64(s->tmp1_i64, tcg_env, decode->op[0].offset + offsetof(XMMReg, XMM_Q(0)));
@@ -3860,7 +3860,7 @@ static void gen_VMOVHLPS(DisasContext *s, CPUX86State *env, X86DecodedInsn *deco
}
}
-static void gen_VMOVLHPS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VMOVLHPS(DisasContext *s, X86DecodedInsn *decode)
{
tcg_gen_ld_i64(s->tmp1_i64, tcg_env, decode->op[2].offset);
tcg_gen_st_i64(s->tmp1_i64, tcg_env, decode->op[0].offset + offsetof(XMMReg, XMM_Q(1)));
@@ -3875,7 +3875,7 @@ static void gen_VMOVLHPS(DisasContext *s, CPUX86State *env, X86DecodedInsn *deco
* Use a gvec move to move everything above the bottom 64 bits.
*/
-static void gen_VMOVLPx(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VMOVLPx(DisasContext *s, X86DecodedInsn *decode)
{
int vec_len = vector_len(s, decode);
@@ -3884,7 +3884,7 @@ static void gen_VMOVLPx(DisasContext *s, CPUX86State *env, X86DecodedInsn *decod
tcg_gen_st_i64(s->tmp1_i64, tcg_env, decode->op[0].offset + offsetof(XMMReg, XMM_Q(0)));
}
-static void gen_VMOVLPx_ld(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VMOVLPx_ld(DisasContext *s, X86DecodedInsn *decode)
{
int vec_len = vector_len(s, decode);
@@ -3893,13 +3893,13 @@ static void gen_VMOVLPx_ld(DisasContext *s, CPUX86State *env, X86DecodedInsn *de
tcg_gen_st_i64(s->tmp1_i64, OP_PTR0, offsetof(ZMMReg, ZMM_Q(0)));
}
-static void gen_VMOVLPx_st(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VMOVLPx_st(DisasContext *s, X86DecodedInsn *decode)
{
tcg_gen_ld_i64(s->tmp1_i64, OP_PTR2, offsetof(ZMMReg, ZMM_Q(0)));
tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEUQ);
}
-static void gen_VMOVSD_ld(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VMOVSD_ld(DisasContext *s, X86DecodedInsn *decode)
{
TCGv_i64 zero = tcg_constant_i64(0);
@@ -3908,7 +3908,7 @@ static void gen_VMOVSD_ld(DisasContext *s, CPUX86State *env, X86DecodedInsn *dec
tcg_gen_st_i64(s->tmp1_i64, OP_PTR0, offsetof(ZMMReg, ZMM_Q(0)));
}
-static void gen_VMOVSS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VMOVSS(DisasContext *s, X86DecodedInsn *decode)
{
int vec_len = vector_len(s, decode);
@@ -3917,7 +3917,7 @@ static void gen_VMOVSS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode
tcg_gen_st_i32(s->tmp2_i32, OP_PTR0, offsetof(ZMMReg, ZMM_L(0)));
}
-static void gen_VMOVSS_ld(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VMOVSS_ld(DisasContext *s, X86DecodedInsn *decode)
{
int vec_len = vector_len(s, decode);
@@ -3926,55 +3926,55 @@ static void gen_VMOVSS_ld(DisasContext *s, CPUX86State *env, X86DecodedInsn *dec
tcg_gen_st_i32(s->tmp2_i32, OP_PTR0, offsetof(ZMMReg, ZMM_L(0)));
}
-static void gen_VMOVSS_st(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VMOVSS_st(DisasContext *s, X86DecodedInsn *decode)
{
tcg_gen_ld_i32(s->tmp2_i32, OP_PTR2, offsetof(ZMMReg, ZMM_L(0)));
tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LEUL);
}
-static void gen_VPMASKMOV_st(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VPMASKMOV_st(DisasContext *s, X86DecodedInsn *decode)
{
if (s->vex_w) {
- gen_VMASKMOVPD_st(s, env, decode);
+ gen_VMASKMOVPD_st(s, decode);
} else {
- gen_VMASKMOVPS_st(s, env, decode);
+ gen_VMASKMOVPS_st(s, decode);
}
}
-static void gen_VPERMD(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VPERMD(DisasContext *s, X86DecodedInsn *decode)
{
assert(s->vex_l);
gen_helper_vpermd_ymm(OP_PTR0, OP_PTR1, OP_PTR2);
}
-static void gen_VPERM2x128(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VPERM2x128(DisasContext *s, X86DecodedInsn *decode)
{
TCGv_i32 imm = tcg_constant8u_i32(decode->immediate);
assert(s->vex_l);
gen_helper_vpermdq_ymm(OP_PTR0, OP_PTR1, OP_PTR2, imm);
}
-static void gen_VPHMINPOSUW(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VPHMINPOSUW(DisasContext *s, X86DecodedInsn *decode)
{
assert(!s->vex_l);
gen_helper_phminposuw_xmm(tcg_env, OP_PTR0, OP_PTR2);
}
-static void gen_VROUNDSD(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VROUNDSD(DisasContext *s, X86DecodedInsn *decode)
{
TCGv_i32 imm = tcg_constant8u_i32(decode->immediate);
assert(!s->vex_l);
gen_helper_roundsd_xmm(tcg_env, OP_PTR0, OP_PTR1, OP_PTR2, imm);
}
-static void gen_VROUNDSS(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VROUNDSS(DisasContext *s, X86DecodedInsn *decode)
{
TCGv_i32 imm = tcg_constant8u_i32(decode->immediate);
assert(!s->vex_l);
gen_helper_roundss_xmm(tcg_env, OP_PTR0, OP_PTR1, OP_PTR2, imm);
}
-static void gen_VSHUF(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VSHUF(DisasContext *s, X86DecodedInsn *decode)
{
TCGv_i32 imm = tcg_constant_i32(decode->immediate);
SSEFunc_0_pppi ps, pd, fn;
@@ -3984,7 +3984,7 @@ static void gen_VSHUF(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
fn(OP_PTR0, OP_PTR1, OP_PTR2, imm);
}
-static void gen_VUCOMI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VUCOMI(DisasContext *s, X86DecodedInsn *decode)
{
SSEFunc_0_epp fn;
fn = s->prefix & PREFIX_DATA ? gen_helper_ucomisd : gen_helper_ucomiss;
@@ -3992,7 +3992,7 @@ static void gen_VUCOMI(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode
assume_cc_op(s, CC_OP_EFLAGS);
}
-static void gen_VZEROALL(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VZEROALL(DisasContext *s, X86DecodedInsn *decode)
{
TCGv_ptr ptr = tcg_temp_new_ptr();
@@ -4001,7 +4001,7 @@ static void gen_VZEROALL(DisasContext *s, CPUX86State *env, X86DecodedInsn *deco
tcg_constant_ptr(CPU_NB_REGS * sizeof(ZMMReg)));
}
-static void gen_VZEROUPPER(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_VZEROUPPER(DisasContext *s, X86DecodedInsn *decode)
{
int i;
@@ -4011,7 +4011,7 @@ static void gen_VZEROUPPER(DisasContext *s, CPUX86State *env, X86DecodedInsn *de
}
}
-static void gen_WAIT(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_WAIT(DisasContext *s, X86DecodedInsn *decode)
{
if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) == (HF_MP_MASK | HF_TS_MASK)) {
gen_NM_exception(s);
@@ -4022,7 +4022,7 @@ static void gen_WAIT(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
}
}
-static void gen_XCHG(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_XCHG(DisasContext *s, X86DecodedInsn *decode)
{
if (s->prefix & PREFIX_LOCK) {
tcg_gen_atomic_xchg_tl(s->T0, s->A0, s->T1,
@@ -4036,7 +4036,7 @@ static void gen_XCHG(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
}
}
-static void gen_XLAT(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_XLAT(DisasContext *s, X86DecodedInsn *decode)
{
/* AL is already zero-extended into s->T0. */
tcg_gen_add_tl(s->A0, cpu_regs[R_EBX], s->T0);
@@ -4044,7 +4044,7 @@ static void gen_XLAT(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
gen_op_ld_v(s, MO_8, s->T0, s->A0);
}
-static void gen_XOR(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode)
+static void gen_XOR(DisasContext *s, X86DecodedInsn *decode)
{
/* special case XOR reg, reg */
if (decode->op[1].unit == X86_OP_INT &&
--
2.45.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PULL 07/25] target/i386: rewrite flags writeback for ADCX/ADOX
2024-06-11 14:24 [PULL 00/25] target/i386, SCSI changes for 2024-06-11 Paolo Bonzini
` (5 preceding siblings ...)
2024-06-11 14:25 ` [PULL 06/25] target/i386: remove CPUX86State argument from generator functions Paolo Bonzini
@ 2024-06-11 14:25 ` Paolo Bonzini
2024-06-11 14:25 ` [PULL 08/25] target/i386: put BLS* input in T1, use generic flag writeback Paolo Bonzini
` (18 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Paolo Bonzini @ 2024-06-11 14:25 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson
Avoid using set_cc_op() in preparation for implementing APX; treat
CC_OP_EFLAGS similar to the case where we have the "opposite" cc_op
(CC_OP_ADOX for ADCX and CC_OP_ADCX for ADOX), except the resulting
cc_op is not CC_OP_ADCOX. This is written easily as two "if"s, whose
conditions are both false for CC_OP_EFLAGS, both true for CC_OP_ADCOX,
and one each true for CC_OP_ADCX/ADOX.
The new logic also makes it easy to drop usage of tmp0.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/cpu.h | 9 +++---
target/i386/tcg/emit.c.inc | 61 ++++++++++++++++++++++----------------
2 files changed, 40 insertions(+), 30 deletions(-)
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 8fe28b67e0f..7e2a9b56aea 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -1260,6 +1260,8 @@ uint64_t x86_cpu_get_supported_feature_word(FeatureWord w,
/* Use a clearer name for this. */
#define CPU_INTERRUPT_INIT CPU_INTERRUPT_RESET
+#define CC_OP_HAS_EFLAGS(op) ((op) >= CC_OP_EFLAGS && (op) <= CC_OP_ADCOX)
+
/* Instead of computing the condition codes after each x86 instruction,
* QEMU just stores one operand (called CC_SRC), the result
* (called CC_DST) and the type of operation (called CC_OP). When the
@@ -1270,6 +1272,9 @@ uint64_t x86_cpu_get_supported_feature_word(FeatureWord w,
typedef enum {
CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */
CC_OP_EFLAGS, /* all cc are explicitly computed, CC_SRC = flags */
+ CC_OP_ADCX, /* CC_DST = C, CC_SRC = rest. */
+ CC_OP_ADOX, /* CC_SRC2 = O, CC_SRC = rest. */
+ CC_OP_ADCOX, /* CC_DST = C, CC_SRC2 = O, CC_SRC = rest. */
CC_OP_MULB, /* modify all flags, C, O = (CC_SRC != 0) */
CC_OP_MULW,
@@ -1326,10 +1331,6 @@ typedef enum {
CC_OP_BMILGL,
CC_OP_BMILGQ,
- CC_OP_ADCX, /* CC_DST = C, CC_SRC = rest. */
- CC_OP_ADOX, /* CC_DST = O, CC_SRC = rest. */
- CC_OP_ADCOX, /* CC_DST = C, CC_SRC2 = O, CC_SRC = rest. */
-
CC_OP_CLR, /* Z set, all other flags clear. */
CC_OP_POPCNT, /* Z via CC_SRC, all other flags clear. */
diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
index df7597c7e2f..2041ea9d04a 100644
--- a/target/i386/tcg/emit.c.inc
+++ b/target/i386/tcg/emit.c.inc
@@ -1122,24 +1122,41 @@ static void gen_ADC(DisasContext *s, X86DecodedInsn *decode)
prepare_update3_cc(decode, s, CC_OP_ADCB + ot, c_in);
}
-/* ADCX/ADOX do not have memory operands and can use set_cc_op. */
-static void gen_ADCOX(DisasContext *s, MemOp ot, int cc_op)
+static void gen_ADCOX(DisasContext *s, X86DecodedInsn *decode, int cc_op)
{
- int opposite_cc_op;
+ MemOp ot = decode->op[0].ot;
TCGv carry_in = NULL;
- TCGv carry_out = (cc_op == CC_OP_ADCX ? cpu_cc_dst : cpu_cc_src2);
+ TCGv *carry_out = (cc_op == CC_OP_ADCX ? &decode->cc_dst : &decode->cc_src2);
TCGv zero;
- if (cc_op == s->cc_op || s->cc_op == CC_OP_ADCOX) {
- /* Re-use the carry-out from a previous round. */
- carry_in = carry_out;
- } else {
- /* We don't have a carry-in, get it out of EFLAGS. */
- if (s->cc_op != CC_OP_ADCX && s->cc_op != CC_OP_ADOX) {
- gen_compute_eflags(s);
+ decode->cc_op = cc_op;
+ *carry_out = tcg_temp_new();
+ if (CC_OP_HAS_EFLAGS(s->cc_op)) {
+ decode->cc_src = cpu_cc_src;
+
+ /* Re-use the carry-out from a previous round? */
+ if (s->cc_op == cc_op || s->cc_op == CC_OP_ADCOX) {
+ carry_in = (cc_op == CC_OP_ADCX ? cpu_cc_dst : cpu_cc_src2);
}
- carry_in = s->tmp0;
- tcg_gen_extract_tl(carry_in, cpu_cc_src,
+
+ /* Preserve the opposite carry from previous rounds? */
+ if (s->cc_op != cc_op && s->cc_op != CC_OP_EFLAGS) {
+ decode->cc_op = CC_OP_ADCOX;
+ if (carry_out == &decode->cc_dst) {
+ decode->cc_src2 = cpu_cc_src2;
+ } else {
+ decode->cc_dst = cpu_cc_dst;
+ }
+ }
+ } else {
+ decode->cc_src = tcg_temp_new();
+ gen_mov_eflags(s, decode->cc_src);
+ }
+
+ if (!carry_in) {
+ /* Get carry_in out of EFLAGS. */
+ carry_in = tcg_temp_new();
+ tcg_gen_extract_tl(carry_in, decode->cc_src,
ctz32(cc_op == CC_OP_ADCX ? CC_C : CC_O), 1);
}
@@ -1151,28 +1168,20 @@ static void gen_ADCOX(DisasContext *s, MemOp ot, int cc_op)
tcg_gen_ext32u_tl(s->T1, s->T1);
tcg_gen_add_i64(s->T0, s->T0, s->T1);
tcg_gen_add_i64(s->T0, s->T0, carry_in);
- tcg_gen_shri_i64(carry_out, s->T0, 32);
+ tcg_gen_shri_i64(*carry_out, s->T0, 32);
break;
#endif
default:
zero = tcg_constant_tl(0);
- tcg_gen_add2_tl(s->T0, carry_out, s->T0, zero, carry_in, zero);
- tcg_gen_add2_tl(s->T0, carry_out, s->T0, carry_out, s->T1, zero);
+ tcg_gen_add2_tl(s->T0, *carry_out, s->T0, zero, carry_in, zero);
+ tcg_gen_add2_tl(s->T0, *carry_out, s->T0, *carry_out, s->T1, zero);
break;
}
-
- opposite_cc_op = cc_op == CC_OP_ADCX ? CC_OP_ADOX : CC_OP_ADCX;
- if (s->cc_op == CC_OP_ADCOX || s->cc_op == opposite_cc_op) {
- /* Merge with the carry-out from the opposite instruction. */
- set_cc_op(s, CC_OP_ADCOX);
- } else {
- set_cc_op(s, cc_op);
- }
}
static void gen_ADCX(DisasContext *s, X86DecodedInsn *decode)
{
- gen_ADCOX(s, decode->op[0].ot, CC_OP_ADCX);
+ gen_ADCOX(s, decode, CC_OP_ADCX);
}
static void gen_ADD(DisasContext *s, X86DecodedInsn *decode)
@@ -1190,7 +1199,7 @@ static void gen_ADD(DisasContext *s, X86DecodedInsn *decode)
static void gen_ADOX(DisasContext *s, X86DecodedInsn *decode)
{
- gen_ADCOX(s, decode->op[0].ot, CC_OP_ADOX);
+ gen_ADCOX(s, decode, CC_OP_ADOX);
}
static void gen_AND(DisasContext *s, X86DecodedInsn *decode)
--
2.45.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PULL 08/25] target/i386: put BLS* input in T1, use generic flag writeback
2024-06-11 14:24 [PULL 00/25] target/i386, SCSI changes for 2024-06-11 Paolo Bonzini
` (6 preceding siblings ...)
2024-06-11 14:25 ` [PULL 07/25] target/i386: rewrite flags writeback for ADCX/ADOX Paolo Bonzini
@ 2024-06-11 14:25 ` Paolo Bonzini
2024-06-11 14:25 ` [PULL 09/25] target/i386: change X86_ENTRYr to use T0 Paolo Bonzini
` (17 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Paolo Bonzini @ 2024-06-11 14:25 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson
This makes for easier cpu_cc_* setup, and not using set_cc_op()
should come in handy if QEMU ever implements APX.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/tcg/decode-new.c.inc | 4 ++--
target/i386/tcg/emit.c.inc | 24 +++++++++---------------
2 files changed, 11 insertions(+), 17 deletions(-)
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index e7d88020481..380fb793531 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -633,7 +633,7 @@ static const X86OpEntry opcodes_0F38_F0toFF[16][5] = {
{},
},
[3] = {
- X86_OP_GROUP3(group17, B,y, E,y, None,None, vex13 cpuid(BMI1)),
+ X86_OP_GROUP3(group17, B,y, None,None, E,y, vex13 cpuid(BMI1)),
{},
{},
{},
@@ -2604,7 +2604,7 @@ static void disas_insn(DisasContext *s, CPUState *cpu)
}
/*
- * Write back flags after last memory access. Some newer ALU instructions, as
+ * Write back flags after last memory access. Some older ALU instructions, as
* well as SSE instructions, write flags in the gen_* function, but that can
* cause incorrect tracking of CC_OP for instructions that write to both memory
* and flags.
diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
index 2041ea9d04a..a25b3dfc6b5 100644
--- a/target/i386/tcg/emit.c.inc
+++ b/target/i386/tcg/emit.c.inc
@@ -1272,40 +1272,34 @@ static void gen_BEXTR(DisasContext *s, X86DecodedInsn *decode)
prepare_update1_cc(decode, s, CC_OP_LOGICB + ot);
}
-/* BLSI do not have memory operands and can use set_cc_op. */
static void gen_BLSI(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[0].ot;
- tcg_gen_mov_tl(cpu_cc_src, s->T0);
- tcg_gen_neg_tl(s->T1, s->T0);
+ /* input in T1, which is ready for prepare_update2_cc */
+ tcg_gen_neg_tl(s->T0, s->T1);
tcg_gen_and_tl(s->T0, s->T0, s->T1);
- tcg_gen_mov_tl(cpu_cc_dst, s->T0);
- set_cc_op(s, CC_OP_BMILGB + ot);
+ prepare_update2_cc(decode, s, CC_OP_BMILGB + ot);
}
-/* BLSMSK do not have memory operands and can use set_cc_op. */
static void gen_BLSMSK(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[0].ot;
- tcg_gen_mov_tl(cpu_cc_src, s->T0);
- tcg_gen_subi_tl(s->T1, s->T0, 1);
+ /* input in T1, which is ready for prepare_update2_cc */
+ tcg_gen_subi_tl(s->T0, s->T1, 1);
tcg_gen_xor_tl(s->T0, s->T0, s->T1);
- tcg_gen_mov_tl(cpu_cc_dst, s->T0);
- set_cc_op(s, CC_OP_BMILGB + ot);
+ prepare_update2_cc(decode, s, CC_OP_BMILGB + ot);
}
-/* BLSR do not have memory operands and can use set_cc_op. */
static void gen_BLSR(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[0].ot;
- tcg_gen_mov_tl(cpu_cc_src, s->T0);
- tcg_gen_subi_tl(s->T1, s->T0, 1);
+ /* input in T1, which is ready for prepare_update2_cc */
+ tcg_gen_subi_tl(s->T0, s->T1, 1);
tcg_gen_and_tl(s->T0, s->T0, s->T1);
- tcg_gen_mov_tl(cpu_cc_dst, s->T0);
- set_cc_op(s, CC_OP_BMILGB + ot);
+ prepare_update2_cc(decode, s, CC_OP_BMILGB + ot);
}
static void gen_BOUND(DisasContext *s, X86DecodedInsn *decode)
--
2.45.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PULL 09/25] target/i386: change X86_ENTRYr to use T0
2024-06-11 14:24 [PULL 00/25] target/i386, SCSI changes for 2024-06-11 Paolo Bonzini
` (7 preceding siblings ...)
2024-06-11 14:25 ` [PULL 08/25] target/i386: put BLS* input in T1, use generic flag writeback Paolo Bonzini
@ 2024-06-11 14:25 ` Paolo Bonzini
2024-06-11 14:25 ` [PULL 10/25] target/i386: change X86_ENTRYwr to use T0, use it for moves Paolo Bonzini
` (16 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Paolo Bonzini @ 2024-06-11 14:25 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson
I am not sure why I made it use T1. It is a bit more symmetric with
respect to X86_ENTRYwr (which uses T0 for the "w"ritten operand
and T1 for the "r"ead operand), but it is also less flexible because it
does not let you apply zextT0/sextT0.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/tcg/decode-new.c.inc | 6 +++---
target/i386/tcg/emit.c.inc | 34 ++++++++++++++++----------------
2 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index 380fb793531..f9d3e2577b2 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -186,7 +186,7 @@
#define X86_OP_ENTRYw(op, op0, s0, ...) \
X86_OP_ENTRY3(op, op0, s0, None, None, None, None, ## __VA_ARGS__)
#define X86_OP_ENTRYr(op, op0, s0, ...) \
- X86_OP_ENTRY3(op, None, None, None, None, op0, s0, ## __VA_ARGS__)
+ X86_OP_ENTRY3(op, None, None, op0, s0, None, None, ## __VA_ARGS__)
#define X86_OP_ENTRY1(op, op0, s0, ...) \
X86_OP_ENTRY3(op, op0, s0, 2op, s0, None, None, ## __VA_ARGS__)
#define X86_OP_ENTRY0(op, ...) \
@@ -1335,9 +1335,9 @@ static void decode_group4_5(DisasContext *s, CPUX86State *env, X86OpEntry *entry
/* 0xff */
[0x08] = X86_OP_ENTRY1(INC, E,v, lock),
[0x09] = X86_OP_ENTRY1(DEC, E,v, lock),
- [0x0a] = X86_OP_ENTRY3(CALL_m, None, None, E,f64, None, None, zextT0),
+ [0x0a] = X86_OP_ENTRYr(CALL_m, E,f64, zextT0),
[0x0b] = X86_OP_ENTRYr(CALLF_m, M,p),
- [0x0c] = X86_OP_ENTRY3(JMP_m, None, None, E,f64, None, None, zextT0),
+ [0x0c] = X86_OP_ENTRYr(JMP_m, E,f64, zextT0),
[0x0d] = X86_OP_ENTRYr(JMPF_m, M,p),
[0x0e] = X86_OP_ENTRYr(PUSH, E,f64),
};
diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
index a25b3dfc6b5..797e6e81406 100644
--- a/target/i386/tcg/emit.c.inc
+++ b/target/i386/tcg/emit.c.inc
@@ -1363,7 +1363,7 @@ static void gen_CALLF(DisasContext *s, X86DecodedInsn *decode)
static void gen_CALLF_m(DisasContext *s, X86DecodedInsn *decode)
{
- MemOp ot = decode->op[2].ot;
+ MemOp ot = decode->op[1].ot;
gen_op_ld_v(s, ot, s->T0, s->A0);
gen_add_A0_im(s, 1 << ot);
@@ -1593,22 +1593,22 @@ static void gen_DEC(DisasContext *s, X86DecodedInsn *decode)
static void gen_DIV(DisasContext *s, X86DecodedInsn *decode)
{
- MemOp ot = decode->op[2].ot;
+ MemOp ot = decode->op[1].ot;
switch(ot) {
case MO_8:
- gen_helper_divb_AL(tcg_env, s->T1);
+ gen_helper_divb_AL(tcg_env, s->T0);
break;
case MO_16:
- gen_helper_divw_AX(tcg_env, s->T1);
+ gen_helper_divw_AX(tcg_env, s->T0);
break;
default:
case MO_32:
- gen_helper_divl_EAX(tcg_env, s->T1);
+ gen_helper_divl_EAX(tcg_env, s->T0);
break;
#ifdef TARGET_X86_64
case MO_64:
- gen_helper_divq_EAX(tcg_env, s->T1);
+ gen_helper_divq_EAX(tcg_env, s->T0);
break;
#endif
}
@@ -1649,22 +1649,22 @@ static void gen_HLT(DisasContext *s, X86DecodedInsn *decode)
static void gen_IDIV(DisasContext *s, X86DecodedInsn *decode)
{
- MemOp ot = decode->op[2].ot;
+ MemOp ot = decode->op[1].ot;
switch(ot) {
case MO_8:
- gen_helper_idivb_AL(tcg_env, s->T1);
+ gen_helper_idivb_AL(tcg_env, s->T0);
break;
case MO_16:
- gen_helper_idivw_AX(tcg_env, s->T1);
+ gen_helper_idivw_AX(tcg_env, s->T0);
break;
default:
case MO_32:
- gen_helper_idivl_EAX(tcg_env, s->T1);
+ gen_helper_idivl_EAX(tcg_env, s->T0);
break;
#ifdef TARGET_X86_64
case MO_64:
- gen_helper_idivq_EAX(tcg_env, s->T1);
+ gen_helper_idivq_EAX(tcg_env, s->T0);
break;
#endif
}
@@ -1926,7 +1926,7 @@ static void gen_JMPF(DisasContext *s, X86DecodedInsn *decode)
static void gen_JMPF_m(DisasContext *s, X86DecodedInsn *decode)
{
- MemOp ot = decode->op[2].ot;
+ MemOp ot = decode->op[1].ot;
gen_op_ld_v(s, ot, s->T0, s->A0);
gen_add_A0_im(s, 1 << ot);
@@ -1947,7 +1947,7 @@ static void gen_LAHF(DisasContext *s, X86DecodedInsn *decode)
static void gen_LDMXCSR(DisasContext *s, X86DecodedInsn *decode)
{
- tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T1);
+ tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
gen_helper_ldmxcsr(tcg_env, s->tmp2_i32);
}
@@ -1995,7 +1995,7 @@ static void gen_LGS(DisasContext *s, X86DecodedInsn *decode)
static void gen_LODS(DisasContext *s, X86DecodedInsn *decode)
{
- MemOp ot = decode->op[2].ot;
+ MemOp ot = decode->op[1].ot;
if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) {
gen_repz(s, ot, gen_lods);
} else {
@@ -2765,7 +2765,7 @@ static void gen_PSLLDQ_i(DisasContext *s, X86DecodedInsn *decode)
static void gen_PUSH(DisasContext *s, X86DecodedInsn *decode)
{
- gen_push_v(s, s->T1);
+ gen_push_v(s, s->T0);
}
static void gen_PUSHA(DisasContext *s, X86DecodedInsn *decode)
@@ -3077,7 +3077,7 @@ static void gen_RCR(DisasContext *s, X86DecodedInsn *decode)
static void gen_RET(DisasContext *s, X86DecodedInsn *decode)
{
- int16_t adjust = decode->e.op2 == X86_TYPE_I ? decode->immediate : 0;
+ int16_t adjust = decode->e.op1 == X86_TYPE_I ? decode->immediate : 0;
MemOp ot = gen_pop_T0(s);
gen_stack_update(s, adjust + (1 << ot));
@@ -3088,7 +3088,7 @@ static void gen_RET(DisasContext *s, X86DecodedInsn *decode)
static void gen_RETF(DisasContext *s, X86DecodedInsn *decode)
{
- int16_t adjust = decode->e.op2 == X86_TYPE_I ? decode->immediate : 0;
+ int16_t adjust = decode->e.op1 == X86_TYPE_I ? decode->immediate : 0;
if (!PE(s) || VM86(s)) {
gen_lea_ss_ofs(s, s->A0, cpu_regs[R_ESP], 0);
--
2.45.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PULL 10/25] target/i386: change X86_ENTRYwr to use T0, use it for moves
2024-06-11 14:24 [PULL 00/25] target/i386, SCSI changes for 2024-06-11 Paolo Bonzini
` (8 preceding siblings ...)
2024-06-11 14:25 ` [PULL 09/25] target/i386: change X86_ENTRYr to use T0 Paolo Bonzini
@ 2024-06-11 14:25 ` Paolo Bonzini
2024-06-11 14:25 ` [PULL 11/25] target/i386: replace NoSeg special with NoLoadEA Paolo Bonzini
` (15 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Paolo Bonzini @ 2024-06-11 14:25 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson
Just like X86_ENTRYr, X86_ENTRYwr is easily changed to use only T0.
In this case, the motivation is to use it for the MOV instruction
family. The case when you need to preserve the input value is the
odd one, as it is used basically only for BLS* instructions.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/tcg/decode-new.c.inc | 48 ++++++++++++++++----------------
target/i386/tcg/emit.c.inc | 2 +-
2 files changed, 25 insertions(+), 25 deletions(-)
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index f9d3e2577b2..d41002e2f5c 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -180,7 +180,7 @@
#define X86_OP_ENTRYrr(op, op0, s0, op1, s1, ...) \
X86_OP_ENTRY3(op, None, None, op0, s0, op1, s1, ## __VA_ARGS__)
#define X86_OP_ENTRYwr(op, op0, s0, op1, s1, ...) \
- X86_OP_ENTRY3(op, op0, s0, None, None, op1, s1, ## __VA_ARGS__)
+ X86_OP_ENTRY3(op, op0, s0, op1, s1, None, None, ## __VA_ARGS__)
#define X86_OP_ENTRY2(op, op0, s0, op1, s1, ...) \
X86_OP_ENTRY3(op, op0, s0, 2op, s0, op1, s1, ## __VA_ARGS__)
#define X86_OP_ENTRYw(op, op0, s0, ...) \
@@ -612,15 +612,15 @@ static const X86OpEntry opcodes_0F38_00toEF[240] = {
/* five rows for no prefix, 66, F3, F2, 66+F2 */
static const X86OpEntry opcodes_0F38_F0toFF[16][5] = {
[0] = {
- X86_OP_ENTRY3(MOVBE, G,y, M,y, None,None, cpuid(MOVBE)),
- X86_OP_ENTRY3(MOVBE, G,w, M,w, None,None, cpuid(MOVBE)),
+ X86_OP_ENTRYwr(MOVBE, G,y, M,y, cpuid(MOVBE)),
+ X86_OP_ENTRYwr(MOVBE, G,w, M,w, cpuid(MOVBE)),
{},
X86_OP_ENTRY2(CRC32, G,d, E,b, cpuid(SSE42)),
X86_OP_ENTRY2(CRC32, G,d, E,b, cpuid(SSE42)),
},
[1] = {
- X86_OP_ENTRY3(MOVBE, M,y, G,y, None,None, cpuid(MOVBE)),
- X86_OP_ENTRY3(MOVBE, M,w, G,w, None,None, cpuid(MOVBE)),
+ X86_OP_ENTRYwr(MOVBE, M,y, G,y, cpuid(MOVBE)),
+ X86_OP_ENTRYwr(MOVBE, M,w, G,w, cpuid(MOVBE)),
{},
X86_OP_ENTRY2(CRC32, G,d, E,y, cpuid(SSE42)),
X86_OP_ENTRY2(CRC32, G,d, E,w, cpuid(SSE42)),
@@ -1586,18 +1586,18 @@ static const X86OpEntry opcodes_root[256] = {
[0x7E] = X86_OP_ENTRYr(Jcc, J,b),
[0x7F] = X86_OP_ENTRYr(Jcc, J,b),
- [0x88] = X86_OP_ENTRY3(MOV, E,b, G,b, None, None),
- [0x89] = X86_OP_ENTRY3(MOV, E,v, G,v, None, None),
- [0x8A] = X86_OP_ENTRY3(MOV, G,b, E,b, None, None),
- [0x8B] = X86_OP_ENTRY3(MOV, G,v, E,v, None, None),
- /* Missing in Table A-2: memory destination is always 16-bit. */
- [0x8C] = X86_OP_ENTRY3(MOV, E,v, S,w, None, None, op0_Mw),
- [0x8D] = X86_OP_ENTRY3(LEA, G,v, M,v, None, None, noseg),
- [0x8E] = X86_OP_ENTRY3(MOV, S,w, E,w, None, None),
+ [0x88] = X86_OP_ENTRYwr(MOV, E,b, G,b),
+ [0x89] = X86_OP_ENTRYwr(MOV, E,v, G,v),
+ [0x8A] = X86_OP_ENTRYwr(MOV, G,b, E,b),
+ [0x8B] = X86_OP_ENTRYwr(MOV, G,v, E,v),
+ /* Missing in Table A-2: memory destination is always 16-bit. */
+ [0x8C] = X86_OP_ENTRYwr(MOV, E,v, S,w, op0_Mw),
+ [0x8D] = X86_OP_ENTRYwr(LEA, G,v, M,v, noseg),
+ [0x8E] = X86_OP_ENTRYwr(MOV, S,w, E,w),
[0x8F] = X86_OP_GROUPw(group1A, E,v),
[0x98] = X86_OP_ENTRY1(CBW, 0,v), /* rAX */
- [0x99] = X86_OP_ENTRY3(CWD, 2,v, 0,v, None, None), /* rDX, rAX */
+ [0x99] = X86_OP_ENTRYwr(CWD, 2,v, 0,v), /* rDX, rAX */
[0x9A] = X86_OP_ENTRYrr(CALLF, I_unsigned,p, I_unsigned,w, chk(i64)),
[0x9B] = X86_OP_ENTRY0(WAIT),
[0x9C] = X86_OP_ENTRY0(PUSHF, chk(vm86_iopl) svm(PUSHF)),
@@ -1607,22 +1607,22 @@ static const X86OpEntry opcodes_root[256] = {
[0xA8] = X86_OP_ENTRYrr(AND, 0,b, I,b), /* AL, Ib */
[0xA9] = X86_OP_ENTRYrr(AND, 0,v, I,z), /* rAX, Iz */
- [0xAA] = X86_OP_ENTRY3(STOS, Y,b, 0,b, None, None),
- [0xAB] = X86_OP_ENTRY3(STOS, Y,v, 0,v, None, None),
+ [0xAA] = X86_OP_ENTRYwr(STOS, Y,b, 0,b),
+ [0xAB] = X86_OP_ENTRYwr(STOS, Y,v, 0,v),
/* Manual writeback because REP LODS (!) has to write EAX/RAX after every LODS. */
[0xAC] = X86_OP_ENTRYr(LODS, X,b),
[0xAD] = X86_OP_ENTRYr(LODS, X,v),
[0xAE] = X86_OP_ENTRYrr(SCAS, 0,b, Y,b),
[0xAF] = X86_OP_ENTRYrr(SCAS, 0,v, Y,v),
- [0xB8] = X86_OP_ENTRY3(MOV, LoBits,v, I,v, None, None),
- [0xB9] = X86_OP_ENTRY3(MOV, LoBits,v, I,v, None, None),
- [0xBA] = X86_OP_ENTRY3(MOV, LoBits,v, I,v, None, None),
- [0xBB] = X86_OP_ENTRY3(MOV, LoBits,v, I,v, None, None),
- [0xBC] = X86_OP_ENTRY3(MOV, LoBits,v, I,v, None, None),
- [0xBD] = X86_OP_ENTRY3(MOV, LoBits,v, I,v, None, None),
- [0xBE] = X86_OP_ENTRY3(MOV, LoBits,v, I,v, None, None),
- [0xBF] = X86_OP_ENTRY3(MOV, LoBits,v, I,v, None, None),
+ [0xB8] = X86_OP_ENTRYwr(MOV, LoBits,v, I,v),
+ [0xB9] = X86_OP_ENTRYwr(MOV, LoBits,v, I,v),
+ [0xBA] = X86_OP_ENTRYwr(MOV, LoBits,v, I,v),
+ [0xBB] = X86_OP_ENTRYwr(MOV, LoBits,v, I,v),
+ [0xBC] = X86_OP_ENTRYwr(MOV, LoBits,v, I,v),
+ [0xBD] = X86_OP_ENTRYwr(MOV, LoBits,v, I,v),
+ [0xBE] = X86_OP_ENTRYwr(MOV, LoBits,v, I,v),
+ [0xBF] = X86_OP_ENTRYwr(MOV, LoBits,v, I,v),
[0xC8] = X86_OP_ENTRYrr(ENTER, I,w, I,b),
[0xC9] = X86_OP_ENTRY1(LEAVE, A,d64),
diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
index 797e6e81406..78d89db57cd 100644
--- a/target/i386/tcg/emit.c.inc
+++ b/target/i386/tcg/emit.c.inc
@@ -1796,7 +1796,7 @@ static void gen_IN(DisasContext *s, X86DecodedInsn *decode)
MemOp ot = decode->op[0].ot;
TCGv_i32 port = tcg_temp_new_i32();
- tcg_gen_trunc_tl_i32(port, s->T1);
+ tcg_gen_trunc_tl_i32(port, s->T0);
tcg_gen_ext16u_i32(port, port);
if (!gen_check_io(s, ot, port, SVM_IOIO_TYPE_MASK)) {
return;
--
2.45.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PULL 11/25] target/i386: replace NoSeg special with NoLoadEA
2024-06-11 14:24 [PULL 00/25] target/i386, SCSI changes for 2024-06-11 Paolo Bonzini
` (9 preceding siblings ...)
2024-06-11 14:25 ` [PULL 10/25] target/i386: change X86_ENTRYwr to use T0, use it for moves Paolo Bonzini
@ 2024-06-11 14:25 ` Paolo Bonzini
2024-06-11 14:25 ` [PULL 12/25] target/i386: fix processing of intercept 0 (read CR0) Paolo Bonzini
` (14 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Paolo Bonzini @ 2024-06-11 14:25 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson
This is a bit more generic, as it can be applied to MPX as well.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/tcg/decode-new.h | 5 +++--
target/i386/tcg/decode-new.c.inc | 12 ++++--------
target/i386/tcg/emit.c.inc | 3 ++-
3 files changed, 9 insertions(+), 11 deletions(-)
diff --git a/target/i386/tcg/decode-new.h b/target/i386/tcg/decode-new.h
index f704698575f..46a96b220d0 100644
--- a/target/i386/tcg/decode-new.h
+++ b/target/i386/tcg/decode-new.h
@@ -170,8 +170,9 @@ typedef enum X86InsnSpecial {
/* Always locked if it has a memory operand (XCHG) */
X86_SPECIAL_Locked,
- /* Do not apply segment base to effective address */
- X86_SPECIAL_NoSeg,
+ /* Do not load effective address in s->A0 */
+ X86_SPECIAL_NoLoadEA,
+
/*
* Rd/Mb or Rd/Mw in the manual: register operand 0 is treated as 32 bits
* (and writeback zero-extends it to 64 bits if applicable). PREFIX_DATA
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index d41002e2f5c..4f5fcdb88dd 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -193,7 +193,7 @@
X86_OP_ENTRY3(op, None, None, None, None, None, None, ## __VA_ARGS__)
#define cpuid(feat) .cpuid = X86_FEAT_##feat,
-#define noseg .special = X86_SPECIAL_NoSeg,
+#define nolea .special = X86_SPECIAL_NoLoadEA,
#define xchg .special = X86_SPECIAL_Locked,
#define lock .special = X86_SPECIAL_HasLock,
#define mmx .special = X86_SPECIAL_MMX,
@@ -1592,7 +1592,7 @@ static const X86OpEntry opcodes_root[256] = {
[0x8B] = X86_OP_ENTRYwr(MOV, G,v, E,v),
/* Missing in Table A-2: memory destination is always 16-bit. */
[0x8C] = X86_OP_ENTRYwr(MOV, E,v, S,w, op0_Mw),
- [0x8D] = X86_OP_ENTRYwr(LEA, G,v, M,v, noseg),
+ [0x8D] = X86_OP_ENTRYwr(LEA, G,v, M,v, nolea),
[0x8E] = X86_OP_ENTRYwr(MOV, S,w, E,w),
[0x8F] = X86_OP_GROUPw(group1A, E,v),
@@ -2524,11 +2524,6 @@ static void disas_insn(DisasContext *s, CPUState *cpu)
assert(decode.op[1].unit == X86_OP_INT);
break;
- case X86_SPECIAL_NoSeg:
- decode.mem.def_seg = -1;
- s->override = -1;
- break;
-
case X86_SPECIAL_Op0_Mw:
assert(decode.op[0].unit == X86_OP_INT);
if (decode.op[0].has_ea) {
@@ -2585,7 +2580,8 @@ static void disas_insn(DisasContext *s, CPUState *cpu)
gen_helper_enter_mmx(tcg_env);
}
- if (decode.op[0].has_ea || decode.op[1].has_ea || decode.op[2].has_ea) {
+ if (decode.e.special != X86_SPECIAL_NoLoadEA &&
+ (decode.op[0].has_ea || decode.op[1].has_ea || decode.op[2].has_ea)) {
gen_load_ea(s, &decode.mem, decode.e.vex_class == 12);
}
if (s->prefix & PREFIX_LOCK) {
diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
index 78d89db57cd..e6521632edd 100644
--- a/target/i386/tcg/emit.c.inc
+++ b/target/i386/tcg/emit.c.inc
@@ -1970,7 +1970,8 @@ static void gen_LDS(DisasContext *s, X86DecodedInsn *decode)
static void gen_LEA(DisasContext *s, X86DecodedInsn *decode)
{
- tcg_gen_mov_tl(s->T0, s->A0);
+ TCGv ea = gen_lea_modrm_1(s, decode->mem, false);
+ gen_lea_v_seg_dest(s, s->aflag, s->T0, ea, -1, -1);
}
static void gen_LEAVE(DisasContext *s, X86DecodedInsn *decode)
--
2.45.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PULL 12/25] target/i386: fix processing of intercept 0 (read CR0)
2024-06-11 14:24 [PULL 00/25] target/i386, SCSI changes for 2024-06-11 Paolo Bonzini
` (10 preceding siblings ...)
2024-06-11 14:25 ` [PULL 11/25] target/i386: replace NoSeg special with NoLoadEA Paolo Bonzini
@ 2024-06-11 14:25 ` Paolo Bonzini
2024-06-11 14:25 ` [PULL 13/25] target/i386: convert MOV from/to CR and DR to new decoder Paolo Bonzini
` (13 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Paolo Bonzini @ 2024-06-11 14:25 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/tcg/decode-new.h | 1 +
target/i386/tcg/decode-new.c.inc | 4 ++--
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/target/i386/tcg/decode-new.h b/target/i386/tcg/decode-new.h
index 46a96b220d0..8465717ea21 100644
--- a/target/i386/tcg/decode-new.h
+++ b/target/i386/tcg/decode-new.h
@@ -272,6 +272,7 @@ struct X86OpEntry {
unsigned valid_prefix:16;
unsigned check:16;
unsigned intercept:8;
+ bool has_intercept:1;
bool is_decode:1;
};
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index 4f5fcdb88dd..cd925fe3589 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -221,7 +221,7 @@
#define vex13 .vex_class = 13,
#define chk(a) .check = X86_CHECK_##a,
-#define svm(a) .intercept = SVM_EXIT_##a,
+#define svm(a) .intercept = SVM_EXIT_##a, .has_intercept = true,
#define avx2_256 .vex_special = X86_VEX_AVX2_256,
@@ -2559,7 +2559,7 @@ static void disas_insn(DisasContext *s, CPUState *cpu)
goto gp_fault;
}
}
- if (decode.e.intercept && unlikely(GUEST(s))) {
+ if (decode.e.has_intercept && unlikely(GUEST(s))) {
gen_helper_svm_check_intercept(tcg_env,
tcg_constant_i32(decode.e.intercept));
}
--
2.45.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PULL 13/25] target/i386: convert MOV from/to CR and DR to new decoder
2024-06-11 14:24 [PULL 00/25] target/i386, SCSI changes for 2024-06-11 Paolo Bonzini
` (11 preceding siblings ...)
2024-06-11 14:25 ` [PULL 12/25] target/i386: fix processing of intercept 0 (read CR0) Paolo Bonzini
@ 2024-06-11 14:25 ` Paolo Bonzini
2024-06-11 14:25 ` [PULL 14/25] target/i386: fix bad sorting of entries in the 0F table Paolo Bonzini
` (12 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Paolo Bonzini @ 2024-06-11 14:25 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson
Complete implementation of C and D operand types, then the operations
are just MOVs.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/tcg/translate.c | 79 --------------------------------
target/i386/tcg/decode-new.c.inc | 53 +++++++++++++++++++--
target/i386/tcg/emit.c.inc | 20 +++++++-
3 files changed, 68 insertions(+), 84 deletions(-)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index fcba9c155f9..4958f4c45d5 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -247,9 +247,6 @@ STUB_HELPER(outb, TCGv_env env, TCGv_i32 port, TCGv_i32 val)
STUB_HELPER(outw, TCGv_env env, TCGv_i32 port, TCGv_i32 val)
STUB_HELPER(outl, TCGv_env env, TCGv_i32 port, TCGv_i32 val)
STUB_HELPER(rdmsr, TCGv_env env)
-STUB_HELPER(read_crN, TCGv ret, TCGv_env env, TCGv_i32 reg)
-STUB_HELPER(get_dr, TCGv ret, TCGv_env env, TCGv_i32 reg)
-STUB_HELPER(set_dr, TCGv_env env, TCGv_i32 reg, TCGv val)
STUB_HELPER(stgi, TCGv_env env)
STUB_HELPER(svm_check_intercept, TCGv_env env, TCGv_i32 type)
STUB_HELPER(vmload, TCGv_env env, TCGv_i32 aflag)
@@ -4192,82 +4189,6 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b)
gen_nop_modrm(env, s, modrm);
break;
- case 0x120: /* mov reg, crN */
- case 0x122: /* mov crN, reg */
- if (!check_cpl0(s)) {
- break;
- }
- modrm = x86_ldub_code(env, s);
- /*
- * Ignore the mod bits (assume (modrm&0xc0)==0xc0).
- * AMD documentation (24594.pdf) and testing of Intel 386 and 486
- * processors all show that the mod bits are assumed to be 1's,
- * regardless of actual values.
- */
- rm = (modrm & 7) | REX_B(s);
- reg = ((modrm >> 3) & 7) | REX_R(s);
- switch (reg) {
- case 0:
- if ((prefixes & PREFIX_LOCK) &&
- (s->cpuid_ext3_features & CPUID_EXT3_CR8LEG)) {
- reg = 8;
- }
- break;
- case 2:
- case 3:
- case 4:
- case 8:
- break;
- default:
- goto unknown_op;
- }
- ot = (CODE64(s) ? MO_64 : MO_32);
-
- translator_io_start(&s->base);
- if (b & 2) {
- gen_svm_check_intercept(s, SVM_EXIT_WRITE_CR0 + reg);
- gen_op_mov_v_reg(s, ot, s->T0, rm);
- gen_helper_write_crN(tcg_env, tcg_constant_i32(reg), s->T0);
- s->base.is_jmp = DISAS_EOB_NEXT;
- } else {
- gen_svm_check_intercept(s, SVM_EXIT_READ_CR0 + reg);
- gen_helper_read_crN(s->T0, tcg_env, tcg_constant_i32(reg));
- gen_op_mov_reg_v(s, ot, rm, s->T0);
- }
- break;
-
- case 0x121: /* mov reg, drN */
- case 0x123: /* mov drN, reg */
- if (check_cpl0(s)) {
- modrm = x86_ldub_code(env, s);
- /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
- * AMD documentation (24594.pdf) and testing of
- * intel 386 and 486 processors all show that the mod bits
- * are assumed to be 1's, regardless of actual values.
- */
- rm = (modrm & 7) | REX_B(s);
- reg = ((modrm >> 3) & 7) | REX_R(s);
- if (CODE64(s))
- ot = MO_64;
- else
- ot = MO_32;
- if (reg >= 8) {
- goto illegal_op;
- }
- if (b & 2) {
- gen_svm_check_intercept(s, SVM_EXIT_WRITE_DR0 + reg);
- gen_op_mov_v_reg(s, ot, s->T0, rm);
- tcg_gen_movi_i32(s->tmp2_i32, reg);
- gen_helper_set_dr(tcg_env, s->tmp2_i32, s->T0);
- s->base.is_jmp = DISAS_EOB_NEXT;
- } else {
- gen_svm_check_intercept(s, SVM_EXIT_READ_DR0 + reg);
- tcg_gen_movi_i32(s->tmp2_i32, reg);
- gen_helper_get_dr(s->T0, tcg_env, s->tmp2_i32);
- gen_op_mov_reg_v(s, ot, rm, s->T0);
- }
- }
- break;
case 0x106: /* clts */
if (check_cpl0(s)) {
gen_svm_check_intercept(s, SVM_EXIT_WRITE_CR0);
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index cd925fe3589..4c567911f41 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -151,6 +151,8 @@
X86_OP_GROUP3(op, op0, s0, 2op, s0, op1, s1, ## __VA_ARGS__)
#define X86_OP_GROUPw(op, op0, s0, ...) \
X86_OP_GROUP3(op, op0, s0, None, None, None, None, ## __VA_ARGS__)
+#define X86_OP_GROUPwr(op, op0, s0, op1, s1, ...) \
+ X86_OP_GROUP3(op, op0, s0, op1, s1, None, None, ## __VA_ARGS__)
#define X86_OP_GROUP0(op, ...) \
X86_OP_GROUP3(op, None, None, None, None, None, None, ## __VA_ARGS__)
@@ -985,6 +987,24 @@ static void decode_0FE6(DisasContext *s, CPUX86State *env, X86OpEntry *entry, ui
*entry = *decode_by_prefix(s, opcodes_0FE6);
}
+/* These are a bit weird, so group all the pre-decode tweaks here. */
+static void decode_MOV_CR_DR(DisasContext *s, CPUX86State *env, X86OpEntry *entry, uint8_t *b)
+{
+ /* No 16-bit mode. */
+ s->dflag = MO_32;
+
+ /*
+ * Ignore the mod bits (assume (modrm&0xc0)==0xc0).
+ * AMD documentation (24594.pdf) and testing of Intel 386 and 486
+ * processors all show that the mod bits are assumed to be 1's,
+ * regardless of actual values.
+ */
+ get_modrm(s, env);
+ s->modrm |= 0xC0;
+
+ entry->gen = gen_MOV;
+}
+
static const X86OpEntry opcodes_0F[256] = {
[0x0E] = X86_OP_ENTRY0(EMMS, cpuid(3DNOW)), /* femms */
/*
@@ -1004,6 +1024,11 @@ static const X86OpEntry opcodes_0F[256] = {
/* Incorrectly listed as Mq,Vq in the manual */
[0x17] = X86_OP_ENTRY3(VMOVHPx_st, M,q, None,None, V,dq, vex5 p_00_66),
+ [0x20] = X86_OP_GROUPwr(MOV_CR_DR, R,y, C,y, chk(cpl0) svm(READ_CR0)),
+ [0x21] = X86_OP_GROUPwr(MOV_CR_DR, R,y, D,y, chk(cpl0) svm(READ_DR0)),
+ [0x22] = X86_OP_GROUPwr(MOV_CR_DR, C,y, R,y, zextT0 chk(cpl0) svm(WRITE_CR0)),
+ [0x23] = X86_OP_GROUPwr(MOV_CR_DR, D,y, R,y, zextT0 chk(cpl0) svm(WRITE_DR0)),
+
[0x40] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
[0x41] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
[0x42] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
@@ -1802,11 +1827,34 @@ static bool decode_op(DisasContext *s, CPUX86State *env, X86DecodedInsn *decode,
case X86_TYPE_C: /* REG in the modrm byte selects a control register */
op->unit = X86_OP_CR;
- goto get_reg;
+ op->n = ((get_modrm(s, env) >> 3) & 7) | REX_R(s);
+ if (op->n == 0 && (s->prefix & PREFIX_LOCK) &&
+ (s->cpuid_ext3_features & CPUID_EXT3_CR8LEG)) {
+ op->n = 8;
+ s->prefix &= ~PREFIX_LOCK;
+ }
+ if (op->n != 0 && op->n != 2 && op->n != 3 && op->n != 4 && op->n != 8) {
+ return false;
+ }
+ if (decode->e.intercept) {
+ decode->e.intercept += op->n;
+ }
+ break;
case X86_TYPE_D: /* REG in the modrm byte selects a debug register */
op->unit = X86_OP_DR;
- goto get_reg;
+ op->n = ((get_modrm(s, env) >> 3) & 7) | REX_R(s);
+ if (op->n >= 8) {
+ /*
+ * illegal opcode. The DR4 and DR5 case is checked in the generated
+ * code instead, to save on hflags bits.
+ */
+ return false;
+ }
+ if (decode->e.intercept) {
+ decode->e.intercept += op->n;
+ }
+ break;
case X86_TYPE_G: /* REG in the modrm byte selects a GPR */
op->unit = X86_OP_INT;
@@ -2431,7 +2479,6 @@ static void disas_insn(DisasContext *s, CPUState *cpu)
case 0x00 ... 0x03: /* mostly privileged instructions */
case 0x05 ... 0x09:
case 0x1a ... 0x1b: /* MPX */
- case 0x20 ... 0x23: /* mov from/to CR and DR */
case 0x30 ... 0x35: /* more privileged instructions */
case 0xa2 ... 0xa5: /* CPUID, BT, SHLD */
case 0xaa ... 0xae: /* RSM, SHRD, grp15 */
diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
index e6521632edd..bcb6bccbd75 100644
--- a/target/i386/tcg/emit.c.inc
+++ b/target/i386/tcg/emit.c.inc
@@ -242,12 +242,19 @@ static void gen_load(DisasContext *s, X86DecodedInsn *decode, int opn, TCGv v)
tcg_gen_ld32u_tl(v, tcg_env,
offsetof(CPUX86State,segs[op->n].selector));
break;
+#ifndef CONFIG_USER_ONLY
case X86_OP_CR:
- tcg_gen_ld_tl(v, tcg_env, offsetof(CPUX86State, cr[op->n]));
+ if (op->n == 8) {
+ gen_helper_read_crN(v, tcg_env, tcg_constant_i32(op->n));
+ } else {
+ tcg_gen_ld_tl(v, tcg_env, offsetof(CPUX86State, cr[op->n]));
+ }
break;
case X86_OP_DR:
- tcg_gen_ld_tl(v, tcg_env, offsetof(CPUX86State, dr[op->n]));
+ /* CR4.DE tested in the helper. */
+ gen_helper_get_dr(v, tcg_env, tcg_constant_i32(op->n));
break;
+#endif
case X86_OP_INT:
if (op->has_ea) {
if (v == s->T0 && decode->e.special == X86_SPECIAL_SExtT0) {
@@ -343,8 +350,17 @@ static void gen_writeback(DisasContext *s, X86DecodedInsn *decode, int opn, TCGv
16, 16, 0);
}
break;
+#ifndef CONFIG_USER_ONLY
case X86_OP_CR:
+ gen_helper_write_crN(tcg_env, tcg_constant_i32(op->n), v);
+ s->base.is_jmp = DISAS_EOB_NEXT;
+ break;
case X86_OP_DR:
+ /* CR4.DE tested in the helper. */
+ gen_helper_set_dr(tcg_env, tcg_constant_i32(op->n), v);
+ s->base.is_jmp = DISAS_EOB_NEXT;
+ break;
+#endif
default:
g_assert_not_reached();
}
--
2.45.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PULL 14/25] target/i386: fix bad sorting of entries in the 0F table
2024-06-11 14:24 [PULL 00/25] target/i386, SCSI changes for 2024-06-11 Paolo Bonzini
` (12 preceding siblings ...)
2024-06-11 14:25 ` [PULL 13/25] target/i386: convert MOV from/to CR and DR to new decoder Paolo Bonzini
@ 2024-06-11 14:25 ` Paolo Bonzini
2024-06-11 14:25 ` [PULL 15/25] target/i386: finish converting 0F AE to the new decoder Paolo Bonzini
` (11 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Paolo Bonzini @ 2024-06-11 14:25 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson
Aesthetic change only.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/tcg/decode-new.c.inc | 93 ++++++++++++++++----------------
1 file changed, 46 insertions(+), 47 deletions(-)
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index 4c567911f41..4e745f10dd8 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -1006,14 +1006,6 @@ static void decode_MOV_CR_DR(DisasContext *s, CPUX86State *env, X86OpEntry *entr
}
static const X86OpEntry opcodes_0F[256] = {
- [0x0E] = X86_OP_ENTRY0(EMMS, cpuid(3DNOW)), /* femms */
- /*
- * 3DNow!'s opcode byte comes *after* modrm and displacements, making it
- * more like an Ib operand. Dispatch to the right helper in a single gen_*
- * function.
- */
- [0x0F] = X86_OP_ENTRY3(3dnow, P,q, Q,q, I,b, cpuid(3DNOW)),
-
[0x10] = X86_OP_GROUP0(0F10),
[0x11] = X86_OP_GROUP0(0F11),
[0x12] = X86_OP_GROUP0(0F12),
@@ -1086,8 +1078,54 @@ static const X86OpEntry opcodes_0F[256] = {
[0xa0] = X86_OP_ENTRYr(PUSH, FS, w),
[0xa1] = X86_OP_ENTRYw(POP, FS, w),
+ [0xb2] = X86_OP_ENTRY3(LSS, G,v, EM,p, None, None),
+ [0xb4] = X86_OP_ENTRY3(LFS, G,v, EM,p, None, None),
+ [0xb5] = X86_OP_ENTRY3(LGS, G,v, EM,p, None, None),
+ [0xb6] = X86_OP_ENTRY3(MOV, G,v, E,b, None, None, zextT0), /* MOVZX */
+ [0xb7] = X86_OP_ENTRY3(MOV, G,v, E,w, None, None, zextT0), /* MOVZX */
+
+ [0xc2] = X86_OP_ENTRY4(VCMP, V,x, H,x, W,x, vex2_rep3 p_00_66_f3_f2),
+ [0xc3] = X86_OP_ENTRY3(MOV, EM,y,G,y, None,None, cpuid(SSE2)), /* MOVNTI */
+ [0xc4] = X86_OP_ENTRY4(PINSRW, V,dq,H,dq,E,w, vex5 mmx p_00_66),
+ [0xc5] = X86_OP_ENTRY3(PEXTRW, G,d, U,dq,I,b, vex5 mmx p_00_66),
+ [0xc6] = X86_OP_ENTRY4(VSHUF, V,x, H,x, W,x, vex4 p_00_66),
+
+ [0xd0] = X86_OP_ENTRY3(VADDSUB, V,x, H,x, W,x, vex2 cpuid(SSE3) p_66_f2),
+ [0xd1] = X86_OP_ENTRY3(PSRLW_r, V,x, H,x, W,x, vex4 mmx avx2_256 p_00_66),
+ [0xd2] = X86_OP_ENTRY3(PSRLD_r, V,x, H,x, W,x, vex4 mmx avx2_256 p_00_66),
+ [0xd3] = X86_OP_ENTRY3(PSRLQ_r, V,x, H,x, W,x, vex4 mmx avx2_256 p_00_66),
+ [0xd4] = X86_OP_ENTRY3(PADDQ, V,x, H,x, W,x, vex4 mmx avx2_256 p_00_66),
+ [0xd5] = X86_OP_ENTRY3(PMULLW, V,x, H,x, W,x, vex4 mmx avx2_256 p_00_66),
+ [0xd6] = X86_OP_GROUP0(0FD6),
+ [0xd7] = X86_OP_ENTRY3(PMOVMSKB, G,d, None,None, U,x, vex7 mmx avx2_256 p_00_66),
+
+ [0xe0] = X86_OP_ENTRY3(PAVGB, V,x, H,x, W,x, vex4 mmx avx2_256 p_00_66),
+ [0xe1] = X86_OP_ENTRY3(PSRAW_r, V,x, H,x, W,x, vex7 mmx avx2_256 p_00_66),
+ [0xe2] = X86_OP_ENTRY3(PSRAD_r, V,x, H,x, W,x, vex7 mmx avx2_256 p_00_66),
+ [0xe3] = X86_OP_ENTRY3(PAVGW, V,x, H,x, W,x, vex4 mmx avx2_256 p_00_66),
+ [0xe4] = X86_OP_ENTRY3(PMULHUW, V,x, H,x, W,x, vex4 mmx avx2_256 p_00_66),
+ [0xe5] = X86_OP_ENTRY3(PMULHW, V,x, H,x, W,x, vex4 mmx avx2_256 p_00_66),
+ [0xe6] = X86_OP_GROUP0(0FE6),
+ [0xe7] = X86_OP_ENTRY3(MOVDQ, W,x, None,None, V,x, vex1 mmx p_00_66), /* MOVNTQ/MOVNTDQ */
+
+ [0xf0] = X86_OP_ENTRY3(MOVDQ, V,x, None,None, WM,x, vex4_unal cpuid(SSE3) p_f2), /* LDDQU */
+ [0xf1] = X86_OP_ENTRY3(PSLLW_r, V,x, H,x, W,x, vex7 mmx avx2_256 p_00_66),
+ [0xf2] = X86_OP_ENTRY3(PSLLD_r, V,x, H,x, W,x, vex7 mmx avx2_256 p_00_66),
+ [0xf3] = X86_OP_ENTRY3(PSLLQ_r, V,x, H,x, W,x, vex7 mmx avx2_256 p_00_66),
+ [0xf4] = X86_OP_ENTRY3(PMULUDQ, V,x, H,x, W,x, vex4 mmx avx2_256 p_00_66),
+ [0xf5] = X86_OP_ENTRY3(PMADDWD, V,x, H,x, W,x, vex4 mmx avx2_256 p_00_66),
+ [0xf6] = X86_OP_ENTRY3(PSADBW, V,x, H,x, W,x, vex4 mmx avx2_256 p_00_66),
+ [0xf7] = X86_OP_ENTRY3(MASKMOV, None,None, V,dq, U,dq, vex4_unal avx2_256 mmx p_00_66),
+
[0x0b] = X86_OP_ENTRY0(UD), /* UD2 */
[0x0d] = X86_OP_ENTRY1(NOP, M,v), /* 3DNow! prefetch */
+ [0x0e] = X86_OP_ENTRY0(EMMS, cpuid(3DNOW)), /* femms */
+ /*
+ * 3DNow!'s opcode byte comes *after* modrm and displacements, making it
+ * more like an Ib operand. Dispatch to the right helper in a single gen_*
+ * function.
+ */
+ [0x0f] = X86_OP_ENTRY3(3dnow, P,q, Q,q, I,b, cpuid(3DNOW)),
[0x18] = X86_OP_ENTRY1(NOP, nop,v), /* prefetch/reserved NOP */
[0x19] = X86_OP_ENTRY1(NOP, nop,v), /* reserved NOP */
@@ -1169,23 +1207,11 @@ static const X86OpEntry opcodes_0F[256] = {
*/
[0xaf] = X86_OP_ENTRY3(IMUL3, G,v, E,v, 2op,v, sextT0),
- [0xb2] = X86_OP_ENTRY3(LSS, G,v, EM,p, None, None),
- [0xb4] = X86_OP_ENTRY3(LFS, G,v, EM,p, None, None),
- [0xb5] = X86_OP_ENTRY3(LGS, G,v, EM,p, None, None),
- [0xb6] = X86_OP_ENTRY3(MOV, G,v, E,b, None, None, zextT0), /* MOVZX */
- [0xb7] = X86_OP_ENTRY3(MOV, G,v, E,w, None, None, zextT0), /* MOVZX */
-
/* decoded as modrm, which is visible as a difference between page fault and #UD */
[0xb9] = X86_OP_ENTRYr(UD, nop,v), /* UD1 */
[0xbe] = X86_OP_ENTRY3(MOV, G,v, E,b, None, None, sextT0), /* MOVSX */
[0xbf] = X86_OP_ENTRY3(MOV, G,v, E,w, None, None, sextT0), /* MOVSX */
- [0xc2] = X86_OP_ENTRY4(VCMP, V,x, H,x, W,x, vex2_rep3 p_00_66_f3_f2),
- [0xc3] = X86_OP_ENTRY3(MOV, EM,y,G,y, None,None, cpuid(SSE2)), /* MOVNTI */
- [0xc4] = X86_OP_ENTRY4(PINSRW, V,dq,H,dq,E,w, vex5 mmx p_00_66),
- [0xc5] = X86_OP_ENTRY3(PEXTRW, G,d, U,dq,I,b, vex5 mmx p_00_66),
- [0xc6] = X86_OP_ENTRY4(VSHUF, V,x, H,x, W,x, vex4 p_00_66),
-
[0xc8] = X86_OP_ENTRY1(BSWAP, LoBits,y),
[0xc9] = X86_OP_ENTRY1(BSWAP, LoBits,y),
[0xca] = X86_OP_ENTRY1(BSWAP, LoBits,y),
@@ -1195,33 +1221,6 @@ static const X86OpEntry opcodes_0F[256] = {
[0xce] = X86_OP_ENTRY1(BSWAP, LoBits,y),
[0xcf] = X86_OP_ENTRY1(BSWAP, LoBits,y),
- [0xd0] = X86_OP_ENTRY3(VADDSUB, V,x, H,x, W,x, vex2 cpuid(SSE3) p_66_f2),
- [0xd1] = X86_OP_ENTRY3(PSRLW_r, V,x, H,x, W,x, vex4 mmx avx2_256 p_00_66),
- [0xd2] = X86_OP_ENTRY3(PSRLD_r, V,x, H,x, W,x, vex4 mmx avx2_256 p_00_66),
- [0xd3] = X86_OP_ENTRY3(PSRLQ_r, V,x, H,x, W,x, vex4 mmx avx2_256 p_00_66),
- [0xd4] = X86_OP_ENTRY3(PADDQ, V,x, H,x, W,x, vex4 mmx avx2_256 p_00_66),
- [0xd5] = X86_OP_ENTRY3(PMULLW, V,x, H,x, W,x, vex4 mmx avx2_256 p_00_66),
- [0xd6] = X86_OP_GROUP0(0FD6),
- [0xd7] = X86_OP_ENTRY3(PMOVMSKB, G,d, None,None, U,x, vex7 mmx avx2_256 p_00_66),
-
- [0xe0] = X86_OP_ENTRY3(PAVGB, V,x, H,x, W,x, vex4 mmx avx2_256 p_00_66),
- [0xe1] = X86_OP_ENTRY3(PSRAW_r, V,x, H,x, W,x, vex7 mmx avx2_256 p_00_66),
- [0xe2] = X86_OP_ENTRY3(PSRAD_r, V,x, H,x, W,x, vex7 mmx avx2_256 p_00_66),
- [0xe3] = X86_OP_ENTRY3(PAVGW, V,x, H,x, W,x, vex4 mmx avx2_256 p_00_66),
- [0xe4] = X86_OP_ENTRY3(PMULHUW, V,x, H,x, W,x, vex4 mmx avx2_256 p_00_66),
- [0xe5] = X86_OP_ENTRY3(PMULHW, V,x, H,x, W,x, vex4 mmx avx2_256 p_00_66),
- [0xe6] = X86_OP_GROUP0(0FE6),
- [0xe7] = X86_OP_ENTRY3(MOVDQ, W,x, None,None, V,x, vex1 mmx p_00_66), /* MOVNTQ/MOVNTDQ */
-
- [0xf0] = X86_OP_ENTRY3(MOVDQ, V,x, None,None, WM,x, vex4_unal cpuid(SSE3) p_f2), /* LDDQU */
- [0xf1] = X86_OP_ENTRY3(PSLLW_r, V,x, H,x, W,x, vex7 mmx avx2_256 p_00_66),
- [0xf2] = X86_OP_ENTRY3(PSLLD_r, V,x, H,x, W,x, vex7 mmx avx2_256 p_00_66),
- [0xf3] = X86_OP_ENTRY3(PSLLQ_r, V,x, H,x, W,x, vex7 mmx avx2_256 p_00_66),
- [0xf4] = X86_OP_ENTRY3(PMULUDQ, V,x, H,x, W,x, vex4 mmx avx2_256 p_00_66),
- [0xf5] = X86_OP_ENTRY3(PMADDWD, V,x, H,x, W,x, vex4 mmx avx2_256 p_00_66),
- [0xf6] = X86_OP_ENTRY3(PSADBW, V,x, H,x, W,x, vex4 mmx avx2_256 p_00_66),
- [0xf7] = X86_OP_ENTRY3(MASKMOV, None,None, V,dq, U,dq, vex4_unal avx2_256 mmx p_00_66),
-
/* Incorrectly missing from 2-17 */
[0xd8] = X86_OP_ENTRY3(PSUBUSB, V,x, H,x, W,x, vex4 mmx avx2_256 p_00_66),
[0xd9] = X86_OP_ENTRY3(PSUBUSW, V,x, H,x, W,x, vex4 mmx avx2_256 p_00_66),
--
2.45.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PULL 15/25] target/i386: finish converting 0F AE to the new decoder
2024-06-11 14:24 [PULL 00/25] target/i386, SCSI changes for 2024-06-11 Paolo Bonzini
` (13 preceding siblings ...)
2024-06-11 14:25 ` [PULL 14/25] target/i386: fix bad sorting of entries in the 0F table Paolo Bonzini
@ 2024-06-11 14:25 ` Paolo Bonzini
2024-06-11 14:25 ` [PULL 16/25] target/i386: replace read_crN helper with read_cr8 Paolo Bonzini
` (10 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Paolo Bonzini @ 2024-06-11 14:25 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson
This is already partly implemented due to VLDMXCSR and VSTMXCSR; finish
the job.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/tcg/decode-new.h | 7 ++
target/i386/tcg/translate.c | 188 -------------------------------
target/i386/tcg/decode-new.c.inc | 48 +++++++-
target/i386/tcg/emit.c.inc | 80 +++++++++++++
4 files changed, 129 insertions(+), 194 deletions(-)
diff --git a/target/i386/tcg/decode-new.h b/target/i386/tcg/decode-new.h
index 8465717ea21..5577f7509aa 100644
--- a/target/i386/tcg/decode-new.h
+++ b/target/i386/tcg/decode-new.h
@@ -108,10 +108,15 @@ typedef enum X86CPUIDFeature {
X86_FEAT_AVX2,
X86_FEAT_BMI1,
X86_FEAT_BMI2,
+ X86_FEAT_CLFLUSH,
+ X86_FEAT_CLFLUSHOPT,
+ X86_FEAT_CLWB,
X86_FEAT_CMOV,
X86_FEAT_CMPCCXADD,
X86_FEAT_F16C,
X86_FEAT_FMA,
+ X86_FEAT_FSGSBASE,
+ X86_FEAT_FXSR,
X86_FEAT_MOVBE,
X86_FEAT_PCLMULQDQ,
X86_FEAT_SHA_NI,
@@ -122,6 +127,8 @@ typedef enum X86CPUIDFeature {
X86_FEAT_SSE41,
X86_FEAT_SSE42,
X86_FEAT_SSE4A,
+ X86_FEAT_XSAVE,
+ X86_FEAT_XSAVEOPT,
} X86CPUIDFeature;
/* Execution flags */
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 4958f4c45d5..ebae745ecba 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -4197,194 +4197,6 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b)
s->base.is_jmp = DISAS_EOB_NEXT;
}
break;
- /* MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4 support */
- case 0x1ae:
- modrm = x86_ldub_code(env, s);
- switch (modrm) {
- CASE_MODRM_MEM_OP(0): /* fxsave */
- if (!(s->cpuid_features & CPUID_FXSR)
- || (prefixes & PREFIX_LOCK)) {
- goto illegal_op;
- }
- if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
- gen_exception(s, EXCP07_PREX);
- break;
- }
- gen_lea_modrm(env, s, modrm);
- gen_helper_fxsave(tcg_env, s->A0);
- break;
-
- CASE_MODRM_MEM_OP(1): /* fxrstor */
- if (!(s->cpuid_features & CPUID_FXSR)
- || (prefixes & PREFIX_LOCK)) {
- goto illegal_op;
- }
- if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
- gen_exception(s, EXCP07_PREX);
- break;
- }
- gen_lea_modrm(env, s, modrm);
- gen_helper_fxrstor(tcg_env, s->A0);
- break;
-
- CASE_MODRM_MEM_OP(2): /* ldmxcsr */
- if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK)) {
- goto illegal_op;
- }
- if (s->flags & HF_TS_MASK) {
- gen_exception(s, EXCP07_PREX);
- break;
- }
- gen_lea_modrm(env, s, modrm);
- tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LEUL);
- gen_helper_ldmxcsr(tcg_env, s->tmp2_i32);
- break;
-
- CASE_MODRM_MEM_OP(3): /* stmxcsr */
- if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK)) {
- goto illegal_op;
- }
- if (s->flags & HF_TS_MASK) {
- gen_exception(s, EXCP07_PREX);
- break;
- }
- gen_helper_update_mxcsr(tcg_env);
- gen_lea_modrm(env, s, modrm);
- tcg_gen_ld32u_tl(s->T0, tcg_env, offsetof(CPUX86State, mxcsr));
- gen_op_st_v(s, MO_32, s->T0, s->A0);
- break;
-
- CASE_MODRM_MEM_OP(4): /* xsave */
- if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
- || (prefixes & (PREFIX_LOCK | PREFIX_DATA
- | PREFIX_REPZ | PREFIX_REPNZ))) {
- goto illegal_op;
- }
- gen_lea_modrm(env, s, modrm);
- tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
- cpu_regs[R_EDX]);
- gen_helper_xsave(tcg_env, s->A0, s->tmp1_i64);
- break;
-
- CASE_MODRM_MEM_OP(5): /* xrstor */
- if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
- || (prefixes & (PREFIX_LOCK | PREFIX_DATA
- | PREFIX_REPZ | PREFIX_REPNZ))) {
- goto illegal_op;
- }
- gen_lea_modrm(env, s, modrm);
- tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
- cpu_regs[R_EDX]);
- gen_helper_xrstor(tcg_env, s->A0, s->tmp1_i64);
- /* XRSTOR is how MPX is enabled, which changes how
- we translate. Thus we need to end the TB. */
- s->base.is_jmp = DISAS_EOB_NEXT;
- break;
-
- CASE_MODRM_MEM_OP(6): /* xsaveopt / clwb */
- if (prefixes & PREFIX_LOCK) {
- goto illegal_op;
- }
- if (prefixes & PREFIX_DATA) {
- /* clwb */
- if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_CLWB)) {
- goto illegal_op;
- }
- gen_nop_modrm(env, s, modrm);
- } else {
- /* xsaveopt */
- if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
- || (s->cpuid_xsave_features & CPUID_XSAVE_XSAVEOPT) == 0
- || (prefixes & (PREFIX_REPZ | PREFIX_REPNZ))) {
- goto illegal_op;
- }
- gen_lea_modrm(env, s, modrm);
- tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX],
- cpu_regs[R_EDX]);
- gen_helper_xsaveopt(tcg_env, s->A0, s->tmp1_i64);
- }
- break;
-
- CASE_MODRM_MEM_OP(7): /* clflush / clflushopt */
- if (prefixes & PREFIX_LOCK) {
- goto illegal_op;
- }
- if (prefixes & PREFIX_DATA) {
- /* clflushopt */
- if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_CLFLUSHOPT)) {
- goto illegal_op;
- }
- } else {
- /* clflush */
- if ((s->prefix & (PREFIX_REPZ | PREFIX_REPNZ))
- || !(s->cpuid_features & CPUID_CLFLUSH)) {
- goto illegal_op;
- }
- }
- gen_nop_modrm(env, s, modrm);
- break;
-
- case 0xc0 ... 0xc7: /* rdfsbase (f3 0f ae /0) */
- case 0xc8 ... 0xcf: /* rdgsbase (f3 0f ae /1) */
- case 0xd0 ... 0xd7: /* wrfsbase (f3 0f ae /2) */
- case 0xd8 ... 0xdf: /* wrgsbase (f3 0f ae /3) */
- if (CODE64(s)
- && (prefixes & PREFIX_REPZ)
- && !(prefixes & PREFIX_LOCK)
- && (s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_FSGSBASE)) {
- TCGv base, treg, src, dst;
-
- /* Preserve hflags bits by testing CR4 at runtime. */
- tcg_gen_movi_i32(s->tmp2_i32, CR4_FSGSBASE_MASK);
- gen_helper_cr4_testbit(tcg_env, s->tmp2_i32);
-
- base = cpu_seg_base[modrm & 8 ? R_GS : R_FS];
- treg = cpu_regs[(modrm & 7) | REX_B(s)];
-
- if (modrm & 0x10) {
- /* wr*base */
- dst = base, src = treg;
- } else {
- /* rd*base */
- dst = treg, src = base;
- }
-
- if (s->dflag == MO_32) {
- tcg_gen_ext32u_tl(dst, src);
- } else {
- tcg_gen_mov_tl(dst, src);
- }
- break;
- }
- goto unknown_op;
-
- case 0xf8 ... 0xff: /* sfence */
- if (!(s->cpuid_features & CPUID_SSE)
- || (prefixes & PREFIX_LOCK)) {
- goto illegal_op;
- }
- tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC);
- break;
- case 0xe8 ... 0xef: /* lfence */
- if (!(s->cpuid_features & CPUID_SSE)
- || (prefixes & PREFIX_LOCK)) {
- goto illegal_op;
- }
- tcg_gen_mb(TCG_MO_LD_LD | TCG_BAR_SC);
- break;
- case 0xf0 ... 0xf7: /* mfence */
- if (!(s->cpuid_features & CPUID_SSE2)
- || (prefixes & PREFIX_LOCK)) {
- goto illegal_op;
- }
- tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
- break;
-
- default:
- goto unknown_op;
- }
- break;
-
case 0x1aa: /* rsm */
gen_svm_check_intercept(s, SVM_EXIT_RSM);
if (!(s->flags & HF_SMM_MASK))
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index 4e745f10dd8..1c6fa39c3eb 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -269,20 +269,41 @@ static inline const X86OpEntry *decode_by_prefix(DisasContext *s, const X86OpEnt
static void decode_group15(DisasContext *s, CPUX86State *env, X86OpEntry *entry, uint8_t *b)
{
- /* only includes ldmxcsr and stmxcsr, because they have AVX variants. */
static const X86OpEntry group15_reg[8] = {
+ [0] = X86_OP_ENTRYw(RDxxBASE, R,y, cpuid(FSGSBASE) chk(o64) p_f3),
+ [1] = X86_OP_ENTRYw(RDxxBASE, R,y, cpuid(FSGSBASE) chk(o64) p_f3),
+ [2] = X86_OP_ENTRYr(WRxxBASE, R,y, cpuid(FSGSBASE) chk(o64) p_f3 zextT0),
+ [3] = X86_OP_ENTRYr(WRxxBASE, R,y, cpuid(FSGSBASE) chk(o64) p_f3 zextT0),
+ [5] = X86_OP_ENTRY0(LFENCE, cpuid(SSE2) p_00),
+ [6] = X86_OP_ENTRY0(MFENCE, cpuid(SSE2) p_00),
+ [7] = X86_OP_ENTRY0(SFENCE, cpuid(SSE2) p_00),
};
static const X86OpEntry group15_mem[8] = {
- [2] = X86_OP_ENTRYr(LDMXCSR, E,d, vex5 chk(VEX128)),
- [3] = X86_OP_ENTRYw(STMXCSR, E,d, vex5 chk(VEX128)),
+ [0] = X86_OP_ENTRYw(FXSAVE, M,y, cpuid(FXSR) p_00),
+ [1] = X86_OP_ENTRYr(FXRSTOR, M,y, cpuid(FXSR) p_00),
+ [2] = X86_OP_ENTRYr(LDMXCSR, E,d, vex5 chk(VEX128) p_00),
+ [3] = X86_OP_ENTRYw(STMXCSR, E,d, vex5 chk(VEX128) p_00),
+ [4] = X86_OP_ENTRYw(XSAVE, M,y, cpuid(XSAVE) p_00),
+ [5] = X86_OP_ENTRYr(XRSTOR, M,y, cpuid(XSAVE) p_00),
+ [6] = X86_OP_ENTRYw(XSAVEOPT, M,b, cpuid(XSAVEOPT) p_00),
+ [7] = X86_OP_ENTRYw(NOP, M,b, cpuid(CLFLUSH) p_00),
+ };
+
+ static const X86OpEntry group15_mem_66[8] = {
+ [6] = X86_OP_ENTRYw(NOP, M,b, cpuid(CLWB)),
+ [7] = X86_OP_ENTRYw(NOP, M,b, cpuid(CLFLUSHOPT)),
};
uint8_t modrm = get_modrm(s, env);
+ int op = (modrm >> 3) & 7;
+
if ((modrm >> 6) == 3) {
- *entry = group15_reg[(modrm >> 3) & 7];
+ *entry = group15_reg[op];
+ } else if (s->prefix & PREFIX_DATA) {
+ *entry = group15_mem_66[op];
} else {
- *entry = group15_mem[(modrm >> 3) & 7];
+ *entry = group15_mem[op];
}
}
@@ -2094,6 +2115,10 @@ static bool has_cpuid_feature(DisasContext *s, X86CPUIDFeature cpuid)
return true;
case X86_FEAT_CMOV:
return (s->cpuid_features & CPUID_CMOV);
+ case X86_FEAT_CLFLUSH:
+ return (s->cpuid_features & CPUID_CLFLUSH);
+ case X86_FEAT_FXSR:
+ return (s->cpuid_features & CPUID_FXSR);
case X86_FEAT_F16C:
return (s->cpuid_ext_features & CPUID_EXT_F16C);
case X86_FEAT_FMA:
@@ -2127,6 +2152,8 @@ static bool has_cpuid_feature(DisasContext *s, X86CPUIDFeature cpuid)
case X86_FEAT_AVX:
return (s->cpuid_ext_features & CPUID_EXT_AVX);
+ case X86_FEAT_XSAVE:
+ return (s->cpuid_ext_features & CPUID_EXT_XSAVE);
case X86_FEAT_3DNOW:
return (s->cpuid_ext2_features & CPUID_EXT2_3DNOW);
@@ -2141,11 +2168,20 @@ static bool has_cpuid_feature(DisasContext *s, X86CPUIDFeature cpuid)
return (s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2);
case X86_FEAT_AVX2:
return (s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_AVX2);
+ case X86_FEAT_CLFLUSHOPT:
+ return (s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_CLFLUSHOPT);
+ case X86_FEAT_CLWB:
+ return (s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_CLWB);
+ case X86_FEAT_FSGSBASE:
+ return (s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_FSGSBASE);
case X86_FEAT_SHA_NI:
return (s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SHA_NI);
case X86_FEAT_CMPCCXADD:
return (s->cpuid_7_1_eax_features & CPUID_7_1_EAX_CMPCCXADD);
+
+ case X86_FEAT_XSAVEOPT:
+ return (s->cpuid_xsave_features & CPUID_XSAVE_XSAVEOPT);
}
g_assert_not_reached();
}
@@ -2480,7 +2516,7 @@ static void disas_insn(DisasContext *s, CPUState *cpu)
case 0x1a ... 0x1b: /* MPX */
case 0x30 ... 0x35: /* more privileged instructions */
case 0xa2 ... 0xa5: /* CPUID, BT, SHLD */
- case 0xaa ... 0xae: /* RSM, SHRD, grp15 */
+ case 0xaa ... 0xad: /* RSM, SHRD */
case 0xb0 ... 0xb1: /* cmpxchg */
case 0xb3: /* btr */
case 0xb8: /* integer ops */
diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
index bcb6bccbd75..5ca3764e006 100644
--- a/target/i386/tcg/emit.c.inc
+++ b/target/i386/tcg/emit.c.inc
@@ -1653,6 +1653,22 @@ static void gen_EXTRQ_r(DisasContext *s, X86DecodedInsn *decode)
gen_helper_extrq_r(tcg_env, OP_PTR0, OP_PTR2);
}
+static void gen_FXRSTOR(DisasContext *s, X86DecodedInsn *decode)
+{
+ if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
+ gen_NM_exception(s);
+ }
+ gen_helper_fxrstor(tcg_env, s->A0);
+}
+
+static void gen_FXSAVE(DisasContext *s, X86DecodedInsn *decode)
+{
+ if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
+ gen_NM_exception(s);
+ }
+ gen_helper_fxsave(tcg_env, s->A0);
+}
+
static void gen_HLT(DisasContext *s, X86DecodedInsn *decode)
{
#ifdef CONFIG_SYSTEM_ONLY
@@ -2000,6 +2016,11 @@ static void gen_LES(DisasContext *s, X86DecodedInsn *decode)
gen_lxx_seg(s, decode, R_ES);
}
+static void gen_LFENCE(DisasContext *s, X86DecodedInsn *decode)
+{
+ tcg_gen_mb(TCG_MO_LD_LD | TCG_BAR_SC);
+}
+
static void gen_LFS(DisasContext *s, X86DecodedInsn *decode)
{
gen_lxx_seg(s, decode, R_FS);
@@ -2059,6 +2080,11 @@ static void gen_LSS(DisasContext *s, X86DecodedInsn *decode)
gen_lxx_seg(s, decode, R_SS);
}
+static void gen_MFENCE(DisasContext *s, X86DecodedInsn *decode)
+{
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
+}
+
static void gen_MOV(DisasContext *s, X86DecodedInsn *decode)
{
/* nothing to do! */
@@ -3092,6 +3118,15 @@ static void gen_RCR(DisasContext *s, X86DecodedInsn *decode)
}
}
+static void gen_RDxxBASE(DisasContext *s, X86DecodedInsn *decode)
+{
+ TCGv base = cpu_seg_base[s->modrm & 8 ? R_GS : R_FS];
+
+ /* Preserve hflags bits by testing CR4 at runtime. */
+ gen_helper_cr4_testbit(tcg_env, tcg_constant_i32(CR4_FSGSBASE_MASK));
+ tcg_gen_mov_tl(s->T0, base);
+}
+
static void gen_RET(DisasContext *s, X86DecodedInsn *decode)
{
int16_t adjust = decode->e.op1 == X86_TYPE_I ? decode->immediate : 0;
@@ -3372,6 +3407,11 @@ static void gen_SETcc(DisasContext *s, X86DecodedInsn *decode)
gen_setcc1(s, decode->b & 0xf, s->T0);
}
+static void gen_SFENCE(DisasContext *s, X86DecodedInsn *decode)
+{
+ tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC);
+}
+
static void gen_SHA1NEXTE(DisasContext *s, X86DecodedInsn *decode)
{
gen_helper_sha1nexte(OP_PTR0, OP_PTR1, OP_PTR2);
@@ -4042,6 +4082,15 @@ static void gen_WAIT(DisasContext *s, X86DecodedInsn *decode)
}
}
+static void gen_WRxxBASE(DisasContext *s, X86DecodedInsn *decode)
+{
+ TCGv base = cpu_seg_base[s->modrm & 8 ? R_GS : R_FS];
+
+ /* Preserve hflags bits by testing CR4 at runtime. */
+ gen_helper_cr4_testbit(tcg_env, tcg_constant_i32(CR4_FSGSBASE_MASK));
+ tcg_gen_mov_tl(base, s->T0);
+}
+
static void gen_XCHG(DisasContext *s, X86DecodedInsn *decode)
{
if (s->prefix & PREFIX_LOCK) {
@@ -4084,3 +4133,34 @@ static void gen_XOR(DisasContext *s, X86DecodedInsn *decode)
prepare_update1_cc(decode, s, CC_OP_LOGICB + ot);
}
}
+
+static void gen_XRSTOR(DisasContext *s, X86DecodedInsn *decode)
+{
+ TCGv_i64 features = tcg_temp_new_i64();
+
+ tcg_gen_concat_tl_i64(features, cpu_regs[R_EAX], cpu_regs[R_EDX]);
+ gen_helper_xrstor(tcg_env, s->A0, features);
+ if (s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_MPX) {
+ /*
+ * XRSTOR is how MPX is enabled, which changes how
+ * we translate. Thus we need to end the TB.
+ */
+ s->base.is_jmp = DISAS_EOB_NEXT;
+ }
+}
+
+static void gen_XSAVE(DisasContext *s, X86DecodedInsn *decode)
+{
+ TCGv_i64 features = tcg_temp_new_i64();
+
+ tcg_gen_concat_tl_i64(features, cpu_regs[R_EAX], cpu_regs[R_EDX]);
+ gen_helper_xsave(tcg_env, s->A0, features);
+}
+
+static void gen_XSAVEOPT(DisasContext *s, X86DecodedInsn *decode)
+{
+ TCGv_i64 features = tcg_temp_new_i64();
+
+ tcg_gen_concat_tl_i64(features, cpu_regs[R_EAX], cpu_regs[R_EDX]);
+ gen_helper_xsave(tcg_env, s->A0, features);
+}
--
2.45.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PULL 16/25] target/i386: replace read_crN helper with read_cr8
2024-06-11 14:24 [PULL 00/25] target/i386, SCSI changes for 2024-06-11 Paolo Bonzini
` (14 preceding siblings ...)
2024-06-11 14:25 ` [PULL 15/25] target/i386: finish converting 0F AE to the new decoder Paolo Bonzini
@ 2024-06-11 14:25 ` Paolo Bonzini
2024-06-11 14:25 ` [PULL 17/25] target/i386: split X86_CHECK_prot into PE and VM86 checks Paolo Bonzini
` (9 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Paolo Bonzini @ 2024-06-11 14:25 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson
All other control registers are stored plainly in CPUX86State.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/helper.h | 2 +-
target/i386/tcg/sysemu/misc_helper.c | 20 +++++---------------
target/i386/tcg/emit.c.inc | 2 +-
3 files changed, 7 insertions(+), 17 deletions(-)
diff --git a/target/i386/helper.h b/target/i386/helper.h
index 2f46cffabd8..eeb8df56eaa 100644
--- a/target/i386/helper.h
+++ b/target/i386/helper.h
@@ -95,7 +95,7 @@ DEF_HELPER_FLAGS_2(monitor, TCG_CALL_NO_WG, void, env, tl)
DEF_HELPER_FLAGS_2(mwait, TCG_CALL_NO_WG, noreturn, env, int)
DEF_HELPER_1(rdmsr, void, env)
DEF_HELPER_1(wrmsr, void, env)
-DEF_HELPER_FLAGS_2(read_crN, TCG_CALL_NO_RWG, tl, env, int)
+DEF_HELPER_FLAGS_1(read_cr8, TCG_CALL_NO_RWG, tl, env)
DEF_HELPER_FLAGS_3(write_crN, TCG_CALL_NO_RWG, void, env, int, tl)
#endif /* !CONFIG_USER_ONLY */
diff --git a/target/i386/tcg/sysemu/misc_helper.c b/target/i386/tcg/sysemu/misc_helper.c
index 7fa0c5a06de..094aa56a20d 100644
--- a/target/i386/tcg/sysemu/misc_helper.c
+++ b/target/i386/tcg/sysemu/misc_helper.c
@@ -63,23 +63,13 @@ target_ulong helper_inl(CPUX86State *env, uint32_t port)
cpu_get_mem_attrs(env), NULL);
}
-target_ulong helper_read_crN(CPUX86State *env, int reg)
+target_ulong helper_read_cr8(CPUX86State *env)
{
- target_ulong val;
-
- switch (reg) {
- default:
- val = env->cr[reg];
- break;
- case 8:
- if (!(env->hflags2 & HF2_VINTR_MASK)) {
- val = cpu_get_apic_tpr(env_archcpu(env)->apic_state);
- } else {
- val = env->int_ctl & V_TPR_MASK;
- }
- break;
+ if (!(env->hflags2 & HF2_VINTR_MASK)) {
+ return cpu_get_apic_tpr(env_archcpu(env)->apic_state);
+ } else {
+ return env->int_ctl & V_TPR_MASK;
}
- return val;
}
void helper_write_crN(CPUX86State *env, int reg, target_ulong t0)
diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
index 5ca3764e006..709ef7b0cb2 100644
--- a/target/i386/tcg/emit.c.inc
+++ b/target/i386/tcg/emit.c.inc
@@ -245,7 +245,7 @@ static void gen_load(DisasContext *s, X86DecodedInsn *decode, int opn, TCGv v)
#ifndef CONFIG_USER_ONLY
case X86_OP_CR:
if (op->n == 8) {
- gen_helper_read_crN(v, tcg_env, tcg_constant_i32(op->n));
+ gen_helper_read_cr8(v, tcg_env);
} else {
tcg_gen_ld_tl(v, tcg_env, offsetof(CPUX86State, cr[op->n]));
}
--
2.45.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PULL 17/25] target/i386: split X86_CHECK_prot into PE and VM86 checks
2024-06-11 14:24 [PULL 00/25] target/i386, SCSI changes for 2024-06-11 Paolo Bonzini
` (15 preceding siblings ...)
2024-06-11 14:25 ` [PULL 16/25] target/i386: replace read_crN helper with read_cr8 Paolo Bonzini
@ 2024-06-11 14:25 ` Paolo Bonzini
2024-06-11 14:25 ` [PULL 18/25] target/i386: convert non-grouped, helper-based 2-byte opcodes Paolo Bonzini
` (8 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Paolo Bonzini @ 2024-06-11 14:25 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson
SYSENTER is allowed in VM86 mode, but not in real mode. Split the check
so that PE and !VM86 are covered by separate bits.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/tcg/decode-new.h | 8 ++++++--
target/i386/tcg/decode-new.c.inc | 9 +++++++--
2 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/target/i386/tcg/decode-new.h b/target/i386/tcg/decode-new.h
index 5577f7509aa..b46a9a0ccb3 100644
--- a/target/i386/tcg/decode-new.h
+++ b/target/i386/tcg/decode-new.h
@@ -149,8 +149,8 @@ typedef enum X86InsnCheck {
X86_CHECK_i64 = 1,
X86_CHECK_o64 = 2,
- /* Fault outside protected mode */
- X86_CHECK_prot = 4,
+ /* Fault in vm86 mode */
+ X86_CHECK_no_vm86 = 4,
/* Privileged instruction checks */
X86_CHECK_cpl0 = 8,
@@ -166,6 +166,10 @@ typedef enum X86InsnCheck {
/* Fault if VEX.W=0 */
X86_CHECK_W1 = 256,
+
+ /* Fault outside protected mode, possibly including vm86 mode */
+ X86_CHECK_prot_or_vm86 = 512,
+ X86_CHECK_prot = X86_CHECK_prot_or_vm86 | X86_CHECK_no_vm86,
} X86InsnCheck;
typedef enum X86InsnSpecial {
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index 1c6fa39c3eb..f02f7c62647 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -2558,8 +2558,13 @@ static void disas_insn(DisasContext *s, CPUState *cpu)
goto illegal_op;
}
}
- if (decode.e.check & X86_CHECK_prot) {
- if (!PE(s) || VM86(s)) {
+ if (decode.e.check & X86_CHECK_prot_or_vm86) {
+ if (!PE(s)) {
+ goto illegal_op;
+ }
+ }
+ if (decode.e.check & X86_CHECK_no_vm86) {
+ if (VM86(s)) {
goto illegal_op;
}
}
--
2.45.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PULL 18/25] target/i386: convert non-grouped, helper-based 2-byte opcodes
2024-06-11 14:24 [PULL 00/25] target/i386, SCSI changes for 2024-06-11 Paolo Bonzini
` (16 preceding siblings ...)
2024-06-11 14:25 ` [PULL 17/25] target/i386: split X86_CHECK_prot into PE and VM86 checks Paolo Bonzini
@ 2024-06-11 14:25 ` Paolo Bonzini
2024-06-11 14:25 ` [PULL 19/25] target/i386: pull load/writeback out of gen_shiftd_rm_T1 Paolo Bonzini
` (7 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Paolo Bonzini @ 2024-06-11 14:25 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson
These have very simple generators and no need for complex group
decoding. Apart from LAR/LSL which are simplified to use
gen_op_deposit_reg_v and movcond, the code is generally lifted
from translate.c into the generators.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/tcg/decode-new.h | 7 ++
target/i386/tcg/seg_helper.c | 16 ++--
target/i386/tcg/translate.c | 148 -----------------------------
target/i386/tcg/decode-new.c.inc | 48 +++++++---
target/i386/tcg/emit.c.inc | 157 ++++++++++++++++++++++++++++++-
5 files changed, 206 insertions(+), 170 deletions(-)
diff --git a/target/i386/tcg/decode-new.h b/target/i386/tcg/decode-new.h
index b46a9a0ccb3..c9f958bb0e5 100644
--- a/target/i386/tcg/decode-new.h
+++ b/target/i386/tcg/decode-new.h
@@ -170,6 +170,13 @@ typedef enum X86InsnCheck {
/* Fault outside protected mode, possibly including vm86 mode */
X86_CHECK_prot_or_vm86 = 512,
X86_CHECK_prot = X86_CHECK_prot_or_vm86 | X86_CHECK_no_vm86,
+
+ /* Fault outside SMM */
+ X86_CHECK_smm = 1024,
+
+ /* Vendor-specific checks for Intel/AMD differences */
+ X86_CHECK_i64_amd = 2048,
+ X86_CHECK_o64_intel = 4096,
} X86InsnCheck;
typedef enum X86InsnSpecial {
diff --git a/target/i386/tcg/seg_helper.c b/target/i386/tcg/seg_helper.c
index 715db1f2326..aee3d19f29b 100644
--- a/target/i386/tcg/seg_helper.c
+++ b/target/i386/tcg/seg_helper.c
@@ -2265,11 +2265,11 @@ void helper_sysexit(CPUX86State *env, int dflag)
target_ulong helper_lsl(CPUX86State *env, target_ulong selector1)
{
unsigned int limit;
- uint32_t e1, e2, eflags, selector;
+ uint32_t e1, e2, selector;
int rpl, dpl, cpl, type;
selector = selector1 & 0xffff;
- eflags = cpu_cc_compute_all(env);
+ assert(CC_OP == CC_OP_EFLAGS);
if ((selector & 0xfffc) == 0) {
goto fail;
}
@@ -2301,22 +2301,22 @@ target_ulong helper_lsl(CPUX86State *env, target_ulong selector1)
}
if (dpl < cpl || dpl < rpl) {
fail:
- CC_SRC = eflags & ~CC_Z;
+ CC_SRC &= ~CC_Z;
return 0;
}
}
limit = get_seg_limit(e1, e2);
- CC_SRC = eflags | CC_Z;
+ CC_SRC |= CC_Z;
return limit;
}
target_ulong helper_lar(CPUX86State *env, target_ulong selector1)
{
- uint32_t e1, e2, eflags, selector;
+ uint32_t e1, e2, selector;
int rpl, dpl, cpl, type;
selector = selector1 & 0xffff;
- eflags = cpu_cc_compute_all(env);
+ assert(CC_OP == CC_OP_EFLAGS);
if ((selector & 0xfffc) == 0) {
goto fail;
}
@@ -2351,11 +2351,11 @@ target_ulong helper_lar(CPUX86State *env, target_ulong selector1)
}
if (dpl < cpl || dpl < rpl) {
fail:
- CC_SRC = eflags & ~CC_Z;
+ CC_SRC &= ~CC_Z;
return 0;
}
}
- CC_SRC = eflags | CC_Z;
+ CC_SRC |= CC_Z;
return e2 & 0x00f0ff00;
}
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index ebae745ecba..4b2f7488022 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -246,7 +246,6 @@ STUB_HELPER(mwait, TCGv_env env, TCGv_i32 pc_ofs)
STUB_HELPER(outb, TCGv_env env, TCGv_i32 port, TCGv_i32 val)
STUB_HELPER(outw, TCGv_env env, TCGv_i32 port, TCGv_i32 val)
STUB_HELPER(outl, TCGv_env env, TCGv_i32 port, TCGv_i32 val)
-STUB_HELPER(rdmsr, TCGv_env env)
STUB_HELPER(stgi, TCGv_env env)
STUB_HELPER(svm_check_intercept, TCGv_env env, TCGv_i32 type)
STUB_HELPER(vmload, TCGv_env env, TCGv_i32 aflag)
@@ -254,7 +253,6 @@ STUB_HELPER(vmmcall, TCGv_env env)
STUB_HELPER(vmrun, TCGv_env env, TCGv_i32 aflag, TCGv_i32 pc_ofs)
STUB_HELPER(vmsave, TCGv_env env, TCGv_i32 aflag)
STUB_HELPER(write_crN, TCGv_env env, TCGv_i32 reg, TCGv val)
-STUB_HELPER(wrmsr, TCGv_env env)
#endif
static void gen_jmp_rel(DisasContext *s, MemOp ot, int diff, int tb_num);
@@ -3470,97 +3468,6 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b)
}
gen_op_mov_reg_v(s, ot, reg, s->T0);
break;
- case 0x130: /* wrmsr */
- case 0x132: /* rdmsr */
- if (check_cpl0(s)) {
- gen_update_cc_op(s);
- gen_update_eip_cur(s);
- if (b & 2) {
- gen_helper_rdmsr(tcg_env);
- } else {
- gen_helper_wrmsr(tcg_env);
- s->base.is_jmp = DISAS_EOB_NEXT;
- }
- }
- break;
- case 0x131: /* rdtsc */
- gen_update_cc_op(s);
- gen_update_eip_cur(s);
- translator_io_start(&s->base);
- gen_helper_rdtsc(tcg_env);
- break;
- case 0x133: /* rdpmc */
- gen_update_cc_op(s);
- gen_update_eip_cur(s);
- gen_helper_rdpmc(tcg_env);
- s->base.is_jmp = DISAS_NORETURN;
- break;
- case 0x134: /* sysenter */
- /* For AMD SYSENTER is not valid in long mode */
- if (LMA(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1) {
- goto illegal_op;
- }
- if (!PE(s)) {
- gen_exception_gpf(s);
- } else {
- gen_helper_sysenter(tcg_env);
- s->base.is_jmp = DISAS_EOB_ONLY;
- }
- break;
- case 0x135: /* sysexit */
- /* For AMD SYSEXIT is not valid in long mode */
- if (LMA(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1) {
- goto illegal_op;
- }
- if (!PE(s) || CPL(s) != 0) {
- gen_exception_gpf(s);
- } else {
- gen_helper_sysexit(tcg_env, tcg_constant_i32(dflag - 1));
- s->base.is_jmp = DISAS_EOB_ONLY;
- }
- break;
- case 0x105: /* syscall */
- /* For Intel SYSCALL is only valid in long mode */
- if (!LMA(s) && env->cpuid_vendor1 == CPUID_VENDOR_INTEL_1) {
- goto illegal_op;
- }
- gen_update_cc_op(s);
- gen_update_eip_cur(s);
- gen_helper_syscall(tcg_env, cur_insn_len_i32(s));
- /* condition codes are modified only in long mode */
- if (LMA(s)) {
- assume_cc_op(s, CC_OP_EFLAGS);
- }
- /* TF handling for the syscall insn is different. The TF bit is checked
- after the syscall insn completes. This allows #DB to not be
- generated after one has entered CPL0 if TF is set in FMASK. */
- s->base.is_jmp = DISAS_EOB_RECHECK_TF;
- break;
- case 0x107: /* sysret */
- /* For Intel SYSRET is only valid in long mode */
- if (!LMA(s) && env->cpuid_vendor1 == CPUID_VENDOR_INTEL_1) {
- goto illegal_op;
- }
- if (!PE(s) || CPL(s) != 0) {
- gen_exception_gpf(s);
- } else {
- gen_helper_sysret(tcg_env, tcg_constant_i32(dflag - 1));
- /* condition codes are modified only in long mode */
- if (LMA(s)) {
- assume_cc_op(s, CC_OP_EFLAGS);
- }
- /* TF handling for the sysret insn is different. The TF bit is
- checked after the sysret insn completes. This allows #DB to be
- generated "as if" the syscall insn in userspace has just
- completed. */
- s->base.is_jmp = DISAS_EOB_RECHECK_TF;
- }
- break;
- case 0x1a2: /* cpuid */
- gen_update_cc_op(s);
- gen_update_eip_cur(s);
- gen_helper_cpuid(tcg_env);
- break;
case 0x100:
modrm = x86_ldub_code(env, s);
mod = (modrm >> 6) & 3;
@@ -3964,39 +3871,6 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b)
}
break;
- case 0x108: /* invd */
- case 0x109: /* wbinvd; wbnoinvd with REPZ prefix */
- if (check_cpl0(s)) {
- gen_svm_check_intercept(s, (b & 1) ? SVM_EXIT_WBINVD : SVM_EXIT_INVD);
- /* nothing to do */
- }
- break;
- case 0x102: /* lar */
- case 0x103: /* lsl */
- {
- TCGLabel *label1;
- TCGv t0;
- if (!PE(s) || VM86(s))
- goto illegal_op;
- ot = dflag != MO_16 ? MO_32 : MO_16;
- modrm = x86_ldub_code(env, s);
- reg = ((modrm >> 3) & 7) | REX_R(s);
- gen_ld_modrm(env, s, modrm, MO_16);
- t0 = tcg_temp_new();
- gen_update_cc_op(s);
- if (b == 0x102) {
- gen_helper_lar(t0, tcg_env, s->T0);
- } else {
- gen_helper_lsl(t0, tcg_env, s->T0);
- }
- tcg_gen_andi_tl(s->tmp0, cpu_cc_src, CC_Z);
- label1 = gen_new_label();
- tcg_gen_brcondi_tl(TCG_COND_EQ, s->tmp0, 0, label1);
- gen_op_mov_reg_v(s, ot, reg, t0);
- gen_set_label(label1);
- set_cc_op(s, CC_OP_EFLAGS);
- }
- break;
case 0x11a:
modrm = x86_ldub_code(env, s);
if (s->flags & HF_MPX_EN_MASK) {
@@ -4188,28 +4062,6 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b)
}
gen_nop_modrm(env, s, modrm);
break;
-
- case 0x106: /* clts */
- if (check_cpl0(s)) {
- gen_svm_check_intercept(s, SVM_EXIT_WRITE_CR0);
- gen_helper_clts(tcg_env);
- /* abort block because static cpu state changed */
- s->base.is_jmp = DISAS_EOB_NEXT;
- }
- break;
- case 0x1aa: /* rsm */
- gen_svm_check_intercept(s, SVM_EXIT_RSM);
- if (!(s->flags & HF_SMM_MASK))
- goto illegal_op;
-#ifdef CONFIG_USER_ONLY
- /* we should not be in SMM mode */
- g_assert_not_reached();
-#else
- gen_helper_rsm(tcg_env);
- assume_cc_op(s, CC_OP_EFLAGS);
-#endif /* CONFIG_USER_ONLY */
- s->base.is_jmp = DISAS_EOB_ONLY;
- break;
case 0x1b8: /* SSE4.2 popcnt */
if ((prefixes & (PREFIX_REPZ | PREFIX_LOCK | PREFIX_REPNZ)) !=
PREFIX_REPZ)
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index f02f7c62647..1db9d1e2bc3 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -223,6 +223,8 @@
#define vex13 .vex_class = 13,
#define chk(a) .check = X86_CHECK_##a,
+#define chk2(a, b) .check = X86_CHECK_##a | X86_CHECK_##b,
+#define chk3(a, b, c) .check = X86_CHECK_##a | X86_CHECK_##b | X86_CHECK_##c,
#define svm(a) .intercept = SVM_EXIT_##a, .has_intercept = true,
#define avx2_256 .vex_special = X86_VEX_AVX2_256,
@@ -1027,6 +1029,12 @@ static void decode_MOV_CR_DR(DisasContext *s, CPUX86State *env, X86OpEntry *entr
}
static const X86OpEntry opcodes_0F[256] = {
+ [0x02] = X86_OP_ENTRYwr(LAR, G,v, E,w, chk(prot)),
+ [0x03] = X86_OP_ENTRYwr(LSL, G,v, E,w, chk(prot)),
+ [0x05] = X86_OP_ENTRY0(SYSCALL, chk(o64_intel)),
+ [0x06] = X86_OP_ENTRY0(CLTS, chk(cpl0) svm(WRITE_CR0)),
+ [0x07] = X86_OP_ENTRY0(SYSRET, chk3(o64_intel, prot, cpl0)),
+
[0x10] = X86_OP_GROUP0(0F10),
[0x11] = X86_OP_GROUP0(0F11),
[0x12] = X86_OP_GROUP0(0F12),
@@ -1042,6 +1050,13 @@ static const X86OpEntry opcodes_0F[256] = {
[0x22] = X86_OP_GROUPwr(MOV_CR_DR, C,y, R,y, zextT0 chk(cpl0) svm(WRITE_CR0)),
[0x23] = X86_OP_GROUPwr(MOV_CR_DR, D,y, R,y, zextT0 chk(cpl0) svm(WRITE_DR0)),
+ [0x30] = X86_OP_ENTRY0(WRMSR, chk(cpl0)),
+ [0x31] = X86_OP_ENTRY0(RDTSC),
+ [0x32] = X86_OP_ENTRY0(RDMSR, chk(cpl0)),
+ [0x33] = X86_OP_ENTRY0(RDPMC),
+ [0x34] = X86_OP_ENTRY0(SYSENTER, chk2(i64_amd, prot_or_vm86)),
+ [0x35] = X86_OP_ENTRY0(SYSEXIT, chk3(i64_amd, prot, cpl0)),
+
[0x40] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
[0x41] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
[0x42] = X86_OP_ENTRY2(CMOVcc, G,v, E,v, cpuid(CMOV)),
@@ -1098,6 +1113,7 @@ static const X86OpEntry opcodes_0F[256] = {
[0xa0] = X86_OP_ENTRYr(PUSH, FS, w),
[0xa1] = X86_OP_ENTRYw(POP, FS, w),
+ [0xa2] = X86_OP_ENTRY0(CPUID),
[0xb2] = X86_OP_ENTRY3(LSS, G,v, EM,p, None, None),
[0xb4] = X86_OP_ENTRY3(LFS, G,v, EM,p, None, None),
@@ -1138,6 +1154,8 @@ static const X86OpEntry opcodes_0F[256] = {
[0xf6] = X86_OP_ENTRY3(PSADBW, V,x, H,x, W,x, vex4 mmx avx2_256 p_00_66),
[0xf7] = X86_OP_ENTRY3(MASKMOV, None,None, V,dq, U,dq, vex4_unal avx2_256 mmx p_00_66),
+ [0x08] = X86_OP_ENTRY0(NOP, svm(INVD)),
+ [0x09] = X86_OP_ENTRY0(NOP, svm(WBINVD)),
[0x0b] = X86_OP_ENTRY0(UD), /* UD2 */
[0x0d] = X86_OP_ENTRY1(NOP, M,v), /* 3DNow! prefetch */
[0x0e] = X86_OP_ENTRY0(EMMS, cpuid(3DNOW)), /* femms */
@@ -1221,6 +1239,7 @@ static const X86OpEntry opcodes_0F[256] = {
[0xa8] = X86_OP_ENTRYr(PUSH, GS, w),
[0xa9] = X86_OP_ENTRYw(POP, GS, w),
+ [0xaa] = X86_OP_ENTRY0(RSM, chk(smm) svm(RSM)),
[0xae] = X86_OP_GROUP0(group15),
/*
* It's slightly more efficient to put Ev operand in T0 and allow gen_IMUL3
@@ -2511,12 +2530,10 @@ static void disas_insn(DisasContext *s, CPUState *cpu)
if (b == 0x0f) {
b = x86_ldub_code(env, s);
switch (b) {
- case 0x00 ... 0x03: /* mostly privileged instructions */
- case 0x05 ... 0x09:
+ case 0x00 ... 0x01: /* mostly privileged instructions */
case 0x1a ... 0x1b: /* MPX */
- case 0x30 ... 0x35: /* more privileged instructions */
- case 0xa2 ... 0xa5: /* CPUID, BT, SHLD */
- case 0xaa ... 0xad: /* RSM, SHRD */
+ case 0xa3 ... 0xa5: /* BT, SHLD */
+ case 0xab ... 0xad: /* BTS, SHRD */
case 0xb0 ... 0xb1: /* cmpxchg */
case 0xb3: /* btr */
case 0xb8: /* integer ops */
@@ -2548,13 +2565,18 @@ static void disas_insn(DisasContext *s, CPUState *cpu)
/* Checks that result in #UD come first. */
if (decode.e.check) {
- if (decode.e.check & X86_CHECK_i64) {
- if (CODE64(s)) {
+ if (CODE64(s)) {
+ if (decode.e.check & X86_CHECK_i64) {
goto illegal_op;
}
- }
- if (decode.e.check & X86_CHECK_o64) {
- if (!CODE64(s)) {
+ if ((decode.e.check & X86_CHECK_i64_amd) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1) {
+ goto illegal_op;
+ }
+ } else {
+ if (decode.e.check & X86_CHECK_o64) {
+ goto illegal_op;
+ }
+ if ((decode.e.check & X86_CHECK_o64_intel) && env->cpuid_vendor1 == CPUID_VENDOR_INTEL_1) {
goto illegal_op;
}
}
@@ -2638,8 +2660,7 @@ static void disas_insn(DisasContext *s, CPUState *cpu)
* exceptions if there is no memory operand). Exceptions are
* vm86 checks (INTn, IRET, PUSHF/POPF), RSM and XSETBV (!).
*
- * RSM and XSETBV will be handled in the gen_* functions
- * instead of using chk().
+ * XSETBV will check for CPL0 in the gen_* function instead of using chk().
*/
if (decode.e.check & X86_CHECK_cpl0) {
if (CPL(s) != 0) {
@@ -2651,6 +2672,9 @@ static void disas_insn(DisasContext *s, CPUState *cpu)
tcg_constant_i32(decode.e.intercept));
}
if (decode.e.check) {
+ if ((decode.e.check & X86_CHECK_smm) && !(s->flags & HF_SMM_MASK)) {
+ goto illegal_op;
+ }
if ((decode.e.check & X86_CHECK_vm86_iopl) && VM86(s)) {
if (IOPL(s) < 3) {
goto gp_fault;
diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
index 709ef7b0cb2..92635f53cf4 100644
--- a/target/i386/tcg/emit.c.inc
+++ b/target/i386/tcg/emit.c.inc
@@ -1410,6 +1410,13 @@ static void gen_CLI(DisasContext *s, X86DecodedInsn *decode)
gen_reset_eflags(s, IF_MASK);
}
+static void gen_CLTS(DisasContext *s, X86DecodedInsn *decode)
+{
+ gen_helper_clts(tcg_env);
+ /* abort block because static cpu state changed */
+ s->base.is_jmp = DISAS_EOB_NEXT;
+}
+
static void gen_CMC(DisasContext *s, X86DecodedInsn *decode)
{
gen_compute_eflags(s);
@@ -1534,6 +1541,13 @@ static void gen_CMPS(DisasContext *s, X86DecodedInsn *decode)
}
}
+static void gen_CPUID(DisasContext *s, X86DecodedInsn *decode)
+{
+ gen_update_cc_op(s);
+ gen_update_eip_cur(s);
+ gen_helper_cpuid(tcg_env);
+}
+
static void gen_CRC32(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[2].ot;
@@ -1657,16 +1671,18 @@ static void gen_FXRSTOR(DisasContext *s, X86DecodedInsn *decode)
{
if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
gen_NM_exception(s);
+ } else {
+ gen_helper_fxrstor(tcg_env, s->A0);
}
- gen_helper_fxrstor(tcg_env, s->A0);
}
static void gen_FXSAVE(DisasContext *s, X86DecodedInsn *decode)
{
if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
gen_NM_exception(s);
+ } else {
+ gen_helper_fxsave(tcg_env, s->A0);
}
- gen_helper_fxsave(tcg_env, s->A0);
}
static void gen_HLT(DisasContext *s, X86DecodedInsn *decode)
@@ -1977,6 +1993,23 @@ static void gen_LAHF(DisasContext *s, X86DecodedInsn *decode)
tcg_gen_deposit_tl(cpu_regs[R_EAX], cpu_regs[R_EAX], s->T0, 8, 8);
}
+static void gen_LAR(DisasContext *s, X86DecodedInsn *decode)
+{
+ MemOp ot = decode->op[0].ot;
+ TCGv result = tcg_temp_new();
+ TCGv dest;
+
+ gen_compute_eflags(s);
+ gen_update_cc_op(s);
+ gen_helper_lar(result, tcg_env, s->T0);
+
+ /* Perform writeback here to skip it if ZF=0. */
+ decode->op[0].unit = X86_OP_SKIP;
+ dest = gen_op_deposit_reg_v(s, ot, decode->op[0].n, result, result);
+ tcg_gen_movcond_tl(TCG_COND_TSTNE, dest, cpu_cc_src, tcg_constant_tl(CC_Z),
+ result, dest);
+}
+
static void gen_LDMXCSR(DisasContext *s, X86DecodedInsn *decode)
{
tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
@@ -2075,6 +2108,23 @@ static void gen_LOOPNE(DisasContext *s, X86DecodedInsn *decode)
gen_conditional_jump_labels(s, decode->immediate, not_taken, taken);
}
+static void gen_LSL(DisasContext *s, X86DecodedInsn *decode)
+{
+ MemOp ot = decode->op[0].ot;
+ TCGv result = tcg_temp_new();
+ TCGv dest;
+
+ gen_compute_eflags(s);
+ gen_update_cc_op(s);
+ gen_helper_lsl(result, tcg_env, s->T0);
+
+ /* Perform writeback here to skip it if ZF=0. */
+ decode->op[0].unit = X86_OP_SKIP;
+ dest = gen_op_deposit_reg_v(s, ot, decode->op[0].n, result, result);
+ tcg_gen_movcond_tl(TCG_COND_TSTNE, dest, cpu_cc_src, tcg_constant_tl(CC_Z),
+ result, dest);
+}
+
static void gen_LSS(DisasContext *s, X86DecodedInsn *decode)
{
gen_lxx_seg(s, decode, R_SS);
@@ -3118,6 +3168,41 @@ static void gen_RCR(DisasContext *s, X86DecodedInsn *decode)
}
}
+#ifdef CONFIG_USER_ONLY
+static void gen_unreachable(DisasContext *s, X86DecodedInsn *decode)
+{
+ g_assert_not_reached();
+}
+#endif
+
+#ifndef CONFIG_USER_ONLY
+static void gen_RDMSR(DisasContext *s, X86DecodedInsn *decode)
+{
+ gen_update_cc_op(s);
+ gen_update_eip_cur(s);
+ gen_helper_rdmsr(tcg_env);
+}
+#else
+#define gen_RDMSR gen_unreachable
+#endif
+
+static void gen_RDPMC(DisasContext *s, X86DecodedInsn *decode)
+{
+ gen_update_cc_op(s);
+ gen_update_eip_cur(s);
+ translator_io_start(&s->base);
+ gen_helper_rdpmc(tcg_env);
+ s->base.is_jmp = DISAS_NORETURN;
+}
+
+static void gen_RDTSC(DisasContext *s, X86DecodedInsn *decode)
+{
+ gen_update_cc_op(s);
+ gen_update_eip_cur(s);
+ translator_io_start(&s->base);
+ gen_helper_rdtsc(tcg_env);
+}
+
static void gen_RDxxBASE(DisasContext *s, X86DecodedInsn *decode)
{
TCGv base = cpu_seg_base[s->modrm & 8 ? R_GS : R_FS];
@@ -3290,6 +3375,17 @@ static void gen_RORX(DisasContext *s, X86DecodedInsn *decode)
}
}
+#ifndef CONFIG_USER_ONLY
+static void gen_RSM(DisasContext *s, X86DecodedInsn *decode)
+{
+ gen_helper_rsm(tcg_env);
+ assume_cc_op(s, CC_OP_EFLAGS);
+ s->base.is_jmp = DISAS_EOB_ONLY;
+}
+#else
+#define gen_RSM gen_UD
+#endif
+
static void gen_SAHF(DisasContext *s, X86DecodedInsn *decode)
{
if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM)) {
@@ -3586,6 +3682,51 @@ static void gen_SUB(DisasContext *s, X86DecodedInsn *decode)
prepare_update2_cc(decode, s, CC_OP_SUBB + ot);
}
+static void gen_SYSCALL(DisasContext *s, X86DecodedInsn *decode)
+{
+ gen_update_cc_op(s);
+ gen_update_eip_cur(s);
+ gen_helper_syscall(tcg_env, cur_insn_len_i32(s));
+ if (LMA(s)) {
+ assume_cc_op(s, CC_OP_EFLAGS);
+ }
+
+ /*
+ * TF handling for the syscall insn is different. The TF bit is checked
+ * after the syscall insn completes. This allows #DB to not be
+ * generated after one has entered CPL0 if TF is set in FMASK.
+ */
+ s->base.is_jmp = DISAS_EOB_RECHECK_TF;
+}
+
+static void gen_SYSENTER(DisasContext *s, X86DecodedInsn *decode)
+{
+ gen_helper_sysenter(tcg_env);
+ s->base.is_jmp = DISAS_EOB_ONLY;
+}
+
+static void gen_SYSEXIT(DisasContext *s, X86DecodedInsn *decode)
+{
+ gen_helper_sysexit(tcg_env, tcg_constant_i32(s->dflag - 1));
+ s->base.is_jmp = DISAS_EOB_ONLY;
+}
+
+static void gen_SYSRET(DisasContext *s, X86DecodedInsn *decode)
+{
+ gen_helper_sysret(tcg_env, tcg_constant_i32(s->dflag - 1));
+ if (LMA(s)) {
+ assume_cc_op(s, CC_OP_EFLAGS);
+ }
+
+ /*
+ * TF handling for the sysret insn is different. The TF bit is checked
+ * after the sysret insn completes. This allows #DB to be
+ * generated "as if" the syscall insn in userspace has just
+ * completed.
+ */
+ s->base.is_jmp = DISAS_EOB_RECHECK_TF;
+}
+
static void gen_UD(DisasContext *s, X86DecodedInsn *decode)
{
gen_illegal_opcode(s);
@@ -4082,6 +4223,18 @@ static void gen_WAIT(DisasContext *s, X86DecodedInsn *decode)
}
}
+#ifndef CONFIG_USER_ONLY
+static void gen_WRMSR(DisasContext *s, X86DecodedInsn *decode)
+{
+ gen_update_cc_op(s);
+ gen_update_eip_cur(s);
+ gen_helper_wrmsr(tcg_env);
+ s->base.is_jmp = DISAS_EOB_NEXT;
+}
+#else
+#define gen_WRMSR gen_unreachable
+#endif
+
static void gen_WRxxBASE(DisasContext *s, X86DecodedInsn *decode)
{
TCGv base = cpu_seg_base[s->modrm & 8 ? R_GS : R_FS];
--
2.45.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PULL 19/25] target/i386: pull load/writeback out of gen_shiftd_rm_T1
2024-06-11 14:24 [PULL 00/25] target/i386, SCSI changes for 2024-06-11 Paolo Bonzini
` (17 preceding siblings ...)
2024-06-11 14:25 ` [PULL 18/25] target/i386: convert non-grouped, helper-based 2-byte opcodes Paolo Bonzini
@ 2024-06-11 14:25 ` Paolo Bonzini
2024-06-11 14:25 ` [PULL 20/25] target/i386: adapt gen_shift_count for SHLD/SHRD Paolo Bonzini
` (6 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Paolo Bonzini @ 2024-06-11 14:25 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson
Use gen_ld_modrm/gen_st_modrm, moving them and gen_shift_flags to the
caller. This way, gen_shiftd_rm_T1 becomes something that the new
decoder can call.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/tcg/translate.c | 55 ++++++++++---------------------------
1 file changed, 14 insertions(+), 41 deletions(-)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 4b2f7488022..5200b578a0e 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -535,15 +535,6 @@ static inline void gen_op_st_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
tcg_gen_qemu_st_tl(t0, a0, s->mem_index, idx | MO_LE);
}
-static inline void gen_op_st_rm_T0_A0(DisasContext *s, int idx, int d)
-{
- if (d == OR_TMP0) {
- gen_op_st_v(s, idx, s->T0, s->A0);
- } else {
- gen_op_mov_reg_v(s, idx, d, s->T0);
- }
-}
-
static void gen_update_eip_next(DisasContext *s)
{
assert(s->pc_save != -1);
@@ -1486,19 +1477,12 @@ static void gen_shift_flags(DisasContext *s, MemOp ot, TCGv result,
}
/* XXX: add faster immediate case */
-static void gen_shiftd_rm_T1(DisasContext *s, MemOp ot, int op1,
+static TCGv gen_shiftd_rm_T1(DisasContext *s, MemOp ot,
bool is_right, TCGv count_in)
{
target_ulong mask = (ot == MO_64 ? 63 : 31);
TCGv count;
- /* load */
- if (op1 == OR_TMP0) {
- gen_op_ld_v(s, ot, s->T0, s->A0);
- } else {
- gen_op_mov_v_reg(s, ot, s->T0, op1);
- }
-
count = tcg_temp_new();
tcg_gen_andi_tl(count, count_in, mask);
@@ -1563,10 +1547,7 @@ static void gen_shiftd_rm_T1(DisasContext *s, MemOp ot, int op1,
break;
}
- /* store */
- gen_op_st_rm_T0_A0(s, ot, op1);
-
- gen_shift_flags(s, ot, s->T0, s->tmp0, count, is_right);
+ return count;
}
#define X86_MAX_INSN_LENGTH 15
@@ -3076,9 +3057,9 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b)
CPUX86State *env = cpu_env(cpu);
int prefixes = s->prefix;
MemOp dflag = s->dflag;
- int shift;
+ TCGv shift;
MemOp ot;
- int modrm, reg, rm, mod, op, opreg, val;
+ int modrm, reg, rm, mod, op, val;
/* now check op code */
switch (b) {
@@ -3244,39 +3225,31 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b)
/* shifts */
case 0x1a4: /* shld imm */
op = 0;
- shift = 1;
+ shift = NULL;
goto do_shiftd;
case 0x1a5: /* shld cl */
op = 0;
- shift = 0;
+ shift = cpu_regs[R_ECX];
goto do_shiftd;
case 0x1ac: /* shrd imm */
op = 1;
- shift = 1;
+ shift = NULL;
goto do_shiftd;
case 0x1ad: /* shrd cl */
op = 1;
- shift = 0;
+ shift = cpu_regs[R_ECX];
do_shiftd:
ot = dflag;
modrm = x86_ldub_code(env, s);
- mod = (modrm >> 6) & 3;
- rm = (modrm & 7) | REX_B(s);
reg = ((modrm >> 3) & 7) | REX_R(s);
- if (mod != 3) {
- gen_lea_modrm(env, s, modrm);
- opreg = OR_TMP0;
- } else {
- opreg = rm;
+ gen_ld_modrm(env, s, modrm, ot);
+ if (!shift) {
+ shift = tcg_constant_tl(x86_ldub_code(env, s));
}
gen_op_mov_v_reg(s, ot, s->T1, reg);
-
- if (shift) {
- TCGv imm = tcg_constant_tl(x86_ldub_code(env, s));
- gen_shiftd_rm_T1(s, ot, opreg, op, imm);
- } else {
- gen_shiftd_rm_T1(s, ot, opreg, op, cpu_regs[R_ECX]);
- }
+ shift = gen_shiftd_rm_T1(s, ot, op, shift);
+ gen_st_modrm(env, s, modrm, ot);
+ gen_shift_flags(s, ot, s->T0, s->tmp0, shift, op);
break;
/************************/
--
2.45.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PULL 20/25] target/i386: adapt gen_shift_count for SHLD/SHRD
2024-06-11 14:24 [PULL 00/25] target/i386, SCSI changes for 2024-06-11 Paolo Bonzini
` (18 preceding siblings ...)
2024-06-11 14:25 ` [PULL 19/25] target/i386: pull load/writeback out of gen_shiftd_rm_T1 Paolo Bonzini
@ 2024-06-11 14:25 ` Paolo Bonzini
2024-06-11 14:25 ` [PULL 21/25] target/i386: convert SHLD/SHRD to new decoder Paolo Bonzini
` (5 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Paolo Bonzini @ 2024-06-11 14:25 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson
SHLD/SHRD can have 3 register operands - s->T0, s->T1 and either
1 or CL - and therefore decode->op[2] is taken by the low part
of the register being shifted. Pass X86_OP_* to gen_shift_count
from its current callers and hardcode cpu_regs[R_ECX] as the
shift count.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/tcg/emit.c.inc | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
index 92635f53cf4..156ea282af4 100644
--- a/target/i386/tcg/emit.c.inc
+++ b/target/i386/tcg/emit.c.inc
@@ -2874,16 +2874,16 @@ static void gen_PUSHF(DisasContext *s, X86DecodedInsn *decode)
}
static MemOp gen_shift_count(DisasContext *s, X86DecodedInsn *decode,
- bool *can_be_zero, TCGv *count)
+ bool *can_be_zero, TCGv *count, int unit)
{
MemOp ot = decode->op[0].ot;
int mask = (ot <= MO_32 ? 0x1f : 0x3f);
*can_be_zero = false;
- switch (decode->op[2].unit) {
+ switch (unit) {
case X86_OP_INT:
*count = tcg_temp_new();
- tcg_gen_andi_tl(*count, s->T1, mask);
+ tcg_gen_andi_tl(*count, cpu_regs[R_ECX], mask);
*can_be_zero = true;
break;
@@ -3068,7 +3068,7 @@ static void gen_RCL(DisasContext *s, X86DecodedInsn *decode)
bool have_1bit_cin, can_be_zero;
TCGv count;
TCGLabel *zero_label = NULL;
- MemOp ot = gen_shift_count(s, decode, &can_be_zero, &count);
+ MemOp ot = gen_shift_count(s, decode, &can_be_zero, &count, decode->op[2].unit);
TCGv low, high, low_count;
if (!count) {
@@ -3120,7 +3120,7 @@ static void gen_RCR(DisasContext *s, X86DecodedInsn *decode)
bool have_1bit_cin, can_be_zero;
TCGv count;
TCGLabel *zero_label = NULL;
- MemOp ot = gen_shift_count(s, decode, &can_be_zero, &count);
+ MemOp ot = gen_shift_count(s, decode, &can_be_zero, &count, decode->op[2].unit);
TCGv low, high, high_count;
if (!count) {
@@ -3298,7 +3298,7 @@ static void gen_ROL(DisasContext *s, X86DecodedInsn *decode)
{
bool can_be_zero;
TCGv count;
- MemOp ot = gen_shift_count(s, decode, &can_be_zero, &count);
+ MemOp ot = gen_shift_count(s, decode, &can_be_zero, &count, decode->op[2].unit);
TCGv_i32 temp32, count32;
TCGv old = tcg_temp_new();
@@ -3326,7 +3326,7 @@ static void gen_ROR(DisasContext *s, X86DecodedInsn *decode)
{
bool can_be_zero;
TCGv count;
- MemOp ot = gen_shift_count(s, decode, &can_be_zero, &count);
+ MemOp ot = gen_shift_count(s, decode, &can_be_zero, &count, decode->op[2].unit);
TCGv_i32 temp32, count32;
TCGv old = tcg_temp_new();
@@ -3438,7 +3438,7 @@ static void gen_SAR(DisasContext *s, X86DecodedInsn *decode)
{
bool can_be_zero;
TCGv count;
- MemOp ot = gen_shift_count(s, decode, &can_be_zero, &count);
+ MemOp ot = gen_shift_count(s, decode, &can_be_zero, &count, decode->op[2].unit);
if (!count) {
return;
@@ -3566,7 +3566,7 @@ static void gen_SHL(DisasContext *s, X86DecodedInsn *decode)
{
bool can_be_zero;
TCGv count;
- MemOp ot = gen_shift_count(s, decode, &can_be_zero, &count);
+ MemOp ot = gen_shift_count(s, decode, &can_be_zero, &count, decode->op[2].unit);
if (!count) {
return;
@@ -3598,7 +3598,7 @@ static void gen_SHR(DisasContext *s, X86DecodedInsn *decode)
{
bool can_be_zero;
TCGv count;
- MemOp ot = gen_shift_count(s, decode, &can_be_zero, &count);
+ MemOp ot = gen_shift_count(s, decode, &can_be_zero, &count, decode->op[2].unit);
if (!count) {
return;
--
2.45.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PULL 21/25] target/i386: convert SHLD/SHRD to new decoder
2024-06-11 14:24 [PULL 00/25] target/i386, SCSI changes for 2024-06-11 Paolo Bonzini
` (19 preceding siblings ...)
2024-06-11 14:25 ` [PULL 20/25] target/i386: adapt gen_shift_count for SHLD/SHRD Paolo Bonzini
@ 2024-06-11 14:25 ` Paolo Bonzini
2024-06-11 14:25 ` [PULL 22/25] target/i386: convert LZCNT/TZCNT/BSF/BSR/POPCNT " Paolo Bonzini
` (4 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Paolo Bonzini @ 2024-06-11 14:25 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson
Use the same flag generation code as SHL and SHR, but use
the existing gen_shiftd_rm_T1 function to compute the result
as well as CC_SRC.
Decoding-wise, SHLD/SHRD by immediate count as a 4 operand
instruction because s->T0 and s->T1 actually occupy three op
slots. The infrastructure used by opcodes in the 0F 3A table
works fine.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/tcg/translate.c | 84 +-------------------------------
target/i386/tcg/decode-new.c.inc | 8 ++-
target/i386/tcg/emit.c.inc | 42 ++++++++++++++++
3 files changed, 50 insertions(+), 84 deletions(-)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 5200b578a0e..33058db4e30 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -1434,57 +1434,11 @@ static bool check_cpl0(DisasContext *s)
return false;
}
-static void gen_shift_flags(DisasContext *s, MemOp ot, TCGv result,
- TCGv shm1, TCGv count, bool is_right)
-{
- TCGv_i32 z32, s32, oldop;
- TCGv z_tl;
-
- /* Store the results into the CC variables. If we know that the
- variable must be dead, store unconditionally. Otherwise we'll
- need to not disrupt the current contents. */
- z_tl = tcg_constant_tl(0);
- if (cc_op_live[s->cc_op] & USES_CC_DST) {
- tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_dst, count, z_tl,
- result, cpu_cc_dst);
- } else {
- tcg_gen_mov_tl(cpu_cc_dst, result);
- }
- if (cc_op_live[s->cc_op] & USES_CC_SRC) {
- tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_src, count, z_tl,
- shm1, cpu_cc_src);
- } else {
- tcg_gen_mov_tl(cpu_cc_src, shm1);
- }
-
- /* Get the two potential CC_OP values into temporaries. */
- tcg_gen_movi_i32(s->tmp2_i32, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
- if (s->cc_op == CC_OP_DYNAMIC) {
- oldop = cpu_cc_op;
- } else {
- tcg_gen_movi_i32(s->tmp3_i32, s->cc_op);
- oldop = s->tmp3_i32;
- }
-
- /* Conditionally store the CC_OP value. */
- z32 = tcg_constant_i32(0);
- s32 = tcg_temp_new_i32();
- tcg_gen_trunc_tl_i32(s32, count);
- tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, s32, z32, s->tmp2_i32, oldop);
-
- /* The CC_OP value is no longer predictable. */
- set_cc_op(s, CC_OP_DYNAMIC);
-}
-
/* XXX: add faster immediate case */
-static TCGv gen_shiftd_rm_T1(DisasContext *s, MemOp ot,
- bool is_right, TCGv count_in)
+static void gen_shiftd_rm_T1(DisasContext *s, MemOp ot,
+ bool is_right, TCGv count)
{
target_ulong mask = (ot == MO_64 ? 63 : 31);
- TCGv count;
-
- count = tcg_temp_new();
- tcg_gen_andi_tl(count, count_in, mask);
switch (ot) {
case MO_16:
@@ -1546,8 +1500,6 @@ static TCGv gen_shiftd_rm_T1(DisasContext *s, MemOp ot,
tcg_gen_or_tl(s->T0, s->T0, s->T1);
break;
}
-
- return count;
}
#define X86_MAX_INSN_LENGTH 15
@@ -3057,7 +3009,6 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b)
CPUX86State *env = cpu_env(cpu);
int prefixes = s->prefix;
MemOp dflag = s->dflag;
- TCGv shift;
MemOp ot;
int modrm, reg, rm, mod, op, val;
@@ -3221,37 +3172,6 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b)
}
break;
- /**************************/
- /* shifts */
- case 0x1a4: /* shld imm */
- op = 0;
- shift = NULL;
- goto do_shiftd;
- case 0x1a5: /* shld cl */
- op = 0;
- shift = cpu_regs[R_ECX];
- goto do_shiftd;
- case 0x1ac: /* shrd imm */
- op = 1;
- shift = NULL;
- goto do_shiftd;
- case 0x1ad: /* shrd cl */
- op = 1;
- shift = cpu_regs[R_ECX];
- do_shiftd:
- ot = dflag;
- modrm = x86_ldub_code(env, s);
- reg = ((modrm >> 3) & 7) | REX_R(s);
- gen_ld_modrm(env, s, modrm, ot);
- if (!shift) {
- shift = tcg_constant_tl(x86_ldub_code(env, s));
- }
- gen_op_mov_v_reg(s, ot, s->T1, reg);
- shift = gen_shiftd_rm_T1(s, ot, op, shift);
- gen_st_modrm(env, s, modrm, ot);
- gen_shift_flags(s, ot, s->T0, s->tmp0, shift, op);
- break;
-
/************************/
/* bit operations */
case 0x1ba: /* bt/bts/btr/btc Gv, im */
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index 1db9d1e2bc3..2d27b07f296 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -1114,6 +1114,8 @@ static const X86OpEntry opcodes_0F[256] = {
[0xa0] = X86_OP_ENTRYr(PUSH, FS, w),
[0xa1] = X86_OP_ENTRYw(POP, FS, w),
[0xa2] = X86_OP_ENTRY0(CPUID),
+ [0xa4] = X86_OP_ENTRY4(SHLD, E,v, 2op,v, G,v),
+ [0xa5] = X86_OP_ENTRY3(SHLD, E,v, 2op,v, G,v),
[0xb2] = X86_OP_ENTRY3(LSS, G,v, EM,p, None, None),
[0xb4] = X86_OP_ENTRY3(LFS, G,v, EM,p, None, None),
@@ -1240,6 +1242,8 @@ static const X86OpEntry opcodes_0F[256] = {
[0xa8] = X86_OP_ENTRYr(PUSH, GS, w),
[0xa9] = X86_OP_ENTRYw(POP, GS, w),
[0xaa] = X86_OP_ENTRY0(RSM, chk(smm) svm(RSM)),
+ [0xac] = X86_OP_ENTRY4(SHRD, E,v, 2op,v, G,v),
+ [0xad] = X86_OP_ENTRY3(SHRD, E,v, 2op,v, G,v),
[0xae] = X86_OP_GROUP0(group15),
/*
* It's slightly more efficient to put Ev operand in T0 and allow gen_IMUL3
@@ -2532,8 +2536,8 @@ static void disas_insn(DisasContext *s, CPUState *cpu)
switch (b) {
case 0x00 ... 0x01: /* mostly privileged instructions */
case 0x1a ... 0x1b: /* MPX */
- case 0xa3 ... 0xa5: /* BT, SHLD */
- case 0xab ... 0xad: /* BTS, SHRD */
+ case 0xa3: /* bt */
+ case 0xab: /* bts */
case 0xb0 ... 0xb1: /* cmpxchg */
case 0xb3: /* btr */
case 0xb8: /* integer ops */
diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
index 156ea282af4..fc4687a35bd 100644
--- a/target/i386/tcg/emit.c.inc
+++ b/target/i386/tcg/emit.c.inc
@@ -3584,6 +3584,27 @@ static void gen_SHL(DisasContext *s, X86DecodedInsn *decode)
}
}
+static void gen_SHLD(DisasContext *s, X86DecodedInsn *decode)
+{
+ bool can_be_zero;
+ TCGv count;
+ int unit = decode->e.op3 == X86_TYPE_I ? X86_OP_IMM : X86_OP_INT;
+ MemOp ot = gen_shift_count(s, decode, &can_be_zero, &count, unit);
+
+ if (!count) {
+ return;
+ }
+
+ decode->cc_dst = s->T0;
+ decode->cc_src = s->tmp0;
+ gen_shiftd_rm_T1(s, ot, false, count);
+ if (can_be_zero) {
+ gen_shift_dynamic_flags(s, decode, count, CC_OP_SHLB + ot);
+ } else {
+ decode->cc_op = CC_OP_SHLB + ot;
+ }
+}
+
static void gen_SHLX(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[0].ot;
@@ -3616,6 +3637,27 @@ static void gen_SHR(DisasContext *s, X86DecodedInsn *decode)
}
}
+static void gen_SHRD(DisasContext *s, X86DecodedInsn *decode)
+{
+ bool can_be_zero;
+ TCGv count;
+ int unit = decode->e.op3 == X86_TYPE_I ? X86_OP_IMM : X86_OP_INT;
+ MemOp ot = gen_shift_count(s, decode, &can_be_zero, &count, unit);
+
+ if (!count) {
+ return;
+ }
+
+ decode->cc_dst = s->T0;
+ decode->cc_src = s->tmp0;
+ gen_shiftd_rm_T1(s, ot, true, count);
+ if (can_be_zero) {
+ gen_shift_dynamic_flags(s, decode, count, CC_OP_SARB + ot);
+ } else {
+ decode->cc_op = CC_OP_SARB + ot;
+ }
+}
+
static void gen_SHRX(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot = decode->op[0].ot;
--
2.45.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PULL 22/25] target/i386: convert LZCNT/TZCNT/BSF/BSR/POPCNT to new decoder
2024-06-11 14:24 [PULL 00/25] target/i386, SCSI changes for 2024-06-11 Paolo Bonzini
` (20 preceding siblings ...)
2024-06-11 14:25 ` [PULL 21/25] target/i386: convert SHLD/SHRD to new decoder Paolo Bonzini
@ 2024-06-11 14:25 ` Paolo Bonzini
2024-06-11 14:25 ` [PULL 23/25] target/i386: convert XADD " Paolo Bonzini
` (3 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Paolo Bonzini @ 2024-06-11 14:25 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/tcg/decode-new.h | 1 +
target/i386/tcg/translate.c | 74 ----------------------------
target/i386/tcg/decode-new.c.inc | 52 +++++++++++++++++++-
target/i386/tcg/emit.c.inc | 82 ++++++++++++++++++++++++++++++++
4 files changed, 133 insertions(+), 76 deletions(-)
diff --git a/target/i386/tcg/decode-new.h b/target/i386/tcg/decode-new.h
index c9f958bb0e5..9b684af7cd0 100644
--- a/target/i386/tcg/decode-new.h
+++ b/target/i386/tcg/decode-new.h
@@ -119,6 +119,7 @@ typedef enum X86CPUIDFeature {
X86_FEAT_FXSR,
X86_FEAT_MOVBE,
X86_FEAT_PCLMULQDQ,
+ X86_FEAT_POPCNT,
X86_FEAT_SHA_NI,
X86_FEAT_SSE,
X86_FEAT_SSE2,
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 33058db4e30..68a11f81786 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -823,11 +823,6 @@ static void gen_movs(DisasContext *s, MemOp ot)
gen_op_add_reg(s, s->aflag, R_EDI, dshift);
}
-static void gen_op_update1_cc(DisasContext *s)
-{
- tcg_gen_mov_tl(cpu_cc_dst, s->T0);
-}
-
static void gen_op_update2_cc(DisasContext *s)
{
tcg_gen_mov_tl(cpu_cc_src, s->T1);
@@ -3311,56 +3306,6 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b)
break;
}
break;
- case 0x1bc: /* bsf / tzcnt */
- case 0x1bd: /* bsr / lzcnt */
- ot = dflag;
- modrm = x86_ldub_code(env, s);
- reg = ((modrm >> 3) & 7) | REX_R(s);
- gen_ld_modrm(env, s, modrm, ot);
- gen_extu(ot, s->T0);
-
- /* Note that lzcnt and tzcnt are in different extensions. */
- if ((prefixes & PREFIX_REPZ)
- && (b & 1
- ? s->cpuid_ext3_features & CPUID_EXT3_ABM
- : s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)) {
- int size = 8 << ot;
- /* For lzcnt/tzcnt, C bit is defined related to the input. */
- tcg_gen_mov_tl(cpu_cc_src, s->T0);
- if (b & 1) {
- /* For lzcnt, reduce the target_ulong result by the
- number of zeros that we expect to find at the top. */
- tcg_gen_clzi_tl(s->T0, s->T0, TARGET_LONG_BITS);
- tcg_gen_subi_tl(s->T0, s->T0, TARGET_LONG_BITS - size);
- } else {
- /* For tzcnt, a zero input must return the operand size. */
- tcg_gen_ctzi_tl(s->T0, s->T0, size);
- }
- /* For lzcnt/tzcnt, Z bit is defined related to the result. */
- gen_op_update1_cc(s);
- set_cc_op(s, CC_OP_BMILGB + ot);
- } else {
- /* For bsr/bsf, only the Z bit is defined and it is related
- to the input and not the result. */
- tcg_gen_mov_tl(cpu_cc_dst, s->T0);
- set_cc_op(s, CC_OP_LOGICB + ot);
-
- /* ??? The manual says that the output is undefined when the
- input is zero, but real hardware leaves it unchanged, and
- real programs appear to depend on that. Accomplish this
- by passing the output as the value to return upon zero. */
- if (b & 1) {
- /* For bsr, return the bit index of the first 1 bit,
- not the count of leading zeros. */
- tcg_gen_xori_tl(s->T1, cpu_regs[reg], TARGET_LONG_BITS - 1);
- tcg_gen_clz_tl(s->T0, s->T0, s->T1);
- tcg_gen_xori_tl(s->T0, s->T0, TARGET_LONG_BITS - 1);
- } else {
- tcg_gen_ctz_tl(s->T0, s->T0, cpu_regs[reg]);
- }
- }
- gen_op_mov_reg_v(s, ot, reg, s->T0);
- break;
case 0x100:
modrm = x86_ldub_code(env, s);
mod = (modrm >> 6) & 3;
@@ -3955,25 +3900,6 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b)
}
gen_nop_modrm(env, s, modrm);
break;
- case 0x1b8: /* SSE4.2 popcnt */
- if ((prefixes & (PREFIX_REPZ | PREFIX_LOCK | PREFIX_REPNZ)) !=
- PREFIX_REPZ)
- goto illegal_op;
- if (!(s->cpuid_ext_features & CPUID_EXT_POPCNT))
- goto illegal_op;
-
- modrm = x86_ldub_code(env, s);
- reg = ((modrm >> 3) & 7) | REX_R(s);
-
- ot = dflag;
- gen_ld_modrm(env, s, modrm, ot);
- gen_extu(ot, s->T0);
- tcg_gen_mov_tl(cpu_cc_src, s->T0);
- tcg_gen_ctpop_tl(s->T0, s->T0);
- gen_op_mov_reg_v(s, ot, reg, s->T0);
-
- set_cc_op(s, CC_OP_POPCNT);
- break;
default:
g_assert_not_reached();
}
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index 2d27b07f296..15ebc1233ea 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -450,6 +450,50 @@ static void decode_0F7F(DisasContext *s, CPUX86State *env, X86OpEntry *entry, ui
*entry = *decode_by_prefix(s, opcodes_0F7F);
}
+static void decode_0FB8(DisasContext *s, CPUX86State *env, X86OpEntry *entry, uint8_t *b)
+{
+ static const X86OpEntry popcnt =
+ X86_OP_ENTRYwr(POPCNT, G,v, E,v, cpuid(POPCNT) zextT0);
+
+ if (s->prefix & PREFIX_REPZ) {
+ *entry = popcnt;
+ } else {
+ memset(entry, 0, sizeof(*entry));
+ }
+}
+
+static void decode_0FBC(DisasContext *s, CPUX86State *env, X86OpEntry *entry, uint8_t *b)
+{
+ /* For BSF, pass 2op as the third operand so that we can use zextT0 */
+ static const X86OpEntry opcodes_0FBC[4] = {
+ X86_OP_ENTRY3(BSF, G,v, E,v, 2op,v, zextT0),
+ X86_OP_ENTRY3(BSF, G,v, E,v, 2op,v, zextT0), /* 0x66 */
+ X86_OP_ENTRYwr(TZCNT, G,v, E,v, zextT0), /* 0xf3 */
+ X86_OP_ENTRY3(BSF, G,v, E,v, 2op,v, zextT0), /* 0xf2 */
+ };
+ if (!(s->cpuid_ext3_features & CPUID_EXT3_ABM)) {
+ *entry = opcodes_0FBC[0];
+ } else {
+ *entry = *decode_by_prefix(s, opcodes_0FBC);
+ }
+}
+
+static void decode_0FBD(DisasContext *s, CPUX86State *env, X86OpEntry *entry, uint8_t *b)
+{
+ /* For BSR, pass 2op as the third operand so that we can use zextT0 */
+ static const X86OpEntry opcodes_0FBD[4] = {
+ X86_OP_ENTRY3(BSR, G,v, E,v, 2op,v, zextT0),
+ X86_OP_ENTRY3(BSR, G,v, E,v, 2op,v, zextT0), /* 0x66 */
+ X86_OP_ENTRYwr(LZCNT, G,v, E,v, zextT0), /* 0xf3 */
+ X86_OP_ENTRY3(BSR, G,v, E,v, 2op,v, zextT0), /* 0xf2 */
+ };
+ if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)) {
+ *entry = opcodes_0FBD[0];
+ } else {
+ *entry = *decode_by_prefix(s, opcodes_0FBD);
+ }
+}
+
static void decode_0FD6(DisasContext *s, CPUX86State *env, X86OpEntry *entry, uint8_t *b)
{
static const X86OpEntry movq[4] = {
@@ -1251,8 +1295,11 @@ static const X86OpEntry opcodes_0F[256] = {
*/
[0xaf] = X86_OP_ENTRY3(IMUL3, G,v, E,v, 2op,v, sextT0),
+ [0xb8] = X86_OP_GROUP0(0FB8),
/* decoded as modrm, which is visible as a difference between page fault and #UD */
[0xb9] = X86_OP_ENTRYr(UD, nop,v), /* UD1 */
+ [0xbc] = X86_OP_GROUP0(0FBC),
+ [0xbd] = X86_OP_GROUP0(0FBD),
[0xbe] = X86_OP_ENTRY3(MOV, G,v, E,b, None, None, sextT0), /* MOVSX */
[0xbf] = X86_OP_ENTRY3(MOV, G,v, E,w, None, None, sextT0), /* MOVSX */
@@ -2150,6 +2197,8 @@ static bool has_cpuid_feature(DisasContext *s, X86CPUIDFeature cpuid)
return (s->cpuid_ext_features & CPUID_EXT_MOVBE);
case X86_FEAT_PCLMULQDQ:
return (s->cpuid_ext_features & CPUID_EXT_PCLMULQDQ);
+ case X86_FEAT_POPCNT:
+ return (s->cpuid_ext_features & CPUID_EXT_POPCNT);
case X86_FEAT_SSE:
return (s->cpuid_features & CPUID_SSE);
case X86_FEAT_SSE2:
@@ -2540,8 +2589,7 @@ static void disas_insn(DisasContext *s, CPUState *cpu)
case 0xab: /* bts */
case 0xb0 ... 0xb1: /* cmpxchg */
case 0xb3: /* btr */
- case 0xb8: /* integer ops */
- case 0xba ... 0xbd: /* integer ops */
+ case 0xba ... 0xbb: /* grp8, btc */
case 0xc0 ... 0xc1: /* xadd */
case 0xc7: /* grp9 */
disas_insn_old(s, cpu, b + 0x100);
diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
index fc4687a35bd..7f554ba1173 100644
--- a/target/i386/tcg/emit.c.inc
+++ b/target/i386/tcg/emit.c.inc
@@ -1329,6 +1329,47 @@ static void gen_BOUND(DisasContext *s, X86DecodedInsn *decode)
}
}
+/* Non-standard convention - on entry T0 is zero-extended input, T1 is the output. */
+static void gen_BSF(DisasContext *s, X86DecodedInsn *decode)
+{
+ MemOp ot = decode->op[0].ot;
+
+ /* Only the Z bit is defined and it is related to the input. */
+ decode->cc_dst = tcg_temp_new();
+ decode->cc_op = CC_OP_LOGICB + ot;
+ tcg_gen_mov_tl(decode->cc_dst, s->T0);
+
+ /*
+ * The manual says that the output is undefined when the
+ * input is zero, but real hardware leaves it unchanged, and
+ * real programs appear to depend on that. Accomplish this
+ * by passing the output as the value to return upon zero.
+ */
+ tcg_gen_ctz_tl(s->T0, s->T0, s->T1);
+}
+
+/* Non-standard convention - on entry T0 is zero-extended input, T1 is the output. */
+static void gen_BSR(DisasContext *s, X86DecodedInsn *decode)
+{
+ MemOp ot = decode->op[0].ot;
+
+ /* Only the Z bit is defined and it is related to the input. */
+ decode->cc_dst = tcg_temp_new();
+ decode->cc_op = CC_OP_LOGICB + ot;
+ tcg_gen_mov_tl(decode->cc_dst, s->T0);
+
+ /*
+ * The manual says that the output is undefined when the
+ * input is zero, but real hardware leaves it unchanged, and
+ * real programs appear to depend on that. Accomplish this
+ * by passing the output as the value to return upon zero.
+ * Plus, return the bit index of the first 1 bit.
+ */
+ tcg_gen_xori_tl(s->T1, s->T1, TARGET_LONG_BITS - 1);
+ tcg_gen_clz_tl(s->T0, s->T0, s->T1);
+ tcg_gen_xori_tl(s->T0, s->T0, TARGET_LONG_BITS - 1);
+}
+
static void gen_BSWAP(DisasContext *s, X86DecodedInsn *decode)
{
#ifdef TARGET_X86_64
@@ -2130,6 +2171,24 @@ static void gen_LSS(DisasContext *s, X86DecodedInsn *decode)
gen_lxx_seg(s, decode, R_SS);
}
+static void gen_LZCNT(DisasContext *s, X86DecodedInsn *decode)
+{
+ MemOp ot = decode->op[0].ot;
+
+ /* C bit (cc_src) is defined related to the input. */
+ decode->cc_src = tcg_temp_new();
+ decode->cc_dst = s->T0;
+ decode->cc_op = CC_OP_BMILGB + ot;
+ tcg_gen_mov_tl(decode->cc_src, s->T0);
+
+ /*
+ * Reduce the target_ulong result by the number of zeros that
+ * we expect to find at the top.
+ */
+ tcg_gen_clzi_tl(s->T0, s->T0, TARGET_LONG_BITS);
+ tcg_gen_subi_tl(s->T0, s->T0, TARGET_LONG_BITS - (8 << ot));
+}
+
static void gen_MFENCE(DisasContext *s, X86DecodedInsn *decode)
{
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
@@ -2688,6 +2747,15 @@ static void gen_POPA(DisasContext *s, X86DecodedInsn *decode)
gen_popa(s);
}
+static void gen_POPCNT(DisasContext *s, X86DecodedInsn *decode)
+{
+ decode->cc_src = tcg_temp_new();
+ decode->cc_op = CC_OP_POPCNT;
+
+ tcg_gen_mov_tl(decode->cc_src, s->T0);
+ tcg_gen_ctpop_tl(s->T0, s->T0);
+}
+
static void gen_POPF(DisasContext *s, X86DecodedInsn *decode)
{
MemOp ot;
@@ -3769,6 +3837,20 @@ static void gen_SYSRET(DisasContext *s, X86DecodedInsn *decode)
s->base.is_jmp = DISAS_EOB_RECHECK_TF;
}
+static void gen_TZCNT(DisasContext *s, X86DecodedInsn *decode)
+{
+ MemOp ot = decode->op[0].ot;
+
+ /* C bit (cc_src) is defined related to the input. */
+ decode->cc_src = tcg_temp_new();
+ decode->cc_dst = s->T0;
+ decode->cc_op = CC_OP_BMILGB + ot;
+ tcg_gen_mov_tl(decode->cc_src, s->T0);
+
+ /* A zero input returns the operand size. */
+ tcg_gen_ctzi_tl(s->T0, s->T0, 8 << ot);
+}
+
static void gen_UD(DisasContext *s, X86DecodedInsn *decode)
{
gen_illegal_opcode(s);
--
2.45.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PULL 23/25] target/i386: convert XADD to new decoder
2024-06-11 14:24 [PULL 00/25] target/i386, SCSI changes for 2024-06-11 Paolo Bonzini
` (21 preceding siblings ...)
2024-06-11 14:25 ` [PULL 22/25] target/i386: convert LZCNT/TZCNT/BSF/BSR/POPCNT " Paolo Bonzini
@ 2024-06-11 14:25 ` Paolo Bonzini
2024-06-11 14:25 ` [PULL 24/25] target/i386: convert CMPXCHG " Paolo Bonzini
` (2 subsequent siblings)
25 siblings, 0 replies; 27+ messages in thread
From: Paolo Bonzini @ 2024-06-11 14:25 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/tcg/translate.c | 35 --------------------------------
target/i386/tcg/decode-new.c.inc | 3 ++-
target/i386/tcg/emit.c.inc | 24 ++++++++++++++++++++++
3 files changed, 26 insertions(+), 36 deletions(-)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 68a11f81786..5d9312bb48c 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -823,12 +823,6 @@ static void gen_movs(DisasContext *s, MemOp ot)
gen_op_add_reg(s, s->aflag, R_EDI, dshift);
}
-static void gen_op_update2_cc(DisasContext *s)
-{
- tcg_gen_mov_tl(cpu_cc_src, s->T1);
- tcg_gen_mov_tl(cpu_cc_dst, s->T0);
-}
-
/* compute all eflags to reg */
static void gen_mov_eflags(DisasContext *s, TCGv reg)
{
@@ -3011,35 +3005,6 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b)
switch (b) {
/**************************/
/* arith & logic */
- case 0x1c0:
- case 0x1c1: /* xadd Ev, Gv */
- ot = mo_b_d(b, dflag);
- modrm = x86_ldub_code(env, s);
- reg = ((modrm >> 3) & 7) | REX_R(s);
- mod = (modrm >> 6) & 3;
- gen_op_mov_v_reg(s, ot, s->T0, reg);
- if (mod == 3) {
- rm = (modrm & 7) | REX_B(s);
- gen_op_mov_v_reg(s, ot, s->T1, rm);
- tcg_gen_add_tl(s->T0, s->T0, s->T1);
- gen_op_mov_reg_v(s, ot, reg, s->T1);
- gen_op_mov_reg_v(s, ot, rm, s->T0);
- } else {
- gen_lea_modrm(env, s, modrm);
- if (s->prefix & PREFIX_LOCK) {
- tcg_gen_atomic_fetch_add_tl(s->T1, s->A0, s->T0,
- s->mem_index, ot | MO_LE);
- tcg_gen_add_tl(s->T0, s->T0, s->T1);
- } else {
- gen_op_ld_v(s, ot, s->T1, s->A0);
- tcg_gen_add_tl(s->T0, s->T0, s->T1);
- gen_op_st_v(s, ot, s->T0, s->A0);
- }
- gen_op_mov_reg_v(s, ot, reg, s->T1);
- }
- gen_op_update2_cc(s);
- set_cc_op(s, CC_OP_ADDB + ot);
- break;
case 0x1b0:
case 0x1b1: /* cmpxchg Ev, Gv */
{
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index 15ebc1233ea..008a8387bda 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -1167,6 +1167,8 @@ static const X86OpEntry opcodes_0F[256] = {
[0xb6] = X86_OP_ENTRY3(MOV, G,v, E,b, None, None, zextT0), /* MOVZX */
[0xb7] = X86_OP_ENTRY3(MOV, G,v, E,w, None, None, zextT0), /* MOVZX */
+ [0xc0] = X86_OP_ENTRY2(XADD, E,b, G,b, lock),
+ [0xc1] = X86_OP_ENTRY2(XADD, E,v, G,v, lock),
[0xc2] = X86_OP_ENTRY4(VCMP, V,x, H,x, W,x, vex2_rep3 p_00_66_f3_f2),
[0xc3] = X86_OP_ENTRY3(MOV, EM,y,G,y, None,None, cpuid(SSE2)), /* MOVNTI */
[0xc4] = X86_OP_ENTRY4(PINSRW, V,dq,H,dq,E,w, vex5 mmx p_00_66),
@@ -2590,7 +2592,6 @@ static void disas_insn(DisasContext *s, CPUState *cpu)
case 0xb0 ... 0xb1: /* cmpxchg */
case 0xb3: /* btr */
case 0xba ... 0xbb: /* grp8, btc */
- case 0xc0 ... 0xc1: /* xadd */
case 0xc7: /* grp9 */
disas_insn_old(s, cpu, b + 0x100);
return;
diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
index 7f554ba1173..9c8fe14e286 100644
--- a/target/i386/tcg/emit.c.inc
+++ b/target/i386/tcg/emit.c.inc
@@ -4368,6 +4368,30 @@ static void gen_WRxxBASE(DisasContext *s, X86DecodedInsn *decode)
tcg_gen_mov_tl(base, s->T0);
}
+static void gen_XADD(DisasContext *s, X86DecodedInsn *decode)
+{
+ MemOp ot = decode->op[1].ot;
+
+ decode->cc_dst = tcg_temp_new();
+ decode->cc_src = s->T1;
+ decode->cc_op = CC_OP_ADDB + ot;
+
+ if (s->prefix & PREFIX_LOCK) {
+ tcg_gen_atomic_fetch_add_tl(s->T0, s->A0, s->T1, s->mem_index, ot | MO_LE);
+ tcg_gen_add_tl(decode->cc_dst, s->T0, s->T1);
+ } else {
+ tcg_gen_add_tl(decode->cc_dst, s->T0, s->T1);
+ /*
+ * NOTE: writing memory first is important for MMU exceptions,
+ * but "new result" wins for XADD AX, AX.
+ */
+ gen_writeback(s, decode, 0, decode->cc_dst);
+ }
+ if (decode->op[0].has_ea || decode->op[2].n != decode->op[0].n) {
+ gen_writeback(s, decode, 2, s->T0);
+ }
+}
+
static void gen_XCHG(DisasContext *s, X86DecodedInsn *decode)
{
if (s->prefix & PREFIX_LOCK) {
--
2.45.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PULL 24/25] target/i386: convert CMPXCHG to new decoder
2024-06-11 14:24 [PULL 00/25] target/i386, SCSI changes for 2024-06-11 Paolo Bonzini
` (22 preceding siblings ...)
2024-06-11 14:25 ` [PULL 23/25] target/i386: convert XADD " Paolo Bonzini
@ 2024-06-11 14:25 ` Paolo Bonzini
2024-06-11 14:25 ` [PULL 25/25] target/i386: SEV: do not assume machine->cgs is SEV Paolo Bonzini
2024-06-13 5:29 ` [PULL 00/25] target/i386, SCSI changes for 2024-06-11 Richard Henderson
25 siblings, 0 replies; 27+ messages in thread
From: Paolo Bonzini @ 2024-06-11 14:25 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/tcg/translate.c | 79 --------------------------------
target/i386/tcg/decode-new.c.inc | 3 +-
target/i386/tcg/emit.c.inc | 51 +++++++++++++++++++++
3 files changed, 53 insertions(+), 80 deletions(-)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 5d9312bb48c..ad1819815ab 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -434,13 +434,6 @@ static inline MemOp mo_stacksize(DisasContext *s)
return CODE64(s) ? MO_64 : SS32(s) ? MO_32 : MO_16;
}
-/* Select size 8 if lsb of B is clear, else OT. Used for decoding
- byte vs word opcodes. */
-static inline MemOp mo_b_d(int b, MemOp ot)
-{
- return b & 1 ? ot : MO_8;
-}
-
/* Compute the result of writing t0 to the OT-sized register REG.
*
* If DEST is NULL, store the result into the register and return the
@@ -715,11 +708,6 @@ static TCGv gen_ext_tl(TCGv dst, TCGv src, MemOp size, bool sign)
return dst;
}
-static void gen_extu(MemOp ot, TCGv reg)
-{
- gen_ext_tl(reg, reg, ot, false);
-}
-
static void gen_exts(MemOp ot, TCGv reg)
{
gen_ext_tl(reg, reg, ot, true);
@@ -3003,73 +2991,6 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b)
/* now check op code */
switch (b) {
- /**************************/
- /* arith & logic */
- case 0x1b0:
- case 0x1b1: /* cmpxchg Ev, Gv */
- {
- TCGv oldv, newv, cmpv, dest;
-
- ot = mo_b_d(b, dflag);
- modrm = x86_ldub_code(env, s);
- reg = ((modrm >> 3) & 7) | REX_R(s);
- mod = (modrm >> 6) & 3;
- oldv = tcg_temp_new();
- newv = tcg_temp_new();
- cmpv = tcg_temp_new();
- gen_op_mov_v_reg(s, ot, newv, reg);
- tcg_gen_mov_tl(cmpv, cpu_regs[R_EAX]);
- gen_extu(ot, cmpv);
- if (s->prefix & PREFIX_LOCK) {
- if (mod == 3) {
- goto illegal_op;
- }
- gen_lea_modrm(env, s, modrm);
- tcg_gen_atomic_cmpxchg_tl(oldv, s->A0, cmpv, newv,
- s->mem_index, ot | MO_LE);
- } else {
- if (mod == 3) {
- rm = (modrm & 7) | REX_B(s);
- gen_op_mov_v_reg(s, ot, oldv, rm);
- gen_extu(ot, oldv);
-
- /*
- * Unlike the memory case, where "the destination operand receives
- * a write cycle without regard to the result of the comparison",
- * rm must not be touched altogether if the write fails, including
- * not zero-extending it on 64-bit processors. So, precompute
- * the result of a successful writeback and perform the movcond
- * directly on cpu_regs. Also need to write accumulator first, in
- * case rm is part of RAX too.
- */
- dest = gen_op_deposit_reg_v(s, ot, rm, newv, newv);
- tcg_gen_movcond_tl(TCG_COND_EQ, dest, oldv, cmpv, newv, dest);
- } else {
- gen_lea_modrm(env, s, modrm);
- gen_op_ld_v(s, ot, oldv, s->A0);
-
- /*
- * Perform an unconditional store cycle like physical cpu;
- * must be before changing accumulator to ensure
- * idempotency if the store faults and the instruction
- * is restarted
- */
- tcg_gen_movcond_tl(TCG_COND_EQ, newv, oldv, cmpv, newv, oldv);
- gen_op_st_v(s, ot, newv, s->A0);
- }
- }
- /*
- * Write EAX only if the cmpxchg fails; reuse newv as the destination,
- * since it's dead here.
- */
- dest = gen_op_deposit_reg_v(s, ot, R_EAX, newv, oldv);
- tcg_gen_movcond_tl(TCG_COND_EQ, dest, oldv, cmpv, dest, newv);
- tcg_gen_mov_tl(cpu_cc_src, oldv);
- tcg_gen_mov_tl(s->cc_srcT, cmpv);
- tcg_gen_sub_tl(cpu_cc_dst, cmpv, oldv);
- set_cc_op(s, CC_OP_SUBB + ot);
- }
- break;
case 0x1c7: /* cmpxchg8b */
modrm = x86_ldub_code(env, s);
mod = (modrm >> 6) & 3;
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index 008a8387bda..d199f2d4b6f 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -1161,6 +1161,8 @@ static const X86OpEntry opcodes_0F[256] = {
[0xa4] = X86_OP_ENTRY4(SHLD, E,v, 2op,v, G,v),
[0xa5] = X86_OP_ENTRY3(SHLD, E,v, 2op,v, G,v),
+ [0xb0] = X86_OP_ENTRY2(CMPXCHG,E,b, G,b, lock),
+ [0xb1] = X86_OP_ENTRY2(CMPXCHG,E,v, G,v, lock),
[0xb2] = X86_OP_ENTRY3(LSS, G,v, EM,p, None, None),
[0xb4] = X86_OP_ENTRY3(LFS, G,v, EM,p, None, None),
[0xb5] = X86_OP_ENTRY3(LGS, G,v, EM,p, None, None),
@@ -2589,7 +2591,6 @@ static void disas_insn(DisasContext *s, CPUState *cpu)
case 0x1a ... 0x1b: /* MPX */
case 0xa3: /* bt */
case 0xab: /* bts */
- case 0xb0 ... 0xb1: /* cmpxchg */
case 0xb3: /* btr */
case 0xba ... 0xbb: /* grp8, btc */
case 0xc7: /* grp9 */
diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
index 9c8fe14e286..aa026ed1fd9 100644
--- a/target/i386/tcg/emit.c.inc
+++ b/target/i386/tcg/emit.c.inc
@@ -1582,6 +1582,57 @@ static void gen_CMPS(DisasContext *s, X86DecodedInsn *decode)
}
}
+static void gen_CMPXCHG(DisasContext *s, X86DecodedInsn *decode)
+{
+ MemOp ot = decode->op[2].ot;
+ TCGv cmpv = tcg_temp_new();
+ TCGv oldv = tcg_temp_new();
+ TCGv newv = tcg_temp_new();
+ TCGv dest;
+
+ tcg_gen_ext_tl(cmpv, cpu_regs[R_EAX], ot);
+ tcg_gen_ext_tl(newv, s->T1, ot);
+ if (s->prefix & PREFIX_LOCK) {
+ tcg_gen_atomic_cmpxchg_tl(oldv, s->A0, cmpv, newv,
+ s->mem_index, ot | MO_LE);
+ } else {
+ tcg_gen_ext_tl(oldv, s->T0, ot);
+ if (decode->op[0].has_ea) {
+ /*
+ * Perform an unconditional store cycle like physical cpu;
+ * must be before changing accumulator to ensure
+ * idempotency if the store faults and the instruction
+ * is restarted
+ */
+ tcg_gen_movcond_tl(TCG_COND_EQ, newv, oldv, cmpv, newv, oldv);
+ gen_op_st_v(s, ot, newv, s->A0);
+ } else {
+ /*
+ * Unlike the memory case, where "the destination operand receives
+ * a write cycle without regard to the result of the comparison",
+ * rm must not be touched altogether if the write fails, including
+ * not zero-extending it on 64-bit processors. So, precompute
+ * the result of a successful writeback and perform the movcond
+ * directly on cpu_regs. In case rm is part of RAX, note that this
+ * movcond and the one below are mutually exclusive is executed.
+ */
+ dest = gen_op_deposit_reg_v(s, ot, decode->op[0].n, newv, newv);
+ tcg_gen_movcond_tl(TCG_COND_EQ, dest, oldv, cmpv, newv, dest);
+ }
+ decode->op[0].unit = X86_OP_SKIP;
+ }
+
+ /* Write RAX only if the cmpxchg fails. */
+ dest = gen_op_deposit_reg_v(s, ot, R_EAX, s->T0, oldv);
+ tcg_gen_movcond_tl(TCG_COND_NE, dest, oldv, cmpv, s->T0, dest);
+
+ tcg_gen_mov_tl(s->cc_srcT, cmpv);
+ tcg_gen_sub_tl(cmpv, cmpv, oldv);
+ decode->cc_dst = cmpv;
+ decode->cc_src = oldv;
+ decode->cc_op = CC_OP_SUBB + ot;
+}
+
static void gen_CPUID(DisasContext *s, X86DecodedInsn *decode)
{
gen_update_cc_op(s);
--
2.45.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PULL 25/25] target/i386: SEV: do not assume machine->cgs is SEV
2024-06-11 14:24 [PULL 00/25] target/i386, SCSI changes for 2024-06-11 Paolo Bonzini
` (23 preceding siblings ...)
2024-06-11 14:25 ` [PULL 24/25] target/i386: convert CMPXCHG " Paolo Bonzini
@ 2024-06-11 14:25 ` Paolo Bonzini
2024-06-13 5:29 ` [PULL 00/25] target/i386, SCSI changes for 2024-06-11 Richard Henderson
25 siblings, 0 replies; 27+ messages in thread
From: Paolo Bonzini @ 2024-06-11 14:25 UTC (permalink / raw)
To: qemu-devel
There can be other confidential computing classes that are not derived
from sev-common. Avoid aborting when encountering them.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/sev.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/target/i386/sev.c b/target/i386/sev.c
index c40562dce31..30b83f1d77d 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -1712,7 +1712,9 @@ void sev_es_set_reset_vector(CPUState *cpu)
{
X86CPU *x86;
CPUX86State *env;
- SevCommonState *sev_common = SEV_COMMON(MACHINE(qdev_get_machine())->cgs);
+ ConfidentialGuestSupport *cgs = MACHINE(qdev_get_machine())->cgs;
+ SevCommonState *sev_common = SEV_COMMON(
+ object_dynamic_cast(OBJECT(cgs), TYPE_SEV_COMMON));
/* Only update if we have valid reset information */
if (!sev_common || !sev_common->reset_data_valid) {
--
2.45.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* Re: [PULL 00/25] target/i386, SCSI changes for 2024-06-11
2024-06-11 14:24 [PULL 00/25] target/i386, SCSI changes for 2024-06-11 Paolo Bonzini
` (24 preceding siblings ...)
2024-06-11 14:25 ` [PULL 25/25] target/i386: SEV: do not assume machine->cgs is SEV Paolo Bonzini
@ 2024-06-13 5:29 ` Richard Henderson
25 siblings, 0 replies; 27+ messages in thread
From: Richard Henderson @ 2024-06-13 5:29 UTC (permalink / raw)
To: Paolo Bonzini, qemu-devel
On 6/11/24 07:24, Paolo Bonzini wrote:
> The following changes since commit 80e8f0602168f451a93e71cbb1d59e93d745e62e:
>
> Merge tag 'bsd-user-misc-2024q2-pull-request' of gitlab.com:bsdimp/qemu into staging (2024-06-09 11:21:55 -0700)
>
> are available in the Git repository at:
>
> https://gitlab.com/bonzini/qemu.git tags/for-upstream
>
> for you to fetch changes up to 58ab5e809ad66a02b6fa273ba11ed35b8b2fea60:
>
> target/i386: SEV: do not assume machine->cgs is SEV (2024-06-11 14:29:23 +0200)
>
> ----------------------------------------------------------------
> * i386: fix issue with cache topology passthrough
> * scsi-disk: migrate emulated requests
> * i386/sev: fix Coverity issues
> * i386/tcg: more conversions to new decoder
Fails testing:
https://gitlab.com/qemu-project/qemu/-/jobs/7087568710
https://gitlab.com/qemu-project/qemu/-/jobs/7087568705
https://gitlab.com/qemu-project/qemu/-/jobs/7087568701
https://gitlab.com/qemu-project/qemu/-/jobs/7087568694
r~
^ permalink raw reply [flat|nested] 27+ messages in thread