* SCSI fixes for Mac OS 9
* Fix CPU reset for x86/KVM nested virtualization state * remove feature_not_found() from the configure script * Meson cleanups from muon * improved i386 TCG tests for BMI and SSE * SSE bugfixes -----BEGIN PGP SIGNATURE----- iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmMQ+IQUHHBib256aW5p QHJlZGhhdC5jb20ACgkQv/vSX3jHroNofQgArLRlbhua699UyDkTEGGv+gBVRRKg qJndTFJp5cvjJo3fNeE1XyZGY0PGLH09ilwHKnGqvn7Bc996ty6zi3sLDC+iT/SO cRik6EVgZH/0QseYZijviuz7NklL8so/bgn7sORP9ibRWwiojBzm91emUt4X2l5N WOmxLYNIPXR/G8LOSv5Dh4C4WXU3zuaLvTmg/fWPoWTF8P+9LU0gEKUzyk0jMJu4 hb9lVLXyNbgEcdtK+VewWjsdJcdmF1tMAR94GTmbUdwxbwmATqX8w16jGUbnXPt2 FZfmjS6CJO90uV7wBA91NnFlrJpWyDn1dKQ+ozpW0ZOAO+wfghpVq7/IRA== =VRK4 -----END PGP SIGNATURE----- Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging * SCSI fixes for Mac OS 9 * Fix CPU reset for x86/KVM nested virtualization state * remove feature_not_found() from the configure script * Meson cleanups from muon * improved i386 TCG tests for BMI and SSE * SSE bugfixes # -----BEGIN PGP SIGNATURE----- # # iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmMQ+IQUHHBib256aW5p # QHJlZGhhdC5jb20ACgkQv/vSX3jHroNofQgArLRlbhua699UyDkTEGGv+gBVRRKg # qJndTFJp5cvjJo3fNeE1XyZGY0PGLH09ilwHKnGqvn7Bc996ty6zi3sLDC+iT/SO # cRik6EVgZH/0QseYZijviuz7NklL8so/bgn7sORP9ibRWwiojBzm91emUt4X2l5N # WOmxLYNIPXR/G8LOSv5Dh4C4WXU3zuaLvTmg/fWPoWTF8P+9LU0gEKUzyk0jMJu4 # hb9lVLXyNbgEcdtK+VewWjsdJcdmF1tMAR94GTmbUdwxbwmATqX8w16jGUbnXPt2 # FZfmjS6CJO90uV7wBA91NnFlrJpWyDn1dKQ+ozpW0ZOAO+wfghpVq7/IRA== # =VRK4 # -----END PGP SIGNATURE----- # gpg: Signature made Thu 01 Sep 2022 14:23:00 EDT # gpg: using RSA key F13338574B662389866C7682BFFBD25F78C7AE83 # gpg: issuer "pbonzini@redhat.com" # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full] # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" [full] # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * tag 'for-upstream' of https://gitlab.com/bonzini/qemu: (39 commits) target/i386: AVX+AES helpers prep target/i386: AVX pclmulqdq prep target/i386: Rewrite blendv helpers target/i386: Misc AVX helper prep target/i386: Destructive FP helpers for AVX target/i386: Dot product AVX helper prep target/i386: reimplement AVX comparison helpers target/i386: Floating point arithmetic helper AVX prep target/i386: Destructive vector helpers for AVX target/i386: Misc integer AVX helper prep target/i386: Rewrite simple integer vector helpers target/i386: Rewrite vector shift helper target/i386: rewrite destructive 3DNow operations target/i386: Add CHECK_NO_VEX target/i386: do not cast gen_helper_* function pointers target/i386: Add size suffix to vector FP helpers target/i386: isolate MMX code more target/i386: check SSE table flags instead of hardcoding opcodes target/i386: Move 3DNOW decoder target/i386: Rework sse_op_table6/7 ... Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
commit
61fd710b8d
@ -719,7 +719,11 @@ static void kvm_dirty_ring_mark_page(KVMState *s, uint32_t as_id,
|
|||||||
|
|
||||||
static bool dirty_gfn_is_dirtied(struct kvm_dirty_gfn *gfn)
|
static bool dirty_gfn_is_dirtied(struct kvm_dirty_gfn *gfn)
|
||||||
{
|
{
|
||||||
return gfn->flags == KVM_DIRTY_GFN_F_DIRTY;
|
/*
|
||||||
|
* Read the flags before the value. Pairs with barrier in
|
||||||
|
* KVM's kvm_dirty_ring_push() function.
|
||||||
|
*/
|
||||||
|
return qatomic_load_acquire(&gfn->flags) == KVM_DIRTY_GFN_F_DIRTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dirty_gfn_set_collected(struct kvm_dirty_gfn *gfn)
|
static void dirty_gfn_set_collected(struct kvm_dirty_gfn *gfn)
|
||||||
|
11
configure
vendored
11
configure
vendored
@ -1468,15 +1468,6 @@ if test "$tcg" = "enabled"; then
|
|||||||
git_submodules="$git_submodules tests/fp/berkeley-softfloat-3"
|
git_submodules="$git_submodules tests/fp/berkeley-softfloat-3"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
feature_not_found() {
|
|
||||||
feature=$1
|
|
||||||
remedy=$2
|
|
||||||
|
|
||||||
error_exit "User requested feature $feature" \
|
|
||||||
"configure was not able to find it." \
|
|
||||||
"$remedy"
|
|
||||||
}
|
|
||||||
|
|
||||||
# ---
|
# ---
|
||||||
# big/little endian test
|
# big/little endian test
|
||||||
cat > $TMPC << EOF
|
cat > $TMPC << EOF
|
||||||
@ -1639,7 +1630,7 @@ else
|
|||||||
;;
|
;;
|
||||||
ucontext)
|
ucontext)
|
||||||
if test "$ucontext_works" != "yes"; then
|
if test "$ucontext_works" != "yes"; then
|
||||||
feature_not_found "ucontext"
|
error_exit "'ucontext' backend requested but makecontext not available"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
sigaltstack)
|
sigaltstack)
|
||||||
|
@ -99,11 +99,6 @@ developers in checking for system features:
|
|||||||
Write a minimal C program main() function to the temporary file
|
Write a minimal C program main() function to the temporary file
|
||||||
indicated by $TMPC
|
indicated by $TMPC
|
||||||
|
|
||||||
``feature_not_found $NAME $REMEDY``
|
|
||||||
Print a message to stderr that the feature $NAME was not available
|
|
||||||
on the system, suggesting the user try $REMEDY to address the
|
|
||||||
problem.
|
|
||||||
|
|
||||||
``error_exit $MESSAGE $MORE...``
|
``error_exit $MESSAGE $MORE...``
|
||||||
Print $MESSAGE to stderr, followed by $MORE... and then exit from the
|
Print $MESSAGE to stderr, followed by $MORE... and then exit from the
|
||||||
configure script with non-zero status
|
configure script with non-zero status
|
||||||
|
@ -292,7 +292,7 @@ static void do_command_phase(ESPState *s)
|
|||||||
esp_fifo_pop_buf(&s->cmdfifo, buf, cmdlen);
|
esp_fifo_pop_buf(&s->cmdfifo, buf, cmdlen);
|
||||||
|
|
||||||
current_lun = scsi_device_find(&s->bus, 0, s->current_dev->id, s->lun);
|
current_lun = scsi_device_find(&s->bus, 0, s->current_dev->id, s->lun);
|
||||||
s->current_req = scsi_req_new(current_lun, 0, s->lun, buf, s);
|
s->current_req = scsi_req_new(current_lun, 0, s->lun, buf, cmdlen, s);
|
||||||
datalen = scsi_req_enqueue(s->current_req);
|
datalen = scsi_req_enqueue(s->current_req);
|
||||||
s->ti_size = datalen;
|
s->ti_size = datalen;
|
||||||
fifo8_reset(&s->cmdfifo);
|
fifo8_reset(&s->cmdfifo);
|
||||||
@ -939,6 +939,11 @@ static void esp_soft_reset(ESPState *s)
|
|||||||
esp_hard_reset(s);
|
esp_hard_reset(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void esp_bus_reset(ESPState *s)
|
||||||
|
{
|
||||||
|
qbus_reset_all(BUS(&s->bus));
|
||||||
|
}
|
||||||
|
|
||||||
static void parent_esp_reset(ESPState *s, int irq, int level)
|
static void parent_esp_reset(ESPState *s, int irq, int level)
|
||||||
{
|
{
|
||||||
if (level) {
|
if (level) {
|
||||||
@ -1067,6 +1072,7 @@ void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val)
|
|||||||
break;
|
break;
|
||||||
case CMD_BUSRESET:
|
case CMD_BUSRESET:
|
||||||
trace_esp_mem_writeb_cmd_bus_reset(val);
|
trace_esp_mem_writeb_cmd_bus_reset(val);
|
||||||
|
esp_bus_reset(s);
|
||||||
if (!(s->wregs[ESP_CFG1] & CFG1_RESREPT)) {
|
if (!(s->wregs[ESP_CFG1] & CFG1_RESREPT)) {
|
||||||
s->rregs[ESP_RINTR] |= INTR_RST;
|
s->rregs[ESP_RINTR] |= INTR_RST;
|
||||||
esp_raise_irq(s);
|
esp_raise_irq(s);
|
||||||
|
@ -864,7 +864,7 @@ static void lsi_do_command(LSIState *s)
|
|||||||
s->current = g_new0(lsi_request, 1);
|
s->current = g_new0(lsi_request, 1);
|
||||||
s->current->tag = s->select_tag;
|
s->current->tag = s->select_tag;
|
||||||
s->current->req = scsi_req_new(dev, s->current->tag, s->current_lun, buf,
|
s->current->req = scsi_req_new(dev, s->current->tag, s->current_lun, buf,
|
||||||
s->current);
|
s->dbc, s->current);
|
||||||
|
|
||||||
n = scsi_req_enqueue(s->current->req);
|
n = scsi_req_enqueue(s->current->req);
|
||||||
if (n) {
|
if (n) {
|
||||||
|
@ -1062,7 +1062,7 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev, int lun,
|
|||||||
info->inquiry_data[0] = 0x7f; /* Force PQual 0x3, PType 0x1f */
|
info->inquiry_data[0] = 0x7f; /* Force PQual 0x3, PType 0x1f */
|
||||||
info->vpd_page83[0] = 0x7f;
|
info->vpd_page83[0] = 0x7f;
|
||||||
megasas_setup_inquiry(cmdbuf, 0, sizeof(info->inquiry_data));
|
megasas_setup_inquiry(cmdbuf, 0, sizeof(info->inquiry_data));
|
||||||
cmd->req = scsi_req_new(sdev, cmd->index, lun, cmdbuf, cmd);
|
cmd->req = scsi_req_new(sdev, cmd->index, lun, cmdbuf, sizeof(cmdbuf), cmd);
|
||||||
if (!cmd->req) {
|
if (!cmd->req) {
|
||||||
trace_megasas_dcmd_req_alloc_failed(cmd->index,
|
trace_megasas_dcmd_req_alloc_failed(cmd->index,
|
||||||
"PD get info std inquiry");
|
"PD get info std inquiry");
|
||||||
@ -1080,7 +1080,7 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev, int lun,
|
|||||||
return MFI_STAT_INVALID_STATUS;
|
return MFI_STAT_INVALID_STATUS;
|
||||||
} else if (info->inquiry_data[0] != 0x7f && info->vpd_page83[0] == 0x7f) {
|
} else if (info->inquiry_data[0] != 0x7f && info->vpd_page83[0] == 0x7f) {
|
||||||
megasas_setup_inquiry(cmdbuf, 0x83, sizeof(info->vpd_page83));
|
megasas_setup_inquiry(cmdbuf, 0x83, sizeof(info->vpd_page83));
|
||||||
cmd->req = scsi_req_new(sdev, cmd->index, lun, cmdbuf, cmd);
|
cmd->req = scsi_req_new(sdev, cmd->index, lun, cmdbuf, sizeof(cmdbuf), cmd);
|
||||||
if (!cmd->req) {
|
if (!cmd->req) {
|
||||||
trace_megasas_dcmd_req_alloc_failed(cmd->index,
|
trace_megasas_dcmd_req_alloc_failed(cmd->index,
|
||||||
"PD get info vpd inquiry");
|
"PD get info vpd inquiry");
|
||||||
@ -1268,7 +1268,7 @@ static int megasas_ld_get_info_submit(SCSIDevice *sdev, int lun,
|
|||||||
cmd->iov_buf = g_malloc0(dcmd_size);
|
cmd->iov_buf = g_malloc0(dcmd_size);
|
||||||
info = cmd->iov_buf;
|
info = cmd->iov_buf;
|
||||||
megasas_setup_inquiry(cdb, 0x83, sizeof(info->vpd_page83));
|
megasas_setup_inquiry(cdb, 0x83, sizeof(info->vpd_page83));
|
||||||
cmd->req = scsi_req_new(sdev, cmd->index, lun, cdb, cmd);
|
cmd->req = scsi_req_new(sdev, cmd->index, lun, cdb, sizeof(cdb), cmd);
|
||||||
if (!cmd->req) {
|
if (!cmd->req) {
|
||||||
trace_megasas_dcmd_req_alloc_failed(cmd->index,
|
trace_megasas_dcmd_req_alloc_failed(cmd->index,
|
||||||
"LD get info vpd inquiry");
|
"LD get info vpd inquiry");
|
||||||
@ -1748,7 +1748,7 @@ static int megasas_handle_scsi(MegasasState *s, MegasasCmd *cmd,
|
|||||||
return MFI_STAT_SCSI_DONE_WITH_ERROR;
|
return MFI_STAT_SCSI_DONE_WITH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd->req = scsi_req_new(sdev, cmd->index, lun_id, cdb, cmd);
|
cmd->req = scsi_req_new(sdev, cmd->index, lun_id, cdb, cdb_len, cmd);
|
||||||
if (!cmd->req) {
|
if (!cmd->req) {
|
||||||
trace_megasas_scsi_req_alloc_failed(
|
trace_megasas_scsi_req_alloc_failed(
|
||||||
mfi_frame_desc(frame_cmd), target_id, lun_id);
|
mfi_frame_desc(frame_cmd), target_id, lun_id);
|
||||||
@ -1823,7 +1823,7 @@ static int megasas_handle_io(MegasasState *s, MegasasCmd *cmd, int frame_cmd)
|
|||||||
|
|
||||||
megasas_encode_lba(cdb, lba_start, lba_count, is_write);
|
megasas_encode_lba(cdb, lba_start, lba_count, is_write);
|
||||||
cmd->req = scsi_req_new(sdev, cmd->index,
|
cmd->req = scsi_req_new(sdev, cmd->index,
|
||||||
lun_id, cdb, cmd);
|
lun_id, cdb, cdb_len, cmd);
|
||||||
if (!cmd->req) {
|
if (!cmd->req) {
|
||||||
trace_megasas_scsi_req_alloc_failed(
|
trace_megasas_scsi_req_alloc_failed(
|
||||||
mfi_frame_desc(frame_cmd), target_id, lun_id);
|
mfi_frame_desc(frame_cmd), target_id, lun_id);
|
||||||
|
@ -324,7 +324,8 @@ static int mptsas_process_scsi_io_request(MPTSASState *s,
|
|||||||
}
|
}
|
||||||
|
|
||||||
req->sreq = scsi_req_new(sdev, scsi_io->MsgContext,
|
req->sreq = scsi_req_new(sdev, scsi_io->MsgContext,
|
||||||
scsi_io->LUN[1], scsi_io->CDB, req);
|
scsi_io->LUN[1], scsi_io->CDB,
|
||||||
|
scsi_io->CDBLength, req);
|
||||||
|
|
||||||
if (req->sreq->cmd.xfer > scsi_io->DataLength) {
|
if (req->sreq->cmd.xfer > scsi_io->DataLength) {
|
||||||
goto overrun;
|
goto overrun;
|
||||||
|
@ -102,15 +102,15 @@ static void scsi_device_unrealize(SCSIDevice *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int scsi_bus_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
|
int scsi_bus_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
|
||||||
void *hba_private)
|
size_t buf_len, void *hba_private)
|
||||||
{
|
{
|
||||||
SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, dev->qdev.parent_bus);
|
SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, dev->qdev.parent_bus);
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
assert(cmd->len == 0);
|
assert(cmd->len == 0);
|
||||||
rc = scsi_req_parse_cdb(dev, cmd, buf);
|
rc = scsi_req_parse_cdb(dev, cmd, buf, buf_len);
|
||||||
if (bus->info->parse_cdb) {
|
if (bus->info->parse_cdb) {
|
||||||
rc = bus->info->parse_cdb(dev, cmd, buf, hba_private);
|
rc = bus->info->parse_cdb(dev, cmd, buf, buf_len, hba_private);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -703,7 +703,7 @@ SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
|
|||||||
}
|
}
|
||||||
|
|
||||||
SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
|
SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
|
||||||
uint8_t *buf, void *hba_private)
|
uint8_t *buf, size_t buf_len, void *hba_private)
|
||||||
{
|
{
|
||||||
SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, d->qdev.parent_bus);
|
SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, d->qdev.parent_bus);
|
||||||
const SCSIReqOps *ops;
|
const SCSIReqOps *ops;
|
||||||
@ -712,6 +712,11 @@ SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
|
|||||||
SCSICommand cmd = { .len = 0 };
|
SCSICommand cmd = { .len = 0 };
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (buf_len == 0) {
|
||||||
|
trace_scsi_req_parse_bad(d->id, lun, tag, 0);
|
||||||
|
goto invalid_opcode;
|
||||||
|
}
|
||||||
|
|
||||||
if ((d->unit_attention.key == UNIT_ATTENTION ||
|
if ((d->unit_attention.key == UNIT_ATTENTION ||
|
||||||
bus->unit_attention.key == UNIT_ATTENTION) &&
|
bus->unit_attention.key == UNIT_ATTENTION) &&
|
||||||
(buf[0] != INQUIRY &&
|
(buf[0] != INQUIRY &&
|
||||||
@ -734,13 +739,14 @@ SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ops != NULL || !sc->parse_cdb) {
|
if (ops != NULL || !sc->parse_cdb) {
|
||||||
ret = scsi_req_parse_cdb(d, &cmd, buf);
|
ret = scsi_req_parse_cdb(d, &cmd, buf, buf_len);
|
||||||
} else {
|
} else {
|
||||||
ret = sc->parse_cdb(d, &cmd, buf, hba_private);
|
ret = sc->parse_cdb(d, &cmd, buf, buf_len, hba_private);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
trace_scsi_req_parse_bad(d->id, lun, tag, buf[0]);
|
trace_scsi_req_parse_bad(d->id, lun, tag, buf[0]);
|
||||||
|
invalid_opcode:
|
||||||
req = scsi_req_alloc(&reqops_invalid_opcode, d, tag, lun, hba_private);
|
req = scsi_req_alloc(&reqops_invalid_opcode, d, tag, lun, hba_private);
|
||||||
} else {
|
} else {
|
||||||
assert(cmd.len != 0);
|
assert(cmd.len != 0);
|
||||||
@ -1308,14 +1314,15 @@ static void scsi_cmd_xfer_mode(SCSICommand *cmd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int scsi_req_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf)
|
int scsi_req_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
|
||||||
|
size_t buf_len)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
cmd->lba = -1;
|
cmd->lba = -1;
|
||||||
len = scsi_cdb_length(buf);
|
len = scsi_cdb_length(buf);
|
||||||
if (len < 0) {
|
if (len < 0 || len > buf_len) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1713,7 +1720,11 @@ static int get_scsi_requests(QEMUFile *f, void *pv, size_t size,
|
|||||||
qemu_get_buffer(f, buf, sizeof(buf));
|
qemu_get_buffer(f, buf, sizeof(buf));
|
||||||
qemu_get_be32s(f, &tag);
|
qemu_get_be32s(f, &tag);
|
||||||
qemu_get_be32s(f, &lun);
|
qemu_get_be32s(f, &lun);
|
||||||
req = scsi_req_new(s, tag, lun, buf, NULL);
|
/*
|
||||||
|
* A too-short CDB would have been rejected by scsi_req_new, so just use
|
||||||
|
* SCSI_CMD_BUF_SIZE as the CDB length.
|
||||||
|
*/
|
||||||
|
req = scsi_req_new(s, tag, lun, buf, sizeof(buf), NULL);
|
||||||
req->retry = (sbyte == 1);
|
req->retry = (sbyte == 1);
|
||||||
if (bus->info->load_request) {
|
if (bus->info->load_request) {
|
||||||
req->hba_private = bus->info->load_request(f, req);
|
req->hba_private = bus->info->load_request(f, req);
|
||||||
|
@ -3030,14 +3030,15 @@ static SCSIRequest *scsi_block_new_request(SCSIDevice *d, uint32_t tag,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int scsi_block_parse_cdb(SCSIDevice *d, SCSICommand *cmd,
|
static int scsi_block_parse_cdb(SCSIDevice *d, SCSICommand *cmd,
|
||||||
uint8_t *buf, void *hba_private)
|
uint8_t *buf, size_t buf_len,
|
||||||
|
void *hba_private)
|
||||||
{
|
{
|
||||||
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
|
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
|
||||||
|
|
||||||
if (scsi_block_is_passthrough(s, buf)) {
|
if (scsi_block_is_passthrough(s, buf)) {
|
||||||
return scsi_bus_parse_cdb(&s->qdev, cmd, buf, hba_private);
|
return scsi_bus_parse_cdb(&s->qdev, cmd, buf, buf_len, hba_private);
|
||||||
} else {
|
} else {
|
||||||
return scsi_req_parse_cdb(&s->qdev, cmd, buf);
|
return scsi_req_parse_cdb(&s->qdev, cmd, buf, buf_len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -791,9 +791,10 @@ static Property scsi_generic_properties[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static int scsi_generic_parse_cdb(SCSIDevice *dev, SCSICommand *cmd,
|
static int scsi_generic_parse_cdb(SCSIDevice *dev, SCSICommand *cmd,
|
||||||
uint8_t *buf, void *hba_private)
|
uint8_t *buf, size_t buf_len,
|
||||||
|
void *hba_private)
|
||||||
{
|
{
|
||||||
return scsi_bus_parse_cdb(dev, cmd, buf, hba_private);
|
return scsi_bus_parse_cdb(dev, cmd, buf, buf_len, hba_private);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scsi_generic_class_initfn(ObjectClass *klass, void *data)
|
static void scsi_generic_class_initfn(ObjectClass *klass, void *data)
|
||||||
|
@ -783,6 +783,7 @@ static int vscsi_queue_cmd(VSCSIState *s, vscsi_req *req)
|
|||||||
union srp_iu *srp = &req_iu(req)->srp;
|
union srp_iu *srp = &req_iu(req)->srp;
|
||||||
SCSIDevice *sdev;
|
SCSIDevice *sdev;
|
||||||
int n, lun;
|
int n, lun;
|
||||||
|
size_t cdb_len = sizeof (srp->cmd.cdb) + (srp->cmd.add_cdb_len & ~3);
|
||||||
|
|
||||||
if ((srp->cmd.lun == 0 || be64_to_cpu(srp->cmd.lun) == SRP_REPORT_LUNS_WLUN)
|
if ((srp->cmd.lun == 0 || be64_to_cpu(srp->cmd.lun) == SRP_REPORT_LUNS_WLUN)
|
||||||
&& srp->cmd.cdb[0] == REPORT_LUNS) {
|
&& srp->cmd.cdb[0] == REPORT_LUNS) {
|
||||||
@ -801,7 +802,7 @@ static int vscsi_queue_cmd(VSCSIState *s, vscsi_req *req)
|
|||||||
} return 1;
|
} return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
req->sreq = scsi_req_new(sdev, req->qtag, lun, srp->cmd.cdb, req);
|
req->sreq = scsi_req_new(sdev, req->qtag, lun, srp->cmd.cdb, cdb_len, req);
|
||||||
n = scsi_req_enqueue(req->sreq);
|
n = scsi_req_enqueue(req->sreq);
|
||||||
|
|
||||||
trace_spapr_vscsi_queue_cmd(req->qtag, srp->cmd.cdb[0],
|
trace_spapr_vscsi_queue_cmd(req->qtag, srp->cmd.cdb[0],
|
||||||
|
@ -622,7 +622,8 @@ static void virtio_scsi_command_complete(SCSIRequest *r, size_t resid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int virtio_scsi_parse_cdb(SCSIDevice *dev, SCSICommand *cmd,
|
static int virtio_scsi_parse_cdb(SCSIDevice *dev, SCSICommand *cmd,
|
||||||
uint8_t *buf, void *hba_private)
|
uint8_t *buf, size_t buf_len,
|
||||||
|
void *hba_private)
|
||||||
{
|
{
|
||||||
VirtIOSCSIReq *req = hba_private;
|
VirtIOSCSIReq *req = hba_private;
|
||||||
|
|
||||||
@ -696,7 +697,7 @@ static int virtio_scsi_handle_cmd_req_prepare(VirtIOSCSI *s, VirtIOSCSIReq *req)
|
|||||||
virtio_scsi_ctx_check(s, d);
|
virtio_scsi_ctx_check(s, d);
|
||||||
req->sreq = scsi_req_new(d, req->req.cmd.tag,
|
req->sreq = scsi_req_new(d, req->req.cmd.tag,
|
||||||
virtio_scsi_get_lun(req->req.cmd.lun),
|
virtio_scsi_get_lun(req->req.cmd.lun),
|
||||||
req->req.cmd.cdb, req);
|
req->req.cmd.cdb, vs->cdb_size, req);
|
||||||
|
|
||||||
if (req->sreq->cmd.mode != SCSI_XFER_NONE
|
if (req->sreq->cmd.mode != SCSI_XFER_NONE
|
||||||
&& (req->sreq->cmd.mode != req->mode ||
|
&& (req->sreq->cmd.mode != req->mode ||
|
||||||
|
@ -730,7 +730,7 @@ pvscsi_process_request_descriptor(PVSCSIState *s,
|
|||||||
r->sg.elemAddr = descr->dataAddr;
|
r->sg.elemAddr = descr->dataAddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
r->sreq = scsi_req_new(d, descr->context, r->lun, descr->cdb, r);
|
r->sreq = scsi_req_new(d, descr->context, r->lun, descr->cdb, descr->cdbLen, r);
|
||||||
if (r->sreq->cmd.mode == SCSI_XFER_FROM_DEV &&
|
if (r->sreq->cmd.mode == SCSI_XFER_FROM_DEV &&
|
||||||
(descr->flags & PVSCSI_FLAG_CMD_DIR_TODEVICE)) {
|
(descr->flags & PVSCSI_FLAG_CMD_DIR_TODEVICE)) {
|
||||||
r->cmp.hostStatus = BTSTAT_BADMSG;
|
r->cmp.hostStatus = BTSTAT_BADMSG;
|
||||||
|
@ -415,7 +415,7 @@ static void usb_msd_handle_data(USBDevice *dev, USBPacket *p)
|
|||||||
cbw.cmd_len, s->data_len);
|
cbw.cmd_len, s->data_len);
|
||||||
assert(le32_to_cpu(s->csw.residue) == 0);
|
assert(le32_to_cpu(s->csw.residue) == 0);
|
||||||
s->scsi_len = 0;
|
s->scsi_len = 0;
|
||||||
s->req = scsi_req_new(scsi_dev, tag, cbw.lun, cbw.cmd, NULL);
|
s->req = scsi_req_new(scsi_dev, tag, cbw.lun, cbw.cmd, cbw.cmd_len, NULL);
|
||||||
if (s->commandlog) {
|
if (s->commandlog) {
|
||||||
scsi_req_print(s->req);
|
scsi_req_print(s->req);
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ typedef struct {
|
|||||||
uint8_t reserved_2;
|
uint8_t reserved_2;
|
||||||
uint64_t lun;
|
uint64_t lun;
|
||||||
uint8_t cdb[16];
|
uint8_t cdb[16];
|
||||||
uint8_t add_cdb[1]; /* not supported by QEMU */
|
uint8_t add_cdb[1];
|
||||||
} QEMU_PACKED uas_iu_command;
|
} QEMU_PACKED uas_iu_command;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -699,6 +699,7 @@ static void usb_uas_command(UASDevice *uas, uas_iu *iu)
|
|||||||
UASRequest *req;
|
UASRequest *req;
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
uint16_t tag = be16_to_cpu(iu->hdr.tag);
|
uint16_t tag = be16_to_cpu(iu->hdr.tag);
|
||||||
|
size_t cdb_len = sizeof(iu->command.cdb) + iu->command.add_cdb_length;
|
||||||
|
|
||||||
if (iu->command.add_cdb_length > 0) {
|
if (iu->command.add_cdb_length > 0) {
|
||||||
qemu_log_mask(LOG_UNIMP, "additional adb length not yet supported\n");
|
qemu_log_mask(LOG_UNIMP, "additional adb length not yet supported\n");
|
||||||
@ -729,7 +730,7 @@ static void usb_uas_command(UASDevice *uas, uas_iu *iu)
|
|||||||
|
|
||||||
req->req = scsi_req_new(req->dev, req->tag,
|
req->req = scsi_req_new(req->dev, req->tag,
|
||||||
usb_uas_get_lun(req->lun),
|
usb_uas_get_lun(req->lun),
|
||||||
iu->command.cdb, req);
|
iu->command.cdb, cdb_len, req);
|
||||||
if (uas->requestlog) {
|
if (uas->requestlog) {
|
||||||
scsi_req_print(req->req);
|
scsi_req_print(req->req);
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ struct SCSIDeviceClass {
|
|||||||
void (*realize)(SCSIDevice *dev, Error **errp);
|
void (*realize)(SCSIDevice *dev, Error **errp);
|
||||||
void (*unrealize)(SCSIDevice *dev);
|
void (*unrealize)(SCSIDevice *dev);
|
||||||
int (*parse_cdb)(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
|
int (*parse_cdb)(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
|
||||||
void *hba_private);
|
size_t buf_len, void *hba_private);
|
||||||
SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun,
|
SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun,
|
||||||
uint8_t *buf, void *hba_private);
|
uint8_t *buf, void *hba_private);
|
||||||
void (*unit_attention_reported)(SCSIDevice *s);
|
void (*unit_attention_reported)(SCSIDevice *s);
|
||||||
@ -122,7 +122,7 @@ struct SCSIBusInfo {
|
|||||||
int tcq;
|
int tcq;
|
||||||
int max_channel, max_target, max_lun;
|
int max_channel, max_target, max_lun;
|
||||||
int (*parse_cdb)(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
|
int (*parse_cdb)(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
|
||||||
void *hba_private);
|
size_t buf_len, void *hba_private);
|
||||||
void (*transfer_data)(SCSIRequest *req, uint32_t arg);
|
void (*transfer_data)(SCSIRequest *req, uint32_t arg);
|
||||||
void (*fail)(SCSIRequest *req);
|
void (*fail)(SCSIRequest *req);
|
||||||
void (*complete)(SCSIRequest *req, size_t residual);
|
void (*complete)(SCSIRequest *req, size_t residual);
|
||||||
@ -192,14 +192,15 @@ void scsi_legacy_handle_cmdline(void);
|
|||||||
SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
|
SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
|
||||||
uint32_t tag, uint32_t lun, void *hba_private);
|
uint32_t tag, uint32_t lun, void *hba_private);
|
||||||
SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
|
SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
|
||||||
uint8_t *buf, void *hba_private);
|
uint8_t *buf, size_t buf_len, void *hba_private);
|
||||||
int32_t scsi_req_enqueue(SCSIRequest *req);
|
int32_t scsi_req_enqueue(SCSIRequest *req);
|
||||||
SCSIRequest *scsi_req_ref(SCSIRequest *req);
|
SCSIRequest *scsi_req_ref(SCSIRequest *req);
|
||||||
void scsi_req_unref(SCSIRequest *req);
|
void scsi_req_unref(SCSIRequest *req);
|
||||||
|
|
||||||
int scsi_bus_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
|
int scsi_bus_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
|
||||||
void *hba_private);
|
size_t buf_len, void *hba_private);
|
||||||
int scsi_req_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf);
|
int scsi_req_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
|
||||||
|
size_t buf_len);
|
||||||
void scsi_req_build_sense(SCSIRequest *req, SCSISense sense);
|
void scsi_req_build_sense(SCSIRequest *req, SCSISense sense);
|
||||||
void scsi_req_print(SCSIRequest *req);
|
void scsi_req_print(SCSIRequest *req);
|
||||||
void scsi_req_continue(SCSIRequest *req);
|
void scsi_req_continue(SCSIRequest *req);
|
||||||
|
@ -3408,7 +3408,6 @@ foreach target : target_dirs
|
|||||||
target_inc += include_directories('linux-headers', is_system: true)
|
target_inc += include_directories('linux-headers', is_system: true)
|
||||||
endif
|
endif
|
||||||
if target.endswith('-softmmu')
|
if target.endswith('-softmmu')
|
||||||
qemu_target_name = 'qemu-system-' + target_name
|
|
||||||
target_type='system'
|
target_type='system'
|
||||||
t = target_softmmu_arch[target_base_arch].apply(config_target, strict: false)
|
t = target_softmmu_arch[target_base_arch].apply(config_target, strict: false)
|
||||||
arch_srcs += t.sources()
|
arch_srcs += t.sources()
|
||||||
@ -3425,7 +3424,6 @@ foreach target : target_dirs
|
|||||||
abi = config_target['TARGET_ABI_DIR']
|
abi = config_target['TARGET_ABI_DIR']
|
||||||
target_type='user'
|
target_type='user'
|
||||||
target_inc += common_user_inc
|
target_inc += common_user_inc
|
||||||
qemu_target_name = 'qemu-' + target_name
|
|
||||||
if target_base_arch in target_user_arch
|
if target_base_arch in target_user_arch
|
||||||
t = target_user_arch[target_base_arch].apply(config_target, strict: false)
|
t = target_user_arch[target_base_arch].apply(config_target, strict: false)
|
||||||
arch_srcs += t.sources()
|
arch_srcs += t.sources()
|
||||||
|
@ -82,9 +82,9 @@ option('tcg', type: 'feature', value: 'enabled',
|
|||||||
description: 'TCG support')
|
description: 'TCG support')
|
||||||
option('tcg_interpreter', type: 'boolean', value: false,
|
option('tcg_interpreter', type: 'boolean', value: false,
|
||||||
description: 'TCG with bytecode interpreter (slow)')
|
description: 'TCG with bytecode interpreter (slow)')
|
||||||
option('cfi', type: 'boolean', value: 'false',
|
option('cfi', type: 'boolean', value: false,
|
||||||
description: 'Control-Flow Integrity (CFI)')
|
description: 'Control-Flow Integrity (CFI)')
|
||||||
option('cfi_debug', type: 'boolean', value: 'false',
|
option('cfi_debug', type: 'boolean', value: false,
|
||||||
description: 'Verbose errors in case of CFI violation')
|
description: 'Verbose errors in case of CFI violation')
|
||||||
option('multiprocess', type: 'feature', value: 'auto',
|
option('multiprocess', type: 'feature', value: 'auto',
|
||||||
description: 'Out of process device emulation support')
|
description: 'Out of process device emulation support')
|
||||||
|
@ -38,7 +38,6 @@ if meson.is_cross_build() or 'CONFIG_XKBCOMMON' not in config_host
|
|||||||
else
|
else
|
||||||
native_qemu_keymap = qemu_keymap
|
native_qemu_keymap = qemu_keymap
|
||||||
endif
|
endif
|
||||||
cp = find_program('cp')
|
|
||||||
|
|
||||||
if native_qemu_keymap.found()
|
if native_qemu_keymap.found()
|
||||||
t = []
|
t = []
|
||||||
|
@ -2,7 +2,7 @@ plugin_ldflags = []
|
|||||||
# Modules need more symbols than just those in plugins/qemu-plugins.symbols
|
# Modules need more symbols than just those in plugins/qemu-plugins.symbols
|
||||||
if not enable_modules
|
if not enable_modules
|
||||||
if targetos == 'darwin'
|
if targetos == 'darwin'
|
||||||
qemu_plugins_symbols_list = configure_file(
|
configure_file(
|
||||||
input: files('qemu-plugins.symbols'),
|
input: files('qemu-plugins.symbols'),
|
||||||
output: 'qemu-plugins-ld64.symbols',
|
output: 'qemu-plugins-ld64.symbols',
|
||||||
capture: true,
|
capture: true,
|
||||||
|
@ -68,21 +68,6 @@ if have_system or have_tools
|
|||||||
]
|
]
|
||||||
endif
|
endif
|
||||||
|
|
||||||
qapi_storage_daemon_modules = [
|
|
||||||
'block-core',
|
|
||||||
'block-export',
|
|
||||||
'char',
|
|
||||||
'common',
|
|
||||||
'control',
|
|
||||||
'crypto',
|
|
||||||
'introspect',
|
|
||||||
'job',
|
|
||||||
'qom',
|
|
||||||
'sockets',
|
|
||||||
'pragma',
|
|
||||||
'transaction',
|
|
||||||
]
|
|
||||||
|
|
||||||
qapi_nonmodule_outputs = [
|
qapi_nonmodule_outputs = [
|
||||||
'qapi-introspect.c', 'qapi-introspect.h',
|
'qapi-introspect.c', 'qapi-introspect.h',
|
||||||
'qapi-types.c', 'qapi-types.h',
|
'qapi-types.c', 'qapi-types.h',
|
||||||
|
@ -1695,6 +1695,30 @@ static void kvm_init_xsave(CPUX86State *env)
|
|||||||
env->xsave_buf_len);
|
env->xsave_buf_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void kvm_init_nested_state(CPUX86State *env)
|
||||||
|
{
|
||||||
|
struct kvm_vmx_nested_state_hdr *vmx_hdr;
|
||||||
|
uint32_t size;
|
||||||
|
|
||||||
|
if (!env->nested_state) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = env->nested_state->size;
|
||||||
|
|
||||||
|
memset(env->nested_state, 0, size);
|
||||||
|
env->nested_state->size = size;
|
||||||
|
|
||||||
|
if (cpu_has_vmx(env)) {
|
||||||
|
env->nested_state->format = KVM_STATE_NESTED_FORMAT_VMX;
|
||||||
|
vmx_hdr = &env->nested_state->hdr.vmx;
|
||||||
|
vmx_hdr->vmxon_pa = -1ull;
|
||||||
|
vmx_hdr->vmcs12_pa = -1ull;
|
||||||
|
} else if (cpu_has_svm(env)) {
|
||||||
|
env->nested_state->format = KVM_STATE_NESTED_FORMAT_SVM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int kvm_arch_init_vcpu(CPUState *cs)
|
int kvm_arch_init_vcpu(CPUState *cs)
|
||||||
{
|
{
|
||||||
struct {
|
struct {
|
||||||
@ -2122,19 +2146,10 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
|||||||
assert(max_nested_state_len >= offsetof(struct kvm_nested_state, data));
|
assert(max_nested_state_len >= offsetof(struct kvm_nested_state, data));
|
||||||
|
|
||||||
if (cpu_has_vmx(env) || cpu_has_svm(env)) {
|
if (cpu_has_vmx(env) || cpu_has_svm(env)) {
|
||||||
struct kvm_vmx_nested_state_hdr *vmx_hdr;
|
|
||||||
|
|
||||||
env->nested_state = g_malloc0(max_nested_state_len);
|
env->nested_state = g_malloc0(max_nested_state_len);
|
||||||
env->nested_state->size = max_nested_state_len;
|
env->nested_state->size = max_nested_state_len;
|
||||||
|
|
||||||
if (cpu_has_vmx(env)) {
|
kvm_init_nested_state(env);
|
||||||
env->nested_state->format = KVM_STATE_NESTED_FORMAT_VMX;
|
|
||||||
vmx_hdr = &env->nested_state->hdr.vmx;
|
|
||||||
vmx_hdr->vmxon_pa = -1ull;
|
|
||||||
vmx_hdr->vmcs12_pa = -1ull;
|
|
||||||
} else {
|
|
||||||
env->nested_state->format = KVM_STATE_NESTED_FORMAT_SVM;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2199,6 +2214,8 @@ void kvm_arch_reset_vcpu(X86CPU *cpu)
|
|||||||
/* enabled by default */
|
/* enabled by default */
|
||||||
env->poll_control_msr = 1;
|
env->poll_control_msr = 1;
|
||||||
|
|
||||||
|
kvm_init_nested_state(env);
|
||||||
|
|
||||||
sev_es_set_reset_vector(CPU(cpu));
|
sev_es_set_reset_vector(CPU(cpu));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4512,6 +4529,18 @@ int kvm_arch_put_registers(CPUState *cpu, int level)
|
|||||||
|
|
||||||
assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu));
|
assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Put MSR_IA32_FEATURE_CONTROL first, this ensures the VM gets out of VMX
|
||||||
|
* root operation upon vCPU reset. kvm_put_msr_feature_control() should also
|
||||||
|
* preceed kvm_put_nested_state() when 'real' nested state is set.
|
||||||
|
*/
|
||||||
|
if (level >= KVM_PUT_RESET_STATE) {
|
||||||
|
ret = kvm_put_msr_feature_control(x86_cpu);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* must be before kvm_put_nested_state so that EFER.SVME is set */
|
/* must be before kvm_put_nested_state so that EFER.SVME is set */
|
||||||
ret = has_sregs2 ? kvm_put_sregs2(x86_cpu) : kvm_put_sregs(x86_cpu);
|
ret = has_sregs2 ? kvm_put_sregs2(x86_cpu) : kvm_put_sregs(x86_cpu);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@ -4523,11 +4552,6 @@ int kvm_arch_put_registers(CPUState *cpu, int level)
|
|||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = kvm_put_msr_feature_control(x86_cpu);
|
|
||||||
if (ret < 0) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (level == KVM_PUT_FULL_STATE) {
|
if (level == KVM_PUT_FULL_STATE) {
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -122,8 +122,8 @@ DEF_HELPER_2(glue(movq_mm_T0, SUFFIX), void, Reg, i64)
|
|||||||
#if SHIFT == 0
|
#if SHIFT == 0
|
||||||
DEF_HELPER_3(glue(pshufw, SUFFIX), void, Reg, Reg, int)
|
DEF_HELPER_3(glue(pshufw, SUFFIX), void, Reg, Reg, int)
|
||||||
#else
|
#else
|
||||||
DEF_HELPER_3(shufps, void, Reg, Reg, int)
|
DEF_HELPER_3(glue(shufps, SUFFIX), void, Reg, Reg, int)
|
||||||
DEF_HELPER_3(shufpd, void, Reg, Reg, int)
|
DEF_HELPER_3(glue(shufpd, SUFFIX), void, Reg, Reg, int)
|
||||||
DEF_HELPER_3(glue(pshufd, SUFFIX), void, Reg, Reg, int)
|
DEF_HELPER_3(glue(pshufd, SUFFIX), void, Reg, Reg, int)
|
||||||
DEF_HELPER_3(glue(pshuflw, SUFFIX), void, Reg, Reg, int)
|
DEF_HELPER_3(glue(pshuflw, SUFFIX), void, Reg, Reg, int)
|
||||||
DEF_HELPER_3(glue(pshufhw, SUFFIX), void, Reg, Reg, int)
|
DEF_HELPER_3(glue(pshufhw, SUFFIX), void, Reg, Reg, int)
|
||||||
@ -134,9 +134,9 @@ DEF_HELPER_3(glue(pshufhw, SUFFIX), void, Reg, Reg, int)
|
|||||||
/* XXX: not accurate */
|
/* XXX: not accurate */
|
||||||
|
|
||||||
#define SSE_HELPER_S(name, F) \
|
#define SSE_HELPER_S(name, F) \
|
||||||
DEF_HELPER_3(name ## ps, void, env, Reg, Reg) \
|
DEF_HELPER_3(glue(name ## ps, SUFFIX), void, env, Reg, Reg) \
|
||||||
DEF_HELPER_3(name ## ss, void, env, Reg, Reg) \
|
DEF_HELPER_3(name ## ss, void, env, Reg, Reg) \
|
||||||
DEF_HELPER_3(name ## pd, void, env, Reg, Reg) \
|
DEF_HELPER_3(glue(name ## pd, SUFFIX), void, env, Reg, Reg) \
|
||||||
DEF_HELPER_3(name ## sd, void, env, Reg, Reg)
|
DEF_HELPER_3(name ## sd, void, env, Reg, Reg)
|
||||||
|
|
||||||
SSE_HELPER_S(add, FPU_ADD)
|
SSE_HELPER_S(add, FPU_ADD)
|
||||||
@ -148,12 +148,12 @@ SSE_HELPER_S(max, FPU_MAX)
|
|||||||
SSE_HELPER_S(sqrt, FPU_SQRT)
|
SSE_HELPER_S(sqrt, FPU_SQRT)
|
||||||
|
|
||||||
|
|
||||||
DEF_HELPER_3(cvtps2pd, void, env, Reg, Reg)
|
DEF_HELPER_3(glue(cvtps2pd, SUFFIX), void, env, Reg, Reg)
|
||||||
DEF_HELPER_3(cvtpd2ps, void, env, Reg, Reg)
|
DEF_HELPER_3(glue(cvtpd2ps, SUFFIX), void, env, Reg, Reg)
|
||||||
DEF_HELPER_3(cvtss2sd, void, env, Reg, Reg)
|
DEF_HELPER_3(cvtss2sd, void, env, Reg, Reg)
|
||||||
DEF_HELPER_3(cvtsd2ss, void, env, Reg, Reg)
|
DEF_HELPER_3(cvtsd2ss, void, env, Reg, Reg)
|
||||||
DEF_HELPER_3(cvtdq2ps, void, env, Reg, Reg)
|
DEF_HELPER_3(glue(cvtdq2ps, SUFFIX), void, env, Reg, Reg)
|
||||||
DEF_HELPER_3(cvtdq2pd, void, env, Reg, Reg)
|
DEF_HELPER_3(glue(cvtdq2pd, SUFFIX), void, env, Reg, Reg)
|
||||||
DEF_HELPER_3(cvtpi2ps, void, env, ZMMReg, MMXReg)
|
DEF_HELPER_3(cvtpi2ps, void, env, ZMMReg, MMXReg)
|
||||||
DEF_HELPER_3(cvtpi2pd, void, env, ZMMReg, MMXReg)
|
DEF_HELPER_3(cvtpi2pd, void, env, ZMMReg, MMXReg)
|
||||||
DEF_HELPER_3(cvtsi2ss, void, env, ZMMReg, i32)
|
DEF_HELPER_3(cvtsi2ss, void, env, ZMMReg, i32)
|
||||||
@ -164,8 +164,8 @@ DEF_HELPER_3(cvtsq2ss, void, env, ZMMReg, i64)
|
|||||||
DEF_HELPER_3(cvtsq2sd, void, env, ZMMReg, i64)
|
DEF_HELPER_3(cvtsq2sd, void, env, ZMMReg, i64)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DEF_HELPER_3(cvtps2dq, void, env, ZMMReg, ZMMReg)
|
DEF_HELPER_3(glue(cvtps2dq, SUFFIX), void, env, ZMMReg, ZMMReg)
|
||||||
DEF_HELPER_3(cvtpd2dq, void, env, ZMMReg, ZMMReg)
|
DEF_HELPER_3(glue(cvtpd2dq, SUFFIX), void, env, ZMMReg, ZMMReg)
|
||||||
DEF_HELPER_3(cvtps2pi, void, env, MMXReg, ZMMReg)
|
DEF_HELPER_3(cvtps2pi, void, env, MMXReg, ZMMReg)
|
||||||
DEF_HELPER_3(cvtpd2pi, void, env, MMXReg, ZMMReg)
|
DEF_HELPER_3(cvtpd2pi, void, env, MMXReg, ZMMReg)
|
||||||
DEF_HELPER_2(cvtss2si, s32, env, ZMMReg)
|
DEF_HELPER_2(cvtss2si, s32, env, ZMMReg)
|
||||||
@ -175,8 +175,8 @@ DEF_HELPER_2(cvtss2sq, s64, env, ZMMReg)
|
|||||||
DEF_HELPER_2(cvtsd2sq, s64, env, ZMMReg)
|
DEF_HELPER_2(cvtsd2sq, s64, env, ZMMReg)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DEF_HELPER_3(cvttps2dq, void, env, ZMMReg, ZMMReg)
|
DEF_HELPER_3(glue(cvttps2dq, SUFFIX), void, env, ZMMReg, ZMMReg)
|
||||||
DEF_HELPER_3(cvttpd2dq, void, env, ZMMReg, ZMMReg)
|
DEF_HELPER_3(glue(cvttpd2dq, SUFFIX), void, env, ZMMReg, ZMMReg)
|
||||||
DEF_HELPER_3(cvttps2pi, void, env, MMXReg, ZMMReg)
|
DEF_HELPER_3(cvttps2pi, void, env, MMXReg, ZMMReg)
|
||||||
DEF_HELPER_3(cvttpd2pi, void, env, MMXReg, ZMMReg)
|
DEF_HELPER_3(cvttpd2pi, void, env, MMXReg, ZMMReg)
|
||||||
DEF_HELPER_2(cvttss2si, s32, env, ZMMReg)
|
DEF_HELPER_2(cvttss2si, s32, env, ZMMReg)
|
||||||
@ -186,42 +186,42 @@ DEF_HELPER_2(cvttss2sq, s64, env, ZMMReg)
|
|||||||
DEF_HELPER_2(cvttsd2sq, s64, env, ZMMReg)
|
DEF_HELPER_2(cvttsd2sq, s64, env, ZMMReg)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DEF_HELPER_3(rsqrtps, void, env, ZMMReg, ZMMReg)
|
DEF_HELPER_3(glue(rsqrtps, SUFFIX), void, env, ZMMReg, ZMMReg)
|
||||||
DEF_HELPER_3(rsqrtss, void, env, ZMMReg, ZMMReg)
|
DEF_HELPER_3(rsqrtss, void, env, ZMMReg, ZMMReg)
|
||||||
DEF_HELPER_3(rcpps, void, env, ZMMReg, ZMMReg)
|
DEF_HELPER_3(glue(rcpps, SUFFIX), void, env, ZMMReg, ZMMReg)
|
||||||
DEF_HELPER_3(rcpss, void, env, ZMMReg, ZMMReg)
|
DEF_HELPER_3(rcpss, void, env, ZMMReg, ZMMReg)
|
||||||
DEF_HELPER_3(extrq_r, void, env, ZMMReg, ZMMReg)
|
DEF_HELPER_3(extrq_r, void, env, ZMMReg, ZMMReg)
|
||||||
DEF_HELPER_4(extrq_i, void, env, ZMMReg, int, int)
|
DEF_HELPER_4(extrq_i, void, env, ZMMReg, int, int)
|
||||||
DEF_HELPER_3(insertq_r, void, env, ZMMReg, ZMMReg)
|
DEF_HELPER_3(insertq_r, void, env, ZMMReg, ZMMReg)
|
||||||
DEF_HELPER_4(insertq_i, void, env, ZMMReg, int, int)
|
DEF_HELPER_4(insertq_i, void, env, ZMMReg, int, int)
|
||||||
DEF_HELPER_3(haddps, void, env, ZMMReg, ZMMReg)
|
DEF_HELPER_3(glue(haddps, SUFFIX), void, env, ZMMReg, ZMMReg)
|
||||||
DEF_HELPER_3(haddpd, void, env, ZMMReg, ZMMReg)
|
DEF_HELPER_3(glue(haddpd, SUFFIX), void, env, ZMMReg, ZMMReg)
|
||||||
DEF_HELPER_3(hsubps, void, env, ZMMReg, ZMMReg)
|
DEF_HELPER_3(glue(hsubps, SUFFIX), void, env, ZMMReg, ZMMReg)
|
||||||
DEF_HELPER_3(hsubpd, void, env, ZMMReg, ZMMReg)
|
DEF_HELPER_3(glue(hsubpd, SUFFIX), void, env, ZMMReg, ZMMReg)
|
||||||
DEF_HELPER_3(addsubps, void, env, ZMMReg, ZMMReg)
|
DEF_HELPER_3(glue(addsubps, SUFFIX), void, env, ZMMReg, ZMMReg)
|
||||||
DEF_HELPER_3(addsubpd, void, env, ZMMReg, ZMMReg)
|
DEF_HELPER_3(glue(addsubpd, SUFFIX), void, env, ZMMReg, ZMMReg)
|
||||||
|
|
||||||
#define SSE_HELPER_CMP(name, F) \
|
#define SSE_HELPER_CMP(name, F, C) \
|
||||||
DEF_HELPER_3(name ## ps, void, env, Reg, Reg) \
|
DEF_HELPER_3(glue(name ## ps, SUFFIX), void, env, Reg, Reg) \
|
||||||
DEF_HELPER_3(name ## ss, void, env, Reg, Reg) \
|
DEF_HELPER_3(name ## ss, void, env, Reg, Reg) \
|
||||||
DEF_HELPER_3(name ## pd, void, env, Reg, Reg) \
|
DEF_HELPER_3(glue(name ## pd, SUFFIX), void, env, Reg, Reg) \
|
||||||
DEF_HELPER_3(name ## sd, void, env, Reg, Reg)
|
DEF_HELPER_3(name ## sd, void, env, Reg, Reg)
|
||||||
|
|
||||||
SSE_HELPER_CMP(cmpeq, FPU_CMPEQ)
|
SSE_HELPER_CMP(cmpeq, FPU_CMPQ, FPU_EQ)
|
||||||
SSE_HELPER_CMP(cmplt, FPU_CMPLT)
|
SSE_HELPER_CMP(cmplt, FPU_CMPS, FPU_LT)
|
||||||
SSE_HELPER_CMP(cmple, FPU_CMPLE)
|
SSE_HELPER_CMP(cmple, FPU_CMPS, FPU_LE)
|
||||||
SSE_HELPER_CMP(cmpunord, FPU_CMPUNORD)
|
SSE_HELPER_CMP(cmpunord, FPU_CMPQ, FPU_UNORD)
|
||||||
SSE_HELPER_CMP(cmpneq, FPU_CMPNEQ)
|
SSE_HELPER_CMP(cmpneq, FPU_CMPQ, !FPU_EQ)
|
||||||
SSE_HELPER_CMP(cmpnlt, FPU_CMPNLT)
|
SSE_HELPER_CMP(cmpnlt, FPU_CMPS, !FPU_LT)
|
||||||
SSE_HELPER_CMP(cmpnle, FPU_CMPNLE)
|
SSE_HELPER_CMP(cmpnle, FPU_CMPS, !FPU_LE)
|
||||||
SSE_HELPER_CMP(cmpord, FPU_CMPORD)
|
SSE_HELPER_CMP(cmpord, FPU_CMPQ, !FPU_UNORD)
|
||||||
|
|
||||||
DEF_HELPER_3(ucomiss, void, env, Reg, Reg)
|
DEF_HELPER_3(ucomiss, void, env, Reg, Reg)
|
||||||
DEF_HELPER_3(comiss, void, env, Reg, Reg)
|
DEF_HELPER_3(comiss, void, env, Reg, Reg)
|
||||||
DEF_HELPER_3(ucomisd, void, env, Reg, Reg)
|
DEF_HELPER_3(ucomisd, void, env, Reg, Reg)
|
||||||
DEF_HELPER_3(comisd, void, env, Reg, Reg)
|
DEF_HELPER_3(comisd, void, env, Reg, Reg)
|
||||||
DEF_HELPER_2(movmskps, i32, env, Reg)
|
DEF_HELPER_2(glue(movmskps, SUFFIX), i32, env, Reg)
|
||||||
DEF_HELPER_2(movmskpd, i32, env, Reg)
|
DEF_HELPER_2(glue(movmskpd, SUFFIX), i32, env, Reg)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DEF_HELPER_2(glue(pmovmskb, SUFFIX), i32, env, Reg)
|
DEF_HELPER_2(glue(pmovmskb, SUFFIX), i32, env, Reg)
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,4 @@
|
|||||||
# FIXME extra_args should accept files()
|
# FIXME extra_args should accept files()
|
||||||
dir = meson.current_source_dir()
|
|
||||||
|
|
||||||
gen = [
|
gen = [
|
||||||
decodetree.process('insn16.decode', extra_args: ['--static-decode=decode_insn16', '--insnwidth=16']),
|
decodetree.process('insn16.decode', extra_args: ['--static-decode=decode_insn16', '--insnwidth=16']),
|
||||||
decodetree.process('insn32.decode', extra_args: '--static-decode=decode_insn32'),
|
decodetree.process('insn32.decode', extra_args: '--static-decode=decode_insn32'),
|
||||||
|
@ -632,7 +632,7 @@ test('fp-test-mulAdd', fptest,
|
|||||||
['f16_mulAdd', 'f32_mulAdd', 'f64_mulAdd', 'f128_mulAdd'],
|
['f16_mulAdd', 'f32_mulAdd', 'f64_mulAdd', 'f128_mulAdd'],
|
||||||
suite: ['softfloat-slow', 'softfloat-ops-slow', 'slow'], timeout: 90)
|
suite: ['softfloat-slow', 'softfloat-ops-slow', 'slow'], timeout: 90)
|
||||||
|
|
||||||
fpbench = executable(
|
executable(
|
||||||
'fp-bench',
|
'fp-bench',
|
||||||
['fp-bench.c', '../../fpu/softfloat.c'],
|
['fp-bench.c', '../../fpu/softfloat.c'],
|
||||||
link_with: [libtestfloat, libsoftfloat],
|
link_with: [libtestfloat, libsoftfloat],
|
||||||
|
@ -215,7 +215,7 @@ test('QAPI schema regression tests', python,
|
|||||||
|
|
||||||
diff = find_program('diff')
|
diff = find_program('diff')
|
||||||
|
|
||||||
qapi_doc = custom_target('QAPI doc',
|
custom_target('QAPI doc',
|
||||||
output: ['doc-good-qapi-commands.c', 'doc-good-qapi-commands.h',
|
output: ['doc-good-qapi-commands.c', 'doc-good-qapi-commands.h',
|
||||||
'doc-good-qapi-emit-events.c', 'doc-good-qapi-emit-events.h',
|
'doc-good-qapi-emit-events.c', 'doc-good-qapi-emit-events.h',
|
||||||
'doc-good-qapi-events.c', 'doc-good-qapi-events.h',
|
'doc-good-qapi-events.c', 'doc-good-qapi-events.h',
|
||||||
|
@ -188,4 +188,4 @@ gdb-%: %
|
|||||||
run: $(RUN_TESTS)
|
run: $(RUN_TESTS)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(TESTS) *.o
|
rm -f $(TESTS) *.o $(CLEANFILES)
|
||||||
|
@ -7,8 +7,8 @@ VPATH += $(I386_SRC)
|
|||||||
|
|
||||||
I386_SRCS=$(notdir $(wildcard $(I386_SRC)/*.c))
|
I386_SRCS=$(notdir $(wildcard $(I386_SRC)/*.c))
|
||||||
ALL_X86_TESTS=$(I386_SRCS:.c=)
|
ALL_X86_TESTS=$(I386_SRCS:.c=)
|
||||||
SKIP_I386_TESTS=test-i386-ssse3
|
SKIP_I386_TESTS=test-i386-ssse3 test-avx
|
||||||
X86_64_TESTS:=$(filter test-i386-ssse3, $(ALL_X86_TESTS))
|
X86_64_TESTS:=$(filter test-i386-bmi2 test-i386-ssse3 test-avx, $(ALL_X86_TESTS))
|
||||||
|
|
||||||
test-i386-sse-exceptions: CFLAGS += -msse4.1 -mfpmath=sse
|
test-i386-sse-exceptions: CFLAGS += -msse4.1 -mfpmath=sse
|
||||||
run-test-i386-sse-exceptions: QEMU_OPTS += -cpu max
|
run-test-i386-sse-exceptions: QEMU_OPTS += -cpu max
|
||||||
@ -18,6 +18,7 @@ test-i386-pcmpistri: CFLAGS += -msse4.2
|
|||||||
run-test-i386-pcmpistri: QEMU_OPTS += -cpu max
|
run-test-i386-pcmpistri: QEMU_OPTS += -cpu max
|
||||||
run-plugin-test-i386-pcmpistri-%: QEMU_OPTS += -cpu max
|
run-plugin-test-i386-pcmpistri-%: QEMU_OPTS += -cpu max
|
||||||
|
|
||||||
|
test-i386-bmi2: CFLAGS=-O2
|
||||||
run-test-i386-bmi2: QEMU_OPTS += -cpu max
|
run-test-i386-bmi2: QEMU_OPTS += -cpu max
|
||||||
run-plugin-test-i386-bmi2-%: QEMU_OPTS += -cpu max
|
run-plugin-test-i386-bmi2-%: QEMU_OPTS += -cpu max
|
||||||
|
|
||||||
@ -80,3 +81,10 @@ run-sha512-sse: QEMU_OPTS+=-cpu max
|
|||||||
run-plugin-sha512-sse-with-%: QEMU_OPTS+=-cpu max
|
run-plugin-sha512-sse-with-%: QEMU_OPTS+=-cpu max
|
||||||
|
|
||||||
TESTS+=sha512-sse
|
TESTS+=sha512-sse
|
||||||
|
|
||||||
|
CLEANFILES += test-avx.h
|
||||||
|
test-avx.h: test-avx.py x86.csv
|
||||||
|
$(PYTHON) $(I386_SRC)/test-avx.py $(I386_SRC)/x86.csv $@
|
||||||
|
|
||||||
|
test-avx: CFLAGS += -masm=intel -O -I.
|
||||||
|
test-avx: test-avx.h
|
||||||
|
@ -15,6 +15,15 @@ The Linux system call vm86() is used to test vm86 emulation.
|
|||||||
Various exceptions are raised to test most of the x86 user space
|
Various exceptions are raised to test most of the x86 user space
|
||||||
exception reporting.
|
exception reporting.
|
||||||
|
|
||||||
|
test-avx
|
||||||
|
--------
|
||||||
|
|
||||||
|
This program executes most SSE/AVX instructions and generates a text output,
|
||||||
|
for comparison with the output obtained with a real CPU or another emulator.
|
||||||
|
|
||||||
|
test-avx.h is generate from x86.csv by test-avx.py
|
||||||
|
x86.csv comes from https://github.com/quasilyte/avx512test
|
||||||
|
|
||||||
linux-test
|
linux-test
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
330
tests/tcg/i386/test-avx.c
Normal file
330
tests/tcg/i386/test-avx.c
Normal file
@ -0,0 +1,330 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
typedef void (*testfn)(void);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_t q0, q1;
|
||||||
|
} __attribute__((aligned(16))) v2di;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_t mm[8];
|
||||||
|
v2di xmm[16];
|
||||||
|
uint64_t r[16];
|
||||||
|
uint64_t flags;
|
||||||
|
uint32_t ff;
|
||||||
|
uint64_t pad;
|
||||||
|
v2di mem[4];
|
||||||
|
v2di mem0[4];
|
||||||
|
} reg_state;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int n;
|
||||||
|
testfn fn;
|
||||||
|
const char *s;
|
||||||
|
reg_state *init;
|
||||||
|
} TestDef;
|
||||||
|
|
||||||
|
reg_state initI;
|
||||||
|
reg_state initF32;
|
||||||
|
reg_state initF64;
|
||||||
|
|
||||||
|
static void dump_xmm(const char *name, int n, const v2di *r, int ff)
|
||||||
|
{
|
||||||
|
printf("%s%d = %016lx %016lx\n",
|
||||||
|
name, n, r->q1, r->q0);
|
||||||
|
if (ff == 64) {
|
||||||
|
double v[2];
|
||||||
|
memcpy(v, r, sizeof(v));
|
||||||
|
printf(" %16g %16g\n",
|
||||||
|
v[1], v[0]);
|
||||||
|
} else if (ff == 32) {
|
||||||
|
float v[4];
|
||||||
|
memcpy(v, r, sizeof(v));
|
||||||
|
printf(" %8g %8g %8g %8g\n",
|
||||||
|
v[3], v[2], v[1], v[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_regs(reg_state *s)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 16; i++) {
|
||||||
|
dump_xmm("xmm", i, &s->xmm[i], 0);
|
||||||
|
}
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
dump_xmm("mem", i, &s->mem0[i], 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void compare_state(const reg_state *a, const reg_state *b)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
if (a->mm[i] != b->mm[i]) {
|
||||||
|
printf("MM%d = %016lx\n", i, b->mm[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; i < 16; i++) {
|
||||||
|
if (a->r[i] != b->r[i]) {
|
||||||
|
printf("r%d = %016lx\n", i, b->r[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; i < 16; i++) {
|
||||||
|
if (memcmp(&a->xmm[i], &b->xmm[i], 16)) {
|
||||||
|
dump_xmm("xmm", i, &b->xmm[i], a->ff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
if (memcmp(&a->mem0[i], &a->mem[i], 16)) {
|
||||||
|
dump_xmm("mem", i, &a->mem[i], a->ff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (a->flags != b->flags) {
|
||||||
|
printf("FLAGS = %016lx\n", b->flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define LOADMM(r, o) "movq " #r ", " #o "[%0]\n\t"
|
||||||
|
#define LOADXMM(r, o) "movdqa " #r ", " #o "[%0]\n\t"
|
||||||
|
#define STOREMM(r, o) "movq " #o "[%1], " #r "\n\t"
|
||||||
|
#define STOREXMM(r, o) "movdqa " #o "[%1], " #r "\n\t"
|
||||||
|
#define MMREG(F) \
|
||||||
|
F(mm0, 0x00) \
|
||||||
|
F(mm1, 0x08) \
|
||||||
|
F(mm2, 0x10) \
|
||||||
|
F(mm3, 0x18) \
|
||||||
|
F(mm4, 0x20) \
|
||||||
|
F(mm5, 0x28) \
|
||||||
|
F(mm6, 0x30) \
|
||||||
|
F(mm7, 0x38)
|
||||||
|
#define XMMREG(F) \
|
||||||
|
F(xmm0, 0x040) \
|
||||||
|
F(xmm1, 0x050) \
|
||||||
|
F(xmm2, 0x060) \
|
||||||
|
F(xmm3, 0x070) \
|
||||||
|
F(xmm4, 0x080) \
|
||||||
|
F(xmm5, 0x090) \
|
||||||
|
F(xmm6, 0x0a0) \
|
||||||
|
F(xmm7, 0x0b0) \
|
||||||
|
F(xmm8, 0x0c0) \
|
||||||
|
F(xmm9, 0x0d0) \
|
||||||
|
F(xmm10, 0x0e0) \
|
||||||
|
F(xmm11, 0x0f0) \
|
||||||
|
F(xmm12, 0x100) \
|
||||||
|
F(xmm13, 0x110) \
|
||||||
|
F(xmm14, 0x120) \
|
||||||
|
F(xmm15, 0x130)
|
||||||
|
#define LOADREG(r, o) "mov " #r ", " #o "[rax]\n\t"
|
||||||
|
#define STOREREG(r, o) "mov " #o "[rax], " #r "\n\t"
|
||||||
|
#define REG(F) \
|
||||||
|
F(rbx, 0x148) \
|
||||||
|
F(rcx, 0x150) \
|
||||||
|
F(rdx, 0x158) \
|
||||||
|
F(rsi, 0x160) \
|
||||||
|
F(rdi, 0x168) \
|
||||||
|
F(r8, 0x180) \
|
||||||
|
F(r9, 0x188) \
|
||||||
|
F(r10, 0x190) \
|
||||||
|
F(r11, 0x198) \
|
||||||
|
F(r12, 0x1a0) \
|
||||||
|
F(r13, 0x1a8) \
|
||||||
|
F(r14, 0x1b0) \
|
||||||
|
F(r15, 0x1b8) \
|
||||||
|
|
||||||
|
static void run_test(const TestDef *t)
|
||||||
|
{
|
||||||
|
reg_state result;
|
||||||
|
reg_state *init = t->init;
|
||||||
|
memcpy(init->mem, init->mem0, sizeof(init->mem));
|
||||||
|
printf("%5d %s\n", t->n, t->s);
|
||||||
|
asm volatile(
|
||||||
|
MMREG(LOADMM)
|
||||||
|
XMMREG(LOADXMM)
|
||||||
|
"sub rsp, 128\n\t"
|
||||||
|
"push rax\n\t"
|
||||||
|
"push rbx\n\t"
|
||||||
|
"push rcx\n\t"
|
||||||
|
"push rdx\n\t"
|
||||||
|
"push %1\n\t"
|
||||||
|
"push %2\n\t"
|
||||||
|
"mov rax, %0\n\t"
|
||||||
|
"pushf\n\t"
|
||||||
|
"pop rbx\n\t"
|
||||||
|
"shr rbx, 8\n\t"
|
||||||
|
"shl rbx, 8\n\t"
|
||||||
|
"mov rcx, 0x1c0[rax]\n\t"
|
||||||
|
"and rcx, 0xff\n\t"
|
||||||
|
"or rbx, rcx\n\t"
|
||||||
|
"push rbx\n\t"
|
||||||
|
"popf\n\t"
|
||||||
|
REG(LOADREG)
|
||||||
|
"mov rax, 0x140[rax]\n\t"
|
||||||
|
"call [rsp]\n\t"
|
||||||
|
"mov [rsp], rax\n\t"
|
||||||
|
"mov rax, 8[rsp]\n\t"
|
||||||
|
REG(STOREREG)
|
||||||
|
"mov rbx, [rsp]\n\t"
|
||||||
|
"mov 0x140[rax], rbx\n\t"
|
||||||
|
"mov rbx, 0\n\t"
|
||||||
|
"mov 0x170[rax], rbx\n\t"
|
||||||
|
"mov 0x178[rax], rbx\n\t"
|
||||||
|
"pushf\n\t"
|
||||||
|
"pop rbx\n\t"
|
||||||
|
"and rbx, 0xff\n\t"
|
||||||
|
"mov 0x1c0[rax], rbx\n\t"
|
||||||
|
"add rsp, 16\n\t"
|
||||||
|
"pop rdx\n\t"
|
||||||
|
"pop rcx\n\t"
|
||||||
|
"pop rbx\n\t"
|
||||||
|
"pop rax\n\t"
|
||||||
|
"add rsp, 128\n\t"
|
||||||
|
MMREG(STOREMM)
|
||||||
|
XMMREG(STOREXMM)
|
||||||
|
: : "r"(init), "r"(&result), "r"(t->fn)
|
||||||
|
: "memory", "cc",
|
||||||
|
"rsi", "rdi",
|
||||||
|
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
|
||||||
|
"mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7",
|
||||||
|
"xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5",
|
||||||
|
"xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11",
|
||||||
|
"xmm12", "xmm13", "xmm14", "xmm15"
|
||||||
|
);
|
||||||
|
compare_state(init, &result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TEST(n, cmd, type) \
|
||||||
|
static void __attribute__((naked)) test_##n(void) \
|
||||||
|
{ \
|
||||||
|
asm volatile(cmd); \
|
||||||
|
asm volatile("ret"); \
|
||||||
|
}
|
||||||
|
#include "test-avx.h"
|
||||||
|
|
||||||
|
|
||||||
|
static const TestDef test_table[] = {
|
||||||
|
#define TEST(n, cmd, type) {n, test_##n, cmd, &init##type},
|
||||||
|
#include "test-avx.h"
|
||||||
|
{-1, NULL, "", NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
static void run_all(void)
|
||||||
|
{
|
||||||
|
const TestDef *t;
|
||||||
|
for (t = test_table; t->fn; t++) {
|
||||||
|
run_test(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ARRAY_LEN(x) (sizeof(x) / sizeof(x[0]))
|
||||||
|
|
||||||
|
float val_f32[] = {2.0, -1.0, 4.8, 0.8, 3, -42.0, 5e6, 7.5, 8.3};
|
||||||
|
double val_f64[] = {2.0, -1.0, 4.8, 0.8, 3, -42.0, 5e6, 7.5};
|
||||||
|
v2di val_i64[] = {
|
||||||
|
{0x3d6b3b6a9e4118f2lu, 0x355ae76d2774d78clu},
|
||||||
|
{0xd851c54a56bf1f29lu, 0x4a84d1d50bf4c4fflu},
|
||||||
|
{0x5826475e2c5fd799lu, 0xfd32edc01243f5e9lu},
|
||||||
|
};
|
||||||
|
|
||||||
|
v2di deadbeef = {0xa5a5a5a5deadbeefull, 0xa5a5a5a5deadbeefull};
|
||||||
|
v2di indexq = {0x000000000000001full, 0x000000000000008full};
|
||||||
|
v2di indexd = {0x00000002000000efull, 0xfffffff500000010ull};
|
||||||
|
|
||||||
|
void init_f32reg(v2di *r)
|
||||||
|
{
|
||||||
|
static int n;
|
||||||
|
float v[4];
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
v[i] = val_f32[n++];
|
||||||
|
if (n == ARRAY_LEN(val_f32)) {
|
||||||
|
n = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memcpy(r, v, sizeof(*r));
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_f64reg(v2di *r)
|
||||||
|
{
|
||||||
|
static int n;
|
||||||
|
double v[2];
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 2; i++) {
|
||||||
|
v[i] = val_f64[n++];
|
||||||
|
if (n == ARRAY_LEN(val_f64)) {
|
||||||
|
n = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memcpy(r, v, sizeof(*r));
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_intreg(v2di *r)
|
||||||
|
{
|
||||||
|
static uint64_t mask;
|
||||||
|
static int n;
|
||||||
|
|
||||||
|
r->q0 = val_i64[n].q0 ^ mask;
|
||||||
|
r->q1 = val_i64[n].q1 ^ mask;
|
||||||
|
n++;
|
||||||
|
if (n == ARRAY_LEN(val_i64)) {
|
||||||
|
n = 0;
|
||||||
|
mask *= 0x104C11DB7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void init_all(reg_state *s)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
s->r[3] = (uint64_t)&s->mem[0]; /* rdx */
|
||||||
|
s->r[5] = (uint64_t)&s->mem[2]; /* rdi */
|
||||||
|
s->flags = 2;
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
s->xmm[i] = deadbeef;
|
||||||
|
}
|
||||||
|
s->xmm[13] = indexd;
|
||||||
|
s->xmm[14] = indexq;
|
||||||
|
for (i = 0; i < 2; i++) {
|
||||||
|
s->mem0[i] = deadbeef;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
init_all(&initI);
|
||||||
|
init_intreg(&initI.xmm[10]);
|
||||||
|
init_intreg(&initI.xmm[11]);
|
||||||
|
init_intreg(&initI.xmm[12]);
|
||||||
|
init_intreg(&initI.mem0[1]);
|
||||||
|
printf("Int:\n");
|
||||||
|
dump_regs(&initI);
|
||||||
|
|
||||||
|
init_all(&initF32);
|
||||||
|
init_f32reg(&initF32.xmm[10]);
|
||||||
|
init_f32reg(&initF32.xmm[11]);
|
||||||
|
init_f32reg(&initF32.xmm[12]);
|
||||||
|
init_f32reg(&initF32.mem0[1]);
|
||||||
|
initF32.ff = 32;
|
||||||
|
printf("F32:\n");
|
||||||
|
dump_regs(&initF32);
|
||||||
|
|
||||||
|
init_all(&initF64);
|
||||||
|
init_f64reg(&initF64.xmm[10]);
|
||||||
|
init_f64reg(&initF64.xmm[11]);
|
||||||
|
init_f64reg(&initF64.xmm[12]);
|
||||||
|
init_f64reg(&initF64.mem0[1]);
|
||||||
|
initF64.ff = 64;
|
||||||
|
printf("F64:\n");
|
||||||
|
dump_regs(&initF64);
|
||||||
|
|
||||||
|
if (argc > 1) {
|
||||||
|
int n = atoi(argv[1]);
|
||||||
|
run_test(&test_table[n]);
|
||||||
|
} else {
|
||||||
|
run_all();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
351
tests/tcg/i386/test-avx.py
Executable file
351
tests/tcg/i386/test-avx.py
Executable file
@ -0,0 +1,351 @@
|
|||||||
|
#! /usr/bin/env python3
|
||||||
|
|
||||||
|
# Generate test-avx.h from x86.csv
|
||||||
|
|
||||||
|
import csv
|
||||||
|
import sys
|
||||||
|
from fnmatch import fnmatch
|
||||||
|
|
||||||
|
archs = [
|
||||||
|
# TODO: MMX?
|
||||||
|
"SSE", "SSE2", "SSE3", "SSSE3", "SSE4_1", "SSE4_2",
|
||||||
|
]
|
||||||
|
|
||||||
|
ignore = set(["FISTTP",
|
||||||
|
"LDMXCSR", "VLDMXCSR", "STMXCSR", "VSTMXCSR"])
|
||||||
|
|
||||||
|
imask = {
|
||||||
|
'vBLENDPD': 0xff,
|
||||||
|
'vBLENDPS': 0x0f,
|
||||||
|
'CMP[PS][SD]': 0x07,
|
||||||
|
'VCMP[PS][SD]': 0x1f,
|
||||||
|
'vDPPD': 0x33,
|
||||||
|
'vDPPS': 0xff,
|
||||||
|
'vEXTRACTPS': 0x03,
|
||||||
|
'vINSERTPS': 0xff,
|
||||||
|
'MPSADBW': 0x7,
|
||||||
|
'VMPSADBW': 0x3f,
|
||||||
|
'vPALIGNR': 0x3f,
|
||||||
|
'vPBLENDW': 0xff,
|
||||||
|
'vPCMP[EI]STR*': 0x0f,
|
||||||
|
'vPEXTRB': 0x0f,
|
||||||
|
'vPEXTRW': 0x07,
|
||||||
|
'vPEXTRD': 0x03,
|
||||||
|
'vPEXTRQ': 0x01,
|
||||||
|
'vPINSRB': 0x0f,
|
||||||
|
'vPINSRW': 0x07,
|
||||||
|
'vPINSRD': 0x03,
|
||||||
|
'vPINSRQ': 0x01,
|
||||||
|
'vPSHUF[DW]': 0xff,
|
||||||
|
'vPSHUF[LH]W': 0xff,
|
||||||
|
'vPS[LR][AL][WDQ]': 0x3f,
|
||||||
|
'vPS[RL]LDQ': 0x1f,
|
||||||
|
'vROUND[PS][SD]': 0x7,
|
||||||
|
'vSHUFPD': 0x0f,
|
||||||
|
'vSHUFPS': 0xff,
|
||||||
|
'vAESKEYGENASSIST': 0,
|
||||||
|
'VEXTRACT[FI]128': 0x01,
|
||||||
|
'VINSERT[FI]128': 0x01,
|
||||||
|
'VPBLENDD': 0xff,
|
||||||
|
'VPERM2[FI]128': 0x33,
|
||||||
|
'VPERMPD': 0xff,
|
||||||
|
'VPERMQ': 0xff,
|
||||||
|
'VPERMILPS': 0xff,
|
||||||
|
'VPERMILPD': 0x0f,
|
||||||
|
}
|
||||||
|
|
||||||
|
def strip_comments(x):
|
||||||
|
for l in x:
|
||||||
|
if l != '' and l[0] != '#':
|
||||||
|
yield l
|
||||||
|
|
||||||
|
def reg_w(w):
|
||||||
|
if w == 8:
|
||||||
|
return 'al'
|
||||||
|
elif w == 16:
|
||||||
|
return 'ax'
|
||||||
|
elif w == 32:
|
||||||
|
return 'eax'
|
||||||
|
elif w == 64:
|
||||||
|
return 'rax'
|
||||||
|
raise Exception("bad reg_w %d" % w)
|
||||||
|
|
||||||
|
def mem_w(w):
|
||||||
|
if w == 8:
|
||||||
|
t = "BYTE"
|
||||||
|
elif w == 16:
|
||||||
|
t = "WORD"
|
||||||
|
elif w == 32:
|
||||||
|
t = "DWORD"
|
||||||
|
elif w == 64:
|
||||||
|
t = "QWORD"
|
||||||
|
elif w == 128:
|
||||||
|
t = "XMMWORD"
|
||||||
|
elif w == 256:
|
||||||
|
t = "YMMWORD"
|
||||||
|
else:
|
||||||
|
raise Exception()
|
||||||
|
|
||||||
|
return t + " PTR 16[rdx]"
|
||||||
|
|
||||||
|
class XMMArg():
|
||||||
|
isxmm = True
|
||||||
|
def __init__(self, reg, mw):
|
||||||
|
if mw not in [0, 8, 16, 32, 64, 128, 256]:
|
||||||
|
raise Exception("Bad /m width: %s" % w)
|
||||||
|
self.reg = reg
|
||||||
|
self.mw = mw
|
||||||
|
self.ismem = mw != 0
|
||||||
|
def regstr(self, n):
|
||||||
|
if n < 0:
|
||||||
|
return mem_w(self.mw)
|
||||||
|
else:
|
||||||
|
return "%smm%d" % (self.reg, n)
|
||||||
|
|
||||||
|
class MMArg():
|
||||||
|
isxmm = True
|
||||||
|
ismem = False # TODO
|
||||||
|
def regstr(self, n):
|
||||||
|
return "mm%d" % (n & 7)
|
||||||
|
|
||||||
|
def match(op, pattern):
|
||||||
|
if pattern[0] == 'v':
|
||||||
|
return fnmatch(op, pattern[1:]) or fnmatch(op, 'V'+pattern[1:])
|
||||||
|
return fnmatch(op, pattern)
|
||||||
|
|
||||||
|
class ArgVSIB():
|
||||||
|
isxmm = True
|
||||||
|
ismem = False
|
||||||
|
def __init__(self, reg, w):
|
||||||
|
if w not in [32, 64]:
|
||||||
|
raise Exception("Bad vsib width: %s" % w)
|
||||||
|
self.w = w
|
||||||
|
self.reg = reg
|
||||||
|
def regstr(self, n):
|
||||||
|
reg = "%smm%d" % (self.reg, n >> 2)
|
||||||
|
return "[rsi + %s * %d]" % (reg, 1 << (n & 3))
|
||||||
|
|
||||||
|
class ArgImm8u():
|
||||||
|
isxmm = False
|
||||||
|
ismem = False
|
||||||
|
def __init__(self, op):
|
||||||
|
for k, v in imask.items():
|
||||||
|
if match(op, k):
|
||||||
|
self.mask = imask[k];
|
||||||
|
return
|
||||||
|
raise Exception("Unknown immediate")
|
||||||
|
def vals(self):
|
||||||
|
mask = self.mask
|
||||||
|
yield 0
|
||||||
|
n = 0
|
||||||
|
while n != mask:
|
||||||
|
n += 1
|
||||||
|
while (n & ~mask) != 0:
|
||||||
|
n += (n & ~mask)
|
||||||
|
yield n
|
||||||
|
|
||||||
|
class ArgRM():
|
||||||
|
isxmm = False
|
||||||
|
def __init__(self, rw, mw):
|
||||||
|
if rw not in [8, 16, 32, 64]:
|
||||||
|
raise Exception("Bad r/w width: %s" % w)
|
||||||
|
if mw not in [0, 8, 16, 32, 64]:
|
||||||
|
raise Exception("Bad r/w width: %s" % w)
|
||||||
|
self.rw = rw
|
||||||
|
self.mw = mw
|
||||||
|
self.ismem = mw != 0
|
||||||
|
def regstr(self, n):
|
||||||
|
if n < 0:
|
||||||
|
return mem_w(self.mw)
|
||||||
|
else:
|
||||||
|
return reg_w(self.rw)
|
||||||
|
|
||||||
|
class ArgMem():
|
||||||
|
isxmm = False
|
||||||
|
ismem = True
|
||||||
|
def __init__(self, w):
|
||||||
|
if w not in [8, 16, 32, 64, 128, 256]:
|
||||||
|
raise Exception("Bad mem width: %s" % w)
|
||||||
|
self.w = w
|
||||||
|
def regstr(self, n):
|
||||||
|
return mem_w(self.w)
|
||||||
|
|
||||||
|
def ArgGenerator(arg, op):
|
||||||
|
if arg[:3] == 'xmm' or arg[:3] == "ymm":
|
||||||
|
if "/" in arg:
|
||||||
|
r, m = arg.split('/')
|
||||||
|
if (m[0] != 'm'):
|
||||||
|
raise Exception("Expected /m: %s", arg)
|
||||||
|
return XMMArg(arg[0], int(m[1:]));
|
||||||
|
else:
|
||||||
|
return XMMArg(arg[0], 0);
|
||||||
|
elif arg[:2] == 'mm':
|
||||||
|
return MMArg();
|
||||||
|
elif arg[:4] == 'imm8':
|
||||||
|
return ArgImm8u(op);
|
||||||
|
elif arg == '<XMM0>':
|
||||||
|
return None
|
||||||
|
elif arg[0] == 'r':
|
||||||
|
if '/m' in arg:
|
||||||
|
r, m = arg.split('/')
|
||||||
|
if (m[0] != 'm'):
|
||||||
|
raise Exception("Expected /m: %s", arg)
|
||||||
|
mw = int(m[1:])
|
||||||
|
if r == 'r':
|
||||||
|
rw = mw
|
||||||
|
else:
|
||||||
|
rw = int(r[1:])
|
||||||
|
return ArgRM(rw, mw)
|
||||||
|
|
||||||
|
return ArgRM(int(arg[1:]), 0);
|
||||||
|
elif arg[0] == 'm':
|
||||||
|
return ArgMem(int(arg[1:]))
|
||||||
|
elif arg[:2] == 'vm':
|
||||||
|
return ArgVSIB(arg[-1], int(arg[2:-1]))
|
||||||
|
else:
|
||||||
|
raise Exception("Unrecognised arg: %s", arg)
|
||||||
|
|
||||||
|
class InsnGenerator:
|
||||||
|
def __init__(self, op, args):
|
||||||
|
self.op = op
|
||||||
|
if op[-2:] in ["PS", "PD", "SS", "SD"]:
|
||||||
|
if op[-1] == 'S':
|
||||||
|
self.optype = 'F32'
|
||||||
|
else:
|
||||||
|
self.optype = 'F64'
|
||||||
|
else:
|
||||||
|
self.optype = 'I'
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.args = list(ArgGenerator(a, op) for a in args)
|
||||||
|
if len(self.args) > 0 and self.args[-1] is None:
|
||||||
|
self.args = self.args[:-1]
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception("Bad arg %s: %s" % (op, e))
|
||||||
|
|
||||||
|
def gen(self):
|
||||||
|
regs = (10, 11, 12)
|
||||||
|
dest = 9
|
||||||
|
|
||||||
|
nreg = len(self.args)
|
||||||
|
if nreg == 0:
|
||||||
|
yield self.op
|
||||||
|
return
|
||||||
|
if isinstance(self.args[-1], ArgImm8u):
|
||||||
|
nreg -= 1
|
||||||
|
immarg = self.args[-1]
|
||||||
|
else:
|
||||||
|
immarg = None
|
||||||
|
memarg = -1
|
||||||
|
for n, arg in enumerate(self.args):
|
||||||
|
if arg.ismem:
|
||||||
|
memarg = n
|
||||||
|
|
||||||
|
if (self.op.startswith("VGATHER") or self.op.startswith("VPGATHER")):
|
||||||
|
if "GATHERD" in self.op:
|
||||||
|
ireg = 13 << 2
|
||||||
|
else:
|
||||||
|
ireg = 14 << 2
|
||||||
|
regset = [
|
||||||
|
(dest, ireg | 0, regs[0]),
|
||||||
|
(dest, ireg | 1, regs[0]),
|
||||||
|
(dest, ireg | 2, regs[0]),
|
||||||
|
(dest, ireg | 3, regs[0]),
|
||||||
|
]
|
||||||
|
if memarg >= 0:
|
||||||
|
raise Exception("vsib with memory: %s" % self.op)
|
||||||
|
elif nreg == 1:
|
||||||
|
regset = [(regs[0],)]
|
||||||
|
if memarg == 0:
|
||||||
|
regset += [(-1,)]
|
||||||
|
elif nreg == 2:
|
||||||
|
regset = [
|
||||||
|
(regs[0], regs[1]),
|
||||||
|
(regs[0], regs[0]),
|
||||||
|
]
|
||||||
|
if memarg == 0:
|
||||||
|
regset += [(-1, regs[0])]
|
||||||
|
elif memarg == 1:
|
||||||
|
regset += [(dest, -1)]
|
||||||
|
elif nreg == 3:
|
||||||
|
regset = [
|
||||||
|
(dest, regs[0], regs[1]),
|
||||||
|
(dest, regs[0], regs[0]),
|
||||||
|
(regs[0], regs[0], regs[1]),
|
||||||
|
(regs[0], regs[1], regs[0]),
|
||||||
|
(regs[0], regs[0], regs[0]),
|
||||||
|
]
|
||||||
|
if memarg == 2:
|
||||||
|
regset += [
|
||||||
|
(dest, regs[0], -1),
|
||||||
|
(regs[0], regs[0], -1),
|
||||||
|
]
|
||||||
|
elif memarg > 0:
|
||||||
|
raise Exception("Memarg %d" % memarg)
|
||||||
|
elif nreg == 4:
|
||||||
|
regset = [
|
||||||
|
(dest, regs[0], regs[1], regs[2]),
|
||||||
|
(dest, regs[0], regs[0], regs[1]),
|
||||||
|
(dest, regs[0], regs[1], regs[0]),
|
||||||
|
(dest, regs[1], regs[0], regs[0]),
|
||||||
|
(dest, regs[0], regs[0], regs[0]),
|
||||||
|
(regs[0], regs[0], regs[1], regs[2]),
|
||||||
|
(regs[0], regs[1], regs[0], regs[2]),
|
||||||
|
(regs[0], regs[1], regs[2], regs[0]),
|
||||||
|
(regs[0], regs[0], regs[0], regs[1]),
|
||||||
|
(regs[0], regs[0], regs[1], regs[0]),
|
||||||
|
(regs[0], regs[1], regs[0], regs[0]),
|
||||||
|
(regs[0], regs[0], regs[0], regs[0]),
|
||||||
|
]
|
||||||
|
if memarg == 2:
|
||||||
|
regset += [
|
||||||
|
(dest, regs[0], -1, regs[1]),
|
||||||
|
(dest, regs[0], -1, regs[0]),
|
||||||
|
(regs[0], regs[0], -1, regs[1]),
|
||||||
|
(regs[0], regs[1], -1, regs[0]),
|
||||||
|
(regs[0], regs[0], -1, regs[0]),
|
||||||
|
]
|
||||||
|
elif memarg > 0:
|
||||||
|
raise Exception("Memarg4 %d" % memarg)
|
||||||
|
else:
|
||||||
|
raise Exception("Too many regs: %s(%d)" % (self.op, nreg))
|
||||||
|
|
||||||
|
for regv in regset:
|
||||||
|
argstr = []
|
||||||
|
for i in range(nreg):
|
||||||
|
arg = self.args[i]
|
||||||
|
argstr.append(arg.regstr(regv[i]))
|
||||||
|
if immarg is None:
|
||||||
|
yield self.op + ' ' + ','.join(argstr)
|
||||||
|
else:
|
||||||
|
for immval in immarg.vals():
|
||||||
|
yield self.op + ' ' + ','.join(argstr) + ',' + str(immval)
|
||||||
|
|
||||||
|
def split0(s):
|
||||||
|
if s == '':
|
||||||
|
return []
|
||||||
|
return s.split(',')
|
||||||
|
|
||||||
|
def main():
|
||||||
|
n = 0
|
||||||
|
if len(sys.argv) != 3:
|
||||||
|
print("Usage: test-avx.py x86.csv test-avx.h")
|
||||||
|
exit(1)
|
||||||
|
csvfile = open(sys.argv[1], 'r', newline='')
|
||||||
|
with open(sys.argv[2], "w") as outf:
|
||||||
|
outf.write("// Generated by test-avx.py. Do not edit.\n")
|
||||||
|
for row in csv.reader(strip_comments(csvfile)):
|
||||||
|
insn = row[0].replace(',', '').split()
|
||||||
|
if insn[0] in ignore:
|
||||||
|
continue
|
||||||
|
cpuid = row[6]
|
||||||
|
if cpuid in archs:
|
||||||
|
g = InsnGenerator(insn[0], insn[1:])
|
||||||
|
for insn in g.gen():
|
||||||
|
outf.write('TEST(%d, "%s", %s)\n' % (n, insn, g.optype))
|
||||||
|
n += 1
|
||||||
|
outf.write("#undef TEST\n")
|
||||||
|
csvfile.close()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
@ -1,6 +1,66 @@
|
|||||||
/* See if various BMI2 instructions give expected results */
|
/* See if various BMI2 instructions give expected results */
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define insn1q(name, arg0) \
|
||||||
|
static inline uint64_t name##q(uint64_t arg0) \
|
||||||
|
{ \
|
||||||
|
uint64_t result64; \
|
||||||
|
asm volatile (#name "q %1, %0" : "=r"(result64) : "rm"(arg0)); \
|
||||||
|
return result64; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define insn1l(name, arg0) \
|
||||||
|
static inline uint32_t name##l(uint32_t arg0) \
|
||||||
|
{ \
|
||||||
|
uint32_t result32; \
|
||||||
|
asm volatile (#name "l %k1, %k0" : "=r"(result32) : "rm"(arg0)); \
|
||||||
|
return result32; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define insn2q(name, arg0, c0, arg1, c1) \
|
||||||
|
static inline uint64_t name##q(uint64_t arg0, uint64_t arg1) \
|
||||||
|
{ \
|
||||||
|
uint64_t result64; \
|
||||||
|
asm volatile (#name "q %2, %1, %0" : "=r"(result64) : c0(arg0), c1(arg1)); \
|
||||||
|
return result64; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define insn2l(name, arg0, c0, arg1, c1) \
|
||||||
|
static inline uint32_t name##l(uint32_t arg0, uint32_t arg1) \
|
||||||
|
{ \
|
||||||
|
uint32_t result32; \
|
||||||
|
asm volatile (#name "l %k2, %k1, %k0" : "=r"(result32) : c0(arg0), c1(arg1)); \
|
||||||
|
return result32; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __x86_64
|
||||||
|
insn2q(pext, src, "r", mask, "rm")
|
||||||
|
insn2q(pdep, src, "r", mask, "rm")
|
||||||
|
insn2q(andn, clear, "rm", val, "r")
|
||||||
|
insn2q(bextr, range, "rm", val, "r")
|
||||||
|
insn2q(bzhi, pos, "rm", val, "r")
|
||||||
|
insn2q(rorx, val, "r", n, "i")
|
||||||
|
insn2q(sarx, val, "rm", n, "r")
|
||||||
|
insn2q(shlx, val, "rm", n, "r")
|
||||||
|
insn2q(shrx, val, "rm", n, "r")
|
||||||
|
insn1q(blsi, src)
|
||||||
|
insn1q(blsmsk, src)
|
||||||
|
insn1q(blsr, src)
|
||||||
|
#endif
|
||||||
|
insn2l(pext, src, "r", mask, "rm")
|
||||||
|
insn2l(pdep, src, "r", mask, "rm")
|
||||||
|
insn2l(andn, clear, "rm", val, "r")
|
||||||
|
insn2l(bextr, range, "rm", val, "r")
|
||||||
|
insn2l(bzhi, pos, "rm", val, "r")
|
||||||
|
insn2l(rorx, val, "r", n, "i")
|
||||||
|
insn2l(sarx, val, "rm", n, "r")
|
||||||
|
insn2l(shlx, val, "rm", n, "r")
|
||||||
|
insn2l(shrx, val, "rm", n, "r")
|
||||||
|
insn1l(blsi, src)
|
||||||
|
insn1l(blsmsk, src)
|
||||||
|
insn1l(blsr, src)
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
uint64_t ehlo = 0x202020204f4c4845ull;
|
uint64_t ehlo = 0x202020204f4c4845ull;
|
||||||
@ -11,32 +71,125 @@ int main(int argc, char *argv[]) {
|
|||||||
uint64_t result64;
|
uint64_t result64;
|
||||||
|
|
||||||
/* 64 bits */
|
/* 64 bits */
|
||||||
asm volatile ("pextq %2, %1, %0" : "=r"(result64) : "r"(ehlo), "m"(mask));
|
result64 = andnq(mask, ehlo);
|
||||||
|
assert(result64 == 0x002020204d4c4844);
|
||||||
|
|
||||||
|
result64 = pextq(ehlo, mask);
|
||||||
assert(result64 == 133);
|
assert(result64 == 133);
|
||||||
|
|
||||||
asm volatile ("pdepq %2, %1, %0" : "=r"(result64) : "r"(result64), "m"(mask));
|
result64 = pdepq(result64, mask);
|
||||||
assert(result64 == (ehlo & mask));
|
assert(result64 == (ehlo & mask));
|
||||||
|
|
||||||
asm volatile ("pextq %2, %1, %0" : "=r"(result64) : "r"(-1ull), "m"(mask));
|
result64 = pextq(-1ull, mask);
|
||||||
assert(result64 == 511); /* mask has 9 bits set */
|
assert(result64 == 511); /* mask has 9 bits set */
|
||||||
|
|
||||||
asm volatile ("pdepq %2, %1, %0" : "=r"(result64) : "r"(-1ull), "m"(mask));
|
result64 = pdepq(-1ull, mask);
|
||||||
assert(result64 == mask);
|
assert(result64 == mask);
|
||||||
|
|
||||||
|
result64 = bextrq(mask, 0x3f00);
|
||||||
|
assert(result64 == (mask & ~INT64_MIN));
|
||||||
|
|
||||||
|
result64 = bextrq(mask, 0x1038);
|
||||||
|
assert(result64 == 0xa0);
|
||||||
|
|
||||||
|
result64 = bextrq(mask, 0x10f8);
|
||||||
|
assert(result64 == 0);
|
||||||
|
|
||||||
|
result64 = blsiq(0x30);
|
||||||
|
assert(result64 == 0x10);
|
||||||
|
|
||||||
|
result64 = blsiq(0x30ull << 32);
|
||||||
|
assert(result64 == 0x10ull << 32);
|
||||||
|
|
||||||
|
result64 = blsmskq(0x30);
|
||||||
|
assert(result64 == 0x1f);
|
||||||
|
|
||||||
|
result64 = blsrq(0x30);
|
||||||
|
assert(result64 == 0x20);
|
||||||
|
|
||||||
|
result64 = blsrq(0x30ull << 32);
|
||||||
|
assert(result64 == 0x20ull << 32);
|
||||||
|
|
||||||
|
result64 = bzhiq(mask, 0x3f);
|
||||||
|
assert(result64 == (mask & ~INT64_MIN));
|
||||||
|
|
||||||
|
result64 = bzhiq(mask, 0x1f);
|
||||||
|
assert(result64 == (mask & ~(-1 << 30)));
|
||||||
|
|
||||||
|
result64 = rorxq(0x2132435465768798, 8);
|
||||||
|
assert(result64 == 0x9821324354657687);
|
||||||
|
|
||||||
|
result64 = sarxq(0xffeeddccbbaa9988, 8);
|
||||||
|
assert(result64 == 0xffffeeddccbbaa99);
|
||||||
|
|
||||||
|
result64 = sarxq(0x77eeddccbbaa9988, 8 | 64);
|
||||||
|
assert(result64 == 0x0077eeddccbbaa99);
|
||||||
|
|
||||||
|
result64 = shrxq(0xffeeddccbbaa9988, 8);
|
||||||
|
assert(result64 == 0x00ffeeddccbbaa99);
|
||||||
|
|
||||||
|
result64 = shrxq(0x77eeddccbbaa9988, 8 | 192);
|
||||||
|
assert(result64 == 0x0077eeddccbbaa99);
|
||||||
|
|
||||||
|
result64 = shlxq(0xffeeddccbbaa9988, 8);
|
||||||
|
assert(result64 == 0xeeddccbbaa998800);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* 32 bits */
|
/* 32 bits */
|
||||||
asm volatile ("pextl %2, %k1, %k0" : "=r"(result32) : "r"((uint32_t) ehlo), "m"(mask));
|
result32 = andnl(mask, ehlo);
|
||||||
|
assert(result32 == 0x04d4c4844);
|
||||||
|
|
||||||
|
result32 = pextl((uint32_t) ehlo, mask);
|
||||||
assert(result32 == 5);
|
assert(result32 == 5);
|
||||||
|
|
||||||
asm volatile ("pdepl %2, %k1, %k0" : "=r"(result32) : "r"(result32), "m"(mask));
|
result32 = pdepl(result32, mask);
|
||||||
assert(result32 == (uint32_t)(ehlo & mask));
|
assert(result32 == (uint32_t)(ehlo & mask));
|
||||||
|
|
||||||
asm volatile ("pextl %2, %k1, %k0" : "=r"(result32) : "r"(-1ull), "m"(mask));
|
result32 = pextl(-1u, mask);
|
||||||
assert(result32 == 7); /* mask has 3 bits set */
|
assert(result32 == 7); /* mask has 3 bits set */
|
||||||
|
|
||||||
asm volatile ("pdepl %2, %k1, %k0" : "=r"(result32) : "r"(-1ull), "m"(mask));
|
result32 = pdepl(-1u, mask);
|
||||||
assert(result32 == (uint32_t)mask);
|
assert(result32 == (uint32_t)mask);
|
||||||
|
|
||||||
|
result32 = bextrl(mask, 0x1f00);
|
||||||
|
assert(result32 == (mask & ~INT32_MIN));
|
||||||
|
|
||||||
|
result32 = bextrl(ehlo, 0x1018);
|
||||||
|
assert(result32 == 0x4f);
|
||||||
|
|
||||||
|
result32 = bextrl(mask, 0x1038);
|
||||||
|
assert(result32 == 0);
|
||||||
|
|
||||||
|
result32 = blsil(0xffff);
|
||||||
|
assert(result32 == 1);
|
||||||
|
|
||||||
|
result32 = blsmskl(0x300);
|
||||||
|
assert(result32 == 0x1ff);
|
||||||
|
|
||||||
|
result32 = blsrl(0xffc);
|
||||||
|
assert(result32 == 0xff8);
|
||||||
|
|
||||||
|
result32 = bzhil(mask, 0xf);
|
||||||
|
assert(result32 == 1);
|
||||||
|
|
||||||
|
result32 = rorxl(0x65768798, 8);
|
||||||
|
assert(result32 == 0x98657687);
|
||||||
|
|
||||||
|
result32 = sarxl(0xffeeddcc, 8);
|
||||||
|
assert(result32 == 0xffffeedd);
|
||||||
|
|
||||||
|
result32 = sarxl(0x77eeddcc, 8 | 32);
|
||||||
|
assert(result32 == 0x0077eedd);
|
||||||
|
|
||||||
|
result32 = shrxl(0xffeeddcc, 8);
|
||||||
|
assert(result32 == 0x00ffeedd);
|
||||||
|
|
||||||
|
result32 = shrxl(0x77eeddcc, 8 | 128);
|
||||||
|
assert(result32 == 0x0077eedd);
|
||||||
|
|
||||||
|
result32 = shlxl(0xffeeddcc, 8);
|
||||||
|
assert(result32 == 0xeeddcc00);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
4658
tests/tcg/i386/x86.csv
Normal file
4658
tests/tcg/i386/x86.csv
Normal file
File diff suppressed because it is too large
Load Diff
@ -14,7 +14,10 @@ TESTS=$(MULTIARCH_TESTS) $(X86_64_TESTS) test-x86_64
|
|||||||
else
|
else
|
||||||
TESTS=$(MULTIARCH_TESTS)
|
TESTS=$(MULTIARCH_TESTS)
|
||||||
endif
|
endif
|
||||||
QEMU_OPTS += -cpu max
|
|
||||||
|
run-test-i386-ssse3: QEMU_OPTS += -cpu max
|
||||||
|
run-test-avx: QEMU_OPTS += -cpu max
|
||||||
|
run-plugin-test-i386-ssse3-%: QEMU_OPTS += -cpu max
|
||||||
|
|
||||||
test-x86_64: LDFLAGS+=-lm -lc
|
test-x86_64: LDFLAGS+=-lm -lc
|
||||||
test-x86_64: test-i386.c test-i386.h test-i386-shift.h test-i386-muldiv.h
|
test-x86_64: test-i386.c test-i386.h test-i386-shift.h test-i386-muldiv.h
|
||||||
|
Loading…
Reference in New Issue
Block a user