Compare commits
99 Commits
pull-usb-5
...
pull-vga-2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a889bc2bb2 | ||
|
|
0850fd583f | ||
|
|
63e3e24db2 | ||
|
|
e2bbfc8ee2 | ||
|
|
411f491e0a | ||
|
|
7931b05987 | ||
|
|
0e96643c98 | ||
|
|
ad600a4d49 | ||
|
|
ba3627ec38 | ||
|
|
4b8abfb78e | ||
|
|
370e681629 | ||
|
|
9b17031ac4 | ||
|
|
ac1307abfe | ||
|
|
90d9d30152 | ||
|
|
f2d953ec31 | ||
|
|
9ffe333276 | ||
|
|
98522f63f4 | ||
|
|
5ff679b47d | ||
|
|
636ea3708c | ||
|
|
acd7fdc6d8 | ||
|
|
b8afb520e4 | ||
|
|
4ab9dab5b9 | ||
|
|
9ce10c0bdc | ||
|
|
da15ee5134 | ||
|
|
1dd3a44753 | ||
|
|
54db38a479 | ||
|
|
02eb19d0ec | ||
|
|
662deb908f | ||
|
|
f46fc4e6a9 | ||
|
|
df9ebea53e | ||
|
|
671c835b7d | ||
|
|
4b304cfae1 | ||
|
|
1194dcba22 | ||
|
|
170bf9315b | ||
|
|
f6c6afc1d4 | ||
|
|
d998e555d2 | ||
|
|
1976cccec8 | ||
|
|
50c5c4d125 | ||
|
|
20022fa15f | ||
|
|
ad5171dbd4 | ||
|
|
b36dc67b95 | ||
|
|
9d85d55732 | ||
|
|
2300aed15d | ||
|
|
e40cdb0e6e | ||
|
|
968fc24d84 | ||
|
|
423d00c857 | ||
|
|
ee25595f01 | ||
|
|
86e117724a | ||
|
|
d61ce900b9 | ||
|
|
1634df567d | ||
|
|
b321afbefd | ||
|
|
0374f5089a | ||
|
|
3bf16cb31a | ||
|
|
4bdd547aaa | ||
|
|
af9fe31070 | ||
|
|
1f91f39219 | ||
|
|
b672cf66c3 | ||
|
|
4c186ee2cf | ||
|
|
dcf91778ca | ||
|
|
06ef8604e9 | ||
|
|
39acc64741 | ||
|
|
e566be049a | ||
|
|
8f811b9a4a | ||
|
|
a9e05a1ceb | ||
|
|
0e154fe92c | ||
|
|
ef3765cb95 | ||
|
|
e8d8fef48f | ||
|
|
6580935246 | ||
|
|
76bff4f82f | ||
|
|
e20b8c04a3 | ||
|
|
8b0190bbde | ||
|
|
f477ed3c11 | ||
|
|
cd2754addc | ||
|
|
3d045dbca5 | ||
|
|
baee04abba | ||
|
|
b144be9e06 | ||
|
|
5e5863ecf1 | ||
|
|
9a734d64f9 | ||
|
|
9a8fa1bdad | ||
|
|
83ebb7cd01 | ||
|
|
42774a56ec | ||
|
|
958683482c | ||
|
|
cd2d46fd21 | ||
|
|
595b8fdd54 | ||
|
|
a4af30447b | ||
|
|
46010969f3 | ||
|
|
c67b67e511 | ||
|
|
1eaa1da7e4 | ||
|
|
8f56ced8aa | ||
|
|
89fe090bb3 | ||
|
|
6b88b37c0e | ||
|
|
075b8ddb9b | ||
|
|
de4d3555fa | ||
|
|
3bd67b7dab | ||
|
|
db4a16458c | ||
|
|
194cfb43d5 | ||
|
|
64f45e4991 | ||
|
|
5238c88657 | ||
|
|
67debe3ae5 |
@@ -310,13 +310,28 @@ static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds)
|
||||
|
||||
/* Called with iothread lock taken. */
|
||||
|
||||
static void set_dirty_tracking(void)
|
||||
static int set_dirty_tracking(void)
|
||||
{
|
||||
BlkMigDevState *bmds;
|
||||
int ret;
|
||||
|
||||
QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
|
||||
bmds->dirty_bitmap = bdrv_create_dirty_bitmap(bmds->bs, BLOCK_SIZE);
|
||||
bmds->dirty_bitmap = bdrv_create_dirty_bitmap(bmds->bs, BLOCK_SIZE,
|
||||
NULL);
|
||||
if (!bmds->dirty_bitmap) {
|
||||
ret = -errno;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
|
||||
if (bmds->dirty_bitmap) {
|
||||
bdrv_release_dirty_bitmap(bmds->bs, bmds->dirty_bitmap);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void unset_dirty_tracking(void)
|
||||
@@ -611,10 +626,17 @@ static int block_save_setup(QEMUFile *f, void *opaque)
|
||||
block_mig_state.submitted, block_mig_state.transferred);
|
||||
|
||||
qemu_mutex_lock_iothread();
|
||||
init_blk_migration(f);
|
||||
|
||||
/* start track dirty blocks */
|
||||
set_dirty_tracking();
|
||||
ret = set_dirty_tracking();
|
||||
|
||||
if (ret) {
|
||||
qemu_mutex_unlock_iothread();
|
||||
return ret;
|
||||
}
|
||||
|
||||
init_blk_migration(f);
|
||||
|
||||
qemu_mutex_unlock_iothread();
|
||||
|
||||
ret = flush_blks(f);
|
||||
|
||||
69
block.c
69
block.c
@@ -332,10 +332,21 @@ void bdrv_register(BlockDriver *bdrv)
|
||||
}
|
||||
|
||||
/* create a new block device (by default it is empty) */
|
||||
BlockDriverState *bdrv_new(const char *device_name)
|
||||
BlockDriverState *bdrv_new(const char *device_name, Error **errp)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
|
||||
if (bdrv_find(device_name)) {
|
||||
error_setg(errp, "Device with id '%s' already exists",
|
||||
device_name);
|
||||
return NULL;
|
||||
}
|
||||
if (bdrv_find_node(device_name)) {
|
||||
error_setg(errp, "Device with node-name '%s' already exists",
|
||||
device_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bs = g_malloc0(sizeof(BlockDriverState));
|
||||
QLIST_INIT(&bs->dirty_bitmaps);
|
||||
pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
|
||||
@@ -788,38 +799,36 @@ static int bdrv_open_flags(BlockDriverState *bs, int flags)
|
||||
return open_flags;
|
||||
}
|
||||
|
||||
static int bdrv_assign_node_name(BlockDriverState *bs,
|
||||
const char *node_name,
|
||||
Error **errp)
|
||||
static void bdrv_assign_node_name(BlockDriverState *bs,
|
||||
const char *node_name,
|
||||
Error **errp)
|
||||
{
|
||||
if (!node_name) {
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* empty string node name is invalid */
|
||||
if (node_name[0] == '\0') {
|
||||
error_setg(errp, "Empty node name");
|
||||
return -EINVAL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* takes care of avoiding namespaces collisions */
|
||||
if (bdrv_find(node_name)) {
|
||||
error_setg(errp, "node-name=%s is conflicting with a device id",
|
||||
node_name);
|
||||
return -EINVAL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* takes care of avoiding duplicates node names */
|
||||
if (bdrv_find_node(node_name)) {
|
||||
error_setg(errp, "Duplicate node name");
|
||||
return -EINVAL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* copy node name into the bs and insert it into the graph list */
|
||||
pstrcpy(bs->node_name, sizeof(bs->node_name), node_name);
|
||||
QTAILQ_INSERT_TAIL(&graph_bdrv_states, bs, node_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -854,9 +863,10 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
|
||||
trace_bdrv_open_common(bs, filename ?: "", flags, drv->format_name);
|
||||
|
||||
node_name = qdict_get_try_str(options, "node-name");
|
||||
ret = bdrv_assign_node_name(bs, node_name, errp);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
bdrv_assign_node_name(bs, node_name, &local_err);
|
||||
if (error_is_set(&local_err)) {
|
||||
error_propagate(errp, local_err);
|
||||
return -EINVAL;
|
||||
}
|
||||
qdict_del(options, "node-name");
|
||||
|
||||
@@ -1221,7 +1231,7 @@ void bdrv_append_temp_snapshot(BlockDriverState *bs, Error **errp)
|
||||
qdict_put(snapshot_options, "file.filename",
|
||||
qstring_from_str(tmp_filename));
|
||||
|
||||
bs_snapshot = bdrv_new("");
|
||||
bs_snapshot = bdrv_new("", &error_abort);
|
||||
bs_snapshot->is_temporary = 1;
|
||||
|
||||
ret = bdrv_open(&bs_snapshot, NULL, NULL, snapshot_options,
|
||||
@@ -1288,7 +1298,7 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
|
||||
if (*pbs) {
|
||||
bs = *pbs;
|
||||
} else {
|
||||
bs = bdrv_new("");
|
||||
bs = bdrv_new("", &error_abort);
|
||||
}
|
||||
|
||||
/* NULL means an empty set of options */
|
||||
@@ -2581,6 +2591,10 @@ static int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset,
|
||||
{
|
||||
int64_t len;
|
||||
|
||||
if (size > INT_MAX) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (!bdrv_is_inserted(bs))
|
||||
return -ENOMEDIUM;
|
||||
|
||||
@@ -2601,7 +2615,7 @@ static int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset,
|
||||
static int bdrv_check_request(BlockDriverState *bs, int64_t sector_num,
|
||||
int nb_sectors)
|
||||
{
|
||||
if (nb_sectors > INT_MAX / BDRV_SECTOR_SIZE) {
|
||||
if (nb_sectors < 0 || nb_sectors > INT_MAX / BDRV_SECTOR_SIZE) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@@ -2686,6 +2700,10 @@ static int bdrv_rw_co(BlockDriverState *bs, int64_t sector_num, uint8_t *buf,
|
||||
.iov_len = nb_sectors * BDRV_SECTOR_SIZE,
|
||||
};
|
||||
|
||||
if (nb_sectors < 0 || nb_sectors > INT_MAX / BDRV_SECTOR_SIZE) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
qemu_iovec_init_external(&qiov, &iov, 1);
|
||||
return bdrv_prwv_co(bs, sector_num << BDRV_SECTOR_BITS,
|
||||
&qiov, is_write, flags);
|
||||
@@ -2741,10 +2759,16 @@ int bdrv_write_zeroes(BlockDriverState *bs, int64_t sector_num,
|
||||
*/
|
||||
int bdrv_make_zero(BlockDriverState *bs, BdrvRequestFlags flags)
|
||||
{
|
||||
int64_t target_size = bdrv_getlength(bs) / BDRV_SECTOR_SIZE;
|
||||
int64_t target_size;
|
||||
int64_t ret, nb_sectors, sector_num = 0;
|
||||
int n;
|
||||
|
||||
target_size = bdrv_getlength(bs);
|
||||
if (target_size < 0) {
|
||||
return target_size;
|
||||
}
|
||||
target_size /= BDRV_SECTOR_SIZE;
|
||||
|
||||
for (;;) {
|
||||
nb_sectors = target_size - sector_num;
|
||||
if (nb_sectors <= 0) {
|
||||
@@ -5096,7 +5120,8 @@ bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov)
|
||||
return true;
|
||||
}
|
||||
|
||||
BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, int granularity)
|
||||
BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, int granularity,
|
||||
Error **errp)
|
||||
{
|
||||
int64_t bitmap_size;
|
||||
BdrvDirtyBitmap *bitmap;
|
||||
@@ -5105,7 +5130,13 @@ BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, int granularity)
|
||||
|
||||
granularity >>= BDRV_SECTOR_BITS;
|
||||
assert(granularity);
|
||||
bitmap_size = (bdrv_getlength(bs) >> BDRV_SECTOR_BITS);
|
||||
bitmap_size = bdrv_getlength(bs);
|
||||
if (bitmap_size < 0) {
|
||||
error_setg_errno(errp, -bitmap_size, "could not get length of device");
|
||||
errno = -bitmap_size;
|
||||
return NULL;
|
||||
}
|
||||
bitmap_size >>= BDRV_SECTOR_BITS;
|
||||
bitmap = g_malloc0(sizeof(BdrvDirtyBitmap));
|
||||
bitmap->bitmap = hbitmap_alloc(bitmap_size, ffs(granularity) - 1);
|
||||
QLIST_INSERT_HEAD(&bs->dirty_bitmaps, bitmap, list);
|
||||
|
||||
@@ -72,7 +72,7 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
}
|
||||
s->block_size = be32_to_cpu(s->block_size);
|
||||
if (s->block_size % 512) {
|
||||
error_setg(errp, "block_size %u must be a multiple of 512",
|
||||
error_setg(errp, "block_size %" PRIu32 " must be a multiple of 512",
|
||||
s->block_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -86,7 +86,7 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
* need a buffer this big.
|
||||
*/
|
||||
if (s->block_size > MAX_BLOCK_SIZE) {
|
||||
error_setg(errp, "block_size %u must be %u MB or less",
|
||||
error_setg(errp, "block_size %" PRIu32 " must be %u MB or less",
|
||||
s->block_size,
|
||||
MAX_BLOCK_SIZE / (1024 * 1024));
|
||||
return -EINVAL;
|
||||
@@ -101,7 +101,7 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
/* read offsets */
|
||||
if (s->n_blocks > (UINT32_MAX - 1) / sizeof(uint64_t)) {
|
||||
/* Prevent integer overflow */
|
||||
error_setg(errp, "n_blocks %u must be %zu or less",
|
||||
error_setg(errp, "n_blocks %" PRIu32 " must be %zu or less",
|
||||
s->n_blocks,
|
||||
(UINT32_MAX - 1) / sizeof(uint64_t));
|
||||
return -EINVAL;
|
||||
@@ -133,7 +133,7 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
|
||||
if (s->offsets[i] < s->offsets[i - 1]) {
|
||||
error_setg(errp, "offsets not monotonically increasing at "
|
||||
"index %u, image file is corrupt", i);
|
||||
"index %" PRIu32 ", image file is corrupt", i);
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
@@ -146,8 +146,8 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
* ridiculous s->compressed_block allocation.
|
||||
*/
|
||||
if (size > 2 * MAX_BLOCK_SIZE) {
|
||||
error_setg(errp, "invalid compressed block size at index %u, "
|
||||
"image file is corrupt", i);
|
||||
error_setg(errp, "invalid compressed block size at index %" PRIu32
|
||||
", image file is corrupt", i);
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -543,7 +543,7 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
return 0;
|
||||
|
||||
out:
|
||||
fprintf(stderr, "CURL: Error opening file: %s\n", state->errmsg);
|
||||
error_setg(errp, "CURL: Error opening file: %s", state->errmsg);
|
||||
curl_easy_cleanup(state->curl);
|
||||
state->curl = NULL;
|
||||
out_noclean:
|
||||
|
||||
@@ -1401,7 +1401,7 @@ static int iscsi_create(const char *filename, QEMUOptionParameter *options,
|
||||
IscsiLun *iscsilun = NULL;
|
||||
QDict *bs_options;
|
||||
|
||||
bs = bdrv_new("");
|
||||
bs = bdrv_new("", &error_abort);
|
||||
|
||||
/* Read out options */
|
||||
while (options && options->name) {
|
||||
|
||||
@@ -605,7 +605,10 @@ static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target,
|
||||
s->granularity = granularity;
|
||||
s->buf_size = MAX(buf_size, granularity);
|
||||
|
||||
s->dirty_bitmap = bdrv_create_dirty_bitmap(bs, granularity);
|
||||
s->dirty_bitmap = bdrv_create_dirty_bitmap(bs, granularity, errp);
|
||||
if (!s->dirty_bitmap) {
|
||||
return;
|
||||
}
|
||||
bdrv_set_enable_write_cache(s->target, true);
|
||||
bdrv_set_on_error(s->target, on_target_error, on_target_error);
|
||||
bdrv_iostatus_enable(s->target);
|
||||
|
||||
16
block/qed.c
16
block/qed.c
@@ -650,19 +650,21 @@ static int bdrv_qed_create(const char *filename, QEMUOptionParameter *options,
|
||||
}
|
||||
|
||||
if (!qed_is_cluster_size_valid(cluster_size)) {
|
||||
fprintf(stderr, "QED cluster size must be within range [%u, %u] and power of 2\n",
|
||||
QED_MIN_CLUSTER_SIZE, QED_MAX_CLUSTER_SIZE);
|
||||
error_setg(errp, "QED cluster size must be within range [%u, %u] "
|
||||
"and power of 2",
|
||||
QED_MIN_CLUSTER_SIZE, QED_MAX_CLUSTER_SIZE);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!qed_is_table_size_valid(table_size)) {
|
||||
fprintf(stderr, "QED table size must be within range [%u, %u] and power of 2\n",
|
||||
QED_MIN_TABLE_SIZE, QED_MAX_TABLE_SIZE);
|
||||
error_setg(errp, "QED table size must be within range [%u, %u] "
|
||||
"and power of 2",
|
||||
QED_MIN_TABLE_SIZE, QED_MAX_TABLE_SIZE);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!qed_is_image_size_valid(image_size, cluster_size, table_size)) {
|
||||
fprintf(stderr, "QED image size must be a non-zero multiple of "
|
||||
"cluster size and less than %" PRIu64 " bytes\n",
|
||||
qed_max_image_size(cluster_size, table_size));
|
||||
error_setg(errp, "QED image size must be a non-zero multiple of "
|
||||
"cluster size and less than %" PRIu64 " bytes",
|
||||
qed_max_image_size(cluster_size, table_size));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
23
block/vmdk.c
23
block/vmdk.c
@@ -262,7 +262,7 @@ static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent)
|
||||
p_name = strstr(desc, cid_str);
|
||||
if (p_name != NULL) {
|
||||
p_name += cid_str_size;
|
||||
sscanf(p_name, "%x", &cid);
|
||||
sscanf(p_name, "%" SCNx32, &cid);
|
||||
}
|
||||
|
||||
return cid;
|
||||
@@ -290,7 +290,7 @@ static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid)
|
||||
p_name = strstr(desc, "CID");
|
||||
if (p_name != NULL) {
|
||||
p_name += sizeof("CID");
|
||||
snprintf(p_name, sizeof(desc) - (p_name - desc), "%x\n", cid);
|
||||
snprintf(p_name, sizeof(desc) - (p_name - desc), "%" PRIx32 "\n", cid);
|
||||
pstrcat(desc, sizeof(desc), tmp_desc);
|
||||
}
|
||||
|
||||
@@ -640,7 +640,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
|
||||
|
||||
if (le32_to_cpu(header.version) > 3) {
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof(buf), "VMDK version %d",
|
||||
snprintf(buf, sizeof(buf), "VMDK version %" PRId32,
|
||||
le32_to_cpu(header.version));
|
||||
error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
|
||||
bs->device_name, "vmdk", buf);
|
||||
@@ -671,8 +671,9 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
|
||||
}
|
||||
if (bdrv_getlength(file) <
|
||||
le64_to_cpu(header.grain_offset) * BDRV_SECTOR_SIZE) {
|
||||
error_setg(errp, "File truncated, expecting at least %lld bytes",
|
||||
le64_to_cpu(header.grain_offset) * BDRV_SECTOR_SIZE);
|
||||
error_setg(errp, "File truncated, expecting at least %" PRId64 " bytes",
|
||||
(int64_t)(le64_to_cpu(header.grain_offset)
|
||||
* BDRV_SECTOR_SIZE));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -1707,8 +1708,8 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
|
||||
const char desc_template[] =
|
||||
"# Disk DescriptorFile\n"
|
||||
"version=1\n"
|
||||
"CID=%x\n"
|
||||
"parentCID=%x\n"
|
||||
"CID=%" PRIx32 "\n"
|
||||
"parentCID=%" PRIx32 "\n"
|
||||
"createType=\"%s\"\n"
|
||||
"%s"
|
||||
"\n"
|
||||
@@ -1720,7 +1721,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
|
||||
"\n"
|
||||
"ddb.virtualHWVersion = \"%d\"\n"
|
||||
"ddb.geometry.cylinders = \"%" PRId64 "\"\n"
|
||||
"ddb.geometry.heads = \"%d\"\n"
|
||||
"ddb.geometry.heads = \"%" PRIu32 "\"\n"
|
||||
"ddb.geometry.sectors = \"63\"\n"
|
||||
"ddb.adapterType = \"%s\"\n";
|
||||
|
||||
@@ -1780,9 +1781,9 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
|
||||
strcmp(fmt, "twoGbMaxExtentFlat"));
|
||||
compress = !strcmp(fmt, "streamOptimized");
|
||||
if (flat) {
|
||||
desc_extent_line = "RW %lld FLAT \"%s\" 0\n";
|
||||
desc_extent_line = "RW %" PRId64 " FLAT \"%s\" 0\n";
|
||||
} else {
|
||||
desc_extent_line = "RW %lld SPARSE \"%s\"\n";
|
||||
desc_extent_line = "RW %" PRId64 " SPARSE \"%s\"\n";
|
||||
}
|
||||
if (flat && backing_file) {
|
||||
error_setg(errp, "Flat image can't have backing file");
|
||||
@@ -1850,7 +1851,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
|
||||
}
|
||||
/* generate descriptor file */
|
||||
desc = g_strdup_printf(desc_template,
|
||||
(unsigned int)time(NULL),
|
||||
(uint32_t)time(NULL),
|
||||
parent_cid,
|
||||
fmt,
|
||||
parent_desc_line,
|
||||
|
||||
@@ -2947,7 +2947,7 @@ static int enable_write_target(BDRVVVFATState *s)
|
||||
unlink(s->qcow_filename);
|
||||
#endif
|
||||
|
||||
s->bs->backing_hd = bdrv_new("");
|
||||
s->bs->backing_hd = bdrv_new("", &error_abort);
|
||||
s->bs->backing_hd->drv = &vvfat_write_target;
|
||||
s->bs->backing_hd->opaque = g_malloc(sizeof(void*));
|
||||
*(void**)s->bs->backing_hd->opaque = s;
|
||||
|
||||
15
blockdev.c
15
blockdev.c
@@ -452,16 +452,14 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
|
||||
}
|
||||
}
|
||||
|
||||
if (bdrv_find_node(qemu_opts_id(opts))) {
|
||||
error_setg(errp, "device id=%s is conflicting with a node-name",
|
||||
qemu_opts_id(opts));
|
||||
goto early_err;
|
||||
}
|
||||
|
||||
/* init */
|
||||
dinfo = g_malloc0(sizeof(*dinfo));
|
||||
dinfo->id = g_strdup(qemu_opts_id(opts));
|
||||
dinfo->bdrv = bdrv_new(dinfo->id);
|
||||
dinfo->bdrv = bdrv_new(dinfo->id, &error);
|
||||
if (error) {
|
||||
error_propagate(errp, error);
|
||||
goto bdrv_new_err;
|
||||
}
|
||||
dinfo->bdrv->open_flags = snapshot ? BDRV_O_SNAPSHOT : 0;
|
||||
dinfo->bdrv->read_only = ro;
|
||||
dinfo->refcount = 1;
|
||||
@@ -523,8 +521,9 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
|
||||
|
||||
err:
|
||||
bdrv_unref(dinfo->bdrv);
|
||||
g_free(dinfo->id);
|
||||
QTAILQ_REMOVE(&drives, dinfo, next);
|
||||
bdrv_new_err:
|
||||
g_free(dinfo->id);
|
||||
g_free(dinfo);
|
||||
early_err:
|
||||
QDECREF(bs_opts);
|
||||
|
||||
5
configure
vendored
5
configure
vendored
@@ -1217,8 +1217,8 @@ Advanced options (experts only):
|
||||
--enable-modules enable modules support
|
||||
--enable-debug-tcg enable TCG debugging
|
||||
--disable-debug-tcg disable TCG debugging (default)
|
||||
--enable-debug-info enable debugging information (default)
|
||||
--disable-debug-info disable debugging information
|
||||
--enable-debug-info enable debugging information (default)
|
||||
--disable-debug-info disable debugging information
|
||||
--enable-debug enable common debug build options
|
||||
--enable-sparse enable sparse checker
|
||||
--disable-sparse disable sparse checker (default)
|
||||
@@ -4095,7 +4095,6 @@ echo "sparse enabled $sparse"
|
||||
echo "strip binaries $strip_opt"
|
||||
echo "profiler $profiler"
|
||||
echo "static build $static"
|
||||
echo "-Werror enabled $werror"
|
||||
if test "$darwin" = "yes" ; then
|
||||
echo "Cocoa support $cocoa"
|
||||
fi
|
||||
|
||||
@@ -5,9 +5,10 @@ QEMU Standard VGA
|
||||
Exists in two variants, for isa and pci.
|
||||
|
||||
command line switches:
|
||||
-vga std [ picks isa for -M isapc, otherwise pci ]
|
||||
-device VGA [ pci variant ]
|
||||
-device isa-vga [ isa variant ]
|
||||
-vga std [ picks isa for -M isapc, otherwise pci ]
|
||||
-device VGA [ pci variant ]
|
||||
-device isa-vga [ isa variant ]
|
||||
-device secondary-vga [ legacy-free pci variant ]
|
||||
|
||||
|
||||
PCI spec
|
||||
@@ -31,9 +32,15 @@ PCI ROM Region:
|
||||
Holds the vgabios (qemu 0.14+).
|
||||
|
||||
|
||||
The legacy-free variant has no ROM and has PCI_CLASS_DISPLAY_OTHER
|
||||
instead of PCI_CLASS_DISPLAY_VGA.
|
||||
|
||||
|
||||
IO ports used
|
||||
-------------
|
||||
|
||||
Doesn't apply to the legacy-free pci variant, use the MMIO bar instead.
|
||||
|
||||
03c0 - 03df : standard vga ports
|
||||
01ce : bochs vbe interface index port
|
||||
01cf : bochs vbe interface data port (x86 only)
|
||||
|
||||
@@ -817,11 +817,14 @@ static int blk_connect(struct XenDevice *xendev)
|
||||
index = (blkdev->xendev.dev - 202 * 256) / 16;
|
||||
blkdev->dinfo = drive_get(IF_XEN, 0, index);
|
||||
if (!blkdev->dinfo) {
|
||||
Error *local_err = NULL;
|
||||
/* setup via xenbus -> create new block driver instance */
|
||||
xen_be_printf(&blkdev->xendev, 2, "create new bdrv (xenbus setup)\n");
|
||||
blkdev->bs = bdrv_new(blkdev->dev);
|
||||
blkdev->bs = bdrv_new(blkdev->dev, &local_err);
|
||||
if (local_err) {
|
||||
blkdev->bs = NULL;
|
||||
}
|
||||
if (blkdev->bs) {
|
||||
Error *local_err = NULL;
|
||||
BlockDriver *drv = bdrv_find_whitelisted_format(blkdev->fileproto,
|
||||
readonly);
|
||||
if (bdrv_open(&blkdev->bs, blkdev->filename, NULL, NULL, qflags,
|
||||
|
||||
@@ -2913,7 +2913,7 @@ static void isa_cirrus_vga_realizefn(DeviceState *dev, Error **errp)
|
||||
ISACirrusVGAState *d = ISA_CIRRUS_VGA(dev);
|
||||
VGACommonState *s = &d->cirrus_vga.vga;
|
||||
|
||||
vga_common_init(s, OBJECT(dev));
|
||||
vga_common_init(s, OBJECT(dev), true);
|
||||
cirrus_init_common(&d->cirrus_vga, OBJECT(dev), CIRRUS_ID_CLGD5430, 0,
|
||||
isa_address_space(isadev),
|
||||
isa_address_space_io(isadev));
|
||||
@@ -2960,7 +2960,7 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
|
||||
int16_t device_id = pc->device_id;
|
||||
|
||||
/* setup VGA */
|
||||
vga_common_init(&s->vga, OBJECT(dev));
|
||||
vga_common_init(&s->vga, OBJECT(dev), true);
|
||||
cirrus_init_common(s, OBJECT(dev), device_id, 1, pci_address_space(dev),
|
||||
pci_address_space_io(dev));
|
||||
s->vga.con = graphic_console_init(DEVICE(dev), 0, s->vga.hw_ops, &s->vga);
|
||||
|
||||
@@ -2061,7 +2061,7 @@ static int qxl_init_primary(PCIDevice *dev)
|
||||
qxl->id = 0;
|
||||
qxl_init_ramsize(qxl);
|
||||
vga->vram_size_mb = qxl->vga.vram_size >> 20;
|
||||
vga_common_init(vga, OBJECT(dev));
|
||||
vga_common_init(vga, OBJECT(dev), true);
|
||||
vga_init(vga, OBJECT(dev),
|
||||
pci_address_space(dev), pci_address_space_io(dev), false);
|
||||
portio_list_init(qxl_vga_port_list, OBJECT(dev), qxl_vga_portio_list,
|
||||
|
||||
@@ -132,7 +132,7 @@ int isa_vga_mm_init(hwaddr vram_base,
|
||||
s = g_malloc0(sizeof(*s));
|
||||
|
||||
s->vga.vram_size_mb = VGA_RAM_SIZE >> 20;
|
||||
vga_common_init(&s->vga, NULL);
|
||||
vga_common_init(&s->vga, NULL, true);
|
||||
vga_mm_init(s, vram_base, ctrl_base, it_shift, address_space);
|
||||
|
||||
s->vga.con = graphic_console_init(NULL, 0, s->vga.hw_ops, s);
|
||||
|
||||
@@ -56,7 +56,7 @@ static void vga_isa_realizefn(DeviceState *dev, Error **errp)
|
||||
MemoryRegion *vga_io_memory;
|
||||
const MemoryRegionPortio *vga_ports, *vbe_ports;
|
||||
|
||||
vga_common_init(s, OBJECT(dev));
|
||||
vga_common_init(s, OBJECT(dev), true);
|
||||
s->legacy_address_space = isa_address_space(isadev);
|
||||
vga_io_memory = vga_init_io(s, OBJECT(dev), &vga_ports, &vbe_ports);
|
||||
isa_register_portio_list(isadev, 0x3b0, vga_ports, s, "vga");
|
||||
|
||||
@@ -147,7 +147,7 @@ static int pci_std_vga_initfn(PCIDevice *dev)
|
||||
VGACommonState *s = &d->vga;
|
||||
|
||||
/* vga + console init */
|
||||
vga_common_init(s, OBJECT(dev));
|
||||
vga_common_init(s, OBJECT(dev), true);
|
||||
vga_init(s, OBJECT(dev), pci_address_space(dev), pci_address_space_io(dev),
|
||||
true);
|
||||
|
||||
@@ -179,12 +179,51 @@ static int pci_std_vga_initfn(PCIDevice *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pci_secondary_vga_initfn(PCIDevice *dev)
|
||||
{
|
||||
PCIVGAState *d = DO_UPCAST(PCIVGAState, dev, dev);
|
||||
VGACommonState *s = &d->vga;
|
||||
|
||||
/* vga + console init */
|
||||
vga_common_init(s, OBJECT(dev), false);
|
||||
s->con = graphic_console_init(DEVICE(dev), 0, s->hw_ops, s);
|
||||
|
||||
/* mmio bar */
|
||||
memory_region_init(&d->mmio, OBJECT(dev), "vga.mmio", 4096);
|
||||
memory_region_init_io(&d->ioport, OBJECT(dev), &pci_vga_ioport_ops, d,
|
||||
"vga ioports remapped", PCI_VGA_IOPORT_SIZE);
|
||||
memory_region_init_io(&d->bochs, OBJECT(dev), &pci_vga_bochs_ops, d,
|
||||
"bochs dispi interface", PCI_VGA_BOCHS_SIZE);
|
||||
|
||||
memory_region_add_subregion(&d->mmio, PCI_VGA_IOPORT_OFFSET,
|
||||
&d->ioport);
|
||||
memory_region_add_subregion(&d->mmio, PCI_VGA_BOCHS_OFFSET,
|
||||
&d->bochs);
|
||||
|
||||
pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram);
|
||||
pci_register_bar(&d->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pci_secondary_vga_reset(DeviceState *dev)
|
||||
{
|
||||
PCIVGAState *d = DO_UPCAST(PCIVGAState, dev.qdev, dev);
|
||||
|
||||
vga_common_reset(&d->vga);
|
||||
}
|
||||
|
||||
static Property vga_pci_properties[] = {
|
||||
DEFINE_PROP_UINT32("vgamem_mb", PCIVGAState, vga.vram_size_mb, 16),
|
||||
DEFINE_PROP_BIT("mmio", PCIVGAState, flags, PCI_VGA_FLAG_ENABLE_MMIO, true),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static Property secondary_pci_properties[] = {
|
||||
DEFINE_PROP_UINT32("vgamem_mb", PCIVGAState, vga.vram_size_mb, 16),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void vga_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
@@ -201,6 +240,20 @@ static void vga_class_init(ObjectClass *klass, void *data)
|
||||
set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
|
||||
}
|
||||
|
||||
static void secondary_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
||||
|
||||
k->init = pci_secondary_vga_initfn;
|
||||
k->vendor_id = PCI_VENDOR_ID_QEMU;
|
||||
k->device_id = PCI_DEVICE_ID_QEMU_VGA;
|
||||
k->class_id = PCI_CLASS_DISPLAY_OTHER;
|
||||
dc->vmsd = &vmstate_vga_pci;
|
||||
dc->props = secondary_pci_properties;
|
||||
dc->reset = pci_secondary_vga_reset;
|
||||
}
|
||||
|
||||
static const TypeInfo vga_info = {
|
||||
.name = "VGA",
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
@@ -208,9 +261,17 @@ static const TypeInfo vga_info = {
|
||||
.class_init = vga_class_init,
|
||||
};
|
||||
|
||||
static const TypeInfo secondary_info = {
|
||||
.name = "secondary-vga",
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(PCIVGAState),
|
||||
.class_init = secondary_class_init,
|
||||
};
|
||||
|
||||
static void vga_register_types(void)
|
||||
{
|
||||
type_register_static(&vga_info);
|
||||
type_register_static(&secondary_info);
|
||||
}
|
||||
|
||||
type_init(vga_register_types)
|
||||
|
||||
@@ -171,6 +171,10 @@ static void vga_update_memory_access(VGACommonState *s)
|
||||
MemoryRegion *region, *old_region = s->chain4_alias;
|
||||
hwaddr base, offset, size;
|
||||
|
||||
if (s->legacy_address_space == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
s->chain4_alias = NULL;
|
||||
|
||||
if ((s->sr[VGA_SEQ_PLANE_WRITE] & VGA_SR02_ALL_PLANES) ==
|
||||
@@ -2252,7 +2256,7 @@ static const GraphicHwOps vga_ops = {
|
||||
.text_update = vga_update_text,
|
||||
};
|
||||
|
||||
void vga_common_init(VGACommonState *s, Object *obj)
|
||||
void vga_common_init(VGACommonState *s, Object *obj, bool global_vmstate)
|
||||
{
|
||||
int i, j, v, b;
|
||||
|
||||
@@ -2289,7 +2293,7 @@ void vga_common_init(VGACommonState *s, Object *obj)
|
||||
|
||||
s->is_vbe_vmstate = 1;
|
||||
memory_region_init_ram(&s->vram, obj, "vga.vram", s->vram_size);
|
||||
vmstate_register_ram_global(&s->vram);
|
||||
vmstate_register_ram(&s->vram, global_vmstate ? NULL : DEVICE(obj));
|
||||
xen_register_framebuffer(&s->vram);
|
||||
s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
|
||||
s->get_bpp = vga_get_bpp;
|
||||
|
||||
@@ -177,7 +177,7 @@ static inline int c6_to_8(int v)
|
||||
return (v << 2) | (b << 1) | b;
|
||||
}
|
||||
|
||||
void vga_common_init(VGACommonState *s, Object *obj);
|
||||
void vga_common_init(VGACommonState *s, Object *obj, bool global_vmstate);
|
||||
void vga_init(VGACommonState *s, Object *obj, MemoryRegion *address_space,
|
||||
MemoryRegion *address_space_io, bool init_vga_ports);
|
||||
MemoryRegion *vga_init_io(VGACommonState *s, Object *obj,
|
||||
|
||||
@@ -1207,7 +1207,7 @@ static void vmsvga_init(DeviceState *dev, struct vmsvga_state_s *s,
|
||||
vmstate_register_ram_global(&s->fifo_ram);
|
||||
s->fifo_ptr = memory_region_get_ram_ptr(&s->fifo_ram);
|
||||
|
||||
vga_common_init(&s->vga, OBJECT(dev));
|
||||
vga_common_init(&s->vga, OBJECT(dev), true);
|
||||
vga_init(&s->vga, OBJECT(dev), address_space, io, true);
|
||||
vmstate_register(NULL, 0, &vmstate_vga_common, &s->vga);
|
||||
s->new_depth = 32;
|
||||
|
||||
@@ -71,7 +71,7 @@ static void eeprom_write_data(SMBusDevice *dev, uint8_t cmd, uint8_t *buf, int l
|
||||
printf("eeprom_write_byte: addr=0x%02x cmd=0x%02x val=0x%02x\n",
|
||||
dev->i2c.address, cmd, buf[0]);
|
||||
#endif
|
||||
/* An page write operation is not a valid SMBus command.
|
||||
/* A page write operation is not a valid SMBus command.
|
||||
It is a block write without a length byte. Fortunately we
|
||||
get the full block anyway. */
|
||||
/* TODO: Should this set the current location? */
|
||||
|
||||
@@ -438,9 +438,9 @@ static void check_cmd(AHCIState *s, int port)
|
||||
|
||||
if ((pr->cmd & PORT_CMD_START) && pr->cmd_issue) {
|
||||
for (slot = 0; (slot < 32) && pr->cmd_issue; slot++) {
|
||||
if ((pr->cmd_issue & (1 << slot)) &&
|
||||
if ((pr->cmd_issue & (1U << slot)) &&
|
||||
!handle_cmd(s, port, slot)) {
|
||||
pr->cmd_issue &= ~(1 << slot);
|
||||
pr->cmd_issue &= ~(1U << slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,7 +180,7 @@ int bdrv_create(BlockDriver *drv, const char* filename,
|
||||
QEMUOptionParameter *options, Error **errp);
|
||||
int bdrv_create_file(const char* filename, QEMUOptionParameter *options,
|
||||
Error **errp);
|
||||
BlockDriverState *bdrv_new(const char *device_name);
|
||||
BlockDriverState *bdrv_new(const char *device_name, Error **errp);
|
||||
void bdrv_make_anon(BlockDriverState *bs);
|
||||
void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old);
|
||||
void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top);
|
||||
@@ -429,7 +429,8 @@ bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov);
|
||||
|
||||
struct HBitmapIter;
|
||||
typedef struct BdrvDirtyBitmap BdrvDirtyBitmap;
|
||||
BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, int granularity);
|
||||
BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, int granularity,
|
||||
Error **errp);
|
||||
void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap);
|
||||
BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs);
|
||||
int bdrv_get_dirty(BlockDriverState *bs, BdrvDirtyBitmap *bitmap, int64_t sector);
|
||||
|
||||
@@ -53,7 +53,7 @@ static inline Int128 int128_rshift(Int128 a, int n)
|
||||
if (n >= 64) {
|
||||
return (Int128) { h, h >> 63 };
|
||||
} else {
|
||||
return (Int128) { (a.lo >> n) | (a.hi << (64 - n)), h };
|
||||
return (Int128) { (a.lo >> n) | ((uint64_t)a.hi << (64 - n)), h };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ static inline Int128 int128_neg(Int128 a)
|
||||
|
||||
static inline Int128 int128_sub(Int128 a, Int128 b)
|
||||
{
|
||||
return (Int128){ a.lo - b.lo, a.hi - b.hi - (a.lo < b.lo) };
|
||||
return (Int128){ a.lo - b.lo, (uint64_t)a.hi - b.hi - (a.lo < b.lo) };
|
||||
}
|
||||
|
||||
static inline bool int128_nonneg(Int128 a)
|
||||
|
||||
@@ -952,10 +952,12 @@ void net_host_device_remove(Monitor *mon, const QDict *qdict)
|
||||
|
||||
nc = net_hub_find_client_by_name(vlan_id, device);
|
||||
if (!nc) {
|
||||
error_report("Host network device '%s' on hub '%d' not found",
|
||||
device, vlan_id);
|
||||
return;
|
||||
}
|
||||
if (!net_host_check_device(nc->model)) {
|
||||
monitor_printf(mon, "invalid host network device %s\n", device);
|
||||
error_report("invalid host network device '%s'", device);
|
||||
return;
|
||||
}
|
||||
qemu_del_net_client(nc);
|
||||
|
||||
@@ -823,7 +823,7 @@ In this case, the block device must be exported using qemu-nbd:
|
||||
qemu-nbd --socket=/tmp/my_socket my_disk.qcow2
|
||||
@end example
|
||||
|
||||
The use of qemu-nbd allows to share a disk between several guests:
|
||||
The use of qemu-nbd allows sharing of a disk between several guests:
|
||||
@example
|
||||
qemu-nbd --socket=/tmp/my_socket --share=2 my_disk.qcow2
|
||||
@end example
|
||||
|
||||
116
qemu-img.c
116
qemu-img.c
@@ -57,8 +57,22 @@ static void format_print(void *opaque, const char *name)
|
||||
printf(" %s", name);
|
||||
}
|
||||
|
||||
static void QEMU_NORETURN GCC_FMT_ATTR(1, 2) error_exit(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
error_printf("qemu-img: ");
|
||||
|
||||
va_start(ap, fmt);
|
||||
error_vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
error_printf("\nTry 'qemu-img --help' for more information\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Please keep in synch with qemu-img.texi */
|
||||
static void help(void)
|
||||
static void QEMU_NORETURN help(void)
|
||||
{
|
||||
const char *help_msg =
|
||||
"qemu-img version " QEMU_VERSION ", Copyright (c) 2004-2008 Fabrice Bellard\n"
|
||||
@@ -129,7 +143,7 @@ static void help(void)
|
||||
printf("%s\nSupported formats:", help_msg);
|
||||
bdrv_iterate_format(format_print, NULL);
|
||||
printf("\n");
|
||||
exit(1);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
static int GCC_FMT_ATTR(2, 3) qprintf(bool quiet, const char *fmt, ...)
|
||||
@@ -262,7 +276,8 @@ static int print_block_option_help(const char *filename, const char *fmt)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BlockDriverState *bdrv_new_open(const char *filename,
|
||||
static BlockDriverState *bdrv_new_open(const char *id,
|
||||
const char *filename,
|
||||
const char *fmt,
|
||||
int flags,
|
||||
bool require_io,
|
||||
@@ -274,7 +289,7 @@ static BlockDriverState *bdrv_new_open(const char *filename,
|
||||
Error *local_err = NULL;
|
||||
int ret;
|
||||
|
||||
bs = bdrv_new("image");
|
||||
bs = bdrv_new(id, &error_abort);
|
||||
|
||||
if (fmt) {
|
||||
drv = bdrv_find_format(fmt);
|
||||
@@ -398,7 +413,7 @@ static int img_create(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (optind >= argc) {
|
||||
help();
|
||||
error_exit("Expecting image file name");
|
||||
}
|
||||
optind++;
|
||||
|
||||
@@ -421,7 +436,7 @@ static int img_create(int argc, char **argv)
|
||||
img_size = (uint64_t)sval;
|
||||
}
|
||||
if (optind != argc) {
|
||||
help();
|
||||
error_exit("Unexpected argument: %s", argv[optind]);
|
||||
}
|
||||
|
||||
bdrv_img_create(filename, fmt, base_filename, base_fmt,
|
||||
@@ -590,7 +605,8 @@ static int img_check(int argc, char **argv)
|
||||
} else if (!strcmp(optarg, "all")) {
|
||||
fix = BDRV_FIX_LEAKS | BDRV_FIX_ERRORS;
|
||||
} else {
|
||||
help();
|
||||
error_exit("Unknown option value for -r "
|
||||
"(expecting 'leaks' or 'all'): %s", optarg);
|
||||
}
|
||||
break;
|
||||
case OPTION_OUTPUT:
|
||||
@@ -602,7 +618,7 @@ static int img_check(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
if (optind != argc - 1) {
|
||||
help();
|
||||
error_exit("Expecting one image file name");
|
||||
}
|
||||
filename = argv[optind++];
|
||||
|
||||
@@ -615,7 +631,7 @@ static int img_check(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
bs = bdrv_new_open(filename, fmt, flags, true, quiet);
|
||||
bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
|
||||
if (!bs) {
|
||||
return 1;
|
||||
}
|
||||
@@ -713,7 +729,7 @@ static int img_commit(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
if (optind != argc - 1) {
|
||||
help();
|
||||
error_exit("Expecting one image file name");
|
||||
}
|
||||
filename = argv[optind++];
|
||||
|
||||
@@ -724,7 +740,7 @@ static int img_commit(int argc, char **argv)
|
||||
return -1;
|
||||
}
|
||||
|
||||
bs = bdrv_new_open(filename, fmt, flags, true, quiet);
|
||||
bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
|
||||
if (!bs) {
|
||||
return 1;
|
||||
}
|
||||
@@ -959,7 +975,7 @@ static int img_compare(int argc, char **argv)
|
||||
|
||||
|
||||
if (optind != argc - 2) {
|
||||
help();
|
||||
error_exit("Expecting two image file names");
|
||||
}
|
||||
filename1 = argv[optind++];
|
||||
filename2 = argv[optind++];
|
||||
@@ -967,14 +983,14 @@ static int img_compare(int argc, char **argv)
|
||||
/* Initialize before goto out */
|
||||
qemu_progress_init(progress, 2.0);
|
||||
|
||||
bs1 = bdrv_new_open(filename1, fmt1, BDRV_O_FLAGS, true, quiet);
|
||||
bs1 = bdrv_new_open("image 1", filename1, fmt1, BDRV_O_FLAGS, true, quiet);
|
||||
if (!bs1) {
|
||||
error_report("Can't open file %s", filename1);
|
||||
ret = 2;
|
||||
goto out3;
|
||||
}
|
||||
|
||||
bs2 = bdrv_new_open(filename2, fmt2, BDRV_O_FLAGS, true, quiet);
|
||||
bs2 = bdrv_new_open("image 2", filename2, fmt2, BDRV_O_FLAGS, true, quiet);
|
||||
if (!bs2) {
|
||||
error_report("Can't open file %s", filename2);
|
||||
ret = 2;
|
||||
@@ -1275,7 +1291,7 @@ static int img_convert(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (bs_n < 1) {
|
||||
help();
|
||||
error_exit("Must specify image file name");
|
||||
}
|
||||
|
||||
|
||||
@@ -1292,8 +1308,11 @@ static int img_convert(int argc, char **argv)
|
||||
|
||||
total_sectors = 0;
|
||||
for (bs_i = 0; bs_i < bs_n; bs_i++) {
|
||||
bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt, BDRV_O_FLAGS, true,
|
||||
quiet);
|
||||
char *id = bs_n > 1 ? g_strdup_printf("source %d", bs_i)
|
||||
: g_strdup("source");
|
||||
bs[bs_i] = bdrv_new_open(id, argv[optind + bs_i], fmt, BDRV_O_FLAGS,
|
||||
true, quiet);
|
||||
g_free(id);
|
||||
if (!bs[bs_i]) {
|
||||
error_report("Could not open '%s'", argv[optind + bs_i]);
|
||||
ret = -1;
|
||||
@@ -1416,7 +1435,7 @@ static int img_convert(int argc, char **argv)
|
||||
return -1;
|
||||
}
|
||||
|
||||
out_bs = bdrv_new_open(out_filename, out_fmt, flags, true, quiet);
|
||||
out_bs = bdrv_new_open("target", out_filename, out_fmt, flags, true, quiet);
|
||||
if (!out_bs) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
@@ -1799,8 +1818,8 @@ static ImageInfoList *collect_image_info_list(const char *filename,
|
||||
}
|
||||
g_hash_table_insert(filenames, (gpointer)filename, NULL);
|
||||
|
||||
bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_NO_BACKING,
|
||||
false, false);
|
||||
bs = bdrv_new_open("image", filename, fmt,
|
||||
BDRV_O_FLAGS | BDRV_O_NO_BACKING, false, false);
|
||||
if (!bs) {
|
||||
goto err;
|
||||
}
|
||||
@@ -1882,7 +1901,7 @@ static int img_info(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
if (optind != argc - 1) {
|
||||
help();
|
||||
error_exit("Expecting one image file name");
|
||||
}
|
||||
filename = argv[optind++];
|
||||
|
||||
@@ -2046,10 +2065,10 @@ static int img_map(int argc, char **argv)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (optind >= argc) {
|
||||
help();
|
||||
if (optind != argc - 1) {
|
||||
error_exit("Expecting one image file name");
|
||||
}
|
||||
filename = argv[optind++];
|
||||
filename = argv[optind];
|
||||
|
||||
if (output && !strcmp(output, "json")) {
|
||||
output_format = OFORMAT_JSON;
|
||||
@@ -2060,7 +2079,7 @@ static int img_map(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS, true, false);
|
||||
bs = bdrv_new_open("image", filename, fmt, BDRV_O_FLAGS, true, false);
|
||||
if (!bs) {
|
||||
return 1;
|
||||
}
|
||||
@@ -2138,7 +2157,7 @@ static int img_snapshot(int argc, char **argv)
|
||||
return 0;
|
||||
case 'l':
|
||||
if (action) {
|
||||
help();
|
||||
error_exit("Cannot mix '-l', '-a', '-c', '-d'");
|
||||
return 0;
|
||||
}
|
||||
action = SNAPSHOT_LIST;
|
||||
@@ -2146,7 +2165,7 @@ static int img_snapshot(int argc, char **argv)
|
||||
break;
|
||||
case 'a':
|
||||
if (action) {
|
||||
help();
|
||||
error_exit("Cannot mix '-l', '-a', '-c', '-d'");
|
||||
return 0;
|
||||
}
|
||||
action = SNAPSHOT_APPLY;
|
||||
@@ -2154,7 +2173,7 @@ static int img_snapshot(int argc, char **argv)
|
||||
break;
|
||||
case 'c':
|
||||
if (action) {
|
||||
help();
|
||||
error_exit("Cannot mix '-l', '-a', '-c', '-d'");
|
||||
return 0;
|
||||
}
|
||||
action = SNAPSHOT_CREATE;
|
||||
@@ -2162,7 +2181,7 @@ static int img_snapshot(int argc, char **argv)
|
||||
break;
|
||||
case 'd':
|
||||
if (action) {
|
||||
help();
|
||||
error_exit("Cannot mix '-l', '-a', '-c', '-d'");
|
||||
return 0;
|
||||
}
|
||||
action = SNAPSHOT_DELETE;
|
||||
@@ -2175,12 +2194,12 @@ static int img_snapshot(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (optind != argc - 1) {
|
||||
help();
|
||||
error_exit("Expecting one image file name");
|
||||
}
|
||||
filename = argv[optind++];
|
||||
|
||||
/* Open the image */
|
||||
bs = bdrv_new_open(filename, NULL, bdrv_oflags, true, quiet);
|
||||
bs = bdrv_new_open("image", filename, NULL, bdrv_oflags, true, quiet);
|
||||
if (!bs) {
|
||||
return 1;
|
||||
}
|
||||
@@ -2288,8 +2307,11 @@ static int img_rebase(int argc, char **argv)
|
||||
progress = 0;
|
||||
}
|
||||
|
||||
if ((optind != argc - 1) || (!unsafe && !out_baseimg)) {
|
||||
help();
|
||||
if (optind != argc - 1) {
|
||||
error_exit("Expecting one image file name");
|
||||
}
|
||||
if (!unsafe && !out_baseimg) {
|
||||
error_exit("Must specify backing file (-b) or use unsafe mode (-u)");
|
||||
}
|
||||
filename = argv[optind++];
|
||||
|
||||
@@ -2309,7 +2331,7 @@ static int img_rebase(int argc, char **argv)
|
||||
* Ignore the old backing file for unsafe rebase in case we want to correct
|
||||
* the reference to a renamed or moved backing file.
|
||||
*/
|
||||
bs = bdrv_new_open(filename, fmt, flags, true, quiet);
|
||||
bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
|
||||
if (!bs) {
|
||||
return 1;
|
||||
}
|
||||
@@ -2344,7 +2366,7 @@ static int img_rebase(int argc, char **argv)
|
||||
} else {
|
||||
char backing_name[1024];
|
||||
|
||||
bs_old_backing = bdrv_new("old_backing");
|
||||
bs_old_backing = bdrv_new("old_backing", &error_abort);
|
||||
bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
|
||||
ret = bdrv_open(&bs_old_backing, backing_name, NULL, NULL, BDRV_O_FLAGS,
|
||||
old_backing_drv, &local_err);
|
||||
@@ -2355,7 +2377,7 @@ static int img_rebase(int argc, char **argv)
|
||||
goto out;
|
||||
}
|
||||
if (out_baseimg[0]) {
|
||||
bs_new_backing = bdrv_new("new_backing");
|
||||
bs_new_backing = bdrv_new("new_backing", &error_abort);
|
||||
ret = bdrv_open(&bs_new_backing, out_baseimg, NULL, NULL,
|
||||
BDRV_O_FLAGS, new_backing_drv, &local_err);
|
||||
if (ret) {
|
||||
@@ -2549,7 +2571,7 @@ static int img_resize(int argc, char **argv)
|
||||
/* Remove size from argv manually so that negative numbers are not treated
|
||||
* as options by getopt. */
|
||||
if (argc < 3) {
|
||||
help();
|
||||
error_exit("Not enough arguments");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -2576,7 +2598,7 @@ static int img_resize(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
if (optind != argc - 1) {
|
||||
help();
|
||||
error_exit("Expecting one image file name");
|
||||
}
|
||||
filename = argv[optind++];
|
||||
|
||||
@@ -2606,7 +2628,8 @@ static int img_resize(int argc, char **argv)
|
||||
n = qemu_opt_get_size(param, BLOCK_OPT_SIZE, 0);
|
||||
qemu_opts_del(param);
|
||||
|
||||
bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR, true, quiet);
|
||||
bs = bdrv_new_open("image", filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR,
|
||||
true, quiet);
|
||||
if (!bs) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
@@ -2692,7 +2715,7 @@ static int img_amend(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (!options) {
|
||||
help();
|
||||
error_exit("Must specify options (-o)");
|
||||
}
|
||||
|
||||
filename = (optind == argc - 1) ? argv[argc - 1] : NULL;
|
||||
@@ -2704,10 +2727,11 @@ static int img_amend(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (optind != argc - 1) {
|
||||
help();
|
||||
error_exit("Expecting one image file name");
|
||||
}
|
||||
|
||||
bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR, true, quiet);
|
||||
bs = bdrv_new_open("image", filename, fmt,
|
||||
BDRV_O_FLAGS | BDRV_O_RDWR, true, quiet);
|
||||
if (!bs) {
|
||||
error_report("Could not open image '%s'", filename);
|
||||
ret = -1;
|
||||
@@ -2775,8 +2799,9 @@ int main(int argc, char **argv)
|
||||
|
||||
qemu_init_main_loop();
|
||||
bdrv_init();
|
||||
if (argc < 2)
|
||||
help();
|
||||
if (argc < 2) {
|
||||
error_exit("Not enough arguments");
|
||||
}
|
||||
cmdname = argv[1];
|
||||
argc--; argv++;
|
||||
|
||||
@@ -2788,6 +2813,5 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
/* not found */
|
||||
help();
|
||||
return 0;
|
||||
error_exit("Command not found: %s", cmdname);
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ static int openfile(char *name, int flags, int growable, QDict *opts)
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
qemuio_bs = bdrv_new("hda");
|
||||
qemuio_bs = bdrv_new("hda", &error_abort);
|
||||
|
||||
if (bdrv_open(&qemuio_bs, name, NULL, opts, flags, NULL, &local_err)
|
||||
< 0)
|
||||
|
||||
@@ -657,7 +657,8 @@ int main(int argc, char **argv)
|
||||
drv = NULL;
|
||||
}
|
||||
|
||||
bs = bdrv_new("hda");
|
||||
bs = bdrv_new("hda", &error_abort);
|
||||
|
||||
srcpath = argv[optind];
|
||||
ret = bdrv_open(&bs, srcpath, NULL, NULL, flags, drv, &local_err);
|
||||
if (ret < 0) {
|
||||
|
||||
@@ -444,7 +444,8 @@ This option defines the type of the media: disk or cdrom.
|
||||
@item cyls=@var{c},heads=@var{h},secs=@var{s}[,trans=@var{t}]
|
||||
These options have the same definition as they have in @option{-hdachs}.
|
||||
@item snapshot=@var{snapshot}
|
||||
@var{snapshot} is "on" or "off" and allows to enable snapshot for given drive (see @option{-snapshot}).
|
||||
@var{snapshot} is "on" or "off" and controls snapshot mode for the given drive
|
||||
(see @option{-snapshot}).
|
||||
@item cache=@var{cache}
|
||||
@var{cache} is "none", "writeback", "unsafe", "directsync" or "writethrough" and controls how the host cache is used to access block data.
|
||||
@item aio=@var{aio}
|
||||
@@ -1242,7 +1243,7 @@ Disable adaptive encodings. Adaptive encodings are enabled by default.
|
||||
An adaptive encoding will try to detect frequently updated screen regions,
|
||||
and send updates in these regions using a lossy encoding (like JPEG).
|
||||
This can be really helpful to save bandwidth when playing videos. Disabling
|
||||
adaptive encodings allows to restore the original static behavior of encodings
|
||||
adaptive encodings restores the original static behavior of encodings
|
||||
like Tight.
|
||||
|
||||
@item share=[allow-exclusive|force-shared|ignore]
|
||||
@@ -2805,7 +2806,7 @@ UTC or local time, respectively. @code{localtime} is required for correct date i
|
||||
MS-DOS or Windows. To start at a specific point in time, provide @var{date} in the
|
||||
format @code{2006-06-17T16:01:21} or @code{2006-06-17}. The default base is UTC.
|
||||
|
||||
By default the RTC is driven by the host system time. This allows to use the
|
||||
By default the RTC is driven by the host system time. This allows using of the
|
||||
RTC as accurate reference clock inside the guest, specifically if the host
|
||||
time is smoothly following an accurate external reference clock, e.g. via NTP.
|
||||
If you want to isolate the guest time from the host, you can set @option{clock}
|
||||
|
||||
@@ -171,7 +171,7 @@ void qmp_guest_set_time(bool has_time, int64_t time_ns, Error **errp)
|
||||
/* Now, if user has passed a time to set and the system time is set, we
|
||||
* just need to synchronize the hardware clock. However, if no time was
|
||||
* passed, user is requesting the opposite: set the system time from the
|
||||
* hardware clock. */
|
||||
* hardware clock (RTC). */
|
||||
pid = fork();
|
||||
if (pid == 0) {
|
||||
setsid();
|
||||
|
||||
@@ -96,8 +96,8 @@
|
||||
##
|
||||
# @guest-get-time:
|
||||
#
|
||||
# Get the information about guest time relative to the Epoch
|
||||
# of 1970-01-01 in UTC.
|
||||
# Get the information about guest's System Time relative to
|
||||
# the Epoch of 1970-01-01 in UTC.
|
||||
#
|
||||
# Returns: Time in nanoseconds.
|
||||
#
|
||||
@@ -117,11 +117,11 @@
|
||||
# gap was, NTP might not be able to resynchronize the
|
||||
# guest.
|
||||
#
|
||||
# This command tries to set guest time to the given value,
|
||||
# then sets the Hardware Clock to the current System Time.
|
||||
# This will make it easier for a guest to resynchronize
|
||||
# without waiting for NTP. If no @time is specified, then
|
||||
# the time to set is read from RTC.
|
||||
# This command tries to set guest's System Time to the
|
||||
# given value, then sets the Hardware Clock (RTC) to the
|
||||
# current System Time. This will make it easier for a guest
|
||||
# to resynchronize without waiting for NTP. If no @time is
|
||||
# specified, then the time to set is read from RTC.
|
||||
#
|
||||
# @time: #optional time of nanoseconds, relative to the Epoch
|
||||
# of 1970-01-01 in UTC.
|
||||
|
||||
183
scripts/coverity-model.c
Normal file
183
scripts/coverity-model.c
Normal file
@@ -0,0 +1,183 @@
|
||||
/* Coverity Scan model
|
||||
*
|
||||
* Copyright (C) 2014 Red Hat, Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Markus Armbruster <armbru@redhat.com>
|
||||
* Paolo Bonzini <pbonzini@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or, at your
|
||||
* option, any later version. See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* This is the source code for our Coverity user model file. The
|
||||
* purpose of user models is to increase scanning accuracy by explaining
|
||||
* code Coverity can't see (out of tree libraries) or doesn't
|
||||
* sufficiently understand. Better accuracy means both fewer false
|
||||
* positives and more true defects. Memory leaks in particular.
|
||||
*
|
||||
* - A model file can't import any header files. Some built-in primitives are
|
||||
* available but not wchar_t, NULL etc.
|
||||
* - Modeling doesn't need full structs and typedefs. Rudimentary structs
|
||||
* and similar types are sufficient.
|
||||
* - An uninitialized local variable signifies that the variable could be
|
||||
* any value.
|
||||
*
|
||||
* The model file must be uploaded by an admin in the analysis settings of
|
||||
* http://scan.coverity.com/projects/378
|
||||
*/
|
||||
|
||||
#define NULL ((void *)0)
|
||||
|
||||
typedef unsigned char uint8_t;
|
||||
typedef char int8_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef int int32_t;
|
||||
typedef long ssize_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
typedef long long int64_t;
|
||||
typedef _Bool bool;
|
||||
|
||||
/* exec.c */
|
||||
|
||||
typedef struct AddressSpace AddressSpace;
|
||||
typedef uint64_t hwaddr;
|
||||
|
||||
static void __write(uint8_t *buf, ssize_t len)
|
||||
{
|
||||
int first, last;
|
||||
__coverity_negative_sink__(len);
|
||||
if (len == 0) return;
|
||||
buf[0] = first;
|
||||
buf[len-1] = last;
|
||||
__coverity_writeall__(buf);
|
||||
}
|
||||
|
||||
static void __read(uint8_t *buf, ssize_t len)
|
||||
{
|
||||
__coverity_negative_sink__(len);
|
||||
if (len == 0) return;
|
||||
int first = buf[0];
|
||||
int last = buf[len-1];
|
||||
}
|
||||
|
||||
bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
|
||||
int len, bool is_write)
|
||||
{
|
||||
bool result;
|
||||
|
||||
// TODO: investigate impact of treating reads as producing
|
||||
// tainted data, with __coverity_tainted_data_argument__(buf).
|
||||
if (is_write) __write(buf, len); else __read(buf, len);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Tainting */
|
||||
|
||||
typedef struct {} name2keysym_t;
|
||||
static int get_keysym(const name2keysym_t *table,
|
||||
const char *name)
|
||||
{
|
||||
int result;
|
||||
if (result > 0) {
|
||||
__coverity_tainted_string_sanitize_content__(name);
|
||||
return result;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* glib memory allocation functions.
|
||||
*
|
||||
* Note that we ignore the fact that g_malloc of 0 bytes returns NULL,
|
||||
* and g_realloc of 0 bytes frees the pointer.
|
||||
*
|
||||
* Modeling this would result in Coverity flagging a lot of memory
|
||||
* allocations as potentially returning NULL, and asking us to check
|
||||
* whether the result of the allocation is NULL or not. However, the
|
||||
* resulting pointer should never be dereferenced anyway, and in fact
|
||||
* it is not in the vast majority of cases.
|
||||
*
|
||||
* If a dereference did happen, this would suppress a defect report
|
||||
* for an actual null pointer dereference. But it's too unlikely to
|
||||
* be worth wading through the false positives, and with some luck
|
||||
* we'll get a buffer overflow reported anyway.
|
||||
*/
|
||||
|
||||
void *malloc(size_t);
|
||||
void *calloc(size_t, size_t);
|
||||
void *realloc(void *, size_t);
|
||||
void free(void *);
|
||||
|
||||
void *
|
||||
g_malloc(size_t n_bytes)
|
||||
{
|
||||
void *mem;
|
||||
__coverity_negative_sink__(n_bytes);
|
||||
mem = malloc(n_bytes == 0 ? 1 : n_bytes);
|
||||
if (!mem) __coverity_panic__();
|
||||
return mem;
|
||||
}
|
||||
|
||||
void *
|
||||
g_malloc0(size_t n_bytes)
|
||||
{
|
||||
void *mem;
|
||||
__coverity_negative_sink__(n_bytes);
|
||||
mem = calloc(1, n_bytes == 0 ? 1 : n_bytes);
|
||||
if (!mem) __coverity_panic__();
|
||||
return mem;
|
||||
}
|
||||
|
||||
void g_free(void *mem)
|
||||
{
|
||||
free(mem);
|
||||
}
|
||||
|
||||
void *g_realloc(void * mem, size_t n_bytes)
|
||||
{
|
||||
__coverity_negative_sink__(n_bytes);
|
||||
mem = realloc(mem, n_bytes == 0 ? 1 : n_bytes);
|
||||
if (!mem) __coverity_panic__();
|
||||
return mem;
|
||||
}
|
||||
|
||||
void *g_try_malloc(size_t n_bytes)
|
||||
{
|
||||
__coverity_negative_sink__(n_bytes);
|
||||
return malloc(n_bytes == 0 ? 1 : n_bytes);
|
||||
}
|
||||
|
||||
void *g_try_malloc0(size_t n_bytes)
|
||||
{
|
||||
__coverity_negative_sink__(n_bytes);
|
||||
return calloc(1, n_bytes == 0 ? 1 : n_bytes);
|
||||
}
|
||||
|
||||
void *g_try_realloc(void *mem, size_t n_bytes)
|
||||
{
|
||||
__coverity_negative_sink__(n_bytes);
|
||||
return realloc(mem, n_bytes == 0 ? 1 : n_bytes);
|
||||
}
|
||||
|
||||
/* Other glib functions */
|
||||
|
||||
typedef struct _GIOChannel GIOChannel;
|
||||
GIOChannel *g_io_channel_unix_new(int fd)
|
||||
{
|
||||
GIOChannel *c = g_malloc0(sizeof(GIOChannel));
|
||||
__coverity_escape__(fd);
|
||||
return c;
|
||||
}
|
||||
|
||||
void g_assertion_message_expr(const char *domain,
|
||||
const char *file,
|
||||
int line,
|
||||
const char *func,
|
||||
const char *expr)
|
||||
{
|
||||
__coverity_panic__();
|
||||
}
|
||||
@@ -820,3 +820,10 @@ uint64_t helper_cvtqg(CPUAlphaState *env, uint64_t a)
|
||||
fr = int64_to_float64(a, &FP_STATUS);
|
||||
return float64_to_g(fr);
|
||||
}
|
||||
|
||||
void helper_fcvtql_v_input(CPUAlphaState *env, uint64_t val)
|
||||
{
|
||||
if (val != (int32_t)val) {
|
||||
arith_excp(env, GETPC(), EXC_M_IOV, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,6 +96,7 @@ DEF_HELPER_FLAGS_3(fp_exc_raise_s, TCG_CALL_NO_WG, void, env, i32, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_2(ieee_input, TCG_CALL_NO_WG, void, env, i64)
|
||||
DEF_HELPER_FLAGS_2(ieee_input_cmp, TCG_CALL_NO_WG, void, env, i64)
|
||||
DEF_HELPER_FLAGS_2(fcvtql_v_input, TCG_CALL_NO_WG, void, env, i64)
|
||||
|
||||
#if !defined (CONFIG_USER_ONLY)
|
||||
DEF_HELPER_2(hw_ret, void, env, i64)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
18
tcg/README
18
tcg/README
@@ -36,6 +36,12 @@ or a memory location which is stored in a register outside QEMU TBs
|
||||
A TCG "basic block" corresponds to a list of instructions terminated
|
||||
by a branch instruction.
|
||||
|
||||
An operation with "undefined behavior" may result in a crash.
|
||||
|
||||
An operation with "unspecified behavior" shall not crash. However,
|
||||
the result may be one of several possibilities so may be considered
|
||||
an "undefined result".
|
||||
|
||||
3) Intermediate representation
|
||||
|
||||
3.1) Introduction
|
||||
@@ -239,23 +245,25 @@ t0=t1|~t2
|
||||
|
||||
* shl_i32/i64 t0, t1, t2
|
||||
|
||||
t0=t1 << t2. Undefined behavior if t2 < 0 or t2 >= 32 (resp 64)
|
||||
t0=t1 << t2. Unspecified behavior if t2 < 0 or t2 >= 32 (resp 64)
|
||||
|
||||
* shr_i32/i64 t0, t1, t2
|
||||
|
||||
t0=t1 >> t2 (unsigned). Undefined behavior if t2 < 0 or t2 >= 32 (resp 64)
|
||||
t0=t1 >> t2 (unsigned). Unspecified behavior if t2 < 0 or t2 >= 32 (resp 64)
|
||||
|
||||
* sar_i32/i64 t0, t1, t2
|
||||
|
||||
t0=t1 >> t2 (signed). Undefined behavior if t2 < 0 or t2 >= 32 (resp 64)
|
||||
t0=t1 >> t2 (signed). Unspecified behavior if t2 < 0 or t2 >= 32 (resp 64)
|
||||
|
||||
* rotl_i32/i64 t0, t1, t2
|
||||
|
||||
Rotation of t2 bits to the left. Undefined behavior if t2 < 0 or t2 >= 32 (resp 64)
|
||||
Rotation of t2 bits to the left.
|
||||
Unspecified behavior if t2 < 0 or t2 >= 32 (resp 64)
|
||||
|
||||
* rotr_i32/i64 t0, t1, t2
|
||||
|
||||
Rotation of t2 bits to the right. Undefined behavior if t2 < 0 or t2 >= 32 (resp 64)
|
||||
Rotation of t2 bits to the right.
|
||||
Unspecified behavior if t2 < 0 or t2 >= 32 (resp 64)
|
||||
|
||||
********* Misc
|
||||
|
||||
|
||||
@@ -102,11 +102,10 @@ static inline void patch_reloc(uint8_t *code_ptr, int type,
|
||||
}
|
||||
}
|
||||
|
||||
#define TCG_CT_CONST_IS32 0x100
|
||||
#define TCG_CT_CONST_AIMM 0x200
|
||||
#define TCG_CT_CONST_LIMM 0x400
|
||||
#define TCG_CT_CONST_ZERO 0x800
|
||||
#define TCG_CT_CONST_MONE 0x1000
|
||||
#define TCG_CT_CONST_AIMM 0x100
|
||||
#define TCG_CT_CONST_LIMM 0x200
|
||||
#define TCG_CT_CONST_ZERO 0x400
|
||||
#define TCG_CT_CONST_MONE 0x800
|
||||
|
||||
/* parse target specific constraints */
|
||||
static int target_parse_constraint(TCGArgConstraint *ct,
|
||||
@@ -131,9 +130,6 @@ static int target_parse_constraint(TCGArgConstraint *ct,
|
||||
tcg_regset_reset_reg(ct->u.regs, TCG_REG_X3);
|
||||
#endif
|
||||
break;
|
||||
case 'w': /* The operand should be considered 32-bit. */
|
||||
ct->ct |= TCG_CT_CONST_IS32;
|
||||
break;
|
||||
case 'A': /* Valid for arithmetic immediate (positive or negative). */
|
||||
ct->ct |= TCG_CT_CONST_AIMM;
|
||||
break;
|
||||
@@ -180,7 +176,7 @@ static inline bool is_limm(uint64_t val)
|
||||
return (val & (val - 1)) == 0;
|
||||
}
|
||||
|
||||
static int tcg_target_const_match(tcg_target_long val,
|
||||
static int tcg_target_const_match(tcg_target_long val, TCGType type,
|
||||
const TCGArgConstraint *arg_ct)
|
||||
{
|
||||
int ct = arg_ct->ct;
|
||||
@@ -188,7 +184,7 @@ static int tcg_target_const_match(tcg_target_long val,
|
||||
if (ct & TCG_CT_CONST) {
|
||||
return 1;
|
||||
}
|
||||
if (ct & TCG_CT_CONST_IS32) {
|
||||
if (type == TCG_TYPE_I32) {
|
||||
val = (int32_t)val;
|
||||
}
|
||||
if ((ct & TCG_CT_CONST_AIMM) && (is_aimm(val) || is_aimm(-val))) {
|
||||
@@ -1053,7 +1049,7 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
|
||||
tcg_out_goto(s, (intptr_t)lb->raddr);
|
||||
}
|
||||
|
||||
static void add_qemu_ldst_label(TCGContext *s, int is_ld, TCGMemOp opc,
|
||||
static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOp opc,
|
||||
TCGReg data_reg, TCGReg addr_reg,
|
||||
int mem_index,
|
||||
uint8_t *raddr, uint8_t *label_ptr)
|
||||
@@ -1226,7 +1222,7 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
|
||||
|
||||
tcg_out_tlb_read(s, addr_reg, s_bits, &label_ptr, mem_index, 1);
|
||||
tcg_out_qemu_ld_direct(s, memop, data_reg, addr_reg, TCG_REG_X1);
|
||||
add_qemu_ldst_label(s, 1, memop, data_reg, addr_reg,
|
||||
add_qemu_ldst_label(s, true, memop, data_reg, addr_reg,
|
||||
mem_index, s->code_ptr, label_ptr);
|
||||
#else /* !CONFIG_SOFTMMU */
|
||||
tcg_out_qemu_ld_direct(s, memop, data_reg, addr_reg,
|
||||
@@ -1243,7 +1239,7 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
|
||||
|
||||
tcg_out_tlb_read(s, addr_reg, s_bits, &label_ptr, mem_index, 0);
|
||||
tcg_out_qemu_st_direct(s, memop, data_reg, addr_reg, TCG_REG_X1);
|
||||
add_qemu_ldst_label(s, 0, memop, data_reg, addr_reg,
|
||||
add_qemu_ldst_label(s, false, memop, data_reg, addr_reg,
|
||||
mem_index, s->code_ptr, label_ptr);
|
||||
#else /* !CONFIG_SOFTMMU */
|
||||
tcg_out_qemu_st_direct(s, memop, data_reg, addr_reg,
|
||||
@@ -1663,9 +1659,9 @@ static const TCGTargetOpDef aarch64_op_defs[] = {
|
||||
{ INDEX_op_st32_i64, { "rZ", "r" } },
|
||||
{ INDEX_op_st_i64, { "rZ", "r" } },
|
||||
|
||||
{ INDEX_op_add_i32, { "r", "r", "rwA" } },
|
||||
{ INDEX_op_add_i32, { "r", "r", "rA" } },
|
||||
{ INDEX_op_add_i64, { "r", "r", "rA" } },
|
||||
{ INDEX_op_sub_i32, { "r", "r", "rwA" } },
|
||||
{ INDEX_op_sub_i32, { "r", "r", "rA" } },
|
||||
{ INDEX_op_sub_i64, { "r", "r", "rA" } },
|
||||
{ INDEX_op_mul_i32, { "r", "r", "r" } },
|
||||
{ INDEX_op_mul_i64, { "r", "r", "r" } },
|
||||
@@ -1677,17 +1673,17 @@ static const TCGTargetOpDef aarch64_op_defs[] = {
|
||||
{ INDEX_op_rem_i64, { "r", "r", "r" } },
|
||||
{ INDEX_op_remu_i32, { "r", "r", "r" } },
|
||||
{ INDEX_op_remu_i64, { "r", "r", "r" } },
|
||||
{ INDEX_op_and_i32, { "r", "r", "rwL" } },
|
||||
{ INDEX_op_and_i32, { "r", "r", "rL" } },
|
||||
{ INDEX_op_and_i64, { "r", "r", "rL" } },
|
||||
{ INDEX_op_or_i32, { "r", "r", "rwL" } },
|
||||
{ INDEX_op_or_i32, { "r", "r", "rL" } },
|
||||
{ INDEX_op_or_i64, { "r", "r", "rL" } },
|
||||
{ INDEX_op_xor_i32, { "r", "r", "rwL" } },
|
||||
{ INDEX_op_xor_i32, { "r", "r", "rL" } },
|
||||
{ INDEX_op_xor_i64, { "r", "r", "rL" } },
|
||||
{ INDEX_op_andc_i32, { "r", "r", "rwL" } },
|
||||
{ INDEX_op_andc_i32, { "r", "r", "rL" } },
|
||||
{ INDEX_op_andc_i64, { "r", "r", "rL" } },
|
||||
{ INDEX_op_orc_i32, { "r", "r", "rwL" } },
|
||||
{ INDEX_op_orc_i32, { "r", "r", "rL" } },
|
||||
{ INDEX_op_orc_i64, { "r", "r", "rL" } },
|
||||
{ INDEX_op_eqv_i32, { "r", "r", "rwL" } },
|
||||
{ INDEX_op_eqv_i32, { "r", "r", "rL" } },
|
||||
{ INDEX_op_eqv_i64, { "r", "r", "rL" } },
|
||||
|
||||
{ INDEX_op_neg_i32, { "r", "r" } },
|
||||
@@ -1706,11 +1702,11 @@ static const TCGTargetOpDef aarch64_op_defs[] = {
|
||||
{ INDEX_op_rotl_i64, { "r", "r", "ri" } },
|
||||
{ INDEX_op_rotr_i64, { "r", "r", "ri" } },
|
||||
|
||||
{ INDEX_op_brcond_i32, { "r", "rwA" } },
|
||||
{ INDEX_op_brcond_i32, { "r", "rA" } },
|
||||
{ INDEX_op_brcond_i64, { "r", "rA" } },
|
||||
{ INDEX_op_setcond_i32, { "r", "r", "rwA" } },
|
||||
{ INDEX_op_setcond_i32, { "r", "r", "rA" } },
|
||||
{ INDEX_op_setcond_i64, { "r", "r", "rA" } },
|
||||
{ INDEX_op_movcond_i32, { "r", "r", "rwA", "rZ", "rZ" } },
|
||||
{ INDEX_op_movcond_i32, { "r", "r", "rA", "rZ", "rZ" } },
|
||||
{ INDEX_op_movcond_i64, { "r", "r", "rA", "rZ", "rZ" } },
|
||||
|
||||
{ INDEX_op_qemu_ld_i32, { "r", "l" } },
|
||||
@@ -1739,9 +1735,9 @@ static const TCGTargetOpDef aarch64_op_defs[] = {
|
||||
{ INDEX_op_deposit_i32, { "r", "0", "rZ" } },
|
||||
{ INDEX_op_deposit_i64, { "r", "0", "rZ" } },
|
||||
|
||||
{ INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rwA", "rwMZ" } },
|
||||
{ INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rA", "rMZ" } },
|
||||
{ INDEX_op_add2_i64, { "r", "r", "rZ", "rZ", "rA", "rMZ" } },
|
||||
{ INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rwA", "rwMZ" } },
|
||||
{ INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rA", "rMZ" } },
|
||||
{ INDEX_op_sub2_i64, { "r", "r", "rZ", "rZ", "rA", "rMZ" } },
|
||||
|
||||
{ INDEX_op_muluh_i64, { "r", "r", "r" } },
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#ifndef TCG_TARGET_AARCH64
|
||||
#define TCG_TARGET_AARCH64 1
|
||||
|
||||
#undef TCG_TARGET_WORDS_BIGENDIAN
|
||||
#undef TCG_TARGET_STACK_GROWSUP
|
||||
|
||||
typedef enum {
|
||||
|
||||
@@ -261,7 +261,7 @@ static inline int check_fit_imm(uint32_t imm)
|
||||
* mov operand2: values represented with x << (2 * y), x < 0x100
|
||||
* add, sub, eor...: ditto
|
||||
*/
|
||||
static inline int tcg_target_const_match(tcg_target_long val,
|
||||
static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
|
||||
const TCGArgConstraint *arg_ct)
|
||||
{
|
||||
int ct;
|
||||
@@ -1253,7 +1253,7 @@ static TCGReg tcg_out_tlb_read(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
|
||||
/* Record the context of a call to the out of line helper code for the slow
|
||||
path for a load or store, so that we can later generate the correct
|
||||
helper code. */
|
||||
static void add_qemu_ldst_label(TCGContext *s, int is_ld, TCGMemOp opc,
|
||||
static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOp opc,
|
||||
TCGReg datalo, TCGReg datahi, TCGReg addrlo,
|
||||
TCGReg addrhi, int mem_index,
|
||||
uint8_t *raddr, uint8_t *label_ptr)
|
||||
@@ -1519,7 +1519,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64)
|
||||
|
||||
tcg_out_qemu_ld_index(s, opc, datalo, datahi, addrlo, addend);
|
||||
|
||||
add_qemu_ldst_label(s, 1, opc, datalo, datahi, addrlo, addrhi,
|
||||
add_qemu_ldst_label(s, true, opc, datalo, datahi, addrlo, addrhi,
|
||||
mem_index, s->code_ptr, label_ptr);
|
||||
#else /* !CONFIG_SOFTMMU */
|
||||
if (GUEST_BASE) {
|
||||
@@ -1647,7 +1647,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64)
|
||||
label_ptr = s->code_ptr;
|
||||
tcg_out_bl_noaddr(s, COND_NE);
|
||||
|
||||
add_qemu_ldst_label(s, 0, opc, datalo, datahi, addrlo, addrhi,
|
||||
add_qemu_ldst_label(s, false, opc, datalo, datahi, addrlo, addrhi,
|
||||
mem_index, s->code_ptr, label_ptr);
|
||||
#else /* !CONFIG_SOFTMMU */
|
||||
if (GUEST_BASE) {
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#ifndef TCG_TARGET_ARM
|
||||
#define TCG_TARGET_ARM 1
|
||||
|
||||
#undef TCG_TARGET_WORDS_BIGENDIAN
|
||||
#undef TCG_TARGET_STACK_GROWSUP
|
||||
|
||||
typedef enum {
|
||||
@@ -79,6 +78,7 @@ extern bool use_idiv_instructions;
|
||||
#define TCG_TARGET_HAS_nor_i32 0
|
||||
#define TCG_TARGET_HAS_deposit_i32 1
|
||||
#define TCG_TARGET_HAS_movcond_i32 1
|
||||
#define TCG_TARGET_HAS_mulu2_i32 1
|
||||
#define TCG_TARGET_HAS_muls2_i32 1
|
||||
#define TCG_TARGET_HAS_muluh_i32 0
|
||||
#define TCG_TARGET_HAS_mulsh_i32 0
|
||||
|
||||
@@ -257,7 +257,7 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
|
||||
}
|
||||
|
||||
/* test if a constant matches the constraint */
|
||||
static inline int tcg_target_const_match(tcg_target_long val,
|
||||
static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
|
||||
const TCGArgConstraint *arg_ct)
|
||||
{
|
||||
int ct = arg_ct->ct;
|
||||
@@ -1244,7 +1244,7 @@ static inline void tcg_out_tlb_load(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
|
||||
* Record the context of a call to the out of line helper code for the slow path
|
||||
* for a load or store, so that we can later generate the correct helper code
|
||||
*/
|
||||
static void add_qemu_ldst_label(TCGContext *s, int is_ld, TCGMemOp opc,
|
||||
static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOp opc,
|
||||
TCGReg datalo, TCGReg datahi,
|
||||
TCGReg addrlo, TCGReg addrhi,
|
||||
int mem_index, uint8_t *raddr,
|
||||
@@ -1554,7 +1554,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64)
|
||||
tcg_out_qemu_ld_direct(s, datalo, datahi, TCG_REG_L1, 0, 0, opc);
|
||||
|
||||
/* Record the current context of a load into ldst label */
|
||||
add_qemu_ldst_label(s, 1, opc, datalo, datahi, addrlo, addrhi,
|
||||
add_qemu_ldst_label(s, true, opc, datalo, datahi, addrlo, addrhi,
|
||||
mem_index, s->code_ptr, label_ptr);
|
||||
#else
|
||||
{
|
||||
@@ -1685,7 +1685,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64)
|
||||
tcg_out_qemu_st_direct(s, datalo, datahi, TCG_REG_L1, 0, 0, opc);
|
||||
|
||||
/* Record the current context of a store into ldst label */
|
||||
add_qemu_ldst_label(s, 0, opc, datalo, datahi, addrlo, addrhi,
|
||||
add_qemu_ldst_label(s, false, opc, datalo, datahi, addrlo, addrhi,
|
||||
mem_index, s->code_ptr, label_ptr);
|
||||
#else
|
||||
{
|
||||
|
||||
@@ -24,8 +24,6 @@
|
||||
#ifndef TCG_TARGET_I386
|
||||
#define TCG_TARGET_I386 1
|
||||
|
||||
#undef TCG_TARGET_WORDS_BIGENDIAN
|
||||
|
||||
#ifdef __x86_64__
|
||||
# define TCG_TARGET_REG_BITS 64
|
||||
# define TCG_TARGET_NB_REGS 16
|
||||
|
||||
@@ -23,8 +23,6 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "tcg-be-null.h"
|
||||
|
||||
/*
|
||||
* Register definitions
|
||||
*/
|
||||
@@ -221,10 +219,12 @@ enum {
|
||||
OPC_ALLOC_M34 = 0x02c00000000ull,
|
||||
OPC_BR_DPTK_FEW_B1 = 0x08400000000ull,
|
||||
OPC_BR_SPTK_MANY_B1 = 0x08000001000ull,
|
||||
OPC_BR_CALL_SPNT_FEW_B3 = 0x0a200000000ull,
|
||||
OPC_BR_SPTK_MANY_B4 = 0x00100001000ull,
|
||||
OPC_BR_CALL_SPTK_MANY_B5 = 0x02100001000ull,
|
||||
OPC_BR_RET_SPTK_MANY_B4 = 0x00108001100ull,
|
||||
OPC_BRL_SPTK_MANY_X3 = 0x18000001000ull,
|
||||
OPC_BRL_CALL_SPNT_MANY_X4 = 0x1a200001000ull,
|
||||
OPC_BRL_CALL_SPTK_MANY_X4 = 0x1a000001000ull,
|
||||
OPC_CMP_LT_A6 = 0x18000000000ull,
|
||||
OPC_CMP_LTU_A6 = 0x1a000000000ull,
|
||||
@@ -356,6 +356,15 @@ static inline uint64_t tcg_opc_b1(int qp, uint64_t opc, uint64_t imm)
|
||||
| (qp & 0x3f);
|
||||
}
|
||||
|
||||
static inline uint64_t tcg_opc_b3(int qp, uint64_t opc, int b1, uint64_t imm)
|
||||
{
|
||||
return opc
|
||||
| ((imm & 0x100000) << 16) /* s */
|
||||
| ((imm & 0x0fffff) << 13) /* imm20b */
|
||||
| ((b1 & 0x7) << 6)
|
||||
| (qp & 0x3f);
|
||||
}
|
||||
|
||||
static inline uint64_t tcg_opc_b4(int qp, uint64_t opc, int b2)
|
||||
{
|
||||
return opc
|
||||
@@ -815,6 +824,7 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
|
||||
#if defined(CONFIG_SOFTMMU)
|
||||
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R56);
|
||||
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R57);
|
||||
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R58);
|
||||
#endif
|
||||
break;
|
||||
case 'Z':
|
||||
@@ -832,7 +842,7 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
|
||||
}
|
||||
|
||||
/* test if a constant matches the constraint */
|
||||
static inline int tcg_target_const_match(tcg_target_long val,
|
||||
static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
|
||||
const TCGArgConstraint *arg_ct)
|
||||
{
|
||||
int ct;
|
||||
@@ -950,15 +960,21 @@ static inline void tcg_out_callr(TCGContext *s, TCGReg addr)
|
||||
static void tcg_out_exit_tb(TCGContext *s, tcg_target_long arg)
|
||||
{
|
||||
int64_t disp;
|
||||
uint64_t imm;
|
||||
uint64_t imm, opc1;
|
||||
|
||||
tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R8, arg);
|
||||
/* At least arg == 0 is a common operation. */
|
||||
if (arg == sextract64(arg, 0, 22)) {
|
||||
opc1 = tcg_opc_movi_a(TCG_REG_P0, TCG_REG_R8, arg);
|
||||
} else {
|
||||
tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R8, arg);
|
||||
opc1 = INSN_NOP_M;
|
||||
}
|
||||
|
||||
disp = tb_ret_addr - s->code_ptr;
|
||||
imm = (uint64_t)disp >> 4;
|
||||
|
||||
tcg_out_bundle(s, mLX,
|
||||
INSN_NOP_M,
|
||||
opc1,
|
||||
tcg_opc_l3 (imm),
|
||||
tcg_opc_x3 (TCG_REG_P0, OPC_BRL_SPTK_MANY_X3, imm));
|
||||
}
|
||||
@@ -1558,238 +1574,284 @@ static inline void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGArg ret,
|
||||
}
|
||||
|
||||
#if defined(CONFIG_SOFTMMU)
|
||||
/* We're expecting to use an signed 22-bit immediate add. */
|
||||
QEMU_BUILD_BUG_ON(offsetof(CPUArchState, tlb_table[NB_MMU_MODES - 1][1])
|
||||
> 0x1fffff)
|
||||
|
||||
/* Load and compare a TLB entry, and return the result in (p6, p7).
|
||||
R2 is loaded with the address of the addend TLB entry.
|
||||
R57 is loaded with the address, zero extented on 32-bit targets. */
|
||||
static inline void tcg_out_qemu_tlb(TCGContext *s, TCGArg addr_reg,
|
||||
TCGMemOp s_bits, uint64_t offset_rw,
|
||||
uint64_t offset_addend)
|
||||
R2 is loaded with the addend TLB entry.
|
||||
R57 is loaded with the address, zero extented on 32-bit targets.
|
||||
R1, R3 are clobbered, leaving R56 free for...
|
||||
BSWAP_1, BSWAP_2 and I-slot insns for swapping data for store. */
|
||||
static inline void tcg_out_qemu_tlb(TCGContext *s, TCGReg addr_reg,
|
||||
TCGMemOp s_bits, int off_rw, int off_add,
|
||||
uint64_t bswap1, uint64_t bswap2)
|
||||
{
|
||||
tcg_out_bundle(s, mII,
|
||||
INSN_NOP_M,
|
||||
tcg_opc_i11(TCG_REG_P0, OPC_EXTR_U_I11, TCG_REG_R2,
|
||||
/*
|
||||
.mii
|
||||
mov r2 = off_rw
|
||||
extr.u r3 = addr_reg, ... # extract tlb page
|
||||
zxt4 r57 = addr_reg # or mov for 64-bit guest
|
||||
;;
|
||||
.mii
|
||||
addl r2 = r2, areg0
|
||||
shl r3 = r3, cteb # via dep.z
|
||||
dep r1 = 0, r57, ... # zero page ofs, keep align
|
||||
;;
|
||||
.mmi
|
||||
add r2 = r2, r3
|
||||
;;
|
||||
ld4 r3 = [r2], off_add-off_rw # or ld8 for 64-bit guest
|
||||
nop
|
||||
;;
|
||||
.mmi
|
||||
nop
|
||||
cmp.eq p6, p7 = r3, r58
|
||||
nop
|
||||
;;
|
||||
*/
|
||||
tcg_out_bundle(s, miI,
|
||||
tcg_opc_movi_a(TCG_REG_P0, TCG_REG_R2, off_rw),
|
||||
tcg_opc_i11(TCG_REG_P0, OPC_EXTR_U_I11, TCG_REG_R3,
|
||||
addr_reg, TARGET_PAGE_BITS, CPU_TLB_BITS - 1),
|
||||
tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12, TCG_REG_R2,
|
||||
TCG_REG_R2, 63 - CPU_TLB_ENTRY_BITS,
|
||||
63 - CPU_TLB_ENTRY_BITS));
|
||||
tcg_out_bundle(s, mII,
|
||||
tcg_opc_a5 (TCG_REG_P0, OPC_ADDL_A5, TCG_REG_R2,
|
||||
offset_rw, TCG_REG_R2),
|
||||
tcg_opc_ext_i(TCG_REG_P0,
|
||||
TARGET_LONG_BITS == 32 ? MO_UL : MO_Q,
|
||||
TCG_REG_R57, addr_reg),
|
||||
TCG_REG_R57, addr_reg));
|
||||
tcg_out_bundle(s, miI,
|
||||
tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1, TCG_REG_R2,
|
||||
TCG_REG_R2, TCG_AREG0));
|
||||
tcg_out_bundle(s, mII,
|
||||
TCG_REG_R2, TCG_AREG0),
|
||||
tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12, TCG_REG_R3,
|
||||
TCG_REG_R3, 63 - CPU_TLB_ENTRY_BITS,
|
||||
63 - CPU_TLB_ENTRY_BITS),
|
||||
tcg_opc_i14(TCG_REG_P0, OPC_DEP_I14, TCG_REG_R1, 0,
|
||||
TCG_REG_R57, 63 - s_bits,
|
||||
TARGET_PAGE_BITS - s_bits - 1));
|
||||
tcg_out_bundle(s, MmI,
|
||||
tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1,
|
||||
TCG_REG_R2, TCG_REG_R2, TCG_REG_R3),
|
||||
tcg_opc_m3 (TCG_REG_P0,
|
||||
(TARGET_LONG_BITS == 32
|
||||
? OPC_LD4_M3 : OPC_LD8_M3), TCG_REG_R56,
|
||||
TCG_REG_R2, offset_addend - offset_rw),
|
||||
tcg_opc_i14(TCG_REG_P0, OPC_DEP_I14, TCG_REG_R3, 0,
|
||||
TCG_REG_R57, 63 - s_bits,
|
||||
TARGET_PAGE_BITS - s_bits - 1),
|
||||
? OPC_LD4_M3 : OPC_LD8_M3), TCG_REG_R3,
|
||||
TCG_REG_R2, off_add - off_rw),
|
||||
bswap1);
|
||||
tcg_out_bundle(s, mmI,
|
||||
tcg_opc_m1 (TCG_REG_P0, OPC_LD8_M1, TCG_REG_R2, TCG_REG_R2),
|
||||
tcg_opc_a6 (TCG_REG_P0, OPC_CMP_EQ_A6, TCG_REG_P6,
|
||||
TCG_REG_P7, TCG_REG_R3, TCG_REG_R56));
|
||||
TCG_REG_P7, TCG_REG_R1, TCG_REG_R3),
|
||||
bswap2);
|
||||
}
|
||||
|
||||
/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
|
||||
int mmu_idx) */
|
||||
static const void * const qemu_ld_helpers[4] = {
|
||||
helper_ldb_mmu,
|
||||
helper_ldw_mmu,
|
||||
helper_ldl_mmu,
|
||||
helper_ldq_mmu,
|
||||
};
|
||||
#define TCG_MAX_QEMU_LDST 640
|
||||
|
||||
static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
|
||||
TCGMemOp opc)
|
||||
typedef struct TCGLabelQemuLdst {
|
||||
bool is_ld;
|
||||
TCGMemOp size;
|
||||
uint8_t *label_ptr; /* label pointers to be updated */
|
||||
} TCGLabelQemuLdst;
|
||||
|
||||
typedef struct TCGBackendData {
|
||||
int nb_ldst_labels;
|
||||
TCGLabelQemuLdst ldst_labels[TCG_MAX_QEMU_LDST];
|
||||
} TCGBackendData;
|
||||
|
||||
static inline void tcg_out_tb_init(TCGContext *s)
|
||||
{
|
||||
s->be->nb_ldst_labels = 0;
|
||||
}
|
||||
|
||||
static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOp opc,
|
||||
uint8_t *label_ptr)
|
||||
{
|
||||
TCGBackendData *be = s->be;
|
||||
TCGLabelQemuLdst *l = &be->ldst_labels[be->nb_ldst_labels++];
|
||||
|
||||
assert(be->nb_ldst_labels <= TCG_MAX_QEMU_LDST);
|
||||
l->is_ld = is_ld;
|
||||
l->size = opc & MO_SIZE;
|
||||
l->label_ptr = label_ptr;
|
||||
}
|
||||
|
||||
static void tcg_out_tb_finalize(TCGContext *s)
|
||||
{
|
||||
static const void * const helpers[8] = {
|
||||
helper_ret_stb_mmu,
|
||||
helper_le_stw_mmu,
|
||||
helper_le_stl_mmu,
|
||||
helper_le_stq_mmu,
|
||||
helper_ret_ldub_mmu,
|
||||
helper_le_lduw_mmu,
|
||||
helper_le_ldul_mmu,
|
||||
helper_le_ldq_mmu,
|
||||
};
|
||||
uintptr_t thunks[8] = { };
|
||||
TCGBackendData *be = s->be;
|
||||
size_t i, n = be->nb_ldst_labels;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
TCGLabelQemuLdst *l = &be->ldst_labels[i];
|
||||
long x = l->is_ld * 4 + l->size;
|
||||
uintptr_t dest = thunks[x];
|
||||
|
||||
/* The out-of-line thunks are all the same; load the return address
|
||||
from B0, load the GP, and branch to the code. Note that we are
|
||||
always post-call, so the register window has rolled, so we're
|
||||
using incomming parameter register numbers, not outgoing. */
|
||||
if (dest == 0) {
|
||||
uintptr_t disp, *desc = (uintptr_t *)helpers[x];
|
||||
|
||||
thunks[x] = dest = (uintptr_t)s->code_ptr;
|
||||
|
||||
tcg_out_bundle(s, mlx,
|
||||
INSN_NOP_M,
|
||||
tcg_opc_l2 (desc[1]),
|
||||
tcg_opc_x2 (TCG_REG_P0, OPC_MOVL_X2,
|
||||
TCG_REG_R1, desc[1]));
|
||||
tcg_out_bundle(s, mii,
|
||||
INSN_NOP_M,
|
||||
INSN_NOP_I,
|
||||
tcg_opc_i22(TCG_REG_P0, OPC_MOV_I22,
|
||||
l->is_ld ? TCG_REG_R35 : TCG_REG_R36,
|
||||
TCG_REG_B0));
|
||||
disp = (desc[0] - (uintptr_t)s->code_ptr) >> 4;
|
||||
tcg_out_bundle(s, mLX,
|
||||
INSN_NOP_M,
|
||||
tcg_opc_l3 (disp),
|
||||
tcg_opc_x3 (TCG_REG_P0, OPC_BRL_SPTK_MANY_X3, disp));
|
||||
}
|
||||
|
||||
reloc_pcrel21b(l->label_ptr, dest);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args)
|
||||
{
|
||||
static const uint64_t opc_ld_m1[4] = {
|
||||
OPC_LD1_M1, OPC_LD2_M1, OPC_LD4_M1, OPC_LD8_M1
|
||||
};
|
||||
int addr_reg, data_reg, mem_index;
|
||||
TCGMemOp s_bits, bswap;
|
||||
TCGMemOp opc, s_bits;
|
||||
uint64_t fin1, fin2;
|
||||
uint8_t *label_ptr;
|
||||
|
||||
data_reg = *args++;
|
||||
addr_reg = *args++;
|
||||
mem_index = *args;
|
||||
data_reg = args[0];
|
||||
addr_reg = args[1];
|
||||
opc = args[2];
|
||||
mem_index = args[3];
|
||||
s_bits = opc & MO_SIZE;
|
||||
bswap = opc & MO_BSWAP;
|
||||
|
||||
/* Read the TLB entry */
|
||||
tcg_out_qemu_tlb(s, addr_reg, s_bits,
|
||||
offsetof(CPUArchState, tlb_table[mem_index][0].addr_read),
|
||||
offsetof(CPUArchState, tlb_table[mem_index][0].addend));
|
||||
offsetof(CPUArchState, tlb_table[mem_index][0].addend),
|
||||
INSN_NOP_I, INSN_NOP_I);
|
||||
|
||||
/* P6 is the fast path, and P7 the slow path */
|
||||
tcg_out_bundle(s, mLX,
|
||||
tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R56, TCG_AREG0),
|
||||
tcg_opc_l2 ((tcg_target_long) qemu_ld_helpers[s_bits]),
|
||||
tcg_opc_x2 (TCG_REG_P7, OPC_MOVL_X2, TCG_REG_R2,
|
||||
(tcg_target_long) qemu_ld_helpers[s_bits]));
|
||||
tcg_out_bundle(s, MmI,
|
||||
tcg_opc_m3 (TCG_REG_P0, OPC_LD8_M3, TCG_REG_R3,
|
||||
TCG_REG_R2, 8),
|
||||
tcg_opc_a1 (TCG_REG_P6, OPC_ADD_A1, TCG_REG_R3,
|
||||
TCG_REG_R3, TCG_REG_R57),
|
||||
tcg_opc_i21(TCG_REG_P7, OPC_MOV_I21, TCG_REG_B6,
|
||||
TCG_REG_R3, 0));
|
||||
if (bswap && s_bits == MO_16) {
|
||||
tcg_out_bundle(s, MmI,
|
||||
tcg_opc_m1 (TCG_REG_P6, opc_ld_m1[s_bits],
|
||||
TCG_REG_R8, TCG_REG_R3),
|
||||
tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1, TCG_REG_R1, TCG_REG_R2),
|
||||
tcg_opc_i12(TCG_REG_P6, OPC_DEP_Z_I12,
|
||||
TCG_REG_R8, TCG_REG_R8, 15, 15));
|
||||
} else if (bswap && s_bits == MO_32) {
|
||||
tcg_out_bundle(s, MmI,
|
||||
tcg_opc_m1 (TCG_REG_P6, opc_ld_m1[s_bits],
|
||||
TCG_REG_R8, TCG_REG_R3),
|
||||
tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1, TCG_REG_R1, TCG_REG_R2),
|
||||
tcg_opc_i12(TCG_REG_P6, OPC_DEP_Z_I12,
|
||||
TCG_REG_R8, TCG_REG_R8, 31, 31));
|
||||
|
||||
fin2 = 0;
|
||||
if (opc & MO_BSWAP) {
|
||||
fin1 = tcg_opc_bswap64_i(TCG_REG_P0, data_reg, TCG_REG_R8);
|
||||
if (s_bits < MO_64) {
|
||||
int shift = 64 - (8 << s_bits);
|
||||
fin2 = (opc & MO_SIGN ? OPC_EXTR_I11 : OPC_EXTR_U_I11);
|
||||
fin2 = tcg_opc_i11(TCG_REG_P0, fin2,
|
||||
data_reg, data_reg, shift, 63 - shift);
|
||||
}
|
||||
} else {
|
||||
tcg_out_bundle(s, mmI,
|
||||
tcg_opc_m1 (TCG_REG_P6, opc_ld_m1[s_bits],
|
||||
TCG_REG_R8, TCG_REG_R3),
|
||||
tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1, TCG_REG_R1, TCG_REG_R2),
|
||||
INSN_NOP_I);
|
||||
}
|
||||
if (!bswap) {
|
||||
tcg_out_bundle(s, miB,
|
||||
tcg_opc_movi_a(TCG_REG_P7, TCG_REG_R58, mem_index),
|
||||
INSN_NOP_I,
|
||||
tcg_opc_b5 (TCG_REG_P7, OPC_BR_CALL_SPTK_MANY_B5,
|
||||
TCG_REG_B0, TCG_REG_B6));
|
||||
} else {
|
||||
tcg_out_bundle(s, miB,
|
||||
tcg_opc_movi_a(TCG_REG_P7, TCG_REG_R58, mem_index),
|
||||
tcg_opc_bswap64_i(TCG_REG_P6, TCG_REG_R8, TCG_REG_R8),
|
||||
tcg_opc_b5 (TCG_REG_P7, OPC_BR_CALL_SPTK_MANY_B5,
|
||||
TCG_REG_B0, TCG_REG_B6));
|
||||
fin1 = tcg_opc_ext_i(TCG_REG_P0, opc, data_reg, TCG_REG_R8);
|
||||
}
|
||||
|
||||
tcg_out_bundle(s, miI,
|
||||
INSN_NOP_M,
|
||||
tcg_out_bundle(s, mmI,
|
||||
tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R56, TCG_AREG0),
|
||||
tcg_opc_a1 (TCG_REG_P6, OPC_ADD_A1, TCG_REG_R2,
|
||||
TCG_REG_R2, TCG_REG_R57),
|
||||
tcg_opc_movi_a(TCG_REG_P7, TCG_REG_R58, mem_index));
|
||||
label_ptr = s->code_ptr + 2;
|
||||
tcg_out_bundle(s, miB,
|
||||
tcg_opc_m1 (TCG_REG_P6, opc_ld_m1[s_bits],
|
||||
TCG_REG_R8, TCG_REG_R2),
|
||||
INSN_NOP_I,
|
||||
tcg_opc_ext_i(TCG_REG_P0, opc, data_reg, TCG_REG_R8));
|
||||
tcg_opc_b3 (TCG_REG_P7, OPC_BR_CALL_SPNT_FEW_B3, TCG_REG_B0,
|
||||
get_reloc_pcrel21b(label_ptr)));
|
||||
|
||||
add_qemu_ldst_label(s, 1, opc, label_ptr);
|
||||
|
||||
/* Note that we always use LE helper functions, so the bswap insns
|
||||
here for the fast path also apply to the slow path. */
|
||||
tcg_out_bundle(s, (fin2 ? mII : miI),
|
||||
INSN_NOP_M,
|
||||
fin1,
|
||||
fin2 ? fin2 : INSN_NOP_I);
|
||||
}
|
||||
|
||||
/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
|
||||
uintxx_t val, int mmu_idx) */
|
||||
static const void * const qemu_st_helpers[4] = {
|
||||
helper_stb_mmu,
|
||||
helper_stw_mmu,
|
||||
helper_stl_mmu,
|
||||
helper_stq_mmu,
|
||||
};
|
||||
|
||||
static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
|
||||
TCGMemOp opc)
|
||||
static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args)
|
||||
{
|
||||
static const uint64_t opc_st_m4[4] = {
|
||||
OPC_ST1_M4, OPC_ST2_M4, OPC_ST4_M4, OPC_ST8_M4
|
||||
};
|
||||
int addr_reg, data_reg, mem_index;
|
||||
TCGMemOp s_bits;
|
||||
TCGReg addr_reg, data_reg;
|
||||
int mem_index;
|
||||
uint64_t pre1, pre2;
|
||||
TCGMemOp opc, s_bits;
|
||||
uint8_t *label_ptr;
|
||||
|
||||
data_reg = *args++;
|
||||
addr_reg = *args++;
|
||||
mem_index = *args;
|
||||
data_reg = args[0];
|
||||
addr_reg = args[1];
|
||||
opc = args[2];
|
||||
mem_index = args[3];
|
||||
s_bits = opc & MO_SIZE;
|
||||
|
||||
/* Note that we always use LE helper functions, so the bswap insns
|
||||
that are here for the fast path also apply to the slow path,
|
||||
and move the data into the argument register. */
|
||||
pre2 = INSN_NOP_I;
|
||||
if (opc & MO_BSWAP) {
|
||||
pre1 = tcg_opc_bswap64_i(TCG_REG_P0, TCG_REG_R58, data_reg);
|
||||
if (s_bits < MO_64) {
|
||||
int shift = 64 - (8 << s_bits);
|
||||
pre2 = tcg_opc_i11(TCG_REG_P0, OPC_EXTR_U_I11,
|
||||
TCG_REG_R58, TCG_REG_R58, shift, 63 - shift);
|
||||
}
|
||||
} else {
|
||||
/* Just move the data into place for the slow path. */
|
||||
pre1 = tcg_opc_ext_i(TCG_REG_P0, opc, TCG_REG_R58, data_reg);
|
||||
}
|
||||
|
||||
tcg_out_qemu_tlb(s, addr_reg, s_bits,
|
||||
offsetof(CPUArchState, tlb_table[mem_index][0].addr_write),
|
||||
offsetof(CPUArchState, tlb_table[mem_index][0].addend));
|
||||
offsetof(CPUArchState, tlb_table[mem_index][0].addend),
|
||||
pre1, pre2);
|
||||
|
||||
/* P6 is the fast path, and P7 the slow path */
|
||||
tcg_out_bundle(s, mLX,
|
||||
tcg_out_bundle(s, mmI,
|
||||
tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R56, TCG_AREG0),
|
||||
tcg_opc_l2 ((tcg_target_long) qemu_st_helpers[s_bits]),
|
||||
tcg_opc_x2 (TCG_REG_P7, OPC_MOVL_X2, TCG_REG_R2,
|
||||
(tcg_target_long) qemu_st_helpers[s_bits]));
|
||||
tcg_out_bundle(s, MmI,
|
||||
tcg_opc_m3 (TCG_REG_P0, OPC_LD8_M3, TCG_REG_R3,
|
||||
TCG_REG_R2, 8),
|
||||
tcg_opc_a1 (TCG_REG_P6, OPC_ADD_A1, TCG_REG_R3,
|
||||
TCG_REG_R3, TCG_REG_R57),
|
||||
tcg_opc_i21(TCG_REG_P7, OPC_MOV_I21, TCG_REG_B6,
|
||||
TCG_REG_R3, 0));
|
||||
|
||||
switch (opc) {
|
||||
case MO_8:
|
||||
case MO_16:
|
||||
case MO_32:
|
||||
case MO_64:
|
||||
tcg_out_bundle(s, mii,
|
||||
tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1,
|
||||
TCG_REG_R1, TCG_REG_R2),
|
||||
tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R58, data_reg),
|
||||
INSN_NOP_I);
|
||||
break;
|
||||
|
||||
case MO_16 | MO_BSWAP:
|
||||
tcg_out_bundle(s, miI,
|
||||
tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1,
|
||||
TCG_REG_R1, TCG_REG_R2),
|
||||
INSN_NOP_I,
|
||||
tcg_opc_i12(TCG_REG_P6, OPC_DEP_Z_I12,
|
||||
TCG_REG_R2, data_reg, 15, 15));
|
||||
tcg_out_bundle(s, miI,
|
||||
tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R58, data_reg),
|
||||
INSN_NOP_I,
|
||||
tcg_opc_bswap64_i(TCG_REG_P6, TCG_REG_R2, TCG_REG_R2));
|
||||
data_reg = TCG_REG_R2;
|
||||
break;
|
||||
|
||||
case MO_32 | MO_BSWAP:
|
||||
tcg_out_bundle(s, miI,
|
||||
tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1,
|
||||
TCG_REG_R1, TCG_REG_R2),
|
||||
INSN_NOP_I,
|
||||
tcg_opc_i12(TCG_REG_P6, OPC_DEP_Z_I12,
|
||||
TCG_REG_R2, data_reg, 31, 31));
|
||||
tcg_out_bundle(s, miI,
|
||||
tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R58, data_reg),
|
||||
INSN_NOP_I,
|
||||
tcg_opc_bswap64_i(TCG_REG_P6, TCG_REG_R2, TCG_REG_R2));
|
||||
data_reg = TCG_REG_R2;
|
||||
break;
|
||||
|
||||
case MO_64 | MO_BSWAP:
|
||||
tcg_out_bundle(s, miI,
|
||||
tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1,
|
||||
TCG_REG_R1, TCG_REG_R2),
|
||||
tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R58, data_reg),
|
||||
tcg_opc_bswap64_i(TCG_REG_P6, TCG_REG_R2, data_reg));
|
||||
data_reg = TCG_REG_R2;
|
||||
break;
|
||||
|
||||
default:
|
||||
tcg_abort();
|
||||
}
|
||||
|
||||
tcg_opc_a1 (TCG_REG_P6, OPC_ADD_A1, TCG_REG_R2,
|
||||
TCG_REG_R2, TCG_REG_R57),
|
||||
tcg_opc_movi_a(TCG_REG_P7, TCG_REG_R59, mem_index));
|
||||
label_ptr = s->code_ptr + 2;
|
||||
tcg_out_bundle(s, miB,
|
||||
tcg_opc_m4 (TCG_REG_P6, opc_st_m4[s_bits],
|
||||
data_reg, TCG_REG_R3),
|
||||
tcg_opc_movi_a(TCG_REG_P7, TCG_REG_R59, mem_index),
|
||||
tcg_opc_b5 (TCG_REG_P7, OPC_BR_CALL_SPTK_MANY_B5,
|
||||
TCG_REG_B0, TCG_REG_B6));
|
||||
TCG_REG_R58, TCG_REG_R2),
|
||||
INSN_NOP_I,
|
||||
tcg_opc_b3 (TCG_REG_P7, OPC_BR_CALL_SPNT_FEW_B3, TCG_REG_B0,
|
||||
get_reloc_pcrel21b(label_ptr)));
|
||||
|
||||
add_qemu_ldst_label(s, 0, opc, label_ptr);
|
||||
}
|
||||
|
||||
#else /* !CONFIG_SOFTMMU */
|
||||
# include "tcg-be-null.h"
|
||||
|
||||
static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
|
||||
TCGMemOp opc)
|
||||
static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args)
|
||||
{
|
||||
static uint64_t const opc_ld_m1[4] = {
|
||||
OPC_LD1_M1, OPC_LD2_M1, OPC_LD4_M1, OPC_LD8_M1
|
||||
};
|
||||
int addr_reg, data_reg;
|
||||
TCGMemOp s_bits, bswap;
|
||||
TCGMemOp opc, s_bits, bswap;
|
||||
|
||||
data_reg = *args++;
|
||||
addr_reg = *args++;
|
||||
data_reg = args[0];
|
||||
addr_reg = args[1];
|
||||
opc = args[2];
|
||||
s_bits = opc & MO_SIZE;
|
||||
bswap = opc & MO_BSWAP;
|
||||
|
||||
@@ -1900,8 +1962,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
|
||||
TCGMemOp opc)
|
||||
static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args)
|
||||
{
|
||||
static uint64_t const opc_st_m4[4] = {
|
||||
OPC_ST1_M4, OPC_ST2_M4, OPC_ST4_M4, OPC_ST8_M4
|
||||
@@ -1910,10 +1971,11 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
|
||||
#if TARGET_LONG_BITS == 64
|
||||
uint64_t add_guest_base;
|
||||
#endif
|
||||
TCGMemOp s_bits, bswap;
|
||||
TCGMemOp opc, s_bits, bswap;
|
||||
|
||||
data_reg = *args++;
|
||||
addr_reg = *args++;
|
||||
data_reg = args[0];
|
||||
addr_reg = args[1];
|
||||
opc = args[2];
|
||||
s_bits = opc & MO_SIZE;
|
||||
bswap = opc & MO_BSWAP;
|
||||
|
||||
@@ -2237,40 +2299,17 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
||||
args[3], const_args[3], args[4], const_args[4], 0);
|
||||
break;
|
||||
|
||||
case INDEX_op_qemu_ld8u:
|
||||
tcg_out_qemu_ld(s, args, MO_UB);
|
||||
case INDEX_op_qemu_ld_i32:
|
||||
tcg_out_qemu_ld(s, args);
|
||||
break;
|
||||
case INDEX_op_qemu_ld8s:
|
||||
tcg_out_qemu_ld(s, args, MO_SB);
|
||||
case INDEX_op_qemu_ld_i64:
|
||||
tcg_out_qemu_ld(s, args);
|
||||
break;
|
||||
case INDEX_op_qemu_ld16u:
|
||||
tcg_out_qemu_ld(s, args, MO_TEUW);
|
||||
case INDEX_op_qemu_st_i32:
|
||||
tcg_out_qemu_st(s, args);
|
||||
break;
|
||||
case INDEX_op_qemu_ld16s:
|
||||
tcg_out_qemu_ld(s, args, MO_TESW);
|
||||
break;
|
||||
case INDEX_op_qemu_ld32:
|
||||
case INDEX_op_qemu_ld32u:
|
||||
tcg_out_qemu_ld(s, args, MO_TEUL);
|
||||
break;
|
||||
case INDEX_op_qemu_ld32s:
|
||||
tcg_out_qemu_ld(s, args, MO_TESL);
|
||||
break;
|
||||
case INDEX_op_qemu_ld64:
|
||||
tcg_out_qemu_ld(s, args, MO_TEQ);
|
||||
break;
|
||||
|
||||
case INDEX_op_qemu_st8:
|
||||
tcg_out_qemu_st(s, args, MO_UB);
|
||||
break;
|
||||
case INDEX_op_qemu_st16:
|
||||
tcg_out_qemu_st(s, args, MO_TEUW);
|
||||
break;
|
||||
case INDEX_op_qemu_st32:
|
||||
tcg_out_qemu_st(s, args, MO_TEUL);
|
||||
break;
|
||||
case INDEX_op_qemu_st64:
|
||||
tcg_out_qemu_st(s, args, MO_TEQ);
|
||||
case INDEX_op_qemu_st_i64:
|
||||
tcg_out_qemu_st(s, args);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -2381,19 +2420,10 @@ static const TCGTargetOpDef ia64_op_defs[] = {
|
||||
{ INDEX_op_deposit_i32, { "r", "rZ", "ri" } },
|
||||
{ INDEX_op_deposit_i64, { "r", "rZ", "ri" } },
|
||||
|
||||
{ INDEX_op_qemu_ld8u, { "r", "r" } },
|
||||
{ INDEX_op_qemu_ld8s, { "r", "r" } },
|
||||
{ INDEX_op_qemu_ld16u, { "r", "r" } },
|
||||
{ INDEX_op_qemu_ld16s, { "r", "r" } },
|
||||
{ INDEX_op_qemu_ld32, { "r", "r" } },
|
||||
{ INDEX_op_qemu_ld32u, { "r", "r" } },
|
||||
{ INDEX_op_qemu_ld32s, { "r", "r" } },
|
||||
{ INDEX_op_qemu_ld64, { "r", "r" } },
|
||||
|
||||
{ INDEX_op_qemu_st8, { "SZ", "r" } },
|
||||
{ INDEX_op_qemu_st16, { "SZ", "r" } },
|
||||
{ INDEX_op_qemu_st32, { "SZ", "r" } },
|
||||
{ INDEX_op_qemu_st64, { "SZ", "r" } },
|
||||
{ INDEX_op_qemu_ld_i32, { "r", "r" } },
|
||||
{ INDEX_op_qemu_ld_i64, { "r", "r" } },
|
||||
{ INDEX_op_qemu_st_i32, { "SZ", "r" } },
|
||||
{ INDEX_op_qemu_st_i64, { "SZ", "r" } },
|
||||
|
||||
{ -1 },
|
||||
};
|
||||
|
||||
@@ -153,7 +153,7 @@ typedef enum {
|
||||
#define TCG_TARGET_HAS_mulsh_i32 0
|
||||
#define TCG_TARGET_HAS_mulsh_i64 0
|
||||
|
||||
#define TCG_TARGET_HAS_new_ldst 0
|
||||
#define TCG_TARGET_HAS_new_ldst 1
|
||||
|
||||
#define TCG_TARGET_deposit_i32_valid(ofs, len) ((len) <= 16)
|
||||
#define TCG_TARGET_deposit_i64_valid(ofs, len) ((len) <= 16)
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
#include "tcg-be-null.h"
|
||||
|
||||
#if defined(TCG_TARGET_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
|
||||
#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
|
||||
# define TCG_NEED_BSWAP 0
|
||||
#else
|
||||
# define TCG_NEED_BSWAP 1
|
||||
@@ -253,7 +253,7 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
|
||||
}
|
||||
|
||||
/* test if a constant matches the constraint */
|
||||
static inline int tcg_target_const_match(tcg_target_long val,
|
||||
static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
|
||||
const TCGArgConstraint *arg_ct)
|
||||
{
|
||||
int ct;
|
||||
@@ -589,7 +589,7 @@ static inline void tcg_out_call_iarg_reg64(TCGContext *s, int *arg_num,
|
||||
{
|
||||
(*arg_num) = (*arg_num + 1) & ~1;
|
||||
|
||||
#if defined(TCG_TARGET_WORDS_BIGENDIAN)
|
||||
#if defined(HOST_WORDS_BIGENDIAN)
|
||||
tcg_out_call_iarg_reg32(s, arg_num, arg_high);
|
||||
tcg_out_call_iarg_reg32(s, arg_num, arg_low);
|
||||
#else
|
||||
@@ -964,7 +964,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
|
||||
#if defined(CONFIG_SOFTMMU)
|
||||
# if TARGET_LONG_BITS == 64
|
||||
addr_regh = *args++;
|
||||
# if defined(TCG_TARGET_WORDS_BIGENDIAN)
|
||||
# if defined(HOST_WORDS_BIGENDIAN)
|
||||
addr_memh = 0;
|
||||
addr_meml = 4;
|
||||
# else
|
||||
@@ -979,7 +979,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
|
||||
#endif
|
||||
|
||||
if (opc == 3) {
|
||||
#if defined(TCG_TARGET_WORDS_BIGENDIAN)
|
||||
#if defined(HOST_WORDS_BIGENDIAN)
|
||||
data_reg1 = data_regh;
|
||||
data_reg2 = data_regl;
|
||||
#else
|
||||
@@ -1152,7 +1152,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
|
||||
#if defined(CONFIG_SOFTMMU)
|
||||
# if TARGET_LONG_BITS == 64
|
||||
addr_regh = *args++;
|
||||
# if defined(TCG_TARGET_WORDS_BIGENDIAN)
|
||||
# if defined(HOST_WORDS_BIGENDIAN)
|
||||
addr_memh = 0;
|
||||
addr_meml = 4;
|
||||
# else
|
||||
@@ -1167,7 +1167,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
|
||||
#endif
|
||||
|
||||
if (opc == 3) {
|
||||
#if defined(TCG_TARGET_WORDS_BIGENDIAN)
|
||||
#if defined(HOST_WORDS_BIGENDIAN)
|
||||
data_reg1 = data_regh;
|
||||
data_reg2 = data_regl;
|
||||
#else
|
||||
|
||||
@@ -26,10 +26,6 @@
|
||||
#ifndef TCG_TARGET_MIPS
|
||||
#define TCG_TARGET_MIPS 1
|
||||
|
||||
#ifdef __MIPSEB__
|
||||
# define TCG_TARGET_WORDS_BIGENDIAN
|
||||
#endif
|
||||
|
||||
#define TCG_TARGET_NB_REGS 32
|
||||
|
||||
typedef enum {
|
||||
@@ -109,6 +105,7 @@ extern bool use_mips32r2_instructions;
|
||||
#define TCG_TARGET_HAS_orc_i32 0
|
||||
#define TCG_TARGET_HAS_eqv_i32 0
|
||||
#define TCG_TARGET_HAS_nand_i32 0
|
||||
#define TCG_TARGET_HAS_mulu2_i32 1
|
||||
#define TCG_TARGET_HAS_muls2_i32 1
|
||||
#define TCG_TARGET_HAS_muluh_i32 1
|
||||
#define TCG_TARGET_HAS_mulsh_i32 1
|
||||
|
||||
@@ -220,34 +220,34 @@ static TCGArg do_constant_folding_2(TCGOpcode op, TCGArg x, TCGArg y)
|
||||
return x ^ y;
|
||||
|
||||
case INDEX_op_shl_i32:
|
||||
return (uint32_t)x << (uint32_t)y;
|
||||
return (uint32_t)x << (y & 31);
|
||||
|
||||
case INDEX_op_shl_i64:
|
||||
return (uint64_t)x << (uint64_t)y;
|
||||
return (uint64_t)x << (y & 63);
|
||||
|
||||
case INDEX_op_shr_i32:
|
||||
return (uint32_t)x >> (uint32_t)y;
|
||||
return (uint32_t)x >> (y & 31);
|
||||
|
||||
case INDEX_op_shr_i64:
|
||||
return (uint64_t)x >> (uint64_t)y;
|
||||
return (uint64_t)x >> (y & 63);
|
||||
|
||||
case INDEX_op_sar_i32:
|
||||
return (int32_t)x >> (int32_t)y;
|
||||
return (int32_t)x >> (y & 31);
|
||||
|
||||
case INDEX_op_sar_i64:
|
||||
return (int64_t)x >> (int64_t)y;
|
||||
return (int64_t)x >> (y & 63);
|
||||
|
||||
case INDEX_op_rotr_i32:
|
||||
return ror32(x, y);
|
||||
return ror32(x, y & 31);
|
||||
|
||||
case INDEX_op_rotr_i64:
|
||||
return ror64(x, y);
|
||||
return ror64(x, y & 63);
|
||||
|
||||
case INDEX_op_rotl_i32:
|
||||
return rol32(x, y);
|
||||
return rol32(x, y & 31);
|
||||
|
||||
case INDEX_op_rotl_i64:
|
||||
return rol64(x, y);
|
||||
return rol64(x, y & 63);
|
||||
|
||||
CASE_OP_32_64(not):
|
||||
return ~x;
|
||||
@@ -806,29 +806,34 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
|
||||
|
||||
case INDEX_op_sar_i32:
|
||||
if (temps[args[2]].state == TCG_TEMP_CONST) {
|
||||
mask = (int32_t)temps[args[1]].mask >> temps[args[2]].val;
|
||||
tmp = temps[args[2]].val & 31;
|
||||
mask = (int32_t)temps[args[1]].mask >> tmp;
|
||||
}
|
||||
break;
|
||||
case INDEX_op_sar_i64:
|
||||
if (temps[args[2]].state == TCG_TEMP_CONST) {
|
||||
mask = (int64_t)temps[args[1]].mask >> temps[args[2]].val;
|
||||
tmp = temps[args[2]].val & 63;
|
||||
mask = (int64_t)temps[args[1]].mask >> tmp;
|
||||
}
|
||||
break;
|
||||
|
||||
case INDEX_op_shr_i32:
|
||||
if (temps[args[2]].state == TCG_TEMP_CONST) {
|
||||
mask = (uint32_t)temps[args[1]].mask >> temps[args[2]].val;
|
||||
tmp = temps[args[2]].val & 31;
|
||||
mask = (uint32_t)temps[args[1]].mask >> tmp;
|
||||
}
|
||||
break;
|
||||
case INDEX_op_shr_i64:
|
||||
if (temps[args[2]].state == TCG_TEMP_CONST) {
|
||||
mask = (uint64_t)temps[args[1]].mask >> temps[args[2]].val;
|
||||
tmp = temps[args[2]].val & 63;
|
||||
mask = (uint64_t)temps[args[1]].mask >> tmp;
|
||||
}
|
||||
break;
|
||||
|
||||
CASE_OP_32_64(shl):
|
||||
if (temps[args[2]].state == TCG_TEMP_CONST) {
|
||||
mask = temps[args[1]].mask << temps[args[2]].val;
|
||||
tmp = temps[args[2]].val & (TCG_TARGET_REG_BITS - 1);
|
||||
mask = temps[args[1]].mask << tmp;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -838,9 +843,8 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
|
||||
break;
|
||||
|
||||
CASE_OP_32_64(deposit):
|
||||
tmp = ((1ull << args[4]) - 1);
|
||||
mask = ((temps[args[1]].mask & ~(tmp << args[3]))
|
||||
| ((temps[args[2]].mask & tmp) << args[3]));
|
||||
mask = deposit64(temps[args[1]].mask, args[3], args[4],
|
||||
temps[args[2]].mask);
|
||||
break;
|
||||
|
||||
CASE_OP_32_64(or):
|
||||
@@ -1055,9 +1059,8 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
|
||||
if (temps[args[1]].state == TCG_TEMP_CONST
|
||||
&& temps[args[2]].state == TCG_TEMP_CONST) {
|
||||
s->gen_opc_buf[op_index] = op_to_movi(op);
|
||||
tmp = ((1ull << args[4]) - 1);
|
||||
tmp = (temps[args[1]].val & ~(tmp << args[3]))
|
||||
| ((temps[args[2]].val & tmp) << args[3]);
|
||||
tmp = deposit64(temps[args[1]].val, args[3], args[4],
|
||||
temps[args[2]].val);
|
||||
tcg_opt_gen_movi(gen_args, args[0], tmp);
|
||||
gen_args += 2;
|
||||
args += 5;
|
||||
|
||||
@@ -298,7 +298,7 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
|
||||
}
|
||||
|
||||
/* test if a constant matches the constraint */
|
||||
static int tcg_target_const_match(tcg_target_long val,
|
||||
static int tcg_target_const_match(tcg_target_long val, TCGType type,
|
||||
const TCGArgConstraint *arg_ct)
|
||||
{
|
||||
int ct;
|
||||
@@ -524,7 +524,7 @@ static void tcg_out_call (TCGContext *s, tcg_target_long arg, int const_arg,
|
||||
#if defined(CONFIG_SOFTMMU)
|
||||
|
||||
static void add_qemu_ldst_label (TCGContext *s,
|
||||
int is_ld,
|
||||
bool is_ld,
|
||||
TCGMemOp opc,
|
||||
int data_reg,
|
||||
int data_reg2,
|
||||
@@ -720,7 +720,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64)
|
||||
break;
|
||||
}
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
add_qemu_ldst_label(s, 1, opc, datalo, datahi, addrlo,
|
||||
add_qemu_ldst_label(s, true, opc, datalo, datahi, addrlo,
|
||||
addrhi, mem_index, s->code_ptr, label_ptr);
|
||||
#endif
|
||||
}
|
||||
@@ -779,7 +779,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
add_qemu_ldst_label(s, 0, opc, datalo, datahi, addrlo, addrhi,
|
||||
add_qemu_ldst_label(s, false, opc, datalo, datahi, addrlo, addrhi,
|
||||
mem_index, s->code_ptr, label_ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#ifndef TCG_TARGET_PPC
|
||||
#define TCG_TARGET_PPC 1
|
||||
|
||||
#define TCG_TARGET_WORDS_BIGENDIAN
|
||||
#define TCG_TARGET_NB_REGS 32
|
||||
|
||||
typedef enum {
|
||||
@@ -95,6 +94,7 @@ typedef enum {
|
||||
#define TCG_TARGET_HAS_nor_i32 1
|
||||
#define TCG_TARGET_HAS_deposit_i32 1
|
||||
#define TCG_TARGET_HAS_movcond_i32 1
|
||||
#define TCG_TARGET_HAS_mulu2_i32 1
|
||||
#define TCG_TARGET_HAS_muls2_i32 0
|
||||
#define TCG_TARGET_HAS_muluh_i32 0
|
||||
#define TCG_TARGET_HAS_mulsh_i32 0
|
||||
|
||||
@@ -290,13 +290,21 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
|
||||
}
|
||||
|
||||
/* test if a constant matches the constraint */
|
||||
static int tcg_target_const_match(tcg_target_long val,
|
||||
static int tcg_target_const_match(tcg_target_long val, TCGType type,
|
||||
const TCGArgConstraint *arg_ct)
|
||||
{
|
||||
int ct = arg_ct->ct;
|
||||
if (ct & TCG_CT_CONST) {
|
||||
return 1;
|
||||
} else if ((ct & TCG_CT_CONST_S16) && val == (int16_t)val) {
|
||||
}
|
||||
|
||||
/* The only 32-bit constraint we use aside from
|
||||
TCG_CT_CONST is TCG_CT_CONST_S16. */
|
||||
if (type == TCG_TYPE_I32) {
|
||||
val = (int32_t)val;
|
||||
}
|
||||
|
||||
if ((ct & TCG_CT_CONST_S16) && val == (int16_t)val) {
|
||||
return 1;
|
||||
} else if ((ct & TCG_CT_CONST_U16) && val == (uint16_t)val) {
|
||||
return 1;
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#ifndef TCG_TARGET_PPC64
|
||||
#define TCG_TARGET_PPC64 1
|
||||
|
||||
#define TCG_TARGET_WORDS_BIGENDIAN
|
||||
#define TCG_TARGET_NB_REGS 32
|
||||
|
||||
typedef enum {
|
||||
|
||||
@@ -38,11 +38,10 @@
|
||||
a 32-bit displacement here Just In Case. */
|
||||
#define USE_LONG_BRANCHES 0
|
||||
|
||||
#define TCG_CT_CONST_32 0x0100
|
||||
#define TCG_CT_CONST_MULI 0x0800
|
||||
#define TCG_CT_CONST_ORI 0x2000
|
||||
#define TCG_CT_CONST_XORI 0x4000
|
||||
#define TCG_CT_CONST_CMPI 0x8000
|
||||
#define TCG_CT_CONST_MULI 0x100
|
||||
#define TCG_CT_CONST_ORI 0x200
|
||||
#define TCG_CT_CONST_XORI 0x400
|
||||
#define TCG_CT_CONST_CMPI 0x800
|
||||
|
||||
/* Several places within the instruction set 0 means "no register"
|
||||
rather than TCG_REG_R0. */
|
||||
@@ -407,9 +406,6 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
|
||||
tcg_regset_clear(ct->u.regs);
|
||||
tcg_regset_set_reg(ct->u.regs, TCG_REG_R3);
|
||||
break;
|
||||
case 'W': /* force 32-bit ("word") immediate */
|
||||
ct->ct |= TCG_CT_CONST_32;
|
||||
break;
|
||||
case 'K':
|
||||
ct->ct |= TCG_CT_CONST_MULI;
|
||||
break;
|
||||
@@ -437,10 +433,10 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
|
||||
can load efficiently, and the immediate load plus the reg-reg OR is
|
||||
smaller than the sequential OI's. */
|
||||
|
||||
static int tcg_match_ori(int ct, tcg_target_long val)
|
||||
static int tcg_match_ori(TCGType type, tcg_target_long val)
|
||||
{
|
||||
if (facilities & FACILITY_EXT_IMM) {
|
||||
if (ct & TCG_CT_CONST_32) {
|
||||
if (type == TCG_TYPE_I32) {
|
||||
/* All 32-bit ORs can be performed with 1 48-bit insn. */
|
||||
return 1;
|
||||
}
|
||||
@@ -466,13 +462,13 @@ static int tcg_match_ori(int ct, tcg_target_long val)
|
||||
extended-immediate facility. That said, there are a few patterns for
|
||||
which it is better to load the value into a register first. */
|
||||
|
||||
static int tcg_match_xori(int ct, tcg_target_long val)
|
||||
static int tcg_match_xori(TCGType type, tcg_target_long val)
|
||||
{
|
||||
if ((facilities & FACILITY_EXT_IMM) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ct & TCG_CT_CONST_32) {
|
||||
if (type == TCG_TYPE_I32) {
|
||||
/* All 32-bit XORs can be performed with 1 48-bit insn. */
|
||||
return 1;
|
||||
}
|
||||
@@ -487,11 +483,11 @@ static int tcg_match_xori(int ct, tcg_target_long val)
|
||||
|
||||
/* Imediates to be used with comparisons. */
|
||||
|
||||
static int tcg_match_cmpi(int ct, tcg_target_long val)
|
||||
static int tcg_match_cmpi(TCGType type, tcg_target_long val)
|
||||
{
|
||||
if (facilities & FACILITY_EXT_IMM) {
|
||||
/* The COMPARE IMMEDIATE instruction is available. */
|
||||
if (ct & TCG_CT_CONST_32) {
|
||||
if (type == TCG_TYPE_I32) {
|
||||
/* We have a 32-bit immediate and can compare against anything. */
|
||||
return 1;
|
||||
} else {
|
||||
@@ -515,7 +511,7 @@ static int tcg_match_cmpi(int ct, tcg_target_long val)
|
||||
}
|
||||
|
||||
/* Test if a constant matches the constraint. */
|
||||
static int tcg_target_const_match(tcg_target_long val,
|
||||
static int tcg_target_const_match(tcg_target_long val, TCGType type,
|
||||
const TCGArgConstraint *arg_ct)
|
||||
{
|
||||
int ct = arg_ct->ct;
|
||||
@@ -524,8 +520,7 @@ static int tcg_target_const_match(tcg_target_long val,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Handle the modifiers. */
|
||||
if (ct & TCG_CT_CONST_32) {
|
||||
if (type == TCG_TYPE_I32) {
|
||||
val = (int32_t)val;
|
||||
}
|
||||
|
||||
@@ -541,11 +536,11 @@ static int tcg_target_const_match(tcg_target_long val,
|
||||
return val == (int16_t)val;
|
||||
}
|
||||
} else if (ct & TCG_CT_CONST_ORI) {
|
||||
return tcg_match_ori(ct, val);
|
||||
return tcg_match_ori(type, val);
|
||||
} else if (ct & TCG_CT_CONST_XORI) {
|
||||
return tcg_match_xori(ct, val);
|
||||
return tcg_match_xori(type, val);
|
||||
} else if (ct & TCG_CT_CONST_CMPI) {
|
||||
return tcg_match_cmpi(ct, val);
|
||||
return tcg_match_cmpi(type, val);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -2112,8 +2107,8 @@ static const TCGTargetOpDef s390_op_defs[] = {
|
||||
{ INDEX_op_divu2_i32, { "b", "a", "0", "1", "r" } },
|
||||
|
||||
{ INDEX_op_and_i32, { "r", "0", "ri" } },
|
||||
{ INDEX_op_or_i32, { "r", "0", "rWO" } },
|
||||
{ INDEX_op_xor_i32, { "r", "0", "rWX" } },
|
||||
{ INDEX_op_or_i32, { "r", "0", "rO" } },
|
||||
{ INDEX_op_xor_i32, { "r", "0", "rX" } },
|
||||
|
||||
{ INDEX_op_neg_i32, { "r", "r" } },
|
||||
|
||||
@@ -2135,9 +2130,9 @@ static const TCGTargetOpDef s390_op_defs[] = {
|
||||
{ INDEX_op_add2_i32, { "r", "r", "0", "1", "r", "r" } },
|
||||
{ INDEX_op_sub2_i32, { "r", "r", "0", "1", "r", "r" } },
|
||||
|
||||
{ INDEX_op_brcond_i32, { "r", "rWC" } },
|
||||
{ INDEX_op_setcond_i32, { "r", "r", "rWC" } },
|
||||
{ INDEX_op_movcond_i32, { "r", "r", "rWC", "r", "0" } },
|
||||
{ INDEX_op_brcond_i32, { "r", "rC" } },
|
||||
{ INDEX_op_setcond_i32, { "r", "r", "rC" } },
|
||||
{ INDEX_op_movcond_i32, { "r", "r", "rC", "r", "0" } },
|
||||
{ INDEX_op_deposit_i32, { "r", "0", "r" } },
|
||||
|
||||
{ INDEX_op_qemu_ld8u, { "r", "L" } },
|
||||
|
||||
@@ -24,8 +24,6 @@
|
||||
#ifndef TCG_TARGET_S390
|
||||
#define TCG_TARGET_S390 1
|
||||
|
||||
#define TCG_TARGET_WORDS_BIGENDIAN
|
||||
|
||||
typedef enum TCGReg {
|
||||
TCG_REG_R0 = 0,
|
||||
TCG_REG_R1,
|
||||
|
||||
@@ -327,14 +327,20 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
|
||||
}
|
||||
|
||||
/* test if a constant matches the constraint */
|
||||
static inline int tcg_target_const_match(tcg_target_long val,
|
||||
static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
|
||||
const TCGArgConstraint *arg_ct)
|
||||
{
|
||||
int ct = arg_ct->ct;
|
||||
|
||||
if (ct & TCG_CT_CONST) {
|
||||
return 1;
|
||||
} else if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
|
||||
}
|
||||
|
||||
if (type == TCG_TYPE_I32) {
|
||||
val = (int32_t)val;
|
||||
}
|
||||
|
||||
if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
|
||||
return 1;
|
||||
} else if ((ct & TCG_CT_CONST_S11) && check_fit_tl(val, 11)) {
|
||||
return 1;
|
||||
|
||||
@@ -32,8 +32,6 @@
|
||||
# error Unknown pointer size for tcg target
|
||||
#endif
|
||||
|
||||
#define TCG_TARGET_WORDS_BIGENDIAN
|
||||
|
||||
#define TCG_TARGET_NB_REGS 32
|
||||
|
||||
typedef enum {
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#define TCG_MAX_QEMU_LDST 640
|
||||
|
||||
typedef struct TCGLabelQemuLdst {
|
||||
int is_ld:1; /* qemu_ld: 1, qemu_st: 0 */
|
||||
bool is_ld:1; /* qemu_ld: true, qemu_st: false */
|
||||
TCGMemOp opc:4;
|
||||
TCGReg addrlo_reg; /* reg index for low word of guest virtual addr */
|
||||
TCGReg addrhi_reg; /* reg index for high word of guest virtual addr */
|
||||
|
||||
48
tcg/tcg-op.h
48
tcg/tcg-op.h
@@ -858,7 +858,7 @@ static inline void tcg_gen_ld_i64(TCGv_i64 ret, TCGv_ptr arg2,
|
||||
{
|
||||
/* since arg2 and ret have different types, they cannot be the
|
||||
same temporary */
|
||||
#ifdef TCG_TARGET_WORDS_BIGENDIAN
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset);
|
||||
tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset + 4);
|
||||
#else
|
||||
@@ -888,7 +888,7 @@ static inline void tcg_gen_st32_i64(TCGv_i64 arg1, TCGv_ptr arg2,
|
||||
static inline void tcg_gen_st_i64(TCGv_i64 arg1, TCGv_ptr arg2,
|
||||
tcg_target_long offset)
|
||||
{
|
||||
#ifdef TCG_TARGET_WORDS_BIGENDIAN
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset);
|
||||
tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset + 4);
|
||||
#else
|
||||
@@ -2437,14 +2437,12 @@ static inline void tcg_gen_muls2_i32(TCGv_i32 rl, TCGv_i32 rh,
|
||||
tcg_gen_op3_i32(INDEX_op_mulsh_i32, rh, arg1, arg2);
|
||||
tcg_gen_mov_i32(rl, t);
|
||||
tcg_temp_free_i32(t);
|
||||
} else if (TCG_TARGET_REG_BITS == 32 && TCG_TARGET_HAS_mulu2_i32) {
|
||||
} else if (TCG_TARGET_REG_BITS == 32) {
|
||||
TCGv_i32 t0 = tcg_temp_new_i32();
|
||||
TCGv_i32 t1 = tcg_temp_new_i32();
|
||||
TCGv_i32 t2 = tcg_temp_new_i32();
|
||||
TCGv_i32 t3 = tcg_temp_new_i32();
|
||||
tcg_gen_op4_i32(INDEX_op_mulu2_i32, t0, t1, arg1, arg2);
|
||||
/* Allow the optimizer room to replace mulu2 with two moves. */
|
||||
tcg_gen_op0(INDEX_op_nop);
|
||||
tcg_gen_mulu2_i32(t0, t1, arg1, arg2);
|
||||
/* Adjust for negative inputs. */
|
||||
tcg_gen_sari_i32(t2, arg1, 31);
|
||||
tcg_gen_sari_i32(t3, arg2, 31);
|
||||
@@ -2522,26 +2520,6 @@ static inline void tcg_gen_mulu2_i64(TCGv_i64 rl, TCGv_i64 rh,
|
||||
tcg_gen_op3_i64(INDEX_op_muluh_i64, rh, arg1, arg2);
|
||||
tcg_gen_mov_i64(rl, t);
|
||||
tcg_temp_free_i64(t);
|
||||
} else if (TCG_TARGET_HAS_mulu2_i64) {
|
||||
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||
TCGv_i64 t1 = tcg_temp_new_i64();
|
||||
TCGv_i64 t2 = tcg_temp_new_i64();
|
||||
TCGv_i64 t3 = tcg_temp_new_i64();
|
||||
tcg_gen_op4_i64(INDEX_op_mulu2_i64, t0, t1, arg1, arg2);
|
||||
/* Allow the optimizer room to replace mulu2 with two moves. */
|
||||
tcg_gen_op0(INDEX_op_nop);
|
||||
/* Adjust for negative inputs. */
|
||||
tcg_gen_sari_i64(t2, arg1, 63);
|
||||
tcg_gen_sari_i64(t3, arg2, 63);
|
||||
tcg_gen_and_i64(t2, t2, arg2);
|
||||
tcg_gen_and_i64(t3, t3, arg1);
|
||||
tcg_gen_sub_i64(rh, t1, t2);
|
||||
tcg_gen_sub_i64(rh, rh, t3);
|
||||
tcg_gen_mov_i64(rl, t0);
|
||||
tcg_temp_free_i64(t0);
|
||||
tcg_temp_free_i64(t1);
|
||||
tcg_temp_free_i64(t2);
|
||||
tcg_temp_free_i64(t3);
|
||||
} else {
|
||||
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||
int sizemask = 0;
|
||||
@@ -2569,6 +2547,24 @@ static inline void tcg_gen_muls2_i64(TCGv_i64 rl, TCGv_i64 rh,
|
||||
tcg_gen_op3_i64(INDEX_op_mulsh_i64, rh, arg1, arg2);
|
||||
tcg_gen_mov_i64(rl, t);
|
||||
tcg_temp_free_i64(t);
|
||||
} else if (TCG_TARGET_HAS_mulu2_i64 || TCG_TARGET_HAS_muluh_i64) {
|
||||
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||
TCGv_i64 t1 = tcg_temp_new_i64();
|
||||
TCGv_i64 t2 = tcg_temp_new_i64();
|
||||
TCGv_i64 t3 = tcg_temp_new_i64();
|
||||
tcg_gen_mulu2_i64(t0, t1, arg1, arg2);
|
||||
/* Adjust for negative inputs. */
|
||||
tcg_gen_sari_i64(t2, arg1, 63);
|
||||
tcg_gen_sari_i64(t3, arg2, 63);
|
||||
tcg_gen_and_i64(t2, t2, arg2);
|
||||
tcg_gen_and_i64(t3, t3, arg1);
|
||||
tcg_gen_sub_i64(rh, t1, t2);
|
||||
tcg_gen_sub_i64(rh, rh, t3);
|
||||
tcg_gen_mov_i64(rl, t0);
|
||||
tcg_temp_free_i64(t0);
|
||||
tcg_temp_free_i64(t1);
|
||||
tcg_temp_free_i64(t2);
|
||||
tcg_temp_free_i64(t3);
|
||||
} else {
|
||||
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||
int sizemask = 0;
|
||||
|
||||
14
tcg/tcg.c
14
tcg/tcg.c
@@ -101,7 +101,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
|
||||
const int *const_args);
|
||||
static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
|
||||
intptr_t arg2);
|
||||
static int tcg_target_const_match(tcg_target_long val,
|
||||
static int tcg_target_const_match(tcg_target_long val, TCGType type,
|
||||
const TCGArgConstraint *arg_ct);
|
||||
static void tcg_out_tb_init(TCGContext *s);
|
||||
static void tcg_out_tb_finalize(TCGContext *s);
|
||||
@@ -444,7 +444,7 @@ static inline int tcg_global_mem_new_internal(TCGType type, int reg,
|
||||
ts->fixed_reg = 0;
|
||||
ts->mem_allocated = 1;
|
||||
ts->mem_reg = reg;
|
||||
#ifdef TCG_TARGET_WORDS_BIGENDIAN
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
ts->mem_offset = offset + 4;
|
||||
#else
|
||||
ts->mem_offset = offset;
|
||||
@@ -459,7 +459,7 @@ static inline int tcg_global_mem_new_internal(TCGType type, int reg,
|
||||
ts->fixed_reg = 0;
|
||||
ts->mem_allocated = 1;
|
||||
ts->mem_reg = reg;
|
||||
#ifdef TCG_TARGET_WORDS_BIGENDIAN
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
ts->mem_offset = offset;
|
||||
#else
|
||||
ts->mem_offset = offset + 4;
|
||||
@@ -686,7 +686,7 @@ void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
|
||||
if (ret != TCG_CALL_DUMMY_ARG) {
|
||||
#if TCG_TARGET_REG_BITS < 64
|
||||
if (sizemask & 1) {
|
||||
#ifdef TCG_TARGET_WORDS_BIGENDIAN
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
*s->gen_opparam_ptr++ = ret + 1;
|
||||
*s->gen_opparam_ptr++ = ret;
|
||||
#else
|
||||
@@ -725,7 +725,7 @@ void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
|
||||
order. If another such target is added, this logic may
|
||||
have to get more complicated to differentiate between
|
||||
stack arguments and register arguments. */
|
||||
#if defined(TCG_TARGET_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
|
||||
#if defined(HOST_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
|
||||
*s->gen_opparam_ptr++ = args[i] + 1;
|
||||
*s->gen_opparam_ptr++ = args[i];
|
||||
#else
|
||||
@@ -2121,7 +2121,7 @@ static void tcg_reg_alloc_op(TCGContext *s,
|
||||
ts->mem_coherent = 1;
|
||||
s->reg_to_temp[reg] = arg;
|
||||
} else if (ts->val_type == TEMP_VAL_CONST) {
|
||||
if (tcg_target_const_match(ts->val, arg_ct)) {
|
||||
if (tcg_target_const_match(ts->val, ts->type, arg_ct)) {
|
||||
/* constant is OK for instruction */
|
||||
const_args[i] = 1;
|
||||
new_args[i] = ts->val;
|
||||
@@ -2365,7 +2365,7 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
|
||||
func_arg = reg;
|
||||
tcg_regset_set_reg(allocated_regs, reg);
|
||||
} else if (ts->val_type == TEMP_VAL_CONST) {
|
||||
if (tcg_target_const_match(func_addr, arg_ct)) {
|
||||
if (tcg_target_const_match(func_addr, ts->type, arg_ct)) {
|
||||
const_func_arg = 1;
|
||||
func_arg = func_addr;
|
||||
} else {
|
||||
|
||||
@@ -97,7 +97,6 @@ typedef uint64_t TCGRegSet;
|
||||
/* Turn some undef macros into true macros. */
|
||||
#define TCG_TARGET_HAS_add2_i32 1
|
||||
#define TCG_TARGET_HAS_sub2_i32 1
|
||||
#define TCG_TARGET_HAS_mulu2_i32 1
|
||||
#endif
|
||||
|
||||
#ifndef TCG_TARGET_deposit_i32_valid
|
||||
@@ -121,6 +120,13 @@ typedef uint64_t TCGRegSet;
|
||||
#define TCG_TARGET_HAS_rem_i64 0
|
||||
#endif
|
||||
|
||||
/* For 32-bit targets, some sort of unsigned widening multiply is required. */
|
||||
#if TCG_TARGET_REG_BITS == 32 \
|
||||
&& !(defined(TCG_TARGET_HAS_mulu2_i32) \
|
||||
|| defined(TCG_TARGET_HAS_muluh_i32))
|
||||
# error "Missing unsigned widening multiply"
|
||||
#endif
|
||||
|
||||
typedef enum TCGOpcode {
|
||||
#define DEF(name, oargs, iargs, cargs, flags) INDEX_op_ ## name,
|
||||
#include "tcg-opc.h"
|
||||
|
||||
@@ -859,7 +859,7 @@ static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
|
||||
}
|
||||
|
||||
/* Test if a constant matches the constraint. */
|
||||
static int tcg_target_const_match(tcg_target_long val,
|
||||
static int tcg_target_const_match(tcg_target_long val, TCGType type,
|
||||
const TCGArgConstraint *arg_ct)
|
||||
{
|
||||
/* No need to return 0 or 1, 0 or != 0 is good enough. */
|
||||
|
||||
@@ -57,12 +57,6 @@
|
||||
#define CONFIG_DEBUG_TCG_INTERPRETER
|
||||
#endif
|
||||
|
||||
#if 0 /* TCI tries to emulate a little endian host. */
|
||||
#if defined(HOST_WORDS_BIGENDIAN)
|
||||
# define TCG_TARGET_WORDS_BIGENDIAN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Optional instructions. */
|
||||
|
||||
#define TCG_TARGET_HAS_bswap16_i32 1
|
||||
@@ -118,6 +112,8 @@
|
||||
#define TCG_TARGET_HAS_mulu2_i64 0
|
||||
#define TCG_TARGET_HAS_muluh_i64 0
|
||||
#define TCG_TARGET_HAS_mulsh_i64 0
|
||||
#else
|
||||
#define TCG_TARGET_HAS_mulu2_i32 1
|
||||
#endif /* TCG_TARGET_REG_BITS == 64 */
|
||||
|
||||
#define TCG_TARGET_HAS_new_ldst 0
|
||||
|
||||
20
tci.c
20
tci.c
@@ -669,32 +669,32 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr)
|
||||
t0 = *tb_ptr++;
|
||||
t1 = tci_read_ri32(&tb_ptr);
|
||||
t2 = tci_read_ri32(&tb_ptr);
|
||||
tci_write_reg32(t0, t1 << t2);
|
||||
tci_write_reg32(t0, t1 << (t2 & 31));
|
||||
break;
|
||||
case INDEX_op_shr_i32:
|
||||
t0 = *tb_ptr++;
|
||||
t1 = tci_read_ri32(&tb_ptr);
|
||||
t2 = tci_read_ri32(&tb_ptr);
|
||||
tci_write_reg32(t0, t1 >> t2);
|
||||
tci_write_reg32(t0, t1 >> (t2 & 31));
|
||||
break;
|
||||
case INDEX_op_sar_i32:
|
||||
t0 = *tb_ptr++;
|
||||
t1 = tci_read_ri32(&tb_ptr);
|
||||
t2 = tci_read_ri32(&tb_ptr);
|
||||
tci_write_reg32(t0, ((int32_t)t1 >> t2));
|
||||
tci_write_reg32(t0, ((int32_t)t1 >> (t2 & 31)));
|
||||
break;
|
||||
#if TCG_TARGET_HAS_rot_i32
|
||||
case INDEX_op_rotl_i32:
|
||||
t0 = *tb_ptr++;
|
||||
t1 = tci_read_ri32(&tb_ptr);
|
||||
t2 = tci_read_ri32(&tb_ptr);
|
||||
tci_write_reg32(t0, rol32(t1, t2));
|
||||
tci_write_reg32(t0, rol32(t1, t2 & 31));
|
||||
break;
|
||||
case INDEX_op_rotr_i32:
|
||||
t0 = *tb_ptr++;
|
||||
t1 = tci_read_ri32(&tb_ptr);
|
||||
t2 = tci_read_ri32(&tb_ptr);
|
||||
tci_write_reg32(t0, ror32(t1, t2));
|
||||
tci_write_reg32(t0, ror32(t1, t2 & 31));
|
||||
break;
|
||||
#endif
|
||||
#if TCG_TARGET_HAS_deposit_i32
|
||||
@@ -936,32 +936,32 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr)
|
||||
t0 = *tb_ptr++;
|
||||
t1 = tci_read_ri64(&tb_ptr);
|
||||
t2 = tci_read_ri64(&tb_ptr);
|
||||
tci_write_reg64(t0, t1 << t2);
|
||||
tci_write_reg64(t0, t1 << (t2 & 63));
|
||||
break;
|
||||
case INDEX_op_shr_i64:
|
||||
t0 = *tb_ptr++;
|
||||
t1 = tci_read_ri64(&tb_ptr);
|
||||
t2 = tci_read_ri64(&tb_ptr);
|
||||
tci_write_reg64(t0, t1 >> t2);
|
||||
tci_write_reg64(t0, t1 >> (t2 & 63));
|
||||
break;
|
||||
case INDEX_op_sar_i64:
|
||||
t0 = *tb_ptr++;
|
||||
t1 = tci_read_ri64(&tb_ptr);
|
||||
t2 = tci_read_ri64(&tb_ptr);
|
||||
tci_write_reg64(t0, ((int64_t)t1 >> t2));
|
||||
tci_write_reg64(t0, ((int64_t)t1 >> (t2 & 63)));
|
||||
break;
|
||||
#if TCG_TARGET_HAS_rot_i64
|
||||
case INDEX_op_rotl_i64:
|
||||
t0 = *tb_ptr++;
|
||||
t1 = tci_read_ri64(&tb_ptr);
|
||||
t2 = tci_read_ri64(&tb_ptr);
|
||||
tci_write_reg64(t0, rol64(t1, t2));
|
||||
tci_write_reg64(t0, rol64(t1, t2 & 63));
|
||||
break;
|
||||
case INDEX_op_rotr_i64:
|
||||
t0 = *tb_ptr++;
|
||||
t1 = tci_read_ri64(&tb_ptr);
|
||||
t2 = tci_read_ri64(&tb_ptr);
|
||||
tci_write_reg64(t0, ror64(t1, t2));
|
||||
tci_write_reg64(t0, ror64(t1, t2 & 63));
|
||||
break;
|
||||
#endif
|
||||
#if TCG_TARGET_HAS_deposit_i64
|
||||
|
||||
@@ -113,6 +113,10 @@ check-qtest-pci-y += tests/tpci200-test$(EXESUF)
|
||||
gcov-files-pci-y += hw/ipack/tpci200.c
|
||||
check-qtest-pci-y += $(check-qtest-ipack-y)
|
||||
gcov-files-pci-y += $(gcov-files-ipack-y)
|
||||
check-qtest-pci-y += tests/display-vga-test$(EXESUF)
|
||||
gcov-files-pci-y += hw/display/vga.c
|
||||
gcov-files-pci-y += hw/display/cirrus_vga.c
|
||||
gcov-files-pci-y += hw/display/vga-pci.c
|
||||
|
||||
check-qtest-i386-y = tests/endianness-test$(EXESUF)
|
||||
check-qtest-i386-y += tests/fdc-test$(EXESUF)
|
||||
@@ -280,6 +284,7 @@ tests/virtio-9p-test$(EXESUF): tests/virtio-9p-test.o
|
||||
tests/virtio-serial-test$(EXESUF): tests/virtio-serial-test.o
|
||||
tests/virtio-console-test$(EXESUF): tests/virtio-console-test.o
|
||||
tests/tpci200-test$(EXESUF): tests/tpci200-test.o
|
||||
tests/display-vga-test$(EXESUF): tests/display-vga-test.o
|
||||
tests/ipoctal232-test$(EXESUF): tests/ipoctal232-test.o
|
||||
tests/qom-test$(EXESUF): tests/qom-test.o
|
||||
tests/blockdev-test$(EXESUF): tests/blockdev-test.o $(libqos-pc-obj-y)
|
||||
|
||||
52
tests/display-vga-test.c
Normal file
52
tests/display-vga-test.c
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* QTest testcase for vga cards
|
||||
*
|
||||
* Copyright (c) 2014 Red Hat, Inc
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
#include <string.h>
|
||||
#include "libqtest.h"
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
static void pci_cirrus(void)
|
||||
{
|
||||
qtest_start("-vga none -device cirrus-vga");
|
||||
qtest_end();
|
||||
}
|
||||
|
||||
static void pci_stdvga(void)
|
||||
{
|
||||
qtest_start("-vga none -device VGA");
|
||||
qtest_end();
|
||||
}
|
||||
|
||||
static void pci_secondary(void)
|
||||
{
|
||||
qtest_start("-vga none -device secondary-vga");
|
||||
qtest_end();
|
||||
}
|
||||
|
||||
static void pci_multihead(void)
|
||||
{
|
||||
qtest_start("-vga none -device VGA -device secondary-vga");
|
||||
qtest_end();
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
|
||||
qtest_add_func("/display/pci/cirrus", pci_cirrus);
|
||||
qtest_add_func("/display/pci/stdvga", pci_stdvga);
|
||||
qtest_add_func("/display/pci/secondary", pci_secondary);
|
||||
qtest_add_func("/display/pci/multihead", pci_multihead);
|
||||
ret = g_test_run();
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -4,10 +4,7 @@ QA output created by 084
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||
Test 1: Maximum size (1024 TB):
|
||||
image: TEST_DIR/t.IMGFMT
|
||||
file format: IMGFMT
|
||||
virtual size: 1024T (1125899905794048 bytes)
|
||||
cluster_size: 1048576
|
||||
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Could not open 'TEST_DIR/t.IMGFMT': Invalid argument
|
||||
|
||||
Test 2: Size too large (1024TB + 1)
|
||||
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Unsupported VDI image size (size is 0x3fffffff10000, max supported is 0x3fffffff00000)
|
||||
|
||||
@@ -72,6 +72,91 @@ run_qemu <<EOF
|
||||
{ "execute": "quit" }
|
||||
EOF
|
||||
|
||||
echo
|
||||
echo === Duplicate ID ===
|
||||
echo
|
||||
|
||||
run_qemu <<EOF
|
||||
{ "execute": "qmp_capabilities" }
|
||||
{ "execute": "blockdev-add",
|
||||
"arguments": {
|
||||
"options": {
|
||||
"driver": "$IMGFMT",
|
||||
"id": "disk",
|
||||
"node-name": "test-node",
|
||||
"file": {
|
||||
"driver": "file",
|
||||
"filename": "$TEST_IMG"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{ "execute": "blockdev-add",
|
||||
"arguments": {
|
||||
"options": {
|
||||
"driver": "$IMGFMT",
|
||||
"id": "disk",
|
||||
"file": {
|
||||
"driver": "file",
|
||||
"filename": "$TEST_IMG"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{ "execute": "blockdev-add",
|
||||
"arguments": {
|
||||
"options": {
|
||||
"driver": "$IMGFMT",
|
||||
"id": "test-node",
|
||||
"file": {
|
||||
"driver": "file",
|
||||
"filename": "$TEST_IMG"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{ "execute": "blockdev-add",
|
||||
"arguments": {
|
||||
"options": {
|
||||
"driver": "$IMGFMT",
|
||||
"id": "disk2",
|
||||
"node-name": "disk",
|
||||
"file": {
|
||||
"driver": "file",
|
||||
"filename": "$TEST_IMG"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{ "execute": "blockdev-add",
|
||||
"arguments": {
|
||||
"options": {
|
||||
"driver": "$IMGFMT",
|
||||
"id": "disk2",
|
||||
"node-name": "test-node",
|
||||
"file": {
|
||||
"driver": "file",
|
||||
"filename": "$TEST_IMG"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{ "execute": "blockdev-add",
|
||||
"arguments": {
|
||||
"options": {
|
||||
"driver": "$IMGFMT",
|
||||
"id": "disk3",
|
||||
"node-name": "disk3",
|
||||
"file": {
|
||||
"driver": "file",
|
||||
"filename": "$TEST_IMG"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{ "execute": "quit" }
|
||||
EOF
|
||||
|
||||
echo
|
||||
echo === aio=native without O_DIRECT ===
|
||||
echo
|
||||
|
||||
@@ -13,6 +13,24 @@ QMP_VERSION
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
|
||||
|
||||
|
||||
=== Duplicate ID ===
|
||||
|
||||
Testing:
|
||||
QMP_VERSION
|
||||
{"return": {}}
|
||||
{"return": {}}
|
||||
{"error": {"class": "GenericError", "desc": "Device with id 'disk' already exists"}}
|
||||
{"error": {"class": "GenericError", "desc": "Device with node-name 'test-node' already exists"}}
|
||||
main-loop: WARNING: I/O thread spun for 1000 iterations
|
||||
{"error": {"class": "GenericError", "desc": "could not open disk image disk2: node-name=disk is conflicting with a device id"}}
|
||||
{"error": {"class": "GenericError", "desc": "could not open disk image disk2: Duplicate node name"}}
|
||||
{"error": {"class": "GenericError", "desc": "could not open disk image disk3: node-name=disk3 is conflicting with a device id"}}
|
||||
{"return": {}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
|
||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
|
||||
|
||||
|
||||
=== aio=native without O_DIRECT ===
|
||||
|
||||
Testing:
|
||||
|
||||
2
vl.c
2
vl.c
@@ -2740,7 +2740,7 @@ static int configure_accelerator(QEMUMachine *machine)
|
||||
if (!accel_list[i].available()) {
|
||||
printf("%s not supported for this target\n",
|
||||
accel_list[i].name);
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
*(accel_list[i].allowed) = true;
|
||||
ret = accel_list[i].init(machine);
|
||||
|
||||
8
xbzrle.c
8
xbzrle.c
@@ -28,7 +28,7 @@ int xbzrle_encode_buffer(uint8_t *old_buf, uint8_t *new_buf, int slen,
|
||||
{
|
||||
uint32_t zrun_len = 0, nzrun_len = 0;
|
||||
int d = 0, i = 0;
|
||||
long res, xor;
|
||||
long res;
|
||||
uint8_t *nzrun_start = NULL;
|
||||
|
||||
g_assert(!(((uintptr_t)old_buf | (uintptr_t)new_buf | slen) %
|
||||
@@ -93,9 +93,11 @@ int xbzrle_encode_buffer(uint8_t *old_buf, uint8_t *new_buf, int slen,
|
||||
/* word at a time for speed, use of 32-bit long okay */
|
||||
if (!res) {
|
||||
/* truncation to 32-bit long okay */
|
||||
long mask = (long)0x0101010101010101ULL;
|
||||
unsigned long mask = (unsigned long)0x0101010101010101ULL;
|
||||
while (i < slen) {
|
||||
xor = *(long *)(old_buf + i) ^ *(long *)(new_buf + i);
|
||||
unsigned long xor;
|
||||
xor = *(unsigned long *)(old_buf + i)
|
||||
^ *(unsigned long *)(new_buf + i);
|
||||
if ((xor - mask) & ~xor & (mask << 7)) {
|
||||
/* found the end of an nzrun within the current long */
|
||||
while (old_buf[i] != new_buf[i]) {
|
||||
|
||||
Reference in New Issue
Block a user