aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS65
-rw-r--r--arm-dis.c24
-rw-r--r--audio/alsaaudio.c2
-rw-r--r--audio/audio.c11
-rw-r--r--audio/audio_int.h2
-rw-r--r--audio/dsoundaudio.c4
-rw-r--r--audio/esdaudio.c3
-rw-r--r--audio/fmodaudio.c4
-rw-r--r--audio/mixeng.c25
-rw-r--r--audio/mixeng.h4
-rw-r--r--audio/mixeng_template.h39
-rw-r--r--audio/ossaudio.c3
-rw-r--r--audio/paaudio.c2
-rw-r--r--audio/spiceaudio.c5
-rw-r--r--audio/winwaveaudio.c3
-rw-r--r--block/vpc.c47
-rw-r--r--block/vvfat.c1
-rw-r--r--bsd-user/elfload.c37
-rwxr-xr-xconfigure464
-rw-r--r--disas.c5
-rw-r--r--exec.c7
-rw-r--r--fpu/softfloat-specialize.h58
-rw-r--r--fpu/softfloat.h5
-rw-r--r--gdbstub.c6
-rw-r--r--hw/arm_sysctl.c17
-rw-r--r--hw/gt64xxx.c115
-rw-r--r--hw/lan9118.c4
-rw-r--r--hw/loader.c5
-rw-r--r--hw/lsi53c895a.c4
-rw-r--r--hw/m48t59.c11
-rw-r--r--hw/mainstone.c3
-rw-r--r--hw/mips.h2
-rw-r--r--hw/mips_malta.c4
-rw-r--r--hw/mips_timer.c44
-rw-r--r--hw/pl031.c25
-rw-r--r--hw/pl050.c35
-rw-r--r--hw/pl080.c58
-rw-r--r--hw/pl110.c44
-rw-r--r--hw/pl190.c36
-rw-r--r--hw/ppc405_uc.c5
-rw-r--r--hw/pxa2xx.c2
-rw-r--r--hw/pxa2xx_lcd.c4
-rw-r--r--hw/r2d.c31
-rw-r--r--hw/sh_pci.c105
-rw-r--r--hw/sh_pci.h9
-rw-r--r--hw/sh_serial.c59
-rw-r--r--hw/sm501.c40
-rw-r--r--hw/smc91c111.c30
-rw-r--r--hw/usb-hid.c5
-rw-r--r--hw/versatilepb.c24
-rw-r--r--hw/zaurus.c4
-rw-r--r--linux-user/ioctls.h2
-rw-r--r--linux-user/signal.c16
-rw-r--r--linux-user/syscall.c4
-rw-r--r--make_device_config.sh2
-rw-r--r--monitor.c4
-rw-r--r--pc-bios/keymaps/bepo333
-rw-r--r--qemu-io.c4
-rw-r--r--rules.mak6
-rw-r--r--slirp/tftp.c4
-rw-r--r--target-arm/cpu.h64
-rw-r--r--target-arm/helper.c29
-rw-r--r--target-arm/helpers.h4
-rw-r--r--target-arm/neon_helper.c47
-rw-r--r--target-arm/translate.c223
-rw-r--r--target-cris/translate.c3
-rw-r--r--target-i386/translate.c34
-rw-r--r--target-microblaze/translate.c192
-rw-r--r--target-mips/translate.c8
-rw-r--r--target-ppc/op_helper.c192
-rw-r--r--target-sh4/cpu.h49
-rw-r--r--target-sh4/helper.c4
-rw-r--r--target-sh4/helper.h3
-rw-r--r--target-sh4/op_helper.c249
-rw-r--r--target-sh4/translate.c162
-rw-r--r--target-sparc/op_helper.c56
-rw-r--r--tcg/README14
-rw-r--r--tcg/arm/tcg-target.c3
-rw-r--r--tcg/ia64/tcg-target.c3
-rw-r--r--tcg/mips/tcg-target.c4
-rw-r--r--tcg/tcg-op.h64
-rw-r--r--tcg/tcg-opc.h6
-rw-r--r--tests/Makefile3
-rw-r--r--tests/cris/check_abs.c5
-rw-r--r--tests/cris/check_addc.c3
-rw-r--r--tests/cris/check_addcm.c6
-rw-r--r--tests/cris/check_bound.c9
-rw-r--r--tests/cris/check_ftag.c12
-rw-r--r--tests/cris/check_int64.c6
-rw-r--r--tests/cris/check_lz.c2
-rw-r--r--tests/cris/check_swap.c2
-rw-r--r--tests/cris/crisutils.h20
-rw-r--r--tests/hello-i386.c4
-rw-r--r--ui/vnc-auth-sasl.c14
94 files changed, 2441 insertions, 984 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 59effc7143..98db32216f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -81,8 +81,8 @@ S: Maintained
F: target-microblaze/
MIPS
-M: qemu-devel@nongnu.org
-S: Orphan
+M: Aurelien Jarno <aurelien@aurel32.net>
+S: Maintained
F: target-mips/
PowerPC
@@ -96,8 +96,8 @@ S: Maintained
F: target-s390x/
SH4
-M: qemu-devel@nongnu.org
-S: Orphan
+M: Aurelien Jarno <aurelien@aurel32.net>
+S: Maintained
F: target-sh4/
SPARC
@@ -202,7 +202,7 @@ M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
S: Maintained
F: hw/etraxfs.c
-M86K Machines
+M68K Machines
-------------
an5206
M: Paul Brook <paul@codesourcery.com>
@@ -279,7 +279,7 @@ F: hw/r2d.c
Shix
M: Magnus Damm <magnus.damm@gmail.com>
-S: Oprhan
+S: Orphan
F: hw/shix.c
SPARC Machines
@@ -426,3 +426,56 @@ Linux user
M: Riku Voipio <riku.voipio@iki.fi>
S: Maintained
F: linux-user/
+
+Tiny Code Generator (TCG)
+-------------------------
+Common code
+M: qemu-devel@nongnu.org
+S: Maintained
+F: tcg/
+
+ARM target
+M: Andrzej Zaborowski <balrogg@gmail.com>
+S: Maintained
+F: tcg/arm/
+
+HPPA target
+M: Richard Henderson <rth@twiddle.net>
+S: Maintained
+F: tcg/hppa/
+
+i386 target
+M: qemu-devel@nongnu.org
+S: Maintained
+F: tcg/i386/
+
+IA64 target
+M: Aurelien Jarno <aurelien@aurel32.net>
+S: Maintained
+F: tcg/ia64/
+
+MIPS target
+M: Aurelien Jarno <aurelien@aurel32.ne>
+S: Maintained
+F: tcg/mips/
+
+PPC
+M: Vassili Karpov (malc) <av1474@comtv.ru>
+S: Maintained
+F: tcg/ppc/
+
+PPC64 target
+M: Vassili Karpov (malc) <av1474@comtv.ru>
+S: Maintained
+F: tcg/ppc64/
+
+S390 target
+M: Alexander Graf <agraf@suse.de>
+M: Richard Henderson <rth@twiddle.net>
+S: Maintained
+F: tcg/s390/
+
+SPARC target
+M: Blue Swirl <blauwirbel@gmail.com>
+S: Maintained
+F: tcg/sparc/
diff --git a/arm-dis.c b/arm-dis.c
index af217397d4..3ece02c1b3 100644
--- a/arm-dis.c
+++ b/arm-dis.c
@@ -4101,6 +4101,30 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info)
addresses, since the addend is not currently pc-relative. */
pc = 0;
+ /* We include the hexdump of the instruction. The format here
+ matches that used by objdump and the ARM ARM (in particular,
+ 32 bit Thumb instructions are displayed as pairs of halfwords,
+ not as a single word.) */
+ if (is_thumb)
+ {
+ if (size == 2)
+ {
+ info->fprintf_func(info->stream, "%04lx ",
+ ((unsigned long)given) & 0xffff);
+ }
+ else
+ {
+ info->fprintf_func(info->stream, "%04lx %04lx ",
+ (((unsigned long)given) >> 16) & 0xffff,
+ ((unsigned long)given) & 0xffff);
+ }
+ }
+ else
+ {
+ info->fprintf_func(info->stream, "%08lx ",
+ ((unsigned long)given) & 0xffffffff);
+ }
+
printer (pc, info, given);
if (is_thumb)
diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c
index 727b9f84c3..4d720146df 100644
--- a/audio/alsaaudio.c
+++ b/audio/alsaaudio.c
@@ -1097,7 +1097,7 @@ static int alsa_run_in (HWVoiceIn *hw)
}
}
- hw->conv (dst, src, nread, &nominal_volume);
+ hw->conv (dst, src, nread);
src = advance (src, nread << hwshift);
dst += nread;
diff --git a/audio/audio.c b/audio/audio.c
index 17074469b2..1729c0be2c 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -104,7 +104,7 @@ static struct {
static AudioState glob_audio_state;
-struct mixeng_volume nominal_volume = {
+const struct mixeng_volume nominal_volume = {
.mute = 0,
#ifdef FLOAT_MIXENG
.r = 1.0,
@@ -702,13 +702,11 @@ void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len)
/*
* Capture
*/
-static void noop_conv (struct st_sample *dst, const void *src,
- int samples, struct mixeng_volume *vol)
+static void noop_conv (struct st_sample *dst, const void *src, int samples)
{
(void) src;
(void) dst;
(void) samples;
- (void) vol;
}
static CaptureVoiceOut *audio_pcm_capture_find_specific (
@@ -956,6 +954,8 @@ int audio_pcm_sw_read (SWVoiceIn *sw, void *buf, int size)
total += isamp;
}
+ mixeng_volume (sw->buf, ret, &sw->vol);
+
sw->clip (buf, sw->buf, ret);
sw->total_hw_samples_acquired += total;
return ret << sw->info.shift;
@@ -1037,7 +1037,8 @@ int audio_pcm_sw_write (SWVoiceOut *sw, void *buf, int size)
swlim = ((int64_t) dead << 32) / sw->ratio;
swlim = audio_MIN (swlim, samples);
if (swlim) {
- sw->conv (sw->buf, buf, swlim, &sw->vol);
+ sw->conv (sw->buf, buf, swlim);
+ mixeng_volume (sw->buf, swlim, &sw->vol);
}
while (swlim) {
diff --git a/audio/audio_int.h b/audio/audio_int.h
index d66f2c3bf6..2003f8bf20 100644
--- a/audio/audio_int.h
+++ b/audio/audio_int.h
@@ -211,7 +211,7 @@ extern struct audio_driver esd_audio_driver;
extern struct audio_driver pa_audio_driver;
extern struct audio_driver spice_audio_driver;
extern struct audio_driver winwave_audio_driver;
-extern struct mixeng_volume nominal_volume;
+extern const struct mixeng_volume nominal_volume;
void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as);
void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len);
diff --git a/audio/dsoundaudio.c b/audio/dsoundaudio.c
index e5479555fa..e2d89fd5d5 100644
--- a/audio/dsoundaudio.c
+++ b/audio/dsoundaudio.c
@@ -831,11 +831,11 @@ static int dsound_run_in (HWVoiceIn *hw)
decr = len1 + len2;
if (p1 && len1) {
- hw->conv (hw->conv_buf + hw->wpos, p1, len1, &nominal_volume);
+ hw->conv (hw->conv_buf + hw->wpos, p1, len1);
}
if (p2 && len2) {
- hw->conv (hw->conv_buf, p2, len2, &nominal_volume);
+ hw->conv (hw->conv_buf, p2, len2);
}
dsound_unlock_in (dscb, p1, p2, blen1, blen2);
diff --git a/audio/esdaudio.c b/audio/esdaudio.c
index 9a1f2f8617..ff97b397d2 100644
--- a/audio/esdaudio.c
+++ b/audio/esdaudio.c
@@ -346,8 +346,7 @@ static void *qesd_thread_in (void *arg)
break;
}
- hw->conv (hw->conv_buf + wpos, buf, nread >> hw->info.shift,
- &nominal_volume);
+ hw->conv (hw->conv_buf + wpos, buf, nread >> hw->info.shift);
wpos = (wpos + chunk) % hw->samples;
to_grab -= chunk;
}
diff --git a/audio/fmodaudio.c b/audio/fmodaudio.c
index 7f08e14718..c34cf53567 100644
--- a/audio/fmodaudio.c
+++ b/audio/fmodaudio.c
@@ -488,10 +488,10 @@ static int fmod_run_in (HWVoiceIn *hw)
decr = len1 + len2;
if (p1 && blen1) {
- hw->conv (hw->conv_buf + hw->wpos, p1, len1, &nominal_volume);
+ hw->conv (hw->conv_buf + hw->wpos, p1, len1);
}
if (p2 && len2) {
- hw->conv (hw->conv_buf, p2, len2, &nominal_volume);
+ hw->conv (hw->conv_buf, p2, len2);
}
fmod_unlock_sample (fmd->fmod_sample, p1, p2, blen1, blen2);
diff --git a/audio/mixeng.c b/audio/mixeng.c
index 9f1d93fcfc..4a9e8ebe2a 100644
--- a/audio/mixeng.c
+++ b/audio/mixeng.c
@@ -333,3 +333,28 @@ void mixeng_clear (struct st_sample *buf, int len)
{
memset (buf, 0, len * sizeof (struct st_sample));
}
+
+void mixeng_volume (struct st_sample *buf, int len, struct mixeng_volume *vol)
+{
+#ifdef CONFIG_MIXEMU
+ if (vol->mute) {
+ mixeng_clear (buf, len);
+ return;
+ }
+
+ while (len--) {
+#ifdef FLOAT_MIXENG
+ buf->l = buf->l * vol->l;
+ buf->r = buf->r * vol->r;
+#else
+ buf->l = (buf->l * vol->l) >> 32;
+ buf->r = (buf->r * vol->r) >> 32;
+#endif
+ buf += 1;
+ }
+#else
+ (void) buf;
+ (void) len;
+ (void) vol;
+#endif
+}
diff --git a/audio/mixeng.h b/audio/mixeng.h
index 4af1dd9891..9de443b01d 100644
--- a/audio/mixeng.h
+++ b/audio/mixeng.h
@@ -33,8 +33,7 @@ struct mixeng_volume { int mute; int64_t r; int64_t l; };
struct st_sample { int64_t l; int64_t r; };
#endif
-typedef void (t_sample) (struct st_sample *dst, const void *src,
- int samples, struct mixeng_volume *vol);
+typedef void (t_sample) (struct st_sample *dst, const void *src, int samples);
typedef void (f_sample) (void *dst, const struct st_sample *src, int samples);
extern t_sample *mixeng_conv[2][2][2][3];
@@ -47,5 +46,6 @@ void st_rate_flow_mix (void *opaque, struct st_sample *ibuf, struct st_sample *o
int *isamp, int *osamp);
void st_rate_stop (void *opaque);
void mixeng_clear (struct st_sample *buf, int len);
+void mixeng_volume (struct st_sample *buf, int len, struct mixeng_volume *vol);
#endif /* mixeng.h */
diff --git a/audio/mixeng_template.h b/audio/mixeng_template.h
index 56177056ce..a2d0ef84fd 100644
--- a/audio/mixeng_template.h
+++ b/audio/mixeng_template.h
@@ -31,16 +31,6 @@
#define HALF (IN_MAX >> 1)
#endif
-#ifdef CONFIG_MIXEMU
-#ifdef FLOAT_MIXENG
-#define VOL(a, b) ((a) * (b))
-#else
-#define VOL(a, b) ((a) * (b)) >> 32
-#endif
-#else
-#define VOL(a, b) a
-#endif
-
#define ET glue (ENDIAN_CONVERSION, glue (_, IN_T))
#ifdef FLOAT_MIXENG
@@ -109,40 +99,26 @@ static inline IN_T glue (clip_, ET) (int64_t v)
#endif
static void glue (glue (conv_, ET), _to_stereo)
- (struct st_sample *dst, const void *src, int samples, struct mixeng_volume *vol)
+ (struct st_sample *dst, const void *src, int samples)
{
struct st_sample *out = dst;
IN_T *in = (IN_T *) src;
-#ifdef CONFIG_MIXEMU
- if (vol->mute) {
- mixeng_clear (dst, samples);
- return;
- }
-#else
- (void) vol;
-#endif
+
while (samples--) {
- out->l = VOL (glue (conv_, ET) (*in++), vol->l);
- out->r = VOL (glue (conv_, ET) (*in++), vol->r);
+ out->l = glue (conv_, ET) (*in++);
+ out->r = glue (conv_, ET) (*in++);
out += 1;
}
}
static void glue (glue (conv_, ET), _to_mono)
- (struct st_sample *dst, const void *src, int samples, struct mixeng_volume *vol)
+ (struct st_sample *dst, const void *src, int samples)
{
struct st_sample *out = dst;
IN_T *in = (IN_T *) src;
-#ifdef CONFIG_MIXEMU
- if (vol->mute) {
- mixeng_clear (dst, samples);
- return;
- }
-#else
- (void) vol;
-#endif
+
while (samples--) {
- out->l = VOL (glue (conv_, ET) (in[0]), vol->l);
+ out->l = glue (conv_, ET) (in[0]);
out->r = out->l;
out += 1;
in += 1;
@@ -174,4 +150,3 @@ static void glue (glue (clip_, ET), _from_mono)
#undef ET
#undef HALF
-#undef VOL
diff --git a/audio/ossaudio.c b/audio/ossaudio.c
index d7a55e5441..b49e102747 100644
--- a/audio/ossaudio.c
+++ b/audio/ossaudio.c
@@ -788,8 +788,7 @@ static int oss_run_in (HWVoiceIn *hw)
hw->info.align + 1);
}
read_samples += nread >> hwshift;
- hw->conv (hw->conv_buf + bufs[i].add, p, nread >> hwshift,
- &nominal_volume);
+ hw->conv (hw->conv_buf + bufs[i].add, p, nread >> hwshift);
}
if (bufs[i].len - nread) {
diff --git a/audio/paaudio.c b/audio/paaudio.c
index ff71dac2a5..9cf685d30f 100644
--- a/audio/paaudio.c
+++ b/audio/paaudio.c
@@ -195,7 +195,7 @@ static void *qpa_thread_in (void *arg)
return NULL;
}
- hw->conv (hw->conv_buf + wpos, buf, chunk, &nominal_volume);
+ hw->conv (hw->conv_buf + wpos, buf, chunk);
wpos = (wpos + chunk) % hw->samples;
to_grab -= chunk;
}
diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c
index 373e4c43ed..a5c0d6bc66 100644
--- a/audio/spiceaudio.c
+++ b/audio/spiceaudio.c
@@ -268,11 +268,10 @@ static int line_in_run (HWVoiceIn *hw)
len[1] = 0;
}
- hw->conv (hw->conv_buf + hw->wpos, samples, len[0], &nominal_volume);
+ hw->conv (hw->conv_buf + hw->wpos, samples, len[0]);
if (len[1]) {
- hw->conv (hw->conv_buf, samples + len[0], len[1],
- &nominal_volume);
+ hw->conv (hw->conv_buf, samples + len[0], len[1]);
}
hw->wpos = (hw->wpos + num_samples) % hw->samples;
diff --git a/audio/winwaveaudio.c b/audio/winwaveaudio.c
index cdf483b89a..e5ad3c6604 100644
--- a/audio/winwaveaudio.c
+++ b/audio/winwaveaudio.c
@@ -581,8 +581,7 @@ static int winwave_run_in (HWVoiceIn *hw)
int conv = audio_MIN (left, decr);
hw->conv (hw->conv_buf + hw->wpos,
advance (wave->pcm_buf, wave->rpos << hw->info.shift),
- conv,
- &nominal_volume);
+ conv);
wave->rpos = (wave->rpos + conv) % hw->samples;
hw->wpos = (hw->wpos + conv) % hw->samples;
diff --git a/block/vpc.c b/block/vpc.c
index 21e2a6870c..7b025be01d 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -502,6 +502,7 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options)
uint8_t secs_per_cyl = 0;
size_t block_size, num_bat_entries;
int64_t total_sectors = 0;
+ int ret = -EIO;
// Read out options
while (options && options->name) {
@@ -521,7 +522,8 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options)
for (i = 0; total_sectors > (int64_t)cyls * heads * secs_per_cyl; i++) {
if (calculate_geometry(total_sectors + i,
&cyls, &heads, &secs_per_cyl)) {
- return -EFBIG;
+ ret = -EFBIG;
+ goto fail;
}
}
total_sectors = (int64_t) cyls * heads * secs_per_cyl;
@@ -560,22 +562,28 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options)
block_size = 0x200000;
num_bat_entries = (total_sectors + block_size / 512) / (block_size / 512);
- if (write(fd, buf, HEADER_SIZE) != HEADER_SIZE)
- return -EIO;
+ if (write(fd, buf, HEADER_SIZE) != HEADER_SIZE) {
+ goto fail;
+ }
- if (lseek(fd, 1536 + ((num_bat_entries * 4 + 511) & ~511), SEEK_SET) < 0)
- return -EIO;
- if (write(fd, buf, HEADER_SIZE) != HEADER_SIZE)
- return -EIO;
+ if (lseek(fd, 1536 + ((num_bat_entries * 4 + 511) & ~511), SEEK_SET) < 0) {
+ goto fail;
+ }
+ if (write(fd, buf, HEADER_SIZE) != HEADER_SIZE) {
+ goto fail;
+ }
// Write the initial BAT
- if (lseek(fd, 3 * 512, SEEK_SET) < 0)
- return -EIO;
+ if (lseek(fd, 3 * 512, SEEK_SET) < 0) {
+ goto fail;
+ }
memset(buf, 0xFF, 512);
- for (i = 0; i < (num_bat_entries * 4 + 511) / 512; i++)
- if (write(fd, buf, 512) != 512)
- return -EIO;
+ for (i = 0; i < (num_bat_entries * 4 + 511) / 512; i++) {
+ if (write(fd, buf, 512) != 512) {
+ goto fail;
+ }
+ }
// Prepare the Dynamic Disk Header
@@ -592,13 +600,18 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options)
dyndisk_header->checksum = be32_to_cpu(vpc_checksum(buf, 1024));
// Write the header
- if (lseek(fd, 512, SEEK_SET) < 0)
- return -EIO;
- if (write(fd, buf, 1024) != 1024)
- return -EIO;
+ if (lseek(fd, 512, SEEK_SET) < 0) {
+ goto fail;
+ }
+ if (write(fd, buf, 1024) != 1024) {
+ goto fail;
+ }
+ ret = 0;
+
+ fail:
close(fd);
- return 0;
+ return ret;
}
static void vpc_close(BlockDriverState *bs)
diff --git a/block/vvfat.c b/block/vvfat.c
index 26dd474bb5..fe568fe2c7 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -756,6 +756,7 @@ static int read_directory(BDRVVVFATState* s, int mapping_index)
if (st.st_size > 0x7fffffff) {
fprintf(stderr, "File %s is larger than 2GB\n", buffer);
free(buffer);
+ closedir(dir);
return -2;
}
direntry->size=cpu_to_le32(S_ISDIR(st.st_mode)?0:st.st_size);
diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c
index 7374912b19..1ef1f972fc 100644
--- a/bsd-user/elfload.c
+++ b/bsd-user/elfload.c
@@ -1044,7 +1044,7 @@ static void load_symbols(struct elfhdr *hdr, int fd)
struct elf_shdr sechdr, symtab, strtab;
char *strings;
struct syminfo *s;
- struct elf_sym *syms;
+ struct elf_sym *syms, *new_syms;
lseek(fd, hdr->e_shoff, SEEK_SET);
for (i = 0; i < hdr->e_shnum; i++) {
@@ -1072,15 +1072,24 @@ static void load_symbols(struct elfhdr *hdr, int fd)
/* Now know where the strtab and symtab are. Snarf them. */
s = malloc(sizeof(*s));
syms = malloc(symtab.sh_size);
- if (!syms)
+ if (!syms) {
+ free(s);
return;
+ }
s->disas_strtab = strings = malloc(strtab.sh_size);
- if (!s->disas_strtab)
+ if (!s->disas_strtab) {
+ free(s);
+ free(syms);
return;
+ }
lseek(fd, symtab.sh_offset, SEEK_SET);
- if (read(fd, syms, symtab.sh_size) != symtab.sh_size)
+ if (read(fd, syms, symtab.sh_size) != symtab.sh_size) {
+ free(s);
+ free(syms);
+ free(strings);
return;
+ }
nsyms = symtab.sh_size / sizeof(struct elf_sym);
@@ -1105,13 +1114,29 @@ static void load_symbols(struct elfhdr *hdr, int fd)
#endif
i++;
}
- syms = realloc(syms, nsyms * sizeof(*syms));
+
+ /* Attempt to free the storage associated with the local symbols
+ that we threw away. Whether or not this has any effect on the
+ memory allocation depends on the malloc implementation and how
+ many symbols we managed to discard. */
+ new_syms = realloc(syms, nsyms * sizeof(*syms));
+ if (new_syms == NULL) {
+ free(s);
+ free(syms);
+ free(strings);
+ return;
+ }
+ syms = new_syms;
qsort(syms, nsyms, sizeof(*syms), symcmp);
lseek(fd, strtab.sh_offset, SEEK_SET);
- if (read(fd, strings, strtab.sh_size) != strtab.sh_size)
+ if (read(fd, strings, strtab.sh_size) != strtab.sh_size) {
+ free(s);
+ free(syms);
+ free(strings);
return;
+ }
s->disas_num_syms = nsyms;
#if ELF_CLASS == ELFCLASS32
s->disas_symtab.elf32 = syms;
diff --git a/configure b/configure
index 831a741c74..d68f862de5 100755
--- a/configure
+++ b/configure
@@ -32,6 +32,12 @@ compile_prog() {
$cc $QEMU_CFLAGS $local_cflags -o $TMPE $TMPC $LDFLAGS $local_ldflags >> config.log 2>&1
}
+# symbolically link $1 to $2. Portable version of "ln -sf".
+symlink() {
+ rm -f $2
+ ln -s $1 $2
+}
+
# check whether a command is available to this shell (may be either an
# executable or a builtin)
has() {
@@ -69,24 +75,17 @@ path_of() {
}
# default parameters
+source_path=`dirname "$0"`
cpu=""
interp_prefix="/usr/gnemul/qemu-%M"
static="no"
sparc_cpu=""
cross_prefix=""
-cc="gcc"
audio_drv_list=""
audio_card_list="ac97 es1370 sb16 hda"
audio_possible_cards="ac97 es1370 sb16 cs4231a adlib gus hda"
block_drv_whitelist=""
host_cc="gcc"
-ar="ar"
-make="make"
-install="install"
-objcopy="objcopy"
-ld="ld"
-strip="strip"
-windres="windres"
helper_cflags=""
libs_softmmu=""
libs_tools=""
@@ -94,13 +93,97 @@ audio_pt_int=""
audio_win_int=""
cc_i386=i386-pc-linux-gnu-gcc
+target_list=""
+
+# Default value for a variable defining feature "foo".
+# * foo="no" feature will only be used if --enable-foo arg is given
+# * foo="" feature will be searched for, and if found, will be used
+# unless --disable-foo is given
+# * foo="yes" this value will only be set by --enable-foo flag.
+# feature will searched for,
+# if not found, configure exits with error
+#
+# Always add --enable-foo and --disable-foo command line args.
+# Distributions want to ensure that several features are compiled in, and it
+# is impossible without a --enable-foo that exits if a feature is not found.
+
+bluez=""
+brlapi=""
+curl=""
+curses=""
+docs=""
+fdt=""
+kvm=""
+kvm_para=""
+nptl=""
+sdl=""
+sparse="no"
+uuid=""
+vde=""
+vnc_tls=""
+vnc_sasl=""
+vnc_jpeg=""
+vnc_png=""
+vnc_thread="no"
+xen=""
+linux_aio=""
+attr=""
+vhost_net=""
+xfs=""
+
+gprof="no"
+debug_tcg="no"
+debug_mon="no"
+debug="no"
+strip_opt="yes"
+bigendian="no"
+mingw32="no"
+EXESUF=""
+prefix="/usr/local"
+mandir="\${prefix}/share/man"
+datadir="\${prefix}/share/qemu"
+docdir="\${prefix}/share/doc/qemu"
+bindir="\${prefix}/bin"
+sysconfdir="\${prefix}/etc"
+confsuffix="/qemu"
+slirp="yes"
+fmod_lib=""
+fmod_inc=""
+oss_lib=""
+bsd="no"
+linux="no"
+solaris="no"
+profiler="no"
+cocoa="no"
+softmmu="yes"
+linux_user="no"
+darwin_user="no"
+bsd_user="no"
+guest_base=""
+uname_release=""
+io_thread="no"
+mixemu="no"
+kerneldir=""
+aix="no"
+blobs="yes"
+pkgversion=""
+check_utests="no"
+user_pie="no"
+zero_malloc=""
+trace_backend="nop"
+trace_file="trace"
+spice=""
+rbd=""
+
# parse CC options first
for opt do
optarg=`expr "x$opt" : 'x[^=]*=\(.*\)'`
case "$opt" in
--cross-prefix=*) cross_prefix="$optarg"
;;
- --cc=*) cc="$optarg"
+ --cc=*) CC="$optarg"
+ ;;
+ --source-path=*) source_path="$optarg"
;;
--cpu=*) cpu="$optarg"
;;
@@ -129,12 +212,14 @@ done
# Using uname is really, really broken. Once we have the right set of checks
# we can eliminate it's usage altogether
-cc="${cross_prefix}${cc}"
-ar="${cross_prefix}${ar}"
-objcopy="${cross_prefix}${objcopy}"
-ld="${cross_prefix}${ld}"
-strip="${cross_prefix}${strip}"
-windres="${cross_prefix}${windres}"
+cc="${cross_prefix}${CC-gcc}"
+ar="${cross_prefix}${AR-ar}"
+objcopy="${cross_prefix}${OBJCOPY-objcopy}"
+ld="${cross_prefix}${LD-ld}"
+strip="${cross_prefix}${STRIP-strip}"
+windres="${cross_prefix}${WINDRES-windres}"
+pkg_config="${cross_prefix}${PKG_CONFIG-pkg-config}"
+sdl_config="${cross_prefix}${SDL_CONFIG-sdl-config}"
# default flags for all hosts
QEMU_CFLAGS="-fno-strict-aliasing $QEMU_CFLAGS"
@@ -143,33 +228,11 @@ QEMU_CFLAGS="-Wall -Wundef -Wendif-labels -Wwrite-strings -Wmissing-prototypes $
QEMU_CFLAGS="-Wstrict-prototypes -Wredundant-decls $QEMU_CFLAGS"
QEMU_CFLAGS="-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE $QEMU_CFLAGS"
QEMU_CFLAGS="-D_FORTIFY_SOURCE=2 $QEMU_CFLAGS"
-QEMU_CFLAGS="-I. -I\$(SRC_PATH) $QEMU_CFLAGS"
+QEMU_INCLUDES="-I. -I\$(SRC_PATH)"
LDFLAGS="-g $LDFLAGS"
-gcc_flags="-Wold-style-declaration -Wold-style-definition -Wtype-limits"
-gcc_flags="-Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers $gcc_flags"
-gcc_flags="-Wmissing-include-dirs -Wempty-body -Wnested-externs $gcc_flags"
-gcc_flags="-fstack-protector-all $gcc_flags"
-cat > $TMPC << EOF
-int main(void) { return 0; }
-EOF
-for flag in $gcc_flags; do
- if compile_prog "-Werror $QEMU_CFLAGS" "-Werror $flag" ; then
- QEMU_CFLAGS="$QEMU_CFLAGS $flag"
- fi
-done
-
-# check that the C compiler works.
-cat > $TMPC <<EOF
-int main(void) {}
-EOF
-
-if compile_object ; then
- : C compiler works ok
-else
- echo "ERROR: \"$cc\" either does not exist or does not work"
- exit 1
-fi
+# make source path absolute
+source_path=`cd "$source_path"; pwd`
check_define() {
cat > $TMPC <<EOF
@@ -216,7 +279,6 @@ else
cpu=`uname -m`
fi
-target_list=""
case "$cpu" in
alpha|cris|ia64|m68k|microblaze|ppc|ppc64|sparc64)
cpu="$cpu"
@@ -254,87 +316,6 @@ case "$cpu" in
;;
esac
-# Default value for a variable defining feature "foo".
-# * foo="no" feature will only be used if --enable-foo arg is given
-# * foo="" feature will be searched for, and if found, will be used
-# unless --disable-foo is given
-# * foo="yes" this value will only be set by --enable-foo flag.
-# feature will searched for,
-# if not found, configure exits with error
-#
-# Always add --enable-foo and --disable-foo command line args.
-# Distributions want to ensure that several features are compiled in, and it
-# is impossible without a --enable-foo that exits if a feature is not found.
-
-bluez=""
-brlapi=""
-curl=""
-curses=""
-docs=""
-fdt=""
-kvm=""
-kvm_para=""
-nptl=""
-sdl=""
-sparse="no"
-uuid=""
-vde=""
-vnc_tls=""
-vnc_sasl=""
-vnc_jpeg=""
-vnc_png=""
-vnc_thread="no"
-xen=""
-linux_aio=""
-attr=""
-vhost_net=""
-xfs=""
-
-gprof="no"
-debug_tcg="no"
-debug_mon="no"
-debug="no"
-strip_opt="yes"
-bigendian="no"
-mingw32="no"
-EXESUF=""
-prefix="/usr/local"
-mandir="\${prefix}/share/man"
-datadir="\${prefix}/share/qemu"
-docdir="\${prefix}/share/doc/qemu"
-bindir="\${prefix}/bin"
-sysconfdir="\${prefix}/etc"
-confsuffix="/qemu"
-slirp="yes"
-fmod_lib=""
-fmod_inc=""
-oss_lib=""
-bsd="no"
-linux="no"
-solaris="no"
-profiler="no"
-cocoa="no"
-softmmu="yes"
-linux_user="no"
-darwin_user="no"
-bsd_user="no"
-guest_base=""
-uname_release=""
-io_thread="no"
-mixemu="no"
-kerneldir=""
-aix="no"
-haiku="no"
-blobs="yes"
-pkgversion=""
-check_utests="no"
-user_pie="no"
-zero_malloc=""
-trace_backend="nop"
-trace_file="trace"
-spice=""
-rbd=""
-
# OS specific
if check_define __linux__ ; then
targetos="Linux"
@@ -369,7 +350,7 @@ GNU/kFreeBSD)
;;
FreeBSD)
bsd="yes"
- make="gmake"
+ make="${MAKE-gmake}"
audio_drv_list="oss"
audio_possible_drivers="oss sdl esd pa"
# needed for kinfo_getvmmap(3) in libutil.h
@@ -377,20 +358,20 @@ FreeBSD)
;;
DragonFly)
bsd="yes"
- make="gmake"
+ make="${MAKE-gmake}"
audio_drv_list="oss"
audio_possible_drivers="oss sdl esd pa"
;;
NetBSD)
bsd="yes"
- make="gmake"
+ make="${MAKE-gmake}"
audio_drv_list="oss"
audio_possible_drivers="oss sdl esd"
oss_lib="-lossaudio"
;;
OpenBSD)
bsd="yes"
- make="gmake"
+ make="${MAKE-gmake}"
audio_drv_list="oss"
audio_possible_drivers="oss sdl esd"
oss_lib="-lossaudio"
@@ -419,8 +400,8 @@ Darwin)
;;
SunOS)
solaris="yes"
- make="gmake"
- install="ginstall"
+ make="${MAKE-gmake}"
+ install="${INSTALL-ginstall}"
ld="gld"
needs_libsunmath="no"
solarisrev=`uname -r | cut -f2 -d.`
@@ -459,7 +440,7 @@ SunOS)
;;
AIX)
aix="yes"
- make="gmake"
+ make="${MAKE-gmake}"
;;
Haiku)
haiku="yes"
@@ -485,6 +466,9 @@ if [ "$bsd" = "yes" ] ; then
bsd_user="yes"
fi
+: ${make=${MAKE-make}}
+: ${install=${INSTALL-install}}
+
if test "$mingw32" = "yes" ; then
EXESUF=".exe"
QEMU_CFLAGS="-DWIN32_LEAN_AND_MEAN -DWINVER=0x501 $QEMU_CFLAGS"
@@ -500,17 +484,6 @@ if test "$mingw32" = "yes" ; then
confsuffix=""
fi
-# find source path
-source_path=`dirname "$0"`
-source_path_used="no"
-workdir=`pwd`
-if [ -z "$source_path" ]; then
- source_path=$workdir
-else
- source_path=`cd "$source_path"; pwd`
-fi
-[ -f "$workdir/vl.c" ] || source_path_used="yes"
-
werror=""
for opt do
@@ -522,8 +495,7 @@ for opt do
;;
--interp-prefix=*) interp_prefix="$optarg"
;;
- --source-path=*) source_path="$optarg"
- source_path_used="yes"
+ --source-path=*)
;;
--cross-prefix=*)
;;
@@ -543,9 +515,9 @@ for opt do
;;
--target-list=*) target_list="$optarg"
;;
- --trace-backend=*) trace_backend="$optarg"
+ --enable-trace-backend=*) trace_backend="$optarg"
;;
- --trace-file=*) trace_file="$optarg"
+ --with-trace-file=*) trace_file="$optarg"
;;
--enable-gprof) gprof="yes"
;;
@@ -935,8 +907,8 @@ echo " --enable-docs enable documentation build"
echo " --disable-docs disable documentation build"
echo " --disable-vhost-net disable vhost-net acceleration support"
echo " --enable-vhost-net enable vhost-net acceleration support"
-echo " --trace-backend=B Trace backend nop simple ust dtrace"
-echo " --trace-file=NAME Full PATH,NAME of file to store traces"
+echo " --enable-trace-backend=B Trace backend nop simple ust dtrace"
+echo " --with-trace-file=NAME Full PATH,NAME of file to store traces"
echo " Default:trace-<pid>"
echo " --disable-spice disable spice"
echo " --enable-spice enable spice"
@@ -946,6 +918,31 @@ echo "NOTE: The object files are built at the place where configure is launched"
exit 1
fi
+# check that the C compiler works.
+cat > $TMPC <<EOF
+int main(void) {}
+EOF
+
+if compile_object ; then
+ : C compiler works ok
+else
+ echo "ERROR: \"$cc\" either does not exist or does not work"
+ exit 1
+fi
+
+gcc_flags="-Wold-style-declaration -Wold-style-definition -Wtype-limits"
+gcc_flags="-Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers $gcc_flags"
+gcc_flags="-Wmissing-include-dirs -Wempty-body -Wnested-externs $gcc_flags"
+gcc_flags="-fstack-protector-all $gcc_flags"
+cat > $TMPC << EOF
+int main(void) { return 0; }
+EOF
+for flag in $gcc_flags; do
+ if compile_prog "-Werror $QEMU_CFLAGS" "-Werror $flag" ; then
+ QEMU_CFLAGS="$QEMU_CFLAGS $flag"
+ fi
+done
+
#
# Solaris specific configure tool chain decisions
#
@@ -1089,13 +1086,15 @@ esac
fi
-# host long bits test
-hostlongbits="32"
-case "$cpu" in
- x86_64|alpha|ia64|sparc64|ppc64|s390x)
- hostlongbits=64
- ;;
-esac
+# host long bits test, actually a pointer size test
+cat > $TMPC << EOF
+int sizeof_pointer_is_8[sizeof(void *) == 8 ? 1 : -1];
+EOF
+if compile_object; then
+hostlongbits=64
+else
+hostlongbits=32
+fi
##########################################
@@ -1162,12 +1161,11 @@ EOF
fi
##########################################
-# pkgconfig probe
+# pkg-config probe
-pkgconfig="${cross_prefix}pkg-config"
-if ! has $pkgconfig; then
- # likely not cross compiling, or hope for the best
- pkgconfig=pkg-config
+if ! has $pkg_config; then
+ echo warning: proceeding without "$pkg_config" >&2
+ pkg_config=/bin/false
fi
##########################################
@@ -1186,21 +1184,17 @@ fi
##########################################
# SDL probe
-# Look for sdl configuration program (pkg-config or sdl-config).
-# Prefer variant with cross prefix if cross compiling,
-# and favour pkg-config with sdl over sdl-config.
-if test -n "$cross_prefix" -a $pkgconfig != pkg-config && \
- $pkgconfig sdl --modversion >/dev/null 2>&1; then
- sdlconfig="$pkgconfig sdl"
- _sdlversion=`$sdlconfig --modversion 2>/dev/null | sed 's/[^0-9]//g'`
-elif test -n "$cross_prefix" && has ${cross_prefix}sdl-config; then
- sdlconfig="${cross_prefix}sdl-config"
- _sdlversion=`$sdlconfig --version | sed 's/[^0-9]//g'`
-elif $pkgconfig sdl --modversion >/dev/null 2>&1; then
- sdlconfig="$pkgconfig sdl"
+# Look for sdl configuration program (pkg-config or sdl-config). Try
+# sdl-config even without cross prefix, and favour pkg-config over sdl-config.
+if test "`basename $sdl_config`" != sdl-config && ! has ${sdl_config}; then
+ sdl_config=sdl-config
+fi
+
+if $pkg_config sdl --modversion >/dev/null 2>&1; then
+ sdlconfig="$pkg_config sdl"
_sdlversion=`$sdlconfig --modversion 2>/dev/null | sed 's/[^0-9]//g'`
-elif has sdl-config; then
- sdlconfig='sdl-config'
+elif has ${sdl_config}; then
+ sdlconfig="$sdl_config"
_sdlversion=`$sdlconfig --version | sed 's/[^0-9]//g'`
else
if test "$sdl" = "yes" ; then
@@ -1208,6 +1202,9 @@ else
fi
sdl=no
fi
+if test -n "$cross_prefix" && test "`basename $sdlconfig`" = sdl-config; then
+ echo warning: using "\"$sdlconfig\"" to detect cross-compiled sdl >&2
+fi
sdl_too_old=no
if test "$sdl" != "no" ; then
@@ -1277,8 +1274,8 @@ if test "$vnc_tls" != "no" ; then
#include <gnutls/gnutls.h>
int main(void) { gnutls_session_t s; gnutls_init(&s, GNUTLS_SERVER); return 0; }
EOF
- vnc_tls_cflags=`$pkgconfig --cflags gnutls 2> /dev/null`
- vnc_tls_libs=`$pkgconfig --libs gnutls 2> /dev/null`
+ vnc_tls_cflags=`$pkg_config --cflags gnutls 2> /dev/null`
+ vnc_tls_libs=`$pkg_config --libs gnutls 2> /dev/null`
if compile_prog "$vnc_tls_cflags" "$vnc_tls_libs" ; then
vnc_tls=yes
libs_softmmu="$vnc_tls_libs $libs_softmmu"
@@ -1592,8 +1589,8 @@ fi
##########################################
# curl probe
-if $pkgconfig libcurl --modversion >/dev/null 2>&1; then
- curlconfig="$pkgconfig libcurl"
+if $pkg_config libcurl --modversion >/dev/null 2>&1; then
+ curlconfig="$pkg_config libcurl"
else
curlconfig=curl-config
fi
@@ -1625,7 +1622,7 @@ if test "$check_utests" != "no" ; then
#include <check.h>
int main(void) { suite_create("qemu test"); return 0; }
EOF
- check_libs=`$pkgconfig --libs check`
+ check_libs=`$pkg_config --libs check`
if compile_prog "" $check_libs ; then
check_utests=yes
libs_tools="$check_libs $libs_tools"
@@ -1644,8 +1641,8 @@ if test "$bluez" != "no" ; then
#include <bluetooth/bluetooth.h>
int main(void) { return bt_error(0); }
EOF
- bluez_cflags=`$pkgconfig --cflags bluez 2> /dev/null`
- bluez_libs=`$pkgconfig --libs bluez 2> /dev/null`
+ bluez_cflags=`$pkg_config --cflags bluez 2> /dev/null`
+ bluez_libs=`$pkg_config --libs bluez 2> /dev/null`
if compile_prog "$bluez_cflags" "$bluez_libs" ; then
bluez=yes
libs_softmmu="$bluez_libs $libs_softmmu"
@@ -1689,7 +1686,7 @@ EOF
kvm_cflags="$kvm_cflags -I$kerneldir/arch/$cpu/include"
fi
else
- kvm_cflags=`$pkgconfig --cflags kvm-kmod 2>/dev/null`
+ kvm_cflags=`$pkg_config --cflags kvm-kmod 2>/dev/null`
fi
if compile_prog "$kvm_cflags" "" ; then
kvm=yes
@@ -2090,6 +2087,23 @@ if compile_prog "$ARCH_CFLAGS" "" ; then
sync_file_range=yes
fi
+# check for linux/fiemap.h and FS_IOC_FIEMAP
+fiemap=no
+cat > $TMPC << EOF
+#include <sys/ioctl.h>
+#include <linux/fs.h>
+#include <linux/fiemap.h>
+
+int main(void)
+{
+ ioctl(0, FS_IOC_FIEMAP, 0);
+ return 0;
+}
+EOF
+if compile_prog "$ARCH_CFLAGS" "" ; then
+ fiemap=yes
+fi
+
# check for dup3
dup3=no
cat > $TMPC << EOF
@@ -2533,7 +2547,7 @@ if test $profiler = "yes" ; then
fi
if test "$slirp" = "yes" ; then
echo "CONFIG_SLIRP=y" >> $config_host_mak
- QEMU_CFLAGS="-I\$(SRC_PATH)/slirp $QEMU_CFLAGS"
+ QEMU_INCLUDES="-I\$(SRC_PATH)/slirp $QEMU_INCLUDES"
fi
if test "$vde" = "yes" ; then
echo "CONFIG_VDE=y" >> $config_host_mak
@@ -2631,6 +2645,9 @@ fi
if test "$sync_file_range" = "yes" ; then
echo "CONFIG_SYNC_FILE_RANGE=y" >> $config_host_mak
fi
+if test "$fiemap" = "yes" ; then
+ echo "CONFIG_FIEMAP=y" >> $config_host_mak
+fi
if test "$dup3" = "yes" ; then
echo "CONFIG_DUP3=y" >> $config_host_mak
fi
@@ -2760,17 +2777,18 @@ echo "INSTALL_PROG=$install -m0755 -p" >> $config_host_mak
echo "CC=$cc" >> $config_host_mak
echo "CC_I386=$cc_i386" >> $config_host_mak
echo "HOST_CC=$host_cc" >> $config_host_mak
-if test "$sparse" = "yes" ; then
- echo "CC := REAL_CC=\"\$(CC)\" cgcc" >> $config_host_mak
- echo "HOST_CC := REAL_CC=\"\$(HOST_CC)\" cgcc" >> $config_host_mak
- echo "QEMU_CFLAGS += -Wbitwise -Wno-transparent-union -Wno-old-initializer -Wno-non-pointer-null" >> $config_host_mak
-fi
echo "AR=$ar" >> $config_host_mak
echo "OBJCOPY=$objcopy" >> $config_host_mak
echo "LD=$ld" >> $config_host_mak
echo "WINDRES=$windres" >> $config_host_mak
echo "CFLAGS=$CFLAGS" >> $config_host_mak
echo "QEMU_CFLAGS=$QEMU_CFLAGS" >> $config_host_mak
+echo "QEMU_INCLUDES=$QEMU_INCLUDES" >> $config_host_mak
+if test "$sparse" = "yes" ; then
+ echo "CC := REAL_CC=\"\$(CC)\" cgcc" >> $config_host_mak
+ echo "HOST_CC := REAL_CC=\"\$(HOST_CC)\" cgcc" >> $config_host_mak
+ echo "QEMU_CFLAGS += -Wbitwise -Wno-transparent-union -Wno-old-initializer -Wno-non-pointer-null" >> $config_host_mak
+fi
echo "HELPER_CFLAGS=$helper_cflags" >> $config_host_mak
echo "LDFLAGS=$LDFLAGS" >> $config_host_mak
echo "ARLIBS_BEGIN=$arlibs_begin" >> $config_host_mak
@@ -2793,8 +2811,7 @@ fi
for d in libdis libdis-user; do
mkdir -p $d
- rm -f $d/Makefile
- ln -s $source_path/Makefile.dis $d/Makefile
+ symlink $source_path/Makefile.dis $d/Makefile
echo > $d/config.mak
done
if test "$static" = "no" -a "$user_pie" = "yes" ; then
@@ -2858,12 +2875,7 @@ mkdir -p $target_dir/ide
if test "$target" = "arm-linux-user" -o "$target" = "armeb-linux-user" -o "$target" = "arm-bsd-user" -o "$target" = "armeb-bsd-user" ; then
mkdir -p $target_dir/nwfpe
fi
-
-#
-# don't use ln -sf as not all "ln -sf" over write the file/link
-#
-rm -f $target_dir/Makefile
-ln -s $source_path/Makefile.target $target_dir/Makefile
+symlink $source_path/Makefile.target $target_dir/Makefile
echo "# Automatically generated by configure - do not modify" > $config_target_mak
@@ -3049,11 +3061,11 @@ if test ! -z "$gdb_xml_files" ; then
fi
case "$target_arch2" in
- alpha|arm|armeb|m68k|microblaze|mips|mipsel|mipsn32|mipsn32el|mips64|mips64el|ppc|ppc64|ppc64abi32|ppcemb|s390x|sparc|sparc64|sparc32plus)
- echo "CONFIG_SOFTFLOAT=y" >> $config_target_mak
+ i386|x86_64)
+ echo "CONFIG_NOSOFTFLOAT=y" >> $config_target_mak
;;
*)
- echo "CONFIG_NOSOFTFLOAT=y" >> $config_target_mak
+ echo "CONFIG_SOFTFLOAT=y" >> $config_target_mak
;;
esac
@@ -3074,19 +3086,20 @@ fi
# generate QEMU_CFLAGS/LDFLAGS for targets
cflags=""
+includes=""
ldflags=""
if test "$ARCH" = "sparc64" ; then
- cflags="-I\$(SRC_PATH)/tcg/sparc $cflags"
+ includes="-I\$(SRC_PATH)/tcg/sparc $includes"
elif test "$ARCH" = "s390x" ; then
- cflags="-I\$(SRC_PATH)/tcg/s390 $cflags"
+ includes="-I\$(SRC_PATH)/tcg/s390 $includes"
elif test "$ARCH" = "x86_64" ; then
- cflags="-I\$(SRC_PATH)/tcg/i386 $cflags"
+ includes="-I\$(SRC_PATH)/tcg/i386 $includes"
else
- cflags="-I\$(SRC_PATH)/tcg/\$(ARCH) $cflags"
+ includes="-I\$(SRC_PATH)/tcg/\$(ARCH) $includes"
fi
-cflags="-I\$(SRC_PATH)/tcg $cflags"
-cflags="-I\$(SRC_PATH)/fpu $cflags"
+includes="-I\$(SRC_PATH)/tcg $includes"
+includes="-I\$(SRC_PATH)/fpu $includes"
if test "$target_user_only" = "yes" ; then
libdis_config_mak=libdis-user/config.mak
@@ -3211,31 +3224,25 @@ fi
echo "LDFLAGS+=$ldflags" >> $config_target_mak
echo "QEMU_CFLAGS+=$cflags" >> $config_target_mak
+echo "QEMU_INCLUDES+=$includes" >> $config_target_mak
done # for target in $targets
-# build tree in object directory if source path is different from current one
-if test "$source_path_used" = "yes" ; then
- DIRS="tests tests/cris slirp audio block net pc-bios/optionrom"
- DIRS="$DIRS roms/seabios roms/vgabios"
- DIRS="$DIRS fsdev ui"
- FILES="Makefile tests/Makefile"
- FILES="$FILES tests/cris/Makefile tests/cris/.gdbinit"
- FILES="$FILES tests/test-mmap.c"
- FILES="$FILES pc-bios/optionrom/Makefile pc-bios/keymaps"
- FILES="$FILES roms/seabios/Makefile roms/vgabios/Makefile"
- for bios_file in $source_path/pc-bios/*.bin $source_path/pc-bios/*.dtb $source_path/pc-bios/openbios-*; do
- FILES="$FILES pc-bios/`basename $bios_file`"
- done
- for dir in $DIRS ; do
- mkdir -p $dir
- done
- # remove the link and recreate it, as not all "ln -sf" overwrite the link
- for f in $FILES ; do
- rm -f $f
- ln -s $source_path/$f $f
- done
-fi
+# build tree in object directory in case the source is not in the current directory
+DIRS="tests tests/cris slirp audio block net pc-bios/optionrom"
+DIRS="$DIRS roms/seabios roms/vgabios"
+DIRS="$DIRS fsdev ui"
+FILES="Makefile tests/Makefile"
+FILES="$FILES tests/cris/Makefile tests/cris/.gdbinit"
+FILES="$FILES pc-bios/optionrom/Makefile pc-bios/keymaps"
+FILES="$FILES roms/seabios/Makefile roms/vgabios/Makefile"
+for bios_file in $source_path/pc-bios/*.bin $source_path/pc-bios/*.dtb $source_path/pc-bios/openbios-*; do
+ FILES="$FILES pc-bios/`basename $bios_file`"
+done
+mkdir -p $DIRS
+for f in $FILES ; do
+ test -e $f || symlink $source_path/$f $f
+done
# temporary config to build submodules
for rom in seabios vgabios ; do
@@ -3247,7 +3254,6 @@ for rom in seabios vgabios ; do
echo "CPP=${cross_prefix}cpp" >> $config_mak
echo "OBJCOPY=objcopy" >> $config_mak
echo "IASL=iasl" >> $config_mak
- echo "HOST_CC=$host_cc" >> $config_mak
echo "LD=$ld" >> $config_mak
done
@@ -3255,15 +3261,13 @@ for hwlib in 32 64; do
d=libhw$hwlib
mkdir -p $d
mkdir -p $d/ide
- rm -f $d/Makefile
- ln -s $source_path/Makefile.hw $d/Makefile
+ symlink $source_path/Makefile.hw $d/Makefile
echo "QEMU_CFLAGS+=-DTARGET_PHYS_ADDR_BITS=$hwlib" > $d/config.mak
done
d=libuser
mkdir -p $d
-rm -f $d/Makefile
-ln -s $source_path/Makefile.user $d/Makefile
+symlink $source_path/Makefile.user $d/Makefile
if test "$static" = "no" -a "$user_pie" = "yes" ; then
echo "QEMU_CFLAGS+=-fpie" > $d/config.mak
fi
diff --git a/disas.c b/disas.c
index dd2db142d7..c76f36f590 100644
--- a/disas.c
+++ b/disas.c
@@ -307,11 +307,6 @@ void disas(FILE *out, void *code, unsigned long size)
#endif
for (pc = (unsigned long)code; size > 0; pc += count, size -= count) {
fprintf(out, "0x%08lx: ", pc);
-#ifdef __arm__
- /* since data is included in the code, it is better to
- display code data too */
- fprintf(out, "%08x ", (int)bfd_getl32((const bfd_byte *)pc));
-#endif
count = print_insn(pc, &disasm_info);
fprintf(out, "\n");
if (count < 0)
diff --git a/exec.c b/exec.c
index 49c28b160e..e950df25c3 100644
--- a/exec.c
+++ b/exec.c
@@ -531,6 +531,13 @@ static void code_gen_alloc(unsigned long tb_size)
/* Cannot map more than that */
if (code_gen_buffer_size > (800 * 1024 * 1024))
code_gen_buffer_size = (800 * 1024 * 1024);
+#elif defined(__sparc_v9__)
+ // Map the buffer below 2G, so we can use direct calls and branches
+ flags |= MAP_FIXED;
+ addr = (void *) 0x60000000UL;
+ if (code_gen_buffer_size > (512 * 1024 * 1024)) {
+ code_gen_buffer_size = (512 * 1024 * 1024);
+ }
#endif
code_gen_buffer = mmap(addr, code_gen_buffer_size,
PROT_WRITE | PROT_READ | PROT_EXEC,
diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index f293f24356..eb644b2273 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -30,7 +30,7 @@ these four paragraphs for those parts of this code that are retained.
=============================================================================*/
-#if defined(TARGET_MIPS)
+#if defined(TARGET_MIPS) || defined(TARGET_SH4)
#define SNAN_BIT_IS_ONE 1
#else
#define SNAN_BIT_IS_ONE 0
@@ -108,7 +108,7 @@ float32 float32_maybe_silence_nan( float32 a_ )
{
if (float32_is_signaling_nan(a_)) {
#if SNAN_BIT_IS_ONE
-# if defined(TARGET_MIPS)
+# if defined(TARGET_MIPS) || defined(TARGET_SH4)
return float32_default_nan;
# else
# error Rules for silencing a signaling NaN are target-specific
@@ -278,9 +278,6 @@ static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
flag aIsLargerSignificand;
bits32 av, bv;
- if ( STATUS(default_nan_mode) )
- return float32_default_nan;
-
aIsQuietNaN = float32_is_quiet_nan( a );
aIsSignalingNaN = float32_is_signaling_nan( a );
bIsQuietNaN = float32_is_quiet_nan( b );
@@ -290,6 +287,9 @@ static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
+ if ( STATUS(default_nan_mode) )
+ return float32_default_nan;
+
if ((bits32)(av<<1) < (bits32)(bv<<1)) {
aIsLargerSignificand = 0;
} else if ((bits32)(bv<<1) < (bits32)(av<<1)) {
@@ -362,7 +362,7 @@ float64 float64_maybe_silence_nan( float64 a_ )
{
if (float64_is_signaling_nan(a_)) {
#if SNAN_BIT_IS_ONE
-# if defined(TARGET_MIPS)
+# if defined(TARGET_MIPS) || defined(TARGET_SH4)
return float64_default_nan;
# else
# error Rules for silencing a signaling NaN are target-specific
@@ -423,9 +423,6 @@ static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
flag aIsLargerSignificand;
bits64 av, bv;
- if ( STATUS(default_nan_mode) )
- return float64_default_nan;
-
aIsQuietNaN = float64_is_quiet_nan( a );
aIsSignalingNaN = float64_is_signaling_nan( a );
bIsQuietNaN = float64_is_quiet_nan( b );
@@ -435,6 +432,9 @@ static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
+ if ( STATUS(default_nan_mode) )
+ return float64_default_nan;
+
if ((bits64)(av<<1) < (bits64)(bv<<1)) {
aIsLargerSignificand = 0;
} else if ((bits64)(bv<<1) < (bits64)(av<<1)) {
@@ -468,7 +468,8 @@ static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
/*----------------------------------------------------------------------------
| Returns 1 if the extended double-precision floating-point value `a' is a
-| quiet NaN; otherwise returns 0.
+| quiet NaN; otherwise returns 0. This slightly differs from the same
+| function for other types as floatx80 has an explicit bit.
*----------------------------------------------------------------------------*/
int floatx80_is_quiet_nan( floatx80 a )
@@ -482,19 +483,22 @@ int floatx80_is_quiet_nan( floatx80 a )
&& (bits64) ( aLow<<1 )
&& ( a.low == aLow );
#else
- return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
+ return ( ( a.high & 0x7FFF ) == 0x7FFF )
+ && (LIT64( 0x8000000000000000 ) <= ((bits64) ( a.low<<1 )));
#endif
}
/*----------------------------------------------------------------------------
| Returns 1 if the extended double-precision floating-point value `a' is a
-| signaling NaN; otherwise returns 0.
+| signaling NaN; otherwise returns 0. This slightly differs from the same
+| function for other types as floatx80 has an explicit bit.
*----------------------------------------------------------------------------*/
int floatx80_is_signaling_nan( floatx80 a )
{
#if SNAN_BIT_IS_ONE
- return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
+ return ( ( a.high & 0x7FFF ) == 0x7FFF )
+ && (LIT64( 0x8000000000000000 ) <= ((bits64) ( a.low<<1 )));
#else
bits64 aLow;
@@ -515,7 +519,7 @@ floatx80 floatx80_maybe_silence_nan( floatx80 a )
{
if (floatx80_is_signaling_nan(a)) {
#if SNAN_BIT_IS_ONE
-# if defined(TARGET_MIPS)
+# if defined(TARGET_MIPS) || defined(TARGET_SH4)
a.low = floatx80_default_nan_low;
a.high = floatx80_default_nan_high;
# else
@@ -574,12 +578,6 @@ static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM)
flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
flag aIsLargerSignificand;
- if ( STATUS(default_nan_mode) ) {
- a.low = floatx80_default_nan_low;
- a.high = floatx80_default_nan_high;
- return a;
- }
-
aIsQuietNaN = floatx80_is_quiet_nan( a );
aIsSignalingNaN = floatx80_is_signaling_nan( a );
bIsQuietNaN = floatx80_is_quiet_nan( b );
@@ -587,6 +585,12 @@ static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM)
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
+ if ( STATUS(default_nan_mode) ) {
+ a.low = floatx80_default_nan_low;
+ a.high = floatx80_default_nan_high;
+ return a;
+ }
+
if (a.low < b.low) {
aIsLargerSignificand = 0;
} else if (b.low < a.low) {
@@ -664,7 +668,7 @@ float128 float128_maybe_silence_nan( float128 a )
{
if (float128_is_signaling_nan(a)) {
#if SNAN_BIT_IS_ONE
-# if defined(TARGET_MIPS)
+# if defined(TARGET_MIPS) || defined(TARGET_SH4)
a.low = float128_default_nan_low;
a.high = float128_default_nan_high;
# else
@@ -719,12 +723,6 @@ static float128 propagateFloat128NaN( float128 a, float128 b STATUS_PARAM)
flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
flag aIsLargerSignificand;
- if ( STATUS(default_nan_mode) ) {
- a.low = float128_default_nan_low;
- a.high = float128_default_nan_high;
- return a;
- }
-
aIsQuietNaN = float128_is_quiet_nan( a );
aIsSignalingNaN = float128_is_signaling_nan( a );
bIsQuietNaN = float128_is_quiet_nan( b );
@@ -732,6 +730,12 @@ static float128 propagateFloat128NaN( float128 a, float128 b STATUS_PARAM)
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
+ if ( STATUS(default_nan_mode) ) {
+ a.low = float128_default_nan_low;
+ a.high = float128_default_nan_high;
+ return a;
+ }
+
if (lt128(a.high<<1, a.low, b.high<<1, b.low)) {
aIsLargerSignificand = 0;
} else if (lt128(b.high<<1, b.low, a.high<<1, a.low)) {
diff --git a/fpu/softfloat.h b/fpu/softfloat.h
index a6d0f16b42..4a5345ceca 100644
--- a/fpu/softfloat.h
+++ b/fpu/softfloat.h
@@ -336,6 +336,11 @@ INLINE int float32_is_any_nan(float32 a)
return ((float32_val(a) & ~(1 << 31)) > 0x7f800000UL);
}
+INLINE int float32_is_zero_or_denormal(float32 a)
+{
+ return (float32_val(a) & 0x7f800000) == 0;
+}
+
#define float32_zero make_float32(0)
#define float32_one make_float32(0x3f800000)
#define float32_ln2 make_float32(0x3f317218)
diff --git a/gdbstub.c b/gdbstub.c
index 0aa081b13b..d6556c9a2f 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -2391,6 +2391,12 @@ void gdb_exit(CPUState *env, int code)
snprintf(buf, sizeof(buf), "W%02x", (uint8_t)code);
put_packet(s, buf);
+
+#ifndef CONFIG_USER_ONLY
+ if (s->chr) {
+ qemu_chr_close(s->chr);
+ }
+#endif
}
#ifdef CONFIG_USER_ONLY
diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c
index bd0664fe7a..d8b062c1bf 100644
--- a/hw/arm_sysctl.c
+++ b/hw/arm_sysctl.c
@@ -28,6 +28,22 @@ typedef struct {
uint32_t proc_id;
} arm_sysctl_state;
+static const VMStateDescription vmstate_arm_sysctl = {
+ .name = "realview_sysctl",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(leds, arm_sysctl_state),
+ VMSTATE_UINT16(lockval, arm_sysctl_state),
+ VMSTATE_UINT32(cfgdata1, arm_sysctl_state),
+ VMSTATE_UINT32(cfgdata2, arm_sysctl_state),
+ VMSTATE_UINT32(flags, arm_sysctl_state),
+ VMSTATE_UINT32(nvflags, arm_sysctl_state),
+ VMSTATE_UINT32(resetlevel, arm_sysctl_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static void arm_sysctl_reset(DeviceState *d)
{
arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, sysbus_from_qdev(d));
@@ -231,6 +247,7 @@ static SysBusDeviceInfo arm_sysctl_info = {
.init = arm_sysctl_init1,
.qdev.name = "realview_sysctl",
.qdev.size = sizeof(arm_sysctl_state),
+ .qdev.vmsd = &vmstate_arm_sysctl,
.qdev.reset = arm_sysctl_reset,
.qdev.props = (Property[]) {
DEFINE_PROP_UINT32("sys_id", arm_sysctl_state, sys_id, 0),
diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c
index 14c6ad364c..7ec09df08c 100644
--- a/hw/gt64xxx.c
+++ b/hw/gt64xxx.c
@@ -223,16 +223,14 @@
#define GT_PCI0_HICMASK (0xca4 >> 2)
#define GT_PCI1_SERR1MASK (0xca8 >> 2)
-
-typedef PCIHostState GT64120PCIState;
-
#define PCI_MAPPING_ENTRY(regname) \
target_phys_addr_t regname ##_start; \
target_phys_addr_t regname ##_length; \
int regname ##_handle
typedef struct GT64120State {
- GT64120PCIState *pci;
+ SysBusDevice busdev;
+ PCIHostState pci;
uint32_t regs[GT_REGS];
PCI_MAPPING_ENTRY(PCI0IO);
PCI_MAPPING_ENTRY(ISD);
@@ -525,13 +523,13 @@ static void gt64120_writel (void *opaque, target_phys_addr_t addr,
/* not implemented */
break;
case GT_PCI0_CFGADDR:
- s->pci->config_reg = val & 0x80fffffc;
+ s->pci.config_reg = val & 0x80fffffc;
break;
case GT_PCI0_CFGDATA:
- if (!(s->regs[GT_PCI0_CMD] & 1) && (s->pci->config_reg & 0x00fff800))
+ if (!(s->regs[GT_PCI0_CMD] & 1) && (s->pci.config_reg & 0x00fff800))
val = bswap32(val);
- if (s->pci->config_reg & (1u << 31))
- pci_data_write(s->pci->bus, s->pci->config_reg, val, 4);
+ if (s->pci.config_reg & (1u << 31))
+ pci_data_write(s->pci.bus, s->pci.config_reg, val, 4);
break;
/* Interrupts */
@@ -765,14 +763,14 @@ static uint32_t gt64120_readl (void *opaque,
/* PCI Internal */
case GT_PCI0_CFGADDR:
- val = s->pci->config_reg;
+ val = s->pci.config_reg;
break;
case GT_PCI0_CFGDATA:
- if (!(s->pci->config_reg & (1 << 31)))
+ if (!(s->pci.config_reg & (1 << 31)))
val = 0xffffffff;
else
- val = pci_data_read(s->pci->bus, s->pci->config_reg, 4);
- if (!(s->regs[GT_PCI0_CMD] & 1) && (s->pci->config_reg & 0x00fff800))
+ val = pci_data_read(s->pci.bus, s->pci.config_reg, 4);
+ if (!(s->regs[GT_PCI0_CMD] & 1) && (s->pci.config_reg & 0x00fff800))
val = bswap32(val);
break;
@@ -864,7 +862,7 @@ static CPUReadMemoryFunc * const gt64120_read[] = {
&gt64120_readl,
};
-static int pci_gt64120_map_irq(PCIDevice *pci_dev, int irq_num)
+static int gt64120_pci_map_irq(PCIDevice *pci_dev, int irq_num)
{
int slot;
@@ -891,7 +889,7 @@ static int pci_gt64120_map_irq(PCIDevice *pci_dev, int irq_num)
static int pci_irq_levels[4];
-static void pci_gt64120_set_irq(void *opaque, int irq_num, int level)
+static void gt64120_pci_set_irq(void *opaque, int irq_num, int level)
{
int i, pic_irq, pic_level;
qemu_irq *pic = opaque;
@@ -1101,50 +1099,71 @@ static int gt64120_load(QEMUFile* f, void *opaque, int version_id)
return 0;
}
-PCIBus *pci_gt64120_init(qemu_irq *pic)
+PCIBus *gt64120_register(qemu_irq *pic)
+{
+ SysBusDevice *s;
+ GT64120State *d;
+ DeviceState *dev;
+
+ dev = qdev_create(NULL, "gt64120");
+ qdev_init_nofail(dev);
+ s = sysbus_from_qdev(dev);
+ d = FROM_SYSBUS(GT64120State, s);
+ d->pci.bus = pci_register_bus(&d->busdev.qdev, "pci",
+ gt64120_pci_set_irq, gt64120_pci_map_irq,
+ pic, PCI_DEVFN(18, 0), 4);
+ d->ISD_handle = cpu_register_io_memory(gt64120_read, gt64120_write, d,
+ DEVICE_NATIVE_ENDIAN);
+
+ pci_create_simple(d->pci.bus, PCI_DEVFN(0, 0), "gt64120_pci");
+ return d->pci.bus;
+}
+
+static int gt64120_init(SysBusDevice *dev)
{
GT64120State *s;
- PCIDevice *d;
- s = qemu_mallocz(sizeof(GT64120State));
- s->pci = qemu_mallocz(sizeof(GT64120PCIState));
+ s = FROM_SYSBUS(GT64120State, dev);
- s->pci->bus = pci_register_bus(NULL, "pci",
- pci_gt64120_set_irq, pci_gt64120_map_irq,
- pic, PCI_DEVFN(18, 0), 4);
- s->ISD_handle = cpu_register_io_memory(gt64120_read, gt64120_write, s,
- DEVICE_NATIVE_ENDIAN);
- d = pci_register_device(s->pci->bus, "GT64120 PCI Bus", sizeof(PCIDevice),
- 0, NULL, NULL);
+ qemu_register_reset(gt64120_reset, s);
+ register_savevm(&dev->qdev, "GT64120 PCI Bus", 0, 1,
+ gt64120_save, gt64120_load, &s->pci);
+ return 0;
+}
+static int gt64120_pci_init(PCIDevice *d)
+{
/* FIXME: Malta specific hw assumptions ahead */
-
pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_MARVELL);
pci_config_set_device_id(d->config, PCI_DEVICE_ID_MARVELL_GT6412X);
-
- d->config[0x04] = 0x00;
- d->config[0x05] = 0x00;
- d->config[0x06] = 0x80;
- d->config[0x07] = 0x02;
-
- d->config[0x08] = 0x10;
- d->config[0x09] = 0x00;
+ pci_set_word(d->config + PCI_COMMAND, 0);
+ pci_set_word(d->config + PCI_STATUS,
+ PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM);
+ pci_set_byte(d->config + PCI_CLASS_REVISION, 0x10);
+ pci_config_set_prog_interface(d->config, 0);
pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
+ pci_set_long(d->config + PCI_BASE_ADDRESS_0, 0x00000008);
+ pci_set_long(d->config + PCI_BASE_ADDRESS_1, 0x01000008);
+ pci_set_long(d->config + PCI_BASE_ADDRESS_2, 0x1c000000);
+ pci_set_long(d->config + PCI_BASE_ADDRESS_3, 0x1f000000);
+ pci_set_long(d->config + PCI_BASE_ADDRESS_4, 0x14000000);
+ pci_set_long(d->config + PCI_BASE_ADDRESS_5, 0x14000001);
+ pci_set_byte(d->config + 0x3d, 0x01);
- d->config[0x10] = 0x08;
- d->config[0x14] = 0x08;
- d->config[0x17] = 0x01;
- d->config[0x1B] = 0x1c;
- d->config[0x1F] = 0x1f;
- d->config[0x23] = 0x14;
- d->config[0x24] = 0x01;
- d->config[0x27] = 0x14;
- d->config[0x3D] = 0x01;
-
- gt64120_reset(s);
+ return 0;
+}
- register_savevm(&d->qdev, "GT64120 PCI Bus", 0, 1,
- gt64120_save, gt64120_load, d);
+static PCIDeviceInfo gt64120_pci_info = {
+ .qdev.name = "gt64120_pci",
+ .qdev.size = sizeof(PCIDevice),
+ .init = gt64120_pci_init,
+};
- return s->pci->bus;
+static void gt64120_pci_register_devices(void)
+{
+ sysbus_register_dev("gt64120", sizeof(GT64120State),
+ gt64120_init);
+ pci_qdev_register(&gt64120_pci_info);
}
+
+device_init(gt64120_pci_register_devices)
diff --git a/hw/lan9118.c b/hw/lan9118.c
index a98866479b..9cc7952b2a 100644
--- a/hw/lan9118.c
+++ b/hw/lan9118.c
@@ -187,7 +187,7 @@ typedef struct {
uint32_t phy_int_mask;
int eeprom_writable;
- uint8_t eeprom[8];
+ uint8_t eeprom[128];
int tx_fifo_size;
LAN9118Packet *txp;
@@ -1003,7 +1003,7 @@ static void lan9118_writel(void *opaque, target_phys_addr_t offset,
s->afc_cfg = val & 0x00ffffff;
break;
case CSR_E2P_CMD:
- lan9118_eeprom_cmd(s, (val >> 28) & 7, val & 0xff);
+ lan9118_eeprom_cmd(s, (val >> 28) & 7, val & 0x7f);
break;
case CSR_E2P_DATA:
s->e2p_data = val & 0xff;
diff --git a/hw/loader.c b/hw/loader.c
index eb198f6723..35d792e647 100644
--- a/hw/loader.c
+++ b/hw/loader.c
@@ -307,8 +307,9 @@ int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
target_data_order = ELFDATA2LSB;
}
- if (target_data_order != e_ident[EI_DATA])
- return -1;
+ if (target_data_order != e_ident[EI_DATA]) {
+ goto fail;
+ }
lseek(fd, 0, SEEK_SET);
if (e_ident[EI_CLASS] == ELFCLASS64) {
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 0129ae3cc0..9c761cdb66 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -1930,7 +1930,7 @@ static uint32_t lsi_ram_readw(void *opaque, target_phys_addr_t addr)
val = s->script_ram[addr >> 2];
if (addr & 2)
val >>= 16;
- return le16_to_cpu(val);
+ return val;
}
static uint32_t lsi_ram_readl(void *opaque, target_phys_addr_t addr)
@@ -1938,7 +1938,7 @@ static uint32_t lsi_ram_readl(void *opaque, target_phys_addr_t addr)
LSIState *s = opaque;
addr &= 0x1fff;
- return le32_to_cpu(s->script_ram[addr >> 2]);
+ return s->script_ram[addr >> 2];
}
static CPUReadMemoryFunc * const lsi_ram_readfn[3] = {
diff --git a/hw/m48t59.c b/hw/m48t59.c
index 6991e2e8e1..2020487bbe 100644
--- a/hw/m48t59.c
+++ b/hw/m48t59.c
@@ -642,6 +642,7 @@ M48t59State *m48t59_init(qemu_irq IRQ, target_phys_addr_t mem_base,
DeviceState *dev;
SysBusDevice *s;
M48t59SysBusState *d;
+ M48t59State *state;
dev = qdev_create(NULL, "m48t59");
qdev_prop_set_uint32(dev, "type", type);
@@ -649,18 +650,18 @@ M48t59State *m48t59_init(qemu_irq IRQ, target_phys_addr_t mem_base,
qdev_prop_set_uint32(dev, "io_base", io_base);
qdev_init_nofail(dev);
s = sysbus_from_qdev(dev);
+ d = FROM_SYSBUS(M48t59SysBusState, s);
+ state = &d->state;
sysbus_connect_irq(s, 0, IRQ);
if (io_base != 0) {
- register_ioport_read(io_base, 0x04, 1, NVRAM_readb, s);
- register_ioport_write(io_base, 0x04, 1, NVRAM_writeb, s);
+ register_ioport_read(io_base, 0x04, 1, NVRAM_readb, state);
+ register_ioport_write(io_base, 0x04, 1, NVRAM_writeb, state);
}
if (mem_base != 0) {
sysbus_mmio_map(s, 0, mem_base);
}
- d = FROM_SYSBUS(M48t59SysBusState, s);
-
- return &d->state;
+ return state;
}
M48t59State *m48t59_init_isa(uint32_t io_base, uint16_t size, int type)
diff --git a/hw/mainstone.c b/hw/mainstone.c
index efa2959c72..58e3f8670d 100644
--- a/hw/mainstone.c
+++ b/hw/mainstone.c
@@ -106,7 +106,8 @@ static void mainstone_common_init(ram_addr_t ram_size,
}
if (!pflash_cfi01_register(mainstone_flash_base[i],
- qemu_ram_alloc(NULL, "mainstone.flash",
+ qemu_ram_alloc(NULL, i ? "mainstone.flash1" :
+ "mainstone.flash0",
MAINSTONE_FLASH),
dinfo->bdrv, sector_len,
MAINSTONE_FLASH / sector_len, 4, 0, 0, 0, 0,
diff --git a/hw/mips.h b/hw/mips.h
index 617ea103c0..757e8f931c 100644
--- a/hw/mips.h
+++ b/hw/mips.h
@@ -3,7 +3,7 @@
/* Definitions for mips board emulation. */
/* gt64xxx.c */
-PCIBus *pci_gt64120_init(qemu_irq *pic);
+PCIBus *gt64120_register(qemu_irq *pic);
/* bonito.c */
PCIBus *bonito_init(qemu_irq *pic);
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 5ef3fcbea9..87554169c5 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -910,7 +910,7 @@ void mips_malta_init (ram_addr_t ram_size,
/* Board ID = 0x420 (Malta Board with CoreLV)
XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
map to the board ID. */
- stl_phys(0x1fc00010LL, 0x00000420);
+ stl_p(qemu_get_ram_ptr(bios_offset) + 0x10, 0x00000420);
/* Init internal devices */
cpu_mips_irq_init_cpu(env);
@@ -921,7 +921,7 @@ void mips_malta_init (ram_addr_t ram_size,
i8259 = i8259_init(env->irq[2]);
/* Northbridge */
- pci_bus = pci_gt64120_init(i8259);
+ pci_bus = gt64120_register(i8259);
/* Southbridge */
diff --git a/hw/mips_timer.c b/hw/mips_timer.c
index e3beee8281..9c95f282a2 100644
--- a/hw/mips_timer.c
+++ b/hw/mips_timer.c
@@ -42,16 +42,6 @@ uint32_t cpu_mips_get_random (CPUState *env)
}
/* MIPS R4K timer */
-uint32_t cpu_mips_get_count (CPUState *env)
-{
- if (env->CP0_Cause & (1 << CP0Ca_DC))
- return env->CP0_Count;
- else
- return env->CP0_Count +
- (uint32_t)muldiv64(qemu_get_clock(vm_clock),
- TIMER_FREQ, get_ticks_per_sec());
-}
-
static void cpu_mips_timer_update(CPUState *env)
{
uint64_t now, next;
@@ -64,6 +54,35 @@ static void cpu_mips_timer_update(CPUState *env)
qemu_mod_timer(env->timer, next);
}
+/* Expire the timer. */
+static void cpu_mips_timer_expire(CPUState *env)
+{
+ cpu_mips_timer_update(env);
+ if (env->insn_flags & ISA_MIPS32R2) {
+ env->CP0_Cause |= 1 << CP0Ca_TI;
+ }
+ qemu_irq_raise(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
+}
+
+uint32_t cpu_mips_get_count (CPUState *env)
+{
+ if (env->CP0_Cause & (1 << CP0Ca_DC)) {
+ return env->CP0_Count;
+ } else {
+ uint64_t now;
+
+ now = qemu_get_clock(vm_clock);
+ if (qemu_timer_pending(env->timer)
+ && qemu_timer_expired(env->timer, now)) {
+ /* The timer has already expired. */
+ cpu_mips_timer_expire(env);
+ }
+
+ return env->CP0_Count +
+ (uint32_t)muldiv64(now, TIMER_FREQ, get_ticks_per_sec());
+ }
+}
+
void cpu_mips_store_count (CPUState *env, uint32_t count)
{
if (env->CP0_Cause & (1 << CP0Ca_DC))
@@ -116,11 +135,8 @@ static void mips_timer_cb (void *opaque)
the comparator value. Offset the count by one to avoid immediately
retriggering the callback before any virtual time has passed. */
env->CP0_Count++;
- cpu_mips_timer_update(env);
+ cpu_mips_timer_expire(env);
env->CP0_Count--;
- if (env->insn_flags & ISA_MIPS32R2)
- env->CP0_Cause |= 1 << CP0Ca_TI;
- qemu_irq_raise(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
}
void cpu_mips_clock_init (CPUState *env)
diff --git a/hw/pl031.c b/hw/pl031.c
index e3700c169c..c488f69511 100644
--- a/hw/pl031.c
+++ b/hw/pl031.c
@@ -44,6 +44,21 @@ typedef struct {
uint32_t is;
} pl031_state;
+static const VMStateDescription vmstate_pl031 = {
+ .name = "pl031",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(tick_offset, pl031_state),
+ VMSTATE_UINT32(mr, pl031_state),
+ VMSTATE_UINT32(lr, pl031_state),
+ VMSTATE_UINT32(cr, pl031_state),
+ VMSTATE_UINT32(im, pl031_state),
+ VMSTATE_UINT32(is, pl031_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static const unsigned char pl031_id[] = {
0x31, 0x10, 0x14, 0x00, /* Device ID */
0x0d, 0xf0, 0x05, 0xb1 /* Cell ID */
@@ -206,9 +221,17 @@ static int pl031_init(SysBusDevice *dev)
return 0;
}
+static SysBusDeviceInfo pl031_info = {
+ .init = pl031_init,
+ .qdev.name = "pl031",
+ .qdev.size = sizeof(pl031_state),
+ .qdev.vmsd = &vmstate_pl031,
+ .qdev.no_user = 1,
+};
+
static void pl031_register_devices(void)
{
- sysbus_register_dev("pl031", sizeof(pl031_state), pl031_init);
+ sysbus_register_withprop(&pl031_info);
}
device_init(pl031_register_devices)
diff --git a/hw/pl050.c b/hw/pl050.c
index 057383985e..b155cc07b6 100644
--- a/hw/pl050.c
+++ b/hw/pl050.c
@@ -21,6 +21,20 @@ typedef struct {
int is_mouse;
} pl050_state;
+static const VMStateDescription vmstate_pl050 = {
+ .name = "pl050",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(cr, pl050_state),
+ VMSTATE_UINT32(clk, pl050_state),
+ VMSTATE_UINT32(last, pl050_state),
+ VMSTATE_INT32(pending, pl050_state),
+ VMSTATE_INT32(is_mouse, pl050_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
#define PL050_TXEMPTY (1 << 6)
#define PL050_TXBUSY (1 << 5)
#define PL050_RXFULL (1 << 4)
@@ -137,7 +151,6 @@ static int pl050_init(SysBusDevice *dev, int is_mouse)
s->dev = ps2_mouse_init(pl050_update, s);
else
s->dev = ps2_kbd_init(pl050_update, s);
- /* ??? Save/restore. */
return 0;
}
@@ -151,12 +164,24 @@ static int pl050_init_mouse(SysBusDevice *dev)
return pl050_init(dev, 1);
}
+static SysBusDeviceInfo pl050_kbd_info = {
+ .init = pl050_init_keyboard,
+ .qdev.name = "pl050_keyboard",
+ .qdev.size = sizeof(pl050_state),
+ .qdev.vmsd = &vmstate_pl050,
+};
+
+static SysBusDeviceInfo pl050_mouse_info = {
+ .init = pl050_init_mouse,
+ .qdev.name = "pl050_mouse",
+ .qdev.size = sizeof(pl050_state),
+ .qdev.vmsd = &vmstate_pl050,
+};
+
static void pl050_register_devices(void)
{
- sysbus_register_dev("pl050_keyboard", sizeof(pl050_state),
- pl050_init_keyboard);
- sysbus_register_dev("pl050_mouse", sizeof(pl050_state),
- pl050_init_mouse);
+ sysbus_register_withprop(&pl050_kbd_info);
+ sysbus_register_withprop(&pl050_mouse_info);
}
device_init(pl050_register_devices)
diff --git a/hw/pl080.c b/hw/pl080.c
index 1a3e06c920..901f04a844 100644
--- a/hw/pl080.c
+++ b/hw/pl080.c
@@ -52,6 +52,43 @@ typedef struct {
qemu_irq irq;
} pl080_state;
+static const VMStateDescription vmstate_pl080_channel = {
+ .name = "pl080_channel",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(src, pl080_channel),
+ VMSTATE_UINT32(dest, pl080_channel),
+ VMSTATE_UINT32(lli, pl080_channel),
+ VMSTATE_UINT32(ctrl, pl080_channel),
+ VMSTATE_UINT32(conf, pl080_channel),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const VMStateDescription vmstate_pl080 = {
+ .name = "pl080",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8(tc_int, pl080_state),
+ VMSTATE_UINT8(tc_mask, pl080_state),
+ VMSTATE_UINT8(err_int, pl080_state),
+ VMSTATE_UINT8(err_mask, pl080_state),
+ VMSTATE_UINT32(conf, pl080_state),
+ VMSTATE_UINT32(sync, pl080_state),
+ VMSTATE_UINT32(req_single, pl080_state),
+ VMSTATE_UINT32(req_burst, pl080_state),
+ VMSTATE_UINT8(tc_int, pl080_state),
+ VMSTATE_UINT8(tc_int, pl080_state),
+ VMSTATE_UINT8(tc_int, pl080_state),
+ VMSTATE_STRUCT_ARRAY(chan, pl080_state, PL080_MAX_CHANNELS,
+ 1, vmstate_pl080_channel, pl080_channel),
+ VMSTATE_INT32(running, pl080_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static const unsigned char pl080_id[] =
{ 0x80, 0x10, 0x04, 0x0a, 0x0d, 0xf0, 0x05, 0xb1 };
@@ -330,7 +367,6 @@ static int pl08x_init(SysBusDevice *dev, int nchannels)
sysbus_init_mmio(dev, 0x1000, iomemtype);
sysbus_init_irq(dev, &s->irq);
s->nchannels = nchannels;
- /* ??? Save/restore. */
return 0;
}
@@ -344,12 +380,28 @@ static int pl081_init(SysBusDevice *dev)
return pl08x_init(dev, 2);
}
+static SysBusDeviceInfo pl080_info = {
+ .init = pl080_init,
+ .qdev.name = "pl080",
+ .qdev.size = sizeof(pl080_state),
+ .qdev.vmsd = &vmstate_pl080,
+ .qdev.no_user = 1,
+};
+
+static SysBusDeviceInfo pl081_info = {
+ .init = pl081_init,
+ .qdev.name = "pl081",
+ .qdev.size = sizeof(pl080_state),
+ .qdev.vmsd = &vmstate_pl080,
+ .qdev.no_user = 1,
+};
+
/* The PL080 and PL081 are the same except for the number of channels
they implement (8 and 2 respectively). */
static void pl080_register_devices(void)
{
- sysbus_register_dev("pl080", sizeof(pl080_state), pl080_init);
- sysbus_register_dev("pl081", sizeof(pl080_state), pl081_init);
+ sysbus_register_withprop(&pl080_info);
+ sysbus_register_withprop(&pl081_info);
}
device_init(pl080_register_devices)
diff --git a/hw/pl110.c b/hw/pl110.c
index a4adb630b0..06d2dfada6 100644
--- a/hw/pl110.c
+++ b/hw/pl110.c
@@ -48,6 +48,28 @@ typedef struct {
qemu_irq irq;
} pl110_state;
+static const VMStateDescription vmstate_pl110 = {
+ .name = "pl110",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_INT32(versatile, pl110_state),
+ VMSTATE_UINT32_ARRAY(timing, pl110_state, 4),
+ VMSTATE_UINT32(cr, pl110_state),
+ VMSTATE_UINT32(upbase, pl110_state),
+ VMSTATE_UINT32(lpbase, pl110_state),
+ VMSTATE_UINT32(int_status, pl110_state),
+ VMSTATE_UINT32(int_mask, pl110_state),
+ VMSTATE_INT32(cols, pl110_state),
+ VMSTATE_INT32(rows, pl110_state),
+ VMSTATE_UINT32(bpp, pl110_state),
+ VMSTATE_INT32(invalidate, pl110_state),
+ VMSTATE_UINT32_ARRAY(pallette, pl110_state, 256),
+ VMSTATE_UINT32_ARRAY(raw_pallette, pl110_state, 128),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static const unsigned char pl110_id[] =
{ 0x10, 0x11, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
@@ -365,7 +387,6 @@ static int pl110_init(SysBusDevice *dev)
s->ds = graphic_console_init(pl110_update_display,
pl110_invalidate_display,
NULL, NULL, s);
- /* ??? Save/restore. */
return 0;
}
@@ -376,11 +397,26 @@ static int pl110_versatile_init(SysBusDevice *dev)
return pl110_init(dev);
}
+static SysBusDeviceInfo pl110_info = {
+ .init = pl110_init,
+ .qdev.name = "pl110",
+ .qdev.size = sizeof(pl110_state),
+ .qdev.vmsd = &vmstate_pl110,
+ .qdev.no_user = 1,
+};
+
+static SysBusDeviceInfo pl110_versatile_info = {
+ .init = pl110_versatile_init,
+ .qdev.name = "pl110_versatile",
+ .qdev.size = sizeof(pl110_state),
+ .qdev.vmsd = &vmstate_pl110,
+ .qdev.no_user = 1,
+};
+
static void pl110_register_devices(void)
{
- sysbus_register_dev("pl110", sizeof(pl110_state), pl110_init);
- sysbus_register_dev("pl110_versatile", sizeof(pl110_state),
- pl110_versatile_init);
+ sysbus_register_withprop(&pl110_info);
+ sysbus_register_withprop(&pl110_versatile_info);
}
device_init(pl110_register_devices)
diff --git a/hw/pl190.c b/hw/pl190.c
index e04e6c17fb..17c279bed7 100644
--- a/hw/pl190.c
+++ b/hw/pl190.c
@@ -212,8 +212,9 @@ static CPUWriteMemoryFunc * const pl190_writefn[] = {
pl190_write
};
-static void pl190_reset(pl190_state *s)
+static void pl190_reset(DeviceState *d)
{
+ pl190_state *s = DO_UPCAST(pl190_state, busdev.qdev, d);
int i;
for (i = 0; i < 16; i++)
@@ -239,14 +240,41 @@ static int pl190_init(SysBusDevice *dev)
qdev_init_gpio_in(&dev->qdev, pl190_set_irq, 32);
sysbus_init_irq(dev, &s->irq);
sysbus_init_irq(dev, &s->fiq);
- pl190_reset(s);
- /* ??? Save/restore. */
return 0;
}
+static const VMStateDescription vmstate_pl190 = {
+ .name = "pl190",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(level, pl190_state),
+ VMSTATE_UINT32(soft_level, pl190_state),
+ VMSTATE_UINT32(irq_enable, pl190_state),
+ VMSTATE_UINT32(fiq_select, pl190_state),
+ VMSTATE_UINT32(default_addr, pl190_state),
+ VMSTATE_UINT8_ARRAY(vect_control, pl190_state, 16),
+ VMSTATE_UINT32_ARRAY(vect_addr, pl190_state, PL190_NUM_PRIO),
+ VMSTATE_UINT32_ARRAY(prio_mask, pl190_state, PL190_NUM_PRIO+1),
+ VMSTATE_INT32(protected, pl190_state),
+ VMSTATE_INT32(priority, pl190_state),
+ VMSTATE_INT32_ARRAY(prev_prio, pl190_state, PL190_NUM_PRIO),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static SysBusDeviceInfo pl190_info = {
+ .init = pl190_init,
+ .qdev.name = "pl190",
+ .qdev.size = sizeof(pl190_state),
+ .qdev.vmsd = &vmstate_pl190,
+ .qdev.reset = pl190_reset,
+ .qdev.no_user = 1,
+};
+
static void pl190_register_devices(void)
{
- sysbus_register_dev("pl190", sizeof(pl190_state), pl190_init);
+ sysbus_register_withprop(&pl190_info);
}
device_init(pl190_register_devices)
diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c
index 8136cb962b..334187e53b 100644
--- a/hw/ppc405_uc.c
+++ b/hw/ppc405_uc.c
@@ -68,8 +68,9 @@ ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd,
stl_phys(bdloc + 0x34, bd->bi_baudrate);
for (i = 0; i < 4; i++)
stb_phys(bdloc + 0x38 + i, bd->bi_s_version[i]);
- for (i = 0; i < 32; i++)
- stb_phys(bdloc + 0x3C + i, bd->bi_s_version[i]);
+ for (i = 0; i < 32; i++) {
+ stb_phys(bdloc + 0x3C + i, bd->bi_r_version[i]);
+ }
stl_phys(bdloc + 0x5C, bd->bi_plb_busfreq);
stl_phys(bdloc + 0x60, bd->bi_pci_busfreq);
for (i = 0; i < 6; i++)
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index ab524a779a..6e72a5c753 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -1476,7 +1476,7 @@ static const VMStateDescription vmstate_pxa2xx_i2c = {
VMSTATE_UINT8(ibmr, PXA2xxI2CState),
VMSTATE_UINT8(data, PXA2xxI2CState),
VMSTATE_STRUCT_POINTER(slave, PXA2xxI2CState,
- vmstate_pxa2xx_i2c, PXA2xxI2CSlaveState *),
+ vmstate_pxa2xx_i2c_slave, PXA2xxI2CSlaveState *),
VMSTATE_END_OF_LIST()
}
};
diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c
index 1f2211a2f0..5b2b07e02c 100644
--- a/hw/pxa2xx_lcd.c
+++ b/hw/pxa2xx_lcd.c
@@ -796,9 +796,9 @@ static void pxa2xx_update_display(void *opaque)
if (miny >= 0) {
if (s->orientation)
- dpy_update(s->ds, miny, 0, maxy, s->xres);
+ dpy_update(s->ds, miny, 0, maxy - miny, s->xres);
else
- dpy_update(s->ds, 0, miny, s->xres, maxy);
+ dpy_update(s->ds, 0, miny, s->xres, maxy - miny);
}
pxa2xx_lcdc_int_update(s);
diff --git a/hw/r2d.c b/hw/r2d.c
index c4f32ef49d..a0f8c1f201 100644
--- a/hw/r2d.c
+++ b/hw/r2d.c
@@ -23,13 +23,13 @@
* THE SOFTWARE.
*/
+#include "sysbus.h"
#include "hw.h"
#include "sh.h"
#include "devices.h"
#include "sysemu.h"
#include "boards.h"
#include "pci.h"
-#include "sh_pci.h"
#include "net.h"
#include "sh7750_regs.h"
#include "ide.h"
@@ -195,17 +195,18 @@ static qemu_irq *r2d_fpga_init(target_phys_addr_t base, qemu_irq irl)
return qemu_allocate_irqs(r2d_fpga_irq_set, s, NR_IRQS);
}
-static void r2d_pci_set_irq(void *opaque, int n, int l)
-{
- qemu_irq *p = opaque;
-
- qemu_set_irq(p[n], l);
-}
+typedef struct ResetData {
+ CPUState *env;
+ uint32_t vector;
+} ResetData;
-static int r2d_pci_map_irq(PCIDevice *d, int irq_num)
+static void main_cpu_reset(void *opaque)
{
- const int intx[] = { PCI_INTA, PCI_INTB, PCI_INTC, PCI_INTD };
- return intx[d->devfn >> 3];
+ ResetData *s = (ResetData *)opaque;
+ CPUState *env = s->env;
+
+ cpu_reset(env);
+ env->pc = s->vector;
}
static struct __attribute__((__packed__))
@@ -228,6 +229,7 @@ static void r2d_init(ram_addr_t ram_size,
const char *initrd_filename, const char *cpu_model)
{
CPUState *env;
+ ResetData *reset_info;
struct SH7750State *s;
ram_addr_t sdram_addr;
qemu_irq *irq;
@@ -242,6 +244,10 @@ static void r2d_init(ram_addr_t ram_size,
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
+ reset_info = qemu_mallocz(sizeof(ResetData));
+ reset_info->env = env;
+ reset_info->vector = env->pc;
+ qemu_register_reset(main_cpu_reset, reset_info);
/* Allocate memory space */
sdram_addr = qemu_ram_alloc(NULL, "r2d.sdram", SDRAM_SIZE);
@@ -249,7 +255,8 @@ static void r2d_init(ram_addr_t ram_size,
/* Register peripherals */
s = sh7750_init(env);
irq = r2d_fpga_init(0x04000000, sh7750_irl(s));
- sh_pci_register_bus(r2d_pci_set_irq, r2d_pci_map_irq, irq, 0, 4);
+ sysbus_create_varargs("sh_pci", 0x1e200000, irq[PCI_INTA], irq[PCI_INTB],
+ irq[PCI_INTC], irq[PCI_INTD], NULL);
sm501_init(0x10000000, SM501_VRAM_SIZE, irq[SM501], serial_hds[2]);
@@ -290,7 +297,7 @@ static void r2d_init(ram_addr_t ram_size,
/* initialization which should be done by firmware */
stl_phys(SH7750_BCR1, 1<<3); /* cs3 SDRAM */
stw_phys(SH7750_BCR2, 3<<(3*2)); /* cs3 32bit */
- env->pc = (SDRAM_BASE + LINUX_LOAD_OFFSET) | 0xa0000000; /* Start from P2 area */
+ reset_info->vector = (SDRAM_BASE + LINUX_LOAD_OFFSET) | 0xa0000000; /* Start from P2 area */
}
if (initrd_filename) {
diff --git a/hw/sh_pci.c b/hw/sh_pci.c
index 072078be51..e99d8dbfb5 100644
--- a/hw/sh_pci.c
+++ b/hw/sh_pci.c
@@ -21,24 +21,26 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-#include "hw.h"
+#include "sysbus.h"
#include "sh.h"
#include "pci.h"
#include "pci_host.h"
-#include "sh_pci.h"
#include "bswap.h"
-typedef struct {
+typedef struct SHPCIState {
+ SysBusDevice busdev;
PCIBus *bus;
PCIDevice *dev;
+ qemu_irq irq[4];
+ int memconfig;
uint32_t par;
uint32_t mbr;
uint32_t iobr;
-} SHPCIC;
+} SHPCIState;
static void sh_pci_reg_write (void *p, target_phys_addr_t addr, uint32_t val)
{
- SHPCIC *pcic = p;
+ SHPCIState *pcic = p;
switch(addr) {
case 0 ... 0xfc:
cpu_to_le32w((uint32_t*)(pcic->dev->config + addr), val);
@@ -65,7 +67,7 @@ static void sh_pci_reg_write (void *p, target_phys_addr_t addr, uint32_t val)
static uint32_t sh_pci_reg_read (void *p, target_phys_addr_t addr)
{
- SHPCIC *pcic = p;
+ SHPCIState *pcic = p;
switch(addr) {
case 0 ... 0xfc:
return le32_to_cpup((uint32_t*)(pcic->dev->config + addr));
@@ -91,32 +93,69 @@ static MemOp sh_pci_reg = {
{ NULL, NULL, sh_pci_reg_write },
};
-PCIBus *sh_pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
- void *opaque, int devfn_min, int nirq)
+static int sh_pci_map_irq(PCIDevice *d, int irq_num)
+{
+ return (d->devfn >> 3);
+}
+
+static void sh_pci_set_irq(void *opaque, int irq_num, int level)
+{
+ qemu_irq *pic = opaque;
+
+ qemu_set_irq(pic[irq_num], level);
+}
+
+static void sh_pci_map(SysBusDevice *dev, target_phys_addr_t base)
+{
+ SHPCIState *s = FROM_SYSBUS(SHPCIState, dev);
+
+ cpu_register_physical_memory(P4ADDR(base), 0x224, s->memconfig);
+ cpu_register_physical_memory(A7ADDR(base), 0x224, s->memconfig);
+
+ s->iobr = 0xfe240000;
+ isa_mmio_init(s->iobr, 0x40000);
+}
+
+static int sh_pci_init_device(SysBusDevice *dev)
+{
+ SHPCIState *s;
+ int i;
+
+ s = FROM_SYSBUS(SHPCIState, dev);
+ for (i = 0; i < 4; i++) {
+ sysbus_init_irq(dev, &s->irq[i]);
+ }
+ s->bus = pci_register_bus(&s->busdev.qdev, "pci",
+ sh_pci_set_irq, sh_pci_map_irq,
+ s->irq, PCI_DEVFN(0, 0), 4);
+ s->memconfig = cpu_register_io_memory(sh_pci_reg.r, sh_pci_reg.w,
+ s, DEVICE_NATIVE_ENDIAN);
+ sysbus_init_mmio_cb(dev, 0x224, sh_pci_map);
+ s->dev = pci_create_simple(s->bus, PCI_DEVFN(0, 0), "sh_pci_host");
+ return 0;
+}
+
+static int sh_pci_host_init(PCIDevice *d)
+{
+ pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_HITACHI);
+ pci_config_set_device_id(d->config, PCI_DEVICE_ID_HITACHI_SH7751R);
+ pci_set_word(d->config + PCI_COMMAND, PCI_COMMAND_WAIT);
+ pci_set_word(d->config + PCI_STATUS, PCI_STATUS_CAP_LIST |
+ PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM);
+ return 0;
+}
+
+static PCIDeviceInfo sh_pci_host_info = {
+ .qdev.name = "sh_pci_host",
+ .qdev.size = sizeof(PCIDevice),
+ .init = sh_pci_host_init,
+};
+
+static void sh_pci_register_devices(void)
{
- SHPCIC *p;
- int reg;
-
- p = qemu_mallocz(sizeof(SHPCIC));
- p->bus = pci_register_bus(NULL, "pci",
- set_irq, map_irq, opaque, devfn_min, nirq);
-
- p->dev = pci_register_device(p->bus, "SH PCIC", sizeof(PCIDevice),
- -1, NULL, NULL);
- reg = cpu_register_io_memory(sh_pci_reg.r, sh_pci_reg.w, p,
- DEVICE_NATIVE_ENDIAN);
- cpu_register_physical_memory(0x1e200000, 0x224, reg);
- cpu_register_physical_memory(0xfe200000, 0x224, reg);
-
- p->iobr = 0xfe240000;
- isa_mmio_init(p->iobr, 0x40000);
-
- pci_config_set_vendor_id(p->dev->config, PCI_VENDOR_ID_HITACHI);
- pci_config_set_device_id(p->dev->config, PCI_DEVICE_ID_HITACHI_SH7751R);
- p->dev->config[0x04] = 0x80;
- p->dev->config[0x05] = 0x00;
- p->dev->config[0x06] = 0x90;
- p->dev->config[0x07] = 0x02;
-
- return p->bus;
+ sysbus_register_dev("sh_pci", sizeof(SHPCIState),
+ sh_pci_init_device);
+ pci_qdev_register(&sh_pci_host_info);
}
+
+device_init(sh_pci_register_devices)
diff --git a/hw/sh_pci.h b/hw/sh_pci.h
deleted file mode 100644
index b1a5ec37c3..0000000000
--- a/hw/sh_pci.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef QEMU_SH_PCI_H
-#define QEMU_SH_PCI_H
-
-#include "qemu-common.h"
-
-PCIBus *sh_pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
- void *pic, int devfn_min, int nirq);
-
-#endif
diff --git a/hw/sh_serial.c b/hw/sh_serial.c
index 1bdc0a5ab2..191f4a60c6 100644
--- a/hw/sh_serial.c
+++ b/hw/sh_serial.c
@@ -74,7 +74,7 @@ static void sh_serial_clear_fifo(sh_serial_state * s)
s->rx_tail = 0;
}
-static void sh_serial_ioport_write(void *opaque, uint32_t offs, uint32_t val)
+static void sh_serial_write(void *opaque, uint32_t offs, uint32_t val)
{
sh_serial_state *s = opaque;
unsigned char ch;
@@ -185,7 +185,7 @@ static void sh_serial_ioport_write(void *opaque, uint32_t offs, uint32_t val)
abort();
}
-static uint32_t sh_serial_ioport_read(void *opaque, uint32_t offs)
+static uint32_t sh_serial_read(void *opaque, uint32_t offs)
{
sh_serial_state *s = opaque;
uint32_t ret = ~0;
@@ -293,26 +293,6 @@ static int sh_serial_can_receive(sh_serial_state *s)
return s->scr & (1 << 4);
}
-static void sh_serial_receive_byte(sh_serial_state *s, int ch)
-{
- if (s->feat & SH_SERIAL_FEAT_SCIF) {
- if (s->rx_cnt < SH_RX_FIFO_LENGTH) {
- s->rx_fifo[s->rx_head++] = ch;
- if (s->rx_head == SH_RX_FIFO_LENGTH)
- s->rx_head = 0;
- s->rx_cnt++;
- if (s->rx_cnt >= s->rtrg) {
- s->flags |= SH_SERIAL_FLAG_RDF;
- if (s->scr & (1 << 6) && s->rxi) {
- qemu_set_irq(s->rxi, 1);
- }
- }
- }
- } else {
- s->rx_fifo[0] = ch;
- }
-}
-
static void sh_serial_receive_break(sh_serial_state *s)
{
if (s->feat & SH_SERIAL_FEAT_SCIF)
@@ -328,7 +308,27 @@ static int sh_serial_can_receive1(void *opaque)
static void sh_serial_receive1(void *opaque, const uint8_t *buf, int size)
{
sh_serial_state *s = opaque;
- sh_serial_receive_byte(s, buf[0]);
+
+ if (s->feat & SH_SERIAL_FEAT_SCIF) {
+ int i;
+ for (i = 0; i < size; i++) {
+ if (s->rx_cnt < SH_RX_FIFO_LENGTH) {
+ s->rx_fifo[s->rx_head++] = buf[i];
+ if (s->rx_head == SH_RX_FIFO_LENGTH) {
+ s->rx_head = 0;
+ }
+ s->rx_cnt++;
+ if (s->rx_cnt >= s->rtrg) {
+ s->flags |= SH_SERIAL_FLAG_RDF;
+ if (s->scr & (1 << 6) && s->rxi) {
+ qemu_set_irq(s->rxi, 1);
+ }
+ }
+ }
+ }
+ } else {
+ s->rx_fifo[0] = buf[0];
+ }
}
static void sh_serial_event(void *opaque, int event)
@@ -338,19 +338,6 @@ static void sh_serial_event(void *opaque, int event)
sh_serial_receive_break(s);
}
-static uint32_t sh_serial_read (void *opaque, target_phys_addr_t addr)
-{
- sh_serial_state *s = opaque;
- return sh_serial_ioport_read(s, addr);
-}
-
-static void sh_serial_write (void *opaque,
- target_phys_addr_t addr, uint32_t value)
-{
- sh_serial_state *s = opaque;
- sh_serial_ioport_write(s, addr, value);
-}
-
static CPUReadMemoryFunc * const sh_serial_readfn[] = {
&sh_serial_read,
&sh_serial_read,
diff --git a/hw/sm501.c b/hw/sm501.c
index f16e6e4e65..388fc085be 100644
--- a/hw/sm501.c
+++ b/hw/sm501.c
@@ -511,6 +511,7 @@ typedef struct SM501State {
uint32_t dc_crt_hwc_color_1_2;
uint32_t dc_crt_hwc_color_3;
+ uint32_t twoD_source;
uint32_t twoD_destination;
uint32_t twoD_dimension;
uint32_t twoD_control;
@@ -636,6 +637,9 @@ static void sm501_2d_operation(SM501State * s)
{
/* obtain operation parameters */
int operation = (s->twoD_control >> 16) & 0x1f;
+ int rtl = s->twoD_control & 0x8000000;
+ int src_x = (s->twoD_source >> 16) & 0x01FFF;
+ int src_y = s->twoD_source & 0xFFFF;
int dst_x = (s->twoD_destination >> 16) & 0x01FFF;
int dst_y = s->twoD_destination & 0xFFFF;
int operation_width = (s->twoD_dimension >> 16) & 0x1FFF;
@@ -645,10 +649,9 @@ static void sm501_2d_operation(SM501State * s)
int addressing = (s->twoD_stretch >> 16) & 0xF;
/* get frame buffer info */
-#if 0 /* for future use */
uint8_t * src = s->local_mem + (s->twoD_source_base & 0x03FFFFFF);
-#endif
uint8_t * dst = s->local_mem + (s->twoD_destination_base & 0x03FFFFFF);
+ int src_width = (s->dc_crt_h_total & 0x00000FFF) + 1;
int dst_width = (s->dc_crt_h_total & 0x00000FFF) + 1;
if (addressing != 0x0) {
@@ -663,8 +666,36 @@ static void sm501_2d_operation(SM501State * s)
}
switch (operation) {
- case 0x01: /* fill rectangle */
+ case 0x00: /* copy area */
+#define COPY_AREA(_bpp, _pixel_type, rtl) { \
+ int y, x, index_d, index_s; \
+ for (y = 0; y < operation_height; y++) { \
+ for (x = 0; x < operation_width; x++) { \
+ if (rtl) { \
+ index_s = ((src_y - y) * src_width + src_x - x) * _bpp; \
+ index_d = ((dst_y - y) * dst_width + dst_x - x) * _bpp; \
+ } else { \
+ index_s = ((src_y + y) * src_width + src_x + x) * _bpp; \
+ index_d = ((dst_y + y) * dst_width + dst_x + x) * _bpp; \
+ } \
+ *(_pixel_type*)&dst[index_d] = *(_pixel_type*)&src[index_s];\
+ } \
+ } \
+ }
+ switch (format_flags) {
+ case 0:
+ COPY_AREA(1, uint8_t, rtl);
+ break;
+ case 1:
+ COPY_AREA(2, uint16_t, rtl);
+ break;
+ case 2:
+ COPY_AREA(4, uint32_t, rtl);
+ break;
+ }
+ break;
+ case 0x01: /* fill rectangle */
#define FILL_RECT(_bpp, _pixel_type) { \
int y, x; \
for (y = 0; y < operation_height; y++) { \
@@ -1072,6 +1103,9 @@ static void sm501_2d_engine_write(void *opaque,
addr, value);
switch(addr) {
+ case SM501_2D_SOURCE:
+ s->twoD_source = value;
+ break;
case SM501_2D_DESTINATION:
s->twoD_destination = value;
break;
diff --git a/hw/smc91c111.c b/hw/smc91c111.c
index fc714d7f28..dafea5cc6e 100644
--- a/hw/smc91c111.c
+++ b/hw/smc91c111.c
@@ -46,6 +46,35 @@ typedef struct {
int mmio_index;
} smc91c111_state;
+static const VMStateDescription vmstate_smc91c111 = {
+ .name = "smc91c111",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_UINT16(tcr, smc91c111_state),
+ VMSTATE_UINT16(rcr, smc91c111_state),
+ VMSTATE_UINT16(cr, smc91c111_state),
+ VMSTATE_UINT16(ctr, smc91c111_state),
+ VMSTATE_UINT16(gpr, smc91c111_state),
+ VMSTATE_UINT16(ptr, smc91c111_state),
+ VMSTATE_UINT16(ercv, smc91c111_state),
+ VMSTATE_INT32(bank, smc91c111_state),
+ VMSTATE_INT32(packet_num, smc91c111_state),
+ VMSTATE_INT32(tx_alloc, smc91c111_state),
+ VMSTATE_INT32(allocated, smc91c111_state),
+ VMSTATE_INT32(tx_fifo_len, smc91c111_state),
+ VMSTATE_INT32_ARRAY(tx_fifo, smc91c111_state, NUM_PACKETS),
+ VMSTATE_INT32(rx_fifo_len, smc91c111_state),
+ VMSTATE_INT32_ARRAY(rx_fifo, smc91c111_state, NUM_PACKETS),
+ VMSTATE_INT32(tx_fifo_done_len, smc91c111_state),
+ VMSTATE_INT32_ARRAY(tx_fifo_done, smc91c111_state, NUM_PACKETS),
+ VMSTATE_BUFFER_UNSAFE(data, smc91c111_state, 0, NUM_PACKETS * 2048),
+ VMSTATE_UINT8(int_level, smc91c111_state),
+ VMSTATE_UINT8(int_mask, smc91c111_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
#define RCR_SOFT_RST 0x8000
#define RCR_STRIP_CRC 0x0200
#define RCR_RXEN 0x0100
@@ -738,6 +767,7 @@ static SysBusDeviceInfo smc91c111_info = {
.init = smc91c111_init1,
.qdev.name = "smc91c111",
.qdev.size = sizeof(smc91c111_state),
+ .qdev.vmsd = &vmstate_smc91c111,
.qdev.props = (Property[]) {
DEFINE_NIC_PROPERTIES(smc91c111_state, conf),
DEFINE_PROP_END_OF_LIST(),
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index 882d933466..12bf46fa7e 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -399,7 +399,7 @@ static const uint8_t usb_hid_usage_keys[0x100] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x4a,
0x52, 0x4b, 0x00, 0x50, 0x00, 0x4f, 0x00, 0x4d,
0x51, 0x4e, 0x49, 0x4c, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -460,15 +460,18 @@ static void usb_keyboard_event(void *opaque, int keycode)
case 0xe0:
if (s->modifiers & (1 << 9)) {
s->modifiers ^= 3 << 8;
+ usb_hid_changed(hs);
return;
}
case 0xe1 ... 0xe7:
if (keycode & (1 << 7)) {
s->modifiers &= ~(1 << (hid_code & 0x0f));
+ usb_hid_changed(hs);
return;
}
case 0xe8 ... 0xef:
s->modifiers |= 1 << (hid_code & 0x0f);
+ usb_hid_changed(hs);
return;
}
diff --git a/hw/versatilepb.c b/hw/versatilepb.c
index be758e447f..9f1bfcf941 100644
--- a/hw/versatilepb.c
+++ b/hw/versatilepb.c
@@ -30,6 +30,18 @@ typedef struct vpb_sic_state
int irq;
} vpb_sic_state;
+static const VMStateDescription vmstate_vpb_sic = {
+ .name = "versatilepb_sic",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(level, vpb_sic_state),
+ VMSTATE_UINT32(mask, vpb_sic_state),
+ VMSTATE_UINT32(pic_enable, vpb_sic_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static void vpb_sic_update(vpb_sic_state *s)
{
uint32_t flags;
@@ -146,7 +158,6 @@ static int vpb_sic_init(SysBusDevice *dev)
vpb_sic_writefn, s,
DEVICE_NATIVE_ENDIAN);
sysbus_init_mmio(dev, 0x1000, iomemtype);
- /* ??? Save/restore. */
return 0;
}
@@ -335,10 +346,17 @@ static void versatile_machine_init(void)
machine_init(versatile_machine_init);
+static SysBusDeviceInfo vpb_sic_info = {
+ .init = vpb_sic_init,
+ .qdev.name = "versatilepb_sic",
+ .qdev.size = sizeof(vpb_sic_state),
+ .qdev.vmsd = &vmstate_vpb_sic,
+ .qdev.no_user = 1,
+};
+
static void versatilepb_register_devices(void)
{
- sysbus_register_dev("versatilepb_sic", sizeof(vpb_sic_state),
- vpb_sic_init);
+ sysbus_register_withprop(&vpb_sic_info);
}
device_init(versatilepb_register_devices)
diff --git a/hw/zaurus.c b/hw/zaurus.c
index 54ec3f00d5..36be94a179 100644
--- a/hw/zaurus.c
+++ b/hw/zaurus.c
@@ -70,7 +70,7 @@ static uint32_t scoop_readb(void *opaque, target_phys_addr_t addr)
{
ScoopInfo *s = (ScoopInfo *) opaque;
- switch (addr) {
+ switch (addr & 0x3f) {
case SCOOP_MCR:
return s->mcr;
case SCOOP_CDR:
@@ -104,7 +104,7 @@ static void scoop_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
ScoopInfo *s = (ScoopInfo *) opaque;
value &= 0xffff;
- switch (addr) {
+ switch (addr & 0x3f) {
case SCOOP_MCR:
s->mcr = value;
break;
diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index 538e2572bb..acff781081 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -76,7 +76,7 @@
#ifdef FIGETBSZ
IOCTL(FIGETBSZ, IOC_R, MK_PTR(TYPE_LONG))
#endif
-#ifdef FS_IOC_FIEMAP
+#ifdef CONFIG_FIEMAP
IOCTL_SPECIAL(FS_IOC_FIEMAP, IOC_W | IOC_R, do_ioctl_fs_ioc_fiemap,
MK_PTR(MK_STRUCT(STRUCT_fiemap)))
#endif
diff --git a/linux-user/signal.c b/linux-user/signal.c
index c846b8c7d4..0664770c94 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1256,6 +1256,14 @@ setup_return(CPUState *env, struct target_sigaction *ka,
abi_ulong handler = ka->_sa_handler;
abi_ulong retcode;
int thumb = handler & 1;
+ uint32_t cpsr = cpsr_read(env);
+
+ cpsr &= ~CPSR_IT;
+ if (thumb) {
+ cpsr |= CPSR_T;
+ } else {
+ cpsr &= ~CPSR_T;
+ }
if (ka->sa_flags & TARGET_SA_RESTORER) {
retcode = ka->sa_restorer;
@@ -1278,13 +1286,7 @@ setup_return(CPUState *env, struct target_sigaction *ka,
env->regs[13] = frame_addr;
env->regs[14] = retcode;
env->regs[15] = handler & (thumb ? ~1 : ~3);
- env->thumb = thumb;
-
-#if 0
-#ifdef TARGET_CONFIG_CPU_32
- env->cpsr = cpsr;
-#endif
-#endif
+ cpsr_write(env, cpsr, 0xffffffff);
return 0;
}
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index f10e17ae23..499c4d7d62 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -83,7 +83,9 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
#include <linux/kd.h>
#include <linux/mtio.h>
#include <linux/fs.h>
+#if defined(CONFIG_FIEMAP)
#include <linux/fiemap.h>
+#endif
#include <linux/fb.h>
#include <linux/vt.h>
#include "linux_loop.h"
@@ -2986,6 +2988,7 @@ struct IOCTLEntry {
#define MAX_STRUCT_SIZE 4096
+#ifdef CONFIG_FIEMAP
/* So fiemap access checks don't overflow on 32 bit systems.
* This is very slightly smaller than the limit imposed by
* the underlying kernel.
@@ -3072,6 +3075,7 @@ static abi_long do_ioctl_fs_ioc_fiemap(const IOCTLEntry *ie, uint8_t *buf_temp,
}
return ret;
}
+#endif
static IOCTLEntry ioctl_entries[] = {
#define IOCTL(cmd, access, ...) \
diff --git a/make_device_config.sh b/make_device_config.sh
index 596fc5bf69..5d14885dfc 100644
--- a/make_device_config.sh
+++ b/make_device_config.sh
@@ -18,7 +18,7 @@ process_includes () {
f=$src
while [ -n "$f" ] ; do
- f=`tr -d '\r' < $f | awk '/^include / {ORS=" "; print "'$src_dir'/" $2}'`
+ f=`tr -d '\r' < $f | awk '/^include / {printf "'$src_dir'/%s", $2}'`
[ $? = 0 ] || exit 1
all_includes="$all_includes $f"
done
diff --git a/monitor.c b/monitor.c
index f2580007f2..d291158c2f 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2275,8 +2275,8 @@ static void mem_info_64(Monitor *mon, CPUState *env)
end = (l1 << 39) + (l2 << 30);
if (pdpe & PG_PRESENT_MASK) {
if (pdpe & PG_PSE_MASK) {
- prot = pde & (PG_USER_MASK | PG_RW_MASK |
- PG_PRESENT_MASK);
+ prot = pdpe & (PG_USER_MASK | PG_RW_MASK |
+ PG_PRESENT_MASK);
mem_print(mon, &start, &last_prot, end, prot);
} else {
pd_addr = pdpe & 0x3fffffffff000ULL;
diff --git a/pc-bios/keymaps/bepo b/pc-bios/keymaps/bepo
new file mode 100644
index 0000000000..d40041a4cb
--- /dev/null
+++ b/pc-bios/keymaps/bepo
@@ -0,0 +1,333 @@
+include common
+
+# Bépo : Improved ergonomic french keymap using Dvorak method.
+# Built by community on 'Dvorak Fr / Bépo' :
+# see http://www.clavier-dvorak.org/wiki/ to join and help.
+#
+# Bépo layout (1.0rc2 version) for a pc105 keyboard (french) :
+# ┌────┐
+# │ S A│ S = Shift, A = AltGr + Shift
+# │ s a│ s = normal, a = AltGr
+# └────┘
+#
+# ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┲━━━━━━━━━┓
+# │ # ¶ │ 1 „ │ 2 “ │ 3 ” │ 4 ≤ │ 5 ≥ │ 6 │ 7 ¬ │ 8 ¼ │ 9 ½ │ 0 ¾ │ ° ′ │ ` ″ ┃ ⌫ Retour┃
+# │ $ – │ " — │ « < │ » > │ ( [ │ ) ] │ @ ^ │ + ± │ - − │ / ÷ │ * × │ = ≠ │ % ‰ ┃ arrière┃
+# ┢━━━━━┷━┱───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┺━┳━━━━━━━┫
+# ┃ ┃ B ¦ │ É ˝ │ P § │ O Œ │ È ` │ ! │ V │ D Ð │ L │ J IJ │ Z Ə │ W ┃Entrée ┃
+# ┃Tab ↹ ┃ b | │ é ˊ │ p & │ o œ │ è ` │ ˆ ¡ │ v ˇ │ d ð │ l / │ j ij │ z ə │ w ̆ ┃ ⏎ ┃
+# ┣━━━━━━━┻┱────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┺┓ ┃
+# ┃ ┃ A Æ │ U Ù │ I ˙ │ E ¤ │ ; ̛ │ C ſ │ T Þ │ S ẞ │ R ™ │ N │ M º │ Ç , ┃ ┃
+# ┃Maj ⇬ ┃ a æ │ u ù │ i ̈ │ e € │ , ’ │ c © │ t þ │ s ß │ r ® │ n ˜ │ m ¯ │ ç ¸ ┃ ┃
+# ┣━━━━━━━┳┹────┬┴────┬┴────┬┴────┬┴────┬┴────┬┴────┬┴────┬┴────┬┴────┬┴────┲┷━━━━━┻━━━━━━┫
+# ┃ ┃ Ê │ À │ Y ‘ │ X ’ │ : · │ K │ ? ̉ │ Q ̣ │ G │ H ‡ │ F ª ┃ ┃
+# ┃Shift ⇧┃ ê / │ à \ │ y { │ x } │ . … │ k ~ │ ' ¿ │ q ˚ │ g µ │ h † │ f ˛ ┃Shift ⇧ ┃
+# ┣━━━━━━━╋━━━━━┷━┳━━━┷━━━┱─┴─────┴─────┴─────┴─────┴─────┴───┲━┷━━━━━╈━━━━━┻━┳━━━━━━━┳━━━┛
+# ┃ ┃ ┃ ┃ Espace inséc. Espace inséc. fin ┃ ┃ ┃ ┃
+# ┃Ctrl ┃Meta ┃Alt ┃ ␣ (Espace) _ ␣ ┃AltGr ⇮┃Menu ┃Ctrl ┃
+# ┗━━━━━━━┻━━━━━━━┻━━━━━━━┹───────────────────────────────────┺━━━━━━━┻━━━━━━━┻━━━━━━━┛
+
+
+# First row
+## keycode 41 = dollar numbersign U+2013 U+00b6
+dollar 0x29
+numbersign 0x29 shift
+U2013 0x29 altgr
+U00b6 0x29 shift altgr
+
+## keycode 2 = +quotedbl +one U+2014 U+201e
+quotedbl 0x2
+one 0x2 shift
+U2014 0x2 altgr
+U201e 0x2 shift altgr
+
+## keycode 3 = +guillemotleft +two less U+201c
+guillemotleft 0x3
+two 0x3 shift
+less 0x3 altgr
+U201c 0x3 shift altgr
+
+## keycode 4 = +guillemotright +three greater U+201d
+guillemotright 0x4
+three 0x4 shift
+greater 0x4 altgr
+U201d 0x4 shift altgr
+
+## keycode 5 = +parenleft +four bracketleft U+2264
+parenleft 0x5
+four 0x5 shift
+bracketleft 0x5 altgr
+U2264 0x5 shift altgr
+
+## keycode 6 = +parenright +five bracketright U+2265
+parenright 0x6
+five 0x6 shift
+bracketright 0x6 altgr
+U2265 0x6 shift altgr
+
+## keycode 7 = +at +six asciicircum
+at 0x7
+six 0x7 shift
+asciicircum 0x7 altgr
+
+## keycode 8 = +plus +seven U+00b1 U+00ac
+plus 0x8
+seven 0x8 shift
+U00b1 0x8 altgr
+U00ac 0x8 shift altgr
+
+## keycode 9 = +minus +eight U+2212 U+00bc
+minus 0x9
+eight 0x9 shift
+U2212 0x9 altgr
+U00bc 0x9 shift altgr
+
+## keycode 10 = +slash +nine U+00f7 U+00bd
+slash 0xa
+nine 0xa shift
+U00f7 0xa altgr
+U00bd 0xa shift altgr
+
+## keycode 11 = +asterisk +zero U+00d7 U+00be
+asterisk 0xb
+zero 0xb shift
+U00d7 0xb altgr
+U00be 0xb shift altgr
+
+## keycode 12 = equal U+00b0 U+2260 U+2032
+equal 0xc
+U00b0 0xc shift
+U2260 0xc altgr
+U2032 0xc shift altgr
+
+## keycode 13 = percent grave U+2030 U+2033
+percent 0xd
+grave 0xd shift
+U2030 0xd altgr
+U2033 0xd shift altgr
+
+
+# Second row
+
+# simplified letter definitions notation :
+## keycode 16 = b
+b 0x10 addupper
+## keycode 18 = p
+p 0x12 addupper
+## keycode 19 = o
+o 0x13 addupper
+## keycode 22 = v
+v 0x16 addupper
+## keycode 23 = d
+d 0x17 addupper
+## keycode 24 = l
+l 0x18 addupper
+## keycode 25 = j
+j 0x19 addupper
+## keycode 26 = z
+z 0x1a addupper
+## keycode 27 = w
+w 0x1b addupper
+
+# then, add specific definitions
+## AltGr keycode 16 = bar
+bar 0x10 altgr
+## Shift AltGr keycode 16 = brokenbar
+brokenbar 0x10 shift altgr
+
+## keycode 17 = +eacute +Eacute dead_acute
+eacute 0x11
+Eacute 0x11 shift
+dead_acute 0x11 altgr
+
+## AltGr keycode 18 = ampersand
+ampersand 0x12 altgr
+## Shift AltGr keycode 18 = U+00a7
+U00a7 0x12 shift altgr
+
+## AltGr keycode 19 = +U+0153
+U+0153 0x13 altgr
+## Shift AltGr keycode 19 = +U+0152
+U+0152 0x13 shift altgr
+
+## keycode 20 = +egrave +Egrave dead_grave grave # no Meta !
+egrave 0x14
+Egrave 0x14 shift
+dead_grave 0x14 altgr
+
+## keycode 21 = dead_circumflex exclam exclamdown
+dead_circumflex 0x15
+exclam 0x15 shift
+exclamdown 0x15 altgr
+
+## AltGr keycode 22 = dead_caron
+dead_caron 0x16 altgr
+
+## AltGr keycode 23 = eth
+eth 0x17 altgr
+## Shift AltGr keycode 23 = ETH
+ETH 0x17 shift altgr
+
+## AltGr keycode 25 = +U+0133
+U+0133 0x19 altgr
+## Shift AltGr keycode 25 = +U+0132
+U+0132 0x19 shift altgr
+
+## AltGr keycode 26 = +U+0259
+U+0259 0x1a altgr
+## Shift AltGr keycode 26 = +U+018f
+U+018f 0x1a shift altgr
+
+
+
+# Third row
+
+# simplified letter definitions notation :
+## keycode 30 = a
+a 0x1e addupper
+## keycode 31 = u
+u 0x1f addupper
+## keycode 32 = i
+i 0x20 addupper
+## keycode 33 = e
+e 0x21 addupper
+## keycode 35 = c
+c 0x23 addupper
+## keycode 36 = t
+t 0x24 addupper
+## keycode 37 = s
+s 0x25 addupper
+## keycode 38 = r
+r 0x26 addupper
+## keycode 39 = n
+n 0x27 addupper
+## keycode 40 = m
+m 0x28 addupper
+
+# then, add specific definitions
+## AltGr keycode 30 = +ae
+ae 0x1e altgr
+## Shift AltGr keycode 30 = +AE
+AE 0x1e shift altgr
+
+## AltGr keycode 31 = +ugrave
+ugrave 0x1f altgr
+## Shift AltGr keycode 31 = +Ugrave
+Ugrave 0x1f shift altgr
+
+## AltGr keycode 32 = dead_diaeresis
+dead_diaeresis 0x20 altgr
+
+
+## AltGr keycode 33 = U+20ac
+U20ac 0x21 altgr
+
+## keycode 34 = comma semicolon U+2019 +U+031b
+comma 0x22
+semicolon 0x22 shift
+U2019 0x22 altgr
+U+031b 0x22 shift altgr
+
+## AltGr keycode 35 = copyright
+copyright 0x23 altgr
+## Shift AltGr keycode 35 = U+017f
+U017f 0x23 shift altgr
+
+## AltGr keycode 36 = +thorn
+thorn 0x24 altgr
+## Shift AltGr keycode 36 = +THORN
+THORN 0x24 shift altgr
+
+## AltGr keycode 37 = +ssharp
+ssharp 0x25 altgr
+## Shift AltGr keycode 37 = U+1e9e
+U1e9e 0x25 shift altgr
+
+## AltGr keycode 38 = registered
+registered 0x26 altgr
+## Shift AltGr keycode 38 = U+2122
+U2122 0x26 shift altgr
+
+## AltGr keycode 39 = dead_tilde
+dead_tilde 0x27 altgr
+
+## Shift AltGr keycode 40 = masculine
+masculine 0x28 shift altgr
+
+## keycode 43 = +ccedilla +Ccedilla dead_cedilla
+ccedilla 0x2b
+Ccedilla 0x2b shift
+dead_cedilla 0x2b altgr
+
+
+# Fourth row
+
+# simplified letter definitions notation :
+## keycode 45 = y
+y 0x2d addupper
+## keycode 46 = x
+x 0x2e addupper
+## keycode 48 = k
+k 0x30 addupper
+## keycode 50 = q
+q 0x32 addupper
+## keycode 51 = g
+g 0x33 addupper
+## keycode 52 = h
+h 0x34 addupper
+## keycode 53 = f
+f 0x35 addupper
+
+# then, add specific definitions
+## keycode 86 = +ecircumflex +Ecircumflex slash slash
+ecircumflex 0x56
+Ecircumflex 0x56 shift
+
+## keycode 44 = +agrave +Agrave backslash
+agrave 0x2c
+Agrave 0x2c shift
+backslash 0x2c altgr
+
+## AltGr keycode 45 = braceleft
+braceleft 0x2d altgr
+## Shift AltGr keycode 45 = U+2018
+U2018 0x2d shift altgr
+
+## AltGr keycode 46 = braceright
+braceright 0x2e altgr
+
+## keycode 47 = period colon U+2026 periodcentered
+period 0x2f
+colon 0x2f shift
+U2026 0x2f altgr
+periodcentered 0x2f shift altgr
+
+## AltGr keycode 48 = asciitilde
+asciitilde 0x30 altgr
+## Shift AltGr keycode 48 = U+2328
+U2328 0x30 shift altgr
+
+## keycode 49 = apostrophe question questiondown +U+0309
+apostrophe 0x31
+question 0x31 shift
+questiondown 0x31 altgr
+U+0309 0x31 shift altgr
+
+## AltGr keycode 51 = mu
+mu 0x33 altgr
+
+## AltGr keycode 52 = U+2020
+U2020 0x34 altgr
+## Shift AltGr keycode 52 = U+2021
+U2021 0x34 shift altgr
+
+## Shift AltGr keycode 53 = ordfeminine
+ordfeminine 0x35 shift altgr
+
+
+
+## keycode 57 = space nobreakspace underscore U+202f
+space 0x39
+nobreakspace 0x39 shift
+underscore 0x39 altgr
+U202f 0x39 shift altgr
diff --git a/qemu-io.c b/qemu-io.c
index 65dee13731..5b24c5eec2 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -1131,8 +1131,10 @@ aio_read_f(int argc, char **argv)
case 'P':
ctx->Pflag = 1;
ctx->pattern = parse_pattern(optarg);
- if (ctx->pattern < 0)
+ if (ctx->pattern < 0) {
+ free(ctx);
return 0;
+ }
break;
case 'q':
ctx->qflag = 1;
diff --git a/rules.mak b/rules.mak
index 6dac7773d5..738eec3282 100644
--- a/rules.mak
+++ b/rules.mak
@@ -15,13 +15,13 @@ MAKEFLAGS += -rR
QEMU_DGFLAGS += -MMD -MP -MT $@ -MF $(*D)/$(*F).d
%.o: %.c
- $(call quiet-command,$(CC) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," CC $(TARGET_DIR)$@")
+ $(call quiet-command,$(CC) $(QEMU_CFLAGS) $(QEMU_INCLUDES) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," CC $(TARGET_DIR)$@")
%.o: %.S
- $(call quiet-command,$(CC) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," AS $(TARGET_DIR)$@")
+ $(call quiet-command,$(CC) $(QEMU_CFLAGS) $(QEMU_INCLUDES) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," AS $(TARGET_DIR)$@")
%.o: %.m
- $(call quiet-command,$(CC) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," OBJC $(TARGET_DIR)$@")
+ $(call quiet-command,$(CC) $(QEMU_CFLAGS) $(QEMU_INCLUDES) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," OBJC $(TARGET_DIR)$@")
LINK = $(call quiet-command,$(CC) $(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $(1) $(LIBS)," LINK $(TARGET_DIR)$@")
diff --git a/slirp/tftp.c b/slirp/tftp.c
index 55e4692acc..1821648251 100644
--- a/slirp/tftp.c
+++ b/slirp/tftp.c
@@ -311,7 +311,7 @@ static void tftp_handle_rrq(Slirp *slirp, struct tftp_t *tp, int pktlen)
return;
}
- if (memcmp(&tp->x.tp_buf[k], "octet\0", 6) != 0) {
+ if (strcasecmp((const char *)&tp->x.tp_buf[k], "octet") != 0) {
tftp_send_error(spt, 4, "Unsupported transfer mode", tp);
return;
}
@@ -351,7 +351,7 @@ static void tftp_handle_rrq(Slirp *slirp, struct tftp_t *tp, int pktlen)
value = (const char *)&tp->x.tp_buf[k];
k += strlen(value) + 1;
- if (strcmp(key, "tsize") == 0) {
+ if (strcasecmp(key, "tsize") == 0) {
int tsize = atoi(value);
struct stat stat_p;
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 340933ef50..5bcd53ac73 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -173,7 +173,20 @@ typedef struct CPUARMState {
/* scratch space when Tn are not sufficient. */
uint32_t scratch[8];
+ /* fp_status is the "normal" fp status. standard_fp_status retains
+ * values corresponding to the ARM "Standard FPSCR Value", ie
+ * default-NaN, flush-to-zero, round-to-nearest and is used by
+ * any operations (generally Neon) which the architecture defines
+ * as controlled by the standard FPSCR value rather than the FPSCR.
+ *
+ * To avoid having to transfer exception bits around, we simply
+ * say that the FPSCR cumulative exception flags are the logical
+ * OR of the flags in the two fp statuses. This relies on the
+ * only thing which needs to read the exception flags being
+ * an explicit FPSCR read.
+ */
float_status fp_status;
+ float_status standard_fp_status;
} vfp;
uint32_t exclusive_addr;
uint32_t exclusive_val;
@@ -440,17 +453,56 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
#include "cpu-all.h"
+/* Bit usage in the TB flags field: */
+#define ARM_TBFLAG_THUMB_SHIFT 0
+#define ARM_TBFLAG_THUMB_MASK (1 << ARM_TBFLAG_THUMB_SHIFT)
+#define ARM_TBFLAG_VECLEN_SHIFT 1
+#define ARM_TBFLAG_VECLEN_MASK (0x7 << ARM_TBFLAG_VECLEN_SHIFT)
+#define ARM_TBFLAG_VECSTRIDE_SHIFT 4
+#define ARM_TBFLAG_VECSTRIDE_MASK (0x3 << ARM_TBFLAG_VECSTRIDE_SHIFT)
+#define ARM_TBFLAG_PRIV_SHIFT 6
+#define ARM_TBFLAG_PRIV_MASK (1 << ARM_TBFLAG_PRIV_SHIFT)
+#define ARM_TBFLAG_VFPEN_SHIFT 7
+#define ARM_TBFLAG_VFPEN_MASK (1 << ARM_TBFLAG_VFPEN_SHIFT)
+#define ARM_TBFLAG_CONDEXEC_SHIFT 8
+#define ARM_TBFLAG_CONDEXEC_MASK (0xff << ARM_TBFLAG_CONDEXEC_SHIFT)
+/* Bits 31..16 are currently unused. */
+
+/* some convenience accessor macros */
+#define ARM_TBFLAG_THUMB(F) \
+ (((F) & ARM_TBFLAG_THUMB_MASK) >> ARM_TBFLAG_THUMB_SHIFT)
+#define ARM_TBFLAG_VECLEN(F) \
+ (((F) & ARM_TBFLAG_VECLEN_MASK) >> ARM_TBFLAG_VECLEN_SHIFT)
+#define ARM_TBFLAG_VECSTRIDE(F) \
+ (((F) & ARM_TBFLAG_VECSTRIDE_MASK) >> ARM_TBFLAG_VECSTRIDE_SHIFT)
+#define ARM_TBFLAG_PRIV(F) \
+ (((F) & ARM_TBFLAG_PRIV_MASK) >> ARM_TBFLAG_PRIV_SHIFT)
+#define ARM_TBFLAG_VFPEN(F) \
+ (((F) & ARM_TBFLAG_VFPEN_MASK) >> ARM_TBFLAG_VFPEN_SHIFT)
+#define ARM_TBFLAG_CONDEXEC(F) \
+ (((F) & ARM_TBFLAG_CONDEXEC_MASK) >> ARM_TBFLAG_CONDEXEC_SHIFT)
+
static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
target_ulong *cs_base, int *flags)
{
+ int privmode;
*pc = env->regs[15];
*cs_base = 0;
- *flags = env->thumb | (env->vfp.vec_len << 1)
- | (env->vfp.vec_stride << 4) | (env->condexec_bits << 8);
- if ((env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR)
- *flags |= (1 << 6);
- if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30))
- *flags |= (1 << 7);
+ *flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
+ | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT)
+ | (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT)
+ | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT);
+ if (arm_feature(env, ARM_FEATURE_M)) {
+ privmode = !((env->v7m.exception == 0) && (env->v7m.control & 1));
+ } else {
+ privmode = (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR;
+ }
+ if (privmode) {
+ *flags |= ARM_TBFLAG_PRIV_MASK;
+ }
+ if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) {
+ *flags |= ARM_TBFLAG_VFPEN_MASK;
+ }
}
#endif
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 705b99f9cb..b562767279 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -237,6 +237,9 @@ void cpu_reset(CPUARMState *env)
env->vfp.xregs[ARM_VFP_FPEXC] = 0;
env->cp15.c2_base_mask = 0xffffc000u;
#endif
+ set_flush_to_zero(1, &env->vfp.standard_fp_status);
+ set_flush_inputs_to_zero(1, &env->vfp.standard_fp_status);
+ set_default_nan_mode(1, &env->vfp.standard_fp_status);
tlb_flush(env, 1);
}
@@ -1846,12 +1849,20 @@ bad_reg:
void HELPER(set_r13_banked)(CPUState *env, uint32_t mode, uint32_t val)
{
- env->banked_r13[bank_number(mode)] = val;
+ if ((env->uncached_cpsr & CPSR_M) == mode) {
+ env->regs[13] = val;
+ } else {
+ env->banked_r13[bank_number(mode)] = val;
+ }
}
uint32_t HELPER(get_r13_banked)(CPUState *env, uint32_t mode)
{
- return env->banked_r13[bank_number(mode)];
+ if ((env->uncached_cpsr & CPSR_M) == mode) {
+ return env->regs[13];
+ } else {
+ return env->banked_r13[bank_number(mode)];
+ }
}
uint32_t HELPER(v7m_mrs)(CPUState *env, uint32_t reg)
@@ -2256,6 +2267,7 @@ uint32_t HELPER(vfp_get_fpscr)(CPUState *env)
| (env->vfp.vec_len << 16)
| (env->vfp.vec_stride << 20);
i = get_float_exception_flags(&env->vfp.fp_status);
+ i |= get_float_exception_flags(&env->vfp.standard_fp_status);
fpscr |= vfp_exceptbits_from_host(i);
return fpscr;
}
@@ -2323,6 +2335,7 @@ void HELPER(vfp_set_fpscr)(CPUState *env, uint32_t val)
i = vfp_exceptbits_to_host(val);
set_float_exception_flags(i, &env->vfp.fp_status);
+ set_float_exception_flags(0, &env->vfp.standard_fp_status);
}
void vfp_set_fpscr(CPUState *env, uint32_t val)
@@ -2611,9 +2624,17 @@ float32 HELPER(recps_f32)(float32 a, float32 b, CPUState *env)
float32 HELPER(rsqrts_f32)(float32 a, float32 b, CPUState *env)
{
- float_status *s = &env->vfp.fp_status;
+ float_status *s = &env->vfp.standard_fp_status;
+ float32 two = int32_to_float32(2, s);
float32 three = int32_to_float32(3, s);
- return float32_sub(three, float32_mul(a, b, s), s);
+ float32 product;
+ if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
+ (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) {
+ product = float32_zero;
+ } else {
+ product = float32_mul(a, b, s);
+ }
+ return float32_div(float32_sub(three, product, s), two, s);
}
/* NEON helpers. */
diff --git a/target-arm/helpers.h b/target-arm/helpers.h
index 0d1bc47d00..b88ebaecc6 100644
--- a/target-arm/helpers.h
+++ b/target-arm/helpers.h
@@ -249,6 +249,10 @@ DEF_HELPER_3(neon_qshl_u32, i32, env, i32, i32)
DEF_HELPER_3(neon_qshl_s32, i32, env, i32, i32)
DEF_HELPER_3(neon_qshl_u64, i64, env, i64, i64)
DEF_HELPER_3(neon_qshl_s64, i64, env, i64, i64)
+DEF_HELPER_3(neon_qshlu_s8, i32, env, i32, i32);
+DEF_HELPER_3(neon_qshlu_s16, i32, env, i32, i32);
+DEF_HELPER_3(neon_qshlu_s32, i32, env, i32, i32);
+DEF_HELPER_3(neon_qshlu_s64, i64, env, i64, i64);
DEF_HELPER_3(neon_qrshl_u8, i32, env, i32, i32)
DEF_HELPER_3(neon_qrshl_s8, i32, env, i32, i32)
DEF_HELPER_3(neon_qrshl_u16, i32, env, i32, i32)
diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index dae063ea1a..20f3c162cd 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -632,6 +632,53 @@ uint64_t HELPER(neon_qshl_s64)(CPUState *env, uint64_t valop, uint64_t shiftop)
return val;
}
+#define NEON_FN(dest, src1, src2) do { \
+ if (src1 & (1 << (sizeof(src1) * 8 - 1))) { \
+ SET_QC(); \
+ dest = 0; \
+ } else { \
+ int8_t tmp; \
+ tmp = (int8_t)src2; \
+ if (tmp >= (ssize_t)sizeof(src1) * 8) { \
+ if (src1) { \
+ SET_QC(); \
+ dest = ~0; \
+ } else { \
+ dest = 0; \
+ } \
+ } else if (tmp <= -(ssize_t)sizeof(src1) * 8) { \
+ dest = 0; \
+ } else if (tmp < 0) { \
+ dest = src1 >> -tmp; \
+ } else { \
+ dest = src1 << tmp; \
+ if ((dest >> tmp) != src1) { \
+ SET_QC(); \
+ dest = ~0; \
+ } \
+ } \
+ }} while (0)
+NEON_VOP_ENV(qshlu_s8, neon_u8, 4)
+NEON_VOP_ENV(qshlu_s16, neon_u16, 2)
+#undef NEON_FN
+
+uint32_t HELPER(neon_qshlu_s32)(CPUState *env, uint32_t valop, uint32_t shiftop)
+{
+ if ((int32_t)valop < 0) {
+ SET_QC();
+ return 0;
+ }
+ return helper_neon_qshl_u32(env, valop, shiftop);
+}
+
+uint64_t HELPER(neon_qshlu_s64)(CPUState *env, uint64_t valop, uint64_t shiftop)
+{
+ if ((int64_t)valop < 0) {
+ SET_QC();
+ return 0;
+ }
+ return helper_neon_qshl_u64(env, valop, shiftop);
+}
/* FIXME: This is wrong. */
#define NEON_FN(dest, src1, src2) do { \
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 2ce82f3bbb..c60cd18e1e 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -59,8 +59,13 @@ typedef struct DisasContext {
#if !defined(CONFIG_USER_ONLY)
int user;
#endif
+ int vfp_enabled;
+ int vec_len;
+ int vec_stride;
} DisasContext;
+static uint32_t gen_opc_condexec_bits[OPC_BUF_SIZE];
+
#if defined(CONFIG_USER_ONLY)
#define IS_USER(s) 1
#else
@@ -2603,12 +2608,6 @@ static void gen_vfp_msr(TCGv tmp)
dead_tmp(tmp);
}
-static inline int
-vfp_enabled(CPUState * env)
-{
- return ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) != 0);
-}
-
static void gen_neon_dup_u8(TCGv var, int shift)
{
TCGv tmp = new_tmp();
@@ -2653,7 +2652,7 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
if (!arm_feature(env, ARM_FEATURE_VFP))
return 1;
- if (!vfp_enabled(env)) {
+ if (!s->vfp_enabled) {
/* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
if ((insn & 0x0fe00fff) != 0x0ee00a10)
return 1;
@@ -2900,7 +2899,7 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
rm = VFP_SREG_M(insn);
}
- veclen = env->vfp.vec_len;
+ veclen = s->vec_len;
if (op == 15 && rn > 3)
veclen = 0;
@@ -2921,9 +2920,9 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
veclen = 0;
} else {
if (dp)
- delta_d = (env->vfp.vec_stride >> 1) + 1;
+ delta_d = (s->vec_stride >> 1) + 1;
else
- delta_d = env->vfp.vec_stride + 1;
+ delta_d = s->vec_stride + 1;
if ((rm & bank_mask) == 0) {
/* mixed scalar/vector */
@@ -3488,6 +3487,14 @@ gen_set_condexec (DisasContext *s)
}
}
+static void gen_exception_insn(DisasContext *s, int offset, int excp)
+{
+ gen_set_condexec(s);
+ gen_set_pc_im(s->pc - offset);
+ gen_exception(excp);
+ s->is_jmp = DISAS_JUMP;
+}
+
static void gen_nop_hint(DisasContext *s, int val)
{
switch (val) {
@@ -3804,7 +3811,7 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
TCGv tmp2;
TCGv_i64 tmp64;
- if (!vfp_enabled(env))
+ if (!s->vfp_enabled)
return 1;
VFP_DREG_D(rd, insn);
rn = (insn >> 16) & 0xf;
@@ -4199,7 +4206,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
TCGv tmp, tmp2, tmp3, tmp4, tmp5;
TCGv_i64 tmp64;
- if (!vfp_enabled(env))
+ if (!s->vfp_enabled)
return 1;
q = (insn & (1 << 6)) != 0;
u = (insn >> 24) & 1;
@@ -4652,14 +4659,22 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
case 5: /* VSHL, VSLI */
gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
break;
- case 6: /* VQSHL */
- if (u)
- gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
- else
- gen_helper_neon_qshl_s64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
+ case 6: /* VQSHLU */
+ if (u) {
+ gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
+ cpu_V0, cpu_V1);
+ } else {
+ return 1;
+ }
break;
- case 7: /* VQSHLU */
- gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
+ case 7: /* VQSHL */
+ if (u) {
+ gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
+ cpu_V0, cpu_V1);
+ } else {
+ gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
+ cpu_V0, cpu_V1);
+ }
break;
}
if (op == 1 || op == 3) {
@@ -4698,17 +4713,30 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
default: return 1;
}
break;
- case 6: /* VQSHL */
- GEN_NEON_INTEGER_OP_ENV(qshl);
- break;
- case 7: /* VQSHLU */
+ case 6: /* VQSHLU */
+ if (!u) {
+ return 1;
+ }
switch (size) {
- case 0: gen_helper_neon_qshl_u8(tmp, cpu_env, tmp, tmp2); break;
- case 1: gen_helper_neon_qshl_u16(tmp, cpu_env, tmp, tmp2); break;
- case 2: gen_helper_neon_qshl_u32(tmp, cpu_env, tmp, tmp2); break;
- default: return 1;
+ case 0:
+ gen_helper_neon_qshlu_s8(tmp, cpu_env,
+ tmp, tmp2);
+ break;
+ case 1:
+ gen_helper_neon_qshlu_s16(tmp, cpu_env,
+ tmp, tmp2);
+ break;
+ case 2:
+ gen_helper_neon_qshlu_s32(tmp, cpu_env,
+ tmp, tmp2);
+ break;
+ default:
+ return 1;
}
break;
+ case 7: /* VQSHL */
+ GEN_NEON_INTEGER_OP_ENV(qshl);
+ break;
}
dead_tmp(tmp2);
@@ -5958,10 +5986,7 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
tcg_gen_mov_i32(cpu_exclusive_test, addr);
tcg_gen_movi_i32(cpu_exclusive_info,
size | (rd << 4) | (rt << 8) | (rt2 << 12));
- gen_set_condexec(s);
- gen_set_pc_im(s->pc - 4);
- gen_exception(EXCP_STREX);
- s->is_jmp = DISAS_JUMP;
+ gen_exception_insn(s, 4, EXCP_STREX);
}
#else
static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
@@ -6101,14 +6126,10 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
goto illegal_op;
ARCH(6);
op1 = (insn & 0x1f);
- if (op1 == (env->uncached_cpsr & CPSR_M)) {
- addr = load_reg(s, 13);
- } else {
- addr = new_tmp();
- tmp = tcg_const_i32(op1);
- gen_helper_get_r13_banked(addr, cpu_env, tmp);
- tcg_temp_free_i32(tmp);
- }
+ addr = new_tmp();
+ tmp = tcg_const_i32(op1);
+ gen_helper_get_r13_banked(addr, cpu_env, tmp);
+ tcg_temp_free_i32(tmp);
i = (insn >> 23) & 3;
switch (i) {
case 0: offset = -4; break; /* DA */
@@ -6135,14 +6156,10 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
}
if (offset)
tcg_gen_addi_i32(addr, addr, offset);
- if (op1 == (env->uncached_cpsr & CPSR_M)) {
- store_reg(s, 13, addr);
- } else {
- tmp = tcg_const_i32(op1);
- gen_helper_set_r13_banked(cpu_env, tmp, addr);
- tcg_temp_free_i32(tmp);
- dead_tmp(addr);
- }
+ tmp = tcg_const_i32(op1);
+ gen_helper_set_r13_banked(cpu_env, tmp, addr);
+ tcg_temp_free_i32(tmp);
+ dead_tmp(addr);
} else {
dead_tmp(addr);
}
@@ -6366,10 +6383,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
goto illegal_op;
}
/* bkpt */
- gen_set_condexec(s);
- gen_set_pc_im(s->pc - 4);
- gen_exception(EXCP_BKPT);
- s->is_jmp = DISAS_JUMP;
+ gen_exception_insn(s, 4, EXCP_BKPT);
break;
case 0x8: /* signed multiply */
case 0xa:
@@ -7268,10 +7282,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
break;
default:
illegal_op:
- gen_set_condexec(s);
- gen_set_pc_im(s->pc - 4);
- gen_exception(EXCP_UDEF);
- s->is_jmp = DISAS_JUMP;
+ gen_exception_insn(s, 4, EXCP_UDEF);
break;
}
}
@@ -7554,14 +7565,10 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
} else {
/* srs */
op = (insn & 0x1f);
- if (op == (env->uncached_cpsr & CPSR_M)) {
- addr = load_reg(s, 13);
- } else {
- addr = new_tmp();
- tmp = tcg_const_i32(op);
- gen_helper_get_r13_banked(addr, cpu_env, tmp);
- tcg_temp_free_i32(tmp);
- }
+ addr = new_tmp();
+ tmp = tcg_const_i32(op);
+ gen_helper_get_r13_banked(addr, cpu_env, tmp);
+ tcg_temp_free_i32(tmp);
if ((insn & (1 << 24)) == 0) {
tcg_gen_addi_i32(addr, addr, -8);
}
@@ -7577,13 +7584,9 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
} else {
tcg_gen_addi_i32(addr, addr, 4);
}
- if (op == (env->uncached_cpsr & CPSR_M)) {
- store_reg(s, 13, addr);
- } else {
- tmp = tcg_const_i32(op);
- gen_helper_set_r13_banked(cpu_env, tmp, addr);
- tcg_temp_free_i32(tmp);
- }
+ tmp = tcg_const_i32(op);
+ gen_helper_set_r13_banked(cpu_env, tmp, addr);
+ tcg_temp_free_i32(tmp);
} else {
dead_tmp(addr);
}
@@ -8925,10 +8928,7 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
break;
case 0xe: /* bkpt */
- gen_set_condexec(s);
- gen_set_pc_im(s->pc - 2);
- gen_exception(EXCP_BKPT);
- s->is_jmp = DISAS_JUMP;
+ gen_exception_insn(s, 2, EXCP_BKPT);
break;
case 0xa: /* rev */
@@ -9014,7 +9014,6 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
if (cond == 0xf) {
/* swi */
- gen_set_condexec(s);
gen_set_pc_im(s->pc);
s->is_jmp = DISAS_SWI;
break;
@@ -9051,17 +9050,11 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
}
return;
undef32:
- gen_set_condexec(s);
- gen_set_pc_im(s->pc - 4);
- gen_exception(EXCP_UDEF);
- s->is_jmp = DISAS_JUMP;
+ gen_exception_insn(s, 4, EXCP_UDEF);
return;
illegal_op:
undef:
- gen_set_condexec(s);
- gen_set_pc_im(s->pc - 2);
- gen_exception(EXCP_UDEF);
- s->is_jmp = DISAS_JUMP;
+ gen_exception_insn(s, 2, EXCP_UDEF);
}
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
@@ -9093,16 +9086,15 @@ static inline void gen_intermediate_code_internal(CPUState *env,
dc->pc = pc_start;
dc->singlestep_enabled = env->singlestep_enabled;
dc->condjmp = 0;
- dc->thumb = env->thumb;
- dc->condexec_mask = (env->condexec_bits & 0xf) << 1;
- dc->condexec_cond = env->condexec_bits >> 4;
+ dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
+ dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
+ dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
#if !defined(CONFIG_USER_ONLY)
- if (IS_M(env)) {
- dc->user = ((env->v7m.exception == 0) && (env->v7m.control & 1));
- } else {
- dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR;
- }
+ dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0);
#endif
+ dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
+ dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
+ dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
cpu_F0s = tcg_temp_new_i32();
cpu_F1s = tcg_temp_new_i32();
cpu_F0d = tcg_temp_new_i64();
@@ -9119,9 +9111,41 @@ static inline void gen_intermediate_code_internal(CPUState *env,
max_insns = CF_COUNT_MASK;
gen_icount_start();
+
+ /* A note on handling of the condexec (IT) bits:
+ *
+ * We want to avoid the overhead of having to write the updated condexec
+ * bits back to the CPUState for every instruction in an IT block. So:
+ * (1) if the condexec bits are not already zero then we write
+ * zero back into the CPUState now. This avoids complications trying
+ * to do it at the end of the block. (For example if we don't do this
+ * it's hard to identify whether we can safely skip writing condexec
+ * at the end of the TB, which we definitely want to do for the case
+ * where a TB doesn't do anything with the IT state at all.)
+ * (2) if we are going to leave the TB then we call gen_set_condexec()
+ * which will write the correct value into CPUState if zero is wrong.
+ * This is done both for leaving the TB at the end, and for leaving
+ * it because of an exception we know will happen, which is done in
+ * gen_exception_insn(). The latter is necessary because we need to
+ * leave the TB with the PC/IT state just prior to execution of the
+ * instruction which caused the exception.
+ * (3) if we leave the TB unexpectedly (eg a data abort on a load)
+ * then the CPUState will be wrong and we need to reset it.
+ * This is handled in the same way as restoration of the
+ * PC in these situations: we will be called again with search_pc=1
+ * and generate a mapping of the condexec bits for each PC in
+ * gen_opc_condexec_bits[]. gen_pc_load[] then uses this to restore
+ * the condexec bits.
+ *
+ * Note that there are no instructions which can read the condexec
+ * bits, and none which can write non-static values to them, so
+ * we don't need to care about whether CPUState is correct in the
+ * middle of a TB.
+ */
+
/* Reset the conditional execution bits immediately. This avoids
complications trying to do it at the end of the block. */
- if (env->condexec_bits)
+ if (dc->condexec_mask || dc->condexec_cond)
{
TCGv tmp = new_tmp();
tcg_gen_movi_i32(tmp, 0);
@@ -9150,10 +9174,7 @@ static inline void gen_intermediate_code_internal(CPUState *env,
if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
if (bp->pc == dc->pc) {
- gen_set_condexec(dc);
- gen_set_pc_im(dc->pc);
- gen_exception(EXCP_DEBUG);
- dc->is_jmp = DISAS_JUMP;
+ gen_exception_insn(dc, 0, EXCP_DEBUG);
/* Advance PC so that clearing the breakpoint will
invalidate this TB. */
dc->pc += 2;
@@ -9170,6 +9191,7 @@ static inline void gen_intermediate_code_internal(CPUState *env,
gen_opc_instr_start[lj++] = 0;
}
gen_opc_pc[lj] = dc->pc;
+ gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1);
gen_opc_instr_start[lj] = 1;
gen_opc_icount[lj] = num_insns;
}
@@ -9177,7 +9199,11 @@ static inline void gen_intermediate_code_internal(CPUState *env,
if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
gen_io_start();
- if (env->thumb) {
+ if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
+ tcg_gen_debug_insn_start(dc->pc);
+ }
+
+ if (dc->thumb) {
disas_thumb_insn(env, dc);
if (dc->condexec_mask) {
dc->condexec_cond = (dc->condexec_cond & 0xe)
@@ -9291,7 +9317,7 @@ done_generating:
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
qemu_log("----------------\n");
qemu_log("IN: %s\n", lookup_symbol(pc_start));
- log_target_disas(pc_start, dc->pc - pc_start, env->thumb);
+ log_target_disas(pc_start, dc->pc - pc_start, dc->thumb);
qemu_log("\n");
}
#endif
@@ -9377,4 +9403,5 @@ void gen_pc_load(CPUState *env, TranslationBlock *tb,
unsigned long searched_pc, int pc_pos, void *puc)
{
env->regs[15] = gen_opc_pc[pc_pos];
+ env->condexec_bits = gen_opc_condexec_bits[pc_pos];
}
diff --git a/target-cris/translate.c b/target-cris/translate.c
index e09aaa9e9d..f4cc1252a5 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -1129,6 +1129,9 @@ static void cris_store_direct_jmp(DisasContext *dc)
{
/* Store the direct jmp state into the cpu-state. */
if (dc->jmp == JMP_DIRECT || dc->jmp == JMP_DIRECT_CC) {
+ if (dc->jmp == JMP_DIRECT) {
+ tcg_gen_movi_tl(env_btaken, 1);
+ }
tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
dc->jmp = JMP_INDIRECT;
}
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 7b6e3c2eae..c00845038a 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -274,28 +274,16 @@ static inline void gen_op_andl_A0_ffff(void)
static inline void gen_op_mov_reg_v(int ot, int reg, TCGv t0)
{
- TCGv tmp;
-
switch(ot) {
case OT_BYTE:
- tmp = tcg_temp_new();
- tcg_gen_ext8u_tl(tmp, t0);
if (reg < 4 X86_64_DEF( || reg >= 8 || x86_64_hregs)) {
- tcg_gen_andi_tl(cpu_regs[reg], cpu_regs[reg], ~0xff);
- tcg_gen_or_tl(cpu_regs[reg], cpu_regs[reg], tmp);
+ tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 8);
} else {
- tcg_gen_shli_tl(tmp, tmp, 8);
- tcg_gen_andi_tl(cpu_regs[reg - 4], cpu_regs[reg - 4], ~0xff00);
- tcg_gen_or_tl(cpu_regs[reg - 4], cpu_regs[reg - 4], tmp);
+ tcg_gen_deposit_tl(cpu_regs[reg - 4], cpu_regs[reg - 4], t0, 8, 8);
}
- tcg_temp_free(tmp);
break;
case OT_WORD:
- tmp = tcg_temp_new();
- tcg_gen_ext16u_tl(tmp, t0);
- tcg_gen_andi_tl(cpu_regs[reg], cpu_regs[reg], ~0xffff);
- tcg_gen_or_tl(cpu_regs[reg], cpu_regs[reg], tmp);
- tcg_temp_free(tmp);
+ tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 16);
break;
default: /* XXX this shouldn't be reached; abort? */
case OT_LONG:
@@ -323,15 +311,9 @@ static inline void gen_op_mov_reg_T1(int ot, int reg)
static inline void gen_op_mov_reg_A0(int size, int reg)
{
- TCGv tmp;
-
switch(size) {
case 0:
- tmp = tcg_temp_new();
- tcg_gen_ext16u_tl(tmp, cpu_A0);
- tcg_gen_andi_tl(cpu_regs[reg], cpu_regs[reg], ~0xffff);
- tcg_gen_or_tl(cpu_regs[reg], cpu_regs[reg], tmp);
- tcg_temp_free(tmp);
+ tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], cpu_A0, 0, 16);
break;
default: /* XXX this shouldn't be reached; abort? */
case 1:
@@ -415,9 +397,7 @@ static inline void gen_op_add_reg_im(int size, int reg, int32_t val)
switch(size) {
case 0:
tcg_gen_addi_tl(cpu_tmp0, cpu_regs[reg], val);
- tcg_gen_ext16u_tl(cpu_tmp0, cpu_tmp0);
- tcg_gen_andi_tl(cpu_regs[reg], cpu_regs[reg], ~0xffff);
- tcg_gen_or_tl(cpu_regs[reg], cpu_regs[reg], cpu_tmp0);
+ tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], cpu_tmp0, 0, 16);
break;
case 1:
tcg_gen_addi_tl(cpu_tmp0, cpu_regs[reg], val);
@@ -439,9 +419,7 @@ static inline void gen_op_add_reg_T0(int size, int reg)
switch(size) {
case 0:
tcg_gen_add_tl(cpu_tmp0, cpu_regs[reg], cpu_T[0]);
- tcg_gen_ext16u_tl(cpu_tmp0, cpu_tmp0);
- tcg_gen_andi_tl(cpu_regs[reg], cpu_regs[reg], ~0xffff);
- tcg_gen_or_tl(cpu_regs[reg], cpu_regs[reg], cpu_tmp0);
+ tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], cpu_tmp0, 0, 16);
break;
case 1:
tcg_gen_add_tl(cpu_tmp0, cpu_regs[reg], cpu_T[0]);
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index c018c99826..4b6ae068ce 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -78,9 +78,10 @@ typedef struct DisasContext {
unsigned int clear_imm;
int is_jmp;
-#define JMP_NOJMP 0
-#define JMP_DIRECT 1
-#define JMP_INDIRECT 2
+#define JMP_NOJMP 0
+#define JMP_DIRECT 1
+#define JMP_DIRECT_CC 2
+#define JMP_INDIRECT 3
unsigned int jmp;
uint32_t jmp_pc;
@@ -751,7 +752,10 @@ static void dec_bit(DisasContext *dc)
static inline void sync_jmpstate(DisasContext *dc)
{
- if (dc->jmp == JMP_DIRECT) {
+ if (dc->jmp == JMP_DIRECT || dc->jmp == JMP_DIRECT_CC) {
+ if (dc->jmp == JMP_DIRECT) {
+ tcg_gen_movi_tl(env_btaken, 1);
+ }
dc->jmp = JMP_INDIRECT;
tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
}
@@ -784,7 +788,7 @@ static inline TCGv *compute_ldst_addr(DisasContext *dc, TCGv *t)
{
unsigned int extimm = dc->tb_flags & IMM_FLAG;
- /* Treat the fast cases first. */
+ /* Treat the common cases first. */
if (!dc->type_b) {
/* If any of the regs is r0, return a ptr to the other. */
if (dc->ra == 0) {
@@ -813,12 +817,35 @@ static inline TCGv *compute_ldst_addr(DisasContext *dc, TCGv *t)
return t;
}
+static inline void dec_byteswap(DisasContext *dc, TCGv dst, TCGv src, int size)
+{
+ if (size == 4) {
+ tcg_gen_bswap32_tl(dst, src);
+ } else if (size == 2) {
+ TCGv t = tcg_temp_new();
+
+ /* bswap16 assumes the high bits are zero. */
+ tcg_gen_andi_tl(t, src, 0xffff);
+ tcg_gen_bswap16_tl(dst, t);
+ tcg_temp_free(t);
+ } else {
+ /* Ignore.
+ cpu_abort(dc->env, "Invalid ldst byteswap size %d\n", size);
+ */
+ }
+}
+
static void dec_load(DisasContext *dc)
{
TCGv t, *addr;
- unsigned int size;
+ unsigned int size, rev = 0;
size = 1 << (dc->opcode & 3);
+
+ if (!dc->type_b) {
+ rev = (dc->ir >> 9) & 1;
+ }
+
if (size > 4 && (dc->tb_flags & MSR_EE_FLAG)
&& (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) {
tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
@@ -826,10 +853,63 @@ static void dec_load(DisasContext *dc)
return;
}
- LOG_DIS("l %x %d\n", dc->opcode, size);
+ LOG_DIS("l%d%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "");
+
t_sync_flags(dc);
addr = compute_ldst_addr(dc, &t);
+ /*
+ * When doing reverse accesses we need to do two things.
+ *
+ * 1. Reverse the address wrt endianess.
+ * 2. Byteswap the data lanes on the way back into the CPU core.
+ */
+ if (rev && size != 4) {
+ /* Endian reverse the address. t is addr. */
+ switch (size) {
+ case 1:
+ {
+ /* 00 -> 11
+ 01 -> 10
+ 10 -> 10
+ 11 -> 00 */
+ TCGv low = tcg_temp_new();
+
+ /* Force addr into the temp. */
+ if (addr != &t) {
+ t = tcg_temp_new();
+ tcg_gen_mov_tl(t, *addr);
+ addr = &t;
+ }
+
+ tcg_gen_andi_tl(low, t, 3);
+ tcg_gen_sub_tl(low, tcg_const_tl(3), low);
+ tcg_gen_andi_tl(t, t, ~3);
+ tcg_gen_or_tl(t, t, low);
+ tcg_gen_mov_tl(env_debug, low);
+ tcg_gen_mov_tl(env_imm, t);
+ tcg_temp_free(low);
+ break;
+ }
+
+ case 2:
+ /* 00 -> 10
+ 10 -> 00. */
+ /* Force addr into the temp. */
+ if (addr != &t) {
+ t = tcg_temp_new();
+ tcg_gen_xori_tl(t, *addr, 2);
+ addr = &t;
+ } else {
+ tcg_gen_xori_tl(t, t, 2);
+ }
+ break;
+ default:
+ cpu_abort(dc->env, "Invalid reverse size\n");
+ break;
+ }
+ }
+
/* If we get a fault on a dslot, the jmpstate better be in sync. */
sync_jmpstate(dc);
@@ -848,13 +928,22 @@ static void dec_load(DisasContext *dc)
tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
gen_helper_memalign(*addr, tcg_const_tl(dc->rd),
tcg_const_tl(0), tcg_const_tl(size - 1));
- if (dc->rd)
- tcg_gen_mov_tl(cpu_R[dc->rd], v);
+ if (dc->rd) {
+ if (rev) {
+ dec_byteswap(dc, cpu_R[dc->rd], v, size);
+ } else {
+ tcg_gen_mov_tl(cpu_R[dc->rd], v);
+ }
+ }
tcg_temp_free(v);
} else {
if (dc->rd) {
gen_load(dc, cpu_R[dc->rd], *addr, size);
+ if (rev) {
+ dec_byteswap(dc, cpu_R[dc->rd], cpu_R[dc->rd], size);
+ }
} else {
+ /* We are loading into r0, no need to reverse. */
gen_load(dc, env_imm, *addr, size);
}
}
@@ -881,9 +970,12 @@ static void gen_store(DisasContext *dc, TCGv addr, TCGv val,
static void dec_store(DisasContext *dc)
{
TCGv t, *addr;
- unsigned int size;
+ unsigned int size, rev = 0;
size = 1 << (dc->opcode & 3);
+ if (!dc->type_b) {
+ rev = (dc->ir >> 9) & 1;
+ }
if (size > 4 && (dc->tb_flags & MSR_EE_FLAG)
&& (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) {
@@ -892,19 +984,84 @@ static void dec_store(DisasContext *dc)
return;
}
- LOG_DIS("s%d%s\n", size, dc->type_b ? "i" : "");
+ LOG_DIS("s%d%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "");
t_sync_flags(dc);
/* If we get a fault on a dslot, the jmpstate better be in sync. */
sync_jmpstate(dc);
addr = compute_ldst_addr(dc, &t);
- gen_store(dc, *addr, cpu_R[dc->rd], size);
+ if (rev && size != 4) {
+ /* Endian reverse the address. t is addr. */
+ switch (size) {
+ case 1:
+ {
+ /* 00 -> 11
+ 01 -> 10
+ 10 -> 10
+ 11 -> 00 */
+ TCGv low = tcg_temp_new();
+
+ /* Force addr into the temp. */
+ if (addr != &t) {
+ t = tcg_temp_new();
+ tcg_gen_mov_tl(t, *addr);
+ addr = &t;
+ }
+
+ tcg_gen_andi_tl(low, t, 3);
+ tcg_gen_sub_tl(low, tcg_const_tl(3), low);
+ tcg_gen_andi_tl(t, t, ~3);
+ tcg_gen_or_tl(t, t, low);
+ tcg_gen_mov_tl(env_debug, low);
+ tcg_gen_mov_tl(env_imm, t);
+ tcg_temp_free(low);
+ break;
+ }
+
+ case 2:
+ /* 00 -> 10
+ 10 -> 00. */
+ /* Force addr into the temp. */
+ if (addr != &t) {
+ t = tcg_temp_new();
+ tcg_gen_xori_tl(t, *addr, 2);
+ addr = &t;
+ } else {
+ tcg_gen_xori_tl(t, t, 2);
+ }
+ break;
+ default:
+ cpu_abort(dc->env, "Invalid reverse size\n");
+ break;
+ }
+
+ if (size != 1) {
+ TCGv bs_data = tcg_temp_new();
+ dec_byteswap(dc, bs_data, cpu_R[dc->rd], size);
+ gen_store(dc, *addr, bs_data, size);
+ tcg_temp_free(bs_data);
+ } else {
+ gen_store(dc, *addr, cpu_R[dc->rd], size);
+ }
+ } else {
+ if (rev) {
+ TCGv bs_data = tcg_temp_new();
+ dec_byteswap(dc, bs_data, cpu_R[dc->rd], size);
+ gen_store(dc, *addr, bs_data, size);
+ tcg_temp_free(bs_data);
+ } else {
+ gen_store(dc, *addr, cpu_R[dc->rd], size);
+ }
+ }
/* Verify alignment if needed. */
if ((dc->env->pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) {
tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
/* FIXME: if the alignment is wrong, we should restore the value
- * in memory.
+ * in memory. One possible way to acheive this is to probe
+ * the MMU prior to the memaccess, thay way we could put
+ * the alignment checks in between the probe and the mem
+ * access.
*/
gen_helper_memalign(*addr, tcg_const_tl(dc->rd),
tcg_const_tl(1), tcg_const_tl(size - 1));
@@ -975,7 +1132,7 @@ static void dec_bcc(DisasContext *dc)
int32_t offset = (int32_t)((int16_t)dc->imm); /* sign-extend. */
tcg_gen_movi_tl(env_btarget, dc->pc + offset);
- dc->jmp = JMP_DIRECT;
+ dc->jmp = JMP_DIRECT_CC;
dc->jmp_pc = dc->pc + offset;
} else {
dc->jmp = JMP_INDIRECT;
@@ -1029,7 +1186,6 @@ static void dec_br(DisasContext *dc)
if (dec_alu_op_b_is_small_imm(dc)) {
dc->jmp = JMP_DIRECT;
dc->jmp_pc = dc->pc + (int32_t)((int16_t)dc->imm);
- tcg_gen_movi_tl(env_btaken, 1);
} else {
tcg_gen_movi_tl(env_btaken, 1);
tcg_gen_movi_tl(env_btarget, dc->pc);
@@ -1451,6 +1607,10 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
eval_cond_jmp(dc, env_btarget, tcg_const_tl(dc->pc));
dc->is_jmp = DISAS_JUMP;
} else if (dc->jmp == JMP_DIRECT) {
+ t_sync_flags(dc);
+ gen_goto_tb(dc, 0, dc->jmp_pc);
+ dc->is_jmp = DISAS_TB_JUMP;
+ } else if (dc->jmp == JMP_DIRECT_CC) {
int l1;
t_sync_flags(dc);
@@ -1475,7 +1635,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
&& num_insns < max_insns);
npc = dc->pc;
- if (dc->jmp == JMP_DIRECT) {
+ if (dc->jmp == JMP_DIRECT || dc->jmp == JMP_DIRECT_CC) {
if (dc->tb_flags & D_FLAG) {
dc->is_jmp = DISAS_UPDATE;
tcg_gen_movi_tl(cpu_SR[SR_PC], npc);
diff --git a/target-mips/translate.c b/target-mips/translate.c
index cce77be0d1..187930e3d2 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -3410,8 +3410,10 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
gen_helper_mfc0_count(arg);
if (use_icount) {
gen_io_end();
- ctx->bstate = BS_STOP;
}
+ /* Break the TB to be able to take timer interrupts immediately
+ after reading count. */
+ ctx->bstate = BS_STOP;
rn = "Count";
break;
/* 6,7 are implementation dependent */
@@ -4581,8 +4583,10 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
gen_helper_mfc0_count(arg);
if (use_icount) {
gen_io_end();
- ctx->bstate = BS_STOP;
}
+ /* Break the TB to be able to take timer interrupts immediately
+ after reading count. */
+ ctx->bstate = BS_STOP;
rn = "Count";
break;
/* 6,7 are implementation dependent */
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index 279f345593..17e070ae75 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -546,7 +546,7 @@ uint32_t helper_compute_fprf (uint64_t arg, uint32_t set_fprf)
int ret;
farg.ll = arg;
isneg = float64_is_neg(farg.d);
- if (unlikely(float64_is_quiet_nan(farg.d))) {
+ if (unlikely(float64_is_any_nan(farg.d))) {
if (float64_is_signaling_nan(farg.d)) {
/* Signaling NaN: flags are undefined */
ret = 0x00;
@@ -975,15 +975,16 @@ uint64_t helper_fadd (uint64_t arg1, uint64_t arg2)
farg1.ll = arg1;
farg2.ll = arg2;
- if (unlikely(float64_is_signaling_nan(farg1.d) ||
- float64_is_signaling_nan(farg2.d))) {
- /* sNaN addition */
- farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
- float64_is_neg(farg1.d) != float64_is_neg(farg2.d))) {
+ if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
+ float64_is_neg(farg1.d) != float64_is_neg(farg2.d))) {
/* Magnitude subtraction of infinities */
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
} else {
+ if (unlikely(float64_is_signaling_nan(farg1.d) ||
+ float64_is_signaling_nan(farg2.d))) {
+ /* sNaN addition */
+ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+ }
farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status);
}
@@ -998,15 +999,16 @@ uint64_t helper_fsub (uint64_t arg1, uint64_t arg2)
farg1.ll = arg1;
farg2.ll = arg2;
- if (unlikely(float64_is_signaling_nan(farg1.d) ||
- float64_is_signaling_nan(farg2.d))) {
- /* sNaN subtraction */
- farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
- float64_is_neg(farg1.d) == float64_is_neg(farg2.d))) {
+ if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
+ float64_is_neg(farg1.d) == float64_is_neg(farg2.d))) {
/* Magnitude subtraction of infinities */
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
} else {
+ if (unlikely(float64_is_signaling_nan(farg1.d) ||
+ float64_is_signaling_nan(farg2.d))) {
+ /* sNaN subtraction */
+ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+ }
farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status);
}
@@ -1021,15 +1023,16 @@ uint64_t helper_fmul (uint64_t arg1, uint64_t arg2)
farg1.ll = arg1;
farg2.ll = arg2;
- if (unlikely(float64_is_signaling_nan(farg1.d) ||
- float64_is_signaling_nan(farg2.d))) {
- /* sNaN multiplication */
- farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
- (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
+ if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
+ (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
/* Multiplication of zero by infinity */
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
} else {
+ if (unlikely(float64_is_signaling_nan(farg1.d) ||
+ float64_is_signaling_nan(farg2.d))) {
+ /* sNaN multiplication */
+ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+ }
farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
}
@@ -1044,17 +1047,18 @@ uint64_t helper_fdiv (uint64_t arg1, uint64_t arg2)
farg1.ll = arg1;
farg2.ll = arg2;
- if (unlikely(float64_is_signaling_nan(farg1.d) ||
- float64_is_signaling_nan(farg2.d))) {
- /* sNaN division */
- farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d))) {
+ if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d))) {
/* Division of infinity by infinity */
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIDI);
} else if (unlikely(float64_is_zero(farg1.d) && float64_is_zero(farg2.d))) {
/* Division of zero by zero */
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXZDZ);
} else {
+ if (unlikely(float64_is_signaling_nan(farg1.d) ||
+ float64_is_signaling_nan(farg2.d))) {
+ /* sNaN division */
+ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+ }
farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status);
}
@@ -1232,16 +1236,17 @@ uint64_t helper_fmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
farg2.ll = arg2;
farg3.ll = arg3;
- if (unlikely(float64_is_signaling_nan(farg1.d) ||
- float64_is_signaling_nan(farg2.d) ||
- float64_is_signaling_nan(farg3.d))) {
- /* sNaN operation */
- farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
- (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
+ if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
+ (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
/* Multiplication of zero by infinity */
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
} else {
+ if (unlikely(float64_is_signaling_nan(farg1.d) ||
+ float64_is_signaling_nan(farg2.d) ||
+ float64_is_signaling_nan(farg3.d))) {
+ /* sNaN operation */
+ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+ }
#ifdef FLOAT128
/* This is the way the PowerPC specification defines it */
float128 ft0_128, ft1_128;
@@ -1276,16 +1281,17 @@ uint64_t helper_fmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
farg2.ll = arg2;
farg3.ll = arg3;
- if (unlikely(float64_is_signaling_nan(farg1.d) ||
- float64_is_signaling_nan(farg2.d) ||
- float64_is_signaling_nan(farg3.d))) {
- /* sNaN operation */
- farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
+ if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
(float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
/* Multiplication of zero by infinity */
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
} else {
+ if (unlikely(float64_is_signaling_nan(farg1.d) ||
+ float64_is_signaling_nan(farg2.d) ||
+ float64_is_signaling_nan(farg3.d))) {
+ /* sNaN operation */
+ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+ }
#ifdef FLOAT128
/* This is the way the PowerPC specification defines it */
float128 ft0_128, ft1_128;
@@ -1319,16 +1325,17 @@ uint64_t helper_fnmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
farg2.ll = arg2;
farg3.ll = arg3;
- if (unlikely(float64_is_signaling_nan(farg1.d) ||
- float64_is_signaling_nan(farg2.d) ||
- float64_is_signaling_nan(farg3.d))) {
- /* sNaN operation */
- farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
- (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
+ if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
+ (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
/* Multiplication of zero by infinity */
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
} else {
+ if (unlikely(float64_is_signaling_nan(farg1.d) ||
+ float64_is_signaling_nan(farg2.d) ||
+ float64_is_signaling_nan(farg3.d))) {
+ /* sNaN operation */
+ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+ }
#ifdef FLOAT128
/* This is the way the PowerPC specification defines it */
float128 ft0_128, ft1_128;
@@ -1349,8 +1356,9 @@ uint64_t helper_fnmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
/* This is OK on x86 hosts */
farg1.d = (farg1.d * farg2.d) + farg3.d;
#endif
- if (likely(!float64_is_quiet_nan(farg1.d)))
+ if (likely(!float64_is_any_nan(farg1.d))) {
farg1.d = float64_chs(farg1.d);
+ }
}
return farg1.ll;
}
@@ -1364,16 +1372,17 @@ uint64_t helper_fnmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
farg2.ll = arg2;
farg3.ll = arg3;
- if (unlikely(float64_is_signaling_nan(farg1.d) ||
- float64_is_signaling_nan(farg2.d) ||
- float64_is_signaling_nan(farg3.d))) {
- /* sNaN operation */
- farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
+ if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
(float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
/* Multiplication of zero by infinity */
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
} else {
+ if (unlikely(float64_is_signaling_nan(farg1.d) ||
+ float64_is_signaling_nan(farg2.d) ||
+ float64_is_signaling_nan(farg3.d))) {
+ /* sNaN operation */
+ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+ }
#ifdef FLOAT128
/* This is the way the PowerPC specification defines it */
float128 ft0_128, ft1_128;
@@ -1394,8 +1403,9 @@ uint64_t helper_fnmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
/* This is OK on x86 hosts */
farg1.d = (farg1.d * farg2.d) - farg3.d;
#endif
- if (likely(!float64_is_quiet_nan(farg1.d)))
+ if (likely(!float64_is_any_nan(farg1.d))) {
farg1.d = float64_chs(farg1.d);
+ }
}
return farg1.ll;
}
@@ -1409,11 +1419,11 @@ uint64_t helper_frsp (uint64_t arg)
if (unlikely(float64_is_signaling_nan(farg.d))) {
/* sNaN square root */
- farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else {
- f32 = float64_to_float32(farg.d, &env->fp_status);
- farg.d = float32_to_float64(f32, &env->fp_status);
+ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
}
+ f32 = float64_to_float32(farg.d, &env->fp_status);
+ farg.d = float32_to_float64(f32, &env->fp_status);
+
return farg.ll;
}
@@ -1423,13 +1433,14 @@ uint64_t helper_fsqrt (uint64_t arg)
CPU_DoubleU farg;
farg.ll = arg;
- if (unlikely(float64_is_signaling_nan(farg.d))) {
- /* sNaN square root */
- farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
+ if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
/* Square root of a negative nonzero number */
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
} else {
+ if (unlikely(float64_is_signaling_nan(farg.d))) {
+ /* sNaN square root */
+ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+ }
farg.d = float64_sqrt(farg.d, &env->fp_status);
}
return farg.ll;
@@ -1443,10 +1454,9 @@ uint64_t helper_fre (uint64_t arg)
if (unlikely(float64_is_signaling_nan(farg.d))) {
/* sNaN reciprocal */
- farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else {
- farg.d = float64_div(float64_one, farg.d, &env->fp_status);
+ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
}
+ farg.d = float64_div(float64_one, farg.d, &env->fp_status);
return farg.d;
}
@@ -1459,12 +1469,12 @@ uint64_t helper_fres (uint64_t arg)
if (unlikely(float64_is_signaling_nan(farg.d))) {
/* sNaN reciprocal */
- farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else {
- farg.d = float64_div(float64_one, farg.d, &env->fp_status);
- f32 = float64_to_float32(farg.d, &env->fp_status);
- farg.d = float32_to_float64(f32, &env->fp_status);
+ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
}
+ farg.d = float64_div(float64_one, farg.d, &env->fp_status);
+ f32 = float64_to_float32(farg.d, &env->fp_status);
+ farg.d = float32_to_float64(f32, &env->fp_status);
+
return farg.ll;
}
@@ -1475,13 +1485,14 @@ uint64_t helper_frsqrte (uint64_t arg)
float32 f32;
farg.ll = arg;
- if (unlikely(float64_is_signaling_nan(farg.d))) {
- /* sNaN reciprocal square root */
- farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
+ if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
/* Reciprocal square root of a negative nonzero number */
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
} else {
+ if (unlikely(float64_is_signaling_nan(farg.d))) {
+ /* sNaN reciprocal square root */
+ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+ }
farg.d = float64_sqrt(farg.d, &env->fp_status);
farg.d = float64_div(float64_one, farg.d, &env->fp_status);
f32 = float64_to_float32(farg.d, &env->fp_status);
@@ -1497,10 +1508,11 @@ uint64_t helper_fsel (uint64_t arg1, uint64_t arg2, uint64_t arg3)
farg1.ll = arg1;
- if ((!float64_is_neg(farg1.d) || float64_is_zero(farg1.d)) && !float64_is_quiet_nan(farg1.d))
+ if ((!float64_is_neg(farg1.d) || float64_is_zero(farg1.d)) && !float64_is_any_nan(farg1.d)) {
return arg2;
- else
+ } else {
return arg3;
+ }
}
void helper_fcmpu (uint64_t arg1, uint64_t arg2, uint32_t crfD)
@@ -1510,8 +1522,8 @@ void helper_fcmpu (uint64_t arg1, uint64_t arg2, uint32_t crfD)
farg1.ll = arg1;
farg2.ll = arg2;
- if (unlikely(float64_is_quiet_nan(farg1.d) ||
- float64_is_quiet_nan(farg2.d))) {
+ if (unlikely(float64_is_any_nan(farg1.d) ||
+ float64_is_any_nan(farg2.d))) {
ret = 0x01UL;
} else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
ret = 0x08UL;
@@ -1539,8 +1551,8 @@ void helper_fcmpo (uint64_t arg1, uint64_t arg2, uint32_t crfD)
farg1.ll = arg1;
farg2.ll = arg2;
- if (unlikely(float64_is_quiet_nan(farg1.d) ||
- float64_is_quiet_nan(farg2.d))) {
+ if (unlikely(float64_is_any_nan(farg1.d) ||
+ float64_is_any_nan(farg2.d))) {
ret = 0x01UL;
} else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
ret = 0x08UL;
@@ -3437,8 +3449,9 @@ uint32_t helper_efdctsi (uint64_t val)
u.ll = val;
/* NaN are not treated the same way IEEE 754 does */
- if (unlikely(float64_is_quiet_nan(u.d)))
+ if (unlikely(float64_is_any_nan(u.d))) {
return 0;
+ }
return float64_to_int32(u.d, &env->vec_status);
}
@@ -3449,8 +3462,9 @@ uint32_t helper_efdctui (uint64_t val)
u.ll = val;
/* NaN are not treated the same way IEEE 754 does */
- if (unlikely(float64_is_quiet_nan(u.d)))
+ if (unlikely(float64_is_any_nan(u.d))) {
return 0;
+ }
return float64_to_uint32(u.d, &env->vec_status);
}
@@ -3461,8 +3475,9 @@ uint32_t helper_efdctsiz (uint64_t val)
u.ll = val;
/* NaN are not treated the same way IEEE 754 does */
- if (unlikely(float64_is_quiet_nan(u.d)))
+ if (unlikely(float64_is_any_nan(u.d))) {
return 0;
+ }
return float64_to_int32_round_to_zero(u.d, &env->vec_status);
}
@@ -3473,8 +3488,9 @@ uint64_t helper_efdctsidz (uint64_t val)
u.ll = val;
/* NaN are not treated the same way IEEE 754 does */
- if (unlikely(float64_is_quiet_nan(u.d)))
+ if (unlikely(float64_is_any_nan(u.d))) {
return 0;
+ }
return float64_to_int64_round_to_zero(u.d, &env->vec_status);
}
@@ -3485,8 +3501,9 @@ uint32_t helper_efdctuiz (uint64_t val)
u.ll = val;
/* NaN are not treated the same way IEEE 754 does */
- if (unlikely(float64_is_quiet_nan(u.d)))
+ if (unlikely(float64_is_any_nan(u.d))) {
return 0;
+ }
return float64_to_uint32_round_to_zero(u.d, &env->vec_status);
}
@@ -3497,8 +3514,9 @@ uint64_t helper_efdctuidz (uint64_t val)
u.ll = val;
/* NaN are not treated the same way IEEE 754 does */
- if (unlikely(float64_is_quiet_nan(u.d)))
+ if (unlikely(float64_is_any_nan(u.d))) {
return 0;
+ }
return float64_to_uint64_round_to_zero(u.d, &env->vec_status);
}
@@ -3534,8 +3552,9 @@ uint32_t helper_efdctsf (uint64_t val)
u.ll = val;
/* NaN are not treated the same way IEEE 754 does */
- if (unlikely(float64_is_quiet_nan(u.d)))
+ if (unlikely(float64_is_any_nan(u.d))) {
return 0;
+ }
tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
u.d = float64_mul(u.d, tmp, &env->vec_status);
@@ -3549,8 +3568,9 @@ uint32_t helper_efdctuf (uint64_t val)
u.ll = val;
/* NaN are not treated the same way IEEE 754 does */
- if (unlikely(float64_is_quiet_nan(u.d)))
+ if (unlikely(float64_is_any_nan(u.d))) {
return 0;
+ }
tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
u.d = float64_mul(u.d, tmp, &env->vec_status);
diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h
index 8ccf25cafb..95df6d2a75 100644
--- a/target-sh4/cpu.h
+++ b/target-sh4/cpu.h
@@ -61,10 +61,37 @@
#define SR_S (1 << 1)
#define SR_T (1 << 0)
-#define FPSCR_FR (1 << 21)
-#define FPSCR_SZ (1 << 20)
-#define FPSCR_PR (1 << 19)
-#define FPSCR_DN (1 << 18)
+#define FPSCR_MASK (0x003fffff)
+#define FPSCR_FR (1 << 21)
+#define FPSCR_SZ (1 << 20)
+#define FPSCR_PR (1 << 19)
+#define FPSCR_DN (1 << 18)
+#define FPSCR_CAUSE_MASK (0x3f << 12)
+#define FPSCR_CAUSE_SHIFT (12)
+#define FPSCR_CAUSE_E (1 << 17)
+#define FPSCR_CAUSE_V (1 << 16)
+#define FPSCR_CAUSE_Z (1 << 15)
+#define FPSCR_CAUSE_O (1 << 14)
+#define FPSCR_CAUSE_U (1 << 13)
+#define FPSCR_CAUSE_I (1 << 12)
+#define FPSCR_ENABLE_MASK (0x1f << 7)
+#define FPSCR_ENABLE_SHIFT (7)
+#define FPSCR_ENABLE_V (1 << 11)
+#define FPSCR_ENABLE_Z (1 << 10)
+#define FPSCR_ENABLE_O (1 << 9)
+#define FPSCR_ENABLE_U (1 << 8)
+#define FPSCR_ENABLE_I (1 << 7)
+#define FPSCR_FLAG_MASK (0x1f << 2)
+#define FPSCR_FLAG_SHIFT (2)
+#define FPSCR_FLAG_V (1 << 6)
+#define FPSCR_FLAG_Z (1 << 5)
+#define FPSCR_FLAG_O (1 << 4)
+#define FPSCR_FLAG_U (1 << 3)
+#define FPSCR_FLAG_I (1 << 2)
+#define FPSCR_RM_MASK (0x03 << 0)
+#define FPSCR_RM_NEAREST (0 << 0)
+#define FPSCR_RM_ZERO (1 << 0)
+
#define DELAY_SLOT (1 << 0)
#define DELAY_SLOT_CONDITIONAL (1 << 1)
#define DELAY_SLOT_TRUE (1 << 2)
@@ -109,8 +136,6 @@ typedef struct memory_content {
} memory_content;
typedef struct CPUSH4State {
- int id; /* CPU model */
-
uint32_t flags; /* general execution flags */
uint32_t gregs[24]; /* general registers */
float32 fregs[32]; /* floating point registers */
@@ -146,14 +171,18 @@ typedef struct CPUSH4State {
uint32_t expevt; /* exception event register */
uint32_t intevt; /* interrupt event register */
+ tlb_t itlb[ITLB_SIZE]; /* instruction translation table */
+ tlb_t utlb[UTLB_SIZE]; /* unified translation table */
+
+ uint32_t ldst;
+
+ CPU_COMMON
+
+ int id; /* CPU model */
uint32_t pvr; /* Processor Version Register */
uint32_t prr; /* Processor Revision Register */
uint32_t cvr; /* Cache Version Register */
- uint32_t ldst;
-
- CPU_COMMON tlb_t utlb[UTLB_SIZE]; /* unified translation table */
- tlb_t itlb[ITLB_SIZE]; /* instruction translation table */
void *intc_handle;
int intr_at_halt; /* SR_BL ignored during sleep */
memory_content *movcal_backup;
diff --git a/target-sh4/helper.c b/target-sh4/helper.c
index 2343366762..45449ea64e 100644
--- a/target-sh4/helper.c
+++ b/target-sh4/helper.c
@@ -380,7 +380,7 @@ static int get_mmu_address(CPUState * env, target_ulong * physical,
MMU_DTLB_VIOLATION_READ;
} else if ((rw == 1) && !(matching->pr & 1)) {
n = MMU_DTLB_VIOLATION_WRITE;
- } else if ((rw == 1) & !matching->d) {
+ } else if ((rw == 1) && !matching->d) {
n = MMU_DTLB_INITIAL_WRITE;
} else {
*prot = PAGE_READ;
@@ -430,7 +430,7 @@ static int get_physical_address(CPUState * env, target_ulong * physical,
}
/* If MMU is disabled, return the corresponding physical page */
- if (!env->mmucr & MMUCR_AT) {
+ if (!(env->mmucr & MMUCR_AT)) {
*physical = address & 0x1FFFFFFF;
*prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
return MMU_OK;
diff --git a/target-sh4/helper.h b/target-sh4/helper.h
index 4b2fcdd536..2e52768414 100644
--- a/target-sh4/helper.h
+++ b/target-sh4/helper.h
@@ -17,7 +17,6 @@ DEF_HELPER_2(addv, i32, i32, i32)
DEF_HELPER_2(addc, i32, i32, i32)
DEF_HELPER_2(subv, i32, i32, i32)
DEF_HELPER_2(subc, i32, i32, i32)
-DEF_HELPER_1(negc, i32, i32)
DEF_HELPER_2(div1, i32, i32, i32)
DEF_HELPER_2(macl, void, i32, i32)
DEF_HELPER_2(macw, void, i32, i32)
@@ -49,5 +48,7 @@ DEF_HELPER_1(fsqrt_FT, i32, i32)
DEF_HELPER_1(fsqrt_DT, i64, i64)
DEF_HELPER_1(ftrc_FT, i32, i32)
DEF_HELPER_1(ftrc_DT, i32, i64)
+DEF_HELPER_2(fipr, void, i32, i32)
+DEF_HELPER_1(ftrv, void, i32)
#include "def-helper.h"
diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c
index 2e5f5552a2..30f9842295 100644
--- a/target-sh4/op_helper.c
+++ b/target-sh4/op_helper.c
@@ -21,6 +21,22 @@
#include "exec.h"
#include "helper.h"
+static void cpu_restore_state_from_retaddr(void *retaddr)
+{
+ TranslationBlock *tb;
+ unsigned long pc;
+
+ if (retaddr) {
+ pc = (unsigned long) retaddr;
+ tb = tb_find_pc(pc);
+ if (tb) {
+ /* the PC is inside the translated code. It means that we have
+ a virtual CPU fault */
+ cpu_restore_state(tb, env, pc, NULL);
+ }
+ }
+}
+
#ifndef CONFIG_USER_ONLY
#define MMUSUFFIX _mmu
@@ -39,9 +55,7 @@
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
{
- TranslationBlock *tb;
CPUState *saved_env;
- unsigned long pc;
int ret;
/* XXX: hack to restore env in all cases, even if not called from
@@ -50,16 +64,8 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
env = cpu_single_env;
ret = cpu_sh4_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
if (ret) {
- if (retaddr) {
- /* now we have a real cpu fault */
- pc = (unsigned long) retaddr;
- tb = tb_find_pc(pc);
- if (tb) {
- /* the PC is inside the translated code. It means that we have
- a virtual CPU fault */
- cpu_restore_state(tb, env, pc, NULL);
- }
- }
+ /* now we have a real cpu fault */
+ cpu_restore_state_from_retaddr(retaddr);
cpu_loop_exit();
}
env = saved_env;
@@ -77,28 +83,31 @@ void helper_ldtlb(void)
#endif
}
-void helper_raise_illegal_instruction(void)
+static inline void raise_exception(int index, void *retaddr)
{
- env->exception_index = 0x180;
+ env->exception_index = index;
+ cpu_restore_state_from_retaddr(retaddr);
cpu_loop_exit();
}
+void helper_raise_illegal_instruction(void)
+{
+ raise_exception(0x180, GETPC());
+}
+
void helper_raise_slot_illegal_instruction(void)
{
- env->exception_index = 0x1a0;
- cpu_loop_exit();
+ raise_exception(0x1a0, GETPC());
}
void helper_raise_fpu_disable(void)
{
- env->exception_index = 0x800;
- cpu_loop_exit();
+ raise_exception(0x800, GETPC());
}
void helper_raise_slot_fpu_disable(void)
{
- env->exception_index = 0x820;
- cpu_loop_exit();
+ raise_exception(0x820, GETPC());
}
void helper_debug(void)
@@ -118,8 +127,7 @@ void helper_sleep(uint32_t next_pc)
void helper_trapa(uint32_t tra)
{
env->tra = tra << 2;
- env->exception_index = 0x160;
- cpu_loop_exit();
+ raise_exception(0x160, GETPC());
}
void helper_movcal(uint32_t address, uint32_t value)
@@ -371,21 +379,6 @@ void helper_macw(uint32_t arg0, uint32_t arg1)
}
}
-uint32_t helper_negc(uint32_t arg)
-{
- uint32_t temp;
-
- temp = -arg;
- arg = temp - (env->sr & SR_T);
- if (0 < temp)
- env->sr |= SR_T;
- else
- env->sr &= ~SR_T;
- if (temp < arg)
- env->sr |= SR_T;
- return arg;
-}
-
uint32_t helper_subc(uint32_t arg0, uint32_t arg1)
{
uint32_t tmp0, tmp1;
@@ -443,11 +436,54 @@ static inline void clr_t(void)
void helper_ld_fpscr(uint32_t val)
{
- env->fpscr = val & 0x003fffff;
- if (val & 0x01)
+ env->fpscr = val & FPSCR_MASK;
+ if ((val & FPSCR_RM_MASK) == FPSCR_RM_ZERO) {
set_float_rounding_mode(float_round_to_zero, &env->fp_status);
- else
+ } else {
set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
+ }
+ set_flush_to_zero((val & FPSCR_DN) != 0, &env->fp_status);
+}
+
+static void update_fpscr(void *retaddr)
+{
+ int xcpt, cause, enable;
+
+ xcpt = get_float_exception_flags(&env->fp_status);
+
+ /* Clear the flag entries */
+ env->fpscr &= ~FPSCR_FLAG_MASK;
+
+ if (unlikely(xcpt)) {
+ if (xcpt & float_flag_invalid) {
+ env->fpscr |= FPSCR_FLAG_V;
+ }
+ if (xcpt & float_flag_divbyzero) {
+ env->fpscr |= FPSCR_FLAG_Z;
+ }
+ if (xcpt & float_flag_overflow) {
+ env->fpscr |= FPSCR_FLAG_O;
+ }
+ if (xcpt & float_flag_underflow) {
+ env->fpscr |= FPSCR_FLAG_U;
+ }
+ if (xcpt & float_flag_inexact) {
+ env->fpscr |= FPSCR_FLAG_I;
+ }
+
+ /* Accumulate in cause entries */
+ env->fpscr |= (env->fpscr & FPSCR_FLAG_MASK)
+ << (FPSCR_CAUSE_SHIFT - FPSCR_FLAG_SHIFT);
+
+ /* Generate an exception if enabled */
+ cause = (env->fpscr & FPSCR_CAUSE_MASK) >> FPSCR_CAUSE_SHIFT;
+ enable = (env->fpscr & FPSCR_ENABLE_MASK) >> FPSCR_ENABLE_SHIFT;
+ if (cause & enable) {
+ cpu_restore_state_from_retaddr(retaddr);
+ env->exception_index = 0x120;
+ cpu_loop_exit();
+ }
+ }
}
uint32_t helper_fabs_FT(uint32_t t0)
@@ -471,7 +507,9 @@ uint32_t helper_fadd_FT(uint32_t t0, uint32_t t1)
CPU_FloatU f0, f1;
f0.l = t0;
f1.l = t1;
+ set_float_exception_flags(0, &env->fp_status);
f0.f = float32_add(f0.f, f1.f, &env->fp_status);
+ update_fpscr(GETPC());
return f0.l;
}
@@ -480,56 +518,82 @@ uint64_t helper_fadd_DT(uint64_t t0, uint64_t t1)
CPU_DoubleU d0, d1;
d0.ll = t0;
d1.ll = t1;
+ set_float_exception_flags(0, &env->fp_status);
d0.d = float64_add(d0.d, d1.d, &env->fp_status);
+ update_fpscr(GETPC());
return d0.ll;
}
void helper_fcmp_eq_FT(uint32_t t0, uint32_t t1)
{
CPU_FloatU f0, f1;
+ int relation;
f0.l = t0;
f1.l = t1;
- if (float32_compare(f0.f, f1.f, &env->fp_status) == 0)
+ set_float_exception_flags(0, &env->fp_status);
+ relation = float32_compare(f0.f, f1.f, &env->fp_status);
+ if (unlikely(relation == float_relation_unordered)) {
+ update_fpscr(GETPC());
+ } else if (relation == float_relation_equal) {
set_t();
- else
+ } else {
clr_t();
+ }
}
void helper_fcmp_eq_DT(uint64_t t0, uint64_t t1)
{
CPU_DoubleU d0, d1;
+ int relation;
d0.ll = t0;
d1.ll = t1;
- if (float64_compare(d0.d, d1.d, &env->fp_status) == 0)
+ set_float_exception_flags(0, &env->fp_status);
+ relation = float64_compare(d0.d, d1.d, &env->fp_status);
+ if (unlikely(relation == float_relation_unordered)) {
+ update_fpscr(GETPC());
+ } else if (relation == float_relation_equal) {
set_t();
- else
+ } else {
clr_t();
+ }
}
void helper_fcmp_gt_FT(uint32_t t0, uint32_t t1)
{
CPU_FloatU f0, f1;
+ int relation;
f0.l = t0;
f1.l = t1;
- if (float32_compare(f0.f, f1.f, &env->fp_status) == 1)
+ set_float_exception_flags(0, &env->fp_status);
+ relation = float32_compare(f0.f, f1.f, &env->fp_status);
+ if (unlikely(relation == float_relation_unordered)) {
+ update_fpscr(GETPC());
+ } else if (relation == float_relation_greater) {
set_t();
- else
+ } else {
clr_t();
+ }
}
void helper_fcmp_gt_DT(uint64_t t0, uint64_t t1)
{
CPU_DoubleU d0, d1;
+ int relation;
d0.ll = t0;
d1.ll = t1;
- if (float64_compare(d0.d, d1.d, &env->fp_status) == 1)
+ set_float_exception_flags(0, &env->fp_status);
+ relation = float64_compare(d0.d, d1.d, &env->fp_status);
+ if (unlikely(relation == float_relation_unordered)) {
+ update_fpscr(GETPC());
+ } else if (relation == float_relation_greater) {
set_t();
- else
+ } else {
clr_t();
+ }
}
uint64_t helper_fcnvsd_FT_DT(uint32_t t0)
@@ -537,7 +601,9 @@ uint64_t helper_fcnvsd_FT_DT(uint32_t t0)
CPU_DoubleU d;
CPU_FloatU f;
f.l = t0;
+ set_float_exception_flags(0, &env->fp_status);
d.d = float32_to_float64(f.f, &env->fp_status);
+ update_fpscr(GETPC());
return d.ll;
}
@@ -546,7 +612,9 @@ uint32_t helper_fcnvds_DT_FT(uint64_t t0)
CPU_DoubleU d;
CPU_FloatU f;
d.ll = t0;
+ set_float_exception_flags(0, &env->fp_status);
f.f = float64_to_float32(d.d, &env->fp_status);
+ update_fpscr(GETPC());
return f.l;
}
@@ -555,7 +623,9 @@ uint32_t helper_fdiv_FT(uint32_t t0, uint32_t t1)
CPU_FloatU f0, f1;
f0.l = t0;
f1.l = t1;
+ set_float_exception_flags(0, &env->fp_status);
f0.f = float32_div(f0.f, f1.f, &env->fp_status);
+ update_fpscr(GETPC());
return f0.l;
}
@@ -564,21 +634,29 @@ uint64_t helper_fdiv_DT(uint64_t t0, uint64_t t1)
CPU_DoubleU d0, d1;
d0.ll = t0;
d1.ll = t1;
+ set_float_exception_flags(0, &env->fp_status);
d0.d = float64_div(d0.d, d1.d, &env->fp_status);
+ update_fpscr(GETPC());
return d0.ll;
}
uint32_t helper_float_FT(uint32_t t0)
{
CPU_FloatU f;
+
+ set_float_exception_flags(0, &env->fp_status);
f.f = int32_to_float32(t0, &env->fp_status);
+ update_fpscr(GETPC());
+
return f.l;
}
uint64_t helper_float_DT(uint32_t t0)
{
CPU_DoubleU d;
+ set_float_exception_flags(0, &env->fp_status);
d.d = int32_to_float64(t0, &env->fp_status);
+ update_fpscr(GETPC());
return d.ll;
}
@@ -588,8 +666,11 @@ uint32_t helper_fmac_FT(uint32_t t0, uint32_t t1, uint32_t t2)
f0.l = t0;
f1.l = t1;
f2.l = t2;
+ set_float_exception_flags(0, &env->fp_status);
f0.f = float32_mul(f0.f, f1.f, &env->fp_status);
f0.f = float32_add(f0.f, f2.f, &env->fp_status);
+ update_fpscr(GETPC());
+
return f0.l;
}
@@ -598,7 +679,9 @@ uint32_t helper_fmul_FT(uint32_t t0, uint32_t t1)
CPU_FloatU f0, f1;
f0.l = t0;
f1.l = t1;
+ set_float_exception_flags(0, &env->fp_status);
f0.f = float32_mul(f0.f, f1.f, &env->fp_status);
+ update_fpscr(GETPC());
return f0.l;
}
@@ -607,7 +690,10 @@ uint64_t helper_fmul_DT(uint64_t t0, uint64_t t1)
CPU_DoubleU d0, d1;
d0.ll = t0;
d1.ll = t1;
+ set_float_exception_flags(0, &env->fp_status);
d0.d = float64_mul(d0.d, d1.d, &env->fp_status);
+ update_fpscr(GETPC());
+
return d0.ll;
}
@@ -623,7 +709,9 @@ uint32_t helper_fsqrt_FT(uint32_t t0)
{
CPU_FloatU f;
f.l = t0;
+ set_float_exception_flags(0, &env->fp_status);
f.f = float32_sqrt(f.f, &env->fp_status);
+ update_fpscr(GETPC());
return f.l;
}
@@ -631,7 +719,9 @@ uint64_t helper_fsqrt_DT(uint64_t t0)
{
CPU_DoubleU d;
d.ll = t0;
+ set_float_exception_flags(0, &env->fp_status);
d.d = float64_sqrt(d.d, &env->fp_status);
+ update_fpscr(GETPC());
return d.ll;
}
@@ -640,29 +730,88 @@ uint32_t helper_fsub_FT(uint32_t t0, uint32_t t1)
CPU_FloatU f0, f1;
f0.l = t0;
f1.l = t1;
+ set_float_exception_flags(0, &env->fp_status);
f0.f = float32_sub(f0.f, f1.f, &env->fp_status);
+ update_fpscr(GETPC());
return f0.l;
}
uint64_t helper_fsub_DT(uint64_t t0, uint64_t t1)
{
CPU_DoubleU d0, d1;
+
d0.ll = t0;
d1.ll = t1;
+ set_float_exception_flags(0, &env->fp_status);
d0.d = float64_sub(d0.d, d1.d, &env->fp_status);
+ update_fpscr(GETPC());
return d0.ll;
}
uint32_t helper_ftrc_FT(uint32_t t0)
{
CPU_FloatU f;
+ uint32_t ret;
f.l = t0;
- return float32_to_int32_round_to_zero(f.f, &env->fp_status);
+ set_float_exception_flags(0, &env->fp_status);
+ ret = float32_to_int32_round_to_zero(f.f, &env->fp_status);
+ update_fpscr(GETPC());
+ return ret;
}
uint32_t helper_ftrc_DT(uint64_t t0)
{
CPU_DoubleU d;
+ uint32_t ret;
d.ll = t0;
- return float64_to_int32_round_to_zero(d.d, &env->fp_status);
+ set_float_exception_flags(0, &env->fp_status);
+ ret = float64_to_int32_round_to_zero(d.d, &env->fp_status);
+ update_fpscr(GETPC());
+ return ret;
+}
+
+void helper_fipr(uint32_t m, uint32_t n)
+{
+ int bank, i;
+ float32 r, p;
+
+ bank = (env->sr & FPSCR_FR) ? 16 : 0;
+ r = float32_zero;
+ set_float_exception_flags(0, &env->fp_status);
+
+ for (i = 0 ; i < 4 ; i++) {
+ p = float32_mul(env->fregs[bank + m + i],
+ env->fregs[bank + n + i],
+ &env->fp_status);
+ r = float32_add(r, p, &env->fp_status);
+ }
+ update_fpscr(GETPC());
+
+ env->fregs[bank + n + 3] = r;
+}
+
+void helper_ftrv(uint32_t n)
+{
+ int bank_matrix, bank_vector;
+ int i, j;
+ float32 r[4];
+ float32 p;
+
+ bank_matrix = (env->sr & FPSCR_FR) ? 0 : 16;
+ bank_vector = (env->sr & FPSCR_FR) ? 16 : 0;
+ set_float_exception_flags(0, &env->fp_status);
+ for (i = 0 ; i < 4 ; i++) {
+ r[i] = float32_zero;
+ for (j = 0 ; j < 4 ; j++) {
+ p = float32_mul(env->fregs[bank_matrix + 4 * j + i],
+ env->fregs[bank_vector + j],
+ &env->fp_status);
+ r[i] = float32_add(r[i], p, &env->fp_status);
+ }
+ }
+ update_fpscr(GETPC());
+
+ for (i = 0 ; i < 4 ; i++) {
+ env->fregs[bank_vector + i] = r[i];
+ }
}
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index f418139931..35573be5ff 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -185,28 +185,27 @@ void cpu_dump_state(CPUState * env, FILE * f,
}
}
-static void cpu_sh4_reset(CPUSH4State * env)
+void cpu_reset(CPUSH4State * env)
{
if (qemu_loglevel_mask(CPU_LOG_RESET)) {
qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
log_cpu_state(env, 0);
}
-#if defined(CONFIG_USER_ONLY)
- env->sr = 0;
-#else
- env->sr = SR_MD | SR_RB | SR_BL | SR_I3 | SR_I2 | SR_I1 | SR_I0;
-#endif
- env->vbr = 0;
+ memset(env, 0, offsetof(CPUSH4State, breakpoints));
+ tlb_flush(env, 1);
+
env->pc = 0xA0000000;
#if defined(CONFIG_USER_ONLY)
env->fpscr = FPSCR_PR; /* value for userspace according to the kernel */
set_float_rounding_mode(float_round_nearest_even, &env->fp_status); /* ?! */
#else
- env->fpscr = 0x00040001; /* CPU reset value according to SH4 manual */
+ env->sr = SR_MD | SR_RB | SR_BL | SR_I3 | SR_I2 | SR_I1 | SR_I0;
+ env->fpscr = FPSCR_DN | FPSCR_RM_ZERO; /* CPU reset value according to SH4 manual */
set_float_rounding_mode(float_round_to_zero, &env->fp_status);
+ set_flush_to_zero(1, &env->fp_status);
#endif
- env->mmucr = 0;
+ set_default_nan_mode(1, &env->fp_status);
}
typedef struct {
@@ -265,7 +264,7 @@ void sh4_cpu_list(FILE *f, fprintf_function cpu_fprintf)
(*cpu_fprintf)(f, "%s\n", sh4_defs[i].name);
}
-static void cpu_sh4_register(CPUSH4State *env, const sh4_def_t *def)
+static void cpu_register(CPUSH4State *env, const sh4_def_t *def)
{
env->pvr = def->pvr;
env->prr = def->prr;
@@ -287,9 +286,8 @@ CPUSH4State *cpu_sh4_init(const char *cpu_model)
env->movcal_backup_tail = &(env->movcal_backup);
sh4_translate_init();
env->cpu_model_str = cpu_model;
- cpu_sh4_reset(env);
- cpu_sh4_register(env, def);
- tlb_flush(env, 1);
+ cpu_reset(env);
+ cpu_register(env, def);
qemu_init_vcpu(env);
return env;
}
@@ -334,7 +332,7 @@ static inline void gen_branch_slot(uint32_t delayed_pc, int t)
tcg_gen_movi_i32(cpu_delayed_pc, delayed_pc);
sr = tcg_temp_new();
tcg_gen_andi_i32(sr, cpu_sr, SR_T);
- tcg_gen_brcondi_i32(TCG_COND_NE, sr, t ? SR_T : 0, label);
+ tcg_gen_brcondi_i32(t ? TCG_COND_EQ:TCG_COND_NE, sr, 0, label);
tcg_gen_ori_i32(cpu_flags, cpu_flags, DELAY_SLOT_TRUE);
gen_set_label(label);
}
@@ -349,7 +347,7 @@ static void gen_conditional_jump(DisasContext * ctx,
l1 = gen_new_label();
sr = tcg_temp_new();
tcg_gen_andi_i32(sr, cpu_sr, SR_T);
- tcg_gen_brcondi_i32(TCG_COND_EQ, sr, SR_T, l1);
+ tcg_gen_brcondi_i32(TCG_COND_NE, sr, 0, l1);
gen_goto_tb(ctx, 0, ifnott);
gen_set_label(l1);
gen_goto_tb(ctx, 1, ift);
@@ -364,7 +362,7 @@ static void gen_delayed_conditional_jump(DisasContext * ctx)
l1 = gen_new_label();
ds = tcg_temp_new();
tcg_gen_andi_i32(ds, cpu_flags, DELAY_SLOT_TRUE);
- tcg_gen_brcondi_i32(TCG_COND_EQ, ds, DELAY_SLOT_TRUE, l1);
+ tcg_gen_brcondi_i32(TCG_COND_NE, ds, 0, l1);
gen_goto_tb(ctx, 1, ctx->pc + 2);
gen_set_label(l1);
tcg_gen_andi_i32(cpu_flags, cpu_flags, ~DELAY_SLOT_TRUE);
@@ -383,26 +381,26 @@ static inline void gen_clr_t(void)
static inline void gen_cmp(int cond, TCGv t0, TCGv t1)
{
- int label1 = gen_new_label();
- int label2 = gen_new_label();
- tcg_gen_brcond_i32(cond, t1, t0, label1);
- gen_clr_t();
- tcg_gen_br(label2);
- gen_set_label(label1);
- gen_set_t();
- gen_set_label(label2);
+ TCGv t;
+
+ t = tcg_temp_new();
+ tcg_gen_setcond_i32(cond, t, t1, t0);
+ tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T);
+ tcg_gen_or_i32(cpu_sr, cpu_sr, t);
+
+ tcg_temp_free(t);
}
static inline void gen_cmp_imm(int cond, TCGv t0, int32_t imm)
{
- int label1 = gen_new_label();
- int label2 = gen_new_label();
- tcg_gen_brcondi_i32(cond, t0, imm, label1);
- gen_clr_t();
- tcg_gen_br(label2);
- gen_set_label(label1);
- gen_set_t();
- gen_set_label(label2);
+ TCGv t;
+
+ t = tcg_temp_new();
+ tcg_gen_setcondi_i32(cond, t, t0, imm);
+ tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T);
+ tcg_gen_or_i32(cpu_sr, cpu_sr, t);
+
+ tcg_temp_free(t);
}
static inline void gen_store_flags(uint32_t flags)
@@ -469,27 +467,27 @@ static inline void gen_store_fpr64 (TCGv_i64 t, int reg)
#define CHECK_NOT_DELAY_SLOT \
if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) \
{ \
- tcg_gen_movi_i32(cpu_pc, ctx->pc-2); \
gen_helper_raise_slot_illegal_instruction(); \
ctx->bstate = BS_EXCP; \
return; \
}
-#define CHECK_PRIVILEGED \
- if (IS_USER(ctx)) { \
- tcg_gen_movi_i32(cpu_pc, ctx->pc); \
- gen_helper_raise_illegal_instruction(); \
- ctx->bstate = BS_EXCP; \
- return; \
+#define CHECK_PRIVILEGED \
+ if (IS_USER(ctx)) { \
+ if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { \
+ gen_helper_raise_slot_illegal_instruction(); \
+ } else { \
+ gen_helper_raise_illegal_instruction(); \
+ } \
+ ctx->bstate = BS_EXCP; \
+ return; \
}
#define CHECK_FPU_ENABLED \
if (ctx->flags & SR_FD) { \
if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { \
- tcg_gen_movi_i32(cpu_pc, ctx->pc-2); \
gen_helper_raise_slot_fpu_disable(); \
} else { \
- tcg_gen_movi_i32(cpu_pc, ctx->pc); \
gen_helper_raise_fpu_disable(); \
} \
ctx->bstate = BS_EXCP; \
@@ -818,24 +816,22 @@ static void _decode_opc(DisasContext * ctx)
return;
case 0x200c: /* cmp/str Rm,Rn */
{
- int label1 = gen_new_label();
- int label2 = gen_new_label();
- TCGv cmp1 = tcg_temp_local_new();
- TCGv cmp2 = tcg_temp_local_new();
+ TCGv cmp1 = tcg_temp_new();
+ TCGv cmp2 = tcg_temp_new();
+ tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T);
tcg_gen_xor_i32(cmp1, REG(B7_4), REG(B11_8));
tcg_gen_andi_i32(cmp2, cmp1, 0xff000000);
- tcg_gen_brcondi_i32(TCG_COND_EQ, cmp2, 0, label1);
+ tcg_gen_setcondi_i32(TCG_COND_EQ, cmp2, cmp2, 0);
+ tcg_gen_or_i32(cpu_sr, cpu_sr, cmp2);
tcg_gen_andi_i32(cmp2, cmp1, 0x00ff0000);
- tcg_gen_brcondi_i32(TCG_COND_EQ, cmp2, 0, label1);
+ tcg_gen_setcondi_i32(TCG_COND_EQ, cmp2, cmp2, 0);
+ tcg_gen_or_i32(cpu_sr, cpu_sr, cmp2);
tcg_gen_andi_i32(cmp2, cmp1, 0x0000ff00);
- tcg_gen_brcondi_i32(TCG_COND_EQ, cmp2, 0, label1);
+ tcg_gen_setcondi_i32(TCG_COND_EQ, cmp2, cmp2, 0);
+ tcg_gen_or_i32(cpu_sr, cpu_sr, cmp2);
tcg_gen_andi_i32(cmp2, cmp1, 0x000000ff);
- tcg_gen_brcondi_i32(TCG_COND_EQ, cmp2, 0, label1);
- tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T);
- tcg_gen_br(label2);
- gen_set_label(label1);
- tcg_gen_ori_i32(cpu_sr, cpu_sr, SR_T);
- gen_set_label(label2);
+ tcg_gen_setcondi_i32(TCG_COND_EQ, cmp2, cmp2, 0);
+ tcg_gen_or_i32(cpu_sr, cpu_sr, cmp2);
tcg_temp_free(cmp2);
tcg_temp_free(cmp1);
}
@@ -956,7 +952,21 @@ static void _decode_opc(DisasContext * ctx)
tcg_gen_neg_i32(REG(B11_8), REG(B7_4));
return;
case 0x600a: /* negc Rm,Rn */
- gen_helper_negc(REG(B11_8), REG(B7_4));
+ {
+ TCGv t0, t1;
+ t0 = tcg_temp_new();
+ tcg_gen_neg_i32(t0, REG(B7_4));
+ t1 = tcg_temp_new();
+ tcg_gen_andi_i32(t1, cpu_sr, SR_T);
+ tcg_gen_sub_i32(REG(B11_8), t0, t1);
+ tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T);
+ tcg_gen_setcond_i32(TCG_COND_GE, t1, REG(B11_8), t0);
+ tcg_gen_or_i32(cpu_sr, cpu_sr, t1);
+ tcg_gen_setcondi_i32(TCG_COND_GE, t1, t0, 0);
+ tcg_gen_or_i32(cpu_sr, cpu_sr, t1);
+ tcg_temp_free(t0);
+ tcg_temp_free(t1);
+ }
return;
case 0x6007: /* not Rm,Rn */
tcg_gen_not_i32(REG(B11_8), REG(B7_4));
@@ -1375,7 +1385,6 @@ static void _decode_opc(DisasContext * ctx)
{
TCGv imm;
CHECK_NOT_DELAY_SLOT
- tcg_gen_movi_i32(cpu_pc, ctx->pc);
imm = tcg_const_i32(B7_0);
gen_helper_trapa(imm);
tcg_temp_free(imm);
@@ -1695,14 +1704,12 @@ static void _decode_opc(DisasContext * ctx)
}
return;
case 0x4004: /* rotl Rn */
- gen_copy_bit_i32(cpu_sr, 0, REG(B11_8), 31);
- tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1);
- gen_copy_bit_i32(REG(B11_8), 0, cpu_sr, 0);
+ tcg_gen_rotli_i32(REG(B11_8), REG(B11_8), 1);
+ gen_copy_bit_i32(cpu_sr, 0, REG(B11_8), 0);
return;
case 0x4005: /* rotr Rn */
gen_copy_bit_i32(cpu_sr, 0, REG(B11_8), 0);
- tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1);
- gen_copy_bit_i32(REG(B11_8), 31, cpu_sr, 0);
+ tcg_gen_rotri_i32(REG(B11_8), REG(B11_8), 1);
return;
case 0x4000: /* shll Rn */
case 0x4020: /* shal Rn */
@@ -1854,13 +1861,40 @@ static void _decode_opc(DisasContext * ctx)
tcg_temp_free_i64(fp);
}
return;
+ case 0xf0ed: /* fipr FVm,FVn */
+ CHECK_FPU_ENABLED
+ if ((ctx->fpscr & FPSCR_PR) == 0) {
+ TCGv m, n;
+ m = tcg_const_i32((ctx->opcode >> 16) & 3);
+ n = tcg_const_i32((ctx->opcode >> 18) & 3);
+ gen_helper_fipr(m, n);
+ tcg_temp_free(m);
+ tcg_temp_free(n);
+ return;
+ }
+ break;
+ case 0xf0fd: /* ftrv XMTRX,FVn */
+ CHECK_FPU_ENABLED
+ if ((ctx->opcode & 0x0300) == 0x0100 &&
+ (ctx->fpscr & FPSCR_PR) == 0) {
+ TCGv n;
+ n = tcg_const_i32((ctx->opcode >> 18) & 3);
+ gen_helper_ftrv(n);
+ tcg_temp_free(n);
+ return;
+ }
+ break;
}
#if 0
fprintf(stderr, "unknown instruction 0x%04x at pc 0x%08x\n",
ctx->opcode, ctx->pc);
fflush(stderr);
#endif
- gen_helper_raise_illegal_instruction();
+ if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) {
+ gen_helper_raise_slot_illegal_instruction();
+ } else {
+ gen_helper_raise_illegal_instruction();
+ }
ctx->bstate = BS_EXCP;
}
@@ -1868,6 +1902,10 @@ static void decode_opc(DisasContext * ctx)
{
uint32_t old_flags = ctx->flags;
+ if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
+ tcg_gen_debug_insn_start(ctx->pc);
+ }
+
_decode_opc(ctx);
if (old_flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) {
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 58f9f82f52..b70970ac2a 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -857,65 +857,77 @@ void helper_fsqrtq(void)
QT0 = float128_sqrt(QT1, &env->fp_status);
}
-#define GEN_FCMP(name, size, reg1, reg2, FS, TRAP) \
+#define GEN_FCMP(name, size, reg1, reg2, FS, E) \
void glue(helper_, name) (void) \
{ \
- target_ulong new_fsr; \
- \
- env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ env->fsr &= FSR_FTT_NMASK; \
+ if (E && (glue(size, _is_any_nan)(reg1) || \
+ glue(size, _is_any_nan)(reg2)) && \
+ (env->fsr & FSR_NVM)) { \
+ env->fsr |= FSR_NVC; \
+ env->fsr |= FSR_FTT_IEEE_EXCP; \
+ raise_exception(TT_FP_EXCP); \
+ } \
switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) { \
case float_relation_unordered: \
- new_fsr = (FSR_FCC1 | FSR_FCC0) << FS; \
- if ((env->fsr & FSR_NVM) || TRAP) { \
- env->fsr |= new_fsr; \
+ if ((env->fsr & FSR_NVM)) { \
env->fsr |= FSR_NVC; \
env->fsr |= FSR_FTT_IEEE_EXCP; \
raise_exception(TT_FP_EXCP); \
} else { \
+ env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS; \
env->fsr |= FSR_NVA; \
} \
break; \
case float_relation_less: \
- new_fsr = FSR_FCC0 << FS; \
+ env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ env->fsr |= FSR_FCC0 << FS; \
break; \
case float_relation_greater: \
- new_fsr = FSR_FCC1 << FS; \
+ env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ env->fsr |= FSR_FCC1 << FS; \
break; \
default: \
- new_fsr = 0; \
+ env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
break; \
} \
- env->fsr |= new_fsr; \
}
-#define GEN_FCMPS(name, size, FS, TRAP) \
+#define GEN_FCMPS(name, size, FS, E) \
void glue(helper_, name)(float32 src1, float32 src2) \
{ \
- target_ulong new_fsr; \
- \
- env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ env->fsr &= FSR_FTT_NMASK; \
+ if (E && (glue(size, _is_any_nan)(src1) || \
+ glue(size, _is_any_nan)(src2)) && \
+ (env->fsr & FSR_NVM)) { \
+ env->fsr |= FSR_NVC; \
+ env->fsr |= FSR_FTT_IEEE_EXCP; \
+ raise_exception(TT_FP_EXCP); \
+ } \
switch (glue(size, _compare) (src1, src2, &env->fp_status)) { \
case float_relation_unordered: \
- new_fsr = (FSR_FCC1 | FSR_FCC0) << FS; \
- if ((env->fsr & FSR_NVM) || TRAP) { \
- env->fsr |= new_fsr; \
+ if ((env->fsr & FSR_NVM)) { \
env->fsr |= FSR_NVC; \
env->fsr |= FSR_FTT_IEEE_EXCP; \
raise_exception(TT_FP_EXCP); \
} else { \
+ env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS; \
env->fsr |= FSR_NVA; \
} \
break; \
case float_relation_less: \
- new_fsr = FSR_FCC0 << FS; \
+ env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ env->fsr |= FSR_FCC0 << FS; \
break; \
case float_relation_greater: \
- new_fsr = FSR_FCC1 << FS; \
+ env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ env->fsr |= FSR_FCC1 << FS; \
break; \
default: \
- new_fsr = 0; \
+ env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
break; \
} \
- env->fsr |= new_fsr; \
}
GEN_FCMPS(fcmps, float32, 0, 0);
diff --git a/tcg/README b/tcg/README
index a18a87ffcd..660012281f 100644
--- a/tcg/README
+++ b/tcg/README
@@ -285,6 +285,20 @@ the four high order bytes are set to zero.
Indicate that the value of t0 won't be used later. It is useful to
force dead code elimination.
+* deposit_i32/i64 dest, t1, t2, pos, len
+
+Deposit T2 as a bitfield into T1, placing the result in DEST.
+The bitfield is described by POS/LEN, which are immediate values:
+
+ LEN - the length of the bitfield
+ POS - the position of the first bit, counting from the LSB
+
+For example, pos=8, len=4 indicates a 4-bit field at bit 8.
+This operation would be equivalent to
+
+ dest = (t1 & ~0x0f00) | ((t2 << 8) & 0x0f00)
+
+
********* Conditional moves
* setcond_i32/i64 cond, dest, t1, t2
diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 1eb5605f8c..918e2f73cb 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -352,6 +352,9 @@ static inline void tcg_out_b(TCGContext *s, int cond, int32_t offset)
static inline void tcg_out_b_noaddr(TCGContext *s, int cond)
{
+ /* We pay attention here to not modify the branch target by skipping
+ the corresponding bytes. This ensure that caches and memory are
+ kept coherent during retranslation. */
#ifdef HOST_WORDS_BIGENDIAN
tcg_out8(s, (cond << 4) | 0x0a);
s->code_ptr += 3;
diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c
index e2e44f7d76..8dac7f72fd 100644
--- a/tcg/ia64/tcg-target.c
+++ b/tcg/ia64/tcg-target.c
@@ -871,6 +871,9 @@ static void tcg_out_br(TCGContext *s, int label_index)
{
TCGLabel *l = &s->labels[label_index];
+ /* We pay attention here to not modify the branch target by reading
+ the existing value and using it again. This ensure that caches and
+ memory are kept coherent during retranslation. */
tcg_out_bundle(s, mmB,
tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index 4e92a50e6f..e04b0dc32f 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -351,7 +351,9 @@ 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)
{
- /* We need to keep the offset unchanged for retranslation */
+ /* We pay attention here to not modify the branch target by reading
+ the existing value and using it again. This ensure that caches and
+ memory are kept coherent during retranslation. */
uint16_t offset = (uint16_t)(*(uint32_t *) s->code_ptr);
tcg_out_opc_imm(s, opc, rt, rs, offset);
diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
index 3ee0a58ed1..207a89fd97 100644
--- a/tcg/tcg-op.h
+++ b/tcg/tcg-op.h
@@ -254,6 +254,30 @@ static inline void tcg_gen_op5i_i64(TCGOpcode opc, TCGv_i64 arg1, TCGv_i64 arg2,
*gen_opparam_ptr++ = arg5;
}
+static inline void tcg_gen_op5ii_i32(TCGOpcode opc, TCGv_i32 arg1,
+ TCGv_i32 arg2, TCGv_i32 arg3,
+ TCGArg arg4, TCGArg arg5)
+{
+ *gen_opc_ptr++ = opc;
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg3);
+ *gen_opparam_ptr++ = arg4;
+ *gen_opparam_ptr++ = arg5;
+}
+
+static inline void tcg_gen_op5ii_i64(TCGOpcode opc, TCGv_i64 arg1,
+ TCGv_i64 arg2, TCGv_i64 arg3,
+ TCGArg arg4, TCGArg arg5)
+{
+ *gen_opc_ptr++ = opc;
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg3);
+ *gen_opparam_ptr++ = arg4;
+ *gen_opparam_ptr++ = arg5;
+}
+
static inline void tcg_gen_op6_i32(TCGOpcode opc, TCGv_i32 arg1, TCGv_i32 arg2,
TCGv_i32 arg3, TCGv_i32 arg4, TCGv_i32 arg5,
TCGv_i32 arg6)
@@ -2071,6 +2095,44 @@ static inline void tcg_gen_rotri_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
}
}
+static inline void tcg_gen_deposit_i32(TCGv_i32 ret, TCGv_i32 arg1,
+ TCGv_i32 arg2, unsigned int ofs,
+ unsigned int len)
+{
+#ifdef TCG_TARGET_HAS_deposit_i32
+ tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, arg1, arg2, ofs, len);
+#else
+ uint32_t mask = (1u << len) - 1;
+ TCGv_i32 t1 = tcg_temp_new_i32 ();
+
+ tcg_gen_andi_i32(t1, arg2, mask);
+ tcg_gen_shli_i32(t1, t1, ofs);
+ tcg_gen_andi_i32(ret, arg1, ~(mask << ofs));
+ tcg_gen_or_i32(ret, ret, t1);
+
+ tcg_temp_free_i32(t1);
+#endif
+}
+
+static inline void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1,
+ TCGv_i64 arg2, unsigned int ofs,
+ unsigned int len)
+{
+#ifdef TCG_TARGET_HAS_deposit_i64
+ tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, arg1, arg2, ofs, len);
+#else
+ uint64_t mask = (1ull << len) - 1;
+ TCGv_i64 t1 = tcg_temp_new_i64 ();
+
+ tcg_gen_andi_i64(t1, arg2, mask);
+ tcg_gen_shli_i64(t1, t1, ofs);
+ tcg_gen_andi_i64(ret, arg1, ~(mask << ofs));
+ tcg_gen_or_i64(ret, ret, t1);
+
+ tcg_temp_free_i64(t1);
+#endif
+}
+
/***************************************/
/* QEMU specific operations. Their type depend on the QEMU CPU
type. */
@@ -2384,6 +2446,7 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index)
#define tcg_gen_rotli_tl tcg_gen_rotli_i64
#define tcg_gen_rotr_tl tcg_gen_rotr_i64
#define tcg_gen_rotri_tl tcg_gen_rotri_i64
+#define tcg_gen_deposit_tl tcg_gen_deposit_i64
#define tcg_const_tl tcg_const_i64
#define tcg_const_local_tl tcg_const_local_i64
#else
@@ -2454,6 +2517,7 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index)
#define tcg_gen_rotli_tl tcg_gen_rotli_i32
#define tcg_gen_rotr_tl tcg_gen_rotr_i32
#define tcg_gen_rotri_tl tcg_gen_rotri_i32
+#define tcg_gen_deposit_tl tcg_gen_deposit_i32
#define tcg_const_tl tcg_const_i32
#define tcg_const_local_tl tcg_const_local_i32
#endif
diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h
index 2a98fed909..2c7ca1a450 100644
--- a/tcg/tcg-opc.h
+++ b/tcg/tcg-opc.h
@@ -78,6 +78,9 @@ DEF(sar_i32, 1, 2, 0, 0)
DEF(rotl_i32, 1, 2, 0, 0)
DEF(rotr_i32, 1, 2, 0, 0)
#endif
+#ifdef TCG_TARGET_HAS_deposit_i32
+DEF(deposit_i32, 1, 2, 2, 0)
+#endif
DEF(brcond_i32, 0, 2, 2, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
#if TCG_TARGET_REG_BITS == 32
@@ -168,6 +171,9 @@ DEF(sar_i64, 1, 2, 0, 0)
DEF(rotl_i64, 1, 2, 0, 0)
DEF(rotr_i64, 1, 2, 0, 0)
#endif
+#ifdef TCG_TARGET_HAS_deposit_i64
+DEF(deposit_i64, 1, 2, 2, 0)
+#endif
DEF(brcond_i64, 0, 2, 2, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
#ifdef TCG_TARGET_HAS_ext8s_i64
diff --git a/tests/Makefile b/tests/Makefile
index e43ec70b6d..9ded4b7349 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -7,7 +7,8 @@ QEMU=../i386-linux-user/qemu-i386
QEMU_X86_64=../x86_64-linux-user/qemu-x86_64
CC_X86_64=$(CC_I386) -m64
-CFLAGS=-Wall -O2 -g -fno-strict-aliasing -I..
+QEMU_INCLUDES += -I..
+CFLAGS=-Wall -O2 -g -fno-strict-aliasing
#CFLAGS+=-msse2
LDFLAGS=
diff --git a/tests/cris/check_abs.c b/tests/cris/check_abs.c
index 3966c87c78..9770a8d9ef 100644
--- a/tests/cris/check_abs.c
+++ b/tests/cris/check_abs.c
@@ -4,13 +4,14 @@
#include "sys.h"
#include "crisutils.h"
-extern inline int cris_abs(int n) {
+static inline int cris_abs(int n)
+{
int r;
asm ("abs\t%1, %0\n" : "=r" (r) : "r" (n));
return r;
}
-extern inline void
+static inline void
verify_abs(int val, int res,
const int n, const int z, const int v, const int c)
{
diff --git a/tests/cris/check_addc.c b/tests/cris/check_addc.c
index e4078555f8..facd1bea2d 100644
--- a/tests/cris/check_addc.c
+++ b/tests/cris/check_addc.c
@@ -4,7 +4,8 @@
#include "sys.h"
#include "crisutils.h"
-extern inline int cris_addc(int a, const int b) {
+static inline int cris_addc(int a, const int b)
+{
asm ("addc\t%1, %0\n" : "+r" (a) : "r" (b));
return a;
}
diff --git a/tests/cris/check_addcm.c b/tests/cris/check_addcm.c
index 9ffea29bd9..7928bc9999 100644
--- a/tests/cris/check_addcm.c
+++ b/tests/cris/check_addcm.c
@@ -5,13 +5,15 @@
#include "crisutils.h"
/* need to avoid acr as source here. */
-extern inline int cris_addc_m(int a, const int *b) {
+static inline int cris_addc_m(int a, const int *b)
+{
asm volatile ("addc [%1], %0\n" : "+r" (a) : "r" (b));
return a;
}
/* 'b' is a crisv32 constrain to avoid postinc with $acr. */
-extern inline int cris_addc_pi_m(int a, int **b) {
+static inline int cris_addc_pi_m(int a, int **b)
+{
asm volatile ("addc [%1+], %0\n" : "+r" (a), "+b" (*b));
return a;
}
diff --git a/tests/cris/check_bound.c b/tests/cris/check_bound.c
index 411d2ad56e..e8831754ec 100644
--- a/tests/cris/check_bound.c
+++ b/tests/cris/check_bound.c
@@ -4,19 +4,22 @@
#include "sys.h"
#include "crisutils.h"
-extern inline int cris_bound_b(int v, int b) {
+static inline int cris_bound_b(int v, int b)
+{
int r = v;
asm ("bound.b\t%1, %0\n" : "+r" (r) : "ri" (b));
return r;
}
-extern inline int cris_bound_w(int v, int b) {
+static inline int cris_bound_w(int v, int b)
+{
int r = v;
asm ("bound.w\t%1, %0\n" : "+r" (r) : "ri" (b));
return r;
}
-extern inline int cris_bound_d(int v, int b) {
+static inline int cris_bound_d(int v, int b)
+{
int r = v;
asm ("bound.d\t%1, %0\n" : "+r" (r) : "ri" (b));
return r;
diff --git a/tests/cris/check_ftag.c b/tests/cris/check_ftag.c
index 40d1507a87..908773a38a 100644
--- a/tests/cris/check_ftag.c
+++ b/tests/cris/check_ftag.c
@@ -4,19 +4,23 @@
#include "sys.h"
#include "crisutils.h"
-extern inline void cris_ftag_i(unsigned int x) {
+static inline void cris_ftag_i(unsigned int x)
+{
register unsigned int v asm("$r10") = x;
asm ("ftagi\t[%0]\n" : : "r" (v) );
}
-extern inline void cris_ftag_d(unsigned int x) {
+static inline void cris_ftag_d(unsigned int x)
+{
register unsigned int v asm("$r10") = x;
asm ("ftagd\t[%0]\n" : : "r" (v) );
}
-extern inline void cris_fidx_i(unsigned int x) {
+static inline void cris_fidx_i(unsigned int x)
+{
register unsigned int v asm("$r10") = x;
asm ("fidxi\t[%0]\n" : : "r" (v) );
}
-extern inline void cris_fidx_d(unsigned int x) {
+static inline void cris_fidx_d(unsigned int x)
+{
register unsigned int v asm("$r10") = x;
asm ("fidxd\t[%0]\n" : : "r" (v) );
}
diff --git a/tests/cris/check_int64.c b/tests/cris/check_int64.c
index 99ca6f1158..fc600176e2 100644
--- a/tests/cris/check_int64.c
+++ b/tests/cris/check_int64.c
@@ -5,11 +5,13 @@
#include "crisutils.h"
-extern inline int64_t add64(const int64_t a, const int64_t b) {
+static inline int64_t add64(const int64_t a, const int64_t b)
+{
return a + b;
}
-extern inline int64_t sub64(const int64_t a, const int64_t b) {
+static inline int64_t sub64(const int64_t a, const int64_t b)
+{
return a - b;
}
diff --git a/tests/cris/check_lz.c b/tests/cris/check_lz.c
index 7b30a265ad..69c2e6d4ec 100644
--- a/tests/cris/check_lz.c
+++ b/tests/cris/check_lz.c
@@ -3,7 +3,7 @@
#include <stdint.h>
#include "sys.h"
-extern inline int cris_lz(int x)
+static inline int cris_lz(int x)
{
int r;
asm ("lz\t%1, %0\n" : "=r" (r) : "r" (x));
diff --git a/tests/cris/check_swap.c b/tests/cris/check_swap.c
index 824a685517..f851cbcef1 100644
--- a/tests/cris/check_swap.c
+++ b/tests/cris/check_swap.c
@@ -9,7 +9,7 @@
#define B 2
#define R 1
-extern inline int cris_swap(const int mode, int x)
+static inline int cris_swap(const int mode, int x)
{
switch (mode)
{
diff --git a/tests/cris/crisutils.h b/tests/cris/crisutils.h
index 7d1ea86f73..29b71cd7b9 100644
--- a/tests/cris/crisutils.h
+++ b/tests/cris/crisutils.h
@@ -10,57 +10,57 @@ void _err(void) {
_fail(tst_cc_loc);
}
-extern inline void cris_tst_cc_n1(void)
+static inline void cris_tst_cc_n1(void)
{
asm volatile ("bpl _err\n"
"nop\n");
}
-extern inline void cris_tst_cc_n0(void)
+static inline void cris_tst_cc_n0(void)
{
asm volatile ("bmi _err\n"
"nop\n");
}
-extern inline void cris_tst_cc_z1(void)
+static inline void cris_tst_cc_z1(void)
{
asm volatile ("bne _err\n"
"nop\n");
}
-extern inline void cris_tst_cc_z0(void)
+static inline void cris_tst_cc_z0(void)
{
asm volatile ("beq _err\n"
"nop\n");
}
-extern inline void cris_tst_cc_v1(void)
+static inline void cris_tst_cc_v1(void)
{
asm volatile ("bvc _err\n"
"nop\n");
}
-extern inline void cris_tst_cc_v0(void)
+static inline void cris_tst_cc_v0(void)
{
asm volatile ("bvs _err\n"
"nop\n");
}
-extern inline void cris_tst_cc_c1(void)
+static inline void cris_tst_cc_c1(void)
{
asm volatile ("bcc _err\n"
"nop\n");
}
-extern inline void cris_tst_cc_c0(void)
+static inline void cris_tst_cc_c0(void)
{
asm volatile ("bcs _err\n"
"nop\n");
}
-extern inline void cris_tst_mov_cc(int n, int z)
+static inline void cris_tst_mov_cc(int n, int z)
{
if (n) cris_tst_cc_n1(); else cris_tst_cc_n0();
if (z) cris_tst_cc_z1(); else cris_tst_cc_z0();
asm volatile ("" : : "g" (_err));
}
-extern inline void cris_tst_cc(const int n, const int z,
+static inline void cris_tst_cc(const int n, const int z,
const int v, const int c)
{
if (n) cris_tst_cc_n1(); else cris_tst_cc_n0();
diff --git a/tests/hello-i386.c b/tests/hello-i386.c
index e00245d3fe..86afc34fb1 100644
--- a/tests/hello-i386.c
+++ b/tests/hello-i386.c
@@ -1,6 +1,6 @@
#include <asm/unistd.h>
-extern inline volatile void exit(int status)
+static inline volatile void exit(int status)
{
int __res;
__asm__ volatile ("movl %%ecx,%%ebx\n"\
@@ -8,7 +8,7 @@ extern inline volatile void exit(int status)
: "=a" (__res) : "0" (__NR_exit),"c" ((long)(status)));
}
-extern inline int write(int fd, const char * buf, int len)
+static inline int write(int fd, const char * buf, int len)
{
int status;
__asm__ volatile ("pushl %%ebx\n"\
diff --git a/ui/vnc-auth-sasl.c b/ui/vnc-auth-sasl.c
index a51ddc8a18..17a621a2ba 100644
--- a/ui/vnc-auth-sasl.c
+++ b/ui/vnc-auth-sasl.c
@@ -444,22 +444,19 @@ static int protocol_client_auth_sasl_mechname(VncState *vs, uint8_t *data, size_
if (vs->sasl.mechlist[len] != '\0' &&
vs->sasl.mechlist[len] != ',') {
VNC_DEBUG("One %d", vs->sasl.mechlist[len]);
- vnc_client_error(vs);
- return -1;
+ goto fail;
}
} else {
char *offset = strstr(vs->sasl.mechlist, mechname);
VNC_DEBUG("Two %p\n", offset);
if (!offset) {
- vnc_client_error(vs);
- return -1;
+ goto fail;
}
VNC_DEBUG("Two '%s'\n", offset);
if (offset[-1] != ',' ||
(offset[len] != '\0'&&
offset[len] != ',')) {
- vnc_client_error(vs);
- return -1;
+ goto fail;
}
}
@@ -469,6 +466,11 @@ static int protocol_client_auth_sasl_mechname(VncState *vs, uint8_t *data, size_
VNC_DEBUG("Validated mechname '%s'\n", mechname);
vnc_read_when(vs, protocol_client_auth_sasl_start_len, 4);
return 0;
+
+ fail:
+ vnc_client_error(vs);
+ free(mechname);
+ return -1;
}
static int protocol_client_auth_sasl_mechname_len(VncState *vs, uint8_t *data, size_t len)