diff options
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/ @@ -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; @@ -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 @@ -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) @@ -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) @@ -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[] = { >64120_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(>64120_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, @@ -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); @@ -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 @@ -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 @@ -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; @@ -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) |