mirror of https://github.com/xemu-project/xemu.git
Merge remote branch 'origin/master' into pci
This commit is contained in:
commit
6107ff1292
2
Makefile
2
Makefile
|
@ -205,7 +205,7 @@ common de-ch es fo fr-ca hu ja mk nl-be pt sl tr
|
||||||
|
|
||||||
ifdef INSTALL_BLOBS
|
ifdef INSTALL_BLOBS
|
||||||
BLOBS=bios.bin vgabios.bin vgabios-cirrus.bin \
|
BLOBS=bios.bin vgabios.bin vgabios-cirrus.bin \
|
||||||
vgabios-stdvga.bin vgabios-vmware.bin \
|
vgabios-stdvga.bin vgabios-vmware.bin vgabios-qxl.bin \
|
||||||
ppc_rom.bin openbios-sparc32 openbios-sparc64 openbios-ppc \
|
ppc_rom.bin openbios-sparc32 openbios-sparc64 openbios-ppc \
|
||||||
gpxe-eepro100-80861209.rom \
|
gpxe-eepro100-80861209.rom \
|
||||||
pxe-e1000.bin \
|
pxe-e1000.bin \
|
||||||
|
|
|
@ -219,6 +219,7 @@ obj-i386-y += vmmouse.o vmport.o hpet.o applesmc.o
|
||||||
obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
|
obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
|
||||||
obj-i386-y += debugcon.o multiboot.o
|
obj-i386-y += debugcon.o multiboot.o
|
||||||
obj-i386-y += pc_piix.o
|
obj-i386-y += pc_piix.o
|
||||||
|
obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
|
||||||
|
|
||||||
# shared objects
|
# shared objects
|
||||||
obj-ppc-y = ppc.o
|
obj-ppc-y = ppc.o
|
||||||
|
|
|
@ -182,6 +182,70 @@ Example:
|
||||||
"host": "127.0.0.1", "sasl_username": "luiz" } },
|
"host": "127.0.0.1", "sasl_username": "luiz" } },
|
||||||
"timestamp": { "seconds": 1263475302, "microseconds": 150772 } }
|
"timestamp": { "seconds": 1263475302, "microseconds": 150772 } }
|
||||||
|
|
||||||
|
SPICE_CONNECTED, SPICE_DISCONNECTED
|
||||||
|
-----------------------------------
|
||||||
|
|
||||||
|
Emitted when a SPICE client connects or disconnects.
|
||||||
|
|
||||||
|
Data:
|
||||||
|
|
||||||
|
- "server": Server information (json-object)
|
||||||
|
- "host": IP address (json-string)
|
||||||
|
- "port": port number (json-string)
|
||||||
|
- "family": address family (json-string, "ipv4" or "ipv6")
|
||||||
|
- "client": Client information (json-object)
|
||||||
|
- "host": IP address (json-string)
|
||||||
|
- "port": port number (json-string)
|
||||||
|
- "family": address family (json-string, "ipv4" or "ipv6")
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
{ "timestamp": {"seconds": 1290688046, "microseconds": 388707},
|
||||||
|
"event": "SPICE_CONNECTED",
|
||||||
|
"data": {
|
||||||
|
"server": { "port": "5920", "family": "ipv4", "host": "127.0.0.1"},
|
||||||
|
"client": {"port": "52873", "family": "ipv4", "host": "127.0.0.1"}
|
||||||
|
}}
|
||||||
|
|
||||||
|
|
||||||
|
SPICE_INITIALIZED
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Emitted after initial handshake and authentication takes place (if any)
|
||||||
|
and the SPICE channel is up'n'running
|
||||||
|
|
||||||
|
Data:
|
||||||
|
|
||||||
|
- "server": Server information (json-object)
|
||||||
|
- "host": IP address (json-string)
|
||||||
|
- "port": port number (json-string)
|
||||||
|
- "family": address family (json-string, "ipv4" or "ipv6")
|
||||||
|
- "auth": authentication method (json-string, optional)
|
||||||
|
- "client": Client information (json-object)
|
||||||
|
- "host": IP address (json-string)
|
||||||
|
- "port": port number (json-string)
|
||||||
|
- "family": address family (json-string, "ipv4" or "ipv6")
|
||||||
|
- "connection-id": spice connection id. All channels with the same id
|
||||||
|
belong to the same spice session (json-int)
|
||||||
|
- "channel-type": channel type. "1" is the main control channel, filter for
|
||||||
|
this one if you want track spice sessions only (json-int)
|
||||||
|
- "channel-id": channel id. Usually "0", might be different needed when
|
||||||
|
multiple channels of the same type exist, such as multiple
|
||||||
|
display channels in a multihead setup (json-int)
|
||||||
|
- "tls": whevener the channel is encrypted (json-bool)
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
{ "timestamp": {"seconds": 1290688046, "microseconds": 417172},
|
||||||
|
"event": "SPICE_INITIALIZED",
|
||||||
|
"data": {"server": {"auth": "spice", "port": "5921",
|
||||||
|
"family": "ipv4", "host": "127.0.0.1"},
|
||||||
|
"client": {"port": "49004", "family": "ipv4", "channel-type": 3,
|
||||||
|
"connection-id": 1804289383, "host": "127.0.0.1",
|
||||||
|
"channel-id": 0, "tls": true}
|
||||||
|
}}
|
||||||
|
|
||||||
|
|
||||||
WATCHDOG
|
WATCHDOG
|
||||||
--------
|
--------
|
||||||
|
|
||||||
|
|
81
arm-semi.c
81
arm-semi.c
|
@ -373,45 +373,64 @@ uint32_t do_arm_semihosting(CPUState *env)
|
||||||
#ifdef CONFIG_USER_ONLY
|
#ifdef CONFIG_USER_ONLY
|
||||||
/* Build a commandline from the original argv. */
|
/* Build a commandline from the original argv. */
|
||||||
{
|
{
|
||||||
char **arg = ts->info->host_argv;
|
char *arm_cmdline_buffer;
|
||||||
int len = ARG(1);
|
const char *host_cmdline_buffer;
|
||||||
/* lock the buffer on the ARM side */
|
|
||||||
char *cmdline_buffer = (char*)lock_user(VERIFY_WRITE, ARG(0), len, 0);
|
|
||||||
|
|
||||||
if (!cmdline_buffer)
|
unsigned int i;
|
||||||
/* FIXME - should this error code be -TARGET_EFAULT ? */
|
unsigned int arm_cmdline_len = ARG(1);
|
||||||
return (uint32_t)-1;
|
unsigned int host_cmdline_len =
|
||||||
|
ts->info->arg_end-ts->info->arg_start;
|
||||||
|
|
||||||
s = cmdline_buffer;
|
if (!arm_cmdline_len || host_cmdline_len > arm_cmdline_len) {
|
||||||
while (*arg && len > 2) {
|
return -1; /* not enough space to store command line */
|
||||||
int n = strlen(*arg);
|
|
||||||
|
|
||||||
if (s != cmdline_buffer) {
|
|
||||||
*(s++) = ' ';
|
|
||||||
len--;
|
|
||||||
}
|
|
||||||
if (n >= len)
|
|
||||||
n = len - 1;
|
|
||||||
memcpy(s, *arg, n);
|
|
||||||
s += n;
|
|
||||||
len -= n;
|
|
||||||
arg++;
|
|
||||||
}
|
}
|
||||||
/* Null terminate the string. */
|
|
||||||
*s = 0;
|
|
||||||
len = s - cmdline_buffer;
|
|
||||||
|
|
||||||
/* Unlock the buffer on the ARM side. */
|
if (!host_cmdline_len) {
|
||||||
unlock_user(cmdline_buffer, ARG(0), len);
|
/* We special-case the "empty command line" case (argc==0).
|
||||||
|
Just provide the terminating 0. */
|
||||||
|
arm_cmdline_buffer = lock_user(VERIFY_WRITE, ARG(0), 1, 0);
|
||||||
|
arm_cmdline_buffer[0] = 0;
|
||||||
|
unlock_user(arm_cmdline_buffer, ARG(0), 1);
|
||||||
|
|
||||||
/* Adjust the commandline length argument. */
|
/* Adjust the commandline length argument. */
|
||||||
SET_ARG(1, len);
|
SET_ARG(1, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Return success if commandline fit into buffer. */
|
/* lock the buffers on the ARM side */
|
||||||
return *arg ? -1 : 0;
|
arm_cmdline_buffer =
|
||||||
|
lock_user(VERIFY_WRITE, ARG(0), host_cmdline_len, 0);
|
||||||
|
host_cmdline_buffer =
|
||||||
|
lock_user(VERIFY_READ, ts->info->arg_start,
|
||||||
|
host_cmdline_len, 1);
|
||||||
|
|
||||||
|
if (arm_cmdline_buffer && host_cmdline_buffer)
|
||||||
|
{
|
||||||
|
/* the last argument is zero-terminated;
|
||||||
|
no need for additional termination */
|
||||||
|
memcpy(arm_cmdline_buffer, host_cmdline_buffer,
|
||||||
|
host_cmdline_len);
|
||||||
|
|
||||||
|
/* separate arguments by white spaces */
|
||||||
|
for (i = 0; i < host_cmdline_len-1; i++) {
|
||||||
|
if (arm_cmdline_buffer[i] == 0) {
|
||||||
|
arm_cmdline_buffer[i] = ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Adjust the commandline length argument. */
|
||||||
|
SET_ARG(1, host_cmdline_len-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unlock the buffers on the ARM side. */
|
||||||
|
unlock_user(arm_cmdline_buffer, ARG(0), host_cmdline_len);
|
||||||
|
unlock_user((void*)host_cmdline_buffer, ts->info->arg_start, 0);
|
||||||
|
|
||||||
|
/* Return success if we could return a commandline. */
|
||||||
|
return (arm_cmdline_buffer && host_cmdline_buffer) ? 0 : -1;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
return -1;
|
return -1;
|
||||||
#endif
|
#endif
|
||||||
case SYS_HEAPINFO:
|
case SYS_HEAPINFO:
|
||||||
{
|
{
|
||||||
|
|
|
@ -318,7 +318,7 @@ static int alsa_write (SWVoiceOut *sw, void *buf, int len)
|
||||||
return audio_pcm_sw_write (sw, buf, len);
|
return audio_pcm_sw_write (sw, buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static snd_pcm_format_t aud_to_alsafmt (audfmt_e fmt)
|
static snd_pcm_format_t aud_to_alsafmt (audfmt_e fmt, int endianness)
|
||||||
{
|
{
|
||||||
switch (fmt) {
|
switch (fmt) {
|
||||||
case AUD_FMT_S8:
|
case AUD_FMT_S8:
|
||||||
|
@ -328,16 +328,36 @@ static snd_pcm_format_t aud_to_alsafmt (audfmt_e fmt)
|
||||||
return SND_PCM_FORMAT_U8;
|
return SND_PCM_FORMAT_U8;
|
||||||
|
|
||||||
case AUD_FMT_S16:
|
case AUD_FMT_S16:
|
||||||
return SND_PCM_FORMAT_S16_LE;
|
if (endianness) {
|
||||||
|
return SND_PCM_FORMAT_S16_BE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return SND_PCM_FORMAT_S16_LE;
|
||||||
|
}
|
||||||
|
|
||||||
case AUD_FMT_U16:
|
case AUD_FMT_U16:
|
||||||
return SND_PCM_FORMAT_U16_LE;
|
if (endianness) {
|
||||||
|
return SND_PCM_FORMAT_U16_BE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return SND_PCM_FORMAT_U16_LE;
|
||||||
|
}
|
||||||
|
|
||||||
case AUD_FMT_S32:
|
case AUD_FMT_S32:
|
||||||
return SND_PCM_FORMAT_S32_LE;
|
if (endianness) {
|
||||||
|
return SND_PCM_FORMAT_S32_BE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return SND_PCM_FORMAT_S32_LE;
|
||||||
|
}
|
||||||
|
|
||||||
case AUD_FMT_U32:
|
case AUD_FMT_U32:
|
||||||
return SND_PCM_FORMAT_U32_LE;
|
if (endianness) {
|
||||||
|
return SND_PCM_FORMAT_U32_BE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return SND_PCM_FORMAT_U32_LE;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
dolog ("Internal logic error: Bad audio format %d\n", fmt);
|
dolog ("Internal logic error: Bad audio format %d\n", fmt);
|
||||||
|
@ -809,7 +829,7 @@ static int alsa_init_out (HWVoiceOut *hw, struct audsettings *as)
|
||||||
snd_pcm_t *handle;
|
snd_pcm_t *handle;
|
||||||
struct audsettings obt_as;
|
struct audsettings obt_as;
|
||||||
|
|
||||||
req.fmt = aud_to_alsafmt (as->fmt);
|
req.fmt = aud_to_alsafmt (as->fmt, as->endianness);
|
||||||
req.freq = as->freq;
|
req.freq = as->freq;
|
||||||
req.nchannels = as->nchannels;
|
req.nchannels = as->nchannels;
|
||||||
req.period_size = conf.period_size_out;
|
req.period_size = conf.period_size_out;
|
||||||
|
@ -918,7 +938,7 @@ static int alsa_init_in (HWVoiceIn *hw, struct audsettings *as)
|
||||||
snd_pcm_t *handle;
|
snd_pcm_t *handle;
|
||||||
struct audsettings obt_as;
|
struct audsettings obt_as;
|
||||||
|
|
||||||
req.fmt = aud_to_alsafmt (as->fmt);
|
req.fmt = aud_to_alsafmt (as->fmt, as->endianness);
|
||||||
req.freq = as->freq;
|
req.freq = as->freq;
|
||||||
req.nchannels = as->nchannels;
|
req.nchannels = as->nchannels;
|
||||||
req.period_size = conf.period_size_in;
|
req.period_size = conf.period_size_in;
|
||||||
|
|
|
@ -117,9 +117,12 @@ static int no_run_in (HWVoiceIn *hw)
|
||||||
|
|
||||||
static int no_read (SWVoiceIn *sw, void *buf, int size)
|
static int no_read (SWVoiceIn *sw, void *buf, int size)
|
||||||
{
|
{
|
||||||
|
/* use custom code here instead of audio_pcm_sw_read() to avoid
|
||||||
|
* useless resampling/mixing */
|
||||||
int samples = size >> sw->info.shift;
|
int samples = size >> sw->info.shift;
|
||||||
int total = sw->hw->total_samples_captured - sw->total_hw_samples_acquired;
|
int total = sw->hw->total_samples_captured - sw->total_hw_samples_acquired;
|
||||||
int to_clear = audio_MIN (samples, total);
|
int to_clear = audio_MIN (samples, total);
|
||||||
|
sw->total_hw_samples_acquired += total;
|
||||||
audio_pcm_info_clear_buf (&sw->info, buf, to_clear);
|
audio_pcm_info_clear_buf (&sw->info, buf, to_clear);
|
||||||
return to_clear << sw->info.shift;
|
return to_clear << sw->info.shift;
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,7 +161,7 @@ static int oss_write (SWVoiceOut *sw, void *buf, int len)
|
||||||
return audio_pcm_sw_write (sw, buf, len);
|
return audio_pcm_sw_write (sw, buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int aud_to_ossfmt (audfmt_e fmt)
|
static int aud_to_ossfmt (audfmt_e fmt, int endianness)
|
||||||
{
|
{
|
||||||
switch (fmt) {
|
switch (fmt) {
|
||||||
case AUD_FMT_S8:
|
case AUD_FMT_S8:
|
||||||
|
@ -171,10 +171,20 @@ static int aud_to_ossfmt (audfmt_e fmt)
|
||||||
return AFMT_U8;
|
return AFMT_U8;
|
||||||
|
|
||||||
case AUD_FMT_S16:
|
case AUD_FMT_S16:
|
||||||
return AFMT_S16_LE;
|
if (endianness) {
|
||||||
|
return AFMT_S16_BE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return AFMT_S16_LE;
|
||||||
|
}
|
||||||
|
|
||||||
case AUD_FMT_U16:
|
case AUD_FMT_U16:
|
||||||
return AFMT_U16_LE;
|
if (endianness) {
|
||||||
|
return AFMT_U16_BE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return AFMT_U16_LE;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
dolog ("Internal logic error: Bad audio format %d\n", fmt);
|
dolog ("Internal logic error: Bad audio format %d\n", fmt);
|
||||||
|
@ -516,7 +526,7 @@ static int oss_init_out (HWVoiceOut *hw, struct audsettings *as)
|
||||||
|
|
||||||
oss->fd = -1;
|
oss->fd = -1;
|
||||||
|
|
||||||
req.fmt = aud_to_ossfmt (as->fmt);
|
req.fmt = aud_to_ossfmt (as->fmt, as->endianness);
|
||||||
req.freq = as->freq;
|
req.freq = as->freq;
|
||||||
req.nchannels = as->nchannels;
|
req.nchannels = as->nchannels;
|
||||||
req.fragsize = conf.fragsize;
|
req.fragsize = conf.fragsize;
|
||||||
|
@ -682,7 +692,7 @@ static int oss_init_in (HWVoiceIn *hw, struct audsettings *as)
|
||||||
|
|
||||||
oss->fd = -1;
|
oss->fd = -1;
|
||||||
|
|
||||||
req.fmt = aud_to_ossfmt (as->fmt);
|
req.fmt = aud_to_ossfmt (as->fmt, as->endianness);
|
||||||
req.freq = as->freq;
|
req.freq = as->freq;
|
||||||
req.nchannels = as->nchannels;
|
req.nchannels = as->nchannels;
|
||||||
req.fragsize = conf.fragsize;
|
req.fragsize = conf.fragsize;
|
||||||
|
|
5
block.c
5
block.c
|
@ -2859,13 +2859,8 @@ int bdrv_img_create(const char *filename, const char *fmt,
|
||||||
if (get_option_parameter(param, BLOCK_OPT_SIZE)->value.n == -1) {
|
if (get_option_parameter(param, BLOCK_OPT_SIZE)->value.n == -1) {
|
||||||
if (backing_file && backing_file->value.s) {
|
if (backing_file && backing_file->value.s) {
|
||||||
uint64_t size;
|
uint64_t size;
|
||||||
const char *fmt = NULL;
|
|
||||||
char buf[32];
|
char buf[32];
|
||||||
|
|
||||||
if (backing_fmt && backing_fmt->value.s) {
|
|
||||||
fmt = backing_fmt->value.s;
|
|
||||||
}
|
|
||||||
|
|
||||||
bs = bdrv_new("");
|
bs = bdrv_new("");
|
||||||
|
|
||||||
ret = bdrv_open(bs, backing_file->value.s, flags, drv);
|
ret = bdrv_open(bs, backing_file->value.s, flags, drv);
|
||||||
|
|
|
@ -176,8 +176,6 @@ int loader_exec(const char * filename, char ** argv, char ** envp,
|
||||||
|
|
||||||
retval = prepare_binprm(&bprm);
|
retval = prepare_binprm(&bprm);
|
||||||
|
|
||||||
infop->host_argv = argv;
|
|
||||||
|
|
||||||
if(retval>=0) {
|
if(retval>=0) {
|
||||||
if (bprm.buf[0] == 0x7f
|
if (bprm.buf[0] == 0x7f
|
||||||
&& bprm.buf[1] == 'E'
|
&& bprm.buf[1] == 'E'
|
||||||
|
|
|
@ -50,7 +50,6 @@ struct image_info {
|
||||||
abi_ulong entry;
|
abi_ulong entry;
|
||||||
abi_ulong code_offset;
|
abi_ulong code_offset;
|
||||||
abi_ulong data_offset;
|
abi_ulong data_offset;
|
||||||
char **host_argv;
|
|
||||||
int personality;
|
int personality;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
15
bswap.h
15
bswap.h
|
@ -144,6 +144,7 @@ CPU_CONVERT(le, 64, uint64_t)
|
||||||
|
|
||||||
#define cpu_to_be16wu(p, v) cpu_to_be16w(p, v)
|
#define cpu_to_be16wu(p, v) cpu_to_be16w(p, v)
|
||||||
#define cpu_to_be32wu(p, v) cpu_to_be32w(p, v)
|
#define cpu_to_be32wu(p, v) cpu_to_be32w(p, v)
|
||||||
|
#define cpu_to_be64wu(p, v) cpu_to_be64w(p, v)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
@ -201,6 +202,20 @@ static inline void cpu_to_be32wu(uint32_t *p, uint32_t v)
|
||||||
p1[3] = v & 0xff;
|
p1[3] = v & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void cpu_to_be64wu(uint64_t *p, uint64_t v)
|
||||||
|
{
|
||||||
|
uint8_t *p1 = (uint8_t *)p;
|
||||||
|
|
||||||
|
p1[0] = v >> 56;
|
||||||
|
p1[1] = v >> 48;
|
||||||
|
p1[2] = v >> 40;
|
||||||
|
p1[3] = v >> 32;
|
||||||
|
p1[4] = v >> 24;
|
||||||
|
p1[5] = v >> 16;
|
||||||
|
p1[6] = v >> 8;
|
||||||
|
p1[7] = v & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HOST_WORDS_BIGENDIAN
|
#ifdef HOST_WORDS_BIGENDIAN
|
||||||
|
|
|
@ -2075,6 +2075,21 @@ if compile_prog "$ARCH_CFLAGS" "" ; then
|
||||||
fallocate=yes
|
fallocate=yes
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# check for sync_file_range
|
||||||
|
sync_file_range=no
|
||||||
|
cat > $TMPC << EOF
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
sync_file_range(0, 0, 0, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
if compile_prog "$ARCH_CFLAGS" "" ; then
|
||||||
|
sync_file_range=yes
|
||||||
|
fi
|
||||||
|
|
||||||
# check for dup3
|
# check for dup3
|
||||||
dup3=no
|
dup3=no
|
||||||
cat > $TMPC << EOF
|
cat > $TMPC << EOF
|
||||||
|
@ -2613,6 +2628,9 @@ fi
|
||||||
if test "$fallocate" = "yes" ; then
|
if test "$fallocate" = "yes" ; then
|
||||||
echo "CONFIG_FALLOCATE=y" >> $config_host_mak
|
echo "CONFIG_FALLOCATE=y" >> $config_host_mak
|
||||||
fi
|
fi
|
||||||
|
if test "$sync_file_range" = "yes" ; then
|
||||||
|
echo "CONFIG_SYNC_FILE_RANGE=y" >> $config_host_mak
|
||||||
|
fi
|
||||||
if test "$dup3" = "yes" ; then
|
if test "$dup3" = "yes" ; then
|
||||||
echo "CONFIG_DUP3=y" >> $config_host_mak
|
echo "CONFIG_DUP3=y" >> $config_host_mak
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -329,7 +329,7 @@ static inline void console_write_ch(console_ch_t *dest, uint32_t ch)
|
||||||
{
|
{
|
||||||
if (!(ch & 0xff))
|
if (!(ch & 0xff))
|
||||||
ch |= ' ';
|
ch |= ' ';
|
||||||
cpu_to_le32wu((uint32_t *) dest, ch);
|
*dest = ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef void (*vga_hw_update_ptr)(void *);
|
typedef void (*vga_hw_update_ptr)(void *);
|
||||||
|
@ -369,6 +369,7 @@ void vnc_display_init(DisplayState *ds);
|
||||||
void vnc_display_close(DisplayState *ds);
|
void vnc_display_close(DisplayState *ds);
|
||||||
int vnc_display_open(DisplayState *ds, const char *display);
|
int vnc_display_open(DisplayState *ds, const char *display);
|
||||||
int vnc_display_password(DisplayState *ds, const char *password);
|
int vnc_display_password(DisplayState *ds, const char *password);
|
||||||
|
int vnc_display_pw_expire(DisplayState *ds, time_t expires);
|
||||||
void do_info_vnc_print(Monitor *mon, const QObject *data);
|
void do_info_vnc_print(Monitor *mon, const QObject *data);
|
||||||
void do_info_vnc(Monitor *mon, QObject **ret_data);
|
void do_info_vnc(Monitor *mon, QObject **ret_data);
|
||||||
char *vnc_display_local_addr(DisplayState *ds);
|
char *vnc_display_local_addr(DisplayState *ds);
|
||||||
|
|
|
@ -454,11 +454,7 @@ int cpu_exec(CPUState *env1)
|
||||||
}
|
}
|
||||||
#elif defined(TARGET_MIPS)
|
#elif defined(TARGET_MIPS)
|
||||||
if ((interrupt_request & CPU_INTERRUPT_HARD) &&
|
if ((interrupt_request & CPU_INTERRUPT_HARD) &&
|
||||||
cpu_mips_hw_interrupts_pending(env) &&
|
cpu_mips_hw_interrupts_pending(env)) {
|
||||||
(env->CP0_Status & (1 << CP0St_IE)) &&
|
|
||||||
!(env->CP0_Status & (1 << CP0St_EXL)) &&
|
|
||||||
!(env->CP0_Status & (1 << CP0St_ERL)) &&
|
|
||||||
!(env->hflags & MIPS_HFLAG_DM)) {
|
|
||||||
/* Raise it */
|
/* Raise it */
|
||||||
env->exception_index = EXCP_EXT_INTERRUPT;
|
env->exception_index = EXCP_EXT_INTERRUPT;
|
||||||
env->error_code = 0;
|
env->error_code = 0;
|
||||||
|
|
|
@ -177,7 +177,7 @@ static inline unsigned int tb_jmp_cache_hash_func(target_ulong pc)
|
||||||
|
|
||||||
static inline unsigned int tb_phys_hash_func(tb_page_addr_t pc)
|
static inline unsigned int tb_phys_hash_func(tb_page_addr_t pc)
|
||||||
{
|
{
|
||||||
return pc & (CODE_GEN_PHYS_HASH_SIZE - 1);
|
return (pc >> 2) & (CODE_GEN_PHYS_HASH_SIZE - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
TranslationBlock *tb_alloc(target_ulong pc);
|
TranslationBlock *tb_alloc(target_ulong pc);
|
||||||
|
@ -204,9 +204,7 @@ static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr
|
||||||
#elif defined(__arm__)
|
#elif defined(__arm__)
|
||||||
static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr)
|
static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr)
|
||||||
{
|
{
|
||||||
#if QEMU_GNUC_PREREQ(4, 1)
|
#if !QEMU_GNUC_PREREQ(4, 1)
|
||||||
void __clear_cache(char *beg, char *end);
|
|
||||||
#else
|
|
||||||
register unsigned long _beg __asm ("a1");
|
register unsigned long _beg __asm ("a1");
|
||||||
register unsigned long _end __asm ("a2");
|
register unsigned long _end __asm ("a2");
|
||||||
register unsigned long _flg __asm ("a3");
|
register unsigned long _flg __asm ("a3");
|
||||||
|
@ -218,7 +216,7 @@ static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr
|
||||||
| (((addr - (jmp_addr + 8)) >> 2) & 0xffffff);
|
| (((addr - (jmp_addr + 8)) >> 2) & 0xffffff);
|
||||||
|
|
||||||
#if QEMU_GNUC_PREREQ(4, 1)
|
#if QEMU_GNUC_PREREQ(4, 1)
|
||||||
__clear_cache((char *) jmp_addr, (char *) jmp_addr + 4);
|
__builtin___clear_cache((char *) jmp_addr, (char *) jmp_addr + 4);
|
||||||
#else
|
#else
|
||||||
/* flush icache */
|
/* flush icache */
|
||||||
_beg = jmp_addr;
|
_beg = jmp_addr;
|
||||||
|
|
3
exec.c
3
exec.c
|
@ -517,7 +517,8 @@ static void code_gen_alloc(unsigned long tb_size)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
|
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) \
|
||||||
|
|| defined(__DragonFly__) || defined(__OpenBSD__)
|
||||||
{
|
{
|
||||||
int flags;
|
int flags;
|
||||||
void *addr = NULL;
|
void *addr = NULL;
|
||||||
|
|
|
@ -254,7 +254,7 @@ int float32_is_signaling_nan( float32 a1)
|
||||||
return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
|
return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
|
||||||
}
|
}
|
||||||
|
|
||||||
int float32_is_nan( float32 a1 )
|
int float32_is_quiet_nan( float32 a1 )
|
||||||
{
|
{
|
||||||
float32u u;
|
float32u u;
|
||||||
uint64_t a;
|
uint64_t a;
|
||||||
|
@ -411,7 +411,7 @@ int float64_is_signaling_nan( float64 a1)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int float64_is_nan( float64 a1 )
|
int float64_is_quiet_nan( float64 a1 )
|
||||||
{
|
{
|
||||||
float64u u;
|
float64u u;
|
||||||
uint64_t a;
|
uint64_t a;
|
||||||
|
@ -504,7 +504,7 @@ int floatx80_is_signaling_nan( floatx80 a1)
|
||||||
&& ( u.i.low == aLow );
|
&& ( u.i.low == aLow );
|
||||||
}
|
}
|
||||||
|
|
||||||
int floatx80_is_nan( floatx80 a1 )
|
int floatx80_is_quiet_nan( floatx80 a1 )
|
||||||
{
|
{
|
||||||
floatx80u u;
|
floatx80u u;
|
||||||
u.f = a1;
|
u.f = a1;
|
||||||
|
|
|
@ -242,7 +242,7 @@ INLINE int float32_unordered( float32 a, float32 b STATUS_PARAM)
|
||||||
int float32_compare( float32, float32 STATUS_PARAM );
|
int float32_compare( float32, float32 STATUS_PARAM );
|
||||||
int float32_compare_quiet( float32, float32 STATUS_PARAM );
|
int float32_compare_quiet( float32, float32 STATUS_PARAM );
|
||||||
int float32_is_signaling_nan( float32 );
|
int float32_is_signaling_nan( float32 );
|
||||||
int float32_is_nan( float32 );
|
int float32_is_quiet_nan( float32 );
|
||||||
|
|
||||||
INLINE float32 float32_abs(float32 a)
|
INLINE float32 float32_abs(float32 a)
|
||||||
{
|
{
|
||||||
|
@ -351,7 +351,7 @@ INLINE int float64_unordered( float64 a, float64 b STATUS_PARAM)
|
||||||
int float64_compare( float64, float64 STATUS_PARAM );
|
int float64_compare( float64, float64 STATUS_PARAM );
|
||||||
int float64_compare_quiet( float64, float64 STATUS_PARAM );
|
int float64_compare_quiet( float64, float64 STATUS_PARAM );
|
||||||
int float64_is_signaling_nan( float64 );
|
int float64_is_signaling_nan( float64 );
|
||||||
int float64_is_nan( float64 );
|
int float64_is_quiet_nan( float64 );
|
||||||
|
|
||||||
INLINE float64 float64_abs(float64 a)
|
INLINE float64 float64_abs(float64 a)
|
||||||
{
|
{
|
||||||
|
@ -455,7 +455,7 @@ INLINE int floatx80_unordered( floatx80 a, floatx80 b STATUS_PARAM)
|
||||||
int floatx80_compare( floatx80, floatx80 STATUS_PARAM );
|
int floatx80_compare( floatx80, floatx80 STATUS_PARAM );
|
||||||
int floatx80_compare_quiet( floatx80, floatx80 STATUS_PARAM );
|
int floatx80_compare_quiet( floatx80, floatx80 STATUS_PARAM );
|
||||||
int floatx80_is_signaling_nan( floatx80 );
|
int floatx80_is_signaling_nan( floatx80 );
|
||||||
int floatx80_is_nan( floatx80 );
|
int floatx80_is_quiet_nan( floatx80 );
|
||||||
|
|
||||||
INLINE floatx80 floatx80_abs(floatx80 a)
|
INLINE floatx80 floatx80_abs(floatx80 a)
|
||||||
{
|
{
|
||||||
|
|
|
@ -30,7 +30,7 @@ these four paragraphs for those parts of this code that are retained.
|
||||||
|
|
||||||
=============================================================================*/
|
=============================================================================*/
|
||||||
|
|
||||||
#if defined(TARGET_MIPS) || defined(TARGET_HPPA)
|
#if defined(TARGET_MIPS)
|
||||||
#define SNAN_BIT_IS_ONE 1
|
#define SNAN_BIT_IS_ONE 1
|
||||||
#else
|
#else
|
||||||
#define SNAN_BIT_IS_ONE 0
|
#define SNAN_BIT_IS_ONE 0
|
||||||
|
@ -61,10 +61,8 @@ typedef struct {
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
#if defined(TARGET_SPARC)
|
#if defined(TARGET_SPARC)
|
||||||
#define float32_default_nan make_float32(0x7FFFFFFF)
|
#define float32_default_nan make_float32(0x7FFFFFFF)
|
||||||
#elif defined(TARGET_POWERPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
|
#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
|
||||||
#define float32_default_nan make_float32(0x7FC00000)
|
#define float32_default_nan make_float32(0x7FC00000)
|
||||||
#elif defined(TARGET_HPPA)
|
|
||||||
#define float32_default_nan make_float32(0x7FA00000)
|
|
||||||
#elif SNAN_BIT_IS_ONE
|
#elif SNAN_BIT_IS_ONE
|
||||||
#define float32_default_nan make_float32(0x7FBFFFFF)
|
#define float32_default_nan make_float32(0x7FBFFFFF)
|
||||||
#else
|
#else
|
||||||
|
@ -76,7 +74,7 @@ typedef struct {
|
||||||
| NaN; otherwise returns 0.
|
| NaN; otherwise returns 0.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
int float32_is_nan( float32 a_ )
|
int float32_is_quiet_nan( float32 a_ )
|
||||||
{
|
{
|
||||||
uint32_t a = float32_val(a_);
|
uint32_t a = float32_val(a_);
|
||||||
#if SNAN_BIT_IS_ONE
|
#if SNAN_BIT_IS_ONE
|
||||||
|
@ -109,13 +107,17 @@ int float32_is_signaling_nan( float32 a_ )
|
||||||
float32 float32_maybe_silence_nan( float32 a_ )
|
float32 float32_maybe_silence_nan( float32 a_ )
|
||||||
{
|
{
|
||||||
if (float32_is_signaling_nan(a_)) {
|
if (float32_is_signaling_nan(a_)) {
|
||||||
uint32_t a = float32_val(a_);
|
|
||||||
#if SNAN_BIT_IS_ONE
|
#if SNAN_BIT_IS_ONE
|
||||||
a &= ~(1 << 22);
|
# if defined(TARGET_MIPS)
|
||||||
|
return float32_default_nan;
|
||||||
|
# else
|
||||||
|
# error Rules for silencing a signaling NaN are target-specific
|
||||||
|
# endif
|
||||||
#else
|
#else
|
||||||
|
bits32 a = float32_val(a_);
|
||||||
a |= (1 << 22);
|
a |= (1 << 22);
|
||||||
#endif
|
|
||||||
return make_float32(a);
|
return make_float32(a);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return a_;
|
return a_;
|
||||||
}
|
}
|
||||||
|
@ -152,6 +154,118 @@ static float32 commonNaNToFloat32( commonNaNT a )
|
||||||
return float32_default_nan;
|
return float32_default_nan;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
| Select which NaN to propagate for a two-input operation.
|
||||||
|
| IEEE754 doesn't specify all the details of this, so the
|
||||||
|
| algorithm is target-specific.
|
||||||
|
| The routine is passed various bits of information about the
|
||||||
|
| two NaNs and should return 0 to select NaN a and 1 for NaN b.
|
||||||
|
| Note that signalling NaNs are always squashed to quiet NaNs
|
||||||
|
| by the caller, by calling floatXX_maybe_silence_nan() before
|
||||||
|
| returning them.
|
||||||
|
|
|
||||||
|
| aIsLargerSignificand is only valid if both a and b are NaNs
|
||||||
|
| of some kind, and is true if a has the larger significand,
|
||||||
|
| or if both a and b have the same significand but a is
|
||||||
|
| positive but b is negative. It is only needed for the x87
|
||||||
|
| tie-break rule.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if defined(TARGET_ARM)
|
||||||
|
static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
|
||||||
|
flag aIsLargerSignificand)
|
||||||
|
{
|
||||||
|
/* ARM mandated NaN propagation rules: take the first of:
|
||||||
|
* 1. A if it is signaling
|
||||||
|
* 2. B if it is signaling
|
||||||
|
* 3. A (quiet)
|
||||||
|
* 4. B (quiet)
|
||||||
|
* A signaling NaN is always quietened before returning it.
|
||||||
|
*/
|
||||||
|
if (aIsSNaN) {
|
||||||
|
return 0;
|
||||||
|
} else if (bIsSNaN) {
|
||||||
|
return 1;
|
||||||
|
} else if (aIsQNaN) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#elif defined(TARGET_MIPS)
|
||||||
|
static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
|
||||||
|
flag aIsLargerSignificand)
|
||||||
|
{
|
||||||
|
/* According to MIPS specifications, if one of the two operands is
|
||||||
|
* a sNaN, a new qNaN has to be generated. This is done in
|
||||||
|
* floatXX_maybe_silence_nan(). For qNaN inputs the specifications
|
||||||
|
* says: "When possible, this QNaN result is one of the operand QNaN
|
||||||
|
* values." In practice it seems that most implementations choose
|
||||||
|
* the first operand if both operands are qNaN. In short this gives
|
||||||
|
* the following rules:
|
||||||
|
* 1. A if it is signaling
|
||||||
|
* 2. B if it is signaling
|
||||||
|
* 3. A (quiet)
|
||||||
|
* 4. B (quiet)
|
||||||
|
* A signaling NaN is always silenced before returning it.
|
||||||
|
*/
|
||||||
|
if (aIsSNaN) {
|
||||||
|
return 0;
|
||||||
|
} else if (bIsSNaN) {
|
||||||
|
return 1;
|
||||||
|
} else if (aIsQNaN) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#elif defined(TARGET_PPC)
|
||||||
|
static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
|
||||||
|
flag aIsLargerSignificand)
|
||||||
|
{
|
||||||
|
/* PowerPC propagation rules:
|
||||||
|
* 1. A if it sNaN or qNaN
|
||||||
|
* 2. B if it sNaN or qNaN
|
||||||
|
* A signaling NaN is always silenced before returning it.
|
||||||
|
*/
|
||||||
|
if (aIsSNaN || aIsQNaN) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
|
||||||
|
flag aIsLargerSignificand)
|
||||||
|
{
|
||||||
|
/* This implements x87 NaN propagation rules:
|
||||||
|
* SNaN + QNaN => return the QNaN
|
||||||
|
* two SNaNs => return the one with the larger significand, silenced
|
||||||
|
* two QNaNs => return the one with the larger significand
|
||||||
|
* SNaN and a non-NaN => return the SNaN, silenced
|
||||||
|
* QNaN and a non-NaN => return the QNaN
|
||||||
|
*
|
||||||
|
* If we get down to comparing significands and they are the same,
|
||||||
|
* return the NaN with the positive sign bit (if any).
|
||||||
|
*/
|
||||||
|
if (aIsSNaN) {
|
||||||
|
if (bIsSNaN) {
|
||||||
|
return aIsLargerSignificand ? 0 : 1;
|
||||||
|
}
|
||||||
|
return bIsQNaN ? 1 : 0;
|
||||||
|
}
|
||||||
|
else if (aIsQNaN) {
|
||||||
|
if (bIsSNaN || !bIsQNaN)
|
||||||
|
return 0;
|
||||||
|
else {
|
||||||
|
return aIsLargerSignificand ? 0 : 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Takes two single-precision floating-point values `a' and `b', one of which
|
| Takes two single-precision floating-point values `a' and `b', one of which
|
||||||
| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
|
| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
|
||||||
|
@ -160,47 +274,36 @@ static float32 commonNaNToFloat32( commonNaNT a )
|
||||||
|
|
||||||
static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
|
static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
|
||||||
{
|
{
|
||||||
flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
|
flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
|
||||||
bits32 av, bv, res;
|
flag aIsLargerSignificand;
|
||||||
|
bits32 av, bv;
|
||||||
|
|
||||||
if ( STATUS(default_nan_mode) )
|
if ( STATUS(default_nan_mode) )
|
||||||
return float32_default_nan;
|
return float32_default_nan;
|
||||||
|
|
||||||
aIsNaN = float32_is_nan( a );
|
aIsQuietNaN = float32_is_quiet_nan( a );
|
||||||
aIsSignalingNaN = float32_is_signaling_nan( a );
|
aIsSignalingNaN = float32_is_signaling_nan( a );
|
||||||
bIsNaN = float32_is_nan( b );
|
bIsQuietNaN = float32_is_quiet_nan( b );
|
||||||
bIsSignalingNaN = float32_is_signaling_nan( b );
|
bIsSignalingNaN = float32_is_signaling_nan( b );
|
||||||
av = float32_val(a);
|
av = float32_val(a);
|
||||||
bv = float32_val(b);
|
bv = float32_val(b);
|
||||||
#if SNAN_BIT_IS_ONE
|
|
||||||
av &= ~0x00400000;
|
|
||||||
bv &= ~0x00400000;
|
|
||||||
#else
|
|
||||||
av |= 0x00400000;
|
|
||||||
bv |= 0x00400000;
|
|
||||||
#endif
|
|
||||||
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
|
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
|
||||||
if ( aIsSignalingNaN ) {
|
|
||||||
if ( bIsSignalingNaN ) goto returnLargerSignificand;
|
if ((bits32)(av<<1) < (bits32)(bv<<1)) {
|
||||||
res = bIsNaN ? bv : av;
|
aIsLargerSignificand = 0;
|
||||||
|
} else if ((bits32)(bv<<1) < (bits32)(av<<1)) {
|
||||||
|
aIsLargerSignificand = 1;
|
||||||
|
} else {
|
||||||
|
aIsLargerSignificand = (av < bv) ? 1 : 0;
|
||||||
}
|
}
|
||||||
else if ( aIsNaN ) {
|
|
||||||
if ( bIsSignalingNaN || ! bIsNaN )
|
if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
|
||||||
res = av;
|
aIsLargerSignificand)) {
|
||||||
else {
|
return float32_maybe_silence_nan(b);
|
||||||
returnLargerSignificand:
|
} else {
|
||||||
if ( (bits32) ( av<<1 ) < (bits32) ( bv<<1 ) )
|
return float32_maybe_silence_nan(a);
|
||||||
res = bv;
|
|
||||||
else if ( (bits32) ( bv<<1 ) < (bits32) ( av<<1 ) )
|
|
||||||
res = av;
|
|
||||||
else
|
|
||||||
res = ( av < bv ) ? av : bv;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
res = bv;
|
|
||||||
}
|
|
||||||
return make_float32(res);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
|
@ -208,10 +311,8 @@ static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
#if defined(TARGET_SPARC)
|
#if defined(TARGET_SPARC)
|
||||||
#define float64_default_nan make_float64(LIT64( 0x7FFFFFFFFFFFFFFF ))
|
#define float64_default_nan make_float64(LIT64( 0x7FFFFFFFFFFFFFFF ))
|
||||||
#elif defined(TARGET_POWERPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
|
#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
|
||||||
#define float64_default_nan make_float64(LIT64( 0x7FF8000000000000 ))
|
#define float64_default_nan make_float64(LIT64( 0x7FF8000000000000 ))
|
||||||
#elif defined(TARGET_HPPA)
|
|
||||||
#define float64_default_nan make_float64(LIT64( 0x7FF4000000000000 ))
|
|
||||||
#elif SNAN_BIT_IS_ONE
|
#elif SNAN_BIT_IS_ONE
|
||||||
#define float64_default_nan make_float64(LIT64( 0x7FF7FFFFFFFFFFFF ))
|
#define float64_default_nan make_float64(LIT64( 0x7FF7FFFFFFFFFFFF ))
|
||||||
#else
|
#else
|
||||||
|
@ -223,7 +324,7 @@ static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
|
||||||
| NaN; otherwise returns 0.
|
| NaN; otherwise returns 0.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
int float64_is_nan( float64 a_ )
|
int float64_is_quiet_nan( float64 a_ )
|
||||||
{
|
{
|
||||||
bits64 a = float64_val(a_);
|
bits64 a = float64_val(a_);
|
||||||
#if SNAN_BIT_IS_ONE
|
#if SNAN_BIT_IS_ONE
|
||||||
|
@ -260,13 +361,17 @@ int float64_is_signaling_nan( float64 a_ )
|
||||||
float64 float64_maybe_silence_nan( float64 a_ )
|
float64 float64_maybe_silence_nan( float64 a_ )
|
||||||
{
|
{
|
||||||
if (float64_is_signaling_nan(a_)) {
|
if (float64_is_signaling_nan(a_)) {
|
||||||
bits64 a = float64_val(a_);
|
|
||||||
#if SNAN_BIT_IS_ONE
|
#if SNAN_BIT_IS_ONE
|
||||||
a &= ~LIT64( 0x0008000000000000 );
|
# if defined(TARGET_MIPS)
|
||||||
|
return float64_default_nan;
|
||||||
|
# else
|
||||||
|
# error Rules for silencing a signaling NaN are target-specific
|
||||||
|
# endif
|
||||||
#else
|
#else
|
||||||
|
bits64 a = float64_val(a_);
|
||||||
a |= LIT64( 0x0008000000000000 );
|
a |= LIT64( 0x0008000000000000 );
|
||||||
#endif
|
|
||||||
return make_float64(a);
|
return make_float64(a);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return a_;
|
return a_;
|
||||||
}
|
}
|
||||||
|
@ -314,47 +419,36 @@ static float64 commonNaNToFloat64( commonNaNT a )
|
||||||
|
|
||||||
static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
|
static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
|
||||||
{
|
{
|
||||||
flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
|
flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
|
||||||
bits64 av, bv, res;
|
flag aIsLargerSignificand;
|
||||||
|
bits64 av, bv;
|
||||||
|
|
||||||
if ( STATUS(default_nan_mode) )
|
if ( STATUS(default_nan_mode) )
|
||||||
return float64_default_nan;
|
return float64_default_nan;
|
||||||
|
|
||||||
aIsNaN = float64_is_nan( a );
|
aIsQuietNaN = float64_is_quiet_nan( a );
|
||||||
aIsSignalingNaN = float64_is_signaling_nan( a );
|
aIsSignalingNaN = float64_is_signaling_nan( a );
|
||||||
bIsNaN = float64_is_nan( b );
|
bIsQuietNaN = float64_is_quiet_nan( b );
|
||||||
bIsSignalingNaN = float64_is_signaling_nan( b );
|
bIsSignalingNaN = float64_is_signaling_nan( b );
|
||||||
av = float64_val(a);
|
av = float64_val(a);
|
||||||
bv = float64_val(b);
|
bv = float64_val(b);
|
||||||
#if SNAN_BIT_IS_ONE
|
|
||||||
av &= ~LIT64( 0x0008000000000000 );
|
|
||||||
bv &= ~LIT64( 0x0008000000000000 );
|
|
||||||
#else
|
|
||||||
av |= LIT64( 0x0008000000000000 );
|
|
||||||
bv |= LIT64( 0x0008000000000000 );
|
|
||||||
#endif
|
|
||||||
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
|
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
|
||||||
if ( aIsSignalingNaN ) {
|
|
||||||
if ( bIsSignalingNaN ) goto returnLargerSignificand;
|
if ((bits64)(av<<1) < (bits64)(bv<<1)) {
|
||||||
res = bIsNaN ? bv : av;
|
aIsLargerSignificand = 0;
|
||||||
|
} else if ((bits64)(bv<<1) < (bits64)(av<<1)) {
|
||||||
|
aIsLargerSignificand = 1;
|
||||||
|
} else {
|
||||||
|
aIsLargerSignificand = (av < bv) ? 1 : 0;
|
||||||
}
|
}
|
||||||
else if ( aIsNaN ) {
|
|
||||||
if ( bIsSignalingNaN || ! bIsNaN )
|
if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
|
||||||
res = av;
|
aIsLargerSignificand)) {
|
||||||
else {
|
return float64_maybe_silence_nan(b);
|
||||||
returnLargerSignificand:
|
} else {
|
||||||
if ( (bits64) ( av<<1 ) < (bits64) ( bv<<1 ) )
|
return float64_maybe_silence_nan(a);
|
||||||
res = bv;
|
|
||||||
else if ( (bits64) ( bv<<1 ) < (bits64) ( av<<1 ) )
|
|
||||||
res = av;
|
|
||||||
else
|
|
||||||
res = ( av < bv ) ? av : bv;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
res = bv;
|
|
||||||
}
|
|
||||||
return make_float64(res);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FLOATX80
|
#ifdef FLOATX80
|
||||||
|
@ -377,7 +471,7 @@ static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
|
||||||
| quiet NaN; otherwise returns 0.
|
| quiet NaN; otherwise returns 0.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
int floatx80_is_nan( floatx80 a )
|
int floatx80_is_quiet_nan( floatx80 a )
|
||||||
{
|
{
|
||||||
#if SNAN_BIT_IS_ONE
|
#if SNAN_BIT_IS_ONE
|
||||||
bits64 aLow;
|
bits64 aLow;
|
||||||
|
@ -412,6 +506,29 @@ int floatx80_is_signaling_nan( floatx80 a )
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
| Returns a quiet NaN if the extended double-precision floating point value
|
||||||
|
| `a' is a signaling NaN; otherwise returns `a'.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
floatx80 floatx80_maybe_silence_nan( floatx80 a )
|
||||||
|
{
|
||||||
|
if (floatx80_is_signaling_nan(a)) {
|
||||||
|
#if SNAN_BIT_IS_ONE
|
||||||
|
# if defined(TARGET_MIPS)
|
||||||
|
a.low = floatx80_default_nan_low;
|
||||||
|
a.high = floatx80_default_nan_high;
|
||||||
|
# else
|
||||||
|
# error Rules for silencing a signaling NaN are target-specific
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
a.low |= LIT64( 0xC000000000000000 );
|
||||||
|
return a;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Returns the result of converting the extended double-precision floating-
|
| Returns the result of converting the extended double-precision floating-
|
||||||
| point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the
|
| point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the
|
||||||
|
@ -454,7 +571,8 @@ static floatx80 commonNaNToFloatx80( commonNaNT a )
|
||||||
|
|
||||||
static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM)
|
static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM)
|
||||||
{
|
{
|
||||||
flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
|
flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
|
||||||
|
flag aIsLargerSignificand;
|
||||||
|
|
||||||
if ( STATUS(default_nan_mode) ) {
|
if ( STATUS(default_nan_mode) ) {
|
||||||
a.low = floatx80_default_nan_low;
|
a.low = floatx80_default_nan_low;
|
||||||
|
@ -462,31 +580,26 @@ static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM)
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
aIsNaN = floatx80_is_nan( a );
|
aIsQuietNaN = floatx80_is_quiet_nan( a );
|
||||||
aIsSignalingNaN = floatx80_is_signaling_nan( a );
|
aIsSignalingNaN = floatx80_is_signaling_nan( a );
|
||||||
bIsNaN = floatx80_is_nan( b );
|
bIsQuietNaN = floatx80_is_quiet_nan( b );
|
||||||
bIsSignalingNaN = floatx80_is_signaling_nan( b );
|
bIsSignalingNaN = floatx80_is_signaling_nan( b );
|
||||||
#if SNAN_BIT_IS_ONE
|
|
||||||
a.low &= ~LIT64( 0xC000000000000000 );
|
|
||||||
b.low &= ~LIT64( 0xC000000000000000 );
|
|
||||||
#else
|
|
||||||
a.low |= LIT64( 0xC000000000000000 );
|
|
||||||
b.low |= LIT64( 0xC000000000000000 );
|
|
||||||
#endif
|
|
||||||
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
|
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
|
||||||
if ( aIsSignalingNaN ) {
|
|
||||||
if ( bIsSignalingNaN ) goto returnLargerSignificand;
|
if (a.low < b.low) {
|
||||||
return bIsNaN ? b : a;
|
aIsLargerSignificand = 0;
|
||||||
|
} else if (b.low < a.low) {
|
||||||
|
aIsLargerSignificand = 1;
|
||||||
|
} else {
|
||||||
|
aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
|
||||||
}
|
}
|
||||||
else if ( aIsNaN ) {
|
|
||||||
if ( bIsSignalingNaN || ! bIsNaN ) return a;
|
if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
|
||||||
returnLargerSignificand:
|
aIsLargerSignificand)) {
|
||||||
if ( a.low < b.low ) return b;
|
return floatx80_maybe_silence_nan(b);
|
||||||
if ( b.low < a.low ) return a;
|
} else {
|
||||||
return ( a.high < b.high ) ? a : b;
|
return floatx80_maybe_silence_nan(a);
|
||||||
}
|
|
||||||
else {
|
|
||||||
return b;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -511,7 +624,7 @@ static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM)
|
||||||
| NaN; otherwise returns 0.
|
| NaN; otherwise returns 0.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
int float128_is_nan( float128 a )
|
int float128_is_quiet_nan( float128 a )
|
||||||
{
|
{
|
||||||
#if SNAN_BIT_IS_ONE
|
#if SNAN_BIT_IS_ONE
|
||||||
return
|
return
|
||||||
|
@ -542,6 +655,29 @@ int float128_is_signaling_nan( float128 a )
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
| Returns a quiet NaN if the quadruple-precision floating point value `a' is
|
||||||
|
| a signaling NaN; otherwise returns `a'.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
float128 float128_maybe_silence_nan( float128 a )
|
||||||
|
{
|
||||||
|
if (float128_is_signaling_nan(a)) {
|
||||||
|
#if SNAN_BIT_IS_ONE
|
||||||
|
# if defined(TARGET_MIPS)
|
||||||
|
a.low = float128_default_nan_low;
|
||||||
|
a.high = float128_default_nan_high;
|
||||||
|
# else
|
||||||
|
# error Rules for silencing a signaling NaN are target-specific
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
a.high |= LIT64( 0x0000800000000000 );
|
||||||
|
return a;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Returns the result of converting the quadruple-precision floating-point NaN
|
| Returns the result of converting the quadruple-precision floating-point NaN
|
||||||
| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
|
| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
|
||||||
|
@ -580,7 +716,8 @@ static float128 commonNaNToFloat128( commonNaNT a )
|
||||||
|
|
||||||
static float128 propagateFloat128NaN( float128 a, float128 b STATUS_PARAM)
|
static float128 propagateFloat128NaN( float128 a, float128 b STATUS_PARAM)
|
||||||
{
|
{
|
||||||
flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
|
flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
|
||||||
|
flag aIsLargerSignificand;
|
||||||
|
|
||||||
if ( STATUS(default_nan_mode) ) {
|
if ( STATUS(default_nan_mode) ) {
|
||||||
a.low = float128_default_nan_low;
|
a.low = float128_default_nan_low;
|
||||||
|
@ -588,31 +725,26 @@ static float128 propagateFloat128NaN( float128 a, float128 b STATUS_PARAM)
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
aIsNaN = float128_is_nan( a );
|
aIsQuietNaN = float128_is_quiet_nan( a );
|
||||||
aIsSignalingNaN = float128_is_signaling_nan( a );
|
aIsSignalingNaN = float128_is_signaling_nan( a );
|
||||||
bIsNaN = float128_is_nan( b );
|
bIsQuietNaN = float128_is_quiet_nan( b );
|
||||||
bIsSignalingNaN = float128_is_signaling_nan( b );
|
bIsSignalingNaN = float128_is_signaling_nan( b );
|
||||||
#if SNAN_BIT_IS_ONE
|
|
||||||
a.high &= ~LIT64( 0x0000800000000000 );
|
|
||||||
b.high &= ~LIT64( 0x0000800000000000 );
|
|
||||||
#else
|
|
||||||
a.high |= LIT64( 0x0000800000000000 );
|
|
||||||
b.high |= LIT64( 0x0000800000000000 );
|
|
||||||
#endif
|
|
||||||
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
|
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
|
||||||
if ( aIsSignalingNaN ) {
|
|
||||||
if ( bIsSignalingNaN ) goto returnLargerSignificand;
|
if (lt128(a.high<<1, a.low, b.high<<1, b.low)) {
|
||||||
return bIsNaN ? b : a;
|
aIsLargerSignificand = 0;
|
||||||
|
} else if (lt128(b.high<<1, b.low, a.high<<1, a.low)) {
|
||||||
|
aIsLargerSignificand = 1;
|
||||||
|
} else {
|
||||||
|
aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
|
||||||
}
|
}
|
||||||
else if ( aIsNaN ) {
|
|
||||||
if ( bIsSignalingNaN || ! bIsNaN ) return a;
|
if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
|
||||||
returnLargerSignificand:
|
aIsLargerSignificand)) {
|
||||||
if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b;
|
return float128_maybe_silence_nan(b);
|
||||||
if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a;
|
} else {
|
||||||
return ( a.high < b.high ) ? a : b;
|
return float128_maybe_silence_nan(a);
|
||||||
}
|
|
||||||
else {
|
|
||||||
return b;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
104
fpu/softfloat.c
104
fpu/softfloat.c
|
@ -30,8 +30,6 @@ these four paragraphs for those parts of this code that are retained.
|
||||||
|
|
||||||
=============================================================================*/
|
=============================================================================*/
|
||||||
|
|
||||||
/* FIXME: Flush-To-Zero only effects results. Denormal inputs should also
|
|
||||||
be flushed to zero. */
|
|
||||||
#include "softfloat.h"
|
#include "softfloat.h"
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
|
@ -203,6 +201,21 @@ INLINE flag extractFloat32Sign( float32 a )
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
| If `a' is denormal and we are in flush-to-zero mode then set the
|
||||||
|
| input-denormal exception and return zero. Otherwise just return the value.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
static float32 float32_squash_input_denormal(float32 a STATUS_PARAM)
|
||||||
|
{
|
||||||
|
if (STATUS(flush_inputs_to_zero)) {
|
||||||
|
if (extractFloat32Exp(a) == 0 && extractFloat32Frac(a) != 0) {
|
||||||
|
float_raise(float_flag_input_denormal STATUS_VAR);
|
||||||
|
return make_float32(float32_val(a) & 0x80000000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Normalizes the subnormal single-precision floating-point value represented
|
| Normalizes the subnormal single-precision floating-point value represented
|
||||||
| by the denormalized significand `aSig'. The normalized exponent and
|
| by the denormalized significand `aSig'. The normalized exponent and
|
||||||
|
@ -367,6 +380,21 @@ INLINE flag extractFloat64Sign( float64 a )
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
| If `a' is denormal and we are in flush-to-zero mode then set the
|
||||||
|
| input-denormal exception and return zero. Otherwise just return the value.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
static float64 float64_squash_input_denormal(float64 a STATUS_PARAM)
|
||||||
|
{
|
||||||
|
if (STATUS(flush_inputs_to_zero)) {
|
||||||
|
if (extractFloat64Exp(a) == 0 && extractFloat64Frac(a) != 0) {
|
||||||
|
float_raise(float_flag_input_denormal STATUS_VAR);
|
||||||
|
return make_float64(float64_val(a) & (1ULL << 63));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Normalizes the subnormal double-precision floating-point value represented
|
| Normalizes the subnormal double-precision floating-point value represented
|
||||||
| by the denormalized significand `aSig'. The normalized exponent and
|
| by the denormalized significand `aSig'. The normalized exponent and
|
||||||
|
@ -1298,6 +1326,7 @@ int32 float32_to_int32( float32 a STATUS_PARAM )
|
||||||
bits32 aSig;
|
bits32 aSig;
|
||||||
bits64 aSig64;
|
bits64 aSig64;
|
||||||
|
|
||||||
|
a = float32_squash_input_denormal(a STATUS_VAR);
|
||||||
aSig = extractFloat32Frac( a );
|
aSig = extractFloat32Frac( a );
|
||||||
aExp = extractFloat32Exp( a );
|
aExp = extractFloat32Exp( a );
|
||||||
aSign = extractFloat32Sign( a );
|
aSign = extractFloat32Sign( a );
|
||||||
|
@ -1327,6 +1356,7 @@ int32 float32_to_int32_round_to_zero( float32 a STATUS_PARAM )
|
||||||
int16 aExp, shiftCount;
|
int16 aExp, shiftCount;
|
||||||
bits32 aSig;
|
bits32 aSig;
|
||||||
int32 z;
|
int32 z;
|
||||||
|
a = float32_squash_input_denormal(a STATUS_VAR);
|
||||||
|
|
||||||
aSig = extractFloat32Frac( a );
|
aSig = extractFloat32Frac( a );
|
||||||
aExp = extractFloat32Exp( a );
|
aExp = extractFloat32Exp( a );
|
||||||
|
@ -1418,6 +1448,7 @@ int64 float32_to_int64( float32 a STATUS_PARAM )
|
||||||
int16 aExp, shiftCount;
|
int16 aExp, shiftCount;
|
||||||
bits32 aSig;
|
bits32 aSig;
|
||||||
bits64 aSig64, aSigExtra;
|
bits64 aSig64, aSigExtra;
|
||||||
|
a = float32_squash_input_denormal(a STATUS_VAR);
|
||||||
|
|
||||||
aSig = extractFloat32Frac( a );
|
aSig = extractFloat32Frac( a );
|
||||||
aExp = extractFloat32Exp( a );
|
aExp = extractFloat32Exp( a );
|
||||||
|
@ -1455,6 +1486,7 @@ int64 float32_to_int64_round_to_zero( float32 a STATUS_PARAM )
|
||||||
bits32 aSig;
|
bits32 aSig;
|
||||||
bits64 aSig64;
|
bits64 aSig64;
|
||||||
int64 z;
|
int64 z;
|
||||||
|
a = float32_squash_input_denormal(a STATUS_VAR);
|
||||||
|
|
||||||
aSig = extractFloat32Frac( a );
|
aSig = extractFloat32Frac( a );
|
||||||
aExp = extractFloat32Exp( a );
|
aExp = extractFloat32Exp( a );
|
||||||
|
@ -1496,6 +1528,7 @@ float64 float32_to_float64( float32 a STATUS_PARAM )
|
||||||
flag aSign;
|
flag aSign;
|
||||||
int16 aExp;
|
int16 aExp;
|
||||||
bits32 aSig;
|
bits32 aSig;
|
||||||
|
a = float32_squash_input_denormal(a STATUS_VAR);
|
||||||
|
|
||||||
aSig = extractFloat32Frac( a );
|
aSig = extractFloat32Frac( a );
|
||||||
aExp = extractFloat32Exp( a );
|
aExp = extractFloat32Exp( a );
|
||||||
|
@ -1528,6 +1561,7 @@ floatx80 float32_to_floatx80( float32 a STATUS_PARAM )
|
||||||
int16 aExp;
|
int16 aExp;
|
||||||
bits32 aSig;
|
bits32 aSig;
|
||||||
|
|
||||||
|
a = float32_squash_input_denormal(a STATUS_VAR);
|
||||||
aSig = extractFloat32Frac( a );
|
aSig = extractFloat32Frac( a );
|
||||||
aExp = extractFloat32Exp( a );
|
aExp = extractFloat32Exp( a );
|
||||||
aSign = extractFloat32Sign( a );
|
aSign = extractFloat32Sign( a );
|
||||||
|
@ -1561,6 +1595,7 @@ float128 float32_to_float128( float32 a STATUS_PARAM )
|
||||||
int16 aExp;
|
int16 aExp;
|
||||||
bits32 aSig;
|
bits32 aSig;
|
||||||
|
|
||||||
|
a = float32_squash_input_denormal(a STATUS_VAR);
|
||||||
aSig = extractFloat32Frac( a );
|
aSig = extractFloat32Frac( a );
|
||||||
aExp = extractFloat32Exp( a );
|
aExp = extractFloat32Exp( a );
|
||||||
aSign = extractFloat32Sign( a );
|
aSign = extractFloat32Sign( a );
|
||||||
|
@ -1593,6 +1628,7 @@ float32 float32_round_to_int( float32 a STATUS_PARAM)
|
||||||
bits32 lastBitMask, roundBitsMask;
|
bits32 lastBitMask, roundBitsMask;
|
||||||
int8 roundingMode;
|
int8 roundingMode;
|
||||||
bits32 z;
|
bits32 z;
|
||||||
|
a = float32_squash_input_denormal(a STATUS_VAR);
|
||||||
|
|
||||||
aExp = extractFloat32Exp( a );
|
aExp = extractFloat32Exp( a );
|
||||||
if ( 0x96 <= aExp ) {
|
if ( 0x96 <= aExp ) {
|
||||||
|
@ -1796,6 +1832,8 @@ static float32 subFloat32Sigs( float32 a, float32 b, flag zSign STATUS_PARAM)
|
||||||
float32 float32_add( float32 a, float32 b STATUS_PARAM )
|
float32 float32_add( float32 a, float32 b STATUS_PARAM )
|
||||||
{
|
{
|
||||||
flag aSign, bSign;
|
flag aSign, bSign;
|
||||||
|
a = float32_squash_input_denormal(a STATUS_VAR);
|
||||||
|
b = float32_squash_input_denormal(b STATUS_VAR);
|
||||||
|
|
||||||
aSign = extractFloat32Sign( a );
|
aSign = extractFloat32Sign( a );
|
||||||
bSign = extractFloat32Sign( b );
|
bSign = extractFloat32Sign( b );
|
||||||
|
@ -1817,6 +1855,8 @@ float32 float32_add( float32 a, float32 b STATUS_PARAM )
|
||||||
float32 float32_sub( float32 a, float32 b STATUS_PARAM )
|
float32 float32_sub( float32 a, float32 b STATUS_PARAM )
|
||||||
{
|
{
|
||||||
flag aSign, bSign;
|
flag aSign, bSign;
|
||||||
|
a = float32_squash_input_denormal(a STATUS_VAR);
|
||||||
|
b = float32_squash_input_denormal(b STATUS_VAR);
|
||||||
|
|
||||||
aSign = extractFloat32Sign( a );
|
aSign = extractFloat32Sign( a );
|
||||||
bSign = extractFloat32Sign( b );
|
bSign = extractFloat32Sign( b );
|
||||||
|
@ -1843,6 +1883,9 @@ float32 float32_mul( float32 a, float32 b STATUS_PARAM )
|
||||||
bits64 zSig64;
|
bits64 zSig64;
|
||||||
bits32 zSig;
|
bits32 zSig;
|
||||||
|
|
||||||
|
a = float32_squash_input_denormal(a STATUS_VAR);
|
||||||
|
b = float32_squash_input_denormal(b STATUS_VAR);
|
||||||
|
|
||||||
aSig = extractFloat32Frac( a );
|
aSig = extractFloat32Frac( a );
|
||||||
aExp = extractFloat32Exp( a );
|
aExp = extractFloat32Exp( a );
|
||||||
aSign = extractFloat32Sign( a );
|
aSign = extractFloat32Sign( a );
|
||||||
|
@ -1900,6 +1943,8 @@ float32 float32_div( float32 a, float32 b STATUS_PARAM )
|
||||||
flag aSign, bSign, zSign;
|
flag aSign, bSign, zSign;
|
||||||
int16 aExp, bExp, zExp;
|
int16 aExp, bExp, zExp;
|
||||||
bits32 aSig, bSig, zSig;
|
bits32 aSig, bSig, zSig;
|
||||||
|
a = float32_squash_input_denormal(a STATUS_VAR);
|
||||||
|
b = float32_squash_input_denormal(b STATUS_VAR);
|
||||||
|
|
||||||
aSig = extractFloat32Frac( a );
|
aSig = extractFloat32Frac( a );
|
||||||
aExp = extractFloat32Exp( a );
|
aExp = extractFloat32Exp( a );
|
||||||
|
@ -1966,6 +2011,8 @@ float32 float32_rem( float32 a, float32 b STATUS_PARAM )
|
||||||
bits64 aSig64, bSig64, q64;
|
bits64 aSig64, bSig64, q64;
|
||||||
bits32 alternateASig;
|
bits32 alternateASig;
|
||||||
sbits32 sigMean;
|
sbits32 sigMean;
|
||||||
|
a = float32_squash_input_denormal(a STATUS_VAR);
|
||||||
|
b = float32_squash_input_denormal(b STATUS_VAR);
|
||||||
|
|
||||||
aSig = extractFloat32Frac( a );
|
aSig = extractFloat32Frac( a );
|
||||||
aExp = extractFloat32Exp( a );
|
aExp = extractFloat32Exp( a );
|
||||||
|
@ -2062,6 +2109,7 @@ float32 float32_sqrt( float32 a STATUS_PARAM )
|
||||||
int16 aExp, zExp;
|
int16 aExp, zExp;
|
||||||
bits32 aSig, zSig;
|
bits32 aSig, zSig;
|
||||||
bits64 rem, term;
|
bits64 rem, term;
|
||||||
|
a = float32_squash_input_denormal(a STATUS_VAR);
|
||||||
|
|
||||||
aSig = extractFloat32Frac( a );
|
aSig = extractFloat32Frac( a );
|
||||||
aExp = extractFloat32Exp( a );
|
aExp = extractFloat32Exp( a );
|
||||||
|
@ -2148,6 +2196,7 @@ float32 float32_exp2( float32 a STATUS_PARAM )
|
||||||
bits32 aSig;
|
bits32 aSig;
|
||||||
float64 r, x, xn;
|
float64 r, x, xn;
|
||||||
int i;
|
int i;
|
||||||
|
a = float32_squash_input_denormal(a STATUS_VAR);
|
||||||
|
|
||||||
aSig = extractFloat32Frac( a );
|
aSig = extractFloat32Frac( a );
|
||||||
aExp = extractFloat32Exp( a );
|
aExp = extractFloat32Exp( a );
|
||||||
|
@ -2194,6 +2243,7 @@ float32 float32_log2( float32 a STATUS_PARAM )
|
||||||
int16 aExp;
|
int16 aExp;
|
||||||
bits32 aSig, zSig, i;
|
bits32 aSig, zSig, i;
|
||||||
|
|
||||||
|
a = float32_squash_input_denormal(a STATUS_VAR);
|
||||||
aSig = extractFloat32Frac( a );
|
aSig = extractFloat32Frac( a );
|
||||||
aExp = extractFloat32Exp( a );
|
aExp = extractFloat32Exp( a );
|
||||||
aSign = extractFloat32Sign( a );
|
aSign = extractFloat32Sign( a );
|
||||||
|
@ -2238,6 +2288,8 @@ float32 float32_log2( float32 a STATUS_PARAM )
|
||||||
|
|
||||||
int float32_eq( float32 a, float32 b STATUS_PARAM )
|
int float32_eq( float32 a, float32 b STATUS_PARAM )
|
||||||
{
|
{
|
||||||
|
a = float32_squash_input_denormal(a STATUS_VAR);
|
||||||
|
b = float32_squash_input_denormal(b STATUS_VAR);
|
||||||
|
|
||||||
if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
|
if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
|
||||||
|| ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
|
|| ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
|
||||||
|
@ -2263,6 +2315,8 @@ int float32_le( float32 a, float32 b STATUS_PARAM )
|
||||||
{
|
{
|
||||||
flag aSign, bSign;
|
flag aSign, bSign;
|
||||||
bits32 av, bv;
|
bits32 av, bv;
|
||||||
|
a = float32_squash_input_denormal(a STATUS_VAR);
|
||||||
|
b = float32_squash_input_denormal(b STATUS_VAR);
|
||||||
|
|
||||||
if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
|
if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
|
||||||
|| ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
|
|| ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
|
||||||
|
@ -2289,6 +2343,8 @@ int float32_lt( float32 a, float32 b STATUS_PARAM )
|
||||||
{
|
{
|
||||||
flag aSign, bSign;
|
flag aSign, bSign;
|
||||||
bits32 av, bv;
|
bits32 av, bv;
|
||||||
|
a = float32_squash_input_denormal(a STATUS_VAR);
|
||||||
|
b = float32_squash_input_denormal(b STATUS_VAR);
|
||||||
|
|
||||||
if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
|
if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
|
||||||
|| ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
|
|| ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
|
||||||
|
@ -2315,6 +2371,8 @@ int float32_lt( float32 a, float32 b STATUS_PARAM )
|
||||||
int float32_eq_signaling( float32 a, float32 b STATUS_PARAM )
|
int float32_eq_signaling( float32 a, float32 b STATUS_PARAM )
|
||||||
{
|
{
|
||||||
bits32 av, bv;
|
bits32 av, bv;
|
||||||
|
a = float32_squash_input_denormal(a STATUS_VAR);
|
||||||
|
b = float32_squash_input_denormal(b STATUS_VAR);
|
||||||
|
|
||||||
if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
|
if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
|
||||||
|| ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
|
|| ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
|
||||||
|
@ -2339,6 +2397,8 @@ int float32_le_quiet( float32 a, float32 b STATUS_PARAM )
|
||||||
{
|
{
|
||||||
flag aSign, bSign;
|
flag aSign, bSign;
|
||||||
bits32 av, bv;
|
bits32 av, bv;
|
||||||
|
a = float32_squash_input_denormal(a STATUS_VAR);
|
||||||
|
b = float32_squash_input_denormal(b STATUS_VAR);
|
||||||
|
|
||||||
if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
|
if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
|
||||||
|| ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
|
|| ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
|
||||||
|
@ -2368,6 +2428,8 @@ int float32_lt_quiet( float32 a, float32 b STATUS_PARAM )
|
||||||
{
|
{
|
||||||
flag aSign, bSign;
|
flag aSign, bSign;
|
||||||
bits32 av, bv;
|
bits32 av, bv;
|
||||||
|
a = float32_squash_input_denormal(a STATUS_VAR);
|
||||||
|
b = float32_squash_input_denormal(b STATUS_VAR);
|
||||||
|
|
||||||
if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
|
if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
|
||||||
|| ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
|
|| ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
|
||||||
|
@ -2401,6 +2463,7 @@ int32 float64_to_int32( float64 a STATUS_PARAM )
|
||||||
flag aSign;
|
flag aSign;
|
||||||
int16 aExp, shiftCount;
|
int16 aExp, shiftCount;
|
||||||
bits64 aSig;
|
bits64 aSig;
|
||||||
|
a = float64_squash_input_denormal(a STATUS_VAR);
|
||||||
|
|
||||||
aSig = extractFloat64Frac( a );
|
aSig = extractFloat64Frac( a );
|
||||||
aExp = extractFloat64Exp( a );
|
aExp = extractFloat64Exp( a );
|
||||||
|
@ -2429,6 +2492,7 @@ int32 float64_to_int32_round_to_zero( float64 a STATUS_PARAM )
|
||||||
int16 aExp, shiftCount;
|
int16 aExp, shiftCount;
|
||||||
bits64 aSig, savedASig;
|
bits64 aSig, savedASig;
|
||||||
int32 z;
|
int32 z;
|
||||||
|
a = float64_squash_input_denormal(a STATUS_VAR);
|
||||||
|
|
||||||
aSig = extractFloat64Frac( a );
|
aSig = extractFloat64Frac( a );
|
||||||
aExp = extractFloat64Exp( a );
|
aExp = extractFloat64Exp( a );
|
||||||
|
@ -2525,6 +2589,7 @@ int64 float64_to_int64( float64 a STATUS_PARAM )
|
||||||
flag aSign;
|
flag aSign;
|
||||||
int16 aExp, shiftCount;
|
int16 aExp, shiftCount;
|
||||||
bits64 aSig, aSigExtra;
|
bits64 aSig, aSigExtra;
|
||||||
|
a = float64_squash_input_denormal(a STATUS_VAR);
|
||||||
|
|
||||||
aSig = extractFloat64Frac( a );
|
aSig = extractFloat64Frac( a );
|
||||||
aExp = extractFloat64Exp( a );
|
aExp = extractFloat64Exp( a );
|
||||||
|
@ -2568,6 +2633,7 @@ int64 float64_to_int64_round_to_zero( float64 a STATUS_PARAM )
|
||||||
int16 aExp, shiftCount;
|
int16 aExp, shiftCount;
|
||||||
bits64 aSig;
|
bits64 aSig;
|
||||||
int64 z;
|
int64 z;
|
||||||
|
a = float64_squash_input_denormal(a STATUS_VAR);
|
||||||
|
|
||||||
aSig = extractFloat64Frac( a );
|
aSig = extractFloat64Frac( a );
|
||||||
aExp = extractFloat64Exp( a );
|
aExp = extractFloat64Exp( a );
|
||||||
|
@ -2617,6 +2683,7 @@ float32 float64_to_float32( float64 a STATUS_PARAM )
|
||||||
int16 aExp;
|
int16 aExp;
|
||||||
bits64 aSig;
|
bits64 aSig;
|
||||||
bits32 zSig;
|
bits32 zSig;
|
||||||
|
a = float64_squash_input_denormal(a STATUS_VAR);
|
||||||
|
|
||||||
aSig = extractFloat64Frac( a );
|
aSig = extractFloat64Frac( a );
|
||||||
aExp = extractFloat64Exp( a );
|
aExp = extractFloat64Exp( a );
|
||||||
|
@ -2694,6 +2761,7 @@ bits16 float32_to_float16( float32 a, flag ieee STATUS_PARAM)
|
||||||
bits32 mask;
|
bits32 mask;
|
||||||
bits32 increment;
|
bits32 increment;
|
||||||
int8 roundingMode;
|
int8 roundingMode;
|
||||||
|
a = float32_squash_input_denormal(a STATUS_VAR);
|
||||||
|
|
||||||
aSig = extractFloat32Frac( a );
|
aSig = extractFloat32Frac( a );
|
||||||
aExp = extractFloat32Exp( a );
|
aExp = extractFloat32Exp( a );
|
||||||
|
@ -2788,6 +2856,7 @@ floatx80 float64_to_floatx80( float64 a STATUS_PARAM )
|
||||||
int16 aExp;
|
int16 aExp;
|
||||||
bits64 aSig;
|
bits64 aSig;
|
||||||
|
|
||||||
|
a = float64_squash_input_denormal(a STATUS_VAR);
|
||||||
aSig = extractFloat64Frac( a );
|
aSig = extractFloat64Frac( a );
|
||||||
aExp = extractFloat64Exp( a );
|
aExp = extractFloat64Exp( a );
|
||||||
aSign = extractFloat64Sign( a );
|
aSign = extractFloat64Sign( a );
|
||||||
|
@ -2822,6 +2891,7 @@ float128 float64_to_float128( float64 a STATUS_PARAM )
|
||||||
int16 aExp;
|
int16 aExp;
|
||||||
bits64 aSig, zSig0, zSig1;
|
bits64 aSig, zSig0, zSig1;
|
||||||
|
|
||||||
|
a = float64_squash_input_denormal(a STATUS_VAR);
|
||||||
aSig = extractFloat64Frac( a );
|
aSig = extractFloat64Frac( a );
|
||||||
aExp = extractFloat64Exp( a );
|
aExp = extractFloat64Exp( a );
|
||||||
aSign = extractFloat64Sign( a );
|
aSign = extractFloat64Sign( a );
|
||||||
|
@ -2855,6 +2925,7 @@ float64 float64_round_to_int( float64 a STATUS_PARAM )
|
||||||
bits64 lastBitMask, roundBitsMask;
|
bits64 lastBitMask, roundBitsMask;
|
||||||
int8 roundingMode;
|
int8 roundingMode;
|
||||||
bits64 z;
|
bits64 z;
|
||||||
|
a = float64_squash_input_denormal(a STATUS_VAR);
|
||||||
|
|
||||||
aExp = extractFloat64Exp( a );
|
aExp = extractFloat64Exp( a );
|
||||||
if ( 0x433 <= aExp ) {
|
if ( 0x433 <= aExp ) {
|
||||||
|
@ -3071,6 +3142,8 @@ static float64 subFloat64Sigs( float64 a, float64 b, flag zSign STATUS_PARAM )
|
||||||
float64 float64_add( float64 a, float64 b STATUS_PARAM )
|
float64 float64_add( float64 a, float64 b STATUS_PARAM )
|
||||||
{
|
{
|
||||||
flag aSign, bSign;
|
flag aSign, bSign;
|
||||||
|
a = float64_squash_input_denormal(a STATUS_VAR);
|
||||||
|
b = float64_squash_input_denormal(b STATUS_VAR);
|
||||||
|
|
||||||
aSign = extractFloat64Sign( a );
|
aSign = extractFloat64Sign( a );
|
||||||
bSign = extractFloat64Sign( b );
|
bSign = extractFloat64Sign( b );
|
||||||
|
@ -3092,6 +3165,8 @@ float64 float64_add( float64 a, float64 b STATUS_PARAM )
|
||||||
float64 float64_sub( float64 a, float64 b STATUS_PARAM )
|
float64 float64_sub( float64 a, float64 b STATUS_PARAM )
|
||||||
{
|
{
|
||||||
flag aSign, bSign;
|
flag aSign, bSign;
|
||||||
|
a = float64_squash_input_denormal(a STATUS_VAR);
|
||||||
|
b = float64_squash_input_denormal(b STATUS_VAR);
|
||||||
|
|
||||||
aSign = extractFloat64Sign( a );
|
aSign = extractFloat64Sign( a );
|
||||||
bSign = extractFloat64Sign( b );
|
bSign = extractFloat64Sign( b );
|
||||||
|
@ -3116,6 +3191,9 @@ float64 float64_mul( float64 a, float64 b STATUS_PARAM )
|
||||||
int16 aExp, bExp, zExp;
|
int16 aExp, bExp, zExp;
|
||||||
bits64 aSig, bSig, zSig0, zSig1;
|
bits64 aSig, bSig, zSig0, zSig1;
|
||||||
|
|
||||||
|
a = float64_squash_input_denormal(a STATUS_VAR);
|
||||||
|
b = float64_squash_input_denormal(b STATUS_VAR);
|
||||||
|
|
||||||
aSig = extractFloat64Frac( a );
|
aSig = extractFloat64Frac( a );
|
||||||
aExp = extractFloat64Exp( a );
|
aExp = extractFloat64Exp( a );
|
||||||
aSign = extractFloat64Sign( a );
|
aSign = extractFloat64Sign( a );
|
||||||
|
@ -3175,6 +3253,8 @@ float64 float64_div( float64 a, float64 b STATUS_PARAM )
|
||||||
bits64 aSig, bSig, zSig;
|
bits64 aSig, bSig, zSig;
|
||||||
bits64 rem0, rem1;
|
bits64 rem0, rem1;
|
||||||
bits64 term0, term1;
|
bits64 term0, term1;
|
||||||
|
a = float64_squash_input_denormal(a STATUS_VAR);
|
||||||
|
b = float64_squash_input_denormal(b STATUS_VAR);
|
||||||
|
|
||||||
aSig = extractFloat64Frac( a );
|
aSig = extractFloat64Frac( a );
|
||||||
aExp = extractFloat64Exp( a );
|
aExp = extractFloat64Exp( a );
|
||||||
|
@ -3246,6 +3326,8 @@ float64 float64_rem( float64 a, float64 b STATUS_PARAM )
|
||||||
bits64 q, alternateASig;
|
bits64 q, alternateASig;
|
||||||
sbits64 sigMean;
|
sbits64 sigMean;
|
||||||
|
|
||||||
|
a = float64_squash_input_denormal(a STATUS_VAR);
|
||||||
|
b = float64_squash_input_denormal(b STATUS_VAR);
|
||||||
aSig = extractFloat64Frac( a );
|
aSig = extractFloat64Frac( a );
|
||||||
aExp = extractFloat64Exp( a );
|
aExp = extractFloat64Exp( a );
|
||||||
aSign = extractFloat64Sign( a );
|
aSign = extractFloat64Sign( a );
|
||||||
|
@ -3328,6 +3410,7 @@ float64 float64_sqrt( float64 a STATUS_PARAM )
|
||||||
int16 aExp, zExp;
|
int16 aExp, zExp;
|
||||||
bits64 aSig, zSig, doubleZSig;
|
bits64 aSig, zSig, doubleZSig;
|
||||||
bits64 rem0, rem1, term0, term1;
|
bits64 rem0, rem1, term0, term1;
|
||||||
|
a = float64_squash_input_denormal(a STATUS_VAR);
|
||||||
|
|
||||||
aSig = extractFloat64Frac( a );
|
aSig = extractFloat64Frac( a );
|
||||||
aExp = extractFloat64Exp( a );
|
aExp = extractFloat64Exp( a );
|
||||||
|
@ -3377,6 +3460,7 @@ float64 float64_log2( float64 a STATUS_PARAM )
|
||||||
flag aSign, zSign;
|
flag aSign, zSign;
|
||||||
int16 aExp;
|
int16 aExp;
|
||||||
bits64 aSig, aSig0, aSig1, zSig, i;
|
bits64 aSig, aSig0, aSig1, zSig, i;
|
||||||
|
a = float64_squash_input_denormal(a STATUS_VAR);
|
||||||
|
|
||||||
aSig = extractFloat64Frac( a );
|
aSig = extractFloat64Frac( a );
|
||||||
aExp = extractFloat64Exp( a );
|
aExp = extractFloat64Exp( a );
|
||||||
|
@ -3422,6 +3506,8 @@ float64 float64_log2( float64 a STATUS_PARAM )
|
||||||
int float64_eq( float64 a, float64 b STATUS_PARAM )
|
int float64_eq( float64 a, float64 b STATUS_PARAM )
|
||||||
{
|
{
|
||||||
bits64 av, bv;
|
bits64 av, bv;
|
||||||
|
a = float64_squash_input_denormal(a STATUS_VAR);
|
||||||
|
b = float64_squash_input_denormal(b STATUS_VAR);
|
||||||
|
|
||||||
if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
|
if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
|
||||||
|| ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
|
|| ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
|
||||||
|
@ -3448,6 +3534,8 @@ int float64_le( float64 a, float64 b STATUS_PARAM )
|
||||||
{
|
{
|
||||||
flag aSign, bSign;
|
flag aSign, bSign;
|
||||||
bits64 av, bv;
|
bits64 av, bv;
|
||||||
|
a = float64_squash_input_denormal(a STATUS_VAR);
|
||||||
|
b = float64_squash_input_denormal(b STATUS_VAR);
|
||||||
|
|
||||||
if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
|
if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
|
||||||
|| ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
|
|| ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
|
||||||
|
@ -3475,6 +3563,8 @@ int float64_lt( float64 a, float64 b STATUS_PARAM )
|
||||||
flag aSign, bSign;
|
flag aSign, bSign;
|
||||||
bits64 av, bv;
|
bits64 av, bv;
|
||||||
|
|
||||||
|
a = float64_squash_input_denormal(a STATUS_VAR);
|
||||||
|
b = float64_squash_input_denormal(b STATUS_VAR);
|
||||||
if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
|
if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
|
||||||
|| ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
|
|| ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
|
||||||
) {
|
) {
|
||||||
|
@ -3500,6 +3590,8 @@ int float64_lt( float64 a, float64 b STATUS_PARAM )
|
||||||
int float64_eq_signaling( float64 a, float64 b STATUS_PARAM )
|
int float64_eq_signaling( float64 a, float64 b STATUS_PARAM )
|
||||||
{
|
{
|
||||||
bits64 av, bv;
|
bits64 av, bv;
|
||||||
|
a = float64_squash_input_denormal(a STATUS_VAR);
|
||||||
|
b = float64_squash_input_denormal(b STATUS_VAR);
|
||||||
|
|
||||||
if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
|
if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
|
||||||
|| ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
|
|| ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
|
||||||
|
@ -3524,6 +3616,8 @@ int float64_le_quiet( float64 a, float64 b STATUS_PARAM )
|
||||||
{
|
{
|
||||||
flag aSign, bSign;
|
flag aSign, bSign;
|
||||||
bits64 av, bv;
|
bits64 av, bv;
|
||||||
|
a = float64_squash_input_denormal(a STATUS_VAR);
|
||||||
|
b = float64_squash_input_denormal(b STATUS_VAR);
|
||||||
|
|
||||||
if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
|
if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
|
||||||
|| ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
|
|| ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
|
||||||
|
@ -3553,6 +3647,8 @@ int float64_lt_quiet( float64 a, float64 b STATUS_PARAM )
|
||||||
{
|
{
|
||||||
flag aSign, bSign;
|
flag aSign, bSign;
|
||||||
bits64 av, bv;
|
bits64 av, bv;
|
||||||
|
a = float64_squash_input_denormal(a STATUS_VAR);
|
||||||
|
b = float64_squash_input_denormal(b STATUS_VAR);
|
||||||
|
|
||||||
if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
|
if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
|
||||||
|| ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
|
|| ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
|
||||||
|
@ -5833,6 +5929,8 @@ INLINE int float ## s ## _compare_internal( float ## s a, float ## s b, \
|
||||||
{ \
|
{ \
|
||||||
flag aSign, bSign; \
|
flag aSign, bSign; \
|
||||||
bits ## s av, bv; \
|
bits ## s av, bv; \
|
||||||
|
a = float ## s ## _squash_input_denormal(a STATUS_VAR); \
|
||||||
|
b = float ## s ## _squash_input_denormal(b STATUS_VAR); \
|
||||||
\
|
\
|
||||||
if (( ( extractFloat ## s ## Exp( a ) == nan_exp ) && \
|
if (( ( extractFloat ## s ## Exp( a ) == nan_exp ) && \
|
||||||
extractFloat ## s ## Frac( a ) ) || \
|
extractFloat ## s ## Frac( a ) ) || \
|
||||||
|
@ -5929,6 +6027,7 @@ float32 float32_scalbn( float32 a, int n STATUS_PARAM )
|
||||||
int16 aExp;
|
int16 aExp;
|
||||||
bits32 aSig;
|
bits32 aSig;
|
||||||
|
|
||||||
|
a = float32_squash_input_denormal(a STATUS_VAR);
|
||||||
aSig = extractFloat32Frac( a );
|
aSig = extractFloat32Frac( a );
|
||||||
aExp = extractFloat32Exp( a );
|
aExp = extractFloat32Exp( a );
|
||||||
aSign = extractFloat32Sign( a );
|
aSign = extractFloat32Sign( a );
|
||||||
|
@ -5952,6 +6051,7 @@ float64 float64_scalbn( float64 a, int n STATUS_PARAM )
|
||||||
int16 aExp;
|
int16 aExp;
|
||||||
bits64 aSig;
|
bits64 aSig;
|
||||||
|
|
||||||
|
a = float64_squash_input_denormal(a STATUS_VAR);
|
||||||
aSig = extractFloat64Frac( a );
|
aSig = extractFloat64Frac( a );
|
||||||
aExp = extractFloat64Exp( a );
|
aExp = extractFloat64Exp( a );
|
||||||
aSign = extractFloat64Sign( a );
|
aSign = extractFloat64Sign( a );
|
||||||
|
|
|
@ -180,7 +180,8 @@ enum {
|
||||||
float_flag_divbyzero = 4,
|
float_flag_divbyzero = 4,
|
||||||
float_flag_overflow = 8,
|
float_flag_overflow = 8,
|
||||||
float_flag_underflow = 16,
|
float_flag_underflow = 16,
|
||||||
float_flag_inexact = 32
|
float_flag_inexact = 32,
|
||||||
|
float_flag_input_denormal = 64
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct float_status {
|
typedef struct float_status {
|
||||||
|
@ -190,7 +191,10 @@ typedef struct float_status {
|
||||||
#ifdef FLOATX80
|
#ifdef FLOATX80
|
||||||
signed char floatx80_rounding_precision;
|
signed char floatx80_rounding_precision;
|
||||||
#endif
|
#endif
|
||||||
|
/* should denormalised results go to zero and set the inexact flag? */
|
||||||
flag flush_to_zero;
|
flag flush_to_zero;
|
||||||
|
/* should denormalised inputs go to zero and set the input_denormal flag? */
|
||||||
|
flag flush_inputs_to_zero;
|
||||||
flag default_nan_mode;
|
flag default_nan_mode;
|
||||||
} float_status;
|
} float_status;
|
||||||
|
|
||||||
|
@ -200,6 +204,10 @@ INLINE void set_flush_to_zero(flag val STATUS_PARAM)
|
||||||
{
|
{
|
||||||
STATUS(flush_to_zero) = val;
|
STATUS(flush_to_zero) = val;
|
||||||
}
|
}
|
||||||
|
INLINE void set_flush_inputs_to_zero(flag val STATUS_PARAM)
|
||||||
|
{
|
||||||
|
STATUS(flush_inputs_to_zero) = val;
|
||||||
|
}
|
||||||
INLINE void set_default_nan_mode(flag val STATUS_PARAM)
|
INLINE void set_default_nan_mode(flag val STATUS_PARAM)
|
||||||
{
|
{
|
||||||
STATUS(default_nan_mode) = val;
|
STATUS(default_nan_mode) = val;
|
||||||
|
@ -287,18 +295,24 @@ int float32_le_quiet( float32, float32 STATUS_PARAM );
|
||||||
int float32_lt_quiet( float32, float32 STATUS_PARAM );
|
int float32_lt_quiet( float32, float32 STATUS_PARAM );
|
||||||
int float32_compare( float32, float32 STATUS_PARAM );
|
int float32_compare( float32, float32 STATUS_PARAM );
|
||||||
int float32_compare_quiet( float32, float32 STATUS_PARAM );
|
int float32_compare_quiet( float32, float32 STATUS_PARAM );
|
||||||
int float32_is_nan( float32 );
|
int float32_is_quiet_nan( float32 );
|
||||||
int float32_is_signaling_nan( float32 );
|
int float32_is_signaling_nan( float32 );
|
||||||
float32 float32_maybe_silence_nan( float32 );
|
float32 float32_maybe_silence_nan( float32 );
|
||||||
float32 float32_scalbn( float32, int STATUS_PARAM );
|
float32 float32_scalbn( float32, int STATUS_PARAM );
|
||||||
|
|
||||||
INLINE float32 float32_abs(float32 a)
|
INLINE float32 float32_abs(float32 a)
|
||||||
{
|
{
|
||||||
|
/* Note that abs does *not* handle NaN specially, nor does
|
||||||
|
* it flush denormal inputs to zero.
|
||||||
|
*/
|
||||||
return make_float32(float32_val(a) & 0x7fffffff);
|
return make_float32(float32_val(a) & 0x7fffffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE float32 float32_chs(float32 a)
|
INLINE float32 float32_chs(float32 a)
|
||||||
{
|
{
|
||||||
|
/* Note that chs does *not* handle NaN specially, nor does
|
||||||
|
* it flush denormal inputs to zero.
|
||||||
|
*/
|
||||||
return make_float32(float32_val(a) ^ 0x80000000);
|
return make_float32(float32_val(a) ^ 0x80000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,18 +381,24 @@ int float64_le_quiet( float64, float64 STATUS_PARAM );
|
||||||
int float64_lt_quiet( float64, float64 STATUS_PARAM );
|
int float64_lt_quiet( float64, float64 STATUS_PARAM );
|
||||||
int float64_compare( float64, float64 STATUS_PARAM );
|
int float64_compare( float64, float64 STATUS_PARAM );
|
||||||
int float64_compare_quiet( float64, float64 STATUS_PARAM );
|
int float64_compare_quiet( float64, float64 STATUS_PARAM );
|
||||||
int float64_is_nan( float64 a );
|
int float64_is_quiet_nan( float64 a );
|
||||||
int float64_is_signaling_nan( float64 );
|
int float64_is_signaling_nan( float64 );
|
||||||
float64 float64_maybe_silence_nan( float64 );
|
float64 float64_maybe_silence_nan( float64 );
|
||||||
float64 float64_scalbn( float64, int STATUS_PARAM );
|
float64 float64_scalbn( float64, int STATUS_PARAM );
|
||||||
|
|
||||||
INLINE float64 float64_abs(float64 a)
|
INLINE float64 float64_abs(float64 a)
|
||||||
{
|
{
|
||||||
|
/* Note that abs does *not* handle NaN specially, nor does
|
||||||
|
* it flush denormal inputs to zero.
|
||||||
|
*/
|
||||||
return make_float64(float64_val(a) & 0x7fffffffffffffffLL);
|
return make_float64(float64_val(a) & 0x7fffffffffffffffLL);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE float64 float64_chs(float64 a)
|
INLINE float64 float64_chs(float64 a)
|
||||||
{
|
{
|
||||||
|
/* Note that chs does *not* handle NaN specially, nor does
|
||||||
|
* it flush denormal inputs to zero.
|
||||||
|
*/
|
||||||
return make_float64(float64_val(a) ^ 0x8000000000000000LL);
|
return make_float64(float64_val(a) ^ 0x8000000000000000LL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -437,8 +457,9 @@ int floatx80_lt( floatx80, floatx80 STATUS_PARAM );
|
||||||
int floatx80_eq_signaling( floatx80, floatx80 STATUS_PARAM );
|
int floatx80_eq_signaling( floatx80, floatx80 STATUS_PARAM );
|
||||||
int floatx80_le_quiet( floatx80, floatx80 STATUS_PARAM );
|
int floatx80_le_quiet( floatx80, floatx80 STATUS_PARAM );
|
||||||
int floatx80_lt_quiet( floatx80, floatx80 STATUS_PARAM );
|
int floatx80_lt_quiet( floatx80, floatx80 STATUS_PARAM );
|
||||||
int floatx80_is_nan( floatx80 );
|
int floatx80_is_quiet_nan( floatx80 );
|
||||||
int floatx80_is_signaling_nan( floatx80 );
|
int floatx80_is_signaling_nan( floatx80 );
|
||||||
|
floatx80 floatx80_maybe_silence_nan( floatx80 );
|
||||||
floatx80 floatx80_scalbn( floatx80, int STATUS_PARAM );
|
floatx80 floatx80_scalbn( floatx80, int STATUS_PARAM );
|
||||||
|
|
||||||
INLINE floatx80 floatx80_abs(floatx80 a)
|
INLINE floatx80 floatx80_abs(floatx80 a)
|
||||||
|
@ -468,6 +489,11 @@ INLINE int floatx80_is_zero(floatx80 a)
|
||||||
return (a.high & 0x7fff) == 0 && a.low == 0;
|
return (a.high & 0x7fff) == 0 && a.low == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INLINE int floatx80_is_any_nan(floatx80 a)
|
||||||
|
{
|
||||||
|
return ((a.high & 0x7fff) == 0x7fff) && (a.low<<1);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef FLOAT128
|
#ifdef FLOAT128
|
||||||
|
@ -503,8 +529,9 @@ int float128_le_quiet( float128, float128 STATUS_PARAM );
|
||||||
int float128_lt_quiet( float128, float128 STATUS_PARAM );
|
int float128_lt_quiet( float128, float128 STATUS_PARAM );
|
||||||
int float128_compare( float128, float128 STATUS_PARAM );
|
int float128_compare( float128, float128 STATUS_PARAM );
|
||||||
int float128_compare_quiet( float128, float128 STATUS_PARAM );
|
int float128_compare_quiet( float128, float128 STATUS_PARAM );
|
||||||
int float128_is_nan( float128 );
|
int float128_is_quiet_nan( float128 );
|
||||||
int float128_is_signaling_nan( float128 );
|
int float128_is_signaling_nan( float128 );
|
||||||
|
float128 float128_maybe_silence_nan( float128 );
|
||||||
float128 float128_scalbn( float128, int STATUS_PARAM );
|
float128 float128_scalbn( float128, int STATUS_PARAM );
|
||||||
|
|
||||||
INLINE float128 float128_abs(float128 a)
|
INLINE float128 float128_abs(float128 a)
|
||||||
|
@ -534,6 +561,12 @@ INLINE int float128_is_zero(float128 a)
|
||||||
return (a.high & 0x7fffffffffffffffLL) == 0 && a.low == 0;
|
return (a.high & 0x7fffffffffffffffLL) == 0 && a.low == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INLINE int float128_is_any_nan(float128 a)
|
||||||
|
{
|
||||||
|
return ((a.high >> 48) & 0x7fff) == 0x7fff &&
|
||||||
|
((a.low != 0) || ((a.high & 0xffffffffffffLL) != 0));
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else /* CONFIG_SOFTFLOAT */
|
#else /* CONFIG_SOFTFLOAT */
|
||||||
|
|
|
@ -1176,6 +1176,60 @@ STEXI
|
||||||
@item block_passwd @var{device} @var{password}
|
@item block_passwd @var{device} @var{password}
|
||||||
@findex block_passwd
|
@findex block_passwd
|
||||||
Set the encrypted device @var{device} password to @var{password}
|
Set the encrypted device @var{device} password to @var{password}
|
||||||
|
ETEXI
|
||||||
|
|
||||||
|
{
|
||||||
|
.name = "set_password",
|
||||||
|
.args_type = "protocol:s,password:s,connected:s?",
|
||||||
|
.params = "protocol password action-if-connected",
|
||||||
|
.help = "set spice/vnc password",
|
||||||
|
.user_print = monitor_user_noop,
|
||||||
|
.mhandler.cmd_new = set_password,
|
||||||
|
},
|
||||||
|
|
||||||
|
STEXI
|
||||||
|
@item set_password [ vnc | spice ] password [ action-if-connected ]
|
||||||
|
@findex set_password
|
||||||
|
|
||||||
|
Change spice/vnc password. Use zero to make the password stay valid
|
||||||
|
forever. @var{action-if-connected} specifies what should happen in
|
||||||
|
case a connection is established: @var{fail} makes the password change
|
||||||
|
fail. @var{disconnect} changes the password and disconnects the
|
||||||
|
client. @var{keep} changes the password and keeps the connection up.
|
||||||
|
@var{keep} is the default.
|
||||||
|
ETEXI
|
||||||
|
|
||||||
|
{
|
||||||
|
.name = "expire_password",
|
||||||
|
.args_type = "protocol:s,time:s",
|
||||||
|
.params = "protocol time",
|
||||||
|
.help = "set spice/vnc password expire-time",
|
||||||
|
.user_print = monitor_user_noop,
|
||||||
|
.mhandler.cmd_new = expire_password,
|
||||||
|
},
|
||||||
|
|
||||||
|
STEXI
|
||||||
|
@item expire_password [ vnc | spice ] expire-time
|
||||||
|
@findex expire_password
|
||||||
|
|
||||||
|
Specify when a password for spice/vnc becomes
|
||||||
|
invalid. @var{expire-time} accepts:
|
||||||
|
|
||||||
|
@table @var
|
||||||
|
@item now
|
||||||
|
Invalidate password instantly.
|
||||||
|
|
||||||
|
@item never
|
||||||
|
Password stays valid forever.
|
||||||
|
|
||||||
|
@item +nsec
|
||||||
|
Password stays valid for @var{nsec} seconds starting now.
|
||||||
|
|
||||||
|
@item nsec
|
||||||
|
Password is invalidated at the given time. @var{nsec} are the seconds
|
||||||
|
passed since 1970, i.e. unix epoch.
|
||||||
|
|
||||||
|
@end table
|
||||||
ETEXI
|
ETEXI
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -1215,7 +1269,7 @@ show i8259 (PIC) state
|
||||||
@item info pci
|
@item info pci
|
||||||
show emulated PCI device info
|
show emulated PCI device info
|
||||||
@item info tlb
|
@item info tlb
|
||||||
show virtual to physical memory mappings (i386 only)
|
show virtual to physical memory mappings (i386, SH4 and SPARC only)
|
||||||
@item info mem
|
@item info mem
|
||||||
show the active virtual memory mappings (i386 only)
|
show the active virtual memory mappings (i386 only)
|
||||||
@item info jit
|
@item info jit
|
||||||
|
|
|
@ -765,7 +765,7 @@ static uint32_t apic_mem_readl(void *opaque, target_phys_addr_t addr)
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void apic_send_msi(target_phys_addr_t addr, uint32 data)
|
static void apic_send_msi(target_phys_addr_t addr, uint32_t data)
|
||||||
{
|
{
|
||||||
uint8_t dest = (addr & MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT;
|
uint8_t dest = (addr & MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT;
|
||||||
uint8_t vector = (data & MSI_DATA_VECTOR_MASK) >> MSI_DATA_VECTOR_SHIFT;
|
uint8_t vector = (data & MSI_DATA_VECTOR_MASK) >> MSI_DATA_VECTOR_SHIFT;
|
||||||
|
|
179
hw/cirrus_vga.c
179
hw/cirrus_vga.c
|
@ -673,46 +673,47 @@ static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s)
|
||||||
|
|
||||||
static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
|
static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
|
||||||
{
|
{
|
||||||
int sx, sy;
|
int sx = 0, sy = 0;
|
||||||
int dx, dy;
|
int dx = 0, dy = 0;
|
||||||
int width, height;
|
int depth = 0;
|
||||||
int depth;
|
|
||||||
int notify = 0;
|
int notify = 0;
|
||||||
|
|
||||||
depth = s->vga.get_bpp(&s->vga) / 8;
|
/* make sure to only copy if it's a plain copy ROP */
|
||||||
s->vga.get_resolution(&s->vga, &width, &height);
|
if (*s->cirrus_rop == cirrus_bitblt_rop_fwd_src ||
|
||||||
|
*s->cirrus_rop == cirrus_bitblt_rop_bkwd_src) {
|
||||||
|
|
||||||
/* extra x, y */
|
int width, height;
|
||||||
sx = (src % ABS(s->cirrus_blt_srcpitch)) / depth;
|
|
||||||
sy = (src / ABS(s->cirrus_blt_srcpitch));
|
|
||||||
dx = (dst % ABS(s->cirrus_blt_dstpitch)) / depth;
|
|
||||||
dy = (dst / ABS(s->cirrus_blt_dstpitch));
|
|
||||||
|
|
||||||
/* normalize width */
|
depth = s->vga.get_bpp(&s->vga) / 8;
|
||||||
w /= depth;
|
s->vga.get_resolution(&s->vga, &width, &height);
|
||||||
|
|
||||||
/* if we're doing a backward copy, we have to adjust
|
/* extra x, y */
|
||||||
our x/y to be the upper left corner (instead of the lower
|
sx = (src % ABS(s->cirrus_blt_srcpitch)) / depth;
|
||||||
right corner) */
|
sy = (src / ABS(s->cirrus_blt_srcpitch));
|
||||||
if (s->cirrus_blt_dstpitch < 0) {
|
dx = (dst % ABS(s->cirrus_blt_dstpitch)) / depth;
|
||||||
sx -= (s->cirrus_blt_width / depth) - 1;
|
dy = (dst / ABS(s->cirrus_blt_dstpitch));
|
||||||
dx -= (s->cirrus_blt_width / depth) - 1;
|
|
||||||
sy -= s->cirrus_blt_height - 1;
|
/* normalize width */
|
||||||
dy -= s->cirrus_blt_height - 1;
|
w /= depth;
|
||||||
|
|
||||||
|
/* if we're doing a backward copy, we have to adjust
|
||||||
|
our x/y to be the upper left corner (instead of the lower
|
||||||
|
right corner) */
|
||||||
|
if (s->cirrus_blt_dstpitch < 0) {
|
||||||
|
sx -= (s->cirrus_blt_width / depth) - 1;
|
||||||
|
dx -= (s->cirrus_blt_width / depth) - 1;
|
||||||
|
sy -= s->cirrus_blt_height - 1;
|
||||||
|
dy -= s->cirrus_blt_height - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* are we in the visible portion of memory? */
|
||||||
|
if (sx >= 0 && sy >= 0 && dx >= 0 && dy >= 0 &&
|
||||||
|
(sx + w) <= width && (sy + h) <= height &&
|
||||||
|
(dx + w) <= width && (dy + h) <= height) {
|
||||||
|
notify = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* are we in the visible portion of memory? */
|
|
||||||
if (sx >= 0 && sy >= 0 && dx >= 0 && dy >= 0 &&
|
|
||||||
(sx + w) <= width && (sy + h) <= height &&
|
|
||||||
(dx + w) <= width && (dy + h) <= height) {
|
|
||||||
notify = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* make to sure only copy if it's a plain copy ROP */
|
|
||||||
if (*s->cirrus_rop != cirrus_bitblt_rop_fwd_src &&
|
|
||||||
*s->cirrus_rop != cirrus_bitblt_rop_bkwd_src)
|
|
||||||
notify = 0;
|
|
||||||
|
|
||||||
/* we have to flush all pending changes so that the copy
|
/* we have to flush all pending changes so that the copy
|
||||||
is generated at the appropriate moment in time */
|
is generated at the appropriate moment in time */
|
||||||
if (notify)
|
if (notify)
|
||||||
|
@ -2003,30 +2004,20 @@ static uint32_t cirrus_vga_mem_readb(void *opaque, target_phys_addr_t addr)
|
||||||
static uint32_t cirrus_vga_mem_readw(void *opaque, target_phys_addr_t addr)
|
static uint32_t cirrus_vga_mem_readw(void *opaque, target_phys_addr_t addr)
|
||||||
{
|
{
|
||||||
uint32_t v;
|
uint32_t v;
|
||||||
#ifdef TARGET_WORDS_BIGENDIAN
|
|
||||||
v = cirrus_vga_mem_readb(opaque, addr) << 8;
|
|
||||||
v |= cirrus_vga_mem_readb(opaque, addr + 1);
|
|
||||||
#else
|
|
||||||
v = cirrus_vga_mem_readb(opaque, addr);
|
v = cirrus_vga_mem_readb(opaque, addr);
|
||||||
v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8;
|
v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8;
|
||||||
#endif
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t cirrus_vga_mem_readl(void *opaque, target_phys_addr_t addr)
|
static uint32_t cirrus_vga_mem_readl(void *opaque, target_phys_addr_t addr)
|
||||||
{
|
{
|
||||||
uint32_t v;
|
uint32_t v;
|
||||||
#ifdef TARGET_WORDS_BIGENDIAN
|
|
||||||
v = cirrus_vga_mem_readb(opaque, addr) << 24;
|
|
||||||
v |= cirrus_vga_mem_readb(opaque, addr + 1) << 16;
|
|
||||||
v |= cirrus_vga_mem_readb(opaque, addr + 2) << 8;
|
|
||||||
v |= cirrus_vga_mem_readb(opaque, addr + 3);
|
|
||||||
#else
|
|
||||||
v = cirrus_vga_mem_readb(opaque, addr);
|
v = cirrus_vga_mem_readb(opaque, addr);
|
||||||
v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8;
|
v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8;
|
||||||
v |= cirrus_vga_mem_readb(opaque, addr + 2) << 16;
|
v |= cirrus_vga_mem_readb(opaque, addr + 2) << 16;
|
||||||
v |= cirrus_vga_mem_readb(opaque, addr + 3) << 24;
|
v |= cirrus_vga_mem_readb(opaque, addr + 3) << 24;
|
||||||
#endif
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2097,28 +2088,16 @@ static void cirrus_vga_mem_writeb(void *opaque, target_phys_addr_t addr,
|
||||||
|
|
||||||
static void cirrus_vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
|
static void cirrus_vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
|
||||||
{
|
{
|
||||||
#ifdef TARGET_WORDS_BIGENDIAN
|
|
||||||
cirrus_vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
|
|
||||||
cirrus_vga_mem_writeb(opaque, addr + 1, val & 0xff);
|
|
||||||
#else
|
|
||||||
cirrus_vga_mem_writeb(opaque, addr, val & 0xff);
|
cirrus_vga_mem_writeb(opaque, addr, val & 0xff);
|
||||||
cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
|
cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cirrus_vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
|
static void cirrus_vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
|
||||||
{
|
{
|
||||||
#ifdef TARGET_WORDS_BIGENDIAN
|
|
||||||
cirrus_vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
|
|
||||||
cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
|
|
||||||
cirrus_vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
|
|
||||||
cirrus_vga_mem_writeb(opaque, addr + 3, val & 0xff);
|
|
||||||
#else
|
|
||||||
cirrus_vga_mem_writeb(opaque, addr, val & 0xff);
|
cirrus_vga_mem_writeb(opaque, addr, val & 0xff);
|
||||||
cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
|
cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
|
||||||
cirrus_vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
|
cirrus_vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
|
||||||
cirrus_vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
|
cirrus_vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static CPUReadMemoryFunc * const cirrus_vga_mem_read[3] = {
|
static CPUReadMemoryFunc * const cirrus_vga_mem_read[3] = {
|
||||||
|
@ -2340,30 +2319,20 @@ static uint32_t cirrus_linear_readb(void *opaque, target_phys_addr_t addr)
|
||||||
static uint32_t cirrus_linear_readw(void *opaque, target_phys_addr_t addr)
|
static uint32_t cirrus_linear_readw(void *opaque, target_phys_addr_t addr)
|
||||||
{
|
{
|
||||||
uint32_t v;
|
uint32_t v;
|
||||||
#ifdef TARGET_WORDS_BIGENDIAN
|
|
||||||
v = cirrus_linear_readb(opaque, addr) << 8;
|
|
||||||
v |= cirrus_linear_readb(opaque, addr + 1);
|
|
||||||
#else
|
|
||||||
v = cirrus_linear_readb(opaque, addr);
|
v = cirrus_linear_readb(opaque, addr);
|
||||||
v |= cirrus_linear_readb(opaque, addr + 1) << 8;
|
v |= cirrus_linear_readb(opaque, addr + 1) << 8;
|
||||||
#endif
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t cirrus_linear_readl(void *opaque, target_phys_addr_t addr)
|
static uint32_t cirrus_linear_readl(void *opaque, target_phys_addr_t addr)
|
||||||
{
|
{
|
||||||
uint32_t v;
|
uint32_t v;
|
||||||
#ifdef TARGET_WORDS_BIGENDIAN
|
|
||||||
v = cirrus_linear_readb(opaque, addr) << 24;
|
|
||||||
v |= cirrus_linear_readb(opaque, addr + 1) << 16;
|
|
||||||
v |= cirrus_linear_readb(opaque, addr + 2) << 8;
|
|
||||||
v |= cirrus_linear_readb(opaque, addr + 3);
|
|
||||||
#else
|
|
||||||
v = cirrus_linear_readb(opaque, addr);
|
v = cirrus_linear_readb(opaque, addr);
|
||||||
v |= cirrus_linear_readb(opaque, addr + 1) << 8;
|
v |= cirrus_linear_readb(opaque, addr + 1) << 8;
|
||||||
v |= cirrus_linear_readb(opaque, addr + 2) << 16;
|
v |= cirrus_linear_readb(opaque, addr + 2) << 16;
|
||||||
v |= cirrus_linear_readb(opaque, addr + 3) << 24;
|
v |= cirrus_linear_readb(opaque, addr + 3) << 24;
|
||||||
#endif
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2411,29 +2380,17 @@ static void cirrus_linear_writeb(void *opaque, target_phys_addr_t addr,
|
||||||
static void cirrus_linear_writew(void *opaque, target_phys_addr_t addr,
|
static void cirrus_linear_writew(void *opaque, target_phys_addr_t addr,
|
||||||
uint32_t val)
|
uint32_t val)
|
||||||
{
|
{
|
||||||
#ifdef TARGET_WORDS_BIGENDIAN
|
|
||||||
cirrus_linear_writeb(opaque, addr, (val >> 8) & 0xff);
|
|
||||||
cirrus_linear_writeb(opaque, addr + 1, val & 0xff);
|
|
||||||
#else
|
|
||||||
cirrus_linear_writeb(opaque, addr, val & 0xff);
|
cirrus_linear_writeb(opaque, addr, val & 0xff);
|
||||||
cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff);
|
cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cirrus_linear_writel(void *opaque, target_phys_addr_t addr,
|
static void cirrus_linear_writel(void *opaque, target_phys_addr_t addr,
|
||||||
uint32_t val)
|
uint32_t val)
|
||||||
{
|
{
|
||||||
#ifdef TARGET_WORDS_BIGENDIAN
|
|
||||||
cirrus_linear_writeb(opaque, addr, (val >> 24) & 0xff);
|
|
||||||
cirrus_linear_writeb(opaque, addr + 1, (val >> 16) & 0xff);
|
|
||||||
cirrus_linear_writeb(opaque, addr + 2, (val >> 8) & 0xff);
|
|
||||||
cirrus_linear_writeb(opaque, addr + 3, val & 0xff);
|
|
||||||
#else
|
|
||||||
cirrus_linear_writeb(opaque, addr, val & 0xff);
|
cirrus_linear_writeb(opaque, addr, val & 0xff);
|
||||||
cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff);
|
cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff);
|
||||||
cirrus_linear_writeb(opaque, addr + 2, (val >> 16) & 0xff);
|
cirrus_linear_writeb(opaque, addr + 2, (val >> 16) & 0xff);
|
||||||
cirrus_linear_writeb(opaque, addr + 3, (val >> 24) & 0xff);
|
cirrus_linear_writeb(opaque, addr + 3, (val >> 24) & 0xff);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2468,30 +2425,20 @@ static uint32_t cirrus_linear_bitblt_readb(void *opaque, target_phys_addr_t addr
|
||||||
static uint32_t cirrus_linear_bitblt_readw(void *opaque, target_phys_addr_t addr)
|
static uint32_t cirrus_linear_bitblt_readw(void *opaque, target_phys_addr_t addr)
|
||||||
{
|
{
|
||||||
uint32_t v;
|
uint32_t v;
|
||||||
#ifdef TARGET_WORDS_BIGENDIAN
|
|
||||||
v = cirrus_linear_bitblt_readb(opaque, addr) << 8;
|
|
||||||
v |= cirrus_linear_bitblt_readb(opaque, addr + 1);
|
|
||||||
#else
|
|
||||||
v = cirrus_linear_bitblt_readb(opaque, addr);
|
v = cirrus_linear_bitblt_readb(opaque, addr);
|
||||||
v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 8;
|
v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 8;
|
||||||
#endif
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t cirrus_linear_bitblt_readl(void *opaque, target_phys_addr_t addr)
|
static uint32_t cirrus_linear_bitblt_readl(void *opaque, target_phys_addr_t addr)
|
||||||
{
|
{
|
||||||
uint32_t v;
|
uint32_t v;
|
||||||
#ifdef TARGET_WORDS_BIGENDIAN
|
|
||||||
v = cirrus_linear_bitblt_readb(opaque, addr) << 24;
|
|
||||||
v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 16;
|
|
||||||
v |= cirrus_linear_bitblt_readb(opaque, addr + 2) << 8;
|
|
||||||
v |= cirrus_linear_bitblt_readb(opaque, addr + 3);
|
|
||||||
#else
|
|
||||||
v = cirrus_linear_bitblt_readb(opaque, addr);
|
v = cirrus_linear_bitblt_readb(opaque, addr);
|
||||||
v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 8;
|
v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 8;
|
||||||
v |= cirrus_linear_bitblt_readb(opaque, addr + 2) << 16;
|
v |= cirrus_linear_bitblt_readb(opaque, addr + 2) << 16;
|
||||||
v |= cirrus_linear_bitblt_readb(opaque, addr + 3) << 24;
|
v |= cirrus_linear_bitblt_readb(opaque, addr + 3) << 24;
|
||||||
#endif
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2512,29 +2459,17 @@ static void cirrus_linear_bitblt_writeb(void *opaque, target_phys_addr_t addr,
|
||||||
static void cirrus_linear_bitblt_writew(void *opaque, target_phys_addr_t addr,
|
static void cirrus_linear_bitblt_writew(void *opaque, target_phys_addr_t addr,
|
||||||
uint32_t val)
|
uint32_t val)
|
||||||
{
|
{
|
||||||
#ifdef TARGET_WORDS_BIGENDIAN
|
|
||||||
cirrus_linear_bitblt_writeb(opaque, addr, (val >> 8) & 0xff);
|
|
||||||
cirrus_linear_bitblt_writeb(opaque, addr + 1, val & 0xff);
|
|
||||||
#else
|
|
||||||
cirrus_linear_bitblt_writeb(opaque, addr, val & 0xff);
|
cirrus_linear_bitblt_writeb(opaque, addr, val & 0xff);
|
||||||
cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 8) & 0xff);
|
cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 8) & 0xff);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cirrus_linear_bitblt_writel(void *opaque, target_phys_addr_t addr,
|
static void cirrus_linear_bitblt_writel(void *opaque, target_phys_addr_t addr,
|
||||||
uint32_t val)
|
uint32_t val)
|
||||||
{
|
{
|
||||||
#ifdef TARGET_WORDS_BIGENDIAN
|
|
||||||
cirrus_linear_bitblt_writeb(opaque, addr, (val >> 24) & 0xff);
|
|
||||||
cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 16) & 0xff);
|
|
||||||
cirrus_linear_bitblt_writeb(opaque, addr + 2, (val >> 8) & 0xff);
|
|
||||||
cirrus_linear_bitblt_writeb(opaque, addr + 3, val & 0xff);
|
|
||||||
#else
|
|
||||||
cirrus_linear_bitblt_writeb(opaque, addr, val & 0xff);
|
cirrus_linear_bitblt_writeb(opaque, addr, val & 0xff);
|
||||||
cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 8) & 0xff);
|
cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 8) & 0xff);
|
||||||
cirrus_linear_bitblt_writeb(opaque, addr + 2, (val >> 16) & 0xff);
|
cirrus_linear_bitblt_writeb(opaque, addr + 2, (val >> 16) & 0xff);
|
||||||
cirrus_linear_bitblt_writeb(opaque, addr + 3, (val >> 24) & 0xff);
|
cirrus_linear_bitblt_writeb(opaque, addr + 3, (val >> 24) & 0xff);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2841,30 +2776,20 @@ static uint32_t cirrus_mmio_readb(void *opaque, target_phys_addr_t addr)
|
||||||
static uint32_t cirrus_mmio_readw(void *opaque, target_phys_addr_t addr)
|
static uint32_t cirrus_mmio_readw(void *opaque, target_phys_addr_t addr)
|
||||||
{
|
{
|
||||||
uint32_t v;
|
uint32_t v;
|
||||||
#ifdef TARGET_WORDS_BIGENDIAN
|
|
||||||
v = cirrus_mmio_readb(opaque, addr) << 8;
|
|
||||||
v |= cirrus_mmio_readb(opaque, addr + 1);
|
|
||||||
#else
|
|
||||||
v = cirrus_mmio_readb(opaque, addr);
|
v = cirrus_mmio_readb(opaque, addr);
|
||||||
v |= cirrus_mmio_readb(opaque, addr + 1) << 8;
|
v |= cirrus_mmio_readb(opaque, addr + 1) << 8;
|
||||||
#endif
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t cirrus_mmio_readl(void *opaque, target_phys_addr_t addr)
|
static uint32_t cirrus_mmio_readl(void *opaque, target_phys_addr_t addr)
|
||||||
{
|
{
|
||||||
uint32_t v;
|
uint32_t v;
|
||||||
#ifdef TARGET_WORDS_BIGENDIAN
|
|
||||||
v = cirrus_mmio_readb(opaque, addr) << 24;
|
|
||||||
v |= cirrus_mmio_readb(opaque, addr + 1) << 16;
|
|
||||||
v |= cirrus_mmio_readb(opaque, addr + 2) << 8;
|
|
||||||
v |= cirrus_mmio_readb(opaque, addr + 3);
|
|
||||||
#else
|
|
||||||
v = cirrus_mmio_readb(opaque, addr);
|
v = cirrus_mmio_readb(opaque, addr);
|
||||||
v |= cirrus_mmio_readb(opaque, addr + 1) << 8;
|
v |= cirrus_mmio_readb(opaque, addr + 1) << 8;
|
||||||
v |= cirrus_mmio_readb(opaque, addr + 2) << 16;
|
v |= cirrus_mmio_readb(opaque, addr + 2) << 16;
|
||||||
v |= cirrus_mmio_readb(opaque, addr + 3) << 24;
|
v |= cirrus_mmio_readb(opaque, addr + 3) << 24;
|
||||||
#endif
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2885,29 +2810,17 @@ static void cirrus_mmio_writeb(void *opaque, target_phys_addr_t addr,
|
||||||
static void cirrus_mmio_writew(void *opaque, target_phys_addr_t addr,
|
static void cirrus_mmio_writew(void *opaque, target_phys_addr_t addr,
|
||||||
uint32_t val)
|
uint32_t val)
|
||||||
{
|
{
|
||||||
#ifdef TARGET_WORDS_BIGENDIAN
|
|
||||||
cirrus_mmio_writeb(opaque, addr, (val >> 8) & 0xff);
|
|
||||||
cirrus_mmio_writeb(opaque, addr + 1, val & 0xff);
|
|
||||||
#else
|
|
||||||
cirrus_mmio_writeb(opaque, addr, val & 0xff);
|
cirrus_mmio_writeb(opaque, addr, val & 0xff);
|
||||||
cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff);
|
cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cirrus_mmio_writel(void *opaque, target_phys_addr_t addr,
|
static void cirrus_mmio_writel(void *opaque, target_phys_addr_t addr,
|
||||||
uint32_t val)
|
uint32_t val)
|
||||||
{
|
{
|
||||||
#ifdef TARGET_WORDS_BIGENDIAN
|
|
||||||
cirrus_mmio_writeb(opaque, addr, (val >> 24) & 0xff);
|
|
||||||
cirrus_mmio_writeb(opaque, addr + 1, (val >> 16) & 0xff);
|
|
||||||
cirrus_mmio_writeb(opaque, addr + 2, (val >> 8) & 0xff);
|
|
||||||
cirrus_mmio_writeb(opaque, addr + 3, val & 0xff);
|
|
||||||
#else
|
|
||||||
cirrus_mmio_writeb(opaque, addr, val & 0xff);
|
cirrus_mmio_writeb(opaque, addr, val & 0xff);
|
||||||
cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff);
|
cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff);
|
||||||
cirrus_mmio_writeb(opaque, addr + 2, (val >> 16) & 0xff);
|
cirrus_mmio_writeb(opaque, addr + 2, (val >> 16) & 0xff);
|
||||||
cirrus_mmio_writeb(opaque, addr + 3, (val >> 24) & 0xff);
|
cirrus_mmio_writeb(opaque, addr + 3, (val >> 24) & 0xff);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3077,7 +2990,7 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci)
|
||||||
|
|
||||||
s->vga.vga_io_memory = cpu_register_io_memory(cirrus_vga_mem_read,
|
s->vga.vga_io_memory = cpu_register_io_memory(cirrus_vga_mem_read,
|
||||||
cirrus_vga_mem_write, s,
|
cirrus_vga_mem_write, s,
|
||||||
DEVICE_NATIVE_ENDIAN);
|
DEVICE_LITTLE_ENDIAN);
|
||||||
cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
|
cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
|
||||||
s->vga.vga_io_memory);
|
s->vga.vga_io_memory);
|
||||||
qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
|
qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
|
||||||
|
@ -3085,18 +2998,18 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci)
|
||||||
/* I/O handler for LFB */
|
/* I/O handler for LFB */
|
||||||
s->cirrus_linear_io_addr =
|
s->cirrus_linear_io_addr =
|
||||||
cpu_register_io_memory(cirrus_linear_read, cirrus_linear_write, s,
|
cpu_register_io_memory(cirrus_linear_read, cirrus_linear_write, s,
|
||||||
DEVICE_NATIVE_ENDIAN);
|
DEVICE_LITTLE_ENDIAN);
|
||||||
|
|
||||||
/* I/O handler for LFB */
|
/* I/O handler for LFB */
|
||||||
s->cirrus_linear_bitblt_io_addr =
|
s->cirrus_linear_bitblt_io_addr =
|
||||||
cpu_register_io_memory(cirrus_linear_bitblt_read,
|
cpu_register_io_memory(cirrus_linear_bitblt_read,
|
||||||
cirrus_linear_bitblt_write, s,
|
cirrus_linear_bitblt_write, s,
|
||||||
DEVICE_NATIVE_ENDIAN);
|
DEVICE_LITTLE_ENDIAN);
|
||||||
|
|
||||||
/* I/O handler for memory-mapped I/O */
|
/* I/O handler for memory-mapped I/O */
|
||||||
s->cirrus_mmio_io_addr =
|
s->cirrus_mmio_io_addr =
|
||||||
cpu_register_io_memory(cirrus_mmio_read, cirrus_mmio_write, s,
|
cpu_register_io_memory(cirrus_mmio_read, cirrus_mmio_write, s,
|
||||||
DEVICE_NATIVE_ENDIAN);
|
DEVICE_LITTLE_ENDIAN);
|
||||||
|
|
||||||
s->real_vram_size =
|
s->real_vram_size =
|
||||||
(s->device_id == CIRRUS_ID_CLGD5446) ? 4096 * 1024 : 2048 * 1024;
|
(s->device_id == CIRRUS_ID_CLGD5446) ? 4096 * 1024 : 2048 * 1024;
|
||||||
|
|
14
hw/hw.h
14
hw/hw.h
|
@ -528,6 +528,17 @@ extern const VMStateInfo vmstate_info_unused_buffer;
|
||||||
.start = (_start), \
|
.start = (_start), \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define VMSTATE_VBUFFER_UINT32(_field, _state, _version, _test, _start, _field_size) { \
|
||||||
|
.name = (stringify(_field)), \
|
||||||
|
.version_id = (_version), \
|
||||||
|
.field_exists = (_test), \
|
||||||
|
.size_offset = vmstate_offset_value(_state, _field_size, uint32_t),\
|
||||||
|
.info = &vmstate_info_buffer, \
|
||||||
|
.flags = VMS_VBUFFER|VMS_POINTER, \
|
||||||
|
.offset = offsetof(_state, _field), \
|
||||||
|
.start = (_start), \
|
||||||
|
}
|
||||||
|
|
||||||
#define VMSTATE_BUFFER_UNSAFE_INFO(_field, _state, _version, _info, _size) { \
|
#define VMSTATE_BUFFER_UNSAFE_INFO(_field, _state, _version, _info, _size) { \
|
||||||
.name = (stringify(_field)), \
|
.name = (stringify(_field)), \
|
||||||
.version_id = (_version), \
|
.version_id = (_version), \
|
||||||
|
@ -745,6 +756,9 @@ extern const VMStateDescription vmstate_i2c_slave;
|
||||||
#define VMSTATE_PARTIAL_VBUFFER(_f, _s, _size) \
|
#define VMSTATE_PARTIAL_VBUFFER(_f, _s, _size) \
|
||||||
VMSTATE_VBUFFER(_f, _s, 0, NULL, 0, _size)
|
VMSTATE_VBUFFER(_f, _s, 0, NULL, 0, _size)
|
||||||
|
|
||||||
|
#define VMSTATE_PARTIAL_VBUFFER_UINT32(_f, _s, _size) \
|
||||||
|
VMSTATE_VBUFFER_UINT32(_f, _s, 0, NULL, 0, _size)
|
||||||
|
|
||||||
#define VMSTATE_SUB_VBUFFER(_f, _s, _start, _size) \
|
#define VMSTATE_SUB_VBUFFER(_f, _s, _start, _size) \
|
||||||
VMSTATE_VBUFFER(_f, _s, 0, NULL, _start, _size)
|
VMSTATE_VBUFFER(_f, _s, 0, NULL, _start, _size)
|
||||||
|
|
||||||
|
|
97
hw/pc.c
97
hw/pc.c
|
@ -40,6 +40,7 @@
|
||||||
#include "sysbus.h"
|
#include "sysbus.h"
|
||||||
#include "sysemu.h"
|
#include "sysemu.h"
|
||||||
#include "blockdev.h"
|
#include "blockdev.h"
|
||||||
|
#include "ui/qemu-spice.h"
|
||||||
|
|
||||||
/* output Bochs bios info messages */
|
/* output Bochs bios info messages */
|
||||||
//#define DEBUG_BIOS
|
//#define DEBUG_BIOS
|
||||||
|
@ -410,11 +411,92 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
|
||||||
qemu_register_reset(pc_cmos_init_late, &arg);
|
qemu_register_reset(pc_cmos_init_late, &arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* port 92 stuff: could be split off */
|
||||||
|
typedef struct Port92State {
|
||||||
|
ISADevice dev;
|
||||||
|
uint8_t outport;
|
||||||
|
qemu_irq *a20_out;
|
||||||
|
} Port92State;
|
||||||
|
|
||||||
|
static void port92_write(void *opaque, uint32_t addr, uint32_t val)
|
||||||
|
{
|
||||||
|
Port92State *s = opaque;
|
||||||
|
|
||||||
|
DPRINTF("port92: write 0x%02x\n", val);
|
||||||
|
s->outport = val;
|
||||||
|
qemu_set_irq(*s->a20_out, (val >> 1) & 1);
|
||||||
|
if (val & 1) {
|
||||||
|
qemu_system_reset_request();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t port92_read(void *opaque, uint32_t addr)
|
||||||
|
{
|
||||||
|
Port92State *s = opaque;
|
||||||
|
uint32_t ret;
|
||||||
|
|
||||||
|
ret = s->outport;
|
||||||
|
DPRINTF("port92: read 0x%02x\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void port92_init(ISADevice *dev, qemu_irq *a20_out)
|
||||||
|
{
|
||||||
|
Port92State *s = DO_UPCAST(Port92State, dev, dev);
|
||||||
|
|
||||||
|
s->a20_out = a20_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const VMStateDescription vmstate_port92_isa = {
|
||||||
|
.name = "port92",
|
||||||
|
.version_id = 1,
|
||||||
|
.minimum_version_id = 1,
|
||||||
|
.minimum_version_id_old = 1,
|
||||||
|
.fields = (VMStateField []) {
|
||||||
|
VMSTATE_UINT8(outport, Port92State),
|
||||||
|
VMSTATE_END_OF_LIST()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static void port92_reset(DeviceState *d)
|
||||||
|
{
|
||||||
|
Port92State *s = container_of(d, Port92State, dev.qdev);
|
||||||
|
|
||||||
|
s->outport &= ~1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int port92_initfn(ISADevice *dev)
|
||||||
|
{
|
||||||
|
Port92State *s = DO_UPCAST(Port92State, dev, dev);
|
||||||
|
|
||||||
|
register_ioport_read(0x92, 1, 1, port92_read, s);
|
||||||
|
register_ioport_write(0x92, 1, 1, port92_write, s);
|
||||||
|
isa_init_ioport(dev, 0x92);
|
||||||
|
s->outport = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ISADeviceInfo port92_info = {
|
||||||
|
.qdev.name = "port92",
|
||||||
|
.qdev.size = sizeof(Port92State),
|
||||||
|
.qdev.vmsd = &vmstate_port92_isa,
|
||||||
|
.qdev.no_user = 1,
|
||||||
|
.qdev.reset = port92_reset,
|
||||||
|
.init = port92_initfn,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void port92_register(void)
|
||||||
|
{
|
||||||
|
isa_qdev_register(&port92_info);
|
||||||
|
}
|
||||||
|
device_init(port92_register)
|
||||||
|
|
||||||
static void handle_a20_line_change(void *opaque, int irq, int level)
|
static void handle_a20_line_change(void *opaque, int irq, int level)
|
||||||
{
|
{
|
||||||
CPUState *cpu = opaque;
|
CPUState *cpu = opaque;
|
||||||
|
|
||||||
/* XXX: send to all CPUs ? */
|
/* XXX: send to all CPUs ? */
|
||||||
|
/* XXX: add logic to handle multiple A20 line sources */
|
||||||
cpu_x86_set_a20(cpu, level);
|
cpu_x86_set_a20(cpu, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -992,6 +1074,13 @@ void pc_vga_init(PCIBus *pci_bus)
|
||||||
pci_vmsvga_init(pci_bus);
|
pci_vmsvga_init(pci_bus);
|
||||||
else
|
else
|
||||||
fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __FUNCTION__);
|
fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __FUNCTION__);
|
||||||
|
#ifdef CONFIG_SPICE
|
||||||
|
} else if (qxl_enabled) {
|
||||||
|
if (pci_bus)
|
||||||
|
pci_create_simple(pci_bus, -1, "qxl-vga");
|
||||||
|
else
|
||||||
|
fprintf(stderr, "%s: qxl: no PCI bus\n", __FUNCTION__);
|
||||||
|
#endif
|
||||||
} else if (std_vga_enabled) {
|
} else if (std_vga_enabled) {
|
||||||
if (pci_bus) {
|
if (pci_bus) {
|
||||||
pci_vga_init(pci_bus);
|
pci_vga_init(pci_bus);
|
||||||
|
@ -1019,7 +1108,7 @@ void pc_basic_device_init(qemu_irq *isa_irq,
|
||||||
PITState *pit;
|
PITState *pit;
|
||||||
qemu_irq rtc_irq = NULL;
|
qemu_irq rtc_irq = NULL;
|
||||||
qemu_irq *a20_line;
|
qemu_irq *a20_line;
|
||||||
ISADevice *i8042;
|
ISADevice *i8042, *port92;
|
||||||
qemu_irq *cpu_exit_irq;
|
qemu_irq *cpu_exit_irq;
|
||||||
|
|
||||||
register_ioport_write(0x80, 1, 1, ioport80_write, NULL);
|
register_ioport_write(0x80, 1, 1, ioport80_write, NULL);
|
||||||
|
@ -1053,10 +1142,12 @@ void pc_basic_device_init(qemu_irq *isa_irq,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
a20_line = qemu_allocate_irqs(handle_a20_line_change, first_cpu, 1);
|
a20_line = qemu_allocate_irqs(handle_a20_line_change, first_cpu, 2);
|
||||||
i8042 = isa_create_simple("i8042");
|
i8042 = isa_create_simple("i8042");
|
||||||
i8042_setup_a20_line(i8042, a20_line);
|
i8042_setup_a20_line(i8042, &a20_line[0]);
|
||||||
vmmouse_init(i8042);
|
vmmouse_init(i8042);
|
||||||
|
port92 = isa_create_simple("port92");
|
||||||
|
port92_init(port92, &a20_line[1]);
|
||||||
|
|
||||||
cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
|
cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
|
||||||
DMA_init(0, cpu_exit_irq);
|
DMA_init(0, cpu_exit_irq);
|
||||||
|
|
19
hw/pckbd.c
19
hw/pckbd.c
|
@ -211,10 +211,8 @@ static void kbd_queue(KBDState *s, int b, int aux)
|
||||||
ps2_queue(s->kbd, b);
|
ps2_queue(s->kbd, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ioport92_write(void *opaque, uint32_t addr, uint32_t val)
|
static void outport_write(KBDState *s, uint32_t val)
|
||||||
{
|
{
|
||||||
KBDState *s = opaque;
|
|
||||||
|
|
||||||
DPRINTF("kbd: write outport=0x%02x\n", val);
|
DPRINTF("kbd: write outport=0x%02x\n", val);
|
||||||
s->outport = val;
|
s->outport = val;
|
||||||
if (s->a20_out) {
|
if (s->a20_out) {
|
||||||
|
@ -225,16 +223,6 @@ static void ioport92_write(void *opaque, uint32_t addr, uint32_t val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t ioport92_read(void *opaque, uint32_t addr)
|
|
||||||
{
|
|
||||||
KBDState *s = opaque;
|
|
||||||
uint32_t ret;
|
|
||||||
|
|
||||||
ret = s->outport;
|
|
||||||
DPRINTF("kbd: read outport=0x%02x\n", ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void kbd_write_command(void *opaque, uint32_t addr, uint32_t val)
|
static void kbd_write_command(void *opaque, uint32_t addr, uint32_t val)
|
||||||
{
|
{
|
||||||
KBDState *s = opaque;
|
KBDState *s = opaque;
|
||||||
|
@ -357,7 +345,7 @@ static void kbd_write_data(void *opaque, uint32_t addr, uint32_t val)
|
||||||
kbd_queue(s, val, 1);
|
kbd_queue(s, val, 1);
|
||||||
break;
|
break;
|
||||||
case KBD_CCMD_WRITE_OUTPORT:
|
case KBD_CCMD_WRITE_OUTPORT:
|
||||||
ioport92_write(s, 0, val);
|
outport_write(s, val);
|
||||||
break;
|
break;
|
||||||
case KBD_CCMD_WRITE_MOUSE:
|
case KBD_CCMD_WRITE_MOUSE:
|
||||||
ps2_write_mouse(s->mouse, val);
|
ps2_write_mouse(s->mouse, val);
|
||||||
|
@ -489,9 +477,6 @@ static int i8042_initfn(ISADevice *dev)
|
||||||
register_ioport_read(0x64, 1, 1, kbd_read_status, s);
|
register_ioport_read(0x64, 1, 1, kbd_read_status, s);
|
||||||
register_ioport_write(0x64, 1, 1, kbd_write_command, s);
|
register_ioport_write(0x64, 1, 1, kbd_write_command, s);
|
||||||
isa_init_ioport(dev, 0x64);
|
isa_init_ioport(dev, 0x64);
|
||||||
register_ioport_read(0x92, 1, 1, ioport92_read, s);
|
|
||||||
register_ioport_write(0x92, 1, 1, ioport92_write, s);
|
|
||||||
isa_init_ioport(dev, 0x92);
|
|
||||||
|
|
||||||
s->kbd = ps2_kbd_init(kbd_update_kbd_irq, s);
|
s->kbd = ps2_kbd_init(kbd_update_kbd_irq, s);
|
||||||
s->mouse = ps2_mouse_init(kbd_update_aux_irq, s);
|
s->mouse = ps2_mouse_init(kbd_update_aux_irq, s);
|
||||||
|
|
|
@ -0,0 +1,248 @@
|
||||||
|
/*
|
||||||
|
* qxl command logging -- for debug purposes
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* maintained by Gerd Hoffmann <kraxel@redhat.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 or
|
||||||
|
* (at your option) version 3 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qxl.h"
|
||||||
|
|
||||||
|
static const char *qxl_type[] = {
|
||||||
|
[ QXL_CMD_NOP ] = "nop",
|
||||||
|
[ QXL_CMD_DRAW ] = "draw",
|
||||||
|
[ QXL_CMD_UPDATE ] = "update",
|
||||||
|
[ QXL_CMD_CURSOR ] = "cursor",
|
||||||
|
[ QXL_CMD_MESSAGE ] = "message",
|
||||||
|
[ QXL_CMD_SURFACE ] = "surface",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *qxl_draw_type[] = {
|
||||||
|
[ QXL_DRAW_NOP ] = "nop",
|
||||||
|
[ QXL_DRAW_FILL ] = "fill",
|
||||||
|
[ QXL_DRAW_OPAQUE ] = "opaque",
|
||||||
|
[ QXL_DRAW_COPY ] = "copy",
|
||||||
|
[ QXL_COPY_BITS ] = "copy-bits",
|
||||||
|
[ QXL_DRAW_BLEND ] = "blend",
|
||||||
|
[ QXL_DRAW_BLACKNESS ] = "blackness",
|
||||||
|
[ QXL_DRAW_WHITENESS ] = "whitemess",
|
||||||
|
[ QXL_DRAW_INVERS ] = "invers",
|
||||||
|
[ QXL_DRAW_ROP3 ] = "rop3",
|
||||||
|
[ QXL_DRAW_STROKE ] = "stroke",
|
||||||
|
[ QXL_DRAW_TEXT ] = "text",
|
||||||
|
[ QXL_DRAW_TRANSPARENT ] = "transparent",
|
||||||
|
[ QXL_DRAW_ALPHA_BLEND ] = "alpha-blend",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *qxl_draw_effect[] = {
|
||||||
|
[ QXL_EFFECT_BLEND ] = "blend",
|
||||||
|
[ QXL_EFFECT_OPAQUE ] = "opaque",
|
||||||
|
[ QXL_EFFECT_REVERT_ON_DUP ] = "revert-on-dup",
|
||||||
|
[ QXL_EFFECT_BLACKNESS_ON_DUP ] = "blackness-on-dup",
|
||||||
|
[ QXL_EFFECT_WHITENESS_ON_DUP ] = "whiteness-on-dup",
|
||||||
|
[ QXL_EFFECT_NOP_ON_DUP ] = "nop-on-dup",
|
||||||
|
[ QXL_EFFECT_NOP ] = "nop",
|
||||||
|
[ QXL_EFFECT_OPAQUE_BRUSH ] = "opaque-brush",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *qxl_surface_cmd[] = {
|
||||||
|
[ QXL_SURFACE_CMD_CREATE ] = "create",
|
||||||
|
[ QXL_SURFACE_CMD_DESTROY ] = "destroy",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *spice_surface_fmt[] = {
|
||||||
|
[ SPICE_SURFACE_FMT_INVALID ] = "invalid",
|
||||||
|
[ SPICE_SURFACE_FMT_1_A ] = "alpha/1",
|
||||||
|
[ SPICE_SURFACE_FMT_8_A ] = "alpha/8",
|
||||||
|
[ SPICE_SURFACE_FMT_16_555 ] = "555/16",
|
||||||
|
[ SPICE_SURFACE_FMT_16_565 ] = "565/16",
|
||||||
|
[ SPICE_SURFACE_FMT_32_xRGB ] = "xRGB/32",
|
||||||
|
[ SPICE_SURFACE_FMT_32_ARGB ] = "ARGB/32",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *qxl_cursor_cmd[] = {
|
||||||
|
[ QXL_CURSOR_SET ] = "set",
|
||||||
|
[ QXL_CURSOR_MOVE ] = "move",
|
||||||
|
[ QXL_CURSOR_HIDE ] = "hide",
|
||||||
|
[ QXL_CURSOR_TRAIL ] = "trail",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *spice_cursor_type[] = {
|
||||||
|
[ SPICE_CURSOR_TYPE_ALPHA ] = "alpha",
|
||||||
|
[ SPICE_CURSOR_TYPE_MONO ] = "mono",
|
||||||
|
[ SPICE_CURSOR_TYPE_COLOR4 ] = "color4",
|
||||||
|
[ SPICE_CURSOR_TYPE_COLOR8 ] = "color8",
|
||||||
|
[ SPICE_CURSOR_TYPE_COLOR16 ] = "color16",
|
||||||
|
[ SPICE_CURSOR_TYPE_COLOR24 ] = "color24",
|
||||||
|
[ SPICE_CURSOR_TYPE_COLOR32 ] = "color32",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *qxl_v2n(const char *n[], size_t l, int v)
|
||||||
|
{
|
||||||
|
if (v >= l || !n[v]) {
|
||||||
|
return "???";
|
||||||
|
}
|
||||||
|
return n[v];
|
||||||
|
}
|
||||||
|
#define qxl_name(_list, _value) qxl_v2n(_list, ARRAY_SIZE(_list), _value)
|
||||||
|
|
||||||
|
static void qxl_log_image(PCIQXLDevice *qxl, QXLPHYSICAL addr, int group_id)
|
||||||
|
{
|
||||||
|
QXLImage *image;
|
||||||
|
QXLImageDescriptor *desc;
|
||||||
|
|
||||||
|
image = qxl_phys2virt(qxl, addr, group_id);
|
||||||
|
desc = &image->descriptor;
|
||||||
|
fprintf(stderr, " (id %" PRIx64 " type %d flags %d width %d height %d",
|
||||||
|
desc->id, desc->type, desc->flags, desc->width, desc->height);
|
||||||
|
switch (desc->type) {
|
||||||
|
case SPICE_IMAGE_TYPE_BITMAP:
|
||||||
|
fprintf(stderr, ", fmt %d flags %d x %d y %d stride %d"
|
||||||
|
" palette %" PRIx64 " data %" PRIx64,
|
||||||
|
image->bitmap.format, image->bitmap.flags,
|
||||||
|
image->bitmap.x, image->bitmap.y,
|
||||||
|
image->bitmap.stride,
|
||||||
|
image->bitmap.palette, image->bitmap.data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fprintf(stderr, ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void qxl_log_rect(QXLRect *rect)
|
||||||
|
{
|
||||||
|
fprintf(stderr, " %dx%d+%d+%d",
|
||||||
|
rect->right - rect->left,
|
||||||
|
rect->bottom - rect->top,
|
||||||
|
rect->left, rect->top);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void qxl_log_cmd_draw_copy(PCIQXLDevice *qxl, QXLCopy *copy, int group_id)
|
||||||
|
{
|
||||||
|
fprintf(stderr, " src %" PRIx64,
|
||||||
|
copy->src_bitmap);
|
||||||
|
qxl_log_image(qxl, copy->src_bitmap, group_id);
|
||||||
|
fprintf(stderr, " area");
|
||||||
|
qxl_log_rect(©->src_area);
|
||||||
|
fprintf(stderr, " rop %d", copy->rop_descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void qxl_log_cmd_draw(PCIQXLDevice *qxl, QXLDrawable *draw, int group_id)
|
||||||
|
{
|
||||||
|
fprintf(stderr, ": surface_id %d type %s effect %s",
|
||||||
|
draw->surface_id,
|
||||||
|
qxl_name(qxl_draw_type, draw->type),
|
||||||
|
qxl_name(qxl_draw_effect, draw->effect));
|
||||||
|
switch (draw->type) {
|
||||||
|
case QXL_DRAW_COPY:
|
||||||
|
qxl_log_cmd_draw_copy(qxl, &draw->u.copy, group_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void qxl_log_cmd_draw_compat(PCIQXLDevice *qxl, QXLCompatDrawable *draw,
|
||||||
|
int group_id)
|
||||||
|
{
|
||||||
|
fprintf(stderr, ": type %s effect %s",
|
||||||
|
qxl_name(qxl_draw_type, draw->type),
|
||||||
|
qxl_name(qxl_draw_effect, draw->effect));
|
||||||
|
if (draw->bitmap_offset) {
|
||||||
|
fprintf(stderr, ": bitmap %d",
|
||||||
|
draw->bitmap_offset);
|
||||||
|
qxl_log_rect(&draw->bitmap_area);
|
||||||
|
}
|
||||||
|
switch (draw->type) {
|
||||||
|
case QXL_DRAW_COPY:
|
||||||
|
qxl_log_cmd_draw_copy(qxl, &draw->u.copy, group_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void qxl_log_cmd_surface(PCIQXLDevice *qxl, QXLSurfaceCmd *cmd)
|
||||||
|
{
|
||||||
|
fprintf(stderr, ": %s id %d",
|
||||||
|
qxl_name(qxl_surface_cmd, cmd->type),
|
||||||
|
cmd->surface_id);
|
||||||
|
if (cmd->type == QXL_SURFACE_CMD_CREATE) {
|
||||||
|
fprintf(stderr, " size %dx%d stride %d format %s (count %d, max %d)",
|
||||||
|
cmd->u.surface_create.width,
|
||||||
|
cmd->u.surface_create.height,
|
||||||
|
cmd->u.surface_create.stride,
|
||||||
|
qxl_name(spice_surface_fmt, cmd->u.surface_create.format),
|
||||||
|
qxl->guest_surfaces.count, qxl->guest_surfaces.max);
|
||||||
|
}
|
||||||
|
if (cmd->type == QXL_SURFACE_CMD_DESTROY) {
|
||||||
|
fprintf(stderr, " (count %d)", qxl->guest_surfaces.count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void qxl_log_cmd_cursor(PCIQXLDevice *qxl, QXLCursorCmd *cmd, int group_id)
|
||||||
|
{
|
||||||
|
QXLCursor *cursor;
|
||||||
|
|
||||||
|
fprintf(stderr, ": %s",
|
||||||
|
qxl_name(qxl_cursor_cmd, cmd->type));
|
||||||
|
switch (cmd->type) {
|
||||||
|
case QXL_CURSOR_SET:
|
||||||
|
fprintf(stderr, " +%d+%d visible %s, shape @ 0x%" PRIx64,
|
||||||
|
cmd->u.set.position.x,
|
||||||
|
cmd->u.set.position.y,
|
||||||
|
cmd->u.set.visible ? "yes" : "no",
|
||||||
|
cmd->u.set.shape);
|
||||||
|
cursor = qxl_phys2virt(qxl, cmd->u.set.shape, group_id);
|
||||||
|
fprintf(stderr, " type %s size %dx%d hot-spot +%d+%d"
|
||||||
|
" unique 0x%" PRIx64 " data-size %d",
|
||||||
|
qxl_name(spice_cursor_type, cursor->header.type),
|
||||||
|
cursor->header.width, cursor->header.height,
|
||||||
|
cursor->header.hot_spot_x, cursor->header.hot_spot_y,
|
||||||
|
cursor->header.unique, cursor->data_size);
|
||||||
|
break;
|
||||||
|
case QXL_CURSOR_MOVE:
|
||||||
|
fprintf(stderr, " +%d+%d", cmd->u.position.x, cmd->u.position.y);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext)
|
||||||
|
{
|
||||||
|
bool compat = ext->flags & QXL_COMMAND_FLAG_COMPAT;
|
||||||
|
void *data;
|
||||||
|
|
||||||
|
if (!qxl->cmdlog) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "qxl-%d/%s:", qxl->id, ring);
|
||||||
|
fprintf(stderr, " cmd @ 0x%" PRIx64 " %s%s", ext->cmd.data,
|
||||||
|
qxl_name(qxl_type, ext->cmd.type),
|
||||||
|
compat ? "(compat)" : "");
|
||||||
|
|
||||||
|
data = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id);
|
||||||
|
switch (ext->cmd.type) {
|
||||||
|
case QXL_CMD_DRAW:
|
||||||
|
if (!compat) {
|
||||||
|
qxl_log_cmd_draw(qxl, data, ext->group_id);
|
||||||
|
} else {
|
||||||
|
qxl_log_cmd_draw_compat(qxl, data, ext->group_id);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case QXL_CMD_SURFACE:
|
||||||
|
qxl_log_cmd_surface(qxl, data);
|
||||||
|
break;
|
||||||
|
case QXL_CMD_CURSOR:
|
||||||
|
qxl_log_cmd_cursor(qxl, data, ext->group_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
|
@ -0,0 +1,226 @@
|
||||||
|
/*
|
||||||
|
* qxl local rendering (aka display on sdl/vnc)
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* maintained by Gerd Hoffmann <kraxel@redhat.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 or
|
||||||
|
* (at your option) version 3 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qxl.h"
|
||||||
|
|
||||||
|
static void qxl_flip(PCIQXLDevice *qxl, QXLRect *rect)
|
||||||
|
{
|
||||||
|
uint8_t *src = qxl->guest_primary.data;
|
||||||
|
uint8_t *dst = qxl->guest_primary.flipped;
|
||||||
|
int len, i;
|
||||||
|
|
||||||
|
src += (qxl->guest_primary.surface.height - rect->top - 1) *
|
||||||
|
qxl->guest_primary.stride;
|
||||||
|
dst += rect->top * qxl->guest_primary.stride;
|
||||||
|
src += rect->left * qxl->guest_primary.bytes_pp;
|
||||||
|
dst += rect->left * qxl->guest_primary.bytes_pp;
|
||||||
|
len = (rect->right - rect->left) * qxl->guest_primary.bytes_pp;
|
||||||
|
|
||||||
|
for (i = rect->top; i < rect->bottom; i++) {
|
||||||
|
memcpy(dst, src, len);
|
||||||
|
dst += qxl->guest_primary.stride;
|
||||||
|
src -= qxl->guest_primary.stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void qxl_render_resize(PCIQXLDevice *qxl)
|
||||||
|
{
|
||||||
|
QXLSurfaceCreate *sc = &qxl->guest_primary.surface;
|
||||||
|
|
||||||
|
qxl->guest_primary.stride = sc->stride;
|
||||||
|
qxl->guest_primary.resized++;
|
||||||
|
switch (sc->format) {
|
||||||
|
case SPICE_SURFACE_FMT_16_555:
|
||||||
|
qxl->guest_primary.bytes_pp = 2;
|
||||||
|
qxl->guest_primary.bits_pp = 15;
|
||||||
|
break;
|
||||||
|
case SPICE_SURFACE_FMT_16_565:
|
||||||
|
qxl->guest_primary.bytes_pp = 2;
|
||||||
|
qxl->guest_primary.bits_pp = 16;
|
||||||
|
break;
|
||||||
|
case SPICE_SURFACE_FMT_32_xRGB:
|
||||||
|
case SPICE_SURFACE_FMT_32_ARGB:
|
||||||
|
qxl->guest_primary.bytes_pp = 4;
|
||||||
|
qxl->guest_primary.bits_pp = 32;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "%s: unhandled format: %x\n", __FUNCTION__,
|
||||||
|
qxl->guest_primary.surface.format);
|
||||||
|
qxl->guest_primary.bytes_pp = 4;
|
||||||
|
qxl->guest_primary.bits_pp = 32;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void qxl_render_update(PCIQXLDevice *qxl)
|
||||||
|
{
|
||||||
|
VGACommonState *vga = &qxl->vga;
|
||||||
|
QXLRect dirty[32], update;
|
||||||
|
void *ptr;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (qxl->guest_primary.resized) {
|
||||||
|
qxl->guest_primary.resized = 0;
|
||||||
|
|
||||||
|
if (qxl->guest_primary.flipped) {
|
||||||
|
qemu_free(qxl->guest_primary.flipped);
|
||||||
|
qxl->guest_primary.flipped = NULL;
|
||||||
|
}
|
||||||
|
qemu_free_displaysurface(vga->ds);
|
||||||
|
|
||||||
|
qxl->guest_primary.data = qemu_get_ram_ptr(qxl->vga.vram_offset);
|
||||||
|
if (qxl->guest_primary.stride < 0) {
|
||||||
|
/* spice surface is upside down -> need extra buffer to flip */
|
||||||
|
qxl->guest_primary.stride = -qxl->guest_primary.stride;
|
||||||
|
qxl->guest_primary.flipped = qemu_malloc(qxl->guest_primary.surface.width *
|
||||||
|
qxl->guest_primary.stride);
|
||||||
|
ptr = qxl->guest_primary.flipped;
|
||||||
|
} else {
|
||||||
|
ptr = qxl->guest_primary.data;
|
||||||
|
}
|
||||||
|
dprint(qxl, 1, "%s: %dx%d, stride %d, bpp %d, depth %d, flip %s\n",
|
||||||
|
__FUNCTION__,
|
||||||
|
qxl->guest_primary.surface.width,
|
||||||
|
qxl->guest_primary.surface.height,
|
||||||
|
qxl->guest_primary.stride,
|
||||||
|
qxl->guest_primary.bytes_pp,
|
||||||
|
qxl->guest_primary.bits_pp,
|
||||||
|
qxl->guest_primary.flipped ? "yes" : "no");
|
||||||
|
vga->ds->surface =
|
||||||
|
qemu_create_displaysurface_from(qxl->guest_primary.surface.width,
|
||||||
|
qxl->guest_primary.surface.height,
|
||||||
|
qxl->guest_primary.bits_pp,
|
||||||
|
qxl->guest_primary.stride,
|
||||||
|
ptr);
|
||||||
|
dpy_resize(vga->ds);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!qxl->guest_primary.commands) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
qxl->guest_primary.commands = 0;
|
||||||
|
|
||||||
|
update.left = 0;
|
||||||
|
update.right = qxl->guest_primary.surface.width;
|
||||||
|
update.top = 0;
|
||||||
|
update.bottom = qxl->guest_primary.surface.height;
|
||||||
|
|
||||||
|
memset(dirty, 0, sizeof(dirty));
|
||||||
|
qxl->ssd.worker->update_area(qxl->ssd.worker, 0, &update,
|
||||||
|
dirty, ARRAY_SIZE(dirty), 1);
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(dirty); i++) {
|
||||||
|
if (qemu_spice_rect_is_empty(dirty+i)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (qxl->guest_primary.flipped) {
|
||||||
|
qxl_flip(qxl, dirty+i);
|
||||||
|
}
|
||||||
|
dpy_update(vga->ds,
|
||||||
|
dirty[i].left, dirty[i].top,
|
||||||
|
dirty[i].right - dirty[i].left,
|
||||||
|
dirty[i].bottom - dirty[i].top);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static QEMUCursor *qxl_cursor(PCIQXLDevice *qxl, QXLCursor *cursor)
|
||||||
|
{
|
||||||
|
QEMUCursor *c;
|
||||||
|
uint8_t *image, *mask;
|
||||||
|
int size;
|
||||||
|
|
||||||
|
c = cursor_alloc(cursor->header.width, cursor->header.height);
|
||||||
|
c->hot_x = cursor->header.hot_spot_x;
|
||||||
|
c->hot_y = cursor->header.hot_spot_y;
|
||||||
|
switch (cursor->header.type) {
|
||||||
|
case SPICE_CURSOR_TYPE_ALPHA:
|
||||||
|
size = cursor->header.width * cursor->header.height * sizeof(uint32_t);
|
||||||
|
memcpy(c->data, cursor->chunk.data, size);
|
||||||
|
if (qxl->debug > 2) {
|
||||||
|
cursor_print_ascii_art(c, "qxl/alpha");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SPICE_CURSOR_TYPE_MONO:
|
||||||
|
mask = cursor->chunk.data;
|
||||||
|
image = mask + cursor_get_mono_bpl(c) * c->width;
|
||||||
|
cursor_set_mono(c, 0xffffff, 0x000000, image, 1, mask);
|
||||||
|
if (qxl->debug > 2) {
|
||||||
|
cursor_print_ascii_art(c, "qxl/mono");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "%s: not implemented: type %d\n",
|
||||||
|
__FUNCTION__, cursor->header.type);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
cursor_put(c);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* called from spice server thread context only */
|
||||||
|
void qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext)
|
||||||
|
{
|
||||||
|
QXLCursorCmd *cmd = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id);
|
||||||
|
QXLCursor *cursor;
|
||||||
|
QEMUCursor *c;
|
||||||
|
int x = -1, y = -1;
|
||||||
|
|
||||||
|
if (!qxl->ssd.ds->mouse_set || !qxl->ssd.ds->cursor_define) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qxl->debug > 1 && cmd->type != QXL_CURSOR_MOVE) {
|
||||||
|
fprintf(stderr, "%s", __FUNCTION__);
|
||||||
|
qxl_log_cmd_cursor(qxl, cmd, ext->group_id);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
switch (cmd->type) {
|
||||||
|
case QXL_CURSOR_SET:
|
||||||
|
x = cmd->u.set.position.x;
|
||||||
|
y = cmd->u.set.position.y;
|
||||||
|
cursor = qxl_phys2virt(qxl, cmd->u.set.shape, ext->group_id);
|
||||||
|
if (cursor->chunk.data_size != cursor->data_size) {
|
||||||
|
fprintf(stderr, "%s: multiple chunks\n", __FUNCTION__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
c = qxl_cursor(qxl, cursor);
|
||||||
|
if (c == NULL) {
|
||||||
|
c = cursor_builtin_left_ptr();
|
||||||
|
}
|
||||||
|
qemu_mutex_lock_iothread();
|
||||||
|
qxl->ssd.ds->cursor_define(c);
|
||||||
|
qxl->ssd.ds->mouse_set(x, y, 1);
|
||||||
|
qemu_mutex_unlock_iothread();
|
||||||
|
cursor_put(c);
|
||||||
|
break;
|
||||||
|
case QXL_CURSOR_MOVE:
|
||||||
|
x = cmd->u.position.x;
|
||||||
|
y = cmd->u.position.y;
|
||||||
|
qemu_mutex_lock_iothread();
|
||||||
|
qxl->ssd.ds->mouse_set(x, y, 1);
|
||||||
|
qemu_mutex_unlock_iothread();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,112 @@
|
||||||
|
#include "qemu-common.h"
|
||||||
|
|
||||||
|
#include "console.h"
|
||||||
|
#include "hw.h"
|
||||||
|
#include "pci.h"
|
||||||
|
#include "vga_int.h"
|
||||||
|
|
||||||
|
#include "ui/qemu-spice.h"
|
||||||
|
#include "ui/spice-display.h"
|
||||||
|
|
||||||
|
enum qxl_mode {
|
||||||
|
QXL_MODE_UNDEFINED,
|
||||||
|
QXL_MODE_VGA,
|
||||||
|
QXL_MODE_COMPAT, /* spice 0.4.x */
|
||||||
|
QXL_MODE_NATIVE,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct PCIQXLDevice {
|
||||||
|
PCIDevice pci;
|
||||||
|
SimpleSpiceDisplay ssd;
|
||||||
|
int id;
|
||||||
|
uint32_t debug;
|
||||||
|
uint32_t guestdebug;
|
||||||
|
uint32_t cmdlog;
|
||||||
|
enum qxl_mode mode;
|
||||||
|
uint32_t cmdflags;
|
||||||
|
int generation;
|
||||||
|
uint32_t revision;
|
||||||
|
|
||||||
|
int32_t num_memslots;
|
||||||
|
int32_t num_surfaces;
|
||||||
|
|
||||||
|
struct guest_slots {
|
||||||
|
QXLMemSlot slot;
|
||||||
|
void *ptr;
|
||||||
|
uint64_t size;
|
||||||
|
uint64_t delta;
|
||||||
|
uint32_t active;
|
||||||
|
} guest_slots[NUM_MEMSLOTS];
|
||||||
|
|
||||||
|
struct guest_primary {
|
||||||
|
QXLSurfaceCreate surface;
|
||||||
|
uint32_t commands;
|
||||||
|
uint32_t resized;
|
||||||
|
int32_t stride;
|
||||||
|
uint32_t bits_pp;
|
||||||
|
uint32_t bytes_pp;
|
||||||
|
uint8_t *data, *flipped;
|
||||||
|
} guest_primary;
|
||||||
|
|
||||||
|
struct surfaces {
|
||||||
|
QXLPHYSICAL cmds[NUM_SURFACES];
|
||||||
|
uint32_t count;
|
||||||
|
uint32_t max;
|
||||||
|
} guest_surfaces;
|
||||||
|
QXLPHYSICAL guest_cursor;
|
||||||
|
|
||||||
|
/* thread signaling */
|
||||||
|
pthread_t main;
|
||||||
|
int pipe[2];
|
||||||
|
|
||||||
|
/* ram pci bar */
|
||||||
|
QXLRam *ram;
|
||||||
|
VGACommonState vga;
|
||||||
|
uint32_t num_free_res;
|
||||||
|
QXLReleaseInfo *last_release;
|
||||||
|
uint32_t last_release_offset;
|
||||||
|
uint32_t oom_running;
|
||||||
|
|
||||||
|
/* rom pci bar */
|
||||||
|
QXLRom shadow_rom;
|
||||||
|
QXLRom *rom;
|
||||||
|
QXLModes *modes;
|
||||||
|
uint32_t rom_size;
|
||||||
|
uint64_t rom_offset;
|
||||||
|
|
||||||
|
/* vram pci bar */
|
||||||
|
uint32_t vram_size;
|
||||||
|
uint64_t vram_offset;
|
||||||
|
|
||||||
|
/* io bar */
|
||||||
|
uint32_t io_base;
|
||||||
|
|
||||||
|
/* spice 0.4 loadvm compatibility */
|
||||||
|
void *worker_data;
|
||||||
|
uint32_t worker_data_size;
|
||||||
|
} PCIQXLDevice;
|
||||||
|
|
||||||
|
#define PANIC_ON(x) if ((x)) { \
|
||||||
|
printf("%s: PANIC %s failed\n", __FUNCTION__, #x); \
|
||||||
|
exit(-1); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define dprint(_qxl, _level, _fmt, ...) \
|
||||||
|
do { \
|
||||||
|
if (_qxl->debug >= _level) { \
|
||||||
|
fprintf(stderr, "qxl-%d: ", _qxl->id); \
|
||||||
|
fprintf(stderr, _fmt, ## __VA_ARGS__); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/* qxl.c */
|
||||||
|
void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL phys, int group_id);
|
||||||
|
|
||||||
|
/* qxl-logger.c */
|
||||||
|
void qxl_log_cmd_cursor(PCIQXLDevice *qxl, QXLCursorCmd *cmd, int group_id);
|
||||||
|
void qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext);
|
||||||
|
|
||||||
|
/* qxl-render.c */
|
||||||
|
void qxl_render_resize(PCIQXLDevice *qxl);
|
||||||
|
void qxl_render_update(PCIQXLDevice *qxl);
|
||||||
|
void qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext);
|
|
@ -17,6 +17,8 @@
|
||||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "virtio-net.h"
|
||||||
|
|
||||||
#define VIRTIO_DEV_OFFS_TYPE 0 /* 8 bits */
|
#define VIRTIO_DEV_OFFS_TYPE 0 /* 8 bits */
|
||||||
#define VIRTIO_DEV_OFFS_NUM_VQ 1 /* 8 bits */
|
#define VIRTIO_DEV_OFFS_NUM_VQ 1 /* 8 bits */
|
||||||
#define VIRTIO_DEV_OFFS_FEATURE_LEN 2 /* 8 bits */
|
#define VIRTIO_DEV_OFFS_FEATURE_LEN 2 /* 8 bits */
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include "hw.h"
|
#include "hw.h"
|
||||||
#include "block.h"
|
#include "block.h"
|
||||||
|
#include "blockdev.h"
|
||||||
#include "sysemu.h"
|
#include "sysemu.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
#include "boards.h"
|
#include "boards.h"
|
||||||
|
|
|
@ -670,6 +670,8 @@ static void sh7750_mmct_writel(void *opaque, target_phys_addr_t addr,
|
||||||
/* do nothing */
|
/* do nothing */
|
||||||
break;
|
break;
|
||||||
case MM_ITLB_ADDR:
|
case MM_ITLB_ADDR:
|
||||||
|
cpu_sh4_write_mmaped_itlb_addr(s->cpu, addr, mem_value);
|
||||||
|
break;
|
||||||
case MM_ITLB_DATA:
|
case MM_ITLB_DATA:
|
||||||
/* XXXXX */
|
/* XXXXX */
|
||||||
abort();
|
abort();
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
/* We need the mask, because one instance of the device is not page
|
/* We need the mask, because one instance of the device is not page
|
||||||
aligned (ledma, start address 0x0010) */
|
aligned (ledma, start address 0x0010) */
|
||||||
#define DMA_MASK (DMA_SIZE - 1)
|
#define DMA_MASK (DMA_SIZE - 1)
|
||||||
/* ledma has more than 4 registers, Solaris reads the 5th one */
|
/* OBP says 0x20 bytes for ledma, the extras are aliased to espdma */
|
||||||
#define DMA_ETH_SIZE (8 * sizeof(uint32_t))
|
#define DMA_ETH_SIZE (8 * sizeof(uint32_t))
|
||||||
#define DMA_MAX_REG_OFFSET (2 * DMA_SIZE - 1)
|
#define DMA_MAX_REG_OFFSET (2 * DMA_SIZE - 1)
|
||||||
|
|
||||||
|
@ -170,7 +170,10 @@ static uint32_t dma_mem_readl(void *opaque, target_phys_addr_t addr)
|
||||||
uint32_t saddr;
|
uint32_t saddr;
|
||||||
|
|
||||||
if (s->is_ledma && (addr > DMA_MAX_REG_OFFSET)) {
|
if (s->is_ledma && (addr > DMA_MAX_REG_OFFSET)) {
|
||||||
return 0; /* extra mystery register(s) */
|
/* aliased to espdma, but we can't get there from here */
|
||||||
|
/* buggy driver if using undocumented behavior, just return 0 */
|
||||||
|
trace_sparc32_dma_mem_readl(addr, 0);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
saddr = (addr & DMA_MASK) >> 2;
|
saddr = (addr & DMA_MASK) >> 2;
|
||||||
trace_sparc32_dma_mem_readl(addr, s->dmaregs[saddr]);
|
trace_sparc32_dma_mem_readl(addr, s->dmaregs[saddr]);
|
||||||
|
@ -183,7 +186,9 @@ static void dma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
|
||||||
uint32_t saddr;
|
uint32_t saddr;
|
||||||
|
|
||||||
if (s->is_ledma && (addr > DMA_MAX_REG_OFFSET)) {
|
if (s->is_ledma && (addr > DMA_MAX_REG_OFFSET)) {
|
||||||
return; /* extra mystery register(s) */
|
/* aliased to espdma, but we can't get there from here */
|
||||||
|
trace_sparc32_dma_mem_writel(addr, 0, val);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
saddr = (addr & DMA_MASK) >> 2;
|
saddr = (addr & DMA_MASK) >> 2;
|
||||||
trace_sparc32_dma_mem_writel(addr, s->dmaregs[saddr], val);
|
trace_sparc32_dma_mem_writel(addr, s->dmaregs[saddr], val);
|
||||||
|
|
6
hw/vga.c
6
hw/vga.c
|
@ -2073,14 +2073,14 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
|
||||||
|
|
||||||
if (full_update) {
|
if (full_update) {
|
||||||
for (i = 0; i < size; src ++, dst ++, i ++)
|
for (i = 0; i < size; src ++, dst ++, i ++)
|
||||||
console_write_ch(dst, VMEM2CHTYPE(*src));
|
console_write_ch(dst, VMEM2CHTYPE(le32_to_cpu(*src)));
|
||||||
|
|
||||||
dpy_update(s->ds, 0, 0, width, height);
|
dpy_update(s->ds, 0, 0, width, height);
|
||||||
} else {
|
} else {
|
||||||
c_max = 0;
|
c_max = 0;
|
||||||
|
|
||||||
for (i = 0; i < size; src ++, dst ++, i ++) {
|
for (i = 0; i < size; src ++, dst ++, i ++) {
|
||||||
console_write_ch(&val, VMEM2CHTYPE(*src));
|
console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
|
||||||
if (*dst != val) {
|
if (*dst != val) {
|
||||||
*dst = val;
|
*dst = val;
|
||||||
c_max = i;
|
c_max = i;
|
||||||
|
@ -2089,7 +2089,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
|
||||||
}
|
}
|
||||||
c_min = i;
|
c_min = i;
|
||||||
for (; i < size; src ++, dst ++, i ++) {
|
for (; i < size; src ++, dst ++, i ++) {
|
||||||
console_write_ch(&val, VMEM2CHTYPE(*src));
|
console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
|
||||||
if (*dst != val) {
|
if (*dst != val) {
|
||||||
*dst = val;
|
*dst = val;
|
||||||
c_max = i;
|
c_max = i;
|
||||||
|
|
|
@ -106,7 +106,7 @@ typedef void (* vga_update_retrace_info_fn)(struct VGACommonState *s);
|
||||||
typedef struct VGACommonState {
|
typedef struct VGACommonState {
|
||||||
uint8_t *vram_ptr;
|
uint8_t *vram_ptr;
|
||||||
ram_addr_t vram_offset;
|
ram_addr_t vram_offset;
|
||||||
unsigned int vram_size;
|
uint32_t vram_size;
|
||||||
uint32_t lfb_addr;
|
uint32_t lfb_addr;
|
||||||
uint32_t lfb_end;
|
uint32_t lfb_end;
|
||||||
uint32_t map_addr;
|
uint32_t map_addr;
|
||||||
|
|
|
@ -53,7 +53,7 @@ static void ib700_write_enable_reg(void *vp, uint32_t addr, uint32_t data)
|
||||||
30, 28, 26, 24, 22, 20, 18, 16,
|
30, 28, 26, 24, 22, 20, 18, 16,
|
||||||
14, 12, 10, 8, 6, 4, 2, 0
|
14, 12, 10, 8, 6, 4, 2, 0
|
||||||
};
|
};
|
||||||
int64 timeout;
|
int64_t timeout;
|
||||||
|
|
||||||
ib700_debug("addr = %x, data = %x\n", addr, data);
|
ib700_debug("addr = %x, data = %x\n", addr, data);
|
||||||
|
|
||||||
|
|
|
@ -199,21 +199,21 @@ static unsigned int PerformComparison(const unsigned int opcode)
|
||||||
{
|
{
|
||||||
case typeSingle:
|
case typeSingle:
|
||||||
//printk("single.\n");
|
//printk("single.\n");
|
||||||
if (float32_is_nan(fpa11->fpreg[Fn].fSingle))
|
if (float32_is_any_nan(fpa11->fpreg[Fn].fSingle))
|
||||||
goto unordered;
|
goto unordered;
|
||||||
rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status);
|
rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case typeDouble:
|
case typeDouble:
|
||||||
//printk("double.\n");
|
//printk("double.\n");
|
||||||
if (float64_is_nan(fpa11->fpreg[Fn].fDouble))
|
if (float64_is_any_nan(fpa11->fpreg[Fn].fDouble))
|
||||||
goto unordered;
|
goto unordered;
|
||||||
rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble, &fpa11->fp_status);
|
rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble, &fpa11->fp_status);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case typeExtended:
|
case typeExtended:
|
||||||
//printk("extended.\n");
|
//printk("extended.\n");
|
||||||
if (floatx80_is_nan(fpa11->fpreg[Fn].fExtended))
|
if (floatx80_is_any_nan(fpa11->fpreg[Fn].fExtended))
|
||||||
goto unordered;
|
goto unordered;
|
||||||
rFn = fpa11->fpreg[Fn].fExtended;
|
rFn = fpa11->fpreg[Fn].fExtended;
|
||||||
break;
|
break;
|
||||||
|
@ -225,7 +225,7 @@ static unsigned int PerformComparison(const unsigned int opcode)
|
||||||
{
|
{
|
||||||
//printk("Fm is a constant: #%d.\n",Fm);
|
//printk("Fm is a constant: #%d.\n",Fm);
|
||||||
rFm = getExtendedConstant(Fm);
|
rFm = getExtendedConstant(Fm);
|
||||||
if (floatx80_is_nan(rFm))
|
if (floatx80_is_any_nan(rFm))
|
||||||
goto unordered;
|
goto unordered;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -235,21 +235,21 @@ static unsigned int PerformComparison(const unsigned int opcode)
|
||||||
{
|
{
|
||||||
case typeSingle:
|
case typeSingle:
|
||||||
//printk("single.\n");
|
//printk("single.\n");
|
||||||
if (float32_is_nan(fpa11->fpreg[Fm].fSingle))
|
if (float32_is_any_nan(fpa11->fpreg[Fm].fSingle))
|
||||||
goto unordered;
|
goto unordered;
|
||||||
rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle, &fpa11->fp_status);
|
rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle, &fpa11->fp_status);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case typeDouble:
|
case typeDouble:
|
||||||
//printk("double.\n");
|
//printk("double.\n");
|
||||||
if (float64_is_nan(fpa11->fpreg[Fm].fDouble))
|
if (float64_is_any_nan(fpa11->fpreg[Fm].fDouble))
|
||||||
goto unordered;
|
goto unordered;
|
||||||
rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble, &fpa11->fp_status);
|
rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble, &fpa11->fp_status);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case typeExtended:
|
case typeExtended:
|
||||||
//printk("extended.\n");
|
//printk("extended.\n");
|
||||||
if (floatx80_is_nan(fpa11->fpreg[Fm].fExtended))
|
if (floatx80_is_any_nan(fpa11->fpreg[Fm].fExtended))
|
||||||
goto unordered;
|
goto unordered;
|
||||||
rFm = fpa11->fpreg[Fm].fExtended;
|
rFm = fpa11->fpreg[Fm].fExtended;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -76,6 +76,10 @@
|
||||||
#ifdef FIGETBSZ
|
#ifdef FIGETBSZ
|
||||||
IOCTL(FIGETBSZ, IOC_R, MK_PTR(TYPE_LONG))
|
IOCTL(FIGETBSZ, IOC_R, MK_PTR(TYPE_LONG))
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef FS_IOC_FIEMAP
|
||||||
|
IOCTL_SPECIAL(FS_IOC_FIEMAP, IOC_W | IOC_R, do_ioctl_fs_ioc_fiemap,
|
||||||
|
MK_PTR(MK_STRUCT(STRUCT_fiemap)))
|
||||||
|
#endif
|
||||||
|
|
||||||
IOCTL(SIOCATMARK, 0, TYPE_NULL)
|
IOCTL(SIOCATMARK, 0, TYPE_NULL)
|
||||||
IOCTL(SIOCADDRT, IOC_W, MK_PTR(MK_STRUCT(STRUCT_rtentry)))
|
IOCTL(SIOCADDRT, IOC_W, MK_PTR(MK_STRUCT(STRUCT_rtentry)))
|
||||||
|
|
|
@ -174,8 +174,6 @@ int loader_exec(const char * filename, char ** argv, char ** envp,
|
||||||
|
|
||||||
retval = prepare_binprm(bprm);
|
retval = prepare_binprm(bprm);
|
||||||
|
|
||||||
infop->host_argv = argv;
|
|
||||||
|
|
||||||
if(retval>=0) {
|
if(retval>=0) {
|
||||||
if (bprm->buf[0] == 0x7f
|
if (bprm->buf[0] == 0x7f
|
||||||
&& bprm->buf[1] == 'E'
|
&& bprm->buf[1] == 'E'
|
||||||
|
|
|
@ -50,7 +50,6 @@ struct image_info {
|
||||||
abi_ulong saved_auxv;
|
abi_ulong saved_auxv;
|
||||||
abi_ulong arg_start;
|
abi_ulong arg_start;
|
||||||
abi_ulong arg_end;
|
abi_ulong arg_end;
|
||||||
char **host_argv;
|
|
||||||
int personality;
|
int personality;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1518,3 +1518,9 @@
|
||||||
#ifdef TARGET_NR_utimensat
|
#ifdef TARGET_NR_utimensat
|
||||||
{ TARGET_NR_utimensat, "utimensat", NULL, print_utimensat, NULL },
|
{ TARGET_NR_utimensat, "utimensat", NULL, print_utimensat, NULL },
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef TARGET_NR_sync_file_range
|
||||||
|
{ TARGET_NR_sync_file_range, "sync_file_range", NULL, NULL, NULL },
|
||||||
|
#endif
|
||||||
|
#ifdef TARGET_NR_sync_file_range2
|
||||||
|
{ TARGET_NR_sync_file_range2, "sync_file_range2", NULL, NULL, NULL },
|
||||||
|
#endif
|
||||||
|
|
|
@ -83,6 +83,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
|
||||||
#include <linux/kd.h>
|
#include <linux/kd.h>
|
||||||
#include <linux/mtio.h>
|
#include <linux/mtio.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
|
#include <linux/fiemap.h>
|
||||||
#include <linux/fb.h>
|
#include <linux/fb.h>
|
||||||
#include <linux/vt.h>
|
#include <linux/vt.h>
|
||||||
#include "linux_loop.h"
|
#include "linux_loop.h"
|
||||||
|
@ -2965,13 +2966,19 @@ enum {
|
||||||
#undef STRUCT
|
#undef STRUCT
|
||||||
#undef STRUCT_SPECIAL
|
#undef STRUCT_SPECIAL
|
||||||
|
|
||||||
typedef struct IOCTLEntry {
|
typedef struct IOCTLEntry IOCTLEntry;
|
||||||
|
|
||||||
|
typedef abi_long do_ioctl_fn(const IOCTLEntry *ie, uint8_t *buf_temp,
|
||||||
|
int fd, abi_long cmd, abi_long arg);
|
||||||
|
|
||||||
|
struct IOCTLEntry {
|
||||||
unsigned int target_cmd;
|
unsigned int target_cmd;
|
||||||
unsigned int host_cmd;
|
unsigned int host_cmd;
|
||||||
const char *name;
|
const char *name;
|
||||||
int access;
|
int access;
|
||||||
|
do_ioctl_fn *do_ioctl;
|
||||||
const argtype arg_type[5];
|
const argtype arg_type[5];
|
||||||
} IOCTLEntry;
|
};
|
||||||
|
|
||||||
#define IOC_R 0x0001
|
#define IOC_R 0x0001
|
||||||
#define IOC_W 0x0002
|
#define IOC_W 0x0002
|
||||||
|
@ -2979,9 +2986,98 @@ typedef struct IOCTLEntry {
|
||||||
|
|
||||||
#define MAX_STRUCT_SIZE 4096
|
#define MAX_STRUCT_SIZE 4096
|
||||||
|
|
||||||
|
/* So fiemap access checks don't overflow on 32 bit systems.
|
||||||
|
* This is very slightly smaller than the limit imposed by
|
||||||
|
* the underlying kernel.
|
||||||
|
*/
|
||||||
|
#define FIEMAP_MAX_EXTENTS ((UINT_MAX - sizeof(struct fiemap)) \
|
||||||
|
/ sizeof(struct fiemap_extent))
|
||||||
|
|
||||||
|
static abi_long do_ioctl_fs_ioc_fiemap(const IOCTLEntry *ie, uint8_t *buf_temp,
|
||||||
|
int fd, abi_long cmd, abi_long arg)
|
||||||
|
{
|
||||||
|
/* The parameter for this ioctl is a struct fiemap followed
|
||||||
|
* by an array of struct fiemap_extent whose size is set
|
||||||
|
* in fiemap->fm_extent_count. The array is filled in by the
|
||||||
|
* ioctl.
|
||||||
|
*/
|
||||||
|
int target_size_in, target_size_out;
|
||||||
|
struct fiemap *fm;
|
||||||
|
const argtype *arg_type = ie->arg_type;
|
||||||
|
const argtype extent_arg_type[] = { MK_STRUCT(STRUCT_fiemap_extent) };
|
||||||
|
void *argptr, *p;
|
||||||
|
abi_long ret;
|
||||||
|
int i, extent_size = thunk_type_size(extent_arg_type, 0);
|
||||||
|
uint32_t outbufsz;
|
||||||
|
int free_fm = 0;
|
||||||
|
|
||||||
|
assert(arg_type[0] == TYPE_PTR);
|
||||||
|
assert(ie->access == IOC_RW);
|
||||||
|
arg_type++;
|
||||||
|
target_size_in = thunk_type_size(arg_type, 0);
|
||||||
|
argptr = lock_user(VERIFY_READ, arg, target_size_in, 1);
|
||||||
|
if (!argptr) {
|
||||||
|
return -TARGET_EFAULT;
|
||||||
|
}
|
||||||
|
thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
|
||||||
|
unlock_user(argptr, arg, 0);
|
||||||
|
fm = (struct fiemap *)buf_temp;
|
||||||
|
if (fm->fm_extent_count > FIEMAP_MAX_EXTENTS) {
|
||||||
|
return -TARGET_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
outbufsz = sizeof (*fm) +
|
||||||
|
(sizeof(struct fiemap_extent) * fm->fm_extent_count);
|
||||||
|
|
||||||
|
if (outbufsz > MAX_STRUCT_SIZE) {
|
||||||
|
/* We can't fit all the extents into the fixed size buffer.
|
||||||
|
* Allocate one that is large enough and use it instead.
|
||||||
|
*/
|
||||||
|
fm = malloc(outbufsz);
|
||||||
|
if (!fm) {
|
||||||
|
return -TARGET_ENOMEM;
|
||||||
|
}
|
||||||
|
memcpy(fm, buf_temp, sizeof(struct fiemap));
|
||||||
|
free_fm = 1;
|
||||||
|
}
|
||||||
|
ret = get_errno(ioctl(fd, ie->host_cmd, fm));
|
||||||
|
if (!is_error(ret)) {
|
||||||
|
target_size_out = target_size_in;
|
||||||
|
/* An extent_count of 0 means we were only counting the extents
|
||||||
|
* so there are no structs to copy
|
||||||
|
*/
|
||||||
|
if (fm->fm_extent_count != 0) {
|
||||||
|
target_size_out += fm->fm_mapped_extents * extent_size;
|
||||||
|
}
|
||||||
|
argptr = lock_user(VERIFY_WRITE, arg, target_size_out, 0);
|
||||||
|
if (!argptr) {
|
||||||
|
ret = -TARGET_EFAULT;
|
||||||
|
} else {
|
||||||
|
/* Convert the struct fiemap */
|
||||||
|
thunk_convert(argptr, fm, arg_type, THUNK_TARGET);
|
||||||
|
if (fm->fm_extent_count != 0) {
|
||||||
|
p = argptr + target_size_in;
|
||||||
|
/* ...and then all the struct fiemap_extents */
|
||||||
|
for (i = 0; i < fm->fm_mapped_extents; i++) {
|
||||||
|
thunk_convert(p, &fm->fm_extents[i], extent_arg_type,
|
||||||
|
THUNK_TARGET);
|
||||||
|
p += extent_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unlock_user(argptr, arg, target_size_out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (free_fm) {
|
||||||
|
free(fm);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static IOCTLEntry ioctl_entries[] = {
|
static IOCTLEntry ioctl_entries[] = {
|
||||||
#define IOCTL(cmd, access, ...) \
|
#define IOCTL(cmd, access, ...) \
|
||||||
{ TARGET_ ## cmd, cmd, #cmd, access, { __VA_ARGS__ } },
|
{ TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
|
||||||
|
#define IOCTL_SPECIAL(cmd, access, dofn, ...) \
|
||||||
|
{ TARGET_ ## cmd, cmd, #cmd, access, dofn, { __VA_ARGS__ } },
|
||||||
#include "ioctls.h"
|
#include "ioctls.h"
|
||||||
{ 0, 0, },
|
{ 0, 0, },
|
||||||
};
|
};
|
||||||
|
@ -3011,6 +3107,10 @@ static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg)
|
||||||
#if defined(DEBUG)
|
#if defined(DEBUG)
|
||||||
gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name);
|
gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name);
|
||||||
#endif
|
#endif
|
||||||
|
if (ie->do_ioctl) {
|
||||||
|
return ie->do_ioctl(ie, buf_temp, fd, cmd, arg);
|
||||||
|
}
|
||||||
|
|
||||||
switch(arg_type[0]) {
|
switch(arg_type[0]) {
|
||||||
case TYPE_NULL:
|
case TYPE_NULL:
|
||||||
/* no argument */
|
/* no argument */
|
||||||
|
@ -7364,6 +7464,29 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||||
case TARGET_NR_fallocate:
|
case TARGET_NR_fallocate:
|
||||||
ret = get_errno(fallocate(arg1, arg2, arg3, arg4));
|
ret = get_errno(fallocate(arg1, arg2, arg3, arg4));
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(CONFIG_SYNC_FILE_RANGE)
|
||||||
|
#if defined(TARGET_NR_sync_file_range)
|
||||||
|
case TARGET_NR_sync_file_range:
|
||||||
|
#if TARGET_ABI_BITS == 32
|
||||||
|
ret = get_errno(sync_file_range(arg1, target_offset64(arg2, arg3),
|
||||||
|
target_offset64(arg4, arg5), arg6));
|
||||||
|
#else
|
||||||
|
ret = get_errno(sync_file_range(arg1, arg2, arg3, arg4));
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(TARGET_NR_sync_file_range2)
|
||||||
|
case TARGET_NR_sync_file_range2:
|
||||||
|
/* This is like sync_file_range but the arguments are reordered */
|
||||||
|
#if TARGET_ABI_BITS == 32
|
||||||
|
ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
|
||||||
|
target_offset64(arg5, arg6), arg2));
|
||||||
|
#else
|
||||||
|
ret = get_errno(sync_file_range(arg1, arg3, arg4, arg2));
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
unimplemented:
|
unimplemented:
|
||||||
|
|
|
@ -783,6 +783,7 @@ struct target_pollfd {
|
||||||
#define TARGET_BLKGETSIZE64 TARGET_IOR(0x12,114,sizeof(uint64_t)) /* return device size in bytes (u64 *arg) */
|
#define TARGET_BLKGETSIZE64 TARGET_IOR(0x12,114,sizeof(uint64_t)) /* return device size in bytes (u64 *arg) */
|
||||||
#define TARGET_FIBMAP TARGET_IO(0x00,1) /* bmap access */
|
#define TARGET_FIBMAP TARGET_IO(0x00,1) /* bmap access */
|
||||||
#define TARGET_FIGETBSZ TARGET_IO(0x00,2) /* get the block size used for bmap */
|
#define TARGET_FIGETBSZ TARGET_IO(0x00,2) /* get the block size used for bmap */
|
||||||
|
#define TARGET_FS_IOC_FIEMAP TARGET_IOWR('f',11,struct fiemap)
|
||||||
|
|
||||||
/* cdrom commands */
|
/* cdrom commands */
|
||||||
#define TARGET_CDROMPAUSE 0x5301 /* Pause Audio Operation */
|
#define TARGET_CDROMPAUSE 0x5301 /* Pause Audio Operation */
|
||||||
|
|
|
@ -165,3 +165,19 @@ STRUCT(vt_stat,
|
||||||
TYPE_SHORT, /* v_active */
|
TYPE_SHORT, /* v_active */
|
||||||
TYPE_SHORT, /* v_signal */
|
TYPE_SHORT, /* v_signal */
|
||||||
TYPE_SHORT) /* v_state */
|
TYPE_SHORT) /* v_state */
|
||||||
|
|
||||||
|
STRUCT(fiemap_extent,
|
||||||
|
TYPE_ULONGLONG, /* fe_logical */
|
||||||
|
TYPE_ULONGLONG, /* fe_physical */
|
||||||
|
TYPE_ULONGLONG, /* fe_length */
|
||||||
|
MK_ARRAY(TYPE_ULONGLONG, 2), /* fe_reserved64[2] */
|
||||||
|
TYPE_INT, /* fe_flags */
|
||||||
|
MK_ARRAY(TYPE_INT, 3)) /* fe_reserved[3] */
|
||||||
|
|
||||||
|
STRUCT(fiemap,
|
||||||
|
TYPE_ULONGLONG, /* fm_start */
|
||||||
|
TYPE_ULONGLONG, /* fm_length */
|
||||||
|
TYPE_INT, /* fm_flags */
|
||||||
|
TYPE_INT, /* fm_mapped_extents */
|
||||||
|
TYPE_INT, /* fm_extent_count */
|
||||||
|
TYPE_INT) /* fm_reserved */
|
||||||
|
|
141
monitor.c
141
monitor.c
|
@ -34,6 +34,7 @@
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
#include "net/slirp.h"
|
#include "net/slirp.h"
|
||||||
#include "qemu-char.h"
|
#include "qemu-char.h"
|
||||||
|
#include "ui/qemu-spice.h"
|
||||||
#include "sysemu.h"
|
#include "sysemu.h"
|
||||||
#include "monitor.h"
|
#include "monitor.h"
|
||||||
#include "readline.h"
|
#include "readline.h"
|
||||||
|
@ -59,6 +60,7 @@
|
||||||
#ifdef CONFIG_SIMPLE_TRACE
|
#ifdef CONFIG_SIMPLE_TRACE
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "ui/qemu-spice.h"
|
||||||
|
|
||||||
//#define DEBUG
|
//#define DEBUG
|
||||||
//#define DEBUG_COMPLETION
|
//#define DEBUG_COMPLETION
|
||||||
|
@ -457,6 +459,15 @@ void monitor_protocol_event(MonitorEvent event, QObject *data)
|
||||||
case QEVENT_WATCHDOG:
|
case QEVENT_WATCHDOG:
|
||||||
event_name = "WATCHDOG";
|
event_name = "WATCHDOG";
|
||||||
break;
|
break;
|
||||||
|
case QEVENT_SPICE_CONNECTED:
|
||||||
|
event_name = "SPICE_CONNECTED";
|
||||||
|
break;
|
||||||
|
case QEVENT_SPICE_INITIALIZED:
|
||||||
|
event_name = "SPICE_INITIALIZED";
|
||||||
|
break;
|
||||||
|
case QEVENT_SPICE_DISCONNECTED:
|
||||||
|
event_name = "SPICE_DISCONNECTED";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
abort();
|
abort();
|
||||||
break;
|
break;
|
||||||
|
@ -1063,6 +1074,105 @@ static int do_change(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int set_password(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
||||||
|
{
|
||||||
|
const char *protocol = qdict_get_str(qdict, "protocol");
|
||||||
|
const char *password = qdict_get_str(qdict, "password");
|
||||||
|
const char *connected = qdict_get_try_str(qdict, "connected");
|
||||||
|
int disconnect_if_connected = 0;
|
||||||
|
int fail_if_connected = 0;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (connected) {
|
||||||
|
if (strcmp(connected, "fail") == 0) {
|
||||||
|
fail_if_connected = 1;
|
||||||
|
} else if (strcmp(connected, "disconnect") == 0) {
|
||||||
|
disconnect_if_connected = 1;
|
||||||
|
} else if (strcmp(connected, "keep") == 0) {
|
||||||
|
/* nothing */
|
||||||
|
} else {
|
||||||
|
qerror_report(QERR_INVALID_PARAMETER, "connected");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(protocol, "spice") == 0) {
|
||||||
|
if (!using_spice) {
|
||||||
|
/* correct one? spice isn't a device ,,, */
|
||||||
|
qerror_report(QERR_DEVICE_NOT_ACTIVE, "spice");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
rc = qemu_spice_set_passwd(password, fail_if_connected,
|
||||||
|
disconnect_if_connected);
|
||||||
|
if (rc != 0) {
|
||||||
|
qerror_report(QERR_SET_PASSWD_FAILED);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(protocol, "vnc") == 0) {
|
||||||
|
if (fail_if_connected || disconnect_if_connected) {
|
||||||
|
/* vnc supports "connected=keep" only */
|
||||||
|
qerror_report(QERR_INVALID_PARAMETER, "connected");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
rc = vnc_display_password(NULL, password);
|
||||||
|
if (rc != 0) {
|
||||||
|
qerror_report(QERR_SET_PASSWD_FAILED);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
qerror_report(QERR_INVALID_PARAMETER, "protocol");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int expire_password(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
||||||
|
{
|
||||||
|
const char *protocol = qdict_get_str(qdict, "protocol");
|
||||||
|
const char *whenstr = qdict_get_str(qdict, "time");
|
||||||
|
time_t when;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (strcmp(whenstr, "now")) {
|
||||||
|
when = 0;
|
||||||
|
} else if (strcmp(whenstr, "never")) {
|
||||||
|
when = TIME_MAX;
|
||||||
|
} else if (whenstr[0] == '+') {
|
||||||
|
when = time(NULL) + strtoull(whenstr+1, NULL, 10);
|
||||||
|
} else {
|
||||||
|
when = strtoull(whenstr, NULL, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(protocol, "spice") == 0) {
|
||||||
|
if (!using_spice) {
|
||||||
|
/* correct one? spice isn't a device ,,, */
|
||||||
|
qerror_report(QERR_DEVICE_NOT_ACTIVE, "spice");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
rc = qemu_spice_set_pw_expire(when);
|
||||||
|
if (rc != 0) {
|
||||||
|
qerror_report(QERR_SET_PASSWD_FAILED);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(protocol, "vnc") == 0) {
|
||||||
|
rc = vnc_display_pw_expire(NULL, when);
|
||||||
|
if (rc != 0) {
|
||||||
|
qerror_report(QERR_SET_PASSWD_FAILED);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
qerror_report(QERR_INVALID_PARAMETER, "protocol");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static int do_screen_dump(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
static int do_screen_dump(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
||||||
{
|
{
|
||||||
vga_hw_screen_dump(qdict_get_str(qdict, "filename"));
|
vga_hw_screen_dump(qdict_get_str(qdict, "filename"));
|
||||||
|
@ -2272,6 +2382,15 @@ static void tlb_info(Monitor *mon)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(TARGET_SPARC)
|
||||||
|
static void tlb_info(Monitor *mon)
|
||||||
|
{
|
||||||
|
CPUState *env1 = mon_get_cpu();
|
||||||
|
|
||||||
|
dump_mmu((FILE*)mon, (fprintf_function)monitor_printf, env1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void do_info_kvm_print(Monitor *mon, const QObject *data)
|
static void do_info_kvm_print(Monitor *mon, const QObject *data)
|
||||||
{
|
{
|
||||||
QDict *qdict;
|
QDict *qdict;
|
||||||
|
@ -2744,7 +2863,7 @@ static const mon_cmd_t info_cmds[] = {
|
||||||
.user_print = do_pci_info_print,
|
.user_print = do_pci_info_print,
|
||||||
.mhandler.info_new = do_pci_info,
|
.mhandler.info_new = do_pci_info,
|
||||||
},
|
},
|
||||||
#if defined(TARGET_I386) || defined(TARGET_SH4)
|
#if defined(TARGET_I386) || defined(TARGET_SH4) || defined(TARGET_SPARC)
|
||||||
{
|
{
|
||||||
.name = "tlb",
|
.name = "tlb",
|
||||||
.args_type = "",
|
.args_type = "",
|
||||||
|
@ -2850,6 +2969,16 @@ static const mon_cmd_t info_cmds[] = {
|
||||||
.user_print = do_info_vnc_print,
|
.user_print = do_info_vnc_print,
|
||||||
.mhandler.info_new = do_info_vnc,
|
.mhandler.info_new = do_info_vnc,
|
||||||
},
|
},
|
||||||
|
#if defined(CONFIG_SPICE)
|
||||||
|
{
|
||||||
|
.name = "spice",
|
||||||
|
.args_type = "",
|
||||||
|
.params = "",
|
||||||
|
.help = "show the spice server status",
|
||||||
|
.user_print = do_info_spice_print,
|
||||||
|
.mhandler.info_new = do_info_spice,
|
||||||
|
},
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
.name = "name",
|
.name = "name",
|
||||||
.args_type = "",
|
.args_type = "",
|
||||||
|
@ -3037,6 +3166,16 @@ static const mon_cmd_t qmp_query_cmds[] = {
|
||||||
.user_print = do_info_vnc_print,
|
.user_print = do_info_vnc_print,
|
||||||
.mhandler.info_new = do_info_vnc,
|
.mhandler.info_new = do_info_vnc,
|
||||||
},
|
},
|
||||||
|
#if defined(CONFIG_SPICE)
|
||||||
|
{
|
||||||
|
.name = "spice",
|
||||||
|
.args_type = "",
|
||||||
|
.params = "",
|
||||||
|
.help = "show the spice server status",
|
||||||
|
.user_print = do_info_spice_print,
|
||||||
|
.mhandler.info_new = do_info_spice,
|
||||||
|
},
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
.name = "name",
|
.name = "name",
|
||||||
.args_type = "",
|
.args_type = "",
|
||||||
|
|
|
@ -32,6 +32,9 @@ typedef enum MonitorEvent {
|
||||||
QEVENT_BLOCK_IO_ERROR,
|
QEVENT_BLOCK_IO_ERROR,
|
||||||
QEVENT_RTC_CHANGE,
|
QEVENT_RTC_CHANGE,
|
||||||
QEVENT_WATCHDOG,
|
QEVENT_WATCHDOG,
|
||||||
|
QEVENT_SPICE_CONNECTED,
|
||||||
|
QEVENT_SPICE_INITIALIZED,
|
||||||
|
QEVENT_SPICE_DISCONNECTED,
|
||||||
QEVENT_MAX,
|
QEVENT_MAX,
|
||||||
} MonitorEvent;
|
} MonitorEvent;
|
||||||
|
|
||||||
|
|
|
@ -43,8 +43,8 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required
|
||||||
char *dev;
|
char *dev;
|
||||||
struct stat s;
|
struct stat s;
|
||||||
|
|
||||||
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__)
|
||||||
/* if no ifname is given, always start the search from tap0. */
|
/* if no ifname is given, always start the search from tap0/tun0. */
|
||||||
int i;
|
int i;
|
||||||
char dname[100];
|
char dname[100];
|
||||||
|
|
||||||
|
@ -52,7 +52,11 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required
|
||||||
if (*ifname) {
|
if (*ifname) {
|
||||||
snprintf(dname, sizeof dname, "/dev/%s", ifname);
|
snprintf(dname, sizeof dname, "/dev/%s", ifname);
|
||||||
} else {
|
} else {
|
||||||
|
#if defined(__OpenBSD__)
|
||||||
|
snprintf(dname, sizeof dname, "/dev/tun%d", i);
|
||||||
|
#else
|
||||||
snprintf(dname, sizeof dname, "/dev/tap%d", i);
|
snprintf(dname, sizeof dname, "/dev/tap%d", i);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
TFR(fd = open(dname, O_RDWR));
|
TFR(fd = open(dname, O_RDWR));
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
|
|
Binary file not shown.
|
@ -50,6 +50,9 @@ typedef struct DeviceState DeviceState;
|
||||||
#if !defined(ENOTSUP)
|
#if !defined(ENOTSUP)
|
||||||
#define ENOTSUP 4096
|
#define ENOTSUP 4096
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef TIME_MAX
|
||||||
|
#define TIME_MAX LONG_MAX
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_IOVEC
|
#ifndef CONFIG_IOVEC
|
||||||
#define CONFIG_IOVEC
|
#define CONFIG_IOVEC
|
||||||
|
|
|
@ -162,6 +162,7 @@ TODO (no longer available)
|
||||||
* pcsys_monitor:: QEMU Monitor
|
* pcsys_monitor:: QEMU Monitor
|
||||||
* disk_images:: Disk Images
|
* disk_images:: Disk Images
|
||||||
* pcsys_network:: Network emulation
|
* pcsys_network:: Network emulation
|
||||||
|
* pcsys_other_devs:: Other Devices
|
||||||
* direct_linux_boot:: Direct Linux Boot
|
* direct_linux_boot:: Direct Linux Boot
|
||||||
* pcsys_usb:: USB emulation
|
* pcsys_usb:: USB emulation
|
||||||
* vnc_security:: VNC security
|
* vnc_security:: VNC security
|
||||||
|
@ -202,7 +203,7 @@ Intel 82801AA AC97 Audio compatible sound card
|
||||||
@item
|
@item
|
||||||
Intel HD Audio Controller and HDA codec
|
Intel HD Audio Controller and HDA codec
|
||||||
@item
|
@item
|
||||||
Adlib(OPL2) - Yamaha YM3812 compatible chip
|
Adlib (OPL2) - Yamaha YM3812 compatible chip
|
||||||
@item
|
@item
|
||||||
Gravis Ultrasound GF1 sound card
|
Gravis Ultrasound GF1 sound card
|
||||||
@item
|
@item
|
||||||
|
@ -222,7 +223,7 @@ VGA BIOS.
|
||||||
|
|
||||||
QEMU uses YM3812 emulation by Tatsuyuki Satoh.
|
QEMU uses YM3812 emulation by Tatsuyuki Satoh.
|
||||||
|
|
||||||
QEMU uses GUS emulation(GUSEMU32 @url{http://www.deinmeister.de/gusemu/})
|
QEMU uses GUS emulation (GUSEMU32 @url{http://www.deinmeister.de/gusemu/})
|
||||||
by Tibor "TS" Schütz.
|
by Tibor "TS" Schütz.
|
||||||
|
|
||||||
Not that, by default, GUS shares IRQ(7) with parallel ports and so
|
Not that, by default, GUS shares IRQ(7) with parallel ports and so
|
||||||
|
@ -715,6 +716,7 @@ Using the @option{-net socket} option, it is possible to make VLANs
|
||||||
that span several QEMU instances. See @ref{sec_invocation} to have a
|
that span several QEMU instances. See @ref{sec_invocation} to have a
|
||||||
basic example.
|
basic example.
|
||||||
|
|
||||||
|
@node pcsys_other_devs
|
||||||
@section Other Devices
|
@section Other Devices
|
||||||
|
|
||||||
@subsection Inter-VM Shared Memory device
|
@subsection Inter-VM Shared Memory device
|
||||||
|
@ -832,7 +834,7 @@ Standard USB keyboard. Will override the PS/2 keyboard (if present).
|
||||||
Serial converter. This emulates an FTDI FT232BM chip connected to host character
|
Serial converter. This emulates an FTDI FT232BM chip connected to host character
|
||||||
device @var{dev}. The available character devices are the same as for the
|
device @var{dev}. The available character devices are the same as for the
|
||||||
@code{-serial} option. The @code{vendorid} and @code{productid} options can be
|
@code{-serial} option. The @code{vendorid} and @code{productid} options can be
|
||||||
used to override the default 0403:6001. For instance,
|
used to override the default 0403:6001. For instance,
|
||||||
@example
|
@example
|
||||||
usb_add serial:productid=FA00:tcp:192.168.0.2:4444
|
usb_add serial:productid=FA00:tcp:192.168.0.2:4444
|
||||||
@end example
|
@end example
|
||||||
|
@ -1047,7 +1049,7 @@ qemu [...OPTIONS...] -vnc :1,tls,x509,sasl -monitor stdio
|
||||||
|
|
||||||
The GNU TLS packages provides a command called @code{certtool} which can
|
The GNU TLS packages provides a command called @code{certtool} which can
|
||||||
be used to generate certificates and keys in PEM format. At a minimum it
|
be used to generate certificates and keys in PEM format. At a minimum it
|
||||||
is neccessary to setup a certificate authority, and issue certificates to
|
is necessary to setup a certificate authority, and issue certificates to
|
||||||
each server. If using certificates for authentication, then each client
|
each server. If using certificates for authentication, then each client
|
||||||
will also need to be issued a certificate. The recommendation is for the
|
will also need to be issued a certificate. The recommendation is for the
|
||||||
server to keep its certificates in either @code{/etc/pki/qemu} or for
|
server to keep its certificates in either @code{/etc/pki/qemu} or for
|
||||||
|
@ -1190,7 +1192,7 @@ keytab: /etc/qemu/krb5.tab
|
||||||
For this to work the administrator of your KDC must generate a Kerberos
|
For this to work the administrator of your KDC must generate a Kerberos
|
||||||
principal for the server, with a name of 'qemu/somehost.example.com@@EXAMPLE.COM'
|
principal for the server, with a name of 'qemu/somehost.example.com@@EXAMPLE.COM'
|
||||||
replacing 'somehost.example.com' with the fully qualified host name of the
|
replacing 'somehost.example.com' with the fully qualified host name of the
|
||||||
machine running QEMU, and 'EXAMPLE.COM' with the Keberos Realm.
|
machine running QEMU, and 'EXAMPLE.COM' with the Kerberos Realm.
|
||||||
|
|
||||||
Other configurations will be left as an exercise for the reader. It should
|
Other configurations will be left as an exercise for the reader. It should
|
||||||
be noted that only Digest-MD5 and GSSAPI provides a SSF layer for data
|
be noted that only Digest-MD5 and GSSAPI provides a SSF layer for data
|
||||||
|
@ -1772,7 +1774,7 @@ enabled in the kernel, and expect 512M RAM. Kernels for The PBX-A9 board
|
||||||
should have CONFIG_SPARSEMEM enabled, CONFIG_REALVIEW_HIGH_PHYS_OFFSET
|
should have CONFIG_SPARSEMEM enabled, CONFIG_REALVIEW_HIGH_PHYS_OFFSET
|
||||||
disabled and expect 1024M RAM.
|
disabled and expect 1024M RAM.
|
||||||
|
|
||||||
The following devices are emuilated:
|
The following devices are emulated:
|
||||||
|
|
||||||
@itemize @minus
|
@itemize @minus
|
||||||
@item
|
@item
|
||||||
|
@ -1872,7 +1874,7 @@ Secure Digital card connected to OMAP MMC/SD host
|
||||||
@item
|
@item
|
||||||
Three OMAP on-chip UARTs and on-chip STI debugging console
|
Three OMAP on-chip UARTs and on-chip STI debugging console
|
||||||
@item
|
@item
|
||||||
A Bluetooth(R) transciever and HCI connected to an UART
|
A Bluetooth(R) transceiver and HCI connected to an UART
|
||||||
@item
|
@item
|
||||||
Mentor Graphics "Inventra" dual-role USB controller embedded in a TI
|
Mentor Graphics "Inventra" dual-role USB controller embedded in a TI
|
||||||
TUSB6010 chip - only USB host mode is supported
|
TUSB6010 chip - only USB host mode is supported
|
||||||
|
@ -1934,7 +1936,7 @@ MV88W8618 audio controller, WM8750 CODEC and mixer
|
||||||
@end itemize
|
@end itemize
|
||||||
|
|
||||||
The Siemens SX1 models v1 and v2 (default) basic emulation.
|
The Siemens SX1 models v1 and v2 (default) basic emulation.
|
||||||
The emulaton includes the following elements:
|
The emulation includes the following elements:
|
||||||
|
|
||||||
@itemize @minus
|
@itemize @minus
|
||||||
@item
|
@item
|
||||||
|
@ -2190,7 +2192,7 @@ Set the x86 stack size in bytes (default=524288)
|
||||||
Select CPU model (-cpu ? for list and additional feature selection)
|
Select CPU model (-cpu ? for list and additional feature selection)
|
||||||
@item -ignore-environment
|
@item -ignore-environment
|
||||||
Start with an empty environment. Without this option,
|
Start with an empty environment. Without this option,
|
||||||
the inital environment is a copy of the caller's environment.
|
the initial environment is a copy of the caller's environment.
|
||||||
@item -E @var{var}=@var{value}
|
@item -E @var{var}=@var{value}
|
||||||
Set environment @var{var} to @var{value}.
|
Set environment @var{var} to @var{value}.
|
||||||
@item -U @var{var}
|
@item -U @var{var}
|
||||||
|
@ -2201,7 +2203,7 @@ the address region required by guest applications is reserved on the host.
|
||||||
This option is currently only supported on some hosts.
|
This option is currently only supported on some hosts.
|
||||||
@item -R size
|
@item -R size
|
||||||
Pre-allocate a guest virtual address space of the given size (in bytes).
|
Pre-allocate a guest virtual address space of the given size (in bytes).
|
||||||
"G", "M", and "k" suffixes may be used when specifying the size.
|
"G", "M", and "k" suffixes may be used when specifying the size.
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
Debug options:
|
Debug options:
|
||||||
|
@ -2420,7 +2422,7 @@ Set the library root path (default=/)
|
||||||
Set the stack size in bytes (default=524288)
|
Set the stack size in bytes (default=524288)
|
||||||
@item -ignore-environment
|
@item -ignore-environment
|
||||||
Start with an empty environment. Without this option,
|
Start with an empty environment. Without this option,
|
||||||
the inital environment is a copy of the caller's environment.
|
the initial environment is a copy of the caller's environment.
|
||||||
@item -E @var{var}=@var{value}
|
@item -E @var{var}=@var{value}
|
||||||
Set environment @var{var} to @var{value}.
|
Set environment @var{var} to @var{value}.
|
||||||
@item -U @var{var}
|
@item -U @var{var}
|
||||||
|
@ -2493,7 +2495,7 @@ correct SDL directory when invoked.
|
||||||
|
|
||||||
@item Install the MinGW version of zlib and make sure
|
@item Install the MinGW version of zlib and make sure
|
||||||
@file{zlib.h} and @file{libz.dll.a} are in
|
@file{zlib.h} and @file{libz.dll.a} are in
|
||||||
MingGW's default header and linker search paths.
|
MinGW's default header and linker search paths.
|
||||||
|
|
||||||
@item Extract the current version of QEMU.
|
@item Extract the current version of QEMU.
|
||||||
|
|
||||||
|
@ -2528,7 +2530,7 @@ the QEMU configuration script.
|
||||||
|
|
||||||
@item Install the MinGW version of zlib and make sure
|
@item Install the MinGW version of zlib and make sure
|
||||||
@file{zlib.h} and @file{libz.dll.a} are in
|
@file{zlib.h} and @file{libz.dll.a} are in
|
||||||
MingGW's default header and linker search paths.
|
MinGW's default header and linker search paths.
|
||||||
|
|
||||||
@item
|
@item
|
||||||
Configure QEMU for Windows cross compilation:
|
Configure QEMU for Windows cross compilation:
|
||||||
|
@ -2537,7 +2539,7 @@ PATH=/usr/i686-pc-mingw32/sys-root/mingw/bin:$PATH ./configure --cross-prefix='i
|
||||||
@end example
|
@end example
|
||||||
The example assumes @file{sdl-config} is installed under @file{/usr/i686-pc-mingw32/sys-root/mingw/bin} and
|
The example assumes @file{sdl-config} is installed under @file{/usr/i686-pc-mingw32/sys-root/mingw/bin} and
|
||||||
MinGW cross compilation tools have names like @file{i686-pc-mingw32-gcc} and @file{i686-pc-mingw32-strip}.
|
MinGW cross compilation tools have names like @file{i686-pc-mingw32-gcc} and @file{i686-pc-mingw32-strip}.
|
||||||
We set the @code{PATH} environment variable to ensure the MingW version of @file{sdl-config} is used and
|
We set the @code{PATH} environment variable to ensure the MinGW version of @file{sdl-config} is used and
|
||||||
use --cross-prefix to specify the name of the cross compiler.
|
use --cross-prefix to specify the name of the cross compiler.
|
||||||
You can also use --prefix to set the Win32 install path which defaults to @file{c:/Program Files/Qemu}.
|
You can also use --prefix to set the Win32 install path which defaults to @file{c:/Program Files/Qemu}.
|
||||||
|
|
||||||
|
|
|
@ -751,7 +751,7 @@ Rotate graphical output 90 deg left (only PXA LCD).
|
||||||
ETEXI
|
ETEXI
|
||||||
|
|
||||||
DEF("vga", HAS_ARG, QEMU_OPTION_vga,
|
DEF("vga", HAS_ARG, QEMU_OPTION_vga,
|
||||||
"-vga [std|cirrus|vmware|xenfb|none]\n"
|
"-vga [std|cirrus|vmware|qxl|xenfb|none]\n"
|
||||||
" select video card type\n", QEMU_ARCH_ALL)
|
" select video card type\n", QEMU_ARCH_ALL)
|
||||||
STEXI
|
STEXI
|
||||||
@item -vga @var{type}
|
@item -vga @var{type}
|
||||||
|
@ -772,6 +772,10 @@ this option.
|
||||||
VMWare SVGA-II compatible adapter. Use it if you have sufficiently
|
VMWare SVGA-II compatible adapter. Use it if you have sufficiently
|
||||||
recent XFree86/XOrg server or Windows guest with a driver for this
|
recent XFree86/XOrg server or Windows guest with a driver for this
|
||||||
card.
|
card.
|
||||||
|
@item qxl
|
||||||
|
QXL paravirtual graphic card. It is VGA compatible (including VESA
|
||||||
|
2.0 VBE support). Works best with qxl guest drivers installed though.
|
||||||
|
Recommended choice when using the spice protocol.
|
||||||
@item none
|
@item none
|
||||||
Disable VGA card.
|
Disable VGA card.
|
||||||
@end table
|
@end table
|
||||||
|
|
|
@ -516,7 +516,7 @@ timers, especially together with the use of bottom halves (BHs).
|
||||||
@section Hardware interrupts
|
@section Hardware interrupts
|
||||||
|
|
||||||
In order to be faster, QEMU does not check at every basic block if an
|
In order to be faster, QEMU does not check at every basic block if an
|
||||||
hardware interrupt is pending. Instead, the user must asynchrously
|
hardware interrupt is pending. Instead, the user must asynchronously
|
||||||
call a specific function to tell that an interrupt is pending. This
|
call a specific function to tell that an interrupt is pending. This
|
||||||
function resets the chaining of the currently executing basic
|
function resets the chaining of the currently executing basic
|
||||||
block. It ensures that the execution will return soon in the main loop
|
block. It ensures that the execution will return soon in the main loop
|
||||||
|
@ -548,7 +548,7 @@ Linux kernel does. The @code{sigreturn()} system call is emulated to return
|
||||||
from the virtual signal handler.
|
from the virtual signal handler.
|
||||||
|
|
||||||
Some signals (such as SIGALRM) directly come from the host. Other
|
Some signals (such as SIGALRM) directly come from the host. Other
|
||||||
signals are synthetized from the virtual CPU exceptions such as SIGFPE
|
signals are synthesized from the virtual CPU exceptions such as SIGFPE
|
||||||
when a division by zero is done (see @code{main.c:cpu_loop()}).
|
when a division by zero is done (see @code{main.c:cpu_loop()}).
|
||||||
|
|
||||||
The blocked signal mask is still handled by the host Linux kernel so
|
The blocked signal mask is still handled by the host Linux kernel so
|
||||||
|
|
|
@ -50,7 +50,8 @@ static void __attribute__((constructor)) init_get_clock(void)
|
||||||
{
|
{
|
||||||
use_rt_clock = 0;
|
use_rt_clock = 0;
|
||||||
#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD_version >= 500000) \
|
#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD_version >= 500000) \
|
||||||
|| defined(__DragonFly__) || defined(__FreeBSD_kernel__)
|
|| defined(__DragonFly__) || defined(__FreeBSD_kernel__) \
|
||||||
|
|| defined(__OpenBSD__)
|
||||||
{
|
{
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
|
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
|
||||||
|
|
129
qmp-commands.hx
129
qmp-commands.hx
|
@ -510,7 +510,7 @@ Set maximum speed for migrations.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
|
|
||||||
- "value": maximum speed, in bytes per second (json-number)
|
- "value": maximum speed, in bytes per second (json-int)
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
@ -735,6 +735,63 @@ Example:
|
||||||
"password": "12345" } }
|
"password": "12345" } }
|
||||||
<- { "return": {} }
|
<- { "return": {} }
|
||||||
|
|
||||||
|
EQMP
|
||||||
|
|
||||||
|
{
|
||||||
|
.name = "set_password",
|
||||||
|
.args_type = "protocol:s,password:s,connected:s?",
|
||||||
|
.params = "protocol password action-if-connected",
|
||||||
|
.help = "set spice/vnc password",
|
||||||
|
.user_print = monitor_user_noop,
|
||||||
|
.mhandler.cmd_new = set_password,
|
||||||
|
},
|
||||||
|
|
||||||
|
SQMP
|
||||||
|
set_password
|
||||||
|
------------
|
||||||
|
|
||||||
|
Set the password for vnc/spice protocols.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
- "protocol": protocol name (json-string)
|
||||||
|
- "password": password (json-string)
|
||||||
|
- "connected": [ keep | disconnect | fail ] (josn-string, optional)
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
-> { "execute": "set_password", "arguments": { "protocol": "vnc",
|
||||||
|
"password": "secret" } }
|
||||||
|
<- { "return": {} }
|
||||||
|
|
||||||
|
EQMP
|
||||||
|
|
||||||
|
{
|
||||||
|
.name = "expire_password",
|
||||||
|
.args_type = "protocol:s,time:s",
|
||||||
|
.params = "protocol time",
|
||||||
|
.help = "set spice/vnc password expire-time",
|
||||||
|
.user_print = monitor_user_noop,
|
||||||
|
.mhandler.cmd_new = expire_password,
|
||||||
|
},
|
||||||
|
|
||||||
|
SQMP
|
||||||
|
expire_password
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Set the password expire time for vnc/spice protocols.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
- "protocol": protocol name (json-string)
|
||||||
|
- "time": [ now | never | +secs | secs ] (json-string)
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
-> { "execute": "expire_password", "arguments": { "protocol": "vnc",
|
||||||
|
"time": "+60" } }
|
||||||
|
<- { "return": {} }
|
||||||
|
|
||||||
EQMP
|
EQMP
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -1438,6 +1495,76 @@ Example:
|
||||||
|
|
||||||
EQMP
|
EQMP
|
||||||
|
|
||||||
|
SQMP
|
||||||
|
query-spice
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Show SPICE server information.
|
||||||
|
|
||||||
|
Return a json-object with server information. Connected clients are returned
|
||||||
|
as a json-array of json-objects.
|
||||||
|
|
||||||
|
The main json-object contains the following:
|
||||||
|
|
||||||
|
- "enabled": true or false (json-bool)
|
||||||
|
- "host": server's IP address (json-string)
|
||||||
|
- "port": server's port number (json-int, optional)
|
||||||
|
- "tls-port": server's port number (json-int, optional)
|
||||||
|
- "auth": authentication method (json-string)
|
||||||
|
- Possible values: "none", "spice"
|
||||||
|
- "channels": a json-array of all active channels clients
|
||||||
|
|
||||||
|
Channels are described by a json-object, each one contain the following:
|
||||||
|
|
||||||
|
- "host": client's IP address (json-string)
|
||||||
|
- "family": address family (json-string)
|
||||||
|
- Possible values: "ipv4", "ipv6", "unix", "unknown"
|
||||||
|
- "port": client's port number (json-string)
|
||||||
|
- "connection-id": spice connection id. All channels with the same id
|
||||||
|
belong to the same spice session (json-int)
|
||||||
|
- "channel-type": channel type. "1" is the main control channel, filter for
|
||||||
|
this one if you want track spice sessions only (json-int)
|
||||||
|
- "channel-id": channel id. Usually "0", might be different needed when
|
||||||
|
multiple channels of the same type exist, such as multiple
|
||||||
|
display channels in a multihead setup (json-int)
|
||||||
|
- "tls": whevener the channel is encrypted (json-bool)
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
-> { "execute": "query-spice" }
|
||||||
|
<- {
|
||||||
|
"return": {
|
||||||
|
"enabled": true,
|
||||||
|
"auth": "spice",
|
||||||
|
"port": 5920,
|
||||||
|
"tls-port": 5921,
|
||||||
|
"host": "0.0.0.0",
|
||||||
|
"channels": [
|
||||||
|
{
|
||||||
|
"port": "54924",
|
||||||
|
"family": "ipv4",
|
||||||
|
"channel-type": 1,
|
||||||
|
"connection-id": 1804289383,
|
||||||
|
"host": "127.0.0.1",
|
||||||
|
"channel-id": 0,
|
||||||
|
"tls": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"port": "36710",
|
||||||
|
"family": "ipv4",
|
||||||
|
"channel-type": 4,
|
||||||
|
"connection-id": 1804289383,
|
||||||
|
"host": "127.0.0.1",
|
||||||
|
"channel-id": 0,
|
||||||
|
"tls": false
|
||||||
|
},
|
||||||
|
[ ... more channels follow ... ]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EQMP
|
||||||
|
|
||||||
SQMP
|
SQMP
|
||||||
query-name
|
query-name
|
||||||
----------
|
----------
|
||||||
|
|
|
@ -92,13 +92,13 @@ static BOOTPClient *find_addr(Slirp *slirp, struct in_addr *paddr,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type,
|
static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type,
|
||||||
const struct in_addr **preq_addr)
|
struct in_addr *preq_addr)
|
||||||
{
|
{
|
||||||
const uint8_t *p, *p_end;
|
const uint8_t *p, *p_end;
|
||||||
int len, tag;
|
int len, tag;
|
||||||
|
|
||||||
*pmsg_type = 0;
|
*pmsg_type = 0;
|
||||||
*preq_addr = NULL;
|
preq_addr->s_addr = htonl(0L);
|
||||||
|
|
||||||
p = bp->bp_vend;
|
p = bp->bp_vend;
|
||||||
p_end = p + DHCP_OPT_LEN;
|
p_end = p + DHCP_OPT_LEN;
|
||||||
|
@ -124,8 +124,9 @@ static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type,
|
||||||
*pmsg_type = p[0];
|
*pmsg_type = p[0];
|
||||||
break;
|
break;
|
||||||
case RFC2132_REQ_ADDR:
|
case RFC2132_REQ_ADDR:
|
||||||
if (len >= 4)
|
if (len >= 4) {
|
||||||
*preq_addr = (struct in_addr *)p;
|
memcpy(&(preq_addr->s_addr), p, 4);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -133,8 +134,9 @@ static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type,
|
||||||
p += len;
|
p += len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (*pmsg_type == DHCPREQUEST && !*preq_addr && bp->bp_ciaddr.s_addr) {
|
if (*pmsg_type == DHCPREQUEST && preq_addr->s_addr == htonl(0L) &&
|
||||||
*preq_addr = &bp->bp_ciaddr;
|
bp->bp_ciaddr.s_addr) {
|
||||||
|
memcpy(&(preq_addr->s_addr), &bp->bp_ciaddr, 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,15 +146,15 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
|
||||||
struct mbuf *m;
|
struct mbuf *m;
|
||||||
struct bootp_t *rbp;
|
struct bootp_t *rbp;
|
||||||
struct sockaddr_in saddr, daddr;
|
struct sockaddr_in saddr, daddr;
|
||||||
const struct in_addr *preq_addr;
|
struct in_addr preq_addr;
|
||||||
int dhcp_msg_type, val;
|
int dhcp_msg_type, val;
|
||||||
uint8_t *q;
|
uint8_t *q;
|
||||||
|
|
||||||
/* extract exact DHCP msg type */
|
/* extract exact DHCP msg type */
|
||||||
dhcp_decode(bp, &dhcp_msg_type, &preq_addr);
|
dhcp_decode(bp, &dhcp_msg_type, &preq_addr);
|
||||||
DPRINTF("bootp packet op=%d msgtype=%d", bp->bp_op, dhcp_msg_type);
|
DPRINTF("bootp packet op=%d msgtype=%d", bp->bp_op, dhcp_msg_type);
|
||||||
if (preq_addr)
|
if (preq_addr.s_addr != htonl(0L))
|
||||||
DPRINTF(" req_addr=%08x\n", ntohl(preq_addr->s_addr));
|
DPRINTF(" req_addr=%08x\n", ntohl(preq_addr.s_addr));
|
||||||
else
|
else
|
||||||
DPRINTF("\n");
|
DPRINTF("\n");
|
||||||
|
|
||||||
|
@ -175,10 +177,10 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
|
||||||
memset(rbp, 0, sizeof(struct bootp_t));
|
memset(rbp, 0, sizeof(struct bootp_t));
|
||||||
|
|
||||||
if (dhcp_msg_type == DHCPDISCOVER) {
|
if (dhcp_msg_type == DHCPDISCOVER) {
|
||||||
if (preq_addr) {
|
if (preq_addr.s_addr != htonl(0L)) {
|
||||||
bc = request_addr(slirp, preq_addr, slirp->client_ethaddr);
|
bc = request_addr(slirp, &preq_addr, slirp->client_ethaddr);
|
||||||
if (bc) {
|
if (bc) {
|
||||||
daddr.sin_addr = *preq_addr;
|
daddr.sin_addr = preq_addr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!bc) {
|
if (!bc) {
|
||||||
|
@ -190,10 +192,10 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
memcpy(bc->macaddr, slirp->client_ethaddr, 6);
|
memcpy(bc->macaddr, slirp->client_ethaddr, 6);
|
||||||
} else if (preq_addr) {
|
} else if (preq_addr.s_addr != htonl(0L)) {
|
||||||
bc = request_addr(slirp, preq_addr, slirp->client_ethaddr);
|
bc = request_addr(slirp, &preq_addr, slirp->client_ethaddr);
|
||||||
if (bc) {
|
if (bc) {
|
||||||
daddr.sin_addr = *preq_addr;
|
daddr.sin_addr = preq_addr;
|
||||||
memcpy(bc->macaddr, slirp->client_ethaddr, 6);
|
memcpy(bc->macaddr, slirp->client_ethaddr, 6);
|
||||||
} else {
|
} else {
|
||||||
daddr.sin_addr.s_addr = 0;
|
daddr.sin_addr.s_addr = 0;
|
||||||
|
|
3
sysemu.h
3
sysemu.h
|
@ -104,7 +104,7 @@ extern int incoming_expected;
|
||||||
extern int bios_size;
|
extern int bios_size;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
VGA_NONE, VGA_STD, VGA_CIRRUS, VGA_VMWARE, VGA_XENFB
|
VGA_NONE, VGA_STD, VGA_CIRRUS, VGA_VMWARE, VGA_XENFB, VGA_QXL,
|
||||||
} VGAInterfaceType;
|
} VGAInterfaceType;
|
||||||
|
|
||||||
extern int vga_interface_type;
|
extern int vga_interface_type;
|
||||||
|
@ -112,6 +112,7 @@ extern int vga_interface_type;
|
||||||
#define std_vga_enabled (vga_interface_type == VGA_STD)
|
#define std_vga_enabled (vga_interface_type == VGA_STD)
|
||||||
#define xenfb_enabled (vga_interface_type == VGA_XENFB)
|
#define xenfb_enabled (vga_interface_type == VGA_XENFB)
|
||||||
#define vmsvga_enabled (vga_interface_type == VGA_VMWARE)
|
#define vmsvga_enabled (vga_interface_type == VGA_VMWARE)
|
||||||
|
#define qxl_enabled (vga_interface_type == VGA_QXL)
|
||||||
|
|
||||||
extern int graphic_width;
|
extern int graphic_width;
|
||||||
extern int graphic_height;
|
extern int graphic_height;
|
||||||
|
|
|
@ -904,7 +904,7 @@ uint64_t helper_cmptun (uint64_t a, uint64_t b)
|
||||||
fa = t_to_float64(a);
|
fa = t_to_float64(a);
|
||||||
fb = t_to_float64(b);
|
fb = t_to_float64(b);
|
||||||
|
|
||||||
if (float64_is_nan(fa) || float64_is_nan(fb))
|
if (float64_is_quiet_nan(fa) || float64_is_quiet_nan(fb))
|
||||||
return 0x4000000000000000ULL;
|
return 0x4000000000000000ULL;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -76,6 +76,7 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
|
||||||
memcpy(env->cp15.c0_c1, arm1136_cp15_c0_c1, 8 * sizeof(uint32_t));
|
memcpy(env->cp15.c0_c1, arm1136_cp15_c0_c1, 8 * sizeof(uint32_t));
|
||||||
memcpy(env->cp15.c0_c2, arm1136_cp15_c0_c2, 8 * sizeof(uint32_t));
|
memcpy(env->cp15.c0_c2, arm1136_cp15_c0_c2, 8 * sizeof(uint32_t));
|
||||||
env->cp15.c0_cachetype = 0x1dd20d2;
|
env->cp15.c0_cachetype = 0x1dd20d2;
|
||||||
|
env->cp15.c1_sys = 0x00050078;
|
||||||
break;
|
break;
|
||||||
case ARM_CPUID_ARM11MPCORE:
|
case ARM_CPUID_ARM11MPCORE:
|
||||||
set_feature(env, ARM_FEATURE_V6);
|
set_feature(env, ARM_FEATURE_V6);
|
||||||
|
@ -109,6 +110,7 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
|
||||||
env->cp15.c0_ccsid[0] = 0xe007e01a; /* 16k L1 dcache. */
|
env->cp15.c0_ccsid[0] = 0xe007e01a; /* 16k L1 dcache. */
|
||||||
env->cp15.c0_ccsid[1] = 0x2007e01a; /* 16k L1 icache. */
|
env->cp15.c0_ccsid[1] = 0x2007e01a; /* 16k L1 icache. */
|
||||||
env->cp15.c0_ccsid[2] = 0xf0000000; /* No L2 icache. */
|
env->cp15.c0_ccsid[2] = 0xf0000000; /* No L2 icache. */
|
||||||
|
env->cp15.c1_sys = 0x00c50078;
|
||||||
break;
|
break;
|
||||||
case ARM_CPUID_CORTEXA9:
|
case ARM_CPUID_CORTEXA9:
|
||||||
set_feature(env, ARM_FEATURE_V6);
|
set_feature(env, ARM_FEATURE_V6);
|
||||||
|
@ -130,6 +132,7 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
|
||||||
env->cp15.c0_clid = (1 << 27) | (1 << 24) | 3;
|
env->cp15.c0_clid = (1 << 27) | (1 << 24) | 3;
|
||||||
env->cp15.c0_ccsid[0] = 0xe00fe015; /* 16k L1 dcache. */
|
env->cp15.c0_ccsid[0] = 0xe00fe015; /* 16k L1 dcache. */
|
||||||
env->cp15.c0_ccsid[1] = 0x200fe015; /* 16k L1 icache. */
|
env->cp15.c0_ccsid[1] = 0x200fe015; /* 16k L1 icache. */
|
||||||
|
env->cp15.c1_sys = 0x00c50078;
|
||||||
break;
|
break;
|
||||||
case ARM_CPUID_CORTEXM3:
|
case ARM_CPUID_CORTEXM3:
|
||||||
set_feature(env, ARM_FEATURE_V6);
|
set_feature(env, ARM_FEATURE_V6);
|
||||||
|
@ -1084,22 +1087,26 @@ static int get_phys_addr_v6(CPUState *env, uint32_t address, int access_type,
|
||||||
}
|
}
|
||||||
code = 15;
|
code = 15;
|
||||||
}
|
}
|
||||||
if (xn && access_type == 2)
|
if (domain == 3) {
|
||||||
goto do_fault;
|
*prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
|
||||||
|
} else {
|
||||||
|
if (xn && access_type == 2)
|
||||||
|
goto do_fault;
|
||||||
|
|
||||||
/* The simplified model uses AP[0] as an access control bit. */
|
/* The simplified model uses AP[0] as an access control bit. */
|
||||||
if ((env->cp15.c1_sys & (1 << 29)) && (ap & 1) == 0) {
|
if ((env->cp15.c1_sys & (1 << 29)) && (ap & 1) == 0) {
|
||||||
/* Access flag fault. */
|
/* Access flag fault. */
|
||||||
code = (code == 15) ? 6 : 3;
|
code = (code == 15) ? 6 : 3;
|
||||||
goto do_fault;
|
goto do_fault;
|
||||||
}
|
}
|
||||||
*prot = check_ap(env, ap, domain, access_type, is_user);
|
*prot = check_ap(env, ap, domain, access_type, is_user);
|
||||||
if (!*prot) {
|
if (!*prot) {
|
||||||
/* Access permission fault. */
|
/* Access permission fault. */
|
||||||
goto do_fault;
|
goto do_fault;
|
||||||
}
|
}
|
||||||
if (!xn) {
|
if (!xn) {
|
||||||
*prot |= PAGE_EXEC;
|
*prot |= PAGE_EXEC;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*phys_ptr = phys_addr;
|
*phys_ptr = phys_addr;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2235,6 +2242,8 @@ static inline int vfp_exceptbits_from_host(int host_bits)
|
||||||
target_bits |= 8;
|
target_bits |= 8;
|
||||||
if (host_bits & float_flag_inexact)
|
if (host_bits & float_flag_inexact)
|
||||||
target_bits |= 0x10;
|
target_bits |= 0x10;
|
||||||
|
if (host_bits & float_flag_input_denormal)
|
||||||
|
target_bits |= 0x80;
|
||||||
return target_bits;
|
return target_bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2271,6 +2280,8 @@ static inline int vfp_exceptbits_to_host(int target_bits)
|
||||||
host_bits |= float_flag_underflow;
|
host_bits |= float_flag_underflow;
|
||||||
if (target_bits & 0x10)
|
if (target_bits & 0x10)
|
||||||
host_bits |= float_flag_inexact;
|
host_bits |= float_flag_inexact;
|
||||||
|
if (target_bits & 0x80)
|
||||||
|
host_bits |= float_flag_input_denormal;
|
||||||
return host_bits;
|
return host_bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2303,12 +2314,14 @@ void HELPER(vfp_set_fpscr)(CPUState *env, uint32_t val)
|
||||||
}
|
}
|
||||||
set_float_rounding_mode(i, &env->vfp.fp_status);
|
set_float_rounding_mode(i, &env->vfp.fp_status);
|
||||||
}
|
}
|
||||||
if (changed & (1 << 24))
|
if (changed & (1 << 24)) {
|
||||||
set_flush_to_zero((val & (1 << 24)) != 0, &env->vfp.fp_status);
|
set_flush_to_zero((val & (1 << 24)) != 0, &env->vfp.fp_status);
|
||||||
|
set_flush_inputs_to_zero((val & (1 << 24)) != 0, &env->vfp.fp_status);
|
||||||
|
}
|
||||||
if (changed & (1 << 25))
|
if (changed & (1 << 25))
|
||||||
set_default_nan_mode((val & (1 << 25)) != 0, &env->vfp.fp_status);
|
set_default_nan_mode((val & (1 << 25)) != 0, &env->vfp.fp_status);
|
||||||
|
|
||||||
i = vfp_exceptbits_to_host((val >> 8) & 0x1f);
|
i = vfp_exceptbits_to_host(val);
|
||||||
set_float_exception_flags(i, &env->vfp.fp_status);
|
set_float_exception_flags(i, &env->vfp.fp_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -560,8 +560,6 @@ uint64_t HELPER(neon_qshl_u64)(CPUState *env, uint64_t val, uint64_t shiftop)
|
||||||
if (val) {
|
if (val) {
|
||||||
val = ~(uint64_t)0;
|
val = ~(uint64_t)0;
|
||||||
SET_QC();
|
SET_QC();
|
||||||
} else {
|
|
||||||
val = 0;
|
|
||||||
}
|
}
|
||||||
} else if (shift <= -64) {
|
} else if (shift <= -64) {
|
||||||
val = 0;
|
val = 0;
|
||||||
|
@ -582,9 +580,15 @@ uint64_t HELPER(neon_qshl_u64)(CPUState *env, uint64_t val, uint64_t shiftop)
|
||||||
int8_t tmp; \
|
int8_t tmp; \
|
||||||
tmp = (int8_t)src2; \
|
tmp = (int8_t)src2; \
|
||||||
if (tmp >= (ssize_t)sizeof(src1) * 8) { \
|
if (tmp >= (ssize_t)sizeof(src1) * 8) { \
|
||||||
if (src1) \
|
if (src1) { \
|
||||||
SET_QC(); \
|
SET_QC(); \
|
||||||
dest = src1 >> 31; \
|
dest = (uint32_t)(1 << (sizeof(src1) * 8 - 1)); \
|
||||||
|
if (src1 > 0) { \
|
||||||
|
dest--; \
|
||||||
|
} \
|
||||||
|
} else { \
|
||||||
|
dest = src1; \
|
||||||
|
} \
|
||||||
} else if (tmp <= -(ssize_t)sizeof(src1) * 8) { \
|
} else if (tmp <= -(ssize_t)sizeof(src1) * 8) { \
|
||||||
dest = src1 >> 31; \
|
dest = src1 >> 31; \
|
||||||
} else if (tmp < 0) { \
|
} else if (tmp < 0) { \
|
||||||
|
@ -593,7 +597,10 @@ uint64_t HELPER(neon_qshl_u64)(CPUState *env, uint64_t val, uint64_t shiftop)
|
||||||
dest = src1 << tmp; \
|
dest = src1 << tmp; \
|
||||||
if ((dest >> tmp) != src1) { \
|
if ((dest >> tmp) != src1) { \
|
||||||
SET_QC(); \
|
SET_QC(); \
|
||||||
dest = src2 >> 31; \
|
dest = (uint32_t)(1 << (sizeof(src1) * 8 - 1)); \
|
||||||
|
if (src1 > 0) { \
|
||||||
|
dest--; \
|
||||||
|
} \
|
||||||
} \
|
} \
|
||||||
}} while (0)
|
}} while (0)
|
||||||
NEON_VOP_ENV(qshl_s8, neon_s8, 4)
|
NEON_VOP_ENV(qshl_s8, neon_s8, 4)
|
||||||
|
@ -608,9 +615,9 @@ uint64_t HELPER(neon_qshl_s64)(CPUState *env, uint64_t valop, uint64_t shiftop)
|
||||||
if (shift >= 64) {
|
if (shift >= 64) {
|
||||||
if (val) {
|
if (val) {
|
||||||
SET_QC();
|
SET_QC();
|
||||||
val = (val >> 63) & ~SIGNBIT64;
|
val = (val >> 63) ^ ~SIGNBIT64;
|
||||||
}
|
}
|
||||||
} else if (shift <= 64) {
|
} else if (shift <= -64) {
|
||||||
val >>= 63;
|
val >>= 63;
|
||||||
} else if (shift < 0) {
|
} else if (shift < 0) {
|
||||||
val >>= -shift;
|
val >>= -shift;
|
||||||
|
|
|
@ -250,13 +250,9 @@ static void gen_rev16(TCGv var)
|
||||||
/* Byteswap low halfword and sign extend. */
|
/* Byteswap low halfword and sign extend. */
|
||||||
static void gen_revsh(TCGv var)
|
static void gen_revsh(TCGv var)
|
||||||
{
|
{
|
||||||
TCGv tmp = new_tmp();
|
tcg_gen_ext16u_i32(var, var);
|
||||||
tcg_gen_shri_i32(tmp, var, 8);
|
tcg_gen_bswap16_i32(var, var);
|
||||||
tcg_gen_andi_i32(tmp, tmp, 0x00ff);
|
tcg_gen_ext16s_i32(var, var);
|
||||||
tcg_gen_shli_i32(var, var, 8);
|
|
||||||
tcg_gen_ext8s_i32(var, var);
|
|
||||||
tcg_gen_or_i32(var, var, tmp);
|
|
||||||
dead_tmp(tmp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unsigned bitfield extract. */
|
/* Unsigned bitfield extract. */
|
||||||
|
@ -291,11 +287,32 @@ static void gen_bfi(TCGv dest, TCGv base, TCGv val, int shift, uint32_t mask)
|
||||||
tcg_gen_or_i32(dest, base, val);
|
tcg_gen_or_i32(dest, base, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Round the top 32 bits of a 64-bit value. */
|
/* Return (b << 32) + a. Mark inputs as dead */
|
||||||
static void gen_roundqd(TCGv a, TCGv b)
|
static TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv b)
|
||||||
{
|
{
|
||||||
tcg_gen_shri_i32(a, a, 31);
|
TCGv_i64 tmp64 = tcg_temp_new_i64();
|
||||||
tcg_gen_add_i32(a, a, b);
|
|
||||||
|
tcg_gen_extu_i32_i64(tmp64, b);
|
||||||
|
dead_tmp(b);
|
||||||
|
tcg_gen_shli_i64(tmp64, tmp64, 32);
|
||||||
|
tcg_gen_add_i64(a, tmp64, a);
|
||||||
|
|
||||||
|
tcg_temp_free_i64(tmp64);
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return (b << 32) - a. Mark inputs as dead. */
|
||||||
|
static TCGv_i64 gen_subq_msw(TCGv_i64 a, TCGv b)
|
||||||
|
{
|
||||||
|
TCGv_i64 tmp64 = tcg_temp_new_i64();
|
||||||
|
|
||||||
|
tcg_gen_extu_i32_i64(tmp64, b);
|
||||||
|
dead_tmp(b);
|
||||||
|
tcg_gen_shli_i64(tmp64, tmp64, 32);
|
||||||
|
tcg_gen_sub_i64(a, tmp64, a);
|
||||||
|
|
||||||
|
tcg_temp_free_i64(tmp64);
|
||||||
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: Most targets have native widening multiplication.
|
/* FIXME: Most targets have native widening multiplication.
|
||||||
|
@ -329,22 +346,6 @@ static TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b)
|
||||||
return tmp1;
|
return tmp1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Signed 32x32->64 multiply. */
|
|
||||||
static void gen_imull(TCGv a, TCGv b)
|
|
||||||
{
|
|
||||||
TCGv_i64 tmp1 = tcg_temp_new_i64();
|
|
||||||
TCGv_i64 tmp2 = tcg_temp_new_i64();
|
|
||||||
|
|
||||||
tcg_gen_ext_i32_i64(tmp1, a);
|
|
||||||
tcg_gen_ext_i32_i64(tmp2, b);
|
|
||||||
tcg_gen_mul_i64(tmp1, tmp1, tmp2);
|
|
||||||
tcg_temp_free_i64(tmp2);
|
|
||||||
tcg_gen_trunc_i64_i32(a, tmp1);
|
|
||||||
tcg_gen_shri_i64(tmp1, tmp1, 32);
|
|
||||||
tcg_gen_trunc_i64_i32(b, tmp1);
|
|
||||||
tcg_temp_free_i64(tmp1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Swap low and high halfwords. */
|
/* Swap low and high halfwords. */
|
||||||
static void gen_swap_half(TCGv var)
|
static void gen_swap_half(TCGv var)
|
||||||
{
|
{
|
||||||
|
@ -4240,9 +4241,9 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
|
||||||
case 9: /* VQSHL */
|
case 9: /* VQSHL */
|
||||||
if (u) {
|
if (u) {
|
||||||
gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
|
gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
|
||||||
cpu_V0, cpu_V0);
|
cpu_V1, cpu_V0);
|
||||||
} else {
|
} else {
|
||||||
gen_helper_neon_qshl_s64(cpu_V1, cpu_env,
|
gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
|
||||||
cpu_V1, cpu_V0);
|
cpu_V1, cpu_V0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -6641,26 +6642,38 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
|
||||||
gen_logic_CC(tmp);
|
gen_logic_CC(tmp);
|
||||||
store_reg(s, rd, tmp);
|
store_reg(s, rd, tmp);
|
||||||
break;
|
break;
|
||||||
default:
|
case 4:
|
||||||
/* 64 bit mul */
|
/* 64 bit mul double accumulate (UMAAL) */
|
||||||
|
ARCH(6);
|
||||||
tmp = load_reg(s, rs);
|
tmp = load_reg(s, rs);
|
||||||
tmp2 = load_reg(s, rm);
|
tmp2 = load_reg(s, rm);
|
||||||
if (insn & (1 << 22))
|
tmp64 = gen_mulu_i64_i32(tmp, tmp2);
|
||||||
tmp64 = gen_muls_i64_i32(tmp, tmp2);
|
gen_addq_lo(s, tmp64, rn);
|
||||||
else
|
gen_addq_lo(s, tmp64, rd);
|
||||||
tmp64 = gen_mulu_i64_i32(tmp, tmp2);
|
|
||||||
if (insn & (1 << 21)) /* mult accumulate */
|
|
||||||
gen_addq(s, tmp64, rn, rd);
|
|
||||||
if (!(insn & (1 << 23))) { /* double accumulate */
|
|
||||||
ARCH(6);
|
|
||||||
gen_addq_lo(s, tmp64, rn);
|
|
||||||
gen_addq_lo(s, tmp64, rd);
|
|
||||||
}
|
|
||||||
if (insn & (1 << 20))
|
|
||||||
gen_logicq_cc(tmp64);
|
|
||||||
gen_storeq_reg(s, rn, rd, tmp64);
|
gen_storeq_reg(s, rn, rd, tmp64);
|
||||||
tcg_temp_free_i64(tmp64);
|
tcg_temp_free_i64(tmp64);
|
||||||
break;
|
break;
|
||||||
|
case 8: case 9: case 10: case 11:
|
||||||
|
case 12: case 13: case 14: case 15:
|
||||||
|
/* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
|
||||||
|
tmp = load_reg(s, rs);
|
||||||
|
tmp2 = load_reg(s, rm);
|
||||||
|
if (insn & (1 << 22)) {
|
||||||
|
tmp64 = gen_muls_i64_i32(tmp, tmp2);
|
||||||
|
} else {
|
||||||
|
tmp64 = gen_mulu_i64_i32(tmp, tmp2);
|
||||||
|
}
|
||||||
|
if (insn & (1 << 21)) { /* mult accumulate */
|
||||||
|
gen_addq(s, tmp64, rn, rd);
|
||||||
|
}
|
||||||
|
if (insn & (1 << 20)) {
|
||||||
|
gen_logicq_cc(tmp64);
|
||||||
|
}
|
||||||
|
gen_storeq_reg(s, rn, rd, tmp64);
|
||||||
|
tcg_temp_free_i64(tmp64);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto illegal_op;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rn = (insn >> 16) & 0xf;
|
rn = (insn >> 16) & 0xf;
|
||||||
|
@ -6945,23 +6958,25 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
|
||||||
tmp = load_reg(s, rm);
|
tmp = load_reg(s, rm);
|
||||||
tmp2 = load_reg(s, rs);
|
tmp2 = load_reg(s, rs);
|
||||||
if (insn & (1 << 20)) {
|
if (insn & (1 << 20)) {
|
||||||
/* Signed multiply most significant [accumulate]. */
|
/* Signed multiply most significant [accumulate].
|
||||||
|
(SMMUL, SMMLA, SMMLS) */
|
||||||
tmp64 = gen_muls_i64_i32(tmp, tmp2);
|
tmp64 = gen_muls_i64_i32(tmp, tmp2);
|
||||||
if (insn & (1 << 5))
|
|
||||||
|
if (rd != 15) {
|
||||||
|
tmp = load_reg(s, rd);
|
||||||
|
if (insn & (1 << 6)) {
|
||||||
|
tmp64 = gen_subq_msw(tmp64, tmp);
|
||||||
|
} else {
|
||||||
|
tmp64 = gen_addq_msw(tmp64, tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (insn & (1 << 5)) {
|
||||||
tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
|
tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
|
||||||
|
}
|
||||||
tcg_gen_shri_i64(tmp64, tmp64, 32);
|
tcg_gen_shri_i64(tmp64, tmp64, 32);
|
||||||
tmp = new_tmp();
|
tmp = new_tmp();
|
||||||
tcg_gen_trunc_i64_i32(tmp, tmp64);
|
tcg_gen_trunc_i64_i32(tmp, tmp64);
|
||||||
tcg_temp_free_i64(tmp64);
|
tcg_temp_free_i64(tmp64);
|
||||||
if (rd != 15) {
|
|
||||||
tmp2 = load_reg(s, rd);
|
|
||||||
if (insn & (1 << 6)) {
|
|
||||||
tcg_gen_sub_i32(tmp, tmp, tmp2);
|
|
||||||
} else {
|
|
||||||
tcg_gen_add_i32(tmp, tmp, tmp2);
|
|
||||||
}
|
|
||||||
dead_tmp(tmp2);
|
|
||||||
}
|
|
||||||
store_reg(s, rn, tmp);
|
store_reg(s, rn, tmp);
|
||||||
} else {
|
} else {
|
||||||
if (insn & (1 << 5))
|
if (insn & (1 << 5))
|
||||||
|
@ -7832,24 +7847,23 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
|
||||||
dead_tmp(tmp2);
|
dead_tmp(tmp2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 5: case 6: /* 32 * 32 -> 32msb */
|
case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
|
||||||
gen_imull(tmp, tmp2);
|
tmp64 = gen_muls_i64_i32(tmp, tmp2);
|
||||||
if (insn & (1 << 5)) {
|
|
||||||
gen_roundqd(tmp, tmp2);
|
|
||||||
dead_tmp(tmp2);
|
|
||||||
} else {
|
|
||||||
dead_tmp(tmp);
|
|
||||||
tmp = tmp2;
|
|
||||||
}
|
|
||||||
if (rs != 15) {
|
if (rs != 15) {
|
||||||
tmp2 = load_reg(s, rs);
|
tmp = load_reg(s, rs);
|
||||||
if (insn & (1 << 21)) {
|
if (insn & (1 << 20)) {
|
||||||
tcg_gen_add_i32(tmp, tmp, tmp2);
|
tmp64 = gen_addq_msw(tmp64, tmp);
|
||||||
} else {
|
} else {
|
||||||
tcg_gen_sub_i32(tmp, tmp2, tmp);
|
tmp64 = gen_subq_msw(tmp64, tmp);
|
||||||
}
|
}
|
||||||
dead_tmp(tmp2);
|
|
||||||
}
|
}
|
||||||
|
if (insn & (1 << 4)) {
|
||||||
|
tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
|
||||||
|
}
|
||||||
|
tcg_gen_shri_i64(tmp64, tmp64, 32);
|
||||||
|
tmp = new_tmp();
|
||||||
|
tcg_gen_trunc_i64_i32(tmp, tmp64);
|
||||||
|
tcg_temp_free_i64(tmp64);
|
||||||
break;
|
break;
|
||||||
case 7: /* Unsigned sum of absolute differences. */
|
case 7: /* Unsigned sum of absolute differences. */
|
||||||
gen_helper_usad8(tmp, tmp, tmp2);
|
gen_helper_usad8(tmp, tmp, tmp2);
|
||||||
|
|
|
@ -577,20 +577,15 @@ static inline void t_gen_swapr(TCGv d, TCGv s)
|
||||||
|
|
||||||
static void t_gen_cc_jmp(TCGv pc_true, TCGv pc_false)
|
static void t_gen_cc_jmp(TCGv pc_true, TCGv pc_false)
|
||||||
{
|
{
|
||||||
TCGv btaken;
|
|
||||||
int l1;
|
int l1;
|
||||||
|
|
||||||
l1 = gen_new_label();
|
l1 = gen_new_label();
|
||||||
btaken = tcg_temp_new();
|
|
||||||
|
|
||||||
/* Conditional jmp. */
|
/* Conditional jmp. */
|
||||||
tcg_gen_mov_tl(btaken, env_btaken);
|
|
||||||
tcg_gen_mov_tl(env_pc, pc_false);
|
tcg_gen_mov_tl(env_pc, pc_false);
|
||||||
tcg_gen_brcondi_tl(TCG_COND_EQ, btaken, 0, l1);
|
tcg_gen_brcondi_tl(TCG_COND_EQ, env_btaken, 0, l1);
|
||||||
tcg_gen_mov_tl(env_pc, pc_true);
|
tcg_gen_mov_tl(env_pc, pc_true);
|
||||||
gen_set_label(l1);
|
gen_set_label(l1);
|
||||||
|
|
||||||
tcg_temp_free(btaken);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
|
static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
|
||||||
|
@ -1134,7 +1129,7 @@ static void cris_store_direct_jmp(DisasContext *dc)
|
||||||
/* Store the direct jmp state into the cpu-state. */
|
/* Store the direct jmp state into the cpu-state. */
|
||||||
if (dc->jmp == JMP_DIRECT) {
|
if (dc->jmp == JMP_DIRECT) {
|
||||||
tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
|
tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
|
||||||
tcg_gen_movi_tl(env_btaken, 1);
|
dc->jmp = JMP_INDIRECT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1144,17 +1139,11 @@ static void cris_prepare_cc_branch (DisasContext *dc,
|
||||||
/* This helps us re-schedule the micro-code to insns in delay-slots
|
/* This helps us re-schedule the micro-code to insns in delay-slots
|
||||||
before the actual jump. */
|
before the actual jump. */
|
||||||
dc->delayed_branch = 2;
|
dc->delayed_branch = 2;
|
||||||
|
dc->jmp = JMP_DIRECT;
|
||||||
dc->jmp_pc = dc->pc + offset;
|
dc->jmp_pc = dc->pc + offset;
|
||||||
|
|
||||||
if (cond != CC_A)
|
gen_tst_cc (dc, env_btaken, cond);
|
||||||
{
|
tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
|
||||||
dc->jmp = JMP_INDIRECT;
|
|
||||||
gen_tst_cc (dc, env_btaken, cond);
|
|
||||||
tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
|
|
||||||
} else {
|
|
||||||
/* Allow chaining. */
|
|
||||||
dc->jmp = JMP_DIRECT;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1166,8 +1155,7 @@ static inline void cris_prepare_jmp (DisasContext *dc, unsigned int type)
|
||||||
before the actual jump. */
|
before the actual jump. */
|
||||||
dc->delayed_branch = 2;
|
dc->delayed_branch = 2;
|
||||||
dc->jmp = type;
|
dc->jmp = type;
|
||||||
if (type == JMP_INDIRECT)
|
tcg_gen_movi_tl(env_btaken, 1);
|
||||||
tcg_gen_movi_tl(env_btaken, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_load64(DisasContext *dc, TCGv_i64 dst, TCGv addr)
|
static void gen_load64(DisasContext *dc, TCGv_i64 dst, TCGv addr)
|
||||||
|
@ -3320,8 +3308,24 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
|
||||||
if (tb->flags & 7)
|
if (tb->flags & 7)
|
||||||
t_gen_mov_env_TN(dslot,
|
t_gen_mov_env_TN(dslot,
|
||||||
tcg_const_tl(0));
|
tcg_const_tl(0));
|
||||||
|
if (dc->cpustate_changed || !dc->flagx_known
|
||||||
|
|| (dc->flags_x != (tb->flags & X_FLAG))) {
|
||||||
|
cris_store_direct_jmp(dc);
|
||||||
|
}
|
||||||
if (dc->jmp == JMP_DIRECT) {
|
if (dc->jmp == JMP_DIRECT) {
|
||||||
dc->is_jmp = DISAS_NEXT;
|
int l1;
|
||||||
|
|
||||||
|
l1 = gen_new_label();
|
||||||
|
cris_evaluate_flags(dc);
|
||||||
|
|
||||||
|
/* Conditional jmp. */
|
||||||
|
tcg_gen_brcondi_tl(TCG_COND_EQ,
|
||||||
|
env_btaken, 0, l1);
|
||||||
|
gen_goto_tb(dc, 1, dc->jmp_pc);
|
||||||
|
gen_set_label(l1);
|
||||||
|
gen_goto_tb(dc, 0, dc->pc);
|
||||||
|
dc->is_jmp = DISAS_TB_JUMP;
|
||||||
|
dc->jmp = JMP_NOJMP;
|
||||||
} else {
|
} else {
|
||||||
t_gen_cc_jmp(env_btarget,
|
t_gen_cc_jmp(env_btarget,
|
||||||
tcg_const_tl(dc->pc));
|
tcg_const_tl(dc->pc));
|
||||||
|
@ -3341,16 +3345,10 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
|
||||||
&& (dc->pc < next_page_start)
|
&& (dc->pc < next_page_start)
|
||||||
&& num_insns < max_insns);
|
&& num_insns < max_insns);
|
||||||
|
|
||||||
if (dc->tb_flags != orig_flags) {
|
|
||||||
dc->cpustate_changed = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dc->clear_locked_irq)
|
if (dc->clear_locked_irq)
|
||||||
t_gen_mov_env_TN(locked_irq, tcg_const_tl(0));
|
t_gen_mov_env_TN(locked_irq, tcg_const_tl(0));
|
||||||
|
|
||||||
npc = dc->pc;
|
npc = dc->pc;
|
||||||
if (dc->jmp == JMP_DIRECT && !dc->delayed_branch)
|
|
||||||
npc = dc->jmp_pc;
|
|
||||||
|
|
||||||
if (tb->cflags & CF_LAST_IO)
|
if (tb->cflags & CF_LAST_IO)
|
||||||
gen_io_end();
|
gen_io_end();
|
||||||
|
|
|
@ -737,10 +737,10 @@ typedef struct CPUX86State {
|
||||||
user */
|
user */
|
||||||
struct DeviceState *apic_state;
|
struct DeviceState *apic_state;
|
||||||
|
|
||||||
uint64 mcg_cap;
|
uint64_t mcg_cap;
|
||||||
uint64 mcg_status;
|
uint64_t mcg_status;
|
||||||
uint64 mcg_ctl;
|
uint64_t mcg_ctl;
|
||||||
uint64 mce_banks[MCE_BANKS_DEF*4];
|
uint64_t mce_banks[MCE_BANKS_DEF*4];
|
||||||
|
|
||||||
uint64_t tsc_aux;
|
uint64_t tsc_aux;
|
||||||
|
|
||||||
|
|
|
@ -175,12 +175,12 @@ cpu_x86_dump_seg_cache(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
|
||||||
#ifdef TARGET_X86_64
|
#ifdef TARGET_X86_64
|
||||||
if (env->hflags & HF_CS64_MASK) {
|
if (env->hflags & HF_CS64_MASK) {
|
||||||
cpu_fprintf(f, "%-3s=%04x %016" PRIx64 " %08x %08x", name,
|
cpu_fprintf(f, "%-3s=%04x %016" PRIx64 " %08x %08x", name,
|
||||||
sc->selector, sc->base, sc->limit, sc->flags);
|
sc->selector, sc->base, sc->limit, sc->flags & 0x00ffff00);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
cpu_fprintf(f, "%-3s=%04x %08x %08x %08x", name, sc->selector,
|
cpu_fprintf(f, "%-3s=%04x %08x %08x %08x", name, sc->selector,
|
||||||
(uint32_t)sc->base, sc->limit, sc->flags);
|
(uint32_t)sc->base, sc->limit, sc->flags & 0x00ffff00);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(env->hflags & HF_PE_MASK) || !(sc->flags & DESC_P_MASK))
|
if (!(env->hflags & HF_PE_MASK) || !(sc->flags & DESC_P_MASK))
|
||||||
|
|
|
@ -614,10 +614,10 @@ float64 HELPER(sub_cmp_f64)(CPUState *env, float64 a, float64 b)
|
||||||
/* ??? Should flush denormals to zero. */
|
/* ??? Should flush denormals to zero. */
|
||||||
float64 res;
|
float64 res;
|
||||||
res = float64_sub(a, b, &env->fp_status);
|
res = float64_sub(a, b, &env->fp_status);
|
||||||
if (float64_is_nan(res)) {
|
if (float64_is_quiet_nan(res)) {
|
||||||
/* +/-inf compares equal against itself, but sub returns nan. */
|
/* +/-inf compares equal against itself, but sub returns nan. */
|
||||||
if (!float64_is_nan(a)
|
if (!float64_is_quiet_nan(a)
|
||||||
&& !float64_is_nan(b)) {
|
&& !float64_is_quiet_nan(b)) {
|
||||||
res = float64_zero;
|
res = float64_zero;
|
||||||
if (float64_lt_quiet(a, res, &env->fp_status))
|
if (float64_lt_quiet(a, res, &env->fp_status))
|
||||||
res = float64_chs(res);
|
res = float64_chs(res);
|
||||||
|
|
|
@ -308,7 +308,7 @@ uint32_t helper_fcmp_un(uint32_t a, uint32_t b)
|
||||||
r = 1;
|
r = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (float32_is_nan(fa.f) || float32_is_nan(fb.f)) {
|
if (float32_is_quiet_nan(fa.f) || float32_is_quiet_nan(fb.f)) {
|
||||||
r = 1;
|
r = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -752,9 +752,8 @@ static void dec_bit(DisasContext *dc)
|
||||||
static inline void sync_jmpstate(DisasContext *dc)
|
static inline void sync_jmpstate(DisasContext *dc)
|
||||||
{
|
{
|
||||||
if (dc->jmp == JMP_DIRECT) {
|
if (dc->jmp == JMP_DIRECT) {
|
||||||
dc->jmp = JMP_INDIRECT;
|
dc->jmp = JMP_INDIRECT;
|
||||||
tcg_gen_movi_tl(env_btaken, 1);
|
tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
|
||||||
tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -976,11 +975,13 @@ static void dec_bcc(DisasContext *dc)
|
||||||
int32_t offset = (int32_t)((int16_t)dc->imm); /* sign-extend. */
|
int32_t offset = (int32_t)((int16_t)dc->imm); /* sign-extend. */
|
||||||
|
|
||||||
tcg_gen_movi_tl(env_btarget, dc->pc + offset);
|
tcg_gen_movi_tl(env_btarget, dc->pc + offset);
|
||||||
|
dc->jmp = JMP_DIRECT;
|
||||||
|
dc->jmp_pc = dc->pc + offset;
|
||||||
} else {
|
} else {
|
||||||
|
dc->jmp = JMP_INDIRECT;
|
||||||
tcg_gen_movi_tl(env_btarget, dc->pc);
|
tcg_gen_movi_tl(env_btarget, dc->pc);
|
||||||
tcg_gen_add_tl(env_btarget, env_btarget, *(dec_alu_op_b(dc)));
|
tcg_gen_add_tl(env_btarget, env_btarget, *(dec_alu_op_b(dc)));
|
||||||
}
|
}
|
||||||
dc->jmp = JMP_INDIRECT;
|
|
||||||
eval_cc(dc, cc, env_btaken, cpu_R[dc->ra], tcg_const_tl(0));
|
eval_cc(dc, cc, env_btaken, cpu_R[dc->ra], tcg_const_tl(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1028,6 +1029,7 @@ static void dec_br(DisasContext *dc)
|
||||||
if (dec_alu_op_b_is_small_imm(dc)) {
|
if (dec_alu_op_b_is_small_imm(dc)) {
|
||||||
dc->jmp = JMP_DIRECT;
|
dc->jmp = JMP_DIRECT;
|
||||||
dc->jmp_pc = dc->pc + (int32_t)((int16_t)dc->imm);
|
dc->jmp_pc = dc->pc + (int32_t)((int16_t)dc->imm);
|
||||||
|
tcg_gen_movi_tl(env_btaken, 1);
|
||||||
} else {
|
} else {
|
||||||
tcg_gen_movi_tl(env_btaken, 1);
|
tcg_gen_movi_tl(env_btaken, 1);
|
||||||
tcg_gen_movi_tl(env_btarget, dc->pc);
|
tcg_gen_movi_tl(env_btarget, dc->pc);
|
||||||
|
@ -1130,6 +1132,7 @@ static void dec_rts(DisasContext *dc)
|
||||||
} else
|
} else
|
||||||
LOG_DIS("rts ir=%x\n", dc->ir);
|
LOG_DIS("rts ir=%x\n", dc->ir);
|
||||||
|
|
||||||
|
dc->jmp = JMP_INDIRECT;
|
||||||
tcg_gen_movi_tl(env_btaken, 1);
|
tcg_gen_movi_tl(env_btaken, 1);
|
||||||
tcg_gen_add_tl(env_btarget, cpu_R[dc->ra], *(dec_alu_op_b(dc)));
|
tcg_gen_add_tl(env_btarget, cpu_R[dc->ra], *(dec_alu_op_b(dc)));
|
||||||
}
|
}
|
||||||
|
@ -1370,6 +1373,9 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
|
||||||
dc->is_jmp = DISAS_NEXT;
|
dc->is_jmp = DISAS_NEXT;
|
||||||
dc->jmp = 0;
|
dc->jmp = 0;
|
||||||
dc->delayed_branch = !!(dc->tb_flags & D_FLAG);
|
dc->delayed_branch = !!(dc->tb_flags & D_FLAG);
|
||||||
|
if (dc->delayed_branch) {
|
||||||
|
dc->jmp = JMP_INDIRECT;
|
||||||
|
}
|
||||||
dc->pc = pc_start;
|
dc->pc = pc_start;
|
||||||
dc->singlestep_enabled = env->singlestep_enabled;
|
dc->singlestep_enabled = env->singlestep_enabled;
|
||||||
dc->cpustate_changed = 0;
|
dc->cpustate_changed = 0;
|
||||||
|
@ -1441,9 +1447,21 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
|
||||||
/* Clear the delay slot flag. */
|
/* Clear the delay slot flag. */
|
||||||
dc->tb_flags &= ~D_FLAG;
|
dc->tb_flags &= ~D_FLAG;
|
||||||
/* If it is a direct jump, try direct chaining. */
|
/* If it is a direct jump, try direct chaining. */
|
||||||
if (dc->jmp != JMP_DIRECT) {
|
if (dc->jmp == JMP_INDIRECT) {
|
||||||
eval_cond_jmp(dc, env_btarget, tcg_const_tl(dc->pc));
|
eval_cond_jmp(dc, env_btarget, tcg_const_tl(dc->pc));
|
||||||
dc->is_jmp = DISAS_JUMP;
|
dc->is_jmp = DISAS_JUMP;
|
||||||
|
} else if (dc->jmp == JMP_DIRECT) {
|
||||||
|
int l1;
|
||||||
|
|
||||||
|
t_sync_flags(dc);
|
||||||
|
l1 = gen_new_label();
|
||||||
|
/* Conditional jmp. */
|
||||||
|
tcg_gen_brcondi_tl(TCG_COND_NE, env_btaken, 0, l1);
|
||||||
|
gen_goto_tb(dc, 1, dc->pc);
|
||||||
|
gen_set_label(l1);
|
||||||
|
gen_goto_tb(dc, 0, dc->jmp_pc);
|
||||||
|
|
||||||
|
dc->is_jmp = DISAS_TB_JUMP;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -532,6 +532,14 @@ static inline int cpu_mips_hw_interrupts_pending(CPUState *env)
|
||||||
int32_t status;
|
int32_t status;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
if (!(env->CP0_Status & (1 << CP0St_IE)) ||
|
||||||
|
(env->CP0_Status & (1 << CP0St_EXL)) ||
|
||||||
|
(env->CP0_Status & (1 << CP0St_ERL)) ||
|
||||||
|
(env->hflags & MIPS_HFLAG_DM)) {
|
||||||
|
/* Interrupts are disabled */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
pending = env->CP0_Cause & CP0Ca_IP_mask;
|
pending = env->CP0_Cause & CP0Ca_IP_mask;
|
||||||
status = env->CP0_Status & CP0Ca_IP_mask;
|
status = env->CP0_Status & CP0Ca_IP_mask;
|
||||||
|
|
||||||
|
|
|
@ -19,10 +19,22 @@ register struct CPUMIPSState *env asm(AREG0);
|
||||||
|
|
||||||
static inline int cpu_has_work(CPUState *env)
|
static inline int cpu_has_work(CPUState *env)
|
||||||
{
|
{
|
||||||
return (env->interrupt_request &
|
int has_work = 0;
|
||||||
(CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* It is implementation dependent if non-enabled interrupts
|
||||||
|
wake-up the CPU, however most of the implementations only
|
||||||
|
check for interrupts that can be taken. */
|
||||||
|
if ((env->interrupt_request & CPU_INTERRUPT_HARD) &&
|
||||||
|
cpu_mips_hw_interrupts_pending(env)) {
|
||||||
|
has_work = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (env->interrupt_request & CPU_INTERRUPT_TIMER) {
|
||||||
|
has_work = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return has_work;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int cpu_halted(CPUState *env)
|
static inline int cpu_halted(CPUState *env)
|
||||||
{
|
{
|
||||||
|
|
|
@ -154,10 +154,10 @@ DEF_HELPER_2(mttlo, void, tl, i32)
|
||||||
DEF_HELPER_2(mtthi, void, tl, i32)
|
DEF_HELPER_2(mtthi, void, tl, i32)
|
||||||
DEF_HELPER_2(mttacx, void, tl, i32)
|
DEF_HELPER_2(mttacx, void, tl, i32)
|
||||||
DEF_HELPER_1(mttdsp, void, tl)
|
DEF_HELPER_1(mttdsp, void, tl)
|
||||||
DEF_HELPER_1(dmt, tl, tl)
|
DEF_HELPER_0(dmt, tl)
|
||||||
DEF_HELPER_1(emt, tl, tl)
|
DEF_HELPER_0(emt, tl)
|
||||||
DEF_HELPER_1(dvpe, tl, tl)
|
DEF_HELPER_0(dvpe, tl)
|
||||||
DEF_HELPER_1(evpe, tl, tl)
|
DEF_HELPER_0(evpe, tl)
|
||||||
#endif /* !CONFIG_USER_ONLY */
|
#endif /* !CONFIG_USER_ONLY */
|
||||||
|
|
||||||
/* microMIPS functions */
|
/* microMIPS functions */
|
||||||
|
|
|
@ -1554,40 +1554,28 @@ void helper_mttdsp(target_ulong arg1)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* MIPS MT functions */
|
/* MIPS MT functions */
|
||||||
target_ulong helper_dmt(target_ulong arg1)
|
target_ulong helper_dmt(void)
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
arg1 = 0;
|
return 0;
|
||||||
// rt = arg1
|
|
||||||
|
|
||||||
return arg1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
target_ulong helper_emt(target_ulong arg1)
|
target_ulong helper_emt(void)
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
arg1 = 0;
|
return 0;
|
||||||
// rt = arg1
|
|
||||||
|
|
||||||
return arg1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
target_ulong helper_dvpe(target_ulong arg1)
|
target_ulong helper_dvpe(void)
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
arg1 = 0;
|
return 0;
|
||||||
// rt = arg1
|
|
||||||
|
|
||||||
return arg1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
target_ulong helper_evpe(target_ulong arg1)
|
target_ulong helper_evpe(void)
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
arg1 = 0;
|
return 0;
|
||||||
// rt = arg1
|
|
||||||
|
|
||||||
return arg1;
|
|
||||||
}
|
}
|
||||||
#endif /* !CONFIG_USER_ONLY */
|
#endif /* !CONFIG_USER_ONLY */
|
||||||
|
|
||||||
|
@ -2889,10 +2877,10 @@ static int float64_is_unordered(int sig, float64 a, float64 b STATUS_PARAM)
|
||||||
{
|
{
|
||||||
if (float64_is_signaling_nan(a) ||
|
if (float64_is_signaling_nan(a) ||
|
||||||
float64_is_signaling_nan(b) ||
|
float64_is_signaling_nan(b) ||
|
||||||
(sig && (float64_is_nan(a) || float64_is_nan(b)))) {
|
(sig && (float64_is_quiet_nan(a) || float64_is_quiet_nan(b)))) {
|
||||||
float_raise(float_flag_invalid, status);
|
float_raise(float_flag_invalid, status);
|
||||||
return 1;
|
return 1;
|
||||||
} else if (float64_is_nan(a) || float64_is_nan(b)) {
|
} else if (float64_is_quiet_nan(a) || float64_is_quiet_nan(b)) {
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2947,10 +2935,10 @@ static flag float32_is_unordered(int sig, float32 a, float32 b STATUS_PARAM)
|
||||||
{
|
{
|
||||||
if (float32_is_signaling_nan(a) ||
|
if (float32_is_signaling_nan(a) ||
|
||||||
float32_is_signaling_nan(b) ||
|
float32_is_signaling_nan(b) ||
|
||||||
(sig && (float32_is_nan(a) || float32_is_nan(b)))) {
|
(sig && (float32_is_quiet_nan(a) || float32_is_quiet_nan(b)))) {
|
||||||
float_raise(float_flag_invalid, status);
|
float_raise(float_flag_invalid, status);
|
||||||
return 1;
|
return 1;
|
||||||
} else if (float32_is_nan(a) || float32_is_nan(b)) {
|
} else if (float32_is_quiet_nan(a) || float32_is_quiet_nan(b)) {
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -12033,22 +12033,22 @@ static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
|
||||||
switch (op2) {
|
switch (op2) {
|
||||||
case OPC_DMT:
|
case OPC_DMT:
|
||||||
check_insn(env, ctx, ASE_MT);
|
check_insn(env, ctx, ASE_MT);
|
||||||
gen_helper_dmt(t0, t0);
|
gen_helper_dmt(t0);
|
||||||
gen_store_gpr(t0, rt);
|
gen_store_gpr(t0, rt);
|
||||||
break;
|
break;
|
||||||
case OPC_EMT:
|
case OPC_EMT:
|
||||||
check_insn(env, ctx, ASE_MT);
|
check_insn(env, ctx, ASE_MT);
|
||||||
gen_helper_emt(t0, t0);
|
gen_helper_emt(t0);
|
||||||
gen_store_gpr(t0, rt);
|
gen_store_gpr(t0, rt);
|
||||||
break;
|
break;
|
||||||
case OPC_DVPE:
|
case OPC_DVPE:
|
||||||
check_insn(env, ctx, ASE_MT);
|
check_insn(env, ctx, ASE_MT);
|
||||||
gen_helper_dvpe(t0, t0);
|
gen_helper_dvpe(t0);
|
||||||
gen_store_gpr(t0, rt);
|
gen_store_gpr(t0, rt);
|
||||||
break;
|
break;
|
||||||
case OPC_EVPE:
|
case OPC_EVPE:
|
||||||
check_insn(env, ctx, ASE_MT);
|
check_insn(env, ctx, ASE_MT);
|
||||||
gen_helper_evpe(t0, t0);
|
gen_helper_evpe(t0);
|
||||||
gen_store_gpr(t0, rt);
|
gen_store_gpr(t0, rt);
|
||||||
break;
|
break;
|
||||||
case OPC_DI:
|
case OPC_DI:
|
||||||
|
|
|
@ -26,9 +26,6 @@
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "exec-all.h"
|
#include "exec-all.h"
|
||||||
|
|
||||||
/* Precise emulation is needed to correctly emulate exception flags */
|
|
||||||
#define USE_PRECISE_EMULATION 1
|
|
||||||
|
|
||||||
register struct CPUPPCState *env asm(AREG0);
|
register struct CPUPPCState *env asm(AREG0);
|
||||||
|
|
||||||
#if !defined(CONFIG_USER_ONLY)
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
|
|
|
@ -546,7 +546,7 @@ uint32_t helper_compute_fprf (uint64_t arg, uint32_t set_fprf)
|
||||||
int ret;
|
int ret;
|
||||||
farg.ll = arg;
|
farg.ll = arg;
|
||||||
isneg = float64_is_neg(farg.d);
|
isneg = float64_is_neg(farg.d);
|
||||||
if (unlikely(float64_is_nan(farg.d))) {
|
if (unlikely(float64_is_quiet_nan(farg.d))) {
|
||||||
if (float64_is_signaling_nan(farg.d)) {
|
if (float64_is_signaling_nan(farg.d)) {
|
||||||
/* Signaling NaN: flags are undefined */
|
/* Signaling NaN: flags are undefined */
|
||||||
ret = 0x00;
|
ret = 0x00;
|
||||||
|
@ -643,7 +643,7 @@ static inline uint64_t fload_invalid_op_excp(int op)
|
||||||
env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
|
env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
|
||||||
if (ve == 0) {
|
if (ve == 0) {
|
||||||
/* Set the result to quiet NaN */
|
/* Set the result to quiet NaN */
|
||||||
ret = 0xFFF8000000000000ULL;
|
ret = 0x7FF8000000000000ULL;
|
||||||
env->fpscr &= ~(0xF << FPSCR_FPCC);
|
env->fpscr &= ~(0xF << FPSCR_FPCC);
|
||||||
env->fpscr |= 0x11 << FPSCR_FPCC;
|
env->fpscr |= 0x11 << FPSCR_FPCC;
|
||||||
}
|
}
|
||||||
|
@ -654,7 +654,7 @@ static inline uint64_t fload_invalid_op_excp(int op)
|
||||||
env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
|
env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
|
||||||
if (ve == 0) {
|
if (ve == 0) {
|
||||||
/* Set the result to quiet NaN */
|
/* Set the result to quiet NaN */
|
||||||
ret = 0xFFF8000000000000ULL;
|
ret = 0x7FF8000000000000ULL;
|
||||||
env->fpscr &= ~(0xF << FPSCR_FPCC);
|
env->fpscr &= ~(0xF << FPSCR_FPCC);
|
||||||
env->fpscr |= 0x11 << FPSCR_FPCC;
|
env->fpscr |= 0x11 << FPSCR_FPCC;
|
||||||
}
|
}
|
||||||
|
@ -974,7 +974,7 @@ uint64_t helper_fadd (uint64_t arg1, uint64_t arg2)
|
||||||
|
|
||||||
farg1.ll = arg1;
|
farg1.ll = arg1;
|
||||||
farg2.ll = arg2;
|
farg2.ll = arg2;
|
||||||
#if USE_PRECISE_EMULATION
|
|
||||||
if (unlikely(float64_is_signaling_nan(farg1.d) ||
|
if (unlikely(float64_is_signaling_nan(farg1.d) ||
|
||||||
float64_is_signaling_nan(farg2.d))) {
|
float64_is_signaling_nan(farg2.d))) {
|
||||||
/* sNaN addition */
|
/* sNaN addition */
|
||||||
|
@ -986,9 +986,7 @@ uint64_t helper_fadd (uint64_t arg1, uint64_t arg2)
|
||||||
} else {
|
} else {
|
||||||
farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status);
|
farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status);
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status);
|
|
||||||
#endif
|
|
||||||
return farg1.ll;
|
return farg1.ll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -999,8 +997,7 @@ uint64_t helper_fsub (uint64_t arg1, uint64_t arg2)
|
||||||
|
|
||||||
farg1.ll = arg1;
|
farg1.ll = arg1;
|
||||||
farg2.ll = arg2;
|
farg2.ll = arg2;
|
||||||
#if USE_PRECISE_EMULATION
|
|
||||||
{
|
|
||||||
if (unlikely(float64_is_signaling_nan(farg1.d) ||
|
if (unlikely(float64_is_signaling_nan(farg1.d) ||
|
||||||
float64_is_signaling_nan(farg2.d))) {
|
float64_is_signaling_nan(farg2.d))) {
|
||||||
/* sNaN subtraction */
|
/* sNaN subtraction */
|
||||||
|
@ -1012,10 +1009,7 @@ uint64_t helper_fsub (uint64_t arg1, uint64_t arg2)
|
||||||
} else {
|
} else {
|
||||||
farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status);
|
farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#else
|
|
||||||
farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status);
|
|
||||||
#endif
|
|
||||||
return farg1.ll;
|
return farg1.ll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1026,7 +1020,7 @@ uint64_t helper_fmul (uint64_t arg1, uint64_t arg2)
|
||||||
|
|
||||||
farg1.ll = arg1;
|
farg1.ll = arg1;
|
||||||
farg2.ll = arg2;
|
farg2.ll = arg2;
|
||||||
#if USE_PRECISE_EMULATION
|
|
||||||
if (unlikely(float64_is_signaling_nan(farg1.d) ||
|
if (unlikely(float64_is_signaling_nan(farg1.d) ||
|
||||||
float64_is_signaling_nan(farg2.d))) {
|
float64_is_signaling_nan(farg2.d))) {
|
||||||
/* sNaN multiplication */
|
/* sNaN multiplication */
|
||||||
|
@ -1038,9 +1032,7 @@ uint64_t helper_fmul (uint64_t arg1, uint64_t arg2)
|
||||||
} else {
|
} else {
|
||||||
farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
|
farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
|
|
||||||
#endif
|
|
||||||
return farg1.ll;
|
return farg1.ll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1051,7 +1043,7 @@ uint64_t helper_fdiv (uint64_t arg1, uint64_t arg2)
|
||||||
|
|
||||||
farg1.ll = arg1;
|
farg1.ll = arg1;
|
||||||
farg2.ll = arg2;
|
farg2.ll = arg2;
|
||||||
#if USE_PRECISE_EMULATION
|
|
||||||
if (unlikely(float64_is_signaling_nan(farg1.d) ||
|
if (unlikely(float64_is_signaling_nan(farg1.d) ||
|
||||||
float64_is_signaling_nan(farg2.d))) {
|
float64_is_signaling_nan(farg2.d))) {
|
||||||
/* sNaN division */
|
/* sNaN division */
|
||||||
|
@ -1065,9 +1057,7 @@ uint64_t helper_fdiv (uint64_t arg1, uint64_t arg2)
|
||||||
} else {
|
} else {
|
||||||
farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status);
|
farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status);
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status);
|
|
||||||
#endif
|
|
||||||
return farg1.ll;
|
return farg1.ll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1111,17 +1101,15 @@ uint64_t helper_fctiw (uint64_t arg)
|
||||||
if (unlikely(float64_is_signaling_nan(farg.d))) {
|
if (unlikely(float64_is_signaling_nan(farg.d))) {
|
||||||
/* sNaN conversion */
|
/* sNaN conversion */
|
||||||
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
|
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
|
||||||
} else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
|
} else if (unlikely(float64_is_quiet_nan(farg.d) || float64_is_infinity(farg.d))) {
|
||||||
/* qNan / infinity conversion */
|
/* qNan / infinity conversion */
|
||||||
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
|
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
|
||||||
} else {
|
} else {
|
||||||
farg.ll = float64_to_int32(farg.d, &env->fp_status);
|
farg.ll = float64_to_int32(farg.d, &env->fp_status);
|
||||||
#if USE_PRECISE_EMULATION
|
|
||||||
/* XXX: higher bits are not supposed to be significant.
|
/* XXX: higher bits are not supposed to be significant.
|
||||||
* to make tests easier, return the same as a real PowerPC 750
|
* to make tests easier, return the same as a real PowerPC 750
|
||||||
*/
|
*/
|
||||||
farg.ll |= 0xFFF80000ULL << 32;
|
farg.ll |= 0xFFF80000ULL << 32;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return farg.ll;
|
return farg.ll;
|
||||||
}
|
}
|
||||||
|
@ -1135,17 +1123,15 @@ uint64_t helper_fctiwz (uint64_t arg)
|
||||||
if (unlikely(float64_is_signaling_nan(farg.d))) {
|
if (unlikely(float64_is_signaling_nan(farg.d))) {
|
||||||
/* sNaN conversion */
|
/* sNaN conversion */
|
||||||
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
|
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
|
||||||
} else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
|
} else if (unlikely(float64_is_quiet_nan(farg.d) || float64_is_infinity(farg.d))) {
|
||||||
/* qNan / infinity conversion */
|
/* qNan / infinity conversion */
|
||||||
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
|
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
|
||||||
} else {
|
} else {
|
||||||
farg.ll = float64_to_int32_round_to_zero(farg.d, &env->fp_status);
|
farg.ll = float64_to_int32_round_to_zero(farg.d, &env->fp_status);
|
||||||
#if USE_PRECISE_EMULATION
|
|
||||||
/* XXX: higher bits are not supposed to be significant.
|
/* XXX: higher bits are not supposed to be significant.
|
||||||
* to make tests easier, return the same as a real PowerPC 750
|
* to make tests easier, return the same as a real PowerPC 750
|
||||||
*/
|
*/
|
||||||
farg.ll |= 0xFFF80000ULL << 32;
|
farg.ll |= 0xFFF80000ULL << 32;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return farg.ll;
|
return farg.ll;
|
||||||
}
|
}
|
||||||
|
@ -1168,7 +1154,7 @@ uint64_t helper_fctid (uint64_t arg)
|
||||||
if (unlikely(float64_is_signaling_nan(farg.d))) {
|
if (unlikely(float64_is_signaling_nan(farg.d))) {
|
||||||
/* sNaN conversion */
|
/* sNaN conversion */
|
||||||
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
|
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
|
||||||
} else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
|
} else if (unlikely(float64_is_quiet_nan(farg.d) || float64_is_infinity(farg.d))) {
|
||||||
/* qNan / infinity conversion */
|
/* qNan / infinity conversion */
|
||||||
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
|
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1186,7 +1172,7 @@ uint64_t helper_fctidz (uint64_t arg)
|
||||||
if (unlikely(float64_is_signaling_nan(farg.d))) {
|
if (unlikely(float64_is_signaling_nan(farg.d))) {
|
||||||
/* sNaN conversion */
|
/* sNaN conversion */
|
||||||
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
|
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
|
||||||
} else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
|
} else if (unlikely(float64_is_quiet_nan(farg.d) || float64_is_infinity(farg.d))) {
|
||||||
/* qNan / infinity conversion */
|
/* qNan / infinity conversion */
|
||||||
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
|
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1205,7 +1191,7 @@ static inline uint64_t do_fri(uint64_t arg, int rounding_mode)
|
||||||
if (unlikely(float64_is_signaling_nan(farg.d))) {
|
if (unlikely(float64_is_signaling_nan(farg.d))) {
|
||||||
/* sNaN round */
|
/* sNaN round */
|
||||||
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
|
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
|
||||||
} else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
|
} else if (unlikely(float64_is_quiet_nan(farg.d) || float64_is_infinity(farg.d))) {
|
||||||
/* qNan / infinity round */
|
/* qNan / infinity round */
|
||||||
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
|
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1245,7 +1231,7 @@ uint64_t helper_fmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
|
||||||
farg1.ll = arg1;
|
farg1.ll = arg1;
|
||||||
farg2.ll = arg2;
|
farg2.ll = arg2;
|
||||||
farg3.ll = arg3;
|
farg3.ll = arg3;
|
||||||
#if USE_PRECISE_EMULATION
|
|
||||||
if (unlikely(float64_is_signaling_nan(farg1.d) ||
|
if (unlikely(float64_is_signaling_nan(farg1.d) ||
|
||||||
float64_is_signaling_nan(farg2.d) ||
|
float64_is_signaling_nan(farg2.d) ||
|
||||||
float64_is_signaling_nan(farg3.d))) {
|
float64_is_signaling_nan(farg3.d))) {
|
||||||
|
@ -1277,10 +1263,7 @@ uint64_t helper_fmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
|
||||||
farg1.d = (farg1.d * farg2.d) + farg3.d;
|
farg1.d = (farg1.d * farg2.d) + farg3.d;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
|
|
||||||
farg1.d = float64_add(farg1.d, farg3.d, &env->fp_status);
|
|
||||||
#endif
|
|
||||||
return farg1.ll;
|
return farg1.ll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1292,7 +1275,7 @@ uint64_t helper_fmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
|
||||||
farg1.ll = arg1;
|
farg1.ll = arg1;
|
||||||
farg2.ll = arg2;
|
farg2.ll = arg2;
|
||||||
farg3.ll = arg3;
|
farg3.ll = arg3;
|
||||||
#if USE_PRECISE_EMULATION
|
|
||||||
if (unlikely(float64_is_signaling_nan(farg1.d) ||
|
if (unlikely(float64_is_signaling_nan(farg1.d) ||
|
||||||
float64_is_signaling_nan(farg2.d) ||
|
float64_is_signaling_nan(farg2.d) ||
|
||||||
float64_is_signaling_nan(farg3.d))) {
|
float64_is_signaling_nan(farg3.d))) {
|
||||||
|
@ -1324,10 +1307,6 @@ uint64_t helper_fmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
|
||||||
farg1.d = (farg1.d * farg2.d) - farg3.d;
|
farg1.d = (farg1.d * farg2.d) - farg3.d;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
|
|
||||||
farg1.d = float64_sub(farg1.d, farg3.d, &env->fp_status);
|
|
||||||
#endif
|
|
||||||
return farg1.ll;
|
return farg1.ll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1350,7 +1329,6 @@ uint64_t helper_fnmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
|
||||||
/* Multiplication of zero by infinity */
|
/* Multiplication of zero by infinity */
|
||||||
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
|
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
|
||||||
} else {
|
} else {
|
||||||
#if USE_PRECISE_EMULATION
|
|
||||||
#ifdef FLOAT128
|
#ifdef FLOAT128
|
||||||
/* This is the way the PowerPC specification defines it */
|
/* This is the way the PowerPC specification defines it */
|
||||||
float128 ft0_128, ft1_128;
|
float128 ft0_128, ft1_128;
|
||||||
|
@ -1371,11 +1349,7 @@ uint64_t helper_fnmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
|
||||||
/* This is OK on x86 hosts */
|
/* This is OK on x86 hosts */
|
||||||
farg1.d = (farg1.d * farg2.d) + farg3.d;
|
farg1.d = (farg1.d * farg2.d) + farg3.d;
|
||||||
#endif
|
#endif
|
||||||
#else
|
if (likely(!float64_is_quiet_nan(farg1.d)))
|
||||||
farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
|
|
||||||
farg1.d = float64_add(farg1.d, farg3.d, &env->fp_status);
|
|
||||||
#endif
|
|
||||||
if (likely(!float64_is_nan(farg1.d)))
|
|
||||||
farg1.d = float64_chs(farg1.d);
|
farg1.d = float64_chs(farg1.d);
|
||||||
}
|
}
|
||||||
return farg1.ll;
|
return farg1.ll;
|
||||||
|
@ -1400,7 +1374,6 @@ uint64_t helper_fnmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
|
||||||
/* Multiplication of zero by infinity */
|
/* Multiplication of zero by infinity */
|
||||||
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
|
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
|
||||||
} else {
|
} else {
|
||||||
#if USE_PRECISE_EMULATION
|
|
||||||
#ifdef FLOAT128
|
#ifdef FLOAT128
|
||||||
/* This is the way the PowerPC specification defines it */
|
/* This is the way the PowerPC specification defines it */
|
||||||
float128 ft0_128, ft1_128;
|
float128 ft0_128, ft1_128;
|
||||||
|
@ -1421,11 +1394,7 @@ uint64_t helper_fnmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
|
||||||
/* This is OK on x86 hosts */
|
/* This is OK on x86 hosts */
|
||||||
farg1.d = (farg1.d * farg2.d) - farg3.d;
|
farg1.d = (farg1.d * farg2.d) - farg3.d;
|
||||||
#endif
|
#endif
|
||||||
#else
|
if (likely(!float64_is_quiet_nan(farg1.d)))
|
||||||
farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
|
|
||||||
farg1.d = float64_sub(farg1.d, farg3.d, &env->fp_status);
|
|
||||||
#endif
|
|
||||||
if (likely(!float64_is_nan(farg1.d)))
|
|
||||||
farg1.d = float64_chs(farg1.d);
|
farg1.d = float64_chs(farg1.d);
|
||||||
}
|
}
|
||||||
return farg1.ll;
|
return farg1.ll;
|
||||||
|
@ -1438,7 +1407,6 @@ uint64_t helper_frsp (uint64_t arg)
|
||||||
float32 f32;
|
float32 f32;
|
||||||
farg.ll = arg;
|
farg.ll = arg;
|
||||||
|
|
||||||
#if USE_PRECISE_EMULATION
|
|
||||||
if (unlikely(float64_is_signaling_nan(farg.d))) {
|
if (unlikely(float64_is_signaling_nan(farg.d))) {
|
||||||
/* sNaN square root */
|
/* sNaN square root */
|
||||||
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
|
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
|
||||||
|
@ -1446,10 +1414,6 @@ uint64_t helper_frsp (uint64_t arg)
|
||||||
f32 = float64_to_float32(farg.d, &env->fp_status);
|
f32 = float64_to_float32(farg.d, &env->fp_status);
|
||||||
farg.d = float32_to_float64(f32, &env->fp_status);
|
farg.d = float32_to_float64(f32, &env->fp_status);
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
f32 = float64_to_float32(farg.d, &env->fp_status);
|
|
||||||
farg.d = float32_to_float64(f32, &env->fp_status);
|
|
||||||
#endif
|
|
||||||
return farg.ll;
|
return farg.ll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1533,7 +1497,7 @@ uint64_t helper_fsel (uint64_t arg1, uint64_t arg2, uint64_t arg3)
|
||||||
|
|
||||||
farg1.ll = arg1;
|
farg1.ll = arg1;
|
||||||
|
|
||||||
if ((!float64_is_neg(farg1.d) || float64_is_zero(farg1.d)) && !float64_is_nan(farg1.d))
|
if ((!float64_is_neg(farg1.d) || float64_is_zero(farg1.d)) && !float64_is_quiet_nan(farg1.d))
|
||||||
return arg2;
|
return arg2;
|
||||||
else
|
else
|
||||||
return arg3;
|
return arg3;
|
||||||
|
@ -1546,8 +1510,8 @@ void helper_fcmpu (uint64_t arg1, uint64_t arg2, uint32_t crfD)
|
||||||
farg1.ll = arg1;
|
farg1.ll = arg1;
|
||||||
farg2.ll = arg2;
|
farg2.ll = arg2;
|
||||||
|
|
||||||
if (unlikely(float64_is_nan(farg1.d) ||
|
if (unlikely(float64_is_quiet_nan(farg1.d) ||
|
||||||
float64_is_nan(farg2.d))) {
|
float64_is_quiet_nan(farg2.d))) {
|
||||||
ret = 0x01UL;
|
ret = 0x01UL;
|
||||||
} else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
|
} else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
|
||||||
ret = 0x08UL;
|
ret = 0x08UL;
|
||||||
|
@ -1575,8 +1539,8 @@ void helper_fcmpo (uint64_t arg1, uint64_t arg2, uint32_t crfD)
|
||||||
farg1.ll = arg1;
|
farg1.ll = arg1;
|
||||||
farg2.ll = arg2;
|
farg2.ll = arg2;
|
||||||
|
|
||||||
if (unlikely(float64_is_nan(farg1.d) ||
|
if (unlikely(float64_is_quiet_nan(farg1.d) ||
|
||||||
float64_is_nan(farg2.d))) {
|
float64_is_quiet_nan(farg2.d))) {
|
||||||
ret = 0x01UL;
|
ret = 0x01UL;
|
||||||
} else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
|
} else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
|
||||||
ret = 0x08UL;
|
ret = 0x08UL;
|
||||||
|
@ -1938,7 +1902,7 @@ target_ulong helper_dlmzb (target_ulong high, target_ulong low, uint32_t update_
|
||||||
/* If X is a NaN, store the corresponding QNaN into RESULT. Otherwise,
|
/* If X is a NaN, store the corresponding QNaN into RESULT. Otherwise,
|
||||||
* execute the following block. */
|
* execute the following block. */
|
||||||
#define DO_HANDLE_NAN(result, x) \
|
#define DO_HANDLE_NAN(result, x) \
|
||||||
if (float32_is_nan(x) || float32_is_signaling_nan(x)) { \
|
if (float32_is_any_nan(x)) { \
|
||||||
CPU_FloatU __f; \
|
CPU_FloatU __f; \
|
||||||
__f.f = x; \
|
__f.f = x; \
|
||||||
__f.l = __f.l | (1 << 22); /* Set QNaN bit. */ \
|
__f.l = __f.l | (1 << 22); /* Set QNaN bit. */ \
|
||||||
|
@ -2283,8 +2247,7 @@ void helper_vcmpbfp_dot (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
|
||||||
float_status s = env->vec_status; \
|
float_status s = env->vec_status; \
|
||||||
set_float_rounding_mode(float_round_to_zero, &s); \
|
set_float_rounding_mode(float_round_to_zero, &s); \
|
||||||
for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
|
for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
|
||||||
if (float32_is_nan(b->f[i]) || \
|
if (float32_is_any_nan(b->f[i])) { \
|
||||||
float32_is_signaling_nan(b->f[i])) { \
|
|
||||||
r->element[i] = 0; \
|
r->element[i] = 0; \
|
||||||
} else { \
|
} else { \
|
||||||
float64 t = float32_to_float64(b->f[i], &s); \
|
float64 t = float32_to_float64(b->f[i], &s); \
|
||||||
|
@ -3132,7 +3095,7 @@ static inline int32_t efsctsi(uint32_t val)
|
||||||
|
|
||||||
u.l = val;
|
u.l = val;
|
||||||
/* NaN are not treated the same way IEEE 754 does */
|
/* NaN are not treated the same way IEEE 754 does */
|
||||||
if (unlikely(float32_is_nan(u.f)))
|
if (unlikely(float32_is_quiet_nan(u.f)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return float32_to_int32(u.f, &env->vec_status);
|
return float32_to_int32(u.f, &env->vec_status);
|
||||||
|
@ -3144,7 +3107,7 @@ static inline uint32_t efsctui(uint32_t val)
|
||||||
|
|
||||||
u.l = val;
|
u.l = val;
|
||||||
/* NaN are not treated the same way IEEE 754 does */
|
/* NaN are not treated the same way IEEE 754 does */
|
||||||
if (unlikely(float32_is_nan(u.f)))
|
if (unlikely(float32_is_quiet_nan(u.f)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return float32_to_uint32(u.f, &env->vec_status);
|
return float32_to_uint32(u.f, &env->vec_status);
|
||||||
|
@ -3156,7 +3119,7 @@ static inline uint32_t efsctsiz(uint32_t val)
|
||||||
|
|
||||||
u.l = val;
|
u.l = val;
|
||||||
/* NaN are not treated the same way IEEE 754 does */
|
/* NaN are not treated the same way IEEE 754 does */
|
||||||
if (unlikely(float32_is_nan(u.f)))
|
if (unlikely(float32_is_quiet_nan(u.f)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return float32_to_int32_round_to_zero(u.f, &env->vec_status);
|
return float32_to_int32_round_to_zero(u.f, &env->vec_status);
|
||||||
|
@ -3168,7 +3131,7 @@ static inline uint32_t efsctuiz(uint32_t val)
|
||||||
|
|
||||||
u.l = val;
|
u.l = val;
|
||||||
/* NaN are not treated the same way IEEE 754 does */
|
/* NaN are not treated the same way IEEE 754 does */
|
||||||
if (unlikely(float32_is_nan(u.f)))
|
if (unlikely(float32_is_quiet_nan(u.f)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return float32_to_uint32_round_to_zero(u.f, &env->vec_status);
|
return float32_to_uint32_round_to_zero(u.f, &env->vec_status);
|
||||||
|
@ -3205,7 +3168,7 @@ static inline uint32_t efsctsf(uint32_t val)
|
||||||
|
|
||||||
u.l = val;
|
u.l = val;
|
||||||
/* NaN are not treated the same way IEEE 754 does */
|
/* NaN are not treated the same way IEEE 754 does */
|
||||||
if (unlikely(float32_is_nan(u.f)))
|
if (unlikely(float32_is_quiet_nan(u.f)))
|
||||||
return 0;
|
return 0;
|
||||||
tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
|
tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
|
||||||
u.f = float32_mul(u.f, tmp, &env->vec_status);
|
u.f = float32_mul(u.f, tmp, &env->vec_status);
|
||||||
|
@ -3220,7 +3183,7 @@ static inline uint32_t efsctuf(uint32_t val)
|
||||||
|
|
||||||
u.l = val;
|
u.l = val;
|
||||||
/* NaN are not treated the same way IEEE 754 does */
|
/* NaN are not treated the same way IEEE 754 does */
|
||||||
if (unlikely(float32_is_nan(u.f)))
|
if (unlikely(float32_is_quiet_nan(u.f)))
|
||||||
return 0;
|
return 0;
|
||||||
tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
|
tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
|
||||||
u.f = float32_mul(u.f, tmp, &env->vec_status);
|
u.f = float32_mul(u.f, tmp, &env->vec_status);
|
||||||
|
@ -3474,7 +3437,7 @@ uint32_t helper_efdctsi (uint64_t val)
|
||||||
|
|
||||||
u.ll = val;
|
u.ll = val;
|
||||||
/* NaN are not treated the same way IEEE 754 does */
|
/* NaN are not treated the same way IEEE 754 does */
|
||||||
if (unlikely(float64_is_nan(u.d)))
|
if (unlikely(float64_is_quiet_nan(u.d)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return float64_to_int32(u.d, &env->vec_status);
|
return float64_to_int32(u.d, &env->vec_status);
|
||||||
|
@ -3486,7 +3449,7 @@ uint32_t helper_efdctui (uint64_t val)
|
||||||
|
|
||||||
u.ll = val;
|
u.ll = val;
|
||||||
/* NaN are not treated the same way IEEE 754 does */
|
/* NaN are not treated the same way IEEE 754 does */
|
||||||
if (unlikely(float64_is_nan(u.d)))
|
if (unlikely(float64_is_quiet_nan(u.d)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return float64_to_uint32(u.d, &env->vec_status);
|
return float64_to_uint32(u.d, &env->vec_status);
|
||||||
|
@ -3498,7 +3461,7 @@ uint32_t helper_efdctsiz (uint64_t val)
|
||||||
|
|
||||||
u.ll = val;
|
u.ll = val;
|
||||||
/* NaN are not treated the same way IEEE 754 does */
|
/* NaN are not treated the same way IEEE 754 does */
|
||||||
if (unlikely(float64_is_nan(u.d)))
|
if (unlikely(float64_is_quiet_nan(u.d)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return float64_to_int32_round_to_zero(u.d, &env->vec_status);
|
return float64_to_int32_round_to_zero(u.d, &env->vec_status);
|
||||||
|
@ -3510,7 +3473,7 @@ uint64_t helper_efdctsidz (uint64_t val)
|
||||||
|
|
||||||
u.ll = val;
|
u.ll = val;
|
||||||
/* NaN are not treated the same way IEEE 754 does */
|
/* NaN are not treated the same way IEEE 754 does */
|
||||||
if (unlikely(float64_is_nan(u.d)))
|
if (unlikely(float64_is_quiet_nan(u.d)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return float64_to_int64_round_to_zero(u.d, &env->vec_status);
|
return float64_to_int64_round_to_zero(u.d, &env->vec_status);
|
||||||
|
@ -3522,7 +3485,7 @@ uint32_t helper_efdctuiz (uint64_t val)
|
||||||
|
|
||||||
u.ll = val;
|
u.ll = val;
|
||||||
/* NaN are not treated the same way IEEE 754 does */
|
/* NaN are not treated the same way IEEE 754 does */
|
||||||
if (unlikely(float64_is_nan(u.d)))
|
if (unlikely(float64_is_quiet_nan(u.d)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return float64_to_uint32_round_to_zero(u.d, &env->vec_status);
|
return float64_to_uint32_round_to_zero(u.d, &env->vec_status);
|
||||||
|
@ -3534,7 +3497,7 @@ uint64_t helper_efdctuidz (uint64_t val)
|
||||||
|
|
||||||
u.ll = val;
|
u.ll = val;
|
||||||
/* NaN are not treated the same way IEEE 754 does */
|
/* NaN are not treated the same way IEEE 754 does */
|
||||||
if (unlikely(float64_is_nan(u.d)))
|
if (unlikely(float64_is_quiet_nan(u.d)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return float64_to_uint64_round_to_zero(u.d, &env->vec_status);
|
return float64_to_uint64_round_to_zero(u.d, &env->vec_status);
|
||||||
|
@ -3571,7 +3534,7 @@ uint32_t helper_efdctsf (uint64_t val)
|
||||||
|
|
||||||
u.ll = val;
|
u.ll = val;
|
||||||
/* NaN are not treated the same way IEEE 754 does */
|
/* NaN are not treated the same way IEEE 754 does */
|
||||||
if (unlikely(float64_is_nan(u.d)))
|
if (unlikely(float64_is_quiet_nan(u.d)))
|
||||||
return 0;
|
return 0;
|
||||||
tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
|
tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
|
||||||
u.d = float64_mul(u.d, tmp, &env->vec_status);
|
u.d = float64_mul(u.d, tmp, &env->vec_status);
|
||||||
|
@ -3586,7 +3549,7 @@ uint32_t helper_efdctuf (uint64_t val)
|
||||||
|
|
||||||
u.ll = val;
|
u.ll = val;
|
||||||
/* NaN are not treated the same way IEEE 754 does */
|
/* NaN are not treated the same way IEEE 754 does */
|
||||||
if (unlikely(float64_is_nan(u.d)))
|
if (unlikely(float64_is_quiet_nan(u.d)))
|
||||||
return 0;
|
return 0;
|
||||||
tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
|
tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
|
||||||
u.d = float64_mul(u.d, tmp, &env->vec_status);
|
u.d = float64_mul(u.d, tmp, &env->vec_status);
|
||||||
|
|
|
@ -7751,10 +7751,10 @@ static inline void gen_evfsabs(DisasContext *ctx)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#if defined(TARGET_PPC64)
|
#if defined(TARGET_PPC64)
|
||||||
tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000080000000LL);
|
tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000080000000LL);
|
||||||
#else
|
#else
|
||||||
tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x80000000);
|
tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x80000000);
|
||||||
tcg_gen_andi_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
|
tcg_gen_andi_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
static inline void gen_evfsnabs(DisasContext *ctx)
|
static inline void gen_evfsnabs(DisasContext *ctx)
|
||||||
|
@ -7764,10 +7764,10 @@ static inline void gen_evfsnabs(DisasContext *ctx)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#if defined(TARGET_PPC64)
|
#if defined(TARGET_PPC64)
|
||||||
tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
|
tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
|
||||||
#else
|
#else
|
||||||
tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
|
tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
|
||||||
tcg_gen_ori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
|
tcg_gen_ori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
static inline void gen_evfsneg(DisasContext *ctx)
|
static inline void gen_evfsneg(DisasContext *ctx)
|
||||||
|
@ -7777,10 +7777,10 @@ static inline void gen_evfsneg(DisasContext *ctx)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#if defined(TARGET_PPC64)
|
#if defined(TARGET_PPC64)
|
||||||
tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
|
tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
|
||||||
#else
|
#else
|
||||||
tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
|
tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
|
||||||
tcg_gen_xori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
|
tcg_gen_xori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7832,7 +7832,7 @@ static inline void gen_efsabs(DisasContext *ctx)
|
||||||
gen_exception(ctx, POWERPC_EXCP_APU);
|
gen_exception(ctx, POWERPC_EXCP_APU);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL);
|
tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL);
|
||||||
}
|
}
|
||||||
static inline void gen_efsnabs(DisasContext *ctx)
|
static inline void gen_efsnabs(DisasContext *ctx)
|
||||||
{
|
{
|
||||||
|
@ -7840,7 +7840,7 @@ static inline void gen_efsnabs(DisasContext *ctx)
|
||||||
gen_exception(ctx, POWERPC_EXCP_APU);
|
gen_exception(ctx, POWERPC_EXCP_APU);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
|
tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
|
||||||
}
|
}
|
||||||
static inline void gen_efsneg(DisasContext *ctx)
|
static inline void gen_efsneg(DisasContext *ctx)
|
||||||
{
|
{
|
||||||
|
@ -7848,7 +7848,7 @@ static inline void gen_efsneg(DisasContext *ctx)
|
||||||
gen_exception(ctx, POWERPC_EXCP_APU);
|
gen_exception(ctx, POWERPC_EXCP_APU);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
|
tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Conversion */
|
/* Conversion */
|
||||||
|
@ -7901,9 +7901,10 @@ static inline void gen_efdabs(DisasContext *ctx)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#if defined(TARGET_PPC64)
|
#if defined(TARGET_PPC64)
|
||||||
tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000000000000LL);
|
tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000000000000LL);
|
||||||
#else
|
#else
|
||||||
tcg_gen_andi_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
|
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
|
||||||
|
tcg_gen_andi_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
static inline void gen_efdnabs(DisasContext *ctx)
|
static inline void gen_efdnabs(DisasContext *ctx)
|
||||||
|
@ -7913,9 +7914,10 @@ static inline void gen_efdnabs(DisasContext *ctx)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#if defined(TARGET_PPC64)
|
#if defined(TARGET_PPC64)
|
||||||
tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
|
tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
|
||||||
#else
|
#else
|
||||||
tcg_gen_ori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
|
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
|
||||||
|
tcg_gen_ori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
static inline void gen_efdneg(DisasContext *ctx)
|
static inline void gen_efdneg(DisasContext *ctx)
|
||||||
|
@ -7925,9 +7927,10 @@ static inline void gen_efdneg(DisasContext *ctx)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#if defined(TARGET_PPC64)
|
#if defined(TARGET_PPC64)
|
||||||
tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
|
tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
|
||||||
#else
|
#else
|
||||||
tcg_gen_xori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
|
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
|
||||||
|
tcg_gen_xori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -119,7 +119,7 @@ int kvm_arch_put_registers(CPUState *env, int level)
|
||||||
|
|
||||||
int kvm_arch_get_registers(CPUState *env)
|
int kvm_arch_get_registers(CPUState *env)
|
||||||
{
|
{
|
||||||
uint32_t ret;
|
int ret;
|
||||||
struct kvm_regs regs;
|
struct kvm_regs regs;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (i = 0; i < 16; i++) {
|
for (i = 0; i < 16; i++) {
|
||||||
cpu_fprintf(f, "F%02d=%016lx", i, env->fregs[i]);
|
cpu_fprintf(f, "F%02d=%016lx", i, (long)env->fregs[i].i);
|
||||||
if ((i % 4) == 3) {
|
if ((i % 4) == 3) {
|
||||||
cpu_fprintf(f, "\n");
|
cpu_fprintf(f, "\n");
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -172,6 +172,8 @@ void do_interrupt(CPUSH4State * env);
|
||||||
void sh4_cpu_list(FILE *f, fprintf_function cpu_fprintf);
|
void sh4_cpu_list(FILE *f, fprintf_function cpu_fprintf);
|
||||||
#if !defined(CONFIG_USER_ONLY)
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
void cpu_sh4_invalidate_tlb(CPUSH4State *s);
|
void cpu_sh4_invalidate_tlb(CPUSH4State *s);
|
||||||
|
void cpu_sh4_write_mmaped_itlb_addr(CPUSH4State *s, target_phys_addr_t addr,
|
||||||
|
uint32_t mem_value);
|
||||||
void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr,
|
void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr,
|
||||||
uint32_t mem_value);
|
uint32_t mem_value);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -280,35 +280,40 @@ static void increment_urc(CPUState * env)
|
||||||
env->mmucr = (env->mmucr & 0xffff03ff) | (urc << 10);
|
env->mmucr = (env->mmucr & 0xffff03ff) | (urc << 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find itlb entry - update itlb from utlb if necessary and asked for
|
/* Copy and utlb entry into itlb
|
||||||
|
Return entry
|
||||||
|
*/
|
||||||
|
static int copy_utlb_entry_itlb(CPUState *env, int utlb)
|
||||||
|
{
|
||||||
|
int itlb;
|
||||||
|
|
||||||
|
tlb_t * ientry;
|
||||||
|
itlb = itlb_replacement(env);
|
||||||
|
ientry = &env->itlb[itlb];
|
||||||
|
if (ientry->v) {
|
||||||
|
tlb_flush_page(env, ientry->vpn << 10);
|
||||||
|
}
|
||||||
|
*ientry = env->utlb[utlb];
|
||||||
|
update_itlb_use(env, itlb);
|
||||||
|
return itlb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find itlb entry
|
||||||
Return entry, MMU_ITLB_MISS, MMU_ITLB_MULTIPLE or MMU_DTLB_MULTIPLE
|
Return entry, MMU_ITLB_MISS, MMU_ITLB_MULTIPLE or MMU_DTLB_MULTIPLE
|
||||||
Update the itlb from utlb if update is not 0
|
|
||||||
*/
|
*/
|
||||||
static int find_itlb_entry(CPUState * env, target_ulong address,
|
static int find_itlb_entry(CPUState * env, target_ulong address,
|
||||||
int use_asid, int update)
|
int use_asid)
|
||||||
{
|
{
|
||||||
int e, n;
|
int e;
|
||||||
|
|
||||||
e = find_tlb_entry(env, address, env->itlb, ITLB_SIZE, use_asid);
|
e = find_tlb_entry(env, address, env->itlb, ITLB_SIZE, use_asid);
|
||||||
if (e == MMU_DTLB_MULTIPLE)
|
if (e == MMU_DTLB_MULTIPLE) {
|
||||||
e = MMU_ITLB_MULTIPLE;
|
e = MMU_ITLB_MULTIPLE;
|
||||||
else if (e == MMU_DTLB_MISS && update) {
|
} else if (e == MMU_DTLB_MISS) {
|
||||||
e = find_tlb_entry(env, address, env->utlb, UTLB_SIZE, use_asid);
|
|
||||||
if (e >= 0) {
|
|
||||||
tlb_t * ientry;
|
|
||||||
n = itlb_replacement(env);
|
|
||||||
ientry = &env->itlb[n];
|
|
||||||
if (ientry->v) {
|
|
||||||
tlb_flush_page(env, ientry->vpn << 10);
|
|
||||||
}
|
|
||||||
*ientry = env->utlb[e];
|
|
||||||
e = n;
|
|
||||||
} else if (e == MMU_DTLB_MISS)
|
|
||||||
e = MMU_ITLB_MISS;
|
|
||||||
} else if (e == MMU_DTLB_MISS)
|
|
||||||
e = MMU_ITLB_MISS;
|
e = MMU_ITLB_MISS;
|
||||||
if (e >= 0)
|
} else if (e >= 0) {
|
||||||
update_itlb_use(env, e);
|
update_itlb_use(env, e);
|
||||||
|
}
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,13 +345,31 @@ static int get_mmu_address(CPUState * env, target_ulong * physical,
|
||||||
use_asid = (env->mmucr & MMUCR_SV) == 0 || (env->sr & SR_MD) == 0;
|
use_asid = (env->mmucr & MMUCR_SV) == 0 || (env->sr & SR_MD) == 0;
|
||||||
|
|
||||||
if (rw == 2) {
|
if (rw == 2) {
|
||||||
n = find_itlb_entry(env, address, use_asid, 1);
|
n = find_itlb_entry(env, address, use_asid);
|
||||||
if (n >= 0) {
|
if (n >= 0) {
|
||||||
matching = &env->itlb[n];
|
matching = &env->itlb[n];
|
||||||
if (!(env->sr & SR_MD) && !(matching->pr & 2))
|
if (!(env->sr & SR_MD) && !(matching->pr & 2))
|
||||||
n = MMU_ITLB_VIOLATION;
|
n = MMU_ITLB_VIOLATION;
|
||||||
else
|
else
|
||||||
*prot = PAGE_EXEC;
|
*prot = PAGE_EXEC;
|
||||||
|
} else {
|
||||||
|
n = find_utlb_entry(env, address, use_asid);
|
||||||
|
if (n >= 0) {
|
||||||
|
n = copy_utlb_entry_itlb(env, n);
|
||||||
|
matching = &env->itlb[n];
|
||||||
|
if (!(env->sr & SR_MD) && !(matching->pr & 2)) {
|
||||||
|
n = MMU_ITLB_VIOLATION;
|
||||||
|
} else {
|
||||||
|
*prot = PAGE_READ | PAGE_EXEC;
|
||||||
|
if ((matching->pr & 1) && matching->d) {
|
||||||
|
*prot |= PAGE_WRITE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (n == MMU_DTLB_MULTIPLE) {
|
||||||
|
n = MMU_ITLB_MULTIPLE;
|
||||||
|
} else if (n == MMU_DTLB_MISS) {
|
||||||
|
n = MMU_ITLB_MISS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
n = find_utlb_entry(env, address, use_asid);
|
n = find_utlb_entry(env, address, use_asid);
|
||||||
|
@ -544,6 +567,25 @@ void cpu_load_tlb(CPUSH4State * env)
|
||||||
tlb_flush(s, 1);
|
tlb_flush(s, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cpu_sh4_write_mmaped_itlb_addr(CPUSH4State *s, target_phys_addr_t addr,
|
||||||
|
uint32_t mem_value)
|
||||||
|
{
|
||||||
|
uint32_t vpn = (mem_value & 0xfffffc00) >> 10;
|
||||||
|
uint8_t v = (uint8_t)((mem_value & 0x00000100) >> 8);
|
||||||
|
uint8_t asid = (uint8_t)(mem_value & 0x000000ff);
|
||||||
|
|
||||||
|
int index = (addr & 0x00003f00) >> 8;
|
||||||
|
tlb_t * entry = &s->itlb[index];
|
||||||
|
if (entry->v) {
|
||||||
|
/* Overwriting valid entry in itlb. */
|
||||||
|
target_ulong address = entry->vpn << 10;
|
||||||
|
tlb_flush_page(s, address);
|
||||||
|
}
|
||||||
|
entry->asid = asid;
|
||||||
|
entry->vpn = vpn;
|
||||||
|
entry->v = v;
|
||||||
|
}
|
||||||
|
|
||||||
void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr,
|
void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr,
|
||||||
uint32_t mem_value)
|
uint32_t mem_value)
|
||||||
{
|
{
|
||||||
|
|
|
@ -448,7 +448,7 @@ int cpu_sparc_handle_mmu_fault(CPUSPARCState *env1, target_ulong address, int rw
|
||||||
int mmu_idx, int is_softmmu);
|
int mmu_idx, int is_softmmu);
|
||||||
#define cpu_handle_mmu_fault cpu_sparc_handle_mmu_fault
|
#define cpu_handle_mmu_fault cpu_sparc_handle_mmu_fault
|
||||||
target_ulong mmu_probe(CPUSPARCState *env, target_ulong address, int mmulev);
|
target_ulong mmu_probe(CPUSPARCState *env, target_ulong address, int mmulev);
|
||||||
void dump_mmu(CPUSPARCState *env);
|
void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env);
|
||||||
|
|
||||||
/* translate.c */
|
/* translate.c */
|
||||||
void gen_intermediate_code_init(CPUSPARCState *env);
|
void gen_intermediate_code_init(CPUSPARCState *env);
|
||||||
|
|
|
@ -320,47 +320,45 @@ target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_MMU
|
void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
|
||||||
void dump_mmu(CPUState *env)
|
|
||||||
{
|
{
|
||||||
target_ulong va, va1, va2;
|
target_ulong va, va1, va2;
|
||||||
unsigned int n, m, o;
|
unsigned int n, m, o;
|
||||||
target_phys_addr_t pde_ptr, pa;
|
target_phys_addr_t pde_ptr, pa;
|
||||||
uint32_t pde;
|
uint32_t pde;
|
||||||
|
|
||||||
printf("MMU dump:\n");
|
|
||||||
pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
|
pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
|
||||||
pde = ldl_phys(pde_ptr);
|
pde = ldl_phys(pde_ptr);
|
||||||
printf("Root ptr: " TARGET_FMT_plx ", ctx: %d\n",
|
(*cpu_fprintf)(f, "Root ptr: " TARGET_FMT_plx ", ctx: %d\n",
|
||||||
(target_phys_addr_t)env->mmuregs[1] << 4, env->mmuregs[2]);
|
(target_phys_addr_t)env->mmuregs[1] << 4, env->mmuregs[2]);
|
||||||
for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
|
for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
|
||||||
pde = mmu_probe(env, va, 2);
|
pde = mmu_probe(env, va, 2);
|
||||||
if (pde) {
|
if (pde) {
|
||||||
pa = cpu_get_phys_page_debug(env, va);
|
pa = cpu_get_phys_page_debug(env, va);
|
||||||
printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
|
(*cpu_fprintf)(f, "VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
|
||||||
" PDE: " TARGET_FMT_lx "\n", va, pa, pde);
|
" PDE: " TARGET_FMT_lx "\n", va, pa, pde);
|
||||||
for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
|
for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
|
||||||
pde = mmu_probe(env, va1, 1);
|
pde = mmu_probe(env, va1, 1);
|
||||||
if (pde) {
|
if (pde) {
|
||||||
pa = cpu_get_phys_page_debug(env, va1);
|
pa = cpu_get_phys_page_debug(env, va1);
|
||||||
printf(" VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
|
(*cpu_fprintf)(f, " VA: " TARGET_FMT_lx ", PA: "
|
||||||
" PDE: " TARGET_FMT_lx "\n", va1, pa, pde);
|
TARGET_FMT_plx " PDE: " TARGET_FMT_lx "\n",
|
||||||
|
va1, pa, pde);
|
||||||
for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
|
for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
|
||||||
pde = mmu_probe(env, va2, 0);
|
pde = mmu_probe(env, va2, 0);
|
||||||
if (pde) {
|
if (pde) {
|
||||||
pa = cpu_get_phys_page_debug(env, va2);
|
pa = cpu_get_phys_page_debug(env, va2);
|
||||||
printf(" VA: " TARGET_FMT_lx ", PA: "
|
(*cpu_fprintf)(f, " VA: " TARGET_FMT_lx ", PA: "
|
||||||
TARGET_FMT_plx " PTE: " TARGET_FMT_lx "\n",
|
TARGET_FMT_plx " PTE: "
|
||||||
va2, pa, pde);
|
TARGET_FMT_lx "\n",
|
||||||
|
va2, pa, pde);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("MMU dump ends\n");
|
|
||||||
}
|
}
|
||||||
#endif /* DEBUG_MMU */
|
|
||||||
|
|
||||||
#else /* !TARGET_SPARC64 */
|
#else /* !TARGET_SPARC64 */
|
||||||
|
|
||||||
|
@ -622,18 +620,19 @@ int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_MMU
|
void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
|
||||||
void dump_mmu(CPUState *env)
|
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
const char *mask;
|
const char *mask;
|
||||||
|
|
||||||
printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n",
|
(*cpu_fprintf)(f, "MMU contexts: Primary: %" PRId64 ", Secondary: %"
|
||||||
env->dmmu.mmu_primary_context, env->dmmu.mmu_secondary_context);
|
PRId64 "\n",
|
||||||
|
env->dmmu.mmu_primary_context,
|
||||||
|
env->dmmu.mmu_secondary_context);
|
||||||
if ((env->lsu & DMMU_E) == 0) {
|
if ((env->lsu & DMMU_E) == 0) {
|
||||||
printf("DMMU disabled\n");
|
(*cpu_fprintf)(f, "DMMU disabled\n");
|
||||||
} else {
|
} else {
|
||||||
printf("DMMU dump:\n");
|
(*cpu_fprintf)(f, "DMMU dump\n");
|
||||||
for (i = 0; i < 64; i++) {
|
for (i = 0; i < 64; i++) {
|
||||||
switch ((env->dtlb[i].tte >> 61) & 3) {
|
switch ((env->dtlb[i].tte >> 61) & 3) {
|
||||||
default:
|
default:
|
||||||
|
@ -651,24 +650,25 @@ void dump_mmu(CPUState *env)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ((env->dtlb[i].tte & 0x8000000000000000ULL) != 0) {
|
if ((env->dtlb[i].tte & 0x8000000000000000ULL) != 0) {
|
||||||
printf("[%02u] VA: %" PRIx64 ", PA: %" PRIx64
|
(*cpu_fprintf)(f, "[%02u] VA: %" PRIx64 ", PA: %" PRIx64
|
||||||
", %s, %s, %s, %s, ctx %" PRId64 " %s\n",
|
", %s, %s, %s, %s, ctx %" PRId64 " %s\n",
|
||||||
i,
|
i,
|
||||||
env->dtlb[i].tag & (uint64_t)~0x1fffULL,
|
env->dtlb[i].tag & (uint64_t)~0x1fffULL,
|
||||||
env->dtlb[i].tte & (uint64_t)0x1ffffffe000ULL,
|
env->dtlb[i].tte & (uint64_t)0x1ffffffe000ULL,
|
||||||
mask,
|
mask,
|
||||||
env->dtlb[i].tte & 0x4? "priv": "user",
|
env->dtlb[i].tte & 0x4? "priv": "user",
|
||||||
env->dtlb[i].tte & 0x2? "RW": "RO",
|
env->dtlb[i].tte & 0x2? "RW": "RO",
|
||||||
env->dtlb[i].tte & 0x40? "locked": "unlocked",
|
env->dtlb[i].tte & 0x40? "locked": "unlocked",
|
||||||
env->dtlb[i].tag & (uint64_t)0x1fffULL,
|
env->dtlb[i].tag & (uint64_t)0x1fffULL,
|
||||||
TTE_IS_GLOBAL(env->dtlb[i].tte)? "global" : "local");
|
TTE_IS_GLOBAL(env->dtlb[i].tte)?
|
||||||
|
"global" : "local");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((env->lsu & IMMU_E) == 0) {
|
if ((env->lsu & IMMU_E) == 0) {
|
||||||
printf("IMMU disabled\n");
|
(*cpu_fprintf)(f, "IMMU disabled\n");
|
||||||
} else {
|
} else {
|
||||||
printf("IMMU dump:\n");
|
(*cpu_fprintf)(f, "IMMU dump\n");
|
||||||
for (i = 0; i < 64; i++) {
|
for (i = 0; i < 64; i++) {
|
||||||
switch ((env->itlb[i].tte >> 61) & 3) {
|
switch ((env->itlb[i].tte >> 61) & 3) {
|
||||||
default:
|
default:
|
||||||
|
@ -686,21 +686,21 @@ void dump_mmu(CPUState *env)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ((env->itlb[i].tte & 0x8000000000000000ULL) != 0) {
|
if ((env->itlb[i].tte & 0x8000000000000000ULL) != 0) {
|
||||||
printf("[%02u] VA: %" PRIx64 ", PA: %" PRIx64
|
(*cpu_fprintf)(f, "[%02u] VA: %" PRIx64 ", PA: %" PRIx64
|
||||||
", %s, %s, %s, ctx %" PRId64 " %s\n",
|
", %s, %s, %s, ctx %" PRId64 " %s\n",
|
||||||
i,
|
i,
|
||||||
env->itlb[i].tag & (uint64_t)~0x1fffULL,
|
env->itlb[i].tag & (uint64_t)~0x1fffULL,
|
||||||
env->itlb[i].tte & (uint64_t)0x1ffffffe000ULL,
|
env->itlb[i].tte & (uint64_t)0x1ffffffe000ULL,
|
||||||
mask,
|
mask,
|
||||||
env->itlb[i].tte & 0x4? "priv": "user",
|
env->itlb[i].tte & 0x4? "priv": "user",
|
||||||
env->itlb[i].tte & 0x40? "locked": "unlocked",
|
env->itlb[i].tte & 0x40? "locked": "unlocked",
|
||||||
env->itlb[i].tag & (uint64_t)0x1fffULL,
|
env->itlb[i].tag & (uint64_t)0x1fffULL,
|
||||||
TTE_IS_GLOBAL(env->itlb[i].tte)? "global" : "local");
|
TTE_IS_GLOBAL(env->itlb[i].tte)?
|
||||||
|
"global" : "local");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* DEBUG_MMU */
|
|
||||||
|
|
||||||
#endif /* TARGET_SPARC64 */
|
#endif /* TARGET_SPARC64 */
|
||||||
#endif /* !CONFIG_USER_ONLY */
|
#endif /* !CONFIG_USER_ONLY */
|
||||||
|
|
|
@ -37,7 +37,9 @@ DEF_HELPER_0(save, void)
|
||||||
DEF_HELPER_0(restore, void)
|
DEF_HELPER_0(restore, void)
|
||||||
DEF_HELPER_1(flush, void, tl)
|
DEF_HELPER_1(flush, void, tl)
|
||||||
DEF_HELPER_2(udiv, tl, tl, tl)
|
DEF_HELPER_2(udiv, tl, tl, tl)
|
||||||
|
DEF_HELPER_2(udiv_cc, tl, tl, tl)
|
||||||
DEF_HELPER_2(sdiv, tl, tl, tl)
|
DEF_HELPER_2(sdiv, tl, tl, tl)
|
||||||
|
DEF_HELPER_2(sdiv_cc, tl, tl, tl)
|
||||||
DEF_HELPER_2(stdf, void, tl, int)
|
DEF_HELPER_2(stdf, void, tl, int)
|
||||||
DEF_HELPER_2(lddf, void, tl, int)
|
DEF_HELPER_2(lddf, void, tl, int)
|
||||||
DEF_HELPER_2(ldqf, void, tl, int)
|
DEF_HELPER_2(ldqf, void, tl, int)
|
||||||
|
|
|
@ -180,7 +180,7 @@ static void demap_tlb(SparcTLBEntry *tlb, target_ulong demap_addr,
|
||||||
replace_tlb_entry(&tlb[i], 0, 0, env1);
|
replace_tlb_entry(&tlb[i], 0, 0, env1);
|
||||||
#ifdef DEBUG_MMU
|
#ifdef DEBUG_MMU
|
||||||
DPRINTF_MMU("%s demap invalidated entry [%02u]\n", strmmu, i);
|
DPRINTF_MMU("%s demap invalidated entry [%02u]\n", strmmu, i);
|
||||||
dump_mmu(env1);
|
dump_mmu(stdout, fprintf, env1);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -198,7 +198,7 @@ static void replace_tlb_1bit_lru(SparcTLBEntry *tlb,
|
||||||
replace_tlb_entry(&tlb[i], tlb_tag, tlb_tte, env1);
|
replace_tlb_entry(&tlb[i], tlb_tag, tlb_tte, env1);
|
||||||
#ifdef DEBUG_MMU
|
#ifdef DEBUG_MMU
|
||||||
DPRINTF_MMU("%s lru replaced invalid entry [%i]\n", strmmu, i);
|
DPRINTF_MMU("%s lru replaced invalid entry [%i]\n", strmmu, i);
|
||||||
dump_mmu(env1);
|
dump_mmu(stdout, fprintf, env1);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -217,7 +217,7 @@ static void replace_tlb_1bit_lru(SparcTLBEntry *tlb,
|
||||||
#ifdef DEBUG_MMU
|
#ifdef DEBUG_MMU
|
||||||
DPRINTF_MMU("%s lru replaced unlocked %s entry [%i]\n",
|
DPRINTF_MMU("%s lru replaced unlocked %s entry [%i]\n",
|
||||||
strmmu, (replace_used?"used":"unused"), i);
|
strmmu, (replace_used?"used":"unused"), i);
|
||||||
dump_mmu(env1);
|
dump_mmu(stdout, fprintf, env1);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1959,7 +1959,7 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG_MMU
|
#ifdef DEBUG_MMU
|
||||||
dump_mmu(env);
|
dump_mmu(stdout, fprintf, env);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2011,7 +2011,7 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
|
||||||
reg, oldreg, env->mmuregs[reg]);
|
reg, oldreg, env->mmuregs[reg]);
|
||||||
}
|
}
|
||||||
#ifdef DEBUG_MMU
|
#ifdef DEBUG_MMU
|
||||||
dump_mmu(env);
|
dump_mmu(stdout, fprintf, env);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2912,7 +2912,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
|
||||||
DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
|
DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
|
||||||
oldreg, env->lsu);
|
oldreg, env->lsu);
|
||||||
#ifdef DEBUG_MMU
|
#ifdef DEBUG_MMU
|
||||||
dump_mmu(env);
|
dump_mmu(stdout, fprintf, env1);
|
||||||
#endif
|
#endif
|
||||||
tlb_flush(env, 1);
|
tlb_flush(env, 1);
|
||||||
}
|
}
|
||||||
|
@ -2957,7 +2957,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
|
||||||
PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
|
PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
|
||||||
}
|
}
|
||||||
#ifdef DEBUG_MMU
|
#ifdef DEBUG_MMU
|
||||||
dump_mmu(env);
|
dump_mmu(stdout, fprintf, env);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2974,7 +2974,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
|
||||||
|
|
||||||
#ifdef DEBUG_MMU
|
#ifdef DEBUG_MMU
|
||||||
DPRINTF_MMU("immu data access replaced entry [%i]\n", i);
|
DPRINTF_MMU("immu data access replaced entry [%i]\n", i);
|
||||||
dump_mmu(env);
|
dump_mmu(stdout, fprintf, env);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3030,7 +3030,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
|
||||||
PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
|
PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
|
||||||
}
|
}
|
||||||
#ifdef DEBUG_MMU
|
#ifdef DEBUG_MMU
|
||||||
dump_mmu(env);
|
dump_mmu(stdout, fprintf, env);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3045,7 +3045,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
|
||||||
|
|
||||||
#ifdef DEBUG_MMU
|
#ifdef DEBUG_MMU
|
||||||
DPRINTF_MMU("dmmu data access replaced entry [%i]\n", i);
|
DPRINTF_MMU("dmmu data access replaced entry [%i]\n", i);
|
||||||
dump_mmu(env);
|
dump_mmu(stdout, fprintf, env);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3300,8 +3300,9 @@ void helper_rett(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
target_ulong helper_udiv(target_ulong a, target_ulong b)
|
static target_ulong helper_udiv_common(target_ulong a, target_ulong b, int cc)
|
||||||
{
|
{
|
||||||
|
int overflow = 0;
|
||||||
uint64_t x0;
|
uint64_t x0;
|
||||||
uint32_t x1;
|
uint32_t x1;
|
||||||
|
|
||||||
|
@ -3314,16 +3315,31 @@ target_ulong helper_udiv(target_ulong a, target_ulong b)
|
||||||
|
|
||||||
x0 = x0 / x1;
|
x0 = x0 / x1;
|
||||||
if (x0 > 0xffffffff) {
|
if (x0 > 0xffffffff) {
|
||||||
env->cc_src2 = 1;
|
x0 = 0xffffffff;
|
||||||
return 0xffffffff;
|
overflow = 1;
|
||||||
} else {
|
|
||||||
env->cc_src2 = 0;
|
|
||||||
return x0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cc) {
|
||||||
|
env->cc_dst = x0;
|
||||||
|
env->cc_src2 = overflow;
|
||||||
|
env->cc_op = CC_OP_DIV;
|
||||||
|
}
|
||||||
|
return x0;
|
||||||
}
|
}
|
||||||
|
|
||||||
target_ulong helper_sdiv(target_ulong a, target_ulong b)
|
target_ulong helper_udiv(target_ulong a, target_ulong b)
|
||||||
{
|
{
|
||||||
|
return helper_udiv_common(a, b, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
target_ulong helper_udiv_cc(target_ulong a, target_ulong b)
|
||||||
|
{
|
||||||
|
return helper_udiv_common(a, b, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static target_ulong helper_sdiv_common(target_ulong a, target_ulong b, int cc)
|
||||||
|
{
|
||||||
|
int overflow = 0;
|
||||||
int64_t x0;
|
int64_t x0;
|
||||||
int32_t x1;
|
int32_t x1;
|
||||||
|
|
||||||
|
@ -3336,12 +3352,26 @@ target_ulong helper_sdiv(target_ulong a, target_ulong b)
|
||||||
|
|
||||||
x0 = x0 / x1;
|
x0 = x0 / x1;
|
||||||
if ((int32_t) x0 != x0) {
|
if ((int32_t) x0 != x0) {
|
||||||
env->cc_src2 = 1;
|
x0 = x0 < 0 ? 0x80000000: 0x7fffffff;
|
||||||
return x0 < 0? 0x80000000: 0x7fffffff;
|
overflow = 1;
|
||||||
} else {
|
|
||||||
env->cc_src2 = 0;
|
|
||||||
return x0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cc) {
|
||||||
|
env->cc_dst = x0;
|
||||||
|
env->cc_src2 = overflow;
|
||||||
|
env->cc_op = CC_OP_DIV;
|
||||||
|
}
|
||||||
|
return x0;
|
||||||
|
}
|
||||||
|
|
||||||
|
target_ulong helper_sdiv(target_ulong a, target_ulong b)
|
||||||
|
{
|
||||||
|
return helper_sdiv_common(a, b, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
target_ulong helper_sdiv_cc(target_ulong a, target_ulong b)
|
||||||
|
{
|
||||||
|
return helper_sdiv_common(a, b, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void helper_stdf(target_ulong addr, int mem_idx)
|
void helper_stdf(target_ulong addr, int mem_idx)
|
||||||
|
|
|
@ -3162,20 +3162,20 @@ static void disas_sparc_insn(DisasContext * dc)
|
||||||
#endif
|
#endif
|
||||||
case 0xe: /* udiv */
|
case 0xe: /* udiv */
|
||||||
CHECK_IU_FEATURE(dc, DIV);
|
CHECK_IU_FEATURE(dc, DIV);
|
||||||
gen_helper_udiv(cpu_dst, cpu_src1, cpu_src2);
|
|
||||||
if (xop & 0x10) {
|
if (xop & 0x10) {
|
||||||
tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
|
gen_helper_udiv_cc(cpu_dst, cpu_src1, cpu_src2);
|
||||||
tcg_gen_movi_i32(cpu_cc_op, CC_OP_DIV);
|
|
||||||
dc->cc_op = CC_OP_DIV;
|
dc->cc_op = CC_OP_DIV;
|
||||||
|
} else {
|
||||||
|
gen_helper_udiv(cpu_dst, cpu_src1, cpu_src2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xf: /* sdiv */
|
case 0xf: /* sdiv */
|
||||||
CHECK_IU_FEATURE(dc, DIV);
|
CHECK_IU_FEATURE(dc, DIV);
|
||||||
gen_helper_sdiv(cpu_dst, cpu_src1, cpu_src2);
|
|
||||||
if (xop & 0x10) {
|
if (xop & 0x10) {
|
||||||
tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
|
gen_helper_sdiv_cc(cpu_dst, cpu_src1, cpu_src2);
|
||||||
tcg_gen_movi_i32(cpu_cc_op, CC_OP_DIV);
|
|
||||||
dc->cc_op = CC_OP_DIV;
|
dc->cc_op = CC_OP_DIV;
|
||||||
|
} else {
|
||||||
|
gen_helper_sdiv(cpu_dst, cpu_src1, cpu_src2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
10
tcg/README
10
tcg/README
|
@ -75,11 +75,11 @@ destroyed, but local temporaries and globals are preserved.
|
||||||
* Helpers:
|
* Helpers:
|
||||||
|
|
||||||
Using the tcg_gen_helper_x_y it is possible to call any function
|
Using the tcg_gen_helper_x_y it is possible to call any function
|
||||||
taking i32, i64 or pointer types. By default, before calling an helper,
|
taking i32, i64 or pointer types. By default, before calling a helper,
|
||||||
all globals are stored at their canonical location and it is assumed
|
all globals are stored at their canonical location and it is assumed
|
||||||
that the function can modify them. This can be overriden by the
|
that the function can modify them. This can be overridden by the
|
||||||
TCG_CALL_CONST function modifier. By default, the helper is allowed to
|
TCG_CALL_CONST function modifier. By default, the helper is allowed to
|
||||||
modify the CPU state or raise an exception. This can be overriden by
|
modify the CPU state or raise an exception. This can be overridden by
|
||||||
the TCG_CALL_PURE function modifier, in which case the call to the
|
the TCG_CALL_PURE function modifier, in which case the call to the
|
||||||
function is removed if the return value is not used.
|
function is removed if the return value is not used.
|
||||||
|
|
||||||
|
@ -364,7 +364,7 @@ formed from two 32-bit arguments. The result is a 32-bit value.
|
||||||
|
|
||||||
********* QEMU specific operations
|
********* QEMU specific operations
|
||||||
|
|
||||||
* tb_exit t0
|
* exit_tb t0
|
||||||
|
|
||||||
Exit the current TB and return the value t0 (word type).
|
Exit the current TB and return the value t0 (word type).
|
||||||
|
|
||||||
|
@ -488,7 +488,7 @@ register.
|
||||||
the speed of the translation.
|
the speed of the translation.
|
||||||
|
|
||||||
- Don't hesitate to use helpers for complicated or seldom used target
|
- Don't hesitate to use helpers for complicated or seldom used target
|
||||||
intructions. There is little performance advantage in using TCG to
|
instructions. There is little performance advantage in using TCG to
|
||||||
implement target instructions taking more than about twenty TCG
|
implement target instructions taking more than about twenty TCG
|
||||||
instructions.
|
instructions.
|
||||||
|
|
||||||
|
|
|
@ -113,12 +113,25 @@ static const int tcg_target_call_oarg_regs[2] = {
|
||||||
TCG_REG_R0, TCG_REG_R1
|
TCG_REG_R0, TCG_REG_R1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline void reloc_abs32(void *code_ptr, tcg_target_long target)
|
||||||
|
{
|
||||||
|
*(uint32_t *) code_ptr = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void reloc_pc24(void *code_ptr, tcg_target_long target)
|
||||||
|
{
|
||||||
|
uint32_t offset = ((target - ((tcg_target_long) code_ptr + 8)) >> 2);
|
||||||
|
|
||||||
|
*(uint32_t *) code_ptr = ((*(uint32_t *) code_ptr) & ~0xffffff)
|
||||||
|
| (offset & 0xffffff);
|
||||||
|
}
|
||||||
|
|
||||||
static void patch_reloc(uint8_t *code_ptr, int type,
|
static void patch_reloc(uint8_t *code_ptr, int type,
|
||||||
tcg_target_long value, tcg_target_long addend)
|
tcg_target_long value, tcg_target_long addend)
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case R_ARM_ABS32:
|
case R_ARM_ABS32:
|
||||||
*(uint32_t *) code_ptr = value;
|
reloc_abs32(code_ptr, value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_ARM_CALL:
|
case R_ARM_CALL:
|
||||||
|
@ -127,8 +140,7 @@ static void patch_reloc(uint8_t *code_ptr, int type,
|
||||||
tcg_abort();
|
tcg_abort();
|
||||||
|
|
||||||
case R_ARM_PC24:
|
case R_ARM_PC24:
|
||||||
*(uint32_t *) code_ptr = ((*(uint32_t *) code_ptr) & 0xff000000) |
|
reloc_pc24(code_ptr, value);
|
||||||
(((value - ((tcg_target_long) code_ptr + 8)) >> 2) & 0xffffff);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -394,35 +406,38 @@ static inline void tcg_out_dat_imm(TCGContext *s,
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void tcg_out_movi32(TCGContext *s,
|
static inline void tcg_out_movi32(TCGContext *s,
|
||||||
int cond, int rd, int32_t arg)
|
int cond, int rd, uint32_t arg)
|
||||||
{
|
{
|
||||||
/* TODO: This is very suboptimal, we can easily have a constant
|
/* TODO: This is very suboptimal, we can easily have a constant
|
||||||
* pool somewhere after all the instructions. */
|
* pool somewhere after all the instructions. */
|
||||||
|
if ((int)arg < 0 && (int)arg >= -0x100) {
|
||||||
if (arg < 0 && arg > -0x100)
|
tcg_out_dat_imm(s, cond, ARITH_MVN, rd, 0, (~arg) & 0xff);
|
||||||
return tcg_out_dat_imm(s, cond, ARITH_MVN, rd, 0, (~arg) & 0xff);
|
} else if (use_armv7_instructions) {
|
||||||
|
|
||||||
if (use_armv7_instructions) {
|
|
||||||
/* use movw/movt */
|
/* use movw/movt */
|
||||||
/* movw */
|
/* movw */
|
||||||
tcg_out32(s, (cond << 28) | 0x03000000 | (rd << 12)
|
tcg_out32(s, (cond << 28) | 0x03000000 | (rd << 12)
|
||||||
| ((arg << 4) & 0x000f0000) | (arg & 0xfff));
|
| ((arg << 4) & 0x000f0000) | (arg & 0xfff));
|
||||||
if (arg & 0xffff0000)
|
if (arg & 0xffff0000) {
|
||||||
/* movt */
|
/* movt */
|
||||||
tcg_out32(s, (cond << 28) | 0x03400000 | (rd << 12)
|
tcg_out32(s, (cond << 28) | 0x03400000 | (rd << 12)
|
||||||
| ((arg >> 12) & 0x000f0000) | ((arg >> 16) & 0xfff));
|
| ((arg >> 12) & 0x000f0000) | ((arg >> 16) & 0xfff));
|
||||||
} else {
|
|
||||||
tcg_out_dat_imm(s, cond, ARITH_MOV, rd, 0, arg & 0xff);
|
|
||||||
if (arg & 0x0000ff00)
|
|
||||||
tcg_out_dat_imm(s, cond, ARITH_ORR, rd, rd,
|
|
||||||
((arg >> 8) & 0xff) | 0xc00);
|
|
||||||
if (arg & 0x00ff0000)
|
|
||||||
tcg_out_dat_imm(s, cond, ARITH_ORR, rd, rd,
|
|
||||||
((arg >> 16) & 0xff) | 0x800);
|
|
||||||
if (arg & 0xff000000)
|
|
||||||
tcg_out_dat_imm(s, cond, ARITH_ORR, rd, rd,
|
|
||||||
((arg >> 24) & 0xff) | 0x400);
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
int opc = ARITH_MOV;
|
||||||
|
int rn = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
int i, rot;
|
||||||
|
|
||||||
|
i = ctz32(arg) & ~1;
|
||||||
|
rot = ((32 - i) << 7) & 0xf00;
|
||||||
|
tcg_out_dat_imm(s, cond, opc, rd, rn, ((arg >> i) & 0xff) | rot);
|
||||||
|
arg &= ~(0xff << i);
|
||||||
|
|
||||||
|
opc = ARITH_ORR;
|
||||||
|
rn = rd;
|
||||||
|
} while (arg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void tcg_out_mul32(TCGContext *s,
|
static inline void tcg_out_mul32(TCGContext *s,
|
||||||
|
@ -1031,7 +1046,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
|
||||||
}
|
}
|
||||||
|
|
||||||
label_ptr = (void *) s->code_ptr;
|
label_ptr = (void *) s->code_ptr;
|
||||||
tcg_out_b(s, COND_EQ, 8);
|
tcg_out_b_noaddr(s, COND_EQ);
|
||||||
|
|
||||||
/* TODO: move this code to where the constants pool will be */
|
/* TODO: move this code to where the constants pool will be */
|
||||||
if (addr_reg != TCG_REG_R0) {
|
if (addr_reg != TCG_REG_R0) {
|
||||||
|
@ -1076,7 +1091,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
*label_ptr += ((void *) s->code_ptr - (void *) label_ptr - 8) >> 2;
|
reloc_pc24(label_ptr, (tcg_target_long)s->code_ptr);
|
||||||
#else /* !CONFIG_SOFTMMU */
|
#else /* !CONFIG_SOFTMMU */
|
||||||
if (GUEST_BASE) {
|
if (GUEST_BASE) {
|
||||||
uint32_t offset = GUEST_BASE;
|
uint32_t offset = GUEST_BASE;
|
||||||
|
@ -1236,7 +1251,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
|
||||||
tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg2);
|
tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg2);
|
||||||
tcg_out_st32_rwb(s, COND_EQ, TCG_REG_R0, TCG_REG_R1, addr_reg);
|
tcg_out_st32_rwb(s, COND_EQ, TCG_REG_R0, TCG_REG_R1, addr_reg);
|
||||||
tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg);
|
tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg);
|
||||||
tcg_out_st32_12(s, COND_EQ, data_reg, TCG_REG_R1, 4);
|
tcg_out_st32_12(s, COND_EQ, TCG_REG_R0, TCG_REG_R1, 4);
|
||||||
} else {
|
} else {
|
||||||
tcg_out_st32_rwb(s, COND_EQ, data_reg, TCG_REG_R1, addr_reg);
|
tcg_out_st32_rwb(s, COND_EQ, data_reg, TCG_REG_R1, addr_reg);
|
||||||
tcg_out_st32_12(s, COND_EQ, data_reg2, TCG_REG_R1, 4);
|
tcg_out_st32_12(s, COND_EQ, data_reg2, TCG_REG_R1, 4);
|
||||||
|
@ -1245,7 +1260,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
|
||||||
}
|
}
|
||||||
|
|
||||||
label_ptr = (void *) s->code_ptr;
|
label_ptr = (void *) s->code_ptr;
|
||||||
tcg_out_b(s, COND_EQ, 8);
|
tcg_out_b_noaddr(s, COND_EQ);
|
||||||
|
|
||||||
/* TODO: move this code to where the constants pool will be */
|
/* TODO: move this code to where the constants pool will be */
|
||||||
tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
|
tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
|
||||||
|
@ -1317,7 +1332,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
|
||||||
if (opc == 3)
|
if (opc == 3)
|
||||||
tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R13, TCG_REG_R13, 0x10);
|
tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R13, TCG_REG_R13, 0x10);
|
||||||
|
|
||||||
*label_ptr += ((void *) s->code_ptr - (void *) label_ptr - 8) >> 2;
|
reloc_pc24(label_ptr, (tcg_target_long)s->code_ptr);
|
||||||
#else /* !CONFIG_SOFTMMU */
|
#else /* !CONFIG_SOFTMMU */
|
||||||
if (GUEST_BASE) {
|
if (GUEST_BASE) {
|
||||||
uint32_t offset = GUEST_BASE;
|
uint32_t offset = GUEST_BASE;
|
||||||
|
@ -1399,7 +1414,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
||||||
/* Direct jump method */
|
/* Direct jump method */
|
||||||
#if defined(USE_DIRECT_JUMP)
|
#if defined(USE_DIRECT_JUMP)
|
||||||
s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
|
s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
|
||||||
tcg_out_b(s, COND_AL, 8);
|
tcg_out_b_noaddr(s, COND_AL);
|
||||||
#else
|
#else
|
||||||
tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
|
tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
|
||||||
s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
|
s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
|
||||||
|
|
|
@ -1329,7 +1329,7 @@ static inline void tcg_out_bswap32(TCGContext *s, TCGArg ret, TCGArg arg)
|
||||||
|
|
||||||
static inline void tcg_out_bswap64(TCGContext *s, TCGArg ret, TCGArg arg)
|
static inline void tcg_out_bswap64(TCGContext *s, TCGArg ret, TCGArg arg)
|
||||||
{
|
{
|
||||||
tcg_out_bundle(s, mII,
|
tcg_out_bundle(s, miI,
|
||||||
tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
|
tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
|
||||||
tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
|
tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
|
||||||
tcg_opc_i3 (TCG_REG_P0, OPC_MUX1_I3, ret, arg, 0xb));
|
tcg_opc_i3 (TCG_REG_P0, OPC_MUX1_I3, ret, arg, 0xb));
|
||||||
|
|
|
@ -352,7 +352,7 @@ static inline void tcg_out_opc_imm(TCGContext *s, int opc, int rt, int rs, int i
|
||||||
static inline void tcg_out_opc_br(TCGContext *s, int opc, int rt, int rs)
|
static inline void tcg_out_opc_br(TCGContext *s, int opc, int rt, int rs)
|
||||||
{
|
{
|
||||||
/* We need to keep the offset unchanged for retranslation */
|
/* We need to keep the offset unchanged for retranslation */
|
||||||
uint16_t offset = (uint16_t)(*(uint32_t *) &s->code_ptr);
|
uint16_t offset = (uint16_t)(*(uint32_t *) s->code_ptr);
|
||||||
|
|
||||||
tcg_out_opc_imm(s, opc, rt, rs, offset);
|
tcg_out_opc_imm(s, opc, rt, rs, offset);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,10 +32,18 @@ void qemu_spice_input_init(void);
|
||||||
void qemu_spice_audio_init(void);
|
void qemu_spice_audio_init(void);
|
||||||
void qemu_spice_display_init(DisplayState *ds);
|
void qemu_spice_display_init(DisplayState *ds);
|
||||||
int qemu_spice_add_interface(SpiceBaseInstance *sin);
|
int qemu_spice_add_interface(SpiceBaseInstance *sin);
|
||||||
|
int qemu_spice_set_passwd(const char *passwd,
|
||||||
|
bool fail_if_connected, bool disconnect_if_connected);
|
||||||
|
int qemu_spice_set_pw_expire(time_t expires);
|
||||||
|
|
||||||
|
void do_info_spice_print(Monitor *mon, const QObject *data);
|
||||||
|
void do_info_spice(Monitor *mon, QObject **ret_data);
|
||||||
|
|
||||||
#else /* CONFIG_SPICE */
|
#else /* CONFIG_SPICE */
|
||||||
|
|
||||||
#define using_spice 0
|
#define using_spice 0
|
||||||
|
#define qemu_spice_set_passwd(_p, _f1, _f2) (-1)
|
||||||
|
#define qemu_spice_set_pw_expire(_e) (-1)
|
||||||
|
|
||||||
#endif /* CONFIG_SPICE */
|
#endif /* CONFIG_SPICE */
|
||||||
|
|
||||||
|
|
261
ui/spice-core.c
261
ui/spice-core.c
|
@ -18,16 +18,26 @@
|
||||||
#include <spice.h>
|
#include <spice.h>
|
||||||
#include <spice-experimental.h>
|
#include <spice-experimental.h>
|
||||||
|
|
||||||
|
#include <netdb.h>
|
||||||
|
|
||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
#include "qemu-spice.h"
|
#include "qemu-spice.h"
|
||||||
#include "qemu-timer.h"
|
#include "qemu-timer.h"
|
||||||
#include "qemu-queue.h"
|
#include "qemu-queue.h"
|
||||||
#include "qemu-x509.h"
|
#include "qemu-x509.h"
|
||||||
|
#include "qemu_socket.h"
|
||||||
|
#include "qint.h"
|
||||||
|
#include "qbool.h"
|
||||||
|
#include "qstring.h"
|
||||||
|
#include "qjson.h"
|
||||||
#include "monitor.h"
|
#include "monitor.h"
|
||||||
|
|
||||||
/* core bits */
|
/* core bits */
|
||||||
|
|
||||||
static SpiceServer *spice_server;
|
static SpiceServer *spice_server;
|
||||||
|
static const char *auth = "spice";
|
||||||
|
static char *auth_passwd;
|
||||||
|
static time_t auth_expires = TIME_MAX;
|
||||||
int using_spice = 0;
|
int using_spice = 0;
|
||||||
|
|
||||||
struct SpiceTimer {
|
struct SpiceTimer {
|
||||||
|
@ -121,6 +131,118 @@ static void watch_remove(SpiceWatch *watch)
|
||||||
qemu_free(watch);
|
qemu_free(watch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if SPICE_INTERFACE_CORE_MINOR >= 3
|
||||||
|
|
||||||
|
typedef struct ChannelList ChannelList;
|
||||||
|
struct ChannelList {
|
||||||
|
SpiceChannelEventInfo *info;
|
||||||
|
QTAILQ_ENTRY(ChannelList) link;
|
||||||
|
};
|
||||||
|
static QTAILQ_HEAD(, ChannelList) channel_list = QTAILQ_HEAD_INITIALIZER(channel_list);
|
||||||
|
|
||||||
|
static void channel_list_add(SpiceChannelEventInfo *info)
|
||||||
|
{
|
||||||
|
ChannelList *item;
|
||||||
|
|
||||||
|
item = qemu_mallocz(sizeof(*item));
|
||||||
|
item->info = info;
|
||||||
|
QTAILQ_INSERT_TAIL(&channel_list, item, link);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void channel_list_del(SpiceChannelEventInfo *info)
|
||||||
|
{
|
||||||
|
ChannelList *item;
|
||||||
|
|
||||||
|
QTAILQ_FOREACH(item, &channel_list, link) {
|
||||||
|
if (item->info != info) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
QTAILQ_REMOVE(&channel_list, item, link);
|
||||||
|
qemu_free(item);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_addr_info(QDict *dict, struct sockaddr *addr, int len)
|
||||||
|
{
|
||||||
|
char host[NI_MAXHOST], port[NI_MAXSERV];
|
||||||
|
const char *family;
|
||||||
|
|
||||||
|
getnameinfo(addr, len, host, sizeof(host), port, sizeof(port),
|
||||||
|
NI_NUMERICHOST | NI_NUMERICSERV);
|
||||||
|
family = inet_strfamily(addr->sa_family);
|
||||||
|
|
||||||
|
qdict_put(dict, "host", qstring_from_str(host));
|
||||||
|
qdict_put(dict, "port", qstring_from_str(port));
|
||||||
|
qdict_put(dict, "family", qstring_from_str(family));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_channel_info(QDict *dict, SpiceChannelEventInfo *info)
|
||||||
|
{
|
||||||
|
int tls = info->flags & SPICE_CHANNEL_EVENT_FLAG_TLS;
|
||||||
|
|
||||||
|
qdict_put(dict, "connection-id", qint_from_int(info->connection_id));
|
||||||
|
qdict_put(dict, "channel-type", qint_from_int(info->type));
|
||||||
|
qdict_put(dict, "channel-id", qint_from_int(info->id));
|
||||||
|
qdict_put(dict, "tls", qbool_from_int(tls));
|
||||||
|
}
|
||||||
|
|
||||||
|
static QList *channel_list_get(void)
|
||||||
|
{
|
||||||
|
ChannelList *item;
|
||||||
|
QList *list;
|
||||||
|
QDict *dict;
|
||||||
|
|
||||||
|
list = qlist_new();
|
||||||
|
QTAILQ_FOREACH(item, &channel_list, link) {
|
||||||
|
dict = qdict_new();
|
||||||
|
add_addr_info(dict, &item->info->paddr, item->info->plen);
|
||||||
|
add_channel_info(dict, item->info);
|
||||||
|
qlist_append(list, dict);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void channel_event(int event, SpiceChannelEventInfo *info)
|
||||||
|
{
|
||||||
|
static const int qevent[] = {
|
||||||
|
[ SPICE_CHANNEL_EVENT_CONNECTED ] = QEVENT_SPICE_CONNECTED,
|
||||||
|
[ SPICE_CHANNEL_EVENT_INITIALIZED ] = QEVENT_SPICE_INITIALIZED,
|
||||||
|
[ SPICE_CHANNEL_EVENT_DISCONNECTED ] = QEVENT_SPICE_DISCONNECTED,
|
||||||
|
};
|
||||||
|
QDict *server, *client;
|
||||||
|
QObject *data;
|
||||||
|
|
||||||
|
client = qdict_new();
|
||||||
|
add_addr_info(client, &info->paddr, info->plen);
|
||||||
|
|
||||||
|
server = qdict_new();
|
||||||
|
add_addr_info(server, &info->laddr, info->llen);
|
||||||
|
|
||||||
|
if (event == SPICE_CHANNEL_EVENT_INITIALIZED) {
|
||||||
|
qdict_put(server, "auth", qstring_from_str(auth));
|
||||||
|
add_channel_info(client, info);
|
||||||
|
channel_list_add(info);
|
||||||
|
}
|
||||||
|
if (event == SPICE_CHANNEL_EVENT_DISCONNECTED) {
|
||||||
|
channel_list_del(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
data = qobject_from_jsonf("{ 'client': %p, 'server': %p }",
|
||||||
|
QOBJECT(client), QOBJECT(server));
|
||||||
|
monitor_protocol_event(qevent[event], data);
|
||||||
|
qobject_decref(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* SPICE_INTERFACE_CORE_MINOR >= 3 */
|
||||||
|
|
||||||
|
static QList *channel_list_get(void)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* SPICE_INTERFACE_CORE_MINOR >= 3 */
|
||||||
|
|
||||||
static SpiceCoreInterface core_interface = {
|
static SpiceCoreInterface core_interface = {
|
||||||
.base.type = SPICE_INTERFACE_CORE,
|
.base.type = SPICE_INTERFACE_CORE,
|
||||||
.base.description = "qemu core services",
|
.base.description = "qemu core services",
|
||||||
|
@ -135,6 +257,10 @@ static SpiceCoreInterface core_interface = {
|
||||||
.watch_add = watch_add,
|
.watch_add = watch_add,
|
||||||
.watch_update_mask = watch_update_mask,
|
.watch_update_mask = watch_update_mask,
|
||||||
.watch_remove = watch_remove,
|
.watch_remove = watch_remove,
|
||||||
|
|
||||||
|
#if SPICE_INTERFACE_CORE_MINOR >= 3
|
||||||
|
.channel_event = channel_event,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/* config string parsing */
|
/* config string parsing */
|
||||||
|
@ -204,6 +330,92 @@ static const char *wan_compression_names[] = {
|
||||||
|
|
||||||
/* functions for the rest of qemu */
|
/* functions for the rest of qemu */
|
||||||
|
|
||||||
|
static void info_spice_iter(QObject *obj, void *opaque)
|
||||||
|
{
|
||||||
|
QDict *client;
|
||||||
|
Monitor *mon = opaque;
|
||||||
|
|
||||||
|
client = qobject_to_qdict(obj);
|
||||||
|
monitor_printf(mon, "Channel:\n");
|
||||||
|
monitor_printf(mon, " address: %s:%s%s\n",
|
||||||
|
qdict_get_str(client, "host"),
|
||||||
|
qdict_get_str(client, "port"),
|
||||||
|
qdict_get_bool(client, "tls") ? " [tls]" : "");
|
||||||
|
monitor_printf(mon, " session: %" PRId64 "\n",
|
||||||
|
qdict_get_int(client, "connection-id"));
|
||||||
|
monitor_printf(mon, " channel: %d:%d\n",
|
||||||
|
(int)qdict_get_int(client, "channel-type"),
|
||||||
|
(int)qdict_get_int(client, "channel-id"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void do_info_spice_print(Monitor *mon, const QObject *data)
|
||||||
|
{
|
||||||
|
QDict *server;
|
||||||
|
QList *channels;
|
||||||
|
const char *host;
|
||||||
|
int port;
|
||||||
|
|
||||||
|
server = qobject_to_qdict(data);
|
||||||
|
if (qdict_get_bool(server, "enabled") == 0) {
|
||||||
|
monitor_printf(mon, "Server: disabled\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
monitor_printf(mon, "Server:\n");
|
||||||
|
host = qdict_get_str(server, "host");
|
||||||
|
port = qdict_get_try_int(server, "port", -1);
|
||||||
|
if (port != -1) {
|
||||||
|
monitor_printf(mon, " address: %s:%d\n", host, port);
|
||||||
|
}
|
||||||
|
port = qdict_get_try_int(server, "tls-port", -1);
|
||||||
|
if (port != -1) {
|
||||||
|
monitor_printf(mon, " address: %s:%d [tls]\n", host, port);
|
||||||
|
}
|
||||||
|
monitor_printf(mon, " auth: %s\n", qdict_get_str(server, "auth"));
|
||||||
|
|
||||||
|
channels = qdict_get_qlist(server, "channels");
|
||||||
|
if (qlist_empty(channels)) {
|
||||||
|
monitor_printf(mon, "Channels: none\n");
|
||||||
|
} else {
|
||||||
|
qlist_iter(channels, info_spice_iter, mon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void do_info_spice(Monitor *mon, QObject **ret_data)
|
||||||
|
{
|
||||||
|
QemuOpts *opts = QTAILQ_FIRST(&qemu_spice_opts.head);
|
||||||
|
QDict *server;
|
||||||
|
QList *clist;
|
||||||
|
const char *addr;
|
||||||
|
int port, tls_port;
|
||||||
|
|
||||||
|
if (!spice_server) {
|
||||||
|
*ret_data = qobject_from_jsonf("{ 'enabled': false }");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = qemu_opt_get(opts, "addr");
|
||||||
|
port = qemu_opt_get_number(opts, "port", 0);
|
||||||
|
tls_port = qemu_opt_get_number(opts, "tls-port", 0);
|
||||||
|
clist = channel_list_get();
|
||||||
|
|
||||||
|
server = qdict_new();
|
||||||
|
qdict_put(server, "enabled", qbool_from_int(true));
|
||||||
|
qdict_put(server, "auth", qstring_from_str(auth));
|
||||||
|
qdict_put(server, "host", qstring_from_str(addr ? addr : "0.0.0.0"));
|
||||||
|
if (port) {
|
||||||
|
qdict_put(server, "port", qint_from_int(port));
|
||||||
|
}
|
||||||
|
if (tls_port) {
|
||||||
|
qdict_put(server, "tls-port", qint_from_int(tls_port));
|
||||||
|
}
|
||||||
|
if (clist) {
|
||||||
|
qdict_put(server, "channels", clist);
|
||||||
|
}
|
||||||
|
|
||||||
|
*ret_data = QOBJECT(server);
|
||||||
|
}
|
||||||
|
|
||||||
static int add_channel(const char *name, const char *value, void *opaque)
|
static int add_channel(const char *name, const char *value, void *opaque)
|
||||||
{
|
{
|
||||||
int security = 0;
|
int security = 0;
|
||||||
|
@ -316,6 +528,7 @@ void qemu_spice_init(void)
|
||||||
spice_server_set_ticket(spice_server, password, 0, 0, 0);
|
spice_server_set_ticket(spice_server, password, 0, 0, 0);
|
||||||
}
|
}
|
||||||
if (qemu_opt_get_bool(opts, "disable-ticketing", 0)) {
|
if (qemu_opt_get_bool(opts, "disable-ticketing", 0)) {
|
||||||
|
auth = "none";
|
||||||
spice_server_set_noauth(spice_server);
|
spice_server_set_noauth(spice_server);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,9 +583,57 @@ void qemu_spice_init(void)
|
||||||
|
|
||||||
int qemu_spice_add_interface(SpiceBaseInstance *sin)
|
int qemu_spice_add_interface(SpiceBaseInstance *sin)
|
||||||
{
|
{
|
||||||
|
if (!spice_server) {
|
||||||
|
if (QTAILQ_FIRST(&qemu_spice_opts.head) != NULL) {
|
||||||
|
fprintf(stderr, "Oops: spice configured but not active\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Create a spice server instance.
|
||||||
|
* It does *not* listen on the network.
|
||||||
|
* It handles QXL local rendering only.
|
||||||
|
*
|
||||||
|
* With a command line like '-vnc :0 -vga qxl' you'll end up here.
|
||||||
|
*/
|
||||||
|
spice_server = spice_server_new();
|
||||||
|
spice_server_init(spice_server, &core_interface);
|
||||||
|
}
|
||||||
return spice_server_add_interface(spice_server, sin);
|
return spice_server_add_interface(spice_server, sin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int qemu_spice_set_ticket(bool fail_if_conn, bool disconnect_if_conn)
|
||||||
|
{
|
||||||
|
time_t lifetime, now = time(NULL);
|
||||||
|
char *passwd;
|
||||||
|
|
||||||
|
if (now < auth_expires) {
|
||||||
|
passwd = auth_passwd;
|
||||||
|
lifetime = (auth_expires - now);
|
||||||
|
if (lifetime > INT_MAX) {
|
||||||
|
lifetime = INT_MAX;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
passwd = NULL;
|
||||||
|
lifetime = 1;
|
||||||
|
}
|
||||||
|
return spice_server_set_ticket(spice_server, passwd, lifetime,
|
||||||
|
fail_if_conn, disconnect_if_conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
int qemu_spice_set_passwd(const char *passwd,
|
||||||
|
bool fail_if_conn, bool disconnect_if_conn)
|
||||||
|
{
|
||||||
|
free(auth_passwd);
|
||||||
|
auth_passwd = strdup(passwd);
|
||||||
|
return qemu_spice_set_ticket(fail_if_conn, disconnect_if_conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
int qemu_spice_set_pw_expire(time_t expires)
|
||||||
|
{
|
||||||
|
auth_expires = expires;
|
||||||
|
return qemu_spice_set_ticket(false, false);
|
||||||
|
}
|
||||||
|
|
||||||
static void spice_register_config(void)
|
static void spice_register_config(void)
|
||||||
{
|
{
|
||||||
qemu_add_opts(&qemu_spice_opts);
|
qemu_add_opts(&qemu_spice_opts);
|
||||||
|
|
44
ui/vnc.c
44
ui/vnc.c
|
@ -2082,18 +2082,15 @@ static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len)
|
||||||
unsigned char response[VNC_AUTH_CHALLENGE_SIZE];
|
unsigned char response[VNC_AUTH_CHALLENGE_SIZE];
|
||||||
int i, j, pwlen;
|
int i, j, pwlen;
|
||||||
unsigned char key[8];
|
unsigned char key[8];
|
||||||
|
time_t now = time(NULL);
|
||||||
|
|
||||||
if (!vs->vd->password || !vs->vd->password[0]) {
|
if (!vs->vd->password || !vs->vd->password[0]) {
|
||||||
VNC_DEBUG("No password configured on server");
|
VNC_DEBUG("No password configured on server");
|
||||||
vnc_write_u32(vs, 1); /* Reject auth */
|
goto reject;
|
||||||
if (vs->minor >= 8) {
|
}
|
||||||
static const char err[] = "Authentication failed";
|
if (vs->vd->expires < now) {
|
||||||
vnc_write_u32(vs, sizeof(err));
|
VNC_DEBUG("Password is expired");
|
||||||
vnc_write(vs, err, sizeof(err));
|
goto reject;
|
||||||
}
|
|
||||||
vnc_flush(vs);
|
|
||||||
vnc_client_error(vs);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(response, vs->challenge, VNC_AUTH_CHALLENGE_SIZE);
|
memcpy(response, vs->challenge, VNC_AUTH_CHALLENGE_SIZE);
|
||||||
|
@ -2109,14 +2106,7 @@ static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len)
|
||||||
/* Compare expected vs actual challenge response */
|
/* Compare expected vs actual challenge response */
|
||||||
if (memcmp(response, data, VNC_AUTH_CHALLENGE_SIZE) != 0) {
|
if (memcmp(response, data, VNC_AUTH_CHALLENGE_SIZE) != 0) {
|
||||||
VNC_DEBUG("Client challenge reponse did not match\n");
|
VNC_DEBUG("Client challenge reponse did not match\n");
|
||||||
vnc_write_u32(vs, 1); /* Reject auth */
|
goto reject;
|
||||||
if (vs->minor >= 8) {
|
|
||||||
static const char err[] = "Authentication failed";
|
|
||||||
vnc_write_u32(vs, sizeof(err));
|
|
||||||
vnc_write(vs, err, sizeof(err));
|
|
||||||
}
|
|
||||||
vnc_flush(vs);
|
|
||||||
vnc_client_error(vs);
|
|
||||||
} else {
|
} else {
|
||||||
VNC_DEBUG("Accepting VNC challenge response\n");
|
VNC_DEBUG("Accepting VNC challenge response\n");
|
||||||
vnc_write_u32(vs, 0); /* Accept auth */
|
vnc_write_u32(vs, 0); /* Accept auth */
|
||||||
|
@ -2125,6 +2115,17 @@ static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len)
|
||||||
start_client_init(vs);
|
start_client_init(vs);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
reject:
|
||||||
|
vnc_write_u32(vs, 1); /* Reject auth */
|
||||||
|
if (vs->minor >= 8) {
|
||||||
|
static const char err[] = "Authentication failed";
|
||||||
|
vnc_write_u32(vs, sizeof(err));
|
||||||
|
vnc_write(vs, err, sizeof(err));
|
||||||
|
}
|
||||||
|
vnc_flush(vs);
|
||||||
|
vnc_client_error(vs);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void start_auth_vnc(VncState *vs)
|
void start_auth_vnc(VncState *vs)
|
||||||
|
@ -2436,6 +2437,7 @@ void vnc_display_init(DisplayState *ds)
|
||||||
|
|
||||||
vs->ds = ds;
|
vs->ds = ds;
|
||||||
QTAILQ_INIT(&vs->clients);
|
QTAILQ_INIT(&vs->clients);
|
||||||
|
vs->expires = TIME_MAX;
|
||||||
|
|
||||||
if (keyboard_layout)
|
if (keyboard_layout)
|
||||||
vs->kbd_layout = init_keyboard_layout(name2keysym, keyboard_layout);
|
vs->kbd_layout = init_keyboard_layout(name2keysym, keyboard_layout);
|
||||||
|
@ -2507,6 +2509,14 @@ int vnc_display_password(DisplayState *ds, const char *password)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int vnc_display_pw_expire(DisplayState *ds, time_t expires)
|
||||||
|
{
|
||||||
|
VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
|
||||||
|
|
||||||
|
vs->expires = expires;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
char *vnc_display_local_addr(DisplayState *ds)
|
char *vnc_display_local_addr(DisplayState *ds)
|
||||||
{
|
{
|
||||||
VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
|
VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
|
||||||
|
|
1
ui/vnc.h
1
ui/vnc.h
|
@ -120,6 +120,7 @@ struct VncDisplay
|
||||||
|
|
||||||
char *display;
|
char *display;
|
||||||
char *password;
|
char *password;
|
||||||
|
time_t expires;
|
||||||
int auth;
|
int auth;
|
||||||
bool lossy;
|
bool lossy;
|
||||||
#ifdef CONFIG_VNC_TLS
|
#ifdef CONFIG_VNC_TLS
|
||||||
|
|
83
usb-bsd.c
83
usb-bsd.c
|
@ -306,14 +306,15 @@ USBDevice *usb_host_device_open(const char *devname)
|
||||||
{
|
{
|
||||||
struct usb_device_info bus_info, dev_info;
|
struct usb_device_info bus_info, dev_info;
|
||||||
USBDevice *d = NULL;
|
USBDevice *d = NULL;
|
||||||
USBHostDevice *dev;
|
USBHostDevice *dev, *ret = NULL;
|
||||||
char ctlpath[PATH_MAX + 1];
|
char ctlpath[PATH_MAX + 1];
|
||||||
char buspath[PATH_MAX + 1];
|
char buspath[PATH_MAX + 1];
|
||||||
int bfd, dfd, bus, address, i;
|
int bfd, dfd, bus, address, i;
|
||||||
int ugendebug = UGEN_DEBUG_LEVEL;
|
int ugendebug = UGEN_DEBUG_LEVEL;
|
||||||
|
|
||||||
if (usb_host_find_device(&bus, &address, devname) < 0)
|
if (usb_host_find_device(&bus, &address, devname) < 0) {
|
||||||
return NULL;
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
snprintf(buspath, PATH_MAX, "/dev/usb%d", bus);
|
snprintf(buspath, PATH_MAX, "/dev/usb%d", bus);
|
||||||
|
|
||||||
|
@ -323,7 +324,7 @@ USBDevice *usb_host_device_open(const char *devname)
|
||||||
printf("usb_host_device_open: failed to open usb bus - %s\n",
|
printf("usb_host_device_open: failed to open usb bus - %s\n",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
#endif
|
#endif
|
||||||
return NULL;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
bus_info.udi_addr = address;
|
bus_info.udi_addr = address;
|
||||||
|
@ -332,7 +333,7 @@ USBDevice *usb_host_device_open(const char *devname)
|
||||||
printf("usb_host_device_open: failed to grab bus information - %s\n",
|
printf("usb_host_device_open: failed to grab bus information - %s\n",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
#endif
|
#endif
|
||||||
return NULL;
|
goto fail_bfd;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
|
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
|
||||||
|
@ -350,46 +351,52 @@ USBDevice *usb_host_device_open(const char *devname)
|
||||||
ctlpath, strerror(errno));
|
ctlpath, strerror(errno));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
goto fail_dfd;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dfd >= 0) {
|
if (ioctl(dfd, USB_GET_DEVICEINFO, &dev_info) < 0) {
|
||||||
if (ioctl(dfd, USB_GET_DEVICEINFO, &dev_info) < 0) {
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf("usb_host_device_open: failed to grab device info - %s\n",
|
printf("usb_host_device_open: failed to grab device info - %s\n",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
#endif
|
#endif
|
||||||
goto fail;
|
goto fail_dfd;
|
||||||
}
|
|
||||||
|
|
||||||
d = usb_create(NULL /* FIXME */, "usb-host");
|
|
||||||
dev = DO_UPCAST(USBHostDevice, dev, d);
|
|
||||||
|
|
||||||
if (dev_info.udi_speed == 1)
|
|
||||||
dev->dev.speed = USB_SPEED_LOW - 1;
|
|
||||||
else
|
|
||||||
dev->dev.speed = USB_SPEED_FULL - 1;
|
|
||||||
|
|
||||||
if (strncmp(dev_info.udi_product, "product", 7) != 0)
|
|
||||||
pstrcpy(dev->dev.product_desc, sizeof(dev->dev.product_desc),
|
|
||||||
dev_info.udi_product);
|
|
||||||
else
|
|
||||||
snprintf(dev->dev.product_desc, sizeof(dev->dev.product_desc),
|
|
||||||
"host:%s", devname);
|
|
||||||
|
|
||||||
pstrcpy(dev->devpath, sizeof(dev->devpath), "/dev/");
|
|
||||||
pstrcat(dev->devpath, sizeof(dev->devpath), dev_info.udi_devnames[0]);
|
|
||||||
|
|
||||||
/* Mark the endpoints as not yet open */
|
|
||||||
for (i = 0; i < USB_MAX_ENDPOINTS; i++)
|
|
||||||
dev->ep_fd[i] = -1;
|
|
||||||
|
|
||||||
ioctl(dfd, USB_SETDEBUG, &ugendebug);
|
|
||||||
|
|
||||||
return (USBDevice *)dev;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
d = usb_create(NULL /* FIXME */, "usb-host");
|
||||||
|
dev = DO_UPCAST(USBHostDevice, dev, d);
|
||||||
|
|
||||||
|
if (dev_info.udi_speed == 1) {
|
||||||
|
dev->dev.speed = USB_SPEED_LOW - 1;
|
||||||
|
} else {
|
||||||
|
dev->dev.speed = USB_SPEED_FULL - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strncmp(dev_info.udi_product, "product", 7) != 0) {
|
||||||
|
pstrcpy(dev->dev.product_desc, sizeof(dev->dev.product_desc),
|
||||||
|
dev_info.udi_product);
|
||||||
|
} else {
|
||||||
|
snprintf(dev->dev.product_desc, sizeof(dev->dev.product_desc),
|
||||||
|
"host:%s", devname);
|
||||||
|
}
|
||||||
|
|
||||||
|
pstrcpy(dev->devpath, sizeof(dev->devpath), "/dev/");
|
||||||
|
pstrcat(dev->devpath, sizeof(dev->devpath), dev_info.udi_devnames[0]);
|
||||||
|
|
||||||
|
/* Mark the endpoints as not yet open */
|
||||||
|
for (i = 0; i < USB_MAX_ENDPOINTS; i++) {
|
||||||
|
dev->ep_fd[i] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ioctl(dfd, USB_SETDEBUG, &ugendebug);
|
||||||
|
|
||||||
|
ret = (USBDevice *)dev;
|
||||||
|
|
||||||
|
fail_dfd:
|
||||||
|
close(dfd);
|
||||||
|
fail_bfd:
|
||||||
|
close(bfd);
|
||||||
fail:
|
fail:
|
||||||
return NULL;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct USBDeviceInfo usb_host_dev_info = {
|
static struct USBDeviceInfo usb_host_dev_info = {
|
||||||
|
|
12
vl.c
12
vl.c
|
@ -759,8 +759,10 @@ char *get_boot_devices_list(uint32_t *size)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i->suffix && devpath) {
|
if (i->suffix && devpath) {
|
||||||
bootpath = qemu_malloc(strlen(devpath) + strlen(i->suffix) + 1);
|
size_t bootpathlen = strlen(devpath) + strlen(i->suffix) + 1;
|
||||||
sprintf(bootpath, "%s%s", devpath, i->suffix);
|
|
||||||
|
bootpath = qemu_malloc(bootpathlen);
|
||||||
|
snprintf(bootpath, bootpathlen, "%s%s", devpath, i->suffix);
|
||||||
qemu_free(devpath);
|
qemu_free(devpath);
|
||||||
} else if (devpath) {
|
} else if (devpath) {
|
||||||
bootpath = devpath;
|
bootpath = devpath;
|
||||||
|
@ -1502,6 +1504,8 @@ static void select_vgahw (const char *p)
|
||||||
vga_interface_type = VGA_VMWARE;
|
vga_interface_type = VGA_VMWARE;
|
||||||
} else if (strstart(p, "xenfb", &opts)) {
|
} else if (strstart(p, "xenfb", &opts)) {
|
||||||
vga_interface_type = VGA_XENFB;
|
vga_interface_type = VGA_XENFB;
|
||||||
|
} else if (strstart(p, "qxl", &opts)) {
|
||||||
|
vga_interface_type = VGA_QXL;
|
||||||
} else if (!strstart(p, "none", &opts)) {
|
} else if (!strstart(p, "none", &opts)) {
|
||||||
invalid_vga:
|
invalid_vga:
|
||||||
fprintf(stderr, "Unknown vga type: %s\n", p);
|
fprintf(stderr, "Unknown vga type: %s\n", p);
|
||||||
|
@ -2601,7 +2605,7 @@ int main(int argc, char **argv, char **envp)
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
*p++ = 0;
|
*p++ = 0;
|
||||||
if (strncmp(p, "process=", 8)) {
|
if (strncmp(p, "process=", 8)) {
|
||||||
fprintf(stderr, "Unknown subargument %s to -name", p);
|
fprintf(stderr, "Unknown subargument %s to -name\n", p);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
p += 8;
|
p += 8;
|
||||||
|
@ -3053,7 +3057,7 @@ int main(int argc, char **argv, char **envp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_SPICE
|
#ifdef CONFIG_SPICE
|
||||||
if (using_spice) {
|
if (using_spice && !qxl_enabled) {
|
||||||
qemu_spice_display_init(ds);
|
qemu_spice_display_init(ds);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue