Merge tag 'for-upstream' of https://repo.or.cz/qemu/kevin into staging
Block layer patches
- Graph locking part 4 (node management)
- qemu-img map: report compressed data blocks
- block-backend: process I/O in the current AioContext
# -----BEGIN PGP SIGNATURE-----
#
# iQJFBAABCAAvFiEE3D3rFZqa+V09dFb+fwmycsiPL9YFAmULHnURHGt3b2xmQHJl
# ZGhhdC5jb20ACgkQfwmycsiPL9aB5hAAqH8To7WIUtg1rj1PY809ck78ghm18PKg
# TNdN7IbrXQghX5foh2VgPwVVl+JaW2CSrJYWQcAO6AbvFduNIi9iKzI6RT0xKXpb
# b8oQXS7zntFzwBv8ohOU5NSVJOgVmNP4h5qJIMmXgB9ZcLFG40zggVH2qQT7guUf
# 9MAc81kI/d5vvSHY0ZjdHjNOgwG4q1j8yytL7OFqWUfB8sXloUCA9lT7w4jIYD8L
# v2StUOLWB01Zts2o8SCNaFxuajs6wUee8b/DM1cyPyLy4KtOdXvLKhq2NlXpLo2i
# aZFr4PtizTVwrQZIJttA9jqM+QCsDOsiSat3BLNNsKUaCWHZB0rOGLCzMCtisyOo
# 4PzuL4UI21ik2zieO1qVM+Thqvw16kHtp6dD9pGk4X4ogGreGYEIxzBl79luR+AV
# NCRizoeFWTHKymS1tSoKrWT9ZNHcLmwemO6Tt1rMYk9jV3T4uY5e1NwxaUavEfsX
# f8dLfQjhNiySOoDknT1OSerBOVdTXURS2ri5H3GZxrxvJ4jOeFkn52C8r3YlZ3Wp
# Cr9LCUJZeXgwY+Q1JQ3D4VLY8aZ83txpw6XKEy0eTEv5wxkBj5LWhXx7hNb5F3lg
# bqaRYijVJn+P82wVxlftIzMfNeVBFHzFE90taPV5grJjr8lgrGBFmD7Puc97kfDX
# oTDBwRxJeew=
# =qTNA
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed 20 Sep 2023 12:31:49 EDT
# gpg: using RSA key DC3DEB159A9AF95D3D7456FE7F09B272C88F2FD6
# gpg: issuer "kwolf@redhat.com"
# gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" [full]
# Primary key fingerprint: DC3D EB15 9A9A F95D 3D74 56FE 7F09 B272 C88F 2FD6
* tag 'for-upstream' of https://repo.or.cz/qemu/kevin: (28 commits)
block: mark aio_poll as non-coroutine
block-backend: process zoned requests in the current AioContext
block-backend: process I/O in the current AioContext
test-bdrv-drain: avoid race with BH in IOThread drain test
block: remove AIOCBInfo->get_aio_context()
qemu-img: map: report compressed data blocks
block: add BDRV_BLOCK_COMPRESSED flag for bdrv_block_status()
block: Mark bdrv_add/del_child() and caller GRAPH_WRLOCK
block: Mark bdrv_unref_child() GRAPH_WRLOCK
block: Mark bdrv_root_unref_child() GRAPH_WRLOCK
block: Take graph rdlock in bdrv_change_aio_context()
block: Take graph rdlock in bdrv_drop_intermediate()
block: Mark bdrv_parent_cb_change_media() GRAPH_RDLOCK
block: Mark bdrv_child_perm() GRAPH_RDLOCK
block: Mark bdrv_get_cumulative_perm() and callers GRAPH_RDLOCK
block: Mark bdrv_parent_perms_conflict() and callers GRAPH_RDLOCK
block: Mark bdrv_attach_child() GRAPH_WRLOCK
block: Call transaction callbacks with lock held
block: Mark bdrv_attach_child_common() GRAPH_WRLOCK
block: Mark bdrv_replace_child_tran() GRAPH_WRLOCK
...
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
diff --git a/.gitlab-ci.d/base.yml b/.gitlab-ci.d/base.yml
index 188a770..ef173a3 100644
--- a/.gitlab-ci.d/base.yml
+++ b/.gitlab-ci.d/base.yml
@@ -68,7 +68,7 @@
#############################################################
# Stage 2: fine tune execution of jobs in specific scenarios
- # where the catch all logic is inapprorpaite
+ # where the catch all logic is inappropriate
#############################################################
# Optional jobs should not be run unless manually triggered
diff --git a/.gitlab-ci.d/cirrus.yml b/.gitlab-ci.d/cirrus.yml
index 41d64d6..e7f1f83 100644
--- a/.gitlab-ci.d/cirrus.yml
+++ b/.gitlab-ci.d/cirrus.yml
@@ -15,8 +15,10 @@
stage: build
image: registry.gitlab.com/libvirt/libvirt-ci/cirrus-run:master
needs: []
+ # 20 mins larger than "timeout_in" in cirrus/build.yml
+ # as there's often a 5-10 minute delay before Cirrus CI
+ # actually starts the task
timeout: 80m
- allow_failure: true
script:
- source .gitlab-ci.d/cirrus/$NAME.vars
- sed -e "s|[@]CI_REPOSITORY_URL@|$CI_REPOSITORY_URL|g"
diff --git a/.gitlab-ci.d/cirrus/build.yml b/.gitlab-ci.d/cirrus/build.yml
index a944490..29d55c4 100644
--- a/.gitlab-ci.d/cirrus/build.yml
+++ b/.gitlab-ci.d/cirrus/build.yml
@@ -16,6 +16,8 @@
TEST_TARGETS: "@TEST_TARGETS@"
build_task:
+ # A little shorter than GitLab timeout in ../cirrus.yml
+ timeout_in: 60m
install_script:
- @UPDATE_COMMAND@
- @INSTALL_COMMAND@ @PKGS@
diff --git a/backends/cryptodev.c b/backends/cryptodev.c
index 4d183f7..e5006bd 100644
--- a/backends/cryptodev.c
+++ b/backends/cryptodev.c
@@ -252,10 +252,11 @@
continue;
}
- throttle_account(&backend->ts, true, ret);
+ throttle_account(&backend->ts, THROTTLE_WRITE, ret);
cryptodev_backend_operation(backend, op_info);
if (throttle_enabled(&backend->tc) &&
- throttle_schedule_timer(&backend->ts, &backend->tt, true)) {
+ throttle_schedule_timer(&backend->ts, &backend->tt,
+ THROTTLE_WRITE)) {
break;
}
}
@@ -271,7 +272,7 @@
goto do_account;
}
- if (throttle_schedule_timer(&backend->ts, &backend->tt, true) ||
+ if (throttle_schedule_timer(&backend->ts, &backend->tt, THROTTLE_WRITE) ||
!QTAILQ_EMPTY(&backend->opinfos)) {
QTAILQ_INSERT_TAIL(&backend->opinfos, op_info, next);
return 0;
@@ -283,7 +284,7 @@
return ret;
}
- throttle_account(&backend->ts, true, ret);
+ throttle_account(&backend->ts, THROTTLE_WRITE, ret);
return cryptodev_backend_operation(backend, op_info);
}
@@ -341,8 +342,7 @@
if (!enabled) {
throttle_init(&backend->ts);
throttle_timers_init(&backend->tt, qemu_get_aio_context(),
- QEMU_CLOCK_REALTIME,
- cryptodev_backend_throttle_timer_cb, /* FIXME */
+ QEMU_CLOCK_REALTIME, NULL,
cryptodev_backend_throttle_timer_cb, backend);
}
diff --git a/block/block-backend.c b/block/block-backend.c
index 9dbdbe5..efe2e7c 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -1355,7 +1355,7 @@
/* throttling disk I/O */
if (blk->public.throttle_group_member.throttle_state) {
throttle_group_co_io_limits_intercept(&blk->public.throttle_group_member,
- bytes, false);
+ bytes, THROTTLE_READ);
}
ret = bdrv_co_preadv_part(blk->root, offset, bytes, qiov, qiov_offset,
@@ -1429,7 +1429,7 @@
/* throttling disk I/O */
if (blk->public.throttle_group_member.throttle_state) {
throttle_group_co_io_limits_intercept(&blk->public.throttle_group_member,
- bytes, true);
+ bytes, THROTTLE_WRITE);
}
if (!blk->enable_write_cache) {
diff --git a/block/file-posix.c b/block/file-posix.c
index 4757914..50e2b20 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -1412,11 +1412,9 @@
BlockZoneModel zoned;
int ret;
- bs->bl.zoned = BLK_Z_NONE;
-
ret = get_sysfs_zoned_model(st, &zoned);
if (ret < 0 || zoned == BLK_Z_NONE) {
- return;
+ goto no_zoned;
}
bs->bl.zoned = zoned;
@@ -1437,10 +1435,10 @@
if (ret < 0) {
error_setg_errno(errp, -ret, "Unable to read chunk_sectors "
"sysfs attribute");
- return;
+ goto no_zoned;
} else if (!ret) {
error_setg(errp, "Read 0 from chunk_sectors sysfs attribute");
- return;
+ goto no_zoned;
}
bs->bl.zone_size = ret << BDRV_SECTOR_BITS;
@@ -1448,10 +1446,10 @@
if (ret < 0) {
error_setg_errno(errp, -ret, "Unable to read nr_zones "
"sysfs attribute");
- return;
+ goto no_zoned;
} else if (!ret) {
error_setg(errp, "Read 0 from nr_zones sysfs attribute");
- return;
+ goto no_zoned;
}
bs->bl.nr_zones = ret;
@@ -1472,10 +1470,15 @@
ret = get_zones_wp(bs, s->fd, 0, bs->bl.nr_zones, 0);
if (ret < 0) {
error_setg_errno(errp, -ret, "report wps failed");
- bs->wps = NULL;
- return;
+ goto no_zoned;
}
qemu_co_mutex_init(&bs->wps->colock);
+ return;
+
+no_zoned:
+ bs->bl.zoned = BLK_Z_NONE;
+ g_free(bs->wps);
+ bs->wps = NULL;
}
#else /* !defined(CONFIG_BLKZONED) */
static void raw_refresh_zoned_limits(BlockDriverState *bs, struct stat *st,
@@ -2452,9 +2455,10 @@
if (fd_open(bs) < 0)
return -EIO;
#if defined(CONFIG_BLKZONED)
- if ((type & (QEMU_AIO_WRITE | QEMU_AIO_ZONE_APPEND)) && bs->wps) {
+ if ((type & (QEMU_AIO_WRITE | QEMU_AIO_ZONE_APPEND)) &&
+ bs->bl.zoned != BLK_Z_NONE) {
qemu_co_mutex_lock(&bs->wps->colock);
- if (type & QEMU_AIO_ZONE_APPEND && bs->bl.zone_size) {
+ if (type & QEMU_AIO_ZONE_APPEND) {
int index = offset / bs->bl.zone_size;
offset = bs->wps->wp[index];
}
@@ -2502,11 +2506,10 @@
out:
#if defined(CONFIG_BLKZONED)
-{
- BlockZoneWps *wps = bs->wps;
- if (ret == 0) {
- if ((type & (QEMU_AIO_WRITE | QEMU_AIO_ZONE_APPEND))
- && wps && bs->bl.zone_size) {
+ if ((type & (QEMU_AIO_WRITE | QEMU_AIO_ZONE_APPEND)) &&
+ bs->bl.zoned != BLK_Z_NONE) {
+ BlockZoneWps *wps = bs->wps;
+ if (ret == 0) {
uint64_t *wp = &wps->wp[offset / bs->bl.zone_size];
if (!BDRV_ZT_IS_CONV(*wp)) {
if (type & QEMU_AIO_ZONE_APPEND) {
@@ -2519,17 +2522,12 @@
*wp = offset + bytes;
}
}
- }
- } else {
- if (type & (QEMU_AIO_WRITE | QEMU_AIO_ZONE_APPEND)) {
+ } else {
update_zones_wp(bs, s->fd, 0, 1);
}
- }
- if ((type & (QEMU_AIO_WRITE | QEMU_AIO_ZONE_APPEND)) && wps) {
qemu_co_mutex_unlock(&wps->colock);
}
-}
#endif
return ret;
}
diff --git a/block/throttle-groups.c b/block/throttle-groups.c
index fb203c3..3eda4c4 100644
--- a/block/throttle-groups.c
+++ b/block/throttle-groups.c
@@ -37,7 +37,7 @@
static void throttle_group_obj_init(Object *obj);
static void throttle_group_obj_complete(UserCreatable *obj, Error **errp);
-static void timer_cb(ThrottleGroupMember *tgm, bool is_write);
+static void timer_cb(ThrottleGroupMember *tgm, ThrottleDirection direction);
/* The ThrottleGroup structure (with its ThrottleState) is shared
* among different ThrottleGroupMembers and it's independent from
@@ -73,8 +73,8 @@
QemuMutex lock; /* This lock protects the following four fields */
ThrottleState ts;
QLIST_HEAD(, ThrottleGroupMember) head;
- ThrottleGroupMember *tokens[2];
- bool any_timer_armed[2];
+ ThrottleGroupMember *tokens[THROTTLE_MAX];
+ bool any_timer_armed[THROTTLE_MAX];
QEMUClockType clock_type;
/* This field is protected by the global QEMU mutex */
@@ -197,13 +197,13 @@
* This assumes that tg->lock is held.
*
* @tgm: the ThrottleGroupMember
- * @is_write: the type of operation (read/write)
+ * @direction: the ThrottleDirection
* @ret: whether the ThrottleGroupMember has pending requests.
*/
static inline bool tgm_has_pending_reqs(ThrottleGroupMember *tgm,
- bool is_write)
+ ThrottleDirection direction)
{
- return tgm->pending_reqs[is_write];
+ return tgm->pending_reqs[direction];
}
/* Return the next ThrottleGroupMember in the round-robin sequence with pending
@@ -212,12 +212,12 @@
* This assumes that tg->lock is held.
*
* @tgm: the current ThrottleGroupMember
- * @is_write: the type of operation (read/write)
+ * @direction: the ThrottleDirection
* @ret: the next ThrottleGroupMember with pending requests, or tgm if
* there is none.
*/
static ThrottleGroupMember *next_throttle_token(ThrottleGroupMember *tgm,
- bool is_write)
+ ThrottleDirection direction)
{
ThrottleState *ts = tgm->throttle_state;
ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
@@ -227,16 +227,16 @@
* it's being drained. Skip the round-robin search and return tgm
* immediately if it has pending requests. Otherwise we could be
* forcing it to wait for other member's throttled requests. */
- if (tgm_has_pending_reqs(tgm, is_write) &&
+ if (tgm_has_pending_reqs(tgm, direction) &&
qatomic_read(&tgm->io_limits_disabled)) {
return tgm;
}
- start = token = tg->tokens[is_write];
+ start = token = tg->tokens[direction];
/* get next bs round in round robin style */
token = throttle_group_next_tgm(token);
- while (token != start && !tgm_has_pending_reqs(token, is_write)) {
+ while (token != start && !tgm_has_pending_reqs(token, direction)) {
token = throttle_group_next_tgm(token);
}
@@ -244,12 +244,12 @@
* then decide the token is the current tgm because chances are
* the current tgm got the current request queued.
*/
- if (token == start && !tgm_has_pending_reqs(token, is_write)) {
+ if (token == start && !tgm_has_pending_reqs(token, direction)) {
token = tgm;
}
/* Either we return the original TGM, or one with pending requests */
- assert(token == tgm || tgm_has_pending_reqs(token, is_write));
+ assert(token == tgm || tgm_has_pending_reqs(token, direction));
return token;
}
@@ -261,11 +261,11 @@
* This assumes that tg->lock is held.
*
* @tgm: the current ThrottleGroupMember
- * @is_write: the type of operation (read/write)
+ * @direction: the ThrottleDirection
* @ret: whether the I/O request needs to be throttled or not
*/
static bool throttle_group_schedule_timer(ThrottleGroupMember *tgm,
- bool is_write)
+ ThrottleDirection direction)
{
ThrottleState *ts = tgm->throttle_state;
ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
@@ -277,16 +277,16 @@
}
/* Check if any of the timers in this group is already armed */
- if (tg->any_timer_armed[is_write]) {
+ if (tg->any_timer_armed[direction]) {
return true;
}
- must_wait = throttle_schedule_timer(ts, tt, is_write);
+ must_wait = throttle_schedule_timer(ts, tt, direction);
/* If a timer just got armed, set tgm as the current token */
if (must_wait) {
- tg->tokens[is_write] = tgm;
- tg->any_timer_armed[is_write] = true;
+ tg->tokens[direction] = tgm;
+ tg->any_timer_armed[direction] = true;
}
return must_wait;
@@ -296,15 +296,15 @@
* any request was actually pending.
*
* @tgm: the current ThrottleGroupMember
- * @is_write: the type of operation (read/write)
+ * @direction: the ThrottleDirection
*/
static bool coroutine_fn throttle_group_co_restart_queue(ThrottleGroupMember *tgm,
- bool is_write)
+ ThrottleDirection direction)
{
bool ret;
qemu_co_mutex_lock(&tgm->throttled_reqs_lock);
- ret = qemu_co_queue_next(&tgm->throttled_reqs[is_write]);
+ ret = qemu_co_queue_next(&tgm->throttled_reqs[direction]);
qemu_co_mutex_unlock(&tgm->throttled_reqs_lock);
return ret;
@@ -315,9 +315,10 @@
* This assumes that tg->lock is held.
*
* @tgm: the current ThrottleGroupMember
- * @is_write: the type of operation (read/write)
+ * @direction: the ThrottleDirection
*/
-static void schedule_next_request(ThrottleGroupMember *tgm, bool is_write)
+static void schedule_next_request(ThrottleGroupMember *tgm,
+ ThrottleDirection direction)
{
ThrottleState *ts = tgm->throttle_state;
ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
@@ -325,27 +326,27 @@
ThrottleGroupMember *token;
/* Check if there's any pending request to schedule next */
- token = next_throttle_token(tgm, is_write);
- if (!tgm_has_pending_reqs(token, is_write)) {
+ token = next_throttle_token(tgm, direction);
+ if (!tgm_has_pending_reqs(token, direction)) {
return;
}
/* Set a timer for the request if it needs to be throttled */
- must_wait = throttle_group_schedule_timer(token, is_write);
+ must_wait = throttle_group_schedule_timer(token, direction);
/* If it doesn't have to wait, queue it for immediate execution */
if (!must_wait) {
/* Give preference to requests from the current tgm */
if (qemu_in_coroutine() &&
- throttle_group_co_restart_queue(tgm, is_write)) {
+ throttle_group_co_restart_queue(tgm, direction)) {
token = tgm;
} else {
ThrottleTimers *tt = &token->throttle_timers;
int64_t now = qemu_clock_get_ns(tg->clock_type);
- timer_mod(tt->timers[is_write], now);
- tg->any_timer_armed[is_write] = true;
+ timer_mod(tt->timers[direction], now);
+ tg->any_timer_armed[direction] = true;
}
- tg->tokens[is_write] = token;
+ tg->tokens[direction] = token;
}
}
@@ -355,48 +356,49 @@
*
* @tgm: the current ThrottleGroupMember
* @bytes: the number of bytes for this I/O
- * @is_write: the type of operation (read/write)
+ * @direction: the ThrottleDirection
*/
void coroutine_fn throttle_group_co_io_limits_intercept(ThrottleGroupMember *tgm,
int64_t bytes,
- bool is_write)
+ ThrottleDirection direction)
{
bool must_wait;
ThrottleGroupMember *token;
ThrottleGroup *tg = container_of(tgm->throttle_state, ThrottleGroup, ts);
assert(bytes >= 0);
+ assert(direction < THROTTLE_MAX);
qemu_mutex_lock(&tg->lock);
/* First we check if this I/O has to be throttled. */
- token = next_throttle_token(tgm, is_write);
- must_wait = throttle_group_schedule_timer(token, is_write);
+ token = next_throttle_token(tgm, direction);
+ must_wait = throttle_group_schedule_timer(token, direction);
/* Wait if there's a timer set or queued requests of this type */
- if (must_wait || tgm->pending_reqs[is_write]) {
- tgm->pending_reqs[is_write]++;
+ if (must_wait || tgm->pending_reqs[direction]) {
+ tgm->pending_reqs[direction]++;
qemu_mutex_unlock(&tg->lock);
qemu_co_mutex_lock(&tgm->throttled_reqs_lock);
- qemu_co_queue_wait(&tgm->throttled_reqs[is_write],
+ qemu_co_queue_wait(&tgm->throttled_reqs[direction],
&tgm->throttled_reqs_lock);
qemu_co_mutex_unlock(&tgm->throttled_reqs_lock);
qemu_mutex_lock(&tg->lock);
- tgm->pending_reqs[is_write]--;
+ tgm->pending_reqs[direction]--;
}
/* The I/O will be executed, so do the accounting */
- throttle_account(tgm->throttle_state, is_write, bytes);
+ throttle_account(tgm->throttle_state, direction, bytes);
/* Schedule the next request */
- schedule_next_request(tgm, is_write);
+ schedule_next_request(tgm, direction);
qemu_mutex_unlock(&tg->lock);
}
typedef struct {
ThrottleGroupMember *tgm;
- bool is_write;
+ ThrottleDirection direction;
} RestartData;
static void coroutine_fn throttle_group_restart_queue_entry(void *opaque)
@@ -405,16 +407,16 @@
ThrottleGroupMember *tgm = data->tgm;
ThrottleState *ts = tgm->throttle_state;
ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
- bool is_write = data->is_write;
+ ThrottleDirection direction = data->direction;
bool empty_queue;
- empty_queue = !throttle_group_co_restart_queue(tgm, is_write);
+ empty_queue = !throttle_group_co_restart_queue(tgm, direction);
/* If the request queue was empty then we have to take care of
* scheduling the next one */
if (empty_queue) {
qemu_mutex_lock(&tg->lock);
- schedule_next_request(tgm, is_write);
+ schedule_next_request(tgm, direction);
qemu_mutex_unlock(&tg->lock);
}
@@ -424,18 +426,19 @@
aio_wait_kick();
}
-static void throttle_group_restart_queue(ThrottleGroupMember *tgm, bool is_write)
+static void throttle_group_restart_queue(ThrottleGroupMember *tgm,
+ ThrottleDirection direction)
{
Coroutine *co;
RestartData *rd = g_new0(RestartData, 1);
rd->tgm = tgm;
- rd->is_write = is_write;
+ rd->direction = direction;
/* This function is called when a timer is fired or when
* throttle_group_restart_tgm() is called. Either way, there can
* be no timer pending on this tgm at this point */
- assert(!timer_pending(tgm->throttle_timers.timers[is_write]));
+ assert(!timer_pending(tgm->throttle_timers.timers[direction]));
qatomic_inc(&tgm->restart_pending);
@@ -445,18 +448,18 @@
void throttle_group_restart_tgm(ThrottleGroupMember *tgm)
{
- int i;
+ ThrottleDirection dir;
if (tgm->throttle_state) {
- for (i = 0; i < 2; i++) {
- QEMUTimer *t = tgm->throttle_timers.timers[i];
+ for (dir = THROTTLE_READ; dir < THROTTLE_MAX; dir++) {
+ QEMUTimer *t = tgm->throttle_timers.timers[dir];
if (timer_pending(t)) {
/* If there's a pending timer on this tgm, fire it now */
timer_del(t);
- timer_cb(tgm, i);
+ timer_cb(tgm, dir);
} else {
/* Else run the next request from the queue manually */
- throttle_group_restart_queue(tgm, i);
+ throttle_group_restart_queue(tgm, dir);
}
}
}
@@ -500,30 +503,30 @@
* because it had been throttled.
*
* @tgm: the ThrottleGroupMember whose request had been throttled
- * @is_write: the type of operation (read/write)
+ * @direction: the ThrottleDirection
*/
-static void timer_cb(ThrottleGroupMember *tgm, bool is_write)
+static void timer_cb(ThrottleGroupMember *tgm, ThrottleDirection direction)
{
ThrottleState *ts = tgm->throttle_state;
ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
/* The timer has just been fired, so we can update the flag */
qemu_mutex_lock(&tg->lock);
- tg->any_timer_armed[is_write] = false;
+ tg->any_timer_armed[direction] = false;
qemu_mutex_unlock(&tg->lock);
/* Run the request that was waiting for this timer */
- throttle_group_restart_queue(tgm, is_write);
+ throttle_group_restart_queue(tgm, direction);
}
static void read_timer_cb(void *opaque)
{
- timer_cb(opaque, false);
+ timer_cb(opaque, THROTTLE_READ);
}
static void write_timer_cb(void *opaque)
{
- timer_cb(opaque, true);
+ timer_cb(opaque, THROTTLE_WRITE);
}
/* Register a ThrottleGroupMember from the throttling group, also initializing
@@ -541,7 +544,7 @@
const char *groupname,
AioContext *ctx)
{
- int i;
+ ThrottleDirection dir;
ThrottleState *ts = throttle_group_incref(groupname);
ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
@@ -551,10 +554,11 @@
QEMU_LOCK_GUARD(&tg->lock);
/* If the ThrottleGroup is new set this ThrottleGroupMember as the token */
- for (i = 0; i < 2; i++) {
- if (!tg->tokens[i]) {
- tg->tokens[i] = tgm;
+ for (dir = THROTTLE_READ; dir < THROTTLE_MAX; dir++) {
+ if (!tg->tokens[dir]) {
+ tg->tokens[dir] = tgm;
}
+ qemu_co_queue_init(&tgm->throttled_reqs[dir]);
}
QLIST_INSERT_HEAD(&tg->head, tgm, round_robin);
@@ -566,8 +570,6 @@
write_timer_cb,
tgm);
qemu_co_mutex_init(&tgm->throttled_reqs_lock);
- qemu_co_queue_init(&tgm->throttled_reqs[0]);
- qemu_co_queue_init(&tgm->throttled_reqs[1]);
}
/* Unregister a ThrottleGroupMember from its group, removing it from the list,
@@ -585,7 +587,7 @@
ThrottleState *ts = tgm->throttle_state;
ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
ThrottleGroupMember *token;
- int i;
+ ThrottleDirection dir;
if (!ts) {
/* Discard already unregistered tgm */
@@ -596,17 +598,17 @@
AIO_WAIT_WHILE(tgm->aio_context, qatomic_read(&tgm->restart_pending) > 0);
WITH_QEMU_LOCK_GUARD(&tg->lock) {
- for (i = 0; i < 2; i++) {
- assert(tgm->pending_reqs[i] == 0);
- assert(qemu_co_queue_empty(&tgm->throttled_reqs[i]));
- assert(!timer_pending(tgm->throttle_timers.timers[i]));
- if (tg->tokens[i] == tgm) {
+ for (dir = THROTTLE_READ; dir < THROTTLE_MAX; dir++) {
+ assert(tgm->pending_reqs[dir] == 0);
+ assert(qemu_co_queue_empty(&tgm->throttled_reqs[dir]));
+ assert(!timer_pending(tgm->throttle_timers.timers[dir]));
+ if (tg->tokens[dir] == tgm) {
token = throttle_group_next_tgm(tgm);
/* Take care of the case where this is the last tgm in the group */
if (token == tgm) {
token = NULL;
}
- tg->tokens[i] = token;
+ tg->tokens[dir] = token;
}
}
@@ -631,19 +633,20 @@
{
ThrottleGroup *tg = container_of(tgm->throttle_state, ThrottleGroup, ts);
ThrottleTimers *tt = &tgm->throttle_timers;
- int i;
+ ThrottleDirection dir;
/* Requests must have been drained */
- assert(tgm->pending_reqs[0] == 0 && tgm->pending_reqs[1] == 0);
- assert(qemu_co_queue_empty(&tgm->throttled_reqs[0]));
- assert(qemu_co_queue_empty(&tgm->throttled_reqs[1]));
+ for (dir = THROTTLE_READ; dir < THROTTLE_MAX; dir++) {
+ assert(tgm->pending_reqs[dir] == 0);
+ assert(qemu_co_queue_empty(&tgm->throttled_reqs[dir]));
+ }
/* Kick off next ThrottleGroupMember, if necessary */
WITH_QEMU_LOCK_GUARD(&tg->lock) {
- for (i = 0; i < 2; i++) {
- if (timer_pending(tt->timers[i])) {
- tg->any_timer_armed[i] = false;
- schedule_next_request(tgm, i);
+ for (dir = THROTTLE_READ; dir < THROTTLE_MAX; dir++) {
+ if (timer_pending(tt->timers[dir])) {
+ tg->any_timer_armed[dir] = false;
+ schedule_next_request(tgm, dir);
}
}
}
diff --git a/block/throttle.c b/block/throttle.c
index 3aaef18..1098a4a 100644
--- a/block/throttle.c
+++ b/block/throttle.c
@@ -118,7 +118,7 @@
{
ThrottleGroupMember *tgm = bs->opaque;
- throttle_group_co_io_limits_intercept(tgm, bytes, false);
+ throttle_group_co_io_limits_intercept(tgm, bytes, THROTTLE_READ);
return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
}
@@ -128,7 +128,7 @@
QEMUIOVector *qiov, BdrvRequestFlags flags)
{
ThrottleGroupMember *tgm = bs->opaque;
- throttle_group_co_io_limits_intercept(tgm, bytes, true);
+ throttle_group_co_io_limits_intercept(tgm, bytes, THROTTLE_WRITE);
return bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
}
@@ -138,7 +138,7 @@
BdrvRequestFlags flags)
{
ThrottleGroupMember *tgm = bs->opaque;
- throttle_group_co_io_limits_intercept(tgm, bytes, true);
+ throttle_group_co_io_limits_intercept(tgm, bytes, THROTTLE_WRITE);
return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
}
@@ -147,7 +147,7 @@
throttle_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
{
ThrottleGroupMember *tgm = bs->opaque;
- throttle_group_co_io_limits_intercept(tgm, bytes, true);
+ throttle_group_co_io_limits_intercept(tgm, bytes, THROTTLE_WRITE);
return bdrv_co_pdiscard(bs->file, offset, bytes);
}
diff --git a/fsdev/qemu-fsdev-throttle.c b/fsdev/qemu-fsdev-throttle.c
index 5c83a1c..d912da9 100644
--- a/fsdev/qemu-fsdev-throttle.c
+++ b/fsdev/qemu-fsdev-throttle.c
@@ -94,20 +94,22 @@
}
}
-void coroutine_fn fsdev_co_throttle_request(FsThrottle *fst, bool is_write,
+void coroutine_fn fsdev_co_throttle_request(FsThrottle *fst,
+ ThrottleDirection direction,
struct iovec *iov, int iovcnt)
{
+ assert(direction < THROTTLE_MAX);
if (throttle_enabled(&fst->cfg)) {
- if (throttle_schedule_timer(&fst->ts, &fst->tt, is_write) ||
- !qemu_co_queue_empty(&fst->throttled_reqs[is_write])) {
- qemu_co_queue_wait(&fst->throttled_reqs[is_write], NULL);
+ if (throttle_schedule_timer(&fst->ts, &fst->tt, direction) ||
+ !qemu_co_queue_empty(&fst->throttled_reqs[direction])) {
+ qemu_co_queue_wait(&fst->throttled_reqs[direction], NULL);
}
- throttle_account(&fst->ts, is_write, iov_size(iov, iovcnt));
+ throttle_account(&fst->ts, direction, iov_size(iov, iovcnt));
- if (!qemu_co_queue_empty(&fst->throttled_reqs[is_write]) &&
- !throttle_schedule_timer(&fst->ts, &fst->tt, is_write)) {
- qemu_co_queue_next(&fst->throttled_reqs[is_write]);
+ if (!qemu_co_queue_empty(&fst->throttled_reqs[direction]) &&
+ !throttle_schedule_timer(&fst->ts, &fst->tt, direction)) {
+ qemu_co_queue_next(&fst->throttled_reqs[direction]);
}
}
}
diff --git a/fsdev/qemu-fsdev-throttle.h b/fsdev/qemu-fsdev-throttle.h
index a21aecd..daa8ca2 100644
--- a/fsdev/qemu-fsdev-throttle.h
+++ b/fsdev/qemu-fsdev-throttle.h
@@ -23,14 +23,14 @@
ThrottleState ts;
ThrottleTimers tt;
ThrottleConfig cfg;
- CoQueue throttled_reqs[2];
+ CoQueue throttled_reqs[THROTTLE_MAX];
} FsThrottle;
int fsdev_throttle_parse_opts(QemuOpts *, FsThrottle *, Error **);
void fsdev_throttle_init(FsThrottle *);
-void coroutine_fn fsdev_co_throttle_request(FsThrottle *, bool ,
+void coroutine_fn fsdev_co_throttle_request(FsThrottle *, ThrottleDirection ,
struct iovec *, int);
void fsdev_throttle_cleanup(FsThrottle *);
diff --git a/hw/9pfs/cofile.c b/hw/9pfs/cofile.c
index 9c53440..71174c3 100644
--- a/hw/9pfs/cofile.c
+++ b/hw/9pfs/cofile.c
@@ -252,7 +252,7 @@
if (v9fs_request_cancelled(pdu)) {
return -EINTR;
}
- fsdev_co_throttle_request(s->ctx.fst, true, iov, iovcnt);
+ fsdev_co_throttle_request(s->ctx.fst, THROTTLE_WRITE, iov, iovcnt);
v9fs_co_run_in_worker(
{
err = s->ops->pwritev(&s->ctx, &fidp->fs, iov, iovcnt, offset);
@@ -272,7 +272,7 @@
if (v9fs_request_cancelled(pdu)) {
return -EINTR;
}
- fsdev_co_throttle_request(s->ctx.fst, false, iov, iovcnt);
+ fsdev_co_throttle_request(s->ctx.fst, THROTTLE_READ, iov, iovcnt);
v9fs_co_run_in_worker(
{
err = s->ops->preadv(&s->ctx, &fidp->fs, iov, iovcnt, offset);
diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c
index 866e11d..cf28cb9 100644
--- a/hw/hppa/machine.c
+++ b/hw/hppa/machine.c
@@ -133,14 +133,10 @@
fw_cfg_add_file(fw_cfg, "/etc/firmware-min-version",
g_memdup(&val, sizeof(val)), sizeof(val));
- val = cpu_to_le64(HPPA_TLB_ENTRIES);
+ val = cpu_to_le64(HPPA_TLB_ENTRIES - HPPA_BTLB_ENTRIES);
fw_cfg_add_file(fw_cfg, "/etc/cpu/tlb_entries",
g_memdup(&val, sizeof(val)), sizeof(val));
- val = cpu_to_le64(HPPA_BTLB_ENTRIES);
- fw_cfg_add_file(fw_cfg, "/etc/cpu/btlb_entries",
- g_memdup(&val, sizeof(val)), sizeof(val));
-
val = cpu_to_le64(HPA_POWER_BUTTON);
fw_cfg_add_file(fw_cfg, "/etc/power-button-addr",
g_memdup(&val, sizeof(val)), sizeof(val));
@@ -433,6 +429,10 @@
cs->exception_index = -1;
cs->halted = 0;
+
+ /* clear any existing TLB and BTLB entries */
+ memset(cpu[i]->env.tlb, 0, sizeof(cpu[i]->env.tlb));
+ cpu[i]->env.tlb_last = HPPA_BTLB_ENTRIES;
}
/* already initialized by machine_hppa_init()? */
diff --git a/include/block/throttle-groups.h b/include/block/throttle-groups.h
index ff282fc..2355e8d 100644
--- a/include/block/throttle-groups.h
+++ b/include/block/throttle-groups.h
@@ -37,7 +37,7 @@
AioContext *aio_context;
/* throttled_reqs_lock protects the CoQueues for throttled requests. */
CoMutex throttled_reqs_lock;
- CoQueue throttled_reqs[2];
+ CoQueue throttled_reqs[THROTTLE_MAX];
/* Nonzero if the I/O limits are currently being ignored; generally
* it is zero. Accessed with atomic operations.
@@ -54,7 +54,7 @@
* throttle_state tells us if I/O limits are configured. */
ThrottleState *throttle_state;
ThrottleTimers throttle_timers;
- unsigned pending_reqs[2];
+ unsigned pending_reqs[THROTTLE_MAX];
QLIST_ENTRY(ThrottleGroupMember) round_robin;
} ThrottleGroupMember;
@@ -78,7 +78,7 @@
void coroutine_fn throttle_group_co_io_limits_intercept(ThrottleGroupMember *tgm,
int64_t bytes,
- bool is_write);
+ ThrottleDirection direction);
void throttle_group_attach_aio_context(ThrottleGroupMember *tgm,
AioContext *new_context);
void throttle_group_detach_aio_context(ThrottleGroupMember *tgm);
diff --git a/include/qemu/throttle.h b/include/qemu/throttle.h
index 05f6346..181245d 100644
--- a/include/qemu/throttle.h
+++ b/include/qemu/throttle.h
@@ -99,13 +99,18 @@
int64_t previous_leak; /* timestamp of the last leak done */
} ThrottleState;
+typedef enum {
+ THROTTLE_READ = 0,
+ THROTTLE_WRITE,
+ THROTTLE_MAX
+} ThrottleDirection;
+
typedef struct ThrottleTimers {
- QEMUTimer *timers[2]; /* timers used to do the throttling */
+ QEMUTimer *timers[THROTTLE_MAX]; /* timers used to do the throttling */
QEMUClockType clock_type; /* the clock used */
/* Callbacks */
- QEMUTimerCB *read_timer_cb;
- QEMUTimerCB *write_timer_cb;
+ QEMUTimerCB *timer_cb[THROTTLE_MAX];
void *timer_opaque;
} ThrottleTimers;
@@ -149,9 +154,10 @@
/* usage */
bool throttle_schedule_timer(ThrottleState *ts,
ThrottleTimers *tt,
- bool is_write);
+ ThrottleDirection direction);
-void throttle_account(ThrottleState *ts, bool is_write, uint64_t size);
+void throttle_account(ThrottleState *ts, ThrottleDirection direction,
+ uint64_t size);
void throttle_limits_to_config(ThrottleLimits *arg, ThrottleConfig *cfg,
Error **errp);
void throttle_config_to_limits(ThrottleConfig *cfg, ThrottleLimits *var);
diff --git a/linux-user/hppa/signal.c b/linux-user/hppa/signal.c
index f253a15..bda6e54 100644
--- a/linux-user/hppa/signal.c
+++ b/linux-user/hppa/signal.c
@@ -149,16 +149,18 @@
target_ulong *fdesc, dest;
haddr &= -4;
- if (!lock_user_struct(VERIFY_READ, fdesc, haddr, 1)) {
+ fdesc = lock_user(VERIFY_READ, haddr, 2 * sizeof(target_ulong), 1);
+ if (!fdesc) {
goto give_sigsegv;
}
__get_user(dest, fdesc);
__get_user(env->gr[19], fdesc + 1);
- unlock_user_struct(fdesc, haddr, 1);
+ unlock_user(fdesc, haddr, 0);
haddr = dest;
}
env->iaoq_f = haddr;
env->iaoq_b = haddr + 4;
+ env->psw_n = 0;
return;
give_sigsegv:
diff --git a/linux-user/loongarch64/signal.c b/linux-user/loongarch64/signal.c
index bb8efb1..39572c1 100644
--- a/linux-user/loongarch64/signal.c
+++ b/linux-user/loongarch64/signal.c
@@ -12,6 +12,7 @@
#include "linux-user/trace.h"
#include "target/loongarch/internals.h"
+#include "target/loongarch/vec.h"
/* FP context was used */
#define SC_USED_FP (1 << 0)
diff --git a/pc-bios/hppa-firmware.img b/pc-bios/hppa-firmware.img
index 0fa3808..c719614 100644
--- a/pc-bios/hppa-firmware.img
+++ b/pc-bios/hppa-firmware.img
Binary files differ
diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py
index c16a0b6..35d5a67 100644
--- a/python/qemu/machine/machine.py
+++ b/python/qemu/machine/machine.py
@@ -191,6 +191,7 @@ def __init__(self,
self.sock_dir, f"{self._name}.con"
)
self._console_socket: Optional[socket.socket] = None
+ self._console_file: Optional[socket.SocketIO] = None
self._remove_files: List[str] = []
self._user_killed = False
self._quit_issued = False
@@ -509,6 +510,11 @@ def _early_cleanup(self) -> None:
# If we keep the console socket open, we may deadlock waiting
# for QEMU to exit, while QEMU is waiting for the socket to
# become writable.
+ if self._console_file is not None:
+ LOG.debug("Closing console file")
+ self._console_file.close()
+ self._console_file = None
+
if self._console_socket is not None:
LOG.debug("Closing console socket")
self._console_socket.close()
@@ -874,6 +880,7 @@ def console_socket(self) -> socket.socket:
Returns a socket connected to the console
"""
if self._console_socket is None:
+ LOG.debug("Opening console socket")
self._console_socket = console_socket.ConsoleSocket(
self._console_address,
file=self._console_log_path,
@@ -881,6 +888,18 @@ def console_socket(self) -> socket.socket:
return self._console_socket
@property
+ def console_file(self) -> socket.SocketIO:
+ """
+ Returns a file associated with the console socket
+ """
+ if self._console_file is None:
+ LOG.debug("Opening console file")
+ self._console_file = self.console_socket.makefile(mode='rb',
+ buffering=0,
+ encoding='utf-8')
+ return self._console_file
+
+ @property
def temp_dir(self) -> str:
"""
Returns a temporary directory to be used for this machine
diff --git a/roms/seabios-hppa b/roms/seabios-hppa
index 673d259..763e3b7 160000
--- a/roms/seabios-hppa
+++ b/roms/seabios-hppa
@@ -1 +1 @@
-Subproject commit 673d2595d4f773cc266cbf8dbaf2f475a6adb949
+Subproject commit 763e3b73499db5fef94087bd310bfc8ccbcf7858
diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index fa13694..730f352 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -211,8 +211,14 @@
target_ureg shadow[7]; /* shadow registers */
/* ??? The number of entries isn't specified by the architecture. */
+#ifdef TARGET_HPPA64
+#define HPPA_BTLB_FIXED 0 /* BTLBs are not supported in 64-bit machines */
+#else
+#define HPPA_BTLB_FIXED 16
+#endif
+#define HPPA_BTLB_VARIABLE 0
#define HPPA_TLB_ENTRIES 256
-#define HPPA_BTLB_ENTRIES 0
+#define HPPA_BTLB_ENTRIES (HPPA_BTLB_FIXED + HPPA_BTLB_VARIABLE)
/* ??? Implement a unified itlb/dtlb for the moment. */
/* ??? We should use a more intelligent data structure. */
@@ -344,7 +350,8 @@
void hppa_cpu_do_interrupt(CPUState *cpu);
bool hppa_cpu_exec_interrupt(CPUState *cpu, int int_req);
int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx,
- int type, hwaddr *pphys, int *pprot);
+ int type, hwaddr *pphys, int *pprot,
+ hppa_tlb_entry **tlb_entry);
extern const MemoryRegionOps hppa_io_eir_ops;
extern const VMStateDescription vmstate_hppa_cpu;
void hppa_cpu_alarm_timer(void *);
diff --git a/target/hppa/helper.h b/target/hppa/helper.h
index c7e35ce..647f043 100644
--- a/target/hppa/helper.h
+++ b/target/hppa/helper.h
@@ -95,4 +95,5 @@
DEF_HELPER_FLAGS_1(ptlbe, TCG_CALL_NO_RWG, void, env)
DEF_HELPER_FLAGS_2(lpa, TCG_CALL_NO_WG, tr, env, tl)
DEF_HELPER_FLAGS_1(change_prot_id, TCG_CALL_NO_RWG, void, env)
+DEF_HELPER_1(diag_btlb, void, env)
#endif
diff --git a/target/hppa/insns.decode b/target/hppa/insns.decode
index 27341d2..aebe03c 100644
--- a/target/hppa/insns.decode
+++ b/target/hppa/insns.decode
@@ -528,4 +528,4 @@
xmpyu 001110 ..... ..... 010 .0111 .00 t:5 r1=%ra64 r2=%rb64
# diag
-diag 000101 ----- ----- ---- ---- ---- ----
+diag 000101 i:26
diff --git a/target/hppa/int_helper.c b/target/hppa/int_helper.c
index bebc732..3ab9934 100644
--- a/target/hppa/int_helper.c
+++ b/target/hppa/int_helper.c
@@ -154,7 +154,7 @@
vaddr = hppa_form_gva_psw(old_psw, iasq_f, vaddr);
t = hppa_get_physical_address(env, vaddr, MMU_KERNEL_IDX,
- 0, &paddr, &prot);
+ 0, &paddr, &prot, NULL);
if (t >= 0) {
/* We can't re-load the instruction. */
env->cr[CR_IIR] = 0;
diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c
index 46c3dca..520fd31 100644
--- a/target/hppa/mem_helper.c
+++ b/target/hppa/mem_helper.c
@@ -41,16 +41,24 @@
return NULL;
}
-static void hppa_flush_tlb_ent(CPUHPPAState *env, hppa_tlb_entry *ent)
+static void hppa_flush_tlb_ent(CPUHPPAState *env, hppa_tlb_entry *ent,
+ bool force_flush_btlb)
{
CPUState *cs = env_cpu(env);
- unsigned i, n = 1 << (2 * ent->page_size);
- uint64_t addr = ent->va_b;
+
+ if (!ent->entry_valid) {
+ return;
+ }
trace_hppa_tlb_flush_ent(env, ent, ent->va_b, ent->va_e, ent->pa);
- for (i = 0; i < n; ++i, addr += TARGET_PAGE_SIZE) {
- tlb_flush_page_by_mmuidx(cs, addr, HPPA_MMU_FLUSH_MASK);
+ tlb_flush_range_by_mmuidx(cs, ent->va_b,
+ ent->va_e - ent->va_b + 1,
+ HPPA_MMU_FLUSH_MASK, TARGET_LONG_BITS);
+
+ /* never clear BTLBs, unless forced to do so. */
+ if (ent < &env->tlb[HPPA_BTLB_ENTRIES] && !force_flush_btlb) {
+ return;
}
memset(ent, 0, sizeof(*ent));
@@ -60,23 +68,35 @@
static hppa_tlb_entry *hppa_alloc_tlb_ent(CPUHPPAState *env)
{
hppa_tlb_entry *ent;
- uint32_t i = env->tlb_last;
+ uint32_t i;
- env->tlb_last = (i == ARRAY_SIZE(env->tlb) - 1 ? 0 : i + 1);
+ if (env->tlb_last < HPPA_BTLB_ENTRIES || env->tlb_last >= ARRAY_SIZE(env->tlb)) {
+ i = HPPA_BTLB_ENTRIES;
+ env->tlb_last = HPPA_BTLB_ENTRIES + 1;
+ } else {
+ i = env->tlb_last;
+ env->tlb_last++;
+ }
+
ent = &env->tlb[i];
- hppa_flush_tlb_ent(env, ent);
+ hppa_flush_tlb_ent(env, ent, false);
return ent;
}
int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx,
- int type, hwaddr *pphys, int *pprot)
+ int type, hwaddr *pphys, int *pprot,
+ hppa_tlb_entry **tlb_entry)
{
hwaddr phys;
int prot, r_prot, w_prot, x_prot, priv;
hppa_tlb_entry *ent;
int ret = -1;
+ if (tlb_entry) {
+ *tlb_entry = NULL;
+ }
+
/* Virtual translation disabled. Direct map virtual to physical. */
if (mmu_idx == MMU_PHYS_IDX) {
phys = addr;
@@ -93,8 +113,12 @@
goto egress;
}
+ if (tlb_entry) {
+ *tlb_entry = ent;
+ }
+
/* We now know the physical address. */
- phys = ent->pa + (addr & ~TARGET_PAGE_MASK);
+ phys = ent->pa + (addr - ent->va_b);
/* Map TLB access_rights field to QEMU protection. */
priv = MMU_IDX_TO_PRIV(mmu_idx);
@@ -193,7 +217,7 @@
}
excp = hppa_get_physical_address(&cpu->env, addr, MMU_KERNEL_IDX, 0,
- &phys, &prot);
+ &phys, &prot, NULL);
/* Since we're translating for debugging, the only error that is a
hard error is no translation at all. Otherwise, while a real cpu
@@ -207,6 +231,7 @@
{
HPPACPU *cpu = HPPA_CPU(cs);
CPUHPPAState *env = &cpu->env;
+ hppa_tlb_entry *ent;
int prot, excp, a_prot;
hwaddr phys;
@@ -223,7 +248,7 @@
}
excp = hppa_get_physical_address(env, addr, mmu_idx,
- a_prot, &phys, &prot);
+ a_prot, &phys, &prot, &ent);
if (unlikely(excp >= 0)) {
if (probe) {
return false;
@@ -243,7 +268,7 @@
phys & TARGET_PAGE_MASK, size, type, mmu_idx);
/* Success! Store the translation into the QEMU TLB. */
tlb_set_page(cs, addr & TARGET_PAGE_MASK, phys & TARGET_PAGE_MASK,
- prot, mmu_idx, TARGET_PAGE_SIZE);
+ prot, mmu_idx, TARGET_PAGE_SIZE << (ent ? 2 * ent->page_size : 0));
return true;
}
@@ -254,11 +279,11 @@
int i;
/* Zap any old entries covering ADDR; notice empty entries on the way. */
- for (i = 0; i < ARRAY_SIZE(env->tlb); ++i) {
+ for (i = HPPA_BTLB_ENTRIES; i < ARRAY_SIZE(env->tlb); ++i) {
hppa_tlb_entry *ent = &env->tlb[i];
if (ent->va_b <= addr && addr <= ent->va_e) {
if (ent->entry_valid) {
- hppa_flush_tlb_ent(env, ent);
+ hppa_flush_tlb_ent(env, ent, false);
}
if (!empty) {
empty = ent;
@@ -278,16 +303,8 @@
trace_hppa_tlb_itlba(env, empty, empty->va_b, empty->va_e, empty->pa);
}
-/* Insert (Insn/Data) TLB Protection. Note this is PA 1.1 only. */
-void HELPER(itlbp)(CPUHPPAState *env, target_ulong addr, target_ureg reg)
+static void set_access_bits(CPUHPPAState *env, hppa_tlb_entry *ent, target_ureg reg)
{
- hppa_tlb_entry *ent = hppa_find_tlb(env, addr);
-
- if (unlikely(ent == NULL)) {
- qemu_log_mask(LOG_GUEST_ERROR, "ITLBP not following ITLBA\n");
- return;
- }
-
ent->access_id = extract32(reg, 1, 18);
ent->u = extract32(reg, 19, 1);
ent->ar_pl2 = extract32(reg, 20, 2);
@@ -301,6 +318,19 @@
ent->ar_pl1, ent->ar_type, ent->b, ent->d, ent->t);
}
+/* Insert (Insn/Data) TLB Protection. Note this is PA 1.1 only. */
+void HELPER(itlbp)(CPUHPPAState *env, target_ulong addr, target_ureg reg)
+{
+ hppa_tlb_entry *ent = hppa_find_tlb(env, addr);
+
+ if (unlikely(ent == NULL)) {
+ qemu_log_mask(LOG_GUEST_ERROR, "ITLBP not following ITLBA\n");
+ return;
+ }
+
+ set_access_bits(env, ent, reg);
+}
+
/* Purge (Insn/Data) TLB. This is explicitly page-based, and is
synchronous across all processors. */
static void ptlb_work(CPUState *cpu, run_on_cpu_data data)
@@ -310,7 +340,7 @@
hppa_tlb_entry *ent = hppa_find_tlb(env, addr);
if (ent && ent->entry_valid) {
- hppa_flush_tlb_ent(env, ent);
+ hppa_flush_tlb_ent(env, ent, false);
}
}
@@ -334,7 +364,10 @@
void HELPER(ptlbe)(CPUHPPAState *env)
{
trace_hppa_tlb_ptlbe(env);
- memset(env->tlb, 0, sizeof(env->tlb));
+ qemu_log_mask(CPU_LOG_MMU, "FLUSH ALL TLB ENTRIES\n");
+ memset(&env->tlb[HPPA_BTLB_ENTRIES], 0,
+ sizeof(env->tlb) - HPPA_BTLB_ENTRIES * sizeof(env->tlb[0]));
+ env->tlb_last = HPPA_BTLB_ENTRIES;
tlb_flush_by_mmuidx(env_cpu(env), HPPA_MMU_FLUSH_MASK);
}
@@ -356,7 +389,7 @@
int prot, excp;
excp = hppa_get_physical_address(env, addr, MMU_KERNEL_IDX, 0,
- &phys, &prot);
+ &phys, &prot, NULL);
if (excp >= 0) {
if (env->psw & PSW_Q) {
/* ??? Needs tweaking for hppa64. */
@@ -379,3 +412,95 @@
hppa_tlb_entry *ent = hppa_find_tlb(env, vaddr);
return ent ? ent->ar_type : -1;
}
+
+/*
+ * diag_btlb() emulates the PDC PDC_BLOCK_TLB firmware call to
+ * allow operating systems to modify the Block TLB (BTLB) entries.
+ * For implementation details see page 1-13 in
+ * https://parisc.wiki.kernel.org/images-parisc/e/ef/Pdc11-v0.96-Ch1-procs.pdf
+ */
+void HELPER(diag_btlb)(CPUHPPAState *env)
+{
+ unsigned int phys_page, len, slot;
+ int mmu_idx = cpu_mmu_index(env, 0);
+ uintptr_t ra = GETPC();
+ hppa_tlb_entry *btlb;
+ uint64_t virt_page;
+ uint32_t *vaddr;
+
+#ifdef TARGET_HPPA64
+ /* BTLBs are not supported on 64-bit CPUs */
+ env->gr[28] = -1; /* nonexistent procedure */
+ return;
+#endif
+ env->gr[28] = 0; /* PDC_OK */
+
+ switch (env->gr[25]) {
+ case 0:
+ /* return BTLB parameters */
+ qemu_log_mask(CPU_LOG_MMU, "PDC_BLOCK_TLB: PDC_BTLB_INFO\n");
+ vaddr = probe_access(env, env->gr[24], 4 * sizeof(target_ulong),
+ MMU_DATA_STORE, mmu_idx, ra);
+ if (vaddr == NULL) {
+ env->gr[28] = -10; /* invalid argument */
+ } else {
+ vaddr[0] = cpu_to_be32(1);
+ vaddr[1] = cpu_to_be32(16 * 1024);
+ vaddr[2] = cpu_to_be32(HPPA_BTLB_FIXED);
+ vaddr[3] = cpu_to_be32(HPPA_BTLB_VARIABLE);
+ }
+ break;
+ case 1:
+ /* insert BTLB entry */
+ virt_page = env->gr[24]; /* upper 32 bits */
+ virt_page <<= 32;
+ virt_page |= env->gr[23]; /* lower 32 bits */
+ phys_page = env->gr[22];
+ len = env->gr[21];
+ slot = env->gr[19];
+ qemu_log_mask(CPU_LOG_MMU, "PDC_BLOCK_TLB: PDC_BTLB_INSERT "
+ "0x%08llx-0x%08llx: vpage 0x%llx for phys page 0x%04x len %d "
+ "into slot %d\n",
+ (long long) virt_page << TARGET_PAGE_BITS,
+ (long long) (virt_page + len) << TARGET_PAGE_BITS,
+ (long long) virt_page, phys_page, len, slot);
+ if (slot < HPPA_BTLB_ENTRIES) {
+ btlb = &env->tlb[slot];
+ /* force flush of possibly existing BTLB entry */
+ hppa_flush_tlb_ent(env, btlb, true);
+ /* create new BTLB entry */
+ btlb->va_b = virt_page << TARGET_PAGE_BITS;
+ btlb->va_e = btlb->va_b + len * TARGET_PAGE_SIZE - 1;
+ btlb->pa = phys_page << TARGET_PAGE_BITS;
+ set_access_bits(env, btlb, env->gr[20]);
+ btlb->t = 0;
+ btlb->d = 1;
+ } else {
+ env->gr[28] = -10; /* invalid argument */
+ }
+ break;
+ case 2:
+ /* Purge BTLB entry */
+ slot = env->gr[22];
+ qemu_log_mask(CPU_LOG_MMU, "PDC_BLOCK_TLB: PDC_BTLB_PURGE slot %d\n",
+ slot);
+ if (slot < HPPA_BTLB_ENTRIES) {
+ btlb = &env->tlb[slot];
+ hppa_flush_tlb_ent(env, btlb, true);
+ } else {
+ env->gr[28] = -10; /* invalid argument */
+ }
+ break;
+ case 3:
+ /* Purge all BTLB entries */
+ qemu_log_mask(CPU_LOG_MMU, "PDC_BLOCK_TLB: PDC_BTLB_PURGE_ALL\n");
+ for (slot = 0; slot < HPPA_BTLB_ENTRIES; slot++) {
+ btlb = &env->tlb[slot];
+ hppa_flush_tlb_ent(env, btlb, true);
+ }
+ break;
+ default:
+ env->gr[28] = -2; /* nonexistent option */
+ break;
+ }
+}
diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c
index f25a5a7..837e2b3 100644
--- a/target/hppa/op_helper.c
+++ b/target/hppa/op_helper.c
@@ -179,7 +179,8 @@
return 0;
}
- excp = hppa_get_physical_address(env, addr, level, 0, &phys, &prot);
+ excp = hppa_get_physical_address(env, addr, level, 0, &phys,
+ &prot, NULL);
if (excp >= 0) {
if (env->psw & PSW_Q) {
/* ??? Needs tweaking for hppa64. */
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index c04dc15..650bbcf 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -4042,9 +4042,18 @@
static bool trans_diag(DisasContext *ctx, arg_diag *a)
{
- qemu_log_mask(LOG_UNIMP, "DIAG opcode ignored\n");
- cond_free(&ctx->null_cond);
- return true;
+ nullify_over(ctx);
+ CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
+#ifndef CONFIG_USER_ONLY
+ if (a->i == 0x100) {
+ /* emulate PDC BTLB, called by SeaBIOS-hppa */
+ gen_helper_diag_btlb(cpu_env);
+ } else
+#endif
+ {
+ qemu_log_mask(LOG_UNIMP, "DIAG opcode 0x%04x ignored\n", a->i);
+ }
+ return nullify_end(ctx);
}
static void hppa_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 65f9320..fc7f70f 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -19,6 +19,7 @@
#include "cpu-csr.h"
#include "sysemu/reset.h"
#include "tcg/tcg.h"
+#include "vec.h"
const char * const regnames[32] = {
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
@@ -54,6 +55,7 @@
[EXCCODE_DBP] = "Debug breakpoint",
[EXCCODE_BCE] = "Bound Check Exception",
[EXCCODE_SXD] = "128 bit vector instructions Disable exception",
+ [EXCCODE_ASXD] = "256 bit vector instructions Disable exception",
};
const char *loongarch_exception_name(int32_t exception)
@@ -189,6 +191,7 @@
case EXCCODE_FPD:
case EXCCODE_FPE:
case EXCCODE_SXD:
+ case EXCCODE_ASXD:
env->CSR_BADV = env->pc;
QEMU_FALLTHROUGH;
case EXCCODE_BCE:
@@ -390,6 +393,7 @@
data = FIELD_DP32(data, CPUCFG2, FP_DP, 1);
data = FIELD_DP32(data, CPUCFG2, FP_VER, 1);
data = FIELD_DP32(data, CPUCFG2, LSX, 1),
+ data = FIELD_DP32(data, CPUCFG2, LASX, 1),
data = FIELD_DP32(data, CPUCFG2, LLFTP, 1);
data = FIELD_DP32(data, CPUCFG2, LLFTP_VER, 1);
data = FIELD_DP32(data, CPUCFG2, LSPW, 1);
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 4d72019..f125a8e 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -251,18 +251,20 @@
FIELD(TLB_MISC, VPPN, 13, 35)
FIELD(TLB_MISC, PS, 48, 6)
-#define LSX_LEN (128)
+#define LSX_LEN (128)
+#define LASX_LEN (256)
+
typedef union VReg {
- int8_t B[LSX_LEN / 8];
- int16_t H[LSX_LEN / 16];
- int32_t W[LSX_LEN / 32];
- int64_t D[LSX_LEN / 64];
- uint8_t UB[LSX_LEN / 8];
- uint16_t UH[LSX_LEN / 16];
- uint32_t UW[LSX_LEN / 32];
- uint64_t UD[LSX_LEN / 64];
- Int128 Q[LSX_LEN / 128];
-}VReg;
+ int8_t B[LASX_LEN / 8];
+ int16_t H[LASX_LEN / 16];
+ int32_t W[LASX_LEN / 32];
+ int64_t D[LASX_LEN / 64];
+ uint8_t UB[LASX_LEN / 8];
+ uint16_t UH[LASX_LEN / 16];
+ uint32_t UW[LASX_LEN / 32];
+ uint64_t UD[LASX_LEN / 64];
+ Int128 Q[LASX_LEN / 128];
+} VReg;
typedef union fpr_t fpr_t;
union fpr_t {
@@ -460,6 +462,7 @@
#define HW_FLAGS_CRMD_PG R_CSR_CRMD_PG_MASK /* 0x10 */
#define HW_FLAGS_EUEN_FPE 0x04
#define HW_FLAGS_EUEN_SXE 0x08
+#define HW_FLAGS_EUEN_ASXE 0x10
#define HW_FLAGS_VA32 0x20
static inline void cpu_get_tb_cpu_state(CPULoongArchState *env, vaddr *pc,
@@ -470,6 +473,7 @@
*flags = env->CSR_CRMD & (R_CSR_CRMD_PLV_MASK | R_CSR_CRMD_PG_MASK);
*flags |= FIELD_EX64(env->CSR_EUEN, CSR_EUEN, FPE) * HW_FLAGS_EUEN_FPE;
*flags |= FIELD_EX64(env->CSR_EUEN, CSR_EUEN, SXE) * HW_FLAGS_EUEN_SXE;
+ *flags |= FIELD_EX64(env->CSR_EUEN, CSR_EUEN, ASXE) * HW_FLAGS_EUEN_ASXE;
*flags |= is_va32(env) * HW_FLAGS_VA32;
}
diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index 5c402d9..c8a29ea 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -1695,3 +1695,927 @@
INSN_LSX(vstelm_w, vr_ii)
INSN_LSX(vstelm_h, vr_ii)
INSN_LSX(vstelm_b, vr_ii)
+
+#define INSN_LASX(insn, type) \
+static bool trans_##insn(DisasContext *ctx, arg_##type * a) \
+{ \
+ output_##type ## _x(ctx, a, #insn); \
+ return true; \
+}
+
+static void output_cv_x(DisasContext *ctx, arg_cv *a, const char *mnemonic)
+{
+ output(ctx, mnemonic, "fcc%d, x%d", a->cd, a->vj);
+}
+
+static void output_v_i_x(DisasContext *ctx, arg_v_i *a, const char *mnemonic)
+{
+ output(ctx, mnemonic, "x%d, 0x%x", a->vd, a->imm);
+}
+
+static void output_vvvv_x(DisasContext *ctx, arg_vvvv *a, const char *mnemonic)
+{
+ output(ctx, mnemonic, "x%d, x%d, x%d, x%d", a->vd, a->vj, a->vk, a->va);
+}
+
+static void output_vvv_x(DisasContext *ctx, arg_vvv * a, const char *mnemonic)
+{
+ output(ctx, mnemonic, "x%d, x%d, x%d", a->vd, a->vj, a->vk);
+}
+
+static void output_vr_x(DisasContext *ctx, arg_vr *a, const char *mnemonic)
+{
+ output(ctx, mnemonic, "x%d, r%d", a->vd, a->rj);
+}
+
+static void output_vv_i_x(DisasContext *ctx, arg_vv_i *a, const char *mnemonic)
+{
+ output(ctx, mnemonic, "x%d, x%d, 0x%x", a->vd, a->vj, a->imm);
+}
+
+static void output_vv_x(DisasContext *ctx, arg_vv *a, const char *mnemonic)
+{
+ output(ctx, mnemonic, "x%d, x%d", a->vd, a->vj);
+}
+
+static void output_vr_i_x(DisasContext *ctx, arg_vr_i *a, const char *mnemonic)
+{
+ output(ctx, mnemonic, "x%d, r%d, 0x%x", a->vd, a->rj, a->imm);
+}
+
+static void output_rv_i_x(DisasContext *ctx, arg_rv_i *a, const char *mnemonic)
+{
+ output(ctx, mnemonic, "r%d, x%d, 0x%x", a->rd, a->vj, a->imm);
+}
+
+static void output_vvr_x(DisasContext *ctx, arg_vvr *a, const char *mnemonic)
+{
+ output(ctx, mnemonic, "x%d, x%d, r%d", a->vd, a->vj, a->rk);
+}
+
+static void output_vrr_x(DisasContext *ctx, arg_vrr *a, const char *mnemonic)
+{
+ output(ctx, mnemonic, "x%d, r%d, r%d", a->vd, a->rj, a->rk);
+}
+
+static void output_vr_ii_x(DisasContext *ctx, arg_vr_ii *a, const char *mnemonic)
+{
+ output(ctx, mnemonic, "x%d, r%d, 0x%x, 0x%x", a->vd, a->rj, a->imm, a->imm2);
+}
+
+INSN_LASX(xvadd_b, vvv)
+INSN_LASX(xvadd_h, vvv)
+INSN_LASX(xvadd_w, vvv)
+INSN_LASX(xvadd_d, vvv)
+INSN_LASX(xvadd_q, vvv)
+INSN_LASX(xvsub_b, vvv)
+INSN_LASX(xvsub_h, vvv)
+INSN_LASX(xvsub_w, vvv)
+INSN_LASX(xvsub_d, vvv)
+INSN_LASX(xvsub_q, vvv)
+
+INSN_LASX(xvaddi_bu, vv_i)
+INSN_LASX(xvaddi_hu, vv_i)
+INSN_LASX(xvaddi_wu, vv_i)
+INSN_LASX(xvaddi_du, vv_i)
+INSN_LASX(xvsubi_bu, vv_i)
+INSN_LASX(xvsubi_hu, vv_i)
+INSN_LASX(xvsubi_wu, vv_i)
+INSN_LASX(xvsubi_du, vv_i)
+
+INSN_LASX(xvneg_b, vv)
+INSN_LASX(xvneg_h, vv)
+INSN_LASX(xvneg_w, vv)
+INSN_LASX(xvneg_d, vv)
+
+INSN_LASX(xvsadd_b, vvv)
+INSN_LASX(xvsadd_h, vvv)
+INSN_LASX(xvsadd_w, vvv)
+INSN_LASX(xvsadd_d, vvv)
+INSN_LASX(xvsadd_bu, vvv)
+INSN_LASX(xvsadd_hu, vvv)
+INSN_LASX(xvsadd_wu, vvv)
+INSN_LASX(xvsadd_du, vvv)
+INSN_LASX(xvssub_b, vvv)
+INSN_LASX(xvssub_h, vvv)
+INSN_LASX(xvssub_w, vvv)
+INSN_LASX(xvssub_d, vvv)
+INSN_LASX(xvssub_bu, vvv)
+INSN_LASX(xvssub_hu, vvv)
+INSN_LASX(xvssub_wu, vvv)
+INSN_LASX(xvssub_du, vvv)
+
+INSN_LASX(xvhaddw_h_b, vvv)
+INSN_LASX(xvhaddw_w_h, vvv)
+INSN_LASX(xvhaddw_d_w, vvv)
+INSN_LASX(xvhaddw_q_d, vvv)
+INSN_LASX(xvhaddw_hu_bu, vvv)
+INSN_LASX(xvhaddw_wu_hu, vvv)
+INSN_LASX(xvhaddw_du_wu, vvv)
+INSN_LASX(xvhaddw_qu_du, vvv)
+INSN_LASX(xvhsubw_h_b, vvv)
+INSN_LASX(xvhsubw_w_h, vvv)
+INSN_LASX(xvhsubw_d_w, vvv)
+INSN_LASX(xvhsubw_q_d, vvv)
+INSN_LASX(xvhsubw_hu_bu, vvv)
+INSN_LASX(xvhsubw_wu_hu, vvv)
+INSN_LASX(xvhsubw_du_wu, vvv)
+INSN_LASX(xvhsubw_qu_du, vvv)
+
+INSN_LASX(xvaddwev_h_b, vvv)
+INSN_LASX(xvaddwev_w_h, vvv)
+INSN_LASX(xvaddwev_d_w, vvv)
+INSN_LASX(xvaddwev_q_d, vvv)
+INSN_LASX(xvaddwod_h_b, vvv)
+INSN_LASX(xvaddwod_w_h, vvv)
+INSN_LASX(xvaddwod_d_w, vvv)
+INSN_LASX(xvaddwod_q_d, vvv)
+INSN_LASX(xvsubwev_h_b, vvv)
+INSN_LASX(xvsubwev_w_h, vvv)
+INSN_LASX(xvsubwev_d_w, vvv)
+INSN_LASX(xvsubwev_q_d, vvv)
+INSN_LASX(xvsubwod_h_b, vvv)
+INSN_LASX(xvsubwod_w_h, vvv)
+INSN_LASX(xvsubwod_d_w, vvv)
+INSN_LASX(xvsubwod_q_d, vvv)
+
+INSN_LASX(xvaddwev_h_bu, vvv)
+INSN_LASX(xvaddwev_w_hu, vvv)
+INSN_LASX(xvaddwev_d_wu, vvv)
+INSN_LASX(xvaddwev_q_du, vvv)
+INSN_LASX(xvaddwod_h_bu, vvv)
+INSN_LASX(xvaddwod_w_hu, vvv)
+INSN_LASX(xvaddwod_d_wu, vvv)
+INSN_LASX(xvaddwod_q_du, vvv)
+INSN_LASX(xvsubwev_h_bu, vvv)
+INSN_LASX(xvsubwev_w_hu, vvv)
+INSN_LASX(xvsubwev_d_wu, vvv)
+INSN_LASX(xvsubwev_q_du, vvv)
+INSN_LASX(xvsubwod_h_bu, vvv)
+INSN_LASX(xvsubwod_w_hu, vvv)
+INSN_LASX(xvsubwod_d_wu, vvv)
+INSN_LASX(xvsubwod_q_du, vvv)
+
+INSN_LASX(xvaddwev_h_bu_b, vvv)
+INSN_LASX(xvaddwev_w_hu_h, vvv)
+INSN_LASX(xvaddwev_d_wu_w, vvv)
+INSN_LASX(xvaddwev_q_du_d, vvv)
+INSN_LASX(xvaddwod_h_bu_b, vvv)
+INSN_LASX(xvaddwod_w_hu_h, vvv)
+INSN_LASX(xvaddwod_d_wu_w, vvv)
+INSN_LASX(xvaddwod_q_du_d, vvv)
+
+INSN_LASX(xvavg_b, vvv)
+INSN_LASX(xvavg_h, vvv)
+INSN_LASX(xvavg_w, vvv)
+INSN_LASX(xvavg_d, vvv)
+INSN_LASX(xvavg_bu, vvv)
+INSN_LASX(xvavg_hu, vvv)
+INSN_LASX(xvavg_wu, vvv)
+INSN_LASX(xvavg_du, vvv)
+INSN_LASX(xvavgr_b, vvv)
+INSN_LASX(xvavgr_h, vvv)
+INSN_LASX(xvavgr_w, vvv)
+INSN_LASX(xvavgr_d, vvv)
+INSN_LASX(xvavgr_bu, vvv)
+INSN_LASX(xvavgr_hu, vvv)
+INSN_LASX(xvavgr_wu, vvv)
+INSN_LASX(xvavgr_du, vvv)
+
+INSN_LASX(xvabsd_b, vvv)
+INSN_LASX(xvabsd_h, vvv)
+INSN_LASX(xvabsd_w, vvv)
+INSN_LASX(xvabsd_d, vvv)
+INSN_LASX(xvabsd_bu, vvv)
+INSN_LASX(xvabsd_hu, vvv)
+INSN_LASX(xvabsd_wu, vvv)
+INSN_LASX(xvabsd_du, vvv)
+
+INSN_LASX(xvadda_b, vvv)
+INSN_LASX(xvadda_h, vvv)
+INSN_LASX(xvadda_w, vvv)
+INSN_LASX(xvadda_d, vvv)
+
+INSN_LASX(xvmax_b, vvv)
+INSN_LASX(xvmax_h, vvv)
+INSN_LASX(xvmax_w, vvv)
+INSN_LASX(xvmax_d, vvv)
+INSN_LASX(xvmin_b, vvv)
+INSN_LASX(xvmin_h, vvv)
+INSN_LASX(xvmin_w, vvv)
+INSN_LASX(xvmin_d, vvv)
+INSN_LASX(xvmax_bu, vvv)
+INSN_LASX(xvmax_hu, vvv)
+INSN_LASX(xvmax_wu, vvv)
+INSN_LASX(xvmax_du, vvv)
+INSN_LASX(xvmin_bu, vvv)
+INSN_LASX(xvmin_hu, vvv)
+INSN_LASX(xvmin_wu, vvv)
+INSN_LASX(xvmin_du, vvv)
+
+INSN_LASX(xvmaxi_b, vv_i)
+INSN_LASX(xvmaxi_h, vv_i)
+INSN_LASX(xvmaxi_w, vv_i)
+INSN_LASX(xvmaxi_d, vv_i)
+INSN_LASX(xvmini_b, vv_i)
+INSN_LASX(xvmini_h, vv_i)
+INSN_LASX(xvmini_w, vv_i)
+INSN_LASX(xvmini_d, vv_i)
+INSN_LASX(xvmaxi_bu, vv_i)
+INSN_LASX(xvmaxi_hu, vv_i)
+INSN_LASX(xvmaxi_wu, vv_i)
+INSN_LASX(xvmaxi_du, vv_i)
+INSN_LASX(xvmini_bu, vv_i)
+INSN_LASX(xvmini_hu, vv_i)
+INSN_LASX(xvmini_wu, vv_i)
+INSN_LASX(xvmini_du, vv_i)
+
+INSN_LASX(xvmul_b, vvv)
+INSN_LASX(xvmul_h, vvv)
+INSN_LASX(xvmul_w, vvv)
+INSN_LASX(xvmul_d, vvv)
+INSN_LASX(xvmuh_b, vvv)
+INSN_LASX(xvmuh_h, vvv)
+INSN_LASX(xvmuh_w, vvv)
+INSN_LASX(xvmuh_d, vvv)
+INSN_LASX(xvmuh_bu, vvv)
+INSN_LASX(xvmuh_hu, vvv)
+INSN_LASX(xvmuh_wu, vvv)
+INSN_LASX(xvmuh_du, vvv)
+
+INSN_LASX(xvmulwev_h_b, vvv)
+INSN_LASX(xvmulwev_w_h, vvv)
+INSN_LASX(xvmulwev_d_w, vvv)
+INSN_LASX(xvmulwev_q_d, vvv)
+INSN_LASX(xvmulwod_h_b, vvv)
+INSN_LASX(xvmulwod_w_h, vvv)
+INSN_LASX(xvmulwod_d_w, vvv)
+INSN_LASX(xvmulwod_q_d, vvv)
+INSN_LASX(xvmulwev_h_bu, vvv)
+INSN_LASX(xvmulwev_w_hu, vvv)
+INSN_LASX(xvmulwev_d_wu, vvv)
+INSN_LASX(xvmulwev_q_du, vvv)
+INSN_LASX(xvmulwod_h_bu, vvv)
+INSN_LASX(xvmulwod_w_hu, vvv)
+INSN_LASX(xvmulwod_d_wu, vvv)
+INSN_LASX(xvmulwod_q_du, vvv)
+INSN_LASX(xvmulwev_h_bu_b, vvv)
+INSN_LASX(xvmulwev_w_hu_h, vvv)
+INSN_LASX(xvmulwev_d_wu_w, vvv)
+INSN_LASX(xvmulwev_q_du_d, vvv)
+INSN_LASX(xvmulwod_h_bu_b, vvv)
+INSN_LASX(xvmulwod_w_hu_h, vvv)
+INSN_LASX(xvmulwod_d_wu_w, vvv)
+INSN_LASX(xvmulwod_q_du_d, vvv)
+
+INSN_LASX(xvmadd_b, vvv)
+INSN_LASX(xvmadd_h, vvv)
+INSN_LASX(xvmadd_w, vvv)
+INSN_LASX(xvmadd_d, vvv)
+INSN_LASX(xvmsub_b, vvv)
+INSN_LASX(xvmsub_h, vvv)
+INSN_LASX(xvmsub_w, vvv)
+INSN_LASX(xvmsub_d, vvv)
+
+INSN_LASX(xvmaddwev_h_b, vvv)
+INSN_LASX(xvmaddwev_w_h, vvv)
+INSN_LASX(xvmaddwev_d_w, vvv)
+INSN_LASX(xvmaddwev_q_d, vvv)
+INSN_LASX(xvmaddwod_h_b, vvv)
+INSN_LASX(xvmaddwod_w_h, vvv)
+INSN_LASX(xvmaddwod_d_w, vvv)
+INSN_LASX(xvmaddwod_q_d, vvv)
+INSN_LASX(xvmaddwev_h_bu, vvv)
+INSN_LASX(xvmaddwev_w_hu, vvv)
+INSN_LASX(xvmaddwev_d_wu, vvv)
+INSN_LASX(xvmaddwev_q_du, vvv)
+INSN_LASX(xvmaddwod_h_bu, vvv)
+INSN_LASX(xvmaddwod_w_hu, vvv)
+INSN_LASX(xvmaddwod_d_wu, vvv)
+INSN_LASX(xvmaddwod_q_du, vvv)
+INSN_LASX(xvmaddwev_h_bu_b, vvv)
+INSN_LASX(xvmaddwev_w_hu_h, vvv)
+INSN_LASX(xvmaddwev_d_wu_w, vvv)
+INSN_LASX(xvmaddwev_q_du_d, vvv)
+INSN_LASX(xvmaddwod_h_bu_b, vvv)
+INSN_LASX(xvmaddwod_w_hu_h, vvv)
+INSN_LASX(xvmaddwod_d_wu_w, vvv)
+INSN_LASX(xvmaddwod_q_du_d, vvv)
+
+INSN_LASX(xvdiv_b, vvv)
+INSN_LASX(xvdiv_h, vvv)
+INSN_LASX(xvdiv_w, vvv)
+INSN_LASX(xvdiv_d, vvv)
+INSN_LASX(xvdiv_bu, vvv)
+INSN_LASX(xvdiv_hu, vvv)
+INSN_LASX(xvdiv_wu, vvv)
+INSN_LASX(xvdiv_du, vvv)
+INSN_LASX(xvmod_b, vvv)
+INSN_LASX(xvmod_h, vvv)
+INSN_LASX(xvmod_w, vvv)
+INSN_LASX(xvmod_d, vvv)
+INSN_LASX(xvmod_bu, vvv)
+INSN_LASX(xvmod_hu, vvv)
+INSN_LASX(xvmod_wu, vvv)
+INSN_LASX(xvmod_du, vvv)
+
+INSN_LASX(xvsat_b, vv_i)
+INSN_LASX(xvsat_h, vv_i)
+INSN_LASX(xvsat_w, vv_i)
+INSN_LASX(xvsat_d, vv_i)
+INSN_LASX(xvsat_bu, vv_i)
+INSN_LASX(xvsat_hu, vv_i)
+INSN_LASX(xvsat_wu, vv_i)
+INSN_LASX(xvsat_du, vv_i)
+
+INSN_LASX(xvexth_h_b, vv)
+INSN_LASX(xvexth_w_h, vv)
+INSN_LASX(xvexth_d_w, vv)
+INSN_LASX(xvexth_q_d, vv)
+INSN_LASX(xvexth_hu_bu, vv)
+INSN_LASX(xvexth_wu_hu, vv)
+INSN_LASX(xvexth_du_wu, vv)
+INSN_LASX(xvexth_qu_du, vv)
+
+INSN_LASX(vext2xv_h_b, vv)
+INSN_LASX(vext2xv_w_b, vv)
+INSN_LASX(vext2xv_d_b, vv)
+INSN_LASX(vext2xv_w_h, vv)
+INSN_LASX(vext2xv_d_h, vv)
+INSN_LASX(vext2xv_d_w, vv)
+INSN_LASX(vext2xv_hu_bu, vv)
+INSN_LASX(vext2xv_wu_bu, vv)
+INSN_LASX(vext2xv_du_bu, vv)
+INSN_LASX(vext2xv_wu_hu, vv)
+INSN_LASX(vext2xv_du_hu, vv)
+INSN_LASX(vext2xv_du_wu, vv)
+
+INSN_LASX(xvsigncov_b, vvv)
+INSN_LASX(xvsigncov_h, vvv)
+INSN_LASX(xvsigncov_w, vvv)
+INSN_LASX(xvsigncov_d, vvv)
+
+INSN_LASX(xvmskltz_b, vv)
+INSN_LASX(xvmskltz_h, vv)
+INSN_LASX(xvmskltz_w, vv)
+INSN_LASX(xvmskltz_d, vv)
+INSN_LASX(xvmskgez_b, vv)
+INSN_LASX(xvmsknz_b, vv)
+
+INSN_LASX(xvldi, v_i)
+
+INSN_LASX(xvand_v, vvv)
+INSN_LASX(xvor_v, vvv)
+INSN_LASX(xvxor_v, vvv)
+INSN_LASX(xvnor_v, vvv)
+INSN_LASX(xvandn_v, vvv)
+INSN_LASX(xvorn_v, vvv)
+
+INSN_LASX(xvandi_b, vv_i)
+INSN_LASX(xvori_b, vv_i)
+INSN_LASX(xvxori_b, vv_i)
+INSN_LASX(xvnori_b, vv_i)
+
+INSN_LASX(xvsll_b, vvv)
+INSN_LASX(xvsll_h, vvv)
+INSN_LASX(xvsll_w, vvv)
+INSN_LASX(xvsll_d, vvv)
+INSN_LASX(xvslli_b, vv_i)
+INSN_LASX(xvslli_h, vv_i)
+INSN_LASX(xvslli_w, vv_i)
+INSN_LASX(xvslli_d, vv_i)
+
+INSN_LASX(xvsrl_b, vvv)
+INSN_LASX(xvsrl_h, vvv)
+INSN_LASX(xvsrl_w, vvv)
+INSN_LASX(xvsrl_d, vvv)
+INSN_LASX(xvsrli_b, vv_i)
+INSN_LASX(xvsrli_h, vv_i)
+INSN_LASX(xvsrli_w, vv_i)
+INSN_LASX(xvsrli_d, vv_i)
+
+INSN_LASX(xvsra_b, vvv)
+INSN_LASX(xvsra_h, vvv)
+INSN_LASX(xvsra_w, vvv)
+INSN_LASX(xvsra_d, vvv)
+INSN_LASX(xvsrai_b, vv_i)
+INSN_LASX(xvsrai_h, vv_i)
+INSN_LASX(xvsrai_w, vv_i)
+INSN_LASX(xvsrai_d, vv_i)
+
+INSN_LASX(xvrotr_b, vvv)
+INSN_LASX(xvrotr_h, vvv)
+INSN_LASX(xvrotr_w, vvv)
+INSN_LASX(xvrotr_d, vvv)
+INSN_LASX(xvrotri_b, vv_i)
+INSN_LASX(xvrotri_h, vv_i)
+INSN_LASX(xvrotri_w, vv_i)
+INSN_LASX(xvrotri_d, vv_i)
+
+INSN_LASX(xvsllwil_h_b, vv_i)
+INSN_LASX(xvsllwil_w_h, vv_i)
+INSN_LASX(xvsllwil_d_w, vv_i)
+INSN_LASX(xvextl_q_d, vv)
+INSN_LASX(xvsllwil_hu_bu, vv_i)
+INSN_LASX(xvsllwil_wu_hu, vv_i)
+INSN_LASX(xvsllwil_du_wu, vv_i)
+INSN_LASX(xvextl_qu_du, vv)
+
+INSN_LASX(xvsrlr_b, vvv)
+INSN_LASX(xvsrlr_h, vvv)
+INSN_LASX(xvsrlr_w, vvv)
+INSN_LASX(xvsrlr_d, vvv)
+INSN_LASX(xvsrlri_b, vv_i)
+INSN_LASX(xvsrlri_h, vv_i)
+INSN_LASX(xvsrlri_w, vv_i)
+INSN_LASX(xvsrlri_d, vv_i)
+
+INSN_LASX(xvsrar_b, vvv)
+INSN_LASX(xvsrar_h, vvv)
+INSN_LASX(xvsrar_w, vvv)
+INSN_LASX(xvsrar_d, vvv)
+INSN_LASX(xvsrari_b, vv_i)
+INSN_LASX(xvsrari_h, vv_i)
+INSN_LASX(xvsrari_w, vv_i)
+INSN_LASX(xvsrari_d, vv_i)
+
+INSN_LASX(xvsrln_b_h, vvv)
+INSN_LASX(xvsrln_h_w, vvv)
+INSN_LASX(xvsrln_w_d, vvv)
+INSN_LASX(xvsran_b_h, vvv)
+INSN_LASX(xvsran_h_w, vvv)
+INSN_LASX(xvsran_w_d, vvv)
+
+INSN_LASX(xvsrlni_b_h, vv_i)
+INSN_LASX(xvsrlni_h_w, vv_i)
+INSN_LASX(xvsrlni_w_d, vv_i)
+INSN_LASX(xvsrlni_d_q, vv_i)
+INSN_LASX(xvsrani_b_h, vv_i)
+INSN_LASX(xvsrani_h_w, vv_i)
+INSN_LASX(xvsrani_w_d, vv_i)
+INSN_LASX(xvsrani_d_q, vv_i)
+
+INSN_LASX(xvsrlrn_b_h, vvv)
+INSN_LASX(xvsrlrn_h_w, vvv)
+INSN_LASX(xvsrlrn_w_d, vvv)
+INSN_LASX(xvsrarn_b_h, vvv)
+INSN_LASX(xvsrarn_h_w, vvv)
+INSN_LASX(xvsrarn_w_d, vvv)
+
+INSN_LASX(xvsrlrni_b_h, vv_i)
+INSN_LASX(xvsrlrni_h_w, vv_i)
+INSN_LASX(xvsrlrni_w_d, vv_i)
+INSN_LASX(xvsrlrni_d_q, vv_i)
+INSN_LASX(xvsrarni_b_h, vv_i)
+INSN_LASX(xvsrarni_h_w, vv_i)
+INSN_LASX(xvsrarni_w_d, vv_i)
+INSN_LASX(xvsrarni_d_q, vv_i)
+
+INSN_LASX(xvssrln_b_h, vvv)
+INSN_LASX(xvssrln_h_w, vvv)
+INSN_LASX(xvssrln_w_d, vvv)
+INSN_LASX(xvssran_b_h, vvv)
+INSN_LASX(xvssran_h_w, vvv)
+INSN_LASX(xvssran_w_d, vvv)
+INSN_LASX(xvssrln_bu_h, vvv)
+INSN_LASX(xvssrln_hu_w, vvv)
+INSN_LASX(xvssrln_wu_d, vvv)
+INSN_LASX(xvssran_bu_h, vvv)
+INSN_LASX(xvssran_hu_w, vvv)
+INSN_LASX(xvssran_wu_d, vvv)
+
+INSN_LASX(xvssrlni_b_h, vv_i)
+INSN_LASX(xvssrlni_h_w, vv_i)
+INSN_LASX(xvssrlni_w_d, vv_i)
+INSN_LASX(xvssrlni_d_q, vv_i)
+INSN_LASX(xvssrani_b_h, vv_i)
+INSN_LASX(xvssrani_h_w, vv_i)
+INSN_LASX(xvssrani_w_d, vv_i)
+INSN_LASX(xvssrani_d_q, vv_i)
+INSN_LASX(xvssrlni_bu_h, vv_i)
+INSN_LASX(xvssrlni_hu_w, vv_i)
+INSN_LASX(xvssrlni_wu_d, vv_i)
+INSN_LASX(xvssrlni_du_q, vv_i)
+INSN_LASX(xvssrani_bu_h, vv_i)
+INSN_LASX(xvssrani_hu_w, vv_i)
+INSN_LASX(xvssrani_wu_d, vv_i)
+INSN_LASX(xvssrani_du_q, vv_i)
+
+INSN_LASX(xvssrlrn_b_h, vvv)
+INSN_LASX(xvssrlrn_h_w, vvv)
+INSN_LASX(xvssrlrn_w_d, vvv)
+INSN_LASX(xvssrarn_b_h, vvv)
+INSN_LASX(xvssrarn_h_w, vvv)
+INSN_LASX(xvssrarn_w_d, vvv)
+INSN_LASX(xvssrlrn_bu_h, vvv)
+INSN_LASX(xvssrlrn_hu_w, vvv)
+INSN_LASX(xvssrlrn_wu_d, vvv)
+INSN_LASX(xvssrarn_bu_h, vvv)
+INSN_LASX(xvssrarn_hu_w, vvv)
+INSN_LASX(xvssrarn_wu_d, vvv)
+
+INSN_LASX(xvssrlrni_b_h, vv_i)
+INSN_LASX(xvssrlrni_h_w, vv_i)
+INSN_LASX(xvssrlrni_w_d, vv_i)
+INSN_LASX(xvssrlrni_d_q, vv_i)
+INSN_LASX(xvssrlrni_bu_h, vv_i)
+INSN_LASX(xvssrlrni_hu_w, vv_i)
+INSN_LASX(xvssrlrni_wu_d, vv_i)
+INSN_LASX(xvssrlrni_du_q, vv_i)
+INSN_LASX(xvssrarni_b_h, vv_i)
+INSN_LASX(xvssrarni_h_w, vv_i)
+INSN_LASX(xvssrarni_w_d, vv_i)
+INSN_LASX(xvssrarni_d_q, vv_i)
+INSN_LASX(xvssrarni_bu_h, vv_i)
+INSN_LASX(xvssrarni_hu_w, vv_i)
+INSN_LASX(xvssrarni_wu_d, vv_i)
+INSN_LASX(xvssrarni_du_q, vv_i)
+
+INSN_LASX(xvclo_b, vv)
+INSN_LASX(xvclo_h, vv)
+INSN_LASX(xvclo_w, vv)
+INSN_LASX(xvclo_d, vv)
+INSN_LASX(xvclz_b, vv)
+INSN_LASX(xvclz_h, vv)
+INSN_LASX(xvclz_w, vv)
+INSN_LASX(xvclz_d, vv)
+
+INSN_LASX(xvpcnt_b, vv)
+INSN_LASX(xvpcnt_h, vv)
+INSN_LASX(xvpcnt_w, vv)
+INSN_LASX(xvpcnt_d, vv)
+
+INSN_LASX(xvbitclr_b, vvv)
+INSN_LASX(xvbitclr_h, vvv)
+INSN_LASX(xvbitclr_w, vvv)
+INSN_LASX(xvbitclr_d, vvv)
+INSN_LASX(xvbitclri_b, vv_i)
+INSN_LASX(xvbitclri_h, vv_i)
+INSN_LASX(xvbitclri_w, vv_i)
+INSN_LASX(xvbitclri_d, vv_i)
+INSN_LASX(xvbitset_b, vvv)
+INSN_LASX(xvbitset_h, vvv)
+INSN_LASX(xvbitset_w, vvv)
+INSN_LASX(xvbitset_d, vvv)
+INSN_LASX(xvbitseti_b, vv_i)
+INSN_LASX(xvbitseti_h, vv_i)
+INSN_LASX(xvbitseti_w, vv_i)
+INSN_LASX(xvbitseti_d, vv_i)
+INSN_LASX(xvbitrev_b, vvv)
+INSN_LASX(xvbitrev_h, vvv)
+INSN_LASX(xvbitrev_w, vvv)
+INSN_LASX(xvbitrev_d, vvv)
+INSN_LASX(xvbitrevi_b, vv_i)
+INSN_LASX(xvbitrevi_h, vv_i)
+INSN_LASX(xvbitrevi_w, vv_i)
+INSN_LASX(xvbitrevi_d, vv_i)
+
+INSN_LASX(xvfrstp_b, vvv)
+INSN_LASX(xvfrstp_h, vvv)
+INSN_LASX(xvfrstpi_b, vv_i)
+INSN_LASX(xvfrstpi_h, vv_i)
+
+INSN_LASX(xvfadd_s, vvv)
+INSN_LASX(xvfadd_d, vvv)
+INSN_LASX(xvfsub_s, vvv)
+INSN_LASX(xvfsub_d, vvv)
+INSN_LASX(xvfmul_s, vvv)
+INSN_LASX(xvfmul_d, vvv)
+INSN_LASX(xvfdiv_s, vvv)
+INSN_LASX(xvfdiv_d, vvv)
+
+INSN_LASX(xvfmadd_s, vvvv)
+INSN_LASX(xvfmadd_d, vvvv)
+INSN_LASX(xvfmsub_s, vvvv)
+INSN_LASX(xvfmsub_d, vvvv)
+INSN_LASX(xvfnmadd_s, vvvv)
+INSN_LASX(xvfnmadd_d, vvvv)
+INSN_LASX(xvfnmsub_s, vvvv)
+INSN_LASX(xvfnmsub_d, vvvv)
+
+INSN_LASX(xvfmax_s, vvv)
+INSN_LASX(xvfmax_d, vvv)
+INSN_LASX(xvfmin_s, vvv)
+INSN_LASX(xvfmin_d, vvv)
+
+INSN_LASX(xvfmaxa_s, vvv)
+INSN_LASX(xvfmaxa_d, vvv)
+INSN_LASX(xvfmina_s, vvv)
+INSN_LASX(xvfmina_d, vvv)
+
+INSN_LASX(xvflogb_s, vv)
+INSN_LASX(xvflogb_d, vv)
+
+INSN_LASX(xvfclass_s, vv)
+INSN_LASX(xvfclass_d, vv)
+
+INSN_LASX(xvfsqrt_s, vv)
+INSN_LASX(xvfsqrt_d, vv)
+INSN_LASX(xvfrecip_s, vv)
+INSN_LASX(xvfrecip_d, vv)
+INSN_LASX(xvfrsqrt_s, vv)
+INSN_LASX(xvfrsqrt_d, vv)
+
+INSN_LASX(xvfcvtl_s_h, vv)
+INSN_LASX(xvfcvth_s_h, vv)
+INSN_LASX(xvfcvtl_d_s, vv)
+INSN_LASX(xvfcvth_d_s, vv)
+INSN_LASX(xvfcvt_h_s, vvv)
+INSN_LASX(xvfcvt_s_d, vvv)
+
+INSN_LASX(xvfrint_s, vv)
+INSN_LASX(xvfrint_d, vv)
+INSN_LASX(xvfrintrm_s, vv)
+INSN_LASX(xvfrintrm_d, vv)
+INSN_LASX(xvfrintrp_s, vv)
+INSN_LASX(xvfrintrp_d, vv)
+INSN_LASX(xvfrintrz_s, vv)
+INSN_LASX(xvfrintrz_d, vv)
+INSN_LASX(xvfrintrne_s, vv)
+INSN_LASX(xvfrintrne_d, vv)
+
+INSN_LASX(xvftint_w_s, vv)
+INSN_LASX(xvftint_l_d, vv)
+INSN_LASX(xvftintrm_w_s, vv)
+INSN_LASX(xvftintrm_l_d, vv)
+INSN_LASX(xvftintrp_w_s, vv)
+INSN_LASX(xvftintrp_l_d, vv)
+INSN_LASX(xvftintrz_w_s, vv)
+INSN_LASX(xvftintrz_l_d, vv)
+INSN_LASX(xvftintrne_w_s, vv)
+INSN_LASX(xvftintrne_l_d, vv)
+INSN_LASX(xvftint_wu_s, vv)
+INSN_LASX(xvftint_lu_d, vv)
+INSN_LASX(xvftintrz_wu_s, vv)
+INSN_LASX(xvftintrz_lu_d, vv)
+INSN_LASX(xvftint_w_d, vvv)
+INSN_LASX(xvftintrm_w_d, vvv)
+INSN_LASX(xvftintrp_w_d, vvv)
+INSN_LASX(xvftintrz_w_d, vvv)
+INSN_LASX(xvftintrne_w_d, vvv)
+INSN_LASX(xvftintl_l_s, vv)
+INSN_LASX(xvftinth_l_s, vv)
+INSN_LASX(xvftintrml_l_s, vv)
+INSN_LASX(xvftintrmh_l_s, vv)
+INSN_LASX(xvftintrpl_l_s, vv)
+INSN_LASX(xvftintrph_l_s, vv)
+INSN_LASX(xvftintrzl_l_s, vv)
+INSN_LASX(xvftintrzh_l_s, vv)
+INSN_LASX(xvftintrnel_l_s, vv)
+INSN_LASX(xvftintrneh_l_s, vv)
+
+INSN_LASX(xvffint_s_w, vv)
+INSN_LASX(xvffint_s_wu, vv)
+INSN_LASX(xvffint_d_l, vv)
+INSN_LASX(xvffint_d_lu, vv)
+INSN_LASX(xvffintl_d_w, vv)
+INSN_LASX(xvffinth_d_w, vv)
+INSN_LASX(xvffint_s_l, vvv)
+
+INSN_LASX(xvseq_b, vvv)
+INSN_LASX(xvseq_h, vvv)
+INSN_LASX(xvseq_w, vvv)
+INSN_LASX(xvseq_d, vvv)
+INSN_LASX(xvseqi_b, vv_i)
+INSN_LASX(xvseqi_h, vv_i)
+INSN_LASX(xvseqi_w, vv_i)
+INSN_LASX(xvseqi_d, vv_i)
+
+INSN_LASX(xvsle_b, vvv)
+INSN_LASX(xvsle_h, vvv)
+INSN_LASX(xvsle_w, vvv)
+INSN_LASX(xvsle_d, vvv)
+INSN_LASX(xvslei_b, vv_i)
+INSN_LASX(xvslei_h, vv_i)
+INSN_LASX(xvslei_w, vv_i)
+INSN_LASX(xvslei_d, vv_i)
+INSN_LASX(xvsle_bu, vvv)
+INSN_LASX(xvsle_hu, vvv)
+INSN_LASX(xvsle_wu, vvv)
+INSN_LASX(xvsle_du, vvv)
+INSN_LASX(xvslei_bu, vv_i)
+INSN_LASX(xvslei_hu, vv_i)
+INSN_LASX(xvslei_wu, vv_i)
+INSN_LASX(xvslei_du, vv_i)
+
+INSN_LASX(xvslt_b, vvv)
+INSN_LASX(xvslt_h, vvv)
+INSN_LASX(xvslt_w, vvv)
+INSN_LASX(xvslt_d, vvv)
+INSN_LASX(xvslti_b, vv_i)
+INSN_LASX(xvslti_h, vv_i)
+INSN_LASX(xvslti_w, vv_i)
+INSN_LASX(xvslti_d, vv_i)
+INSN_LASX(xvslt_bu, vvv)
+INSN_LASX(xvslt_hu, vvv)
+INSN_LASX(xvslt_wu, vvv)
+INSN_LASX(xvslt_du, vvv)
+INSN_LASX(xvslti_bu, vv_i)
+INSN_LASX(xvslti_hu, vv_i)
+INSN_LASX(xvslti_wu, vv_i)
+INSN_LASX(xvslti_du, vv_i)
+
+#define output_xvfcmp(C, PREFIX, SUFFIX) \
+{ \
+ (C)->info->fprintf_func((C)->info->stream, "%08x %s%s\tx%d, x%d, x%d", \
+ (C)->insn, PREFIX, SUFFIX, a->vd, \
+ a->vj, a->vk); \
+}
+static bool output_xxx_fcond(DisasContext *ctx, arg_vvv_fcond * a,
+ const char *suffix)
+{
+ bool ret = true;
+ switch (a->fcond) {
+ case 0x0:
+ output_xvfcmp(ctx, "xvfcmp_caf_", suffix);
+ break;
+ case 0x1:
+ output_xvfcmp(ctx, "xvfcmp_saf_", suffix);
+ break;
+ case 0x2:
+ output_xvfcmp(ctx, "xvfcmp_clt_", suffix);
+ break;
+ case 0x3:
+ output_xvfcmp(ctx, "xvfcmp_slt_", suffix);
+ break;
+ case 0x4:
+ output_xvfcmp(ctx, "xvfcmp_ceq_", suffix);
+ break;
+ case 0x5:
+ output_xvfcmp(ctx, "xvfcmp_seq_", suffix);
+ break;
+ case 0x6:
+ output_xvfcmp(ctx, "xvfcmp_cle_", suffix);
+ break;
+ case 0x7:
+ output_xvfcmp(ctx, "xvfcmp_sle_", suffix);
+ break;
+ case 0x8:
+ output_xvfcmp(ctx, "xvfcmp_cun_", suffix);
+ break;
+ case 0x9:
+ output_xvfcmp(ctx, "xvfcmp_sun_", suffix);
+ break;
+ case 0xA:
+ output_xvfcmp(ctx, "xvfcmp_cult_", suffix);
+ break;
+ case 0xB:
+ output_xvfcmp(ctx, "xvfcmp_sult_", suffix);
+ break;
+ case 0xC:
+ output_xvfcmp(ctx, "xvfcmp_cueq_", suffix);
+ break;
+ case 0xD:
+ output_xvfcmp(ctx, "xvfcmp_sueq_", suffix);
+ break;
+ case 0xE:
+ output_xvfcmp(ctx, "xvfcmp_cule_", suffix);
+ break;
+ case 0xF:
+ output_xvfcmp(ctx, "xvfcmp_sule_", suffix);
+ break;
+ case 0x10:
+ output_xvfcmp(ctx, "xvfcmp_cne_", suffix);
+ break;
+ case 0x11:
+ output_xvfcmp(ctx, "xvfcmp_sne_", suffix);
+ break;
+ case 0x14:
+ output_xvfcmp(ctx, "xvfcmp_cor_", suffix);
+ break;
+ case 0x15:
+ output_xvfcmp(ctx, "xvfcmp_sor_", suffix);
+ break;
+ case 0x18:
+ output_xvfcmp(ctx, "xvfcmp_cune_", suffix);
+ break;
+ case 0x19:
+ output_xvfcmp(ctx, "xvfcmp_sune_", suffix);
+ break;
+ default:
+ ret = false;
+ }
+ return ret;
+}
+
+#define LASX_FCMP_INSN(suffix) \
+static bool trans_xvfcmp_cond_##suffix(DisasContext *ctx, \
+ arg_vvv_fcond * a) \
+{ \
+ return output_xxx_fcond(ctx, a, #suffix); \
+}
+
+LASX_FCMP_INSN(s)
+LASX_FCMP_INSN(d)
+
+INSN_LASX(xvbitsel_v, vvvv)
+INSN_LASX(xvbitseli_b, vv_i)
+
+INSN_LASX(xvseteqz_v, cv)
+INSN_LASX(xvsetnez_v, cv)
+INSN_LASX(xvsetanyeqz_b, cv)
+INSN_LASX(xvsetanyeqz_h, cv)
+INSN_LASX(xvsetanyeqz_w, cv)
+INSN_LASX(xvsetanyeqz_d, cv)
+INSN_LASX(xvsetallnez_b, cv)
+INSN_LASX(xvsetallnez_h, cv)
+INSN_LASX(xvsetallnez_w, cv)
+INSN_LASX(xvsetallnez_d, cv)
+
+INSN_LASX(xvinsgr2vr_w, vr_i)
+INSN_LASX(xvinsgr2vr_d, vr_i)
+INSN_LASX(xvpickve2gr_w, rv_i)
+INSN_LASX(xvpickve2gr_d, rv_i)
+INSN_LASX(xvpickve2gr_wu, rv_i)
+INSN_LASX(xvpickve2gr_du, rv_i)
+
+INSN_LASX(xvreplgr2vr_b, vr)
+INSN_LASX(xvreplgr2vr_h, vr)
+INSN_LASX(xvreplgr2vr_w, vr)
+INSN_LASX(xvreplgr2vr_d, vr)
+
+INSN_LASX(xvreplve_b, vvr)
+INSN_LASX(xvreplve_h, vvr)
+INSN_LASX(xvreplve_w, vvr)
+INSN_LASX(xvreplve_d, vvr)
+INSN_LASX(xvrepl128vei_b, vv_i)
+INSN_LASX(xvrepl128vei_h, vv_i)
+INSN_LASX(xvrepl128vei_w, vv_i)
+INSN_LASX(xvrepl128vei_d, vv_i)
+
+INSN_LASX(xvreplve0_b, vv)
+INSN_LASX(xvreplve0_h, vv)
+INSN_LASX(xvreplve0_w, vv)
+INSN_LASX(xvreplve0_d, vv)
+INSN_LASX(xvreplve0_q, vv)
+
+INSN_LASX(xvinsve0_w, vv_i)
+INSN_LASX(xvinsve0_d, vv_i)
+
+INSN_LASX(xvpickve_w, vv_i)
+INSN_LASX(xvpickve_d, vv_i)
+
+INSN_LASX(xvbsll_v, vv_i)
+INSN_LASX(xvbsrl_v, vv_i)
+
+INSN_LASX(xvpackev_b, vvv)
+INSN_LASX(xvpackev_h, vvv)
+INSN_LASX(xvpackev_w, vvv)
+INSN_LASX(xvpackev_d, vvv)
+INSN_LASX(xvpackod_b, vvv)
+INSN_LASX(xvpackod_h, vvv)
+INSN_LASX(xvpackod_w, vvv)
+INSN_LASX(xvpackod_d, vvv)
+
+INSN_LASX(xvpickev_b, vvv)
+INSN_LASX(xvpickev_h, vvv)
+INSN_LASX(xvpickev_w, vvv)
+INSN_LASX(xvpickev_d, vvv)
+INSN_LASX(xvpickod_b, vvv)
+INSN_LASX(xvpickod_h, vvv)
+INSN_LASX(xvpickod_w, vvv)
+INSN_LASX(xvpickod_d, vvv)
+
+INSN_LASX(xvilvl_b, vvv)
+INSN_LASX(xvilvl_h, vvv)
+INSN_LASX(xvilvl_w, vvv)
+INSN_LASX(xvilvl_d, vvv)
+INSN_LASX(xvilvh_b, vvv)
+INSN_LASX(xvilvh_h, vvv)
+INSN_LASX(xvilvh_w, vvv)
+INSN_LASX(xvilvh_d, vvv)
+
+INSN_LASX(xvshuf_b, vvvv)
+INSN_LASX(xvshuf_h, vvv)
+INSN_LASX(xvshuf_w, vvv)
+INSN_LASX(xvshuf_d, vvv)
+
+INSN_LASX(xvperm_w, vvv)
+
+INSN_LASX(xvshuf4i_b, vv_i)
+INSN_LASX(xvshuf4i_h, vv_i)
+INSN_LASX(xvshuf4i_w, vv_i)
+INSN_LASX(xvshuf4i_d, vv_i)
+
+INSN_LASX(xvpermi_w, vv_i)
+INSN_LASX(xvpermi_d, vv_i)
+INSN_LASX(xvpermi_q, vv_i)
+
+INSN_LASX(xvextrins_d, vv_i)
+INSN_LASX(xvextrins_w, vv_i)
+INSN_LASX(xvextrins_h, vv_i)
+INSN_LASX(xvextrins_b, vv_i)
+
+INSN_LASX(xvld, vr_i)
+INSN_LASX(xvst, vr_i)
+INSN_LASX(xvldx, vrr)
+INSN_LASX(xvstx, vrr)
+
+INSN_LASX(xvldrepl_d, vr_i)
+INSN_LASX(xvldrepl_w, vr_i)
+INSN_LASX(xvldrepl_h, vr_i)
+INSN_LASX(xvldrepl_b, vr_i)
+INSN_LASX(xvstelm_d, vr_ii)
+INSN_LASX(xvstelm_w, vr_ii)
+INSN_LASX(xvstelm_h, vr_ii)
+INSN_LASX(xvstelm_b, vr_ii)
diff --git a/target/loongarch/gdbstub.c b/target/loongarch/gdbstub.c
index b09804b..5fc2f19 100644
--- a/target/loongarch/gdbstub.c
+++ b/target/loongarch/gdbstub.c
@@ -11,6 +11,7 @@
#include "internals.h"
#include "exec/gdbstub.h"
#include "gdbstub/helpers.h"
+#include "vec.h"
uint64_t read_fcc(CPULoongArchState *env)
{
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index ffb1e0b..b3b64a0 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -133,22 +133,22 @@
#endif
/* LoongArch LSX */
-DEF_HELPER_4(vhaddw_h_b, void, env, i32, i32, i32)
-DEF_HELPER_4(vhaddw_w_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vhaddw_d_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vhaddw_q_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vhaddw_hu_bu, void, env, i32, i32, i32)
-DEF_HELPER_4(vhaddw_wu_hu, void, env, i32, i32, i32)
-DEF_HELPER_4(vhaddw_du_wu, void, env, i32, i32, i32)
-DEF_HELPER_4(vhaddw_qu_du, void, env, i32, i32, i32)
-DEF_HELPER_4(vhsubw_h_b, void, env, i32, i32, i32)
-DEF_HELPER_4(vhsubw_w_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vhsubw_d_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vhsubw_q_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vhsubw_hu_bu, void, env, i32, i32, i32)
-DEF_HELPER_4(vhsubw_wu_hu, void, env, i32, i32, i32)
-DEF_HELPER_4(vhsubw_du_wu, void, env, i32, i32, i32)
-DEF_HELPER_4(vhsubw_qu_du, void, env, i32, i32, i32)
+DEF_HELPER_FLAGS_4(vhaddw_h_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vhaddw_w_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vhaddw_d_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vhaddw_q_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vhaddw_hu_bu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vhaddw_wu_hu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vhaddw_du_wu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vhaddw_qu_du, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vhsubw_h_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vhsubw_w_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vhsubw_d_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vhsubw_q_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vhsubw_hu_bu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vhsubw_wu_hu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vhsubw_du_wu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vhsubw_qu_du, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(vaddwev_h_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(vaddwev_w_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
@@ -305,22 +305,22 @@
DEF_HELPER_FLAGS_4(vmaddwod_w_hu_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(vmaddwod_d_wu_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
-DEF_HELPER_4(vdiv_b, void, env, i32, i32, i32)
-DEF_HELPER_4(vdiv_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vdiv_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vdiv_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vdiv_bu, void, env, i32, i32, i32)
-DEF_HELPER_4(vdiv_hu, void, env, i32, i32, i32)
-DEF_HELPER_4(vdiv_wu, void, env, i32, i32, i32)
-DEF_HELPER_4(vdiv_du, void, env, i32, i32, i32)
-DEF_HELPER_4(vmod_b, void, env, i32, i32, i32)
-DEF_HELPER_4(vmod_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vmod_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vmod_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vmod_bu, void, env, i32, i32, i32)
-DEF_HELPER_4(vmod_hu, void, env, i32, i32, i32)
-DEF_HELPER_4(vmod_wu, void, env, i32, i32, i32)
-DEF_HELPER_4(vmod_du, void, env, i32, i32, i32)
+DEF_HELPER_FLAGS_4(vdiv_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vdiv_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vdiv_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vdiv_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vdiv_bu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vdiv_hu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vdiv_wu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vdiv_du, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmod_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmod_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmod_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmod_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmod_bu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmod_hu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmod_wu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmod_du, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(vsat_b, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
DEF_HELPER_FLAGS_4(vsat_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
@@ -331,161 +331,174 @@
DEF_HELPER_FLAGS_4(vsat_wu, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
DEF_HELPER_FLAGS_4(vsat_du, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
-DEF_HELPER_3(vexth_h_b, void, env, i32, i32)
-DEF_HELPER_3(vexth_w_h, void, env, i32, i32)
-DEF_HELPER_3(vexth_d_w, void, env, i32, i32)
-DEF_HELPER_3(vexth_q_d, void, env, i32, i32)
-DEF_HELPER_3(vexth_hu_bu, void, env, i32, i32)
-DEF_HELPER_3(vexth_wu_hu, void, env, i32, i32)
-DEF_HELPER_3(vexth_du_wu, void, env, i32, i32)
-DEF_HELPER_3(vexth_qu_du, void, env, i32, i32)
+DEF_HELPER_FLAGS_3(vexth_h_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(vexth_w_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(vexth_d_w, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(vexth_q_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(vexth_hu_bu, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(vexth_wu_hu, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(vexth_du_wu, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(vexth_qu_du, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+
+DEF_HELPER_FLAGS_3(vext2xv_h_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(vext2xv_w_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(vext2xv_d_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(vext2xv_w_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(vext2xv_d_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(vext2xv_d_w, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(vext2xv_hu_bu, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(vext2xv_wu_bu, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(vext2xv_du_bu, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(vext2xv_wu_hu, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(vext2xv_du_hu, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(vext2xv_du_wu, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(vsigncov_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(vsigncov_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(vsigncov_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(vsigncov_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
-DEF_HELPER_3(vmskltz_b, void, env, i32, i32)
-DEF_HELPER_3(vmskltz_h, void, env, i32, i32)
-DEF_HELPER_3(vmskltz_w, void, env, i32, i32)
-DEF_HELPER_3(vmskltz_d, void, env, i32, i32)
-DEF_HELPER_3(vmskgez_b, void, env, i32, i32)
-DEF_HELPER_3(vmsknz_b, void, env, i32,i32)
+DEF_HELPER_FLAGS_3(vmskltz_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(vmskltz_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(vmskltz_w, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(vmskltz_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(vmskgez_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(vmsknz_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(vnori_b, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
-DEF_HELPER_4(vsllwil_h_b, void, env, i32, i32, i32)
-DEF_HELPER_4(vsllwil_w_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vsllwil_d_w, void, env, i32, i32, i32)
-DEF_HELPER_3(vextl_q_d, void, env, i32, i32)
-DEF_HELPER_4(vsllwil_hu_bu, void, env, i32, i32, i32)
-DEF_HELPER_4(vsllwil_wu_hu, void, env, i32, i32, i32)
-DEF_HELPER_4(vsllwil_du_wu, void, env, i32, i32, i32)
-DEF_HELPER_3(vextl_qu_du, void, env, i32, i32)
+DEF_HELPER_FLAGS_4(vsllwil_h_b, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vsllwil_w_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vsllwil_d_w, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_3(vextl_q_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsllwil_hu_bu, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vsllwil_wu_hu, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vsllwil_du_wu, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_3(vextl_qu_du, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
-DEF_HELPER_4(vsrlr_b, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrlr_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrlr_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrlr_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrlri_b, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrlri_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrlri_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrlri_d, void, env, i32, i32, i32)
+DEF_HELPER_FLAGS_4(vsrlr_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsrlr_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsrlr_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsrlr_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsrlri_b, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vsrlri_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vsrlri_w, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vsrlri_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
-DEF_HELPER_4(vsrar_b, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrar_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrar_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrar_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrari_b, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrari_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrari_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrari_d, void, env, i32, i32, i32)
+DEF_HELPER_FLAGS_4(vsrar_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsrar_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsrar_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsrar_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsrari_b, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vsrari_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vsrari_w, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vsrari_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
-DEF_HELPER_4(vsrln_b_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrln_h_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrln_w_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vsran_b_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vsran_h_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vsran_w_d, void, env, i32, i32, i32)
+DEF_HELPER_FLAGS_4(vsrln_b_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsrln_h_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsrln_w_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsran_b_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsran_h_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsran_w_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
-DEF_HELPER_4(vsrlni_b_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrlni_h_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrlni_w_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrlni_d_q, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrani_b_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrani_h_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrani_w_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrani_d_q, void, env, i32, i32, i32)
+DEF_HELPER_FLAGS_4(vsrlni_b_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vsrlni_h_w, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vsrlni_w_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vsrlni_d_q, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vsrani_b_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vsrani_h_w, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vsrani_w_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vsrani_d_q, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
-DEF_HELPER_4(vsrlrn_b_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrlrn_h_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrlrn_w_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrarn_b_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrarn_h_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrarn_w_d, void, env, i32, i32, i32)
+DEF_HELPER_FLAGS_4(vsrlrn_b_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsrlrn_h_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsrlrn_w_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsrarn_b_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsrarn_h_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsrarn_w_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
-DEF_HELPER_4(vsrlrni_b_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrlrni_h_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrlrni_w_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrlrni_d_q, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrarni_b_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrarni_h_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrarni_w_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vsrarni_d_q, void, env, i32, i32, i32)
+DEF_HELPER_FLAGS_4(vsrlrni_b_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vsrlrni_h_w, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vsrlrni_w_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vsrlrni_d_q, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vsrarni_b_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vsrarni_h_w, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vsrarni_w_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vsrarni_d_q, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
-DEF_HELPER_4(vssrln_b_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrln_h_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrln_w_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vssran_b_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vssran_h_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vssran_w_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrln_bu_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrln_hu_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrln_wu_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vssran_bu_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vssran_hu_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vssran_wu_d, void, env, i32, i32, i32)
+DEF_HELPER_FLAGS_4(vssrln_b_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vssrln_h_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vssrln_w_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vssran_b_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vssran_h_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vssran_w_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vssrln_bu_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vssrln_hu_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vssrln_wu_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vssran_bu_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vssran_hu_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vssran_wu_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
-DEF_HELPER_4(vssrlni_b_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrlni_h_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrlni_w_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrlni_d_q, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrani_b_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrani_h_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrani_w_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrani_d_q, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrlni_bu_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrlni_hu_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrlni_wu_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrlni_du_q, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrani_bu_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrani_hu_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrani_wu_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrani_du_q, void, env, i32, i32, i32)
+DEF_HELPER_FLAGS_4(vssrlni_b_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vssrlni_h_w, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vssrlni_w_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vssrlni_d_q, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vssrani_b_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vssrani_h_w, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vssrani_w_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vssrani_d_q, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vssrlni_bu_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vssrlni_hu_w, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vssrlni_wu_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vssrlni_du_q, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vssrani_bu_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vssrani_hu_w, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vssrani_wu_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vssrani_du_q, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
-DEF_HELPER_4(vssrlrn_b_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrlrn_h_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrlrn_w_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrarn_b_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrarn_h_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrarn_w_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrlrn_bu_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrlrn_hu_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrlrn_wu_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrarn_bu_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrarn_hu_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrarn_wu_d, void, env, i32, i32, i32)
+DEF_HELPER_FLAGS_4(vssrlrn_b_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vssrlrn_h_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vssrlrn_w_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vssrarn_b_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vssrarn_h_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vssrarn_w_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vssrlrn_bu_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vssrlrn_hu_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vssrlrn_wu_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vssrarn_bu_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vssrarn_hu_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vssrarn_wu_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
-DEF_HELPER_4(vssrlrni_b_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrlrni_h_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrlrni_w_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrlrni_d_q, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrarni_b_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrarni_h_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrarni_w_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrarni_d_q, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrlrni_bu_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrlrni_hu_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrlrni_wu_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrlrni_du_q, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrarni_bu_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrarni_hu_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrarni_wu_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vssrarni_du_q, void, env, i32, i32, i32)
+DEF_HELPER_FLAGS_4(vssrlrni_b_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vssrlrni_h_w, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vssrlrni_w_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vssrlrni_d_q, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vssrarni_b_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vssrarni_h_w, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vssrarni_w_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vssrarni_d_q, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vssrlrni_bu_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vssrlrni_hu_w, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vssrlrni_wu_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vssrlrni_du_q, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vssrarni_bu_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vssrarni_hu_w, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vssrarni_wu_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vssrarni_du_q, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
-DEF_HELPER_3(vclo_b, void, env, i32, i32)
-DEF_HELPER_3(vclo_h, void, env, i32, i32)
-DEF_HELPER_3(vclo_w, void, env, i32, i32)
-DEF_HELPER_3(vclo_d, void, env, i32, i32)
-DEF_HELPER_3(vclz_b, void, env, i32, i32)
-DEF_HELPER_3(vclz_h, void, env, i32, i32)
-DEF_HELPER_3(vclz_w, void, env, i32, i32)
-DEF_HELPER_3(vclz_d, void, env, i32, i32)
+DEF_HELPER_FLAGS_3(vclo_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(vclo_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(vclo_w, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(vclo_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(vclz_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(vclz_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(vclz_w, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(vclz_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
-DEF_HELPER_3(vpcnt_b, void, env, i32, i32)
-DEF_HELPER_3(vpcnt_h, void, env, i32, i32)
-DEF_HELPER_3(vpcnt_w, void, env, i32, i32)
-DEF_HELPER_3(vpcnt_d, void, env, i32, i32)
+DEF_HELPER_FLAGS_3(vpcnt_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(vpcnt_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(vpcnt_w, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(vpcnt_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(vbitclr_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(vbitclr_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
@@ -514,107 +527,107 @@
DEF_HELPER_FLAGS_4(vbitrevi_w, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
DEF_HELPER_FLAGS_4(vbitrevi_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
-DEF_HELPER_4(vfrstp_b, void, env, i32, i32, i32)
-DEF_HELPER_4(vfrstp_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vfrstpi_b, void, env, i32, i32, i32)
-DEF_HELPER_4(vfrstpi_h, void, env, i32, i32, i32)
+DEF_HELPER_FLAGS_4(vfrstp_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vfrstp_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vfrstpi_b, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vfrstpi_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
-DEF_HELPER_4(vfadd_s, void, env, i32, i32, i32)
-DEF_HELPER_4(vfadd_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vfsub_s, void, env, i32, i32, i32)
-DEF_HELPER_4(vfsub_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vfmul_s, void, env, i32, i32, i32)
-DEF_HELPER_4(vfmul_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vfdiv_s, void, env, i32, i32, i32)
-DEF_HELPER_4(vfdiv_d, void, env, i32, i32, i32)
+DEF_HELPER_FLAGS_5(vfadd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_5(vfadd_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_5(vfsub_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_5(vfsub_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_5(vfmul_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_5(vfmul_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_5(vfdiv_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_5(vfdiv_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, env, i32)
-DEF_HELPER_5(vfmadd_s, void, env, i32, i32, i32, i32)
-DEF_HELPER_5(vfmadd_d, void, env, i32, i32, i32, i32)
-DEF_HELPER_5(vfmsub_s, void, env, i32, i32, i32, i32)
-DEF_HELPER_5(vfmsub_d, void, env, i32, i32, i32, i32)
-DEF_HELPER_5(vfnmadd_s, void, env, i32, i32, i32, i32)
-DEF_HELPER_5(vfnmadd_d, void, env, i32, i32, i32, i32)
-DEF_HELPER_5(vfnmsub_s, void, env, i32, i32, i32, i32)
-DEF_HELPER_5(vfnmsub_d, void, env, i32, i32, i32, i32)
+DEF_HELPER_FLAGS_6(vfmadd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_6(vfmadd_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_6(vfmsub_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_6(vfmsub_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_6(vfnmadd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_6(vfnmadd_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_6(vfnmsub_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_6(vfnmsub_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, env, i32)
-DEF_HELPER_4(vfmax_s, void, env, i32, i32, i32)
-DEF_HELPER_4(vfmax_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vfmin_s, void, env, i32, i32, i32)
-DEF_HELPER_4(vfmin_d, void, env, i32, i32, i32)
+DEF_HELPER_FLAGS_5(vfmax_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_5(vfmax_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_5(vfmin_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_5(vfmin_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, env, i32)
-DEF_HELPER_4(vfmaxa_s, void, env, i32, i32, i32)
-DEF_HELPER_4(vfmaxa_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vfmina_s, void, env, i32, i32, i32)
-DEF_HELPER_4(vfmina_d, void, env, i32, i32, i32)
+DEF_HELPER_FLAGS_5(vfmaxa_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_5(vfmaxa_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_5(vfmina_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_5(vfmina_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, env, i32)
-DEF_HELPER_3(vflogb_s, void, env, i32, i32)
-DEF_HELPER_3(vflogb_d, void, env, i32, i32)
+DEF_HELPER_FLAGS_4(vflogb_s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vflogb_d, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
-DEF_HELPER_3(vfclass_s, void, env, i32, i32)
-DEF_HELPER_3(vfclass_d, void, env, i32, i32)
+DEF_HELPER_FLAGS_4(vfclass_s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vfclass_d, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
-DEF_HELPER_3(vfsqrt_s, void, env, i32, i32)
-DEF_HELPER_3(vfsqrt_d, void, env, i32, i32)
-DEF_HELPER_3(vfrecip_s, void, env, i32, i32)
-DEF_HELPER_3(vfrecip_d, void, env, i32, i32)
-DEF_HELPER_3(vfrsqrt_s, void, env, i32, i32)
-DEF_HELPER_3(vfrsqrt_d, void, env, i32, i32)
+DEF_HELPER_FLAGS_4(vfsqrt_s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vfsqrt_d, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vfrecip_s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vfrecip_d, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vfrsqrt_s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vfrsqrt_d, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
-DEF_HELPER_3(vfcvtl_s_h, void, env, i32, i32)
-DEF_HELPER_3(vfcvth_s_h, void, env, i32, i32)
-DEF_HELPER_3(vfcvtl_d_s, void, env, i32, i32)
-DEF_HELPER_3(vfcvth_d_s, void, env, i32, i32)
-DEF_HELPER_4(vfcvt_h_s, void, env, i32, i32, i32)
-DEF_HELPER_4(vfcvt_s_d, void, env, i32, i32, i32)
+DEF_HELPER_FLAGS_4(vfcvtl_s_h, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vfcvth_s_h, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vfcvtl_d_s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vfcvth_d_s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_5(vfcvt_h_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_5(vfcvt_s_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, env, i32)
-DEF_HELPER_3(vfrintrne_s, void, env, i32, i32)
-DEF_HELPER_3(vfrintrne_d, void, env, i32, i32)
-DEF_HELPER_3(vfrintrz_s, void, env, i32, i32)
-DEF_HELPER_3(vfrintrz_d, void, env, i32, i32)
-DEF_HELPER_3(vfrintrp_s, void, env, i32, i32)
-DEF_HELPER_3(vfrintrp_d, void, env, i32, i32)
-DEF_HELPER_3(vfrintrm_s, void, env, i32, i32)
-DEF_HELPER_3(vfrintrm_d, void, env, i32, i32)
-DEF_HELPER_3(vfrint_s, void, env, i32, i32)
-DEF_HELPER_3(vfrint_d, void, env, i32, i32)
+DEF_HELPER_FLAGS_4(vfrintrne_s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vfrintrne_d, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vfrintrz_s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vfrintrz_d, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vfrintrp_s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vfrintrp_d, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vfrintrm_s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vfrintrm_d, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vfrint_s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vfrint_d, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
-DEF_HELPER_3(vftintrne_w_s, void, env, i32, i32)
-DEF_HELPER_3(vftintrne_l_d, void, env, i32, i32)
-DEF_HELPER_3(vftintrz_w_s, void, env, i32, i32)
-DEF_HELPER_3(vftintrz_l_d, void, env, i32, i32)
-DEF_HELPER_3(vftintrp_w_s, void, env, i32, i32)
-DEF_HELPER_3(vftintrp_l_d, void, env, i32, i32)
-DEF_HELPER_3(vftintrm_w_s, void, env, i32, i32)
-DEF_HELPER_3(vftintrm_l_d, void, env, i32, i32)
-DEF_HELPER_3(vftint_w_s, void, env, i32, i32)
-DEF_HELPER_3(vftint_l_d, void, env, i32, i32)
-DEF_HELPER_3(vftintrz_wu_s, void, env, i32, i32)
-DEF_HELPER_3(vftintrz_lu_d, void, env, i32, i32)
-DEF_HELPER_3(vftint_wu_s, void, env, i32, i32)
-DEF_HELPER_3(vftint_lu_d, void, env, i32, i32)
-DEF_HELPER_4(vftintrne_w_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vftintrz_w_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vftintrp_w_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vftintrm_w_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vftint_w_d, void, env, i32, i32, i32)
-DEF_HELPER_3(vftintrnel_l_s, void, env, i32, i32)
-DEF_HELPER_3(vftintrneh_l_s, void, env, i32, i32)
-DEF_HELPER_3(vftintrzl_l_s, void, env, i32, i32)
-DEF_HELPER_3(vftintrzh_l_s, void, env, i32, i32)
-DEF_HELPER_3(vftintrpl_l_s, void, env, i32, i32)
-DEF_HELPER_3(vftintrph_l_s, void, env, i32, i32)
-DEF_HELPER_3(vftintrml_l_s, void, env, i32, i32)
-DEF_HELPER_3(vftintrmh_l_s, void, env, i32, i32)
-DEF_HELPER_3(vftintl_l_s, void, env, i32, i32)
-DEF_HELPER_3(vftinth_l_s, void, env, i32, i32)
+DEF_HELPER_FLAGS_4(vftintrne_w_s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vftintrne_l_d, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vftintrz_w_s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vftintrz_l_d, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vftintrp_w_s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vftintrp_l_d, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vftintrm_w_s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vftintrm_l_d, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vftint_w_s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vftint_l_d, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vftintrz_wu_s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vftintrz_lu_d, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vftint_wu_s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vftint_lu_d, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_5(vftintrne_w_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_5(vftintrz_w_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_5(vftintrp_w_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_5(vftintrm_w_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_5(vftint_w_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vftintrnel_l_s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vftintrneh_l_s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vftintrzl_l_s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vftintrzh_l_s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vftintrpl_l_s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vftintrph_l_s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vftintrml_l_s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vftintrmh_l_s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vftintl_l_s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vftinth_l_s, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
-DEF_HELPER_3(vffint_s_w, void, env, i32, i32)
-DEF_HELPER_3(vffint_d_l, void, env, i32, i32)
-DEF_HELPER_3(vffint_s_wu, void, env, i32, i32)
-DEF_HELPER_3(vffint_d_lu, void, env, i32, i32)
-DEF_HELPER_3(vffintl_d_w, void, env, i32, i32)
-DEF_HELPER_3(vffinth_d_w, void, env, i32, i32)
-DEF_HELPER_4(vffint_s_l, void, env, i32, i32, i32)
+DEF_HELPER_FLAGS_4(vffint_s_w, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vffint_d_l, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vffint_s_wu, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vffint_d_lu, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vffintl_d_w, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_4(vffinth_d_w, TCG_CALL_NO_RWG, void, ptr, ptr, env, i32)
+DEF_HELPER_FLAGS_5(vffint_s_l, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, env, i32)
DEF_HELPER_FLAGS_4(vseqi_b, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
DEF_HELPER_FLAGS_4(vseqi_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
@@ -639,61 +652,69 @@
DEF_HELPER_FLAGS_4(vslti_wu, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
DEF_HELPER_FLAGS_4(vslti_du, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
-DEF_HELPER_5(vfcmp_c_s, void, env, i32, i32, i32, i32)
-DEF_HELPER_5(vfcmp_s_s, void, env, i32, i32, i32, i32)
-DEF_HELPER_5(vfcmp_c_d, void, env, i32, i32, i32, i32)
-DEF_HELPER_5(vfcmp_s_d, void, env, i32, i32, i32, i32)
+DEF_HELPER_6(vfcmp_c_s, void, env, i32, i32, i32, i32, i32)
+DEF_HELPER_6(vfcmp_s_s, void, env, i32, i32, i32, i32, i32)
+DEF_HELPER_6(vfcmp_c_d, void, env, i32, i32, i32, i32, i32)
+DEF_HELPER_6(vfcmp_s_d, void, env, i32, i32, i32, i32, i32)
DEF_HELPER_FLAGS_4(vbitseli_b, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
-DEF_HELPER_3(vsetanyeqz_b, void, env, i32, i32)
-DEF_HELPER_3(vsetanyeqz_h, void, env, i32, i32)
-DEF_HELPER_3(vsetanyeqz_w, void, env, i32, i32)
-DEF_HELPER_3(vsetanyeqz_d, void, env, i32, i32)
-DEF_HELPER_3(vsetallnez_b, void, env, i32, i32)
-DEF_HELPER_3(vsetallnez_h, void, env, i32, i32)
-DEF_HELPER_3(vsetallnez_w, void, env, i32, i32)
-DEF_HELPER_3(vsetallnez_d, void, env, i32, i32)
+DEF_HELPER_4(vsetanyeqz_b, void, env, i32, i32, i32)
+DEF_HELPER_4(vsetanyeqz_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vsetanyeqz_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vsetanyeqz_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vsetallnez_b, void, env, i32, i32, i32)
+DEF_HELPER_4(vsetallnez_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vsetallnez_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vsetallnez_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vpackev_b, void, env, i32, i32, i32)
-DEF_HELPER_4(vpackev_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vpackev_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vpackev_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vpackod_b, void, env, i32, i32, i32)
-DEF_HELPER_4(vpackod_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vpackod_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vpackod_d, void, env, i32, i32, i32)
+DEF_HELPER_FLAGS_4(xvinsve0_w, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(xvinsve0_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(xvpickve_w, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(xvpickve_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
-DEF_HELPER_4(vpickev_b, void, env, i32, i32, i32)
-DEF_HELPER_4(vpickev_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vpickev_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vpickev_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vpickod_b, void, env, i32, i32, i32)
-DEF_HELPER_4(vpickod_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vpickod_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vpickod_d, void, env, i32, i32, i32)
+DEF_HELPER_FLAGS_4(vpackev_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vpackev_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vpackev_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vpackev_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vpackod_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vpackod_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vpackod_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vpackod_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
-DEF_HELPER_4(vilvl_b, void, env, i32, i32, i32)
-DEF_HELPER_4(vilvl_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vilvl_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vilvl_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vilvh_b, void, env, i32, i32, i32)
-DEF_HELPER_4(vilvh_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vilvh_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vilvh_d, void, env, i32, i32, i32)
+DEF_HELPER_FLAGS_4(vpickev_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vpickev_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vpickev_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vpickev_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vpickod_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vpickod_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vpickod_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vpickod_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
-DEF_HELPER_5(vshuf_b, void, env, i32, i32, i32, i32)
-DEF_HELPER_4(vshuf_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vshuf_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vshuf_d, void, env, i32, i32, i32)
-DEF_HELPER_4(vshuf4i_b, void, env, i32, i32, i32)
-DEF_HELPER_4(vshuf4i_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vshuf4i_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vshuf4i_d, void, env, i32, i32, i32)
+DEF_HELPER_FLAGS_4(vilvl_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vilvl_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vilvl_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vilvl_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vilvh_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vilvh_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vilvh_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vilvh_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
-DEF_HELPER_4(vpermi_w, void, env, i32, i32, i32)
+DEF_HELPER_FLAGS_5(vshuf_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vshuf_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vshuf_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vshuf_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vshuf4i_b, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vshuf4i_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vshuf4i_w, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vshuf4i_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
-DEF_HELPER_4(vextrins_b, void, env, i32, i32, i32)
-DEF_HELPER_4(vextrins_h, void, env, i32, i32, i32)
-DEF_HELPER_4(vextrins_w, void, env, i32, i32, i32)
-DEF_HELPER_4(vextrins_d, void, env, i32, i32, i32)
+DEF_HELPER_FLAGS_4(vperm_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vpermi_w, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vpermi_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vpermi_q, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+
+DEF_HELPER_FLAGS_4(vextrins_b, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vextrins_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vextrins_w, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vextrins_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc b/target/loongarch/insn_trans/trans_vec.c.inc
similarity index 61%
rename from target/loongarch/insn_trans/trans_lsx.c.inc
rename to target/loongarch/insn_trans/trans_vec.c.inc
index 5fbf271..c647137 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_vec.c.inc
@@ -1,78 +1,254 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
- * LSX translate functions
+ * LoongArch vector translate functions
* Copyright (c) 2022-2023 Loongson Technology Corporation Limited
*/
#ifndef CONFIG_USER_ONLY
-#define CHECK_SXE do { \
- if ((ctx->base.tb->flags & HW_FLAGS_EUEN_SXE) == 0) { \
- generate_exception(ctx, EXCCODE_SXD); \
- return true; \
- } \
-} while (0)
+
+static bool check_vec(DisasContext *ctx, uint32_t oprsz)
+{
+ if ((oprsz == 16) && ((ctx->base.tb->flags & HW_FLAGS_EUEN_SXE) == 0)) {
+ generate_exception(ctx, EXCCODE_SXD);
+ return false;
+ }
+
+ if ((oprsz == 32) && ((ctx->base.tb->flags & HW_FLAGS_EUEN_ASXE) == 0)) {
+ generate_exception(ctx, EXCCODE_ASXD);
+ return false;
+ }
+
+ return true;
+}
+
#else
-#define CHECK_SXE
+
+static bool check_vec(DisasContext *ctx, uint32_t oprsz)
+{
+ return true;
+}
+
#endif
+static bool gen_vvvv_ptr_vl(DisasContext *ctx, arg_vvvv *a, uint32_t oprsz,
+ gen_helper_gvec_4_ptr *fn)
+{
+ if (!check_vec(ctx, oprsz)) {
+ return true;
+ }
+
+ tcg_gen_gvec_4_ptr(vec_full_offset(a->vd),
+ vec_full_offset(a->vj),
+ vec_full_offset(a->vk),
+ vec_full_offset(a->va),
+ cpu_env,
+ oprsz, ctx->vl / 8, 0, fn);
+ return true;
+}
+
+static bool gen_vvvv_ptr(DisasContext *ctx, arg_vvvv *a,
+ gen_helper_gvec_4_ptr *fn)
+{
+ return gen_vvvv_ptr_vl(ctx, a, 16, fn);
+}
+
+static bool gen_xxxx_ptr(DisasContext *ctx, arg_vvvv *a,
+ gen_helper_gvec_4_ptr *fn)
+{
+ return gen_vvvv_ptr_vl(ctx, a, 32, fn);
+}
+
+static bool gen_vvvv_vl(DisasContext *ctx, arg_vvvv *a, uint32_t oprsz,
+ gen_helper_gvec_4 *fn)
+{
+ if (!check_vec(ctx, oprsz)) {
+ return true;
+ }
+
+ tcg_gen_gvec_4_ool(vec_full_offset(a->vd),
+ vec_full_offset(a->vj),
+ vec_full_offset(a->vk),
+ vec_full_offset(a->va),
+ oprsz, ctx->vl / 8, 0, fn);
+ return true;
+}
+
static bool gen_vvvv(DisasContext *ctx, arg_vvvv *a,
- void (*func)(TCGv_ptr, TCGv_i32, TCGv_i32,
- TCGv_i32, TCGv_i32))
+ gen_helper_gvec_4 *fn)
{
- TCGv_i32 vd = tcg_constant_i32(a->vd);
- TCGv_i32 vj = tcg_constant_i32(a->vj);
- TCGv_i32 vk = tcg_constant_i32(a->vk);
- TCGv_i32 va = tcg_constant_i32(a->va);
+ return gen_vvvv_vl(ctx, a, 16, fn);
+}
- CHECK_SXE;
- func(cpu_env, vd, vj, vk, va);
+static bool gen_xxxx(DisasContext *ctx, arg_vvvv *a,
+ gen_helper_gvec_4 *fn)
+{
+ return gen_vvvv_vl(ctx, a, 32, fn);
+}
+
+static bool gen_vvv_ptr_vl(DisasContext *ctx, arg_vvv *a, uint32_t oprsz,
+ gen_helper_gvec_3_ptr *fn)
+{
+ if (!check_vec(ctx, oprsz)) {
+ return true;
+ }
+ tcg_gen_gvec_3_ptr(vec_full_offset(a->vd),
+ vec_full_offset(a->vj),
+ vec_full_offset(a->vk),
+ cpu_env,
+ oprsz, ctx->vl / 8, 0, fn);
return true;
}
-static bool gen_vvv(DisasContext *ctx, arg_vvv *a,
- void (*func)(TCGv_ptr, TCGv_i32, TCGv_i32, TCGv_i32))
+static bool gen_vvv_ptr(DisasContext *ctx, arg_vvv *a,
+ gen_helper_gvec_3_ptr *fn)
{
- TCGv_i32 vd = tcg_constant_i32(a->vd);
- TCGv_i32 vj = tcg_constant_i32(a->vj);
- TCGv_i32 vk = tcg_constant_i32(a->vk);
+ return gen_vvv_ptr_vl(ctx, a, 16, fn);
+}
- CHECK_SXE;
+static bool gen_xxx_ptr(DisasContext *ctx, arg_vvv *a,
+ gen_helper_gvec_3_ptr *fn)
+{
+ return gen_vvv_ptr_vl(ctx, a, 32, fn);
+}
- func(cpu_env, vd, vj, vk);
+static bool gen_vvv_vl(DisasContext *ctx, arg_vvv *a, uint32_t oprsz,
+ gen_helper_gvec_3 *fn)
+{
+ if (!check_vec(ctx, oprsz)) {
+ return true;
+ }
+
+ tcg_gen_gvec_3_ool(vec_full_offset(a->vd),
+ vec_full_offset(a->vj),
+ vec_full_offset(a->vk),
+ oprsz, ctx->vl / 8, 0, fn);
return true;
}
-static bool gen_vv(DisasContext *ctx, arg_vv *a,
- void (*func)(TCGv_ptr, TCGv_i32, TCGv_i32))
+static bool gen_vvv(DisasContext *ctx, arg_vvv *a, gen_helper_gvec_3 *fn)
{
- TCGv_i32 vd = tcg_constant_i32(a->vd);
- TCGv_i32 vj = tcg_constant_i32(a->vj);
+ return gen_vvv_vl(ctx, a, 16, fn);
+}
- CHECK_SXE;
- func(cpu_env, vd, vj);
+static bool gen_xxx(DisasContext *ctx, arg_vvv *a, gen_helper_gvec_3 *fn)
+{
+ return gen_vvv_vl(ctx, a, 32, fn);
+}
+
+static bool gen_vv_ptr_vl(DisasContext *ctx, arg_vv *a, uint32_t oprsz,
+ gen_helper_gvec_2_ptr *fn)
+{
+ if (!check_vec(ctx, oprsz)) {
+ return true;
+ }
+
+ tcg_gen_gvec_2_ptr(vec_full_offset(a->vd),
+ vec_full_offset(a->vj),
+ cpu_env,
+ oprsz, ctx->vl / 8, 0, fn);
return true;
}
-static bool gen_vv_i(DisasContext *ctx, arg_vv_i *a,
- void (*func)(TCGv_ptr, TCGv_i32, TCGv_i32, TCGv_i32))
+static bool gen_vv_ptr(DisasContext *ctx, arg_vv *a,
+ gen_helper_gvec_2_ptr *fn)
{
- TCGv_i32 vd = tcg_constant_i32(a->vd);
- TCGv_i32 vj = tcg_constant_i32(a->vj);
- TCGv_i32 imm = tcg_constant_i32(a->imm);
+ return gen_vv_ptr_vl(ctx, a, 16, fn);
+}
- CHECK_SXE;
- func(cpu_env, vd, vj, imm);
+static bool gen_xx_ptr(DisasContext *ctx, arg_vv *a,
+ gen_helper_gvec_2_ptr *fn)
+{
+ return gen_vv_ptr_vl(ctx, a, 32, fn);
+}
+
+static bool gen_vv_vl(DisasContext *ctx, arg_vv *a, uint32_t oprsz,
+ gen_helper_gvec_2 *fn)
+{
+ if (!check_vec(ctx, oprsz)) {
+ return true;
+ }
+
+ tcg_gen_gvec_2_ool(vec_full_offset(a->vd),
+ vec_full_offset(a->vj),
+ oprsz, ctx->vl / 8, 0, fn);
+ return true;
+}
+
+static bool gen_vv(DisasContext *ctx, arg_vv *a, gen_helper_gvec_2 *fn)
+{
+ return gen_vv_vl(ctx, a, 16, fn);
+}
+
+static bool gen_xx(DisasContext *ctx, arg_vv *a, gen_helper_gvec_2 *fn)
+{
+ return gen_vv_vl(ctx, a, 32, fn);
+}
+
+static bool gen_vv_i_vl(DisasContext *ctx, arg_vv_i *a, uint32_t oprsz,
+ gen_helper_gvec_2i *fn)
+{
+ if (!check_vec(ctx, oprsz)) {
+ return true;
+ }
+
+ tcg_gen_gvec_2i_ool(vec_full_offset(a->vd),
+ vec_full_offset(a->vj),
+ tcg_constant_i64(a->imm),
+ oprsz, ctx->vl / 8, 0, fn);
+ return true;
+}
+
+static bool gen_vv_i(DisasContext *ctx, arg_vv_i *a, gen_helper_gvec_2i *fn)
+{
+ return gen_vv_i_vl(ctx, a, 16, fn);
+}
+
+static bool gen_xx_i(DisasContext *ctx, arg_vv_i *a, gen_helper_gvec_2i *fn)
+{
+ return gen_vv_i_vl(ctx, a, 32, fn);
+}
+
+static bool gen_cv_vl(DisasContext *ctx, arg_cv *a, uint32_t sz,
+ void (*func)(TCGv_ptr, TCGv_i32, TCGv_i32, TCGv_i32))
+{
+ if (!check_vec(ctx, sz)) {
+ return true;
+ }
+
+ TCGv_i32 vj = tcg_constant_i32(a->vj);
+ TCGv_i32 cd = tcg_constant_i32(a->cd);
+ TCGv_i32 oprsz = tcg_constant_i32(sz);
+
+ func(cpu_env, oprsz, cd, vj);
return true;
}
static bool gen_cv(DisasContext *ctx, arg_cv *a,
- void (*func)(TCGv_ptr, TCGv_i32, TCGv_i32))
+ void (*func)(TCGv_ptr, TCGv_i32, TCGv_i32, TCGv_i32))
{
- TCGv_i32 vj = tcg_constant_i32(a->vj);
- TCGv_i32 cd = tcg_constant_i32(a->cd);
+ return gen_cv_vl(ctx, a, 16, func);
+}
- CHECK_SXE;
- func(cpu_env, cd, vj);
+static bool gen_cx(DisasContext *ctx, arg_cv *a,
+ void (*func)(TCGv_ptr, TCGv_i32, TCGv_i32, TCGv_i32))
+{
+ return gen_cv_vl(ctx, a, 32, func);
+}
+
+static bool gvec_vvv_vl(DisasContext *ctx, arg_vvv *a,
+ uint32_t oprsz, MemOp mop,
+ void (*func)(unsigned, uint32_t, uint32_t,
+ uint32_t, uint32_t, uint32_t))
+{
+ uint32_t vd_ofs = vec_full_offset(a->vd);
+ uint32_t vj_ofs = vec_full_offset(a->vj);
+ uint32_t vk_ofs = vec_full_offset(a->vk);
+
+ if (!check_vec(ctx, oprsz)) {
+ return true;
+ }
+
+ func(mop, vd_ofs, vj_ofs, vk_ofs, oprsz, ctx->vl / 8);
return true;
}
@@ -80,30 +256,60 @@
void (*func)(unsigned, uint32_t, uint32_t,
uint32_t, uint32_t, uint32_t))
{
- uint32_t vd_ofs, vj_ofs, vk_ofs;
+ return gvec_vvv_vl(ctx, a, 16, mop, func);
+}
- CHECK_SXE;
+static bool gvec_xxx(DisasContext *ctx, arg_vvv *a, MemOp mop,
+ void (*func)(unsigned, uint32_t, uint32_t,
+ uint32_t, uint32_t, uint32_t))
+{
+ return gvec_vvv_vl(ctx, a, 32, mop, func);
+}
- vd_ofs = vec_full_offset(a->vd);
- vj_ofs = vec_full_offset(a->vj);
- vk_ofs = vec_full_offset(a->vk);
+static bool gvec_vv_vl(DisasContext *ctx, arg_vv *a,
+ uint32_t oprsz, MemOp mop,
+ void (*func)(unsigned, uint32_t, uint32_t,
+ uint32_t, uint32_t))
+{
+ uint32_t vd_ofs = vec_full_offset(a->vd);
+ uint32_t vj_ofs = vec_full_offset(a->vj);
- func(mop, vd_ofs, vj_ofs, vk_ofs, 16, ctx->vl/8);
+ if (!check_vec(ctx, oprsz)) {
+ return true;
+ }
+
+ func(mop, vd_ofs, vj_ofs, oprsz, ctx->vl / 8);
return true;
}
+
static bool gvec_vv(DisasContext *ctx, arg_vv *a, MemOp mop,
void (*func)(unsigned, uint32_t, uint32_t,
uint32_t, uint32_t))
{
- uint32_t vd_ofs, vj_ofs;
+ return gvec_vv_vl(ctx, a, 16, mop, func);
+}
- CHECK_SXE;
+static bool gvec_xx(DisasContext *ctx, arg_vv *a, MemOp mop,
+ void (*func)(unsigned, uint32_t, uint32_t,
+ uint32_t, uint32_t))
+{
+ return gvec_vv_vl(ctx, a, 32, mop, func);
+}
- vd_ofs = vec_full_offset(a->vd);
- vj_ofs = vec_full_offset(a->vj);
+static bool gvec_vv_i_vl(DisasContext *ctx, arg_vv_i *a,
+ uint32_t oprsz, MemOp mop,
+ void (*func)(unsigned, uint32_t, uint32_t,
+ int64_t, uint32_t, uint32_t))
+{
+ uint32_t vd_ofs = vec_full_offset(a->vd);
+ uint32_t vj_ofs = vec_full_offset(a->vj);
- func(mop, vd_ofs, vj_ofs, 16, ctx->vl/8);
+ if (!check_vec(ctx, oprsz)) {
+ return true;
+ }
+
+ func(mop, vd_ofs, vj_ofs, a->imm, oprsz, ctx->vl / 8);
return true;
}
@@ -111,73 +317,108 @@
void (*func)(unsigned, uint32_t, uint32_t,
int64_t, uint32_t, uint32_t))
{
- uint32_t vd_ofs, vj_ofs;
+ return gvec_vv_i_vl(ctx, a, 16, mop, func);
+}
- CHECK_SXE;
+static bool gvec_xx_i(DisasContext *ctx, arg_vv_i *a, MemOp mop,
+ void (*func)(unsigned, uint32_t, uint32_t,
+ int64_t, uint32_t, uint32_t))
+{
+ return gvec_vv_i_vl(ctx,a, 32, mop, func);
+}
- vd_ofs = vec_full_offset(a->vd);
- vj_ofs = vec_full_offset(a->vj);
+static bool gvec_subi_vl(DisasContext *ctx, arg_vv_i *a,
+ uint32_t oprsz, MemOp mop)
+{
+ uint32_t vd_ofs = vec_full_offset(a->vd);
+ uint32_t vj_ofs = vec_full_offset(a->vj);
- func(mop, vd_ofs, vj_ofs, a->imm , 16, ctx->vl/8);
+ if (!check_vec(ctx, oprsz)) {
+ return true;
+ }
+
+ tcg_gen_gvec_addi(mop, vd_ofs, vj_ofs, -a->imm, oprsz, ctx->vl / 8);
return true;
}
static bool gvec_subi(DisasContext *ctx, arg_vv_i *a, MemOp mop)
{
- uint32_t vd_ofs, vj_ofs;
+ return gvec_subi_vl(ctx, a, 16, mop);
+}
- CHECK_SXE;
-
- vd_ofs = vec_full_offset(a->vd);
- vj_ofs = vec_full_offset(a->vj);
-
- tcg_gen_gvec_addi(mop, vd_ofs, vj_ofs, -a->imm, 16, ctx->vl/8);
- return true;
+static bool gvec_xsubi(DisasContext *ctx, arg_vv_i *a, MemOp mop)
+{
+ return gvec_subi_vl(ctx, a, 32, mop);
}
TRANS(vadd_b, LSX, gvec_vvv, MO_8, tcg_gen_gvec_add)
TRANS(vadd_h, LSX, gvec_vvv, MO_16, tcg_gen_gvec_add)
TRANS(vadd_w, LSX, gvec_vvv, MO_32, tcg_gen_gvec_add)
TRANS(vadd_d, LSX, gvec_vvv, MO_64, tcg_gen_gvec_add)
+TRANS(xvadd_b, LASX, gvec_xxx, MO_8, tcg_gen_gvec_add)
+TRANS(xvadd_h, LASX, gvec_xxx, MO_16, tcg_gen_gvec_add)
+TRANS(xvadd_w, LASX, gvec_xxx, MO_32, tcg_gen_gvec_add)
+TRANS(xvadd_d, LASX, gvec_xxx, MO_64, tcg_gen_gvec_add)
-#define VADDSUB_Q(NAME) \
-static bool trans_v## NAME ##_q(DisasContext *ctx, arg_vvv *a) \
-{ \
- TCGv_i64 rh, rl, ah, al, bh, bl; \
- \
- if (!avail_LSX(ctx)) { \
- return false; \
- } \
- \
- CHECK_SXE; \
- \
- rh = tcg_temp_new_i64(); \
- rl = tcg_temp_new_i64(); \
- ah = tcg_temp_new_i64(); \
- al = tcg_temp_new_i64(); \
- bh = tcg_temp_new_i64(); \
- bl = tcg_temp_new_i64(); \
- \
- get_vreg64(ah, a->vj, 1); \
- get_vreg64(al, a->vj, 0); \
- get_vreg64(bh, a->vk, 1); \
- get_vreg64(bl, a->vk, 0); \
- \
- tcg_gen_## NAME ##2_i64(rl, rh, al, ah, bl, bh); \
- \
- set_vreg64(rh, a->vd, 1); \
- set_vreg64(rl, a->vd, 0); \
- \
- return true; \
+static bool gen_vaddsub_q_vl(DisasContext *ctx, arg_vvv *a, uint32_t oprsz,
+ void (*func)(TCGv_i64, TCGv_i64, TCGv_i64,
+ TCGv_i64, TCGv_i64, TCGv_i64))
+{
+ int i;
+ TCGv_i64 rh, rl, ah, al, bh, bl;
+
+ if (!check_vec(ctx, oprsz)) {
+ return true;
+ }
+
+ rh = tcg_temp_new_i64();
+ rl = tcg_temp_new_i64();
+ ah = tcg_temp_new_i64();
+ al = tcg_temp_new_i64();
+ bh = tcg_temp_new_i64();
+ bl = tcg_temp_new_i64();
+
+ for (i = 0; i < oprsz / 16; i++) {
+ get_vreg64(ah, a->vj, 1 + i * 2);
+ get_vreg64(al, a->vj, i * 2);
+ get_vreg64(bh, a->vk, 1 + i * 2);
+ get_vreg64(bl, a->vk, i * 2);
+
+ func(rl, rh, al, ah, bl, bh);
+
+ set_vreg64(rh, a->vd, 1 + i * 2);
+ set_vreg64(rl, a->vd, i * 2);
+ }
+ return true;
}
-VADDSUB_Q(add)
-VADDSUB_Q(sub)
+static bool gen_vaddsub_q(DisasContext *ctx, arg_vvv *a,
+ void (*func)(TCGv_i64, TCGv_i64, TCGv_i64,
+ TCGv_i64, TCGv_i64, TCGv_i64))
+{
+ return gen_vaddsub_q_vl(ctx, a, 16, func);
+}
+
+static bool gen_xvaddsub_q(DisasContext *ctx, arg_vvv *a,
+ void (*func)(TCGv_i64, TCGv_i64, TCGv_i64,
+ TCGv_i64, TCGv_i64, TCGv_i64))
+{
+ return gen_vaddsub_q_vl(ctx, a, 32, func);
+}
TRANS(vsub_b, LSX, gvec_vvv, MO_8, tcg_gen_gvec_sub)
TRANS(vsub_h, LSX, gvec_vvv, MO_16, tcg_gen_gvec_sub)
TRANS(vsub_w, LSX, gvec_vvv, MO_32, tcg_gen_gvec_sub)
TRANS(vsub_d, LSX, gvec_vvv, MO_64, tcg_gen_gvec_sub)
+TRANS(xvsub_b, LASX, gvec_xxx, MO_8, tcg_gen_gvec_sub)
+TRANS(xvsub_h, LASX, gvec_xxx, MO_16, tcg_gen_gvec_sub)
+TRANS(xvsub_w, LASX, gvec_xxx, MO_32, tcg_gen_gvec_sub)
+TRANS(xvsub_d, LASX, gvec_xxx, MO_64, tcg_gen_gvec_sub)
+
+TRANS(vadd_q, LSX, gen_vaddsub_q, tcg_gen_add2_i64)
+TRANS(vsub_q, LSX, gen_vaddsub_q, tcg_gen_sub2_i64)
+TRANS(xvadd_q, LASX, gen_xvaddsub_q, tcg_gen_add2_i64)
+TRANS(xvsub_q, LASX, gen_xvaddsub_q, tcg_gen_sub2_i64)
TRANS(vaddi_bu, LSX, gvec_vv_i, MO_8, tcg_gen_gvec_addi)
TRANS(vaddi_hu, LSX, gvec_vv_i, MO_16, tcg_gen_gvec_addi)
@@ -187,11 +428,23 @@
TRANS(vsubi_hu, LSX, gvec_subi, MO_16)
TRANS(vsubi_wu, LSX, gvec_subi, MO_32)
TRANS(vsubi_du, LSX, gvec_subi, MO_64)
+TRANS(xvaddi_bu, LASX, gvec_xx_i, MO_8, tcg_gen_gvec_addi)
+TRANS(xvaddi_hu, LASX, gvec_xx_i, MO_16, tcg_gen_gvec_addi)
+TRANS(xvaddi_wu, LASX, gvec_xx_i, MO_32, tcg_gen_gvec_addi)
+TRANS(xvaddi_du, LASX, gvec_xx_i, MO_64, tcg_gen_gvec_addi)
+TRANS(xvsubi_bu, LASX, gvec_xsubi, MO_8)
+TRANS(xvsubi_hu, LASX, gvec_xsubi, MO_16)
+TRANS(xvsubi_wu, LASX, gvec_xsubi, MO_32)
+TRANS(xvsubi_du, LASX, gvec_xsubi, MO_64)
TRANS(vneg_b, LSX, gvec_vv, MO_8, tcg_gen_gvec_neg)
TRANS(vneg_h, LSX, gvec_vv, MO_16, tcg_gen_gvec_neg)
TRANS(vneg_w, LSX, gvec_vv, MO_32, tcg_gen_gvec_neg)
TRANS(vneg_d, LSX, gvec_vv, MO_64, tcg_gen_gvec_neg)
+TRANS(xvneg_b, LASX, gvec_xx, MO_8, tcg_gen_gvec_neg)
+TRANS(xvneg_h, LASX, gvec_xx, MO_16, tcg_gen_gvec_neg)
+TRANS(xvneg_w, LASX, gvec_xx, MO_32, tcg_gen_gvec_neg)
+TRANS(xvneg_d, LASX, gvec_xx, MO_64, tcg_gen_gvec_neg)
TRANS(vsadd_b, LSX, gvec_vvv, MO_8, tcg_gen_gvec_ssadd)
TRANS(vsadd_h, LSX, gvec_vvv, MO_16, tcg_gen_gvec_ssadd)
@@ -210,6 +463,23 @@
TRANS(vssub_wu, LSX, gvec_vvv, MO_32, tcg_gen_gvec_ussub)
TRANS(vssub_du, LSX, gvec_vvv, MO_64, tcg_gen_gvec_ussub)
+TRANS(xvsadd_b, LASX, gvec_xxx, MO_8, tcg_gen_gvec_ssadd)
+TRANS(xvsadd_h, LASX, gvec_xxx, MO_16, tcg_gen_gvec_ssadd)
+TRANS(xvsadd_w, LASX, gvec_xxx, MO_32, tcg_gen_gvec_ssadd)
+TRANS(xvsadd_d, LASX, gvec_xxx, MO_64, tcg_gen_gvec_ssadd)
+TRANS(xvsadd_bu, LASX, gvec_xxx, MO_8, tcg_gen_gvec_usadd)
+TRANS(xvsadd_hu, LASX, gvec_xxx, MO_16, tcg_gen_gvec_usadd)
+TRANS(xvsadd_wu, LASX, gvec_xxx, MO_32, tcg_gen_gvec_usadd)
+TRANS(xvsadd_du, LASX, gvec_xxx, MO_64, tcg_gen_gvec_usadd)
+TRANS(xvssub_b, LASX, gvec_xxx, MO_8, tcg_gen_gvec_sssub)
+TRANS(xvssub_h, LASX, gvec_xxx, MO_16, tcg_gen_gvec_sssub)
+TRANS(xvssub_w, LASX, gvec_xxx, MO_32, tcg_gen_gvec_sssub)
+TRANS(xvssub_d, LASX, gvec_xxx, MO_64, tcg_gen_gvec_sssub)
+TRANS(xvssub_bu, LASX, gvec_xxx, MO_8, tcg_gen_gvec_ussub)
+TRANS(xvssub_hu, LASX, gvec_xxx, MO_16, tcg_gen_gvec_ussub)
+TRANS(xvssub_wu, LASX, gvec_xxx, MO_32, tcg_gen_gvec_ussub)
+TRANS(xvssub_du, LASX, gvec_xxx, MO_64, tcg_gen_gvec_ussub)
+
TRANS(vhaddw_h_b, LSX, gen_vvv, gen_helper_vhaddw_h_b)
TRANS(vhaddw_w_h, LSX, gen_vvv, gen_helper_vhaddw_w_h)
TRANS(vhaddw_d_w, LSX, gen_vvv, gen_helper_vhaddw_d_w)
@@ -227,6 +497,23 @@
TRANS(vhsubw_du_wu, LSX, gen_vvv, gen_helper_vhsubw_du_wu)
TRANS(vhsubw_qu_du, LSX, gen_vvv, gen_helper_vhsubw_qu_du)
+TRANS(xvhaddw_h_b, LASX, gen_xxx, gen_helper_vhaddw_h_b)
+TRANS(xvhaddw_w_h, LASX, gen_xxx, gen_helper_vhaddw_w_h)
+TRANS(xvhaddw_d_w, LASX, gen_xxx, gen_helper_vhaddw_d_w)
+TRANS(xvhaddw_q_d, LASX, gen_xxx, gen_helper_vhaddw_q_d)
+TRANS(xvhaddw_hu_bu, LASX, gen_xxx, gen_helper_vhaddw_hu_bu)
+TRANS(xvhaddw_wu_hu, LASX, gen_xxx, gen_helper_vhaddw_wu_hu)
+TRANS(xvhaddw_du_wu, LASX, gen_xxx, gen_helper_vhaddw_du_wu)
+TRANS(xvhaddw_qu_du, LASX, gen_xxx, gen_helper_vhaddw_qu_du)
+TRANS(xvhsubw_h_b, LASX, gen_xxx, gen_helper_vhsubw_h_b)
+TRANS(xvhsubw_w_h, LASX, gen_xxx, gen_helper_vhsubw_w_h)
+TRANS(xvhsubw_d_w, LASX, gen_xxx, gen_helper_vhsubw_d_w)
+TRANS(xvhsubw_q_d, LASX, gen_xxx, gen_helper_vhsubw_q_d)
+TRANS(xvhsubw_hu_bu, LASX, gen_xxx, gen_helper_vhsubw_hu_bu)
+TRANS(xvhsubw_wu_hu, LASX, gen_xxx, gen_helper_vhsubw_wu_hu)
+TRANS(xvhsubw_du_wu, LASX, gen_xxx, gen_helper_vhsubw_du_wu)
+TRANS(xvhsubw_qu_du, LASX, gen_xxx, gen_helper_vhsubw_qu_du)
+
static void gen_vaddwev_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
{
TCGv_vec t1, t2;
@@ -309,6 +596,10 @@
TRANS(vaddwev_w_h, LSX, gvec_vvv, MO_16, do_vaddwev_s)
TRANS(vaddwev_d_w, LSX, gvec_vvv, MO_32, do_vaddwev_s)
TRANS(vaddwev_q_d, LSX, gvec_vvv, MO_64, do_vaddwev_s)
+TRANS(xvaddwev_h_b, LASX, gvec_xxx, MO_8, do_vaddwev_s)
+TRANS(xvaddwev_w_h, LASX, gvec_xxx, MO_16, do_vaddwev_s)
+TRANS(xvaddwev_d_w, LASX, gvec_xxx, MO_32, do_vaddwev_s)
+TRANS(xvaddwev_q_d, LASX, gvec_xxx, MO_64, do_vaddwev_s)
static void gen_vaddwod_w_h(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
{
@@ -388,6 +679,11 @@
TRANS(vaddwod_w_h, LSX, gvec_vvv, MO_16, do_vaddwod_s)
TRANS(vaddwod_d_w, LSX, gvec_vvv, MO_32, do_vaddwod_s)
TRANS(vaddwod_q_d, LSX, gvec_vvv, MO_64, do_vaddwod_s)
+TRANS(xvaddwod_h_b, LASX, gvec_xxx, MO_8, do_vaddwod_s)
+TRANS(xvaddwod_w_h, LASX, gvec_xxx, MO_16, do_vaddwod_s)
+TRANS(xvaddwod_d_w, LASX, gvec_xxx, MO_32, do_vaddwod_s)
+TRANS(xvaddwod_q_d, LASX, gvec_xxx, MO_64, do_vaddwod_s)
+
static void gen_vsubwev_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
{
@@ -471,6 +767,10 @@
TRANS(vsubwev_w_h, LSX, gvec_vvv, MO_16, do_vsubwev_s)
TRANS(vsubwev_d_w, LSX, gvec_vvv, MO_32, do_vsubwev_s)
TRANS(vsubwev_q_d, LSX, gvec_vvv, MO_64, do_vsubwev_s)
+TRANS(xvsubwev_h_b, LASX, gvec_xxx, MO_8, do_vsubwev_s)
+TRANS(xvsubwev_w_h, LASX, gvec_xxx, MO_16, do_vsubwev_s)
+TRANS(xvsubwev_d_w, LASX, gvec_xxx, MO_32, do_vsubwev_s)
+TRANS(xvsubwev_q_d, LASX, gvec_xxx, MO_64, do_vsubwev_s)
static void gen_vsubwod_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
{
@@ -550,6 +850,10 @@
TRANS(vsubwod_w_h, LSX, gvec_vvv, MO_16, do_vsubwod_s)
TRANS(vsubwod_d_w, LSX, gvec_vvv, MO_32, do_vsubwod_s)
TRANS(vsubwod_q_d, LSX, gvec_vvv, MO_64, do_vsubwod_s)
+TRANS(xvsubwod_h_b, LASX, gvec_xxx, MO_8, do_vsubwod_s)
+TRANS(xvsubwod_w_h, LASX, gvec_xxx, MO_16, do_vsubwod_s)
+TRANS(xvsubwod_d_w, LASX, gvec_xxx, MO_32, do_vsubwod_s)
+TRANS(xvsubwod_q_d, LASX, gvec_xxx, MO_64, do_vsubwod_s)
static void gen_vaddwev_u(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
{
@@ -625,6 +929,10 @@
TRANS(vaddwev_w_hu, LSX, gvec_vvv, MO_16, do_vaddwev_u)
TRANS(vaddwev_d_wu, LSX, gvec_vvv, MO_32, do_vaddwev_u)
TRANS(vaddwev_q_du, LSX, gvec_vvv, MO_64, do_vaddwev_u)
+TRANS(xvaddwev_h_bu, LASX, gvec_xxx, MO_8, do_vaddwev_u)
+TRANS(xvaddwev_w_hu, LASX, gvec_xxx, MO_16, do_vaddwev_u)
+TRANS(xvaddwev_d_wu, LASX, gvec_xxx, MO_32, do_vaddwev_u)
+TRANS(xvaddwev_q_du, LASX, gvec_xxx, MO_64, do_vaddwev_u)
static void gen_vaddwod_u(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
{
@@ -704,6 +1012,10 @@
TRANS(vaddwod_w_hu, LSX, gvec_vvv, MO_16, do_vaddwod_u)
TRANS(vaddwod_d_wu, LSX, gvec_vvv, MO_32, do_vaddwod_u)
TRANS(vaddwod_q_du, LSX, gvec_vvv, MO_64, do_vaddwod_u)
+TRANS(xvaddwod_h_bu, LASX, gvec_xxx, MO_8, do_vaddwod_u)
+TRANS(xvaddwod_w_hu, LASX, gvec_xxx, MO_16, do_vaddwod_u)
+TRANS(xvaddwod_d_wu, LASX, gvec_xxx, MO_32, do_vaddwod_u)
+TRANS(xvaddwod_q_du, LASX, gvec_xxx, MO_64, do_vaddwod_u)
static void gen_vsubwev_u(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
{
@@ -779,6 +1091,10 @@
TRANS(vsubwev_w_hu, LSX, gvec_vvv, MO_16, do_vsubwev_u)
TRANS(vsubwev_d_wu, LSX, gvec_vvv, MO_32, do_vsubwev_u)
TRANS(vsubwev_q_du, LSX, gvec_vvv, MO_64, do_vsubwev_u)
+TRANS(xvsubwev_h_bu, LASX, gvec_xxx, MO_8, do_vsubwev_u)
+TRANS(xvsubwev_w_hu, LASX, gvec_xxx, MO_16, do_vsubwev_u)
+TRANS(xvsubwev_d_wu, LASX, gvec_xxx, MO_32, do_vsubwev_u)
+TRANS(xvsubwev_q_du, LASX, gvec_xxx, MO_64, do_vsubwev_u)
static void gen_vsubwod_u(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
{
@@ -858,6 +1174,10 @@
TRANS(vsubwod_w_hu, LSX, gvec_vvv, MO_16, do_vsubwod_u)
TRANS(vsubwod_d_wu, LSX, gvec_vvv, MO_32, do_vsubwod_u)
TRANS(vsubwod_q_du, LSX, gvec_vvv, MO_64, do_vsubwod_u)
+TRANS(xvsubwod_h_bu, LASX, gvec_xxx, MO_8, do_vsubwod_u)
+TRANS(xvsubwod_w_hu, LASX, gvec_xxx, MO_16, do_vsubwod_u)
+TRANS(xvsubwod_d_wu, LASX, gvec_xxx, MO_32, do_vsubwod_u)
+TRANS(xvsubwod_q_du, LASX, gvec_xxx, MO_64, do_vsubwod_u)
static void gen_vaddwev_u_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
{
@@ -941,6 +1261,10 @@
TRANS(vaddwev_w_hu_h, LSX, gvec_vvv, MO_16, do_vaddwev_u_s)
TRANS(vaddwev_d_wu_w, LSX, gvec_vvv, MO_32, do_vaddwev_u_s)
TRANS(vaddwev_q_du_d, LSX, gvec_vvv, MO_64, do_vaddwev_u_s)
+TRANS(xvaddwev_h_bu_b, LASX, gvec_xxx, MO_8, do_vaddwev_u_s)
+TRANS(xvaddwev_w_hu_h, LASX, gvec_xxx, MO_16, do_vaddwev_u_s)
+TRANS(xvaddwev_d_wu_w, LASX, gvec_xxx, MO_32, do_vaddwev_u_s)
+TRANS(xvaddwev_q_du_d, LASX, gvec_xxx, MO_64, do_vaddwev_u_s)
static void gen_vaddwod_u_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
{
@@ -1021,6 +1345,10 @@
TRANS(vaddwod_w_hu_h, LSX, gvec_vvv, MO_16, do_vaddwod_u_s)
TRANS(vaddwod_d_wu_w, LSX, gvec_vvv, MO_32, do_vaddwod_u_s)
TRANS(vaddwod_q_du_d, LSX, gvec_vvv, MO_64, do_vaddwod_u_s)
+TRANS(xvaddwod_h_bu_b, LSX, gvec_xxx, MO_8, do_vaddwod_u_s)
+TRANS(xvaddwod_w_hu_h, LSX, gvec_xxx, MO_16, do_vaddwod_u_s)
+TRANS(xvaddwod_d_wu_w, LSX, gvec_xxx, MO_32, do_vaddwod_u_s)
+TRANS(xvaddwod_q_du_d, LSX, gvec_xxx, MO_64, do_vaddwod_u_s)
static void do_vavg(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b,
void (*gen_shr_vec)(unsigned, TCGv_vec,
@@ -1137,6 +1465,14 @@
TRANS(vavg_hu, LSX, gvec_vvv, MO_16, do_vavg_u)
TRANS(vavg_wu, LSX, gvec_vvv, MO_32, do_vavg_u)
TRANS(vavg_du, LSX, gvec_vvv, MO_64, do_vavg_u)
+TRANS(xvavg_b, LASX, gvec_xxx, MO_8, do_vavg_s)
+TRANS(xvavg_h, LASX, gvec_xxx, MO_16, do_vavg_s)
+TRANS(xvavg_w, LASX, gvec_xxx, MO_32, do_vavg_s)
+TRANS(xvavg_d, LASX, gvec_xxx, MO_64, do_vavg_s)
+TRANS(xvavg_bu, LASX, gvec_xxx, MO_8, do_vavg_u)
+TRANS(xvavg_hu, LASX, gvec_xxx, MO_16, do_vavg_u)
+TRANS(xvavg_wu, LASX, gvec_xxx, MO_32, do_vavg_u)
+TRANS(xvavg_du, LASX, gvec_xxx, MO_64, do_vavg_u)
static void do_vavgr_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
@@ -1218,6 +1554,14 @@
TRANS(vavgr_hu, LSX, gvec_vvv, MO_16, do_vavgr_u)
TRANS(vavgr_wu, LSX, gvec_vvv, MO_32, do_vavgr_u)
TRANS(vavgr_du, LSX, gvec_vvv, MO_64, do_vavgr_u)
+TRANS(xvavgr_b, LASX, gvec_xxx, MO_8, do_vavgr_s)
+TRANS(xvavgr_h, LASX, gvec_xxx, MO_16, do_vavgr_s)
+TRANS(xvavgr_w, LASX, gvec_xxx, MO_32, do_vavgr_s)
+TRANS(xvavgr_d, LASX, gvec_xxx, MO_64, do_vavgr_s)
+TRANS(xvavgr_bu, LASX, gvec_xxx, MO_8, do_vavgr_u)
+TRANS(xvavgr_hu, LASX, gvec_xxx, MO_16, do_vavgr_u)
+TRANS(xvavgr_wu, LASX, gvec_xxx, MO_32, do_vavgr_u)
+TRANS(xvavgr_du, LASX, gvec_xxx, MO_64, do_vavgr_u)
static void gen_vabsd_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
{
@@ -1313,6 +1657,14 @@
TRANS(vabsd_hu, LSX, gvec_vvv, MO_16, do_vabsd_u)
TRANS(vabsd_wu, LSX, gvec_vvv, MO_32, do_vabsd_u)
TRANS(vabsd_du, LSX, gvec_vvv, MO_64, do_vabsd_u)
+TRANS(xvabsd_b, LASX, gvec_xxx, MO_8, do_vabsd_s)
+TRANS(xvabsd_h, LASX, gvec_xxx, MO_16, do_vabsd_s)
+TRANS(xvabsd_w, LASX, gvec_xxx, MO_32, do_vabsd_s)
+TRANS(xvabsd_d, LASX, gvec_xxx, MO_64, do_vabsd_s)
+TRANS(xvabsd_bu, LASX, gvec_xxx, MO_8, do_vabsd_u)
+TRANS(xvabsd_hu, LASX, gvec_xxx, MO_16, do_vabsd_u)
+TRANS(xvabsd_wu, LASX, gvec_xxx, MO_32, do_vabsd_u)
+TRANS(xvabsd_du, LASX, gvec_xxx, MO_64, do_vabsd_u)
static void gen_vadda(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
{
@@ -1366,6 +1718,10 @@
TRANS(vadda_h, LSX, gvec_vvv, MO_16, do_vadda)
TRANS(vadda_w, LSX, gvec_vvv, MO_32, do_vadda)
TRANS(vadda_d, LSX, gvec_vvv, MO_64, do_vadda)
+TRANS(xvadda_b, LASX, gvec_xxx, MO_8, do_vadda)
+TRANS(xvadda_h, LASX, gvec_xxx, MO_16, do_vadda)
+TRANS(xvadda_w, LASX, gvec_xxx, MO_32, do_vadda)
+TRANS(xvadda_d, LASX, gvec_xxx, MO_64, do_vadda)
TRANS(vmax_b, LSX, gvec_vvv, MO_8, tcg_gen_gvec_smax)
TRANS(vmax_h, LSX, gvec_vvv, MO_16, tcg_gen_gvec_smax)
@@ -1375,6 +1731,14 @@
TRANS(vmax_hu, LSX, gvec_vvv, MO_16, tcg_gen_gvec_umax)
TRANS(vmax_wu, LSX, gvec_vvv, MO_32, tcg_gen_gvec_umax)
TRANS(vmax_du, LSX, gvec_vvv, MO_64, tcg_gen_gvec_umax)
+TRANS(xvmax_b, LASX, gvec_xxx, MO_8, tcg_gen_gvec_smax)
+TRANS(xvmax_h, LASX, gvec_xxx, MO_16, tcg_gen_gvec_smax)
+TRANS(xvmax_w, LASX, gvec_xxx, MO_32, tcg_gen_gvec_smax)
+TRANS(xvmax_d, LASX, gvec_xxx, MO_64, tcg_gen_gvec_smax)
+TRANS(xvmax_bu, LASX, gvec_xxx, MO_8, tcg_gen_gvec_umax)
+TRANS(xvmax_hu, LASX, gvec_xxx, MO_16, tcg_gen_gvec_umax)
+TRANS(xvmax_wu, LASX, gvec_xxx, MO_32, tcg_gen_gvec_umax)
+TRANS(xvmax_du, LASX, gvec_xxx, MO_64, tcg_gen_gvec_umax)
TRANS(vmin_b, LSX, gvec_vvv, MO_8, tcg_gen_gvec_smin)
TRANS(vmin_h, LSX, gvec_vvv, MO_16, tcg_gen_gvec_smin)
@@ -1384,6 +1748,14 @@
TRANS(vmin_hu, LSX, gvec_vvv, MO_16, tcg_gen_gvec_umin)
TRANS(vmin_wu, LSX, gvec_vvv, MO_32, tcg_gen_gvec_umin)
TRANS(vmin_du, LSX, gvec_vvv, MO_64, tcg_gen_gvec_umin)
+TRANS(xvmin_b, LASX, gvec_xxx, MO_8, tcg_gen_gvec_smin)
+TRANS(xvmin_h, LASX, gvec_xxx, MO_16, tcg_gen_gvec_smin)
+TRANS(xvmin_w, LASX, gvec_xxx, MO_32, tcg_gen_gvec_smin)
+TRANS(xvmin_d, LASX, gvec_xxx, MO_64, tcg_gen_gvec_smin)
+TRANS(xvmin_bu, LASX, gvec_xxx, MO_8, tcg_gen_gvec_umin)
+TRANS(xvmin_hu, LASX, gvec_xxx, MO_16, tcg_gen_gvec_umin)
+TRANS(xvmin_wu, LASX, gvec_xxx, MO_32, tcg_gen_gvec_umin)
+TRANS(xvmin_du, LASX, gvec_xxx, MO_64, tcg_gen_gvec_umin)
static void gen_vmini_s(unsigned vece, TCGv_vec t, TCGv_vec a, int64_t imm)
{
@@ -1485,6 +1857,14 @@
TRANS(vmini_hu, LSX, gvec_vv_i, MO_16, do_vmini_u)
TRANS(vmini_wu, LSX, gvec_vv_i, MO_32, do_vmini_u)
TRANS(vmini_du, LSX, gvec_vv_i, MO_64, do_vmini_u)
+TRANS(xvmini_b, LASX, gvec_xx_i, MO_8, do_vmini_s)
+TRANS(xvmini_h, LASX, gvec_xx_i, MO_16, do_vmini_s)
+TRANS(xvmini_w, LASX, gvec_xx_i, MO_32, do_vmini_s)
+TRANS(xvmini_d, LASX, gvec_xx_i, MO_64, do_vmini_s)
+TRANS(xvmini_bu, LASX, gvec_xx_i, MO_8, do_vmini_u)
+TRANS(xvmini_hu, LASX, gvec_xx_i, MO_16, do_vmini_u)
+TRANS(xvmini_wu, LASX, gvec_xx_i, MO_32, do_vmini_u)
+TRANS(xvmini_du, LASX, gvec_xx_i, MO_64, do_vmini_u)
static void do_vmaxi_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
int64_t imm, uint32_t oprsz, uint32_t maxsz)
@@ -1566,11 +1946,23 @@
TRANS(vmaxi_hu, LSX, gvec_vv_i, MO_16, do_vmaxi_u)
TRANS(vmaxi_wu, LSX, gvec_vv_i, MO_32, do_vmaxi_u)
TRANS(vmaxi_du, LSX, gvec_vv_i, MO_64, do_vmaxi_u)
+TRANS(xvmaxi_b, LASX, gvec_xx_i, MO_8, do_vmaxi_s)
+TRANS(xvmaxi_h, LASX, gvec_xx_i, MO_16, do_vmaxi_s)
+TRANS(xvmaxi_w, LASX, gvec_xx_i, MO_32, do_vmaxi_s)
+TRANS(xvmaxi_d, LASX, gvec_xx_i, MO_64, do_vmaxi_s)
+TRANS(xvmaxi_bu, LASX, gvec_xx_i, MO_8, do_vmaxi_u)
+TRANS(xvmaxi_hu, LASX, gvec_xx_i, MO_16, do_vmaxi_u)
+TRANS(xvmaxi_wu, LASX, gvec_xx_i, MO_32, do_vmaxi_u)
+TRANS(xvmaxi_du, LASX, gvec_xx_i, MO_64, do_vmaxi_u)
TRANS(vmul_b, LSX, gvec_vvv, MO_8, tcg_gen_gvec_mul)
TRANS(vmul_h, LSX, gvec_vvv, MO_16, tcg_gen_gvec_mul)
TRANS(vmul_w, LSX, gvec_vvv, MO_32, tcg_gen_gvec_mul)
TRANS(vmul_d, LSX, gvec_vvv, MO_64, tcg_gen_gvec_mul)
+TRANS(xvmul_b, LASX, gvec_xxx, MO_8, tcg_gen_gvec_mul)
+TRANS(xvmul_h, LASX, gvec_xxx, MO_16, tcg_gen_gvec_mul)
+TRANS(xvmul_w, LASX, gvec_xxx, MO_32, tcg_gen_gvec_mul)
+TRANS(xvmul_d, LASX, gvec_xxx, MO_64, tcg_gen_gvec_mul)
static void gen_vmuh_w(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
{
@@ -1615,6 +2007,10 @@
TRANS(vmuh_h, LSX, gvec_vvv, MO_16, do_vmuh_s)
TRANS(vmuh_w, LSX, gvec_vvv, MO_32, do_vmuh_s)
TRANS(vmuh_d, LSX, gvec_vvv, MO_64, do_vmuh_s)
+TRANS(xvmuh_b, LASX, gvec_xxx, MO_8, do_vmuh_s)
+TRANS(xvmuh_h, LASX, gvec_xxx, MO_16, do_vmuh_s)
+TRANS(xvmuh_w, LASX, gvec_xxx, MO_32, do_vmuh_s)
+TRANS(xvmuh_d, LASX, gvec_xxx, MO_64, do_vmuh_s)
static void gen_vmuh_wu(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
{
@@ -1659,6 +2055,10 @@
TRANS(vmuh_hu, LSX, gvec_vvv, MO_16, do_vmuh_u)
TRANS(vmuh_wu, LSX, gvec_vvv, MO_32, do_vmuh_u)
TRANS(vmuh_du, LSX, gvec_vvv, MO_64, do_vmuh_u)
+TRANS(xvmuh_bu, LASX, gvec_xxx, MO_8, do_vmuh_u)
+TRANS(xvmuh_hu, LASX, gvec_xxx, MO_16, do_vmuh_u)
+TRANS(xvmuh_wu, LASX, gvec_xxx, MO_32, do_vmuh_u)
+TRANS(xvmuh_du, LASX, gvec_xxx, MO_64, do_vmuh_u)
static void gen_vmulwev_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
{
@@ -1731,6 +2131,9 @@
TRANS(vmulwev_h_b, LSX, gvec_vvv, MO_8, do_vmulwev_s)
TRANS(vmulwev_w_h, LSX, gvec_vvv, MO_16, do_vmulwev_s)
TRANS(vmulwev_d_w, LSX, gvec_vvv, MO_32, do_vmulwev_s)
+TRANS(xvmulwev_h_b, LASX, gvec_xxx, MO_8, do_vmulwev_s)
+TRANS(xvmulwev_w_h, LASX, gvec_xxx, MO_16, do_vmulwev_s)
+TRANS(xvmulwev_d_w, LASX, gvec_xxx, MO_32, do_vmulwev_s)
static void tcg_gen_mulus2_i64(TCGv_i64 rl, TCGv_i64 rh,
TCGv_i64 arg1, TCGv_i64 arg2)
@@ -1738,37 +2141,62 @@
tcg_gen_mulsu2_i64(rl, rh, arg2, arg1);
}
-#define VMUL_Q(NAME, FN, idx1, idx2) \
-static bool trans_## NAME (DisasContext *ctx, arg_vvv *a) \
-{ \
- TCGv_i64 rh, rl, arg1, arg2; \
- \
- if (!avail_LSX(ctx)) { \
- return false; \
- } \
- \
- rh = tcg_temp_new_i64(); \
- rl = tcg_temp_new_i64(); \
- arg1 = tcg_temp_new_i64(); \
- arg2 = tcg_temp_new_i64(); \
- \
- get_vreg64(arg1, a->vj, idx1); \
- get_vreg64(arg2, a->vk, idx2); \
- \
- tcg_gen_## FN ##_i64(rl, rh, arg1, arg2); \
- \
- set_vreg64(rh, a->vd, 1); \
- set_vreg64(rl, a->vd, 0); \
- \
- return true; \
+static bool gen_vmul_q_vl(DisasContext *ctx,
+ arg_vvv *a, uint32_t oprsz, int idx1, int idx2,
+ void (*func)(TCGv_i64, TCGv_i64,
+ TCGv_i64, TCGv_i64))
+{
+ TCGv_i64 rh, rl, arg1, arg2;
+ int i;
+
+ if (!check_vec(ctx, oprsz)) {
+ return true;
+ }
+
+ rh = tcg_temp_new_i64();
+ rl = tcg_temp_new_i64();
+ arg1 = tcg_temp_new_i64();
+ arg2 = tcg_temp_new_i64();
+
+ for (i = 0; i < oprsz / 16; i++) {
+ get_vreg64(arg1, a->vj, 2 * i + idx1);
+ get_vreg64(arg2, a->vk, 2 * i + idx2);
+
+ func(rl, rh, arg1, arg2);
+
+ set_vreg64(rh, a->vd, 2 * i + 1);
+ set_vreg64(rl, a->vd, 2 * i);
+ }
+
+ return true;
}
-VMUL_Q(vmulwev_q_d, muls2, 0, 0)
-VMUL_Q(vmulwod_q_d, muls2, 1, 1)
-VMUL_Q(vmulwev_q_du, mulu2, 0, 0)
-VMUL_Q(vmulwod_q_du, mulu2, 1, 1)
-VMUL_Q(vmulwev_q_du_d, mulus2, 0, 0)
-VMUL_Q(vmulwod_q_du_d, mulus2, 1, 1)
+static bool gen_vmul_q(DisasContext *ctx, arg_vvv *a, int idx1, int idx2,
+ void (*func)(TCGv_i64, TCGv_i64,
+ TCGv_i64, TCGv_i64))
+{
+ return gen_vmul_q_vl(ctx, a, 16, idx1, idx2, func);
+}
+
+static bool gen_xvmul_q(DisasContext *ctx, arg_vvv *a, int idx1, int idx2,
+ void (*func)(TCGv_i64, TCGv_i64,
+ TCGv_i64, TCGv_i64))
+{
+ return gen_vmul_q_vl(ctx, a, 32, idx1, idx2, func);
+}
+
+TRANS(vmulwev_q_d, LSX, gen_vmul_q, 0, 0, tcg_gen_muls2_i64)
+TRANS(vmulwod_q_d, LSX, gen_vmul_q, 1, 1, tcg_gen_muls2_i64)
+TRANS(vmulwev_q_du, LSX, gen_vmul_q, 0, 0, tcg_gen_mulu2_i64)
+TRANS(vmulwod_q_du, LSX, gen_vmul_q, 1, 1, tcg_gen_mulu2_i64)
+TRANS(vmulwev_q_du_d, LSX, gen_vmul_q, 0, 0, tcg_gen_mulus2_i64)
+TRANS(vmulwod_q_du_d, LSX, gen_vmul_q, 1, 1, tcg_gen_mulus2_i64)
+TRANS(xvmulwev_q_d, LASX, gen_xvmul_q, 0, 0, tcg_gen_muls2_i64)
+TRANS(xvmulwod_q_d, LASX, gen_xvmul_q, 1, 1, tcg_gen_muls2_i64)
+TRANS(xvmulwev_q_du, LASX, gen_xvmul_q, 0, 0, tcg_gen_mulu2_i64)
+TRANS(xvmulwod_q_du, LASX, gen_xvmul_q, 1, 1, tcg_gen_mulu2_i64)
+TRANS(xvmulwev_q_du_d, LASX, gen_xvmul_q, 0, 0, tcg_gen_mulus2_i64)
+TRANS(xvmulwod_q_du_d, LASX, gen_xvmul_q, 1, 1, tcg_gen_mulus2_i64)
static void gen_vmulwod_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
{
@@ -1839,6 +2267,9 @@
TRANS(vmulwod_h_b, LSX, gvec_vvv, MO_8, do_vmulwod_s)
TRANS(vmulwod_w_h, LSX, gvec_vvv, MO_16, do_vmulwod_s)
TRANS(vmulwod_d_w, LSX, gvec_vvv, MO_32, do_vmulwod_s)
+TRANS(xvmulwod_h_b, LASX, gvec_xxx, MO_8, do_vmulwod_s)
+TRANS(xvmulwod_w_h, LASX, gvec_xxx, MO_16, do_vmulwod_s)
+TRANS(xvmulwod_d_w, LASX, gvec_xxx, MO_32, do_vmulwod_s)
static void gen_vmulwev_u(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
{
@@ -1909,6 +2340,9 @@
TRANS(vmulwev_h_bu, LSX, gvec_vvv, MO_8, do_vmulwev_u)
TRANS(vmulwev_w_hu, LSX, gvec_vvv, MO_16, do_vmulwev_u)
TRANS(vmulwev_d_wu, LSX, gvec_vvv, MO_32, do_vmulwev_u)
+TRANS(xvmulwev_h_bu, LASX, gvec_xxx, MO_8, do_vmulwev_u)
+TRANS(xvmulwev_w_hu, LASX, gvec_xxx, MO_16, do_vmulwev_u)
+TRANS(xvmulwev_d_wu, LASX, gvec_xxx, MO_32, do_vmulwev_u)
static void gen_vmulwod_u(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
{
@@ -1979,6 +2413,9 @@
TRANS(vmulwod_h_bu, LSX, gvec_vvv, MO_8, do_vmulwod_u)
TRANS(vmulwod_w_hu, LSX, gvec_vvv, MO_16, do_vmulwod_u)
TRANS(vmulwod_d_wu, LSX, gvec_vvv, MO_32, do_vmulwod_u)
+TRANS(xvmulwod_h_bu, LASX, gvec_xxx, MO_8, do_vmulwod_u)
+TRANS(xvmulwod_w_hu, LASX, gvec_xxx, MO_16, do_vmulwod_u)
+TRANS(xvmulwod_d_wu, LASX, gvec_xxx, MO_32, do_vmulwod_u)
static void gen_vmulwev_u_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
{
@@ -2051,6 +2488,9 @@
TRANS(vmulwev_h_bu_b, LSX, gvec_vvv, MO_8, do_vmulwev_u_s)
TRANS(vmulwev_w_hu_h, LSX, gvec_vvv, MO_16, do_vmulwev_u_s)
TRANS(vmulwev_d_wu_w, LSX, gvec_vvv, MO_32, do_vmulwev_u_s)
+TRANS(xvmulwev_h_bu_b, LASX, gvec_xxx, MO_8, do_vmulwev_u_s)
+TRANS(xvmulwev_w_hu_h, LASX, gvec_xxx, MO_16, do_vmulwev_u_s)
+TRANS(xvmulwev_d_wu_w, LASX, gvec_xxx, MO_32, do_vmulwev_u_s)
static void gen_vmulwod_u_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
{
@@ -2120,6 +2560,9 @@
TRANS(vmulwod_h_bu_b, LSX, gvec_vvv, MO_8, do_vmulwod_u_s)
TRANS(vmulwod_w_hu_h, LSX, gvec_vvv, MO_16, do_vmulwod_u_s)
TRANS(vmulwod_d_wu_w, LSX, gvec_vvv, MO_32, do_vmulwod_u_s)
+TRANS(xvmulwod_h_bu_b, LASX, gvec_xxx, MO_8, do_vmulwod_u_s)
+TRANS(xvmulwod_w_hu_h, LASX, gvec_xxx, MO_16, do_vmulwod_u_s)
+TRANS(xvmulwod_d_wu_w, LASX, gvec_xxx, MO_32, do_vmulwod_u_s)
static void gen_vmadd(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
{
@@ -2194,6 +2637,10 @@
TRANS(vmadd_h, LSX, gvec_vvv, MO_16, do_vmadd)
TRANS(vmadd_w, LSX, gvec_vvv, MO_32, do_vmadd)
TRANS(vmadd_d, LSX, gvec_vvv, MO_64, do_vmadd)
+TRANS(xvmadd_b, LASX, gvec_xxx, MO_8, do_vmadd)
+TRANS(xvmadd_h, LASX, gvec_xxx, MO_16, do_vmadd)
+TRANS(xvmadd_w, LASX, gvec_xxx, MO_32, do_vmadd)
+TRANS(xvmadd_d, LASX, gvec_xxx, MO_64, do_vmadd)
static void gen_vmsub(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
{
@@ -2268,6 +2715,10 @@
TRANS(vmsub_h, LSX, gvec_vvv, MO_16, do_vmsub)
TRANS(vmsub_w, LSX, gvec_vvv, MO_32, do_vmsub)
TRANS(vmsub_d, LSX, gvec_vvv, MO_64, do_vmsub)
+TRANS(xvmsub_b, LASX, gvec_xxx, MO_8, do_vmsub)
+TRANS(xvmsub_h, LASX, gvec_xxx, MO_16, do_vmsub)
+TRANS(xvmsub_w, LASX, gvec_xxx, MO_32, do_vmsub)
+TRANS(xvmsub_d, LASX, gvec_xxx, MO_64, do_vmsub)
static void gen_vmaddwev_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
{
@@ -2342,43 +2793,69 @@
TRANS(vmaddwev_h_b, LSX, gvec_vvv, MO_8, do_vmaddwev_s)
TRANS(vmaddwev_w_h, LSX, gvec_vvv, MO_16, do_vmaddwev_s)
TRANS(vmaddwev_d_w, LSX, gvec_vvv, MO_32, do_vmaddwev_s)
+TRANS(xvmaddwev_h_b, LASX, gvec_xxx, MO_8, do_vmaddwev_s)
+TRANS(xvmaddwev_w_h, LASX, gvec_xxx, MO_16, do_vmaddwev_s)
+TRANS(xvmaddwev_d_w, LASX, gvec_xxx, MO_32, do_vmaddwev_s)
-#define VMADD_Q(NAME, FN, idx1, idx2) \
-static bool trans_## NAME (DisasContext *ctx, arg_vvv *a) \
-{ \
- TCGv_i64 rh, rl, arg1, arg2, th, tl; \
- \
- if (!avail_LSX(ctx)) { \
- return false; \
- } \
- \
- rh = tcg_temp_new_i64(); \
- rl = tcg_temp_new_i64(); \
- arg1 = tcg_temp_new_i64(); \
- arg2 = tcg_temp_new_i64(); \
- th = tcg_temp_new_i64(); \
- tl = tcg_temp_new_i64(); \
- \
- get_vreg64(arg1, a->vj, idx1); \
- get_vreg64(arg2, a->vk, idx2); \
- get_vreg64(rh, a->vd, 1); \
- get_vreg64(rl, a->vd, 0); \
- \
- tcg_gen_## FN ##_i64(tl, th, arg1, arg2); \
- tcg_gen_add2_i64(rl, rh, rl, rh, tl, th); \
- \
- set_vreg64(rh, a->vd, 1); \
- set_vreg64(rl, a->vd, 0); \
- \
- return true; \
+static bool gen_vmadd_q_vl(DisasContext * ctx,
+ arg_vvv *a, uint32_t oprsz, int idx1, int idx2,
+ void (*func)(TCGv_i64, TCGv_i64,
+ TCGv_i64, TCGv_i64))
+{
+ TCGv_i64 rh, rl, arg1, arg2, th, tl;
+ int i;
+
+ if (!check_vec(ctx, oprsz)) {
+ return true;
+ }
+
+ rh = tcg_temp_new_i64();
+ rl = tcg_temp_new_i64();
+ arg1 = tcg_temp_new_i64();
+ arg2 = tcg_temp_new_i64();
+ th = tcg_temp_new_i64();
+ tl = tcg_temp_new_i64();
+
+ for (i = 0; i < oprsz / 16; i++) {
+ get_vreg64(arg1, a->vj, 2 * i + idx1);
+ get_vreg64(arg2, a->vk, 2 * i + idx2);
+ get_vreg64(rh, a->vd, 2 * i + 1);
+ get_vreg64(rl, a->vd, 2 * i);
+
+ func(tl, th, arg1, arg2);
+ tcg_gen_add2_i64(rl, rh, rl, rh, tl, th);
+
+ set_vreg64(rh, a->vd, 2 * i + 1);
+ set_vreg64(rl, a->vd, 2 * i);
+ }
+
+ return true;
}
-VMADD_Q(vmaddwev_q_d, muls2, 0, 0)
-VMADD_Q(vmaddwod_q_d, muls2, 1, 1)
-VMADD_Q(vmaddwev_q_du, mulu2, 0, 0)
-VMADD_Q(vmaddwod_q_du, mulu2, 1, 1)
-VMADD_Q(vmaddwev_q_du_d, mulus2, 0, 0)
-VMADD_Q(vmaddwod_q_du_d, mulus2, 1, 1)
+static bool gen_vmadd_q(DisasContext *ctx, arg_vvv *a, int idx1, int idx2,
+ void (*func)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64))
+{
+ return gen_vmadd_q_vl(ctx, a, 16, idx1, idx2, func);
+}
+
+static bool gen_xvmadd_q(DisasContext *ctx, arg_vvv *a, int idx1, int idx2,
+ void (*func)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64))
+{
+ return gen_vmadd_q_vl(ctx, a, 32, idx1, idx2, func);
+}
+
+TRANS(vmaddwev_q_d, LSX, gen_vmadd_q, 0, 0, tcg_gen_muls2_i64)
+TRANS(vmaddwod_q_d, LSX, gen_vmadd_q, 1, 1, tcg_gen_muls2_i64)
+TRANS(vmaddwev_q_du, LSX, gen_vmadd_q, 0, 0, tcg_gen_mulu2_i64)
+TRANS(vmaddwod_q_du, LSX, gen_vmadd_q, 1, 1, tcg_gen_mulu2_i64)
+TRANS(vmaddwev_q_du_d, LSX, gen_vmadd_q, 0, 0, tcg_gen_mulus2_i64)
+TRANS(vmaddwod_q_du_d, LSX, gen_vmadd_q, 1, 1, tcg_gen_mulus2_i64)
+TRANS(xvmaddwev_q_d, LASX, gen_xvmadd_q, 0, 0, tcg_gen_muls2_i64)
+TRANS(xvmaddwod_q_d, LASX, gen_xvmadd_q, 1, 1, tcg_gen_muls2_i64)
+TRANS(xvmaddwev_q_du, LASX, gen_xvmadd_q, 0, 0, tcg_gen_mulu2_i64)
+TRANS(xvmaddwod_q_du, LASX, gen_xvmadd_q, 1, 1, tcg_gen_mulu2_i64)
+TRANS(xvmaddwev_q_du_d, LASX, gen_xvmadd_q, 0, 0, tcg_gen_mulus2_i64)
+TRANS(xvmaddwod_q_du_d, LASX, gen_xvmadd_q, 1, 1, tcg_gen_mulus2_i64)
static void gen_vmaddwod_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
{
@@ -2450,6 +2927,9 @@
TRANS(vmaddwod_h_b, LSX, gvec_vvv, MO_8, do_vmaddwod_s)
TRANS(vmaddwod_w_h, LSX, gvec_vvv, MO_16, do_vmaddwod_s)
TRANS(vmaddwod_d_w, LSX, gvec_vvv, MO_32, do_vmaddwod_s)
+TRANS(xvmaddwod_h_b, LASX, gvec_xxx, MO_8, do_vmaddwod_s)
+TRANS(xvmaddwod_w_h, LASX, gvec_xxx, MO_16, do_vmaddwod_s)
+TRANS(xvmaddwod_d_w, LASX, gvec_xxx, MO_32, do_vmaddwod_s)
static void gen_vmaddwev_u(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
{
@@ -2520,6 +3000,9 @@
TRANS(vmaddwev_h_bu, LSX, gvec_vvv, MO_8, do_vmaddwev_u)
TRANS(vmaddwev_w_hu, LSX, gvec_vvv, MO_16, do_vmaddwev_u)
TRANS(vmaddwev_d_wu, LSX, gvec_vvv, MO_32, do_vmaddwev_u)
+TRANS(xvmaddwev_h_bu, LASX, gvec_xxx, MO_8, do_vmaddwev_u)
+TRANS(xvmaddwev_w_hu, LASX, gvec_xxx, MO_16, do_vmaddwev_u)
+TRANS(xvmaddwev_d_wu, LASX, gvec_xxx, MO_32, do_vmaddwev_u)
static void gen_vmaddwod_u(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
{
@@ -2591,6 +3074,9 @@
TRANS(vmaddwod_h_bu, LSX, gvec_vvv, MO_8, do_vmaddwod_u)
TRANS(vmaddwod_w_hu, LSX, gvec_vvv, MO_16, do_vmaddwod_u)
TRANS(vmaddwod_d_wu, LSX, gvec_vvv, MO_32, do_vmaddwod_u)
+TRANS(xvmaddwod_h_bu, LASX, gvec_xxx, MO_8, do_vmaddwod_u)
+TRANS(xvmaddwod_w_hu, LASX, gvec_xxx, MO_16, do_vmaddwod_u)
+TRANS(xvmaddwod_d_wu, LASX, gvec_xxx, MO_32, do_vmaddwod_u)
static void gen_vmaddwev_u_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
{
@@ -2664,6 +3150,9 @@
TRANS(vmaddwev_h_bu_b, LSX, gvec_vvv, MO_8, do_vmaddwev_u_s)
TRANS(vmaddwev_w_hu_h, LSX, gvec_vvv, MO_16, do_vmaddwev_u_s)
TRANS(vmaddwev_d_wu_w, LSX, gvec_vvv, MO_32, do_vmaddwev_u_s)
+TRANS(xvmaddwev_h_bu_b, LASX, gvec_xxx, MO_8, do_vmaddwev_u_s)
+TRANS(xvmaddwev_w_hu_h, LASX, gvec_xxx, MO_16, do_vmaddwev_u_s)
+TRANS(xvmaddwev_d_wu_w, LASX, gvec_xxx, MO_32, do_vmaddwev_u_s)
static void gen_vmaddwod_u_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
{
@@ -2736,6 +3225,9 @@
TRANS(vmaddwod_h_bu_b, LSX, gvec_vvv, MO_8, do_vmaddwod_u_s)
TRANS(vmaddwod_w_hu_h, LSX, gvec_vvv, MO_16, do_vmaddwod_u_s)
TRANS(vmaddwod_d_wu_w, LSX, gvec_vvv, MO_32, do_vmaddwod_u_s)
+TRANS(xvmaddwod_h_bu_b, LASX, gvec_xxx, MO_8, do_vmaddwod_u_s)
+TRANS(xvmaddwod_w_hu_h, LASX, gvec_xxx, MO_16, do_vmaddwod_u_s)
+TRANS(xvmaddwod_d_wu_w, LASX, gvec_xxx, MO_32, do_vmaddwod_u_s)
TRANS(vdiv_b, LSX, gen_vvv, gen_helper_vdiv_b)
TRANS(vdiv_h, LSX, gen_vvv, gen_helper_vdiv_h)
@@ -2753,6 +3245,22 @@
TRANS(vmod_hu, LSX, gen_vvv, gen_helper_vmod_hu)
TRANS(vmod_wu, LSX, gen_vvv, gen_helper_vmod_wu)
TRANS(vmod_du, LSX, gen_vvv, gen_helper_vmod_du)
+TRANS(xvdiv_b, LASX, gen_xxx, gen_helper_vdiv_b)
+TRANS(xvdiv_h, LASX, gen_xxx, gen_helper_vdiv_h)
+TRANS(xvdiv_w, LASX, gen_xxx, gen_helper_vdiv_w)
+TRANS(xvdiv_d, LASX, gen_xxx, gen_helper_vdiv_d)
+TRANS(xvdiv_bu, LASX, gen_xxx, gen_helper_vdiv_bu)
+TRANS(xvdiv_hu, LASX, gen_xxx, gen_helper_vdiv_hu)
+TRANS(xvdiv_wu, LASX, gen_xxx, gen_helper_vdiv_wu)
+TRANS(xvdiv_du, LASX, gen_xxx, gen_helper_vdiv_du)
+TRANS(xvmod_b, LASX, gen_xxx, gen_helper_vmod_b)
+TRANS(xvmod_h, LASX, gen_xxx, gen_helper_vmod_h)
+TRANS(xvmod_w, LASX, gen_xxx, gen_helper_vmod_w)
+TRANS(xvmod_d, LASX, gen_xxx, gen_helper_vmod_d)
+TRANS(xvmod_bu, LASX, gen_xxx, gen_helper_vmod_bu)
+TRANS(xvmod_hu, LASX, gen_xxx, gen_helper_vmod_hu)
+TRANS(xvmod_wu, LASX, gen_xxx, gen_helper_vmod_wu)
+TRANS(xvmod_du, LASX, gen_xxx, gen_helper_vmod_du)
static void gen_vsat_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec max)
{
@@ -2805,6 +3313,10 @@
TRANS(vsat_h, LSX, gvec_vv_i, MO_16, do_vsat_s)
TRANS(vsat_w, LSX, gvec_vv_i, MO_32, do_vsat_s)
TRANS(vsat_d, LSX, gvec_vv_i, MO_64, do_vsat_s)
+TRANS(xvsat_b, LASX, gvec_xx_i, MO_8, do_vsat_s)
+TRANS(xvsat_h, LASX, gvec_xx_i, MO_16, do_vsat_s)
+TRANS(xvsat_w, LASX, gvec_xx_i, MO_32, do_vsat_s)
+TRANS(xvsat_d, LASX, gvec_xx_i, MO_64, do_vsat_s)
static void gen_vsat_u(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec max)
{
@@ -2854,6 +3366,10 @@
TRANS(vsat_hu, LSX, gvec_vv_i, MO_16, do_vsat_u)
TRANS(vsat_wu, LSX, gvec_vv_i, MO_32, do_vsat_u)
TRANS(vsat_du, LSX, gvec_vv_i, MO_64, do_vsat_u)
+TRANS(xvsat_bu, LASX, gvec_xx_i, MO_8, do_vsat_u)
+TRANS(xvsat_hu, LASX, gvec_xx_i, MO_16, do_vsat_u)
+TRANS(xvsat_wu, LASX, gvec_xx_i, MO_32, do_vsat_u)
+TRANS(xvsat_du, LASX, gvec_xx_i, MO_64, do_vsat_u)
TRANS(vexth_h_b, LSX, gen_vv, gen_helper_vexth_h_b)
TRANS(vexth_w_h, LSX, gen_vv, gen_helper_vexth_w_h)
@@ -2863,6 +3379,27 @@
TRANS(vexth_wu_hu, LSX, gen_vv, gen_helper_vexth_wu_hu)
TRANS(vexth_du_wu, LSX, gen_vv, gen_helper_vexth_du_wu)
TRANS(vexth_qu_du, LSX, gen_vv, gen_helper_vexth_qu_du)
+TRANS(xvexth_h_b, LASX, gen_xx, gen_helper_vexth_h_b)
+TRANS(xvexth_w_h, LASX, gen_xx, gen_helper_vexth_w_h)
+TRANS(xvexth_d_w, LASX, gen_xx, gen_helper_vexth_d_w)
+TRANS(xvexth_q_d, LASX, gen_xx, gen_helper_vexth_q_d)
+TRANS(xvexth_hu_bu, LASX, gen_xx, gen_helper_vexth_hu_bu)
+TRANS(xvexth_wu_hu, LASX, gen_xx, gen_helper_vexth_wu_hu)
+TRANS(xvexth_du_wu, LASX, gen_xx, gen_helper_vexth_du_wu)
+TRANS(xvexth_qu_du, LASX, gen_xx, gen_helper_vexth_qu_du)
+
+TRANS(vext2xv_h_b, LASX, gen_xx, gen_helper_vext2xv_h_b)
+TRANS(vext2xv_w_b, LASX, gen_xx, gen_helper_vext2xv_w_b)
+TRANS(vext2xv_d_b, LASX, gen_xx, gen_helper_vext2xv_d_b)
+TRANS(vext2xv_w_h, LASX, gen_xx, gen_helper_vext2xv_w_h)
+TRANS(vext2xv_d_h, LASX, gen_xx, gen_helper_vext2xv_d_h)
+TRANS(vext2xv_d_w, LASX, gen_xx, gen_helper_vext2xv_d_w)
+TRANS(vext2xv_hu_bu, LASX, gen_xx, gen_helper_vext2xv_hu_bu)
+TRANS(vext2xv_wu_bu, LASX, gen_xx, gen_helper_vext2xv_wu_bu)
+TRANS(vext2xv_du_bu, LASX, gen_xx, gen_helper_vext2xv_du_bu)
+TRANS(vext2xv_wu_hu, LASX, gen_xx, gen_helper_vext2xv_wu_hu)
+TRANS(vext2xv_du_hu, LASX, gen_xx, gen_helper_vext2xv_du_hu)
+TRANS(vext2xv_du_wu, LASX, gen_xx, gen_helper_vext2xv_du_wu)
static void gen_vsigncov(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
{
@@ -2916,6 +3453,10 @@
TRANS(vsigncov_h, LSX, gvec_vvv, MO_16, do_vsigncov)
TRANS(vsigncov_w, LSX, gvec_vvv, MO_32, do_vsigncov)
TRANS(vsigncov_d, LSX, gvec_vvv, MO_64, do_vsigncov)
+TRANS(xvsigncov_b, LASX, gvec_xxx, MO_8, do_vsigncov)
+TRANS(xvsigncov_h, LASX, gvec_xxx, MO_16, do_vsigncov)
+TRANS(xvsigncov_w, LASX, gvec_xxx, MO_32, do_vsigncov)
+TRANS(xvsigncov_d, LASX, gvec_xxx, MO_64, do_vsigncov)
TRANS(vmskltz_b, LSX, gen_vv, gen_helper_vmskltz_b)
TRANS(vmskltz_h, LSX, gen_vv, gen_helper_vmskltz_h)
@@ -2923,6 +3464,12 @@
TRANS(vmskltz_d, LSX, gen_vv, gen_helper_vmskltz_d)
TRANS(vmskgez_b, LSX, gen_vv, gen_helper_vmskgez_b)
TRANS(vmsknz_b, LSX, gen_vv, gen_helper_vmsknz_b)
+TRANS(xvmskltz_b, LASX, gen_xx, gen_helper_vmskltz_b)
+TRANS(xvmskltz_h, LASX, gen_xx, gen_helper_vmskltz_h)
+TRANS(xvmskltz_w, LASX, gen_xx, gen_helper_vmskltz_w)
+TRANS(xvmskltz_d, LASX, gen_xx, gen_helper_vmskltz_d)
+TRANS(xvmskgez_b, LASX, gen_xx, gen_helper_vmskgez_b)
+TRANS(xvmsknz_b, LASX, gen_xx, gen_helper_vmsknz_b)
#define EXPAND_BYTE(bit) ((uint64_t)(bit ? 0xff : 0))
@@ -3040,17 +3587,15 @@
return data;
}
-static bool trans_vldi(DisasContext *ctx, arg_vldi *a)
+static bool gen_vldi(DisasContext *ctx, arg_vldi *a, uint32_t oprsz)
{
int sel, vece;
uint64_t value;
- if (!avail_LSX(ctx)) {
- return false;
+ if (!check_vec(ctx, oprsz)) {
+ return true;
}
- CHECK_SXE;
-
sel = (a->imm >> 12) & 0x1;
if (sel) {
@@ -3061,37 +3606,29 @@
vece = (a->imm >> 10) & 0x3;
}
- tcg_gen_gvec_dup_i64(vece, vec_full_offset(a->vd), 16, ctx->vl/8,
+ tcg_gen_gvec_dup_i64(vece, vec_full_offset(a->vd), oprsz, ctx->vl/8,
tcg_constant_i64(value));
return true;
}
-TRANS(vand_v, LSX, gvec_vvv, MO_64, tcg_gen_gvec_and)
-TRANS(vor_v, LSX, gvec_vvv, MO_64, tcg_gen_gvec_or)
-TRANS(vxor_v, LSX, gvec_vvv, MO_64, tcg_gen_gvec_xor)
-TRANS(vnor_v, LSX, gvec_vvv, MO_64, tcg_gen_gvec_nor)
+TRANS(vldi, LSX, gen_vldi, 16)
+TRANS(xvldi, LASX, gen_vldi, 32)
-static bool trans_vandn_v(DisasContext *ctx, arg_vvv *a)
+static bool gen_vandn_v(DisasContext *ctx, arg_vvv *a, uint32_t oprsz)
{
uint32_t vd_ofs, vj_ofs, vk_ofs;
- if (!avail_LSX(ctx)) {
- return false;
+ if (!check_vec(ctx, oprsz)) {
+ return true;
}
- CHECK_SXE;
-
vd_ofs = vec_full_offset(a->vd);
vj_ofs = vec_full_offset(a->vj);
vk_ofs = vec_full_offset(a->vk);
- tcg_gen_gvec_andc(MO_64, vd_ofs, vk_ofs, vj_ofs, 16, ctx->vl/8);
+ tcg_gen_gvec_andc(MO_64, vd_ofs, vk_ofs, vj_ofs, oprsz, ctx->vl / 8);
return true;
}
-TRANS(vorn_v, LSX, gvec_vvv, MO_64, tcg_gen_gvec_orc)
-TRANS(vandi_b, LSX, gvec_vv_i, MO_8, tcg_gen_gvec_andi)
-TRANS(vori_b, LSX, gvec_vv_i, MO_8, tcg_gen_gvec_ori)
-TRANS(vxori_b, LSX, gvec_vv_i, MO_8, tcg_gen_gvec_xori)
static void gen_vnori(unsigned vece, TCGv_vec t, TCGv_vec a, int64_t imm)
{
@@ -3124,7 +3661,26 @@
tcg_gen_gvec_2i(vd_ofs, vj_ofs, oprsz, maxsz, imm, &op);
}
+TRANS(vand_v, LSX, gvec_vvv, MO_64, tcg_gen_gvec_and)
+TRANS(vor_v, LSX, gvec_vvv, MO_64, tcg_gen_gvec_or)
+TRANS(vxor_v, LSX, gvec_vvv, MO_64, tcg_gen_gvec_xor)
+TRANS(vnor_v, LSX, gvec_vvv, MO_64, tcg_gen_gvec_nor)
+TRANS(vandn_v, LSX, gen_vandn_v, 16)
+TRANS(vorn_v, LSX, gvec_vvv, MO_64, tcg_gen_gvec_orc)
+TRANS(vandi_b, LSX, gvec_vv_i, MO_8, tcg_gen_gvec_andi)
+TRANS(vori_b, LSX, gvec_vv_i, MO_8, tcg_gen_gvec_ori)
+TRANS(vxori_b, LSX, gvec_vv_i, MO_8, tcg_gen_gvec_xori)
TRANS(vnori_b, LSX, gvec_vv_i, MO_8, do_vnori_b)
+TRANS(xvand_v, LASX, gvec_xxx, MO_64, tcg_gen_gvec_and)
+TRANS(xvor_v, LASX, gvec_xxx, MO_64, tcg_gen_gvec_or)
+TRANS(xvxor_v, LASX, gvec_xxx, MO_64, tcg_gen_gvec_xor)
+TRANS(xvnor_v, LASX, gvec_xxx, MO_64, tcg_gen_gvec_nor)
+TRANS(xvandn_v, LASX, gen_vandn_v, 32)
+TRANS(xvorn_v, LASX, gvec_xxx, MO_64, tcg_gen_gvec_orc)
+TRANS(xvandi_b, LASX, gvec_xx_i, MO_8, tcg_gen_gvec_andi)
+TRANS(xvori_b, LASX, gvec_xx_i, MO_8, tcg_gen_gvec_ori)
+TRANS(xvxori_b, LASX, gvec_xx_i, MO_8, tcg_gen_gvec_xori)
+TRANS(xvnori_b, LASX, gvec_xx_i, MO_8, do_vnori_b)
TRANS(vsll_b, LSX, gvec_vvv, MO_8, tcg_gen_gvec_shlv)
TRANS(vsll_h, LSX, gvec_vvv, MO_16, tcg_gen_gvec_shlv)
@@ -3134,6 +3690,14 @@
TRANS(vslli_h, LSX, gvec_vv_i, MO_16, tcg_gen_gvec_shli)
TRANS(vslli_w, LSX, gvec_vv_i, MO_32, tcg_gen_gvec_shli)
TRANS(vslli_d, LSX, gvec_vv_i, MO_64, tcg_gen_gvec_shli)
+TRANS(xvsll_b, LASX, gvec_xxx, MO_8, tcg_gen_gvec_shlv)
+TRANS(xvsll_h, LASX, gvec_xxx, MO_16, tcg_gen_gvec_shlv)
+TRANS(xvsll_w, LASX, gvec_xxx, MO_32, tcg_gen_gvec_shlv)
+TRANS(xvsll_d, LASX, gvec_xxx, MO_64, tcg_gen_gvec_shlv)
+TRANS(xvslli_b, LASX, gvec_xx_i, MO_8, tcg_gen_gvec_shli)
+TRANS(xvslli_h, LASX, gvec_xx_i, MO_16, tcg_gen_gvec_shli)
+TRANS(xvslli_w, LASX, gvec_xx_i, MO_32, tcg_gen_gvec_shli)
+TRANS(xvslli_d, LASX, gvec_xx_i, MO_64, tcg_gen_gvec_shli)
TRANS(vsrl_b, LSX, gvec_vvv, MO_8, tcg_gen_gvec_shrv)
TRANS(vsrl_h, LSX, gvec_vvv, MO_16, tcg_gen_gvec_shrv)
@@ -3143,6 +3707,14 @@
TRANS(vsrli_h, LSX, gvec_vv_i, MO_16, tcg_gen_gvec_shri)
TRANS(vsrli_w, LSX, gvec_vv_i, MO_32, tcg_gen_gvec_shri)
TRANS(vsrli_d, LSX, gvec_vv_i, MO_64, tcg_gen_gvec_shri)
+TRANS(xvsrl_b, LASX, gvec_xxx, MO_8, tcg_gen_gvec_shrv)
+TRANS(xvsrl_h, LASX, gvec_xxx, MO_16, tcg_gen_gvec_shrv)
+TRANS(xvsrl_w, LASX, gvec_xxx, MO_32, tcg_gen_gvec_shrv)
+TRANS(xvsrl_d, LASX, gvec_xxx, MO_64, tcg_gen_gvec_shrv)
+TRANS(xvsrli_b, LASX, gvec_xx_i, MO_8, tcg_gen_gvec_shri)
+TRANS(xvsrli_h, LASX, gvec_xx_i, MO_16, tcg_gen_gvec_shri)
+TRANS(xvsrli_w, LASX, gvec_xx_i, MO_32, tcg_gen_gvec_shri)
+TRANS(xvsrli_d, LASX, gvec_xx_i, MO_64, tcg_gen_gvec_shri)
TRANS(vsra_b, LSX, gvec_vvv, MO_8, tcg_gen_gvec_sarv)
TRANS(vsra_h, LSX, gvec_vvv, MO_16, tcg_gen_gvec_sarv)
@@ -3152,6 +3724,14 @@
TRANS(vsrai_h, LSX, gvec_vv_i, MO_16, tcg_gen_gvec_sari)
TRANS(vsrai_w, LSX, gvec_vv_i, MO_32, tcg_gen_gvec_sari)
TRANS(vsrai_d, LSX, gvec_vv_i, MO_64, tcg_gen_gvec_sari)
+TRANS(xvsra_b, LASX, gvec_xxx, MO_8, tcg_gen_gvec_sarv)
+TRANS(xvsra_h, LASX, gvec_xxx, MO_16, tcg_gen_gvec_sarv)
+TRANS(xvsra_w, LASX, gvec_xxx, MO_32, tcg_gen_gvec_sarv)
+TRANS(xvsra_d, LASX, gvec_xxx, MO_64, tcg_gen_gvec_sarv)
+TRANS(xvsrai_b, LASX, gvec_xx_i, MO_8, tcg_gen_gvec_sari)
+TRANS(xvsrai_h, LASX, gvec_xx_i, MO_16, tcg_gen_gvec_sari)
+TRANS(xvsrai_w, LASX, gvec_xx_i, MO_32, tcg_gen_gvec_sari)
+TRANS(xvsrai_d, LASX, gvec_xx_i, MO_64, tcg_gen_gvec_sari)
TRANS(vrotr_b, LSX, gvec_vvv, MO_8, tcg_gen_gvec_rotrv)
TRANS(vrotr_h, LSX, gvec_vvv, MO_16, tcg_gen_gvec_rotrv)
@@ -3161,6 +3741,14 @@
TRANS(vrotri_h, LSX, gvec_vv_i, MO_16, tcg_gen_gvec_rotri)
TRANS(vrotri_w, LSX, gvec_vv_i, MO_32, tcg_gen_gvec_rotri)
TRANS(vrotri_d, LSX, gvec_vv_i, MO_64, tcg_gen_gvec_rotri)
+TRANS(xvrotr_b, LASX, gvec_xxx, MO_8, tcg_gen_gvec_rotrv)
+TRANS(xvrotr_h, LASX, gvec_xxx, MO_16, tcg_gen_gvec_rotrv)
+TRANS(xvrotr_w, LASX, gvec_xxx, MO_32, tcg_gen_gvec_rotrv)
+TRANS(xvrotr_d, LASX, gvec_xxx, MO_64, tcg_gen_gvec_rotrv)
+TRANS(xvrotri_b, LASX, gvec_xx_i, MO_8, tcg_gen_gvec_rotri)
+TRANS(xvrotri_h, LASX, gvec_xx_i, MO_16, tcg_gen_gvec_rotri)
+TRANS(xvrotri_w, LASX, gvec_xx_i, MO_32, tcg_gen_gvec_rotri)
+TRANS(xvrotri_d, LASX, gvec_xx_i, MO_64, tcg_gen_gvec_rotri)
TRANS(vsllwil_h_b, LSX, gen_vv_i, gen_helper_vsllwil_h_b)
TRANS(vsllwil_w_h, LSX, gen_vv_i, gen_helper_vsllwil_w_h)
@@ -3170,6 +3758,14 @@
TRANS(vsllwil_wu_hu, LSX, gen_vv_i, gen_helper_vsllwil_wu_hu)
TRANS(vsllwil_du_wu, LSX, gen_vv_i, gen_helper_vsllwil_du_wu)
TRANS(vextl_qu_du, LSX, gen_vv, gen_helper_vextl_qu_du)
+TRANS(xvsllwil_h_b, LASX, gen_xx_i, gen_helper_vsllwil_h_b)
+TRANS(xvsllwil_w_h, LASX, gen_xx_i, gen_helper_vsllwil_w_h)
+TRANS(xvsllwil_d_w, LASX, gen_xx_i, gen_helper_vsllwil_d_w)
+TRANS(xvextl_q_d, LASX, gen_xx, gen_helper_vextl_q_d)
+TRANS(xvsllwil_hu_bu, LASX, gen_xx_i, gen_helper_vsllwil_hu_bu)
+TRANS(xvsllwil_wu_hu, LASX, gen_xx_i, gen_helper_vsllwil_wu_hu)
+TRANS(xvsllwil_du_wu, LASX, gen_xx_i, gen_helper_vsllwil_du_wu)
+TRANS(xvextl_qu_du, LASX, gen_xx, gen_helper_vextl_qu_du)
TRANS(vsrlr_b, LSX, gen_vvv, gen_helper_vsrlr_b)
TRANS(vsrlr_h, LSX, gen_vvv, gen_helper_vsrlr_h)
@@ -3179,6 +3775,14 @@
TRANS(vsrlri_h, LSX, gen_vv_i, gen_helper_vsrlri_h)
TRANS(vsrlri_w, LSX, gen_vv_i, gen_helper_vsrlri_w)
TRANS(vsrlri_d, LSX, gen_vv_i, gen_helper_vsrlri_d)
+TRANS(xvsrlr_b, LASX, gen_xxx, gen_helper_vsrlr_b)
+TRANS(xvsrlr_h, LASX, gen_xxx, gen_helper_vsrlr_h)
+TRANS(xvsrlr_w, LASX, gen_xxx, gen_helper_vsrlr_w)
+TRANS(xvsrlr_d, LASX, gen_xxx, gen_helper_vsrlr_d)
+TRANS(xvsrlri_b, LASX, gen_xx_i, gen_helper_vsrlri_b)
+TRANS(xvsrlri_h, LASX, gen_xx_i, gen_helper_vsrlri_h)
+TRANS(xvsrlri_w, LASX, gen_xx_i, gen_helper_vsrlri_w)
+TRANS(xvsrlri_d, LASX, gen_xx_i, gen_helper_vsrlri_d)
TRANS(vsrar_b, LSX, gen_vvv, gen_helper_vsrar_b)
TRANS(vsrar_h, LSX, gen_vvv, gen_helper_vsrar_h)
@@ -3188,6 +3792,14 @@
TRANS(vsrari_h, LSX, gen_vv_i, gen_helper_vsrari_h)
TRANS(vsrari_w, LSX, gen_vv_i, gen_helper_vsrari_w)
TRANS(vsrari_d, LSX, gen_vv_i, gen_helper_vsrari_d)
+TRANS(xvsrar_b, LASX, gen_xxx, gen_helper_vsrar_b)
+TRANS(xvsrar_h, LASX, gen_xxx, gen_helper_vsrar_h)
+TRANS(xvsrar_w, LASX, gen_xxx, gen_helper_vsrar_w)
+TRANS(xvsrar_d, LASX, gen_xxx, gen_helper_vsrar_d)
+TRANS(xvsrari_b, LASX, gen_xx_i, gen_helper_vsrari_b)
+TRANS(xvsrari_h, LASX, gen_xx_i, gen_helper_vsrari_h)
+TRANS(xvsrari_w, LASX, gen_xx_i, gen_helper_vsrari_w)
+TRANS(xvsrari_d, LASX, gen_xx_i, gen_helper_vsrari_d)
TRANS(vsrln_b_h, LSX, gen_vvv, gen_helper_vsrln_b_h)
TRANS(vsrln_h_w, LSX, gen_vvv, gen_helper_vsrln_h_w)
@@ -3195,6 +3807,12 @@
TRANS(vsran_b_h, LSX, gen_vvv, gen_helper_vsran_b_h)
TRANS(vsran_h_w, LSX, gen_vvv, gen_helper_vsran_h_w)
TRANS(vsran_w_d, LSX, gen_vvv, gen_helper_vsran_w_d)
+TRANS(xvsrln_b_h, LASX, gen_xxx, gen_helper_vsrln_b_h)
+TRANS(xvsrln_h_w, LASX, gen_xxx, gen_helper_vsrln_h_w)
+TRANS(xvsrln_w_d, LASX, gen_xxx, gen_helper_vsrln_w_d)
+TRANS(xvsran_b_h, LASX, gen_xxx, gen_helper_vsran_b_h)
+TRANS(xvsran_h_w, LASX, gen_xxx, gen_helper_vsran_h_w)
+TRANS(xvsran_w_d, LASX, gen_xxx, gen_helper_vsran_w_d)
TRANS(vsrlni_b_h, LSX, gen_vv_i, gen_helper_vsrlni_b_h)
TRANS(vsrlni_h_w, LSX, gen_vv_i, gen_helper_vsrlni_h_w)
@@ -3204,6 +3822,14 @@
TRANS(vsrani_h_w, LSX, gen_vv_i, gen_helper_vsrani_h_w)
TRANS(vsrani_w_d, LSX, gen_vv_i, gen_helper_vsrani_w_d)
TRANS(vsrani_d_q, LSX, gen_vv_i, gen_helper_vsrani_d_q)
+TRANS(xvsrlni_b_h, LASX, gen_xx_i, gen_helper_vsrlni_b_h)
+TRANS(xvsrlni_h_w, LASX, gen_xx_i, gen_helper_vsrlni_h_w)
+TRANS(xvsrlni_w_d, LASX, gen_xx_i, gen_helper_vsrlni_w_d)
+TRANS(xvsrlni_d_q, LASX, gen_xx_i, gen_helper_vsrlni_d_q)
+TRANS(xvsrani_b_h, LASX, gen_xx_i, gen_helper_vsrani_b_h)
+TRANS(xvsrani_h_w, LASX, gen_xx_i, gen_helper_vsrani_h_w)
+TRANS(xvsrani_w_d, LASX, gen_xx_i, gen_helper_vsrani_w_d)
+TRANS(xvsrani_d_q, LASX, gen_xx_i, gen_helper_vsrani_d_q)
TRANS(vsrlrn_b_h, LSX, gen_vvv, gen_helper_vsrlrn_b_h)
TRANS(vsrlrn_h_w, LSX, gen_vvv, gen_helper_vsrlrn_h_w)
@@ -3211,6 +3837,12 @@
TRANS(vsrarn_b_h, LSX, gen_vvv, gen_helper_vsrarn_b_h)
TRANS(vsrarn_h_w, LSX, gen_vvv, gen_helper_vsrarn_h_w)
TRANS(vsrarn_w_d, LSX, gen_vvv, gen_helper_vsrarn_w_d)
+TRANS(xvsrlrn_b_h, LASX, gen_xxx, gen_helper_vsrlrn_b_h)
+TRANS(xvsrlrn_h_w, LASX, gen_xxx, gen_helper_vsrlrn_h_w)
+TRANS(xvsrlrn_w_d, LASX, gen_xxx, gen_helper_vsrlrn_w_d)
+TRANS(xvsrarn_b_h, LASX, gen_xxx, gen_helper_vsrarn_b_h)
+TRANS(xvsrarn_h_w, LASX, gen_xxx, gen_helper_vsrarn_h_w)
+TRANS(xvsrarn_w_d, LASX, gen_xxx, gen_helper_vsrarn_w_d)
TRANS(vsrlrni_b_h, LSX, gen_vv_i, gen_helper_vsrlrni_b_h)
TRANS(vsrlrni_h_w, LSX, gen_vv_i, gen_helper_vsrlrni_h_w)
@@ -3220,6 +3852,14 @@
TRANS(vsrarni_h_w, LSX, gen_vv_i, gen_helper_vsrarni_h_w)
TRANS(vsrarni_w_d, LSX, gen_vv_i, gen_helper_vsrarni_w_d)
TRANS(vsrarni_d_q, LSX, gen_vv_i, gen_helper_vsrarni_d_q)
+TRANS(xvsrlrni_b_h, LASX, gen_xx_i, gen_helper_vsrlrni_b_h)
+TRANS(xvsrlrni_h_w, LASX, gen_xx_i, gen_helper_vsrlrni_h_w)
+TRANS(xvsrlrni_w_d, LASX, gen_xx_i, gen_helper_vsrlrni_w_d)
+TRANS(xvsrlrni_d_q, LASX, gen_xx_i, gen_helper_vsrlrni_d_q)
+TRANS(xvsrarni_b_h, LASX, gen_xx_i, gen_helper_vsrarni_b_h)
+TRANS(xvsrarni_h_w, LASX, gen_xx_i, gen_helper_vsrarni_h_w)
+TRANS(xvsrarni_w_d, LASX, gen_xx_i, gen_helper_vsrarni_w_d)
+TRANS(xvsrarni_d_q, LASX, gen_xx_i, gen_helper_vsrarni_d_q)
TRANS(vssrln_b_h, LSX, gen_vvv, gen_helper_vssrln_b_h)
TRANS(vssrln_h_w, LSX, gen_vvv, gen_helper_vssrln_h_w)
@@ -3233,6 +3873,18 @@
TRANS(vssran_bu_h, LSX, gen_vvv, gen_helper_vssran_bu_h)
TRANS(vssran_hu_w, LSX, gen_vvv, gen_helper_vssran_hu_w)
TRANS(vssran_wu_d, LSX, gen_vvv, gen_helper_vssran_wu_d)
+TRANS(xvssrln_b_h, LASX, gen_xxx, gen_helper_vssrln_b_h)
+TRANS(xvssrln_h_w, LASX, gen_xxx, gen_helper_vssrln_h_w)
+TRANS(xvssrln_w_d, LASX, gen_xxx, gen_helper_vssrln_w_d)
+TRANS(xvssran_b_h, LASX, gen_xxx, gen_helper_vssran_b_h)
+TRANS(xvssran_h_w, LASX, gen_xxx, gen_helper_vssran_h_w)
+TRANS(xvssran_w_d, LASX, gen_xxx, gen_helper_vssran_w_d)
+TRANS(xvssrln_bu_h, LASX, gen_xxx, gen_helper_vssrln_bu_h)
+TRANS(xvssrln_hu_w, LASX, gen_xxx, gen_helper_vssrln_hu_w)
+TRANS(xvssrln_wu_d, LASX, gen_xxx, gen_helper_vssrln_wu_d)
+TRANS(xvssran_bu_h, LASX, gen_xxx, gen_helper_vssran_bu_h)
+TRANS(xvssran_hu_w, LASX, gen_xxx, gen_helper_vssran_hu_w)
+TRANS(xvssran_wu_d, LASX, gen_xxx, gen_helper_vssran_wu_d)
TRANS(vssrlni_b_h, LSX, gen_vv_i, gen_helper_vssrlni_b_h)
TRANS(vssrlni_h_w, LSX, gen_vv_i, gen_helper_vssrlni_h_w)
@@ -3250,6 +3902,22 @@
TRANS(vssrani_hu_w, LSX, gen_vv_i, gen_helper_vssrani_hu_w)
TRANS(vssrani_wu_d, LSX, gen_vv_i, gen_helper_vssrani_wu_d)
TRANS(vssrani_du_q, LSX, gen_vv_i, gen_helper_vssrani_du_q)
+TRANS(xvssrlni_b_h, LASX, gen_xx_i, gen_helper_vssrlni_b_h)
+TRANS(xvssrlni_h_w, LASX, gen_xx_i, gen_helper_vssrlni_h_w)
+TRANS(xvssrlni_w_d, LASX, gen_xx_i, gen_helper_vssrlni_w_d)
+TRANS(xvssrlni_d_q, LASX, gen_xx_i, gen_helper_vssrlni_d_q)
+TRANS(xvssrani_b_h, LASX, gen_xx_i, gen_helper_vssrani_b_h)
+TRANS(xvssrani_h_w, LASX, gen_xx_i, gen_helper_vssrani_h_w)
+TRANS(xvssrani_w_d, LASX, gen_xx_i, gen_helper_vssrani_w_d)
+TRANS(xvssrani_d_q, LASX, gen_xx_i, gen_helper_vssrani_d_q)
+TRANS(xvssrlni_bu_h, LASX, gen_xx_i, gen_helper_vssrlni_bu_h)
+TRANS(xvssrlni_hu_w, LASX, gen_xx_i, gen_helper_vssrlni_hu_w)
+TRANS(xvssrlni_wu_d, LASX, gen_xx_i, gen_helper_vssrlni_wu_d)
+TRANS(xvssrlni_du_q, LASX, gen_xx_i, gen_helper_vssrlni_du_q)
+TRANS(xvssrani_bu_h, LASX, gen_xx_i, gen_helper_vssrani_bu_h)
+TRANS(xvssrani_hu_w, LASX, gen_xx_i, gen_helper_vssrani_hu_w)
+TRANS(xvssrani_wu_d, LASX, gen_xx_i, gen_helper_vssrani_wu_d)
+TRANS(xvssrani_du_q, LASX, gen_xx_i, gen_helper_vssrani_du_q)
TRANS(vssrlrn_b_h, LSX, gen_vvv, gen_helper_vssrlrn_b_h)
TRANS(vssrlrn_h_w, LSX, gen_vvv, gen_helper_vssrlrn_h_w)
@@ -3263,6 +3931,18 @@
TRANS(vssrarn_bu_h, LSX, gen_vvv, gen_helper_vssrarn_bu_h)
TRANS(vssrarn_hu_w, LSX, gen_vvv, gen_helper_vssrarn_hu_w)
TRANS(vssrarn_wu_d, LSX, gen_vvv, gen_helper_vssrarn_wu_d)
+TRANS(xvssrlrn_b_h, LASX, gen_xxx, gen_helper_vssrlrn_b_h)
+TRANS(xvssrlrn_h_w, LASX, gen_xxx, gen_helper_vssrlrn_h_w)
+TRANS(xvssrlrn_w_d, LASX, gen_xxx, gen_helper_vssrlrn_w_d)
+TRANS(xvssrarn_b_h, LASX, gen_xxx, gen_helper_vssrarn_b_h)
+TRANS(xvssrarn_h_w, LASX, gen_xxx, gen_helper_vssrarn_h_w)
+TRANS(xvssrarn_w_d, LASX, gen_xxx, gen_helper_vssrarn_w_d)
+TRANS(xvssrlrn_bu_h, LASX, gen_xxx, gen_helper_vssrlrn_bu_h)
+TRANS(xvssrlrn_hu_w, LASX, gen_xxx, gen_helper_vssrlrn_hu_w)
+TRANS(xvssrlrn_wu_d, LASX, gen_xxx, gen_helper_vssrlrn_wu_d)
+TRANS(xvssrarn_bu_h, LASX, gen_xxx, gen_helper_vssrarn_bu_h)
+TRANS(xvssrarn_hu_w, LASX, gen_xxx, gen_helper_vssrarn_hu_w)
+TRANS(xvssrarn_wu_d, LASX, gen_xxx, gen_helper_vssrarn_wu_d)
TRANS(vssrlrni_b_h, LSX, gen_vv_i, gen_helper_vssrlrni_b_h)
TRANS(vssrlrni_h_w, LSX, gen_vv_i, gen_helper_vssrlrni_h_w)
@@ -3280,6 +3960,22 @@
TRANS(vssrarni_hu_w, LSX, gen_vv_i, gen_helper_vssrarni_hu_w)
TRANS(vssrarni_wu_d, LSX, gen_vv_i, gen_helper_vssrarni_wu_d)
TRANS(vssrarni_du_q, LSX, gen_vv_i, gen_helper_vssrarni_du_q)
+TRANS(xvssrlrni_b_h, LASX, gen_xx_i, gen_helper_vssrlrni_b_h)
+TRANS(xvssrlrni_h_w, LASX, gen_xx_i, gen_helper_vssrlrni_h_w)
+TRANS(xvssrlrni_w_d, LASX, gen_xx_i, gen_helper_vssrlrni_w_d)
+TRANS(xvssrlrni_d_q, LASX, gen_xx_i, gen_helper_vssrlrni_d_q)
+TRANS(xvssrarni_b_h, LASX, gen_xx_i, gen_helper_vssrarni_b_h)
+TRANS(xvssrarni_h_w, LASX, gen_xx_i, gen_helper_vssrarni_h_w)
+TRANS(xvssrarni_w_d, LASX, gen_xx_i, gen_helper_vssrarni_w_d)
+TRANS(xvssrarni_d_q, LASX, gen_xx_i, gen_helper_vssrarni_d_q)
+TRANS(xvssrlrni_bu_h, LASX, gen_xx_i, gen_helper_vssrlrni_bu_h)
+TRANS(xvssrlrni_hu_w, LASX, gen_xx_i, gen_helper_vssrlrni_hu_w)
+TRANS(xvssrlrni_wu_d, LASX, gen_xx_i, gen_helper_vssrlrni_wu_d)
+TRANS(xvssrlrni_du_q, LASX, gen_xx_i, gen_helper_vssrlrni_du_q)
+TRANS(xvssrarni_bu_h, LASX, gen_xx_i, gen_helper_vssrarni_bu_h)
+TRANS(xvssrarni_hu_w, LASX, gen_xx_i, gen_helper_vssrarni_hu_w)
+TRANS(xvssrarni_wu_d, LASX, gen_xx_i, gen_helper_vssrarni_wu_d)
+TRANS(xvssrarni_du_q, LASX, gen_xx_i, gen_helper_vssrarni_du_q)
TRANS(vclo_b, LSX, gen_vv, gen_helper_vclo_b)
TRANS(vclo_h, LSX, gen_vv, gen_helper_vclo_h)
@@ -3289,11 +3985,23 @@
TRANS(vclz_h, LSX, gen_vv, gen_helper_vclz_h)
TRANS(vclz_w, LSX, gen_vv, gen_helper_vclz_w)
TRANS(vclz_d, LSX, gen_vv, gen_helper_vclz_d)
+TRANS(xvclo_b, LASX, gen_xx, gen_helper_vclo_b)
+TRANS(xvclo_h, LASX, gen_xx, gen_helper_vclo_h)
+TRANS(xvclo_w, LASX, gen_xx, gen_helper_vclo_w)
+TRANS(xvclo_d, LASX, gen_xx, gen_helper_vclo_d)
+TRANS(xvclz_b, LASX, gen_xx, gen_helper_vclz_b)
+TRANS(xvclz_h, LASX, gen_xx, gen_helper_vclz_h)
+TRANS(xvclz_w, LASX, gen_xx, gen_helper_vclz_w)
+TRANS(xvclz_d, LASX, gen_xx, gen_helper_vclz_d)
TRANS(vpcnt_b, LSX, gen_vv, gen_helper_vpcnt_b)
TRANS(vpcnt_h, LSX, gen_vv, gen_helper_vpcnt_h)
TRANS(vpcnt_w, LSX, gen_vv, gen_helper_vpcnt_w)
TRANS(vpcnt_d, LSX, gen_vv, gen_helper_vpcnt_d)
+TRANS(xvpcnt_b, LASX, gen_xx, gen_helper_vpcnt_b)
+TRANS(xvpcnt_h, LASX, gen_xx, gen_helper_vpcnt_h)
+TRANS(xvpcnt_w, LASX, gen_xx, gen_helper_vpcnt_w)
+TRANS(xvpcnt_d, LASX, gen_xx, gen_helper_vpcnt_d)
static void do_vbit(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b,
void (*func)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec))
@@ -3365,6 +4073,10 @@
TRANS(vbitclr_h, LSX, gvec_vvv, MO_16, do_vbitclr)
TRANS(vbitclr_w, LSX, gvec_vvv, MO_32, do_vbitclr)
TRANS(vbitclr_d, LSX, gvec_vvv, MO_64, do_vbitclr)
+TRANS(xvbitclr_b, LASX, gvec_xxx, MO_8, do_vbitclr)
+TRANS(xvbitclr_h, LASX, gvec_xxx, MO_16, do_vbitclr)
+TRANS(xvbitclr_w, LASX, gvec_xxx, MO_32, do_vbitclr)
+TRANS(xvbitclr_d, LASX, gvec_xxx, MO_64, do_vbitclr)
static void do_vbiti(unsigned vece, TCGv_vec t, TCGv_vec a, int64_t imm,
void (*func)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec))
@@ -3435,6 +4147,10 @@
TRANS(vbitclri_h, LSX, gvec_vv_i, MO_16, do_vbitclri)
TRANS(vbitclri_w, LSX, gvec_vv_i, MO_32, do_vbitclri)
TRANS(vbitclri_d, LSX, gvec_vv_i, MO_64, do_vbitclri)
+TRANS(xvbitclri_b, LASX, gvec_xx_i, MO_8, do_vbitclri)
+TRANS(xvbitclri_h, LASX, gvec_xx_i, MO_16, do_vbitclri)
+TRANS(xvbitclri_w, LASX, gvec_xx_i, MO_32, do_vbitclri)
+TRANS(xvbitclri_d, LASX, gvec_xx_i, MO_64, do_vbitclri)
static void do_vbitset(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
@@ -3476,6 +4192,10 @@
TRANS(vbitset_h, LSX, gvec_vvv, MO_16, do_vbitset)
TRANS(vbitset_w, LSX, gvec_vvv, MO_32, do_vbitset)
TRANS(vbitset_d, LSX, gvec_vvv, MO_64, do_vbitset)
+TRANS(xvbitset_b, LASX, gvec_xxx, MO_8, do_vbitset)
+TRANS(xvbitset_h, LASX, gvec_xxx, MO_16, do_vbitset)
+TRANS(xvbitset_w, LASX, gvec_xxx, MO_32, do_vbitset)
+TRANS(xvbitset_d, LASX, gvec_xxx, MO_64, do_vbitset)
static void do_vbitseti(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
int64_t imm, uint32_t oprsz, uint32_t maxsz)
@@ -3517,6 +4237,10 @@
TRANS(vbitseti_h, LSX, gvec_vv_i, MO_16, do_vbitseti)
TRANS(vbitseti_w, LSX, gvec_vv_i, MO_32, do_vbitseti)
TRANS(vbitseti_d, LSX, gvec_vv_i, MO_64, do_vbitseti)
+TRANS(xvbitseti_b, LASX, gvec_xx_i, MO_8, do_vbitseti)
+TRANS(xvbitseti_h, LASX, gvec_xx_i, MO_16, do_vbitseti)
+TRANS(xvbitseti_w, LASX, gvec_xx_i, MO_32, do_vbitseti)
+TRANS(xvbitseti_d, LASX, gvec_xx_i, MO_64, do_vbitseti)
static void do_vbitrev(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
@@ -3558,6 +4282,10 @@
TRANS(vbitrev_h, LSX, gvec_vvv, MO_16, do_vbitrev)
TRANS(vbitrev_w, LSX, gvec_vvv, MO_32, do_vbitrev)
TRANS(vbitrev_d, LSX, gvec_vvv, MO_64, do_vbitrev)
+TRANS(xvbitrev_b, LASX, gvec_xxx, MO_8, do_vbitrev)
+TRANS(xvbitrev_h, LASX, gvec_xxx, MO_16, do_vbitrev)
+TRANS(xvbitrev_w, LASX, gvec_xxx, MO_32, do_vbitrev)
+TRANS(xvbitrev_d, LASX, gvec_xxx, MO_64, do_vbitrev)
static void do_vbitrevi(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
int64_t imm, uint32_t oprsz, uint32_t maxsz)
@@ -3599,356 +4327,409 @@
TRANS(vbitrevi_h, LSX, gvec_vv_i, MO_16, do_vbitrevi)
TRANS(vbitrevi_w, LSX, gvec_vv_i, MO_32, do_vbitrevi)
TRANS(vbitrevi_d, LSX, gvec_vv_i, MO_64, do_vbitrevi)
+TRANS(xvbitrevi_b, LASX, gvec_xx_i, MO_8, do_vbitrevi)
+TRANS(xvbitrevi_h, LASX, gvec_xx_i, MO_16, do_vbitrevi)
+TRANS(xvbitrevi_w, LASX, gvec_xx_i, MO_32, do_vbitrevi)
+TRANS(xvbitrevi_d, LASX, gvec_xx_i, MO_64, do_vbitrevi)
TRANS(vfrstp_b, LSX, gen_vvv, gen_helper_vfrstp_b)
TRANS(vfrstp_h, LSX, gen_vvv, gen_helper_vfrstp_h)
TRANS(vfrstpi_b, LSX, gen_vv_i, gen_helper_vfrstpi_b)
TRANS(vfrstpi_h, LSX, gen_vv_i, gen_helper_vfrstpi_h)
+TRANS(xvfrstp_b, LASX, gen_xxx, gen_helper_vfrstp_b)
+TRANS(xvfrstp_h, LASX, gen_xxx, gen_helper_vfrstp_h)
+TRANS(xvfrstpi_b, LASX, gen_xx_i, gen_helper_vfrstpi_b)
+TRANS(xvfrstpi_h, LASX, gen_xx_i, gen_helper_vfrstpi_h)
-TRANS(vfadd_s, LSX, gen_vvv, gen_helper_vfadd_s)
-TRANS(vfadd_d, LSX, gen_vvv, gen_helper_vfadd_d)
-TRANS(vfsub_s, LSX, gen_vvv, gen_helper_vfsub_s)
-TRANS(vfsub_d, LSX, gen_vvv, gen_helper_vfsub_d)
-TRANS(vfmul_s, LSX, gen_vvv, gen_helper_vfmul_s)
-TRANS(vfmul_d, LSX, gen_vvv, gen_helper_vfmul_d)
-TRANS(vfdiv_s, LSX, gen_vvv, gen_helper_vfdiv_s)
-TRANS(vfdiv_d, LSX, gen_vvv, gen_helper_vfdiv_d)
+TRANS(vfadd_s, LSX, gen_vvv_ptr, gen_helper_vfadd_s)
+TRANS(vfadd_d, LSX, gen_vvv_ptr, gen_helper_vfadd_d)
+TRANS(vfsub_s, LSX, gen_vvv_ptr, gen_helper_vfsub_s)
+TRANS(vfsub_d, LSX, gen_vvv_ptr, gen_helper_vfsub_d)
+TRANS(vfmul_s, LSX, gen_vvv_ptr, gen_helper_vfmul_s)
+TRANS(vfmul_d, LSX, gen_vvv_ptr, gen_helper_vfmul_d)
+TRANS(vfdiv_s, LSX, gen_vvv_ptr, gen_helper_vfdiv_s)
+TRANS(vfdiv_d, LSX, gen_vvv_ptr, gen_helper_vfdiv_d)
+TRANS(xvfadd_s, LASX, gen_xxx_ptr, gen_helper_vfadd_s)
+TRANS(xvfadd_d, LASX, gen_xxx_ptr, gen_helper_vfadd_d)
+TRANS(xvfsub_s, LASX, gen_xxx_ptr, gen_helper_vfsub_s)
+TRANS(xvfsub_d, LASX, gen_xxx_ptr, gen_helper_vfsub_d)
+TRANS(xvfmul_s, LASX, gen_xxx_ptr, gen_helper_vfmul_s)
+TRANS(xvfmul_d, LASX, gen_xxx_ptr, gen_helper_vfmul_d)
+TRANS(xvfdiv_s, LASX, gen_xxx_ptr, gen_helper_vfdiv_s)
+TRANS(xvfdiv_d, LASX, gen_xxx_ptr, gen_helper_vfdiv_d)
-TRANS(vfmadd_s, LSX, gen_vvvv, gen_helper_vfmadd_s)
-TRANS(vfmadd_d, LSX, gen_vvvv, gen_helper_vfmadd_d)
-TRANS(vfmsub_s, LSX, gen_vvvv, gen_helper_vfmsub_s)
-TRANS(vfmsub_d, LSX, gen_vvvv, gen_helper_vfmsub_d)
-TRANS(vfnmadd_s, LSX, gen_vvvv, gen_helper_vfnmadd_s)
-TRANS(vfnmadd_d, LSX, gen_vvvv, gen_helper_vfnmadd_d)
-TRANS(vfnmsub_s, LSX, gen_vvvv, gen_helper_vfnmsub_s)
-TRANS(vfnmsub_d, LSX, gen_vvvv, gen_helper_vfnmsub_d)
+TRANS(vfmadd_s, LSX, gen_vvvv_ptr, gen_helper_vfmadd_s)
+TRANS(vfmadd_d, LSX, gen_vvvv_ptr, gen_helper_vfmadd_d)
+TRANS(vfmsub_s, LSX, gen_vvvv_ptr, gen_helper_vfmsub_s)
+TRANS(vfmsub_d, LSX, gen_vvvv_ptr, gen_helper_vfmsub_d)
+TRANS(vfnmadd_s, LSX, gen_vvvv_ptr, gen_helper_vfnmadd_s)
+TRANS(vfnmadd_d, LSX, gen_vvvv_ptr, gen_helper_vfnmadd_d)
+TRANS(vfnmsub_s, LSX, gen_vvvv_ptr, gen_helper_vfnmsub_s)
+TRANS(vfnmsub_d, LSX, gen_vvvv_ptr, gen_helper_vfnmsub_d)
+TRANS(xvfmadd_s, LASX, gen_xxxx_ptr, gen_helper_vfmadd_s)
+TRANS(xvfmadd_d, LASX, gen_xxxx_ptr, gen_helper_vfmadd_d)
+TRANS(xvfmsub_s, LASX, gen_xxxx_ptr, gen_helper_vfmsub_s)
+TRANS(xvfmsub_d, LASX, gen_xxxx_ptr, gen_helper_vfmsub_d)
+TRANS(xvfnmadd_s, LASX, gen_xxxx_ptr, gen_helper_vfnmadd_s)
+TRANS(xvfnmadd_d, LASX, gen_xxxx_ptr, gen_helper_vfnmadd_d)
+TRANS(xvfnmsub_s, LASX, gen_xxxx_ptr, gen_helper_vfnmsub_s)
+TRANS(xvfnmsub_d, LASX, gen_xxxx_ptr, gen_helper_vfnmsub_d)
-TRANS(vfmax_s, LSX, gen_vvv, gen_helper_vfmax_s)
-TRANS(vfmax_d, LSX, gen_vvv, gen_helper_vfmax_d)
-TRANS(vfmin_s, LSX, gen_vvv, gen_helper_vfmin_s)
-TRANS(vfmin_d, LSX, gen_vvv, gen_helper_vfmin_d)
+TRANS(vfmax_s, LSX, gen_vvv_ptr, gen_helper_vfmax_s)
+TRANS(vfmax_d, LSX, gen_vvv_ptr, gen_helper_vfmax_d)
+TRANS(vfmin_s, LSX, gen_vvv_ptr, gen_helper_vfmin_s)
+TRANS(vfmin_d, LSX, gen_vvv_ptr, gen_helper_vfmin_d)
+TRANS(xvfmax_s, LASX, gen_xxx_ptr, gen_helper_vfmax_s)
+TRANS(xvfmax_d, LASX, gen_xxx_ptr, gen_helper_vfmax_d)
+TRANS(xvfmin_s, LASX, gen_xxx_ptr, gen_helper_vfmin_s)
+TRANS(xvfmin_d, LASX, gen_xxx_ptr, gen_helper_vfmin_d)
-TRANS(vfmaxa_s, LSX, gen_vvv, gen_helper_vfmaxa_s)
-TRANS(vfmaxa_d, LSX, gen_vvv, gen_helper_vfmaxa_d)
-TRANS(vfmina_s, LSX, gen_vvv, gen_helper_vfmina_s)
-TRANS(vfmina_d, LSX, gen_vvv, gen_helper_vfmina_d)
+TRANS(vfmaxa_s, LSX, gen_vvv_ptr, gen_helper_vfmaxa_s)
+TRANS(vfmaxa_d, LSX, gen_vvv_ptr, gen_helper_vfmaxa_d)
+TRANS(vfmina_s, LSX, gen_vvv_ptr, gen_helper_vfmina_s)
+TRANS(vfmina_d, LSX, gen_vvv_ptr, gen_helper_vfmina_d)
+TRANS(xvfmaxa_s, LASX, gen_xxx_ptr, gen_helper_vfmaxa_s)
+TRANS(xvfmaxa_d, LASX, gen_xxx_ptr, gen_helper_vfmaxa_d)
+TRANS(xvfmina_s, LASX, gen_xxx_ptr, gen_helper_vfmina_s)
+TRANS(xvfmina_d, LASX, gen_xxx_ptr, gen_helper_vfmina_d)
-TRANS(vflogb_s, LSX, gen_vv, gen_helper_vflogb_s)
-TRANS(vflogb_d, LSX, gen_vv, gen_helper_vflogb_d)
+TRANS(vflogb_s, LSX, gen_vv_ptr, gen_helper_vflogb_s)
+TRANS(vflogb_d, LSX, gen_vv_ptr, gen_helper_vflogb_d)
+TRANS(xvflogb_s, LASX, gen_xx_ptr, gen_helper_vflogb_s)
+TRANS(xvflogb_d, LASX, gen_xx_ptr, gen_helper_vflogb_d)
-TRANS(vfclass_s, LSX, gen_vv, gen_helper_vfclass_s)
-TRANS(vfclass_d, LSX, gen_vv, gen_helper_vfclass_d)
+TRANS(vfclass_s, LSX, gen_vv_ptr, gen_helper_vfclass_s)
+TRANS(vfclass_d, LSX, gen_vv_ptr, gen_helper_vfclass_d)
+TRANS(xvfclass_s, LASX, gen_xx_ptr, gen_helper_vfclass_s)
+TRANS(xvfclass_d, LASX, gen_xx_ptr, gen_helper_vfclass_d)
-TRANS(vfsqrt_s, LSX, gen_vv, gen_helper_vfsqrt_s)
-TRANS(vfsqrt_d, LSX, gen_vv, gen_helper_vfsqrt_d)
-TRANS(vfrecip_s, LSX, gen_vv, gen_helper_vfrecip_s)
-TRANS(vfrecip_d, LSX, gen_vv, gen_helper_vfrecip_d)
-TRANS(vfrsqrt_s, LSX, gen_vv, gen_helper_vfrsqrt_s)
-TRANS(vfrsqrt_d, LSX, gen_vv, gen_helper_vfrsqrt_d)
+TRANS(vfsqrt_s, LSX, gen_vv_ptr, gen_helper_vfsqrt_s)
+TRANS(vfsqrt_d, LSX, gen_vv_ptr, gen_helper_vfsqrt_d)
+TRANS(vfrecip_s, LSX, gen_vv_ptr, gen_helper_vfrecip_s)
+TRANS(vfrecip_d, LSX, gen_vv_ptr, gen_helper_vfrecip_d)
+TRANS(vfrsqrt_s, LSX, gen_vv_ptr, gen_helper_vfrsqrt_s)
+TRANS(vfrsqrt_d, LSX, gen_vv_ptr, gen_helper_vfrsqrt_d)
+TRANS(xvfsqrt_s, LASX, gen_xx_ptr, gen_helper_vfsqrt_s)
+TRANS(xvfsqrt_d, LASX, gen_xx_ptr, gen_helper_vfsqrt_d)
+TRANS(xvfrecip_s, LASX, gen_xx_ptr, gen_helper_vfrecip_s)
+TRANS(xvfrecip_d, LASX, gen_xx_ptr, gen_helper_vfrecip_d)
+TRANS(xvfrsqrt_s, LASX, gen_xx_ptr, gen_helper_vfrsqrt_s)
+TRANS(xvfrsqrt_d, LASX, gen_xx_ptr, gen_helper_vfrsqrt_d)
-TRANS(vfcvtl_s_h, LSX, gen_vv, gen_helper_vfcvtl_s_h)
-TRANS(vfcvth_s_h, LSX, gen_vv, gen_helper_vfcvth_s_h)
-TRANS(vfcvtl_d_s, LSX, gen_vv, gen_helper_vfcvtl_d_s)
-TRANS(vfcvth_d_s, LSX, gen_vv, gen_helper_vfcvth_d_s)
-TRANS(vfcvt_h_s, LSX, gen_vvv, gen_helper_vfcvt_h_s)
-TRANS(vfcvt_s_d, LSX, gen_vvv, gen_helper_vfcvt_s_d)
+TRANS(vfcvtl_s_h, LSX, gen_vv_ptr, gen_helper_vfcvtl_s_h)
+TRANS(vfcvth_s_h, LSX, gen_vv_ptr, gen_helper_vfcvth_s_h)
+TRANS(vfcvtl_d_s, LSX, gen_vv_ptr, gen_helper_vfcvtl_d_s)
+TRANS(vfcvth_d_s, LSX, gen_vv_ptr, gen_helper_vfcvth_d_s)
+TRANS(vfcvt_h_s, LSX, gen_vvv_ptr, gen_helper_vfcvt_h_s)
+TRANS(vfcvt_s_d, LSX, gen_vvv_ptr, gen_helper_vfcvt_s_d)
+TRANS(xvfcvtl_s_h, LASX, gen_xx_ptr, gen_helper_vfcvtl_s_h)
+TRANS(xvfcvth_s_h, LASX, gen_xx_ptr, gen_helper_vfcvth_s_h)
+TRANS(xvfcvtl_d_s, LASX, gen_xx_ptr, gen_helper_vfcvtl_d_s)
+TRANS(xvfcvth_d_s, LASX, gen_xx_ptr, gen_helper_vfcvth_d_s)
+TRANS(xvfcvt_h_s, LASX, gen_xxx_ptr, gen_helper_vfcvt_h_s)
+TRANS(xvfcvt_s_d, LASX, gen_xxx_ptr, gen_helper_vfcvt_s_d)
-TRANS(vfrintrne_s, LSX, gen_vv, gen_helper_vfrintrne_s)
-TRANS(vfrintrne_d, LSX, gen_vv, gen_helper_vfrintrne_d)
-TRANS(vfrintrz_s, LSX, gen_vv, gen_helper_vfrintrz_s)
-TRANS(vfrintrz_d, LSX, gen_vv, gen_helper_vfrintrz_d)
-TRANS(vfrintrp_s, LSX, gen_vv, gen_helper_vfrintrp_s)
-TRANS(vfrintrp_d, LSX, gen_vv, gen_helper_vfrintrp_d)
-TRANS(vfrintrm_s, LSX, gen_vv, gen_helper_vfrintrm_s)
-TRANS(vfrintrm_d, LSX, gen_vv, gen_helper_vfrintrm_d)
-TRANS(vfrint_s, LSX, gen_vv, gen_helper_vfrint_s)
-TRANS(vfrint_d, LSX, gen_vv, gen_helper_vfrint_d)
+TRANS(vfrintrne_s, LSX, gen_vv_ptr, gen_helper_vfrintrne_s)
+TRANS(vfrintrne_d, LSX, gen_vv_ptr, gen_helper_vfrintrne_d)
+TRANS(vfrintrz_s, LSX, gen_vv_ptr, gen_helper_vfrintrz_s)
+TRANS(vfrintrz_d, LSX, gen_vv_ptr, gen_helper_vfrintrz_d)
+TRANS(vfrintrp_s, LSX, gen_vv_ptr, gen_helper_vfrintrp_s)
+TRANS(vfrintrp_d, LSX, gen_vv_ptr, gen_helper_vfrintrp_d)
+TRANS(vfrintrm_s, LSX, gen_vv_ptr, gen_helper_vfrintrm_s)
+TRANS(vfrintrm_d, LSX, gen_vv_ptr, gen_helper_vfrintrm_d)
+TRANS(vfrint_s, LSX, gen_vv_ptr, gen_helper_vfrint_s)
+TRANS(vfrint_d, LSX, gen_vv_ptr, gen_helper_vfrint_d)
+TRANS(xvfrintrne_s, LASX, gen_xx_ptr, gen_helper_vfrintrne_s)
+TRANS(xvfrintrne_d, LASX, gen_xx_ptr, gen_helper_vfrintrne_d)
+TRANS(xvfrintrz_s, LASX, gen_xx_ptr, gen_helper_vfrintrz_s)
+TRANS(xvfrintrz_d, LASX, gen_xx_ptr, gen_helper_vfrintrz_d)
+TRANS(xvfrintrp_s, LASX, gen_xx_ptr, gen_helper_vfrintrp_s)
+TRANS(xvfrintrp_d, LASX, gen_xx_ptr, gen_helper_vfrintrp_d)
+TRANS(xvfrintrm_s, LASX, gen_xx_ptr, gen_helper_vfrintrm_s)
+TRANS(xvfrintrm_d, LASX, gen_xx_ptr, gen_helper_vfrintrm_d)
+TRANS(xvfrint_s, LASX, gen_xx_ptr, gen_helper_vfrint_s)
+TRANS(xvfrint_d, LASX, gen_xx_ptr, gen_helper_vfrint_d)
-TRANS(vftintrne_w_s, LSX, gen_vv, gen_helper_vftintrne_w_s)
-TRANS(vftintrne_l_d, LSX, gen_vv, gen_helper_vftintrne_l_d)
-TRANS(vftintrz_w_s, LSX, gen_vv, gen_helper_vftintrz_w_s)
-TRANS(vftintrz_l_d, LSX, gen_vv, gen_helper_vftintrz_l_d)
-TRANS(vftintrp_w_s, LSX, gen_vv, gen_helper_vftintrp_w_s)
-TRANS(vftintrp_l_d, LSX, gen_vv, gen_helper_vftintrp_l_d)
-TRANS(vftintrm_w_s, LSX, gen_vv, gen_helper_vftintrm_w_s)
-TRANS(vftintrm_l_d, LSX, gen_vv, gen_helper_vftintrm_l_d)
-TRANS(vftint_w_s, LSX, gen_vv, gen_helper_vftint_w_s)
-TRANS(vftint_l_d, LSX, gen_vv, gen_helper_vftint_l_d)
-TRANS(vftintrz_wu_s, LSX, gen_vv, gen_helper_vftintrz_wu_s)
-TRANS(vftintrz_lu_d, LSX, gen_vv, gen_helper_vftintrz_lu_d)
-TRANS(vftint_wu_s, LSX, gen_vv, gen_helper_vftint_wu_s)
-TRANS(vftint_lu_d, LSX, gen_vv, gen_helper_vftint_lu_d)
-TRANS(vftintrne_w_d, LSX, gen_vvv, gen_helper_vftintrne_w_d)
-TRANS(vftintrz_w_d, LSX, gen_vvv, gen_helper_vftintrz_w_d)
-TRANS(vftintrp_w_d, LSX, gen_vvv, gen_helper_vftintrp_w_d)
-TRANS(vftintrm_w_d, LSX, gen_vvv, gen_helper_vftintrm_w_d)
-TRANS(vftint_w_d, LSX, gen_vvv, gen_helper_vftint_w_d)
-TRANS(vftintrnel_l_s, LSX, gen_vv, gen_helper_vftintrnel_l_s)
-TRANS(vftintrneh_l_s, LSX, gen_vv, gen_helper_vftintrneh_l_s)
-TRANS(vftintrzl_l_s, LSX, gen_vv, gen_helper_vftintrzl_l_s)
-TRANS(vftintrzh_l_s, LSX, gen_vv, gen_helper_vftintrzh_l_s)
-TRANS(vftintrpl_l_s, LSX, gen_vv, gen_helper_vftintrpl_l_s)
-TRANS(vftintrph_l_s, LSX, gen_vv, gen_helper_vftintrph_l_s)
-TRANS(vftintrml_l_s, LSX, gen_vv, gen_helper_vftintrml_l_s)
-TRANS(vftintrmh_l_s, LSX, gen_vv, gen_helper_vftintrmh_l_s)
-TRANS(vftintl_l_s, LSX, gen_vv, gen_helper_vftintl_l_s)
-TRANS(vftinth_l_s, LSX, gen_vv, gen_helper_vftinth_l_s)
+TRANS(vftintrne_w_s, LSX, gen_vv_ptr, gen_helper_vftintrne_w_s)
+TRANS(vftintrne_l_d, LSX, gen_vv_ptr, gen_helper_vftintrne_l_d)
+TRANS(vftintrz_w_s, LSX, gen_vv_ptr, gen_helper_vftintrz_w_s)
+TRANS(vftintrz_l_d, LSX, gen_vv_ptr, gen_helper_vftintrz_l_d)
+TRANS(vftintrp_w_s, LSX, gen_vv_ptr, gen_helper_vftintrp_w_s)
+TRANS(vftintrp_l_d, LSX, gen_vv_ptr, gen_helper_vftintrp_l_d)
+TRANS(vftintrm_w_s, LSX, gen_vv_ptr, gen_helper_vftintrm_w_s)
+TRANS(vftintrm_l_d, LSX, gen_vv_ptr, gen_helper_vftintrm_l_d)
+TRANS(vftint_w_s, LSX, gen_vv_ptr, gen_helper_vftint_w_s)
+TRANS(vftint_l_d, LSX, gen_vv_ptr, gen_helper_vftint_l_d)
+TRANS(vftintrz_wu_s, LSX, gen_vv_ptr, gen_helper_vftintrz_wu_s)
+TRANS(vftintrz_lu_d, LSX, gen_vv_ptr, gen_helper_vftintrz_lu_d)
+TRANS(vftint_wu_s, LSX, gen_vv_ptr, gen_helper_vftint_wu_s)
+TRANS(vftint_lu_d, LSX, gen_vv_ptr, gen_helper_vftint_lu_d)
+TRANS(vftintrne_w_d, LSX, gen_vvv_ptr, gen_helper_vftintrne_w_d)
+TRANS(vftintrz_w_d, LSX, gen_vvv_ptr, gen_helper_vftintrz_w_d)
+TRANS(vftintrp_w_d, LSX, gen_vvv_ptr, gen_helper_vftintrp_w_d)
+TRANS(vftintrm_w_d, LSX, gen_vvv_ptr, gen_helper_vftintrm_w_d)
+TRANS(vftint_w_d, LSX, gen_vvv_ptr, gen_helper_vftint_w_d)
+TRANS(vftintrnel_l_s, LSX, gen_vv_ptr, gen_helper_vftintrnel_l_s)
+TRANS(vftintrneh_l_s, LSX, gen_vv_ptr, gen_helper_vftintrneh_l_s)
+TRANS(vftintrzl_l_s, LSX, gen_vv_ptr, gen_helper_vftintrzl_l_s)
+TRANS(vftintrzh_l_s, LSX, gen_vv_ptr, gen_helper_vftintrzh_l_s)
+TRANS(vftintrpl_l_s, LSX, gen_vv_ptr, gen_helper_vftintrpl_l_s)
+TRANS(vftintrph_l_s, LSX, gen_vv_ptr, gen_helper_vftintrph_l_s)
+TRANS(vftintrml_l_s, LSX, gen_vv_ptr, gen_helper_vftintrml_l_s)
+TRANS(vftintrmh_l_s, LSX, gen_vv_ptr, gen_helper_vftintrmh_l_s)
+TRANS(vftintl_l_s, LSX, gen_vv_ptr, gen_helper_vftintl_l_s)
+TRANS(vftinth_l_s, LSX, gen_vv_ptr, gen_helper_vftinth_l_s)
+TRANS(xvftintrne_w_s, LASX, gen_xx_ptr, gen_helper_vftintrne_w_s)
+TRANS(xvftintrne_l_d, LASX, gen_xx_ptr, gen_helper_vftintrne_l_d)
+TRANS(xvftintrz_w_s, LASX, gen_xx_ptr, gen_helper_vftintrz_w_s)
+TRANS(xvftintrz_l_d, LASX, gen_xx_ptr, gen_helper_vftintrz_l_d)
+TRANS(xvftintrp_w_s, LASX, gen_xx_ptr, gen_helper_vftintrp_w_s)
+TRANS(xvftintrp_l_d, LASX, gen_xx_ptr, gen_helper_vftintrp_l_d)
+TRANS(xvftintrm_w_s, LASX, gen_xx_ptr, gen_helper_vftintrm_w_s)
+TRANS(xvftintrm_l_d, LASX, gen_xx_ptr, gen_helper_vftintrm_l_d)
+TRANS(xvftint_w_s, LASX, gen_xx_ptr, gen_helper_vftint_w_s)
+TRANS(xvftint_l_d, LASX, gen_xx_ptr, gen_helper_vftint_l_d)
+TRANS(xvftintrz_wu_s, LASX, gen_xx_ptr, gen_helper_vftintrz_wu_s)
+TRANS(xvftintrz_lu_d, LASX, gen_xx_ptr, gen_helper_vftintrz_lu_d)
+TRANS(xvftint_wu_s, LASX, gen_xx_ptr, gen_helper_vftint_wu_s)
+TRANS(xvftint_lu_d, LASX, gen_xx_ptr, gen_helper_vftint_lu_d)
+TRANS(xvftintrne_w_d, LASX, gen_xxx_ptr, gen_helper_vftintrne_w_d)
+TRANS(xvftintrz_w_d, LASX, gen_xxx_ptr, gen_helper_vftintrz_w_d)
+TRANS(xvftintrp_w_d, LASX, gen_xxx_ptr, gen_helper_vftintrp_w_d)
+TRANS(xvftintrm_w_d, LASX, gen_xxx_ptr, gen_helper_vftintrm_w_d)
+TRANS(xvftint_w_d, LASX, gen_xxx_ptr, gen_helper_vftint_w_d)
+TRANS(xvftintrnel_l_s, LASX, gen_xx_ptr, gen_helper_vftintrnel_l_s)
+TRANS(xvftintrneh_l_s, LASX, gen_xx_ptr, gen_helper_vftintrneh_l_s)
+TRANS(xvftintrzl_l_s, LASX, gen_xx_ptr, gen_helper_vftintrzl_l_s)
+TRANS(xvftintrzh_l_s, LASX, gen_xx_ptr, gen_helper_vftintrzh_l_s)
+TRANS(xvftintrpl_l_s, LASX, gen_xx_ptr, gen_helper_vftintrpl_l_s)
+TRANS(xvftintrph_l_s, LASX, gen_xx_ptr, gen_helper_vftintrph_l_s)
+TRANS(xvftintrml_l_s, LASX, gen_xx_ptr, gen_helper_vftintrml_l_s)
+TRANS(xvftintrmh_l_s, LASX, gen_xx_ptr, gen_helper_vftintrmh_l_s)
+TRANS(xvftintl_l_s, LASX, gen_xx_ptr, gen_helper_vftintl_l_s)
+TRANS(xvftinth_l_s, LASX, gen_xx_ptr, gen_helper_vftinth_l_s)
-TRANS(vffint_s_w, LSX, gen_vv, gen_helper_vffint_s_w)
-TRANS(vffint_d_l, LSX, gen_vv, gen_helper_vffint_d_l)
-TRANS(vffint_s_wu, LSX, gen_vv, gen_helper_vffint_s_wu)
-TRANS(vffint_d_lu, LSX, gen_vv, gen_helper_vffint_d_lu)
-TRANS(vffintl_d_w, LSX, gen_vv, gen_helper_vffintl_d_w)
-TRANS(vffinth_d_w, LSX, gen_vv, gen_helper_vffinth_d_w)
-TRANS(vffint_s_l, LSX, gen_vvv, gen_helper_vffint_s_l)
+TRANS(vffint_s_w, LSX, gen_vv_ptr, gen_helper_vffint_s_w)
+TRANS(vffint_d_l, LSX, gen_vv_ptr, gen_helper_vffint_d_l)
+TRANS(vffint_s_wu, LSX, gen_vv_ptr, gen_helper_vffint_s_wu)
+TRANS(vffint_d_lu, LSX, gen_vv_ptr, gen_helper_vffint_d_lu)
+TRANS(vffintl_d_w, LSX, gen_vv_ptr, gen_helper_vffintl_d_w)
+TRANS(vffinth_d_w, LSX, gen_vv_ptr, gen_helper_vffinth_d_w)
+TRANS(vffint_s_l, LSX, gen_vvv_ptr, gen_helper_vffint_s_l)
+TRANS(xvffint_s_w, LASX, gen_xx_ptr, gen_helper_vffint_s_w)
+TRANS(xvffint_d_l, LASX, gen_xx_ptr, gen_helper_vffint_d_l)
+TRANS(xvffint_s_wu, LASX, gen_xx_ptr, gen_helper_vffint_s_wu)
+TRANS(xvffint_d_lu, LASX, gen_xx_ptr, gen_helper_vffint_d_lu)
+TRANS(xvffintl_d_w, LASX, gen_xx_ptr, gen_helper_vffintl_d_w)
+TRANS(xvffinth_d_w, LASX, gen_xx_ptr, gen_helper_vffinth_d_w)
+TRANS(xvffint_s_l, LASX, gen_xxx_ptr, gen_helper_vffint_s_l)
-static bool do_cmp(DisasContext *ctx, arg_vvv *a, MemOp mop, TCGCond cond)
+static bool do_cmp_vl(DisasContext *ctx, arg_vvv *a,
+ uint32_t oprsz, MemOp mop, TCGCond cond)
{
uint32_t vd_ofs, vj_ofs, vk_ofs;
- CHECK_SXE;
+ if (!check_vec(ctx, oprsz)) {
+ return true;
+ }
vd_ofs = vec_full_offset(a->vd);
vj_ofs = vec_full_offset(a->vj);
vk_ofs = vec_full_offset(a->vk);
- tcg_gen_gvec_cmp(cond, mop, vd_ofs, vj_ofs, vk_ofs, 16, ctx->vl/8);
+ tcg_gen_gvec_cmp(cond, mop, vd_ofs, vj_ofs, vk_ofs, oprsz, ctx->vl / 8);
return true;
}
-static void do_cmpi_vec(TCGCond cond,
- unsigned vece, TCGv_vec t, TCGv_vec a, int64_t imm)
+static bool do_cmp(DisasContext *ctx, arg_vvv *a,
+ MemOp mop, TCGCond cond)
{
- tcg_gen_cmp_vec(cond, vece, t, a, tcg_constant_vec_matching(t, vece, imm));
+ return do_cmp_vl(ctx, a, 16, mop, cond);
}
-static void gen_vseqi_s_vec(unsigned vece, TCGv_vec t, TCGv_vec a, int64_t imm)
+static bool do_xcmp(DisasContext *ctx, arg_vvv *a,
+ MemOp mop, TCGCond cond)
{
- do_cmpi_vec(TCG_COND_EQ, vece, t, a, imm);
+ return do_cmp_vl(ctx, a, 32, mop, cond);
}
-static void gen_vslei_s_vec(unsigned vece, TCGv_vec t, TCGv_vec a, int64_t imm)
+static bool do_cmpi_vl(DisasContext *ctx, arg_vv_i *a,
+ uint32_t oprsz, MemOp mop, TCGCond cond)
{
- do_cmpi_vec(TCG_COND_LE, vece, t, a, imm);
+ uint32_t vd_ofs, vj_ofs;
+
+ if (!check_vec(ctx, oprsz)) {
+ return true;
+ }
+
+ vd_ofs = vec_full_offset(a->vd);
+ vj_ofs = vec_full_offset(a->vj);
+
+ tcg_gen_gvec_cmpi(cond, mop, vd_ofs, vj_ofs, a->imm, oprsz, ctx->vl / 8);
+ return true;
}
-static void gen_vslti_s_vec(unsigned vece, TCGv_vec t, TCGv_vec a, int64_t imm)
+static bool do_cmpi(DisasContext *ctx, arg_vv_i *a,
+ MemOp mop, TCGCond cond)
{
- do_cmpi_vec(TCG_COND_LT, vece, t, a, imm);
+ return do_cmpi_vl(ctx, a, 16, mop, cond);
}
-static void gen_vslei_u_vec(unsigned vece, TCGv_vec t, TCGv_vec a, int64_t imm)
+static bool do_xcmpi(DisasContext *ctx, arg_vv_i *a,
+ MemOp mop, TCGCond cond)
{
- do_cmpi_vec(TCG_COND_LEU, vece, t, a, imm);
+ return do_cmpi_vl(ctx, a, 32, mop, cond);
}
-static void gen_vslti_u_vec(unsigned vece, TCGv_vec t, TCGv_vec a, int64_t imm)
-{
- do_cmpi_vec(TCG_COND_LTU, vece, t, a, imm);
-}
-
-#define DO_CMPI_S(NAME) \
-static bool do_## NAME ##_s(DisasContext *ctx, arg_vv_i *a, MemOp mop) \
-{ \
- uint32_t vd_ofs, vj_ofs; \
- \
- CHECK_SXE; \
- \
- static const TCGOpcode vecop_list[] = { \
- INDEX_op_cmp_vec, 0 \
- }; \
- static const GVecGen2i op[4] = { \
- { \
- .fniv = gen_## NAME ##_s_vec, \
- .fnoi = gen_helper_## NAME ##_b, \
- .opt_opc = vecop_list, \
- .vece = MO_8 \
- }, \
- { \
- .fniv = gen_## NAME ##_s_vec, \
- .fnoi = gen_helper_## NAME ##_h, \
- .opt_opc = vecop_list, \
- .vece = MO_16 \
- }, \
- { \
- .fniv = gen_## NAME ##_s_vec, \
- .fnoi = gen_helper_## NAME ##_w, \
- .opt_opc = vecop_list, \
- .vece = MO_32 \
- }, \
- { \
- .fniv = gen_## NAME ##_s_vec, \
- .fnoi = gen_helper_## NAME ##_d, \
- .opt_opc = vecop_list, \
- .vece = MO_64 \
- } \
- }; \
- \
- vd_ofs = vec_full_offset(a->vd); \
- vj_ofs = vec_full_offset(a->vj); \
- \
- tcg_gen_gvec_2i(vd_ofs, vj_ofs, 16, ctx->vl/8, a->imm, &op[mop]); \
- \
- return true; \
-}
-
-DO_CMPI_S(vseqi)
-DO_CMPI_S(vslei)
-DO_CMPI_S(vslti)
-
-#define DO_CMPI_U(NAME) \
-static bool do_## NAME ##_u(DisasContext *ctx, arg_vv_i *a, MemOp mop) \
-{ \
- uint32_t vd_ofs, vj_ofs; \
- \
- CHECK_SXE; \
- \
- static const TCGOpcode vecop_list[] = { \
- INDEX_op_cmp_vec, 0 \
- }; \
- static const GVecGen2i op[4] = { \
- { \
- .fniv = gen_## NAME ##_u_vec, \
- .fnoi = gen_helper_## NAME ##_bu, \
- .opt_opc = vecop_list, \
- .vece = MO_8 \
- }, \
- { \
- .fniv = gen_## NAME ##_u_vec, \
- .fnoi = gen_helper_## NAME ##_hu, \
- .opt_opc = vecop_list, \
- .vece = MO_16 \
- }, \
- { \
- .fniv = gen_## NAME ##_u_vec, \
- .fnoi = gen_helper_## NAME ##_wu, \
- .opt_opc = vecop_list, \
- .vece = MO_32 \
- }, \
- { \
- .fniv = gen_## NAME ##_u_vec, \
- .fnoi = gen_helper_## NAME ##_du, \
- .opt_opc = vecop_list, \
- .vece = MO_64 \
- } \
- }; \
- \
- vd_ofs = vec_full_offset(a->vd); \
- vj_ofs = vec_full_offset(a->vj); \
- \
- tcg_gen_gvec_2i(vd_ofs, vj_ofs, 16, ctx->vl/8, a->imm, &op[mop]); \
- \
- return true; \
-}
-
-DO_CMPI_U(vslei)
-DO_CMPI_U(vslti)
-
TRANS(vseq_b, LSX, do_cmp, MO_8, TCG_COND_EQ)
TRANS(vseq_h, LSX, do_cmp, MO_16, TCG_COND_EQ)
TRANS(vseq_w, LSX, do_cmp, MO_32, TCG_COND_EQ)
TRANS(vseq_d, LSX, do_cmp, MO_64, TCG_COND_EQ)
-TRANS(vseqi_b, LSX, do_vseqi_s, MO_8)
-TRANS(vseqi_h, LSX, do_vseqi_s, MO_16)
-TRANS(vseqi_w, LSX, do_vseqi_s, MO_32)
-TRANS(vseqi_d, LSX, do_vseqi_s, MO_64)
+TRANS(vseqi_b, LSX, do_cmpi, MO_8, TCG_COND_EQ)
+TRANS(vseqi_h, LSX, do_cmpi, MO_16, TCG_COND_EQ)
+TRANS(vseqi_w, LSX, do_cmpi, MO_32, TCG_COND_EQ)
+TRANS(vseqi_d, LSX, do_cmpi, MO_64, TCG_COND_EQ)
+TRANS(xvseq_b, LASX, do_xcmp, MO_8, TCG_COND_EQ)
+TRANS(xvseq_h, LASX, do_xcmp, MO_16, TCG_COND_EQ)
+TRANS(xvseq_w, LASX, do_xcmp, MO_32, TCG_COND_EQ)
+TRANS(xvseq_d, LASX, do_xcmp, MO_64, TCG_COND_EQ)
+TRANS(xvseqi_b, LASX, do_xcmpi, MO_8, TCG_COND_EQ)
+TRANS(xvseqi_h, LASX, do_xcmpi, MO_16, TCG_COND_EQ)
+TRANS(xvseqi_w, LASX, do_xcmpi, MO_32, TCG_COND_EQ)
+TRANS(xvseqi_d, LASX, do_xcmpi, MO_64, TCG_COND_EQ)
TRANS(vsle_b, LSX, do_cmp, MO_8, TCG_COND_LE)
TRANS(vsle_h, LSX, do_cmp, MO_16, TCG_COND_LE)
TRANS(vsle_w, LSX, do_cmp, MO_32, TCG_COND_LE)
TRANS(vsle_d, LSX, do_cmp, MO_64, TCG_COND_LE)
-TRANS(vslei_b, LSX, do_vslei_s, MO_8)
-TRANS(vslei_h, LSX, do_vslei_s, MO_16)
-TRANS(vslei_w, LSX, do_vslei_s, MO_32)
-TRANS(vslei_d, LSX, do_vslei_s, MO_64)
+TRANS(vslei_b, LSX, do_cmpi, MO_8, TCG_COND_LE)
+TRANS(vslei_h, LSX, do_cmpi, MO_16, TCG_COND_LE)
+TRANS(vslei_w, LSX, do_cmpi, MO_32, TCG_COND_LE)
+TRANS(vslei_d, LSX, do_cmpi, MO_64, TCG_COND_LE)
TRANS(vsle_bu, LSX, do_cmp, MO_8, TCG_COND_LEU)
TRANS(vsle_hu, LSX, do_cmp, MO_16, TCG_COND_LEU)
TRANS(vsle_wu, LSX, do_cmp, MO_32, TCG_COND_LEU)
TRANS(vsle_du, LSX, do_cmp, MO_64, TCG_COND_LEU)
-TRANS(vslei_bu, LSX, do_vslei_u, MO_8)
-TRANS(vslei_hu, LSX, do_vslei_u, MO_16)
-TRANS(vslei_wu, LSX, do_vslei_u, MO_32)
-TRANS(vslei_du, LSX, do_vslei_u, MO_64)
+TRANS(vslei_bu, LSX, do_cmpi, MO_8, TCG_COND_LEU)
+TRANS(vslei_hu, LSX, do_cmpi, MO_16, TCG_COND_LEU)
+TRANS(vslei_wu, LSX, do_cmpi, MO_32, TCG_COND_LEU)
+TRANS(vslei_du, LSX, do_cmpi, MO_64, TCG_COND_LEU)
+TRANS(xvsle_b, LASX, do_xcmp, MO_8, TCG_COND_LE)
+TRANS(xvsle_h, LASX, do_xcmp, MO_16, TCG_COND_LE)
+TRANS(xvsle_w, LASX, do_xcmp, MO_32, TCG_COND_LE)
+TRANS(xvsle_d, LASX, do_xcmp, MO_64, TCG_COND_LE)
+TRANS(xvslei_b, LASX, do_xcmpi, MO_8, TCG_COND_LE)
+TRANS(xvslei_h, LASX, do_xcmpi, MO_16, TCG_COND_LE)
+TRANS(xvslei_w, LASX, do_xcmpi, MO_32, TCG_COND_LE)
+TRANS(xvslei_d, LASX, do_xcmpi, MO_64, TCG_COND_LE)
+TRANS(xvsle_bu, LASX, do_xcmp, MO_8, TCG_COND_LEU)
+TRANS(xvsle_hu, LASX, do_xcmp, MO_16, TCG_COND_LEU)
+TRANS(xvsle_wu, LASX, do_xcmp, MO_32, TCG_COND_LEU)
+TRANS(xvsle_du, LASX, do_xcmp, MO_64, TCG_COND_LEU)
+TRANS(xvslei_bu, LASX, do_xcmpi, MO_8, TCG_COND_LEU)
+TRANS(xvslei_hu, LASX, do_xcmpi, MO_16, TCG_COND_LEU)
+TRANS(xvslei_wu, LASX, do_xcmpi, MO_32, TCG_COND_LEU)
+TRANS(xvslei_du, LASX, do_xcmpi, MO_64, TCG_COND_LEU)
TRANS(vslt_b, LSX, do_cmp, MO_8, TCG_COND_LT)
TRANS(vslt_h, LSX, do_cmp, MO_16, TCG_COND_LT)
TRANS(vslt_w, LSX, do_cmp, MO_32, TCG_COND_LT)
TRANS(vslt_d, LSX, do_cmp, MO_64, TCG_COND_LT)
-TRANS(vslti_b, LSX, do_vslti_s, MO_8)
-TRANS(vslti_h, LSX, do_vslti_s, MO_16)
-TRANS(vslti_w, LSX, do_vslti_s, MO_32)
-TRANS(vslti_d, LSX, do_vslti_s, MO_64)
+TRANS(vslti_b, LSX, do_cmpi, MO_8, TCG_COND_LT)
+TRANS(vslti_h, LSX, do_cmpi, MO_16, TCG_COND_LT)
+TRANS(vslti_w, LSX, do_cmpi, MO_32, TCG_COND_LT)
+TRANS(vslti_d, LSX, do_cmpi, MO_64, TCG_COND_LT)
TRANS(vslt_bu, LSX, do_cmp, MO_8, TCG_COND_LTU)
TRANS(vslt_hu, LSX, do_cmp, MO_16, TCG_COND_LTU)
TRANS(vslt_wu, LSX, do_cmp, MO_32, TCG_COND_LTU)
TRANS(vslt_du, LSX, do_cmp, MO_64, TCG_COND_LTU)
-TRANS(vslti_bu, LSX, do_vslti_u, MO_8)
-TRANS(vslti_hu, LSX, do_vslti_u, MO_16)
-TRANS(vslti_wu, LSX, do_vslti_u, MO_32)
-TRANS(vslti_du, LSX, do_vslti_u, MO_64)
+TRANS(vslti_bu, LSX, do_cmpi, MO_8, TCG_COND_LTU)
+TRANS(vslti_hu, LSX, do_cmpi, MO_16, TCG_COND_LTU)
+TRANS(vslti_wu, LSX, do_cmpi, MO_32, TCG_COND_LTU)
+TRANS(vslti_du, LSX, do_cmpi, MO_64, TCG_COND_LTU)
+TRANS(xvslt_b, LASX, do_xcmp, MO_8, TCG_COND_LT)
+TRANS(xvslt_h, LASX, do_xcmp, MO_16, TCG_COND_LT)
+TRANS(xvslt_w, LASX, do_xcmp, MO_32, TCG_COND_LT)
+TRANS(xvslt_d, LASX, do_xcmp, MO_64, TCG_COND_LT)
+TRANS(xvslti_b, LASX, do_xcmpi, MO_8, TCG_COND_LT)
+TRANS(xvslti_h, LASX, do_xcmpi, MO_16, TCG_COND_LT)
+TRANS(xvslti_w, LASX, do_xcmpi, MO_32, TCG_COND_LT)
+TRANS(xvslti_d, LASX, do_xcmpi, MO_64, TCG_COND_LT)
+TRANS(xvslt_bu, LASX, do_xcmp, MO_8, TCG_COND_LTU)
+TRANS(xvslt_hu, LASX, do_xcmp, MO_16, TCG_COND_LTU)
+TRANS(xvslt_wu, LASX, do_xcmp, MO_32, TCG_COND_LTU)
+TRANS(xvslt_du, LASX, do_xcmp, MO_64, TCG_COND_LTU)
+TRANS(xvslti_bu, LASX, do_xcmpi, MO_8, TCG_COND_LTU)
+TRANS(xvslti_hu, LASX, do_xcmpi, MO_16, TCG_COND_LTU)
+TRANS(xvslti_wu, LASX, do_xcmpi, MO_32, TCG_COND_LTU)
+TRANS(xvslti_du, LASX, do_xcmpi, MO_64, TCG_COND_LTU)
-static bool trans_vfcmp_cond_s(DisasContext *ctx, arg_vvv_fcond *a)
+static bool do_vfcmp_cond_s(DisasContext *ctx, arg_vvv_fcond *a, uint32_t sz)
{
uint32_t flags;
- void (*fn)(TCGv_env, TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32);
+ void (*fn)(TCGv_env, TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32);
TCGv_i32 vd = tcg_constant_i32(a->vd);
TCGv_i32 vj = tcg_constant_i32(a->vj);
TCGv_i32 vk = tcg_constant_i32(a->vk);
+ TCGv_i32 oprsz = tcg_constant_i32(sz);
- if (!avail_LSX(ctx)) {
- return false;
+ if (!check_vec(ctx, sz)) {
+ return true;
}
- CHECK_SXE;
-
fn = (a->fcond & 1 ? gen_helper_vfcmp_s_s : gen_helper_vfcmp_c_s);
flags = get_fcmp_flags(a->fcond >> 1);
- fn(cpu_env, vd, vj, vk, tcg_constant_i32(flags));
+ fn(cpu_env, oprsz, vd, vj, vk, tcg_constant_i32(flags));
return true;
}
-static bool trans_vfcmp_cond_d(DisasContext *ctx, arg_vvv_fcond *a)
+static bool do_vfcmp_cond_d(DisasContext *ctx, arg_vvv_fcond *a, uint32_t sz)
{
uint32_t flags;
- void (*fn)(TCGv_env, TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32);
+ void (*fn)(TCGv_env, TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32);
TCGv_i32 vd = tcg_constant_i32(a->vd);
TCGv_i32 vj = tcg_constant_i32(a->vj);
TCGv_i32 vk = tcg_constant_i32(a->vk);
+ TCGv_i32 oprsz = tcg_constant_i32(sz);
- if (!avail_LSX(ctx)) {
- return false;
+ if (!check_vec(ctx, sz)) {
+ return true;
}
- CHECK_SXE;
-
fn = (a->fcond & 1 ? gen_helper_vfcmp_s_d : gen_helper_vfcmp_c_d);
flags = get_fcmp_flags(a->fcond >> 1);
- fn(cpu_env, vd, vj, vk, tcg_constant_i32(flags));
+ fn(cpu_env, oprsz, vd, vj, vk, tcg_constant_i32(flags));
return true;
}
-static bool trans_vbitsel_v(DisasContext *ctx, arg_vvvv *a)
-{
- if (!avail_LSX(ctx)) {
- return false;
- }
+TRANS(vfcmp_cond_s, LSX, do_vfcmp_cond_s, 16)
+TRANS(vfcmp_cond_d, LSX, do_vfcmp_cond_d, 16)
+TRANS(xvfcmp_cond_s, LASX, do_vfcmp_cond_s, 32)
+TRANS(xvfcmp_cond_d, LASX, do_vfcmp_cond_d, 32)
- CHECK_SXE;
+static bool do_vbitsel_v(DisasContext *ctx, arg_vvvv *a, uint32_t oprsz)
+{
+ if (!check_vec(ctx, oprsz)) {
+ return true;
+ }
tcg_gen_gvec_bitsel(MO_64, vec_full_offset(a->vd), vec_full_offset(a->va),
vec_full_offset(a->vk), vec_full_offset(a->vj),
- 16, ctx->vl/8);
+ oprsz, ctx->vl / 8);
return true;
}
+TRANS(vbitsel_v, LSX, do_vbitsel_v, 16)
+TRANS(xvbitsel_v, LASX, do_vbitsel_v, 32)
+
static void gen_vbitseli(unsigned vece, TCGv_vec a, TCGv_vec b, int64_t imm)
{
tcg_gen_bitsel_vec(vece, a, a, tcg_constant_vec_matching(a, vece, imm), b);
}
-static bool trans_vbitseli_b(DisasContext *ctx, arg_vv_i *a)
+static bool do_vbitseli_b(DisasContext *ctx, arg_vv_i *a, uint32_t oprsz)
{
static const GVecGen2i op = {
.fniv = gen_vbitseli,
@@ -3957,17 +4738,18 @@
.load_dest = true
};
- if (!avail_LSX(ctx)) {
- return false;
+ if (!check_vec(ctx, oprsz)) {
+ return true;
}
- CHECK_SXE;
-
tcg_gen_gvec_2i(vec_full_offset(a->vd), vec_full_offset(a->vj),
- 16, ctx->vl/8, a->imm, &op);
+ oprsz, ctx->vl / 8, a->imm , &op);
return true;
}
+TRANS(vbitseli_b, LSX, do_vbitseli_b, 16)
+TRANS(xvbitseli_b, LASX, do_vbitseli_b, 32)
+
#define VSET(NAME, COND) \
static bool trans_## NAME (DisasContext *ctx, arg_cv *a) \
{ \
@@ -3984,7 +4766,10 @@
return false; \
} \
\
- CHECK_SXE; \
+ if (!check_vec(ctx, 16)) { \
+ return true; \
+ } \
+ \
tcg_gen_or_i64(t1, al, ah); \
tcg_gen_setcondi_i64(COND, t1, t1, 0); \
tcg_gen_st8_tl(t1, cpu_env, offsetof(CPULoongArchState, cf[a->cd & 0x7])); \
@@ -4004,193 +4789,156 @@
TRANS(vsetallnez_w, LSX, gen_cv, gen_helper_vsetallnez_w)
TRANS(vsetallnez_d, LSX, gen_cv, gen_helper_vsetallnez_d)
-static bool trans_vinsgr2vr_b(DisasContext *ctx, arg_vr_i *a)
+#define XVSET(NAME, COND) \
+static bool trans_## NAME(DisasContext *ctx, arg_cv * a) \
+{ \
+ TCGv_i64 t1, t2, d[4]; \
+ \
+ d[0] = tcg_temp_new_i64(); \
+ d[1] = tcg_temp_new_i64(); \
+ d[2] = tcg_temp_new_i64(); \
+ d[3] = tcg_temp_new_i64(); \
+ t1 = tcg_temp_new_i64(); \
+ t2 = tcg_temp_new_i64(); \
+ \
+ get_vreg64(d[0], a->vj, 0); \
+ get_vreg64(d[1], a->vj, 1); \
+ get_vreg64(d[2], a->vj, 2); \
+ get_vreg64(d[3], a->vj, 3); \
+ \
+ if (!avail_LASX(ctx)) { \
+ return false; \
+ } \
+ \
+ if (!check_vec(ctx, 32)) { \
+ return true; \
+ } \
+ \
+ tcg_gen_or_i64(t1, d[0], d[1]); \
+ tcg_gen_or_i64(t2, d[2], d[3]); \
+ tcg_gen_or_i64(t1, t2, t1); \
+ tcg_gen_setcondi_i64(COND, t1, t1, 0); \
+ tcg_gen_st8_tl(t1, cpu_env, offsetof(CPULoongArchState, cf[a->cd & 0x7])); \
+ \
+ return true; \
+}
+
+XVSET(xvseteqz_v, TCG_COND_EQ)
+XVSET(xvsetnez_v, TCG_COND_NE)
+
+TRANS(xvsetanyeqz_b, LASX, gen_cx, gen_helper_vsetanyeqz_b)
+TRANS(xvsetanyeqz_h, LASX, gen_cx, gen_helper_vsetanyeqz_h)
+TRANS(xvsetanyeqz_w, LASX, gen_cx, gen_helper_vsetanyeqz_w)
+TRANS(xvsetanyeqz_d, LASX, gen_cx, gen_helper_vsetanyeqz_d)
+TRANS(xvsetallnez_b, LASX, gen_cx, gen_helper_vsetallnez_b)
+TRANS(xvsetallnez_h, LASX, gen_cx, gen_helper_vsetallnez_h)
+TRANS(xvsetallnez_w, LASX, gen_cx, gen_helper_vsetallnez_w)
+TRANS(xvsetallnez_d, LASX, gen_cx, gen_helper_vsetallnez_d)
+
+static bool gen_g2v_vl(DisasContext *ctx, arg_vr_i *a, uint32_t oprsz, MemOp mop,
+ void (*func)(TCGv, TCGv_ptr, tcg_target_long))
{
TCGv src = gpr_src(ctx, a->rj, EXT_NONE);
- if (!avail_LSX(ctx)) {
- return false;
+ if (!check_vec(ctx, oprsz)) {
+ return true;
}
- CHECK_SXE;
- tcg_gen_st8_i64(src, cpu_env,
- offsetof(CPULoongArchState, fpr[a->vd].vreg.B(a->imm)));
+ func(src, cpu_env, vec_reg_offset(a->vd, a->imm, mop));
+
return true;
}
-static bool trans_vinsgr2vr_h(DisasContext *ctx, arg_vr_i *a)
+static bool gen_g2v(DisasContext *ctx, arg_vr_i *a, MemOp mop,
+ void (*func)(TCGv, TCGv_ptr, tcg_target_long))
+{
+ return gen_g2v_vl(ctx, a, 16, mop, func);
+}
+
+static bool gen_g2x(DisasContext *ctx, arg_vr_i *a, MemOp mop,
+ void (*func)(TCGv, TCGv_ptr, tcg_target_long))
+{
+ return gen_g2v_vl(ctx, a, 32, mop, func);
+}
+
+TRANS(vinsgr2vr_b, LSX, gen_g2v, MO_8, tcg_gen_st8_i64)
+TRANS(vinsgr2vr_h, LSX, gen_g2v, MO_16, tcg_gen_st16_i64)
+TRANS(vinsgr2vr_w, LSX, gen_g2v, MO_32, tcg_gen_st32_i64)
+TRANS(vinsgr2vr_d, LSX, gen_g2v, MO_64, tcg_gen_st_i64)
+TRANS(xvinsgr2vr_w, LASX, gen_g2x, MO_32, tcg_gen_st32_i64)
+TRANS(xvinsgr2vr_d, LASX, gen_g2x, MO_64, tcg_gen_st_i64)
+
+static bool gen_v2g_vl(DisasContext *ctx, arg_rv_i *a, uint32_t oprsz, MemOp mop,
+ void (*func)(TCGv, TCGv_ptr, tcg_target_long))
+{
+ TCGv dst = gpr_dst(ctx, a->rd, EXT_NONE);
+
+ if (!check_vec(ctx, oprsz)) {
+ return true;
+ }
+
+ func(dst, cpu_env, vec_reg_offset(a->vj, a->imm, mop));
+
+ return true;
+}
+
+static bool gen_v2g(DisasContext *ctx, arg_rv_i *a, MemOp mop,
+ void (*func)(TCGv, TCGv_ptr, tcg_target_long))
+{
+ return gen_v2g_vl(ctx, a, 16, mop, func);
+}
+
+static bool gen_x2g(DisasContext *ctx, arg_rv_i *a, MemOp mop,
+ void (*func)(TCGv, TCGv_ptr, tcg_target_long))
+{
+ return gen_v2g_vl(ctx, a, 32, mop, func);
+}
+
+TRANS(vpickve2gr_b, LSX, gen_v2g, MO_8, tcg_gen_ld8s_i64)
+TRANS(vpickve2gr_h, LSX, gen_v2g, MO_16, tcg_gen_ld16s_i64)
+TRANS(vpickve2gr_w, LSX, gen_v2g, MO_32, tcg_gen_ld32s_i64)
+TRANS(vpickve2gr_d, LSX, gen_v2g, MO_64, tcg_gen_ld_i64)
+TRANS(vpickve2gr_bu, LSX, gen_v2g, MO_8, tcg_gen_ld8u_i64)
+TRANS(vpickve2gr_hu, LSX, gen_v2g, MO_16, tcg_gen_ld16u_i64)
+TRANS(vpickve2gr_wu, LSX, gen_v2g, MO_32, tcg_gen_ld32u_i64)
+TRANS(vpickve2gr_du, LSX, gen_v2g, MO_64, tcg_gen_ld_i64)
+TRANS(xvpickve2gr_w, LASX, gen_x2g, MO_32, tcg_gen_ld32s_i64)
+TRANS(xvpickve2gr_d, LASX, gen_x2g, MO_64, tcg_gen_ld_i64)
+TRANS(xvpickve2gr_wu, LASX, gen_x2g, MO_32, tcg_gen_ld32u_i64)
+TRANS(xvpickve2gr_du, LASX, gen_x2g, MO_64, tcg_gen_ld_i64)
+
+static bool gvec_dup_vl(DisasContext *ctx, arg_vr *a,
+ uint32_t oprsz, MemOp mop)
{
TCGv src = gpr_src(ctx, a->rj, EXT_NONE);
- if (!avail_LSX(ctx)) {
- return false;
+ if (!check_vec(ctx, oprsz)) {
+ return true;
}
- CHECK_SXE;
- tcg_gen_st16_i64(src, cpu_env,
- offsetof(CPULoongArchState, fpr[a->vd].vreg.H(a->imm)));
- return true;
-}
-
-static bool trans_vinsgr2vr_w(DisasContext *ctx, arg_vr_i *a)
-{
- TCGv src = gpr_src(ctx, a->rj, EXT_NONE);
-
- if (!avail_LSX(ctx)) {
- return false;
- }
-
- CHECK_SXE;
- tcg_gen_st32_i64(src, cpu_env,
- offsetof(CPULoongArchState, fpr[a->vd].vreg.W(a->imm)));
- return true;
-}
-
-static bool trans_vinsgr2vr_d(DisasContext *ctx, arg_vr_i *a)
-{
- TCGv src = gpr_src(ctx, a->rj, EXT_NONE);
-
- if (!avail_LSX(ctx)) {
- return false;
- }
-
- CHECK_SXE;
- tcg_gen_st_i64(src, cpu_env,
- offsetof(CPULoongArchState, fpr[a->vd].vreg.D(a->imm)));
- return true;
-}
-
-static bool trans_vpickve2gr_b(DisasContext *ctx, arg_rv_i *a)
-{
- TCGv dst = gpr_dst(ctx, a->rd, EXT_NONE);
-
- if (!avail_LSX(ctx)) {
- return false;
- }
-
- CHECK_SXE;
- tcg_gen_ld8s_i64(dst, cpu_env,
- offsetof(CPULoongArchState, fpr[a->vj].vreg.B(a->imm)));
- return true;
-}
-
-static bool trans_vpickve2gr_h(DisasContext *ctx, arg_rv_i *a)
-{
- TCGv dst = gpr_dst(ctx, a->rd, EXT_NONE);
-
- if (!avail_LSX(ctx)) {
- return false;
- }
-
- CHECK_SXE;
- tcg_gen_ld16s_i64(dst, cpu_env,
- offsetof(CPULoongArchState, fpr[a->vj].vreg.H(a->imm)));
- return true;
-}
-
-static bool trans_vpickve2gr_w(DisasContext *ctx, arg_rv_i *a)
-{
- TCGv dst = gpr_dst(ctx, a->rd, EXT_NONE);
-
- if (!avail_LSX(ctx)) {
- return false;
- }
-
- CHECK_SXE;
- tcg_gen_ld32s_i64(dst, cpu_env,
- offsetof(CPULoongArchState, fpr[a->vj].vreg.W(a->imm)));
- return true;
-}
-
-static bool trans_vpickve2gr_d(DisasContext *ctx, arg_rv_i *a)
-{
- TCGv dst = gpr_dst(ctx, a->rd, EXT_NONE);
-
- if (!avail_LSX(ctx)) {
- return false;
- }
-
- CHECK_SXE;
- tcg_gen_ld_i64(dst, cpu_env,
- offsetof(CPULoongArchState, fpr[a->vj].vreg.D(a->imm)));
- return true;
-}
-
-static bool trans_vpickve2gr_bu(DisasContext *ctx, arg_rv_i *a)
-{
- TCGv dst = gpr_dst(ctx, a->rd, EXT_NONE);
-
- if (!avail_LSX(ctx)) {
- return false;
- }
-
- CHECK_SXE;
- tcg_gen_ld8u_i64(dst, cpu_env,
- offsetof(CPULoongArchState, fpr[a->vj].vreg.B(a->imm)));
- return true;
-}
-
-static bool trans_vpickve2gr_hu(DisasContext *ctx, arg_rv_i *a)
-{
- TCGv dst = gpr_dst(ctx, a->rd, EXT_NONE);
-
- if (!avail_LSX(ctx)) {
- return false;
- }
-
- CHECK_SXE;
- tcg_gen_ld16u_i64(dst, cpu_env,
- offsetof(CPULoongArchState, fpr[a->vj].vreg.H(a->imm)));
- return true;
-}
-
-static bool trans_vpickve2gr_wu(DisasContext *ctx, arg_rv_i *a)
-{
- TCGv dst = gpr_dst(ctx, a->rd, EXT_NONE);
-
- if (!avail_LSX(ctx)) {
- return false;
- }
-
- CHECK_SXE;
- tcg_gen_ld32u_i64(dst, cpu_env,
- offsetof(CPULoongArchState, fpr[a->vj].vreg.W(a->imm)));
- return true;
-}
-
-static bool trans_vpickve2gr_du(DisasContext *ctx, arg_rv_i *a)
-{
- TCGv dst = gpr_dst(ctx, a->rd, EXT_NONE);
-
- if (!avail_LSX(ctx)) {
- return false;
- }
-
- CHECK_SXE;
- tcg_gen_ld_i64(dst, cpu_env,
- offsetof(CPULoongArchState, fpr[a->vj].vreg.D(a->imm)));
+ tcg_gen_gvec_dup_i64(mop, vec_full_offset(a->vd),
+ oprsz, ctx->vl/8, src);
return true;
}
static bool gvec_dup(DisasContext *ctx, arg_vr *a, MemOp mop)
{
- TCGv src = gpr_src(ctx, a->rj, EXT_NONE);
+ return gvec_dup_vl(ctx, a, 16, mop);
+}
- if (!avail_LSX(ctx)) {
- return false;
- }
-
- CHECK_SXE;
-
- tcg_gen_gvec_dup_i64(mop, vec_full_offset(a->vd),
- 16, ctx->vl/8, src);
- return true;
+static bool gvec_dupx(DisasContext *ctx, arg_vr *a, MemOp mop)
+{
+ return gvec_dup_vl(ctx, a, 32, mop);
}
TRANS(vreplgr2vr_b, LSX, gvec_dup, MO_8)
TRANS(vreplgr2vr_h, LSX, gvec_dup, MO_16)
TRANS(vreplgr2vr_w, LSX, gvec_dup, MO_32)
TRANS(vreplgr2vr_d, LSX, gvec_dup, MO_64)
+TRANS(xvreplgr2vr_b, LASX, gvec_dupx, MO_8)
+TRANS(xvreplgr2vr_h, LASX, gvec_dupx, MO_16)
+TRANS(xvreplgr2vr_w, LASX, gvec_dupx, MO_32)
+TRANS(xvreplgr2vr_d, LASX, gvec_dupx, MO_64)
static bool trans_vreplvei_b(DisasContext *ctx, arg_vv_i *a)
{
@@ -4198,7 +4946,10 @@
return false;
}
- CHECK_SXE;
+ if (!check_vec(ctx, 16)) {
+ return true;
+ }
+
tcg_gen_gvec_dup_mem(MO_8,vec_full_offset(a->vd),
offsetof(CPULoongArchState,
fpr[a->vj].vreg.B((a->imm))),
@@ -4212,7 +4963,10 @@
return false;
}
- CHECK_SXE;
+ if (!check_vec(ctx, 16)) {
+ return true;
+ }
+
tcg_gen_gvec_dup_mem(MO_16, vec_full_offset(a->vd),
offsetof(CPULoongArchState,
fpr[a->vj].vreg.H((a->imm))),
@@ -4225,7 +4979,10 @@
return false;
}
- CHECK_SXE;
+ if (!check_vec(ctx, 16)) {
+ return true;
+ }
+
tcg_gen_gvec_dup_mem(MO_32, vec_full_offset(a->vd),
offsetof(CPULoongArchState,
fpr[a->vj].vreg.W((a->imm))),
@@ -4238,7 +4995,10 @@
return false;
}
- CHECK_SXE;
+ if (!check_vec(ctx, 16)) {
+ return true;
+ }
+
tcg_gen_gvec_dup_mem(MO_64, vec_full_offset(a->vd),
offsetof(CPULoongArchState,
fpr[a->vj].vreg.D((a->imm))),
@@ -4246,106 +5006,169 @@
return true;
}
-static bool gen_vreplve(DisasContext *ctx, arg_vvr *a, int vece, int bit,
- void (*func)(TCGv_i64, TCGv_ptr, tcg_target_long))
+static bool gen_vreplve_vl(DisasContext *ctx, arg_vvr *a,
+ uint32_t oprsz, int vece, int bit,
+ void (*func)(TCGv_i64, TCGv_ptr, tcg_target_long))
{
+ int i;
TCGv_i64 t0 = tcg_temp_new_i64();
TCGv_ptr t1 = tcg_temp_new_ptr();
TCGv_i64 t2 = tcg_temp_new_i64();
- if (!avail_LSX(ctx)) {
- return false;
+ if (!check_vec(ctx, oprsz)) {
+ return true;
}
- CHECK_SXE;
-
- tcg_gen_andi_i64(t0, gpr_src(ctx, a->rk, EXT_NONE), (LSX_LEN/bit) -1);
+ tcg_gen_andi_i64(t0, gpr_src(ctx, a->rk, EXT_NONE), (LSX_LEN / bit) - 1);
tcg_gen_shli_i64(t0, t0, vece);
if (HOST_BIG_ENDIAN) {
- tcg_gen_xori_i64(t0, t0, vece << ((LSX_LEN/bit) -1));
+ tcg_gen_xori_i64(t0, t0, vece << ((LSX_LEN / bit) - 1));
}
tcg_gen_trunc_i64_ptr(t1, t0);
tcg_gen_add_ptr(t1, t1, cpu_env);
- func(t2, t1, vec_full_offset(a->vj));
- tcg_gen_gvec_dup_i64(vece, vec_full_offset(a->vd), 16, ctx->vl/8, t2);
+
+ for (i = 0; i < oprsz; i += 16) {
+ func(t2, t1, vec_full_offset(a->vj) + i);
+ tcg_gen_gvec_dup_i64(vece, vec_full_offset(a->vd) + i, 16, 16, t2);
+ }
return true;
}
+static bool gen_vreplve(DisasContext *ctx, arg_vvr *a, int vece, int bit,
+ void (*func)(TCGv_i64, TCGv_ptr, tcg_target_long))
+{
+ return gen_vreplve_vl(ctx, a, 16, vece, bit, func);
+}
+
+static bool gen_xvreplve(DisasContext *ctx, arg_vvr *a, int vece, int bit,
+ void (*func)(TCGv_i64, TCGv_ptr, tcg_target_long))
+{
+ return gen_vreplve_vl(ctx, a, 32, vece, bit, func);
+}
+
TRANS(vreplve_b, LSX, gen_vreplve, MO_8, 8, tcg_gen_ld8u_i64)
TRANS(vreplve_h, LSX, gen_vreplve, MO_16, 16, tcg_gen_ld16u_i64)
TRANS(vreplve_w, LSX, gen_vreplve, MO_32, 32, tcg_gen_ld32u_i64)
TRANS(vreplve_d, LSX, gen_vreplve, MO_64, 64, tcg_gen_ld_i64)
+TRANS(xvreplve_b, LASX, gen_xvreplve, MO_8, 8, tcg_gen_ld8u_i64)
+TRANS(xvreplve_h, LASX, gen_xvreplve, MO_16, 16, tcg_gen_ld16u_i64)
+TRANS(xvreplve_w, LASX, gen_xvreplve, MO_32, 32, tcg_gen_ld32u_i64)
+TRANS(xvreplve_d, LASX, gen_xvreplve, MO_64, 64, tcg_gen_ld_i64)
-static bool trans_vbsll_v(DisasContext *ctx, arg_vv_i *a)
+static bool gen_xvrepl128(DisasContext *ctx, arg_vv_i *a, MemOp mop)
{
- int ofs;
- TCGv_i64 desthigh, destlow, high, low;
+ int i;
- if (!avail_LSX(ctx)) {
- return false;
+ if (!check_vec(ctx, 32)) {
+ return true;
}
- CHECK_SXE;
+ for (i = 0; i < 32; i += 16) {
+ tcg_gen_gvec_dup_mem(mop, vec_full_offset(a->vd) + i,
+ vec_reg_offset(a->vj, a->imm, mop) + i, 16, 16);
- desthigh = tcg_temp_new_i64();
- destlow = tcg_temp_new_i64();
- high = tcg_temp_new_i64();
- low = tcg_temp_new_i64();
+ }
+ return true;
+}
- get_vreg64(low, a->vj, 0);
+TRANS(xvrepl128vei_b, LASX, gen_xvrepl128, MO_8)
+TRANS(xvrepl128vei_h, LASX, gen_xvrepl128, MO_16)
+TRANS(xvrepl128vei_w, LASX, gen_xvrepl128, MO_32)
+TRANS(xvrepl128vei_d, LASX, gen_xvrepl128, MO_64)
- ofs = ((a->imm) & 0xf) * 8;
- if (ofs < 64) {
- get_vreg64(high, a->vj, 1);
- tcg_gen_extract2_i64(desthigh, low, high, 64 - ofs);
- tcg_gen_shli_i64(destlow, low, ofs);
- } else {
- tcg_gen_shli_i64(desthigh, low, ofs - 64);
- destlow = tcg_constant_i64(0);
+static bool gen_xvreplve0(DisasContext *ctx, arg_vv *a, MemOp mop)
+{
+ if (!check_vec(ctx, 32)) {
+ return true;
}
- set_vreg64(desthigh, a->vd, 1);
- set_vreg64(destlow, a->vd, 0);
+ tcg_gen_gvec_dup_mem(mop, vec_full_offset(a->vd),
+ vec_full_offset(a->vj), 32, 32);
+ return true;
+}
+
+TRANS(xvreplve0_b, LASX, gen_xvreplve0, MO_8)
+TRANS(xvreplve0_h, LASX, gen_xvreplve0, MO_16)
+TRANS(xvreplve0_w, LASX, gen_xvreplve0, MO_32)
+TRANS(xvreplve0_d, LASX, gen_xvreplve0, MO_64)
+TRANS(xvreplve0_q, LASX, gen_xvreplve0, MO_128)
+
+TRANS(xvinsve0_w, LASX, gen_xx_i, gen_helper_xvinsve0_w)
+TRANS(xvinsve0_d, LASX, gen_xx_i, gen_helper_xvinsve0_d)
+
+TRANS(xvpickve_w, LASX, gen_xx_i, gen_helper_xvpickve_w)
+TRANS(xvpickve_d, LASX, gen_xx_i, gen_helper_xvpickve_d)
+
+static bool do_vbsll_v(DisasContext *ctx, arg_vv_i *a, uint32_t oprsz)
+{
+ int i, ofs;
+
+ if (!check_vec(ctx, oprsz)) {
+ return true;
+ }
+
+ for (i = 0; i < oprsz / 16; i++) {
+ TCGv desthigh = tcg_temp_new_i64();
+ TCGv destlow = tcg_temp_new_i64();
+ TCGv high = tcg_temp_new_i64();
+ TCGv low = tcg_temp_new_i64();
+
+ get_vreg64(low, a->vj, 2 * i);
+
+ ofs = ((a->imm) & 0xf) * 8;
+ if (ofs < 64) {
+ get_vreg64(high, a->vj, 2 * i + 1);
+ tcg_gen_extract2_i64(desthigh, low, high, 64 - ofs);
+ tcg_gen_shli_i64(destlow, low, ofs);
+ } else {
+ tcg_gen_shli_i64(desthigh, low, ofs - 64);
+ destlow = tcg_constant_i64(0);
+ }
+ set_vreg64(desthigh, a->vd, 2 * i + 1);
+ set_vreg64(destlow, a->vd, 2 * i);
+ }
return true;
}
-static bool trans_vbsrl_v(DisasContext *ctx, arg_vv_i *a)
+static bool do_vbsrl_v(DisasContext *ctx, arg_vv_i *a, uint32_t oprsz)
{
- TCGv_i64 desthigh, destlow, high, low;
- int ofs;
+ int i, ofs;
- if (!avail_LSX(ctx)) {
- return false;
+ if (!check_vec(ctx, 32)) {
+ return true;
}
- CHECK_SXE;
+ for (i = 0; i < oprsz / 16; i++) {
+ TCGv desthigh = tcg_temp_new_i64();
+ TCGv destlow = tcg_temp_new_i64();
+ TCGv high = tcg_temp_new_i64();
+ TCGv low = tcg_temp_new_i64();
+ get_vreg64(high, a->vj, 2 * i + 1);
- desthigh = tcg_temp_new_i64();
- destlow = tcg_temp_new_i64();
- high = tcg_temp_new_i64();
- low = tcg_temp_new_i64();
-
- get_vreg64(high, a->vj, 1);
-
- ofs = ((a->imm) & 0xf) * 8;
- if (ofs < 64) {
- get_vreg64(low, a->vj, 0);
- tcg_gen_extract2_i64(destlow, low, high, ofs);
- tcg_gen_shri_i64(desthigh, high, ofs);
- } else {
- tcg_gen_shri_i64(destlow, high, ofs - 64);
- desthigh = tcg_constant_i64(0);
+ ofs = ((a->imm) & 0xf) * 8;
+ if (ofs < 64) {
+ get_vreg64(low, a->vj, 2 * i);
+ tcg_gen_extract2_i64(destlow, low, high, ofs);
+ tcg_gen_shri_i64(desthigh, high, ofs);
+ } else {
+ tcg_gen_shri_i64(destlow, high, ofs - 64);
+ desthigh = tcg_constant_i64(0);
+ }
+ set_vreg64(desthigh, a->vd, 2 * i + 1);
+ set_vreg64(destlow, a->vd, 2 * i);
}
- set_vreg64(desthigh, a->vd, 1);
- set_vreg64(destlow, a->vd, 0);
-
return true;
}
+TRANS(vbsll_v, LSX, do_vbsll_v, 16)
+TRANS(vbsrl_v, LSX, do_vbsrl_v, 16)
+TRANS(xvbsll_v, LASX, do_vbsll_v, 32)
+TRANS(xvbsrl_v, LASX, do_vbsrl_v, 32)
+
TRANS(vpackev_b, LSX, gen_vvv, gen_helper_vpackev_b)
TRANS(vpackev_h, LSX, gen_vvv, gen_helper_vpackev_h)
TRANS(vpackev_w, LSX, gen_vvv, gen_helper_vpackev_w)
@@ -4354,6 +5177,14 @@
TRANS(vpackod_h, LSX, gen_vvv, gen_helper_vpackod_h)
TRANS(vpackod_w, LSX, gen_vvv, gen_helper_vpackod_w)
TRANS(vpackod_d, LSX, gen_vvv, gen_helper_vpackod_d)
+TRANS(xvpackev_b, LASX, gen_xxx, gen_helper_vpackev_b)
+TRANS(xvpackev_h, LASX, gen_xxx, gen_helper_vpackev_h)
+TRANS(xvpackev_w, LASX, gen_xxx, gen_helper_vpackev_w)
+TRANS(xvpackev_d, LASX, gen_xxx, gen_helper_vpackev_d)
+TRANS(xvpackod_b, LASX, gen_xxx, gen_helper_vpackod_b)
+TRANS(xvpackod_h, LASX, gen_xxx, gen_helper_vpackod_h)
+TRANS(xvpackod_w, LASX, gen_xxx, gen_helper_vpackod_w)
+TRANS(xvpackod_d, LASX, gen_xxx, gen_helper_vpackod_d)
TRANS(vpickev_b, LSX, gen_vvv, gen_helper_vpickev_b)
TRANS(vpickev_h, LSX, gen_vvv, gen_helper_vpickev_h)
@@ -4363,6 +5194,14 @@
TRANS(vpickod_h, LSX, gen_vvv, gen_helper_vpickod_h)
TRANS(vpickod_w, LSX, gen_vvv, gen_helper_vpickod_w)
TRANS(vpickod_d, LSX, gen_vvv, gen_helper_vpickod_d)
+TRANS(xvpickev_b, LASX, gen_xxx, gen_helper_vpickev_b)
+TRANS(xvpickev_h, LASX, gen_xxx, gen_helper_vpickev_h)
+TRANS(xvpickev_w, LASX, gen_xxx, gen_helper_vpickev_w)
+TRANS(xvpickev_d, LASX, gen_xxx, gen_helper_vpickev_d)
+TRANS(xvpickod_b, LASX, gen_xxx, gen_helper_vpickod_b)
+TRANS(xvpickod_h, LASX, gen_xxx, gen_helper_vpickod_h)
+TRANS(xvpickod_w, LASX, gen_xxx, gen_helper_vpickod_w)
+TRANS(xvpickod_d, LASX, gen_xxx, gen_helper_vpickod_d)
TRANS(vilvl_b, LSX, gen_vvv, gen_helper_vilvl_b)
TRANS(vilvl_h, LSX, gen_vvv, gen_helper_vilvl_h)
@@ -4372,22 +5211,46 @@
TRANS(vilvh_h, LSX, gen_vvv, gen_helper_vilvh_h)
TRANS(vilvh_w, LSX, gen_vvv, gen_helper_vilvh_w)
TRANS(vilvh_d, LSX, gen_vvv, gen_helper_vilvh_d)
+TRANS(xvilvl_b, LASX, gen_xxx, gen_helper_vilvl_b)
+TRANS(xvilvl_h, LASX, gen_xxx, gen_helper_vilvl_h)
+TRANS(xvilvl_w, LASX, gen_xxx, gen_helper_vilvl_w)
+TRANS(xvilvl_d, LASX, gen_xxx, gen_helper_vilvl_d)
+TRANS(xvilvh_b, LASX, gen_xxx, gen_helper_vilvh_b)
+TRANS(xvilvh_h, LASX, gen_xxx, gen_helper_vilvh_h)
+TRANS(xvilvh_w, LASX, gen_xxx, gen_helper_vilvh_w)
+TRANS(xvilvh_d, LASX, gen_xxx, gen_helper_vilvh_d)
TRANS(vshuf_b, LSX, gen_vvvv, gen_helper_vshuf_b)
TRANS(vshuf_h, LSX, gen_vvv, gen_helper_vshuf_h)
TRANS(vshuf_w, LSX, gen_vvv, gen_helper_vshuf_w)
TRANS(vshuf_d, LSX, gen_vvv, gen_helper_vshuf_d)
+TRANS(xvshuf_b, LASX, gen_xxxx, gen_helper_vshuf_b)
+TRANS(xvshuf_h, LASX, gen_xxx, gen_helper_vshuf_h)
+TRANS(xvshuf_w, LASX, gen_xxx, gen_helper_vshuf_w)
+TRANS(xvshuf_d, LASX, gen_xxx, gen_helper_vshuf_d)
TRANS(vshuf4i_b, LSX, gen_vv_i, gen_helper_vshuf4i_b)
TRANS(vshuf4i_h, LSX, gen_vv_i, gen_helper_vshuf4i_h)
TRANS(vshuf4i_w, LSX, gen_vv_i, gen_helper_vshuf4i_w)
TRANS(vshuf4i_d, LSX, gen_vv_i, gen_helper_vshuf4i_d)
+TRANS(xvshuf4i_b, LASX, gen_xx_i, gen_helper_vshuf4i_b)
+TRANS(xvshuf4i_h, LASX, gen_xx_i, gen_helper_vshuf4i_h)
+TRANS(xvshuf4i_w, LASX, gen_xx_i, gen_helper_vshuf4i_w)
+TRANS(xvshuf4i_d, LASX, gen_xx_i, gen_helper_vshuf4i_d)
+TRANS(xvperm_w, LASX, gen_xxx, gen_helper_vperm_w)
TRANS(vpermi_w, LSX, gen_vv_i, gen_helper_vpermi_w)
+TRANS(xvpermi_w, LASX, gen_xx_i, gen_helper_vpermi_w)
+TRANS(xvpermi_d, LASX, gen_xx_i, gen_helper_vpermi_d)
+TRANS(xvpermi_q, LASX, gen_xx_i, gen_helper_vpermi_q)
TRANS(vextrins_b, LSX, gen_vv_i, gen_helper_vextrins_b)
TRANS(vextrins_h, LSX, gen_vv_i, gen_helper_vextrins_h)
TRANS(vextrins_w, LSX, gen_vv_i, gen_helper_vextrins_w)
TRANS(vextrins_d, LSX, gen_vv_i, gen_helper_vextrins_d)
+TRANS(xvextrins_b, LASX, gen_xx_i, gen_helper_vextrins_b)
+TRANS(xvextrins_h, LASX, gen_xx_i, gen_helper_vextrins_h)
+TRANS(xvextrins_w, LASX, gen_xx_i, gen_helper_vextrins_w)
+TRANS(xvextrins_d, LASX, gen_xx_i, gen_helper_vextrins_d)
static bool trans_vld(DisasContext *ctx, arg_vr_i *a)
{
@@ -4399,7 +5262,9 @@
return false;
}
- CHECK_SXE;
+ if (!check_vec(ctx, 16)) {
+ return true;
+ }
addr = gpr_src(ctx, a->rj, EXT_NONE);
val = tcg_temp_new_i128();
@@ -4426,7 +5291,9 @@
return false;
}
- CHECK_SXE;
+ if (!check_vec(ctx, 16)) {
+ return true;
+ }
addr = gpr_src(ctx, a->rj, EXT_NONE);
val = tcg_temp_new_i128();
@@ -4453,7 +5320,9 @@
return false;
}
- CHECK_SXE;
+ if (!check_vec(ctx, 16)) {
+ return true;
+ }
src1 = gpr_src(ctx, a->rj, EXT_NONE);
src2 = gpr_src(ctx, a->rk, EXT_NONE);
@@ -4480,7 +5349,9 @@
return false;
}
- CHECK_SXE;
+ if (!check_vec(ctx, 16)) {
+ return true;
+ }
src1 = gpr_src(ctx, a->rj, EXT_NONE);
src2 = gpr_src(ctx, a->rk, EXT_NONE);
@@ -4497,59 +5368,155 @@
return true;
}
-#define VLDREPL(NAME, MO) \
-static bool trans_## NAME (DisasContext *ctx, arg_vr_i *a) \
-{ \
- TCGv addr; \
- TCGv_i64 val; \
- \
- if (!avail_LSX(ctx)) { \
- return false; \
- } \
- \
- CHECK_SXE; \
- \
- addr = gpr_src(ctx, a->rj, EXT_NONE); \
- val = tcg_temp_new_i64(); \
- \
- addr = make_address_i(ctx, addr, a->imm); \
- \
- tcg_gen_qemu_ld_i64(val, addr, ctx->mem_idx, MO); \
- tcg_gen_gvec_dup_i64(MO, vec_full_offset(a->vd), 16, ctx->vl/8, val); \
- \
- return true; \
+static bool do_vldrepl_vl(DisasContext *ctx, arg_vr_i *a,
+ uint32_t oprsz, MemOp mop)
+{
+ TCGv addr;
+ TCGv_i64 val;
+
+ if (!check_vec(ctx, oprsz)) {
+ return true;
+ }
+
+ addr = gpr_src(ctx, a->rj, EXT_NONE);
+ val = tcg_temp_new_i64();
+
+ addr = make_address_i(ctx, addr, a->imm);
+
+ tcg_gen_qemu_ld_i64(val, addr, ctx->mem_idx, mop);
+ tcg_gen_gvec_dup_i64(mop, vec_full_offset(a->vd), oprsz, ctx->vl / 8, val);
+
+ return true;
}
-VLDREPL(vldrepl_b, MO_8)
-VLDREPL(vldrepl_h, MO_16)
-VLDREPL(vldrepl_w, MO_32)
-VLDREPL(vldrepl_d, MO_64)
-
-#define VSTELM(NAME, MO, E) \
-static bool trans_## NAME (DisasContext *ctx, arg_vr_ii *a) \
-{ \
- TCGv addr; \
- TCGv_i64 val; \
- \
- if (!avail_LSX(ctx)) { \
- return false; \
- } \
- \
- CHECK_SXE; \
- \
- addr = gpr_src(ctx, a->rj, EXT_NONE); \
- val = tcg_temp_new_i64(); \
- \
- addr = make_address_i(ctx, addr, a->imm); \
- \
- tcg_gen_ld_i64(val, cpu_env, \
- offsetof(CPULoongArchState, fpr[a->vd].vreg.E(a->imm2))); \
- tcg_gen_qemu_st_i64(val, addr, ctx->mem_idx, MO); \
- \
- return true; \
+static bool do_vldrepl(DisasContext *ctx, arg_vr_i *a, MemOp mop)
+{
+ return do_vldrepl_vl(ctx, a, 16, mop);
}
-VSTELM(vstelm_b, MO_8, B)
-VSTELM(vstelm_h, MO_16, H)
-VSTELM(vstelm_w, MO_32, W)
-VSTELM(vstelm_d, MO_64, D)
+static bool do_xvldrepl(DisasContext *ctx, arg_vr_i *a, MemOp mop)
+{
+ return do_vldrepl_vl(ctx, a, 32, mop);
+}
+
+TRANS(vldrepl_b, LSX, do_vldrepl, MO_8)
+TRANS(vldrepl_h, LSX, do_vldrepl, MO_16)
+TRANS(vldrepl_w, LSX, do_vldrepl, MO_32)
+TRANS(vldrepl_d, LSX, do_vldrepl, MO_64)
+TRANS(xvldrepl_b, LASX, do_xvldrepl, MO_8)
+TRANS(xvldrepl_h, LASX, do_xvldrepl, MO_16)
+TRANS(xvldrepl_w, LASX, do_xvldrepl, MO_32)
+TRANS(xvldrepl_d, LASX, do_xvldrepl, MO_64)
+
+static bool do_vstelm_vl(DisasContext *ctx,
+ arg_vr_ii *a, uint32_t oprsz, MemOp mop)
+{
+ TCGv addr;
+ TCGv_i64 val;
+
+ if (!check_vec(ctx, oprsz)) {
+ return true;
+ }
+
+ addr = gpr_src(ctx, a->rj, EXT_NONE);
+ val = tcg_temp_new_i64();
+
+ addr = make_address_i(ctx, addr, a->imm);
+ tcg_gen_ld_i64(val, cpu_env, vec_reg_offset(a->vd, a->imm2, mop));
+ tcg_gen_qemu_st_i64(val, addr, ctx->mem_idx, mop);
+ return true;
+}
+
+static bool do_vstelm(DisasContext *ctx, arg_vr_ii *a, MemOp mop)
+{
+ return do_vstelm_vl(ctx, a, 16, mop);
+}
+
+static bool do_xvstelm(DisasContext *ctx, arg_vr_ii *a, MemOp mop)
+{
+ return do_vstelm_vl(ctx, a, 32, mop);
+}
+
+TRANS(vstelm_b, LSX, do_vstelm, MO_8)
+TRANS(vstelm_h, LSX, do_vstelm, MO_16)
+TRANS(vstelm_w, LSX, do_vstelm, MO_32)
+TRANS(vstelm_d, LSX, do_vstelm, MO_64)
+TRANS(xvstelm_b, LASX, do_xvstelm, MO_8)
+TRANS(xvstelm_h, LASX, do_xvstelm, MO_16)
+TRANS(xvstelm_w, LASX, do_xvstelm, MO_32)
+TRANS(xvstelm_d, LASX, do_xvstelm, MO_64)
+
+static bool gen_lasx_memory(DisasContext *ctx, arg_vr_i *a,
+ void (*func)(DisasContext *, int, TCGv))
+{
+ TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
+ TCGv temp = NULL;
+
+ if (!check_vec(ctx, 32)) {
+ return true;
+ }
+
+ if (a->imm) {
+ temp = tcg_temp_new();
+ tcg_gen_addi_tl(temp, addr, a->imm);
+ addr = temp;
+ }
+
+ func(ctx, a->vd, addr);
+ return true;
+}
+
+static void gen_xvld(DisasContext *ctx, int vreg, TCGv addr)
+{
+ int i;
+ TCGv temp = tcg_temp_new();
+ TCGv dest = tcg_temp_new();
+
+ tcg_gen_qemu_ld_i64(dest, addr, ctx->mem_idx, MO_TEUQ);
+ set_vreg64(dest, vreg, 0);
+
+ for (i = 1; i < 4; i++) {
+ tcg_gen_addi_tl(temp, addr, 8 * i);
+ tcg_gen_qemu_ld_i64(dest, temp, ctx->mem_idx, MO_TEUQ);
+ set_vreg64(dest, vreg, i);
+ }
+}
+
+static void gen_xvst(DisasContext * ctx, int vreg, TCGv addr)
+{
+ int i;
+ TCGv temp = tcg_temp_new();
+ TCGv dest = tcg_temp_new();
+
+ get_vreg64(dest, vreg, 0);
+ tcg_gen_qemu_st_i64(dest, addr, ctx->mem_idx, MO_TEUQ);
+
+ for (i = 1; i < 4; i++) {
+ tcg_gen_addi_tl(temp, addr, 8 * i);
+ get_vreg64(dest, vreg, i);
+ tcg_gen_qemu_st_i64(dest, temp, ctx->mem_idx, MO_TEUQ);
+ }
+}
+
+TRANS(xvld, LASX, gen_lasx_memory, gen_xvld)
+TRANS(xvst, LASX, gen_lasx_memory, gen_xvst)
+
+static bool gen_lasx_memoryx(DisasContext *ctx, arg_vrr *a,
+ void (*func)(DisasContext*, int, TCGv))
+{
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+ TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+ TCGv addr = tcg_temp_new();
+
+ if (!check_vec(ctx, 32)) {
+ return true;
+ }
+
+ tcg_gen_add_tl(addr, src1, src2);
+ func(ctx, a->vd, addr);
+
+ return true;
+}
+
+TRANS(xvldx, LASX, gen_lasx_memoryx, gen_xvld)
+TRANS(xvstx, LASX, gen_lasx_memoryx, gen_xvst)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index c9c3bc2..64b308f 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -550,6 +550,10 @@
@vr_i8i2 .... ........ imm2:2 ........ rj:5 vd:5 &vr_ii imm=%i8s2
@vr_i8i3 .... ....... imm2:3 ........ rj:5 vd:5 &vr_ii imm=%i8s1
@vr_i8i4 .... ...... imm2:4 imm:s8 rj:5 vd:5 &vr_ii
+@vr_i8i2x .... ........ imm2:2 ........ rj:5 vd:5 &vr_ii imm=%i8s3
+@vr_i8i3x .... ....... imm2:3 ........ rj:5 vd:5 &vr_ii imm=%i8s2
+@vr_i8i4x .... ...... imm2:4 ........ rj:5 vd:5 &vr_ii imm=%i8s1
+@vr_i8i5x .... ..... imm2:5 imm:s8 rj:5 vd:5 &vr_ii
@vrr .... ........ ..... rk:5 rj:5 vd:5 &vrr
@v_i13 .... ........ .. imm:13 vd:5 &v_i
@@ -1296,3 +1300,781 @@
vstelm_w 0011 00010010 .. ........ ..... ..... @vr_i8i2
vstelm_h 0011 0001010 ... ........ ..... ..... @vr_i8i3
vstelm_b 0011 000110 .... ........ ..... ..... @vr_i8i4
+
+#
+# LoongArch LASX instructions
+#
+xvadd_b 0111 01000000 10100 ..... ..... ..... @vvv
+xvadd_h 0111 01000000 10101 ..... ..... ..... @vvv
+xvadd_w 0111 01000000 10110 ..... ..... ..... @vvv
+xvadd_d 0111 01000000 10111 ..... ..... ..... @vvv
+xvadd_q 0111 01010010 11010 ..... ..... ..... @vvv
+xvsub_b 0111 01000000 11000 ..... ..... ..... @vvv
+xvsub_h 0111 01000000 11001 ..... ..... ..... @vvv
+xvsub_w 0111 01000000 11010 ..... ..... ..... @vvv
+xvsub_d 0111 01000000 11011 ..... ..... ..... @vvv
+xvsub_q 0111 01010010 11011 ..... ..... ..... @vvv
+
+xvaddi_bu 0111 01101000 10100 ..... ..... ..... @vv_ui5
+xvaddi_hu 0111 01101000 10101 ..... ..... ..... @vv_ui5
+xvaddi_wu 0111 01101000 10110 ..... ..... ..... @vv_ui5
+xvaddi_du 0111 01101000 10111 ..... ..... ..... @vv_ui5
+xvsubi_bu 0111 01101000 11000 ..... ..... ..... @vv_ui5
+xvsubi_hu 0111 01101000 11001 ..... ..... ..... @vv_ui5
+xvsubi_wu 0111 01101000 11010 ..... ..... ..... @vv_ui5
+xvsubi_du 0111 01101000 11011 ..... ..... ..... @vv_ui5
+
+xvneg_b 0111 01101001 11000 01100 ..... ..... @vv
+xvneg_h 0111 01101001 11000 01101 ..... ..... @vv
+xvneg_w 0111 01101001 11000 01110 ..... ..... @vv
+xvneg_d 0111 01101001 11000 01111 ..... ..... @vv
+
+xvsadd_b 0111 01000100 01100 ..... ..... ..... @vvv
+xvsadd_h 0111 01000100 01101 ..... ..... ..... @vvv
+xvsadd_w 0111 01000100 01110 ..... ..... ..... @vvv
+xvsadd_d 0111 01000100 01111 ..... ..... ..... @vvv
+xvsadd_bu 0111 01000100 10100 ..... ..... ..... @vvv
+xvsadd_hu 0111 01000100 10101 ..... ..... ..... @vvv
+xvsadd_wu 0111 01000100 10110 ..... ..... ..... @vvv
+xvsadd_du 0111 01000100 10111 ..... ..... ..... @vvv
+
+xvssub_b 0111 01000100 10000 ..... ..... ..... @vvv
+xvssub_h 0111 01000100 10001 ..... ..... ..... @vvv
+xvssub_w 0111 01000100 10010 ..... ..... ..... @vvv
+xvssub_d 0111 01000100 10011 ..... ..... ..... @vvv
+xvssub_bu 0111 01000100 11000 ..... ..... ..... @vvv
+xvssub_hu 0111 01000100 11001 ..... ..... ..... @vvv
+xvssub_wu 0111 01000100 11010 ..... ..... ..... @vvv
+xvssub_du 0111 01000100 11011 ..... ..... ..... @vvv
+
+xvhaddw_h_b 0111 01000101 01000 ..... ..... ..... @vvv
+xvhaddw_w_h 0111 01000101 01001 ..... ..... ..... @vvv
+xvhaddw_d_w 0111 01000101 01010 ..... ..... ..... @vvv
+xvhaddw_q_d 0111 01000101 01011 ..... ..... ..... @vvv
+xvhaddw_hu_bu 0111 01000101 10000 ..... ..... ..... @vvv
+xvhaddw_wu_hu 0111 01000101 10001 ..... ..... ..... @vvv
+xvhaddw_du_wu 0111 01000101 10010 ..... ..... ..... @vvv
+xvhaddw_qu_du 0111 01000101 10011 ..... ..... ..... @vvv
+
+xvhsubw_h_b 0111 01000101 01100 ..... ..... ..... @vvv
+xvhsubw_w_h 0111 01000101 01101 ..... ..... ..... @vvv
+xvhsubw_d_w 0111 01000101 01110 ..... ..... ..... @vvv
+xvhsubw_q_d 0111 01000101 01111 ..... ..... ..... @vvv
+xvhsubw_hu_bu 0111 01000101 10100 ..... ..... ..... @vvv
+xvhsubw_wu_hu 0111 01000101 10101 ..... ..... ..... @vvv
+xvhsubw_du_wu 0111 01000101 10110 ..... ..... ..... @vvv
+xvhsubw_qu_du 0111 01000101 10111 ..... ..... ..... @vvv
+
+xvaddwev_h_b 0111 01000001 11100 ..... ..... ..... @vvv
+xvaddwev_w_h 0111 01000001 11101 ..... ..... ..... @vvv
+xvaddwev_d_w 0111 01000001 11110 ..... ..... ..... @vvv
+xvaddwev_q_d 0111 01000001 11111 ..... ..... ..... @vvv
+xvaddwod_h_b 0111 01000010 00100 ..... ..... ..... @vvv
+xvaddwod_w_h 0111 01000010 00101 ..... ..... ..... @vvv
+xvaddwod_d_w 0111 01000010 00110 ..... ..... ..... @vvv
+xvaddwod_q_d 0111 01000010 00111 ..... ..... ..... @vvv
+
+xvsubwev_h_b 0111 01000010 00000 ..... ..... ..... @vvv
+xvsubwev_w_h 0111 01000010 00001 ..... ..... ..... @vvv
+xvsubwev_d_w 0111 01000010 00010 ..... ..... ..... @vvv
+xvsubwev_q_d 0111 01000010 00011 ..... ..... ..... @vvv
+xvsubwod_h_b 0111 01000010 01000 ..... ..... ..... @vvv
+xvsubwod_w_h 0111 01000010 01001 ..... ..... ..... @vvv
+xvsubwod_d_w 0111 01000010 01010 ..... ..... ..... @vvv
+xvsubwod_q_d 0111 01000010 01011 ..... ..... ..... @vvv
+
+xvaddwev_h_bu 0111 01000010 11100 ..... ..... ..... @vvv
+xvaddwev_w_hu 0111 01000010 11101 ..... ..... ..... @vvv
+xvaddwev_d_wu 0111 01000010 11110 ..... ..... ..... @vvv
+xvaddwev_q_du 0111 01000010 11111 ..... ..... ..... @vvv
+xvaddwod_h_bu 0111 01000011 00100 ..... ..... ..... @vvv
+xvaddwod_w_hu 0111 01000011 00101 ..... ..... ..... @vvv
+xvaddwod_d_wu 0111 01000011 00110 ..... ..... ..... @vvv
+xvaddwod_q_du 0111 01000011 00111 ..... ..... ..... @vvv
+
+xvsubwev_h_bu 0111 01000011 00000 ..... ..... ..... @vvv
+xvsubwev_w_hu 0111 01000011 00001 ..... ..... ..... @vvv
+xvsubwev_d_wu 0111 01000011 00010 ..... ..... ..... @vvv
+xvsubwev_q_du 0111 01000011 00011 ..... ..... ..... @vvv
+xvsubwod_h_bu 0111 01000011 01000 ..... ..... ..... @vvv
+xvsubwod_w_hu 0111 01000011 01001 ..... ..... ..... @vvv
+xvsubwod_d_wu 0111 01000011 01010 ..... ..... ..... @vvv
+xvsubwod_q_du 0111 01000011 01011 ..... ..... ..... @vvv
+
+xvaddwev_h_bu_b 0111 01000011 11100 ..... ..... ..... @vvv
+xvaddwev_w_hu_h 0111 01000011 11101 ..... ..... ..... @vvv
+xvaddwev_d_wu_w 0111 01000011 11110 ..... ..... ..... @vvv
+xvaddwev_q_du_d 0111 01000011 11111 ..... ..... ..... @vvv
+xvaddwod_h_bu_b 0111 01000100 00000 ..... ..... ..... @vvv
+xvaddwod_w_hu_h 0111 01000100 00001 ..... ..... ..... @vvv
+xvaddwod_d_wu_w 0111 01000100 00010 ..... ..... ..... @vvv
+xvaddwod_q_du_d 0111 01000100 00011 ..... ..... ..... @vvv
+
+xvavg_b 0111 01000110 01000 ..... ..... ..... @vvv
+xvavg_h 0111 01000110 01001 ..... ..... ..... @vvv
+xvavg_w 0111 01000110 01010 ..... ..... ..... @vvv
+xvavg_d 0111 01000110 01011 ..... ..... ..... @vvv
+xvavg_bu 0111 01000110 01100 ..... ..... ..... @vvv
+xvavg_hu 0111 01000110 01101 ..... ..... ..... @vvv
+xvavg_wu 0111 01000110 01110 ..... ..... ..... @vvv
+xvavg_du 0111 01000110 01111 ..... ..... ..... @vvv
+xvavgr_b 0111 01000110 10000 ..... ..... ..... @vvv
+xvavgr_h 0111 01000110 10001 ..... ..... ..... @vvv
+xvavgr_w 0111 01000110 10010 ..... ..... ..... @vvv
+xvavgr_d 0111 01000110 10011 ..... ..... ..... @vvv
+xvavgr_bu 0111 01000110 10100 ..... ..... ..... @vvv
+xvavgr_hu 0111 01000110 10101 ..... ..... ..... @vvv
+xvavgr_wu 0111 01000110 10110 ..... ..... ..... @vvv
+xvavgr_du 0111 01000110 10111 ..... ..... ..... @vvv
+
+xvabsd_b 0111 01000110 00000 ..... ..... ..... @vvv
+xvabsd_h 0111 01000110 00001 ..... ..... ..... @vvv
+xvabsd_w 0111 01000110 00010 ..... ..... ..... @vvv
+xvabsd_d 0111 01000110 00011 ..... ..... ..... @vvv
+xvabsd_bu 0111 01000110 00100 ..... ..... ..... @vvv
+xvabsd_hu 0111 01000110 00101 ..... ..... ..... @vvv
+xvabsd_wu 0111 01000110 00110 ..... ..... ..... @vvv
+xvabsd_du 0111 01000110 00111 ..... ..... ..... @vvv
+
+xvadda_b 0111 01000101 11000 ..... ..... ..... @vvv
+xvadda_h 0111 01000101 11001 ..... ..... ..... @vvv
+xvadda_w 0111 01000101 11010 ..... ..... ..... @vvv
+xvadda_d 0111 01000101 11011 ..... ..... ..... @vvv
+
+xvmax_b 0111 01000111 00000 ..... ..... ..... @vvv
+xvmax_h 0111 01000111 00001 ..... ..... ..... @vvv
+xvmax_w 0111 01000111 00010 ..... ..... ..... @vvv
+xvmax_d 0111 01000111 00011 ..... ..... ..... @vvv
+xvmax_bu 0111 01000111 01000 ..... ..... ..... @vvv
+xvmax_hu 0111 01000111 01001 ..... ..... ..... @vvv
+xvmax_wu 0111 01000111 01010 ..... ..... ..... @vvv
+xvmax_du 0111 01000111 01011 ..... ..... ..... @vvv
+
+xvmaxi_b 0111 01101001 00000 ..... ..... ..... @vv_i5
+xvmaxi_h 0111 01101001 00001 ..... ..... ..... @vv_i5
+xvmaxi_w 0111 01101001 00010 ..... ..... ..... @vv_i5
+xvmaxi_d 0111 01101001 00011 ..... ..... ..... @vv_i5
+xvmaxi_bu 0111 01101001 01000 ..... ..... ..... @vv_ui5
+xvmaxi_hu 0111 01101001 01001 ..... ..... ..... @vv_ui5
+xvmaxi_wu 0111 01101001 01010 ..... ..... ..... @vv_ui5
+xvmaxi_du 0111 01101001 01011 ..... ..... ..... @vv_ui5
+
+xvmin_b 0111 01000111 00100 ..... ..... ..... @vvv
+xvmin_h 0111 01000111 00101 ..... ..... ..... @vvv
+xvmin_w 0111 01000111 00110 ..... ..... ..... @vvv
+xvmin_d 0111 01000111 00111 ..... ..... ..... @vvv
+xvmin_bu 0111 01000111 01100 ..... ..... ..... @vvv
+xvmin_hu 0111 01000111 01101 ..... ..... ..... @vvv
+xvmin_wu 0111 01000111 01110 ..... ..... ..... @vvv
+xvmin_du 0111 01000111 01111 ..... ..... ..... @vvv
+
+xvmini_b 0111 01101001 00100 ..... ..... ..... @vv_i5
+xvmini_h 0111 01101001 00101 ..... ..... ..... @vv_i5
+xvmini_w 0111 01101001 00110 ..... ..... ..... @vv_i5
+xvmini_d 0111 01101001 00111 ..... ..... ..... @vv_i5
+xvmini_bu 0111 01101001 01100 ..... ..... ..... @vv_ui5
+xvmini_hu 0111 01101001 01101 ..... ..... ..... @vv_ui5
+xvmini_wu 0111 01101001 01110 ..... ..... ..... @vv_ui5
+xvmini_du 0111 01101001 01111 ..... ..... ..... @vv_ui5
+
+xvmul_b 0111 01001000 01000 ..... ..... ..... @vvv
+xvmul_h 0111 01001000 01001 ..... ..... ..... @vvv
+xvmul_w 0111 01001000 01010 ..... ..... ..... @vvv
+xvmul_d 0111 01001000 01011 ..... ..... ..... @vvv
+xvmuh_b 0111 01001000 01100 ..... ..... ..... @vvv
+xvmuh_h 0111 01001000 01101 ..... ..... ..... @vvv
+xvmuh_w 0111 01001000 01110 ..... ..... ..... @vvv
+xvmuh_d 0111 01001000 01111 ..... ..... ..... @vvv
+xvmuh_bu 0111 01001000 10000 ..... ..... ..... @vvv
+xvmuh_hu 0111 01001000 10001 ..... ..... ..... @vvv
+xvmuh_wu 0111 01001000 10010 ..... ..... ..... @vvv
+xvmuh_du 0111 01001000 10011 ..... ..... ..... @vvv
+
+xvmulwev_h_b 0111 01001001 00000 ..... ..... ..... @vvv
+xvmulwev_w_h 0111 01001001 00001 ..... ..... ..... @vvv
+xvmulwev_d_w 0111 01001001 00010 ..... ..... ..... @vvv
+xvmulwev_q_d 0111 01001001 00011 ..... ..... ..... @vvv
+xvmulwod_h_b 0111 01001001 00100 ..... ..... ..... @vvv
+xvmulwod_w_h 0111 01001001 00101 ..... ..... ..... @vvv
+xvmulwod_d_w 0111 01001001 00110 ..... ..... ..... @vvv
+xvmulwod_q_d 0111 01001001 00111 ..... ..... ..... @vvv
+xvmulwev_h_bu 0111 01001001 10000 ..... ..... ..... @vvv
+xvmulwev_w_hu 0111 01001001 10001 ..... ..... ..... @vvv
+xvmulwev_d_wu 0111 01001001 10010 ..... ..... ..... @vvv
+xvmulwev_q_du 0111 01001001 10011 ..... ..... ..... @vvv
+xvmulwod_h_bu 0111 01001001 10100 ..... ..... ..... @vvv
+xvmulwod_w_hu 0111 01001001 10101 ..... ..... ..... @vvv
+xvmulwod_d_wu 0111 01001001 10110 ..... ..... ..... @vvv
+xvmulwod_q_du 0111 01001001 10111 ..... ..... ..... @vvv
+xvmulwev_h_bu_b 0111 01001010 00000 ..... ..... ..... @vvv
+xvmulwev_w_hu_h 0111 01001010 00001 ..... ..... ..... @vvv
+xvmulwev_d_wu_w 0111 01001010 00010 ..... ..... ..... @vvv
+xvmulwev_q_du_d 0111 01001010 00011 ..... ..... ..... @vvv
+xvmulwod_h_bu_b 0111 01001010 00100 ..... ..... ..... @vvv
+xvmulwod_w_hu_h 0111 01001010 00101 ..... ..... ..... @vvv
+xvmulwod_d_wu_w 0111 01001010 00110 ..... ..... ..... @vvv
+xvmulwod_q_du_d 0111 01001010 00111 ..... ..... ..... @vvv
+
+xvmadd_b 0111 01001010 10000 ..... ..... ..... @vvv
+xvmadd_h 0111 01001010 10001 ..... ..... ..... @vvv
+xvmadd_w 0111 01001010 10010 ..... ..... ..... @vvv
+xvmadd_d 0111 01001010 10011 ..... ..... ..... @vvv
+xvmsub_b 0111 01001010 10100 ..... ..... ..... @vvv
+xvmsub_h 0111 01001010 10101 ..... ..... ..... @vvv
+xvmsub_w 0111 01001010 10110 ..... ..... ..... @vvv
+xvmsub_d 0111 01001010 10111 ..... ..... ..... @vvv
+
+xvmaddwev_h_b 0111 01001010 11000 ..... ..... ..... @vvv
+xvmaddwev_w_h 0111 01001010 11001 ..... ..... ..... @vvv
+xvmaddwev_d_w 0111 01001010 11010 ..... ..... ..... @vvv
+xvmaddwev_q_d 0111 01001010 11011 ..... ..... ..... @vvv
+xvmaddwod_h_b 0111 01001010 11100 ..... ..... ..... @vvv
+xvmaddwod_w_h 0111 01001010 11101 ..... ..... ..... @vvv
+xvmaddwod_d_w 0111 01001010 11110 ..... ..... ..... @vvv
+xvmaddwod_q_d 0111 01001010 11111 ..... ..... ..... @vvv
+xvmaddwev_h_bu 0111 01001011 01000 ..... ..... ..... @vvv
+xvmaddwev_w_hu 0111 01001011 01001 ..... ..... ..... @vvv
+xvmaddwev_d_wu 0111 01001011 01010 ..... ..... ..... @vvv
+xvmaddwev_q_du 0111 01001011 01011 ..... ..... ..... @vvv
+xvmaddwod_h_bu 0111 01001011 01100 ..... ..... ..... @vvv
+xvmaddwod_w_hu 0111 01001011 01101 ..... ..... ..... @vvv
+xvmaddwod_d_wu 0111 01001011 01110 ..... ..... ..... @vvv
+xvmaddwod_q_du 0111 01001011 01111 ..... ..... ..... @vvv
+xvmaddwev_h_bu_b 0111 01001011 11000 ..... ..... ..... @vvv
+xvmaddwev_w_hu_h 0111 01001011 11001 ..... ..... ..... @vvv
+xvmaddwev_d_wu_w 0111 01001011 11010 ..... ..... ..... @vvv
+xvmaddwev_q_du_d 0111 01001011 11011 ..... ..... ..... @vvv
+xvmaddwod_h_bu_b 0111 01001011 11100 ..... ..... ..... @vvv
+xvmaddwod_w_hu_h 0111 01001011 11101 ..... ..... ..... @vvv
+xvmaddwod_d_wu_w 0111 01001011 11110 ..... ..... ..... @vvv
+xvmaddwod_q_du_d 0111 01001011 11111 ..... ..... ..... @vvv
+
+xvdiv_b 0111 01001110 00000 ..... ..... ..... @vvv
+xvdiv_h 0111 01001110 00001 ..... ..... ..... @vvv
+xvdiv_w 0111 01001110 00010 ..... ..... ..... @vvv
+xvdiv_d 0111 01001110 00011 ..... ..... ..... @vvv
+xvmod_b 0111 01001110 00100 ..... ..... ..... @vvv
+xvmod_h 0111 01001110 00101 ..... ..... ..... @vvv
+xvmod_w 0111 01001110 00110 ..... ..... ..... @vvv
+xvmod_d 0111 01001110 00111 ..... ..... ..... @vvv
+xvdiv_bu 0111 01001110 01000 ..... ..... ..... @vvv
+xvdiv_hu 0111 01001110 01001 ..... ..... ..... @vvv
+xvdiv_wu 0111 01001110 01010 ..... ..... ..... @vvv
+xvdiv_du 0111 01001110 01011 ..... ..... ..... @vvv
+xvmod_bu 0111 01001110 01100 ..... ..... ..... @vvv
+xvmod_hu 0111 01001110 01101 ..... ..... ..... @vvv
+xvmod_wu 0111 01001110 01110 ..... ..... ..... @vvv
+xvmod_du 0111 01001110 01111 ..... ..... ..... @vvv
+
+xvsat_b 0111 01110010 01000 01 ... ..... ..... @vv_ui3
+xvsat_h 0111 01110010 01000 1 .... ..... ..... @vv_ui4
+xvsat_w 0111 01110010 01001 ..... ..... ..... @vv_ui5
+xvsat_d 0111 01110010 0101 ...... ..... ..... @vv_ui6
+xvsat_bu 0111 01110010 10000 01 ... ..... ..... @vv_ui3
+xvsat_hu 0111 01110010 10000 1 .... ..... ..... @vv_ui4
+xvsat_wu 0111 01110010 10001 ..... ..... ..... @vv_ui5
+xvsat_du 0111 01110010 1001 ...... ..... ..... @vv_ui6
+
+xvexth_h_b 0111 01101001 11101 11000 ..... ..... @vv
+xvexth_w_h 0111 01101001 11101 11001 ..... ..... @vv
+xvexth_d_w 0111 01101001 11101 11010 ..... ..... @vv
+xvexth_q_d 0111 01101001 11101 11011 ..... ..... @vv
+xvexth_hu_bu 0111 01101001 11101 11100 ..... ..... @vv
+xvexth_wu_hu 0111 01101001 11101 11101 ..... ..... @vv
+xvexth_du_wu 0111 01101001 11101 11110 ..... ..... @vv
+xvexth_qu_du 0111 01101001 11101 11111 ..... ..... @vv
+
+vext2xv_h_b 0111 01101001 11110 00100 ..... ..... @vv
+vext2xv_w_b 0111 01101001 11110 00101 ..... ..... @vv
+vext2xv_d_b 0111 01101001 11110 00110 ..... ..... @vv
+vext2xv_w_h 0111 01101001 11110 00111 ..... ..... @vv
+vext2xv_d_h 0111 01101001 11110 01000 ..... ..... @vv
+vext2xv_d_w 0111 01101001 11110 01001 ..... ..... @vv
+vext2xv_hu_bu 0111 01101001 11110 01010 ..... ..... @vv
+vext2xv_wu_bu 0111 01101001 11110 01011 ..... ..... @vv
+vext2xv_du_bu 0111 01101001 11110 01100 ..... ..... @vv
+vext2xv_wu_hu 0111 01101001 11110 01101 ..... ..... @vv
+vext2xv_du_hu 0111 01101001 11110 01110 ..... ..... @vv
+vext2xv_du_wu 0111 01101001 11110 01111 ..... ..... @vv
+
+xvsigncov_b 0111 01010010 11100 ..... ..... ..... @vvv
+xvsigncov_h 0111 01010010 11101 ..... ..... ..... @vvv
+xvsigncov_w 0111 01010010 11110 ..... ..... ..... @vvv
+xvsigncov_d 0111 01010010 11111 ..... ..... ..... @vvv
+
+xvmskltz_b 0111 01101001 11000 10000 ..... ..... @vv
+xvmskltz_h 0111 01101001 11000 10001 ..... ..... @vv
+xvmskltz_w 0111 01101001 11000 10010 ..... ..... @vv
+xvmskltz_d 0111 01101001 11000 10011 ..... ..... @vv
+xvmskgez_b 0111 01101001 11000 10100 ..... ..... @vv
+xvmsknz_b 0111 01101001 11000 11000 ..... ..... @vv
+
+xvldi 0111 01111110 00 ............. ..... @v_i13
+
+xvand_v 0111 01010010 01100 ..... ..... ..... @vvv
+xvor_v 0111 01010010 01101 ..... ..... ..... @vvv
+xvxor_v 0111 01010010 01110 ..... ..... ..... @vvv
+xvnor_v 0111 01010010 01111 ..... ..... ..... @vvv
+xvandn_v 0111 01010010 10000 ..... ..... ..... @vvv
+xvorn_v 0111 01010010 10001 ..... ..... ..... @vvv
+
+xvandi_b 0111 01111101 00 ........ ..... ..... @vv_ui8
+xvori_b 0111 01111101 01 ........ ..... ..... @vv_ui8
+xvxori_b 0111 01111101 10 ........ ..... ..... @vv_ui8
+xvnori_b 0111 01111101 11 ........ ..... ..... @vv_ui8
+
+xvsll_b 0111 01001110 10000 ..... ..... ..... @vvv
+xvsll_h 0111 01001110 10001 ..... ..... ..... @vvv
+xvsll_w 0111 01001110 10010 ..... ..... ..... @vvv
+xvsll_d 0111 01001110 10011 ..... ..... ..... @vvv
+xvslli_b 0111 01110010 11000 01 ... ..... ..... @vv_ui3
+xvslli_h 0111 01110010 11000 1 .... ..... ..... @vv_ui4
+xvslli_w 0111 01110010 11001 ..... ..... ..... @vv_ui5
+xvslli_d 0111 01110010 1101 ...... ..... ..... @vv_ui6
+xvsrl_b 0111 01001110 10100 ..... ..... ..... @vvv
+xvsrl_h 0111 01001110 10101 ..... ..... ..... @vvv
+xvsrl_w 0111 01001110 10110 ..... ..... ..... @vvv
+xvsrl_d 0111 01001110 10111 ..... ..... ..... @vvv
+xvsrli_b 0111 01110011 00000 01 ... ..... ..... @vv_ui3
+xvsrli_h 0111 01110011 00000 1 .... ..... ..... @vv_ui4
+xvsrli_w 0111 01110011 00001 ..... ..... ..... @vv_ui5
+xvsrli_d 0111 01110011 0001 ...... ..... ..... @vv_ui6
+xvsra_b 0111 01001110 11000 ..... ..... ..... @vvv
+xvsra_h 0111 01001110 11001 ..... ..... ..... @vvv
+xvsra_w 0111 01001110 11010 ..... ..... ..... @vvv
+xvsra_d 0111 01001110 11011 ..... ..... ..... @vvv
+xvsrai_b 0111 01110011 01000 01 ... ..... ..... @vv_ui3
+xvsrai_h 0111 01110011 01000 1 .... ..... ..... @vv_ui4
+xvsrai_w 0111 01110011 01001 ..... ..... ..... @vv_ui5
+xvsrai_d 0111 01110011 0101 ...... ..... ..... @vv_ui6
+xvrotr_b 0111 01001110 11100 ..... ..... ..... @vvv
+xvrotr_h 0111 01001110 11101 ..... ..... ..... @vvv
+xvrotr_w 0111 01001110 11110 ..... ..... ..... @vvv
+xvrotr_d 0111 01001110 11111 ..... ..... ..... @vvv
+xvrotri_b 0111 01101010 00000 01 ... ..... ..... @vv_ui3
+xvrotri_h 0111 01101010 00000 1 .... ..... ..... @vv_ui4
+xvrotri_w 0111 01101010 00001 ..... ..... ..... @vv_ui5
+xvrotri_d 0111 01101010 0001 ...... ..... ..... @vv_ui6
+
+xvsllwil_h_b 0111 01110000 10000 01 ... ..... ..... @vv_ui3
+xvsllwil_w_h 0111 01110000 10000 1 .... ..... ..... @vv_ui4
+xvsllwil_d_w 0111 01110000 10001 ..... ..... ..... @vv_ui5
+xvextl_q_d 0111 01110000 10010 00000 ..... ..... @vv
+xvsllwil_hu_bu 0111 01110000 11000 01 ... ..... ..... @vv_ui3
+xvsllwil_wu_hu 0111 01110000 11000 1 .... ..... ..... @vv_ui4
+xvsllwil_du_wu 0111 01110000 11001 ..... ..... ..... @vv_ui5
+xvextl_qu_du 0111 01110000 11010 00000 ..... ..... @vv
+
+xvsrlr_b 0111 01001111 00000 ..... ..... ..... @vvv
+xvsrlr_h 0111 01001111 00001 ..... ..... ..... @vvv
+xvsrlr_w 0111 01001111 00010 ..... ..... ..... @vvv
+xvsrlr_d 0111 01001111 00011 ..... ..... ..... @vvv
+xvsrlri_b 0111 01101010 01000 01 ... ..... ..... @vv_ui3
+xvsrlri_h 0111 01101010 01000 1 .... ..... ..... @vv_ui4
+xvsrlri_w 0111 01101010 01001 ..... ..... ..... @vv_ui5
+xvsrlri_d 0111 01101010 0101 ...... ..... ..... @vv_ui6
+xvsrar_b 0111 01001111 00100 ..... ..... ..... @vvv
+xvsrar_h 0111 01001111 00101 ..... ..... ..... @vvv
+xvsrar_w 0111 01001111 00110 ..... ..... ..... @vvv
+xvsrar_d 0111 01001111 00111 ..... ..... ..... @vvv
+xvsrari_b 0111 01101010 10000 01 ... ..... ..... @vv_ui3
+xvsrari_h 0111 01101010 10000 1 .... ..... ..... @vv_ui4
+xvsrari_w 0111 01101010 10001 ..... ..... ..... @vv_ui5
+xvsrari_d 0111 01101010 1001 ...... ..... ..... @vv_ui6
+
+xvsrln_b_h 0111 01001111 01001 ..... ..... ..... @vvv
+xvsrln_h_w 0111 01001111 01010 ..... ..... ..... @vvv
+xvsrln_w_d 0111 01001111 01011 ..... ..... ..... @vvv
+xvsran_b_h 0111 01001111 01101 ..... ..... ..... @vvv
+xvsran_h_w 0111 01001111 01110 ..... ..... ..... @vvv
+xvsran_w_d 0111 01001111 01111 ..... ..... ..... @vvv
+
+xvsrlni_b_h 0111 01110100 00000 1 .... ..... ..... @vv_ui4
+xvsrlni_h_w 0111 01110100 00001 ..... ..... ..... @vv_ui5
+xvsrlni_w_d 0111 01110100 0001 ...... ..... ..... @vv_ui6
+xvsrlni_d_q 0111 01110100 001 ....... ..... ..... @vv_ui7
+xvsrani_b_h 0111 01110101 10000 1 .... ..... ..... @vv_ui4
+xvsrani_h_w 0111 01110101 10001 ..... ..... ..... @vv_ui5
+xvsrani_w_d 0111 01110101 1001 ...... ..... ..... @vv_ui6
+xvsrani_d_q 0111 01110101 101 ....... ..... ..... @vv_ui7
+
+xvsrlrn_b_h 0111 01001111 10001 ..... ..... ..... @vvv
+xvsrlrn_h_w 0111 01001111 10010 ..... ..... ..... @vvv
+xvsrlrn_w_d 0111 01001111 10011 ..... ..... ..... @vvv
+xvsrarn_b_h 0111 01001111 10101 ..... ..... ..... @vvv
+xvsrarn_h_w 0111 01001111 10110 ..... ..... ..... @vvv
+xvsrarn_w_d 0111 01001111 10111 ..... ..... ..... @vvv
+
+xvsrlrni_b_h 0111 01110100 01000 1 .... ..... ..... @vv_ui4
+xvsrlrni_h_w 0111 01110100 01001 ..... ..... ..... @vv_ui5
+xvsrlrni_w_d 0111 01110100 0101 ...... ..... ..... @vv_ui6
+xvsrlrni_d_q 0111 01110100 011 ....... ..... ..... @vv_ui7
+xvsrarni_b_h 0111 01110101 11000 1 .... ..... ..... @vv_ui4
+xvsrarni_h_w 0111 01110101 11001 ..... ..... ..... @vv_ui5
+xvsrarni_w_d 0111 01110101 1101 ...... ..... ..... @vv_ui6
+xvsrarni_d_q 0111 01110101 111 ....... ..... ..... @vv_ui7
+
+xvssrln_b_h 0111 01001111 11001 ..... ..... ..... @vvv
+xvssrln_h_w 0111 01001111 11010 ..... ..... ..... @vvv
+xvssrln_w_d 0111 01001111 11011 ..... ..... ..... @vvv
+xvssran_b_h 0111 01001111 11101 ..... ..... ..... @vvv
+xvssran_h_w 0111 01001111 11110 ..... ..... ..... @vvv
+xvssran_w_d 0111 01001111 11111 ..... ..... ..... @vvv
+xvssrln_bu_h 0111 01010000 01001 ..... ..... ..... @vvv
+xvssrln_hu_w 0111 01010000 01010 ..... ..... ..... @vvv
+xvssrln_wu_d 0111 01010000 01011 ..... ..... ..... @vvv
+xvssran_bu_h 0111 01010000 01101 ..... ..... ..... @vvv
+xvssran_hu_w 0111 01010000 01110 ..... ..... ..... @vvv
+xvssran_wu_d 0111 01010000 01111 ..... ..... ..... @vvv
+
+xvssrlni_b_h 0111 01110100 10000 1 .... ..... ..... @vv_ui4
+xvssrlni_h_w 0111 01110100 10001 ..... ..... ..... @vv_ui5
+xvssrlni_w_d 0111 01110100 1001 ...... ..... ..... @vv_ui6
+xvssrlni_d_q 0111 01110100 101 ....... ..... ..... @vv_ui7
+xvssrani_b_h 0111 01110110 00000 1 .... ..... ..... @vv_ui4
+xvssrani_h_w 0111 01110110 00001 ..... ..... ..... @vv_ui5
+xvssrani_w_d 0111 01110110 0001 ...... ..... ..... @vv_ui6
+xvssrani_d_q 0111 01110110 001 ....... ..... ..... @vv_ui7
+xvssrlni_bu_h 0111 01110100 11000 1 .... ..... ..... @vv_ui4
+xvssrlni_hu_w 0111 01110100 11001 ..... ..... ..... @vv_ui5
+xvssrlni_wu_d 0111 01110100 1101 ...... ..... ..... @vv_ui6
+xvssrlni_du_q 0111 01110100 111 ....... ..... ..... @vv_ui7
+xvssrani_bu_h 0111 01110110 01000 1 .... ..... ..... @vv_ui4
+xvssrani_hu_w 0111 01110110 01001 ..... ..... ..... @vv_ui5
+xvssrani_wu_d 0111 01110110 0101 ...... ..... ..... @vv_ui6
+xvssrani_du_q 0111 01110110 011 ....... ..... ..... @vv_ui7
+
+xvssrlrn_b_h 0111 01010000 00001 ..... ..... ..... @vvv
+xvssrlrn_h_w 0111 01010000 00010 ..... ..... ..... @vvv
+xvssrlrn_w_d 0111 01010000 00011 ..... ..... ..... @vvv
+xvssrarn_b_h 0111 01010000 00101 ..... ..... ..... @vvv
+xvssrarn_h_w 0111 01010000 00110 ..... ..... ..... @vvv
+xvssrarn_w_d 0111 01010000 00111 ..... ..... ..... @vvv
+xvssrlrn_bu_h 0111 01010000 10001 ..... ..... ..... @vvv
+xvssrlrn_hu_w 0111 01010000 10010 ..... ..... ..... @vvv
+xvssrlrn_wu_d 0111 01010000 10011 ..... ..... ..... @vvv
+xvssrarn_bu_h 0111 01010000 10101 ..... ..... ..... @vvv
+xvssrarn_hu_w 0111 01010000 10110 ..... ..... ..... @vvv
+xvssrarn_wu_d 0111 01010000 10111 ..... ..... ..... @vvv
+
+xvssrlrni_b_h 0111 01110101 00000 1 .... ..... ..... @vv_ui4
+xvssrlrni_h_w 0111 01110101 00001 ..... ..... ..... @vv_ui5
+xvssrlrni_w_d 0111 01110101 0001 ...... ..... ..... @vv_ui6
+xvssrlrni_d_q 0111 01110101 001 ....... ..... ..... @vv_ui7
+xvssrarni_b_h 0111 01110110 10000 1 .... ..... ..... @vv_ui4
+xvssrarni_h_w 0111 01110110 10001 ..... ..... ..... @vv_ui5
+xvssrarni_w_d 0111 01110110 1001 ...... ..... ..... @vv_ui6
+xvssrarni_d_q 0111 01110110 101 ....... ..... ..... @vv_ui7
+xvssrlrni_bu_h 0111 01110101 01000 1 .... ..... ..... @vv_ui4
+xvssrlrni_hu_w 0111 01110101 01001 ..... ..... ..... @vv_ui5
+xvssrlrni_wu_d 0111 01110101 0101 ...... ..... ..... @vv_ui6
+xvssrlrni_du_q 0111 01110101 011 ....... ..... ..... @vv_ui7
+xvssrarni_bu_h 0111 01110110 11000 1 .... ..... ..... @vv_ui4
+xvssrarni_hu_w 0111 01110110 11001 ..... ..... ..... @vv_ui5
+xvssrarni_wu_d 0111 01110110 1101 ...... ..... ..... @vv_ui6
+xvssrarni_du_q 0111 01110110 111 ....... ..... ..... @vv_ui7
+
+xvclo_b 0111 01101001 11000 00000 ..... ..... @vv
+xvclo_h 0111 01101001 11000 00001 ..... ..... @vv
+xvclo_w 0111 01101001 11000 00010 ..... ..... @vv
+xvclo_d 0111 01101001 11000 00011 ..... ..... @vv
+xvclz_b 0111 01101001 11000 00100 ..... ..... @vv
+xvclz_h 0111 01101001 11000 00101 ..... ..... @vv
+xvclz_w 0111 01101001 11000 00110 ..... ..... @vv
+xvclz_d 0111 01101001 11000 00111 ..... ..... @vv
+
+xvpcnt_b 0111 01101001 11000 01000 ..... ..... @vv
+xvpcnt_h 0111 01101001 11000 01001 ..... ..... @vv
+xvpcnt_w 0111 01101001 11000 01010 ..... ..... @vv
+xvpcnt_d 0111 01101001 11000 01011 ..... ..... @vv
+
+xvbitclr_b 0111 01010000 11000 ..... ..... ..... @vvv
+xvbitclr_h 0111 01010000 11001 ..... ..... ..... @vvv
+xvbitclr_w 0111 01010000 11010 ..... ..... ..... @vvv
+xvbitclr_d 0111 01010000 11011 ..... ..... ..... @vvv
+xvbitclri_b 0111 01110001 00000 01 ... ..... ..... @vv_ui3
+xvbitclri_h 0111 01110001 00000 1 .... ..... ..... @vv_ui4
+xvbitclri_w 0111 01110001 00001 ..... ..... ..... @vv_ui5
+xvbitclri_d 0111 01110001 0001 ...... ..... ..... @vv_ui6
+
+xvbitset_b 0111 01010000 11100 ..... ..... ..... @vvv
+xvbitset_h 0111 01010000 11101 ..... ..... ..... @vvv
+xvbitset_w 0111 01010000 11110 ..... ..... ..... @vvv
+xvbitset_d 0111 01010000 11111 ..... ..... ..... @vvv
+xvbitseti_b 0111 01110001 01000 01 ... ..... ..... @vv_ui3
+xvbitseti_h 0111 01110001 01000 1 .... ..... ..... @vv_ui4
+xvbitseti_w 0111 01110001 01001 ..... ..... ..... @vv_ui5
+xvbitseti_d 0111 01110001 0101 ...... ..... ..... @vv_ui6
+
+xvbitrev_b 0111 01010001 00000 ..... ..... ..... @vvv
+xvbitrev_h 0111 01010001 00001 ..... ..... ..... @vvv
+xvbitrev_w 0111 01010001 00010 ..... ..... ..... @vvv
+xvbitrev_d 0111 01010001 00011 ..... ..... ..... @vvv
+xvbitrevi_b 0111 01110001 10000 01 ... ..... ..... @vv_ui3
+xvbitrevi_h 0111 01110001 10000 1 .... ..... ..... @vv_ui4
+xvbitrevi_w 0111 01110001 10001 ..... ..... ..... @vv_ui5
+xvbitrevi_d 0111 01110001 1001 ...... ..... ..... @vv_ui6
+
+xvfrstp_b 0111 01010010 10110 ..... ..... ..... @vvv
+xvfrstp_h 0111 01010010 10111 ..... ..... ..... @vvv
+xvfrstpi_b 0111 01101001 10100 ..... ..... ..... @vv_ui5
+xvfrstpi_h 0111 01101001 10101 ..... ..... ..... @vv_ui5
+
+xvfadd_s 0111 01010011 00001 ..... ..... ..... @vvv
+xvfadd_d 0111 01010011 00010 ..... ..... ..... @vvv
+xvfsub_s 0111 01010011 00101 ..... ..... ..... @vvv
+xvfsub_d 0111 01010011 00110 ..... ..... ..... @vvv
+xvfmul_s 0111 01010011 10001 ..... ..... ..... @vvv
+xvfmul_d 0111 01010011 10010 ..... ..... ..... @vvv
+xvfdiv_s 0111 01010011 10101 ..... ..... ..... @vvv
+xvfdiv_d 0111 01010011 10110 ..... ..... ..... @vvv
+
+xvfmadd_s 0000 10100001 ..... ..... ..... ..... @vvvv
+xvfmadd_d 0000 10100010 ..... ..... ..... ..... @vvvv
+xvfmsub_s 0000 10100101 ..... ..... ..... ..... @vvvv
+xvfmsub_d 0000 10100110 ..... ..... ..... ..... @vvvv
+xvfnmadd_s 0000 10101001 ..... ..... ..... ..... @vvvv
+xvfnmadd_d 0000 10101010 ..... ..... ..... ..... @vvvv
+xvfnmsub_s 0000 10101101 ..... ..... ..... ..... @vvvv
+xvfnmsub_d 0000 10101110 ..... ..... ..... ..... @vvvv
+
+xvfmax_s 0111 01010011 11001 ..... ..... ..... @vvv
+xvfmax_d 0111 01010011 11010 ..... ..... ..... @vvv
+xvfmin_s 0111 01010011 11101 ..... ..... ..... @vvv
+xvfmin_d 0111 01010011 11110 ..... ..... ..... @vvv
+
+xvfmaxa_s 0111 01010100 00001 ..... ..... ..... @vvv
+xvfmaxa_d 0111 01010100 00010 ..... ..... ..... @vvv
+xvfmina_s 0111 01010100 00101 ..... ..... ..... @vvv
+xvfmina_d 0111 01010100 00110 ..... ..... ..... @vvv
+
+xvflogb_s 0111 01101001 11001 10001 ..... ..... @vv
+xvflogb_d 0111 01101001 11001 10010 ..... ..... @vv
+
+xvfclass_s 0111 01101001 11001 10101 ..... ..... @vv
+xvfclass_d 0111 01101001 11001 10110 ..... ..... @vv
+
+xvfsqrt_s 0111 01101001 11001 11001 ..... ..... @vv
+xvfsqrt_d 0111 01101001 11001 11010 ..... ..... @vv
+xvfrecip_s 0111 01101001 11001 11101 ..... ..... @vv
+xvfrecip_d 0111 01101001 11001 11110 ..... ..... @vv
+xvfrsqrt_s 0111 01101001 11010 00001 ..... ..... @vv
+xvfrsqrt_d 0111 01101001 11010 00010 ..... ..... @vv
+
+xvfcvtl_s_h 0111 01101001 11011 11010 ..... ..... @vv
+xvfcvth_s_h 0111 01101001 11011 11011 ..... ..... @vv
+xvfcvtl_d_s 0111 01101001 11011 11100 ..... ..... @vv
+xvfcvth_d_s 0111 01101001 11011 11101 ..... ..... @vv
+xvfcvt_h_s 0111 01010100 01100 ..... ..... ..... @vvv
+xvfcvt_s_d 0111 01010100 01101 ..... ..... ..... @vvv
+
+xvfrintrne_s 0111 01101001 11010 11101 ..... ..... @vv
+xvfrintrne_d 0111 01101001 11010 11110 ..... ..... @vv
+xvfrintrz_s 0111 01101001 11010 11001 ..... ..... @vv
+xvfrintrz_d 0111 01101001 11010 11010 ..... ..... @vv
+xvfrintrp_s 0111 01101001 11010 10101 ..... ..... @vv
+xvfrintrp_d 0111 01101001 11010 10110 ..... ..... @vv
+xvfrintrm_s 0111 01101001 11010 10001 ..... ..... @vv
+xvfrintrm_d 0111 01101001 11010 10010 ..... ..... @vv
+xvfrint_s 0111 01101001 11010 01101 ..... ..... @vv
+xvfrint_d 0111 01101001 11010 01110 ..... ..... @vv
+
+xvftintrne_w_s 0111 01101001 11100 10100 ..... ..... @vv
+xvftintrne_l_d 0111 01101001 11100 10101 ..... ..... @vv
+xvftintrz_w_s 0111 01101001 11100 10010 ..... ..... @vv
+xvftintrz_l_d 0111 01101001 11100 10011 ..... ..... @vv
+xvftintrp_w_s 0111 01101001 11100 10000 ..... ..... @vv
+xvftintrp_l_d 0111 01101001 11100 10001 ..... ..... @vv
+xvftintrm_w_s 0111 01101001 11100 01110 ..... ..... @vv
+xvftintrm_l_d 0111 01101001 11100 01111 ..... ..... @vv
+xvftint_w_s 0111 01101001 11100 01100 ..... ..... @vv
+xvftint_l_d 0111 01101001 11100 01101 ..... ..... @vv
+xvftintrz_wu_s 0111 01101001 11100 11100 ..... ..... @vv
+xvftintrz_lu_d 0111 01101001 11100 11101 ..... ..... @vv
+xvftint_wu_s 0111 01101001 11100 10110 ..... ..... @vv
+xvftint_lu_d 0111 01101001 11100 10111 ..... ..... @vv
+
+xvftintrne_w_d 0111 01010100 10111 ..... ..... ..... @vvv
+xvftintrz_w_d 0111 01010100 10110 ..... ..... ..... @vvv
+xvftintrp_w_d 0111 01010100 10101 ..... ..... ..... @vvv
+xvftintrm_w_d 0111 01010100 10100 ..... ..... ..... @vvv
+xvftint_w_d 0111 01010100 10011 ..... ..... ..... @vvv
+
+xvftintrnel_l_s 0111 01101001 11101 01000 ..... ..... @vv
+xvftintrneh_l_s 0111 01101001 11101 01001 ..... ..... @vv
+xvftintrzl_l_s 0111 01101001 11101 00110 ..... ..... @vv
+xvftintrzh_l_s 0111 01101001 11101 00111 ..... ..... @vv
+xvftintrpl_l_s 0111 01101001 11101 00100 ..... ..... @vv
+xvftintrph_l_s 0111 01101001 11101 00101 ..... ..... @vv
+xvftintrml_l_s 0111 01101001 11101 00010 ..... ..... @vv
+xvftintrmh_l_s 0111 01101001 11101 00011 ..... ..... @vv
+xvftintl_l_s 0111 01101001 11101 00000 ..... ..... @vv
+xvftinth_l_s 0111 01101001 11101 00001 ..... ..... @vv
+
+xvffint_s_w 0111 01101001 11100 00000 ..... ..... @vv
+xvffint_d_l 0111 01101001 11100 00010 ..... ..... @vv
+xvffint_s_wu 0111 01101001 11100 00001 ..... ..... @vv
+xvffint_d_lu 0111 01101001 11100 00011 ..... ..... @vv
+xvffintl_d_w 0111 01101001 11100 00100 ..... ..... @vv
+xvffinth_d_w 0111 01101001 11100 00101 ..... ..... @vv
+xvffint_s_l 0111 01010100 10000 ..... ..... ..... @vvv
+
+xvseq_b 0111 01000000 00000 ..... ..... ..... @vvv
+xvseq_h 0111 01000000 00001 ..... ..... ..... @vvv
+xvseq_w 0111 01000000 00010 ..... ..... ..... @vvv
+xvseq_d 0111 01000000 00011 ..... ..... ..... @vvv
+xvseqi_b 0111 01101000 00000 ..... ..... ..... @vv_i5
+xvseqi_h 0111 01101000 00001 ..... ..... ..... @vv_i5
+xvseqi_w 0111 01101000 00010 ..... ..... ..... @vv_i5
+xvseqi_d 0111 01101000 00011 ..... ..... ..... @vv_i5
+
+xvsle_b 0111 01000000 00100 ..... ..... ..... @vvv
+xvsle_h 0111 01000000 00101 ..... ..... ..... @vvv
+xvsle_w 0111 01000000 00110 ..... ..... ..... @vvv
+xvsle_d 0111 01000000 00111 ..... ..... ..... @vvv
+xvslei_b 0111 01101000 00100 ..... ..... ..... @vv_i5
+xvslei_h 0111 01101000 00101 ..... ..... ..... @vv_i5
+xvslei_w 0111 01101000 00110 ..... ..... ..... @vv_i5
+xvslei_d 0111 01101000 00111 ..... ..... ..... @vv_i5
+xvsle_bu 0111 01000000 01000 ..... ..... ..... @vvv
+xvsle_hu 0111 01000000 01001 ..... ..... ..... @vvv
+xvsle_wu 0111 01000000 01010 ..... ..... ..... @vvv
+xvsle_du 0111 01000000 01011 ..... ..... ..... @vvv
+xvslei_bu 0111 01101000 01000 ..... ..... ..... @vv_ui5
+xvslei_hu 0111 01101000 01001 ..... ..... ..... @vv_ui5
+xvslei_wu 0111 01101000 01010 ..... ..... ..... @vv_ui5
+xvslei_du 0111 01101000 01011 ..... ..... ..... @vv_ui5
+
+xvslt_b 0111 01000000 01100 ..... ..... ..... @vvv
+xvslt_h 0111 01000000 01101 ..... ..... ..... @vvv
+xvslt_w 0111 01000000 01110 ..... ..... ..... @vvv
+xvslt_d 0111 01000000 01111 ..... ..... ..... @vvv
+xvslti_b 0111 01101000 01100 ..... ..... ..... @vv_i5
+xvslti_h 0111 01101000 01101 ..... ..... ..... @vv_i5
+xvslti_w 0111 01101000 01110 ..... ..... ..... @vv_i5
+xvslti_d 0111 01101000 01111 ..... ..... ..... @vv_i5
+xvslt_bu 0111 01000000 10000 ..... ..... ..... @vvv
+xvslt_hu 0111 01000000 10001 ..... ..... ..... @vvv
+xvslt_wu 0111 01000000 10010 ..... ..... ..... @vvv
+xvslt_du 0111 01000000 10011 ..... ..... ..... @vvv
+xvslti_bu 0111 01101000 10000 ..... ..... ..... @vv_ui5
+xvslti_hu 0111 01101000 10001 ..... ..... ..... @vv_ui5
+xvslti_wu 0111 01101000 10010 ..... ..... ..... @vv_ui5
+xvslti_du 0111 01101000 10011 ..... ..... ..... @vv_ui5
+
+xvfcmp_cond_s 0000 11001001 ..... ..... ..... ..... @vvv_fcond
+xvfcmp_cond_d 0000 11001010 ..... ..... ..... ..... @vvv_fcond
+
+xvbitsel_v 0000 11010010 ..... ..... ..... ..... @vvvv
+
+xvbitseli_b 0111 01111100 01 ........ ..... ..... @vv_ui8
+
+xvseteqz_v 0111 01101001 11001 00110 ..... 00 ... @cv
+xvsetnez_v 0111 01101001 11001 00111 ..... 00 ... @cv
+xvsetanyeqz_b 0111 01101001 11001 01000 ..... 00 ... @cv
+xvsetanyeqz_h 0111 01101001 11001 01001 ..... 00 ... @cv
+xvsetanyeqz_w 0111 01101001 11001 01010 ..... 00 ... @cv
+xvsetanyeqz_d 0111 01101001 11001 01011 ..... 00 ... @cv
+xvsetallnez_b 0111 01101001 11001 01100 ..... 00 ... @cv
+xvsetallnez_h 0111 01101001 11001 01101 ..... 00 ... @cv
+xvsetallnez_w 0111 01101001 11001 01110 ..... 00 ... @cv
+xvsetallnez_d 0111 01101001 11001 01111 ..... 00 ... @cv
+
+xvinsgr2vr_w 0111 01101110 10111 10 ... ..... ..... @vr_ui3
+xvinsgr2vr_d 0111 01101110 10111 110 .. ..... ..... @vr_ui2
+xvpickve2gr_w 0111 01101110 11111 10 ... ..... ..... @rv_ui3
+xvpickve2gr_d 0111 01101110 11111 110 .. ..... ..... @rv_ui2
+xvpickve2gr_wu 0111 01101111 00111 10 ... ..... ..... @rv_ui3
+xvpickve2gr_du 0111 01101111 00111 110 .. ..... ..... @rv_ui2
+
+xvreplgr2vr_b 0111 01101001 11110 00000 ..... ..... @vr
+xvreplgr2vr_h 0111 01101001 11110 00001 ..... ..... @vr
+xvreplgr2vr_w 0111 01101001 11110 00010 ..... ..... @vr
+xvreplgr2vr_d 0111 01101001 11110 00011 ..... ..... @vr
+
+xvreplve_b 0111 01010010 00100 ..... ..... ..... @vvr
+xvreplve_h 0111 01010010 00101 ..... ..... ..... @vvr
+xvreplve_w 0111 01010010 00110 ..... ..... ..... @vvr
+xvreplve_d 0111 01010010 00111 ..... ..... ..... @vvr
+
+xvrepl128vei_b 0111 01101111 01111 0 .... ..... ..... @vv_ui4
+xvrepl128vei_h 0111 01101111 01111 10 ... ..... ..... @vv_ui3
+xvrepl128vei_w 0111 01101111 01111 110 .. ..... ..... @vv_ui2
+xvrepl128vei_d 0111 01101111 01111 1110 . ..... ..... @vv_ui1
+
+xvreplve0_b 0111 01110000 01110 00000 ..... ..... @vv
+xvreplve0_h 0111 01110000 01111 00000 ..... ..... @vv
+xvreplve0_w 0111 01110000 01111 10000 ..... ..... @vv
+xvreplve0_d 0111 01110000 01111 11000 ..... ..... @vv
+xvreplve0_q 0111 01110000 01111 11100 ..... ..... @vv
+
+xvinsve0_w 0111 01101111 11111 10 ... ..... ..... @vv_ui3
+xvinsve0_d 0111 01101111 11111 110 .. ..... ..... @vv_ui2
+
+xvpickve_w 0111 01110000 00111 10 ... ..... ..... @vv_ui3
+xvpickve_d 0111 01110000 00111 110 .. ..... ..... @vv_ui2
+
+xvbsll_v 0111 01101000 11100 ..... ..... ..... @vv_ui5
+xvbsrl_v 0111 01101000 11101 ..... ..... ..... @vv_ui5
+
+xvpackev_b 0111 01010001 01100 ..... ..... ..... @vvv
+xvpackev_h 0111 01010001 01101 ..... ..... ..... @vvv
+xvpackev_w 0111 01010001 01110 ..... ..... ..... @vvv
+xvpackev_d 0111 01010001 01111 ..... ..... ..... @vvv
+xvpackod_b 0111 01010001 10000 ..... ..... ..... @vvv
+xvpackod_h 0111 01010001 10001 ..... ..... ..... @vvv
+xvpackod_w 0111 01010001 10010 ..... ..... ..... @vvv
+xvpackod_d 0111 01010001 10011 ..... ..... ..... @vvv
+
+xvpickev_b 0111 01010001 11100 ..... ..... ..... @vvv
+xvpickev_h 0111 01010001 11101 ..... ..... ..... @vvv
+xvpickev_w 0111 01010001 11110 ..... ..... ..... @vvv
+xvpickev_d 0111 01010001 11111 ..... ..... ..... @vvv
+xvpickod_b 0111 01010010 00000 ..... ..... ..... @vvv
+xvpickod_h 0111 01010010 00001 ..... ..... ..... @vvv
+xvpickod_w 0111 01010010 00010 ..... ..... ..... @vvv
+xvpickod_d 0111 01010010 00011 ..... ..... ..... @vvv
+
+xvilvl_b 0111 01010001 10100 ..... ..... ..... @vvv
+xvilvl_h 0111 01010001 10101 ..... ..... ..... @vvv
+xvilvl_w 0111 01010001 10110 ..... ..... ..... @vvv
+xvilvl_d 0111 01010001 10111 ..... ..... ..... @vvv
+xvilvh_b 0111 01010001 11000 ..... ..... ..... @vvv
+xvilvh_h 0111 01010001 11001 ..... ..... ..... @vvv
+xvilvh_w 0111 01010001 11010 ..... ..... ..... @vvv
+xvilvh_d 0111 01010001 11011 ..... ..... ..... @vvv
+
+xvshuf_b 0000 11010110 ..... ..... ..... ..... @vvvv
+xvshuf_h 0111 01010111 10101 ..... ..... ..... @vvv
+xvshuf_w 0111 01010111 10110 ..... ..... ..... @vvv
+xvshuf_d 0111 01010111 10111 ..... ..... ..... @vvv
+
+xvperm_w 0111 01010111 11010 ..... ..... ..... @vvv
+
+xvshuf4i_b 0111 01111001 00 ........ ..... ..... @vv_ui8
+xvshuf4i_h 0111 01111001 01 ........ ..... ..... @vv_ui8
+xvshuf4i_w 0111 01111001 10 ........ ..... ..... @vv_ui8
+xvshuf4i_d 0111 01111001 11 ........ ..... ..... @vv_ui8
+
+xvpermi_w 0111 01111110 01 ........ ..... ..... @vv_ui8
+xvpermi_d 0111 01111110 10 ........ ..... ..... @vv_ui8
+xvpermi_q 0111 01111110 11 ........ ..... ..... @vv_ui8
+
+xvextrins_d 0111 01111000 00 ........ ..... ..... @vv_ui8
+xvextrins_w 0111 01111000 01 ........ ..... ..... @vv_ui8
+xvextrins_h 0111 01111000 10 ........ ..... ..... @vv_ui8
+xvextrins_b 0111 01111000 11 ........ ..... ..... @vv_ui8
+
+xvld 0010 110010 ............ ..... ..... @vr_i12
+xvst 0010 110011 ............ ..... ..... @vr_i12
+xvldx 0011 10000100 10000 ..... ..... ..... @vrr
+xvstx 0011 10000100 11000 ..... ..... ..... @vrr
+
+xvldrepl_d 0011 00100001 0 ......... ..... ..... @vr_i9
+xvldrepl_w 0011 00100010 .......... ..... ..... @vr_i10
+xvldrepl_h 0011 0010010 ........... ..... ..... @vr_i11
+xvldrepl_b 0011 001010 ............ ..... ..... @vr_i12
+xvstelm_d 0011 00110001 .. ........ ..... ..... @vr_i8i2x
+xvstelm_w 0011 0011001 ... ........ ..... ..... @vr_i8i3x
+xvstelm_h 0011 001101 .... ........ ..... ..... @vr_i8i4x
+xvstelm_b 0011 00111 ..... ........ ..... ..... @vr_i8i5x
diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
index 7b0f29c..c492863 100644
--- a/target/loongarch/internals.h
+++ b/target/loongarch/internals.h
@@ -21,28 +21,6 @@
/* Global bit for huge page */
#define LOONGARCH_HGLOBAL_SHIFT 12
-#if HOST_BIG_ENDIAN
-#define B(x) B[15 - (x)]
-#define H(x) H[7 - (x)]
-#define W(x) W[3 - (x)]
-#define D(x) D[1 - (x)]
-#define UB(x) UB[15 - (x)]
-#define UH(x) UH[7 - (x)]
-#define UW(x) UW[3 - (x)]
-#define UD(x) UD[1 -(x)]
-#define Q(x) Q[x]
-#else
-#define B(x) B[x]
-#define H(x) H[x]
-#define W(x) W[x]
-#define D(x) D[x]
-#define UB(x) UB[x]
-#define UH(x) UH[x]
-#define UW(x) UW[x]
-#define UD(x) UD[x]
-#define Q(x) Q[x]
-#endif
-
void loongarch_translate_init(void);
void loongarch_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
diff --git a/target/loongarch/lsx_helper.c b/target/loongarch/lsx_helper.c
deleted file mode 100644
index 9571f0a..0000000
--- a/target/loongarch/lsx_helper.c
+++ /dev/null
@@ -1,3004 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * QEMU LoongArch LSX helper functions.
- *
- * Copyright (c) 2022-2023 Loongson Technology Corporation Limited
- */
-
-#include "qemu/osdep.h"
-#include "cpu.h"
-#include "exec/exec-all.h"
-#include "exec/helper-proto.h"
-#include "fpu/softfloat.h"
-#include "internals.h"
-#include "tcg/tcg.h"
-
-#define DO_ADD(a, b) (a + b)
-#define DO_SUB(a, b) (a - b)
-
-#define DO_ODD_EVEN(NAME, BIT, E1, E2, DO_OP) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t vk) \
-{ \
- int i; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- VReg *Vk = &(env->fpr[vk].vreg); \
- typedef __typeof(Vd->E1(0)) TD; \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E1(i) = DO_OP((TD)Vj->E2(2 * i + 1), (TD)Vk->E2(2 * i)); \
- } \
-}
-
-DO_ODD_EVEN(vhaddw_h_b, 16, H, B, DO_ADD)
-DO_ODD_EVEN(vhaddw_w_h, 32, W, H, DO_ADD)
-DO_ODD_EVEN(vhaddw_d_w, 64, D, W, DO_ADD)
-
-void HELPER(vhaddw_q_d)(CPULoongArchState *env,
- uint32_t vd, uint32_t vj, uint32_t vk)
-{
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
- VReg *Vk = &(env->fpr[vk].vreg);
-
- Vd->Q(0) = int128_add(int128_makes64(Vj->D(1)), int128_makes64(Vk->D(0)));
-}
-
-DO_ODD_EVEN(vhsubw_h_b, 16, H, B, DO_SUB)
-DO_ODD_EVEN(vhsubw_w_h, 32, W, H, DO_SUB)
-DO_ODD_EVEN(vhsubw_d_w, 64, D, W, DO_SUB)
-
-void HELPER(vhsubw_q_d)(CPULoongArchState *env,
- uint32_t vd, uint32_t vj, uint32_t vk)
-{
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
- VReg *Vk = &(env->fpr[vk].vreg);
-
- Vd->Q(0) = int128_sub(int128_makes64(Vj->D(1)), int128_makes64(Vk->D(0)));
-}
-
-DO_ODD_EVEN(vhaddw_hu_bu, 16, UH, UB, DO_ADD)
-DO_ODD_EVEN(vhaddw_wu_hu, 32, UW, UH, DO_ADD)
-DO_ODD_EVEN(vhaddw_du_wu, 64, UD, UW, DO_ADD)
-
-void HELPER(vhaddw_qu_du)(CPULoongArchState *env,
- uint32_t vd, uint32_t vj, uint32_t vk)
-{
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
- VReg *Vk = &(env->fpr[vk].vreg);
-
- Vd->Q(0) = int128_add(int128_make64((uint64_t)Vj->D(1)),
- int128_make64((uint64_t)Vk->D(0)));
-}
-
-DO_ODD_EVEN(vhsubw_hu_bu, 16, UH, UB, DO_SUB)
-DO_ODD_EVEN(vhsubw_wu_hu, 32, UW, UH, DO_SUB)
-DO_ODD_EVEN(vhsubw_du_wu, 64, UD, UW, DO_SUB)
-
-void HELPER(vhsubw_qu_du)(CPULoongArchState *env,
- uint32_t vd, uint32_t vj, uint32_t vk)
-{
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
- VReg *Vk = &(env->fpr[vk].vreg);
-
- Vd->Q(0) = int128_sub(int128_make64((uint64_t)Vj->D(1)),
- int128_make64((uint64_t)Vk->D(0)));
-}
-
-#define DO_EVEN(NAME, BIT, E1, E2, DO_OP) \
-void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t v) \
-{ \
- int i; \
- VReg *Vd = (VReg *)vd; \
- VReg *Vj = (VReg *)vj; \
- VReg *Vk = (VReg *)vk; \
- typedef __typeof(Vd->E1(0)) TD; \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E1(i) = DO_OP((TD)Vj->E2(2 * i) ,(TD)Vk->E2(2 * i)); \
- } \
-}
-
-#define DO_ODD(NAME, BIT, E1, E2, DO_OP) \
-void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t v) \
-{ \
- int i; \
- VReg *Vd = (VReg *)vd; \
- VReg *Vj = (VReg *)vj; \
- VReg *Vk = (VReg *)vk; \
- typedef __typeof(Vd->E1(0)) TD; \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E1(i) = DO_OP((TD)Vj->E2(2 * i + 1), (TD)Vk->E2(2 * i + 1)); \
- } \
-}
-
-void HELPER(vaddwev_q_d)(void *vd, void *vj, void *vk, uint32_t v)
-{
- VReg *Vd = (VReg *)vd;
- VReg *Vj = (VReg *)vj;
- VReg *Vk = (VReg *)vk;
-
- Vd->Q(0) = int128_add(int128_makes64(Vj->D(0)), int128_makes64(Vk->D(0)));
-}
-
-DO_EVEN(vaddwev_h_b, 16, H, B, DO_ADD)
-DO_EVEN(vaddwev_w_h, 32, W, H, DO_ADD)
-DO_EVEN(vaddwev_d_w, 64, D, W, DO_ADD)
-
-void HELPER(vaddwod_q_d)(void *vd, void *vj, void *vk, uint32_t v)
-{
- VReg *Vd = (VReg *)vd;
- VReg *Vj = (VReg *)vj;
- VReg *Vk = (VReg *)vk;
-
- Vd->Q(0) = int128_add(int128_makes64(Vj->D(1)), int128_makes64(Vk->D(1)));
-}
-
-DO_ODD(vaddwod_h_b, 16, H, B, DO_ADD)
-DO_ODD(vaddwod_w_h, 32, W, H, DO_ADD)
-DO_ODD(vaddwod_d_w, 64, D, W, DO_ADD)
-
-void HELPER(vsubwev_q_d)(void *vd, void *vj, void *vk, uint32_t v)
-{
- VReg *Vd = (VReg *)vd;
- VReg *Vj = (VReg *)vj;
- VReg *Vk = (VReg *)vk;
-
- Vd->Q(0) = int128_sub(int128_makes64(Vj->D(0)), int128_makes64(Vk->D(0)));
-}
-
-DO_EVEN(vsubwev_h_b, 16, H, B, DO_SUB)
-DO_EVEN(vsubwev_w_h, 32, W, H, DO_SUB)
-DO_EVEN(vsubwev_d_w, 64, D, W, DO_SUB)
-
-void HELPER(vsubwod_q_d)(void *vd, void *vj, void *vk, uint32_t v)
-{
- VReg *Vd = (VReg *)vd;
- VReg *Vj = (VReg *)vj;
- VReg *Vk = (VReg *)vk;
-
- Vd->Q(0) = int128_sub(int128_makes64(Vj->D(1)), int128_makes64(Vk->D(1)));
-}
-
-DO_ODD(vsubwod_h_b, 16, H, B, DO_SUB)
-DO_ODD(vsubwod_w_h, 32, W, H, DO_SUB)
-DO_ODD(vsubwod_d_w, 64, D, W, DO_SUB)
-
-void HELPER(vaddwev_q_du)(void *vd, void *vj, void *vk, uint32_t v)
-{
- VReg *Vd = (VReg *)vd;
- VReg *Vj = (VReg *)vj;
- VReg *Vk = (VReg *)vk;
-
- Vd->Q(0) = int128_add(int128_make64((uint64_t)Vj->D(0)),
- int128_make64((uint64_t)Vk->D(0)));
-}
-
-DO_EVEN(vaddwev_h_bu, 16, UH, UB, DO_ADD)
-DO_EVEN(vaddwev_w_hu, 32, UW, UH, DO_ADD)
-DO_EVEN(vaddwev_d_wu, 64, UD, UW, DO_ADD)
-
-void HELPER(vaddwod_q_du)(void *vd, void *vj, void *vk, uint32_t v)
-{
- VReg *Vd = (VReg *)vd;
- VReg *Vj = (VReg *)vj;
- VReg *Vk = (VReg *)vk;
-
- Vd->Q(0) = int128_add(int128_make64((uint64_t)Vj->D(1)),
- int128_make64((uint64_t)Vk->D(1)));
-}
-
-DO_ODD(vaddwod_h_bu, 16, UH, UB, DO_ADD)
-DO_ODD(vaddwod_w_hu, 32, UW, UH, DO_ADD)
-DO_ODD(vaddwod_d_wu, 64, UD, UW, DO_ADD)
-
-void HELPER(vsubwev_q_du)(void *vd, void *vj, void *vk, uint32_t v)
-{
- VReg *Vd = (VReg *)vd;
- VReg *Vj = (VReg *)vj;
- VReg *Vk = (VReg *)vk;
-
- Vd->Q(0) = int128_sub(int128_make64((uint64_t)Vj->D(0)),
- int128_make64((uint64_t)Vk->D(0)));
-}
-
-DO_EVEN(vsubwev_h_bu, 16, UH, UB, DO_SUB)
-DO_EVEN(vsubwev_w_hu, 32, UW, UH, DO_SUB)
-DO_EVEN(vsubwev_d_wu, 64, UD, UW, DO_SUB)
-
-void HELPER(vsubwod_q_du)(void *vd, void *vj, void *vk, uint32_t v)
-{
- VReg *Vd = (VReg *)vd;
- VReg *Vj = (VReg *)vj;
- VReg *Vk = (VReg *)vk;
-
- Vd->Q(0) = int128_sub(int128_make64((uint64_t)Vj->D(1)),
- int128_make64((uint64_t)Vk->D(1)));
-}
-
-DO_ODD(vsubwod_h_bu, 16, UH, UB, DO_SUB)
-DO_ODD(vsubwod_w_hu, 32, UW, UH, DO_SUB)
-DO_ODD(vsubwod_d_wu, 64, UD, UW, DO_SUB)
-
-#define DO_EVEN_U_S(NAME, BIT, ES1, EU1, ES2, EU2, DO_OP) \
-void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t v) \
-{ \
- int i; \
- VReg *Vd = (VReg *)vd; \
- VReg *Vj = (VReg *)vj; \
- VReg *Vk = (VReg *)vk; \
- typedef __typeof(Vd->ES1(0)) TDS; \
- typedef __typeof(Vd->EU1(0)) TDU; \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->ES1(i) = DO_OP((TDU)Vj->EU2(2 * i) ,(TDS)Vk->ES2(2 * i)); \
- } \
-}
-
-#define DO_ODD_U_S(NAME, BIT, ES1, EU1, ES2, EU2, DO_OP) \
-void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t v) \
-{ \
- int i; \
- VReg *Vd = (VReg *)vd; \
- VReg *Vj = (VReg *)vj; \
- VReg *Vk = (VReg *)vk; \
- typedef __typeof(Vd->ES1(0)) TDS; \
- typedef __typeof(Vd->EU1(0)) TDU; \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->ES1(i) = DO_OP((TDU)Vj->EU2(2 * i + 1), (TDS)Vk->ES2(2 * i + 1)); \
- } \
-}
-
-void HELPER(vaddwev_q_du_d)(void *vd, void *vj, void *vk, uint32_t v)
-{
- VReg *Vd = (VReg *)vd;
- VReg *Vj = (VReg *)vj;
- VReg *Vk = (VReg *)vk;
-
- Vd->Q(0) = int128_add(int128_make64((uint64_t)Vj->D(0)),
- int128_makes64(Vk->D(0)));
-}
-
-DO_EVEN_U_S(vaddwev_h_bu_b, 16, H, UH, B, UB, DO_ADD)
-DO_EVEN_U_S(vaddwev_w_hu_h, 32, W, UW, H, UH, DO_ADD)
-DO_EVEN_U_S(vaddwev_d_wu_w, 64, D, UD, W, UW, DO_ADD)
-
-void HELPER(vaddwod_q_du_d)(void *vd, void *vj, void *vk, uint32_t v)
-{
- VReg *Vd = (VReg *)vd;
- VReg *Vj = (VReg *)vj;
- VReg *Vk = (VReg *)vk;
-
- Vd->Q(0) = int128_add(int128_make64((uint64_t)Vj->D(1)),
- int128_makes64(Vk->D(1)));
-}
-
-DO_ODD_U_S(vaddwod_h_bu_b, 16, H, UH, B, UB, DO_ADD)
-DO_ODD_U_S(vaddwod_w_hu_h, 32, W, UW, H, UH, DO_ADD)
-DO_ODD_U_S(vaddwod_d_wu_w, 64, D, UD, W, UW, DO_ADD)
-
-#define DO_VAVG(a, b) ((a >> 1) + (b >> 1) + (a & b & 1))
-#define DO_VAVGR(a, b) ((a >> 1) + (b >> 1) + ((a | b) & 1))
-
-#define DO_3OP(NAME, BIT, E, DO_OP) \
-void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t v) \
-{ \
- int i; \
- VReg *Vd = (VReg *)vd; \
- VReg *Vj = (VReg *)vj; \
- VReg *Vk = (VReg *)vk; \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E(i) = DO_OP(Vj->E(i), Vk->E(i)); \
- } \
-}
-
-DO_3OP(vavg_b, 8, B, DO_VAVG)
-DO_3OP(vavg_h, 16, H, DO_VAVG)
-DO_3OP(vavg_w, 32, W, DO_VAVG)
-DO_3OP(vavg_d, 64, D, DO_VAVG)
-DO_3OP(vavgr_b, 8, B, DO_VAVGR)
-DO_3OP(vavgr_h, 16, H, DO_VAVGR)
-DO_3OP(vavgr_w, 32, W, DO_VAVGR)
-DO_3OP(vavgr_d, 64, D, DO_VAVGR)
-DO_3OP(vavg_bu, 8, UB, DO_VAVG)
-DO_3OP(vavg_hu, 16, UH, DO_VAVG)
-DO_3OP(vavg_wu, 32, UW, DO_VAVG)
-DO_3OP(vavg_du, 64, UD, DO_VAVG)
-DO_3OP(vavgr_bu, 8, UB, DO_VAVGR)
-DO_3OP(vavgr_hu, 16, UH, DO_VAVGR)
-DO_3OP(vavgr_wu, 32, UW, DO_VAVGR)
-DO_3OP(vavgr_du, 64, UD, DO_VAVGR)
-
-#define DO_VABSD(a, b) ((a > b) ? (a -b) : (b-a))
-
-DO_3OP(vabsd_b, 8, B, DO_VABSD)
-DO_3OP(vabsd_h, 16, H, DO_VABSD)
-DO_3OP(vabsd_w, 32, W, DO_VABSD)
-DO_3OP(vabsd_d, 64, D, DO_VABSD)
-DO_3OP(vabsd_bu, 8, UB, DO_VABSD)
-DO_3OP(vabsd_hu, 16, UH, DO_VABSD)
-DO_3OP(vabsd_wu, 32, UW, DO_VABSD)
-DO_3OP(vabsd_du, 64, UD, DO_VABSD)
-
-#define DO_VABS(a) ((a < 0) ? (-a) : (a))
-
-#define DO_VADDA(NAME, BIT, E, DO_OP) \
-void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t v) \
-{ \
- int i; \
- VReg *Vd = (VReg *)vd; \
- VReg *Vj = (VReg *)vj; \
- VReg *Vk = (VReg *)vk; \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E(i) = DO_OP(Vj->E(i)) + DO_OP(Vk->E(i)); \
- } \
-}
-
-DO_VADDA(vadda_b, 8, B, DO_VABS)
-DO_VADDA(vadda_h, 16, H, DO_VABS)
-DO_VADDA(vadda_w, 32, W, DO_VABS)
-DO_VADDA(vadda_d, 64, D, DO_VABS)
-
-#define DO_MIN(a, b) (a < b ? a : b)
-#define DO_MAX(a, b) (a > b ? a : b)
-
-#define VMINMAXI(NAME, BIT, E, DO_OP) \
-void HELPER(NAME)(void *vd, void *vj, uint64_t imm, uint32_t v) \
-{ \
- int i; \
- VReg *Vd = (VReg *)vd; \
- VReg *Vj = (VReg *)vj; \
- typedef __typeof(Vd->E(0)) TD; \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E(i) = DO_OP(Vj->E(i), (TD)imm); \
- } \
-}
-
-VMINMAXI(vmini_b, 8, B, DO_MIN)
-VMINMAXI(vmini_h, 16, H, DO_MIN)
-VMINMAXI(vmini_w, 32, W, DO_MIN)
-VMINMAXI(vmini_d, 64, D, DO_MIN)
-VMINMAXI(vmaxi_b, 8, B, DO_MAX)
-VMINMAXI(vmaxi_h, 16, H, DO_MAX)
-VMINMAXI(vmaxi_w, 32, W, DO_MAX)
-VMINMAXI(vmaxi_d, 64, D, DO_MAX)
-VMINMAXI(vmini_bu, 8, UB, DO_MIN)
-VMINMAXI(vmini_hu, 16, UH, DO_MIN)
-VMINMAXI(vmini_wu, 32, UW, DO_MIN)
-VMINMAXI(vmini_du, 64, UD, DO_MIN)
-VMINMAXI(vmaxi_bu, 8, UB, DO_MAX)
-VMINMAXI(vmaxi_hu, 16, UH, DO_MAX)
-VMINMAXI(vmaxi_wu, 32, UW, DO_MAX)
-VMINMAXI(vmaxi_du, 64, UD, DO_MAX)
-
-#define DO_VMUH(NAME, BIT, E1, E2, DO_OP) \
-void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t v) \
-{ \
- int i; \
- VReg *Vd = (VReg *)vd; \
- VReg *Vj = (VReg *)vj; \
- VReg *Vk = (VReg *)vk; \
- typedef __typeof(Vd->E1(0)) T; \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E2(i) = ((T)Vj->E2(i)) * ((T)Vk->E2(i)) >> BIT; \
- } \
-}
-
-void HELPER(vmuh_d)(void *vd, void *vj, void *vk, uint32_t v)
-{
- uint64_t l, h1, h2;
- VReg *Vd = (VReg *)vd;
- VReg *Vj = (VReg *)vj;
- VReg *Vk = (VReg *)vk;
-
- muls64(&l, &h1, Vj->D(0), Vk->D(0));
- muls64(&l, &h2, Vj->D(1), Vk->D(1));
-
- Vd->D(0) = h1;
- Vd->D(1) = h2;
-}
-
-DO_VMUH(vmuh_b, 8, H, B, DO_MUH)
-DO_VMUH(vmuh_h, 16, W, H, DO_MUH)
-DO_VMUH(vmuh_w, 32, D, W, DO_MUH)
-
-void HELPER(vmuh_du)(void *vd, void *vj, void *vk, uint32_t v)
-{
- uint64_t l, h1, h2;
- VReg *Vd = (VReg *)vd;
- VReg *Vj = (VReg *)vj;
- VReg *Vk = (VReg *)vk;
-
- mulu64(&l, &h1, Vj->D(0), Vk->D(0));
- mulu64(&l, &h2, Vj->D(1), Vk->D(1));
-
- Vd->D(0) = h1;
- Vd->D(1) = h2;
-}
-
-DO_VMUH(vmuh_bu, 8, UH, UB, DO_MUH)
-DO_VMUH(vmuh_hu, 16, UW, UH, DO_MUH)
-DO_VMUH(vmuh_wu, 32, UD, UW, DO_MUH)
-
-#define DO_MUL(a, b) (a * b)
-
-DO_EVEN(vmulwev_h_b, 16, H, B, DO_MUL)
-DO_EVEN(vmulwev_w_h, 32, W, H, DO_MUL)
-DO_EVEN(vmulwev_d_w, 64, D, W, DO_MUL)
-
-DO_ODD(vmulwod_h_b, 16, H, B, DO_MUL)
-DO_ODD(vmulwod_w_h, 32, W, H, DO_MUL)
-DO_ODD(vmulwod_d_w, 64, D, W, DO_MUL)
-
-DO_EVEN(vmulwev_h_bu, 16, UH, UB, DO_MUL)
-DO_EVEN(vmulwev_w_hu, 32, UW, UH, DO_MUL)
-DO_EVEN(vmulwev_d_wu, 64, UD, UW, DO_MUL)
-
-DO_ODD(vmulwod_h_bu, 16, UH, UB, DO_MUL)
-DO_ODD(vmulwod_w_hu, 32, UW, UH, DO_MUL)
-DO_ODD(vmulwod_d_wu, 64, UD, UW, DO_MUL)
-
-DO_EVEN_U_S(vmulwev_h_bu_b, 16, H, UH, B, UB, DO_MUL)
-DO_EVEN_U_S(vmulwev_w_hu_h, 32, W, UW, H, UH, DO_MUL)
-DO_EVEN_U_S(vmulwev_d_wu_w, 64, D, UD, W, UW, DO_MUL)
-
-DO_ODD_U_S(vmulwod_h_bu_b, 16, H, UH, B, UB, DO_MUL)
-DO_ODD_U_S(vmulwod_w_hu_h, 32, W, UW, H, UH, DO_MUL)
-DO_ODD_U_S(vmulwod_d_wu_w, 64, D, UD, W, UW, DO_MUL)
-
-#define DO_MADD(a, b, c) (a + b * c)
-#define DO_MSUB(a, b, c) (a - b * c)
-
-#define VMADDSUB(NAME, BIT, E, DO_OP) \
-void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t v) \
-{ \
- int i; \
- VReg *Vd = (VReg *)vd; \
- VReg *Vj = (VReg *)vj; \
- VReg *Vk = (VReg *)vk; \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E(i) = DO_OP(Vd->E(i), Vj->E(i) ,Vk->E(i)); \
- } \
-}
-
-VMADDSUB(vmadd_b, 8, B, DO_MADD)
-VMADDSUB(vmadd_h, 16, H, DO_MADD)
-VMADDSUB(vmadd_w, 32, W, DO_MADD)
-VMADDSUB(vmadd_d, 64, D, DO_MADD)
-VMADDSUB(vmsub_b, 8, B, DO_MSUB)
-VMADDSUB(vmsub_h, 16, H, DO_MSUB)
-VMADDSUB(vmsub_w, 32, W, DO_MSUB)
-VMADDSUB(vmsub_d, 64, D, DO_MSUB)
-
-#define VMADDWEV(NAME, BIT, E1, E2, DO_OP) \
-void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t v) \
-{ \
- int i; \
- VReg *Vd = (VReg *)vd; \
- VReg *Vj = (VReg *)vj; \
- VReg *Vk = (VReg *)vk; \
- typedef __typeof(Vd->E1(0)) TD; \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E1(i) += DO_OP((TD)Vj->E2(2 * i), (TD)Vk->E2(2 * i)); \
- } \
-}
-
-VMADDWEV(vmaddwev_h_b, 16, H, B, DO_MUL)
-VMADDWEV(vmaddwev_w_h, 32, W, H, DO_MUL)
-VMADDWEV(vmaddwev_d_w, 64, D, W, DO_MUL)
-VMADDWEV(vmaddwev_h_bu, 16, UH, UB, DO_MUL)
-VMADDWEV(vmaddwev_w_hu, 32, UW, UH, DO_MUL)
-VMADDWEV(vmaddwev_d_wu, 64, UD, UW, DO_MUL)
-
-#define VMADDWOD(NAME, BIT, E1, E2, DO_OP) \
-void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t v) \
-{ \
- int i; \
- VReg *Vd = (VReg *)vd; \
- VReg *Vj = (VReg *)vj; \
- VReg *Vk = (VReg *)vk; \
- typedef __typeof(Vd->E1(0)) TD; \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E1(i) += DO_OP((TD)Vj->E2(2 * i + 1), \
- (TD)Vk->E2(2 * i + 1)); \
- } \
-}
-
-VMADDWOD(vmaddwod_h_b, 16, H, B, DO_MUL)
-VMADDWOD(vmaddwod_w_h, 32, W, H, DO_MUL)
-VMADDWOD(vmaddwod_d_w, 64, D, W, DO_MUL)
-VMADDWOD(vmaddwod_h_bu, 16, UH, UB, DO_MUL)
-VMADDWOD(vmaddwod_w_hu, 32, UW, UH, DO_MUL)
-VMADDWOD(vmaddwod_d_wu, 64, UD, UW, DO_MUL)
-
-#define VMADDWEV_U_S(NAME, BIT, ES1, EU1, ES2, EU2, DO_OP) \
-void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t v) \
-{ \
- int i; \
- VReg *Vd = (VReg *)vd; \
- VReg *Vj = (VReg *)vj; \
- VReg *Vk = (VReg *)vk; \
- typedef __typeof(Vd->ES1(0)) TS1; \
- typedef __typeof(Vd->EU1(0)) TU1; \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->ES1(i) += DO_OP((TU1)Vj->EU2(2 * i), \
- (TS1)Vk->ES2(2 * i)); \
- } \
-}
-
-VMADDWEV_U_S(vmaddwev_h_bu_b, 16, H, UH, B, UB, DO_MUL)
-VMADDWEV_U_S(vmaddwev_w_hu_h, 32, W, UW, H, UH, DO_MUL)
-VMADDWEV_U_S(vmaddwev_d_wu_w, 64, D, UD, W, UW, DO_MUL)
-
-#define VMADDWOD_U_S(NAME, BIT, ES1, EU1, ES2, EU2, DO_OP) \
-void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t v) \
-{ \
- int i; \
- VReg *Vd = (VReg *)vd; \
- VReg *Vj = (VReg *)vj; \
- VReg *Vk = (VReg *)vk; \
- typedef __typeof(Vd->ES1(0)) TS1; \
- typedef __typeof(Vd->EU1(0)) TU1; \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->ES1(i) += DO_OP((TU1)Vj->EU2(2 * i + 1), \
- (TS1)Vk->ES2(2 * i + 1)); \
- } \
-}
-
-VMADDWOD_U_S(vmaddwod_h_bu_b, 16, H, UH, B, UB, DO_MUL)
-VMADDWOD_U_S(vmaddwod_w_hu_h, 32, W, UW, H, UH, DO_MUL)
-VMADDWOD_U_S(vmaddwod_d_wu_w, 64, D, UD, W, UW, DO_MUL)
-
-#define DO_DIVU(N, M) (unlikely(M == 0) ? 0 : N / M)
-#define DO_REMU(N, M) (unlikely(M == 0) ? 0 : N % M)
-#define DO_DIV(N, M) (unlikely(M == 0) ? 0 :\
- unlikely((N == -N) && (M == (__typeof(N))(-1))) ? N : N / M)
-#define DO_REM(N, M) (unlikely(M == 0) ? 0 :\
- unlikely((N == -N) && (M == (__typeof(N))(-1))) ? 0 : N % M)
-
-#define VDIV(NAME, BIT, E, DO_OP) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t vk) \
-{ \
- int i; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- VReg *Vk = &(env->fpr[vk].vreg); \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E(i) = DO_OP(Vj->E(i), Vk->E(i)); \
- } \
-}
-
-VDIV(vdiv_b, 8, B, DO_DIV)
-VDIV(vdiv_h, 16, H, DO_DIV)
-VDIV(vdiv_w, 32, W, DO_DIV)
-VDIV(vdiv_d, 64, D, DO_DIV)
-VDIV(vdiv_bu, 8, UB, DO_DIVU)
-VDIV(vdiv_hu, 16, UH, DO_DIVU)
-VDIV(vdiv_wu, 32, UW, DO_DIVU)
-VDIV(vdiv_du, 64, UD, DO_DIVU)
-VDIV(vmod_b, 8, B, DO_REM)
-VDIV(vmod_h, 16, H, DO_REM)
-VDIV(vmod_w, 32, W, DO_REM)
-VDIV(vmod_d, 64, D, DO_REM)
-VDIV(vmod_bu, 8, UB, DO_REMU)
-VDIV(vmod_hu, 16, UH, DO_REMU)
-VDIV(vmod_wu, 32, UW, DO_REMU)
-VDIV(vmod_du, 64, UD, DO_REMU)
-
-#define VSAT_S(NAME, BIT, E) \
-void HELPER(NAME)(void *vd, void *vj, uint64_t max, uint32_t v) \
-{ \
- int i; \
- VReg *Vd = (VReg *)vd; \
- VReg *Vj = (VReg *)vj; \
- typedef __typeof(Vd->E(0)) TD; \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E(i) = Vj->E(i) > (TD)max ? (TD)max : \
- Vj->E(i) < (TD)~max ? (TD)~max: Vj->E(i); \
- } \
-}
-
-VSAT_S(vsat_b, 8, B)
-VSAT_S(vsat_h, 16, H)
-VSAT_S(vsat_w, 32, W)
-VSAT_S(vsat_d, 64, D)
-
-#define VSAT_U(NAME, BIT, E) \
-void HELPER(NAME)(void *vd, void *vj, uint64_t max, uint32_t v) \
-{ \
- int i; \
- VReg *Vd = (VReg *)vd; \
- VReg *Vj = (VReg *)vj; \
- typedef __typeof(Vd->E(0)) TD; \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E(i) = Vj->E(i) > (TD)max ? (TD)max : Vj->E(i); \
- } \
-}
-
-VSAT_U(vsat_bu, 8, UB)
-VSAT_U(vsat_hu, 16, UH)
-VSAT_U(vsat_wu, 32, UW)
-VSAT_U(vsat_du, 64, UD)
-
-#define VEXTH(NAME, BIT, E1, E2) \
-void HELPER(NAME)(CPULoongArchState *env, uint32_t vd, uint32_t vj) \
-{ \
- int i; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E1(i) = Vj->E2(i + LSX_LEN/BIT); \
- } \
-}
-
-void HELPER(vexth_q_d)(CPULoongArchState *env, uint32_t vd, uint32_t vj)
-{
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
-
- Vd->Q(0) = int128_makes64(Vj->D(1));
-}
-
-void HELPER(vexth_qu_du)(CPULoongArchState *env, uint32_t vd, uint32_t vj)
-{
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
-
- Vd->Q(0) = int128_make64((uint64_t)Vj->D(1));
-}
-
-VEXTH(vexth_h_b, 16, H, B)
-VEXTH(vexth_w_h, 32, W, H)
-VEXTH(vexth_d_w, 64, D, W)
-VEXTH(vexth_hu_bu, 16, UH, UB)
-VEXTH(vexth_wu_hu, 32, UW, UH)
-VEXTH(vexth_du_wu, 64, UD, UW)
-
-#define DO_SIGNCOV(a, b) (a == 0 ? 0 : a < 0 ? -b : b)
-
-DO_3OP(vsigncov_b, 8, B, DO_SIGNCOV)
-DO_3OP(vsigncov_h, 16, H, DO_SIGNCOV)
-DO_3OP(vsigncov_w, 32, W, DO_SIGNCOV)
-DO_3OP(vsigncov_d, 64, D, DO_SIGNCOV)
-
-static uint64_t do_vmskltz_b(int64_t val)
-{
- uint64_t m = 0x8080808080808080ULL;
- uint64_t c = val & m;
- c |= c << 7;
- c |= c << 14;
- c |= c << 28;
- return c >> 56;
-}
-
-void HELPER(vmskltz_b)(CPULoongArchState *env, uint32_t vd, uint32_t vj)
-{
- uint16_t temp = 0;
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
-
- temp = do_vmskltz_b(Vj->D(0));
- temp |= (do_vmskltz_b(Vj->D(1)) << 8);
- Vd->D(0) = temp;
- Vd->D(1) = 0;
-}
-
-static uint64_t do_vmskltz_h(int64_t val)
-{
- uint64_t m = 0x8000800080008000ULL;
- uint64_t c = val & m;
- c |= c << 15;
- c |= c << 30;
- return c >> 60;
-}
-
-void HELPER(vmskltz_h)(CPULoongArchState *env, uint32_t vd, uint32_t vj)
-{
- uint16_t temp = 0;
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
-
- temp = do_vmskltz_h(Vj->D(0));
- temp |= (do_vmskltz_h(Vj->D(1)) << 4);
- Vd->D(0) = temp;
- Vd->D(1) = 0;
-}
-
-static uint64_t do_vmskltz_w(int64_t val)
-{
- uint64_t m = 0x8000000080000000ULL;
- uint64_t c = val & m;
- c |= c << 31;
- return c >> 62;
-}
-
-void HELPER(vmskltz_w)(CPULoongArchState *env, uint32_t vd, uint32_t vj)
-{
- uint16_t temp = 0;
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
-
- temp = do_vmskltz_w(Vj->D(0));
- temp |= (do_vmskltz_w(Vj->D(1)) << 2);
- Vd->D(0) = temp;
- Vd->D(1) = 0;
-}
-
-static uint64_t do_vmskltz_d(int64_t val)
-{
- return (uint64_t)val >> 63;
-}
-void HELPER(vmskltz_d)(CPULoongArchState *env, uint32_t vd, uint32_t vj)
-{
- uint16_t temp = 0;
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
-
- temp = do_vmskltz_d(Vj->D(0));
- temp |= (do_vmskltz_d(Vj->D(1)) << 1);
- Vd->D(0) = temp;
- Vd->D(1) = 0;
-}
-
-void HELPER(vmskgez_b)(CPULoongArchState *env, uint32_t vd, uint32_t vj)
-{
- uint16_t temp = 0;
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
-
- temp = do_vmskltz_b(Vj->D(0));
- temp |= (do_vmskltz_b(Vj->D(1)) << 8);
- Vd->D(0) = (uint16_t)(~temp);
- Vd->D(1) = 0;
-}
-
-static uint64_t do_vmskez_b(uint64_t a)
-{
- uint64_t m = 0x7f7f7f7f7f7f7f7fULL;
- uint64_t c = ~(((a & m) + m) | a | m);
- c |= c << 7;
- c |= c << 14;
- c |= c << 28;
- return c >> 56;
-}
-
-void HELPER(vmsknz_b)(CPULoongArchState *env, uint32_t vd, uint32_t vj)
-{
- uint16_t temp = 0;
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
-
- temp = do_vmskez_b(Vj->D(0));
- temp |= (do_vmskez_b(Vj->D(1)) << 8);
- Vd->D(0) = (uint16_t)(~temp);
- Vd->D(1) = 0;
-}
-
-void HELPER(vnori_b)(void *vd, void *vj, uint64_t imm, uint32_t v)
-{
- int i;
- VReg *Vd = (VReg *)vd;
- VReg *Vj = (VReg *)vj;
-
- for (i = 0; i < LSX_LEN/8; i++) {
- Vd->B(i) = ~(Vj->B(i) | (uint8_t)imm);
- }
-}
-
-#define VSLLWIL(NAME, BIT, E1, E2) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t imm) \
-{ \
- int i; \
- VReg temp; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- typedef __typeof(temp.E1(0)) TD; \
- \
- temp.D(0) = 0; \
- temp.D(1) = 0; \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- temp.E1(i) = (TD)Vj->E2(i) << (imm % BIT); \
- } \
- *Vd = temp; \
-}
-
-void HELPER(vextl_q_d)(CPULoongArchState *env, uint32_t vd, uint32_t vj)
-{
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
-
- Vd->Q(0) = int128_makes64(Vj->D(0));
-}
-
-void HELPER(vextl_qu_du)(CPULoongArchState *env, uint32_t vd, uint32_t vj)
-{
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
-
- Vd->Q(0) = int128_make64(Vj->D(0));
-}
-
-VSLLWIL(vsllwil_h_b, 16, H, B)
-VSLLWIL(vsllwil_w_h, 32, W, H)
-VSLLWIL(vsllwil_d_w, 64, D, W)
-VSLLWIL(vsllwil_hu_bu, 16, UH, UB)
-VSLLWIL(vsllwil_wu_hu, 32, UW, UH)
-VSLLWIL(vsllwil_du_wu, 64, UD, UW)
-
-#define do_vsrlr(E, T) \
-static T do_vsrlr_ ##E(T s1, int sh) \
-{ \
- if (sh == 0) { \
- return s1; \
- } else { \
- return (s1 >> sh) + ((s1 >> (sh - 1)) & 0x1); \
- } \
-}
-
-do_vsrlr(B, uint8_t)
-do_vsrlr(H, uint16_t)
-do_vsrlr(W, uint32_t)
-do_vsrlr(D, uint64_t)
-
-#define VSRLR(NAME, BIT, T, E) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t vk) \
-{ \
- int i; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- VReg *Vk = &(env->fpr[vk].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E(i) = do_vsrlr_ ## E(Vj->E(i), ((T)Vk->E(i))%BIT); \
- } \
-}
-
-VSRLR(vsrlr_b, 8, uint8_t, B)
-VSRLR(vsrlr_h, 16, uint16_t, H)
-VSRLR(vsrlr_w, 32, uint32_t, W)
-VSRLR(vsrlr_d, 64, uint64_t, D)
-
-#define VSRLRI(NAME, BIT, E) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t imm) \
-{ \
- int i; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E(i) = do_vsrlr_ ## E(Vj->E(i), imm); \
- } \
-}
-
-VSRLRI(vsrlri_b, 8, B)
-VSRLRI(vsrlri_h, 16, H)
-VSRLRI(vsrlri_w, 32, W)
-VSRLRI(vsrlri_d, 64, D)
-
-#define do_vsrar(E, T) \
-static T do_vsrar_ ##E(T s1, int sh) \
-{ \
- if (sh == 0) { \
- return s1; \
- } else { \
- return (s1 >> sh) + ((s1 >> (sh - 1)) & 0x1); \
- } \
-}
-
-do_vsrar(B, int8_t)
-do_vsrar(H, int16_t)
-do_vsrar(W, int32_t)
-do_vsrar(D, int64_t)
-
-#define VSRAR(NAME, BIT, T, E) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t vk) \
-{ \
- int i; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- VReg *Vk = &(env->fpr[vk].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E(i) = do_vsrar_ ## E(Vj->E(i), ((T)Vk->E(i))%BIT); \
- } \
-}
-
-VSRAR(vsrar_b, 8, uint8_t, B)
-VSRAR(vsrar_h, 16, uint16_t, H)
-VSRAR(vsrar_w, 32, uint32_t, W)
-VSRAR(vsrar_d, 64, uint64_t, D)
-
-#define VSRARI(NAME, BIT, E) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t imm) \
-{ \
- int i; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E(i) = do_vsrar_ ## E(Vj->E(i), imm); \
- } \
-}
-
-VSRARI(vsrari_b, 8, B)
-VSRARI(vsrari_h, 16, H)
-VSRARI(vsrari_w, 32, W)
-VSRARI(vsrari_d, 64, D)
-
-#define R_SHIFT(a, b) (a >> b)
-
-#define VSRLN(NAME, BIT, T, E1, E2) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t vk) \
-{ \
- int i; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- VReg *Vk = &(env->fpr[vk].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E1(i) = R_SHIFT((T)Vj->E2(i),((T)Vk->E2(i)) % BIT); \
- } \
- Vd->D(1) = 0; \
-}
-
-VSRLN(vsrln_b_h, 16, uint16_t, B, H)
-VSRLN(vsrln_h_w, 32, uint32_t, H, W)
-VSRLN(vsrln_w_d, 64, uint64_t, W, D)
-
-#define VSRAN(NAME, BIT, T, E1, E2) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t vk) \
-{ \
- int i; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- VReg *Vk = &(env->fpr[vk].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E1(i) = R_SHIFT(Vj->E2(i), ((T)Vk->E2(i)) % BIT); \
- } \
- Vd->D(1) = 0; \
-}
-
-VSRAN(vsran_b_h, 16, uint16_t, B, H)
-VSRAN(vsran_h_w, 32, uint32_t, H, W)
-VSRAN(vsran_w_d, 64, uint64_t, W, D)
-
-#define VSRLNI(NAME, BIT, T, E1, E2) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t imm) \
-{ \
- int i, max; \
- VReg temp; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- \
- temp.D(0) = 0; \
- temp.D(1) = 0; \
- max = LSX_LEN/BIT; \
- for (i = 0; i < max; i++) { \
- temp.E1(i) = R_SHIFT((T)Vj->E2(i), imm); \
- temp.E1(i + max) = R_SHIFT((T)Vd->E2(i), imm); \
- } \
- *Vd = temp; \
-}
-
-void HELPER(vsrlni_d_q)(CPULoongArchState *env,
- uint32_t vd, uint32_t vj, uint32_t imm)
-{
- VReg temp;
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
-
- temp.D(0) = 0;
- temp.D(1) = 0;
- temp.D(0) = int128_getlo(int128_urshift(Vj->Q(0), imm % 128));
- temp.D(1) = int128_getlo(int128_urshift(Vd->Q(0), imm % 128));
- *Vd = temp;
-}
-
-VSRLNI(vsrlni_b_h, 16, uint16_t, B, H)
-VSRLNI(vsrlni_h_w, 32, uint32_t, H, W)
-VSRLNI(vsrlni_w_d, 64, uint64_t, W, D)
-
-#define VSRANI(NAME, BIT, E1, E2) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t imm) \
-{ \
- int i, max; \
- VReg temp; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- \
- temp.D(0) = 0; \
- temp.D(1) = 0; \
- max = LSX_LEN/BIT; \
- for (i = 0; i < max; i++) { \
- temp.E1(i) = R_SHIFT(Vj->E2(i), imm); \
- temp.E1(i + max) = R_SHIFT(Vd->E2(i), imm); \
- } \
- *Vd = temp; \
-}
-
-void HELPER(vsrani_d_q)(CPULoongArchState *env,
- uint32_t vd, uint32_t vj, uint32_t imm)
-{
- VReg temp;
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
-
- temp.D(0) = 0;
- temp.D(1) = 0;
- temp.D(0) = int128_getlo(int128_rshift(Vj->Q(0), imm % 128));
- temp.D(1) = int128_getlo(int128_rshift(Vd->Q(0), imm % 128));
- *Vd = temp;
-}
-
-VSRANI(vsrani_b_h, 16, B, H)
-VSRANI(vsrani_h_w, 32, H, W)
-VSRANI(vsrani_w_d, 64, W, D)
-
-#define VSRLRN(NAME, BIT, T, E1, E2) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t vk) \
-{ \
- int i; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- VReg *Vk = &(env->fpr[vk].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E1(i) = do_vsrlr_ ## E2(Vj->E2(i), ((T)Vk->E2(i))%BIT); \
- } \
- Vd->D(1) = 0; \
-}
-
-VSRLRN(vsrlrn_b_h, 16, uint16_t, B, H)
-VSRLRN(vsrlrn_h_w, 32, uint32_t, H, W)
-VSRLRN(vsrlrn_w_d, 64, uint64_t, W, D)
-
-#define VSRARN(NAME, BIT, T, E1, E2) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t vk) \
-{ \
- int i; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- VReg *Vk = &(env->fpr[vk].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E1(i) = do_vsrar_ ## E2(Vj->E2(i), ((T)Vk->E2(i))%BIT); \
- } \
- Vd->D(1) = 0; \
-}
-
-VSRARN(vsrarn_b_h, 16, uint8_t, B, H)
-VSRARN(vsrarn_h_w, 32, uint16_t, H, W)
-VSRARN(vsrarn_w_d, 64, uint32_t, W, D)
-
-#define VSRLRNI(NAME, BIT, E1, E2) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t imm) \
-{ \
- int i, max; \
- VReg temp; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- \
- temp.D(0) = 0; \
- temp.D(1) = 0; \
- max = LSX_LEN/BIT; \
- for (i = 0; i < max; i++) { \
- temp.E1(i) = do_vsrlr_ ## E2(Vj->E2(i), imm); \
- temp.E1(i + max) = do_vsrlr_ ## E2(Vd->E2(i), imm); \
- } \
- *Vd = temp; \
-}
-
-void HELPER(vsrlrni_d_q)(CPULoongArchState *env,
- uint32_t vd, uint32_t vj, uint32_t imm)
-{
- VReg temp;
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
- Int128 r1, r2;
-
- if (imm == 0) {
- temp.D(0) = int128_getlo(Vj->Q(0));
- temp.D(1) = int128_getlo(Vd->Q(0));
- } else {
- r1 = int128_and(int128_urshift(Vj->Q(0), (imm -1)), int128_one());
- r2 = int128_and(int128_urshift(Vd->Q(0), (imm -1)), int128_one());
-
- temp.D(0) = int128_getlo(int128_add(int128_urshift(Vj->Q(0), imm), r1));
- temp.D(1) = int128_getlo(int128_add(int128_urshift(Vd->Q(0), imm), r2));
- }
- *Vd = temp;
-}
-
-VSRLRNI(vsrlrni_b_h, 16, B, H)
-VSRLRNI(vsrlrni_h_w, 32, H, W)
-VSRLRNI(vsrlrni_w_d, 64, W, D)
-
-#define VSRARNI(NAME, BIT, E1, E2) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t imm) \
-{ \
- int i, max; \
- VReg temp; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- \
- temp.D(0) = 0; \
- temp.D(1) = 0; \
- max = LSX_LEN/BIT; \
- for (i = 0; i < max; i++) { \
- temp.E1(i) = do_vsrar_ ## E2(Vj->E2(i), imm); \
- temp.E1(i + max) = do_vsrar_ ## E2(Vd->E2(i), imm); \
- } \
- *Vd = temp; \
-}
-
-void HELPER(vsrarni_d_q)(CPULoongArchState *env,
- uint32_t vd, uint32_t vj, uint32_t imm)
-{
- VReg temp;
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
- Int128 r1, r2;
-
- if (imm == 0) {
- temp.D(0) = int128_getlo(Vj->Q(0));
- temp.D(1) = int128_getlo(Vd->Q(0));
- } else {
- r1 = int128_and(int128_rshift(Vj->Q(0), (imm -1)), int128_one());
- r2 = int128_and(int128_rshift(Vd->Q(0), (imm -1)), int128_one());
-
- temp.D(0) = int128_getlo(int128_add(int128_rshift(Vj->Q(0), imm), r1));
- temp.D(1) = int128_getlo(int128_add(int128_rshift(Vd->Q(0), imm), r2));
- }
- *Vd = temp;
-}
-
-VSRARNI(vsrarni_b_h, 16, B, H)
-VSRARNI(vsrarni_h_w, 32, H, W)
-VSRARNI(vsrarni_w_d, 64, W, D)
-
-#define SSRLNS(NAME, T1, T2, T3) \
-static T1 do_ssrlns_ ## NAME(T2 e2, int sa, int sh) \
-{ \
- T1 shft_res; \
- if (sa == 0) { \
- shft_res = e2; \
- } else { \
- shft_res = (((T1)e2) >> sa); \
- } \
- T3 mask; \
- mask = (1ull << sh) -1; \
- if (shft_res > mask) { \
- return mask; \
- } else { \
- return shft_res; \
- } \
-}
-
-SSRLNS(B, uint16_t, int16_t, uint8_t)
-SSRLNS(H, uint32_t, int32_t, uint16_t)
-SSRLNS(W, uint64_t, int64_t, uint32_t)
-
-#define VSSRLN(NAME, BIT, T, E1, E2) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t vk) \
-{ \
- int i; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- VReg *Vk = &(env->fpr[vk].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E1(i) = do_ssrlns_ ## E1(Vj->E2(i), (T)Vk->E2(i)% BIT, BIT/2 -1); \
- } \
- Vd->D(1) = 0; \
-}
-
-VSSRLN(vssrln_b_h, 16, uint16_t, B, H)
-VSSRLN(vssrln_h_w, 32, uint32_t, H, W)
-VSSRLN(vssrln_w_d, 64, uint64_t, W, D)
-
-#define SSRANS(E, T1, T2) \
-static T1 do_ssrans_ ## E(T1 e2, int sa, int sh) \
-{ \
- T1 shft_res; \
- if (sa == 0) { \
- shft_res = e2; \
- } else { \
- shft_res = e2 >> sa; \
- } \
- T2 mask; \
- mask = (1ll << sh) -1; \
- if (shft_res > mask) { \
- return mask; \
- } else if (shft_res < -(mask +1)) { \
- return ~mask; \
- } else { \
- return shft_res; \
- } \
-}
-
-SSRANS(B, int16_t, int8_t)
-SSRANS(H, int32_t, int16_t)
-SSRANS(W, int64_t, int32_t)
-
-#define VSSRAN(NAME, BIT, T, E1, E2) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t vk) \
-{ \
- int i; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- VReg *Vk = &(env->fpr[vk].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E1(i) = do_ssrans_ ## E1(Vj->E2(i), (T)Vk->E2(i)%BIT, BIT/2 -1); \
- } \
- Vd->D(1) = 0; \
-}
-
-VSSRAN(vssran_b_h, 16, uint16_t, B, H)
-VSSRAN(vssran_h_w, 32, uint32_t, H, W)
-VSSRAN(vssran_w_d, 64, uint64_t, W, D)
-
-#define SSRLNU(E, T1, T2, T3) \
-static T1 do_ssrlnu_ ## E(T3 e2, int sa, int sh) \
-{ \
- T1 shft_res; \
- if (sa == 0) { \
- shft_res = e2; \
- } else { \
- shft_res = (((T1)e2) >> sa); \
- } \
- T2 mask; \
- mask = (1ull << sh) -1; \
- if (shft_res > mask) { \
- return mask; \
- } else { \
- return shft_res; \
- } \
-}
-
-SSRLNU(B, uint16_t, uint8_t, int16_t)
-SSRLNU(H, uint32_t, uint16_t, int32_t)
-SSRLNU(W, uint64_t, uint32_t, int64_t)
-
-#define VSSRLNU(NAME, BIT, T, E1, E2) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t vk) \
-{ \
- int i; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- VReg *Vk = &(env->fpr[vk].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E1(i) = do_ssrlnu_ ## E1(Vj->E2(i), (T)Vk->E2(i)%BIT, BIT/2); \
- } \
- Vd->D(1) = 0; \
-}
-
-VSSRLNU(vssrln_bu_h, 16, uint16_t, B, H)
-VSSRLNU(vssrln_hu_w, 32, uint32_t, H, W)
-VSSRLNU(vssrln_wu_d, 64, uint64_t, W, D)
-
-#define SSRANU(E, T1, T2, T3) \
-static T1 do_ssranu_ ## E(T3 e2, int sa, int sh) \
-{ \
- T1 shft_res; \
- if (sa == 0) { \
- shft_res = e2; \
- } else { \
- shft_res = e2 >> sa; \
- } \
- if (e2 < 0) { \
- shft_res = 0; \
- } \
- T2 mask; \
- mask = (1ull << sh) -1; \
- if (shft_res > mask) { \
- return mask; \
- } else { \
- return shft_res; \
- } \
-}
-
-SSRANU(B, uint16_t, uint8_t, int16_t)
-SSRANU(H, uint32_t, uint16_t, int32_t)
-SSRANU(W, uint64_t, uint32_t, int64_t)
-
-#define VSSRANU(NAME, BIT, T, E1, E2) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t vk) \
-{ \
- int i; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- VReg *Vk = &(env->fpr[vk].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E1(i) = do_ssranu_ ## E1(Vj->E2(i), (T)Vk->E2(i)%BIT, BIT/2); \
- } \
- Vd->D(1) = 0; \
-}
-
-VSSRANU(vssran_bu_h, 16, uint16_t, B, H)
-VSSRANU(vssran_hu_w, 32, uint32_t, H, W)
-VSSRANU(vssran_wu_d, 64, uint64_t, W, D)
-
-#define VSSRLNI(NAME, BIT, E1, E2) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t imm) \
-{ \
- int i; \
- VReg temp; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- temp.E1(i) = do_ssrlns_ ## E1(Vj->E2(i), imm, BIT/2 -1); \
- temp.E1(i + LSX_LEN/BIT) = do_ssrlns_ ## E1(Vd->E2(i), imm, BIT/2 -1);\
- } \
- *Vd = temp; \
-}
-
-void HELPER(vssrlni_d_q)(CPULoongArchState *env,
- uint32_t vd, uint32_t vj, uint32_t imm)
-{
- Int128 shft_res1, shft_res2, mask;
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
-
- if (imm == 0) {
- shft_res1 = Vj->Q(0);
- shft_res2 = Vd->Q(0);
- } else {
- shft_res1 = int128_urshift(Vj->Q(0), imm);
- shft_res2 = int128_urshift(Vd->Q(0), imm);
- }
- mask = int128_sub(int128_lshift(int128_one(), 63), int128_one());
-
- if (int128_ult(mask, shft_res1)) {
- Vd->D(0) = int128_getlo(mask);
- }else {
- Vd->D(0) = int128_getlo(shft_res1);
- }
-
- if (int128_ult(mask, shft_res2)) {
- Vd->D(1) = int128_getlo(mask);
- }else {
- Vd->D(1) = int128_getlo(shft_res2);
- }
-}
-
-VSSRLNI(vssrlni_b_h, 16, B, H)
-VSSRLNI(vssrlni_h_w, 32, H, W)
-VSSRLNI(vssrlni_w_d, 64, W, D)
-
-#define VSSRANI(NAME, BIT, E1, E2) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t imm) \
-{ \
- int i; \
- VReg temp; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- temp.E1(i) = do_ssrans_ ## E1(Vj->E2(i), imm, BIT/2 -1); \
- temp.E1(i + LSX_LEN/BIT) = do_ssrans_ ## E1(Vd->E2(i), imm, BIT/2 -1); \
- } \
- *Vd = temp; \
-}
-
-void HELPER(vssrani_d_q)(CPULoongArchState *env,
- uint32_t vd, uint32_t vj, uint32_t imm)
-{
- Int128 shft_res1, shft_res2, mask, min;
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
-
- if (imm == 0) {
- shft_res1 = Vj->Q(0);
- shft_res2 = Vd->Q(0);
- } else {
- shft_res1 = int128_rshift(Vj->Q(0), imm);
- shft_res2 = int128_rshift(Vd->Q(0), imm);
- }
- mask = int128_sub(int128_lshift(int128_one(), 63), int128_one());
- min = int128_lshift(int128_one(), 63);
-
- if (int128_gt(shft_res1, mask)) {
- Vd->D(0) = int128_getlo(mask);
- } else if (int128_lt(shft_res1, int128_neg(min))) {
- Vd->D(0) = int128_getlo(min);
- } else {
- Vd->D(0) = int128_getlo(shft_res1);
- }
-
- if (int128_gt(shft_res2, mask)) {
- Vd->D(1) = int128_getlo(mask);
- } else if (int128_lt(shft_res2, int128_neg(min))) {
- Vd->D(1) = int128_getlo(min);
- } else {
- Vd->D(1) = int128_getlo(shft_res2);
- }
-}
-
-VSSRANI(vssrani_b_h, 16, B, H)
-VSSRANI(vssrani_h_w, 32, H, W)
-VSSRANI(vssrani_w_d, 64, W, D)
-
-#define VSSRLNUI(NAME, BIT, E1, E2) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t imm) \
-{ \
- int i; \
- VReg temp; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- temp.E1(i) = do_ssrlnu_ ## E1(Vj->E2(i), imm, BIT/2); \
- temp.E1(i + LSX_LEN/BIT) = do_ssrlnu_ ## E1(Vd->E2(i), imm, BIT/2); \
- } \
- *Vd = temp; \
-}
-
-void HELPER(vssrlni_du_q)(CPULoongArchState *env,
- uint32_t vd, uint32_t vj, uint32_t imm)
-{
- Int128 shft_res1, shft_res2, mask;
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
-
- if (imm == 0) {
- shft_res1 = Vj->Q(0);
- shft_res2 = Vd->Q(0);
- } else {
- shft_res1 = int128_urshift(Vj->Q(0), imm);
- shft_res2 = int128_urshift(Vd->Q(0), imm);
- }
- mask = int128_sub(int128_lshift(int128_one(), 64), int128_one());
-
- if (int128_ult(mask, shft_res1)) {
- Vd->D(0) = int128_getlo(mask);
- }else {
- Vd->D(0) = int128_getlo(shft_res1);
- }
-
- if (int128_ult(mask, shft_res2)) {
- Vd->D(1) = int128_getlo(mask);
- }else {
- Vd->D(1) = int128_getlo(shft_res2);
- }
-}
-
-VSSRLNUI(vssrlni_bu_h, 16, B, H)
-VSSRLNUI(vssrlni_hu_w, 32, H, W)
-VSSRLNUI(vssrlni_wu_d, 64, W, D)
-
-#define VSSRANUI(NAME, BIT, E1, E2) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t imm) \
-{ \
- int i; \
- VReg temp; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- temp.E1(i) = do_ssranu_ ## E1(Vj->E2(i), imm, BIT/2); \
- temp.E1(i + LSX_LEN/BIT) = do_ssranu_ ## E1(Vd->E2(i), imm, BIT/2); \
- } \
- *Vd = temp; \
-}
-
-void HELPER(vssrani_du_q)(CPULoongArchState *env,
- uint32_t vd, uint32_t vj, uint32_t imm)
-{
- Int128 shft_res1, shft_res2, mask;
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
-
- if (imm == 0) {
- shft_res1 = Vj->Q(0);
- shft_res2 = Vd->Q(0);
- } else {
- shft_res1 = int128_rshift(Vj->Q(0), imm);
- shft_res2 = int128_rshift(Vd->Q(0), imm);
- }
-
- if (int128_lt(Vj->Q(0), int128_zero())) {
- shft_res1 = int128_zero();
- }
-
- if (int128_lt(Vd->Q(0), int128_zero())) {
- shft_res2 = int128_zero();
- }
-
- mask = int128_sub(int128_lshift(int128_one(), 64), int128_one());
-
- if (int128_ult(mask, shft_res1)) {
- Vd->D(0) = int128_getlo(mask);
- }else {
- Vd->D(0) = int128_getlo(shft_res1);
- }
-
- if (int128_ult(mask, shft_res2)) {
- Vd->D(1) = int128_getlo(mask);
- }else {
- Vd->D(1) = int128_getlo(shft_res2);
- }
-}
-
-VSSRANUI(vssrani_bu_h, 16, B, H)
-VSSRANUI(vssrani_hu_w, 32, H, W)
-VSSRANUI(vssrani_wu_d, 64, W, D)
-
-#define SSRLRNS(E1, E2, T1, T2, T3) \
-static T1 do_ssrlrns_ ## E1(T2 e2, int sa, int sh) \
-{ \
- T1 shft_res; \
- \
- shft_res = do_vsrlr_ ## E2(e2, sa); \
- T1 mask; \
- mask = (1ull << sh) -1; \
- if (shft_res > mask) { \
- return mask; \
- } else { \
- return shft_res; \
- } \
-}
-
-SSRLRNS(B, H, uint16_t, int16_t, uint8_t)
-SSRLRNS(H, W, uint32_t, int32_t, uint16_t)
-SSRLRNS(W, D, uint64_t, int64_t, uint32_t)
-
-#define VSSRLRN(NAME, BIT, T, E1, E2) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t vk) \
-{ \
- int i; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- VReg *Vk = &(env->fpr[vk].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E1(i) = do_ssrlrns_ ## E1(Vj->E2(i), (T)Vk->E2(i)%BIT, BIT/2 -1); \
- } \
- Vd->D(1) = 0; \
-}
-
-VSSRLRN(vssrlrn_b_h, 16, uint16_t, B, H)
-VSSRLRN(vssrlrn_h_w, 32, uint32_t, H, W)
-VSSRLRN(vssrlrn_w_d, 64, uint64_t, W, D)
-
-#define SSRARNS(E1, E2, T1, T2) \
-static T1 do_ssrarns_ ## E1(T1 e2, int sa, int sh) \
-{ \
- T1 shft_res; \
- \
- shft_res = do_vsrar_ ## E2(e2, sa); \
- T2 mask; \
- mask = (1ll << sh) -1; \
- if (shft_res > mask) { \
- return mask; \
- } else if (shft_res < -(mask +1)) { \
- return ~mask; \
- } else { \
- return shft_res; \
- } \
-}
-
-SSRARNS(B, H, int16_t, int8_t)
-SSRARNS(H, W, int32_t, int16_t)
-SSRARNS(W, D, int64_t, int32_t)
-
-#define VSSRARN(NAME, BIT, T, E1, E2) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t vk) \
-{ \
- int i; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- VReg *Vk = &(env->fpr[vk].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E1(i) = do_ssrarns_ ## E1(Vj->E2(i), (T)Vk->E2(i)%BIT, BIT/2 -1); \
- } \
- Vd->D(1) = 0; \
-}
-
-VSSRARN(vssrarn_b_h, 16, uint16_t, B, H)
-VSSRARN(vssrarn_h_w, 32, uint32_t, H, W)
-VSSRARN(vssrarn_w_d, 64, uint64_t, W, D)
-
-#define SSRLRNU(E1, E2, T1, T2, T3) \
-static T1 do_ssrlrnu_ ## E1(T3 e2, int sa, int sh) \
-{ \
- T1 shft_res; \
- \
- shft_res = do_vsrlr_ ## E2(e2, sa); \
- \
- T2 mask; \
- mask = (1ull << sh) -1; \
- if (shft_res > mask) { \
- return mask; \
- } else { \
- return shft_res; \
- } \
-}
-
-SSRLRNU(B, H, uint16_t, uint8_t, int16_t)
-SSRLRNU(H, W, uint32_t, uint16_t, int32_t)
-SSRLRNU(W, D, uint64_t, uint32_t, int64_t)
-
-#define VSSRLRNU(NAME, BIT, T, E1, E2) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t vk) \
-{ \
- int i; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- VReg *Vk = &(env->fpr[vk].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E1(i) = do_ssrlrnu_ ## E1(Vj->E2(i), (T)Vk->E2(i)%BIT, BIT/2); \
- } \
- Vd->D(1) = 0; \
-}
-
-VSSRLRNU(vssrlrn_bu_h, 16, uint16_t, B, H)
-VSSRLRNU(vssrlrn_hu_w, 32, uint32_t, H, W)
-VSSRLRNU(vssrlrn_wu_d, 64, uint64_t, W, D)
-
-#define SSRARNU(E1, E2, T1, T2, T3) \
-static T1 do_ssrarnu_ ## E1(T3 e2, int sa, int sh) \
-{ \
- T1 shft_res; \
- \
- if (e2 < 0) { \
- shft_res = 0; \
- } else { \
- shft_res = do_vsrar_ ## E2(e2, sa); \
- } \
- T2 mask; \
- mask = (1ull << sh) -1; \
- if (shft_res > mask) { \
- return mask; \
- } else { \
- return shft_res; \
- } \
-}
-
-SSRARNU(B, H, uint16_t, uint8_t, int16_t)
-SSRARNU(H, W, uint32_t, uint16_t, int32_t)
-SSRARNU(W, D, uint64_t, uint32_t, int64_t)
-
-#define VSSRARNU(NAME, BIT, T, E1, E2) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t vk) \
-{ \
- int i; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- VReg *Vk = &(env->fpr[vk].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E1(i) = do_ssrarnu_ ## E1(Vj->E2(i), (T)Vk->E2(i)%BIT, BIT/2); \
- } \
- Vd->D(1) = 0; \
-}
-
-VSSRARNU(vssrarn_bu_h, 16, uint16_t, B, H)
-VSSRARNU(vssrarn_hu_w, 32, uint32_t, H, W)
-VSSRARNU(vssrarn_wu_d, 64, uint64_t, W, D)
-
-#define VSSRLRNI(NAME, BIT, E1, E2) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t imm) \
-{ \
- int i; \
- VReg temp; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- temp.E1(i) = do_ssrlrns_ ## E1(Vj->E2(i), imm, BIT/2 -1); \
- temp.E1(i + LSX_LEN/BIT) = do_ssrlrns_ ## E1(Vd->E2(i), imm, BIT/2 -1);\
- } \
- *Vd = temp; \
-}
-
-#define VSSRLRNI_Q(NAME, sh) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t imm) \
-{ \
- Int128 shft_res1, shft_res2, mask, r1, r2; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- \
- if (imm == 0) { \
- shft_res1 = Vj->Q(0); \
- shft_res2 = Vd->Q(0); \
- } else { \
- r1 = int128_and(int128_urshift(Vj->Q(0), (imm -1)), int128_one()); \
- r2 = int128_and(int128_urshift(Vd->Q(0), (imm -1)), int128_one()); \
- \
- shft_res1 = (int128_add(int128_urshift(Vj->Q(0), imm), r1)); \
- shft_res2 = (int128_add(int128_urshift(Vd->Q(0), imm), r2)); \
- } \
- \
- mask = int128_sub(int128_lshift(int128_one(), sh), int128_one()); \
- \
- if (int128_ult(mask, shft_res1)) { \
- Vd->D(0) = int128_getlo(mask); \
- }else { \
- Vd->D(0) = int128_getlo(shft_res1); \
- } \
- \
- if (int128_ult(mask, shft_res2)) { \
- Vd->D(1) = int128_getlo(mask); \
- }else { \
- Vd->D(1) = int128_getlo(shft_res2); \
- } \
-}
-
-VSSRLRNI(vssrlrni_b_h, 16, B, H)
-VSSRLRNI(vssrlrni_h_w, 32, H, W)
-VSSRLRNI(vssrlrni_w_d, 64, W, D)
-VSSRLRNI_Q(vssrlrni_d_q, 63)
-
-#define VSSRARNI(NAME, BIT, E1, E2) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t imm) \
-{ \
- int i; \
- VReg temp; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- temp.E1(i) = do_ssrarns_ ## E1(Vj->E2(i), imm, BIT/2 -1); \
- temp.E1(i + LSX_LEN/BIT) = do_ssrarns_ ## E1(Vd->E2(i), imm, BIT/2 -1); \
- } \
- *Vd = temp; \
-}
-
-void HELPER(vssrarni_d_q)(CPULoongArchState *env,
- uint32_t vd, uint32_t vj, uint32_t imm)
-{
- Int128 shft_res1, shft_res2, mask1, mask2, r1, r2;
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
-
- if (imm == 0) {
- shft_res1 = Vj->Q(0);
- shft_res2 = Vd->Q(0);
- } else {
- r1 = int128_and(int128_rshift(Vj->Q(0), (imm -1)), int128_one());
- r2 = int128_and(int128_rshift(Vd->Q(0), (imm -1)), int128_one());
-
- shft_res1 = int128_add(int128_rshift(Vj->Q(0), imm), r1);
- shft_res2 = int128_add(int128_rshift(Vd->Q(0), imm), r2);
- }
-
- mask1 = int128_sub(int128_lshift(int128_one(), 63), int128_one());
- mask2 = int128_lshift(int128_one(), 63);
-
- if (int128_gt(shft_res1, mask1)) {
- Vd->D(0) = int128_getlo(mask1);
- } else if (int128_lt(shft_res1, int128_neg(mask2))) {
- Vd->D(0) = int128_getlo(mask2);
- } else {
- Vd->D(0) = int128_getlo(shft_res1);
- }
-
- if (int128_gt(shft_res2, mask1)) {
- Vd->D(1) = int128_getlo(mask1);
- } else if (int128_lt(shft_res2, int128_neg(mask2))) {
- Vd->D(1) = int128_getlo(mask2);
- } else {
- Vd->D(1) = int128_getlo(shft_res2);
- }
-}
-
-VSSRARNI(vssrarni_b_h, 16, B, H)
-VSSRARNI(vssrarni_h_w, 32, H, W)
-VSSRARNI(vssrarni_w_d, 64, W, D)
-
-#define VSSRLRNUI(NAME, BIT, E1, E2) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t imm) \
-{ \
- int i; \
- VReg temp; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- temp.E1(i) = do_ssrlrnu_ ## E1(Vj->E2(i), imm, BIT/2); \
- temp.E1(i + LSX_LEN/BIT) = do_ssrlrnu_ ## E1(Vd->E2(i), imm, BIT/2); \
- } \
- *Vd = temp; \
-}
-
-VSSRLRNUI(vssrlrni_bu_h, 16, B, H)
-VSSRLRNUI(vssrlrni_hu_w, 32, H, W)
-VSSRLRNUI(vssrlrni_wu_d, 64, W, D)
-VSSRLRNI_Q(vssrlrni_du_q, 64)
-
-#define VSSRARNUI(NAME, BIT, E1, E2) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t imm) \
-{ \
- int i; \
- VReg temp; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- temp.E1(i) = do_ssrarnu_ ## E1(Vj->E2(i), imm, BIT/2); \
- temp.E1(i + LSX_LEN/BIT) = do_ssrarnu_ ## E1(Vd->E2(i), imm, BIT/2); \
- } \
- *Vd = temp; \
-}
-
-void HELPER(vssrarni_du_q)(CPULoongArchState *env,
- uint32_t vd, uint32_t vj, uint32_t imm)
-{
- Int128 shft_res1, shft_res2, mask1, mask2, r1, r2;
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
-
- if (imm == 0) {
- shft_res1 = Vj->Q(0);
- shft_res2 = Vd->Q(0);
- } else {
- r1 = int128_and(int128_rshift(Vj->Q(0), (imm -1)), int128_one());
- r2 = int128_and(int128_rshift(Vd->Q(0), (imm -1)), int128_one());
-
- shft_res1 = int128_add(int128_rshift(Vj->Q(0), imm), r1);
- shft_res2 = int128_add(int128_rshift(Vd->Q(0), imm), r2);
- }
-
- if (int128_lt(Vj->Q(0), int128_zero())) {
- shft_res1 = int128_zero();
- }
- if (int128_lt(Vd->Q(0), int128_zero())) {
- shft_res2 = int128_zero();
- }
-
- mask1 = int128_sub(int128_lshift(int128_one(), 64), int128_one());
- mask2 = int128_lshift(int128_one(), 64);
-
- if (int128_gt(shft_res1, mask1)) {
- Vd->D(0) = int128_getlo(mask1);
- } else if (int128_lt(shft_res1, int128_neg(mask2))) {
- Vd->D(0) = int128_getlo(mask2);
- } else {
- Vd->D(0) = int128_getlo(shft_res1);
- }
-
- if (int128_gt(shft_res2, mask1)) {
- Vd->D(1) = int128_getlo(mask1);
- } else if (int128_lt(shft_res2, int128_neg(mask2))) {
- Vd->D(1) = int128_getlo(mask2);
- } else {
- Vd->D(1) = int128_getlo(shft_res2);
- }
-}
-
-VSSRARNUI(vssrarni_bu_h, 16, B, H)
-VSSRARNUI(vssrarni_hu_w, 32, H, W)
-VSSRARNUI(vssrarni_wu_d, 64, W, D)
-
-#define DO_2OP(NAME, BIT, E, DO_OP) \
-void HELPER(NAME)(CPULoongArchState *env, uint32_t vd, uint32_t vj) \
-{ \
- int i; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) \
- { \
- Vd->E(i) = DO_OP(Vj->E(i)); \
- } \
-}
-
-#define DO_CLO_B(N) (clz32(~N & 0xff) - 24)
-#define DO_CLO_H(N) (clz32(~N & 0xffff) - 16)
-#define DO_CLO_W(N) (clz32(~N))
-#define DO_CLO_D(N) (clz64(~N))
-#define DO_CLZ_B(N) (clz32(N) - 24)
-#define DO_CLZ_H(N) (clz32(N) - 16)
-#define DO_CLZ_W(N) (clz32(N))
-#define DO_CLZ_D(N) (clz64(N))
-
-DO_2OP(vclo_b, 8, UB, DO_CLO_B)
-DO_2OP(vclo_h, 16, UH, DO_CLO_H)
-DO_2OP(vclo_w, 32, UW, DO_CLO_W)
-DO_2OP(vclo_d, 64, UD, DO_CLO_D)
-DO_2OP(vclz_b, 8, UB, DO_CLZ_B)
-DO_2OP(vclz_h, 16, UH, DO_CLZ_H)
-DO_2OP(vclz_w, 32, UW, DO_CLZ_W)
-DO_2OP(vclz_d, 64, UD, DO_CLZ_D)
-
-#define VPCNT(NAME, BIT, E, FN) \
-void HELPER(NAME)(CPULoongArchState *env, uint32_t vd, uint32_t vj) \
-{ \
- int i; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) \
- { \
- Vd->E(i) = FN(Vj->E(i)); \
- } \
-}
-
-VPCNT(vpcnt_b, 8, UB, ctpop8)
-VPCNT(vpcnt_h, 16, UH, ctpop16)
-VPCNT(vpcnt_w, 32, UW, ctpop32)
-VPCNT(vpcnt_d, 64, UD, ctpop64)
-
-#define DO_BITCLR(a, bit) (a & ~(1ull << bit))
-#define DO_BITSET(a, bit) (a | 1ull << bit)
-#define DO_BITREV(a, bit) (a ^ (1ull << bit))
-
-#define DO_BIT(NAME, BIT, E, DO_OP) \
-void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t v) \
-{ \
- int i; \
- VReg *Vd = (VReg *)vd; \
- VReg *Vj = (VReg *)vj; \
- VReg *Vk = (VReg *)vk; \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E(i) = DO_OP(Vj->E(i), Vk->E(i)%BIT); \
- } \
-}
-
-DO_BIT(vbitclr_b, 8, UB, DO_BITCLR)
-DO_BIT(vbitclr_h, 16, UH, DO_BITCLR)
-DO_BIT(vbitclr_w, 32, UW, DO_BITCLR)
-DO_BIT(vbitclr_d, 64, UD, DO_BITCLR)
-DO_BIT(vbitset_b, 8, UB, DO_BITSET)
-DO_BIT(vbitset_h, 16, UH, DO_BITSET)
-DO_BIT(vbitset_w, 32, UW, DO_BITSET)
-DO_BIT(vbitset_d, 64, UD, DO_BITSET)
-DO_BIT(vbitrev_b, 8, UB, DO_BITREV)
-DO_BIT(vbitrev_h, 16, UH, DO_BITREV)
-DO_BIT(vbitrev_w, 32, UW, DO_BITREV)
-DO_BIT(vbitrev_d, 64, UD, DO_BITREV)
-
-#define DO_BITI(NAME, BIT, E, DO_OP) \
-void HELPER(NAME)(void *vd, void *vj, uint64_t imm, uint32_t v) \
-{ \
- int i; \
- VReg *Vd = (VReg *)vd; \
- VReg *Vj = (VReg *)vj; \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E(i) = DO_OP(Vj->E(i), imm); \
- } \
-}
-
-DO_BITI(vbitclri_b, 8, UB, DO_BITCLR)
-DO_BITI(vbitclri_h, 16, UH, DO_BITCLR)
-DO_BITI(vbitclri_w, 32, UW, DO_BITCLR)
-DO_BITI(vbitclri_d, 64, UD, DO_BITCLR)
-DO_BITI(vbitseti_b, 8, UB, DO_BITSET)
-DO_BITI(vbitseti_h, 16, UH, DO_BITSET)
-DO_BITI(vbitseti_w, 32, UW, DO_BITSET)
-DO_BITI(vbitseti_d, 64, UD, DO_BITSET)
-DO_BITI(vbitrevi_b, 8, UB, DO_BITREV)
-DO_BITI(vbitrevi_h, 16, UH, DO_BITREV)
-DO_BITI(vbitrevi_w, 32, UW, DO_BITREV)
-DO_BITI(vbitrevi_d, 64, UD, DO_BITREV)
-
-#define VFRSTP(NAME, BIT, MASK, E) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t vk) \
-{ \
- int i, m; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- VReg *Vk = &(env->fpr[vk].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- if (Vj->E(i) < 0) { \
- break; \
- } \
- } \
- m = Vk->E(0) & MASK; \
- Vd->E(m) = i; \
-}
-
-VFRSTP(vfrstp_b, 8, 0xf, B)
-VFRSTP(vfrstp_h, 16, 0x7, H)
-
-#define VFRSTPI(NAME, BIT, E) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t imm) \
-{ \
- int i, m; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- if (Vj->E(i) < 0) { \
- break; \
- } \
- } \
- m = imm % (LSX_LEN/BIT); \
- Vd->E(m) = i; \
-}
-
-VFRSTPI(vfrstpi_b, 8, B)
-VFRSTPI(vfrstpi_h, 16, H)
-
-static void vec_update_fcsr0_mask(CPULoongArchState *env,
- uintptr_t pc, int mask)
-{
- int flags = get_float_exception_flags(&env->fp_status);
-
- set_float_exception_flags(0, &env->fp_status);
-
- flags &= ~mask;
-
- if (flags) {
- flags = ieee_ex_to_loongarch(flags);
- UPDATE_FP_CAUSE(env->fcsr0, flags);
- }
-
- if (GET_FP_ENABLES(env->fcsr0) & flags) {
- do_raise_exception(env, EXCCODE_FPE, pc);
- } else {
- UPDATE_FP_FLAGS(env->fcsr0, flags);
- }
-}
-
-static void vec_update_fcsr0(CPULoongArchState *env, uintptr_t pc)
-{
- vec_update_fcsr0_mask(env, pc, 0);
-}
-
-static inline void vec_clear_cause(CPULoongArchState *env)
-{
- SET_FP_CAUSE(env->fcsr0, 0);
-}
-
-#define DO_3OP_F(NAME, BIT, E, FN) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t vk) \
-{ \
- int i; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- VReg *Vk = &(env->fpr[vk].vreg); \
- \
- vec_clear_cause(env); \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E(i) = FN(Vj->E(i), Vk->E(i), &env->fp_status); \
- vec_update_fcsr0(env, GETPC()); \
- } \
-}
-
-DO_3OP_F(vfadd_s, 32, UW, float32_add)
-DO_3OP_F(vfadd_d, 64, UD, float64_add)
-DO_3OP_F(vfsub_s, 32, UW, float32_sub)
-DO_3OP_F(vfsub_d, 64, UD, float64_sub)
-DO_3OP_F(vfmul_s, 32, UW, float32_mul)
-DO_3OP_F(vfmul_d, 64, UD, float64_mul)
-DO_3OP_F(vfdiv_s, 32, UW, float32_div)
-DO_3OP_F(vfdiv_d, 64, UD, float64_div)
-DO_3OP_F(vfmax_s, 32, UW, float32_maxnum)
-DO_3OP_F(vfmax_d, 64, UD, float64_maxnum)
-DO_3OP_F(vfmin_s, 32, UW, float32_minnum)
-DO_3OP_F(vfmin_d, 64, UD, float64_minnum)
-DO_3OP_F(vfmaxa_s, 32, UW, float32_maxnummag)
-DO_3OP_F(vfmaxa_d, 64, UD, float64_maxnummag)
-DO_3OP_F(vfmina_s, 32, UW, float32_minnummag)
-DO_3OP_F(vfmina_d, 64, UD, float64_minnummag)
-
-#define DO_4OP_F(NAME, BIT, E, FN, flags) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t vk, uint32_t va) \
-{ \
- int i; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- VReg *Vk = &(env->fpr[vk].vreg); \
- VReg *Va = &(env->fpr[va].vreg); \
- \
- vec_clear_cause(env); \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E(i) = FN(Vj->E(i), Vk->E(i), Va->E(i), flags, &env->fp_status); \
- vec_update_fcsr0(env, GETPC()); \
- } \
-}
-
-DO_4OP_F(vfmadd_s, 32, UW, float32_muladd, 0)
-DO_4OP_F(vfmadd_d, 64, UD, float64_muladd, 0)
-DO_4OP_F(vfmsub_s, 32, UW, float32_muladd, float_muladd_negate_c)
-DO_4OP_F(vfmsub_d, 64, UD, float64_muladd, float_muladd_negate_c)
-DO_4OP_F(vfnmadd_s, 32, UW, float32_muladd, float_muladd_negate_result)
-DO_4OP_F(vfnmadd_d, 64, UD, float64_muladd, float_muladd_negate_result)
-DO_4OP_F(vfnmsub_s, 32, UW, float32_muladd,
- float_muladd_negate_c | float_muladd_negate_result)
-DO_4OP_F(vfnmsub_d, 64, UD, float64_muladd,
- float_muladd_negate_c | float_muladd_negate_result)
-
-#define DO_2OP_F(NAME, BIT, E, FN) \
-void HELPER(NAME)(CPULoongArchState *env, uint32_t vd, uint32_t vj) \
-{ \
- int i; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- \
- vec_clear_cause(env); \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E(i) = FN(env, Vj->E(i)); \
- } \
-}
-
-#define FLOGB(BIT, T) \
-static T do_flogb_## BIT(CPULoongArchState *env, T fj) \
-{ \
- T fp, fd; \
- float_status *status = &env->fp_status; \
- FloatRoundMode old_mode = get_float_rounding_mode(status); \
- \
- set_float_rounding_mode(float_round_down, status); \
- fp = float ## BIT ##_log2(fj, status); \
- fd = float ## BIT ##_round_to_int(fp, status); \
- set_float_rounding_mode(old_mode, status); \
- vec_update_fcsr0_mask(env, GETPC(), float_flag_inexact); \
- return fd; \
-}
-
-FLOGB(32, uint32_t)
-FLOGB(64, uint64_t)
-
-#define FCLASS(NAME, BIT, E, FN) \
-void HELPER(NAME)(CPULoongArchState *env, uint32_t vd, uint32_t vj) \
-{ \
- int i; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E(i) = FN(env, Vj->E(i)); \
- } \
-}
-
-FCLASS(vfclass_s, 32, UW, helper_fclass_s)
-FCLASS(vfclass_d, 64, UD, helper_fclass_d)
-
-#define FSQRT(BIT, T) \
-static T do_fsqrt_## BIT(CPULoongArchState *env, T fj) \
-{ \
- T fd; \
- fd = float ## BIT ##_sqrt(fj, &env->fp_status); \
- vec_update_fcsr0(env, GETPC()); \
- return fd; \
-}
-
-FSQRT(32, uint32_t)
-FSQRT(64, uint64_t)
-
-#define FRECIP(BIT, T) \
-static T do_frecip_## BIT(CPULoongArchState *env, T fj) \
-{ \
- T fd; \
- fd = float ## BIT ##_div(float ## BIT ##_one, fj, &env->fp_status); \
- vec_update_fcsr0(env, GETPC()); \
- return fd; \
-}
-
-FRECIP(32, uint32_t)
-FRECIP(64, uint64_t)
-
-#define FRSQRT(BIT, T) \
-static T do_frsqrt_## BIT(CPULoongArchState *env, T fj) \
-{ \
- T fd, fp; \
- fp = float ## BIT ##_sqrt(fj, &env->fp_status); \
- fd = float ## BIT ##_div(float ## BIT ##_one, fp, &env->fp_status); \
- vec_update_fcsr0(env, GETPC()); \
- return fd; \
-}
-
-FRSQRT(32, uint32_t)
-FRSQRT(64, uint64_t)
-
-DO_2OP_F(vflogb_s, 32, UW, do_flogb_32)
-DO_2OP_F(vflogb_d, 64, UD, do_flogb_64)
-DO_2OP_F(vfsqrt_s, 32, UW, do_fsqrt_32)
-DO_2OP_F(vfsqrt_d, 64, UD, do_fsqrt_64)
-DO_2OP_F(vfrecip_s, 32, UW, do_frecip_32)
-DO_2OP_F(vfrecip_d, 64, UD, do_frecip_64)
-DO_2OP_F(vfrsqrt_s, 32, UW, do_frsqrt_32)
-DO_2OP_F(vfrsqrt_d, 64, UD, do_frsqrt_64)
-
-static uint32_t float16_cvt_float32(uint16_t h, float_status *status)
-{
- return float16_to_float32(h, true, status);
-}
-static uint64_t float32_cvt_float64(uint32_t s, float_status *status)
-{
- return float32_to_float64(s, status);
-}
-
-static uint16_t float32_cvt_float16(uint32_t s, float_status *status)
-{
- return float32_to_float16(s, true, status);
-}
-static uint32_t float64_cvt_float32(uint64_t d, float_status *status)
-{
- return float64_to_float32(d, status);
-}
-
-void HELPER(vfcvtl_s_h)(CPULoongArchState *env, uint32_t vd, uint32_t vj)
-{
- int i;
- VReg temp;
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
-
- vec_clear_cause(env);
- for (i = 0; i < LSX_LEN/32; i++) {
- temp.UW(i) = float16_cvt_float32(Vj->UH(i), &env->fp_status);
- vec_update_fcsr0(env, GETPC());
- }
- *Vd = temp;
-}
-
-void HELPER(vfcvtl_d_s)(CPULoongArchState *env, uint32_t vd, uint32_t vj)
-{
- int i;
- VReg temp;
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
-
- vec_clear_cause(env);
- for (i = 0; i < LSX_LEN/64; i++) {
- temp.UD(i) = float32_cvt_float64(Vj->UW(i), &env->fp_status);
- vec_update_fcsr0(env, GETPC());
- }
- *Vd = temp;
-}
-
-void HELPER(vfcvth_s_h)(CPULoongArchState *env, uint32_t vd, uint32_t vj)
-{
- int i;
- VReg temp;
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
-
- vec_clear_cause(env);
- for (i = 0; i < LSX_LEN/32; i++) {
- temp.UW(i) = float16_cvt_float32(Vj->UH(i + 4), &env->fp_status);
- vec_update_fcsr0(env, GETPC());
- }
- *Vd = temp;
-}
-
-void HELPER(vfcvth_d_s)(CPULoongArchState *env, uint32_t vd, uint32_t vj)
-{
- int i;
- VReg temp;
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
-
- vec_clear_cause(env);
- for (i = 0; i < LSX_LEN/64; i++) {
- temp.UD(i) = float32_cvt_float64(Vj->UW(i + 2), &env->fp_status);
- vec_update_fcsr0(env, GETPC());
- }
- *Vd = temp;
-}
-
-void HELPER(vfcvt_h_s)(CPULoongArchState *env,
- uint32_t vd, uint32_t vj, uint32_t vk)
-{
- int i;
- VReg temp;
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
- VReg *Vk = &(env->fpr[vk].vreg);
-
- vec_clear_cause(env);
- for(i = 0; i < LSX_LEN/32; i++) {
- temp.UH(i + 4) = float32_cvt_float16(Vj->UW(i), &env->fp_status);
- temp.UH(i) = float32_cvt_float16(Vk->UW(i), &env->fp_status);
- vec_update_fcsr0(env, GETPC());
- }
- *Vd = temp;
-}
-
-void HELPER(vfcvt_s_d)(CPULoongArchState *env,
- uint32_t vd, uint32_t vj, uint32_t vk)
-{
- int i;
- VReg temp;
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
- VReg *Vk = &(env->fpr[vk].vreg);
-
- vec_clear_cause(env);
- for(i = 0; i < LSX_LEN/64; i++) {
- temp.UW(i + 2) = float64_cvt_float32(Vj->UD(i), &env->fp_status);
- temp.UW(i) = float64_cvt_float32(Vk->UD(i), &env->fp_status);
- vec_update_fcsr0(env, GETPC());
- }
- *Vd = temp;
-}
-
-void HELPER(vfrint_s)(CPULoongArchState *env, uint32_t vd, uint32_t vj)
-{
- int i;
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
-
- vec_clear_cause(env);
- for (i = 0; i < 4; i++) {
- Vd->W(i) = float32_round_to_int(Vj->UW(i), &env->fp_status);
- vec_update_fcsr0(env, GETPC());
- }
-}
-
-void HELPER(vfrint_d)(CPULoongArchState *env, uint32_t vd, uint32_t vj)
-{
- int i;
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
-
- vec_clear_cause(env);
- for (i = 0; i < 2; i++) {
- Vd->D(i) = float64_round_to_int(Vj->UD(i), &env->fp_status);
- vec_update_fcsr0(env, GETPC());
- }
-}
-
-#define FCVT_2OP(NAME, BIT, E, MODE) \
-void HELPER(NAME)(CPULoongArchState *env, uint32_t vd, uint32_t vj) \
-{ \
- int i; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- \
- vec_clear_cause(env); \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); \
- set_float_rounding_mode(MODE, &env->fp_status); \
- Vd->E(i) = float## BIT ## _round_to_int(Vj->E(i), &env->fp_status); \
- set_float_rounding_mode(old_mode, &env->fp_status); \
- vec_update_fcsr0(env, GETPC()); \
- } \
-}
-
-FCVT_2OP(vfrintrne_s, 32, UW, float_round_nearest_even)
-FCVT_2OP(vfrintrne_d, 64, UD, float_round_nearest_even)
-FCVT_2OP(vfrintrz_s, 32, UW, float_round_to_zero)
-FCVT_2OP(vfrintrz_d, 64, UD, float_round_to_zero)
-FCVT_2OP(vfrintrp_s, 32, UW, float_round_up)
-FCVT_2OP(vfrintrp_d, 64, UD, float_round_up)
-FCVT_2OP(vfrintrm_s, 32, UW, float_round_down)
-FCVT_2OP(vfrintrm_d, 64, UD, float_round_down)
-
-#define FTINT(NAME, FMT1, FMT2, T1, T2, MODE) \
-static T2 do_ftint ## NAME(CPULoongArchState *env, T1 fj) \
-{ \
- T2 fd; \
- FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); \
- \
- set_float_rounding_mode(MODE, &env->fp_status); \
- fd = do_## FMT1 ##_to_## FMT2(env, fj); \
- set_float_rounding_mode(old_mode, &env->fp_status); \
- return fd; \
-}
-
-#define DO_FTINT(FMT1, FMT2, T1, T2) \
-static T2 do_## FMT1 ##_to_## FMT2(CPULoongArchState *env, T1 fj) \
-{ \
- T2 fd; \
- \
- fd = FMT1 ##_to_## FMT2(fj, &env->fp_status); \
- if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { \
- if (FMT1 ##_is_any_nan(fj)) { \
- fd = 0; \
- } \
- } \
- vec_update_fcsr0(env, GETPC()); \
- return fd; \
-}
-
-DO_FTINT(float32, int32, uint32_t, uint32_t)
-DO_FTINT(float64, int64, uint64_t, uint64_t)
-DO_FTINT(float32, uint32, uint32_t, uint32_t)
-DO_FTINT(float64, uint64, uint64_t, uint64_t)
-DO_FTINT(float64, int32, uint64_t, uint32_t)
-DO_FTINT(float32, int64, uint32_t, uint64_t)
-
-FTINT(rne_w_s, float32, int32, uint32_t, uint32_t, float_round_nearest_even)
-FTINT(rne_l_d, float64, int64, uint64_t, uint64_t, float_round_nearest_even)
-FTINT(rp_w_s, float32, int32, uint32_t, uint32_t, float_round_up)
-FTINT(rp_l_d, float64, int64, uint64_t, uint64_t, float_round_up)
-FTINT(rz_w_s, float32, int32, uint32_t, uint32_t, float_round_to_zero)
-FTINT(rz_l_d, float64, int64, uint64_t, uint64_t, float_round_to_zero)
-FTINT(rm_w_s, float32, int32, uint32_t, uint32_t, float_round_down)
-FTINT(rm_l_d, float64, int64, uint64_t, uint64_t, float_round_down)
-
-DO_2OP_F(vftintrne_w_s, 32, UW, do_ftintrne_w_s)
-DO_2OP_F(vftintrne_l_d, 64, UD, do_ftintrne_l_d)
-DO_2OP_F(vftintrp_w_s, 32, UW, do_ftintrp_w_s)
-DO_2OP_F(vftintrp_l_d, 64, UD, do_ftintrp_l_d)
-DO_2OP_F(vftintrz_w_s, 32, UW, do_ftintrz_w_s)
-DO_2OP_F(vftintrz_l_d, 64, UD, do_ftintrz_l_d)
-DO_2OP_F(vftintrm_w_s, 32, UW, do_ftintrm_w_s)
-DO_2OP_F(vftintrm_l_d, 64, UD, do_ftintrm_l_d)
-DO_2OP_F(vftint_w_s, 32, UW, do_float32_to_int32)
-DO_2OP_F(vftint_l_d, 64, UD, do_float64_to_int64)
-
-FTINT(rz_wu_s, float32, uint32, uint32_t, uint32_t, float_round_to_zero)
-FTINT(rz_lu_d, float64, uint64, uint64_t, uint64_t, float_round_to_zero)
-
-DO_2OP_F(vftintrz_wu_s, 32, UW, do_ftintrz_wu_s)
-DO_2OP_F(vftintrz_lu_d, 64, UD, do_ftintrz_lu_d)
-DO_2OP_F(vftint_wu_s, 32, UW, do_float32_to_uint32)
-DO_2OP_F(vftint_lu_d, 64, UD, do_float64_to_uint64)
-
-FTINT(rm_w_d, float64, int32, uint64_t, uint32_t, float_round_down)
-FTINT(rp_w_d, float64, int32, uint64_t, uint32_t, float_round_up)
-FTINT(rz_w_d, float64, int32, uint64_t, uint32_t, float_round_to_zero)
-FTINT(rne_w_d, float64, int32, uint64_t, uint32_t, float_round_nearest_even)
-
-#define FTINT_W_D(NAME, FN) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t vk) \
-{ \
- int i; \
- VReg temp; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- VReg *Vk = &(env->fpr[vk].vreg); \
- \
- vec_clear_cause(env); \
- for (i = 0; i < 2; i++) { \
- temp.W(i + 2) = FN(env, Vj->UD(i)); \
- temp.W(i) = FN(env, Vk->UD(i)); \
- } \
- *Vd = temp; \
-}
-
-FTINT_W_D(vftint_w_d, do_float64_to_int32)
-FTINT_W_D(vftintrm_w_d, do_ftintrm_w_d)
-FTINT_W_D(vftintrp_w_d, do_ftintrp_w_d)
-FTINT_W_D(vftintrz_w_d, do_ftintrz_w_d)
-FTINT_W_D(vftintrne_w_d, do_ftintrne_w_d)
-
-FTINT(rml_l_s, float32, int64, uint32_t, uint64_t, float_round_down)
-FTINT(rpl_l_s, float32, int64, uint32_t, uint64_t, float_round_up)
-FTINT(rzl_l_s, float32, int64, uint32_t, uint64_t, float_round_to_zero)
-FTINT(rnel_l_s, float32, int64, uint32_t, uint64_t, float_round_nearest_even)
-FTINT(rmh_l_s, float32, int64, uint32_t, uint64_t, float_round_down)
-FTINT(rph_l_s, float32, int64, uint32_t, uint64_t, float_round_up)
-FTINT(rzh_l_s, float32, int64, uint32_t, uint64_t, float_round_to_zero)
-FTINT(rneh_l_s, float32, int64, uint32_t, uint64_t, float_round_nearest_even)
-
-#define FTINTL_L_S(NAME, FN) \
-void HELPER(NAME)(CPULoongArchState *env, uint32_t vd, uint32_t vj) \
-{ \
- int i; \
- VReg temp; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- \
- vec_clear_cause(env); \
- for (i = 0; i < 2; i++) { \
- temp.D(i) = FN(env, Vj->UW(i)); \
- } \
- *Vd = temp; \
-}
-
-FTINTL_L_S(vftintl_l_s, do_float32_to_int64)
-FTINTL_L_S(vftintrml_l_s, do_ftintrml_l_s)
-FTINTL_L_S(vftintrpl_l_s, do_ftintrpl_l_s)
-FTINTL_L_S(vftintrzl_l_s, do_ftintrzl_l_s)
-FTINTL_L_S(vftintrnel_l_s, do_ftintrnel_l_s)
-
-#define FTINTH_L_S(NAME, FN) \
-void HELPER(NAME)(CPULoongArchState *env, uint32_t vd, uint32_t vj) \
-{ \
- int i; \
- VReg temp; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- \
- vec_clear_cause(env); \
- for (i = 0; i < 2; i++) { \
- temp.D(i) = FN(env, Vj->UW(i + 2)); \
- } \
- *Vd = temp; \
-}
-
-FTINTH_L_S(vftinth_l_s, do_float32_to_int64)
-FTINTH_L_S(vftintrmh_l_s, do_ftintrmh_l_s)
-FTINTH_L_S(vftintrph_l_s, do_ftintrph_l_s)
-FTINTH_L_S(vftintrzh_l_s, do_ftintrzh_l_s)
-FTINTH_L_S(vftintrneh_l_s, do_ftintrneh_l_s)
-
-#define FFINT(NAME, FMT1, FMT2, T1, T2) \
-static T2 do_ffint_ ## NAME(CPULoongArchState *env, T1 fj) \
-{ \
- T2 fd; \
- \
- fd = FMT1 ##_to_## FMT2(fj, &env->fp_status); \
- vec_update_fcsr0(env, GETPC()); \
- return fd; \
-}
-
-FFINT(s_w, int32, float32, int32_t, uint32_t)
-FFINT(d_l, int64, float64, int64_t, uint64_t)
-FFINT(s_wu, uint32, float32, uint32_t, uint32_t)
-FFINT(d_lu, uint64, float64, uint64_t, uint64_t)
-
-DO_2OP_F(vffint_s_w, 32, W, do_ffint_s_w)
-DO_2OP_F(vffint_d_l, 64, D, do_ffint_d_l)
-DO_2OP_F(vffint_s_wu, 32, UW, do_ffint_s_wu)
-DO_2OP_F(vffint_d_lu, 64, UD, do_ffint_d_lu)
-
-void HELPER(vffintl_d_w)(CPULoongArchState *env, uint32_t vd, uint32_t vj)
-{
- int i;
- VReg temp;
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
-
- vec_clear_cause(env);
- for (i = 0; i < 2; i++) {
- temp.D(i) = int32_to_float64(Vj->W(i), &env->fp_status);
- vec_update_fcsr0(env, GETPC());
- }
- *Vd = temp;
-}
-
-void HELPER(vffinth_d_w)(CPULoongArchState *env, uint32_t vd, uint32_t vj)
-{
- int i;
- VReg temp;
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
-
- vec_clear_cause(env);
- for (i = 0; i < 2; i++) {
- temp.D(i) = int32_to_float64(Vj->W(i + 2), &env->fp_status);
- vec_update_fcsr0(env, GETPC());
- }
- *Vd = temp;
-}
-
-void HELPER(vffint_s_l)(CPULoongArchState *env,
- uint32_t vd, uint32_t vj, uint32_t vk)
-{
- int i;
- VReg temp;
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
- VReg *Vk = &(env->fpr[vk].vreg);
-
- vec_clear_cause(env);
- for (i = 0; i < 2; i++) {
- temp.W(i + 2) = int64_to_float32(Vj->D(i), &env->fp_status);
- temp.W(i) = int64_to_float32(Vk->D(i), &env->fp_status);
- vec_update_fcsr0(env, GETPC());
- }
- *Vd = temp;
-}
-
-#define VSEQ(a, b) (a == b ? -1 : 0)
-#define VSLE(a, b) (a <= b ? -1 : 0)
-#define VSLT(a, b) (a < b ? -1 : 0)
-
-#define VCMPI(NAME, BIT, E, DO_OP) \
-void HELPER(NAME)(void *vd, void *vj, uint64_t imm, uint32_t v) \
-{ \
- int i; \
- VReg *Vd = (VReg *)vd; \
- VReg *Vj = (VReg *)vj; \
- typedef __typeof(Vd->E(0)) TD; \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- Vd->E(i) = DO_OP(Vj->E(i), (TD)imm); \
- } \
-}
-
-VCMPI(vseqi_b, 8, B, VSEQ)
-VCMPI(vseqi_h, 16, H, VSEQ)
-VCMPI(vseqi_w, 32, W, VSEQ)
-VCMPI(vseqi_d, 64, D, VSEQ)
-VCMPI(vslei_b, 8, B, VSLE)
-VCMPI(vslei_h, 16, H, VSLE)
-VCMPI(vslei_w, 32, W, VSLE)
-VCMPI(vslei_d, 64, D, VSLE)
-VCMPI(vslei_bu, 8, UB, VSLE)
-VCMPI(vslei_hu, 16, UH, VSLE)
-VCMPI(vslei_wu, 32, UW, VSLE)
-VCMPI(vslei_du, 64, UD, VSLE)
-VCMPI(vslti_b, 8, B, VSLT)
-VCMPI(vslti_h, 16, H, VSLT)
-VCMPI(vslti_w, 32, W, VSLT)
-VCMPI(vslti_d, 64, D, VSLT)
-VCMPI(vslti_bu, 8, UB, VSLT)
-VCMPI(vslti_hu, 16, UH, VSLT)
-VCMPI(vslti_wu, 32, UW, VSLT)
-VCMPI(vslti_du, 64, UD, VSLT)
-
-static uint64_t vfcmp_common(CPULoongArchState *env,
- FloatRelation cmp, uint32_t flags)
-{
- uint64_t ret = 0;
-
- switch (cmp) {
- case float_relation_less:
- ret = (flags & FCMP_LT);
- break;
- case float_relation_equal:
- ret = (flags & FCMP_EQ);
- break;
- case float_relation_greater:
- ret = (flags & FCMP_GT);
- break;
- case float_relation_unordered:
- ret = (flags & FCMP_UN);
- break;
- default:
- g_assert_not_reached();
- }
-
- if (ret) {
- ret = -1;
- }
-
- return ret;
-}
-
-#define VFCMP(NAME, BIT, E, FN) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t vk, uint32_t flags) \
-{ \
- int i; \
- VReg t; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- VReg *Vk = &(env->fpr[vk].vreg); \
- \
- vec_clear_cause(env); \
- for (i = 0; i < LSX_LEN/BIT ; i++) { \
- FloatRelation cmp; \
- cmp = FN(Vj->E(i), Vk->E(i), &env->fp_status); \
- t.E(i) = vfcmp_common(env, cmp, flags); \
- vec_update_fcsr0(env, GETPC()); \
- } \
- *Vd = t; \
-}
-
-VFCMP(vfcmp_c_s, 32, UW, float32_compare_quiet)
-VFCMP(vfcmp_s_s, 32, UW, float32_compare)
-VFCMP(vfcmp_c_d, 64, UD, float64_compare_quiet)
-VFCMP(vfcmp_s_d, 64, UD, float64_compare)
-
-void HELPER(vbitseli_b)(void *vd, void *vj, uint64_t imm, uint32_t v)
-{
- int i;
- VReg *Vd = (VReg *)vd;
- VReg *Vj = (VReg *)vj;
-
- for (i = 0; i < 16; i++) {
- Vd->B(i) = (~Vd->B(i) & Vj->B(i)) | (Vd->B(i) & imm);
- }
-}
-
-/* Copy from target/arm/tcg/sve_helper.c */
-static inline bool do_match2(uint64_t n, uint64_t m0, uint64_t m1, int esz)
-{
- uint64_t bits = 8 << esz;
- uint64_t ones = dup_const(esz, 1);
- uint64_t signs = ones << (bits - 1);
- uint64_t cmp0, cmp1;
-
- cmp1 = dup_const(esz, n);
- cmp0 = cmp1 ^ m0;
- cmp1 = cmp1 ^ m1;
- cmp0 = (cmp0 - ones) & ~cmp0;
- cmp1 = (cmp1 - ones) & ~cmp1;
- return (cmp0 | cmp1) & signs;
-}
-
-#define SETANYEQZ(NAME, MO) \
-void HELPER(NAME)(CPULoongArchState *env, uint32_t cd, uint32_t vj) \
-{ \
- VReg *Vj = &(env->fpr[vj].vreg); \
- \
- env->cf[cd & 0x7] = do_match2(0, Vj->D(0), Vj->D(1), MO); \
-}
-SETANYEQZ(vsetanyeqz_b, MO_8)
-SETANYEQZ(vsetanyeqz_h, MO_16)
-SETANYEQZ(vsetanyeqz_w, MO_32)
-SETANYEQZ(vsetanyeqz_d, MO_64)
-
-#define SETALLNEZ(NAME, MO) \
-void HELPER(NAME)(CPULoongArchState *env, uint32_t cd, uint32_t vj) \
-{ \
- VReg *Vj = &(env->fpr[vj].vreg); \
- \
- env->cf[cd & 0x7]= !do_match2(0, Vj->D(0), Vj->D(1), MO); \
-}
-SETALLNEZ(vsetallnez_b, MO_8)
-SETALLNEZ(vsetallnez_h, MO_16)
-SETALLNEZ(vsetallnez_w, MO_32)
-SETALLNEZ(vsetallnez_d, MO_64)
-
-#define VPACKEV(NAME, BIT, E) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t vk) \
-{ \
- int i; \
- VReg temp; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- VReg *Vk = &(env->fpr[vk].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- temp.E(2 * i + 1) = Vj->E(2 * i); \
- temp.E(2 *i) = Vk->E(2 * i); \
- } \
- *Vd = temp; \
-}
-
-VPACKEV(vpackev_b, 16, B)
-VPACKEV(vpackev_h, 32, H)
-VPACKEV(vpackev_w, 64, W)
-VPACKEV(vpackev_d, 128, D)
-
-#define VPACKOD(NAME, BIT, E) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t vk) \
-{ \
- int i; \
- VReg temp; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- VReg *Vk = &(env->fpr[vk].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- temp.E(2 * i + 1) = Vj->E(2 * i + 1); \
- temp.E(2 * i) = Vk->E(2 * i + 1); \
- } \
- *Vd = temp; \
-}
-
-VPACKOD(vpackod_b, 16, B)
-VPACKOD(vpackod_h, 32, H)
-VPACKOD(vpackod_w, 64, W)
-VPACKOD(vpackod_d, 128, D)
-
-#define VPICKEV(NAME, BIT, E) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t vk) \
-{ \
- int i; \
- VReg temp; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- VReg *Vk = &(env->fpr[vk].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- temp.E(i + LSX_LEN/BIT) = Vj->E(2 * i); \
- temp.E(i) = Vk->E(2 * i); \
- } \
- *Vd = temp; \
-}
-
-VPICKEV(vpickev_b, 16, B)
-VPICKEV(vpickev_h, 32, H)
-VPICKEV(vpickev_w, 64, W)
-VPICKEV(vpickev_d, 128, D)
-
-#define VPICKOD(NAME, BIT, E) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t vk) \
-{ \
- int i; \
- VReg temp; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- VReg *Vk = &(env->fpr[vk].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- temp.E(i + LSX_LEN/BIT) = Vj->E(2 * i + 1); \
- temp.E(i) = Vk->E(2 * i + 1); \
- } \
- *Vd = temp; \
-}
-
-VPICKOD(vpickod_b, 16, B)
-VPICKOD(vpickod_h, 32, H)
-VPICKOD(vpickod_w, 64, W)
-VPICKOD(vpickod_d, 128, D)
-
-#define VILVL(NAME, BIT, E) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t vk) \
-{ \
- int i; \
- VReg temp; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- VReg *Vk = &(env->fpr[vk].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- temp.E(2 * i + 1) = Vj->E(i); \
- temp.E(2 * i) = Vk->E(i); \
- } \
- *Vd = temp; \
-}
-
-VILVL(vilvl_b, 16, B)
-VILVL(vilvl_h, 32, H)
-VILVL(vilvl_w, 64, W)
-VILVL(vilvl_d, 128, D)
-
-#define VILVH(NAME, BIT, E) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t vk) \
-{ \
- int i; \
- VReg temp; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- VReg *Vk = &(env->fpr[vk].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- temp.E(2 * i + 1) = Vj->E(i + LSX_LEN/BIT); \
- temp.E(2 * i) = Vk->E(i + LSX_LEN/BIT); \
- } \
- *Vd = temp; \
-}
-
-VILVH(vilvh_b, 16, B)
-VILVH(vilvh_h, 32, H)
-VILVH(vilvh_w, 64, W)
-VILVH(vilvh_d, 128, D)
-
-void HELPER(vshuf_b)(CPULoongArchState *env,
- uint32_t vd, uint32_t vj, uint32_t vk, uint32_t va)
-{
- int i, m;
- VReg temp;
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
- VReg *Vk = &(env->fpr[vk].vreg);
- VReg *Va = &(env->fpr[va].vreg);
-
- m = LSX_LEN/8;
- for (i = 0; i < m ; i++) {
- uint64_t k = (uint8_t)Va->B(i) % (2 * m);
- temp.B(i) = k < m ? Vk->B(k) : Vj->B(k - m);
- }
- *Vd = temp;
-}
-
-#define VSHUF(NAME, BIT, E) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t vk) \
-{ \
- int i, m; \
- VReg temp; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- VReg *Vk = &(env->fpr[vk].vreg); \
- \
- m = LSX_LEN/BIT; \
- for (i = 0; i < m; i++) { \
- uint64_t k = ((uint8_t) Vd->E(i)) % (2 * m); \
- temp.E(i) = k < m ? Vk->E(k) : Vj->E(k - m); \
- } \
- *Vd = temp; \
-}
-
-VSHUF(vshuf_h, 16, H)
-VSHUF(vshuf_w, 32, W)
-VSHUF(vshuf_d, 64, D)
-
-#define VSHUF4I(NAME, BIT, E) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t imm) \
-{ \
- int i; \
- VReg temp; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- \
- for (i = 0; i < LSX_LEN/BIT; i++) { \
- temp.E(i) = Vj->E(((i) & 0xfc) + (((imm) >> \
- (2 * ((i) & 0x03))) & 0x03)); \
- } \
- *Vd = temp; \
-}
-
-VSHUF4I(vshuf4i_b, 8, B)
-VSHUF4I(vshuf4i_h, 16, H)
-VSHUF4I(vshuf4i_w, 32, W)
-
-void HELPER(vshuf4i_d)(CPULoongArchState *env,
- uint32_t vd, uint32_t vj, uint32_t imm)
-{
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
-
- VReg temp;
- temp.D(0) = (imm & 2 ? Vj : Vd)->D(imm & 1);
- temp.D(1) = (imm & 8 ? Vj : Vd)->D((imm >> 2) & 1);
- *Vd = temp;
-}
-
-void HELPER(vpermi_w)(CPULoongArchState *env,
- uint32_t vd, uint32_t vj, uint32_t imm)
-{
- VReg temp;
- VReg *Vd = &(env->fpr[vd].vreg);
- VReg *Vj = &(env->fpr[vj].vreg);
-
- temp.W(0) = Vj->W(imm & 0x3);
- temp.W(1) = Vj->W((imm >> 2) & 0x3);
- temp.W(2) = Vd->W((imm >> 4) & 0x3);
- temp.W(3) = Vd->W((imm >> 6) & 0x3);
- *Vd = temp;
-}
-
-#define VEXTRINS(NAME, BIT, E, MASK) \
-void HELPER(NAME)(CPULoongArchState *env, \
- uint32_t vd, uint32_t vj, uint32_t imm) \
-{ \
- int ins, extr; \
- VReg *Vd = &(env->fpr[vd].vreg); \
- VReg *Vj = &(env->fpr[vj].vreg); \
- \
- ins = (imm >> 4) & MASK; \
- extr = imm & MASK; \
- Vd->E(ins) = Vj->E(extr); \
-}
-
-VEXTRINS(vextrins_b, 8, B, 0xf)
-VEXTRINS(vextrins_h, 16, H, 0x7)
-VEXTRINS(vextrins_w, 32, W, 0x3)
-VEXTRINS(vextrins_d, 64, D, 0x1)
diff --git a/target/loongarch/machine.c b/target/loongarch/machine.c
index d8ac99c..1c4e01d 100644
--- a/target/loongarch/machine.c
+++ b/target/loongarch/machine.c
@@ -8,7 +8,7 @@
#include "qemu/osdep.h"
#include "cpu.h"
#include "migration/cpu.h"
-#include "internals.h"
+#include "vec.h"
static const VMStateDescription vmstate_fpu_reg = {
.name = "fpu_reg",
@@ -76,6 +76,39 @@
},
};
+static const VMStateDescription vmstate_lasxh_reg = {
+ .name = "lasxh_reg",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT64(UD(2), VReg),
+ VMSTATE_UINT64(UD(3), VReg),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+#define VMSTATE_LASXH_REGS(_field, _state, _start) \
+ VMSTATE_STRUCT_SUB_ARRAY(_field, _state, _start, 32, 0, \
+ vmstate_lasxh_reg, fpr_t)
+
+static bool lasx_needed(void *opaque)
+{
+ LoongArchCPU *cpu = opaque;
+
+ return FIELD_EX64(cpu->env.cpucfg[2], CPUCFG2, LASX);
+}
+
+static const VMStateDescription vmstate_lasx = {
+ .name = "cpu/lasx",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = lasx_needed,
+ .fields = (VMStateField[]) {
+ VMSTATE_LASXH_REGS(env.fpr, LoongArchCPU, 0),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
/* TLB state */
const VMStateDescription vmstate_tlb = {
.name = "cpu/tlb",
@@ -163,6 +196,7 @@
.subsections = (const VMStateDescription*[]) {
&vmstate_fpu,
&vmstate_lsx,
+ &vmstate_lasx,
NULL
}
};
diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build
index b7a27df..7fbf045 100644
--- a/target/loongarch/meson.build
+++ b/target/loongarch/meson.build
@@ -11,7 +11,7 @@
'op_helper.c',
'translate.c',
'gdbstub.c',
- 'lsx_helper.c',
+ 'vec_helper.c',
))
loongarch_tcg_ss.add(zlib)
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index fd393ed..f6038fc 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -18,6 +18,7 @@
#include "fpu/softfloat.h"
#include "translate.h"
#include "internals.h"
+#include "vec.h"
/* Global register indices */
TCGv cpu_gpr[32], cpu_pc;
@@ -36,6 +37,18 @@
return offsetof(CPULoongArchState, fpr[regno]);
}
+static inline int vec_reg_offset(int regno, int index, MemOp mop)
+{
+ const uint8_t size = 1 << mop;
+ int offs = index * size;
+
+ if (HOST_BIG_ENDIAN && size < 8 ) {
+ offs ^= (8 - size);
+ }
+
+ return offs + vec_full_offset(regno);
+}
+
static inline void get_vreg64(TCGv_i64 dest, int regno, int index)
{
tcg_gen_ld_i64(dest, cpu_env,
@@ -123,6 +136,10 @@
ctx->vl = LSX_LEN;
}
+ if (FIELD_EX64(env->cpucfg[2], CPUCFG2, LASX)) {
+ ctx->vl = LASX_LEN;
+ }
+
ctx->la64 = is_la64(env);
ctx->va32 = (ctx->base.tb->flags & HW_FLAGS_VA32) != 0;
@@ -261,7 +278,7 @@
#include "insn_trans/trans_fmemory.c.inc"
#include "insn_trans/trans_branch.c.inc"
#include "insn_trans/trans_privileged.c.inc"
-#include "insn_trans/trans_lsx.c.inc"
+#include "insn_trans/trans_vec.c.inc"
static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
{
diff --git a/target/loongarch/translate.h b/target/loongarch/translate.h
index 89b49a8..195f535 100644
--- a/target/loongarch/translate.h
+++ b/target/loongarch/translate.h
@@ -23,6 +23,7 @@
#define avail_LSPW(C) (FIELD_EX32((C)->cpucfg2, CPUCFG2, LSPW))
#define avail_LAM(C) (FIELD_EX32((C)->cpucfg2, CPUCFG2, LAM))
#define avail_LSX(C) (FIELD_EX32((C)->cpucfg2, CPUCFG2, LSX))
+#define avail_LASX(C) (FIELD_EX32((C)->cpucfg2, CPUCFG2, LASX))
#define avail_IOCSR(C) (FIELD_EX32((C)->cpucfg1, CPUCFG1, IOCSR))
/*
diff --git a/target/loongarch/vec.h b/target/loongarch/vec.h
new file mode 100644
index 0000000..3c9adf8
--- /dev/null
+++ b/target/loongarch/vec.h
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch vector utilitites
+ *
+ * Copyright (c) 2023 Loongson Technology Corporation Limited
+ */
+
+#ifndef LOONGARCH_VEC_H
+#define LOONGARCH_VEC_H
+
+#if HOST_BIG_ENDIAN
+#define B(x) B[(x) ^ 15]
+#define H(x) H[(x) ^ 7]
+#define W(x) W[(x) ^ 3]
+#define D(x) D[(x) ^ 1]
+#define UB(x) UB[(x) ^ 15]
+#define UH(x) UH[(x) ^ 7]
+#define UW(x) UW[(x) ^ 3]
+#define UD(x) UD[(x) ^ 1]
+#define Q(x) Q[x]
+#else
+#define B(x) B[x]
+#define H(x) H[x]
+#define W(x) W[x]
+#define D(x) D[x]
+#define UB(x) UB[x]
+#define UH(x) UH[x]
+#define UW(x) UW[x]
+#define UD(x) UD[x]
+#define Q(x) Q[x]
+#endif /* HOST_BIG_ENDIAN */
+
+#define DO_ADD(a, b) (a + b)
+#define DO_SUB(a, b) (a - b)
+#define DO_VAVG(a, b) ((a >> 1) + (b >> 1) + (a & b & 1))
+#define DO_VAVGR(a, b) ((a >> 1) + (b >> 1) + ((a | b) & 1))
+#define DO_VABSD(a, b) ((a > b) ? (a -b) : (b-a))
+#define DO_VABS(a) ((a < 0) ? (-a) : (a))
+#define DO_MIN(a, b) (a < b ? a : b)
+#define DO_MAX(a, b) (a > b ? a : b)
+#define DO_MUL(a, b) (a * b)
+#define DO_MADD(a, b, c) (a + b * c)
+#define DO_MSUB(a, b, c) (a - b * c)
+
+#define DO_DIVU(N, M) (unlikely(M == 0) ? 0 : N / M)
+#define DO_REMU(N, M) (unlikely(M == 0) ? 0 : N % M)
+#define DO_DIV(N, M) (unlikely(M == 0) ? 0 :\
+ unlikely((N == -N) && (M == (__typeof(N))(-1))) ? N : N / M)
+#define DO_REM(N, M) (unlikely(M == 0) ? 0 :\
+ unlikely((N == -N) && (M == (__typeof(N))(-1))) ? 0 : N % M)
+
+#define DO_SIGNCOV(a, b) (a == 0 ? 0 : a < 0 ? -b : b)
+
+#define R_SHIFT(a, b) (a >> b)
+
+#define DO_CLO_B(N) (clz32(~N & 0xff) - 24)
+#define DO_CLO_H(N) (clz32(~N & 0xffff) - 16)
+#define DO_CLO_W(N) (clz32(~N))
+#define DO_CLO_D(N) (clz64(~N))
+#define DO_CLZ_B(N) (clz32(N) - 24)
+#define DO_CLZ_H(N) (clz32(N) - 16)
+#define DO_CLZ_W(N) (clz32(N))
+#define DO_CLZ_D(N) (clz64(N))
+
+#define DO_BITCLR(a, bit) (a & ~(1ull << bit))
+#define DO_BITSET(a, bit) (a | 1ull << bit)
+#define DO_BITREV(a, bit) (a ^ (1ull << bit))
+
+#define VSEQ(a, b) (a == b ? -1 : 0)
+#define VSLE(a, b) (a <= b ? -1 : 0)
+#define VSLT(a, b) (a < b ? -1 : 0)
+
+#define SHF_POS(i, imm) (((i) & 0xfc) + (((imm) >> (2 * ((i) & 0x03))) & 0x03))
+
+#endif /* LOONGARCH_VEC_H */
diff --git a/target/loongarch/vec_helper.c b/target/loongarch/vec_helper.c
new file mode 100644
index 0000000..3faf52c
--- /dev/null
+++ b/target/loongarch/vec_helper.c
@@ -0,0 +1,3494 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch vector helper functions.
+ *
+ * Copyright (c) 2022-2023 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "exec/exec-all.h"
+#include "exec/helper-proto.h"
+#include "fpu/softfloat.h"
+#include "internals.h"
+#include "tcg/tcg.h"
+#include "vec.h"
+#include "tcg/tcg-gvec-desc.h"
+
+#define DO_ODD_EVEN(NAME, BIT, E1, E2, DO_OP) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ typedef __typeof(Vd->E1(0)) TD; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ for (i = 0; i < oprsz / (BIT / 8); i++) { \
+ Vd->E1(i) = DO_OP((TD)Vj->E2(2 * i + 1), (TD)Vk->E2(2 * i)); \
+ } \
+}
+
+DO_ODD_EVEN(vhaddw_h_b, 16, H, B, DO_ADD)
+DO_ODD_EVEN(vhaddw_w_h, 32, W, H, DO_ADD)
+DO_ODD_EVEN(vhaddw_d_w, 64, D, W, DO_ADD)
+
+void HELPER(vhaddw_q_d)(void *vd, void *vj, void *vk, uint32_t desc)
+{
+ int i;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ VReg *Vk = (VReg *)vk;
+ int oprsz = simd_oprsz(desc);
+
+ for (i = 0; i < oprsz / 16 ; i++) {
+ Vd->Q(i) = int128_add(int128_makes64(Vj->D(2 * i + 1)),
+ int128_makes64(Vk->D(2 * i)));
+ }
+}
+
+DO_ODD_EVEN(vhsubw_h_b, 16, H, B, DO_SUB)
+DO_ODD_EVEN(vhsubw_w_h, 32, W, H, DO_SUB)
+DO_ODD_EVEN(vhsubw_d_w, 64, D, W, DO_SUB)
+
+void HELPER(vhsubw_q_d)(void *vd, void *vj, void *vk, uint32_t desc)
+{
+ int i;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ VReg *Vk = (VReg *)vk;
+ int oprsz = simd_oprsz(desc);
+
+ for (i = 0; i < oprsz / 16; i++) {
+ Vd->Q(i) = int128_sub(int128_makes64(Vj->D(2 * i + 1)),
+ int128_makes64(Vk->D(2 * i)));
+ }
+}
+
+DO_ODD_EVEN(vhaddw_hu_bu, 16, UH, UB, DO_ADD)
+DO_ODD_EVEN(vhaddw_wu_hu, 32, UW, UH, DO_ADD)
+DO_ODD_EVEN(vhaddw_du_wu, 64, UD, UW, DO_ADD)
+
+void HELPER(vhaddw_qu_du)(void *vd, void *vj, void *vk, uint32_t desc)
+{
+ int i;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ VReg *Vk = (VReg *)vk;
+ int oprsz = simd_oprsz(desc);
+
+ for (i = 0; i < oprsz / 16; i ++) {
+ Vd->Q(i) = int128_add(int128_make64(Vj->UD(2 * i + 1)),
+ int128_make64(Vk->UD(2 * i)));
+ }
+}
+
+DO_ODD_EVEN(vhsubw_hu_bu, 16, UH, UB, DO_SUB)
+DO_ODD_EVEN(vhsubw_wu_hu, 32, UW, UH, DO_SUB)
+DO_ODD_EVEN(vhsubw_du_wu, 64, UD, UW, DO_SUB)
+
+void HELPER(vhsubw_qu_du)(void *vd, void *vj, void *vk, uint32_t desc)
+{
+ int i;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ VReg *Vk = (VReg *)vk;
+ int oprsz = simd_oprsz(desc);
+
+ for (i = 0; i < oprsz / 16; i++) {
+ Vd->Q(i) = int128_sub(int128_make64(Vj->UD(2 * i + 1)),
+ int128_make64(Vk->UD(2 * i)));
+ }
+}
+
+#define DO_EVEN(NAME, BIT, E1, E2, DO_OP) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ typedef __typeof(Vd->E1(0)) TD; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ for (i = 0; i < oprsz / (BIT / 8); i++) { \
+ Vd->E1(i) = DO_OP((TD)Vj->E2(2 * i) ,(TD)Vk->E2(2 * i)); \
+ } \
+}
+
+#define DO_ODD(NAME, BIT, E1, E2, DO_OP) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ typedef __typeof(Vd->E1(0)) TD; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ for (i = 0; i < oprsz / (BIT / 8); i++) { \
+ Vd->E1(i) = DO_OP((TD)Vj->E2(2 * i + 1), (TD)Vk->E2(2 * i + 1)); \
+ } \
+}
+
+void HELPER(vaddwev_q_d)(void *vd, void *vj, void *vk, uint32_t desc)
+{
+ int i;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ VReg *Vk = (VReg *)vk;
+ int oprsz = simd_oprsz(desc);
+
+ for (i = 0; i < oprsz / 16; i++) {
+ Vd->Q(i) = int128_add(int128_makes64(Vj->D(2 * i)),
+ int128_makes64(Vk->D(2 * i)));
+ }
+}
+
+DO_EVEN(vaddwev_h_b, 16, H, B, DO_ADD)
+DO_EVEN(vaddwev_w_h, 32, W, H, DO_ADD)
+DO_EVEN(vaddwev_d_w, 64, D, W, DO_ADD)
+
+void HELPER(vaddwod_q_d)(void *vd, void *vj, void *vk, uint32_t desc)
+{
+ int i;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ VReg *Vk = (VReg *)vk;
+ int oprsz = simd_oprsz(desc);
+
+ for (i = 0; i < oprsz / 16; i++) {
+ Vd->Q(i) = int128_add(int128_makes64(Vj->D(2 * i +1)),
+ int128_makes64(Vk->D(2 * i +1)));
+ }
+}
+
+DO_ODD(vaddwod_h_b, 16, H, B, DO_ADD)
+DO_ODD(vaddwod_w_h, 32, W, H, DO_ADD)
+DO_ODD(vaddwod_d_w, 64, D, W, DO_ADD)
+
+void HELPER(vsubwev_q_d)(void *vd, void *vj, void *vk, uint32_t desc)
+{
+ int i;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ VReg *Vk = (VReg *)vk;
+ int oprsz = simd_oprsz(desc);
+
+ for (i = 0; i < oprsz / 16; i++) {
+ Vd->Q(i) = int128_sub(int128_makes64(Vj->D(2 * i)),
+ int128_makes64(Vk->D(2 * i)));
+ }
+}
+
+DO_EVEN(vsubwev_h_b, 16, H, B, DO_SUB)
+DO_EVEN(vsubwev_w_h, 32, W, H, DO_SUB)
+DO_EVEN(vsubwev_d_w, 64, D, W, DO_SUB)
+
+void HELPER(vsubwod_q_d)(void *vd, void *vj, void *vk, uint32_t desc)
+{
+ int i;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ VReg *Vk = (VReg *)vk;
+ int oprsz = simd_oprsz(desc);
+
+ for (i = 0; i < oprsz / 16; i++) {
+ Vd->Q(i) = int128_sub(int128_makes64(Vj->D(2 * i + 1)),
+ int128_makes64(Vk->D(2 * i + 1)));
+ }
+}
+
+DO_ODD(vsubwod_h_b, 16, H, B, DO_SUB)
+DO_ODD(vsubwod_w_h, 32, W, H, DO_SUB)
+DO_ODD(vsubwod_d_w, 64, D, W, DO_SUB)
+
+void HELPER(vaddwev_q_du)(void *vd, void *vj, void *vk, uint32_t desc)
+{
+ int i;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ VReg *Vk = (VReg *)vk;
+ int oprsz = simd_oprsz(desc);
+
+ for (i = 0; i < oprsz / 16; i++) {
+ Vd->Q(i) = int128_add(int128_make64(Vj->UD(2 * i)),
+ int128_make64(Vk->UD(2 * i)));
+ }
+}
+
+DO_EVEN(vaddwev_h_bu, 16, UH, UB, DO_ADD)
+DO_EVEN(vaddwev_w_hu, 32, UW, UH, DO_ADD)
+DO_EVEN(vaddwev_d_wu, 64, UD, UW, DO_ADD)
+
+void HELPER(vaddwod_q_du)(void *vd, void *vj, void *vk, uint32_t desc)
+{
+ int i;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ VReg *Vk = (VReg *)vk;
+ int oprsz = simd_oprsz(desc);
+
+ for (i = 0; i < oprsz / 16; i++) {
+ Vd->Q(i) = int128_add(int128_make64(Vj->UD(2 * i + 1)),
+ int128_make64(Vk->UD(2 * i + 1)));
+ }
+}
+
+DO_ODD(vaddwod_h_bu, 16, UH, UB, DO_ADD)
+DO_ODD(vaddwod_w_hu, 32, UW, UH, DO_ADD)
+DO_ODD(vaddwod_d_wu, 64, UD, UW, DO_ADD)
+
+void HELPER(vsubwev_q_du)(void *vd, void *vj, void *vk, uint32_t desc)
+{
+ int i;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ VReg *Vk = (VReg *)vk;
+ int oprsz = simd_oprsz(desc);
+
+ for (i = 0; i < oprsz / 16; i++) {
+ Vd->Q(i) = int128_sub(int128_make64(Vj->UD(2 * i)),
+ int128_make64(Vk->UD(2 * i)));
+ }
+}
+
+DO_EVEN(vsubwev_h_bu, 16, UH, UB, DO_SUB)
+DO_EVEN(vsubwev_w_hu, 32, UW, UH, DO_SUB)
+DO_EVEN(vsubwev_d_wu, 64, UD, UW, DO_SUB)
+
+void HELPER(vsubwod_q_du)(void *vd, void *vj, void *vk, uint32_t desc)
+{
+ int i;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ VReg *Vk = (VReg *)vk;
+ int oprsz = simd_oprsz(desc);
+
+ for (i = 0; i < oprsz / 16; i++) {
+ Vd->Q(i) = int128_sub(int128_make64(Vj->UD(2 * i + 1)),
+ int128_make64(Vk->UD(2 * i + 1)));
+ }
+}
+
+DO_ODD(vsubwod_h_bu, 16, UH, UB, DO_SUB)
+DO_ODD(vsubwod_w_hu, 32, UW, UH, DO_SUB)
+DO_ODD(vsubwod_d_wu, 64, UD, UW, DO_SUB)
+
+#define DO_EVEN_U_S(NAME, BIT, ES1, EU1, ES2, EU2, DO_OP) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ typedef __typeof(Vd->ES1(0)) TDS; \
+ typedef __typeof(Vd->EU1(0)) TDU; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ for (i = 0; i < oprsz / (BIT / 8); i++) { \
+ Vd->ES1(i) = DO_OP((TDU)Vj->EU2(2 * i) ,(TDS)Vk->ES2(2 * i)); \
+ } \
+}
+
+#define DO_ODD_U_S(NAME, BIT, ES1, EU1, ES2, EU2, DO_OP) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ typedef __typeof(Vd->ES1(0)) TDS; \
+ typedef __typeof(Vd->EU1(0)) TDU; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ for (i = 0; i < oprsz / (BIT / 8); i++) { \
+ Vd->ES1(i) = DO_OP((TDU)Vj->EU2(2 * i + 1), (TDS)Vk->ES2(2 * i + 1)); \
+ } \
+}
+
+void HELPER(vaddwev_q_du_d)(void *vd, void *vj, void *vk, uint32_t desc)
+{
+ int i;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ VReg *Vk = (VReg *)vk;
+ int oprsz = simd_oprsz(desc);
+
+ for (i = 0; i < oprsz / 16; i++) {
+ Vd->Q(i) = int128_add(int128_make64(Vj->UD(2 * i)),
+ int128_makes64(Vk->D(2 * i)));
+ }
+}
+
+DO_EVEN_U_S(vaddwev_h_bu_b, 16, H, UH, B, UB, DO_ADD)
+DO_EVEN_U_S(vaddwev_w_hu_h, 32, W, UW, H, UH, DO_ADD)
+DO_EVEN_U_S(vaddwev_d_wu_w, 64, D, UD, W, UW, DO_ADD)
+
+void HELPER(vaddwod_q_du_d)(void *vd, void *vj, void *vk, uint32_t desc)
+{
+ int i;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ VReg *Vk = (VReg *)vk;
+ int oprsz = simd_oprsz(desc);
+
+ for (i = 0; i < oprsz / 16; i++) {
+ Vd->Q(i) = int128_add(int128_make64(Vj->UD(2 * i + 1)),
+ int128_makes64(Vk->D(2 * i + 1)));
+ }
+}
+
+DO_ODD_U_S(vaddwod_h_bu_b, 16, H, UH, B, UB, DO_ADD)
+DO_ODD_U_S(vaddwod_w_hu_h, 32, W, UW, H, UH, DO_ADD)
+DO_ODD_U_S(vaddwod_d_wu_w, 64, D, UD, W, UW, DO_ADD)
+
+#define DO_3OP(NAME, BIT, E, DO_OP) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ for (i = 0; i < oprsz / (BIT / 8); i++) { \
+ Vd->E(i) = DO_OP(Vj->E(i), Vk->E(i)); \
+ } \
+}
+
+DO_3OP(vavg_b, 8, B, DO_VAVG)
+DO_3OP(vavg_h, 16, H, DO_VAVG)
+DO_3OP(vavg_w, 32, W, DO_VAVG)
+DO_3OP(vavg_d, 64, D, DO_VAVG)
+DO_3OP(vavgr_b, 8, B, DO_VAVGR)
+DO_3OP(vavgr_h, 16, H, DO_VAVGR)
+DO_3OP(vavgr_w, 32, W, DO_VAVGR)
+DO_3OP(vavgr_d, 64, D, DO_VAVGR)
+DO_3OP(vavg_bu, 8, UB, DO_VAVG)
+DO_3OP(vavg_hu, 16, UH, DO_VAVG)
+DO_3OP(vavg_wu, 32, UW, DO_VAVG)
+DO_3OP(vavg_du, 64, UD, DO_VAVG)
+DO_3OP(vavgr_bu, 8, UB, DO_VAVGR)
+DO_3OP(vavgr_hu, 16, UH, DO_VAVGR)
+DO_3OP(vavgr_wu, 32, UW, DO_VAVGR)
+DO_3OP(vavgr_du, 64, UD, DO_VAVGR)
+
+DO_3OP(vabsd_b, 8, B, DO_VABSD)
+DO_3OP(vabsd_h, 16, H, DO_VABSD)
+DO_3OP(vabsd_w, 32, W, DO_VABSD)
+DO_3OP(vabsd_d, 64, D, DO_VABSD)
+DO_3OP(vabsd_bu, 8, UB, DO_VABSD)
+DO_3OP(vabsd_hu, 16, UH, DO_VABSD)
+DO_3OP(vabsd_wu, 32, UW, DO_VABSD)
+DO_3OP(vabsd_du, 64, UD, DO_VABSD)
+
+#define DO_VADDA(NAME, BIT, E) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ for (i = 0; i < oprsz / (BIT / 8); i++) { \
+ Vd->E(i) = DO_VABS(Vj->E(i)) + DO_VABS(Vk->E(i)); \
+ } \
+}
+
+DO_VADDA(vadda_b, 8, B)
+DO_VADDA(vadda_h, 16, H)
+DO_VADDA(vadda_w, 32, W)
+DO_VADDA(vadda_d, 64, D)
+
+#define VMINMAXI(NAME, BIT, E, DO_OP) \
+void HELPER(NAME)(void *vd, void *vj, uint64_t imm, uint32_t desc) \
+{ \
+ int i; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ typedef __typeof(Vd->E(0)) TD; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ for (i = 0; i < oprsz / (BIT / 8); i++) { \
+ Vd->E(i) = DO_OP(Vj->E(i), (TD)imm); \
+ } \
+}
+
+VMINMAXI(vmini_b, 8, B, DO_MIN)
+VMINMAXI(vmini_h, 16, H, DO_MIN)
+VMINMAXI(vmini_w, 32, W, DO_MIN)
+VMINMAXI(vmini_d, 64, D, DO_MIN)
+VMINMAXI(vmaxi_b, 8, B, DO_MAX)
+VMINMAXI(vmaxi_h, 16, H, DO_MAX)
+VMINMAXI(vmaxi_w, 32, W, DO_MAX)
+VMINMAXI(vmaxi_d, 64, D, DO_MAX)
+VMINMAXI(vmini_bu, 8, UB, DO_MIN)
+VMINMAXI(vmini_hu, 16, UH, DO_MIN)
+VMINMAXI(vmini_wu, 32, UW, DO_MIN)
+VMINMAXI(vmini_du, 64, UD, DO_MIN)
+VMINMAXI(vmaxi_bu, 8, UB, DO_MAX)
+VMINMAXI(vmaxi_hu, 16, UH, DO_MAX)
+VMINMAXI(vmaxi_wu, 32, UW, DO_MAX)
+VMINMAXI(vmaxi_du, 64, UD, DO_MAX)
+
+#define DO_VMUH(NAME, BIT, E1, E2, DO_OP) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ typedef __typeof(Vd->E1(0)) T; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ for (i = 0; i < oprsz / (BIT / 8); i++) { \
+ Vd->E2(i) = ((T)Vj->E2(i)) * ((T)Vk->E2(i)) >> BIT; \
+ } \
+}
+
+void HELPER(vmuh_d)(void *vd, void *vj, void *vk, uint32_t desc)
+{
+ int i;
+ uint64_t l, h;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ VReg *Vk = (VReg *)vk;
+ int oprsz = simd_oprsz(desc);
+
+ for (i = 0; i < oprsz / 8; i++) {
+ muls64(&l, &h, Vj->D(i), Vk->D(i));
+ Vd->D(i) = h;
+ }
+}
+
+DO_VMUH(vmuh_b, 8, H, B, DO_MUH)
+DO_VMUH(vmuh_h, 16, W, H, DO_MUH)
+DO_VMUH(vmuh_w, 32, D, W, DO_MUH)
+
+void HELPER(vmuh_du)(void *vd, void *vj, void *vk, uint32_t desc)
+{
+ int i;
+ uint64_t l, h;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ VReg *Vk = (VReg *)vk;
+ int oprsz = simd_oprsz(desc);
+
+ for (i = 0; i < oprsz / 8; i++) {
+ mulu64(&l, &h, Vj->D(i), Vk->D(i));
+ Vd->D(i) = h;
+ }
+}
+
+DO_VMUH(vmuh_bu, 8, UH, UB, DO_MUH)
+DO_VMUH(vmuh_hu, 16, UW, UH, DO_MUH)
+DO_VMUH(vmuh_wu, 32, UD, UW, DO_MUH)
+
+DO_EVEN(vmulwev_h_b, 16, H, B, DO_MUL)
+DO_EVEN(vmulwev_w_h, 32, W, H, DO_MUL)
+DO_EVEN(vmulwev_d_w, 64, D, W, DO_MUL)
+
+DO_ODD(vmulwod_h_b, 16, H, B, DO_MUL)
+DO_ODD(vmulwod_w_h, 32, W, H, DO_MUL)
+DO_ODD(vmulwod_d_w, 64, D, W, DO_MUL)
+
+DO_EVEN(vmulwev_h_bu, 16, UH, UB, DO_MUL)
+DO_EVEN(vmulwev_w_hu, 32, UW, UH, DO_MUL)
+DO_EVEN(vmulwev_d_wu, 64, UD, UW, DO_MUL)
+
+DO_ODD(vmulwod_h_bu, 16, UH, UB, DO_MUL)
+DO_ODD(vmulwod_w_hu, 32, UW, UH, DO_MUL)
+DO_ODD(vmulwod_d_wu, 64, UD, UW, DO_MUL)
+
+DO_EVEN_U_S(vmulwev_h_bu_b, 16, H, UH, B, UB, DO_MUL)
+DO_EVEN_U_S(vmulwev_w_hu_h, 32, W, UW, H, UH, DO_MUL)
+DO_EVEN_U_S(vmulwev_d_wu_w, 64, D, UD, W, UW, DO_MUL)
+
+DO_ODD_U_S(vmulwod_h_bu_b, 16, H, UH, B, UB, DO_MUL)
+DO_ODD_U_S(vmulwod_w_hu_h, 32, W, UW, H, UH, DO_MUL)
+DO_ODD_U_S(vmulwod_d_wu_w, 64, D, UD, W, UW, DO_MUL)
+
+#define VMADDSUB(NAME, BIT, E, DO_OP) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ for (i = 0; i < oprsz / (BIT / 8); i++) { \
+ Vd->E(i) = DO_OP(Vd->E(i), Vj->E(i) ,Vk->E(i)); \
+ } \
+}
+
+VMADDSUB(vmadd_b, 8, B, DO_MADD)
+VMADDSUB(vmadd_h, 16, H, DO_MADD)
+VMADDSUB(vmadd_w, 32, W, DO_MADD)
+VMADDSUB(vmadd_d, 64, D, DO_MADD)
+VMADDSUB(vmsub_b, 8, B, DO_MSUB)
+VMADDSUB(vmsub_h, 16, H, DO_MSUB)
+VMADDSUB(vmsub_w, 32, W, DO_MSUB)
+VMADDSUB(vmsub_d, 64, D, DO_MSUB)
+
+#define VMADDWEV(NAME, BIT, E1, E2, DO_OP) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ typedef __typeof(Vd->E1(0)) TD; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ for (i = 0; i < oprsz / (BIT / 8); i++) { \
+ Vd->E1(i) += DO_OP((TD)Vj->E2(2 * i), (TD)Vk->E2(2 * i)); \
+ } \
+}
+
+VMADDWEV(vmaddwev_h_b, 16, H, B, DO_MUL)
+VMADDWEV(vmaddwev_w_h, 32, W, H, DO_MUL)
+VMADDWEV(vmaddwev_d_w, 64, D, W, DO_MUL)
+VMADDWEV(vmaddwev_h_bu, 16, UH, UB, DO_MUL)
+VMADDWEV(vmaddwev_w_hu, 32, UW, UH, DO_MUL)
+VMADDWEV(vmaddwev_d_wu, 64, UD, UW, DO_MUL)
+
+#define VMADDWOD(NAME, BIT, E1, E2, DO_OP) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ typedef __typeof(Vd->E1(0)) TD; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ for (i = 0; i < oprsz / (BIT / 8); i++) { \
+ Vd->E1(i) += DO_OP((TD)Vj->E2(2 * i + 1), \
+ (TD)Vk->E2(2 * i + 1)); \
+ } \
+}
+
+VMADDWOD(vmaddwod_h_b, 16, H, B, DO_MUL)
+VMADDWOD(vmaddwod_w_h, 32, W, H, DO_MUL)
+VMADDWOD(vmaddwod_d_w, 64, D, W, DO_MUL)
+VMADDWOD(vmaddwod_h_bu, 16, UH, UB, DO_MUL)
+VMADDWOD(vmaddwod_w_hu, 32, UW, UH, DO_MUL)
+VMADDWOD(vmaddwod_d_wu, 64, UD, UW, DO_MUL)
+
+#define VMADDWEV_U_S(NAME, BIT, ES1, EU1, ES2, EU2, DO_OP) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ typedef __typeof(Vd->ES1(0)) TS1; \
+ typedef __typeof(Vd->EU1(0)) TU1; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ for (i = 0; i < oprsz / (BIT / 8); i++) { \
+ Vd->ES1(i) += DO_OP((TU1)Vj->EU2(2 * i), \
+ (TS1)Vk->ES2(2 * i)); \
+ } \
+}
+
+VMADDWEV_U_S(vmaddwev_h_bu_b, 16, H, UH, B, UB, DO_MUL)
+VMADDWEV_U_S(vmaddwev_w_hu_h, 32, W, UW, H, UH, DO_MUL)
+VMADDWEV_U_S(vmaddwev_d_wu_w, 64, D, UD, W, UW, DO_MUL)
+
+#define VMADDWOD_U_S(NAME, BIT, ES1, EU1, ES2, EU2, DO_OP) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ typedef __typeof(Vd->ES1(0)) TS1; \
+ typedef __typeof(Vd->EU1(0)) TU1; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ for (i = 0; i < oprsz / (BIT / 8); i++) { \
+ Vd->ES1(i) += DO_OP((TU1)Vj->EU2(2 * i + 1), \
+ (TS1)Vk->ES2(2 * i + 1)); \
+ } \
+}
+
+VMADDWOD_U_S(vmaddwod_h_bu_b, 16, H, UH, B, UB, DO_MUL)
+VMADDWOD_U_S(vmaddwod_w_hu_h, 32, W, UW, H, UH, DO_MUL)
+VMADDWOD_U_S(vmaddwod_d_wu_w, 64, D, UD, W, UW, DO_MUL)
+
+#define VDIV(NAME, BIT, E, DO_OP) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ for (i = 0; i < oprsz / (BIT / 8); i++) { \
+ Vd->E(i) = DO_OP(Vj->E(i), Vk->E(i)); \
+ } \
+}
+
+VDIV(vdiv_b, 8, B, DO_DIV)
+VDIV(vdiv_h, 16, H, DO_DIV)
+VDIV(vdiv_w, 32, W, DO_DIV)
+VDIV(vdiv_d, 64, D, DO_DIV)
+VDIV(vdiv_bu, 8, UB, DO_DIVU)
+VDIV(vdiv_hu, 16, UH, DO_DIVU)
+VDIV(vdiv_wu, 32, UW, DO_DIVU)
+VDIV(vdiv_du, 64, UD, DO_DIVU)
+VDIV(vmod_b, 8, B, DO_REM)
+VDIV(vmod_h, 16, H, DO_REM)
+VDIV(vmod_w, 32, W, DO_REM)
+VDIV(vmod_d, 64, D, DO_REM)
+VDIV(vmod_bu, 8, UB, DO_REMU)
+VDIV(vmod_hu, 16, UH, DO_REMU)
+VDIV(vmod_wu, 32, UW, DO_REMU)
+VDIV(vmod_du, 64, UD, DO_REMU)
+
+#define VSAT_S(NAME, BIT, E) \
+void HELPER(NAME)(void *vd, void *vj, uint64_t max, uint32_t desc) \
+{ \
+ int i; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ typedef __typeof(Vd->E(0)) TD; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ for (i = 0; i < oprsz / (BIT / 8); i++) { \
+ Vd->E(i) = Vj->E(i) > (TD)max ? (TD)max : \
+ Vj->E(i) < (TD)~max ? (TD)~max: Vj->E(i); \
+ } \
+}
+
+VSAT_S(vsat_b, 8, B)
+VSAT_S(vsat_h, 16, H)
+VSAT_S(vsat_w, 32, W)
+VSAT_S(vsat_d, 64, D)
+
+#define VSAT_U(NAME, BIT, E) \
+void HELPER(NAME)(void *vd, void *vj, uint64_t max, uint32_t desc) \
+{ \
+ int i; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ typedef __typeof(Vd->E(0)) TD; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ for (i = 0; i < oprsz / (BIT / 8); i++) { \
+ Vd->E(i) = Vj->E(i) > (TD)max ? (TD)max : Vj->E(i); \
+ } \
+}
+
+VSAT_U(vsat_bu, 8, UB)
+VSAT_U(vsat_hu, 16, UH)
+VSAT_U(vsat_wu, 32, UW)
+VSAT_U(vsat_du, 64, UD)
+
+#define VEXTH(NAME, BIT, E1, E2) \
+void HELPER(NAME)(void *vd, void *vj, uint32_t desc) \
+{ \
+ int i, j, ofs; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ ofs = LSX_LEN / BIT; \
+ for (i = 0; i < oprsz / 16; i++) { \
+ for (j = 0; j < ofs; j++) { \
+ Vd->E1(j + i * ofs) = Vj->E2(j + ofs + ofs * 2 * i); \
+ } \
+ } \
+}
+
+void HELPER(vexth_q_d)(void *vd, void *vj, uint32_t desc)
+{
+ int i;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ int oprsz = simd_oprsz(desc);
+
+ for (i = 0; i < oprsz / 16; i++) {
+ Vd->Q(i) = int128_makes64(Vj->D(2 * i + 1));
+ }
+}
+
+void HELPER(vexth_qu_du)(void *vd, void *vj, uint32_t desc)
+{
+ int i;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ int oprsz = simd_oprsz(desc);
+
+ for (i = 0; i < oprsz / 16; i++) {
+ Vd->Q(i) = int128_make64(Vj->UD(2 * i + 1));
+ }
+}
+
+VEXTH(vexth_h_b, 16, H, B)
+VEXTH(vexth_w_h, 32, W, H)
+VEXTH(vexth_d_w, 64, D, W)
+VEXTH(vexth_hu_bu, 16, UH, UB)
+VEXTH(vexth_wu_hu, 32, UW, UH)
+VEXTH(vexth_du_wu, 64, UD, UW)
+
+#define VEXT2XV(NAME, BIT, E1, E2) \
+void HELPER(NAME)(void *vd, void *vj, uint32_t desc) \
+{ \
+ int i; \
+ VReg temp = {}; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ for (i = 0; i < oprsz / (BIT / 8); i++) { \
+ temp.E1(i) = Vj->E2(i); \
+ } \
+ *Vd = temp; \
+}
+
+VEXT2XV(vext2xv_h_b, 16, H, B)
+VEXT2XV(vext2xv_w_b, 32, W, B)
+VEXT2XV(vext2xv_d_b, 64, D, B)
+VEXT2XV(vext2xv_w_h, 32, W, H)
+VEXT2XV(vext2xv_d_h, 64, D, H)
+VEXT2XV(vext2xv_d_w, 64, D, W)
+VEXT2XV(vext2xv_hu_bu, 16, UH, UB)
+VEXT2XV(vext2xv_wu_bu, 32, UW, UB)
+VEXT2XV(vext2xv_du_bu, 64, UD, UB)
+VEXT2XV(vext2xv_wu_hu, 32, UW, UH)
+VEXT2XV(vext2xv_du_hu, 64, UD, UH)
+VEXT2XV(vext2xv_du_wu, 64, UD, UW)
+
+DO_3OP(vsigncov_b, 8, B, DO_SIGNCOV)
+DO_3OP(vsigncov_h, 16, H, DO_SIGNCOV)
+DO_3OP(vsigncov_w, 32, W, DO_SIGNCOV)
+DO_3OP(vsigncov_d, 64, D, DO_SIGNCOV)
+
+static uint64_t do_vmskltz_b(int64_t val)
+{
+ uint64_t m = 0x8080808080808080ULL;
+ uint64_t c = val & m;
+ c |= c << 7;
+ c |= c << 14;
+ c |= c << 28;
+ return c >> 56;
+}
+
+void HELPER(vmskltz_b)(void *vd, void *vj, uint32_t desc)
+{
+ int i;
+ uint16_t temp = 0;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ int oprsz = simd_oprsz(desc);
+
+ for (i = 0; i < oprsz / 16; i++) {
+ temp = 0;
+ temp = do_vmskltz_b(Vj->D(2 * i));
+ temp |= (do_vmskltz_b(Vj->D(2 * i + 1)) << 8);
+ Vd->D(2 * i) = temp;
+ Vd->D(2 * i + 1) = 0;
+ }
+}
+
+static uint64_t do_vmskltz_h(int64_t val)
+{
+ uint64_t m = 0x8000800080008000ULL;
+ uint64_t c = val & m;
+ c |= c << 15;
+ c |= c << 30;
+ return c >> 60;
+}
+
+void HELPER(vmskltz_h)(void *vd, void *vj, uint32_t desc)
+{
+ int i;
+ uint16_t temp = 0;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ int oprsz = simd_oprsz(desc);
+
+ for (i = 0; i < oprsz / 16; i++) {
+ temp = 0;
+ temp = do_vmskltz_h(Vj->D(2 * i));
+ temp |= (do_vmskltz_h(Vj->D(2 * i + 1)) << 4);
+ Vd->D(2 * i) = temp;
+ Vd->D(2 * i + 1) = 0;
+ }
+}
+
+static uint64_t do_vmskltz_w(int64_t val)
+{
+ uint64_t m = 0x8000000080000000ULL;
+ uint64_t c = val & m;
+ c |= c << 31;
+ return c >> 62;
+}
+
+void HELPER(vmskltz_w)(void *vd, void *vj, uint32_t desc)
+{
+ int i;
+ uint16_t temp = 0;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ int oprsz = simd_oprsz(desc);
+
+ for (i = 0; i < oprsz / 16; i++) {
+ temp = 0;
+ temp = do_vmskltz_w(Vj->D(2 * i));
+ temp |= (do_vmskltz_w(Vj->D(2 * i + 1)) << 2);
+ Vd->D(2 * i) = temp;
+ Vd->D(2 * i + 1) = 0;
+ }
+}
+
+static uint64_t do_vmskltz_d(int64_t val)
+{
+ return (uint64_t)val >> 63;
+}
+void HELPER(vmskltz_d)(void *vd, void *vj, uint32_t desc)
+{
+ int i;
+ uint16_t temp = 0;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ int oprsz = simd_oprsz(desc);
+
+ for (i = 0; i < oprsz / 16; i++) {
+ temp = 0;
+ temp = do_vmskltz_d(Vj->D(2 * i));
+ temp |= (do_vmskltz_d(Vj->D(2 * i + 1)) << 1);
+ Vd->D(2 * i) = temp;
+ Vd->D(2 * i + 1) = 0;
+ }
+}
+
+void HELPER(vmskgez_b)(void *vd, void *vj, uint32_t desc)
+{
+ int i;
+ uint16_t temp = 0;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ int oprsz = simd_oprsz(desc);
+
+ for (i = 0; i < oprsz / 16; i++) {
+ temp = 0;
+ temp = do_vmskltz_b(Vj->D(2 * i));
+ temp |= (do_vmskltz_b(Vj->D(2 * i + 1)) << 8);
+ Vd->D(2 * i) = (uint16_t)(~temp);
+ Vd->D(2 * i + 1) = 0;
+ }
+}
+
+static uint64_t do_vmskez_b(uint64_t a)
+{
+ uint64_t m = 0x7f7f7f7f7f7f7f7fULL;
+ uint64_t c = ~(((a & m) + m) | a | m);
+ c |= c << 7;
+ c |= c << 14;
+ c |= c << 28;
+ return c >> 56;
+}
+
+void HELPER(vmsknz_b)(void *vd, void *vj, uint32_t desc)
+{
+ int i;
+ uint16_t temp = 0;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ int oprsz = simd_oprsz(desc);
+
+ for (i = 0; i < oprsz / 16; i++) {
+ temp = 0;
+ temp = do_vmskez_b(Vj->D(2 * i));
+ temp |= (do_vmskez_b(Vj->D(2 * i + 1)) << 8);
+ Vd->D(2 * i) = (uint16_t)(~temp);
+ Vd->D(2 * i + 1) = 0;
+ }
+}
+
+void HELPER(vnori_b)(void *vd, void *vj, uint64_t imm, uint32_t desc)
+{
+ int i;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+
+ for (i = 0; i < simd_oprsz(desc); i++) {
+ Vd->B(i) = ~(Vj->B(i) | (uint8_t)imm);
+ }
+}
+
+#define VSLLWIL(NAME, BIT, E1, E2) \
+void HELPER(NAME)(void *vd, void *vj, uint64_t imm, uint32_t desc) \
+{ \
+ int i, j, ofs; \
+ VReg temp = {}; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ int oprsz = simd_oprsz(desc); \
+ typedef __typeof(temp.E1(0)) TD; \
+ \
+ ofs = LSX_LEN / BIT; \
+ for (i = 0; i < oprsz / 16; i++) { \
+ for (j = 0; j < ofs; j++) { \
+ temp.E1(j + ofs * i) = (TD)Vj->E2(j + ofs * 2 * i) << (imm % BIT); \
+ } \
+ } \
+ *Vd = temp; \
+}
+
+
+void HELPER(vextl_q_d)(void *vd, void *vj, uint32_t desc)
+{
+ int i;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ int oprsz = simd_oprsz(desc);
+
+ for (i = 0; i < oprsz / 16; i++) {
+ Vd->Q(i) = int128_makes64(Vj->D(2 * i));
+ }
+}
+
+void HELPER(vextl_qu_du)(void *vd, void *vj, uint32_t desc)
+{
+ int i;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ int oprsz = simd_oprsz(desc);
+
+ for (i = 0; i < oprsz / 16; i++) {
+ Vd->Q(i) = int128_make64(Vj->UD(2 * i));
+ }
+}
+
+VSLLWIL(vsllwil_h_b, 16, H, B)
+VSLLWIL(vsllwil_w_h, 32, W, H)
+VSLLWIL(vsllwil_d_w, 64, D, W)
+VSLLWIL(vsllwil_hu_bu, 16, UH, UB)
+VSLLWIL(vsllwil_wu_hu, 32, UW, UH)
+VSLLWIL(vsllwil_du_wu, 64, UD, UW)
+
+#define do_vsrlr(E, T) \
+static T do_vsrlr_ ##E(T s1, int sh) \
+{ \
+ if (sh == 0) { \
+ return s1; \
+ } else { \
+ return (s1 >> sh) + ((s1 >> (sh - 1)) & 0x1); \
+ } \
+}
+
+do_vsrlr(B, uint8_t)
+do_vsrlr(H, uint16_t)
+do_vsrlr(W, uint32_t)
+do_vsrlr(D, uint64_t)
+
+#define VSRLR(NAME, BIT, T, E) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ for (i = 0; i < oprsz / (BIT / 8); i++) { \
+ Vd->E(i) = do_vsrlr_ ## E(Vj->E(i), ((T)Vk->E(i))%BIT); \
+ } \
+}
+
+VSRLR(vsrlr_b, 8, uint8_t, B)
+VSRLR(vsrlr_h, 16, uint16_t, H)
+VSRLR(vsrlr_w, 32, uint32_t, W)
+VSRLR(vsrlr_d, 64, uint64_t, D)
+
+#define VSRLRI(NAME, BIT, E) \
+void HELPER(NAME)(void *vd, void *vj, uint64_t imm, uint32_t desc) \
+{ \
+ int i; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ for (i = 0; i < oprsz / (BIT / 8); i++) { \
+ Vd->E(i) = do_vsrlr_ ## E(Vj->E(i), imm); \
+ } \
+}
+
+VSRLRI(vsrlri_b, 8, B)
+VSRLRI(vsrlri_h, 16, H)
+VSRLRI(vsrlri_w, 32, W)
+VSRLRI(vsrlri_d, 64, D)
+
+#define do_vsrar(E, T) \
+static T do_vsrar_ ##E(T s1, int sh) \
+{ \
+ if (sh == 0) { \
+ return s1; \
+ } else { \
+ return (s1 >> sh) + ((s1 >> (sh - 1)) & 0x1); \
+ } \
+}
+
+do_vsrar(B, int8_t)
+do_vsrar(H, int16_t)
+do_vsrar(W, int32_t)
+do_vsrar(D, int64_t)
+
+#define VSRAR(NAME, BIT, T, E) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ for (i = 0; i < oprsz / (BIT / 8); i++) { \
+ Vd->E(i) = do_vsrar_ ## E(Vj->E(i), ((T)Vk->E(i))%BIT); \
+ } \
+}
+
+VSRAR(vsrar_b, 8, uint8_t, B)
+VSRAR(vsrar_h, 16, uint16_t, H)
+VSRAR(vsrar_w, 32, uint32_t, W)
+VSRAR(vsrar_d, 64, uint64_t, D)
+
+#define VSRARI(NAME, BIT, E) \
+void HELPER(NAME)(void *vd, void *vj, uint64_t imm, uint32_t desc) \
+{ \
+ int i; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ for (i = 0; i < oprsz / (BIT / 8); i++) { \
+ Vd->E(i) = do_vsrar_ ## E(Vj->E(i), imm); \
+ } \
+}
+
+VSRARI(vsrari_b, 8, B)
+VSRARI(vsrari_h, 16, H)
+VSRARI(vsrari_w, 32, W)
+VSRARI(vsrari_d, 64, D)
+
+#define VSRLN(NAME, BIT, E1, E2) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i, j, ofs; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ ofs = LSX_LEN / BIT; \
+ for (i = 0; i < oprsz / 16; i++) { \
+ for (j = 0; j < ofs; j++) { \
+ Vd->E1(j + ofs * 2 * i) = R_SHIFT(Vj->E2(j + ofs * i), \
+ Vk->E2(j + ofs * i) % BIT); \
+ } \
+ Vd->D(2 * i + 1) = 0; \
+ } \
+}
+
+VSRLN(vsrln_b_h, 16, B, UH)
+VSRLN(vsrln_h_w, 32, H, UW)
+VSRLN(vsrln_w_d, 64, W, UD)
+
+#define VSRAN(NAME, BIT, E1, E2, E3) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i, j, ofs; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ ofs = LSX_LEN / BIT; \
+ for (i = 0; i < oprsz / 16; i++) { \
+ for (j = 0; j < ofs; j++) { \
+ Vd->E1(j + ofs * 2 * i) = R_SHIFT(Vj->E2(j + ofs * i), \
+ Vk->E3(j + ofs * i) % BIT); \
+ } \
+ Vd->D(2 * i + 1) = 0; \
+ } \
+}
+
+VSRAN(vsran_b_h, 16, B, H, UH)
+VSRAN(vsran_h_w, 32, H, W, UW)
+VSRAN(vsran_w_d, 64, W, D, UD)
+
+#define VSRLNI(NAME, BIT, E1, E2) \
+void HELPER(NAME)(void *vd, void *vj, uint64_t imm, uint32_t desc) \
+{ \
+ int i, j, ofs; \
+ VReg temp = {}; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ ofs = LSX_LEN / BIT; \
+ for (i = 0; i < oprsz / 16; i++) { \
+ for (j = 0; j < ofs; j++) { \
+ temp.E1(j + ofs * 2 * i) = R_SHIFT(Vj->E2(j + ofs * i), imm); \
+ temp.E1(j + ofs * (2 * i + 1)) = R_SHIFT(Vd->E2(j + ofs * i), \
+ imm); \
+ } \
+ } \
+ *Vd = temp; \
+}
+
+void HELPER(vsrlni_d_q)(void *vd, void *vj, uint64_t imm, uint32_t desc)
+{
+ int i;
+ VReg temp = {};
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+
+ for (i = 0; i < 2; i++) {
+ temp.D(2 * i) = int128_getlo(int128_urshift(Vj->Q(i), imm % 128));
+ temp.D(2 * i +1) = int128_getlo(int128_urshift(Vd->Q(i), imm % 128));
+ }
+ *Vd = temp;
+}
+
+VSRLNI(vsrlni_b_h, 16, B, UH)
+VSRLNI(vsrlni_h_w, 32, H, UW)
+VSRLNI(vsrlni_w_d, 64, W, UD)
+
+#define VSRANI(NAME, BIT, E1, E2) \
+void HELPER(NAME)(void *vd, void *vj, uint64_t imm, uint32_t desc) \
+{ \
+ int i, j, ofs; \
+ VReg temp = {}; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ ofs = LSX_LEN / BIT; \
+ for (i = 0; i < oprsz / 16; i++) { \
+ for (j = 0; j < ofs; j++) { \
+ temp.E1(j + ofs * 2 * i) = R_SHIFT(Vj->E2(j + ofs * i), imm); \
+ temp.E1(j + ofs * (2 * i + 1)) = R_SHIFT(Vd->E2(j + ofs * i), \
+ imm); \
+ } \
+ } \
+ *Vd = temp; \
+}
+
+void HELPER(vsrani_d_q)(void *vd, void *vj, uint64_t imm, uint32_t desc)
+{
+ int i;
+ VReg temp = {};
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+
+ for (i = 0; i < 2; i++) {
+ temp.D(2 * i) = int128_getlo(int128_rshift(Vj->Q(i), imm % 128));
+ temp.D(2 * i + 1) = int128_getlo(int128_rshift(Vd->Q(i), imm % 128));
+ }
+ *Vd = temp;
+}
+
+VSRANI(vsrani_b_h, 16, B, H)
+VSRANI(vsrani_h_w, 32, H, W)
+VSRANI(vsrani_w_d, 64, W, D)
+
+#define VSRLRN(NAME, BIT, E1, E2, E3) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i, j, ofs; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ ofs = LSX_LEN / BIT; \
+ for (i = 0; i < oprsz / 16; i++) { \
+ for (j = 0; j < ofs; j++) { \
+ Vd->E1(j + ofs * 2 * i) = do_vsrlr_ ##E2(Vj->E2(j + ofs * i), \
+ Vk->E3(j + ofs * i) % BIT); \
+ } \
+ Vd->D(2 * i + 1) = 0; \
+ } \
+}
+
+VSRLRN(vsrlrn_b_h, 16, B, H, UH)
+VSRLRN(vsrlrn_h_w, 32, H, W, UW)
+VSRLRN(vsrlrn_w_d, 64, W, D, UD)
+
+#define VSRARN(NAME, BIT, E1, E2, E3) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i, j, ofs; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ ofs = LSX_LEN / BIT; \
+ for (i = 0; i < oprsz / 16; i++) { \
+ for (j = 0; j < ofs; j++) { \
+ Vd->E1(j + ofs * 2 * i) = do_vsrar_ ## E2(Vj->E2(j + ofs * i), \
+ Vk->E3(j + ofs * i) % BIT); \
+ } \
+ Vd->D(2 * i + 1) = 0; \
+ } \
+}
+
+VSRARN(vsrarn_b_h, 16, B, H, UH)
+VSRARN(vsrarn_h_w, 32, H, W, UW)
+VSRARN(vsrarn_w_d, 64, W, D, UD)
+
+#define VSRLRNI(NAME, BIT, E1, E2) \
+void HELPER(NAME)(void *vd, void *vj, uint64_t imm, uint32_t desc) \
+{ \
+ int i, j, ofs; \
+ VReg temp = {}; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ ofs = LSX_LEN / BIT; \
+ for (i = 0; i < oprsz / 16; i++) { \
+ for (j = 0; j < ofs; j++) { \
+ temp.E1(j + ofs * 2 * i) = do_vsrlr_ ## E2(Vj->E2(j + ofs * i), imm); \
+ temp.E1(j + ofs * (2 * i + 1)) = do_vsrlr_ ## E2(Vd->E2(j + ofs * i), \
+ imm); \
+ } \
+ } \
+ *Vd = temp; \
+}
+
+void HELPER(vsrlrni_d_q)(void *vd, void *vj, uint64_t imm, uint32_t desc)
+{
+ int i;
+ VReg temp = {};
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ Int128 r[4];
+ int oprsz = simd_oprsz(desc);
+
+ for (i = 0; i < oprsz / 16; i++) {
+ if (imm == 0) {
+ temp.D(2 * i) = int128_getlo(Vj->Q(i));
+ temp.D(2 * i + 1) = int128_getlo(Vd->Q(i));
+ } else {
+ r[2 * i] = int128_and(int128_urshift(Vj->Q(i), (imm - 1)),
+ int128_one());
+ r[2 * i + 1] = int128_and(int128_urshift(Vd->Q(i), (imm - 1)),
+ int128_one());
+ temp.D(2 * i) = int128_getlo(int128_add(int128_urshift(Vj->Q(i),
+ imm), r[2 * i]));
+ temp.D(2 * i + 1) = int128_getlo(int128_add(int128_urshift(Vd->Q(i),
+ imm), r[ 2 * i + 1]));
+ }
+ }
+ *Vd = temp;
+}
+
+VSRLRNI(vsrlrni_b_h, 16, B, H)
+VSRLRNI(vsrlrni_h_w, 32, H, W)
+VSRLRNI(vsrlrni_w_d, 64, W, D)
+
+#define VSRARNI(NAME, BIT, E1, E2) \
+void HELPER(NAME)(void *vd, void *vj, uint64_t imm, uint32_t desc) \
+{ \
+ int i, j, ofs; \
+ VReg temp = {}; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ ofs = LSX_LEN / BIT; \
+ for (i = 0; i < oprsz / 16; i++) { \
+ for (j = 0; j < ofs; j++) { \
+ temp.E1(j + ofs * 2 * i) = do_vsrar_ ## E2(Vj->E2(j + ofs * i), imm); \
+ temp.E1(j + ofs * (2 * i + 1)) = do_vsrar_ ## E2(Vd->E2(j + ofs * i), \
+ imm); \
+ } \
+ } \
+ *Vd = temp; \
+}
+
+void HELPER(vsrarni_d_q)(void *vd, void *vj, uint64_t imm, uint32_t desc)
+{
+ int i;
+ VReg temp = {};
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ Int128 r[4];
+ int oprsz = simd_oprsz(desc);
+
+ for (i = 0; i < oprsz / 16; i++) {
+ if (imm == 0) {
+ temp.D(2 * i) = int128_getlo(Vj->Q(i));
+ temp.D(2 * i + 1) = int128_getlo(Vd->Q(i));
+ } else {
+ r[2 * i] = int128_and(int128_rshift(Vj->Q(i), (imm - 1)),
+ int128_one());
+ r[2 * i + 1] = int128_and(int128_rshift(Vd->Q(i), (imm - 1)),
+ int128_one());
+ temp.D(2 * i) = int128_getlo(int128_add(int128_rshift(Vj->Q(i),
+ imm), r[2 * i]));
+ temp.D(2 * i + 1) = int128_getlo(int128_add(int128_rshift(Vd->Q(i),
+ imm), r[2 * i + 1]));
+ }
+ }
+ *Vd = temp;
+}
+
+VSRARNI(vsrarni_b_h, 16, B, H)
+VSRARNI(vsrarni_h_w, 32, H, W)
+VSRARNI(vsrarni_w_d, 64, W, D)
+
+#define SSRLNS(NAME, T1, T2, T3) \
+static T1 do_ssrlns_ ## NAME(T2 e2, int sa, int sh) \
+{ \
+ T1 shft_res; \
+ if (sa == 0) { \
+ shft_res = e2; \
+ } else { \
+ shft_res = (((T1)e2) >> sa); \
+ } \
+ T3 mask; \
+ mask = (1ull << sh) -1; \
+ if (shft_res > mask) { \
+ return mask; \
+ } else { \
+ return shft_res; \
+ } \
+}
+
+SSRLNS(B, uint16_t, int16_t, uint8_t)
+SSRLNS(H, uint32_t, int32_t, uint16_t)
+SSRLNS(W, uint64_t, int64_t, uint32_t)
+
+#define VSSRLN(NAME, BIT, E1, E2, E3) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i, j, ofs; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ ofs = LSX_LEN / BIT; \
+ for (i = 0; i < oprsz / 16; i++) { \
+ for (j = 0; j < ofs; j++) { \
+ Vd->E1(j + ofs * 2 * i) = do_ssrlns_ ## E1(Vj->E2(j + ofs * i), \
+ Vk->E3(j + ofs * i) % BIT, \
+ BIT / 2 - 1); \
+ } \
+ Vd->D(2 * i + 1) = 0; \
+ } \
+}
+
+VSSRLN(vssrln_b_h, 16, B, H, UH)
+VSSRLN(vssrln_h_w, 32, H, W, UW)
+VSSRLN(vssrln_w_d, 64, W, D, UD)
+
+#define SSRANS(E, T1, T2) \
+static T1 do_ssrans_ ## E(T1 e2, int sa, int sh) \
+{ \
+ T1 shft_res; \
+ if (sa == 0) { \
+ shft_res = e2; \
+ } else { \
+ shft_res = e2 >> sa; \
+ } \
+ T2 mask; \
+ mask = (1ll << sh) - 1; \
+ if (shft_res > mask) { \
+ return mask; \
+ } else if (shft_res < -(mask + 1)) { \
+ return ~mask; \
+ } else { \
+ return shft_res; \
+ } \
+}
+
+SSRANS(B, int16_t, int8_t)
+SSRANS(H, int32_t, int16_t)
+SSRANS(W, int64_t, int32_t)
+
+#define VSSRAN(NAME, BIT, E1, E2, E3) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i, j, ofs; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ ofs = LSX_LEN / BIT; \
+ for (i = 0; i < oprsz / 16; i++) { \
+ for (j = 0; j < ofs; j++) { \
+ Vd->E1(j + ofs * 2 * i) = do_ssrans_ ## E1(Vj->E2(j + ofs * i), \
+ Vk->E3(j + ofs * i) % BIT, \
+ BIT / 2 - 1); \
+ } \
+ Vd->D(2 * i + 1) = 0; \
+ } \
+}
+
+VSSRAN(vssran_b_h, 16, B, H, UH)
+VSSRAN(vssran_h_w, 32, H, W, UW)
+VSSRAN(vssran_w_d, 64, W, D, UD)
+
+#define SSRLNU(E, T1, T2, T3) \
+static T1 do_ssrlnu_ ## E(T3 e2, int sa, int sh) \
+{ \
+ T1 shft_res; \
+ if (sa == 0) { \
+ shft_res = e2; \
+ } else { \
+ shft_res = (((T1)e2) >> sa); \
+ } \
+ T2 mask; \
+ mask = (1ull << sh) - 1; \
+ if (shft_res > mask) { \
+ return mask; \
+ } else { \
+ return shft_res; \
+ } \
+}
+
+SSRLNU(B, uint16_t, uint8_t, int16_t)
+SSRLNU(H, uint32_t, uint16_t, int32_t)
+SSRLNU(W, uint64_t, uint32_t, int64_t)
+
+#define VSSRLNU(NAME, BIT, E1, E2, E3) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i, j, ofs; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ ofs = LSX_LEN / BIT; \
+ for (i = 0; i < oprsz / 16; i++) { \
+ for (j = 0; j < ofs; j++) { \
+ Vd->E1(j + ofs * 2 * i) = do_ssrlnu_ ## E1(Vj->E2(j + ofs * i), \
+ Vk->E3(j + ofs * i) % BIT, \
+ BIT / 2); \
+ } \
+ Vd->D(2 * i + 1) = 0; \
+ } \
+}
+
+VSSRLNU(vssrln_bu_h, 16, B, H, UH)
+VSSRLNU(vssrln_hu_w, 32, H, W, UW)
+VSSRLNU(vssrln_wu_d, 64, W, D, UD)
+
+#define SSRANU(E, T1, T2, T3) \
+static T1 do_ssranu_ ## E(T3 e2, int sa, int sh) \
+{ \
+ T1 shft_res; \
+ if (sa == 0) { \
+ shft_res = e2; \
+ } else { \
+ shft_res = e2 >> sa; \
+ } \
+ if (e2 < 0) { \
+ shft_res = 0; \
+ } \
+ T2 mask; \
+ mask = (1ull << sh) - 1; \
+ if (shft_res > mask) { \
+ return mask; \
+ } else { \
+ return shft_res; \
+ } \
+}
+
+SSRANU(B, uint16_t, uint8_t, int16_t)
+SSRANU(H, uint32_t, uint16_t, int32_t)
+SSRANU(W, uint64_t, uint32_t, int64_t)
+
+#define VSSRANU(NAME, BIT, E1, E2, E3) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i, j, ofs; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ ofs = LSX_LEN / BIT; \
+ for (i = 0; i < oprsz / 16; i++) { \
+ for (j = 0; j < ofs; j++) { \
+ Vd->E1(j + ofs * 2 * i) = do_ssranu_ ## E1(Vj->E2(j + ofs * i), \
+ Vk->E3(j + ofs * i) % BIT, \
+ BIT / 2); \
+ } \
+ Vd->D(2 * i + 1) = 0; \
+ } \
+}
+
+VSSRANU(vssran_bu_h, 16, B, H, UH)
+VSSRANU(vssran_hu_w, 32, H, W, UW)
+VSSRANU(vssran_wu_d, 64, W, D, UD)
+
+#define VSSRLNI(NAME, BIT, E1, E2) \
+void HELPER(NAME)(void *vd, void *vj, uint64_t imm, uint32_t desc) \
+{ \
+ int i, j, ofs; \
+ VReg temp = {}; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ ofs = LSX_LEN / BIT; \
+ for (i = 0; i < oprsz / 16; i++) { \
+ for (j = 0; j < ofs; j++) { \
+ temp.E1(j + ofs * 2 * i) = do_ssrlns_ ## E1(Vj->E2(j + ofs * i), \
+ imm, BIT / 2 - 1); \
+ temp.E1(j + ofs * (2 * i + 1)) = do_ssrlns_ ## E1(Vd->E2(j + ofs * i), \
+ imm, BIT / 2 - 1); \
+ } \
+ } \
+ *Vd = temp; \
+}
+
+static void do_vssrlni_q(VReg *Vd, VReg *Vj,
+ uint64_t imm, int idx, Int128 mask)
+{
+ Int128 shft_res1, shft_res2;
+
+ if (imm == 0) {
+ shft_res1 = Vj->Q(idx);
+ shft_res2 = Vd->Q(idx);
+ } else {
+ shft_res1 = int128_urshift(Vj->Q(idx), imm);
+ shft_res2 = int128_urshift(Vd->Q(idx), imm);
+ }
+
+ if (int128_ult(mask, shft_res1)) {
+ Vd->D(idx * 2) = int128_getlo(mask);
+ }else {
+ Vd->D(idx * 2) = int128_getlo(shft_res1);
+ }
+
+ if (int128_ult(mask, shft_res2)) {
+ Vd->D(idx * 2 + 1) = int128_getlo(mask);
+ }else {
+ Vd->D(idx * 2 + 1) = int128_getlo(shft_res2);
+ }
+}
+
+void HELPER(vssrlni_d_q)(void *vd, void *vj, uint64_t imm, uint32_t desc)
+{
+ int i;
+ Int128 mask;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ int oprsz = simd_oprsz(desc);
+
+ mask = int128_sub(int128_lshift(int128_one(), 63), int128_one());
+
+ for (i = 0; i < oprsz / 16; i++) {
+ do_vssrlni_q(Vd, Vj, imm, i, mask);
+ }
+}
+
+VSSRLNI(vssrlni_b_h, 16, B, H)
+VSSRLNI(vssrlni_h_w, 32, H, W)
+VSSRLNI(vssrlni_w_d, 64, W, D)
+
+#define VSSRANI(NAME, BIT, E1, E2) \
+void HELPER(NAME)(void *vd, void *vj, uint64_t imm, uint32_t desc) \
+{ \
+ int i, j, ofs; \
+ VReg temp = {}; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ ofs = LSX_LEN / BIT; \
+ for (i = 0; i < oprsz / 16; i++) { \
+ for (j = 0; j < ofs; j++) { \
+ temp.E1(j + ofs * 2 * i) = do_ssrans_ ## E1(Vj->E2(j + ofs * i), \
+ imm, BIT / 2 - 1); \
+ temp.E1(j + ofs * (2 * i + 1)) = do_ssrans_ ## E1(Vd->E2(j + ofs * i), \
+ imm, BIT / 2 - 1); \
+ } \
+ } \
+ *Vd = temp; \
+}
+
+static void do_vssrani_d_q(VReg *Vd, VReg *Vj,
+ uint64_t imm, int idx, Int128 mask, Int128 min)
+{
+ Int128 shft_res1, shft_res2;
+
+ if (imm == 0) {
+ shft_res1 = Vj->Q(idx);
+ shft_res2 = Vd->Q(idx);
+ } else {
+ shft_res1 = int128_rshift(Vj->Q(idx), imm);
+ shft_res2 = int128_rshift(Vd->Q(idx), imm);
+ }
+
+ if (int128_gt(shft_res1, mask)) {
+ Vd->D(idx * 2) = int128_getlo(mask);
+ } else if (int128_lt(shft_res1, int128_neg(min))) {
+ Vd->D(idx * 2) = int128_getlo(min);
+ } else {
+ Vd->D(idx * 2) = int128_getlo(shft_res1);
+ }
+
+ if (int128_gt(shft_res2, mask)) {
+ Vd->D(idx * 2 + 1) = int128_getlo(mask);
+ } else if (int128_lt(shft_res2, int128_neg(min))) {
+ Vd->D(idx * 2 + 1) = int128_getlo(min);
+ } else {
+ Vd->D(idx * 2 + 1) = int128_getlo(shft_res2);
+ }
+}
+
+void HELPER(vssrani_d_q)(void *vd, void *vj, uint64_t imm, uint32_t desc)
+{
+ int i;
+ Int128 mask, min;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ int oprsz = simd_oprsz(desc);
+
+ mask = int128_sub(int128_lshift(int128_one(), 63), int128_one());
+ min = int128_lshift(int128_one(), 63);
+
+ for (i = 0; i < oprsz / 16; i++) {
+ do_vssrani_d_q(Vd, Vj, imm, i, mask, min);
+ }
+}
+
+
+VSSRANI(vssrani_b_h, 16, B, H)
+VSSRANI(vssrani_h_w, 32, H, W)
+VSSRANI(vssrani_w_d, 64, W, D)
+
+#define VSSRLNUI(NAME, BIT, E1, E2) \
+void HELPER(NAME)(void *vd, void *vj, uint64_t imm, uint32_t desc) \
+{ \
+ int i, j, ofs; \
+ VReg temp = {}; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ ofs = LSX_LEN / BIT; \
+ for (i = 0; i < oprsz / 16; i++) { \
+ for (j = 0; j < ofs; j++) { \
+ temp.E1(j + ofs * 2 * i) = do_ssrlnu_ ## E1(Vj->E2(j + ofs * i), \
+ imm, BIT / 2); \
+ temp.E1(j + ofs * (2 * i + 1)) = do_ssrlnu_ ## E1(Vd->E2(j + ofs * i), \
+ imm, BIT / 2); \
+ } \
+ } \
+ *Vd = temp; \
+}
+
+void HELPER(vssrlni_du_q)(void *vd, void *vj, uint64_t imm, uint32_t desc)
+{
+ int i;
+ Int128 mask;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ int oprsz = simd_oprsz(desc);
+
+ mask = int128_sub(int128_lshift(int128_one(), 64), int128_one());
+
+ for (i = 0; i < oprsz / 16; i++) {
+ do_vssrlni_q(Vd, Vj, imm, i, mask);
+ }
+}
+
+VSSRLNUI(vssrlni_bu_h, 16, B, H)
+VSSRLNUI(vssrlni_hu_w, 32, H, W)
+VSSRLNUI(vssrlni_wu_d, 64, W, D)
+
+#define VSSRANUI(NAME, BIT, E1, E2) \
+void HELPER(NAME)(void *vd, void *vj, uint64_t imm, uint32_t desc) \
+{ \
+ int i, j, ofs; \
+ VReg temp = {}; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ ofs = LSX_LEN / BIT; \
+ for (i = 0; i < oprsz / 16; i++) { \
+ for (j = 0; j < ofs; j++) { \
+ temp.E1(j + ofs * 2 * i) = do_ssranu_ ## E1(Vj->E2(j + ofs * i), \
+ imm, BIT / 2); \
+ temp.E1(j + ofs * (2 * i + 1)) = do_ssranu_ ## E1(Vd->E2(j + ofs * i), \
+ imm, BIT / 2); \
+ } \
+ } \
+ *Vd = temp; \
+}
+
+static void do_vssrani_du_q(VReg *Vd, VReg *Vj,
+ uint64_t imm, int idx, Int128 mask)
+{
+ Int128 shft_res1, shft_res2;
+
+ if (imm == 0) {
+ shft_res1 = Vj->Q(idx);
+ shft_res2 = Vd->Q(idx);
+ } else {
+ shft_res1 = int128_rshift(Vj->Q(idx), imm);
+ shft_res2 = int128_rshift(Vd->Q(idx), imm);
+ }
+
+ if (int128_lt(Vj->Q(idx), int128_zero())) {
+ shft_res1 = int128_zero();
+ }
+
+ if (int128_lt(Vd->Q(idx), int128_zero())) {
+ shft_res2 = int128_zero();
+ }
+ if (int128_ult(mask, shft_res1)) {
+ Vd->D(idx * 2) = int128_getlo(mask);
+ }else {
+ Vd->D(idx * 2) = int128_getlo(shft_res1);
+ }
+
+ if (int128_ult(mask, shft_res2)) {
+ Vd->D(idx * 2 + 1) = int128_getlo(mask);
+ }else {
+ Vd->D(idx * 2 + 1) = int128_getlo(shft_res2);
+ }
+
+}
+
+void HELPER(vssrani_du_q)(void *vd, void *vj, uint64_t imm, uint32_t desc)
+{
+ int i;
+ Int128 mask;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ int oprsz = simd_oprsz(desc);
+
+ mask = int128_sub(int128_lshift(int128_one(), 64), int128_one());
+
+ for (i = 0; i < oprsz / 16; i++) {
+ do_vssrani_du_q(Vd, Vj, imm, i, mask);
+ }
+}
+
+VSSRANUI(vssrani_bu_h, 16, B, H)
+VSSRANUI(vssrani_hu_w, 32, H, W)
+VSSRANUI(vssrani_wu_d, 64, W, D)
+
+#define SSRLRNS(E1, E2, T1, T2, T3) \
+static T1 do_ssrlrns_ ## E1(T2 e2, int sa, int sh) \
+{ \
+ T1 shft_res; \
+ \
+ shft_res = do_vsrlr_ ## E2(e2, sa); \
+ T1 mask; \
+ mask = (1ull << sh) - 1; \
+ if (shft_res > mask) { \
+ return mask; \
+ } else { \
+ return shft_res; \
+ } \
+}
+
+SSRLRNS(B, H, uint16_t, int16_t, uint8_t)
+SSRLRNS(H, W, uint32_t, int32_t, uint16_t)
+SSRLRNS(W, D, uint64_t, int64_t, uint32_t)
+
+#define VSSRLRN(NAME, BIT, E1, E2, E3) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i, j, ofs; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ ofs = LSX_LEN / BIT; \
+ for (i = 0; i < oprsz / 16; i++) { \
+ for (j = 0; j < ofs; j++) { \
+ Vd->E1(j + ofs * 2 * i) = do_ssrlrns_ ## E1(Vj->E2(j + ofs * i), \
+ Vk->E3(j + ofs * i) % BIT, \
+ BIT / 2 - 1); \
+ } \
+ Vd->D(2 * i + 1) = 0; \
+ } \
+}
+
+VSSRLRN(vssrlrn_b_h, 16, B, H, UH)
+VSSRLRN(vssrlrn_h_w, 32, H, W, UW)
+VSSRLRN(vssrlrn_w_d, 64, W, D, UD)
+
+#define SSRARNS(E1, E2, T1, T2) \
+static T1 do_ssrarns_ ## E1(T1 e2, int sa, int sh) \
+{ \
+ T1 shft_res; \
+ \
+ shft_res = do_vsrar_ ## E2(e2, sa); \
+ T2 mask; \
+ mask = (1ll << sh) - 1; \
+ if (shft_res > mask) { \
+ return mask; \
+ } else if (shft_res < -(mask +1)) { \
+ return ~mask; \
+ } else { \
+ return shft_res; \
+ } \
+}
+
+SSRARNS(B, H, int16_t, int8_t)
+SSRARNS(H, W, int32_t, int16_t)
+SSRARNS(W, D, int64_t, int32_t)
+
+#define VSSRARN(NAME, BIT, E1, E2, E3) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i, j, ofs; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ ofs = LSX_LEN / BIT; \
+ for (i = 0; i < oprsz / 16; i++) { \
+ for (j = 0; j < ofs; j++) { \
+ Vd->E1(j + ofs * 2 * i) = do_ssrarns_ ## E1(Vj->E2(j + ofs * i), \
+ Vk->E3(j + ofs * i) % BIT, \
+ BIT/ 2 - 1); \
+ } \
+ Vd->D(2 * i + 1) = 0; \
+ } \
+}
+
+VSSRARN(vssrarn_b_h, 16, B, H, UH)
+VSSRARN(vssrarn_h_w, 32, H, W, UW)
+VSSRARN(vssrarn_w_d, 64, W, D, UD)
+
+#define SSRLRNU(E1, E2, T1, T2, T3) \
+static T1 do_ssrlrnu_ ## E1(T3 e2, int sa, int sh) \
+{ \
+ T1 shft_res; \
+ \
+ shft_res = do_vsrlr_ ## E2(e2, sa); \
+ \
+ T2 mask; \
+ mask = (1ull << sh) - 1; \
+ if (shft_res > mask) { \
+ return mask; \
+ } else { \
+ return shft_res; \
+ } \
+}
+
+SSRLRNU(B, H, uint16_t, uint8_t, int16_t)
+SSRLRNU(H, W, uint32_t, uint16_t, int32_t)
+SSRLRNU(W, D, uint64_t, uint32_t, int64_t)
+
+#define VSSRLRNU(NAME, BIT, E1, E2, E3) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i, j, ofs; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ ofs = LSX_LEN / BIT; \
+ for (i = 0; i < oprsz / 16; i++) { \
+ for (j = 0; j < ofs; j++) { \
+ Vd->E1(j + ofs * 2 * i) = do_ssrlrnu_ ## E1(Vj->E2(j + ofs * i), \
+ Vk->E3(j + ofs * i) % BIT, \
+ BIT / 2); \
+ } \
+ Vd->D(2 * i + 1) = 0; \
+ } \
+}
+
+VSSRLRNU(vssrlrn_bu_h, 16, B, H, UH)
+VSSRLRNU(vssrlrn_hu_w, 32, H, W, UW)
+VSSRLRNU(vssrlrn_wu_d, 64, W, D, UD)
+
+#define SSRARNU(E1, E2, T1, T2, T3) \
+static T1 do_ssrarnu_ ## E1(T3 e2, int sa, int sh) \
+{ \
+ T1 shft_res; \
+ \
+ if (e2 < 0) { \
+ shft_res = 0; \
+ } else { \
+ shft_res = do_vsrar_ ## E2(e2, sa); \
+ } \
+ T2 mask; \
+ mask = (1ull << sh) - 1; \
+ if (shft_res > mask) { \
+ return mask; \
+ } else { \
+ return shft_res; \
+ } \
+}
+
+SSRARNU(B, H, uint16_t, uint8_t, int16_t)
+SSRARNU(H, W, uint32_t, uint16_t, int32_t)
+SSRARNU(W, D, uint64_t, uint32_t, int64_t)
+
+#define VSSRARNU(NAME, BIT, E1, E2, E3) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i, j, ofs; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ ofs = LSX_LEN / BIT; \
+ for (i = 0; i < oprsz / 16; i++) { \
+ for (j = 0; j < ofs; j++) { \
+ Vd->E1(j + ofs * 2 * i) = do_ssrarnu_ ## E1(Vj->E2(j + ofs * i), \
+ Vk->E3(j + ofs * i) % BIT, \
+ BIT / 2); \
+ } \
+ Vd->D(2 * i + 1) = 0; \
+ } \
+}
+
+VSSRARNU(vssrarn_bu_h, 16, B, H, UH)
+VSSRARNU(vssrarn_hu_w, 32, H, W, UW)
+VSSRARNU(vssrarn_wu_d, 64, W, D, UD)
+
+#define VSSRLRNI(NAME, BIT, E1, E2) \
+void HELPER(NAME)(void *vd, void *vj, uint64_t imm, uint32_t desc) \
+{ \
+ int i, j, ofs; \
+ VReg temp = {}; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ ofs = LSX_LEN / BIT; \
+ for (i = 0; i < oprsz / 16; i++) { \
+ for (j = 0; j < ofs; j++) { \
+ temp.E1(j + ofs * 2 * i) = do_ssrlrns_ ## E1(Vj->E2(j + ofs * i), \
+ imm, BIT / 2 - 1); \
+ temp.E1(j + ofs * (2 * i + 1)) = do_ssrlrns_ ## E1(Vd->E2(j + ofs * i), \
+ imm, BIT / 2 - 1); \
+ } \
+ } \
+ *Vd = temp; \
+}
+
+static void do_vssrlrni_q(VReg *Vd, VReg * Vj,
+ uint64_t imm, int idx, Int128 mask)
+{
+ Int128 shft_res1, shft_res2, r1, r2;
+ if (imm == 0) {
+ shft_res1 = Vj->Q(idx);
+ shft_res2 = Vd->Q(idx);
+ } else {
+ r1 = int128_and(int128_urshift(Vj->Q(idx), (imm - 1)), int128_one());
+ r2 = int128_and(int128_urshift(Vd->Q(idx), (imm - 1)), int128_one());
+ shft_res1 = (int128_add(int128_urshift(Vj->Q(idx), imm), r1));
+ shft_res2 = (int128_add(int128_urshift(Vd->Q(idx), imm), r2));
+ }
+
+ if (int128_ult(mask, shft_res1)) {
+ Vd->D(idx * 2) = int128_getlo(mask);
+ }else {
+ Vd->D(idx * 2) = int128_getlo(shft_res1);
+ }
+
+ if (int128_ult(mask, shft_res2)) {
+ Vd->D(idx * 2 + 1) = int128_getlo(mask);
+ }else {
+ Vd->D(idx * 2 + 1) = int128_getlo(shft_res2);
+ }
+}
+
+void HELPER(vssrlrni_d_q)(void *vd, void *vj, uint64_t imm, uint32_t desc)
+{
+ int i;
+ Int128 mask;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ int oprsz = simd_oprsz(desc);
+
+ mask = int128_sub(int128_lshift(int128_one(), 63), int128_one());
+
+ for (i = 0; i < oprsz / 16; i++) {
+ do_vssrlrni_q(Vd, Vj, imm, i, mask);
+ }
+}
+
+VSSRLRNI(vssrlrni_b_h, 16, B, H)
+VSSRLRNI(vssrlrni_h_w, 32, H, W)
+VSSRLRNI(vssrlrni_w_d, 64, W, D)
+
+#define VSSRARNI(NAME, BIT, E1, E2) \
+void HELPER(NAME)(void *vd, void *vj, uint64_t imm, uint32_t desc) \
+{ \
+ int i, j, ofs; \
+ VReg temp = {}; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ ofs = LSX_LEN / BIT; \
+ for (i = 0; i < oprsz / 16; i++) { \
+ for (j = 0; j < ofs; j++) { \
+ temp.E1(j + ofs * 2 * i) = do_ssrarns_ ## E1(Vj->E2(j + ofs * i), \
+ imm, BIT / 2 - 1); \
+ temp.E1(j + ofs * (2 * i + 1)) = do_ssrarns_ ## E1(Vd->E2(j + ofs * i), \
+ imm, BIT / 2 - 1); \
+ } \
+ } \
+ *Vd = temp; \
+}
+
+static void do_vssrarni_d_q(VReg *Vd, VReg *Vj,
+ uint64_t imm, int idx, Int128 mask1, Int128 mask2)
+{
+ Int128 shft_res1, shft_res2, r1, r2;
+
+ if (imm == 0) {
+ shft_res1 = Vj->Q(idx);
+ shft_res2 = Vd->Q(idx);
+ } else {
+ r1 = int128_and(int128_rshift(Vj->Q(idx), (imm - 1)), int128_one());
+ r2 = int128_and(int128_rshift(Vd->Q(idx), (imm - 1)), int128_one());
+ shft_res1 = int128_add(int128_rshift(Vj->Q(idx), imm), r1);
+ shft_res2 = int128_add(int128_rshift(Vd->Q(idx), imm), r2);
+ }
+ if (int128_gt(shft_res1, mask1)) {
+ Vd->D(idx * 2) = int128_getlo(mask1);
+ } else if (int128_lt(shft_res1, int128_neg(mask2))) {
+ Vd->D(idx * 2) = int128_getlo(mask2);
+ } else {
+ Vd->D(idx * 2) = int128_getlo(shft_res1);
+ }
+
+ if (int128_gt(shft_res2, mask1)) {
+ Vd->D(idx * 2 + 1) = int128_getlo(mask1);
+ } else if (int128_lt(shft_res2, int128_neg(mask2))) {
+ Vd->D(idx * 2 + 1) = int128_getlo(mask2);
+ } else {
+ Vd->D(idx * 2 + 1) = int128_getlo(shft_res2);
+ }
+}
+
+void HELPER(vssrarni_d_q)(void *vd, void *vj, uint64_t imm, uint32_t desc)
+{
+ int i;
+ Int128 mask1, mask2;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ int oprsz = simd_oprsz(desc);
+
+ mask1 = int128_sub(int128_lshift(int128_one(), 63), int128_one());
+ mask2 = int128_lshift(int128_one(), 63);
+
+ for (i = 0; i < oprsz / 16; i++) {
+ do_vssrarni_d_q(Vd, Vj, imm, i, mask1, mask2);
+ }
+}
+
+VSSRARNI(vssrarni_b_h, 16, B, H)
+VSSRARNI(vssrarni_h_w, 32, H, W)
+VSSRARNI(vssrarni_w_d, 64, W, D)
+
+#define VSSRLRNUI(NAME, BIT, E1, E2) \
+void HELPER(NAME)(void *vd, void *vj, uint64_t imm, uint32_t desc) \
+{ \
+ int i, j, ofs; \
+ VReg temp = {}; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ ofs = LSX_LEN / BIT; \
+ for (i = 0; i < oprsz / 16; i++) { \
+ for (j = 0; j < ofs; j++) { \
+ temp.E1(j + ofs * 2 * i) = do_ssrlrnu_ ## E1(Vj->E2(j + ofs * i), \
+ imm, BIT / 2); \
+ temp.E1(j + ofs * (2 * i + 1)) = do_ssrlrnu_ ## E1(Vd->E2(j + ofs * i), \
+ imm, BIT / 2); \
+ } \
+ } \
+ *Vd = temp; \
+}
+
+void HELPER(vssrlrni_du_q)(void *vd, void *vj, uint64_t imm, uint32_t desc)
+{
+ int i;
+ Int128 mask;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ int oprsz = simd_oprsz(desc);
+
+ mask = int128_sub(int128_lshift(int128_one(), 64), int128_one());
+
+ for (i = 0; i < oprsz / 16; i++) {
+ do_vssrlrni_q(Vd, Vj, imm, i, mask);
+ }
+}
+
+VSSRLRNUI(vssrlrni_bu_h, 16, B, H)
+VSSRLRNUI(vssrlrni_hu_w, 32, H, W)
+VSSRLRNUI(vssrlrni_wu_d, 64, W, D)
+
+#define VSSRARNUI(NAME, BIT, E1, E2) \
+void HELPER(NAME)(void *vd, void *vj, uint64_t imm, uint32_t desc) \
+{ \
+ int i, j, ofs; \
+ VReg temp = {}; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ ofs = LSX_LEN / BIT; \
+ for (i = 0; i < oprsz / 16; i++) { \
+ for (j = 0; j < ofs; j++) { \
+ temp.E1(j + ofs * 2 * i) = do_ssrarnu_ ## E1(Vj->E2(j + ofs * i), \
+ imm, BIT / 2); \
+ temp.E1(j + ofs * (2 * i + 1)) = do_ssrarnu_ ## E1(Vd->E2(j + ofs * i), \
+ imm, BIT / 2); \
+ } \
+ } \
+ *Vd = temp; \
+}
+
+static void do_vssrarni_du_q(VReg *Vd, VReg *Vj,
+ uint64_t imm, int idx, Int128 mask1, Int128 mask2)
+{
+ Int128 shft_res1, shft_res2, r1, r2;
+
+ if (imm == 0) {
+ shft_res1 = Vj->Q(idx);
+ shft_res2 = Vd->Q(idx);
+ } else {
+ r1 = int128_and(int128_rshift(Vj->Q(idx), (imm - 1)), int128_one());
+ r2 = int128_and(int128_rshift(Vd->Q(idx), (imm - 1)), int128_one());
+ shft_res1 = int128_add(int128_rshift(Vj->Q(idx), imm), r1);
+ shft_res2 = int128_add(int128_rshift(Vd->Q(idx), imm), r2);
+ }
+
+ if (int128_lt(Vj->Q(idx), int128_zero())) {
+ shft_res1 = int128_zero();
+ }
+ if (int128_lt(Vd->Q(idx), int128_zero())) {
+ shft_res2 = int128_zero();
+ }
+
+ if (int128_gt(shft_res1, mask1)) {
+ Vd->D(idx * 2) = int128_getlo(mask1);
+ } else if (int128_lt(shft_res1, int128_neg(mask2))) {
+ Vd->D(idx * 2) = int128_getlo(mask2);
+ } else {
+ Vd->D(idx * 2) = int128_getlo(shft_res1);
+ }
+
+ if (int128_gt(shft_res2, mask1)) {
+ Vd->D(idx * 2 + 1) = int128_getlo(mask1);
+ } else if (int128_lt(shft_res2, int128_neg(mask2))) {
+ Vd->D(idx * 2 + 1) = int128_getlo(mask2);
+ } else {
+ Vd->D(idx * 2 + 1) = int128_getlo(shft_res2);
+ }
+}
+
+void HELPER(vssrarni_du_q)(void *vd, void *vj, uint64_t imm, uint32_t desc)
+{
+ int i;
+ Int128 mask1, mask2;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ int oprsz = simd_oprsz(desc);
+
+ mask1 = int128_sub(int128_lshift(int128_one(), 64), int128_one());
+ mask2 = int128_lshift(int128_one(), 64);
+
+ for (i = 0; i < oprsz / 16; i++) {
+ do_vssrarni_du_q(Vd, Vj, imm, i, mask1, mask2);
+ }
+}
+
+VSSRARNUI(vssrarni_bu_h, 16, B, H)
+VSSRARNUI(vssrarni_hu_w, 32, H, W)
+VSSRARNUI(vssrarni_wu_d, 64, W, D)
+
+#define DO_2OP(NAME, BIT, E, DO_OP) \
+void HELPER(NAME)(void *vd, void *vj, uint32_t desc) \
+{ \
+ int i; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ for (i = 0; i < oprsz / (BIT / 8); i++) \
+ { \
+ Vd->E(i) = DO_OP(Vj->E(i)); \
+ } \
+}
+
+DO_2OP(vclo_b, 8, UB, DO_CLO_B)
+DO_2OP(vclo_h, 16, UH, DO_CLO_H)
+DO_2OP(vclo_w, 32, UW, DO_CLO_W)
+DO_2OP(vclo_d, 64, UD, DO_CLO_D)
+DO_2OP(vclz_b, 8, UB, DO_CLZ_B)
+DO_2OP(vclz_h, 16, UH, DO_CLZ_H)
+DO_2OP(vclz_w, 32, UW, DO_CLZ_W)
+DO_2OP(vclz_d, 64, UD, DO_CLZ_D)
+
+#define VPCNT(NAME, BIT, E, FN) \
+void HELPER(NAME)(void *vd, void *vj, uint32_t desc) \
+{ \
+ int i; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ for (i = 0; i < oprsz / (BIT / 8); i++) \
+ { \
+ Vd->E(i) = FN(Vj->E(i)); \
+ } \
+}
+
+VPCNT(vpcnt_b, 8, UB, ctpop8)
+VPCNT(vpcnt_h, 16, UH, ctpop16)
+VPCNT(vpcnt_w, 32, UW, ctpop32)
+VPCNT(vpcnt_d, 64, UD, ctpop64)
+
+#define DO_BIT(NAME, BIT, E, DO_OP) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ for (i = 0; i < oprsz / (BIT / 8); i++) { \
+ Vd->E(i) = DO_OP(Vj->E(i), Vk->E(i)%BIT); \
+ } \
+}
+
+DO_BIT(vbitclr_b, 8, UB, DO_BITCLR)
+DO_BIT(vbitclr_h, 16, UH, DO_BITCLR)
+DO_BIT(vbitclr_w, 32, UW, DO_BITCLR)
+DO_BIT(vbitclr_d, 64, UD, DO_BITCLR)
+DO_BIT(vbitset_b, 8, UB, DO_BITSET)
+DO_BIT(vbitset_h, 16, UH, DO_BITSET)
+DO_BIT(vbitset_w, 32, UW, DO_BITSET)
+DO_BIT(vbitset_d, 64, UD, DO_BITSET)
+DO_BIT(vbitrev_b, 8, UB, DO_BITREV)
+DO_BIT(vbitrev_h, 16, UH, DO_BITREV)
+DO_BIT(vbitrev_w, 32, UW, DO_BITREV)
+DO_BIT(vbitrev_d, 64, UD, DO_BITREV)
+
+#define DO_BITI(NAME, BIT, E, DO_OP) \
+void HELPER(NAME)(void *vd, void *vj, uint64_t imm, uint32_t desc) \
+{ \
+ int i; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ for (i = 0; i < oprsz / (BIT / 8); i++) { \
+ Vd->E(i) = DO_OP(Vj->E(i), imm); \
+ } \
+}
+
+DO_BITI(vbitclri_b, 8, UB, DO_BITCLR)
+DO_BITI(vbitclri_h, 16, UH, DO_BITCLR)
+DO_BITI(vbitclri_w, 32, UW, DO_BITCLR)
+DO_BITI(vbitclri_d, 64, UD, DO_BITCLR)
+DO_BITI(vbitseti_b, 8, UB, DO_BITSET)
+DO_BITI(vbitseti_h, 16, UH, DO_BITSET)
+DO_BITI(vbitseti_w, 32, UW, DO_BITSET)
+DO_BITI(vbitseti_d, 64, UD, DO_BITSET)
+DO_BITI(vbitrevi_b, 8, UB, DO_BITREV)
+DO_BITI(vbitrevi_h, 16, UH, DO_BITREV)
+DO_BITI(vbitrevi_w, 32, UW, DO_BITREV)
+DO_BITI(vbitrevi_d, 64, UD, DO_BITREV)
+
+#define VFRSTP(NAME, BIT, MASK, E) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i, j, m, ofs; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ ofs = LSX_LEN / BIT; \
+ for (i = 0; i < oprsz / 16; i++) { \
+ m = Vk->E(i * ofs) & MASK; \
+ for (j = 0; j < ofs; j++) { \
+ if (Vj->E(j + ofs * i) < 0) { \
+ break; \
+ } \
+ } \
+ Vd->E(m + i * ofs) = j; \
+ } \
+}
+
+VFRSTP(vfrstp_b, 8, 0xf, B)
+VFRSTP(vfrstp_h, 16, 0x7, H)
+
+#define VFRSTPI(NAME, BIT, E) \
+void HELPER(NAME)(void *vd, void *vj, uint64_t imm, uint32_t desc) \
+{ \
+ int i, j, m, ofs; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ ofs = LSX_LEN / BIT; \
+ m = imm % ofs; \
+ for (i = 0; i < oprsz / 16; i++) { \
+ for (j = 0; j < ofs; j++) { \
+ if (Vj->E(j + ofs * i) < 0) { \
+ break; \
+ } \
+ } \
+ Vd->E(m + i * ofs) = j; \
+ } \
+}
+
+VFRSTPI(vfrstpi_b, 8, B)
+VFRSTPI(vfrstpi_h, 16, H)
+
+static void vec_update_fcsr0_mask(CPULoongArchState *env,
+ uintptr_t pc, int mask)
+{
+ int flags = get_float_exception_flags(&env->fp_status);
+
+ set_float_exception_flags(0, &env->fp_status);
+
+ flags &= ~mask;
+
+ if (flags) {
+ flags = ieee_ex_to_loongarch(flags);
+ UPDATE_FP_CAUSE(env->fcsr0, flags);
+ }
+
+ if (GET_FP_ENABLES(env->fcsr0) & flags) {
+ do_raise_exception(env, EXCCODE_FPE, pc);
+ } else {
+ UPDATE_FP_FLAGS(env->fcsr0, flags);
+ }
+}
+
+static void vec_update_fcsr0(CPULoongArchState *env, uintptr_t pc)
+{
+ vec_update_fcsr0_mask(env, pc, 0);
+}
+
+static inline void vec_clear_cause(CPULoongArchState *env)
+{
+ SET_FP_CAUSE(env->fcsr0, 0);
+}
+
+#define DO_3OP_F(NAME, BIT, E, FN) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, \
+ CPULoongArchState *env, uint32_t desc) \
+{ \
+ int i; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ vec_clear_cause(env); \
+ for (i = 0; i < oprsz / (BIT / 8); i++) { \
+ Vd->E(i) = FN(Vj->E(i), Vk->E(i), &env->fp_status); \
+ vec_update_fcsr0(env, GETPC()); \
+ } \
+}
+
+DO_3OP_F(vfadd_s, 32, UW, float32_add)
+DO_3OP_F(vfadd_d, 64, UD, float64_add)
+DO_3OP_F(vfsub_s, 32, UW, float32_sub)
+DO_3OP_F(vfsub_d, 64, UD, float64_sub)
+DO_3OP_F(vfmul_s, 32, UW, float32_mul)
+DO_3OP_F(vfmul_d, 64, UD, float64_mul)
+DO_3OP_F(vfdiv_s, 32, UW, float32_div)
+DO_3OP_F(vfdiv_d, 64, UD, float64_div)
+DO_3OP_F(vfmax_s, 32, UW, float32_maxnum)
+DO_3OP_F(vfmax_d, 64, UD, float64_maxnum)
+DO_3OP_F(vfmin_s, 32, UW, float32_minnum)
+DO_3OP_F(vfmin_d, 64, UD, float64_minnum)
+DO_3OP_F(vfmaxa_s, 32, UW, float32_maxnummag)
+DO_3OP_F(vfmaxa_d, 64, UD, float64_maxnummag)
+DO_3OP_F(vfmina_s, 32, UW, float32_minnummag)
+DO_3OP_F(vfmina_d, 64, UD, float64_minnummag)
+
+#define DO_4OP_F(NAME, BIT, E, FN, flags) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, void *va, \
+ CPULoongArchState *env, uint32_t desc) \
+{ \
+ int i; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ VReg *Va = (VReg *)va; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ vec_clear_cause(env); \
+ for (i = 0; i < oprsz / (BIT / 8); i++) { \
+ Vd->E(i) = FN(Vj->E(i), Vk->E(i), Va->E(i), flags, &env->fp_status); \
+ vec_update_fcsr0(env, GETPC()); \
+ } \
+}
+
+DO_4OP_F(vfmadd_s, 32, UW, float32_muladd, 0)
+DO_4OP_F(vfmadd_d, 64, UD, float64_muladd, 0)
+DO_4OP_F(vfmsub_s, 32, UW, float32_muladd, float_muladd_negate_c)
+DO_4OP_F(vfmsub_d, 64, UD, float64_muladd, float_muladd_negate_c)
+DO_4OP_F(vfnmadd_s, 32, UW, float32_muladd, float_muladd_negate_result)
+DO_4OP_F(vfnmadd_d, 64, UD, float64_muladd, float_muladd_negate_result)
+DO_4OP_F(vfnmsub_s, 32, UW, float32_muladd,
+ float_muladd_negate_c | float_muladd_negate_result)
+DO_4OP_F(vfnmsub_d, 64, UD, float64_muladd,
+ float_muladd_negate_c | float_muladd_negate_result)
+
+#define DO_2OP_F(NAME, BIT, E, FN) \
+void HELPER(NAME)(void *vd, void *vj, \
+ CPULoongArchState *env, uint32_t desc) \
+{ \
+ int i; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ vec_clear_cause(env); \
+ for (i = 0; i < oprsz / (BIT / 8); i++) { \
+ Vd->E(i) = FN(env, Vj->E(i)); \
+ } \
+}
+
+#define FLOGB(BIT, T) \
+static T do_flogb_## BIT(CPULoongArchState *env, T fj) \
+{ \
+ T fp, fd; \
+ float_status *status = &env->fp_status; \
+ FloatRoundMode old_mode = get_float_rounding_mode(status); \
+ \
+ set_float_rounding_mode(float_round_down, status); \
+ fp = float ## BIT ##_log2(fj, status); \
+ fd = float ## BIT ##_round_to_int(fp, status); \
+ set_float_rounding_mode(old_mode, status); \
+ vec_update_fcsr0_mask(env, GETPC(), float_flag_inexact); \
+ return fd; \
+}
+
+FLOGB(32, uint32_t)
+FLOGB(64, uint64_t)
+
+#define FCLASS(NAME, BIT, E, FN) \
+void HELPER(NAME)(void *vd, void *vj, \
+ CPULoongArchState *env, uint32_t desc) \
+{ \
+ int i; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ for (i = 0; i < oprsz / (BIT / 8); i++) { \
+ Vd->E(i) = FN(env, Vj->E(i)); \
+ } \
+}
+
+FCLASS(vfclass_s, 32, UW, helper_fclass_s)
+FCLASS(vfclass_d, 64, UD, helper_fclass_d)
+
+#define FSQRT(BIT, T) \
+static T do_fsqrt_## BIT(CPULoongArchState *env, T fj) \
+{ \
+ T fd; \
+ fd = float ## BIT ##_sqrt(fj, &env->fp_status); \
+ vec_update_fcsr0(env, GETPC()); \
+ return fd; \
+}
+
+FSQRT(32, uint32_t)
+FSQRT(64, uint64_t)
+
+#define FRECIP(BIT, T) \
+static T do_frecip_## BIT(CPULoongArchState *env, T fj) \
+{ \
+ T fd; \
+ fd = float ## BIT ##_div(float ## BIT ##_one, fj, &env->fp_status); \
+ vec_update_fcsr0(env, GETPC()); \
+ return fd; \
+}
+
+FRECIP(32, uint32_t)
+FRECIP(64, uint64_t)
+
+#define FRSQRT(BIT, T) \
+static T do_frsqrt_## BIT(CPULoongArchState *env, T fj) \
+{ \
+ T fd, fp; \
+ fp = float ## BIT ##_sqrt(fj, &env->fp_status); \
+ fd = float ## BIT ##_div(float ## BIT ##_one, fp, &env->fp_status); \
+ vec_update_fcsr0(env, GETPC()); \
+ return fd; \
+}
+
+FRSQRT(32, uint32_t)
+FRSQRT(64, uint64_t)
+
+DO_2OP_F(vflogb_s, 32, UW, do_flogb_32)
+DO_2OP_F(vflogb_d, 64, UD, do_flogb_64)
+DO_2OP_F(vfsqrt_s, 32, UW, do_fsqrt_32)
+DO_2OP_F(vfsqrt_d, 64, UD, do_fsqrt_64)
+DO_2OP_F(vfrecip_s, 32, UW, do_frecip_32)
+DO_2OP_F(vfrecip_d, 64, UD, do_frecip_64)
+DO_2OP_F(vfrsqrt_s, 32, UW, do_frsqrt_32)
+DO_2OP_F(vfrsqrt_d, 64, UD, do_frsqrt_64)
+
+static uint32_t float16_cvt_float32(uint16_t h, float_status *status)
+{
+ return float16_to_float32(h, true, status);
+}
+static uint64_t float32_cvt_float64(uint32_t s, float_status *status)
+{
+ return float32_to_float64(s, status);
+}
+
+static uint16_t float32_cvt_float16(uint32_t s, float_status *status)
+{
+ return float32_to_float16(s, true, status);
+}
+static uint32_t float64_cvt_float32(uint64_t d, float_status *status)
+{
+ return float64_to_float32(d, status);
+}
+
+void HELPER(vfcvtl_s_h)(void *vd, void *vj,
+ CPULoongArchState *env, uint32_t desc)
+{
+ int i, j, ofs;
+ VReg temp = {};
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ int oprsz = simd_oprsz(desc);
+
+ ofs = LSX_LEN / 32;
+ vec_clear_cause(env);
+ for (i = 0; i < oprsz / 16; i++) {
+ for (j = 0; j < ofs; j++) {
+ temp.UW(j + ofs * i) =float16_cvt_float32(Vj->UH(j + ofs * 2 * i),
+ &env->fp_status);
+ }
+ vec_update_fcsr0(env, GETPC());
+ }
+ *Vd = temp;
+}
+
+void HELPER(vfcvtl_d_s)(void *vd, void *vj,
+ CPULoongArchState *env, uint32_t desc)
+{
+ int i, j, ofs;
+ VReg temp = {};
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ int oprsz = simd_oprsz(desc);
+
+ ofs = LSX_LEN / 64;
+ vec_clear_cause(env);
+ for (i = 0; i < oprsz / 16; i++) {
+ for (j = 0; j < ofs; j++) {
+ temp.UD(j + ofs * i) = float32_cvt_float64(Vj->UW(j + ofs * 2 * i),
+ &env->fp_status);
+ }
+ vec_update_fcsr0(env, GETPC());
+ }
+ *Vd = temp;
+}
+
+void HELPER(vfcvth_s_h)(void *vd, void *vj,
+ CPULoongArchState *env, uint32_t desc)
+{
+ int i, j, ofs;
+ VReg temp = {};
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ int oprsz = simd_oprsz(desc);
+
+ ofs = LSX_LEN / 32;
+ vec_clear_cause(env);
+ for (i = 0; i < oprsz / 16; i++) {
+ for (j = 0; j < ofs; j++) {
+ temp.UW(j + ofs * i) = float16_cvt_float32(Vj->UH(j + ofs * (2 * i + 1)),
+ &env->fp_status);
+ }
+ vec_update_fcsr0(env, GETPC());
+ }
+ *Vd = temp;
+}
+
+void HELPER(vfcvth_d_s)(void *vd, void *vj,
+ CPULoongArchState *env, uint32_t desc)
+{
+ int i, j, ofs;
+ VReg temp = {};
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ int oprsz = simd_oprsz(desc);
+
+ ofs = LSX_LEN / 64;
+ vec_clear_cause(env);
+ for (i = 0; i < oprsz / 16; i++) {
+ for (j = 0; j < ofs; j++) {
+ temp.UD(j + ofs * i) = float32_cvt_float64(Vj->UW(j + ofs * (2 * i + 1)),
+ &env->fp_status);
+ }
+ vec_update_fcsr0(env, GETPC());
+ }
+ *Vd = temp;
+}
+
+void HELPER(vfcvt_h_s)(void *vd, void *vj, void *vk,
+ CPULoongArchState *env, uint32_t desc)
+{
+ int i, j, ofs;
+ VReg temp = {};
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ VReg *Vk = (VReg *)vk;
+ int oprsz = simd_oprsz(desc);
+
+ ofs = LSX_LEN / 32;
+ vec_clear_cause(env);
+ for(i = 0; i < oprsz / 16; i++) {
+ for (j = 0; j < ofs; j++) {
+ temp.UH(j + ofs * (2 * i + 1)) = float32_cvt_float16(Vj->UW(j + ofs * i),
+ &env->fp_status);
+ temp.UH(j + ofs * 2 * i) = float32_cvt_float16(Vk->UW(j + ofs * i),
+ &env->fp_status);
+ }
+ vec_update_fcsr0(env, GETPC());
+ }
+ *Vd = temp;
+}
+
+void HELPER(vfcvt_s_d)(void *vd, void *vj, void *vk,
+ CPULoongArchState *env, uint32_t desc)
+{
+ int i, j, ofs;
+ VReg temp = {};
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ VReg *Vk = (VReg *)vk;
+ int oprsz = simd_oprsz(desc);
+
+ ofs = LSX_LEN / 64;
+ vec_clear_cause(env);
+ for(i = 0; i < oprsz / 16; i++) {
+ for (j = 0; j < ofs; j++) {
+ temp.UW(j + ofs * (2 * i + 1)) = float64_cvt_float32(Vj->UD(j + ofs * i),
+ &env->fp_status);
+ temp.UW(j + ofs * 2 * i) = float64_cvt_float32(Vk->UD(j + ofs * i),
+ &env->fp_status);
+ }
+ vec_update_fcsr0(env, GETPC());
+ }
+ *Vd = temp;
+}
+
+void HELPER(vfrint_s)(void *vd, void *vj,
+ CPULoongArchState *env, uint32_t desc)
+{
+ int i;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ int oprsz = simd_oprsz(desc);
+
+ vec_clear_cause(env);
+ for (i = 0; i < oprsz / 4; i++) {
+ Vd->W(i) = float32_round_to_int(Vj->UW(i), &env->fp_status);
+ vec_update_fcsr0(env, GETPC());
+ }
+}
+
+void HELPER(vfrint_d)(void *vd, void *vj,
+ CPULoongArchState *env, uint32_t desc)
+{
+ int i;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ int oprsz = simd_oprsz(desc);
+
+ vec_clear_cause(env);
+ for (i = 0; i < oprsz / 8; i++) {
+ Vd->D(i) = float64_round_to_int(Vj->UD(i), &env->fp_status);
+ vec_update_fcsr0(env, GETPC());
+ }
+}
+
+#define FCVT_2OP(NAME, BIT, E, MODE) \
+void HELPER(NAME)(void *vd, void *vj, \
+ CPULoongArchState *env, uint32_t desc) \
+{ \
+ int i; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ vec_clear_cause(env); \
+ for (i = 0; i < oprsz / (BIT / 8); i++) { \
+ FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); \
+ set_float_rounding_mode(MODE, &env->fp_status); \
+ Vd->E(i) = float## BIT ## _round_to_int(Vj->E(i), &env->fp_status); \
+ set_float_rounding_mode(old_mode, &env->fp_status); \
+ vec_update_fcsr0(env, GETPC()); \
+ } \
+}
+
+FCVT_2OP(vfrintrne_s, 32, UW, float_round_nearest_even)
+FCVT_2OP(vfrintrne_d, 64, UD, float_round_nearest_even)
+FCVT_2OP(vfrintrz_s, 32, UW, float_round_to_zero)
+FCVT_2OP(vfrintrz_d, 64, UD, float_round_to_zero)
+FCVT_2OP(vfrintrp_s, 32, UW, float_round_up)
+FCVT_2OP(vfrintrp_d, 64, UD, float_round_up)
+FCVT_2OP(vfrintrm_s, 32, UW, float_round_down)
+FCVT_2OP(vfrintrm_d, 64, UD, float_round_down)
+
+#define FTINT(NAME, FMT1, FMT2, T1, T2, MODE) \
+static T2 do_ftint ## NAME(CPULoongArchState *env, T1 fj) \
+{ \
+ T2 fd; \
+ FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); \
+ \
+ set_float_rounding_mode(MODE, &env->fp_status); \
+ fd = do_## FMT1 ##_to_## FMT2(env, fj); \
+ set_float_rounding_mode(old_mode, &env->fp_status); \
+ return fd; \
+}
+
+#define DO_FTINT(FMT1, FMT2, T1, T2) \
+static T2 do_## FMT1 ##_to_## FMT2(CPULoongArchState *env, T1 fj) \
+{ \
+ T2 fd; \
+ \
+ fd = FMT1 ##_to_## FMT2(fj, &env->fp_status); \
+ if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { \
+ if (FMT1 ##_is_any_nan(fj)) { \
+ fd = 0; \
+ } \
+ } \
+ vec_update_fcsr0(env, GETPC()); \
+ return fd; \
+}
+
+DO_FTINT(float32, int32, uint32_t, uint32_t)
+DO_FTINT(float64, int64, uint64_t, uint64_t)
+DO_FTINT(float32, uint32, uint32_t, uint32_t)
+DO_FTINT(float64, uint64, uint64_t, uint64_t)
+DO_FTINT(float64, int32, uint64_t, uint32_t)
+DO_FTINT(float32, int64, uint32_t, uint64_t)
+
+FTINT(rne_w_s, float32, int32, uint32_t, uint32_t, float_round_nearest_even)
+FTINT(rne_l_d, float64, int64, uint64_t, uint64_t, float_round_nearest_even)
+FTINT(rp_w_s, float32, int32, uint32_t, uint32_t, float_round_up)
+FTINT(rp_l_d, float64, int64, uint64_t, uint64_t, float_round_up)
+FTINT(rz_w_s, float32, int32, uint32_t, uint32_t, float_round_to_zero)
+FTINT(rz_l_d, float64, int64, uint64_t, uint64_t, float_round_to_zero)
+FTINT(rm_w_s, float32, int32, uint32_t, uint32_t, float_round_down)
+FTINT(rm_l_d, float64, int64, uint64_t, uint64_t, float_round_down)
+
+DO_2OP_F(vftintrne_w_s, 32, UW, do_ftintrne_w_s)
+DO_2OP_F(vftintrne_l_d, 64, UD, do_ftintrne_l_d)
+DO_2OP_F(vftintrp_w_s, 32, UW, do_ftintrp_w_s)
+DO_2OP_F(vftintrp_l_d, 64, UD, do_ftintrp_l_d)
+DO_2OP_F(vftintrz_w_s, 32, UW, do_ftintrz_w_s)
+DO_2OP_F(vftintrz_l_d, 64, UD, do_ftintrz_l_d)
+DO_2OP_F(vftintrm_w_s, 32, UW, do_ftintrm_w_s)
+DO_2OP_F(vftintrm_l_d, 64, UD, do_ftintrm_l_d)
+DO_2OP_F(vftint_w_s, 32, UW, do_float32_to_int32)
+DO_2OP_F(vftint_l_d, 64, UD, do_float64_to_int64)
+
+FTINT(rz_wu_s, float32, uint32, uint32_t, uint32_t, float_round_to_zero)
+FTINT(rz_lu_d, float64, uint64, uint64_t, uint64_t, float_round_to_zero)
+
+DO_2OP_F(vftintrz_wu_s, 32, UW, do_ftintrz_wu_s)
+DO_2OP_F(vftintrz_lu_d, 64, UD, do_ftintrz_lu_d)
+DO_2OP_F(vftint_wu_s, 32, UW, do_float32_to_uint32)
+DO_2OP_F(vftint_lu_d, 64, UD, do_float64_to_uint64)
+
+FTINT(rm_w_d, float64, int32, uint64_t, uint32_t, float_round_down)
+FTINT(rp_w_d, float64, int32, uint64_t, uint32_t, float_round_up)
+FTINT(rz_w_d, float64, int32, uint64_t, uint32_t, float_round_to_zero)
+FTINT(rne_w_d, float64, int32, uint64_t, uint32_t, float_round_nearest_even)
+
+#define FTINT_W_D(NAME, FN) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, \
+ CPULoongArchState *env, uint32_t desc) \
+{ \
+ int i, j, ofs; \
+ VReg temp = {}; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ ofs = LSX_LEN / 64; \
+ vec_clear_cause(env); \
+ for (i = 0; i < oprsz / 16; i++) { \
+ for (j = 0; j < ofs; j++) { \
+ temp.W(j + ofs * (2 * i + 1)) = FN(env, Vj->UD(j + ofs * i)); \
+ temp.W(j + ofs * 2 * i) = FN(env, Vk->UD(j + ofs * i)); \
+ } \
+ } \
+ *Vd = temp; \
+}
+
+FTINT_W_D(vftint_w_d, do_float64_to_int32)
+FTINT_W_D(vftintrm_w_d, do_ftintrm_w_d)
+FTINT_W_D(vftintrp_w_d, do_ftintrp_w_d)
+FTINT_W_D(vftintrz_w_d, do_ftintrz_w_d)
+FTINT_W_D(vftintrne_w_d, do_ftintrne_w_d)
+
+FTINT(rml_l_s, float32, int64, uint32_t, uint64_t, float_round_down)
+FTINT(rpl_l_s, float32, int64, uint32_t, uint64_t, float_round_up)
+FTINT(rzl_l_s, float32, int64, uint32_t, uint64_t, float_round_to_zero)
+FTINT(rnel_l_s, float32, int64, uint32_t, uint64_t, float_round_nearest_even)
+FTINT(rmh_l_s, float32, int64, uint32_t, uint64_t, float_round_down)
+FTINT(rph_l_s, float32, int64, uint32_t, uint64_t, float_round_up)
+FTINT(rzh_l_s, float32, int64, uint32_t, uint64_t, float_round_to_zero)
+FTINT(rneh_l_s, float32, int64, uint32_t, uint64_t, float_round_nearest_even)
+
+#define FTINTL_L_S(NAME, FN) \
+void HELPER(NAME)(void *vd, void *vj, \
+ CPULoongArchState *env, uint32_t desc) \
+{ \
+ int i, j, ofs; \
+ VReg temp; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ ofs = LSX_LEN / 64; \
+ vec_clear_cause(env); \
+ for (i = 0; i < oprsz / 16; i++) { \
+ for (j = 0; j < ofs; j++) { \
+ temp.D(j + ofs * i) = FN(env, Vj->UW(j + ofs * 2 * i)); \
+ } \
+ } \
+ *Vd = temp; \
+}
+
+FTINTL_L_S(vftintl_l_s, do_float32_to_int64)
+FTINTL_L_S(vftintrml_l_s, do_ftintrml_l_s)
+FTINTL_L_S(vftintrpl_l_s, do_ftintrpl_l_s)
+FTINTL_L_S(vftintrzl_l_s, do_ftintrzl_l_s)
+FTINTL_L_S(vftintrnel_l_s, do_ftintrnel_l_s)
+
+#define FTINTH_L_S(NAME, FN) \
+void HELPER(NAME)(void *vd, void *vj, \
+ CPULoongArchState *env, uint32_t desc) \
+{ \
+ int i, j, ofs; \
+ VReg temp = {}; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ ofs = LSX_LEN / 64; \
+ vec_clear_cause(env); \
+ for (i = 0; i < oprsz / 16; i++) { \
+ for (j = 0; j < ofs; j++) { \
+ temp.D(j + ofs * i) = FN(env, Vj->UW(j + ofs * (2 * i + 1))); \
+ } \
+ } \
+ *Vd = temp; \
+}
+
+FTINTH_L_S(vftinth_l_s, do_float32_to_int64)
+FTINTH_L_S(vftintrmh_l_s, do_ftintrmh_l_s)
+FTINTH_L_S(vftintrph_l_s, do_ftintrph_l_s)
+FTINTH_L_S(vftintrzh_l_s, do_ftintrzh_l_s)
+FTINTH_L_S(vftintrneh_l_s, do_ftintrneh_l_s)
+
+#define FFINT(NAME, FMT1, FMT2, T1, T2) \
+static T2 do_ffint_ ## NAME(CPULoongArchState *env, T1 fj) \
+{ \
+ T2 fd; \
+ \
+ fd = FMT1 ##_to_## FMT2(fj, &env->fp_status); \
+ vec_update_fcsr0(env, GETPC()); \
+ return fd; \
+}
+
+FFINT(s_w, int32, float32, int32_t, uint32_t)
+FFINT(d_l, int64, float64, int64_t, uint64_t)
+FFINT(s_wu, uint32, float32, uint32_t, uint32_t)
+FFINT(d_lu, uint64, float64, uint64_t, uint64_t)
+
+DO_2OP_F(vffint_s_w, 32, W, do_ffint_s_w)
+DO_2OP_F(vffint_d_l, 64, D, do_ffint_d_l)
+DO_2OP_F(vffint_s_wu, 32, UW, do_ffint_s_wu)
+DO_2OP_F(vffint_d_lu, 64, UD, do_ffint_d_lu)
+
+void HELPER(vffintl_d_w)(void *vd, void *vj,
+ CPULoongArchState *env, uint32_t desc)
+{
+ int i, j, ofs;
+ VReg temp = {};
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ int oprsz = simd_oprsz(desc);
+
+ ofs = LSX_LEN / 64;
+ vec_clear_cause(env);
+ for (i = 0; i < oprsz / 16; i++) {
+ for (j = 0; j < ofs; j++) {
+ temp.D(j + ofs * i) = int32_to_float64(Vj->W(j + ofs * 2 * i),
+ &env->fp_status);
+ }
+ vec_update_fcsr0(env, GETPC());
+ }
+ *Vd = temp;
+}
+
+void HELPER(vffinth_d_w)(void *vd, void *vj,
+ CPULoongArchState *env, uint32_t desc)
+{
+ int i, j, ofs;
+ VReg temp = {};
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ int oprsz = simd_oprsz(desc);
+
+ ofs = LSX_LEN / 64;
+ vec_clear_cause(env);
+ for (i = 0; i < oprsz /16; i++) {
+ for (j = 0; j < ofs; j++) {
+ temp.D(j + ofs * i) = int32_to_float64(Vj->W(j + ofs * (2 * i + 1)),
+ &env->fp_status);
+ }
+ vec_update_fcsr0(env, GETPC());
+ }
+ *Vd = temp;
+}
+
+void HELPER(vffint_s_l)(void *vd, void *vj, void *vk,
+ CPULoongArchState *env, uint32_t desc)
+{
+ int i, j, ofs;
+ VReg temp = {};
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ VReg *Vk = (VReg *)vk;
+ int oprsz = simd_oprsz(desc);
+
+ ofs = LSX_LEN / 64;
+ vec_clear_cause(env);
+ for (i = 0; i < oprsz / 16; i++) {
+ for (j = 0; j < ofs; j++) {
+ temp.W(j + ofs * (2 * i + 1)) = int64_to_float32(Vj->D(j + ofs * i),
+ &env->fp_status);
+ temp.W(j + ofs * 2 * i) = int64_to_float32(Vk->D(j + ofs * i),
+ &env->fp_status);
+ }
+ vec_update_fcsr0(env, GETPC());
+ }
+ *Vd = temp;
+}
+
+#define VCMPI(NAME, BIT, E, DO_OP) \
+void HELPER(NAME)(void *vd, void *vj, uint64_t imm, uint32_t desc) \
+{ \
+ int i; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ typedef __typeof(Vd->E(0)) TD; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ for (i = 0; i < oprsz / (BIT / 8); i++) { \
+ Vd->E(i) = DO_OP(Vj->E(i), (TD)imm); \
+ } \
+}
+
+VCMPI(vseqi_b, 8, B, VSEQ)
+VCMPI(vseqi_h, 16, H, VSEQ)
+VCMPI(vseqi_w, 32, W, VSEQ)
+VCMPI(vseqi_d, 64, D, VSEQ)
+VCMPI(vslei_b, 8, B, VSLE)
+VCMPI(vslei_h, 16, H, VSLE)
+VCMPI(vslei_w, 32, W, VSLE)
+VCMPI(vslei_d, 64, D, VSLE)
+VCMPI(vslei_bu, 8, UB, VSLE)
+VCMPI(vslei_hu, 16, UH, VSLE)
+VCMPI(vslei_wu, 32, UW, VSLE)
+VCMPI(vslei_du, 64, UD, VSLE)
+VCMPI(vslti_b, 8, B, VSLT)
+VCMPI(vslti_h, 16, H, VSLT)
+VCMPI(vslti_w, 32, W, VSLT)
+VCMPI(vslti_d, 64, D, VSLT)
+VCMPI(vslti_bu, 8, UB, VSLT)
+VCMPI(vslti_hu, 16, UH, VSLT)
+VCMPI(vslti_wu, 32, UW, VSLT)
+VCMPI(vslti_du, 64, UD, VSLT)
+
+static uint64_t vfcmp_common(CPULoongArchState *env,
+ FloatRelation cmp, uint32_t flags)
+{
+ uint64_t ret = 0;
+
+ switch (cmp) {
+ case float_relation_less:
+ ret = (flags & FCMP_LT);
+ break;
+ case float_relation_equal:
+ ret = (flags & FCMP_EQ);
+ break;
+ case float_relation_greater:
+ ret = (flags & FCMP_GT);
+ break;
+ case float_relation_unordered:
+ ret = (flags & FCMP_UN);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ if (ret) {
+ ret = -1;
+ }
+
+ return ret;
+}
+
+#define VFCMP(NAME, BIT, E, FN) \
+void HELPER(NAME)(CPULoongArchState *env, uint32_t oprsz, \
+ uint32_t vd, uint32_t vj, uint32_t vk, uint32_t flags) \
+{ \
+ int i; \
+ VReg t; \
+ VReg *Vd = &(env->fpr[vd].vreg); \
+ VReg *Vj = &(env->fpr[vj].vreg); \
+ VReg *Vk = &(env->fpr[vk].vreg); \
+ \
+ vec_clear_cause(env); \
+ for (i = 0; i < oprsz / (BIT / 8); i++) { \
+ FloatRelation cmp; \
+ cmp = FN(Vj->E(i), Vk->E(i), &env->fp_status); \
+ t.E(i) = vfcmp_common(env, cmp, flags); \
+ vec_update_fcsr0(env, GETPC()); \
+ } \
+ *Vd = t; \
+}
+
+VFCMP(vfcmp_c_s, 32, UW, float32_compare_quiet)
+VFCMP(vfcmp_s_s, 32, UW, float32_compare)
+VFCMP(vfcmp_c_d, 64, UD, float64_compare_quiet)
+VFCMP(vfcmp_s_d, 64, UD, float64_compare)
+
+void HELPER(vbitseli_b)(void *vd, void *vj, uint64_t imm, uint32_t desc)
+{
+ int i;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+
+ for (i = 0; i < simd_oprsz(desc); i++) {
+ Vd->B(i) = (~Vd->B(i) & Vj->B(i)) | (Vd->B(i) & imm);
+ }
+}
+
+/* Copy from target/arm/tcg/sve_helper.c */
+static inline bool do_match2(uint64_t n, uint64_t m0, uint64_t m1, int esz)
+{
+ int bits = 8 << esz;
+ uint64_t ones = dup_const(esz, 1);
+ uint64_t signs = ones << (bits - 1);
+ uint64_t cmp0, cmp1;
+
+ cmp1 = dup_const(esz, n);
+ cmp0 = cmp1 ^ m0;
+ cmp1 = cmp1 ^ m1;
+ cmp0 = (cmp0 - ones) & ~cmp0;
+ cmp1 = (cmp1 - ones) & ~cmp1;
+ return (cmp0 | cmp1) & signs;
+}
+
+#define SETANYEQZ(NAME, MO) \
+void HELPER(NAME)(CPULoongArchState *env, \
+ uint32_t oprsz, uint32_t cd, uint32_t vj) \
+{ \
+ VReg *Vj = &(env->fpr[vj].vreg); \
+ \
+ env->cf[cd & 0x7] = do_match2(0, Vj->D(0), Vj->D(1), MO); \
+ if (oprsz == 32) { \
+ env->cf[cd & 0x7] = env->cf[cd & 0x7] || \
+ do_match2(0, Vj->D(2), Vj->D(3), MO); \
+ } \
+}
+
+SETANYEQZ(vsetanyeqz_b, MO_8)
+SETANYEQZ(vsetanyeqz_h, MO_16)
+SETANYEQZ(vsetanyeqz_w, MO_32)
+SETANYEQZ(vsetanyeqz_d, MO_64)
+
+#define SETALLNEZ(NAME, MO) \
+void HELPER(NAME)(CPULoongArchState *env, \
+ uint32_t oprsz, uint32_t cd, uint32_t vj) \
+{ \
+ VReg *Vj = &(env->fpr[vj].vreg); \
+ \
+ env->cf[cd & 0x7]= !do_match2(0, Vj->D(0), Vj->D(1), MO); \
+ if (oprsz == 32) { \
+ env->cf[cd & 0x7] = env->cf[cd & 0x7] && \
+ !do_match2(0, Vj->D(2), Vj->D(3), MO); \
+ } \
+}
+
+SETALLNEZ(vsetallnez_b, MO_8)
+SETALLNEZ(vsetallnez_h, MO_16)
+SETALLNEZ(vsetallnez_w, MO_32)
+SETALLNEZ(vsetallnez_d, MO_64)
+
+#define XVINSVE0(NAME, E, MASK) \
+void HELPER(NAME)(void *vd, void *vj, uint64_t imm, uint32_t desc) \
+{ \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ Vd->E(imm & MASK) = Vj->E(0); \
+}
+
+XVINSVE0(xvinsve0_w, W, 0x7)
+XVINSVE0(xvinsve0_d, D, 0x3)
+
+#define XVPICKVE(NAME, E, BIT, MASK) \
+void HELPER(NAME)(void *vd, void *vj, uint64_t imm, uint32_t desc) \
+{ \
+ int i; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ Vd->E(0) = Vj->E(imm & MASK); \
+ for (i = 1; i < oprsz / (BIT / 8); i++) { \
+ Vd->E(i) = 0; \
+ } \
+}
+
+XVPICKVE(xvpickve_w, W, 32, 0x7)
+XVPICKVE(xvpickve_d, D, 64, 0x3)
+
+#define VPACKEV(NAME, BIT, E) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i; \
+ VReg temp = {}; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ for (i = 0; i < oprsz / (BIT / 8); i++) { \
+ temp.E(2 * i + 1) = Vj->E(2 * i); \
+ temp.E(2 *i) = Vk->E(2 * i); \
+ } \
+ *Vd = temp; \
+}
+
+VPACKEV(vpackev_b, 16, B)
+VPACKEV(vpackev_h, 32, H)
+VPACKEV(vpackev_w, 64, W)
+VPACKEV(vpackev_d, 128, D)
+
+#define VPACKOD(NAME, BIT, E) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i; \
+ VReg temp = {}; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ for (i = 0; i < oprsz / (BIT / 8); i++) { \
+ temp.E(2 * i + 1) = Vj->E(2 * i + 1); \
+ temp.E(2 * i) = Vk->E(2 * i + 1); \
+ } \
+ *Vd = temp; \
+}
+
+VPACKOD(vpackod_b, 16, B)
+VPACKOD(vpackod_h, 32, H)
+VPACKOD(vpackod_w, 64, W)
+VPACKOD(vpackod_d, 128, D)
+
+#define VPICKEV(NAME, BIT, E) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i, j, ofs; \
+ VReg temp = {}; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ ofs = LSX_LEN / BIT; \
+ for (i = 0; i < oprsz / 16; i++) { \
+ for (j = 0; j < ofs; j++) { \
+ temp.E(j + ofs * (2 * i + 1)) = Vj->E(2 * (j + ofs * i)); \
+ temp.E(j + ofs * 2 * i) = Vk->E(2 * (j + ofs * i)); \
+ } \
+ } \
+ *Vd = temp; \
+}
+
+VPICKEV(vpickev_b, 16, B)
+VPICKEV(vpickev_h, 32, H)
+VPICKEV(vpickev_w, 64, W)
+VPICKEV(vpickev_d, 128, D)
+
+#define VPICKOD(NAME, BIT, E) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i, j, ofs; \
+ VReg temp = {}; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ ofs = LSX_LEN / BIT; \
+ for (i = 0; i < oprsz / 16; i++) { \
+ for (j = 0; j < ofs; j++) { \
+ temp.E(j + ofs * (2 * i + 1)) = Vj->E(2 * (j + ofs * i) + 1); \
+ temp.E(j + ofs * 2 * i) = Vk->E(2 * (j + ofs * i) + 1); \
+ } \
+ } \
+ *Vd = temp; \
+}
+
+VPICKOD(vpickod_b, 16, B)
+VPICKOD(vpickod_h, 32, H)
+VPICKOD(vpickod_w, 64, W)
+VPICKOD(vpickod_d, 128, D)
+
+#define VILVL(NAME, BIT, E) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i, j, ofs; \
+ VReg temp = {}; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ ofs = LSX_LEN / BIT; \
+ for (i = 0; i < oprsz / 16; i++) { \
+ for (j = 0; j < ofs; j++) { \
+ temp.E(2 * (j + ofs * i) + 1) = Vj->E(j + ofs * 2 * i); \
+ temp.E(2 * (j + ofs * i)) = Vk->E(j + ofs * 2 * i); \
+ } \
+ } \
+ *Vd = temp; \
+}
+
+VILVL(vilvl_b, 16, B)
+VILVL(vilvl_h, 32, H)
+VILVL(vilvl_w, 64, W)
+VILVL(vilvl_d, 128, D)
+
+#define VILVH(NAME, BIT, E) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i, j, ofs; \
+ VReg temp = {}; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ ofs = LSX_LEN / BIT; \
+ for (i = 0; i < oprsz / 16; i++) { \
+ for (j = 0; j < ofs; j++) { \
+ temp.E(2 * (j + ofs * i) + 1) = Vj->E(j + ofs * (2 * i + 1)); \
+ temp.E(2 * (j + ofs * i)) = Vk->E(j + ofs * (2 * i + 1)); \
+ } \
+ } \
+ *Vd = temp; \
+}
+
+VILVH(vilvh_b, 16, B)
+VILVH(vilvh_h, 32, H)
+VILVH(vilvh_w, 64, W)
+VILVH(vilvh_d, 128, D)
+
+void HELPER(vshuf_b)(void *vd, void *vj, void *vk, void *va, uint32_t desc)
+{
+ int i, j, m;
+ VReg temp = {};
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ VReg *Vk = (VReg *)vk;
+ VReg *Va = (VReg *)va;
+ int oprsz = simd_oprsz(desc);
+
+ m = LSX_LEN / 8;
+ for (i = 0; i < (oprsz / 16) * m; i++) {
+ j = i < m ? 0 : 1;
+ uint64_t k = (uint8_t)Va->B(i) % (2 * m);
+ temp.B(i) = k < m ? Vk->B(k + j * m): Vj->B(k + (j - 1) * m);
+ }
+ *Vd = temp;
+}
+
+#define VSHUF(NAME, BIT, E) \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t desc) \
+{ \
+ int i, j, m; \
+ VReg temp = {}; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ VReg *Vk = (VReg *)vk; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ m = LSX_LEN / BIT; \
+ for (i = 0; i < (oprsz / 16) * m; i++) { \
+ j = i < m ? 0 : 1; \
+ uint64_t k = ((uint8_t)Vd->E(i)) % (2 * m); \
+ temp.E(i) = k < m ? Vk->E(k + j * m) : Vj->E(k + (j - 1) * m); \
+ } \
+ *Vd = temp; \
+}
+
+VSHUF(vshuf_h, 16, H)
+VSHUF(vshuf_w, 32, W)
+VSHUF(vshuf_d, 64, D)
+
+#define VSHUF4I(NAME, BIT, E) \
+void HELPER(NAME)(void *vd, void *vj, uint64_t imm, uint32_t desc) \
+{ \
+ int i, j, max; \
+ VReg temp = {}; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ max = LSX_LEN / BIT; \
+ for (i = 0; i < oprsz / (BIT / 8); i++) { \
+ j = i < max ? 1 : 2; \
+ temp.E(i) = Vj->E(SHF_POS(i - ((j -1)* max), imm) + (j - 1) * max); \
+ } \
+ *Vd = temp; \
+}
+
+VSHUF4I(vshuf4i_b, 8, B)
+VSHUF4I(vshuf4i_h, 16, H)
+VSHUF4I(vshuf4i_w, 32, W)
+
+void HELPER(vshuf4i_d)(void *vd, void *vj, uint64_t imm, uint32_t desc)
+{
+ int i;
+ VReg temp = {};
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ int oprsz = simd_oprsz(desc);
+
+ for (i = 0; i < oprsz / 16; i++) {
+ temp.D(2 * i) = (imm & 2 ? Vj : Vd)->D((imm & 1) + 2 * i);
+ temp.D(2 * i + 1) = (imm & 8 ? Vj : Vd)->D(((imm >> 2) & 1) + 2 * i);
+ }
+ *Vd = temp;
+}
+
+void HELPER(vperm_w)(void *vd, void *vj, void *vk, uint32_t desc)
+{
+ int i, m;
+ VReg temp = {};
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ VReg *Vk = (VReg *)vk;
+
+ m = LASX_LEN / 32;
+ for (i = 0; i < m ; i++) {
+ uint64_t k = (uint8_t)Vk->W(i) % 8;
+ temp.W(i) = Vj->W(k);
+ }
+ *Vd = temp;
+}
+
+void HELPER(vpermi_w)(void *vd, void *vj, uint64_t imm, uint32_t desc)
+{
+ int i;
+ VReg temp = {};
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+ int oprsz = simd_oprsz(desc);
+
+ for (i = 0; i < oprsz / 16; i++) {
+ temp.W(4 * i) = Vj->W((imm & 0x3) + 4 * i);
+ temp.W(4 * i + 1) = Vj->W(((imm >> 2) & 0x3) + 4 * i);
+ temp.W(4 * i + 2) = Vd->W(((imm >> 4) & 0x3) + 4 * i);
+ temp.W(4 * i + 3) = Vd->W(((imm >> 6) & 0x3) + 4 * i);
+ }
+ *Vd = temp;
+}
+
+void HELPER(vpermi_d)(void *vd, void *vj, uint64_t imm, uint32_t desc)
+{
+ VReg temp = {};
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+
+ temp.D(0) = Vj->D(imm & 0x3);
+ temp.D(1) = Vj->D((imm >> 2) & 0x3);
+ temp.D(2) = Vj->D((imm >> 4) & 0x3);
+ temp.D(3) = Vj->D((imm >> 6) & 0x3);
+ *Vd = temp;
+}
+
+void HELPER(vpermi_q)(void *vd, void *vj, uint64_t imm, uint32_t desc)
+{
+ int i;
+ VReg temp;
+ VReg *Vd = (VReg *)vd;
+ VReg *Vj = (VReg *)vj;
+
+ for (i = 0; i < 2; i++, imm >>= 4) {
+ temp.Q(i) = (imm & 2 ? Vd: Vj)->Q(imm & 1);
+ }
+ *Vd = temp;
+}
+
+#define VEXTRINS(NAME, BIT, E, MASK) \
+void HELPER(NAME)(void *vd, void *vj, uint64_t imm, uint32_t desc) \
+{ \
+ int i, ins, extr, max; \
+ VReg *Vd = (VReg *)vd; \
+ VReg *Vj = (VReg *)vj; \
+ int oprsz = simd_oprsz(desc); \
+ \
+ max = LSX_LEN / BIT; \
+ ins = (imm >> 4) & MASK; \
+ extr = imm & MASK; \
+ for (i = 0; i < oprsz / 16; i++) { \
+ Vd->E(ins + i * max) = Vj->E(extr + i * max); \
+ } \
+}
+
+VEXTRINS(vextrins_b, 8, B, 0xf)
+VEXTRINS(vextrins_h, 16, H, 0x7)
+VEXTRINS(vextrins_w, 32, W, 0x3)
+VEXTRINS(vextrins_d, 64, D, 0x1)
diff --git a/tests/avocado/avocado_qemu/__init__.py b/tests/avocado/avocado_qemu/__init__.py
index 3309090..0172a35 100644
--- a/tests/avocado/avocado_qemu/__init__.py
+++ b/tests/avocado/avocado_qemu/__init__.py
@@ -137,7 +137,7 @@ def _console_interaction(test, success_message, failure_message,
assert not keep_sending or send_string
if vm is None:
vm = test.vm
- console = vm.console_socket.makefile(mode='rb', encoding='utf-8')
+ console = vm.console_file
console_logger = logging.getLogger('console')
while True:
if send_string:
diff --git a/tests/avocado/boot_linux_console.py b/tests/avocado/boot_linux_console.py
index 6eab515..01ee149 100644
--- a/tests/avocado/boot_linux_console.py
+++ b/tests/avocado/boot_linux_console.py
@@ -116,6 +116,7 @@ def test_x86_64_pc(self):
console_pattern = 'Kernel command line: %s' % kernel_command_line
self.wait_for_console_pattern(console_pattern)
+ @skip('https://gitlab.com/qemu-project/qemu/-/issues/1884')
def test_mips_malta(self):
"""
:avocado: tags=arch:mips
@@ -138,6 +139,7 @@ def test_mips_malta(self):
console_pattern = 'Kernel command line: %s' % kernel_command_line
self.wait_for_console_pattern(console_pattern)
+ @skip('https://gitlab.com/qemu-project/qemu/-/issues/1884')
def test_mips64el_malta(self):
"""
This test requires the ar tool to extract "data.tar.gz" from
@@ -191,6 +193,7 @@ def test_mips64el_fuloong2e(self):
console_pattern = 'Kernel command line: %s' % kernel_command_line
self.wait_for_console_pattern(console_pattern)
+ @skip('https://gitlab.com/qemu-project/qemu/-/issues/1884')
def test_mips_malta_cpio(self):
"""
:avocado: tags=arch:mips
@@ -232,6 +235,7 @@ def test_mips_malta_cpio(self):
# Wait for VM to shut down gracefully
self.vm.wait()
+ @skip('https://gitlab.com/qemu-project/qemu/-/issues/1884')
@skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code')
def test_mips64el_malta_5KEc_cpio(self):
"""
@@ -292,6 +296,7 @@ def do_test_mips_malta32el_nanomips(self, kernel_url, kernel_hash):
console_pattern = 'Kernel command line: %s' % kernel_command_line
self.wait_for_console_pattern(console_pattern)
+ @skip('https://gitlab.com/qemu-project/qemu/-/issues/1884')
def test_mips_malta32el_nanomips_4k(self):
"""
:avocado: tags=arch:mipsel
@@ -305,6 +310,7 @@ def test_mips_malta32el_nanomips_4k(self):
kernel_hash = '477456aafd2a0f1ddc9482727f20fe9575565dd6'
self.do_test_mips_malta32el_nanomips(kernel_url, kernel_hash)
+ @skip('https://gitlab.com/qemu-project/qemu/-/issues/1884')
def test_mips_malta32el_nanomips_16k_up(self):
"""
:avocado: tags=arch:mipsel
@@ -318,6 +324,7 @@ def test_mips_malta32el_nanomips_16k_up(self):
kernel_hash = 'e882868f944c71c816e832e2303b7874d044a7bc'
self.do_test_mips_malta32el_nanomips(kernel_url, kernel_hash)
+ @skip('https://gitlab.com/qemu-project/qemu/-/issues/1884')
def test_mips_malta32el_nanomips_64k_dbg(self):
"""
:avocado: tags=arch:mipsel
diff --git a/tests/avocado/machine_mips_malta.py b/tests/avocado/machine_mips_malta.py
index 9223345..3620266 100644
--- a/tests/avocado/machine_mips_malta.py
+++ b/tests/avocado/machine_mips_malta.py
@@ -11,6 +11,7 @@
import gzip
import logging
+from avocado import skip
from avocado import skipIf
from avocado import skipUnless
from avocado.utils import archive
@@ -93,6 +94,7 @@ def do_test_i6400_framebuffer_logo(self, cpu_cores_count):
cv2.imwrite(debug_png, screendump_bgr)
self.assertGreaterEqual(tuxlogo_count, cpu_cores_count)
+ @skip('https://gitlab.com/qemu-project/qemu/-/issues/1884')
def test_mips_malta_i6400_framebuffer_logo_1core(self):
"""
:avocado: tags=arch:mips64el
@@ -101,6 +103,7 @@ def test_mips_malta_i6400_framebuffer_logo_1core(self):
"""
self.do_test_i6400_framebuffer_logo(1)
+ @skip('https://gitlab.com/qemu-project/qemu/-/issues/1884')
@skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab')
def test_mips_malta_i6400_framebuffer_logo_7cores(self):
"""
@@ -111,6 +114,7 @@ def test_mips_malta_i6400_framebuffer_logo_7cores(self):
"""
self.do_test_i6400_framebuffer_logo(7)
+ @skip('https://gitlab.com/qemu-project/qemu/-/issues/1884')
@skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab')
def test_mips_malta_i6400_framebuffer_logo_8cores(self):
"""
@@ -142,6 +146,7 @@ def do_test_yamon(self):
wait_for_console_pattern(self, prompt)
self.vm.shutdown()
+ @skip('https://gitlab.com/qemu-project/qemu/-/issues/1884')
def test_mipsel_malta_yamon(self):
"""
:avocado: tags=arch:mipsel
@@ -150,6 +155,7 @@ def test_mipsel_malta_yamon(self):
"""
self.do_test_yamon()
+ @skip('https://gitlab.com/qemu-project/qemu/-/issues/1884')
def test_mips64el_malta_yamon(self):
"""
:avocado: tags=arch:mips64el
diff --git a/tests/avocado/replay_kernel.py b/tests/avocado/replay_kernel.py
index a186105..f7ccfd2 100644
--- a/tests/avocado/replay_kernel.py
+++ b/tests/avocado/replay_kernel.py
@@ -98,6 +98,7 @@ def test_x86_64_pc(self):
self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5)
+ @skip('https://gitlab.com/qemu-project/qemu/-/issues/1884')
def test_mips_malta(self):
"""
:avocado: tags=arch:mips
@@ -116,6 +117,7 @@ def test_mips_malta(self):
self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5)
+ @skip('https://gitlab.com/qemu-project/qemu/-/issues/1884')
def test_mips64el_malta(self):
"""
This test requires the ar tool to extract "data.tar.gz" from
@@ -431,6 +433,7 @@ class ReplayKernelSlow(ReplayKernelBase):
# making it very slow.
timeout = 180
+ @skip('https://gitlab.com/qemu-project/qemu/-/issues/1884')
def test_mips_malta_cpio(self):
"""
:avocado: tags=arch:mips
@@ -460,6 +463,7 @@ def test_mips_malta_cpio(self):
self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5,
args=('-initrd', initrd_path))
+ @skip('https://gitlab.com/qemu-project/qemu/-/issues/1884')
@skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code')
def test_mips64el_malta_5KEc_cpio(self):
"""
@@ -502,6 +506,7 @@ def do_test_mips_malta32el_nanomips(self, kernel_path_xz):
console_pattern = 'Kernel command line: %s' % kernel_command_line
self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5)
+ @skip('https://gitlab.com/qemu-project/qemu/-/issues/1884')
def test_mips_malta32el_nanomips_4k(self):
"""
:avocado: tags=arch:mipsel
@@ -516,6 +521,7 @@ def test_mips_malta32el_nanomips_4k(self):
kernel_path_xz = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
self.do_test_mips_malta32el_nanomips(kernel_path_xz)
+ @skip('https://gitlab.com/qemu-project/qemu/-/issues/1884')
def test_mips_malta32el_nanomips_16k_up(self):
"""
:avocado: tags=arch:mipsel
@@ -530,6 +536,7 @@ def test_mips_malta32el_nanomips_16k_up(self):
kernel_path_xz = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
self.do_test_mips_malta32el_nanomips(kernel_path_xz)
+ @skip('https://gitlab.com/qemu-project/qemu/-/issues/1884')
def test_mips_malta32el_nanomips_64k_dbg(self):
"""
:avocado: tags=arch:mipsel
diff --git a/tests/avocado/tuxrun_baselines.py b/tests/avocado/tuxrun_baselines.py
index e12250e..610b7e2 100644
--- a/tests/avocado/tuxrun_baselines.py
+++ b/tests/avocado/tuxrun_baselines.py
@@ -352,6 +352,7 @@ def test_i386(self):
self.common_tuxrun(csums=sums, drive="virtio-blk-pci")
+ @skip('https://gitlab.com/qemu-project/qemu/-/issues/1884')
def test_mips32(self):
"""
:avocado: tags=arch:mips
@@ -370,6 +371,7 @@ def test_mips32(self):
self.common_tuxrun(csums=sums, drive="driver=ide-hd,bus=ide.0,unit=0")
+ @skip('https://gitlab.com/qemu-project/qemu/-/issues/1884')
def test_mips32el(self):
"""
:avocado: tags=arch:mipsel
@@ -387,6 +389,7 @@ def test_mips32el(self):
self.common_tuxrun(csums=sums, drive="driver=ide-hd,bus=ide.0,unit=0")
+ @skip('https://gitlab.com/qemu-project/qemu/-/issues/1884')
def test_mips64(self):
"""
:avocado: tags=arch:mips64
@@ -404,6 +407,7 @@ def test_mips64(self):
self.common_tuxrun(csums=sums, drive="driver=ide-hd,bus=ide.0,unit=0")
+ @skip('https://gitlab.com/qemu-project/qemu/-/issues/1884')
def test_mips64el(self):
"""
:avocado: tags=arch:mips64el
diff --git a/tests/docker/dockerfiles/debian-amd64-cross.docker b/tests/docker/dockerfiles/debian-amd64-cross.docker
index 0cf3ba6..0991938 100644
--- a/tests/docker/dockerfiles/debian-amd64-cross.docker
+++ b/tests/docker/dockerfiles/debian-amd64-cross.docker
@@ -1,10 +1,10 @@
# THIS FILE WAS AUTO-GENERATED
#
-# $ lcitool dockerfile --layers all --cross-arch x86_64 debian-11 qemu
+# $ lcitool dockerfile --layers all --cross-arch x86_64 debian-12 qemu
#
# https://gitlab.com/libvirt/libvirt-ci
-FROM docker.io/library/debian:11-slim
+FROM docker.io/library/debian:12-slim
RUN export DEBIAN_FRONTEND=noninteractive && \
apt-get update && \
@@ -47,11 +47,9 @@
python3-opencv \
python3-pillow \
python3-pip \
- python3-setuptools \
python3-sphinx \
python3-sphinx-rtd-theme \
python3-venv \
- python3-wheel \
python3-yaml \
rpm2cpio \
sed \
@@ -67,8 +65,6 @@
sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \
dpkg-reconfigure locales
-RUN /usr/bin/pip3 install tomli
-
ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
ENV LANG "en_US.UTF-8"
ENV MAKE "/usr/bin/make"
@@ -146,6 +142,7 @@
libvdeplug-dev:amd64 \
libvirglrenderer-dev:amd64 \
libvte-2.91-dev:amd64 \
+ libxdp-dev:amd64 \
libxen-dev:amd64 \
libzstd-dev:amd64 \
nettle-dev:amd64 \
diff --git a/tests/docker/dockerfiles/debian-amd64.docker b/tests/docker/dockerfiles/debian-amd64.docker
index e3e1de2..61dbc3f 100644
--- a/tests/docker/dockerfiles/debian-amd64.docker
+++ b/tests/docker/dockerfiles/debian-amd64.docker
@@ -1,10 +1,10 @@
# THIS FILE WAS AUTO-GENERATED
#
-# $ lcitool dockerfile --layers all debian-11 qemu
+# $ lcitool dockerfile --layers all debian-12 qemu
#
# https://gitlab.com/libvirt/libvirt-ci
-FROM docker.io/library/debian:11-slim
+FROM docker.io/library/debian:12-slim
RUN export DEBIAN_FRONTEND=noninteractive && \
apt-get update && \
@@ -97,6 +97,7 @@
libvdeplug-dev \
libvirglrenderer-dev \
libvte-2.91-dev \
+ libxdp-dev \
libxen-dev \
libzstd-dev \
llvm \
@@ -115,11 +116,9 @@
python3-opencv \
python3-pillow \
python3-pip \
- python3-setuptools \
python3-sphinx \
python3-sphinx-rtd-theme \
python3-venv \
- python3-wheel \
python3-yaml \
rpm2cpio \
sed \
@@ -145,8 +144,6 @@
ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/g++ && \
ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/gcc
-RUN /usr/bin/pip3 install tomli
-
ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
ENV LANG "en_US.UTF-8"
ENV MAKE "/usr/bin/make"
diff --git a/tests/docker/dockerfiles/debian-arm64-cross.docker b/tests/docker/dockerfiles/debian-arm64-cross.docker
index d8cd4f8..74eabb2 100644
--- a/tests/docker/dockerfiles/debian-arm64-cross.docker
+++ b/tests/docker/dockerfiles/debian-arm64-cross.docker
@@ -1,10 +1,10 @@
# THIS FILE WAS AUTO-GENERATED
#
-# $ lcitool dockerfile --layers all --cross-arch aarch64 debian-11 qemu
+# $ lcitool dockerfile --layers all --cross-arch aarch64 debian-12 qemu
#
# https://gitlab.com/libvirt/libvirt-ci
-FROM docker.io/library/debian:11-slim
+FROM docker.io/library/debian:12-slim
RUN export DEBIAN_FRONTEND=noninteractive && \
apt-get update && \
@@ -47,11 +47,9 @@
python3-opencv \
python3-pillow \
python3-pip \
- python3-setuptools \
python3-sphinx \
python3-sphinx-rtd-theme \
python3-venv \
- python3-wheel \
python3-yaml \
rpm2cpio \
sed \
@@ -67,8 +65,6 @@
sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \
dpkg-reconfigure locales
-RUN /usr/bin/pip3 install tomli
-
ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
ENV LANG "en_US.UTF-8"
ENV MAKE "/usr/bin/make"
@@ -145,6 +141,7 @@
libvdeplug-dev:arm64 \
libvirglrenderer-dev:arm64 \
libvte-2.91-dev:arm64 \
+ libxdp-dev:arm64 \
libxen-dev:arm64 \
libzstd-dev:arm64 \
nettle-dev:arm64 \
diff --git a/tests/docker/dockerfiles/debian-armhf-cross.docker b/tests/docker/dockerfiles/debian-armhf-cross.docker
index f45cfed..1ebd6eb 100644
--- a/tests/docker/dockerfiles/debian-armhf-cross.docker
+++ b/tests/docker/dockerfiles/debian-armhf-cross.docker
@@ -1,10 +1,10 @@
# THIS FILE WAS AUTO-GENERATED
#
-# $ lcitool dockerfile --layers all --cross-arch armv7l debian-11 qemu
+# $ lcitool dockerfile --layers all --cross-arch armv7l debian-12 qemu
#
# https://gitlab.com/libvirt/libvirt-ci
-FROM docker.io/library/debian:11-slim
+FROM docker.io/library/debian:12-slim
RUN export DEBIAN_FRONTEND=noninteractive && \
apt-get update && \
@@ -47,11 +47,9 @@
python3-opencv \
python3-pillow \
python3-pip \
- python3-setuptools \
python3-sphinx \
python3-sphinx-rtd-theme \
python3-venv \
- python3-wheel \
python3-yaml \
rpm2cpio \
sed \
@@ -67,8 +65,6 @@
sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \
dpkg-reconfigure locales
-RUN /usr/bin/pip3 install tomli
-
ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
ENV LANG "en_US.UTF-8"
ENV MAKE "/usr/bin/make"
@@ -145,6 +141,7 @@
libvdeplug-dev:armhf \
libvirglrenderer-dev:armhf \
libvte-2.91-dev:armhf \
+ libxdp-dev:armhf \
libxen-dev:armhf \
libzstd-dev:armhf \
nettle-dev:armhf \
diff --git a/tests/docker/dockerfiles/debian-loongarch-cross.docker b/tests/docker/dockerfiles/debian-loongarch-cross.docker
index 9d95754..b4bf265 100644
--- a/tests/docker/dockerfiles/debian-loongarch-cross.docker
+++ b/tests/docker/dockerfiles/debian-loongarch-cross.docker
@@ -20,7 +20,7 @@
git \
python3-minimal
-RUN curl -#SL https://github.com/loongson/build-tools/releases/download/2022.05.29/loongarch64-clfs-5.0-cross-tools-gcc-glibc.tar.xz \
+RUN curl -#SL https://github.com/loongson/build-tools/releases/download/2023.08.08/CLFS-loongarch64-8.1-x86_64-cross-tools-gcc-glibc.tar.xz \
| tar -xJC /opt
ENV PATH $PATH:/opt/cross-tools/bin
diff --git a/tests/docker/dockerfiles/debian-ppc64el-cross.docker b/tests/docker/dockerfiles/debian-ppc64el-cross.docker
index 52f8c34..59091fe 100644
--- a/tests/docker/dockerfiles/debian-ppc64el-cross.docker
+++ b/tests/docker/dockerfiles/debian-ppc64el-cross.docker
@@ -1,10 +1,10 @@
# THIS FILE WAS AUTO-GENERATED
#
-# $ lcitool dockerfile --layers all --cross-arch ppc64le debian-11 qemu
+# $ lcitool dockerfile --layers all --cross-arch ppc64le debian-12 qemu
#
# https://gitlab.com/libvirt/libvirt-ci
-FROM docker.io/library/debian:11-slim
+FROM docker.io/library/debian:12-slim
RUN export DEBIAN_FRONTEND=noninteractive && \
apt-get update && \
@@ -47,11 +47,9 @@
python3-opencv \
python3-pillow \
python3-pip \
- python3-setuptools \
python3-sphinx \
python3-sphinx-rtd-theme \
python3-venv \
- python3-wheel \
python3-yaml \
rpm2cpio \
sed \
@@ -67,8 +65,6 @@
sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \
dpkg-reconfigure locales
-RUN /usr/bin/pip3 install tomli
-
ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
ENV LANG "en_US.UTF-8"
ENV MAKE "/usr/bin/make"
@@ -145,6 +141,7 @@
libvdeplug-dev:ppc64el \
libvirglrenderer-dev:ppc64el \
libvte-2.91-dev:ppc64el \
+ libxdp-dev:ppc64el \
libzstd-dev:ppc64el \
nettle-dev:ppc64el \
systemtap-sdt-dev:ppc64el \
diff --git a/tests/docker/dockerfiles/debian-s390x-cross.docker b/tests/docker/dockerfiles/debian-s390x-cross.docker
index 208e57b..48b2f28 100644
--- a/tests/docker/dockerfiles/debian-s390x-cross.docker
+++ b/tests/docker/dockerfiles/debian-s390x-cross.docker
@@ -1,10 +1,10 @@
# THIS FILE WAS AUTO-GENERATED
#
-# $ lcitool dockerfile --layers all --cross-arch s390x debian-11 qemu
+# $ lcitool dockerfile --layers all --cross-arch s390x debian-12 qemu
#
# https://gitlab.com/libvirt/libvirt-ci
-FROM docker.io/library/debian:11-slim
+FROM docker.io/library/debian:12-slim
RUN export DEBIAN_FRONTEND=noninteractive && \
apt-get update && \
@@ -47,11 +47,9 @@
python3-opencv \
python3-pillow \
python3-pip \
- python3-setuptools \
python3-sphinx \
python3-sphinx-rtd-theme \
python3-venv \
- python3-wheel \
python3-yaml \
rpm2cpio \
sed \
@@ -67,8 +65,6 @@
sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \
dpkg-reconfigure locales
-RUN /usr/bin/pip3 install tomli
-
ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
ENV LANG "en_US.UTF-8"
ENV MAKE "/usr/bin/make"
@@ -144,6 +140,7 @@
libvdeplug-dev:s390x \
libvirglrenderer-dev:s390x \
libvte-2.91-dev:s390x \
+ libxdp-dev:s390x \
libzstd-dev:s390x \
nettle-dev:s390x \
systemtap-sdt-dev:s390x \
diff --git a/tests/lcitool/libvirt-ci b/tests/lcitool/libvirt-ci
index 5f84a21..e3ed1e5 160000
--- a/tests/lcitool/libvirt-ci
+++ b/tests/lcitool/libvirt-ci
@@ -1 +1 @@
-Subproject commit 5f84a21881577a5fb56cc956f6fe4e2abd6fcff0
+Subproject commit e3ed1e5da101943e53d8d89424e17b22120743f5
diff --git a/tests/lcitool/refresh b/tests/lcitool/refresh
index 4584870..92e7d30 100755
--- a/tests/lcitool/refresh
+++ b/tests/lcitool/refresh
@@ -93,7 +93,7 @@
# Netmap still needs to be manually built as it is yet to be packaged
# into a distro. We also add cscope and gtags which are used in the CI
# test
-debian11_extras = [
+debian12_extras = [
"# netmap/cscope/global\n",
"RUN DEBIAN_FRONTEND=noninteractive eatmydata \\\n",
" apt install -y --no-install-recommends \\\n",
@@ -123,8 +123,8 @@
#
generate_dockerfile("alpine", "alpine-318")
generate_dockerfile("centos8", "centos-stream-8")
- generate_dockerfile("debian-amd64", "debian-11",
- trailer="".join(debian11_extras))
+ generate_dockerfile("debian-amd64", "debian-12",
+ trailer="".join(debian12_extras))
generate_dockerfile("fedora", "fedora-38")
generate_dockerfile("opensuse-leap", "opensuse-leap-15")
generate_dockerfile("ubuntu2004", "ubuntu-2004")
@@ -133,24 +133,25 @@
#
# Cross compiling builds
#
- generate_dockerfile("debian-amd64-cross", "debian-11",
+ generate_dockerfile("debian-amd64-cross", "debian-12",
cross="x86_64",
trailer=cross_build("x86_64-linux-gnu-",
"x86_64-softmmu,"
"x86_64-linux-user,"
"i386-softmmu,i386-linux-user"))
- generate_dockerfile("debian-arm64-cross", "debian-11",
+ generate_dockerfile("debian-arm64-cross", "debian-12",
cross="aarch64",
trailer=cross_build("aarch64-linux-gnu-",
"aarch64-softmmu,aarch64-linux-user"))
+ # migration to bookworm stalled: https://lists.debian.org/debian-arm/2023/09/msg00006.html
generate_dockerfile("debian-armel-cross", "debian-11",
cross="armv6l",
trailer=cross_build("arm-linux-gnueabi-",
"arm-softmmu,arm-linux-user,armeb-linux-user"))
- generate_dockerfile("debian-armhf-cross", "debian-11",
+ generate_dockerfile("debian-armhf-cross", "debian-12",
cross="armv7l",
trailer=cross_build("arm-linux-gnueabihf-",
"arm-softmmu,arm-linux-user"))
@@ -165,7 +166,7 @@
trailer=cross_build("mipsel-linux-gnu-",
"mipsel-softmmu,mipsel-linux-user"))
- generate_dockerfile("debian-ppc64el-cross", "debian-11",
+ generate_dockerfile("debian-ppc64el-cross", "debian-12",
cross="ppc64le",
trailer=cross_build("powerpc64le-linux-gnu-",
"ppc64-softmmu,ppc64-linux-user"))
@@ -176,7 +177,7 @@
trailer=cross_build("riscv64-linux-gnu-",
"riscv64-softmmu,riscv64-linux-user"))
- generate_dockerfile("debian-s390x-cross", "debian-11",
+ generate_dockerfile("debian-s390x-cross", "debian-12",
cross="s390x",
trailer=cross_build("s390x-linux-gnu-",
"s390x-softmmu,s390x-linux-user"))
diff --git a/tests/qemu-iotests/tests/file-io-error b/tests/qemu-iotests/tests/file-io-error
new file mode 100755
index 0000000..88ee5f6
--- /dev/null
+++ b/tests/qemu-iotests/tests/file-io-error
@@ -0,0 +1,119 @@
+#!/usr/bin/env bash
+# group: rw
+#
+# Produce an I/O error in file-posix, and hope that it is not catastrophic.
+# Regression test for: https://bugzilla.redhat.com/show_bug.cgi?id=2234374
+#
+# Copyright (C) 2023 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+seq=$(basename "$0")
+echo "QA output created by $seq"
+
+status=1 # failure is the default!
+
+_cleanup()
+{
+ _cleanup_qemu
+ rm -f "$TEST_DIR/fuse-export"
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ../common.rc
+. ../common.filter
+. ../common.qemu
+
+# Format-agnostic (we do not use any), but we do test the file protocol
+_supported_proto file
+_require_drivers blkdebug null-co
+
+if [ "$IMGOPTSSYNTAX" = "true" ]; then
+ # We need `$QEMU_IO -f file` to work; IMGOPTSSYNTAX uses --image-opts,
+ # breaking -f.
+ _unsupported_fmt $IMGFMT
+fi
+
+# This is a regression test of a bug in which flie-posix would access zone
+# information in case of an I/O error even when there is no zone information,
+# resulting in a division by zero.
+# To reproduce the problem, we need to trigger an I/O error inside of
+# file-posix, which can be done (rootless) by providing a FUSE export that
+# presents only errors when accessed.
+
+_launch_qemu
+_send_qemu_cmd $QEMU_HANDLE \
+ "{'execute': 'qmp_capabilities'}" \
+ 'return'
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{'execute': 'blockdev-add',
+ 'arguments': {
+ 'driver': 'blkdebug',
+ 'node-name': 'node0',
+ 'inject-error': [{'event': 'none'}],
+ 'image': {
+ 'driver': 'null-co'
+ }
+ }}" \
+ 'return'
+
+# FUSE mountpoint must exist and be a regular file
+touch "$TEST_DIR/fuse-export"
+
+# The grep -v to filter fusermount's (benign) error when /etc/fuse.conf does
+# not contain user_allow_other and the subsequent check for missing FUSE support
+# have both been taken from iotest 308.
+output=$(_send_qemu_cmd $QEMU_HANDLE \
+ "{'execute': 'block-export-add',
+ 'arguments': {
+ 'id': 'exp0',
+ 'type': 'fuse',
+ 'node-name': 'node0',
+ 'mountpoint': '$TEST_DIR/fuse-export',
+ 'writable': true
+ }}" \
+ 'return' \
+ | grep -v 'option allow_other only allowed if')
+
+if echo "$output" | grep -q "Parameter 'type' does not accept value 'fuse'"; then
+ _notrun 'No FUSE support'
+fi
+echo "$output"
+
+echo
+# This should fail, but gracefully, i.e. just print an I/O error, not crash.
+$QEMU_IO -f file -c 'write 0 64M' "$TEST_DIR/fuse-export" | _filter_qemu_io
+echo
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{'execute': 'block-export-del',
+ 'arguments': {'id': 'exp0'}}" \
+ 'return'
+
+_send_qemu_cmd $QEMU_HANDLE \
+ '' \
+ 'BLOCK_EXPORT_DELETED'
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{'execute': 'blockdev-del',
+ 'arguments': {'node-name': 'node0'}}" \
+ 'return'
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/tests/file-io-error.out b/tests/qemu-iotests/tests/file-io-error.out
new file mode 100644
index 0000000..0f46455
--- /dev/null
+++ b/tests/qemu-iotests/tests/file-io-error.out
@@ -0,0 +1,33 @@
+QA output created by file-io-error
+{'execute': 'qmp_capabilities'}
+{"return": {}}
+{'execute': 'blockdev-add',
+ 'arguments': {
+ 'driver': 'blkdebug',
+ 'node-name': 'node0',
+ 'inject-error': [{'event': 'none'}],
+ 'image': {
+ 'driver': 'null-co'
+ }
+ }}
+{"return": {}}
+{'execute': 'block-export-add',
+ 'arguments': {
+ 'id': 'exp0',
+ 'type': 'fuse',
+ 'node-name': 'node0',
+ 'mountpoint': 'TEST_DIR/fuse-export',
+ 'writable': true
+ }}
+{"return": {}}
+
+write failed: Input/output error
+
+{'execute': 'block-export-del',
+ 'arguments': {'id': 'exp0'}}
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "exp0"}}
+{'execute': 'blockdev-del',
+ 'arguments': {'node-name': 'node0'}}
+{"return": {}}
+*** done
diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c
index 34b9c14..b1eba71 100644
--- a/tests/qtest/libqtest.c
+++ b/tests/qtest/libqtest.c
@@ -24,6 +24,9 @@
#ifdef __linux__
#include <sys/prctl.h>
#endif /* __linux__ */
+#ifdef __FreeBSD__
+#include <sys/procctl.h>
+#endif /* __FreeBSD__ */
#include "libqtest.h"
#include "libqmp.h"
@@ -414,6 +417,10 @@
*/
prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
#endif /* __linux__ */
+#ifdef __FreeBSD__
+ int sig = SIGKILL;
+ procctl(P_PID, getpid(), PROC_PDEATHSIG_CTL, &sig);
+#endif /* __FreeBSD__ */
if (!g_setenv("QEMU_AUDIO_DRV", "none", true)) {
exit(1);
}
diff --git a/tests/qtest/microbit-test.c b/tests/qtest/microbit-test.c
index 2abcad8..72190d3 100644
--- a/tests/qtest/microbit-test.c
+++ b/tests/qtest/microbit-test.c
@@ -434,6 +434,8 @@
g_assert_true(qtest_get_irq(qts, 0));
qtest_set_irq_in(qts, "/machine/nrf51", "unnamed-gpio-in", 3, 0);
g_assert_true(qtest_get_irq(qts, 0));
+
+ qtest_quit(qts);
}
static void timer_task(QTestState *qts, hwaddr task)
diff --git a/tests/unit/test-throttle.c b/tests/unit/test-throttle.c
index dc8739c..cb587e3 100644
--- a/tests/unit/test-throttle.c
+++ b/tests/unit/test-throttle.c
@@ -169,8 +169,72 @@
/* check initialized fields */
g_assert(tt->clock_type == QEMU_CLOCK_VIRTUAL);
- g_assert(tt->timers[0]);
- g_assert(tt->timers[1]);
+ g_assert(tt->timers[THROTTLE_READ]);
+ g_assert(tt->timers[THROTTLE_WRITE]);
+
+ /* check other fields where cleared */
+ g_assert(!ts.previous_leak);
+ g_assert(!ts.cfg.op_size);
+ for (i = 0; i < BUCKETS_COUNT; i++) {
+ g_assert(!ts.cfg.buckets[i].avg);
+ g_assert(!ts.cfg.buckets[i].max);
+ g_assert(!ts.cfg.buckets[i].level);
+ }
+
+ throttle_timers_destroy(tt);
+}
+
+static void test_init_readonly(void)
+{
+ int i;
+
+ tt = &tgm.throttle_timers;
+
+ /* fill the structures with crap */
+ memset(&ts, 1, sizeof(ts));
+ memset(tt, 1, sizeof(*tt));
+
+ /* init structures */
+ throttle_init(&ts);
+ throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
+ read_timer_cb, NULL, &ts);
+
+ /* check initialized fields */
+ g_assert(tt->clock_type == QEMU_CLOCK_VIRTUAL);
+ g_assert(tt->timers[THROTTLE_READ]);
+ g_assert(!tt->timers[THROTTLE_WRITE]);
+
+ /* check other fields where cleared */
+ g_assert(!ts.previous_leak);
+ g_assert(!ts.cfg.op_size);
+ for (i = 0; i < BUCKETS_COUNT; i++) {
+ g_assert(!ts.cfg.buckets[i].avg);
+ g_assert(!ts.cfg.buckets[i].max);
+ g_assert(!ts.cfg.buckets[i].level);
+ }
+
+ throttle_timers_destroy(tt);
+}
+
+static void test_init_writeonly(void)
+{
+ int i;
+
+ tt = &tgm.throttle_timers;
+
+ /* fill the structures with crap */
+ memset(&ts, 1, sizeof(ts));
+ memset(tt, 1, sizeof(*tt));
+
+ /* init structures */
+ throttle_init(&ts);
+ throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
+ NULL, write_timer_cb, &ts);
+
+ /* check initialized fields */
+ g_assert(tt->clock_type == QEMU_CLOCK_VIRTUAL);
+ g_assert(!tt->timers[THROTTLE_READ]);
+ g_assert(tt->timers[THROTTLE_WRITE]);
/* check other fields where cleared */
g_assert(!ts.previous_leak);
@@ -191,7 +255,7 @@
throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
read_timer_cb, write_timer_cb, &ts);
throttle_timers_destroy(tt);
- for (i = 0; i < 2; i++) {
+ for (i = 0; i < THROTTLE_MAX; i++) {
g_assert(!tt->timers[i]);
}
}
@@ -573,9 +637,9 @@
throttle_config(&ts, QEMU_CLOCK_VIRTUAL, &cfg);
/* account a read */
- throttle_account(&ts, false, size);
+ throttle_account(&ts, THROTTLE_READ, size);
/* account a write */
- throttle_account(&ts, true, size);
+ throttle_account(&ts, THROTTLE_WRITE, size);
/* check total result */
index = to_test[is_ops][0];
@@ -752,6 +816,8 @@
g_test_add_func("/throttle/leak_bucket", test_leak_bucket);
g_test_add_func("/throttle/compute_wait", test_compute_wait);
g_test_add_func("/throttle/init", test_init);
+ g_test_add_func("/throttle/init_readonly", test_init_readonly);
+ g_test_add_func("/throttle/init_writeonly", test_init_writeonly);
g_test_add_func("/throttle/destroy", test_destroy);
g_test_add_func("/throttle/have_timer", test_have_timer);
g_test_add_func("/throttle/detach_attach", test_detach_attach);
diff --git a/util/throttle.c b/util/throttle.c
index 81f247a..9582899 100644
--- a/util/throttle.c
+++ b/util/throttle.c
@@ -136,13 +136,14 @@
/* This function compute the time that must be waited while this IO
*
- * @is_write: true if the current IO is a write, false if it's a read
+ * @direction: throttle direction
* @ret: time to wait
*/
static int64_t throttle_compute_wait_for(ThrottleState *ts,
- bool is_write)
+ ThrottleDirection direction)
{
- BucketType to_check[2][4] = { {THROTTLE_BPS_TOTAL,
+ static const BucketType to_check[THROTTLE_MAX][4] = {
+ {THROTTLE_BPS_TOTAL,
THROTTLE_OPS_TOTAL,
THROTTLE_BPS_READ,
THROTTLE_OPS_READ},
@@ -153,8 +154,8 @@
int64_t wait, max_wait = 0;
int i;
- for (i = 0; i < 4; i++) {
- BucketType index = to_check[is_write][i];
+ for (i = 0; i < ARRAY_SIZE(to_check[THROTTLE_READ]); i++) {
+ BucketType index = to_check[direction][i];
wait = throttle_compute_wait(&ts->cfg.buckets[index]);
if (wait > max_wait) {
max_wait = wait;
@@ -166,13 +167,13 @@
/* compute the timer for this type of operation
*
- * @is_write: the type of operation
+ * @direction: throttle direction
* @now: the current clock timestamp
* @next_timestamp: the resulting timer
* @ret: true if a timer must be set
*/
static bool throttle_compute_timer(ThrottleState *ts,
- bool is_write,
+ ThrottleDirection direction,
int64_t now,
int64_t *next_timestamp)
{
@@ -182,7 +183,7 @@
throttle_do_leak(ts, now);
/* compute the wait time if any */
- wait = throttle_compute_wait_for(ts, is_write);
+ wait = throttle_compute_wait_for(ts, direction);
/* if the code must wait compute when the next timer should fire */
if (wait) {
@@ -199,10 +200,15 @@
void throttle_timers_attach_aio_context(ThrottleTimers *tt,
AioContext *new_context)
{
- tt->timers[0] = aio_timer_new(new_context, tt->clock_type, SCALE_NS,
- tt->read_timer_cb, tt->timer_opaque);
- tt->timers[1] = aio_timer_new(new_context, tt->clock_type, SCALE_NS,
- tt->write_timer_cb, tt->timer_opaque);
+ ThrottleDirection dir;
+
+ for (dir = THROTTLE_READ; dir < THROTTLE_MAX; dir++) {
+ if (tt->timer_cb[dir]) {
+ tt->timers[dir] =
+ aio_timer_new(new_context, tt->clock_type, SCALE_NS,
+ tt->timer_cb[dir], tt->timer_opaque);
+ }
+ }
}
/*
@@ -233,11 +239,12 @@
QEMUTimerCB *write_timer_cb,
void *timer_opaque)
{
+ assert(read_timer_cb || write_timer_cb);
memset(tt, 0, sizeof(ThrottleTimers));
tt->clock_type = clock_type;
- tt->read_timer_cb = read_timer_cb;
- tt->write_timer_cb = write_timer_cb;
+ tt->timer_cb[THROTTLE_READ] = read_timer_cb;
+ tt->timer_cb[THROTTLE_WRITE] = write_timer_cb;
tt->timer_opaque = timer_opaque;
throttle_timers_attach_aio_context(tt, aio_context);
}
@@ -245,7 +252,9 @@
/* destroy a timer */
static void throttle_timer_destroy(QEMUTimer **timer)
{
- assert(*timer != NULL);
+ if (*timer == NULL) {
+ return;
+ }
timer_free(*timer);
*timer = NULL;
@@ -254,10 +263,10 @@
/* Remove timers from event loop */
void throttle_timers_detach_aio_context(ThrottleTimers *tt)
{
- int i;
+ ThrottleDirection dir;
- for (i = 0; i < 2; i++) {
- throttle_timer_destroy(&tt->timers[i]);
+ for (dir = THROTTLE_READ; dir < THROTTLE_MAX; dir++) {
+ throttle_timer_destroy(&tt->timers[dir]);
}
}
@@ -270,8 +279,12 @@
/* is any throttling timer configured */
bool throttle_timers_are_initialized(ThrottleTimers *tt)
{
- if (tt->timers[0]) {
- return true;
+ ThrottleDirection dir;
+
+ for (dir = THROTTLE_READ; dir < THROTTLE_MAX; dir++) {
+ if (tt->timers[dir]) {
+ return true;
+ }
}
return false;
@@ -413,19 +426,24 @@
* NOTE: this function is not unit tested due to it's usage of timer_mod
*
* @tt: the timers structure
- * @is_write: the type of operation (read/write)
+ * @direction: throttle direction
* @ret: true if the timer has been scheduled else false
*/
bool throttle_schedule_timer(ThrottleState *ts,
ThrottleTimers *tt,
- bool is_write)
+ ThrottleDirection direction)
{
int64_t now = qemu_clock_get_ns(tt->clock_type);
int64_t next_timestamp;
+ QEMUTimer *timer;
bool must_wait;
+ assert(direction < THROTTLE_MAX);
+ timer = tt->timers[direction];
+ assert(timer);
+
must_wait = throttle_compute_timer(ts,
- is_write,
+ direction,
now,
&next_timestamp);
@@ -435,48 +453,50 @@
}
/* request throttled and timer pending -> do nothing */
- if (timer_pending(tt->timers[is_write])) {
+ if (timer_pending(timer)) {
return true;
}
/* request throttled and timer not pending -> arm timer */
- timer_mod(tt->timers[is_write], next_timestamp);
+ timer_mod(timer, next_timestamp);
return true;
}
/* do the accounting for this operation
*
- * @is_write: the type of operation (read/write)
+ * @direction: throttle direction
* @size: the size of the operation
*/
-void throttle_account(ThrottleState *ts, bool is_write, uint64_t size)
+void throttle_account(ThrottleState *ts, ThrottleDirection direction,
+ uint64_t size)
{
- const BucketType bucket_types_size[2][2] = {
+ static const BucketType bucket_types_size[THROTTLE_MAX][2] = {
{ THROTTLE_BPS_TOTAL, THROTTLE_BPS_READ },
{ THROTTLE_BPS_TOTAL, THROTTLE_BPS_WRITE }
};
- const BucketType bucket_types_units[2][2] = {
+ static const BucketType bucket_types_units[THROTTLE_MAX][2] = {
{ THROTTLE_OPS_TOTAL, THROTTLE_OPS_READ },
{ THROTTLE_OPS_TOTAL, THROTTLE_OPS_WRITE }
};
double units = 1.0;
unsigned i;
+ assert(direction < THROTTLE_MAX);
/* if cfg.op_size is defined and smaller than size we compute unit count */
if (ts->cfg.op_size && size > ts->cfg.op_size) {
units = (double) size / ts->cfg.op_size;
}
- for (i = 0; i < 2; i++) {
+ for (i = 0; i < ARRAY_SIZE(bucket_types_size[THROTTLE_READ]); i++) {
LeakyBucket *bkt;
- bkt = &ts->cfg.buckets[bucket_types_size[is_write][i]];
+ bkt = &ts->cfg.buckets[bucket_types_size[direction][i]];
bkt->level += size;
if (bkt->burst_length > 1) {
bkt->burst_level += size;
}
- bkt = &ts->cfg.buckets[bucket_types_units[is_write][i]];
+ bkt = &ts->cfg.buckets[bucket_types_units[direction][i]];
bkt->level += units;
if (bkt->burst_length > 1) {
bkt->burst_level += units;