From 399bf6bec92db4d144bb684d7c4f8174e019cb5c Mon Sep 17 00:00:00 2001 From: blueswir1 Date: Wed, 25 Jun 2008 18:31:21 +0000 Subject: Reset correct channel aka NetBSD boot fix git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4790 c046a42c-6fe2-441c-8c8c-71466251a162 --- hw/slavio_serial.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/slavio_serial.c b/hw/slavio_serial.c index 1ef3c119e..97891cc52 100644 --- a/hw/slavio_serial.c +++ b/hw/slavio_serial.c @@ -529,10 +529,10 @@ static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, default: break; case MINTR_RST_B: - slavio_serial_reset_chn(&serial->chn[1]); + slavio_serial_reset_chn(&serial->chn[0]); return; case MINTR_RST_A: - slavio_serial_reset_chn(&serial->chn[0]); + slavio_serial_reset_chn(&serial->chn[1]); return; case MINTR_RST_ALL: slavio_serial_reset(serial); -- cgit v1.2.3 From a214c59855bc9d5dd509588160361f1cb0b4e8d8 Mon Sep 17 00:00:00 2001 From: blueswir1 Date: Wed, 25 Jun 2008 19:59:53 +0000 Subject: Suppress OpenBSD warning messages for leftover fifo bytes git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4791 c046a42c-6fe2-441c-8c8c-71466251a162 --- hw/esp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/esp.c b/hw/esp.c index 1843fb895..0a8b3e4d8 100644 --- a/hw/esp.c +++ b/hw/esp.c @@ -496,6 +496,7 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) //s->ti_size = 0; s->rregs[ESP_RINTR] = INTR_FC; s->rregs[ESP_RSEQ] = 0; + s->rregs[ESP_RFLAGS] = 0; break; case CMD_RESET: DPRINTF("Chip reset (%2.2x)\n", val); -- cgit v1.2.3 From 0c58ac1c76603ce639e419cedd16cfcdcd813045 Mon Sep 17 00:00:00 2001 From: malc Date: Wed, 25 Jun 2008 21:04:05 +0000 Subject: Change the way audio is configured Instead of having separate option for each card and driver use --audio-drv-list and --audio-card-list options. Under Linux it allows to set the default(first probed) driver to something other than OSS. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4792 c046a42c-6fe2-441c-8c8c-71466251a162 --- audio/audio.c | 22 +--------- configure | 129 ++++++++++++++++------------------------------------------ qemu-doc.texi | 4 +- 3 files changed, 37 insertions(+), 118 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 46b39df76..84eaa8359 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -38,27 +38,7 @@ #define SW_NAME(sw) (sw)->name ? (sw)->name : "unknown" static struct audio_driver *drvtab[] = { -#ifdef CONFIG_OSS - &oss_audio_driver, -#endif -#ifdef CONFIG_ALSA - &alsa_audio_driver, -#endif -#ifdef CONFIG_COREAUDIO - &coreaudio_audio_driver, -#endif -#ifdef CONFIG_DSOUND - &dsound_audio_driver, -#endif -#ifdef CONFIG_FMOD - &fmod_audio_driver, -#endif -#ifdef CONFIG_SDL - &sdl_audio_driver, -#endif -#ifdef CONFIG_ESD - &esd_audio_driver, -#endif + AUDIO_DRIVERS &no_audio_driver, &wav_audio_driver }; diff --git a/configure b/configure index efecd20c4..05ee62c2a 100755 --- a/configure +++ b/configure @@ -24,6 +24,8 @@ cross_prefix="" cc="gcc" gcc3_search="yes" gcc3_list="gcc-3.4.6 gcc-3.4 gcc34 gcc-3.3.6 gcc-3.3 gcc33 gcc-3.2 gcc32" +audio_drv_list="" +audio_card_list="" host_cc="gcc" ar="ar" make="make" @@ -87,16 +89,6 @@ mingw32="no" EXESUF="" gdbstub="yes" slirp="yes" -adlib="no" -ac97="no" -gus="no" -cs4231a="no" -oss="no" -dsound="no" -coreaudio="no" -alsa="no" -esd="no" -fmod="no" fmod_lib="" fmod_inc="" vnc_tls="yes" @@ -133,32 +125,32 @@ if [ "$cpu" = "i386" ] ; then fi ;; GNU/kFreeBSD) -oss="yes" +audio_drv_list="oss" if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then kqemu="yes" fi ;; FreeBSD) bsd="yes" -oss="yes" +audio_drv_list="oss" if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then kqemu="yes" fi ;; NetBSD) bsd="yes" -oss="yes" +audio_drv_list="oss" ;; OpenBSD) bsd="yes" -oss="yes" +audio_drv_list="oss" ;; Darwin) bsd="yes" darwin="yes" darwin_user="yes" cocoa="yes" -coreaudio="yes" +audio_drv_list="coreaudio" OS_CFLAGS="-mdynamic-no-pic" OS_LDFLAGS="-framework CoreFoundation -framework IOKit" ;; @@ -191,11 +183,11 @@ SunOS) fi fi if test -f /usr/include/sys/soundcard.h ; then - oss=yes + audio_drv_list="oss" fi ;; *) -oss="yes" +audio_drv_list="oss" linux="yes" linux_user="yes" if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then @@ -264,17 +256,11 @@ for opt do ;; --disable-sdl) sdl="no" ;; - --enable-coreaudio) coreaudio="yes" - ;; - --enable-alsa) alsa="yes" - ;; - --enable-esd) esd="yes" - ;; - --enable-dsound) dsound="yes" + --fmod-lib=*) fmod_lib="$optarg" ;; - --enable-fmod) fmod="yes" + --audio-card-list=*) audio_card_list="$optarg" ;; - --fmod-lib=*) fmod_lib="$optarg" + --audio-drv-list=*) audio_drv_list="$optarg" ;; --fmod-inc=*) fmod_inc="$optarg" ;; @@ -284,21 +270,13 @@ for opt do ;; --disable-slirp) slirp="no" ;; - --enable-adlib) adlib="yes" - ;; - --enable-ac97) ac97="yes" - ;; - --enable-gus) gus="yes" - ;; - --enable-cs4231a) cs4231a="yes" - ;; --disable-kqemu) kqemu="no" ;; --disable-brlapi) brlapi="no" ;; --enable-profiler) profiler="yes" ;; - --enable-cocoa) cocoa="yes" ; coreaudio="yes" ; sdl="no" + --enable-cocoa) cocoa="yes" ; sdl="no" ; ;; --disable-gfx-check) check_gfx="no" ;; @@ -422,15 +400,8 @@ echo " --disable-werror disable compilation abort on warning" echo " --disable-sdl disable SDL" echo " --enable-cocoa enable COCOA (Mac OS X only)" echo " --enable-mingw32 enable Win32 cross compilation with mingw32" -echo " --enable-adlib enable Adlib emulation" -echo " --enable-ac97 enable AC97 emulation" -echo " --enable-gus enable Gravis Ultrasound emulation" -echo " --enable-cs4231a enable CS4231A emulation" -echo " --enable-coreaudio enable Coreaudio audio driver" -echo " --enable-alsa enable ALSA audio driver" -echo " --enable-esd enable EsoundD audio driver" -echo " --enable-fmod enable FMOD audio driver" -echo " --enable-dsound enable DirectSound audio driver" +echo " --audio-drv-list set audio drivers list" +echo " --audio-card-list set list of additional emulated audio cards" echo " --enable-mixemu enable mixer emulation" echo " --disable-brlapi disable BrlAPI" echo " --disable-vnc-tls disable TLS encryption for VNC server" @@ -721,7 +692,7 @@ else # Make sure to disable cocoa if sdl was set if test "$sdl" = "yes" ; then cocoa="no" - coreaudio="no" + audio_drv_list="echo $audio_drv_list | sed s,coreaudio,,g" fi fi # -z $sdl @@ -835,14 +806,8 @@ if test "$sdl" != "no" ; then fi echo "curses support $curses" echo "mingw32 support $mingw32" -echo "Adlib support $adlib" -echo "AC97 support $ac97" -echo "GUS support $gus" -echo "CS4231A support $cs4231a" -echo "CoreAudio support $coreaudio" -echo "ALSA support $alsa" -echo "EsounD support $esd" -echo "DSound support $dsound" +echo "Audio drivers $audio_drv_list" +echo "Extra audio cards $audio_card_list" echo "Mixer emulation $mixemu" if test "$fmod" = "yes"; then if test -z $fmod_lib || test -z $fmod_inc; then @@ -1036,52 +1001,26 @@ if test "$slirp" = "yes" ; then echo "CONFIG_SLIRP=yes" >> $config_mak echo "#define CONFIG_SLIRP 1" >> $config_h fi -if test "$adlib" = "yes" ; then - echo "CONFIG_ADLIB=yes" >> $config_mak - echo "#define CONFIG_ADLIB 1" >> $config_h -fi -if test "$ac97" = "yes" ; then - echo "CONFIG_AC97=yes" >> $config_mak - echo "#define CONFIG_AC97 1" >> $config_h -fi -if test "$gus" = "yes" ; then - echo "CONFIG_GUS=yes" >> $config_mak - echo "#define CONFIG_GUS 1" >> $config_h -fi -if test "$cs4231a" = "yes" ; then - echo "CONFIG_CS4231A=yes" >> $config_mak - echo "#define CONFIG_CS4231A 1" >> $config_h -fi -if test "$oss" = "yes" ; then - echo "CONFIG_OSS=yes" >> $config_mak - echo "#define CONFIG_OSS 1" >> $config_h -fi -if test "$coreaudio" = "yes" ; then - echo "CONFIG_COREAUDIO=yes" >> $config_mak - echo "#define CONFIG_COREAUDIO 1" >> $config_h -fi -if test "$alsa" = "yes" ; then - echo "CONFIG_ALSA=yes" >> $config_mak - echo "#define CONFIG_ALSA 1" >> $config_h -fi -if test "$esd" = "yes" ; then - echo "CONFIG_ESD=yes" >> $config_mak - echo "#define CONFIG_ESD 1" >> $config_h -fi -if test "$dsound" = "yes" ; then - echo "CONFIG_DSOUND=yes" >> $config_mak - echo "#define CONFIG_DSOUND 1" >> $config_h -fi +for card in $audio_card_list; do + def=CONFIG_`echo $card | tr [:lower:] [:upper:]` + echo "$def=yes" >> $config_mak + echo "#define $def 1" >> $config_h +done +echo "#define AUDIO_DRIVERS \\" >> $config_h +for drv in $audio_drv_list; do + echo " &${drv}_audio_driver, \\" >>$config_h + def=CONFIG_`echo $drv | tr [:lower:] [:upper:]` + echo "$def=yes" >> $config_mak + if test "$drv" == "fmod"; then + echo "CONFIG_FMOD_LIB=$fmod_lib" >> $config_mak + echo "CONFIG_FMOD_INC=$fmod_inc" >> $config_mak + fi +done +echo "" >>$config_h if test "$mixemu" = "yes" ; then echo "CONFIG_MIXEMU=yes" >> $config_mak echo "#define CONFIG_MIXEMU 1" >> $config_h fi -if test "$fmod" = "yes" ; then - echo "CONFIG_FMOD=yes" >> $config_mak - echo "CONFIG_FMOD_LIB=$fmod_lib" >> $config_mak - echo "CONFIG_FMOD_INC=$fmod_inc" >> $config_mak - echo "#define CONFIG_FMOD 1" >> $config_h -fi if test "$vnc_tls" = "yes" ; then echo "CONFIG_VNC_TLS=yes" >> $config_mak echo "CONFIG_VNC_TLS_CFLAGS=$vnc_tls_cflags" >> $config_mak diff --git a/qemu-doc.texi b/qemu-doc.texi index d01a04b93..80c172c27 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -183,8 +183,8 @@ PCI UHCI USB controller and a virtual USB hub. SMP is supported with up to 255 CPUs. Note that adlib, ac97, gus and cs4231a are only available when QEMU -was configured with --enable-adlib, --enable-ac97, --enable-gus or ---enable-cs4231a respectively. +was configured with --audio-card-list option containing the name(s) of +required cards. QEMU uses the PC BIOS from the Bochs project and the Plex86/Bochs LGPL VGA BIOS. -- cgit v1.2.3 From a37ee56cb7f2094a65fff14ed5d4ff325652b802 Mon Sep 17 00:00:00 2001 From: blueswir1 Date: Thu, 26 Jun 2008 18:43:24 +0000 Subject: Fix bogus format, reading uninitialised memory (original patch by Julian Seward) git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4793 c046a42c-6fe2-441c-8c8c-71466251a162 --- target-sparc/helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-sparc/helper.c b/target-sparc/helper.c index a3e50bd4c..1cfe170de 100644 --- a/target-sparc/helper.c +++ b/target-sparc/helper.c @@ -1603,7 +1603,7 @@ void cpu_dump_state(CPUState *env, FILE *f, for (i = 0; i < 32; i++) { if ((i & 3) == 0) cpu_fprintf(f, "%%f%02d:", i); - cpu_fprintf(f, " %016lf", env->fpr[i]); + cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]); if ((i & 3) == 3) cpu_fprintf(f, "\n"); } -- cgit v1.2.3 From b5dc7732e1cc2fb549e48b7b5d664f2c79628e2e Mon Sep 17 00:00:00 2001 From: ths Date: Fri, 27 Jun 2008 10:02:35 +0000 Subject: More efficient target register / TC accesses. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4794 c046a42c-6fe2-441c-8c8c-71466251a162 --- cpu-exec.c | 2 +- gdbstub.c | 20 +-- hw/mips_mipssim.c | 4 +- hw/mips_r4k.c | 2 +- linux-user/main.c | 26 ++-- linux-user/mips/target_signal.h | 2 +- linux-user/mips64/target_signal.h | 2 +- linux-user/mipsn32/target_signal.h | 2 +- linux-user/signal.c | 34 ++--- linux-user/syscall.c | 2 +- monitor.c | 2 +- target-mips/cpu.h | 77 ++++++----- target-mips/helper.c | 30 ++--- target-mips/op_helper.c | 268 ++++++++++++++++++++++++++----------- target-mips/translate.c | 98 +++++--------- target-mips/translate_init.c | 2 - 16 files changed, 327 insertions(+), 246 deletions(-) diff --git a/cpu-exec.c b/cpu-exec.c index b8c208b41..9d00cffb5 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -197,7 +197,7 @@ static inline TranslationBlock *tb_find_fast(void) #elif defined(TARGET_MIPS) flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK); cs_base = 0; - pc = env->PC[env->current_tc]; + pc = env->active_tc.PC; #elif defined(TARGET_M68K) flags = (env->fpcr & M68K_FPCR_PREC) /* Bit 6 */ | (env->sr & SR_S) /* Bit 13 */ diff --git a/gdbstub.c b/gdbstub.c index d4ca6f3c9..3f062be9f 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -704,17 +704,17 @@ static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf) ptr = mem_buf; for (i = 0; i < 32; i++) { - *(target_ulong *)ptr = tswapl(env->gpr[env->current_tc][i]); + *(target_ulong *)ptr = tswapl(env->active_tc.gpr[i]); ptr += sizeof(target_ulong); } *(target_ulong *)ptr = (int32_t)tswap32(env->CP0_Status); ptr += sizeof(target_ulong); - *(target_ulong *)ptr = tswapl(env->LO[env->current_tc][0]); + *(target_ulong *)ptr = tswapl(env->active_tc.LO[0]); ptr += sizeof(target_ulong); - *(target_ulong *)ptr = tswapl(env->HI[env->current_tc][0]); + *(target_ulong *)ptr = tswapl(env->active_tc.HI[0]); ptr += sizeof(target_ulong); *(target_ulong *)ptr = tswapl(env->CP0_BadVAddr); @@ -723,7 +723,7 @@ static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf) *(target_ulong *)ptr = (int32_t)tswap32(env->CP0_Cause); ptr += sizeof(target_ulong); - *(target_ulong *)ptr = tswapl(env->PC[env->current_tc]); + *(target_ulong *)ptr = tswapl(env->active_tc.PC); ptr += sizeof(target_ulong); if (env->CP0_Config1 & (1 << CP0C1_FP)) @@ -781,17 +781,17 @@ static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size) ptr = mem_buf; for (i = 0; i < 32; i++) { - env->gpr[env->current_tc][i] = tswapl(*(target_ulong *)ptr); + env->active_tc.gpr[i] = tswapl(*(target_ulong *)ptr); ptr += sizeof(target_ulong); } env->CP0_Status = tswapl(*(target_ulong *)ptr); ptr += sizeof(target_ulong); - env->LO[env->current_tc][0] = tswapl(*(target_ulong *)ptr); + env->active_tc.LO[0] = tswapl(*(target_ulong *)ptr); ptr += sizeof(target_ulong); - env->HI[env->current_tc][0] = tswapl(*(target_ulong *)ptr); + env->active_tc.HI[0] = tswapl(*(target_ulong *)ptr); ptr += sizeof(target_ulong); env->CP0_BadVAddr = tswapl(*(target_ulong *)ptr); @@ -800,7 +800,7 @@ static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size) env->CP0_Cause = tswapl(*(target_ulong *)ptr); ptr += sizeof(target_ulong); - env->PC[env->current_tc] = tswapl(*(target_ulong *)ptr); + env->active_tc.PC = tswapl(*(target_ulong *)ptr); ptr += sizeof(target_ulong); if (env->CP0_Config1 & (1 << CP0C1_FP)) @@ -1003,7 +1003,7 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf) #elif defined (TARGET_SH4) env->pc = addr; #elif defined (TARGET_MIPS) - env->PC[env->current_tc] = addr; + env->active_tc.PC = addr; #elif defined (TARGET_CRIS) env->pc = addr; #endif @@ -1040,7 +1040,7 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf) #elif defined (TARGET_SH4) env->pc = addr; #elif defined (TARGET_MIPS) - env->PC[env->current_tc] = addr; + env->active_tc.PC = addr; #elif defined (TARGET_CRIS) env->pc = addr; #endif diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c index e29d8af46..af09d9599 100644 --- a/hw/mips_mipssim.c +++ b/hw/mips_mipssim.c @@ -65,7 +65,7 @@ static void load_kernel (CPUState *env) if (kernel_size >= 0) { if ((entry & ~0x7fffffffULL) == 0x80000000) entry = (int32_t)entry; - env->PC[env->current_tc] = entry; + env->active_tc.PC = entry; } else { fprintf(stderr, "qemu: could not load kernel '%s'\n", loaderparams.kernel_filename); @@ -152,7 +152,7 @@ mips_mipssim_init (ram_addr_t ram_size, int vga_ram_size, cpu_register_physical_memory(0x1fc00000LL, bios_size, bios_offset | IO_MEM_ROM); /* We have a boot vector start address. */ - env->PC[env->current_tc] = (target_long)(int32_t)0xbfc00000; + env->active_tc.PC = (target_long)(int32_t)0xbfc00000; } if (kernel_filename) { diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c index 66ae13561..4540cbf45 100644 --- a/hw/mips_r4k.c +++ b/hw/mips_r4k.c @@ -87,7 +87,7 @@ static void load_kernel (CPUState *env) if (kernel_size >= 0) { if ((entry & ~0x7fffffffULL) == 0x80000000) entry = (int32_t)entry; - env->PC[env->current_tc] = entry; + env->active_tc.PC = entry; } else { fprintf(stderr, "qemu: could not load kernel '%s'\n", loaderparams.kernel_filename); diff --git a/linux-user/main.c b/linux-user/main.c index a4ffea3fd..060ef823e 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -1779,8 +1779,8 @@ void cpu_loop(CPUMIPSState *env) trapnr = cpu_mips_exec(env); switch(trapnr) { case EXCP_SYSCALL: - syscall_num = env->gpr[env->current_tc][2] - 4000; - env->PC[env->current_tc] += 4; + syscall_num = env->active_tc.gpr[2] - 4000; + env->active_tc.PC += 4; if (syscall_num >= sizeof(mips_syscall_args)) { ret = -ENOSYS; } else { @@ -1789,7 +1789,7 @@ void cpu_loop(CPUMIPSState *env) abi_ulong arg5 = 0, arg6 = 0, arg7 = 0, arg8 = 0; nb_args = mips_syscall_args[syscall_num]; - sp_reg = env->gpr[env->current_tc][29]; + sp_reg = env->active_tc.gpr[29]; switch (nb_args) { /* these arguments are taken from the stack */ /* FIXME - what to do if get_user() fails? */ @@ -1800,20 +1800,20 @@ void cpu_loop(CPUMIPSState *env) default: break; } - ret = do_syscall(env, env->gpr[env->current_tc][2], - env->gpr[env->current_tc][4], - env->gpr[env->current_tc][5], - env->gpr[env->current_tc][6], - env->gpr[env->current_tc][7], + ret = do_syscall(env, env->active_tc.gpr[2], + env->active_tc.gpr[4], + env->active_tc.gpr[5], + env->active_tc.gpr[6], + env->active_tc.gpr[7], arg5, arg6/*, arg7, arg8*/); } if ((unsigned int)ret >= (unsigned int)(-1133)) { - env->gpr[env->current_tc][7] = 1; /* error flag */ + env->active_tc.gpr[7] = 1; /* error flag */ ret = -ret; } else { - env->gpr[env->current_tc][7] = 0; /* error flag */ + env->active_tc.gpr[7] = 0; /* error flag */ } - env->gpr[env->current_tc][2] = ret; + env->active_tc.gpr[2] = ret; break; case EXCP_TLBL: case EXCP_TLBS: @@ -2566,9 +2566,9 @@ int main(int argc, char **argv) int i; for(i = 0; i < 32; i++) { - env->gpr[env->current_tc][i] = regs->regs[i]; + env->active_tc.gpr[i] = regs->regs[i]; } - env->PC[env->current_tc] = regs->cp0_epc; + env->active_tc.PC = regs->cp0_epc; } #elif defined(TARGET_SH4) { diff --git a/linux-user/mips/target_signal.h b/linux-user/mips/target_signal.h index f3ef38d24..6e1dc8b6e 100644 --- a/linux-user/mips/target_signal.h +++ b/linux-user/mips/target_signal.h @@ -23,7 +23,7 @@ typedef struct target_sigaltstack { static inline abi_ulong get_sp_from_cpustate(CPUMIPSState *state) { - return state->gpr[state->current_tc][29]; + return state->active_tc.gpr[29]; } #endif /* TARGET_SIGNAL_H */ diff --git a/linux-user/mips64/target_signal.h b/linux-user/mips64/target_signal.h index f3ef38d24..6e1dc8b6e 100644 --- a/linux-user/mips64/target_signal.h +++ b/linux-user/mips64/target_signal.h @@ -23,7 +23,7 @@ typedef struct target_sigaltstack { static inline abi_ulong get_sp_from_cpustate(CPUMIPSState *state) { - return state->gpr[state->current_tc][29]; + return state->active_tc.gpr[29]; } #endif /* TARGET_SIGNAL_H */ diff --git a/linux-user/mipsn32/target_signal.h b/linux-user/mipsn32/target_signal.h index 5da84112b..ff20d9e33 100644 --- a/linux-user/mipsn32/target_signal.h +++ b/linux-user/mipsn32/target_signal.h @@ -23,7 +23,7 @@ typedef struct target_sigaltstack { static inline target_ulong get_sp_from_cpustate(CPUMIPSState *state) { - return state->gpr[state->current_tc][29]; + return state->active_tc.gpr[29]; } #endif /* TARGET_SIGNAL_H */ diff --git a/linux-user/signal.c b/linux-user/signal.c index 623a5e31c..599b8af2c 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -2290,10 +2290,10 @@ setup_sigcontext(CPUState *regs, struct target_sigcontext *sc) { int err = 0; - err |= __put_user(regs->PC[regs->current_tc], &sc->sc_pc); + err |= __put_user(regs->active_tc.PC, &sc->sc_pc); -#define save_gp_reg(i) do { \ - err |= __put_user(regs->gpr[regs->current_tc][i], &sc->sc_regs[i]); \ +#define save_gp_reg(i) do { \ + err |= __put_user(regs->active_tc.gpr[i], &sc->sc_regs[i]); \ } while(0) __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2); save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6); @@ -2306,8 +2306,8 @@ setup_sigcontext(CPUState *regs, struct target_sigcontext *sc) save_gp_reg(31); #undef save_gp_reg - err |= __put_user(regs->HI[regs->current_tc][0], &sc->sc_mdhi); - err |= __put_user(regs->LO[regs->current_tc][0], &sc->sc_mdlo); + err |= __put_user(regs->active_tc.HI[0], &sc->sc_mdhi); + err |= __put_user(regs->active_tc.LO[0], &sc->sc_mdlo); /* Not used yet, but might be useful if we ever have DSP suppport */ #if 0 @@ -2367,11 +2367,11 @@ restore_sigcontext(CPUState *regs, struct target_sigcontext *sc) err |= __get_user(regs->CP0_EPC, &sc->sc_pc); - err |= __get_user(regs->HI[regs->current_tc][0], &sc->sc_mdhi); - err |= __get_user(regs->LO[regs->current_tc][0], &sc->sc_mdlo); + err |= __get_user(regs->active_tc.HI[0], &sc->sc_mdhi); + err |= __get_user(regs->active_tc.LO[0], &sc->sc_mdlo); #define restore_gp_reg(i) do { \ - err |= __get_user(regs->gpr[regs->current_tc][i], &sc->sc_regs[i]); \ + err |= __get_user(regs->active_tc.gpr[i], &sc->sc_regs[i]); \ } while(0) restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3); restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6); @@ -2437,7 +2437,7 @@ get_sigframe(struct target_sigaction *ka, CPUState *regs, size_t frame_size) unsigned long sp; /* Default to using normal stack */ - sp = regs->gpr[regs->current_tc][29]; + sp = regs->active_tc.gpr[29]; /* * FPU emulator may have it's own trampoline active just @@ -2486,15 +2486,15 @@ static void setup_frame(int sig, struct target_sigaction * ka, * $25 and PC point to the signal handler, $29 points to the * struct sigframe. */ - regs->gpr[regs->current_tc][ 4] = sig; - regs->gpr[regs->current_tc][ 5] = 0; - regs->gpr[regs->current_tc][ 6] = frame_addr + offsetof(struct sigframe, sf_sc); - regs->gpr[regs->current_tc][29] = frame_addr; - regs->gpr[regs->current_tc][31] = frame_addr + offsetof(struct sigframe, sf_code); + regs->active_tc.gpr[ 4] = sig; + regs->active_tc.gpr[ 5] = 0; + regs->active_tc.gpr[ 6] = frame_addr + offsetof(struct sigframe, sf_sc); + regs->active_tc.gpr[29] = frame_addr; + regs->active_tc.gpr[31] = frame_addr + offsetof(struct sigframe, sf_code); /* The original kernel code sets CP0_EPC to the handler * since it returns to userland using eret * we cannot do this here, and we must set PC directly */ - regs->PC[regs->current_tc] = regs->gpr[regs->current_tc][25] = ka->_sa_handler; + regs->active_tc.PC = regs->active_tc.gpr[25] = ka->_sa_handler; unlock_user_struct(frame, frame_addr, 1); return; @@ -2515,7 +2515,7 @@ long do_sigreturn(CPUState *regs) #if defined(DEBUG_SIGNAL) fprintf(stderr, "do_sigreturn\n"); #endif - frame_addr = regs->gpr[regs->current_tc][29]; + frame_addr = regs->active_tc.gpr[29]; if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) goto badframe; @@ -2542,7 +2542,7 @@ long do_sigreturn(CPUState *regs) /* Unreached */ #endif - regs->PC[regs->current_tc] = regs->CP0_EPC; + regs->active_tc.PC = regs->CP0_EPC; /* I am not sure this is right, but it seems to work * maybe a problem with nested signals ? */ regs->CP0_EPC = 0; diff --git a/linux-user/syscall.c b/linux-user/syscall.c index cd90946ae..839ac7f75 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -3686,7 +3686,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, if (!is_error(ret)) { #if defined(TARGET_MIPS) CPUMIPSState *env = (CPUMIPSState*)cpu_env; - env->gpr[env->current_tc][3] = host_pipe[1]; + env->active_tc.gpr[3] = host_pipe[1]; ret = host_pipe[0]; #elif defined(TARGET_SH4) ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1]; diff --git a/monitor.c b/monitor.c index 914f4c6e3..fc135caf5 100644 --- a/monitor.c +++ b/monitor.c @@ -316,7 +316,7 @@ static void do_info_cpus(void) #elif defined(TARGET_SPARC) term_printf(" pc=0x" TARGET_FMT_lx " npc=0x" TARGET_FMT_lx, env->pc, env->npc); #elif defined(TARGET_MIPS) - term_printf(" PC=0x" TARGET_FMT_lx, env->PC[env->current_tc]); + term_printf(" PC=0x" TARGET_FMT_lx, env->active_tc.PC); #endif if (env->halted) term_printf(" (halted)"); diff --git a/target-mips/cpu.h b/target-mips/cpu.h index fdb05ccfd..78851ed93 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -134,29 +134,53 @@ typedef struct mips_def_t mips_def_t; #define MIPS_TC_MAX 5 #define MIPS_DSP_ACC 4 +typedef struct TCState TCState; +struct TCState { + target_ulong gpr[32]; + target_ulong PC; + target_ulong HI[MIPS_DSP_ACC]; + target_ulong LO[MIPS_DSP_ACC]; + target_ulong ACX[MIPS_DSP_ACC]; + target_ulong DSPControl; + int32_t CP0_TCStatus; +#define CP0TCSt_TCU3 31 +#define CP0TCSt_TCU2 30 +#define CP0TCSt_TCU1 29 +#define CP0TCSt_TCU0 28 +#define CP0TCSt_TMX 27 +#define CP0TCSt_RNST 23 +#define CP0TCSt_TDS 21 +#define CP0TCSt_DT 20 +#define CP0TCSt_DA 15 +#define CP0TCSt_A 13 +#define CP0TCSt_TKSU 11 +#define CP0TCSt_IXMT 10 +#define CP0TCSt_TASID 0 + int32_t CP0_TCBind; +#define CP0TCBd_CurTC 21 +#define CP0TCBd_TBE 17 +#define CP0TCBd_CurVPE 0 + target_ulong CP0_TCHalt; + target_ulong CP0_TCContext; + target_ulong CP0_TCSchedule; + target_ulong CP0_TCScheFBack; + int32_t CP0_Debug_tcstatus; +}; + typedef struct CPUMIPSState CPUMIPSState; struct CPUMIPSState { - /* General integer registers */ - target_ulong gpr[MIPS_SHADOW_SET_MAX][32]; - /* Special registers */ - target_ulong PC[MIPS_TC_MAX]; + TCState active_tc; + /* temporary hack for FP globals */ #ifndef USE_HOST_FLOAT_REGS fpr_t ft0; fpr_t ft1; fpr_t ft2; #endif - target_ulong HI[MIPS_TC_MAX][MIPS_DSP_ACC]; - target_ulong LO[MIPS_TC_MAX][MIPS_DSP_ACC]; - target_ulong ACX[MIPS_TC_MAX][MIPS_DSP_ACC]; - target_ulong DSPControl[MIPS_TC_MAX]; - CPUMIPSMVPContext *mvp; CPUMIPSTLBContext *tlb; CPUMIPSFPUContext *fpu; uint32_t current_tc; - target_ulong *current_tc_gprs; - target_ulong *current_tc_hi; uint32_t SEGBITS; target_ulong SEGMask; @@ -206,28 +230,6 @@ struct CPUMIPSState { #define CP0VPEOpt_DWX1 1 #define CP0VPEOpt_DWX0 0 target_ulong CP0_EntryLo0; - int32_t CP0_TCStatus[MIPS_TC_MAX]; -#define CP0TCSt_TCU3 31 -#define CP0TCSt_TCU2 30 -#define CP0TCSt_TCU1 29 -#define CP0TCSt_TCU0 28 -#define CP0TCSt_TMX 27 -#define CP0TCSt_RNST 23 -#define CP0TCSt_TDS 21 -#define CP0TCSt_DT 20 -#define CP0TCSt_DA 15 -#define CP0TCSt_A 13 -#define CP0TCSt_TKSU 11 -#define CP0TCSt_IXMT 10 -#define CP0TCSt_TASID 0 - int32_t CP0_TCBind[MIPS_TC_MAX]; -#define CP0TCBd_CurTC 21 -#define CP0TCBd_TBE 17 -#define CP0TCBd_CurVPE 0 - target_ulong CP0_TCHalt[MIPS_TC_MAX]; - target_ulong CP0_TCContext[MIPS_TC_MAX]; - target_ulong CP0_TCSchedule[MIPS_TC_MAX]; - target_ulong CP0_TCScheFBack[MIPS_TC_MAX]; target_ulong CP0_EntryLo1; target_ulong CP0_Context; int32_t CP0_PageMask; @@ -398,7 +400,6 @@ struct CPUMIPSState { #define CP0DB_DDBL 2 #define CP0DB_DBp 1 #define CP0DB_DSS 0 - int32_t CP0_Debug_tcstatus[MIPS_TC_MAX]; target_ulong CP0_DEPC; int32_t CP0_Performance0; int32_t CP0_TagLo; @@ -407,6 +408,8 @@ struct CPUMIPSState { int32_t CP0_DataHi; target_ulong CP0_ErrorEPC; int32_t CP0_DESAVE; + /* We waste some space so we can handle shadow registers like TCs. */ + TCState tcs[MIPS_SHADOW_SET_MAX]; /* Qemu */ int interrupt_request; int error_code; @@ -501,9 +504,9 @@ static inline int cpu_mmu_index (CPUState *env) static inline void cpu_clone_regs(CPUState *env, target_ulong newsp) { if (newsp) - env->gpr[env->current_tc][29] = newsp; - env->gpr[env->current_tc][7] = 0; - env->gpr[env->current_tc][2] = 0; + env->active_tc.gpr[29] = newsp; + env->active_tc.gpr[7] = 0; + env->active_tc.gpr[2] = 0; } #endif diff --git a/target-mips/helper.c b/target-mips/helper.c index b9622959b..11f58c225 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -241,7 +241,7 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, cpu_dump_state(env, logfile, fprintf, 0); #endif fprintf(logfile, "%s pc " TARGET_FMT_lx " ad " TARGET_FMT_lx " rw %d mmu_idx %d smmu %d\n", - __func__, env->PC[env->current_tc], address, rw, mmu_idx, is_softmmu); + __func__, env->active_tc.PC, address, rw, mmu_idx, is_softmmu); } rw &= 1; @@ -370,7 +370,7 @@ void do_interrupt (CPUState *env) name = excp_names[env->exception_index]; fprintf(logfile, "%s enter: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " %s exception\n", - __func__, env->PC[env->current_tc], env->CP0_EPC, name); + __func__, env->active_tc.PC, env->CP0_EPC, name); } if (env->exception_index == EXCP_EXT_INTERRUPT && (env->hflags & MIPS_HFLAG_DM)) @@ -384,7 +384,7 @@ void do_interrupt (CPUState *env) * (but we assume the pc has always been updated during * code translation). */ - env->CP0_DEPC = env->PC[env->current_tc]; + env->CP0_DEPC = env->active_tc.PC; goto enter_debug_mode; case EXCP_DINT: env->CP0_Debug |= 1 << CP0DB_DINT; @@ -404,10 +404,10 @@ void do_interrupt (CPUState *env) if (env->hflags & MIPS_HFLAG_BMASK) { /* If the exception was raised from a delay slot, come back to the jump. */ - env->CP0_DEPC = env->PC[env->current_tc] - 4; + env->CP0_DEPC = env->active_tc.PC - 4; env->hflags &= ~MIPS_HFLAG_BMASK; } else { - env->CP0_DEPC = env->PC[env->current_tc]; + env->CP0_DEPC = env->active_tc.PC; } enter_debug_mode: env->hflags |= MIPS_HFLAG_DM | MIPS_HFLAG_64 | MIPS_HFLAG_CP0; @@ -415,7 +415,7 @@ void do_interrupt (CPUState *env) /* EJTAG probe trap enable is not implemented... */ if (!(env->CP0_Status & (1 << CP0St_EXL))) env->CP0_Cause &= ~(1 << CP0Ca_BD); - env->PC[env->current_tc] = (int32_t)0xBFC00480; + env->active_tc.PC = (int32_t)0xBFC00480; break; case EXCP_RESET: cpu_reset(env); @@ -430,17 +430,17 @@ void do_interrupt (CPUState *env) if (env->hflags & MIPS_HFLAG_BMASK) { /* If the exception was raised from a delay slot, come back to the jump. */ - env->CP0_ErrorEPC = env->PC[env->current_tc] - 4; + env->CP0_ErrorEPC = env->active_tc.PC - 4; env->hflags &= ~MIPS_HFLAG_BMASK; } else { - env->CP0_ErrorEPC = env->PC[env->current_tc]; + env->CP0_ErrorEPC = env->active_tc.PC; } env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV); env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0; env->hflags &= ~(MIPS_HFLAG_KSU); if (!(env->CP0_Status & (1 << CP0St_EXL))) env->CP0_Cause &= ~(1 << CP0Ca_BD); - env->PC[env->current_tc] = (int32_t)0xBFC00000; + env->active_tc.PC = (int32_t)0xBFC00000; break; case EXCP_EXT_INTERRUPT: cause = 0; @@ -545,10 +545,10 @@ void do_interrupt (CPUState *env) if (env->hflags & MIPS_HFLAG_BMASK) { /* If the exception was raised from a delay slot, come back to the jump. */ - env->CP0_EPC = env->PC[env->current_tc] - 4; + env->CP0_EPC = env->active_tc.PC - 4; env->CP0_Cause |= (1 << CP0Ca_BD); } else { - env->CP0_EPC = env->PC[env->current_tc]; + env->CP0_EPC = env->active_tc.PC; env->CP0_Cause &= ~(1 << CP0Ca_BD); } env->CP0_Status |= (1 << CP0St_EXL); @@ -557,11 +557,11 @@ void do_interrupt (CPUState *env) } env->hflags &= ~MIPS_HFLAG_BMASK; if (env->CP0_Status & (1 << CP0St_BEV)) { - env->PC[env->current_tc] = (int32_t)0xBFC00200; + env->active_tc.PC = (int32_t)0xBFC00200; } else { - env->PC[env->current_tc] = (int32_t)(env->CP0_EBase & ~0x3ff); + env->active_tc.PC = (int32_t)(env->CP0_EBase & ~0x3ff); } - env->PC[env->current_tc] += offset; + env->active_tc.PC += offset; env->CP0_Cause = (env->CP0_Cause & ~(0x1f << CP0Ca_EC)) | (cause << CP0Ca_EC); break; default: @@ -575,7 +575,7 @@ void do_interrupt (CPUState *env) if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) { fprintf(logfile, "%s: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " cause %d\n" " S %08x C %08x A " TARGET_FMT_lx " D " TARGET_FMT_lx "\n", - __func__, env->PC[env->current_tc], env->CP0_EPC, cause, + __func__, env->active_tc.PC, env->CP0_EPC, cause, env->CP0_Status, env->CP0_Cause, env->CP0_BadVAddr, env->CP0_DEPC); } diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index eae5b7489..fe3bbd4d2 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -89,25 +89,25 @@ target_ulong do_dclz (target_ulong t0) /* 64 bits arithmetic for 32 bits hosts */ static always_inline uint64_t get_HILO (void) { - return ((uint64_t)(env->HI[env->current_tc][0]) << 32) | (uint32_t)env->LO[env->current_tc][0]; + return ((uint64_t)(env->active_tc.HI[0]) << 32) | (uint32_t)env->active_tc.LO[0]; } static always_inline void set_HILO (uint64_t HILO) { - env->LO[env->current_tc][0] = (int32_t)HILO; - env->HI[env->current_tc][0] = (int32_t)(HILO >> 32); + env->active_tc.LO[0] = (int32_t)HILO; + env->active_tc.HI[0] = (int32_t)(HILO >> 32); } static always_inline void set_HIT0_LO (target_ulong t0, uint64_t HILO) { - env->LO[env->current_tc][0] = (int32_t)(HILO & 0xFFFFFFFF); - t0 = env->HI[env->current_tc][0] = (int32_t)(HILO >> 32); + env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF); + t0 = env->active_tc.HI[0] = (int32_t)(HILO >> 32); } static always_inline void set_HI_LOT0 (target_ulong t0, uint64_t HILO) { - t0 = env->LO[env->current_tc][0] = (int32_t)(HILO & 0xFFFFFFFF); - env->HI[env->current_tc][0] = (int32_t)(HILO >> 32); + t0 = env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF); + env->active_tc.HI[0] = (int32_t)(HILO >> 32); } #if TARGET_LONG_BITS > HOST_LONG_BITS @@ -246,12 +246,12 @@ target_ulong do_mulshiu (target_ulong t0, target_ulong t1) #ifdef TARGET_MIPS64 void do_dmult (target_ulong t0, target_ulong t1) { - muls64(&(env->LO[env->current_tc][0]), &(env->HI[env->current_tc][0]), t0, t1); + muls64(&(env->active_tc.LO[0]), &(env->active_tc.HI[0]), t0, t1); } void do_dmultu (target_ulong t0, target_ulong t1) { - mulu64(&(env->LO[env->current_tc][0]), &(env->HI[env->current_tc][0]), t0, t1); + mulu64(&(env->active_tc.LO[0]), &(env->active_tc.HI[0]), t0, t1); } #endif @@ -672,86 +672,107 @@ target_ulong do_mfc0_random (void) target_ulong do_mfc0_tcstatus (void) { - return env->CP0_TCStatus[env->current_tc]; + return env->active_tc.CP0_TCStatus; } target_ulong do_mftc0_tcstatus(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - return env->CP0_TCStatus[other_tc]; + if (other_tc == env->current_tc) + return env->active_tc.CP0_TCStatus; + else + return env->tcs[other_tc].CP0_TCStatus; } target_ulong do_mfc0_tcbind (void) { - return env->CP0_TCBind[env->current_tc]; + return env->active_tc.CP0_TCBind; } target_ulong do_mftc0_tcbind(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - return env->CP0_TCBind[other_tc]; + if (other_tc == env->current_tc) + return env->active_tc.CP0_TCBind; + else + return env->tcs[other_tc].CP0_TCBind; } target_ulong do_mfc0_tcrestart (void) { - return env->PC[env->current_tc]; + return env->active_tc.PC; } target_ulong do_mftc0_tcrestart(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - return env->PC[other_tc]; + if (other_tc == env->current_tc) + return env->active_tc.PC; + else + return env->tcs[other_tc].PC; } target_ulong do_mfc0_tchalt (void) { - return env->CP0_TCHalt[env->current_tc]; + return env->active_tc.CP0_TCHalt; } target_ulong do_mftc0_tchalt(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - return env->CP0_TCHalt[other_tc]; + if (other_tc == env->current_tc) + return env->active_tc.CP0_TCHalt; + else + return env->tcs[other_tc].CP0_TCHalt; } target_ulong do_mfc0_tccontext (void) { - return env->CP0_TCContext[env->current_tc]; + return env->active_tc.CP0_TCContext; } target_ulong do_mftc0_tccontext(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - return env->CP0_TCContext[other_tc]; + if (other_tc == env->current_tc) + return env->active_tc.CP0_TCContext; + else + return env->tcs[other_tc].CP0_TCContext; } target_ulong do_mfc0_tcschedule (void) { - return env->CP0_TCSchedule[env->current_tc]; + return env->active_tc.CP0_TCSchedule; } target_ulong do_mftc0_tcschedule(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - return env->CP0_TCSchedule[other_tc]; + if (other_tc == env->current_tc) + return env->active_tc.CP0_TCSchedule; + else + return env->tcs[other_tc].CP0_TCSchedule; } target_ulong do_mfc0_tcschefback (void) { - return env->CP0_TCScheFBack[env->current_tc]; + return env->active_tc.CP0_TCScheFBack; } target_ulong do_mftc0_tcschefback(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - return env->CP0_TCScheFBack[other_tc]; + if (other_tc == env->current_tc) + return env->active_tc.CP0_TCScheFBack; + else + return env->tcs[other_tc].CP0_TCScheFBack; } target_ulong do_mfc0_count (void) @@ -762,15 +783,26 @@ target_ulong do_mfc0_count (void) target_ulong do_mftc0_entryhi(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + int32_t tcstatus; - return (env->CP0_EntryHi & ~0xff) | (env->CP0_TCStatus[other_tc] & 0xff); + if (other_tc == env->current_tc) + tcstatus = env->active_tc.CP0_TCStatus; + else + tcstatus = env->tcs[other_tc].CP0_TCStatus; + + return (env->CP0_EntryHi & ~0xff) | (tcstatus & 0xff); } target_ulong do_mftc0_status(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - uint32_t tcstatus = env->CP0_TCStatus[other_tc]; target_ulong t0; + int32_t tcstatus; + + if (other_tc == env->current_tc) + tcstatus = env->active_tc.CP0_TCStatus; + else + tcstatus = env->tcs[other_tc].CP0_TCStatus; t0 = env->CP0_Status & ~0xf1000018; t0 |= tcstatus & (0xf << CP0TCSt_TCU0); @@ -807,37 +839,42 @@ target_ulong do_mfc0_debug (void) target_ulong do_mftc0_debug(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + int32_t tcstatus; + + if (other_tc == env->current_tc) + tcstatus = env->active_tc.CP0_Debug_tcstatus; + else + tcstatus = env->tcs[other_tc].CP0_Debug_tcstatus; /* XXX: Might be wrong, check with EJTAG spec. */ return (env->CP0_Debug & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) | - (env->CP0_Debug_tcstatus[other_tc] & - ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))); + (tcstatus & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))); } #if defined(TARGET_MIPS64) target_ulong do_dmfc0_tcrestart (void) { - return env->PC[env->current_tc]; + return env->active_tc.PC; } target_ulong do_dmfc0_tchalt (void) { - return env->CP0_TCHalt[env->current_tc]; + return env->active_tc.CP0_TCHalt; } target_ulong do_dmfc0_tccontext (void) { - return env->CP0_TCContext[env->current_tc]; + return env->active_tc.CP0_TCContext; } target_ulong do_dmfc0_tcschedule (void) { - return env->CP0_TCSchedule[env->current_tc]; + return env->active_tc.CP0_TCSchedule; } target_ulong do_dmfc0_tcschefback (void) { - return env->CP0_TCScheFBack[env->current_tc]; + return env->active_tc.CP0_TCScheFBack; } target_ulong do_dmfc0_lladdr (void) @@ -955,11 +992,11 @@ void do_mtc0_tcstatus (target_ulong t0) uint32_t mask = env->CP0_TCStatus_rw_bitmask; uint32_t newval; - newval = (env->CP0_TCStatus[env->current_tc] & ~mask) | (t0 & mask); + newval = (env->active_tc.CP0_TCStatus & ~mask) | (t0 & mask); // TODO: Sync with CP0_Status. - env->CP0_TCStatus[env->current_tc] = newval; + env->active_tc.CP0_TCStatus = newval; } void do_mttc0_tcstatus (target_ulong t0) @@ -968,7 +1005,10 @@ void do_mttc0_tcstatus (target_ulong t0) // TODO: Sync with CP0_Status. - env->CP0_TCStatus[other_tc] = t0; + if (other_tc == env->current_tc) + env->active_tc.CP0_TCStatus = t0; + else + env->tcs[other_tc].CP0_TCStatus = t0; } void do_mtc0_tcbind (target_ulong t0) @@ -978,8 +1018,8 @@ void do_mtc0_tcbind (target_ulong t0) if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC)) mask |= (1 << CP0TCBd_CurVPE); - newval = (env->CP0_TCBind[env->current_tc] & ~mask) | (t0 & mask); - env->CP0_TCBind[env->current_tc] = newval; + newval = (env->active_tc.CP0_TCBind & ~mask) | (t0 & mask); + env->active_tc.CP0_TCBind = newval; } void do_mttc0_tcbind (target_ulong t0) @@ -990,14 +1030,19 @@ void do_mttc0_tcbind (target_ulong t0) if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC)) mask |= (1 << CP0TCBd_CurVPE); - newval = (env->CP0_TCBind[other_tc] & ~mask) | (t0 & mask); - env->CP0_TCBind[other_tc] = newval; + if (other_tc == env->current_tc) { + newval = (env->active_tc.CP0_TCBind & ~mask) | (t0 & mask); + env->active_tc.CP0_TCBind = newval; + } else { + newval = (env->tcs[other_tc].CP0_TCBind & ~mask) | (t0 & mask); + env->tcs[other_tc].CP0_TCBind = newval; + } } void do_mtc0_tcrestart (target_ulong t0) { - env->PC[env->current_tc] = t0; - env->CP0_TCStatus[env->current_tc] &= ~(1 << CP0TCSt_TDS); + env->active_tc.PC = t0; + env->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS); env->CP0_LLAddr = 0ULL; /* MIPS16 not implemented. */ } @@ -1006,15 +1051,22 @@ void do_mttc0_tcrestart (target_ulong t0) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - env->PC[other_tc] = t0; - env->CP0_TCStatus[other_tc] &= ~(1 << CP0TCSt_TDS); - env->CP0_LLAddr = 0ULL; - /* MIPS16 not implemented. */ + if (other_tc == env->current_tc) { + env->active_tc.PC = t0; + env->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS); + env->CP0_LLAddr = 0ULL; + /* MIPS16 not implemented. */ + } else { + env->tcs[other_tc].PC = t0; + env->tcs[other_tc].CP0_TCStatus &= ~(1 << CP0TCSt_TDS); + env->CP0_LLAddr = 0ULL; + /* MIPS16 not implemented. */ + } } void do_mtc0_tchalt (target_ulong t0) { - env->CP0_TCHalt[env->current_tc] = t0 & 0x1; + env->active_tc.CP0_TCHalt = t0 & 0x1; // TODO: Halt TC / Restart (if allocated+active) TC. } @@ -1025,43 +1077,55 @@ void do_mttc0_tchalt (target_ulong t0) // TODO: Halt TC / Restart (if allocated+active) TC. - env->CP0_TCHalt[other_tc] = t0; + if (other_tc == env->current_tc) + env->active_tc.CP0_TCHalt = t0; + else + env->tcs[other_tc].CP0_TCHalt = t0; } void do_mtc0_tccontext (target_ulong t0) { - env->CP0_TCContext[env->current_tc] = t0; + env->active_tc.CP0_TCContext = t0; } void do_mttc0_tccontext (target_ulong t0) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - env->CP0_TCContext[other_tc] = t0; + if (other_tc == env->current_tc) + env->active_tc.CP0_TCContext = t0; + else + env->tcs[other_tc].CP0_TCContext = t0; } void do_mtc0_tcschedule (target_ulong t0) { - env->CP0_TCSchedule[env->current_tc] = t0; + env->active_tc.CP0_TCSchedule = t0; } void do_mttc0_tcschedule (target_ulong t0) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - env->CP0_TCSchedule[other_tc] = t0; + if (other_tc == env->current_tc) + env->active_tc.CP0_TCSchedule = t0; + else + env->tcs[other_tc].CP0_TCSchedule = t0; } void do_mtc0_tcschefback (target_ulong t0) { - env->CP0_TCScheFBack[env->current_tc] = t0; + env->active_tc.CP0_TCScheFBack = t0; } void do_mttc0_tcschefback (target_ulong t0) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - env->CP0_TCScheFBack[other_tc] = t0; + if (other_tc == env->current_tc) + env->active_tc.CP0_TCScheFBack = t0; + else + env->tcs[other_tc].CP0_TCScheFBack = t0; } void do_mtc0_entrylo1 (target_ulong t0) @@ -1142,8 +1206,8 @@ void do_mtc0_entryhi (target_ulong t0) old = env->CP0_EntryHi; env->CP0_EntryHi = val; if (env->CP0_Config3 & (1 << CP0C3_MT)) { - uint32_t tcst = env->CP0_TCStatus[env->current_tc] & ~0xff; - env->CP0_TCStatus[env->current_tc] = tcst | (val & 0xff); + uint32_t tcst = env->active_tc.CP0_TCStatus & ~0xff; + env->active_tc.CP0_TCStatus = tcst | (val & 0xff); } /* If the ASID changes, flush qemu's TLB. */ if ((old & 0xFF) != (val & 0xFF)) @@ -1153,9 +1217,16 @@ void do_mtc0_entryhi (target_ulong t0) void do_mttc0_entryhi(target_ulong t0) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + int32_t tcstatus; env->CP0_EntryHi = (env->CP0_EntryHi & 0xff) | (t0 & ~0xff); - env->CP0_TCStatus[other_tc] = (env->CP0_TCStatus[other_tc] & ~0xff) | (t0 & 0xff); + if (other_tc == env->current_tc) { + tcstatus = (env->active_tc.CP0_TCStatus & ~0xff) | (t0 & 0xff); + env->active_tc.CP0_TCStatus = tcstatus; + } else { + tcstatus = (env->tcs[other_tc].CP0_TCStatus & ~0xff) | (t0 & 0xff); + env->tcs[other_tc].CP0_TCStatus = tcstatus; + } } void do_mtc0_compare (target_ulong t0) @@ -1180,13 +1251,16 @@ void do_mtc0_status (target_ulong t0) void do_mttc0_status(target_ulong t0) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - uint32_t tcstatus = env->CP0_TCStatus[other_tc]; + int32_t tcstatus = env->tcs[other_tc].CP0_TCStatus; env->CP0_Status = t0 & ~0xf1000018; tcstatus = (tcstatus & ~(0xf << CP0TCSt_TCU0)) | (t0 & (0xf << CP0St_CU0)); tcstatus = (tcstatus & ~(1 << CP0TCSt_TMX)) | ((t0 & (1 << CP0St_MX)) << (CP0TCSt_TMX - CP0St_MX)); tcstatus = (tcstatus & ~(0x3 << CP0TCSt_TKSU)) | ((t0 & (0x3 << CP0St_KSU)) << (CP0TCSt_TKSU - CP0St_KSU)); - env->CP0_TCStatus[other_tc] = tcstatus; + if (other_tc == env->current_tc) + env->active_tc.CP0_TCStatus = tcstatus; + else + env->tcs[other_tc].CP0_TCStatus = tcstatus; } void do_mtc0_intctl (target_ulong t0) @@ -1279,9 +1353,13 @@ void do_mtc0_debug (target_ulong t0) void do_mttc0_debug(target_ulong t0) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + uint32_t val = t0 & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt)); /* XXX: Might be wrong, check with EJTAG spec. */ - env->CP0_Debug_tcstatus[other_tc] = t0 & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt)); + if (other_tc == env->current_tc) + env->active_tc.CP0_Debug_tcstatus = val; + else + env->tcs[other_tc].CP0_Debug_tcstatus = val; env->CP0_Debug = (env->CP0_Debug & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) | (t0 & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))); } @@ -1336,70 +1414,100 @@ target_ulong do_mftgpr(target_ulong t0, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - return env->gpr[other_tc][sel]; + if (other_tc == env->current_tc) + return env->active_tc.gpr[sel]; + else + return env->tcs[other_tc].gpr[sel]; } target_ulong do_mftlo(target_ulong t0, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - return env->LO[other_tc][sel]; + if (other_tc == env->current_tc) + return env->active_tc.LO[sel]; + else + return env->tcs[other_tc].LO[sel]; } target_ulong do_mfthi(target_ulong t0, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - return env->HI[other_tc][sel]; + if (other_tc == env->current_tc) + return env->active_tc.HI[sel]; + else + return env->tcs[other_tc].HI[sel]; } target_ulong do_mftacx(target_ulong t0, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - return env->ACX[other_tc][sel]; + if (other_tc == env->current_tc) + return env->active_tc.ACX[sel]; + else + return env->tcs[other_tc].ACX[sel]; } target_ulong do_mftdsp(target_ulong t0) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - return env->DSPControl[other_tc]; + if (other_tc == env->current_tc) + return env->active_tc.DSPControl; + else + return env->tcs[other_tc].DSPControl; } void do_mttgpr(target_ulong t0, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - env->gpr[other_tc][sel] = t0; + if (other_tc == env->current_tc) + env->active_tc.gpr[sel] = t0; + else + env->tcs[other_tc].gpr[sel] = t0; } void do_mttlo(target_ulong t0, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - env->LO[other_tc][sel] = t0; + if (other_tc == env->current_tc) + env->active_tc.LO[sel] = t0; + else + env->tcs[other_tc].LO[sel] = t0; } void do_mtthi(target_ulong t0, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - env->HI[other_tc][sel] = t0; + if (other_tc == env->current_tc) + env->active_tc.HI[sel] = t0; + else + env->tcs[other_tc].HI[sel] = t0; } void do_mttacx(target_ulong t0, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - env->ACX[other_tc][sel] = t0; + if (other_tc == env->current_tc) + env->active_tc.ACX[sel] = t0; + else + env->tcs[other_tc].ACX[sel] = t0; } void do_mttdsp(target_ulong t0) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - env->DSPControl[other_tc] = t0; + if (other_tc == env->current_tc) + env->active_tc.DSPControl = t0; + else + env->tcs[other_tc].DSPControl = t0; } /* MIPS MT functions */ @@ -1452,7 +1560,7 @@ target_ulong do_yield(target_ulong t0) /* No scheduling policy implemented. */ if (t0 != -2) { if (env->CP0_VPEControl & (1 << CP0VPECo_YSI) && - env->CP0_TCStatus[env->current_tc] & (1 << CP0TCSt_DT)) { + env->active_tc.CP0_TCStatus & (1 << CP0TCSt_DT)) { env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT); env->CP0_VPEControl |= 4 << CP0VPECo_EXCPT; do_raise_exception(EXCP_THREAD); @@ -1659,7 +1767,7 @@ target_ulong do_ei (target_ulong t0) void debug_pre_eret (void) { fprintf(logfile, "ERET: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx, - env->PC[env->current_tc], env->CP0_EPC); + env->active_tc.PC, env->CP0_EPC); if (env->CP0_Status & (1 << CP0St_ERL)) fprintf(logfile, " ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC); if (env->hflags & MIPS_HFLAG_DM) @@ -1670,7 +1778,7 @@ void debug_pre_eret (void) void debug_post_eret (void) { fprintf(logfile, " => PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx, - env->PC[env->current_tc], env->CP0_EPC); + env->active_tc.PC, env->CP0_EPC); if (env->CP0_Status & (1 << CP0St_ERL)) fprintf(logfile, " ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC); if (env->hflags & MIPS_HFLAG_DM) @@ -1688,10 +1796,10 @@ void do_eret (void) if (loglevel & CPU_LOG_EXEC) debug_pre_eret(); if (env->CP0_Status & (1 << CP0St_ERL)) { - env->PC[env->current_tc] = env->CP0_ErrorEPC; + env->active_tc.PC = env->CP0_ErrorEPC; env->CP0_Status &= ~(1 << CP0St_ERL); } else { - env->PC[env->current_tc] = env->CP0_EPC; + env->active_tc.PC = env->CP0_EPC; env->CP0_Status &= ~(1 << CP0St_EXL); } compute_hflags(env); @@ -1704,7 +1812,7 @@ void do_deret (void) { if (loglevel & CPU_LOG_EXEC) debug_pre_eret(); - env->PC[env->current_tc] = env->CP0_DEPC; + env->active_tc.PC = env->CP0_DEPC; env->hflags &= MIPS_HFLAG_DM; compute_hflags(env); if (loglevel & CPU_LOG_EXEC) @@ -1804,21 +1912,21 @@ void do_pmon (int function) function /= 2; switch (function) { case 2: /* TODO: char inbyte(int waitflag); */ - if (env->gpr[env->current_tc][4] == 0) - env->gpr[env->current_tc][2] = -1; + if (env->active_tc.gpr[4] == 0) + env->active_tc.gpr[2] = -1; /* Fall through */ case 11: /* TODO: char inbyte (void); */ - env->gpr[env->current_tc][2] = -1; + env->active_tc.gpr[2] = -1; break; case 3: case 12: - printf("%c", (char)(env->gpr[env->current_tc][4] & 0xFF)); + printf("%c", (char)(env->active_tc.gpr[4] & 0xFF)); break; case 17: break; case 158: { - unsigned char *fmt = (void *)(unsigned long)env->gpr[env->current_tc][4]; + unsigned char *fmt = (void *)(unsigned long)env->active_tc.gpr[4]; printf("%s", fmt); } break; diff --git a/target-mips/translate.c b/target-mips/translate.c index 41a27b4e2..c4d91f0e5 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -423,7 +423,7 @@ enum { }; /* global register indices */ -static TCGv cpu_env, current_tc_gprs, current_tc_hi, current_fpu; +static TCGv cpu_env, current_fpu; /* FPU TNs, global for now. */ static TCGv fpu32_T[3], fpu64_T[3], fpu32h_T[3]; @@ -563,40 +563,40 @@ static inline void gen_load_gpr (TCGv t, int reg) if (reg == 0) tcg_gen_movi_tl(t, 0); else - tcg_gen_ld_tl(t, current_tc_gprs, sizeof(target_ulong) * reg); + tcg_gen_ld_tl(t, cpu_env, offsetof(CPUState, active_tc.gpr) + + sizeof(target_ulong) * reg); } static inline void gen_store_gpr (TCGv t, int reg) { if (reg != 0) - tcg_gen_st_tl(t, current_tc_gprs, sizeof(target_ulong) * reg); + tcg_gen_st_tl(t, cpu_env, offsetof(CPUState, active_tc.gpr) + + sizeof(target_ulong) * reg); } /* Moves to/from HI and LO registers. */ static inline void gen_load_LO (TCGv t, int reg) { - tcg_gen_ld_tl(t, current_tc_hi, - offsetof(CPUState, LO) - - offsetof(CPUState, HI) - + sizeof(target_ulong) * reg); + tcg_gen_ld_tl(t, cpu_env, offsetof(CPUState, active_tc.LO) + + sizeof(target_ulong) * reg); } static inline void gen_store_LO (TCGv t, int reg) { - tcg_gen_st_tl(t, current_tc_hi, - offsetof(CPUState, LO) - - offsetof(CPUState, HI) - + sizeof(target_ulong) * reg); + tcg_gen_st_tl(t, cpu_env, offsetof(CPUState, active_tc.LO) + + sizeof(target_ulong) * reg); } static inline void gen_load_HI (TCGv t, int reg) { - tcg_gen_ld_tl(t, current_tc_hi, sizeof(target_ulong) * reg); + tcg_gen_ld_tl(t, cpu_env, offsetof(CPUState, active_tc.HI) + + sizeof(target_ulong) * reg); } static inline void gen_store_HI (TCGv t, int reg) { - tcg_gen_st_tl(t, current_tc_hi, sizeof(target_ulong) * reg); + tcg_gen_st_tl(t, cpu_env, offsetof(CPUState, active_tc.HI) + + sizeof(target_ulong) * reg); } /* Moves to/from shadow registers. */ @@ -805,38 +805,18 @@ OP_CONDZ(ltz, TCG_COND_LT); static inline void gen_save_pc(target_ulong pc) { TCGv r_tmp = tcg_temp_new(TCG_TYPE_TL); - TCGv r_tc_off = tcg_temp_new(TCG_TYPE_I32); - TCGv r_tc_off_ptr = tcg_temp_new(TCG_TYPE_PTR); - TCGv r_ptr = tcg_temp_new(TCG_TYPE_PTR); tcg_gen_movi_tl(r_tmp, pc); - tcg_gen_ld_i32(r_tc_off, cpu_env, offsetof(CPUState, current_tc)); - tcg_gen_muli_i32(r_tc_off, r_tc_off, sizeof(target_ulong)); - tcg_gen_ext_i32_ptr(r_tc_off_ptr, r_tc_off); - tcg_gen_add_ptr(r_ptr, cpu_env, r_tc_off_ptr); - tcg_gen_st_tl(r_tmp, r_ptr, offsetof(CPUState, PC)); - tcg_temp_free(r_tc_off); - tcg_temp_free(r_tc_off_ptr); - tcg_temp_free(r_ptr); + tcg_gen_st_tl(r_tmp, cpu_env, offsetof(CPUState, active_tc.PC)); tcg_temp_free(r_tmp); } static inline void gen_breg_pc(void) { TCGv r_tmp = tcg_temp_new(TCG_TYPE_TL); - TCGv r_tc_off = tcg_temp_new(TCG_TYPE_I32); - TCGv r_tc_off_ptr = tcg_temp_new(TCG_TYPE_PTR); - TCGv r_ptr = tcg_temp_new(TCG_TYPE_PTR); tcg_gen_ld_tl(r_tmp, cpu_env, offsetof(CPUState, btarget)); - tcg_gen_ld_i32(r_tc_off, cpu_env, offsetof(CPUState, current_tc)); - tcg_gen_muli_i32(r_tc_off, r_tc_off, sizeof(target_ulong)); - tcg_gen_ext_i32_ptr(r_tc_off_ptr, r_tc_off); - tcg_gen_add_ptr(r_ptr, cpu_env, r_tc_off_ptr); - tcg_gen_st_tl(r_tmp, r_ptr, offsetof(CPUState, PC)); - tcg_temp_free(r_tc_off); - tcg_temp_free(r_tc_off_ptr); - tcg_temp_free(r_ptr); + tcg_gen_st_tl(r_tmp, cpu_env, offsetof(CPUState, active_tc.PC)); tcg_temp_free(r_tmp); } @@ -5202,8 +5182,8 @@ static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd, TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL); if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 && - ((env->CP0_TCBind[other_tc] & (0xf << CP0TCBd_CurVPE)) != - (env->CP0_TCBind[env->current_tc] & (0xf << CP0TCBd_CurVPE)))) + ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) != + (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) tcg_gen_movi_tl(t0, -1); else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) > (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) @@ -5371,8 +5351,8 @@ static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt, gen_load_gpr(t0, rt); if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 && - ((env->CP0_TCBind[other_tc] & (0xf << CP0TCBd_CurVPE)) != - (env->CP0_TCBind[env->current_tc] & (0xf << CP0TCBd_CurVPE)))) + ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) != + (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) /* NOP */ ; else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) > (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) @@ -8009,8 +7989,8 @@ void dump_fpu (CPUState *env) "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx " LO=0x" TARGET_FMT_lx " ds %04x " TARGET_FMT_lx " %04x\n", - env->PC[env->current_tc], env->HI[env->current_tc][0], - env->LO[env->current_tc][0], env->hflags, env->btarget, + env->active_tc.PC, env->active_tc.HI[0], + env->active_tc.LO[0], env->hflags, env->btarget, env->bcond); fpu_dump_state(env, logfile, fprintf, 0); } @@ -8028,18 +8008,18 @@ void cpu_mips_check_sign_extensions (CPUState *env, FILE *f, { int i; - if (!SIGN_EXT_P(env->PC[env->current_tc])) - cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->PC[env->current_tc]); - if (!SIGN_EXT_P(env->HI[env->current_tc][0])) - cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->HI[env->current_tc][0]); - if (!SIGN_EXT_P(env->LO[env->current_tc][0])) - cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->LO[env->current_tc][0]); + if (!SIGN_EXT_P(env->active_tc.PC)) + cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC); + if (!SIGN_EXT_P(env->active_tc.HI[0])) + cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]); + if (!SIGN_EXT_P(env->active_tc.LO[0])) + cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]); if (!SIGN_EXT_P(env->btarget)) cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget); for (i = 0; i < 32; i++) { - if (!SIGN_EXT_P(env->gpr[env->current_tc][i])) - cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->gpr[env->current_tc][i]); + if (!SIGN_EXT_P(env->active_tc.gpr[i])) + cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]); } if (!SIGN_EXT_P(env->CP0_EPC)) @@ -8056,11 +8036,11 @@ void cpu_dump_state (CPUState *env, FILE *f, int i; cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx " LO=0x" TARGET_FMT_lx " ds %04x " TARGET_FMT_lx " %d\n", - env->PC[env->current_tc], env->HI[env->current_tc], env->LO[env->current_tc], env->hflags, env->btarget, env->bcond); + env->active_tc.PC, env->active_tc.HI, env->active_tc.LO, env->hflags, env->btarget, env->bcond); for (i = 0; i < 32; i++) { if ((i & 3) == 0) cpu_fprintf(f, "GPR%02d:", i); - cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->gpr[env->current_tc][i]); + cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]); if ((i & 3) == 3) cpu_fprintf(f, "\n"); } @@ -8085,14 +8065,6 @@ static void mips_tcg_init(void) return; cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env"); - current_tc_gprs = tcg_global_mem_new(TCG_TYPE_PTR, - TCG_AREG0, - offsetof(CPUState, current_tc_gprs), - "current_tc_gprs"); - current_tc_hi = tcg_global_mem_new(TCG_TYPE_PTR, - TCG_AREG0, - offsetof(CPUState, current_tc_hi), - "current_tc_hi"); current_fpu = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0, offsetof(CPUState, fpu), @@ -8149,11 +8121,11 @@ void cpu_reset (CPUMIPSState *env) if (env->hflags & MIPS_HFLAG_BMASK) { /* If the exception was raised from a delay slot, * come back to the jump. */ - env->CP0_ErrorEPC = env->PC[env->current_tc] - 4; + env->CP0_ErrorEPC = env->active_tc.PC - 4; } else { - env->CP0_ErrorEPC = env->PC[env->current_tc]; + env->CP0_ErrorEPC = env->active_tc.PC; } - env->PC[env->current_tc] = (int32_t)0xBFC00000; + env->active_tc.PC = (int32_t)0xBFC00000; env->CP0_Wired = 0; /* SMP not implemented */ env->CP0_EBase = 0x80000000; @@ -8187,7 +8159,7 @@ void cpu_reset (CPUMIPSState *env) void gen_pc_load(CPUState *env, TranslationBlock *tb, unsigned long searched_pc, int pc_pos, void *puc) { - env->PC[env->current_tc] = gen_opc_pc[pc_pos]; + env->active_tc.PC = gen_opc_pc[pc_pos]; env->hflags &= ~MIPS_HFLAG_BMASK; env->hflags |= gen_opc_hflags[pc_pos]; } diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c index d84bee01e..b7d68cc28 100644 --- a/target-mips/translate_init.c +++ b/target-mips/translate_init.c @@ -546,8 +546,6 @@ static int cpu_mips_register (CPUMIPSState *env, const mips_def_t *def) env->CP0_TCStatus_rw_bitmask = def->CP0_TCStatus_rw_bitmask; env->CP0_SRSCtl = def->CP0_SRSCtl; env->current_tc = 0; - env->current_tc_gprs = &env->gpr[env->current_tc][0]; - env->current_tc_hi = &env->HI[env->current_tc][0]; env->SEGBITS = def->SEGBITS; env->SEGMask = (target_ulong)((1ULL << def->SEGBITS) - 1); #if defined(TARGET_MIPS64) -- cgit v1.2.3 From 2796188e563dcb2c1e8d75e02ca284bb9dc792e3 Mon Sep 17 00:00:00 2001 From: ths Date: Fri, 27 Jun 2008 10:03:42 +0000 Subject: Avoid unused input arguments which triggered tcg errors. Spotted by Stefan Weil. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4795 c046a42c-6fe2-441c-8c8c-71466251a162 --- target-mips/helper.h | 12 ++++++------ target-mips/op_helper.c | 34 ++++++++++++++++++---------------- target-mips/translate.c | 12 ++++++------ 3 files changed, 30 insertions(+), 28 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index 9fb5d7402..eed8bd597 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -239,14 +239,14 @@ FOP_PROTO(ngt) #undef FOP_PROTO /* Special functions */ -DEF_HELPER(target_ulong, do_di, (target_ulong t0)) -DEF_HELPER(target_ulong, do_ei, (target_ulong t0)) +DEF_HELPER(target_ulong, do_di, (void)) +DEF_HELPER(target_ulong, do_ei, (void)) DEF_HELPER(void, do_eret, (void)) DEF_HELPER(void, do_deret, (void)) -DEF_HELPER(target_ulong, do_rdhwr_cpunum, (target_ulong t0)) -DEF_HELPER(target_ulong, do_rdhwr_synci_step, (target_ulong t0)) -DEF_HELPER(target_ulong, do_rdhwr_cc, (target_ulong t0)) -DEF_HELPER(target_ulong, do_rdhwr_ccres, (target_ulong t0)) +DEF_HELPER(target_ulong, do_rdhwr_cpunum, (void)) +DEF_HELPER(target_ulong, do_rdhwr_synci_step, (void)) +DEF_HELPER(target_ulong, do_rdhwr_cc, (void)) +DEF_HELPER(target_ulong, do_rdhwr_ccres, (void)) DEF_HELPER(void, do_pmon, (int function)) DEF_HELPER(void, do_wait, (void)) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index fe3bbd4d2..6c1d048b7 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -1746,18 +1746,20 @@ void r4k_do_tlbr (void) #endif /* !CONFIG_USER_ONLY */ /* Specials */ -target_ulong do_di (target_ulong t0) +target_ulong do_di (void) { - t0 = env->CP0_Status; + target_ulong t0 = env->CP0_Status; + env->CP0_Status = t0 & ~(1 << CP0St_IE); cpu_mips_update_irq(env); return t0; } -target_ulong do_ei (target_ulong t0) +target_ulong do_ei (void) { - t0 = env->CP0_Status; + target_ulong t0 = env->CP0_Status; + env->CP0_Status = t0 | (1 << CP0St_IE); cpu_mips_update_irq(env); @@ -1820,48 +1822,48 @@ void do_deret (void) env->CP0_LLAddr = 1; } -target_ulong do_rdhwr_cpunum(target_ulong t0) +target_ulong do_rdhwr_cpunum(void) { if ((env->hflags & MIPS_HFLAG_CP0) || (env->CP0_HWREna & (1 << 0))) - t0 = env->CP0_EBase & 0x3ff; + return env->CP0_EBase & 0x3ff; else do_raise_exception(EXCP_RI); - return t0; + return 0; } -target_ulong do_rdhwr_synci_step(target_ulong t0) +target_ulong do_rdhwr_synci_step(void) { if ((env->hflags & MIPS_HFLAG_CP0) || (env->CP0_HWREna & (1 << 1))) - t0 = env->SYNCI_Step; + return env->SYNCI_Step; else do_raise_exception(EXCP_RI); - return t0; + return 0; } -target_ulong do_rdhwr_cc(target_ulong t0) +target_ulong do_rdhwr_cc(void) { if ((env->hflags & MIPS_HFLAG_CP0) || (env->CP0_HWREna & (1 << 2))) - t0 = env->CP0_Count; + return env->CP0_Count; else do_raise_exception(EXCP_RI); - return t0; + return 0; } -target_ulong do_rdhwr_ccres(target_ulong t0) +target_ulong do_rdhwr_ccres(void) { if ((env->hflags & MIPS_HFLAG_CP0) || (env->CP0_HWREna & (1 << 3))) - t0 = env->CCRes; + return env->CCRes; else do_raise_exception(EXCP_RI); - return t0; + return 0; } /* Bitfield operations. */ diff --git a/target-mips/translate.c b/target-mips/translate.c index c4d91f0e5..9c97b9c48 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -7386,19 +7386,19 @@ static void decode_opc (CPUState *env, DisasContext *ctx) switch (rd) { case 0: save_cpu_state(ctx, 1); - tcg_gen_helper_1_1(do_rdhwr_cpunum, t0, t0); + tcg_gen_helper_1_0(do_rdhwr_cpunum, t0); break; case 1: save_cpu_state(ctx, 1); - tcg_gen_helper_1_1(do_rdhwr_synci_step, t0, t0); + tcg_gen_helper_1_0(do_rdhwr_synci_step, t0); break; case 2: save_cpu_state(ctx, 1); - tcg_gen_helper_1_1(do_rdhwr_cc, t0, t0); + tcg_gen_helper_1_0(do_rdhwr_cc, t0); break; case 3: save_cpu_state(ctx, 1); - tcg_gen_helper_1_1(do_rdhwr_ccres, t0, t0); + tcg_gen_helper_1_0(do_rdhwr_ccres, t0); break; case 29: #if defined (CONFIG_USER_ONLY) @@ -7548,14 +7548,14 @@ static void decode_opc (CPUState *env, DisasContext *ctx) case OPC_DI: check_insn(env, ctx, ISA_MIPS32R2); save_cpu_state(ctx, 1); - tcg_gen_helper_1_1(do_di, t0, t0); + tcg_gen_helper_1_0(do_di, t0); /* Stop translation as we may have switched the execution mode */ ctx->bstate = BS_STOP; break; case OPC_EI: check_insn(env, ctx, ISA_MIPS32R2); save_cpu_state(ctx, 1); - tcg_gen_helper_1_1(do_ei, t0, t0); + tcg_gen_helper_1_0(do_ei, t0); /* Stop translation as we may have switched the execution mode */ ctx->bstate = BS_STOP; break; -- cgit v1.2.3 From e5178e8de4aea20e0602e0d31881c691ab7b4c5f Mon Sep 17 00:00:00 2001 From: malc Date: Sat, 28 Jun 2008 19:13:02 +0000 Subject: Consistency git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4796 c046a42c-6fe2-441c-8c8c-71466251a162 --- qemu-doc.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qemu-doc.texi b/qemu-doc.texi index 80c172c27..e8641178d 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -184,7 +184,7 @@ SMP is supported with up to 255 CPUs. Note that adlib, ac97, gus and cs4231a are only available when QEMU was configured with --audio-card-list option containing the name(s) of -required cards. +required card(s). QEMU uses the PC BIOS from the Bochs project and the Plex86/Bochs LGPL VGA BIOS. -- cgit v1.2.3 From c2de5c91a25eb3dcc73b63f1ce515b8e44d1d011 Mon Sep 17 00:00:00 2001 From: malc Date: Sat, 28 Jun 2008 19:13:06 +0000 Subject: Document usage of new options remove stray variables, check for ALSA/FMOD/ESD git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4797 c046a42c-6fe2-441c-8c8c-71466251a162 --- configure | 101 ++++++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 66 insertions(+), 35 deletions(-) diff --git a/configure b/configure index 05ee62c2a..6a7edb310 100755 --- a/configure +++ b/configure @@ -117,15 +117,18 @@ OS_CFLAGS="-mno-cygwin" if [ "$cpu" = "i386" ] ; then kqemu="yes" fi +audio_possible_drivers="sdl" ;; MINGW32*) mingw32="yes" if [ "$cpu" = "i386" ] ; then kqemu="yes" fi +audio_possible_drivers="dsound sdl fmod" ;; GNU/kFreeBSD) audio_drv_list="oss" +audio_possible_drivers="oss sdl esd" if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then kqemu="yes" fi @@ -133,6 +136,7 @@ fi FreeBSD) bsd="yes" audio_drv_list="oss" +audio_possible_drivers="oss sdl esd" if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then kqemu="yes" fi @@ -140,10 +144,12 @@ fi NetBSD) bsd="yes" audio_drv_list="oss" +audio_possible_drivers="oss sdl esd" ;; OpenBSD) bsd="yes" audio_drv_list="oss" +audio_possible_drivers="oss sdl esd" ;; Darwin) bsd="yes" @@ -151,6 +157,7 @@ darwin="yes" darwin_user="yes" cocoa="yes" audio_drv_list="coreaudio" +audio_possible_drivers="coreaudio sdl fmod" OS_CFLAGS="-mdynamic-no-pic" OS_LDFLAGS="-framework CoreFoundation -framework IOKit" ;; @@ -185,13 +192,16 @@ SunOS) if test -f /usr/include/sys/soundcard.h ; then audio_drv_list="oss" fi + audio_possible_drivers="oss sdl" ;; *) audio_drv_list="oss" +audio_possible_drivers="oss alsa sdl esd" linux="yes" linux_user="yes" if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then kqemu="yes" + audio_possible_drivers="$audio_possible_drivers fmod" fi ;; esac @@ -258,12 +268,12 @@ for opt do ;; --fmod-lib=*) fmod_lib="$optarg" ;; + --fmod-inc=*) fmod_inc="$optarg" + ;; --audio-card-list=*) audio_card_list="$optarg" ;; --audio-drv-list=*) audio_drv_list="$optarg" ;; - --fmod-inc=*) fmod_inc="$optarg" - ;; --disable-vnc-tls) vnc_tls="no" ;; --enable-mingw32) mingw32="yes" ; cross_prefix="i386-mingw32-" ; linux_user="no" @@ -276,7 +286,10 @@ for opt do ;; --enable-profiler) profiler="yes" ;; - --enable-cocoa) cocoa="yes" ; sdl="no" ; + --enable-cocoa) + cocoa="yes" ; + sdl="no" ; + audio_drv_list="coreaudio `echo $audio_drv_list | sed s,coreaudio,,g`" ;; --disable-gfx-check) check_gfx="no" ;; @@ -400,8 +413,10 @@ echo " --disable-werror disable compilation abort on warning" echo " --disable-sdl disable SDL" echo " --enable-cocoa enable COCOA (Mac OS X only)" echo " --enable-mingw32 enable Win32 cross compilation with mingw32" -echo " --audio-drv-list set audio drivers list" -echo " --audio-card-list set list of additional emulated audio cards" +echo " --audio-drv-list=LIST set audio drivers list:" +echo " Available drivers: $audio_possible_drivers" +echo " --audio-card-list=LIST set list of additional emulated audio cards" +echo " Available cards: ac97 adlib cs4231a gus" echo " --enable-mixemu enable mixer emulation" echo " --disable-brlapi disable BrlAPI" echo " --disable-vnc-tls disable TLS encryption for VNC server" @@ -692,7 +707,7 @@ else # Make sure to disable cocoa if sdl was set if test "$sdl" = "yes" ; then cocoa="no" - audio_drv_list="echo $audio_drv_list | sed s,coreaudio,,g" + audio_drv_list="`echo $audio_drv_list | sed s,coreaudio,,g`" fi fi # -z $sdl @@ -707,23 +722,53 @@ if test "$vnc_tls" = "yes" ; then fi ########################################## -# alsa sound support libraries +# Sound support libraries probe -if test "$alsa" = "yes" ; then - cat > $TMPC << EOF -#include -int main(void) { snd_pcm_t **handle; return snd_pcm_close(*handle); } +audio_drv_probe() +{ + drv=$1 + hdr=$2 + lib=$3 + exp=$4 + cfl=$5 + cat > $TMPC << EOF +#include <$hdr> +int main(void) { $exp } EOF - if $cc $ARCH_CFLAGS -o $TMPE $TMPC -lasound 2> /dev/null ; then - : - else - echo - echo "Error: Could not find alsa" - echo "Make sure to have the alsa libs and headers installed." - echo - exit 1 - fi -fi + if $cc $ARCH_CFLAGS $cfl -o $TMPE $TMPC $lib 2> /dev/null ; then + : + else + echo + echo "Error: $drv check failed" + echo "Make sure to have the $drv libs and headers installed." + echo + exit 1 + fi +} + +for drv in $audio_drv_list; do + case $drv in + alsa) + audio_drv_probe $drv alsa/asoundlib.h -lasound \ + "snd_pcm_t **handle; return snd_pcm_close(*handle);" + ;; + + fmod) + if test -z $fmod_lib || test -z $fmod_inc; then + echo + echo "Error: You must specify path to FMOD library and headers" + echo "Example: --fmod-inc=/path/include/fmod --fmod-lib=/path/lib/libfmod-3.74.so" + echo + exit 1 + fi + audio_drv_probe $drv fmod.h $fmod_lib "return FSOUND_GetVersion();" "-I $fmod_inc" + ;; + + esd) + audio_drv_probe $drv esd.h -lesd 'return esd_play_stream(0, 0, "", 0);' + ;; + esac +done ########################################## # BrlAPI probe @@ -809,20 +854,6 @@ echo "mingw32 support $mingw32" echo "Audio drivers $audio_drv_list" echo "Extra audio cards $audio_card_list" echo "Mixer emulation $mixemu" -if test "$fmod" = "yes"; then - if test -z $fmod_lib || test -z $fmod_inc; then - echo - echo "Error: You must specify path to FMOD library and headers" - echo "Example: --fmod-inc=/path/include/fmod --fmod-lib=/path/lib/libfmod-3.74.so" - echo - exit 1 - fi - fmod_support=" (lib='$fmod_lib' include='$fmod_inc')" -else - fmod_support="" -fi -echo "FMOD support $fmod $fmod_support" -echo "OSS support $oss" echo "VNC TLS support $vnc_tls" if test "$vnc_tls" = "yes" ; then echo " TLS CFLAGS $vnc_tls_cflags" -- cgit v1.2.3 From f6e5889e7f581d286cd2153a71c386795a7070ac Mon Sep 17 00:00:00 2001 From: pbrook Date: Sun, 29 Jun 2008 01:00:34 +0000 Subject: Fix shell quoting. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4798 c046a42c-6fe2-441c-8c8c-71466251a162 --- configure | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 6a7edb310..e763d0ef7 100755 --- a/configure +++ b/configure @@ -1033,14 +1033,14 @@ if test "$slirp" = "yes" ; then echo "#define CONFIG_SLIRP 1" >> $config_h fi for card in $audio_card_list; do - def=CONFIG_`echo $card | tr [:lower:] [:upper:]` + def=CONFIG_`echo $card | tr '[:lower:]' '[:upper:]'` echo "$def=yes" >> $config_mak echo "#define $def 1" >> $config_h done echo "#define AUDIO_DRIVERS \\" >> $config_h for drv in $audio_drv_list; do echo " &${drv}_audio_driver, \\" >>$config_h - def=CONFIG_`echo $drv | tr [:lower:] [:upper:]` + def=CONFIG_`echo $drv | tr '[:lower:]' '[:upper:]'` echo "$def=yes" >> $config_mak if test "$drv" == "fmod"; then echo "CONFIG_FMOD_LIB=$fmod_lib" >> $config_mak -- cgit v1.2.3 From 2e70f6efa8b960d3b5401373ad6fa98747bb9578 Mon Sep 17 00:00:00 2001 From: pbrook Date: Sun, 29 Jun 2008 01:03:05 +0000 Subject: Add instruction counter. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4799 c046a42c-6fe2-441c-8c8c-71466251a162 --- cpu-all.h | 2 + cpu-defs.h | 34 +++++-- cpu-exec.c | 93 +++++++++++------ exec-all.h | 33 ++++-- exec.c | 147 +++++++++++++++++++++------ hw/mips_timer.c | 5 + qemu-doc.texi | 11 ++ softmmu_template.h | 22 +++- target-alpha/cpu.h | 2 + target-alpha/translate.c | 33 +++++- target-arm/cpu.h | 2 + target-arm/translate.c | 31 +++++- target-cris/cpu.h | 2 + target-cris/translate.c | 21 +++- target-i386/cpu.h | 2 + target-i386/translate.c | 65 +++++++++++- target-m68k/cpu.h | 2 + target-m68k/translate.c | 21 +++- target-mips/cpu.h | 6 ++ target-mips/translate.c | 51 ++++++++++ target-ppc/cpu.h | 3 + target-ppc/helper.c | 1 + target-ppc/translate.c | 32 +++++- target-sh4/cpu.h | 5 + target-sh4/translate.c | 31 ++++++ target-sparc/cpu.h | 5 + target-sparc/translate.c | 20 +++- translate-all.c | 9 ++ vl.c | 256 +++++++++++++++++++++++++++++++++++++++++------ 29 files changed, 830 insertions(+), 117 deletions(-) diff --git a/cpu-all.h b/cpu-all.h index 6a1612536..0b19ac9e3 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -782,6 +782,8 @@ void cpu_abort(CPUState *env, const char *fmt, ...) __attribute__ ((__noreturn__)); extern CPUState *first_cpu; extern CPUState *cpu_single_env; +extern int64_t qemu_icount; +extern int use_icount; #define CPU_INTERRUPT_EXIT 0x01 /* wants exit from main loop */ #define CPU_INTERRUPT_HARD 0x02 /* hardware interrupt pending */ diff --git a/cpu-defs.h b/cpu-defs.h index e19768604..9621b947d 100644 --- a/cpu-defs.h +++ b/cpu-defs.h @@ -130,17 +130,29 @@ typedef struct CPUTLBEntry { sizeof(target_phys_addr_t))]; } CPUTLBEntry; +#ifdef WORDS_BIGENDIAN +typedef struct icount_decr_u16 { + uint16_t high; + uint16_t low; +} icount_decr_u16; +#else +typedef struct icount_decr_u16 { + uint16_t low; + uint16_t high; +} icount_decr_u16; +#endif + #define CPU_TEMP_BUF_NLONGS 128 #define CPU_COMMON \ struct TranslationBlock *current_tb; /* currently executing TB */ \ /* soft mmu support */ \ - /* in order to avoid passing too many arguments to the memory \ - write helpers, we store some rarely used information in the CPU \ + /* in order to avoid passing too many arguments to the MMIO \ + helpers, we store some rarely used information in the CPU \ context) */ \ - unsigned long mem_write_pc; /* host pc at which the memory was \ - written */ \ - target_ulong mem_write_vaddr; /* target virtual addr at which the \ - memory was written */ \ + unsigned long mem_io_pc; /* host pc at which the memory was \ + accessed */ \ + target_ulong mem_io_vaddr; /* target virtual addr at which the \ + memory was accessed */ \ int halted; /* TRUE if the CPU is in suspend state */ \ /* The meaning of the MMU modes is defined in the target code. */ \ CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE]; \ @@ -149,6 +161,16 @@ typedef struct CPUTLBEntry { /* buffer for temporaries in the code generator */ \ long temp_buf[CPU_TEMP_BUF_NLONGS]; \ \ + int64_t icount_extra; /* Instructions until next timer event. */ \ + /* Number of cycles left, with interrupt flag in high bit. \ + This allows a single read-compare-cbranch-write sequence to test \ + for both decrementer underflow and exceptions. */ \ + union { \ + uint32_t u32; \ + icount_decr_u16 u16; \ + } icount_decr; \ + uint32_t can_do_io; /* nonzero if memory mapped IO is safe. */ \ + \ /* from this point: preserved by CPU reset */ \ /* ice debug support */ \ target_ulong breakpoints[MAX_BREAKPOINTS]; \ diff --git a/cpu-exec.c b/cpu-exec.c index 9d00cffb5..08e10f432 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -82,15 +82,40 @@ void cpu_resume_from_signal(CPUState *env1, void *puc) longjmp(env->jmp_env, 1); } +/* Execute the code without caching the generated code. An interpreter + could be used if available. */ +static void cpu_exec_nocache(int max_cycles, TranslationBlock *orig_tb) +{ + unsigned long next_tb; + TranslationBlock *tb; + + /* Should never happen. + We only end up here when an existing TB is too long. */ + if (max_cycles > CF_COUNT_MASK) + max_cycles = CF_COUNT_MASK; + + tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags, + max_cycles); + env->current_tb = tb; + /* execute the generated code */ + next_tb = tcg_qemu_tb_exec(tb->tc_ptr); + + if ((next_tb & 3) == 2) { + /* Restore PC. This may happen if async event occurs before + the TB starts executing. */ + CPU_PC_FROM_TB(env, tb); + } + tb_phys_invalidate(tb, -1); + tb_free(tb); +} + static TranslationBlock *tb_find_slow(target_ulong pc, target_ulong cs_base, uint64_t flags) { TranslationBlock *tb, **ptb1; - int code_gen_size; unsigned int h; target_ulong phys_pc, phys_page1, phys_page2, virt_page2; - uint8_t *tc_ptr; tb_invalidated_flag = 0; @@ -124,30 +149,8 @@ static TranslationBlock *tb_find_slow(target_ulong pc, ptb1 = &tb->phys_hash_next; } not_found: - /* if no translated code available, then translate it now */ - tb = tb_alloc(pc); - if (!tb) { - /* flush must be done */ - tb_flush(env); - /* cannot fail at this point */ - tb = tb_alloc(pc); - /* don't forget to invalidate previous TB info */ - tb_invalidated_flag = 1; - } - tc_ptr = code_gen_ptr; - tb->tc_ptr = tc_ptr; - tb->cs_base = cs_base; - tb->flags = flags; - cpu_gen_code(env, tb, &code_gen_size); - code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1)); - - /* check next page if needed */ - virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK; - phys_page2 = -1; - if ((pc & TARGET_PAGE_MASK) != virt_page2) { - phys_page2 = get_phys_addr_code(env, virt_page2); - } - tb_link_phys(tb, phys_pc, phys_page2); + /* if no translated code available, then translate it now */ + tb = tb_gen_code(env, pc, cs_base, flags, 0); found: /* we add the TB in the virtual pc hash table */ @@ -583,6 +586,7 @@ int cpu_exec(CPUState *env1) of memory exceptions while generating the code, we must recompute the hash index here */ next_tb = 0; + tb_invalidated_flag = 0; } #ifdef DEBUG_EXEC if ((loglevel & CPU_LOG_EXEC)) { @@ -604,16 +608,45 @@ int cpu_exec(CPUState *env1) } } spin_unlock(&tb_lock); - tc_ptr = tb->tc_ptr; env->current_tb = tb; + while (env->current_tb) { + tc_ptr = tb->tc_ptr; /* execute the generated code */ #if defined(__sparc__) && !defined(HOST_SOLARIS) #undef env - env = cpu_single_env; + env = cpu_single_env; #define env cpu_single_env #endif - next_tb = tcg_qemu_tb_exec(tc_ptr); - env->current_tb = NULL; + next_tb = tcg_qemu_tb_exec(tc_ptr); + env->current_tb = NULL; + if ((next_tb & 3) == 2) { + /* Instruction counter exired. */ + int insns_left; + tb = (TranslationBlock *)(long)(next_tb & ~3); + /* Restore PC. */ + CPU_PC_FROM_TB(env, tb); + insns_left = env->icount_decr.u32; + if (env->icount_extra && insns_left >= 0) { + /* Refill decrementer and continue execution. */ + env->icount_extra += insns_left; + if (env->icount_extra > 0xffff) { + insns_left = 0xffff; + } else { + insns_left = env->icount_extra; + } + env->icount_extra -= insns_left; + env->icount_decr.u16.low = insns_left; + } else { + if (insns_left > 0) { + /* Execute remaining instructions. */ + cpu_exec_nocache(insns_left, tb); + } + env->exception_index = EXCP_INTERRUPT; + next_tb = 0; + cpu_loop_exit(); + } + } + } /* reset soft MMU for next block (it can currently only be set by a memory fault) */ #if defined(USE_KQEMU) diff --git a/exec-all.h b/exec-all.h index 62a939487..b16937000 100644 --- a/exec-all.h +++ b/exec-all.h @@ -27,7 +27,7 @@ #define DISAS_UPDATE 2 /* cpu state was modified dynamically */ #define DISAS_TB_JUMP 3 /* only pc was modified statically */ -struct TranslationBlock; +typedef struct TranslationBlock TranslationBlock; /* XXX: make safe guess about sizes */ #define MAX_OP_PER_INSTR 64 @@ -48,6 +48,7 @@ extern target_ulong gen_opc_pc[OPC_BUF_SIZE]; extern target_ulong gen_opc_npc[OPC_BUF_SIZE]; extern uint8_t gen_opc_cc_op[OPC_BUF_SIZE]; extern uint8_t gen_opc_instr_start[OPC_BUF_SIZE]; +extern uint16_t gen_opc_icount[OPC_BUF_SIZE]; extern target_ulong gen_opc_jump_pc[2]; extern uint32_t gen_opc_hflags[OPC_BUF_SIZE]; @@ -75,6 +76,10 @@ int cpu_restore_state_copy(struct TranslationBlock *tb, CPUState *env, unsigned long searched_pc, void *puc); void cpu_resume_from_signal(CPUState *env1, void *puc); +void cpu_io_recompile(CPUState *env, void *retaddr); +TranslationBlock *tb_gen_code(CPUState *env, + target_ulong pc, target_ulong cs_base, int flags, + int cflags); void cpu_exec_init(CPUState *env); int page_unprotect(target_ulong address, unsigned long pc, void *puc); void tb_invalidate_phys_page_range(target_phys_addr_t start, target_phys_addr_t end, @@ -117,16 +122,15 @@ static inline int tlb_set_page(CPUState *env1, target_ulong vaddr, #define USE_DIRECT_JUMP #endif -typedef struct TranslationBlock { +struct TranslationBlock { target_ulong pc; /* simulated PC corresponding to this block (EIP + CS base) */ target_ulong cs_base; /* CS base for this block */ uint64_t flags; /* flags defining in which context the code was generated */ uint16_t size; /* size of target code for this block (1 <= size <= TARGET_PAGE_SIZE) */ uint16_t cflags; /* compile flags */ -#define CF_TB_FP_USED 0x0002 /* fp ops are used in the TB */ -#define CF_FP_USED 0x0004 /* fp ops are used in the TB or in a chained TB */ -#define CF_SINGLE_INSN 0x0008 /* compile only a single instruction */ +#define CF_COUNT_MASK 0x7fff +#define CF_LAST_IO 0x8000 /* Last insn may be an IO access. */ uint8_t *tc_ptr; /* pointer to the translated code */ /* next matching tb for physical address. */ @@ -150,7 +154,8 @@ typedef struct TranslationBlock { jmp_first */ struct TranslationBlock *jmp_next[2]; struct TranslationBlock *jmp_first; -} TranslationBlock; + uint32_t icount; +}; static inline unsigned int tb_jmp_cache_hash_page(target_ulong pc) { @@ -173,9 +178,11 @@ static inline unsigned int tb_phys_hash_func(unsigned long pc) } TranslationBlock *tb_alloc(target_ulong pc); +void tb_free(TranslationBlock *tb); void tb_flush(CPUState *env); void tb_link_phys(TranslationBlock *tb, target_ulong phys_pc, target_ulong phys_page2); +void tb_phys_invalidate(TranslationBlock *tb, target_ulong page_addr); extern TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE]; extern uint8_t *code_gen_ptr; @@ -364,6 +371,20 @@ static inline target_ulong get_phys_addr_code(CPUState *env1, target_ulong addr) } return addr + env1->tlb_table[mmu_idx][page_index].addend - (unsigned long)phys_ram_base; } + +/* Deterministic execution requires that IO only be performaed on the last + instruction of a TB so that interrupts take effect immediately. */ +static inline int can_do_io(CPUState *env) +{ + if (!use_icount) + return 1; + + /* If not executing code then assume we are ok. */ + if (!env->current_tb) + return 1; + + return env->can_do_io != 0; +} #endif #ifdef USE_KQEMU diff --git a/exec.c b/exec.c index 48600e49a..06d92538f 100644 --- a/exec.c +++ b/exec.c @@ -107,6 +107,13 @@ CPUState *first_cpu; /* current CPU in the current thread. It is only valid inside cpu_exec() */ CPUState *cpu_single_env; +/* 0 = Do not count executed instructions. + 1 = Precice instruction counting. + 2 = Adaptive rate instruction counting. */ +int use_icount = 0; +/* Current instruction counter. While executing translated code this may + include some instructions that have not yet been executed. */ +int64_t qemu_icount; typedef struct PageDesc { /* list of TBs intersecting this ram page */ @@ -633,7 +640,7 @@ static inline void tb_reset_jump(TranslationBlock *tb, int n) tb_set_jmp_target(tb, n, (unsigned long)(tb->tc_ptr + tb->tb_next_offset[n])); } -static inline void tb_phys_invalidate(TranslationBlock *tb, target_ulong page_addr) +void tb_phys_invalidate(TranslationBlock *tb, target_ulong page_addr) { CPUState *env; PageDesc *p; @@ -746,11 +753,9 @@ static void build_page_bitmap(PageDesc *p) } } -#ifdef TARGET_HAS_PRECISE_SMC - -static void tb_gen_code(CPUState *env, - target_ulong pc, target_ulong cs_base, int flags, - int cflags) +TranslationBlock *tb_gen_code(CPUState *env, + target_ulong pc, target_ulong cs_base, + int flags, int cflags) { TranslationBlock *tb; uint8_t *tc_ptr; @@ -764,6 +769,8 @@ static void tb_gen_code(CPUState *env, tb_flush(env); /* cannot fail at this point */ tb = tb_alloc(pc); + /* Don't forget to invalidate previous TB info. */ + tb_invalidated_flag = 1; } tc_ptr = code_gen_ptr; tb->tc_ptr = tc_ptr; @@ -780,8 +787,8 @@ static void tb_gen_code(CPUState *env, phys_page2 = get_phys_addr_code(env, virt_page2); } tb_link_phys(tb, phys_pc, phys_page2); + return tb; } -#endif /* invalidate all TBs which intersect with the target physical page starting in range [start;end[. NOTE: start and end must refer to @@ -836,13 +843,13 @@ void tb_invalidate_phys_page_range(target_phys_addr_t start, target_phys_addr_t if (current_tb_not_found) { current_tb_not_found = 0; current_tb = NULL; - if (env->mem_write_pc) { + if (env->mem_io_pc) { /* now we have a real cpu fault */ - current_tb = tb_find_pc(env->mem_write_pc); + current_tb = tb_find_pc(env->mem_io_pc); } } if (current_tb == tb && - !(current_tb->cflags & CF_SINGLE_INSN)) { + (current_tb->cflags & CF_COUNT_MASK) != 1) { /* If we are modifying the current TB, we must stop its execution. We could be more precise by checking that the modification is after the current PC, but it @@ -851,7 +858,7 @@ void tb_invalidate_phys_page_range(target_phys_addr_t start, target_phys_addr_t current_tb_modified = 1; cpu_restore_state(current_tb, env, - env->mem_write_pc, NULL); + env->mem_io_pc, NULL); #if defined(TARGET_I386) current_flags = env->hflags; current_flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK)); @@ -883,7 +890,7 @@ void tb_invalidate_phys_page_range(target_phys_addr_t start, target_phys_addr_t if (!p->first_tb) { invalidate_page_bitmap(p); if (is_cpu_write_access) { - tlb_unprotect_code_phys(env, start, env->mem_write_vaddr); + tlb_unprotect_code_phys(env, start, env->mem_io_vaddr); } } #endif @@ -893,8 +900,7 @@ void tb_invalidate_phys_page_range(target_phys_addr_t start, target_phys_addr_t modifying the memory. It will ensure that it cannot modify itself */ env->current_tb = NULL; - tb_gen_code(env, current_pc, current_cs_base, current_flags, - CF_SINGLE_INSN); + tb_gen_code(env, current_pc, current_cs_base, current_flags, 1); cpu_resume_from_signal(env, NULL); } #endif @@ -909,7 +915,7 @@ static inline void tb_invalidate_phys_page_fast(target_phys_addr_t start, int le if (1) { if (loglevel) { fprintf(logfile, "modifying code at 0x%x size=%d EIP=%x PC=%08x\n", - cpu_single_env->mem_write_vaddr, len, + cpu_single_env->mem_io_vaddr, len, cpu_single_env->eip, cpu_single_env->eip + (long)cpu_single_env->segs[R_CS].base); } @@ -961,7 +967,7 @@ static void tb_invalidate_phys_page(target_phys_addr_t addr, tb = (TranslationBlock *)((long)tb & ~3); #ifdef TARGET_HAS_PRECISE_SMC if (current_tb == tb && - !(current_tb->cflags & CF_SINGLE_INSN)) { + (current_tb->cflags & CF_COUNT_MASK) != 1) { /* If we are modifying the current TB, we must stop its execution. We could be more precise by checking that the modification is after the current PC, but it @@ -990,8 +996,7 @@ static void tb_invalidate_phys_page(target_phys_addr_t addr, modifying the memory. It will ensure that it cannot modify itself */ env->current_tb = NULL; - tb_gen_code(env, current_pc, current_cs_base, current_flags, - CF_SINGLE_INSN); + tb_gen_code(env, current_pc, current_cs_base, current_flags, 1); cpu_resume_from_signal(env, puc); } #endif @@ -1068,6 +1073,17 @@ TranslationBlock *tb_alloc(target_ulong pc) return tb; } +void tb_free(TranslationBlock *tb) +{ + /* In practice this is mostly used for single use temorary TB + Ignore the hard cases and just back up if this TB happens to + be the last one generated. */ + if (nb_tbs > 0 && tb == &tbs[nb_tbs - 1]) { + code_gen_ptr = tb->tc_ptr; + nb_tbs--; + } +} + /* add a new TB and link it to the physical page tables. phys_page2 is (-1) to indicate that only one page contains the TB. */ void tb_link_phys(TranslationBlock *tb, @@ -1369,7 +1385,9 @@ void cpu_interrupt(CPUState *env, int mask) TranslationBlock *tb; static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED; #endif + int old_mask; + old_mask = env->interrupt_request; /* FIXME: This is probably not threadsafe. A different thread could be in the mittle of a read-modify-write operation. */ env->interrupt_request |= mask; @@ -1379,13 +1397,25 @@ void cpu_interrupt(CPUState *env, int mask) emulation this often isn't actually as bad as it sounds. Often signals are used primarily to interrupt blocking syscalls. */ #else - /* if the cpu is currently executing code, we must unlink it and - all the potentially executing TB */ - tb = env->current_tb; - if (tb && !testandset(&interrupt_lock)) { - env->current_tb = NULL; - tb_reset_jump_recursive(tb); - resetlock(&interrupt_lock); + if (use_icount) { + env->icount_decr.u16.high = 0x8000; +#ifndef CONFIG_USER_ONLY + /* CPU_INTERRUPT_EXIT isn't a real interrupt. It just means + an async event happened and we need to process it. */ + if (!can_do_io(env) + && (mask & ~(old_mask | CPU_INTERRUPT_EXIT)) != 0) { + cpu_abort(env, "Raised interrupt while not in I/O function"); + } +#endif + } else { + tb = env->current_tb; + /* if the cpu is currently executing code, we must unlink it and + all the potentially executing TB */ + if (tb && !testandset(&interrupt_lock)) { + env->current_tb = NULL; + tb_reset_jump_recursive(tb); + resetlock(&interrupt_lock); + } } #endif } @@ -2227,7 +2257,7 @@ static void notdirty_mem_writeb(void *opaque, target_phys_addr_t ram_addr, /* we remove the notdirty callback only if the code has been flushed */ if (dirty_flags == 0xff) - tlb_set_dirty(cpu_single_env, cpu_single_env->mem_write_vaddr); + tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr); } static void notdirty_mem_writew(void *opaque, target_phys_addr_t ram_addr, @@ -2252,7 +2282,7 @@ static void notdirty_mem_writew(void *opaque, target_phys_addr_t ram_addr, /* we remove the notdirty callback only if the code has been flushed */ if (dirty_flags == 0xff) - tlb_set_dirty(cpu_single_env, cpu_single_env->mem_write_vaddr); + tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr); } static void notdirty_mem_writel(void *opaque, target_phys_addr_t ram_addr, @@ -2277,7 +2307,7 @@ static void notdirty_mem_writel(void *opaque, target_phys_addr_t ram_addr, /* we remove the notdirty callback only if the code has been flushed */ if (dirty_flags == 0xff) - tlb_set_dirty(cpu_single_env, cpu_single_env->mem_write_vaddr); + tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr); } static CPUReadMemoryFunc *error_mem_read[3] = { @@ -2299,7 +2329,7 @@ static void check_watchpoint(int offset, int flags) target_ulong vaddr; int i; - vaddr = (env->mem_write_vaddr & TARGET_PAGE_MASK) + offset; + vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset; for (i = 0; i < env->nb_watchpoints; i++) { if (vaddr == env->watchpoint[i].vaddr && (env->watchpoint[i].type & flags)) { @@ -2967,6 +2997,65 @@ int cpu_memory_rw_debug(CPUState *env, target_ulong addr, return 0; } +/* in deterministic execution mode, instructions doing device I/Os + must be at the end of the TB */ +void cpu_io_recompile(CPUState *env, void *retaddr) +{ + TranslationBlock *tb; + uint32_t n, cflags; + target_ulong pc, cs_base; + uint64_t flags; + + tb = tb_find_pc((unsigned long)retaddr); + if (!tb) { + cpu_abort(env, "cpu_io_recompile: could not find TB for pc=%p", + retaddr); + } + n = env->icount_decr.u16.low + tb->icount; + cpu_restore_state(tb, env, (unsigned long)retaddr, NULL); + /* Calculate how many instructions had been executed before the fault + occured. */ + n = n - env->icount_decr.u16.low; + /* Generate a new TB ending on the I/O insn. */ + n++; + /* On MIPS and SH, delay slot instructions can only be restarted if + they were already the first instruction in the TB. If this is not + the first instruction in a TB then re-execute the preceeding + branch. */ +#if defined(TARGET_MIPS) + if ((env->hflags & MIPS_HFLAG_BMASK) != 0 && n > 1) { + env->active_tc.PC -= 4; + env->icount_decr.u16.low++; + env->hflags &= ~MIPS_HFLAG_BMASK; + } +#elif defined(TARGET_SH4) + if ((env->flags & ((DELAY_SLOT | DELAY_SLOT_CONDITIONAL))) != 0 + && n > 1) { + env->pc -= 2; + env->icount_decr.u16.low++; + env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL); + } +#endif + /* This should never happen. */ + if (n > CF_COUNT_MASK) + cpu_abort(env, "TB too big during recompile"); + + cflags = n | CF_LAST_IO; + pc = tb->pc; + cs_base = tb->cs_base; + flags = tb->flags; + tb_phys_invalidate(tb, -1); + /* FIXME: In theory this could raise an exception. In practice + we have already translated the block once so it's probably ok. */ + tb_gen_code(env, pc, cs_base, flags, cflags); + /* TODO: If env->pc != tb->pc (i.e. the failuting instruction was not + the first in the TB) then we end up generating a whole new TB and + repeating the fault, which is horribly inefficient. + Better would be to execute just this insn uncached, or generate a + second new TB. */ + cpu_resume_from_signal(env, NULL); +} + void dump_exec_info(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...)) { diff --git a/hw/mips_timer.c b/hw/mips_timer.c index 5b172ea42..5549e2483 100644 --- a/hw/mips_timer.c +++ b/hw/mips_timer.c @@ -91,7 +91,12 @@ static void mips_timer_cb (void *opaque) if (env->CP0_Cause & (1 << CP0Ca_DC)) return; + /* ??? This callback should occur when the counter is exactly equal to + 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); + 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]); diff --git a/qemu-doc.texi b/qemu-doc.texi index e8641178d..057b9f655 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -965,6 +965,17 @@ On M68K this implements the "ColdFire GDB" interface used by libgloss. Note that this allows guest direct access to the host filesystem, so should only be used with trusted guest OS. + +@item -icount [N|auto] +Enable virtual instruction counter. The virtual cpu will execute one +instruction every 2^N ns of virtual time. If @code{auto} is specified +then the virtual cpu speed will be automatically adjusted to keep virtual +time within a few seconds of real time. + +Note that while this option can give deterministic behavior, it does not +provide cycle accurate emulation. Modern CPUs contain superscalar out of +order cores with complex cache heirachies. The number of instructions +executed often has little or no correlation with actual performance. @end table @c man end diff --git a/softmmu_template.h b/softmmu_template.h index 934df5286..98dd37881 100644 --- a/softmmu_template.h +++ b/softmmu_template.h @@ -51,12 +51,18 @@ static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr, int mmu_idx, void *retaddr); static inline DATA_TYPE glue(io_read, SUFFIX)(target_phys_addr_t physaddr, - target_ulong addr) + target_ulong addr, + void *retaddr) { DATA_TYPE res; int index; index = (physaddr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); physaddr = (physaddr & TARGET_PAGE_MASK) + addr; + env->mem_io_pc = (unsigned long)retaddr; + if (index > (IO_MEM_NOTDIRTY >> IO_MEM_SHIFT) + && !can_do_io(env)) { + cpu_io_recompile(env, retaddr); + } #if SHIFT <= 2 res = io_mem_read[index][SHIFT](io_mem_opaque[index], physaddr); @@ -95,8 +101,9 @@ DATA_TYPE REGPARM glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr, /* IO access */ if ((addr & (DATA_SIZE - 1)) != 0) goto do_unaligned_access; + retaddr = GETPC(); addend = env->iotlb[mmu_idx][index]; - res = glue(io_read, SUFFIX)(addend, addr); + res = glue(io_read, SUFFIX)(addend, addr, retaddr); } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) { /* slow unaligned access (it spans two pages or IO) */ do_unaligned_access: @@ -148,8 +155,9 @@ static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr, /* IO access */ if ((addr & (DATA_SIZE - 1)) != 0) goto do_unaligned_access; + retaddr = GETPC(); addend = env->iotlb[mmu_idx][index]; - res = glue(io_read, SUFFIX)(addend, addr); + res = glue(io_read, SUFFIX)(addend, addr, retaddr); } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) { do_unaligned_access: /* slow unaligned access (it spans two pages) */ @@ -194,9 +202,13 @@ static inline void glue(io_write, SUFFIX)(target_phys_addr_t physaddr, int index; index = (physaddr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); physaddr = (physaddr & TARGET_PAGE_MASK) + addr; + if (index > (IO_MEM_NOTDIRTY >> IO_MEM_SHIFT) + && !can_do_io(env)) { + cpu_io_recompile(env, retaddr); + } - env->mem_write_vaddr = addr; - env->mem_write_pc = (unsigned long)retaddr; + env->mem_io_vaddr = addr; + env->mem_io_pc = (unsigned long)retaddr; #if SHIFT <= 2 io_mem_write[index][SHIFT](io_mem_opaque[index], physaddr, val); #else diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h index e9b2b0757..bdd0ae612 100644 --- a/target-alpha/cpu.h +++ b/target-alpha/cpu.h @@ -415,4 +415,6 @@ void cpu_loop_exit (void); void pal_init (CPUState *env); void call_pal (CPUState *env, int palcode); +#define CPU_PC_FROM_TB(env, tb) env->pc = tb->pc + #endif /* !defined (__CPU_ALPHA_H__) */ diff --git a/target-alpha/translate.c b/target-alpha/translate.c index a3991022e..4a741573d 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -43,6 +43,19 @@ struct DisasContext { uint32_t amask; }; +TCGv cpu_env; + +#include "gen-icount.h" + +void alpha_translate_init() +{ + static int done_init = 0; + if (done_init) + return; + cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env"); + done_init = 1; +} + static always_inline void gen_op_nop (void) { #if defined(GENERATE_NOP) @@ -1970,6 +1983,8 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, uint16_t *gen_opc_end; int j, lj = -1; int ret; + int num_insns; + int max_insns; pc_start = tb->pc; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; @@ -1981,6 +1996,12 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, ctx.mem_idx = ((env->ps >> 3) & 3); ctx.pal_mode = env->ipr[IPR_EXC_ADDR] & 1; #endif + num_insns = 0; + max_insns = tb->cflags & CF_COUNT_MASK; + if (max_insns == 0) + max_insns = CF_COUNT_MASK; + + gen_icount_start(); for (ret = 0; ret == 0;) { if (env->nb_breakpoints > 0) { for(j = 0; j < env->nb_breakpoints; j++) { @@ -1998,8 +2019,11 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, gen_opc_instr_start[lj++] = 0; gen_opc_pc[lj] = ctx.pc; gen_opc_instr_start[lj] = 1; + gen_opc_icount[lj] = num_insns; } } + if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) + gen_io_start(); #if defined ALPHA_DEBUG_DISAS insn_count++; if (logfile != NULL) { @@ -2014,6 +2038,7 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, fprintf(logfile, "opcode %08x %d\n", insn, insn_count); } #endif + num_insns++; ctx.pc += 4; ret = translate_one(ctxp, insn); if (ret != 0) @@ -2022,7 +2047,8 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, * generation */ if (((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0) || - (env->singlestep_enabled)) { + (env->singlestep_enabled) || + num_insns >= max_insns) { break; } #if defined (DO_SINGLE_STEP) @@ -2035,8 +2061,11 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, #if defined (DO_TB_FLUSH) gen_op_tb_flush(); #endif + if (tb->cflags & CF_LAST_IO) + gen_io_end(); /* Generate the return instruction */ tcg_gen_exit_tb(0); + gen_icount_end(tb, num_insns); *gen_opc_ptr = INDEX_op_end; if (search_pc) { j = gen_opc_ptr - gen_opc_buf; @@ -2045,6 +2074,7 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, gen_opc_instr_start[lj++] = 0; } else { tb->size = ctx.pc - pc_start; + tb->icount = num_insns; } #if defined ALPHA_DEBUG_DISAS if (loglevel & CPU_LOG_TB_CPU) { @@ -2079,6 +2109,7 @@ CPUAlphaState * cpu_alpha_init (const char *cpu_model) if (!env) return NULL; cpu_exec_init(env); + alpha_translate_init(); tlb_flush(env, 1); /* XXX: should not be hardcoded */ env->implver = IMPLVER_2106x; diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 5005bf6dd..6b16e5d04 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -417,6 +417,8 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp) } #endif +#define CPU_PC_FROM_TB(env, tb) env->regs[15] = tb->pc + #include "cpu-all.h" #endif diff --git a/target-arm/translate.c b/target-arm/translate.c index 91328c813..701745225 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -84,6 +84,9 @@ static TCGv cpu_V0, cpu_V1, cpu_M0; static TCGv cpu_T[2]; static TCGv cpu_F0s, cpu_F1s, cpu_F0d, cpu_F1d; +#define ICOUNT_TEMP cpu_T[0] +#include "gen-icount.h" + /* initialize TCG globals. */ void arm_translate_init(void) { @@ -8539,6 +8542,8 @@ static inline int gen_intermediate_code_internal(CPUState *env, int j, lj; target_ulong pc_start; uint32_t next_page_start; + int num_insns; + int max_insns; /* generate intermediate code */ num_temps = 0; @@ -8575,6 +8580,12 @@ static inline int gen_intermediate_code_internal(CPUState *env, cpu_M0 = tcg_temp_new(TCG_TYPE_I64); next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; lj = -1; + num_insns = 0; + max_insns = tb->cflags & CF_COUNT_MASK; + if (max_insns == 0) + max_insns = CF_COUNT_MASK; + + gen_icount_start(); /* Reset the conditional execution bits immediately. This avoids complications trying to do it at the end of the block. */ if (env->condexec_bits) @@ -8625,8 +8636,12 @@ static inline int gen_intermediate_code_internal(CPUState *env, } gen_opc_pc[lj] = dc->pc; gen_opc_instr_start[lj] = 1; + gen_opc_icount[lj] = num_insns; } + if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) + gen_io_start(); + if (env->thumb) { disas_thumb_insn(env, dc); if (dc->condexec_mask) { @@ -8659,9 +8674,20 @@ static inline int gen_intermediate_code_internal(CPUState *env, * Otherwise the subsequent code could get translated several times. * Also stop translation when a page boundary is reached. This * ensures prefech aborts occur at the right place. */ + num_insns ++; } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && !env->singlestep_enabled && - dc->pc < next_page_start); + dc->pc < next_page_start && + num_insns < max_insns); + + if (tb->cflags & CF_LAST_IO) { + if (dc->condjmp) { + /* FIXME: This can theoretically happen with self-modifying + code. */ + cpu_abort(env, "IO on conditional branch instruction"); + } + gen_io_end(); + } /* At this stage dc->condjmp will only be set when the skipped instruction was a conditional branch or trap, and the PC has @@ -8726,7 +8752,9 @@ static inline int gen_intermediate_code_internal(CPUState *env, dc->condjmp = 0; } } + done_generating: + gen_icount_end(tb, num_insns); *gen_opc_ptr = INDEX_op_end; #ifdef DEBUG_DISAS @@ -8744,6 +8772,7 @@ done_generating: gen_opc_instr_start[lj++] = 0; } else { tb->size = dc->pc - pc_start; + tb->icount = num_insns; } return 0; } diff --git a/target-cris/cpu.h b/target-cris/cpu.h index 447e780b2..d086221d3 100644 --- a/target-cris/cpu.h +++ b/target-cris/cpu.h @@ -238,5 +238,7 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp) #define SFR_RW_MM_TLB_LO env->pregs[PR_SRS]][5 #define SFR_RW_MM_TLB_HI env->pregs[PR_SRS]][6 +#define CPU_PC_FROM_TB(env, tb) env->pc = tb->pc + #include "cpu-all.h" #endif diff --git a/target-cris/translate.c b/target-cris/translate.c index cd0c2e15f..c3b8adef8 100644 --- a/target-cris/translate.c +++ b/target-cris/translate.c @@ -77,6 +77,8 @@ TCGv env_btaken; TCGv env_btarget; TCGv env_pc; +#include "gen-icount.h" + /* This is the state at translation time. */ typedef struct DisasContext { CPUState *env; @@ -3032,6 +3034,8 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, struct DisasContext *dc = &ctx; uint32_t next_page_start; target_ulong npc; + int num_insns; + int max_insns; if (!logfile) logfile = stderr; @@ -3092,6 +3096,12 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; lj = -1; + num_insns = 0; + max_insns = tb->cflags & CF_COUNT_MASK; + if (max_insns == 0) + max_insns = CF_COUNT_MASK; + + gen_icount_start(); do { check_breakpoint(env, dc); @@ -3108,6 +3118,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, else gen_opc_pc[lj] = dc->pc; gen_opc_instr_start[lj] = 1; + gen_opc_icount[lj] = num_insns; } /* Pretty disas. */ @@ -3116,6 +3127,8 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, DIS(fprintf(logfile, "%x ", dc->pc)); } + if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) + gen_io_start(); dc->clear_x = 1; if (unlikely(loglevel & CPU_LOG_TB_OP)) tcg_gen_debug_insn_start(dc->pc); @@ -3125,6 +3138,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, if (dc->clear_x) cris_clear_x_flag(dc); + num_insns++; /* Check for delayed branches here. If we do it before actually genereating any host code, the simulator will just loop doing nothing for on this program location. */ @@ -3151,12 +3165,15 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, if (!(tb->pc & 1) && env->singlestep_enabled) break; } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end - && (dc->pc < next_page_start)); + && (dc->pc < next_page_start) + && num_insns < max_insns); npc = dc->pc; if (dc->jmp == JMP_DIRECT && !dc->delayed_branch) npc = dc->jmp_pc; + if (tb->cflags & CF_LAST_IO) + gen_io_end(); /* Force an update if the per-tb cpu state has changed. */ if (dc->is_jmp == DISAS_NEXT && (dc->cpustate_changed || !dc->flagx_known @@ -3194,6 +3211,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, break; } } + gen_icount_end(tb, num_insns); *gen_opc_ptr = INDEX_op_end; if (search_pc) { j = gen_opc_ptr - gen_opc_buf; @@ -3202,6 +3220,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, gen_opc_instr_start[lj++] = 0; } else { tb->size = dc->pc - pc_start; + tb->icount = num_insns; } #ifdef DEBUG_DISAS diff --git a/target-i386/cpu.h b/target-i386/cpu.h index d80ffb871..285b5a750 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -753,6 +753,8 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp) } #endif +#define CPU_PC_FROM_TB(env, tb) env->eip = tb->pc - tb->cs_base + #include "cpu-all.h" #include "svm.h" diff --git a/target-i386/translate.c b/target-i386/translate.c index 6f9c25672..ea0933ef5 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -65,6 +65,8 @@ static TCGv cpu_T[2], cpu_T3; static TCGv cpu_tmp0, cpu_tmp1_i64, cpu_tmp2_i32, cpu_tmp3_i32, cpu_tmp4, cpu_ptr0, cpu_ptr1; static TCGv cpu_tmp5, cpu_tmp6; +#include "gen-icount.h" + #ifdef TARGET_X86_64 static int x86_64_hregs; #endif @@ -1203,6 +1205,8 @@ static inline void gen_cmps(DisasContext *s, int ot) static inline void gen_ins(DisasContext *s, int ot) { + if (use_icount) + gen_io_start(); gen_string_movl_A0_EDI(s); /* Note: we must do this dummy write first to be restartable in case of page fault. */ @@ -1215,10 +1219,14 @@ static inline void gen_ins(DisasContext *s, int ot) gen_op_st_T0_A0(ot + s->mem_index); gen_op_movl_T0_Dshift(ot); gen_op_add_reg_T0(s->aflag, R_EDI); + if (use_icount) + gen_io_end(); } static inline void gen_outs(DisasContext *s, int ot) { + if (use_icount) + gen_io_start(); gen_string_movl_A0_ESI(s); gen_op_ld_T0_A0(ot + s->mem_index); @@ -1230,6 +1238,8 @@ static inline void gen_outs(DisasContext *s, int ot) gen_op_movl_T0_Dshift(ot); gen_op_add_reg_T0(s->aflag, R_ESI); + if (use_icount) + gen_io_end(); } /* same method as Valgrind : we generate jumps to current or next @@ -5570,6 +5580,9 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); } else { gen_ins(s, ot); + if (use_icount) { + gen_jmp(s, s->pc - s->cs_base); + } } break; case 0x6e: /* outsS */ @@ -5586,6 +5599,9 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); } else { gen_outs(s, ot); + if (use_icount) { + gen_jmp(s, s->pc - s->cs_base); + } } break; @@ -5602,9 +5618,15 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_op_movl_T0_im(val); gen_check_io(s, ot, pc_start - s->cs_base, SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes)); + if (use_icount) + gen_io_start(); tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); tcg_gen_helper_1_1(helper_in_func[ot], cpu_T[1], cpu_tmp2_i32); gen_op_mov_reg_T1(ot, R_EAX); + if (use_icount) { + gen_io_end(); + gen_jmp(s, s->pc - s->cs_base); + } break; case 0xe6: case 0xe7: @@ -5618,10 +5640,16 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) svm_is_rep(prefixes)); gen_op_mov_TN_reg(ot, 1, R_EAX); + if (use_icount) + gen_io_start(); tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff); tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]); tcg_gen_helper_0_2(helper_out_func[ot], cpu_tmp2_i32, cpu_tmp3_i32); + if (use_icount) { + gen_io_end(); + gen_jmp(s, s->pc - s->cs_base); + } break; case 0xec: case 0xed: @@ -5633,9 +5661,15 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_op_andl_T0_ffff(); gen_check_io(s, ot, pc_start - s->cs_base, SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes)); + if (use_icount) + gen_io_start(); tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); tcg_gen_helper_1_1(helper_in_func[ot], cpu_T[1], cpu_tmp2_i32); gen_op_mov_reg_T1(ot, R_EAX); + if (use_icount) { + gen_io_end(); + gen_jmp(s, s->pc - s->cs_base); + } break; case 0xee: case 0xef: @@ -5649,10 +5683,16 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) svm_is_rep(prefixes)); gen_op_mov_TN_reg(ot, 1, R_EAX); + if (use_icount) + gen_io_start(); tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff); tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]); tcg_gen_helper_0_2(helper_out_func[ot], cpu_tmp2_i32, cpu_tmp3_i32); + if (use_icount) { + gen_io_end(); + gen_jmp(s, s->pc - s->cs_base); + } break; /************************/ @@ -7109,6 +7149,8 @@ static inline int gen_intermediate_code_internal(CPUState *env, uint64_t flags; target_ulong pc_start; target_ulong cs_base; + int num_insns; + int max_insns; /* generate intermediate code */ pc_start = tb->pc; @@ -7179,7 +7221,12 @@ static inline int gen_intermediate_code_internal(CPUState *env, dc->is_jmp = DISAS_NEXT; pc_ptr = pc_start; lj = -1; + num_insns = 0; + max_insns = tb->cflags & CF_COUNT_MASK; + if (max_insns == 0) + max_insns = CF_COUNT_MASK; + gen_icount_start(); for(;;) { if (env->nb_breakpoints > 0) { for(j = 0; j < env->nb_breakpoints; j++) { @@ -7199,8 +7246,13 @@ static inline int gen_intermediate_code_internal(CPUState *env, gen_opc_pc[lj] = pc_ptr; gen_opc_cc_op[lj] = dc->cc_op; gen_opc_instr_start[lj] = 1; + gen_opc_icount[lj] = num_insns; } + if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) + gen_io_start(); + pc_ptr = disas_insn(dc, pc_ptr); + num_insns++; /* stop translation if indicated */ if (dc->is_jmp) break; @@ -7210,20 +7262,23 @@ static inline int gen_intermediate_code_internal(CPUState *env, the flag and abort the translation to give the irqs a change to be happen */ if (dc->tf || dc->singlestep_enabled || - (flags & HF_INHIBIT_IRQ_MASK) || - (cflags & CF_SINGLE_INSN)) { + (flags & HF_INHIBIT_IRQ_MASK)) { gen_jmp_im(pc_ptr - dc->cs_base); gen_eob(dc); break; } /* if too long translation, stop generation too */ if (gen_opc_ptr >= gen_opc_end || - (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32)) { + (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32) || + num_insns >= max_insns) { gen_jmp_im(pc_ptr - dc->cs_base); gen_eob(dc); break; } } + if (tb->cflags & CF_LAST_IO) + gen_io_end(); + gen_icount_end(tb, num_insns); *gen_opc_ptr = INDEX_op_end; /* we don't forget to fill the last values */ if (search_pc) { @@ -7252,8 +7307,10 @@ static inline int gen_intermediate_code_internal(CPUState *env, } #endif - if (!search_pc) + if (!search_pc) { tb->size = pc_ptr - pc_start; + tb->icount = num_insns; + } return 0; } diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h index cfeafc003..aaf9e4263 100644 --- a/target-m68k/cpu.h +++ b/target-m68k/cpu.h @@ -235,6 +235,8 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp) } #endif +#define CPU_PC_FROM_TB(env, tb) env->pc = tb->pc + #include "cpu-all.h" #endif diff --git a/target-m68k/translate.c b/target-m68k/translate.c index 0d603bdf5..a920d213b 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -63,6 +63,8 @@ static TCGv NULL_QREG; /* Used to distinguish stores from bad addressing modes. */ static TCGv store_dummy; +#include "gen-icount.h" + void m68k_tcg_init(void) { char *p; @@ -2919,6 +2921,8 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, target_ulong pc_start; int pc_offset; int last_cc_op; + int num_insns; + int max_insns; /* generate intermediate code */ pc_start = tb->pc; @@ -2937,6 +2941,12 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, dc->is_mem = 0; dc->mactmp = NULL_QREG; lj = -1; + num_insns = 0; + max_insns = tb->cflags & CF_COUNT_MASK; + if (max_insns == 0) + max_insns = CF_COUNT_MASK; + + gen_icount_start(); do { pc_offset = dc->pc - pc_start; gen_throws_exception = NULL; @@ -2960,10 +2970,14 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, } gen_opc_pc[lj] = dc->pc; gen_opc_instr_start[lj] = 1; + gen_opc_icount[lj] = num_insns; } + if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) + gen_io_start(); last_cc_op = dc->cc_op; dc->insn_pc = dc->pc; disas_m68k_insn(env, dc); + num_insns++; /* Terminate the TB on memory ops if watchpoints are present. */ /* FIXME: This should be replacd by the deterministic execution @@ -2972,8 +2986,11 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, break; } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && !env->singlestep_enabled && - (pc_offset) < (TARGET_PAGE_SIZE - 32)); + (pc_offset) < (TARGET_PAGE_SIZE - 32) && + num_insns < max_insns); + if (tb->cflags & CF_LAST_IO) + gen_io_end(); if (__builtin_expect(env->singlestep_enabled, 0)) { /* Make sure the pc is updated, and raise a debug exception. */ if (!dc->is_jmp) { @@ -2999,6 +3016,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, break; } } + gen_icount_end(tb, num_insns); *gen_opc_ptr = INDEX_op_end; #ifdef DEBUG_DISAS @@ -3016,6 +3034,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, gen_opc_instr_start[lj++] = 0; } else { tb->size = dc->pc - pc_start; + tb->icount = num_insns; } //optimize_flags(); diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 78851ed93..8e21f6b4a 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -572,4 +572,10 @@ CPUMIPSState *cpu_mips_init(const char *cpu_model); uint32_t cpu_mips_get_clock (void); int cpu_mips_signal_handler(int host_signum, void *pinfo, void *puc); +#define CPU_PC_FROM_TB(env, tb) do { \ + env->active_tc.PC = tb->pc; \ + env->hflags &= ~MIPS_HFLAG_BMASK; \ + env->hflags |= tb->flags & MIPS_HFLAG_BMASK; \ + } while (0) + #endif /* !defined (__MIPS_CPU_H__) */ diff --git a/target-mips/translate.c b/target-mips/translate.c index 9c97b9c48..67fbbedf7 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -428,6 +428,8 @@ static TCGv cpu_env, current_fpu; /* FPU TNs, global for now. */ static TCGv fpu32_T[3], fpu64_T[3], fpu32h_T[3]; +#include "gen-icount.h" + static inline void tcg_gen_helper_0_i(void *func, TCGv arg) { TCGv tmp = tcg_const_i32(arg); @@ -3061,7 +3063,14 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int se case 9: switch (sel) { case 0: + /* Mark as an IO operation because we read the time. */ + if (use_icount) + gen_io_start(); tcg_gen_helper_1_0(do_mfc0_count, t0); + if (use_icount) { + gen_io_end(); + ctx->bstate = BS_STOP; + } rn = "Count"; break; /* 6,7 are implementation dependent */ @@ -3422,6 +3431,9 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int se if (sel != 0) check_insn(env, ctx, ISA_MIPS32); + if (use_icount) + gen_io_start(); + switch (reg) { case 0: switch (sel) { @@ -4004,6 +4016,11 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int se rn, reg, sel); } #endif + /* For simplicitly assume that all writes can cause interrupts. */ + if (use_icount) { + gen_io_end(); + ctx->bstate = BS_STOP; + } return; die: @@ -4238,7 +4255,14 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int s case 9: switch (sel) { case 0: + /* Mark as an IO operation because we read the time. */ + if (use_icount) + gen_io_start(); tcg_gen_helper_1_0(do_mfc0_count, t0); + if (use_icount) { + gen_io_end(); + ctx->bstate = BS_STOP; + } rn = "Count"; break; /* 6,7 are implementation dependent */ @@ -4591,6 +4615,9 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int s if (sel != 0) check_insn(env, ctx, ISA_MIPS64); + if (use_icount) + gen_io_start(); + switch (reg) { case 0: switch (sel) { @@ -5161,6 +5188,11 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int s } #endif tcg_temp_free(t0); + /* For simplicitly assume that all writes can cause interrupts. */ + if (use_icount) { + gen_io_end(); + ctx->bstate = BS_STOP; + } return; die: @@ -7760,6 +7792,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx) ctx->hflags &= ~MIPS_HFLAG_BMASK; ctx->bstate = BS_BRANCH; save_cpu_state(ctx, 0); + /* FIXME: Need to clear can_do_io. */ switch (hflags) { case MIPS_HFLAG_B: /* unconditional branch */ @@ -7807,6 +7840,8 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, target_ulong pc_start; uint16_t *gen_opc_end; int j, lj = -1; + int num_insns; + int max_insns; if (search_pc && loglevel) fprintf (logfile, "search pc %d\n", search_pc); @@ -7826,6 +7861,11 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, #else ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU; #endif + num_insns = 0; + num_insns = 0; + max_insns = tb->cflags & CF_COUNT_MASK; + if (max_insns == 0) + max_insns = CF_COUNT_MASK; #ifdef DEBUG_DISAS if (loglevel & CPU_LOG_TB_CPU) { fprintf(logfile, "------------------------------------------------\n"); @@ -7838,6 +7878,7 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, fprintf(logfile, "\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags); #endif + gen_icount_start(); while (ctx.bstate == BS_NONE) { if (env->nb_breakpoints > 0) { for(j = 0; j < env->nb_breakpoints; j++) { @@ -7863,10 +7904,14 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, gen_opc_pc[lj] = ctx.pc; gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK; gen_opc_instr_start[lj] = 1; + gen_opc_icount[lj] = num_insns; } + if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) + gen_io_start(); ctx.opcode = ldl_code(ctx.pc); decode_opc(env, &ctx); ctx.pc += 4; + num_insns++; if (env->singlestep_enabled) break; @@ -7880,10 +7925,14 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, if (gen_opc_ptr >= gen_opc_end) break; + if (num_insns >= max_insns) + break; #if defined (MIPS_SINGLE_STEP) break; #endif } + if (tb->cflags & CF_LAST_IO) + gen_io_end(); if (env->singlestep_enabled) { save_cpu_state(&ctx, ctx.bstate == BS_NONE); tcg_gen_helper_0_i(do_raise_exception, EXCP_DEBUG); @@ -7907,6 +7956,7 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, } } done_generating: + gen_icount_end(tb, num_insns); *gen_opc_ptr = INDEX_op_end; if (search_pc) { j = gen_opc_ptr - gen_opc_buf; @@ -7915,6 +7965,7 @@ done_generating: gen_opc_instr_start[lj++] = 0; } else { tb->size = ctx.pc - pc_start; + tb->icount = num_insns; } #ifdef DEBUG_DISAS #if defined MIPS_DEBUG_DISAS diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index d08bbba99..d9dcf58ef 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -697,6 +697,7 @@ struct mmu_ctx_t { /*****************************************************************************/ CPUPPCState *cpu_ppc_init (const char *cpu_model); +void ppc_translate_init(void); int cpu_ppc_exec (CPUPPCState *s); void cpu_ppc_close (CPUPPCState *s); /* you can call this signal handler from your SIGBUS and SIGSEGV @@ -833,6 +834,8 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp) } #endif +#define CPU_PC_FROM_TB(env, tb) env->nip = tb->pc + #include "cpu-all.h" /*****************************************************************************/ diff --git a/target-ppc/helper.c b/target-ppc/helper.c index 2a52dc69a..c6ac6cb0e 100644 --- a/target-ppc/helper.c +++ b/target-ppc/helper.c @@ -2977,6 +2977,7 @@ CPUPPCState *cpu_ppc_init (const char *cpu_model) if (!env) return NULL; cpu_exec_init(env); + ppc_translate_init(); env->cpu_model_str = cpu_model; cpu_ppc_register_internal(env, def); cpu_ppc_reset(env); diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 28cb6abdd..b98ba35bd 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -43,6 +43,19 @@ /*****************************************************************************/ /* Code translation helpers */ +static TCGv cpu_env; + +#include "gen-icount.h" + +void ppc_translate_init(void) +{ + int done_init = 0; + if (done_init) + return; + cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env"); + done_init = 1; +} + #if defined(OPTIMIZE_FPRF_UPDATE) static uint16_t *gen_fprf_buf[OPC_BUF_SIZE]; static uint16_t **gen_fprf_ptr; @@ -6168,6 +6181,8 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, uint16_t *gen_opc_end; int supervisor, little_endian; int j, lj = -1; + int num_insns; + int max_insns; pc_start = tb->pc; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; @@ -6211,6 +6226,12 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, /* Single step trace mode */ msr_se = 1; #endif + num_insns = 0; + max_insns = tb->cflags & CF_COUNT_MASK; + if (max_insns == 0) + max_insns = CF_COUNT_MASK; + + gen_icount_start(); /* Set env in case of segfault during code fetch */ while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) { if (unlikely(env->nb_breakpoints > 0)) { @@ -6230,6 +6251,7 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, gen_opc_instr_start[lj++] = 0; gen_opc_pc[lj] = ctx.nip; gen_opc_instr_start[lj] = 1; + gen_opc_icount[lj] = num_insns; } } #if defined PPC_DEBUG_DISAS @@ -6239,6 +6261,8 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, ctx.nip, supervisor, (int)msr_ir); } #endif + if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) + gen_io_start(); if (unlikely(little_endian)) { ctx.opcode = bswap32(ldl_code(ctx.nip)); } else { @@ -6253,6 +6277,7 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, #endif ctx.nip += 4; table = env->opcodes; + num_insns++; handler = table[opc1(ctx.opcode)]; if (is_indirect_opcode(handler)) { table = ind_table(handler); @@ -6306,7 +6331,8 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, ctx.exception != POWERPC_EXCP_BRANCH)) { GEN_EXCP(ctxp, POWERPC_EXCP_TRACE, 0); } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) || - (env->singlestep_enabled))) { + (env->singlestep_enabled) || + num_insns >= max_insns)) { /* if we reach a page boundary or are single stepping, stop * generation */ @@ -6316,6 +6342,8 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, break; #endif } + if (tb->cflags & CF_LAST_IO) + gen_io_end(); if (ctx.exception == POWERPC_EXCP_NONE) { gen_goto_tb(&ctx, 0, ctx.nip); } else if (ctx.exception != POWERPC_EXCP_BRANCH) { @@ -6326,6 +6354,7 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, /* Generate the return instruction */ tcg_gen_exit_tb(0); } + gen_icount_end(tb, num_insns); *gen_opc_ptr = INDEX_op_end; if (unlikely(search_pc)) { j = gen_opc_ptr - gen_opc_buf; @@ -6334,6 +6363,7 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, gen_opc_instr_start[lj++] = 0; } else { tb->size = ctx.nip - pc_start; + tb->icount = num_insns; } #if defined(DEBUG_DISAS) if (loglevel & CPU_LOG_TB_CPU) { diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h index c349bc886..014ecd342 100644 --- a/target-sh4/cpu.h +++ b/target-sh4/cpu.h @@ -152,6 +152,11 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp) } #endif +#define CPU_PC_FROM_TB(env, tb) do { \ + env->pc = tb->pc; \ + env->flags = tb->flags; \ + } while (0) + #include "cpu-all.h" /* Memory access type */ diff --git a/target-sh4/translate.c b/target-sh4/translate.c index 3564a6761..8e3f324f3 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -56,6 +56,19 @@ enum { BS_EXCP = 3, /* We reached an exception condition */ }; +static TCGv cpu_env; + +#include "gen-icount.h" + +void sh4_translate_init() +{ + static int done_init = 0; + if (done_init) + return; + cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env"); + done_init = 1; +} + #ifdef CONFIG_USER_ONLY #define GEN_OP_LD(width, reg) \ @@ -143,6 +156,7 @@ CPUSH4State *cpu_sh4_init(const char *cpu_model) if (!env) return NULL; cpu_exec_init(env); + sh4_translate_init(); cpu_sh4_reset(env); tlb_flush(env, 1); return env; @@ -1189,6 +1203,8 @@ gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb, target_ulong pc_start; static uint16_t *gen_opc_end; int i, ii; + int num_insns; + int max_insns; pc_start = tb->pc; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; @@ -1213,6 +1229,11 @@ gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb, #endif ii = -1; + num_insns = 0; + max_insns = tb->cflags & CF_COUNT_MASK; + if (max_insns == 0) + max_insns = CF_COUNT_MASK; + gen_icount_start(); while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) { if (env->nb_breakpoints > 0) { for (i = 0; i < env->nb_breakpoints; i++) { @@ -1235,22 +1256,30 @@ gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb, gen_opc_pc[ii] = ctx.pc; gen_opc_hflags[ii] = ctx.flags; gen_opc_instr_start[ii] = 1; + gen_opc_icount[ii] = num_insns; } + if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) + gen_io_start(); #if 0 fprintf(stderr, "Loading opcode at address 0x%08x\n", ctx.pc); fflush(stderr); #endif ctx.opcode = lduw_code(ctx.pc); decode_opc(&ctx); + num_insns++; ctx.pc += 2; if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0) break; if (env->singlestep_enabled) break; + if (num_insns >= max_insns) + break; #ifdef SH4_SINGLE_STEP break; #endif } + if (tb->cflags & CF_LAST_IO) + gen_io_end(); if (env->singlestep_enabled) { gen_op_debug(); } else { @@ -1274,6 +1303,7 @@ gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb, } } + gen_icount_end(tb, num_insns); *gen_opc_ptr = INDEX_op_end; if (search_pc) { i = gen_opc_ptr - gen_opc_buf; @@ -1282,6 +1312,7 @@ gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb, gen_opc_instr_start[ii++] = 0; } else { tb->size = ctx.pc - pc_start; + tb->icount = num_insns; } #ifdef DEBUG_DISAS diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index b56dc91ff..03bc2dfd0 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -437,6 +437,11 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp) } #endif +#define CPU_PC_FROM_TB(env, tb) do { \ + env->pc = tb->pc; \ + env->npc = tb->cs_base; \ + } while(0) + #include "cpu-all.h" #endif diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 98c629150..49f998e90 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -48,6 +48,8 @@ static TCGv cpu_xcc; /* local register indexes (only used inside old micro ops) */ static TCGv cpu_tmp0, cpu_tmp32, cpu_tmp64; +#include "gen-icount.h" + typedef struct DisasContext { target_ulong pc; /* current Program Counter: integer or DYNAMIC_PC */ target_ulong npc; /* next PC: integer or DYNAMIC_PC or JUMP_PC */ @@ -4719,6 +4721,8 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb, uint16_t *gen_opc_end; DisasContext dc1, *dc = &dc1; int j, lj = -1; + int num_insns; + int max_insns; memset(dc, 0, sizeof(DisasContext)); dc->tb = tb; @@ -4747,6 +4751,11 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb, cpu_val = tcg_temp_local_new(TCG_TYPE_TL); cpu_addr = tcg_temp_local_new(TCG_TYPE_TL); + num_insns = 0; + max_insns = tb->cflags & CF_COUNT_MASK; + if (max_insns == 0) + max_insns = CF_COUNT_MASK; + gen_icount_start(); do { if (env->nb_breakpoints > 0) { for(j = 0; j < env->nb_breakpoints; j++) { @@ -4771,10 +4780,14 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb, gen_opc_pc[lj] = dc->pc; gen_opc_npc[lj] = dc->npc; gen_opc_instr_start[lj] = 1; + gen_opc_icount[lj] = num_insns; } } + if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) + gen_io_start(); last_pc = dc->pc; disas_sparc_insn(dc); + num_insns++; if (dc->is_br) break; @@ -4793,7 +4806,8 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb, break; } } while ((gen_opc_ptr < gen_opc_end) && - (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32)); + (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32) && + num_insns < max_insns); exit_gen_loop: tcg_temp_free(cpu_addr); @@ -4802,6 +4816,8 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb, tcg_temp_free(cpu_tmp64); tcg_temp_free(cpu_tmp32); tcg_temp_free(cpu_tmp0); + if (tb->cflags & CF_LAST_IO) + gen_io_end(); if (!dc->is_br) { if (dc->pc != DYNAMIC_PC && (dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) { @@ -4814,6 +4830,7 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb, tcg_gen_exit_tb(0); } } + gen_icount_end(tb, num_insns); *gen_opc_ptr = INDEX_op_end; if (spc) { j = gen_opc_ptr - gen_opc_buf; @@ -4829,6 +4846,7 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb, gen_opc_jump_pc[1] = dc->jump_pc[1]; } else { tb->size = last_pc + 4 - pc_start; + tb->icount = num_insns; } #ifdef DEBUG_DISAS if (loglevel & CPU_LOG_TB_IN_ASM) { diff --git a/translate-all.c b/translate-all.c index 8b8b6a281..263649578 100644 --- a/translate-all.c +++ b/translate-all.c @@ -38,6 +38,7 @@ uint16_t gen_opc_buf[OPC_BUF_SIZE]; TCGArg gen_opparam_buf[OPPARAM_BUF_SIZE]; target_ulong gen_opc_pc[OPC_BUF_SIZE]; +uint16_t gen_opc_icount[OPC_BUF_SIZE]; uint8_t gen_opc_instr_start[OPC_BUF_SIZE]; #if defined(TARGET_I386) uint8_t gen_opc_cc_op[OPC_BUF_SIZE]; @@ -158,6 +159,13 @@ int cpu_restore_state(TranslationBlock *tb, if (gen_intermediate_code_pc(env, tb) < 0) return -1; + if (use_icount) { + /* Reset the cycle counter to the start of the block. */ + env->icount_decr.u16.low += tb->icount; + /* Clear the IO flag. */ + env->can_do_io = 0; + } + /* find opc index corresponding to search_pc */ tc_ptr = (unsigned long)tb->tc_ptr; if (searched_pc < tc_ptr) @@ -177,6 +185,7 @@ int cpu_restore_state(TranslationBlock *tb, /* now find start of instruction before */ while (gen_opc_instr_start[j] == 0) j--; + env->icount_decr.u16.low -= gen_opc_icount[j]; gen_pc_load(env, tb, searched_pc, j, puc); diff --git a/vl.c b/vl.c index 908aa3922..72ce67b02 100644 --- a/vl.c +++ b/vl.c @@ -239,6 +239,14 @@ struct drive_opt { static CPUState *cur_cpu; static CPUState *next_cpu; static int event_pending = 1; +/* Conversion factor from emulated instrctions to virtual clock ticks. */ +static int icount_time_shift; +/* Arbitrarily pick 1MIPS as the minimum alowable speed. */ +#define MAX_ICOUNT_SHIFT 10 +/* Compensate for varying guest execution speed. */ +static int64_t qemu_icount_bias; +QEMUTimer *icount_rt_timer; +QEMUTimer *icount_vm_timer; #define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR) @@ -733,9 +741,22 @@ static int64_t get_clock(void) return tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000); } } - #endif +/* Return the virtual CPU time, based on the instruction counter. */ +static int64_t cpu_get_icount(void) +{ + int64_t icount; + CPUState *env = cpu_single_env;; + icount = qemu_icount; + if (env) { + if (!can_do_io(env)) + fprintf(stderr, "Bad clock read\n"); + icount -= (env->icount_decr.u16.low + env->icount_extra); + } + return qemu_icount_bias + (icount << icount_time_shift); +} + /***********************************************************/ /* guest cycle counter */ @@ -747,6 +768,9 @@ static int cpu_ticks_enabled; /* return the host CPU cycle counter and handle stop/restart */ int64_t cpu_get_ticks(void) { + if (use_icount) { + return cpu_get_icount(); + } if (!cpu_ticks_enabled) { return cpu_ticks_offset; } else { @@ -878,6 +902,71 @@ static void rtc_stop_timer(struct qemu_alarm_timer *t); #endif /* _WIN32 */ +/* Correlation between real and virtual time is always going to be + farly approximate, so ignore small variation. + When the guest is idle real and virtual time will be aligned in + the IO wait loop. */ +#define ICOUNT_WOBBLE (QEMU_TIMER_BASE / 10) + +static void icount_adjust(void) +{ + int64_t cur_time; + int64_t cur_icount; + int64_t delta; + static int64_t last_delta; + /* If the VM is not running, then do nothing. */ + if (!vm_running) + return; + + cur_time = cpu_get_clock(); + cur_icount = qemu_get_clock(vm_clock); + delta = cur_icount - cur_time; + /* FIXME: This is a very crude algorithm, somewhat prone to oscillation. */ + if (delta > 0 + && last_delta + ICOUNT_WOBBLE < delta * 2 + && icount_time_shift > 0) { + /* The guest is getting too far ahead. Slow time down. */ + icount_time_shift--; + } + if (delta < 0 + && last_delta - ICOUNT_WOBBLE > delta * 2 + && icount_time_shift < MAX_ICOUNT_SHIFT) { + /* The guest is getting too far behind. Speed time up. */ + icount_time_shift++; + } + last_delta = delta; + qemu_icount_bias = cur_icount - (qemu_icount << icount_time_shift); +} + +static void icount_adjust_rt(void * opaque) +{ + qemu_mod_timer(icount_rt_timer, + qemu_get_clock(rt_clock) + 1000); + icount_adjust(); +} + +static void icount_adjust_vm(void * opaque) +{ + qemu_mod_timer(icount_vm_timer, + qemu_get_clock(vm_clock) + QEMU_TIMER_BASE / 10); + icount_adjust(); +} + +static void init_icount_adjust(void) +{ + /* Have both realtime and virtual time triggers for speed adjustment. + The realtime trigger catches emulated time passing too slowly, + the virtual time trigger catches emulated time passing too fast. + Realtime triggers occur even when idle, so use them less frequently + than VM triggers. */ + icount_rt_timer = qemu_new_timer(rt_clock, icount_adjust_rt, NULL); + qemu_mod_timer(icount_rt_timer, + qemu_get_clock(rt_clock) + 1000); + icount_vm_timer = qemu_new_timer(vm_clock, icount_adjust_vm, NULL); + qemu_mod_timer(icount_vm_timer, + qemu_get_clock(vm_clock) + QEMU_TIMER_BASE / 10); +} + static struct qemu_alarm_timer alarm_timers[] = { #ifndef _WIN32 #ifdef __linux__ @@ -914,6 +1003,7 @@ static void configure_alarms(char const *opt) int count = (sizeof(alarm_timers) / sizeof(*alarm_timers)) - 1; char *arg; char *name; + struct qemu_alarm_timer tmp; if (!strcmp(opt, "?")) { show_available_alarms(); @@ -925,8 +1015,6 @@ static void configure_alarms(char const *opt) /* Reorder the array */ name = strtok(arg, ","); while (name) { - struct qemu_alarm_timer tmp; - for (i = 0; i < count && alarm_timers[i].name; i++) { if (!strcmp(alarm_timers[i].name, name)) break; @@ -954,7 +1042,7 @@ next: free(arg); if (cur) { - /* Disable remaining timers */ + /* Disable remaining timers */ for (i = cur; i < count; i++) alarm_timers[i].name = NULL; } else { @@ -1039,9 +1127,15 @@ void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time) *pt = ts; /* Rearm if necessary */ - if ((alarm_timer->flags & ALARM_FLAG_EXPIRED) == 0 && - pt == &active_timers[ts->clock->type]) - qemu_rearm_alarm_timer(alarm_timer); + if (pt == &active_timers[ts->clock->type]) { + if ((alarm_timer->flags & ALARM_FLAG_EXPIRED) == 0) { + qemu_rearm_alarm_timer(alarm_timer); + } + /* Interrupt execution to force deadline recalculation. */ + if (use_icount && cpu_single_env) { + cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT); + } + } } int qemu_timer_pending(QEMUTimer *ts) @@ -1085,7 +1179,11 @@ int64_t qemu_get_clock(QEMUClock *clock) return get_clock() / 1000000; default: case QEMU_TIMER_VIRTUAL: - return cpu_get_clock(); + if (use_icount) { + return cpu_get_icount(); + } else { + return cpu_get_clock(); + } } } @@ -1184,8 +1282,9 @@ static void host_alarm_handler(int host_signum) } #endif if (alarm_has_dynticks(alarm_timer) || - qemu_timer_expired(active_timers[QEMU_TIMER_VIRTUAL], - qemu_get_clock(vm_clock)) || + (!use_icount && + qemu_timer_expired(active_timers[QEMU_TIMER_VIRTUAL], + qemu_get_clock(vm_clock))) || qemu_timer_expired(active_timers[QEMU_TIMER_REALTIME], qemu_get_clock(rt_clock))) { #ifdef _WIN32 @@ -1209,28 +1308,45 @@ static void host_alarm_handler(int host_signum) } } -static uint64_t qemu_next_deadline(void) +static int64_t qemu_next_deadline(void) { - int64_t nearest_delta_us = INT64_MAX; - int64_t vmdelta_us; - - if (active_timers[QEMU_TIMER_REALTIME]) - nearest_delta_us = (active_timers[QEMU_TIMER_REALTIME]->expire_time - - qemu_get_clock(rt_clock))*1000; + int64_t delta; if (active_timers[QEMU_TIMER_VIRTUAL]) { - /* round up */ - vmdelta_us = (active_timers[QEMU_TIMER_VIRTUAL]->expire_time - - qemu_get_clock(vm_clock)+999)/1000; - if (vmdelta_us < nearest_delta_us) - nearest_delta_us = vmdelta_us; + delta = active_timers[QEMU_TIMER_VIRTUAL]->expire_time - + qemu_get_clock(vm_clock); + } else { + /* To avoid problems with overflow limit this to 2^32. */ + delta = INT32_MAX; } - /* Avoid arming the timer to negative, zero, or too low values */ - if (nearest_delta_us <= MIN_TIMER_REARM_US) - nearest_delta_us = MIN_TIMER_REARM_US; + if (delta < 0) + delta = 0; - return nearest_delta_us; + return delta; +} + +static uint64_t qemu_next_deadline_dyntick(void) +{ + int64_t delta; + int64_t rtdelta; + + if (use_icount) + delta = INT32_MAX; + else + delta = (qemu_next_deadline() + 999) / 1000; + + if (active_timers[QEMU_TIMER_REALTIME]) { + rtdelta = (active_timers[QEMU_TIMER_REALTIME]->expire_time - + qemu_get_clock(rt_clock))*1000; + if (rtdelta < delta) + delta = rtdelta; + } + + if (delta < MIN_TIMER_REARM_US) + delta = MIN_TIMER_REARM_US; + + return delta; } #ifndef _WIN32 @@ -1386,7 +1502,7 @@ static void dynticks_rearm_timer(struct qemu_alarm_timer *t) !active_timers[QEMU_TIMER_VIRTUAL]) return; - nearest_delta_us = qemu_next_deadline(); + nearest_delta_us = qemu_next_deadline_dyntick(); /* check whether a timer is already running */ if (timer_gettime(host_timer, &timeout)) { @@ -1513,7 +1629,7 @@ static void win32_rearm_timer(struct qemu_alarm_timer *t) !active_timers[QEMU_TIMER_VIRTUAL]) return; - nearest_delta_us = qemu_next_deadline(); + nearest_delta_us = qemu_next_deadline_dyntick(); nearest_delta_us /= 1000; timeKillEvent(data->timerId); @@ -7068,10 +7184,33 @@ static int main_loop(void) #ifdef CONFIG_PROFILER ti = profile_getclock(); #endif + if (use_icount) { + int64_t count; + int decr; + qemu_icount -= (env->icount_decr.u16.low + env->icount_extra); + env->icount_decr.u16.low = 0; + env->icount_extra = 0; + count = qemu_next_deadline(); + count = (count + (1 << icount_time_shift) - 1) + >> icount_time_shift; + qemu_icount += count; + decr = (count > 0xffff) ? 0xffff : count; + count -= decr; + env->icount_decr.u16.low = decr; + env->icount_extra = count; + } ret = cpu_exec(env); #ifdef CONFIG_PROFILER qemu_time += profile_getclock() - ti; #endif + if (use_icount) { + /* Fold pending instructions back into the + instruction counter, and clear the interrupt flag. */ + qemu_icount -= (env->icount_decr.u16.low + + env->icount_extra); + env->icount_decr.u32 = 0; + env->icount_extra = 0; + } next_cpu = env->next_cpu ?: first_cpu; if (event_pending && likely(ret != EXCP_DEBUG)) { ret = EXCP_INTERRUPT; @@ -7115,10 +7254,46 @@ static int main_loop(void) } /* If all cpus are halted then wait until the next IRQ */ /* XXX: use timeout computed from timers */ - if (ret == EXCP_HALTED) - timeout = 10; - else + if (ret == EXCP_HALTED) { + if (use_icount) { + int64_t add; + int64_t delta; + /* Advance virtual time to the next event. */ + if (use_icount == 1) { + /* When not using an adaptive execution frequency + we tend to get badly out of sync with real time, + so just delay for a resonable amount of time. */ + delta = 0; + } else { + delta = cpu_get_icount() - cpu_get_clock(); + } + if (delta > 0) { + /* If virtual time is ahead of real time then just + wait for IO. */ + timeout = (delta / 1000000) + 1; + } else { + /* Wait for either IO to occur or the next + timer event. */ + add = qemu_next_deadline(); + /* We advance the timer before checking for IO. + Limit the amount we advance so that early IO + activity won't get the guest too far ahead. */ + if (add > 10000000) + add = 10000000; + delta += add; + add = (add + (1 << icount_time_shift) - 1) + >> icount_time_shift; + qemu_icount += add; + timeout = delta / 1000000; + if (timeout < 0) + timeout = 0; + } + } else { + timeout = 10; + } + } else { timeout = 0; + } } else { timeout = 10; } @@ -7270,6 +7445,8 @@ static void help(int exitcode) "-clock force the use of the given methods for timer alarm.\n" " To see what timers are available use -clock ?\n" "-startdate select initial date of the clock\n" + "-icount [N|auto]\n" + " Enable virtual instruction counter with 2^N clock ticks per instructon\n" "\n" "During emulation, the following keys are useful:\n" "ctrl-alt-f toggle full screen\n" @@ -7374,6 +7551,7 @@ enum { QEMU_OPTION_clock, QEMU_OPTION_startdate, QEMU_OPTION_tb_size, + QEMU_OPTION_icount, }; typedef struct QEMUOption { @@ -7486,6 +7664,7 @@ const QEMUOption qemu_options[] = { { "clock", HAS_ARG, QEMU_OPTION_clock }, { "startdate", HAS_ARG, QEMU_OPTION_startdate }, { "tb-size", HAS_ARG, QEMU_OPTION_tb_size }, + { "icount", HAS_ARG, QEMU_OPTION_icount }, { NULL }, }; @@ -8310,6 +8489,14 @@ int main(int argc, char **argv) if (tb_size < 0) tb_size = 0; break; + case QEMU_OPTION_icount: + use_icount = 1; + if (strcmp(optarg, "auto") == 0) { + icount_time_shift = -1; + } else { + icount_time_shift = strtol(optarg, NULL, 0); + } + break; } } } @@ -8395,6 +8582,13 @@ int main(int argc, char **argv) init_timers(); init_timer_alarm(); qemu_aio_init(); + if (use_icount && icount_time_shift < 0) { + use_icount = 2; + /* 125MIPS seems a reasonable initial guess at the guest speed. + It will be corrected fairly quickly anyway. */ + icount_time_shift = 3; + init_icount_adjust(); + } #ifdef _WIN32 socket_init(); -- cgit v1.2.3 From dd5d6fe913b458463aecb3abd6dca049e5d5b0c6 Mon Sep 17 00:00:00 2001 From: pbrook Date: Sun, 29 Jun 2008 10:43:16 +0000 Subject: Add missing file. Fix spelling errors. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4800 c046a42c-6fe2-441c-8c8c-71466251a162 --- gen-icount.h | 56 +++++++++++++++++++++++++++++++++++++++++++++++++ qemu-doc.texi | 2 +- target-mips/translate.c | 1 - vl.c | 2 +- 4 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 gen-icount.h diff --git a/gen-icount.h b/gen-icount.h new file mode 100644 index 000000000..172b2bc7d --- /dev/null +++ b/gen-icount.h @@ -0,0 +1,56 @@ +/* Helpewrs for instruction counting code genration. */ + +static TCGArg *icount_arg; +static int icount_label; + +static inline void gen_icount_start(void) +{ + TCGv count; + + if (!use_icount) + return; + + icount_label = gen_new_label(); + /* FIXME: This generates lousy code. We can't use tcg_new_temp because + count needs to live over the conditional branch. To workaround this + we allow the target to supply a convenient register temporary. */ +#ifndef ICOUNT_TEMP + count = tcg_temp_local_new(TCG_TYPE_I32); +#else + count = ICOUNT_TEMP; +#endif + tcg_gen_ld_i32(count, cpu_env, offsetof(CPUState, icount_decr.u32)); + /* This is a horrid hack to allow fixing up the value later. */ + icount_arg = gen_opparam_ptr + 1; + tcg_gen_subi_i32(count, count, 0xdeadbeef); + + tcg_gen_brcondi_i32(TCG_COND_LT, count, 0, icount_label); + tcg_gen_st16_i32(count, cpu_env, offsetof(CPUState, icount_decr.u16.low)); +#ifndef ICOUNT_TEMP + tcg_temp_free(count); +#endif +} + +static void gen_icount_end(TranslationBlock *tb, int num_insns) +{ + if (use_icount) { + *icount_arg = num_insns; + gen_set_label(icount_label); + tcg_gen_exit_tb((long)tb + 2); + } +} + +static void inline gen_io_start(void) +{ + TCGv tmp = tcg_const_i32(1); + tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, can_do_io)); + tcg_temp_free(tmp); +} + +static inline void gen_io_end(void) +{ + TCGv tmp = tcg_const_i32(0); + tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, can_do_io)); + tcg_temp_free(tmp); +} + diff --git a/qemu-doc.texi b/qemu-doc.texi index 057b9f655..cda403faa 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -974,7 +974,7 @@ time within a few seconds of real time. Note that while this option can give deterministic behavior, it does not provide cycle accurate emulation. Modern CPUs contain superscalar out of -order cores with complex cache heirachies. The number of instructions +order cores with complex cache hierarchies. The number of instructions executed often has little or no correlation with actual performance. @end table diff --git a/target-mips/translate.c b/target-mips/translate.c index 67fbbedf7..a4329f383 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -7861,7 +7861,6 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, #else ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU; #endif - num_insns = 0; num_insns = 0; max_insns = tb->cflags & CF_COUNT_MASK; if (max_insns == 0) diff --git a/vl.c b/vl.c index 72ce67b02..00d43eeee 100644 --- a/vl.c +++ b/vl.c @@ -7446,7 +7446,7 @@ static void help(int exitcode) " To see what timers are available use -clock ?\n" "-startdate select initial date of the clock\n" "-icount [N|auto]\n" - " Enable virtual instruction counter with 2^N clock ticks per instructon\n" + " Enable virtual instruction counter with 2^N clock ticks per instruction\n" "\n" "During emulation, the following keys are useful:\n" "ctrl-alt-f toggle full screen\n" -- cgit v1.2.3 From b2437bf267670890c2919b03bde0fb22eb0eca5f Mon Sep 17 00:00:00 2001 From: pbrook Date: Sun, 29 Jun 2008 12:29:56 +0000 Subject: Add missing static qualifiers. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4801 c046a42c-6fe2-441c-8c8c-71466251a162 --- target-alpha/translate.c | 4 ++-- target-ppc/translate.c | 2 +- target-sh4/translate.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/target-alpha/translate.c b/target-alpha/translate.c index 4a741573d..9bf6163e6 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -43,11 +43,11 @@ struct DisasContext { uint32_t amask; }; -TCGv cpu_env; +static TCGv cpu_env; #include "gen-icount.h" -void alpha_translate_init() +static void alpha_translate_init() { static int done_init = 0; if (done_init) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index b98ba35bd..e0c318582 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -49,7 +49,7 @@ static TCGv cpu_env; void ppc_translate_init(void) { - int done_init = 0; + static int done_init = 0; if (done_init) return; cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env"); diff --git a/target-sh4/translate.c b/target-sh4/translate.c index 8e3f324f3..0a6f4171f 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -60,7 +60,7 @@ static TCGv cpu_env; #include "gen-icount.h" -void sh4_translate_init() +static void sh4_translate_init() { static int done_init = 0; if (done_init) -- cgit v1.2.3 From d26968ecd8c93334f2793749c5c33c00d1c12d63 Mon Sep 17 00:00:00 2001 From: ths Date: Sun, 29 Jun 2008 14:53:11 +0000 Subject: Remove unnecessary helper arguments, and fix some typos. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4802 c046a42c-6fe2-441c-8c8c-71466251a162 --- target-mips/helper.h | 10 +++++----- target-mips/op_helper.c | 10 +++++----- target-mips/translate.c | 32 +++++++++++++++++++++----------- 3 files changed, 31 insertions(+), 21 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index eed8bd597..7dfc25958 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -251,12 +251,12 @@ DEF_HELPER(void, do_pmon, (int function)) DEF_HELPER(void, do_wait, (void)) /* Bitfield operations. */ -DEF_HELPER(target_ulong, do_ext, (target_ulong t0, target_ulong t1, uint32_t pos, uint32_t size)) +DEF_HELPER(target_ulong, do_ext, (target_ulong t1, uint32_t pos, uint32_t size)) DEF_HELPER(target_ulong, do_ins, (target_ulong t0, target_ulong t1, uint32_t pos, uint32_t size)) -DEF_HELPER(target_ulong, do_wsbh, (target_ulong t0, target_ulong t1)) +DEF_HELPER(target_ulong, do_wsbh, (target_ulong t1)) #ifdef TARGET_MIPS64 -DEF_HELPER(target_ulong, do_dext, (target_ulong t0, target_ulong t1, uint32_t pos, uint32_t size)) +DEF_HELPER(target_ulong, do_dext, (target_ulong t1, uint32_t pos, uint32_t size)) DEF_HELPER(target_ulong, do_dins, (target_ulong t0, target_ulong t1, uint32_t pos, uint32_t size)) -DEF_HELPER(target_ulong, do_dsbh, (target_ulong t0, target_ulong t1)) -DEF_HELPER(target_ulong, do_dshd, (target_ulong t0, target_ulong t1)) +DEF_HELPER(target_ulong, do_dsbh, (target_ulong t1)) +DEF_HELPER(target_ulong, do_dshd, (target_ulong t1)) #endif diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 6c1d048b7..309856344 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -1867,7 +1867,7 @@ target_ulong do_rdhwr_ccres(void) } /* Bitfield operations. */ -target_ulong do_ext(target_ulong t0, target_ulong t1, uint32_t pos, uint32_t size) +target_ulong do_ext(target_ulong t1, uint32_t pos, uint32_t size) { return (int32_t)((t1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0)); } @@ -1879,13 +1879,13 @@ target_ulong do_ins(target_ulong t0, target_ulong t1, uint32_t pos, uint32_t siz return (int32_t)((t0 & ~mask) | ((t1 << pos) & mask)); } -target_ulong do_wsbh(target_ulong t0, target_ulong t1) +target_ulong do_wsbh(target_ulong t1) { return (int32_t)(((t1 << 8) & ~0x00FF00FF) | ((t1 >> 8) & 0x00FF00FF)); } #if defined(TARGET_MIPS64) -target_ulong do_dext(target_ulong t0, target_ulong t1, uint32_t pos, uint32_t size) +target_ulong do_dext(target_ulong t1, uint32_t pos, uint32_t size) { return (t1 >> pos) & ((size < 64) ? ((1ULL << size) - 1) : ~0ULL); } @@ -1897,12 +1897,12 @@ target_ulong do_dins(target_ulong t0, target_ulong t1, uint32_t pos, uint32_t si return (t0 & ~mask) | ((t1 << pos) & mask); } -target_ulong do_dsbh(target_ulong t0, target_ulong t1) +target_ulong do_dsbh(target_ulong t1) { return ((t1 << 8) & ~0x00FF00FF00FF00FFULL) | ((t1 >> 8) & 0x00FF00FF00FF00FFULL); } -target_ulong do_dshd(target_ulong t0, target_ulong t1) +target_ulong do_dshd(target_ulong t1) { t1 = ((t1 << 16) & ~0x0000FFFF0000FFFFULL) | ((t1 >> 16) & 0x0000FFFF0000FFFFULL); return (t1 << 32) | (t1 >> 32); diff --git a/target-mips/translate.c b/target-mips/translate.c index a4329f383..9d3340eaa 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -464,12 +464,12 @@ static inline void tcg_gen_helper_0_2i(void *func, TCGv arg1, TCGv arg2, TCGv ar tcg_temp_free(tmp); } -static inline void tcg_gen_helper_0_2ii(void *func, TCGv arg1, TCGv arg2, TCGv arg3, TCGv arg4) +static inline void tcg_gen_helper_0_1ii(void *func, TCGv arg1, TCGv arg2, TCGv arg3) { - TCGv tmp1 = tcg_const_i32(arg3); + TCGv tmp1 = tcg_const_i32(arg2); TCGv tmp2 = tcg_const_i32(arg3); - tcg_gen_helper_0_4(func, arg1, arg2, tmp1, tmp2); + tcg_gen_helper_0_3(func, arg1, tmp1, tmp2); tcg_temp_free(tmp1); tcg_temp_free(tmp2); } @@ -490,6 +490,16 @@ static inline void tcg_gen_helper_1_1i(void *func, TCGv ret, TCGv arg1, TCGv arg tcg_temp_free(tmp); } +static inline void tcg_gen_helper_1_1ii(void *func, TCGv ret, TCGv arg1, TCGv arg2, TCGv arg3) +{ + TCGv tmp1 = tcg_const_i32(arg2); + TCGv tmp2 = tcg_const_i32(arg3); + + tcg_gen_helper_1_3(func, ret, arg1, tmp1, tmp2); + tcg_temp_free(tmp1); + tcg_temp_free(tmp2); +} + static inline void tcg_gen_helper_1_2i(void *func, TCGv ret, TCGv arg1, TCGv arg2, TCGv arg3) { TCGv tmp = tcg_const_i32(arg3); @@ -501,7 +511,7 @@ static inline void tcg_gen_helper_1_2i(void *func, TCGv ret, TCGv arg1, TCGv arg static inline void tcg_gen_helper_1_2ii(void *func, TCGv ret, TCGv arg1, TCGv arg2, TCGv arg3, TCGv arg4) { TCGv tmp1 = tcg_const_i32(arg3); - TCGv tmp2 = tcg_const_i32(arg3); + TCGv tmp2 = tcg_const_i32(arg4); tcg_gen_helper_1_4(func, ret, arg1, arg2, tmp1, tmp2); tcg_temp_free(tmp1); @@ -2748,23 +2758,23 @@ static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt, case OPC_EXT: if (lsb + msb > 31) goto fail; - tcg_gen_helper_1_2ii(do_ext, t0, t0, t1, lsb, msb + 1); + tcg_gen_helper_1_1ii(do_ext, t0, t1, lsb, msb + 1); break; #if defined(TARGET_MIPS64) case OPC_DEXTM: if (lsb + msb > 63) goto fail; - tcg_gen_helper_1_2ii(do_dext, t0, t0, t1, lsb, msb + 1 + 32); + tcg_gen_helper_1_1ii(do_dext, t0, t1, lsb, msb + 1 + 32); break; case OPC_DEXTU: if (lsb + msb > 63) goto fail; - tcg_gen_helper_1_2ii(do_dext, t0, t0, t1, lsb + 32, msb + 1); + tcg_gen_helper_1_1ii(do_dext, t0, t1, lsb + 32, msb + 1); break; case OPC_DEXT: if (lsb + msb > 63) goto fail; - tcg_gen_helper_1_2ii(do_dext, t0, t0, t1, lsb, msb + 1); + tcg_gen_helper_1_1ii(do_dext, t0, t1, lsb, msb + 1); break; #endif case OPC_INS: @@ -7388,7 +7398,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx) switch (op2) { case OPC_WSBH: gen_load_gpr(t1, rt); - tcg_gen_helper_1_2(do_wsbh, t0, t0, t1); + tcg_gen_helper_1_1(do_wsbh, t0, t1); gen_store_gpr(t0, rd); break; case OPC_SEB: @@ -7490,11 +7500,11 @@ static void decode_opc (CPUState *env, DisasContext *ctx) switch (op2) { case OPC_DSBH: gen_load_gpr(t1, rt); - tcg_gen_helper_1_2(do_dsbh, t0, t0, t1); + tcg_gen_helper_1_1(do_dsbh, t0, t1); break; case OPC_DSHD: gen_load_gpr(t1, rt); - tcg_gen_helper_1_2(do_dshd, t0, t0, t1); + tcg_gen_helper_1_1(do_dshd, t0, t1); break; default: /* Invalid */ MIPS_INVAL("dbshfl"); -- cgit v1.2.3 From a50f5b9186c1bf76899365ab61b11d8ef487f4a8 Mon Sep 17 00:00:00 2001 From: pbrook Date: Sun, 29 Jun 2008 15:25:29 +0000 Subject: Suppress bogus compiler warnings. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4803 c046a42c-6fe2-441c-8c8c-71466251a162 --- target-arm/translate.c | 11 +++++++++++ tcg/tcg.h | 3 +++ 2 files changed, 14 insertions(+) diff --git a/target-arm/translate.c b/target-arm/translate.c index 701745225..b9b9838fe 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -3757,6 +3757,7 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn) } } else /* size == 0 */ { if (load) { + TCGV_UNUSED(tmp2); for (n = 0; n < 4; n++) { tmp = gen_ld8u(cpu_T[1], IS_USER(s)); gen_op_addl_T1_im(stride); @@ -3812,6 +3813,8 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn) break; case 3: return 1; + default: /* Avoid compiler warnings. */ + abort(); } gen_op_addl_T1_im(1 << size); tmp2 = new_tmp(); @@ -3854,6 +3857,8 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn) case 2: tmp = gen_ld32(cpu_T[1], IS_USER(s)); break; + default: /* Avoid compiler warnings. */ + abort(); } if (size != 2) { tmp2 = neon_load_reg(rd, pass); @@ -4856,9 +4861,11 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) NEON_GET_REG(T0, rn, 1); gen_neon_movl_scratch_T0(2); } + TCGV_UNUSED(tmp3); for (pass = 0; pass < 2; pass++) { if (src1_wide) { neon_load_reg64(cpu_V0, rn + pass); + TCGV_UNUSED(tmp); } else { if (pass == 1 && rd == rn) { gen_neon_movl_T0_scratch(2); @@ -4873,6 +4880,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) } if (src2_wide) { neon_load_reg64(cpu_V1, rm + pass); + TCGV_UNUSED(tmp2); } else { if (pass == 1 && rd == rm) { gen_neon_movl_T0_scratch(2); @@ -5284,6 +5292,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */ if (size == 3) return 1; + TCGV_UNUSED(tmp2); for (pass = 0; pass < 2; pass++) { neon_load_reg64(cpu_V0, rm + pass); tmp = new_tmp(); @@ -6642,6 +6651,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) /* compute total size */ loaded_base = 0; + TCGV_UNUSED(loaded_var); n = 0; for(i=0;i<16;i++) { if (insn & (1 << i)) @@ -8339,6 +8349,7 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) tcg_gen_addi_i32(addr, addr, 4); } } + TCGV_UNUSED(tmp); if (insn & (1 << 8)) { if (insn & (1 << 11)) { /* pop pc */ diff --git a/tcg/tcg.h b/tcg/tcg.h index 9299176ab..2ce36b878 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -143,6 +143,9 @@ typedef int TCGv; #endif /* DEBUG_TCGV */ +/* Dummy definition to avoid compiler warnings. */ +#define TCGV_UNUSED(x) x = MAKE_TCGV(-1) + /* call flags */ #define TCG_CALL_TYPE_MASK 0x000f #define TCG_CALL_TYPE_STD 0x0000 /* standard C call */ -- cgit v1.2.3 From d297f464d386f85eda77263d81c598c7aaff46d9 Mon Sep 17 00:00:00 2001 From: edgar_igl Date: Mon, 30 Jun 2008 08:59:49 +0000 Subject: Avoid CRIS related warnings by Jan Kiszka. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4804 c046a42c-6fe2-441c-8c8c-71466251a162 --- hw/etraxfs_dma.c | 52 ++++++++++++++++++++++++++----------------------- hw/etraxfs_eth.c | 10 ++++++---- hw/etraxfs_timer.c | 10 +++++----- target-cris/mmu.c | 6 ++++++ target-cris/translate.c | 9 +++++---- 5 files changed, 50 insertions(+), 37 deletions(-) diff --git a/hw/etraxfs_dma.c b/hw/etraxfs_dma.c index 776cfb9cf..39d11230b 100644 --- a/hw/etraxfs_dma.c +++ b/hw/etraxfs_dma.c @@ -214,6 +214,7 @@ static inline int fs_channel(target_phys_addr_t base, target_phys_addr_t addr) return (addr - base) >> 13; } +#ifdef USE_THIS_DEAD_CODE static void channel_load_g(struct fs_dma_ctrl *ctrl, int c) { target_phys_addr_t addr = channel_reg(ctrl, c, RW_GROUP); @@ -227,23 +228,24 @@ static void channel_load_g(struct fs_dma_ctrl *ctrl, int c) static void dump_c(int ch, struct dma_descr_context *c) { printf("%s ch=%d\n", __func__, ch); - printf("next=%x\n", (uint32_t) c->next); - printf("saved_data=%x\n", (uint32_t) c->saved_data); - printf("saved_data_buf=%x\n", (uint32_t) c->saved_data_buf); + printf("next=%p\n", c->next); + printf("saved_data=%p\n", c->saved_data); + printf("saved_data_buf=%p\n", c->saved_data_buf); printf("eol=%x\n", (uint32_t) c->eol); } static void dump_d(int ch, struct dma_descr_data *d) { printf("%s ch=%d\n", __func__, ch); - printf("next=%x\n", (uint32_t) d->next); - printf("buf=%x\n", (uint32_t) d->buf); - printf("after=%x\n", (uint32_t) d->after); + printf("next=%p\n", d->next); + printf("buf=%p\n", d->buf); + printf("after=%p\n", d->after); printf("intr=%x\n", (uint32_t) d->intr); printf("out_eop=%x\n", (uint32_t) d->out_eop); printf("in_eop=%x\n", (uint32_t) d->in_eop); printf("eol=%x\n", (uint32_t) d->eol); } +#endif static void channel_load_c(struct fs_dma_ctrl *ctrl, int c) { @@ -256,10 +258,10 @@ static void channel_load_c(struct fs_dma_ctrl *ctrl, int c) D(dump_c(c, &ctrl->channels[c].current_c)); /* I guess this should update the current pos. */ - ctrl->channels[c].regs[RW_SAVED_DATA] = - (uint32_t)ctrl->channels[c].current_c.saved_data; + ctrl->channels[c].regs[RW_SAVED_DATA] = + (uint32_t)(unsigned long)ctrl->channels[c].current_c.saved_data; ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = - (uint32_t)ctrl->channels[c].current_c.saved_data_buf; + (uint32_t)(unsigned long)ctrl->channels[c].current_c.saved_data_buf; } static void channel_load_d(struct fs_dma_ctrl *ctrl, int c) @@ -339,12 +341,12 @@ static void channel_continue(struct fs_dma_ctrl *ctrl, int c) D(printf("continue %d ok %p\n", c, ctrl->channels[c].current_d.next)); ctrl->channels[c].regs[RW_SAVED_DATA] = - (uint32_t) ctrl->channels[c].current_d.next; + (uint32_t)(unsigned long)ctrl->channels[c].current_d.next; channel_load_d(ctrl, c); channel_start(ctrl, c); } ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = - (uint32_t) ctrl->channels[c].current_d.buf; + (uint32_t)(unsigned long)ctrl->channels[c].current_d.buf; } static void channel_stream_cmd(struct fs_dma_ctrl *ctrl, int c, uint32_t v) @@ -402,7 +404,7 @@ static void channel_out_run(struct fs_dma_ctrl *ctrl, int c) (uint32_t)ctrl->channels[c].current_d.after, saved_data_buf)); - len = (uint32_t) ctrl->channels[c].current_d.after; + len = (uint32_t)(unsigned long) ctrl->channels[c].current_d.after; len -= saved_data_buf; if (len > sizeof buf) @@ -420,7 +422,8 @@ static void channel_out_run(struct fs_dma_ctrl *ctrl, int c) saved_data_buf += len; - if (saved_data_buf == (uint32_t)ctrl->channels[c].current_d.after) { + if (saved_data_buf == + (uint32_t)(unsigned long)ctrl->channels[c].current_d.after) { /* Done. Step to next. */ if (ctrl->channels[c].current_d.out_eop) { /* TODO: signal eop to the client. */ @@ -444,10 +447,10 @@ static void channel_out_run(struct fs_dma_ctrl *ctrl, int c) channel_stop(ctrl, c); } else { ctrl->channels[c].regs[RW_SAVED_DATA] = - (uint32_t) ctrl->channels[c].current_d.next; + (uint32_t)(unsigned long) ctrl->channels[c].current_d.next; /* Load new descriptor. */ channel_load_d(ctrl, c); - saved_data_buf = (uint32_t) + saved_data_buf = (uint32_t)(unsigned long) ctrl->channels[c].current_d.buf; } @@ -468,7 +471,7 @@ static int channel_in_process(struct fs_dma_ctrl *ctrl, int c, return 0; saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF); - len = (uint32_t) ctrl->channels[c].current_d.after; + len = (uint32_t)(unsigned long) ctrl->channels[c].current_d.after; len -= saved_data_buf; if (len > buflen) @@ -477,7 +480,8 @@ static int channel_in_process(struct fs_dma_ctrl *ctrl, int c, cpu_physical_memory_write (saved_data_buf, buf, len); saved_data_buf += len; - if (saved_data_buf == (uint32_t)ctrl->channels[c].current_d.after + if (saved_data_buf == + (uint32_t)(unsigned long)ctrl->channels[c].current_d.after || eop) { uint32_t r_intr = ctrl->channels[c].regs[R_INTR]; @@ -485,7 +489,7 @@ static int channel_in_process(struct fs_dma_ctrl *ctrl, int c, ctrl->channels[c].current_d.after - ctrl->channels[c].current_d.buf)); ctrl->channels[c].current_d.after = - (void *) saved_data_buf; + (void *)(unsigned long) saved_data_buf; /* Done. Step to next. */ if (ctrl->channels[c].current_d.intr) { @@ -514,10 +518,10 @@ static int channel_in_process(struct fs_dma_ctrl *ctrl, int c, channel_stop(ctrl, c); } else { ctrl->channels[c].regs[RW_SAVED_DATA] = - (uint32_t) ctrl->channels[c].current_d.next; + (uint32_t)(unsigned long) ctrl->channels[c].current_d.next; /* Load new descriptor. */ channel_load_d(ctrl, c); - saved_data_buf = (uint32_t) + saved_data_buf = (uint32_t)(unsigned long) ctrl->channels[c].current_d.buf; } } @@ -537,8 +541,8 @@ static uint32_t dma_rinvalid (void *opaque, target_phys_addr_t addr) { struct fs_dma_ctrl *ctrl = opaque; CPUState *env = ctrl->env; - cpu_abort(env, "Unsupported short access. reg=%x pc=%x.\n", - addr, env->pc); + cpu_abort(env, "Unsupported short access. reg=" TARGET_FMT_plx + " pc=%x.\n", addr, env->pc); return 0; } @@ -574,8 +578,8 @@ dma_winvalid (void *opaque, target_phys_addr_t addr, uint32_t value) { struct fs_dma_ctrl *ctrl = opaque; CPUState *env = ctrl->env; - cpu_abort(env, "Unsupported short access. reg=%x pc=%x.\n", - addr, env->pc); + cpu_abort(env, "Unsupported short access. reg=" TARGET_FMT_plx + " pc=%x.\n", addr, env->pc); } static void diff --git a/hw/etraxfs_eth.c b/hw/etraxfs_eth.c index 3d7ca0f62..96cec8ad2 100644 --- a/hw/etraxfs_eth.c +++ b/hw/etraxfs_eth.c @@ -154,11 +154,13 @@ mdio_attach(struct qemu_mdio *bus, struct qemu_phy *phy, unsigned int addr) bus->devs[addr & 0x1f] = phy; } +#ifdef USE_THIS_DEAD_CODE static void mdio_detach(struct qemu_mdio *bus, struct qemu_phy *phy, unsigned int addr) { bus->devs[addr & 0x1f] = NULL; } +#endif static void mdio_read_req(struct qemu_mdio *bus) { @@ -328,8 +330,8 @@ static uint32_t eth_rinvalid (void *opaque, target_phys_addr_t addr) { struct fs_eth *eth = opaque; CPUState *env = eth->env; - cpu_abort(env, "Unsupported short access. reg=%x pc=%x.\n", - addr, env->pc); + cpu_abort(env, "Unsupported short access. reg=" TARGET_FMT_plx + " pc=%x.\n", addr, env->pc); return 0; } @@ -359,8 +361,8 @@ eth_winvalid (void *opaque, target_phys_addr_t addr, uint32_t value) { struct fs_eth *eth = opaque; CPUState *env = eth->env; - cpu_abort(env, "Unsupported short access. reg=%x pc=%x.\n", - addr, env->pc); + cpu_abort(env, "Unsupported short access. reg=" TARGET_FMT_plx + " pc=%x.\n", addr, env->pc); } static void eth_update_ma(struct fs_eth *eth, int ma) diff --git a/hw/etraxfs_timer.c b/hw/etraxfs_timer.c index e996c57f6..789992a2d 100644 --- a/hw/etraxfs_timer.c +++ b/hw/etraxfs_timer.c @@ -80,8 +80,8 @@ static uint32_t timer_rinvalid (void *opaque, target_phys_addr_t addr) { struct fs_timer_t *t = opaque; CPUState *env = t->env; - cpu_abort(env, "Unsupported short access. reg=%x pc=%x.\n", - addr, env->pc); + cpu_abort(env, "Unsupported short access. reg=" TARGET_FMT_plx + " pc=%x.\n", addr, env->pc); return 0; } @@ -120,8 +120,8 @@ timer_winvalid (void *opaque, target_phys_addr_t addr, uint32_t value) { struct fs_timer_t *t = opaque; CPUState *env = t->env; - cpu_abort(env, "Unsupported short access. reg=%x pc=%x.\n", - addr, env->pc); + cpu_abort(env, "Unsupported short access. reg=" TARGET_FMT_plx + " pc=%x.\n", addr, env->pc); } #define TIMER_SLOWDOWN 1 @@ -309,7 +309,7 @@ timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value) t->rw_ack_intr = 0; break; default: - printf ("%s %x %x pc=%x\n", + printf ("%s " TARGET_FMT_plx " %x pc=%x\n", __func__, addr, value, env->pc); break; } diff --git a/target-cris/mmu.c b/target-cris/mmu.c index 86f625b75..122e652e4 100644 --- a/target-cris/mmu.c +++ b/target-cris/mmu.c @@ -30,7 +30,11 @@ #include "mmu.h" #include "exec-all.h" +#ifdef DEBUG +#define D(x) x +#else #define D(x) +#endif void cris_mmu_init(CPUState *env) { @@ -95,6 +99,7 @@ static inline void set_field(uint32_t *dst, unsigned int val, *dst |= val; } +#ifdef DEBUG static void dump_tlb(CPUState *env, int mmu) { int set; @@ -113,6 +118,7 @@ static void dump_tlb(CPUState *env, int mmu) } } } +#endif /* rw 0 = read, 1 = write, 2 = exec. */ static int cris_mmu_translate_page(struct cris_mmu_result_t *res, diff --git a/target-cris/translate.c b/target-cris/translate.c index c3b8adef8..2fc4101d4 100644 --- a/target-cris/translate.c +++ b/target-cris/translate.c @@ -3075,14 +3075,15 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, if (loglevel & CPU_LOG_TB_IN_ASM) { fprintf(logfile, - "srch=%d pc=%x %x flg=%llx bt=%x ds=%lld ccs=%x\n" + "srch=%d pc=%x %x flg=%llx bt=%x ds=%u ccs=%x\n" "pid=%x usp=%x\n" "%x.%x.%x.%x\n" "%x.%x.%x.%x\n" "%x.%x.%x.%x\n" "%x.%x.%x.%x\n", - search_pc, dc->pc, dc->ppc, tb->flags, - env->btarget, tb->flags & 7, + search_pc, dc->pc, dc->ppc, + (unsigned long long)tb->flags, + env->btarget, (unsigned)tb->flags & 7, env->pregs[PR_CCS], env->pregs[PR_PID], env->pregs[PR_USP], env->regs[0], env->regs[1], env->regs[2], env->regs[3], @@ -3228,7 +3229,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, fprintf(logfile, "--------------\n"); fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start)); target_disas(logfile, pc_start, dc->pc - pc_start, 0); - fprintf(logfile, "\nisize=%d osize=%d\n", + fprintf(logfile, "\nisize=%d osize=%zd\n", dc->pc - pc_start, gen_opc_ptr - gen_opc_buf); } #endif -- cgit v1.2.3 From d077b6f759d6758e0d2a80f053448f152ca2ba6d Mon Sep 17 00:00:00 2001 From: ths Date: Mon, 30 Jun 2008 11:30:34 +0000 Subject: Make bcond and btarget TCG registers. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4805 c046a42c-6fe2-441c-8c8c-71466251a162 --- target-mips/translate.c | 116 ++++++++++++++++++------------------------------ 1 file changed, 43 insertions(+), 73 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index 9d3340eaa..bd14e3255 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -423,7 +423,7 @@ enum { }; /* global register indices */ -static TCGv cpu_env, current_fpu; +static TCGv cpu_env, bcond, btarget, current_fpu; /* FPU TNs, global for now. */ static TCGv fpu32_T[3], fpu64_T[3], fpu32h_T[3]; @@ -532,8 +532,7 @@ typedef struct DisasContext { enum { BS_NONE = 0, /* We go out of the TB without reaching a branch or an - * exception condition - */ + * exception condition */ BS_STOP = 1, /* We want to stop translation for any reason */ BS_BRANCH = 2, /* We reached a branch condition */ BS_EXCP = 3, /* We reached an exception condition */ @@ -823,33 +822,6 @@ static inline void gen_save_pc(target_ulong pc) tcg_temp_free(r_tmp); } -static inline void gen_breg_pc(void) -{ - TCGv r_tmp = tcg_temp_new(TCG_TYPE_TL); - - tcg_gen_ld_tl(r_tmp, cpu_env, offsetof(CPUState, btarget)); - tcg_gen_st_tl(r_tmp, cpu_env, offsetof(CPUState, active_tc.PC)); - tcg_temp_free(r_tmp); -} - -static inline void gen_save_btarget(target_ulong btarget) -{ - TCGv r_tmp = tcg_temp_new(TCG_TYPE_TL); - - tcg_gen_movi_tl(r_tmp, btarget); - tcg_gen_st_tl(r_tmp, cpu_env, offsetof(CPUState, btarget)); - tcg_temp_free(r_tmp); -} - -static always_inline void gen_save_breg_target(int reg) -{ - TCGv r_tmp = tcg_temp_new(TCG_TYPE_TL); - - gen_load_gpr(r_tmp, reg); - tcg_gen_st_tl(r_tmp, cpu_env, offsetof(CPUState, btarget)); - tcg_temp_free(r_tmp); -} - static always_inline void save_cpu_state (DisasContext *ctx, int do_save_pc) { #if defined MIPS_DEBUG_DISAS @@ -875,7 +847,7 @@ static always_inline void save_cpu_state (DisasContext *ctx, int do_save_pc) case MIPS_HFLAG_BC: case MIPS_HFLAG_BL: case MIPS_HFLAG_B: - gen_save_btarget(ctx->btarget); + tcg_gen_movi_tl(btarget, ctx->btarget); break; } } @@ -2505,7 +2477,7 @@ static always_inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong des static void gen_compute_branch (DisasContext *ctx, uint32_t opc, int rs, int rt, int32_t offset) { - target_ulong btarget = -1; + target_ulong btgt = -1; int blink = 0; int bcond = 0; TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL); @@ -2535,7 +2507,7 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, gen_load_gpr(t1, rt); bcond = 1; } - btarget = ctx->pc + 4 + offset; + btgt = ctx->pc + 4 + offset; break; case OPC_BGEZ: case OPC_BGEZAL: @@ -2554,12 +2526,12 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, gen_load_gpr(t0, rs); bcond = 1; } - btarget = ctx->pc + 4 + offset; + btgt = ctx->pc + 4 + offset; break; case OPC_J: case OPC_JAL: /* Jump to immediate */ - btarget = ((ctx->pc + 4) & (int32_t)0xF0000000) | (uint32_t)offset; + btgt = ((ctx->pc + 4) & (int32_t)0xF0000000) | (uint32_t)offset; break; case OPC_JR: case OPC_JALR: @@ -2571,7 +2543,7 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, generate_exception(ctx, EXCP_RI); goto out; } - gen_save_breg_target(rs); + gen_load_gpr(btarget, rs); break; default: MIPS_INVAL("branch/jump"); @@ -2625,12 +2597,12 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, goto out; case OPC_J: ctx->hflags |= MIPS_HFLAG_B; - MIPS_DEBUG("j " TARGET_FMT_lx, btarget); + MIPS_DEBUG("j " TARGET_FMT_lx, btgt); break; case OPC_JAL: blink = 31; ctx->hflags |= MIPS_HFLAG_B; - MIPS_DEBUG("jal " TARGET_FMT_lx, btarget); + MIPS_DEBUG("jal " TARGET_FMT_lx, btgt); break; case OPC_JR: ctx->hflags |= MIPS_HFLAG_BR; @@ -2651,80 +2623,80 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, case OPC_BEQ: gen_op_eq(t0, t1); MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx, - regnames[rs], regnames[rt], btarget); + regnames[rs], regnames[rt], btgt); goto not_likely; case OPC_BEQL: gen_op_eq(t0, t1); MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx, - regnames[rs], regnames[rt], btarget); + regnames[rs], regnames[rt], btgt); goto likely; case OPC_BNE: gen_op_ne(t0, t1); MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx, - regnames[rs], regnames[rt], btarget); + regnames[rs], regnames[rt], btgt); goto not_likely; case OPC_BNEL: gen_op_ne(t0, t1); MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx, - regnames[rs], regnames[rt], btarget); + regnames[rs], regnames[rt], btgt); goto likely; case OPC_BGEZ: gen_op_gez(t0); - MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btarget); + MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt); goto not_likely; case OPC_BGEZL: gen_op_gez(t0); - MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btarget); + MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt); goto likely; case OPC_BGEZAL: gen_op_gez(t0); - MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btarget); + MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt); blink = 31; goto not_likely; case OPC_BGEZALL: gen_op_gez(t0); blink = 31; - MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btarget); + MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt); goto likely; case OPC_BGTZ: gen_op_gtz(t0); - MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btarget); + MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt); goto not_likely; case OPC_BGTZL: gen_op_gtz(t0); - MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btarget); + MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt); goto likely; case OPC_BLEZ: gen_op_lez(t0); - MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btarget); + MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt); goto not_likely; case OPC_BLEZL: gen_op_lez(t0); - MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btarget); + MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt); goto likely; case OPC_BLTZ: gen_op_ltz(t0); - MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btarget); + MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt); goto not_likely; case OPC_BLTZL: gen_op_ltz(t0); - MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btarget); + MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt); goto likely; case OPC_BLTZAL: gen_op_ltz(t0); blink = 31; - MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btarget); + MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt); not_likely: ctx->hflags |= MIPS_HFLAG_BC; - tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, bcond)); + tcg_gen_trunc_tl_i32(bcond, t0); break; case OPC_BLTZALL: gen_op_ltz(t0); blink = 31; - MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btarget); + MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt); likely: ctx->hflags |= MIPS_HFLAG_BL; - tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, bcond)); + tcg_gen_trunc_tl_i32(bcond, t0); break; default: MIPS_INVAL("conditional branch/jump"); @@ -2733,9 +2705,9 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, } } MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx, - blink, ctx->hflags, btarget); + blink, ctx->hflags, btgt); - ctx->btarget = btarget; + ctx->btarget = btgt; if (blink > 0) { tcg_gen_movi_tl(t0, ctx->pc + 8); gen_store_gpr(t0, blink); @@ -5789,7 +5761,7 @@ static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op, opn = "bc1tl"; likely: ctx->hflags |= MIPS_HFLAG_BL; - tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, bcond)); + tcg_gen_trunc_tl_i32(bcond, t0); break; case OPC_BC1FANY2: { @@ -5874,7 +5846,7 @@ static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op, opn = "bc1any4t"; not_likely: ctx->hflags |= MIPS_HFLAG_BC; - tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, bcond)); + tcg_gen_trunc_tl_i32(bcond, t0); break; default: MIPS_INVAL(opn); @@ -7209,19 +7181,16 @@ static void decode_opc (CPUState *env, DisasContext *ctx) /* Handle blikely not taken case */ if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) { - TCGv r_tmp = tcg_temp_local_new(TCG_TYPE_TL); int l1 = gen_new_label(); MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4); - tcg_gen_ld_tl(r_tmp, cpu_env, offsetof(CPUState, bcond)); - tcg_gen_brcondi_tl(TCG_COND_NE, r_tmp, 0, l1); - tcg_temp_free(r_tmp); + tcg_gen_brcondi_i32(TCG_COND_NE, bcond, 0, l1); { - TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32); + TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32); - tcg_gen_movi_i32(r_tmp2, ctx->hflags & ~MIPS_HFLAG_BMASK); - tcg_gen_st_i32(r_tmp2, cpu_env, offsetof(CPUState, hflags)); - tcg_temp_free(r_tmp2); + tcg_gen_movi_i32(r_tmp, ctx->hflags & ~MIPS_HFLAG_BMASK); + tcg_gen_st_i32(r_tmp, cpu_env, offsetof(CPUState, hflags)); + tcg_temp_free(r_tmp); } gen_goto_tb(ctx, 1, ctx->pc + 4); gen_set_label(l1); @@ -7818,12 +7787,9 @@ static void decode_opc (CPUState *env, DisasContext *ctx) /* Conditional branch */ MIPS_DEBUG("conditional branch"); { - TCGv r_tmp = tcg_temp_local_new(TCG_TYPE_TL); int l1 = gen_new_label(); - tcg_gen_ld_tl(r_tmp, cpu_env, offsetof(CPUState, bcond)); - tcg_gen_brcondi_tl(TCG_COND_NE, r_tmp, 0, l1); - tcg_temp_free(r_tmp); + tcg_gen_brcondi_i32(TCG_COND_NE, bcond, 0, l1); gen_goto_tb(ctx, 1, ctx->pc + 4); gen_set_label(l1); gen_goto_tb(ctx, 0, ctx->btarget); @@ -7832,7 +7798,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx) case MIPS_HFLAG_BR: /* unconditional branch to register */ MIPS_DEBUG("branch to register"); - gen_breg_pc(); + tcg_gen_st_tl(btarget, cpu_env, offsetof(CPUState, active_tc.PC)); tcg_gen_exit_tb(0); break; default: @@ -8125,6 +8091,10 @@ static void mips_tcg_init(void) return; cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env"); + bcond = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0, + offsetof(CPUState, bcond), "bcond"); + btarget = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0, + offsetof(CPUState, btarget), "btarget"); current_fpu = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0, offsetof(CPUState, fpu), -- cgit v1.2.3 From d27b2e5044b143f9e522d6c3e80f498eb083a618 Mon Sep 17 00:00:00 2001 From: edgar_igl Date: Mon, 30 Jun 2008 11:51:12 +0000 Subject: Avoid refering to CRIS specific cpu-state to be able to use these blocks with other cores. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4806 c046a42c-6fe2-441c-8c8c-71466251a162 --- hw/etraxfs_dma.c | 22 ++++++++++------------ hw/etraxfs_eth.c | 11 +++++------ hw/etraxfs_ser.c | 9 ++++----- hw/etraxfs_timer.c | 16 +++++++--------- 4 files changed, 26 insertions(+), 32 deletions(-) diff --git a/hw/etraxfs_dma.c b/hw/etraxfs_dma.c index 39d11230b..a2750386f 100644 --- a/hw/etraxfs_dma.c +++ b/hw/etraxfs_dma.c @@ -353,8 +353,8 @@ static void channel_stream_cmd(struct fs_dma_ctrl *ctrl, int c, uint32_t v) { unsigned int cmd = v & ((1 << 10) - 1); - D(printf("%s ch=%d cmd=%x pc=%x\n", - __func__, c, cmd, ctrl->env->pc)); + D(printf("%s ch=%d cmd=%x\n", + __func__, c, cmd)); if (cmd & regk_dma_load_d) { channel_load_d(ctrl, c); if (cmd & regk_dma_burst) @@ -541,8 +541,8 @@ static uint32_t dma_rinvalid (void *opaque, target_phys_addr_t addr) { struct fs_dma_ctrl *ctrl = opaque; CPUState *env = ctrl->env; - cpu_abort(env, "Unsupported short access. reg=" TARGET_FMT_plx - " pc=%x.\n", addr, env->pc); + cpu_abort(env, "Unsupported short access. reg=" TARGET_FMT_plx "\n", + addr); return 0; } @@ -566,8 +566,8 @@ dma_readl (void *opaque, target_phys_addr_t addr) default: r = ctrl->channels[c].regs[addr]; - D(printf ("%s c=%d addr=%x pc=%x\n", - __func__, c, addr, ctrl->env->pc)); + D(printf ("%s c=%d addr=%x\n", + __func__, c, addr)); break; } return r; @@ -578,8 +578,8 @@ dma_winvalid (void *opaque, target_phys_addr_t addr, uint32_t value) { struct fs_dma_ctrl *ctrl = opaque; CPUState *env = ctrl->env; - cpu_abort(env, "Unsupported short access. reg=" TARGET_FMT_plx - " pc=%x.\n", addr, env->pc); + cpu_abort(env, "Unsupported short access. reg=" TARGET_FMT_plx "\n", + addr); } static void @@ -623,14 +623,12 @@ dma_writel (void *opaque, target_phys_addr_t addr, uint32_t value) case RW_STREAM_CMD: ctrl->channels[c].regs[addr] = value; - D(printf("stream_cmd ch=%d pc=%x\n", - c, ctrl->env->pc)); + D(printf("stream_cmd ch=%d\n", c)); channel_stream_cmd(ctrl, c, value); break; default: - D(printf ("%s c=%d %x %x pc=%x\n", - __func__, c, addr, value, ctrl->env->pc)); + D(printf ("%s c=%d %x %x\n", __func__, c, addr)); break; } } diff --git a/hw/etraxfs_eth.c b/hw/etraxfs_eth.c index 96cec8ad2..9ef610fd1 100644 --- a/hw/etraxfs_eth.c +++ b/hw/etraxfs_eth.c @@ -330,15 +330,14 @@ static uint32_t eth_rinvalid (void *opaque, target_phys_addr_t addr) { struct fs_eth *eth = opaque; CPUState *env = eth->env; - cpu_abort(env, "Unsupported short access. reg=" TARGET_FMT_plx - " pc=%x.\n", addr, env->pc); + cpu_abort(env, "Unsupported short access. reg=" TARGET_FMT_plx "\n", + addr); return 0; } static uint32_t eth_readl (void *opaque, target_phys_addr_t addr) { struct fs_eth *eth = opaque; - D(CPUState *env = eth->env); uint32_t r = 0; /* Make addr relative to this instances base. */ @@ -350,7 +349,7 @@ static uint32_t eth_readl (void *opaque, target_phys_addr_t addr) break; default: r = eth->regs[addr]; - D(printf ("%s %x p=%x\n", __func__, addr, env->pc)); + D(printf ("%s %x\n", __func__, addr)); break; } return r; @@ -361,8 +360,8 @@ eth_winvalid (void *opaque, target_phys_addr_t addr, uint32_t value) { struct fs_eth *eth = opaque; CPUState *env = eth->env; - cpu_abort(env, "Unsupported short access. reg=" TARGET_FMT_plx - " pc=%x.\n", addr, env->pc); + cpu_abort(env, "Unsupported short access. reg=" TARGET_FMT_plx "\n", + addr); } static void eth_update_ma(struct fs_eth *eth, int ma) diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c index bb971f8d2..11a0f2210 100644 --- a/hw/etraxfs_ser.c +++ b/hw/etraxfs_ser.c @@ -89,7 +89,7 @@ static void ser_update_irq(struct etrax_serial_t *s) static uint32_t ser_readb (void *opaque, target_phys_addr_t addr) { D(CPUState *env = opaque); - D(printf ("%s %x pc=%x\n", __func__, addr, env->pc)); + D(printf ("%s %x\n", __func__, addr)); return 0; } @@ -132,7 +132,7 @@ static uint32_t ser_readl (void *opaque, target_phys_addr_t addr) break; default: - D(printf ("%s %x p=%x\n", __func__, addr, env->pc)); + D(printf ("%s %x\n", __func__, addr)); break; } return r; @@ -143,7 +143,7 @@ ser_writeb (void *opaque, target_phys_addr_t addr, uint32_t value) { D(struct etrax_serial_t *s = opaque); D(CPUState *env = s->env); - D(printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc)); + D(printf ("%s %x %x\n", __func__, addr, value)); } static void ser_writel (void *opaque, target_phys_addr_t addr, uint32_t value) @@ -181,8 +181,7 @@ ser_writel (void *opaque, target_phys_addr_t addr, uint32_t value) s->rw_intr_mask = value; break; default: - D(printf ("%s %x %x pc=%x\n", - __func__, addr, value, env->pc)); + D(printf ("%s %x %x\n", __func__, addr, value)); break; } ser_update_irq(s); diff --git a/hw/etraxfs_timer.c b/hw/etraxfs_timer.c index 789992a2d..8d4505192 100644 --- a/hw/etraxfs_timer.c +++ b/hw/etraxfs_timer.c @@ -80,15 +80,14 @@ static uint32_t timer_rinvalid (void *opaque, target_phys_addr_t addr) { struct fs_timer_t *t = opaque; CPUState *env = t->env; - cpu_abort(env, "Unsupported short access. reg=" TARGET_FMT_plx - " pc=%x.\n", addr, env->pc); + cpu_abort(env, "Unsupported short access. reg=" TARGET_FMT_plx "\n", + addr); return 0; } static uint32_t timer_readl (void *opaque, target_phys_addr_t addr) { struct fs_timer_t *t = opaque; - D(CPUState *env = t->env); uint32_t r = 0; /* Make addr relative to this instances base. */ @@ -109,7 +108,7 @@ static uint32_t timer_readl (void *opaque, target_phys_addr_t addr) r = t->r_intr & t->rw_intr_mask; break; default: - D(printf ("%s %x p=%x\n", __func__, addr, env->pc)); + D(printf ("%s %x\n", __func__, addr)); break; } return r; @@ -120,8 +119,8 @@ timer_winvalid (void *opaque, target_phys_addr_t addr, uint32_t value) { struct fs_timer_t *t = opaque; CPUState *env = t->env; - cpu_abort(env, "Unsupported short access. reg=" TARGET_FMT_plx - " pc=%x.\n", addr, env->pc); + cpu_abort(env, "Unsupported short access. reg=" TARGET_FMT_plx "\n", + addr); } #define TIMER_SLOWDOWN 1 @@ -273,7 +272,6 @@ static void timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value) { struct fs_timer_t *t = opaque; - CPUState *env = t->env; /* Make addr relative to this instances base. */ addr -= t->base; @@ -309,8 +307,8 @@ timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value) t->rw_ack_intr = 0; break; default: - printf ("%s " TARGET_FMT_plx " %x pc=%x\n", - __func__, addr, value, env->pc); + printf ("%s " TARGET_FMT_plx " %x\n", + __func__, addr, value); break; } } -- cgit v1.2.3 From 6913ba56807e5a5275bd839550e8a951d2ef63af Mon Sep 17 00:00:00 2001 From: edgar_igl Date: Mon, 30 Jun 2008 15:27:47 +0000 Subject: CRIS: Correct writes to TLB hi. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4807 c046a42c-6fe2-441c-8c8c-71466251a162 --- target-cris/op_helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target-cris/op_helper.c b/target-cris/op_helper.c index 0e7d3c37f..148c1e08f 100644 --- a/target-cris/op_helper.c +++ b/target-cris/op_helper.c @@ -121,8 +121,8 @@ void helper_movl_sreg_reg (uint32_t sreg, uint32_t reg) if (sreg == 6) { /* Writes to tlb-hi write to mm_cause as a side effect. */ - env->sregs[SFR_RW_MM_TLB_HI] = T0; - env->sregs[SFR_R_MM_CAUSE] = T0; + env->sregs[SFR_RW_MM_TLB_HI] = env->regs[reg]; + env->sregs[SFR_R_MM_CAUSE] = env->regs[reg]; } else if (sreg == 5) { uint32_t set; -- cgit v1.2.3 From b3c7724cbc70109630227c92df2d59deca4dab64 Mon Sep 17 00:00:00 2001 From: pbrook Date: Mon, 30 Jun 2008 16:31:04 +0000 Subject: Move CPU save/load registration to common code. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4808 c046a42c-6fe2-441c-8c8c-71466251a162 --- exec.c | 5 +++++ hw/etraxfs.c | 1 - hw/mips_jazz.c | 1 - hw/mips_malta.c | 1 - hw/mips_mipssim.c | 1 - hw/mips_r4k.c | 1 - hw/pc.c | 1 - hw/ppc4xx_devs.c | 1 - hw/ppc_chrp.c | 1 - hw/ppc_oldworld.c | 1 - hw/ppc_prep.c | 1 - hw/pxa2xx.c | 6 ------ hw/sun4m.c | 3 --- hw/sun4u.c | 1 - qemu-common.h | 4 ++++ sysemu.h | 3 --- target-arm/cpu.h | 2 +- target-arm/machine.c | 2 +- target-cris/cpu.h | 2 ++ target-i386/cpu.h | 2 ++ target-mips/cpu.h | 2 ++ target-ppc/cpu.h | 2 ++ target-sparc/cpu.h | 2 ++ 23 files changed, 21 insertions(+), 25 deletions(-) diff --git a/exec.c b/exec.c index 06d92538f..a664b6fab 100644 --- a/exec.c +++ b/exec.c @@ -37,6 +37,7 @@ #include "exec-all.h" #include "qemu-common.h" #include "tcg.h" +#include "hw/hw.h" #if defined(CONFIG_USER_ONLY) #include #endif @@ -457,6 +458,10 @@ void cpu_exec_init(CPUState *env) env->cpu_index = cpu_index; env->nb_watchpoints = 0; *penv = env; +#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY) + register_savevm("cpu", cpu_index, CPU_SAVE_VERSION, + cpu_save, cpu_load, env); +#endif } static inline void invalidate_page_bitmap(PageDesc *p) diff --git a/hw/etraxfs.c b/hw/etraxfs.c index 0efcd831f..276f1fd09 100644 --- a/hw/etraxfs.c +++ b/hw/etraxfs.c @@ -67,7 +67,6 @@ void bareetraxfs_init (ram_addr_t ram_size, int vga_ram_size, cpu_model = "crisv32"; } env = cpu_init(cpu_model); - register_savevm("cpu", 0, 1, cpu_save, cpu_load, env); qemu_register_reset(main_cpu_reset, env); /* allocate RAM */ diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c index bfd8b53bc..52cf47b84 100644 --- a/hw/mips_jazz.c +++ b/hw/mips_jazz.c @@ -146,7 +146,6 @@ void mips_jazz_init (ram_addr_t ram_size, int vga_ram_size, fprintf(stderr, "Unable to find CPU definition\n"); exit(1); } - register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); qemu_register_reset(main_cpu_reset, env); /* allocate RAM */ diff --git a/hw/mips_malta.c b/hw/mips_malta.c index cc31082e2..a19a69f56 100644 --- a/hw/mips_malta.c +++ b/hw/mips_malta.c @@ -802,7 +802,6 @@ void mips_malta_init (ram_addr_t ram_size, int vga_ram_size, fprintf(stderr, "Unable to find CPU definition\n"); exit(1); } - register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); qemu_register_reset(main_cpu_reset, env); /* allocate RAM */ diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c index af09d9599..d04c660b4 100644 --- a/hw/mips_mipssim.c +++ b/hw/mips_mipssim.c @@ -129,7 +129,6 @@ mips_mipssim_init (ram_addr_t ram_size, int vga_ram_size, fprintf(stderr, "Unable to find CPU definition\n"); exit(1); } - register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); qemu_register_reset(main_cpu_reset, env); /* Allocate RAM. */ diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c index 4540cbf45..a9d42eadc 100644 --- a/hw/mips_r4k.c +++ b/hw/mips_r4k.c @@ -175,7 +175,6 @@ void mips_r4k_init (ram_addr_t ram_size, int vga_ram_size, fprintf(stderr, "Unable to find CPU definition\n"); exit(1); } - register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); qemu_register_reset(main_cpu_reset, env); /* allocate RAM */ diff --git a/hw/pc.c b/hw/pc.c index 4c5e1c343..99df09d9a 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -764,7 +764,6 @@ static void pc_init1(ram_addr_t ram_size, int vga_ram_size, /* XXX: enable it in all cases */ env->cpuid_features |= CPUID_APIC; } - register_savevm("cpu", i, 5, cpu_save, cpu_load, env); qemu_register_reset(main_cpu_reset, env); if (pci_enabled) { apic_init(env); diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c index 125f2d43e..f9143dd4f 100644 --- a/hw/ppc4xx_devs.c +++ b/hw/ppc4xx_devs.c @@ -56,7 +56,6 @@ CPUState *ppc4xx_init (const unsigned char *cpu_model, ppc_dcr_init(env, NULL, NULL); /* Register qemu callbacks */ qemu_register_reset(&cpu_ppc_reset, env); - register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); return env; } diff --git a/hw/ppc_chrp.c b/hw/ppc_chrp.c index deb97611b..a100896c2 100644 --- a/hw/ppc_chrp.c +++ b/hw/ppc_chrp.c @@ -103,7 +103,6 @@ static void ppc_core99_init (ram_addr_t ram_size, int vga_ram_size, env->osi_call = vga_osi_call; #endif qemu_register_reset(&cpu_ppc_reset, env); - register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); envs[i] = env; } if (env->nip < 0xFFF80000) { diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c index be5ee6710..85d3b2ce8 100644 --- a/hw/ppc_oldworld.c +++ b/hw/ppc_oldworld.c @@ -143,7 +143,6 @@ static void ppc_heathrow_init (ram_addr_t ram_size, int vga_ram_size, cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL); env->osi_call = vga_osi_call; qemu_register_reset(&cpu_ppc_reset, env); - register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); envs[i] = env; } if (env->nip < 0xFFF80000) { diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c index 9238e6d43..88ba6b03d 100644 --- a/hw/ppc_prep.c +++ b/hw/ppc_prep.c @@ -580,7 +580,6 @@ static void ppc_prep_init (ram_addr_t ram_size, int vga_ram_size, cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL); } qemu_register_reset(&cpu_ppc_reset, env); - register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); envs[i] = env; } diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c index 6e06baada..cb6670c35 100644 --- a/hw/pxa2xx.c +++ b/hw/pxa2xx.c @@ -2046,9 +2046,6 @@ struct pxa2xx_state_s *pxa270_init(unsigned int sdram_size, fprintf(stderr, "Unable to find CPU definition\n"); exit(1); } - register_savevm("cpu", 0, ARM_CPU_SAVE_VERSION, cpu_save, cpu_load, - s->env); - s->reset = qemu_allocate_irqs(pxa2xx_reset, s, 1)[0]; /* SDRAM & Internal Memory Storage */ @@ -2173,9 +2170,6 @@ struct pxa2xx_state_s *pxa255_init(unsigned int sdram_size, fprintf(stderr, "Unable to find CPU definition\n"); exit(1); } - register_savevm("cpu", 0, ARM_CPU_SAVE_VERSION, cpu_save, cpu_load, - s->env); - s->reset = qemu_allocate_irqs(pxa2xx_reset, s, 1)[0]; /* SDRAM & Internal Memory Storage */ diff --git a/hw/sun4m.c b/hw/sun4m.c index e1ff225e3..899e2d506 100644 --- a/hw/sun4m.c +++ b/hw/sun4m.c @@ -426,7 +426,6 @@ static void sun4m_hw_init(const struct hwdef *hwdef, ram_addr_t RAM_size, qemu_register_reset(secondary_cpu_reset, env); env->halted = 1; } - register_savevm("cpu", i, 4, cpu_save, cpu_load, env); cpu_irqs[i] = qemu_allocate_irqs(cpu_set_irq, envs[i], MAX_PILS); env->prom_addr = hwdef->slavio_base; } @@ -601,7 +600,6 @@ static void sun4c_hw_init(const struct hwdef *hwdef, ram_addr_t RAM_size, cpu_sparc_set_id(env, 0); qemu_register_reset(main_cpu_reset, env); - register_savevm("cpu", 0, 4, cpu_save, cpu_load, env); cpu_irqs = qemu_allocate_irqs(cpu_set_irq, env, MAX_PILS); env->prom_addr = hwdef->slavio_base; @@ -1413,7 +1411,6 @@ static void sun4d_hw_init(const struct sun4d_hwdef *hwdef, ram_addr_t RAM_size, qemu_register_reset(secondary_cpu_reset, env); env->halted = 1; } - register_savevm("cpu", i, 4, cpu_save, cpu_load, env); cpu_irqs[i] = qemu_allocate_irqs(cpu_set_irq, envs[i], MAX_PILS); env->prom_addr = hwdef->slavio_base; } diff --git a/hw/sun4u.c b/hw/sun4u.c index f97c7a05b..c648314a6 100644 --- a/hw/sun4u.c +++ b/hw/sun4u.c @@ -282,7 +282,6 @@ static void sun4u_init(ram_addr_t RAM_size, int vga_ram_size, bh = qemu_bh_new(hstick_irq, env); env->hstick = ptimer_init(bh); ptimer_set_period(env->hstick, 1ULL); - register_savevm("cpu", 0, 4, cpu_save, cpu_load, env); qemu_register_reset(main_cpu_reset, env); main_cpu_reset(env); diff --git a/qemu-common.h b/qemu-common.h index a24614467..0512d4963 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -132,4 +132,8 @@ typedef struct SerialState SerialState; typedef struct IRQState *qemu_irq; struct pcmcia_card_s; +/* CPU save/load. */ +void cpu_save(QEMUFile *f, void *opaque); +int cpu_load(QEMUFile *f, void *opaque, int version_id); + #endif diff --git a/sysemu.h b/sysemu.h index f666f73fa..b12fae0a9 100644 --- a/sysemu.h +++ b/sysemu.h @@ -41,9 +41,6 @@ void qemu_system_powerdown(void); #endif void qemu_system_reset(void); -void cpu_save(QEMUFile *f, void *opaque); -int cpu_load(QEMUFile *f, void *opaque, int version_id); - void do_savevm(const char *name); void do_loadvm(const char *name); void do_delvm(const char *name); diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 6b16e5d04..1d7333264 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -397,7 +397,7 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum, #define cpu_signal_handler cpu_arm_signal_handler #define cpu_list arm_cpu_list -#define ARM_CPU_SAVE_VERSION 1 +#define CPU_SAVE_VERSION 1 /* MMU modes definitions */ #define MMU_MODE0_SUFFIX _kernel diff --git a/target-arm/machine.c b/target-arm/machine.c index 6637e72ed..42ff5844c 100644 --- a/target-arm/machine.c +++ b/target-arm/machine.c @@ -120,7 +120,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) CPUARMState *env = (CPUARMState *)opaque; int i; - if (version_id != ARM_CPU_SAVE_VERSION) + if (version_id != CPU_SAVE_VERSION) return -EINVAL; for (i = 0; i < 16; i++) { diff --git a/target-cris/cpu.h b/target-cris/cpu.h index d086221d3..e45456858 100644 --- a/target-cris/cpu.h +++ b/target-cris/cpu.h @@ -210,6 +210,8 @@ enum { #define cpu_gen_code cpu_cris_gen_code #define cpu_signal_handler cpu_cris_signal_handler +#define CPU_SAVE_VERSION 1 + /* MMU modes definitions */ #define MMU_MODE0_SUFFIX _kernel #define MMU_MODE1_SUFFIX _user diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 285b5a750..098d5e48e 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -726,6 +726,8 @@ static inline int cpu_get_time_fast(void) #define cpu_signal_handler cpu_x86_signal_handler #define cpu_list x86_cpu_list +#define CPU_SAVE_VERSION 5 + /* MMU modes definitions */ #define MMU_MODE0_SUFFIX _kernel #define MMU_MODE1_SUFFIX _user diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 8e21f6b4a..93c1610f1 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -489,6 +489,8 @@ void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec, #define cpu_signal_handler cpu_mips_signal_handler #define cpu_list mips_cpu_list +#define CPU_SAVE_VERSION 3 + /* MMU modes definitions. We carefully match the indices with our hflags layout. */ #define MMU_MODE0_SUFFIX _kernel diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index d9dcf58ef..4e1f2f14f 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -813,6 +813,8 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val); #define cpu_signal_handler cpu_ppc_signal_handler #define cpu_list ppc_cpu_list +#define CPU_SAVE_VERSION 3 + /* MMU modes definitions */ #define MMU_MODE0_SUFFIX _user #define MMU_MODE1_SUFFIX _kernel diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index 03bc2dfd0..34a20cd2a 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -388,6 +388,8 @@ void cpu_check_irqs(CPUSPARCState *env); #define cpu_signal_handler cpu_sparc_signal_handler #define cpu_list sparc_cpu_list +#define CPU_SAVE_VERSION 4 + /* MMU modes definitions */ #define MMU_MODE0_SUFFIX _user #define MMU_MODE1_SUFFIX _kernel -- cgit v1.2.3 From bf20dc076b30e474635679e167c3ac04b656bb63 Mon Sep 17 00:00:00 2001 From: ths Date: Mon, 30 Jun 2008 17:22:19 +0000 Subject: Spelling fixes, spotted by Stuart Brady. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4809 c046a42c-6fe2-441c-8c8c-71466251a162 --- cpu-exec.c | 2 +- exec-all.h | 2 +- exec.c | 12 ++++++------ gen-icount.h | 2 +- target-arm/translate.c | 2 +- target-cris/translate.c | 2 +- target-m68k/translate.c | 2 +- target-mips/translate.c | 4 ++-- vl.c | 8 ++++---- 9 files changed, 18 insertions(+), 18 deletions(-) diff --git a/cpu-exec.c b/cpu-exec.c index 08e10f432..6b46bd2c9 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -620,7 +620,7 @@ int cpu_exec(CPUState *env1) next_tb = tcg_qemu_tb_exec(tc_ptr); env->current_tb = NULL; if ((next_tb & 3) == 2) { - /* Instruction counter exired. */ + /* Instruction counter expired. */ int insns_left; tb = (TranslationBlock *)(long)(next_tb & ~3); /* Restore PC. */ diff --git a/exec-all.h b/exec-all.h index b16937000..4469e95c8 100644 --- a/exec-all.h +++ b/exec-all.h @@ -372,7 +372,7 @@ static inline target_ulong get_phys_addr_code(CPUState *env1, target_ulong addr) return addr + env1->tlb_table[mmu_idx][page_index].addend - (unsigned long)phys_ram_base; } -/* Deterministic execution requires that IO only be performaed on the last +/* Deterministic execution requires that IO only be performed on the last instruction of a TB so that interrupts take effect immediately. */ static inline int can_do_io(CPUState *env) { diff --git a/exec.c b/exec.c index a664b6fab..64c87b31e 100644 --- a/exec.c +++ b/exec.c @@ -109,7 +109,7 @@ CPUState *first_cpu; cpu_exec() */ CPUState *cpu_single_env; /* 0 = Do not count executed instructions. - 1 = Precice instruction counting. + 1 = Precise instruction counting. 2 = Adaptive rate instruction counting. */ int use_icount = 0; /* Current instruction counter. While executing translated code this may @@ -1080,7 +1080,7 @@ TranslationBlock *tb_alloc(target_ulong pc) void tb_free(TranslationBlock *tb) { - /* In practice this is mostly used for single use temorary TB + /* In practice this is mostly used for single use temporary TB Ignore the hard cases and just back up if this TB happens to be the last one generated. */ if (nb_tbs > 0 && tb == &tbs[nb_tbs - 1]) { @@ -1394,7 +1394,7 @@ void cpu_interrupt(CPUState *env, int mask) old_mask = env->interrupt_request; /* FIXME: This is probably not threadsafe. A different thread could - be in the mittle of a read-modify-write operation. */ + be in the middle of a read-modify-write operation. */ env->interrupt_request |= mask; #if defined(USE_NPTL) /* FIXME: TB unchaining isn't SMP safe. For now just ignore the @@ -3019,13 +3019,13 @@ void cpu_io_recompile(CPUState *env, void *retaddr) n = env->icount_decr.u16.low + tb->icount; cpu_restore_state(tb, env, (unsigned long)retaddr, NULL); /* Calculate how many instructions had been executed before the fault - occured. */ + occurred. */ n = n - env->icount_decr.u16.low; /* Generate a new TB ending on the I/O insn. */ n++; /* On MIPS and SH, delay slot instructions can only be restarted if they were already the first instruction in the TB. If this is not - the first instruction in a TB then re-execute the preceeding + the first instruction in a TB then re-execute the preceding branch. */ #if defined(TARGET_MIPS) if ((env->hflags & MIPS_HFLAG_BMASK) != 0 && n > 1) { @@ -3053,7 +3053,7 @@ void cpu_io_recompile(CPUState *env, void *retaddr) /* FIXME: In theory this could raise an exception. In practice we have already translated the block once so it's probably ok. */ tb_gen_code(env, pc, cs_base, flags, cflags); - /* TODO: If env->pc != tb->pc (i.e. the failuting instruction was not + /* TODO: If env->pc != tb->pc (i.e. the faulting instruction was not the first in the TB) then we end up generating a whole new TB and repeating the fault, which is horribly inefficient. Better would be to execute just this insn uncached, or generate a diff --git a/gen-icount.h b/gen-icount.h index 172b2bc7d..61545f157 100644 --- a/gen-icount.h +++ b/gen-icount.h @@ -1,4 +1,4 @@ -/* Helpewrs for instruction counting code genration. */ +/* Helpers for instruction counting code generation. */ static TCGArg *icount_arg; static int icount_label; diff --git a/target-arm/translate.c b/target-arm/translate.c index b9b9838fe..2831432e7 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -8684,7 +8684,7 @@ static inline int gen_intermediate_code_internal(CPUState *env, /* Translation stops when a conditional branch is enoutered. * Otherwise the subsequent code could get translated several times. * Also stop translation when a page boundary is reached. This - * ensures prefech aborts occur at the right place. */ + * ensures prefetch aborts occur at the right place. */ num_insns ++; } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && !env->singlestep_enabled && diff --git a/target-cris/translate.c b/target-cris/translate.c index 2fc4101d4..81b61326f 100644 --- a/target-cris/translate.c +++ b/target-cris/translate.c @@ -3141,7 +3141,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, num_insns++; /* Check for delayed branches here. If we do it before - actually genereating any host code, the simulator will just + actually generating any host code, the simulator will just loop doing nothing for on this program location. */ if (dc->delayed_branch) { dc->delayed_branch--; diff --git a/target-m68k/translate.c b/target-m68k/translate.c index a920d213b..e808db5e8 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -2980,7 +2980,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, num_insns++; /* Terminate the TB on memory ops if watchpoints are present. */ - /* FIXME: This should be replacd by the deterministic execution + /* FIXME: This should be replaced by the deterministic execution * IRQ raising bits. */ if (dc->is_mem && env->nb_watchpoints) break; diff --git a/target-mips/translate.c b/target-mips/translate.c index bd14e3255..c1b38233a 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -3998,7 +3998,7 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int se rn, reg, sel); } #endif - /* For simplicitly assume that all writes can cause interrupts. */ + /* For simplicity assume that all writes can cause interrupts. */ if (use_icount) { gen_io_end(); ctx->bstate = BS_STOP; @@ -5170,7 +5170,7 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int s } #endif tcg_temp_free(t0); - /* For simplicitly assume that all writes can cause interrupts. */ + /* For simplicity assume that all writes can cause interrupts. */ if (use_icount) { gen_io_end(); ctx->bstate = BS_STOP; diff --git a/vl.c b/vl.c index 00d43eeee..d6da115eb 100644 --- a/vl.c +++ b/vl.c @@ -239,9 +239,9 @@ struct drive_opt { static CPUState *cur_cpu; static CPUState *next_cpu; static int event_pending = 1; -/* Conversion factor from emulated instrctions to virtual clock ticks. */ +/* Conversion factor from emulated instructions to virtual clock ticks. */ static int icount_time_shift; -/* Arbitrarily pick 1MIPS as the minimum alowable speed. */ +/* Arbitrarily pick 1MIPS as the minimum allowable speed. */ #define MAX_ICOUNT_SHIFT 10 /* Compensate for varying guest execution speed. */ static int64_t qemu_icount_bias; @@ -903,7 +903,7 @@ static void rtc_stop_timer(struct qemu_alarm_timer *t); #endif /* _WIN32 */ /* Correlation between real and virtual time is always going to be - farly approximate, so ignore small variation. + fairly approximate, so ignore small variation. When the guest is idle real and virtual time will be aligned in the IO wait loop. */ #define ICOUNT_WOBBLE (QEMU_TIMER_BASE / 10) @@ -7262,7 +7262,7 @@ static int main_loop(void) if (use_icount == 1) { /* When not using an adaptive execution frequency we tend to get badly out of sync with real time, - so just delay for a resonable amount of time. */ + so just delay for a reasonable amount of time. */ delta = 0; } else { delta = cpu_get_icount() - cpu_get_clock(); -- cgit v1.2.3 From efade670fe2c97c820cff17bb9d7817b8607c5fb Mon Sep 17 00:00:00 2001 From: pbrook Date: Mon, 30 Jun 2008 17:51:26 +0000 Subject: Fix rdtsc instruction counting. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4810 c046a42c-6fe2-441c-8c8c-71466251a162 --- target-i386/translate.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/target-i386/translate.c b/target-i386/translate.c index ea0933ef5..f7313ea8e 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -6382,7 +6382,13 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_jmp_im(pc_start - s->cs_base); + if (use_icount) + gen_io_start(); tcg_gen_helper_0_0(helper_rdtsc); + if (use_icount) { + gen_io_end(); + gen_jmp(s, s->pc - s->cs_base); + } break; case 0x133: /* rdpmc */ if (s->cc_op != CC_OP_DYNAMIC) -- cgit v1.2.3 From ea334207a3152e5e4fee4cb82a76233fd43fa14d Mon Sep 17 00:00:00 2001 From: ths Date: Tue, 1 Jul 2008 08:45:45 +0000 Subject: Delete duplicate code. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4811 c046a42c-6fe2-441c-8c8c-71466251a162 --- target-mips/translate.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index c1b38233a..76a963de0 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -7897,9 +7897,6 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, if (gen_opc_ptr >= gen_opc_end) break; - if (gen_opc_ptr >= gen_opc_end) - break; - if (num_insns >= max_insns) break; #if defined (MIPS_SINGLE_STEP) -- cgit v1.2.3 From c60e08d9c6bbace33c04dab2b5cacbc42e2e3d47 Mon Sep 17 00:00:00 2001 From: pbrook Date: Tue, 1 Jul 2008 16:24:38 +0000 Subject: Implement resolution switching in common console code. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4812 c046a42c-6fe2-441c-8c8c-71466251a162 --- console.c | 35 ++++++++++++++++++++--------------- console.h | 1 + hw/blizzard.c | 9 +++++---- hw/cirrus_vga.c | 4 ++-- hw/g364fb.c | 17 +++++++---------- hw/jazz_led.c | 11 +++++++---- hw/musicpal.c | 15 ++++----------- hw/nseries.c | 4 +++- hw/omap_lcdc.c | 10 ++++++---- hw/palm.c | 3 +++ hw/pl110.c | 11 +++++++---- hw/pxa2xx_lcd.c | 10 ++++++---- hw/ssd0303.c | 8 +++++--- hw/ssd0323.c | 10 ++++++---- hw/tcx.c | 18 ++++++++---------- hw/vga.c | 20 ++++++++++---------- hw/vga_int.h | 1 + hw/vmware_vga.c | 10 ++++++---- qemu-common.h | 1 + vl.c | 2 +- 20 files changed, 109 insertions(+), 91 deletions(-) diff --git a/console.c b/console.c index 880ac831a..a1bc769c8 100644 --- a/console.c +++ b/console.c @@ -28,6 +28,7 @@ //#define DEBUG_CONSOLE #define DEFAULT_BACKSCROLL 512 #define MAX_CONSOLES 12 +#define DEFAULT_MONITOR_SIZE "800x600" #define QEMU_RGBA(r, g, b, a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)) #define QEMU_RGB(r, g, b) QEMU_RGBA(r, g, b, 0xff) @@ -108,8 +109,7 @@ static int qemu_fifo_read(QEMUFIFO *f, uint8_t *buf, int len1) typedef enum { GRAPHIC_CONSOLE, - TEXT_CONSOLE, - TEXT_CONSOLE_FIXED_SIZE + TEXT_CONSOLE } console_type_t; /* ??? This is mis-named. @@ -1041,6 +1041,9 @@ void console_select(unsigned int index) s = consoles[index]; if (s) { active_console = s; + if (s->g_width && s->g_height + && (s->g_width != s->ds->width || s->g_height != s->ds->height)) + dpy_resize(s->ds, s->g_width, s->g_height); vga_hw_invalidate(); } } @@ -1149,18 +1152,6 @@ static void text_console_invalidate(void *opaque) { TextConsole *s = (TextConsole *) opaque; - if (s->console_type != GRAPHIC_CONSOLE) { - if (s->g_width != s->ds->width || - s->g_height != s->ds->height) { - if (s->console_type == TEXT_CONSOLE_FIXED_SIZE) - dpy_resize(s->ds, s->g_width, s->g_height); - else { - s->g_width = s->ds->width; - s->g_height = s->ds->height; - text_console_resize(s); - } - } - } console_refresh(s); } @@ -1268,11 +1259,14 @@ CharDriverState *text_console_init(DisplayState *ds, const char *p) chr = qemu_mallocz(sizeof(CharDriverState)); if (!chr) return NULL; - s = new_console(ds, (p == 0) ? TEXT_CONSOLE : TEXT_CONSOLE_FIXED_SIZE); + s = new_console(ds, TEXT_CONSOLE); if (!s) { free(chr); return NULL; } + if (!p) + p = DEFAULT_MONITOR_SIZE; + chr->opaque = s; chr->chr_write = console_puts; chr->chr_send_event = console_send_event; @@ -1332,3 +1326,14 @@ CharDriverState *text_console_init(DisplayState *ds, const char *p) return chr; } + +void qemu_console_resize(QEMUConsole *console, int width, int height) +{ + if (console->g_width != width || console->g_height != height) { + console->g_width = width; + console->g_height = height; + if (active_console == console) { + dpy_resize(console->ds, width, height); + } + } +} diff --git a/console.h b/console.h index c7f29f507..561ef51bc 100644 --- a/console.h +++ b/console.h @@ -135,6 +135,7 @@ int is_graphic_console(void); CharDriverState *text_console_init(DisplayState *ds, const char *p); void console_select(unsigned int index); void console_color_init(DisplayState *ds); +void qemu_console_resize(QEMUConsole *console, int width, int height); /* sdl.c */ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame); diff --git a/hw/blizzard.c b/hw/blizzard.c index 9ad7e6a15..37330e7f2 100644 --- a/hw/blizzard.c +++ b/hw/blizzard.c @@ -73,6 +73,7 @@ struct blizzard_s { uint8_t iformat; uint8_t source; DisplayState *state; + QEMUConsole *console; blizzard_fn_t *line_fn_tab[2]; void *fb; @@ -896,7 +897,7 @@ static void blizzard_update_display(void *opaque) if (s->x != s->state->width || s->y != s->state->height) { s->invalidate = 1; - dpy_resize(s->state, s->x, s->y); + qemu_console_resize(s->console, s->x, s->y); } if (s->invalidate) { @@ -993,9 +994,9 @@ void *s1d13745_init(qemu_irq gpio_int, DisplayState *ds) blizzard_reset(s); - graphic_console_init(s->state, blizzard_update_display, - blizzard_invalidate_display, blizzard_screen_dump, - NULL, s); + s->console = graphic_console_init(s->state, blizzard_update_display, + blizzard_invalidate_display, + blizzard_screen_dump, NULL, s); return s; } diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c index 4e9f98d37..2d0f66ab0 100644 --- a/hw/cirrus_vga.c +++ b/hw/cirrus_vga.c @@ -3288,8 +3288,8 @@ void pci_cirrus_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, ds, vga_ram_base, vga_ram_offset, vga_ram_size); cirrus_init_common(s, device_id, 1); - graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, - s->text_update, s); + s->console = graphic_console_init(s->ds, s->update, s->invalidate, + s->screen_dump, s->text_update, s); s->pci_dev = (PCIDevice *)d; diff --git a/hw/g364fb.c b/hw/g364fb.c index 0dd4ee766..3dfc8e1cd 100644 --- a/hw/g364fb.c +++ b/hw/g364fb.c @@ -33,6 +33,7 @@ typedef struct G364State { uint8_t palette[256][3]; /* display refresh support */ DisplayState *ds; + QEMUConsole *console; int graphic_mode; uint32_t scr_width, scr_height; /* in pixels */ uint32_t last_scr_width, last_scr_height; /* in pixels */ @@ -74,13 +75,6 @@ static void g364fb_draw_graphic(G364State *s, int full_update) { if (s->scr_width == 0 || s->scr_height == 0) return; - if (s->scr_width != s->last_scr_width - || s->scr_height != s->last_scr_height) { - s->last_scr_width = s->scr_width; - s->last_scr_height = s->scr_height; - dpy_resize(s->ds, s->last_scr_width, s->last_scr_height); - full_update = 1; - } switch (s->ds->depth) { case 8: @@ -272,7 +266,10 @@ static void g364fb_ctrl_writeb(void *opaque, target_phys_addr_t addr, uint32_t v #endif break; } + if (s->scr_width && s->scr_height) + qemu_console_resize(s->console, s->scr_width, s->scr_height); } + s->graphic_mode = -1; /* force full update */ } static void g364fb_ctrl_writew(void *opaque, target_phys_addr_t addr, uint32_t val) @@ -382,9 +379,9 @@ int g364fb_mm_init(DisplayState *ds, s->ds = ds; s->vram_base = vram_base; - graphic_console_init(ds, g364fb_update_display, - g364fb_invalidate_display, g364fb_screen_dump, - NULL, s); + s->console = graphic_console_init(ds, g364fb_update_display, + g364fb_invalidate_display, + g364fb_screen_dump, NULL, s); io_vram = cpu_register_io_memory(0, g364fb_mem_read, g364fb_mem_write, s); cpu_register_physical_memory(s->vram_base, vram_size, io_vram); diff --git a/hw/jazz_led.c b/hw/jazz_led.c index d547138b9..8460bfcd5 100644 --- a/hw/jazz_led.c +++ b/hw/jazz_led.c @@ -37,6 +37,7 @@ typedef struct LedState { target_phys_addr_t base; uint8_t segments; DisplayState *ds; + QEMUConsole *console; screen_state_t state; } LedState; @@ -291,7 +292,7 @@ static void jazz_led_text_update(void *opaque, console_ch_t *chardata) char buf[2]; dpy_cursor(s->ds, -1, -1); - dpy_resize(s->ds, 2, 1); + qemu_console_resize(s->console, 2, 1); /* TODO: draw the segments */ snprintf(buf, 2, "%02hhx\n", s->segments); @@ -317,7 +318,9 @@ void jazz_led_init(DisplayState *ds, target_phys_addr_t base) io = cpu_register_io_memory(0, led_read, led_write, s); cpu_register_physical_memory(s->base, 1, io); - graphic_console_init(ds, jazz_led_update_display, - jazz_led_invalidate_display, jazz_led_screen_dump, - jazz_led_text_update, s); + s->console = graphic_console_init(ds, jazz_led_update_display, + jazz_led_invalidate_display, + jazz_led_screen_dump, + jazz_led_text_update, s); + qemu_console_resize(s->console, 60, 80); } diff --git a/hw/musicpal.c b/hw/musicpal.c index b0fcee25b..e4d8c89be 100644 --- a/hw/musicpal.c +++ b/hw/musicpal.c @@ -758,8 +758,8 @@ typedef struct musicpal_lcd_state { int page; int page_off; DisplayState *ds; + QEMUConsole *console; uint8_t video_ram[128*64/8]; - int invalidate; } musicpal_lcd_state; static uint32_t lcd_brightness; @@ -818,11 +818,6 @@ static void lcd_refresh(void *opaque) musicpal_lcd_state *s = opaque; int x, y, col; - if (s->invalidate && (s->ds->width != 128*3 || s->ds->height != 64*3)) { - dpy_resize(s->ds, 128*3, 64*3); - s->invalidate = 0; - } - switch (s->ds->depth) { case 0: return; @@ -851,9 +846,6 @@ static void lcd_refresh(void *opaque) static void lcd_invalidate(void *opaque) { - musicpal_lcd_state *s = opaque; - - s->invalidate = 1; } static uint32_t musicpal_lcd_read(void *opaque, target_phys_addr_t offset) @@ -932,12 +924,13 @@ static void musicpal_lcd_init(DisplayState *ds, uint32_t base) return; s->base = base; s->ds = ds; - s->invalidate = 1; iomemtype = cpu_register_io_memory(0, musicpal_lcd_readfn, musicpal_lcd_writefn, s); cpu_register_physical_memory(base, MP_LCD_SIZE, iomemtype); - graphic_console_init(ds, lcd_refresh, lcd_invalidate, NULL, NULL, s); + s->console = graphic_console_init(ds, lcd_refresh, lcd_invalidate, + NULL, NULL, s); + qemu_console_resize(s->console, 128*3, 64*3); } /* PIC register offsets */ diff --git a/hw/nseries.c b/hw/nseries.c index 5620897b1..725554d44 100644 --- a/hw/nseries.c +++ b/hw/nseries.c @@ -1307,7 +1307,9 @@ static void n8x0_init(ram_addr_t ram_size, const char *boot_device, n800_setup_nolo_tags(phys_ram_base + sdram_size); } - + /* FIXME: We shouldn't really be doing this here. The LCD controller + will set the size once configured, so this just sets an initial + size until the guest activates the display. */ dpy_resize(ds, 800, 480); } diff --git a/hw/omap_lcdc.c b/hw/omap_lcdc.c index 42174f7e0..99e8b4fa4 100644 --- a/hw/omap_lcdc.c +++ b/hw/omap_lcdc.c @@ -26,6 +26,7 @@ struct omap_lcd_panel_s { target_phys_addr_t base; qemu_irq irq; DisplayState *state; + QEMUConsole *console; ram_addr_t imif_base; ram_addr_t emiff_base; @@ -175,8 +176,8 @@ static void omap_update_display(void *opaque) width = omap_lcd->width; if (width != omap_lcd->state->width || omap_lcd->height != omap_lcd->state->height) { - dpy_resize(omap_lcd->state, - omap_lcd->width, omap_lcd->height); + qemu_console_resize(omap_lcd->console, + omap_lcd->width, omap_lcd->height); omap_lcd->invalidate = 1; } @@ -494,8 +495,9 @@ struct omap_lcd_panel_s *omap_lcdc_init(target_phys_addr_t base, qemu_irq irq, omap_lcdc_writefn, s); cpu_register_physical_memory(s->base, 0x100, iomemtype); - graphic_console_init(ds, omap_update_display, - omap_invalidate_display, omap_screen_dump, NULL, s); + s->console = graphic_console_init(ds, omap_update_display, + omap_invalidate_display, + omap_screen_dump, NULL, s); return s; } diff --git a/hw/palm.c b/hw/palm.c index a573ed7d1..9af0b1362 100644 --- a/hw/palm.c +++ b/hw/palm.c @@ -275,6 +275,9 @@ static void palmte_init(ram_addr_t ram_size, int vga_ram_size, arm_load_kernel(cpu->env, &palmte_binfo); } + /* FIXME: We shouldn't really be doing this here. The LCD controller + will set the size once configured, so this just sets an initial + size until the guest activates the display. */ dpy_resize(ds, 320, 320); } diff --git a/hw/pl110.c b/hw/pl110.c index 7f450851a..2437185f6 100644 --- a/hw/pl110.c +++ b/hw/pl110.c @@ -30,6 +30,8 @@ enum pl110_bppmode typedef struct { uint32_t base; DisplayState *ds; + QEMUConsole *console; + /* The Versatile/PB uses a slightly modified PL110 controller. */ int versatile; uint32_t timing[4]; @@ -270,7 +272,7 @@ static void pl110_resize(pl110_state *s, int width, int height) { if (width != s->cols || height != s->rows) { if (pl110_enabled(s)) { - dpy_resize(s->ds, width, height); + qemu_console_resize(s->console, width, height); } } s->cols = width; @@ -387,7 +389,7 @@ static void pl110_write(void *opaque, target_phys_addr_t offset, s->cr = val; s->bpp = (val >> 1) & 7; if (pl110_enabled(s)) { - dpy_resize(s->ds, s->cols, s->rows); + qemu_console_resize(s->console, s->cols, s->rows); } break; case 10: /* LCDICR */ @@ -425,8 +427,9 @@ void *pl110_init(DisplayState *ds, uint32_t base, qemu_irq irq, s->ds = ds; s->versatile = versatile; s->irq = irq; - graphic_console_init(ds, pl110_update_display, pl110_invalidate_display, - NULL, NULL, s); + s->console = graphic_console_init(ds, pl110_update_display, + pl110_invalidate_display, + NULL, NULL, s); /* ??? Save/restore. */ return s; } diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c index 7203a3fb6..5e834fe76 100644 --- a/hw/pxa2xx_lcd.c +++ b/hw/pxa2xx_lcd.c @@ -23,6 +23,7 @@ struct pxa2xx_lcdc_s { int invalidated; DisplayState *ds; + QEMUConsole *console; drawfn *line_fn[2]; int dest_width; int xres, yres; @@ -794,9 +795,9 @@ static void pxa2xx_lcdc_resize(struct pxa2xx_lcdc_s *s) if (width != s->xres || height != s->yres) { if (s->orientation) - dpy_resize(s->ds, height, width); + qemu_console_resize(s->console, height, width); else - dpy_resize(s->ds, width, height); + qemu_console_resize(s->console, width, height); s->invalidated = 1; s->xres = width; s->yres = height; @@ -1001,8 +1002,9 @@ struct pxa2xx_lcdc_s *pxa2xx_lcdc_init(target_phys_addr_t base, qemu_irq irq, pxa2xx_lcdc_writefn, s); cpu_register_physical_memory(base, 0x00100000, iomemtype); - graphic_console_init(ds, pxa2xx_update_display, - pxa2xx_invalidate_display, pxa2xx_screen_dump, NULL, s); + s->console = graphic_console_init(ds, pxa2xx_update_display, + pxa2xx_invalidate_display, + pxa2xx_screen_dump, NULL, s); switch (s->ds->depth) { case 0: diff --git a/hw/ssd0303.c b/hw/ssd0303.c index daa92924a..1b178f262 100644 --- a/hw/ssd0303.c +++ b/hw/ssd0303.c @@ -45,6 +45,7 @@ enum ssd0303_cmd { typedef struct { i2c_slave i2c; DisplayState *ds; + QEMUConsole *console; int row; int col; int start_line; @@ -269,7 +270,8 @@ void ssd0303_init(DisplayState *ds, i2c_bus *bus, int address) s->i2c.event = ssd0303_event; s->i2c.recv = ssd0303_recv; s->i2c.send = ssd0303_send; - graphic_console_init(ds, ssd0303_update_display, ssd0303_invalidate_display, - NULL, NULL, s); - dpy_resize(s->ds, 96 * MAGNIFY, 16 * MAGNIFY); + s->console = graphic_console_init(ds, ssd0303_update_display, + ssd0303_invalidate_display, + NULL, NULL, s); + qemu_console_resize(s->console, 96 * MAGNIFY, 16 * MAGNIFY); } diff --git a/hw/ssd0323.c b/hw/ssd0323.c index e2e619f07..3071596f0 100644 --- a/hw/ssd0323.c +++ b/hw/ssd0323.c @@ -44,6 +44,7 @@ enum ssd0323_mode typedef struct { DisplayState *ds; + QEMUConsole *console; int cmd_len; int cmd; @@ -278,12 +279,13 @@ void *ssd0323_init(DisplayState *ds, qemu_irq *cmd_p) qemu_irq *cmd; s = (ssd0323_state *)qemu_mallocz(sizeof(ssd0323_state)); - s->ds = ds; - graphic_console_init(ds, ssd0323_update_display, ssd0323_invalidate_display, - NULL, NULL, s); - dpy_resize(s->ds, 128 * MAGNIFY, 64 * MAGNIFY); s->col_end = 63; s->row_end = 79; + s->ds = ds; + s->console = graphic_console_init(ds, ssd0323_update_display, + ssd0323_invalidate_display, + NULL, NULL, s); + qemu_console_resize(s->console, 128 * MAGNIFY, 64 * MAGNIFY); cmd = qemu_allocate_irqs(ssd0323_cd, s, 1); *cmd_p = *cmd; diff --git a/hw/tcx.c b/hw/tcx.c index a63b44188..df02ea74e 100644 --- a/hw/tcx.c +++ b/hw/tcx.c @@ -36,6 +36,7 @@ typedef struct TCXState { target_phys_addr_t addr; DisplayState *ds; + QEMUConsole *console; uint8_t *vram; uint32_t *vram24, *cplane; ram_addr_t vram_offset, vram24_offset, cplane_offset; @@ -186,8 +187,6 @@ static void tcx_update_display(void *opaque) if (ts->ds->depth == 0) return; - if (ts->ds->width != ts->width || ts->ds->height != ts->height) - dpy_resize(ts->ds, ts->width, ts->height); page = ts->vram_offset; y_start = -1; page_min = 0xffffffff; @@ -266,8 +265,6 @@ static void tcx24_update_display(void *opaque) if (ts->ds->depth != 32) return; - if (ts->ds->width != ts->width || ts->ds->height != ts->height) - dpy_resize(ts->ds, ts->width, ts->height); page = ts->vram_offset; page24 = ts->vram24_offset; cpage = ts->cplane_offset; @@ -541,14 +538,15 @@ void tcx_init(DisplayState *ds, target_phys_addr_t addr, uint8_t *vram_base, s->cplane = (uint32_t *)vram_base; s->cplane_offset = vram_offset; cpu_register_physical_memory(addr + 0x0a000000ULL, size, vram_offset); - graphic_console_init(s->ds, tcx24_update_display, - tcx24_invalidate_display, - tcx24_screen_dump, NULL, s); + s->console = graphic_console_init(s->ds, tcx24_update_display, + tcx24_invalidate_display, + tcx24_screen_dump, NULL, s); } else { cpu_register_physical_memory(addr + 0x00300000ULL, TCX_THC_NREGS_8, dummy_memory); - graphic_console_init(s->ds, tcx_update_display, tcx_invalidate_display, - tcx_screen_dump, NULL, s); + s->console = graphic_console_init(s->ds, tcx_update_display, + tcx_invalidate_display, + tcx_screen_dump, NULL, s); } // NetBSD writes here even with 8-bit display cpu_register_physical_memory(addr + 0x00301000ULL, TCX_THC_NREGS_24, @@ -557,7 +555,7 @@ void tcx_init(DisplayState *ds, target_phys_addr_t addr, uint8_t *vram_base, register_savevm("tcx", addr, 4, tcx_save, tcx_load, s); qemu_register_reset(tcx_reset, s); tcx_reset(s); - dpy_resize(s->ds, width, height); + qemu_console_resize(s->console, width, height); } static void tcx_screen_dump(void *opaque, const char *filename) diff --git a/hw/vga.c b/hw/vga.c index 2e7de564f..5a3203c62 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -1155,7 +1155,7 @@ static void vga_draw_text(VGAState *s, int full_update) cw != s->last_cw || cheight != s->last_ch) { s->last_scr_width = width * cw; s->last_scr_height = height * cheight; - dpy_resize(s->ds, s->last_scr_width, s->last_scr_height); + qemu_console_resize(s->console, s->last_scr_width, s->last_scr_height); s->last_width = width; s->last_height = height; s->last_ch = cheight; @@ -1499,7 +1499,7 @@ static void vga_draw_graphic(VGAState *s, int full_update) if (disp_width != s->last_width || height != s->last_height) { - dpy_resize(s->ds, disp_width, height); + qemu_console_resize(s->console, disp_width, height); s->last_scr_width = disp_width; s->last_scr_height = height; s->last_width = disp_width; @@ -1734,7 +1734,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata) cw != s->last_cw || cheight != s->last_ch) { s->last_scr_width = width * cw; s->last_scr_height = height * cheight; - dpy_resize(s->ds, width, height); + qemu_console_resize(s->console, width, height); s->last_width = width; s->last_height = height; s->last_ch = cheight; @@ -1814,7 +1814,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata) s->last_width = 60; s->last_height = height = 3; dpy_cursor(s->ds, -1, -1); - dpy_resize(s->ds, s->last_width, height); + qemu_console_resize(s->console, s->last_width, height); for (dst = chardata, i = 0; i < s->last_width * height; i ++) console_write_ch(dst ++, ' '); @@ -2140,8 +2140,8 @@ int isa_vga_init(DisplayState *ds, uint8_t *vga_ram_base, vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size); vga_init(s); - graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, - s->text_update, s); + s->console = graphic_console_init(s->ds, s->update, s->invalidate, + s->screen_dump, s->text_update, s); #ifdef CONFIG_BOCHS_VBE /* XXX: use optimized standard vga accesses */ @@ -2165,8 +2165,8 @@ int isa_vga_mm_init(DisplayState *ds, uint8_t *vga_ram_base, vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size); vga_mm_init(s, vram_base, ctrl_base, it_shift); - graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, - s->text_update, s); + s->console = graphic_console_init(s->ds, s->update, s->invalidate, + s->screen_dump, s->text_update, s); #ifdef CONFIG_BOCHS_VBE /* XXX: use optimized standard vga accesses */ @@ -2194,8 +2194,8 @@ int pci_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size); vga_init(s); - graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, - s->text_update, s); + s->console = graphic_console_init(s->ds, s->update, s->invalidate, + s->screen_dump, s->text_update, s); s->pci_dev = &d->dev; diff --git a/hw/vga_int.h b/hw/vga_int.h index 5d11a7ac4..343da3457 100644 --- a/hw/vga_int.h +++ b/hw/vga_int.h @@ -121,6 +121,7 @@ VGA_STATE_COMMON_BOCHS_VBE \ /* display refresh support */ \ DisplayState *ds; \ + QEMUConsole *console; \ uint32_t font_offsets[2]; \ int graphic_mode; \ uint8_t shift_control; \ diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c index 2f9b15ccd..25c7915b4 100644 --- a/hw/vmware_vga.c +++ b/hw/vmware_vga.c @@ -57,6 +57,7 @@ struct vmsvga_state_s { #ifndef EMBED_STDVGA DisplayState *ds; + QEMUConsole *console; int vram_size; ram_addr_t vram_offset; #endif @@ -869,7 +870,7 @@ static inline void vmsvga_size(struct vmsvga_state_s *s) if (s->new_width != s->width || s->new_height != s->height) { s->width = s->new_width; s->height = s->new_height; - dpy_resize(s->ds, s->width, s->height); + qemu_console_resize(s->console, s->width, s->height); s->invalidated = 1; } } @@ -1122,9 +1123,10 @@ static void vmsvga_init(struct vmsvga_state_s *s, DisplayState *ds, vmsvga_reset(s); - graphic_console_init(ds, vmsvga_update_display, - vmsvga_invalidate_display, vmsvga_screen_dump, - vmsvga_text_update, s); + s->console = graphic_console_init(ds, vmsvga_update_display, + vmsvga_invalidate_display, + vmsvga_screen_dump, + vmsvga_text_update, s); #ifdef EMBED_STDVGA vga_common_init((VGAState *) s, ds, diff --git a/qemu-common.h b/qemu-common.h index 0512d4963..b991c2bac 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -119,6 +119,7 @@ typedef struct AudioState AudioState; typedef struct BlockDriverState BlockDriverState; typedef struct DisplayState DisplayState; typedef struct TextConsole TextConsole; +typedef TextConsole QEMUConsole; typedef struct CharDriverState CharDriverState; typedef struct VLANState VLANState; typedef struct QEMUFile QEMUFile; diff --git a/vl.c b/vl.c index d6da115eb..84eab32c5 100644 --- a/vl.c +++ b/vl.c @@ -7935,7 +7935,7 @@ int main(int argc, char **argv) kernel_cmdline = ""; cyls = heads = secs = 0; translation = BIOS_ATA_TRANSLATION_AUTO; - monitor_device = "vc:800x600"; + monitor_device = "vc"; serial_devices[0] = "vc:80Cx24C"; for(i = 1; i < MAX_SERIAL_PORTS; i++) -- cgit v1.2.3 From 356265ae4a865dc384f4985f2498374dac2b3dc8 Mon Sep 17 00:00:00 2001 From: ths Date: Tue, 1 Jul 2008 16:37:52 +0000 Subject: Static'ify some functions, and use standard inline in translate.c. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4813 c046a42c-6fe2-441c-8c8c-71466251a162 --- target-mips/translate.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index 76a963de0..803a48f32 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -757,7 +757,7 @@ FOP_CONDS(abs, ps) /* Tests */ #define OP_COND(name, cond) \ -void glue(gen_op_, name) (TCGv t0, TCGv t1) \ +static inline void glue(gen_op_, name) (TCGv t0, TCGv t1) \ { \ int l1 = gen_new_label(); \ int l2 = gen_new_label(); \ @@ -778,7 +778,7 @@ OP_COND(ltu, TCG_COND_LTU); #undef OP_COND #define OP_CONDI(name, cond) \ -void glue(gen_op_, name) (TCGv t, target_ulong val) \ +static inline void glue(gen_op_, name) (TCGv t, target_ulong val) \ { \ int l1 = gen_new_label(); \ int l2 = gen_new_label(); \ @@ -795,7 +795,7 @@ OP_CONDI(ltiu, TCG_COND_LTU); #undef OP_CONDI #define OP_CONDZ(name, cond) \ -void glue(gen_op_, name) (TCGv t) \ +static inline void glue(gen_op_, name) (TCGv t) \ { \ int l1 = gen_new_label(); \ int l2 = gen_new_label(); \ @@ -822,7 +822,7 @@ static inline void gen_save_pc(target_ulong pc) tcg_temp_free(r_tmp); } -static always_inline void save_cpu_state (DisasContext *ctx, int do_save_pc) +static inline void save_cpu_state (DisasContext *ctx, int do_save_pc) { #if defined MIPS_DEBUG_DISAS if (loglevel & CPU_LOG_TB_IN_ASM) { @@ -853,7 +853,7 @@ static always_inline void save_cpu_state (DisasContext *ctx, int do_save_pc) } } -static always_inline void restore_cpu_state (CPUState *env, DisasContext *ctx) +static inline void restore_cpu_state (CPUState *env, DisasContext *ctx) { ctx->saved_hflags = ctx->hflags; switch (ctx->hflags & MIPS_HFLAG_BMASK) { @@ -867,7 +867,7 @@ static always_inline void restore_cpu_state (CPUState *env, DisasContext *ctx) } } -static always_inline void +static inline void generate_exception_err (DisasContext *ctx, int excp, int err) { save_cpu_state(ctx, 1); @@ -876,7 +876,7 @@ generate_exception_err (DisasContext *ctx, int excp, int err) tcg_gen_exit_tb(0); } -static always_inline void +static inline void generate_exception (DisasContext *ctx, int excp) { save_cpu_state(ctx, 1); @@ -911,13 +911,13 @@ static inline void gen_op_addr_add (TCGv t0, TCGv t1) #endif } -static always_inline void check_cp0_enabled(DisasContext *ctx) +static inline void check_cp0_enabled(DisasContext *ctx) { if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) generate_exception_err(ctx, EXCP_CpU, 1); } -static always_inline void check_cp1_enabled(DisasContext *ctx) +static inline void check_cp1_enabled(DisasContext *ctx) { if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU))) generate_exception_err(ctx, EXCP_CpU, 1); @@ -927,7 +927,7 @@ static always_inline void check_cp1_enabled(DisasContext *ctx) This is associated with the nabla symbol in the MIPS32 and MIPS64 opcode tables. */ -static always_inline void check_cop1x(DisasContext *ctx) +static inline void check_cop1x(DisasContext *ctx) { if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) generate_exception(ctx, EXCP_RI); @@ -936,7 +936,7 @@ static always_inline void check_cop1x(DisasContext *ctx) /* Verify that the processor is running with 64-bit floating-point operations enabled. */ -static always_inline void check_cp1_64bitmode(DisasContext *ctx) +static inline void check_cp1_64bitmode(DisasContext *ctx) { if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X))) generate_exception(ctx, EXCP_RI); @@ -953,7 +953,7 @@ static always_inline void check_cp1_64bitmode(DisasContext *ctx) * Multiple 64 bit wide registers can be checked by calling * gen_op_cp1_registers(freg1 | freg2 | ... | fregN); */ -void check_cp1_registers(DisasContext *ctx, int regs) +static inline void check_cp1_registers(DisasContext *ctx, int regs) { if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) generate_exception(ctx, EXCP_RI); @@ -961,7 +961,7 @@ void check_cp1_registers(DisasContext *ctx, int regs) /* This code generates a "reserved instruction" exception if the CPU does not support the instruction set corresponding to flags. */ -static always_inline void check_insn(CPUState *env, DisasContext *ctx, int flags) +static inline void check_insn(CPUState *env, DisasContext *ctx, int flags) { if (unlikely(!(env->insn_flags & flags))) generate_exception(ctx, EXCP_RI); @@ -969,7 +969,7 @@ static always_inline void check_insn(CPUState *env, DisasContext *ctx, int flags /* This code generates a "reserved instruction" exception if 64-bit instructions are not enabled. */ -static always_inline void check_mips_64(DisasContext *ctx) +static inline void check_mips_64(DisasContext *ctx) { if (unlikely(!(ctx->hflags & MIPS_HFLAG_64))) generate_exception(ctx, EXCP_RI); @@ -977,7 +977,7 @@ static always_inline void check_mips_64(DisasContext *ctx) /* load/store instructions. */ #define OP_LD(insn,fname) \ -void inline op_ldst_##insn(TCGv t0, DisasContext *ctx) \ +static inline void op_ldst_##insn(TCGv t0, DisasContext *ctx) \ { \ tcg_gen_qemu_##fname(t0, t0, ctx->mem_idx); \ } @@ -993,7 +993,7 @@ OP_LD(ld,ld64); #undef OP_LD #define OP_ST(insn,fname) \ -void inline op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \ +static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \ { \ tcg_gen_qemu_##fname(t1, t0, ctx->mem_idx); \ } @@ -1006,7 +1006,7 @@ OP_ST(sd,st64); #undef OP_ST #define OP_LD_ATOMIC(insn,fname) \ -void inline op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \ +static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \ { \ tcg_gen_mov_tl(t1, t0); \ tcg_gen_qemu_##fname(t0, t0, ctx->mem_idx); \ @@ -1019,7 +1019,7 @@ OP_LD_ATOMIC(lld,ld64); #undef OP_LD_ATOMIC #define OP_ST_ATOMIC(insn,fname,almask) \ -void inline op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \ +static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \ { \ TCGv r_tmp = tcg_temp_local_new(TCG_TYPE_TL); \ int l1 = gen_new_label(); \ @@ -1213,7 +1213,7 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt, /* Load and store */ static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft, - int base, int16_t offset) + int base, int16_t offset) { const char *opn = "flt_ldst"; TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL); @@ -2459,7 +2459,7 @@ static void gen_trap (DisasContext *ctx, uint32_t opc, tcg_temp_free(t1); } -static always_inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) +static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) { TranslationBlock *tb; tb = ctx->tb; @@ -2720,7 +2720,7 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, /* special3 bitfield operations */ static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt, - int rs, int lsb, int msb) + int rs, int lsb, int msb) { TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL); TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL); @@ -7808,7 +7808,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx) } } -static always_inline int +static inline int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, int search_pc) { -- cgit v1.2.3 From a982b5310de5d64b67ecced32ba1fd4051c437b8 Mon Sep 17 00:00:00 2001 From: ths Date: Tue, 1 Jul 2008 16:40:04 +0000 Subject: Add missing return in arm-semi, by Laurent Desnogues. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4814 c046a42c-6fe2-441c-8c8c-71466251a162 --- arm-semi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arm-semi.c b/arm-semi.c index 1cf220388..cd77d1da0 100644 --- a/arm-semi.c +++ b/arm-semi.c @@ -362,6 +362,7 @@ uint32_t do_arm_semihosting(CPUState *env) return (uint32_t)-1; ret = set_swi_errno(ts, system(s)); unlock_user(s, ARG(0), 0); + return ret; } case SYS_ERRNO: #ifdef CONFIG_USER_ONLY -- cgit v1.2.3 From ad1a897e52d6928c3d2b98dec69d765bfc2d1121 Mon Sep 17 00:00:00 2001 From: ths Date: Tue, 1 Jul 2008 16:44:58 +0000 Subject: block-vvfat.c - fix is_free predicate, by Tristan Gingold. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4815 c046a42c-6fe2-441c-8c8c-71466251a162 --- block-vvfat.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/block-vvfat.c b/block-vvfat.c index a93fde970..f5ae4f164 100644 --- a/block-vvfat.c +++ b/block-vvfat.c @@ -454,8 +454,7 @@ static inline direntry_t* create_long_filename(BDRVVVFATState* s,const char* fil static char is_free(const direntry_t* direntry) { - /* return direntry->name[0]==0 ; */ - return direntry->attributes == 0 || direntry->name[0]==0xe5; + return direntry->name[0]==0xe5 || direntry->name[0]==0x00; } static char is_volume_label(const direntry_t* direntry) -- cgit v1.2.3 From a5cdf952204931960bbb269494469843be789b52 Mon Sep 17 00:00:00 2001 From: blueswir1 Date: Tue, 1 Jul 2008 19:28:23 +0000 Subject: Fix DMA length bug seen with NetBSD (Cliff Wright) git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4816 c046a42c-6fe2-441c-8c8c-71466251a162 --- hw/iommu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/iommu.c b/hw/iommu.c index 0879df95f..fe6911e5e 100644 --- a/hw/iommu.c +++ b/hw/iommu.c @@ -301,9 +301,9 @@ void sparc_iommu_memory_rw(void *opaque, target_phys_addr_t addr, iommu_bad_addr(opaque, page, is_write); return; } - cpu_physical_memory_write(phys_addr, buf, len); + cpu_physical_memory_write(phys_addr, buf, l); } else { - cpu_physical_memory_read(phys_addr, buf, len); + cpu_physical_memory_read(phys_addr, buf, l); } len -= l; buf += l; -- cgit v1.2.3 From 9656f324d25895ec16ebc5eaf624e28a96c1f1be Mon Sep 17 00:00:00 2001 From: pbrook Date: Tue, 1 Jul 2008 20:01:19 +0000 Subject: Move interrupt_request and user_mode_only to common cpu state. Save and restore env->interrupt_request and env->halted. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4817 c046a42c-6fe2-441c-8c8c-71466251a162 --- cpu-defs.h | 5 ++++- exec.c | 29 +++++++++++++++++++++++++++++ target-alpha/cpu.h | 2 -- target-arm/cpu.h | 4 ---- target-cris/cpu.h | 3 --- target-i386/cpu.h | 4 +--- target-i386/machine.c | 7 ++++--- target-m68k/cpu.h | 4 ---- target-mips/cpu.h | 2 -- target-ppc/cpu.h | 2 -- target-sh4/cpu.h | 2 -- target-sparc/cpu.h | 2 -- 12 files changed, 38 insertions(+), 28 deletions(-) diff --git a/cpu-defs.h b/cpu-defs.h index 9621b947d..cc69a3c0c 100644 --- a/cpu-defs.h +++ b/cpu-defs.h @@ -153,7 +153,8 @@ typedef struct icount_decr_u16 { accessed */ \ target_ulong mem_io_vaddr; /* target virtual addr at which the \ memory was accessed */ \ - int halted; /* TRUE if the CPU is in suspend state */ \ + uint32_t halted; /* Nonzero if the CPU is in suspend state */ \ + uint32_t interrupt_request; \ /* The meaning of the MMU modes is defined in the target code. */ \ CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE]; \ target_phys_addr_t iotlb[NB_MMU_MODES][CPU_TLB_SIZE]; \ @@ -188,6 +189,8 @@ typedef struct icount_decr_u16 { jmp_buf jmp_env; \ int exception_index; \ \ + int user_mode_only; \ + \ void *next_cpu; /* next CPU sharing TB cache */ \ int cpu_index; /* CPU index (informative) */ \ int running; /* Nonzero if cpu is currently running(usermode). */ \ diff --git a/exec.c b/exec.c index 64c87b31e..f02abe068 100644 --- a/exec.c +++ b/exec.c @@ -443,6 +443,33 @@ void cpu_exec_init_all(unsigned long tb_size) #endif } +#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY) + +#define CPU_COMMON_SAVE_VERSION 1 + +static void cpu_common_save(QEMUFile *f, void *opaque) +{ + CPUState *env = opaque; + + qemu_put_be32s(f, &env->halted); + qemu_put_be32s(f, &env->interrupt_request); +} + +static int cpu_common_load(QEMUFile *f, void *opaque, int version_id) +{ + CPUState *env = opaque; + + if (version_id != CPU_COMMON_SAVE_VERSION) + return -EINVAL; + + qemu_get_be32s(f, &env->halted); + qemu_put_be32s(f, &env->interrupt_request); + tlb_flush(env, 1); + + return 0; +} +#endif + void cpu_exec_init(CPUState *env) { CPUState **penv; @@ -459,6 +486,8 @@ void cpu_exec_init(CPUState *env) env->nb_watchpoints = 0; *penv = env; #if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY) + register_savevm("cpu_common", cpu_index, CPU_COMMON_SAVE_VERSION, + cpu_common_save, cpu_common_load, env); register_savevm("cpu", cpu_index, CPU_SAVE_VERSION, cpu_save, cpu_load, env); #endif diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h index bdd0ae612..3d39888ae 100644 --- a/target-alpha/cpu.h +++ b/target-alpha/cpu.h @@ -282,11 +282,9 @@ struct CPUAlphaState { /* Those resources are used only in Qemu core */ CPU_COMMON - int user_mode_only; /* user mode only simulation */ uint32_t hflags; int error_code; - int interrupt_request; uint32_t features; uint32_t amask; diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 1d7333264..ff765f783 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -156,10 +156,6 @@ typedef struct CPUARMState { int (*get_irq_vector)(struct CPUARMState *); void *irq_opaque; - /* exception/interrupt handling */ - int interrupt_request; - int user_mode_only; - /* VFP coprocessor state. */ struct { float64 regs[32]; diff --git a/target-cris/cpu.h b/target-cris/cpu.h index e45456858..39b106172 100644 --- a/target-cris/cpu.h +++ b/target-cris/cpu.h @@ -125,7 +125,6 @@ typedef struct CPUCRISState { /* X flag at the time of cc snapshot. */ int cc_x; - int interrupt_request; int interrupt_vector; int fault_vector; int trap_vector; @@ -156,8 +155,6 @@ typedef struct CPUCRISState { uint32_t lo; } tlbsets[2][4][16]; - int user_mode_only; - CPU_COMMON } CPUCRISState; diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 098d5e48e..22169a90c 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -567,8 +567,6 @@ typedef struct CPUX86State { target_ulong exception_next_eip; target_ulong dr[8]; /* debug registers */ uint32_t smbase; - int interrupt_request; - int user_mode_only; /* user mode only simulation */ int old_exception; /* exception in flight */ CPU_COMMON @@ -726,7 +724,7 @@ static inline int cpu_get_time_fast(void) #define cpu_signal_handler cpu_x86_signal_handler #define cpu_list x86_cpu_list -#define CPU_SAVE_VERSION 5 +#define CPU_SAVE_VERSION 6 /* MMU modes definitions */ #define MMU_MODE0_SUFFIX _kernel diff --git a/target-i386/machine.c b/target-i386/machine.c index 938c49591..91dbd5527 100644 --- a/target-i386/machine.c +++ b/target-i386/machine.c @@ -123,7 +123,6 @@ void cpu_save(QEMUFile *f, void *opaque) qemu_put_be64s(f, &env->pat); qemu_put_be32s(f, &env->hflags2); - qemu_put_be32s(f, (uint32_t *)&env->halted); qemu_put_be64s(f, &env->vm_hsave); qemu_put_be64s(f, &env->vm_vmcb); @@ -169,7 +168,8 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) uint16_t fpus, fpuc, fptag, fpregs_format; int32_t a20_mask; - if (version_id != 3 && version_id != 4 && version_id != 5) + if (version_id != 3 && version_id != 4 && version_id != 5 + && version_id != 6) return -EINVAL; for(i = 0; i < CPU_NB_REGS; i++) qemu_get_betls(f, &env->regs[i]); @@ -279,7 +279,8 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) if (version_id >= 5) { qemu_get_be64s(f, &env->pat); qemu_get_be32s(f, &env->hflags2); - qemu_get_be32s(f, (uint32_t *)&env->halted); + if (version_id < 6) + qemu_get_be32s(f, &env->halted); qemu_get_be64s(f, &env->vm_hsave); qemu_get_be64s(f, &env->vm_vmcb); diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h index aaf9e4263..a6687b11a 100644 --- a/target-m68k/cpu.h +++ b/target-m68k/cpu.h @@ -103,10 +103,6 @@ typedef struct CPUM68KState { /* ??? remove this. */ uint32_t t1; - /* exception/interrupt handling */ - int interrupt_request; - int user_mode_only; - int pending_vector; int pending_level; diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 93c1610f1..e747bc888 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -411,9 +411,7 @@ struct CPUMIPSState { /* We waste some space so we can handle shadow registers like TCs. */ TCState tcs[MIPS_SHADOW_SET_MAX]; /* Qemu */ - int interrupt_request; int error_code; - int user_mode_only; /* user mode only simulation */ uint32_t hflags; /* CPU State */ /* TMASK defines different execution modes */ #define MIPS_HFLAG_TMASK 0x01FF diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index 4e1f2f14f..834c08ddd 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -647,7 +647,6 @@ struct CPUPPCState { uint32_t flags; int error_code; - int interrupt_request; uint32_t pending_interrupts; #if !defined(CONFIG_USER_ONLY) /* This is the IRQ controller, which is implementation dependant @@ -671,7 +670,6 @@ struct CPUPPCState { opc_handler_t *opcodes[0x40]; /* Those resources are used only in Qemu core */ - int user_mode_only; /* user mode only simulation */ target_ulong hflags; /* hflags is a MSR & HFLAGS_MASK */ target_ulong hflags_nmsr; /* specific hflags, not comming from MSR */ int mmu_idx; /* precomputed MMU index to speed up mem accesses */ diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h index 014ecd342..9dbadf4d3 100644 --- a/target-sh4/cpu.h +++ b/target-sh4/cpu.h @@ -114,8 +114,6 @@ typedef struct CPUSH4State { uint32_t expevt; /* exception event register */ uint32_t intevt; /* interrupt event register */ - int user_mode_only; - int interrupt_request; CPU_COMMON tlb_t utlb[UTLB_SIZE]; /* unified translation table */ tlb_t itlb[ITLB_SIZE]; /* instruction translation table */ void *intc_handle; diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index 34a20cd2a..937ce6f96 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -215,9 +215,7 @@ typedef struct CPUSPARCState { uint32_t pil_in; /* incoming interrupt level bitmap */ int psref; /* enable fpu */ target_ulong version; - int user_mode_only; int interrupt_index; - int interrupt_request; uint32_t mmu_bm; uint32_t mmu_ctpr_mask; uint32_t mmu_cxr_mask; -- cgit v1.2.3 From 18be51872917e70e00cb21e018b6bff33162c4f7 Mon Sep 17 00:00:00 2001 From: pbrook Date: Tue, 1 Jul 2008 21:31:54 +0000 Subject: Remove duplicate device index calculations. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4818 c046a42c-6fe2-441c-8c8c-71466251a162 --- hw/ads7846.c | 5 +---- hw/ide.c | 4 +--- hw/lm832x.c | 5 +---- hw/max111x.c | 5 +---- hw/max7310.c | 5 +---- hw/nand.c | 4 +--- hw/tmp105.c | 5 +---- hw/tsc2005.c | 5 +---- hw/tsc210x.c | 7 ++----- hw/twl92230.c | 5 +---- hw/wm8750.c | 4 +--- vl.c | 11 +++++++++-- 12 files changed, 21 insertions(+), 44 deletions(-) diff --git a/hw/ads7846.c b/hw/ads7846.c index 578bb5493..b39c00f51 100644 --- a/hw/ads7846.c +++ b/hw/ads7846.c @@ -140,8 +140,6 @@ static int ads7846_load(QEMUFile *f, void *opaque, int version_id) return 0; } -static int ads7846_iid = 0; - struct ads7846_state_s *ads7846_init(qemu_irq penirq) { struct ads7846_state_s *s; @@ -162,8 +160,7 @@ struct ads7846_state_s *ads7846_init(qemu_irq penirq) ads7846_int_update(s); - register_savevm("ads7846", ads7846_iid ++, 0, - ads7846_save, ads7846_load, s); + register_savevm("ads7846", -1, 0, ads7846_save, ads7846_load, s); return s; } diff --git a/hw/ide.c b/hw/ide.c index dc4198292..91244be91 100644 --- a/hw/ide.c +++ b/hw/ide.c @@ -3596,8 +3596,6 @@ static int md_load(QEMUFile *f, void *opaque, int version_id) return 0; } -static int md_iid = 0; - static const uint8_t dscm1xxxx_cis[0x14a] = { [0x000] = CISTPL_DEVICE, /* 5V Device Information */ [0x002] = 0x03, /* Tuple length = 4 bytes */ @@ -3824,7 +3822,7 @@ struct pcmcia_card_s *dscm1xxxx_init(BlockDriverState *bdrv) md->ide->mdata_size = METADATA_SIZE; md->ide->mdata_storage = (uint8_t *) qemu_mallocz(METADATA_SIZE); - register_savevm("microdrive", md_iid ++, 0, md_save, md_load, md); + register_savevm("microdrive", -1, 0, md_save, md_load, md); return &md->card; } diff --git a/hw/lm832x.c b/hw/lm832x.c index efb80f7e7..1e4564e3b 100644 --- a/hw/lm832x.c +++ b/hw/lm832x.c @@ -490,8 +490,6 @@ static int lm_kbd_load(QEMUFile *f, void *opaque, int version_id) return 0; } -static int lm_kbd_iid = 0; - struct i2c_slave *lm8323_init(i2c_bus *bus, qemu_irq nirq) { struct lm_kbd_s *s; @@ -510,8 +508,7 @@ struct i2c_slave *lm8323_init(i2c_bus *bus, qemu_irq nirq) lm_kbd_reset(s); qemu_register_reset((void *) lm_kbd_reset, s); - register_savevm("LM8323", lm_kbd_iid ++, 0, - lm_kbd_save, lm_kbd_load, s); + register_savevm("LM8323", -1, 0, lm_kbd_save, lm_kbd_load, s); return &s->i2c; } diff --git a/hw/max111x.c b/hw/max111x.c index cc3ded1df..15392a21f 100644 --- a/hw/max111x.c +++ b/hw/max111x.c @@ -121,8 +121,6 @@ static int max111x_load(QEMUFile *f, void *opaque, int version_id) return 0; } -static int max111x_iid = 0; - static struct max111x_s *max111x_init(qemu_irq cb) { struct max111x_s *s; @@ -143,8 +141,7 @@ static struct max111x_s *max111x_init(qemu_irq cb) s->input[7] = 0x80; s->com = 0; - register_savevm("max111x", max111x_iid ++, 0, - max111x_save, max111x_load, s); + register_savevm("max111x", -1, 0, max111x_save, max111x_load, s); return s; } diff --git a/hw/max7310.c b/hw/max7310.c index 397950a08..2816611a8 100644 --- a/hw/max7310.c +++ b/hw/max7310.c @@ -177,8 +177,6 @@ static int max7310_load(QEMUFile *f, void *opaque, int version_id) return 0; } -static int max7310_iid = 0; - static void max7310_gpio_set(void *opaque, int line, int level) { struct max7310_s *s = (struct max7310_s *) opaque; @@ -205,8 +203,7 @@ struct i2c_slave *max7310_init(i2c_bus *bus) max7310_reset(&s->i2c); - register_savevm("max7310", max7310_iid ++, 0, - max7310_save, max7310_load, s); + register_savevm("max7310", -1, 0, max7310_save, max7310_load, s); return &s->i2c; } diff --git a/hw/nand.c b/hw/nand.c index aa0c200f2..294a83f85 100644 --- a/hw/nand.c +++ b/hw/nand.c @@ -319,8 +319,6 @@ static int nand_load(QEMUFile *f, void *opaque, int version_id) return 0; } -static int nand_iid = 0; - /* * Chip inputs are CLE, ALE, CE, WP, GND and eight I/O pins. Chip * outputs are R/B and eight I/O pins. @@ -495,7 +493,7 @@ struct nand_flash_s *nand_init(int manf_id, int chip_id) s->storage = (uint8_t *) memset(qemu_malloc(s->pages * pagesize), 0xff, s->pages * pagesize); - register_savevm("nand", nand_iid ++, 0, nand_save, nand_load, s); + register_savevm("nand", -1, 0, nand_save, nand_load, s); return s; } diff --git a/hw/tmp105.c b/hw/tmp105.c index da26e4671..a4a0103d7 100644 --- a/hw/tmp105.c +++ b/hw/tmp105.c @@ -228,8 +228,6 @@ void tmp105_reset(i2c_slave *i2c) tmp105_interrupt_update(s); } -static int tmp105_iid = 0; - struct i2c_slave *tmp105_init(i2c_bus *bus, qemu_irq alarm) { struct tmp105_s *s = (struct tmp105_s *) @@ -242,8 +240,7 @@ struct i2c_slave *tmp105_init(i2c_bus *bus, qemu_irq alarm) tmp105_reset(&s->i2c); - register_savevm("TMP105", tmp105_iid ++, 0, - tmp105_save, tmp105_load, s); + register_savevm("TMP105", -1, 0, tmp105_save, tmp105_load, s); return &s->i2c; } diff --git a/hw/tsc2005.c b/hw/tsc2005.c index 7708a36d5..f7a35b2d9 100644 --- a/hw/tsc2005.c +++ b/hw/tsc2005.c @@ -520,8 +520,6 @@ static int tsc2005_load(QEMUFile *f, void *opaque, int version_id) return 0; } -static int tsc2005_iid = 0; - void *tsc2005_init(qemu_irq pintdav) { struct tsc2005_state_s *s; @@ -551,8 +549,7 @@ void *tsc2005_init(qemu_irq pintdav) "QEMU TSC2005-driven Touchscreen"); qemu_register_reset((void *) tsc2005_reset, s); - register_savevm("tsc2005", tsc2005_iid ++, 0, - tsc2005_save, tsc2005_load, s); + register_savevm("tsc2005", -1, 0, tsc2005_save, tsc2005_load, s); return s; } diff --git a/hw/tsc210x.c b/hw/tsc210x.c index f15aebaf1..97c21ef02 100644 --- a/hw/tsc210x.c +++ b/hw/tsc210x.c @@ -1107,8 +1107,6 @@ static int tsc210x_load(QEMUFile *f, void *opaque, int version_id) return 0; } -static int tsc2102_iid = 0; - struct uwire_slave_s *tsc2102_init(qemu_irq pint, AudioState *audio) { struct tsc210x_state_s *s; @@ -1154,7 +1152,7 @@ struct uwire_slave_s *tsc2102_init(qemu_irq pint, AudioState *audio) AUD_register_card(s->audio, s->name, &s->card); qemu_register_reset((void *) tsc210x_reset, s); - register_savevm(s->name, tsc2102_iid ++, 0, + register_savevm(s->name, -1, 0, tsc210x_save, tsc210x_load, s); return &s->chip; @@ -1208,8 +1206,7 @@ struct uwire_slave_s *tsc2301_init(qemu_irq penirq, qemu_irq kbirq, AUD_register_card(s->audio, s->name, &s->card); qemu_register_reset((void *) tsc210x_reset, s); - register_savevm(s->name, tsc2102_iid ++, 0, - tsc210x_save, tsc210x_load, s); + register_savevm(s->name, -1, 0, tsc210x_save, tsc210x_load, s); return &s->chip; } diff --git a/hw/twl92230.c b/hw/twl92230.c index 8d0ce5da6..8fad96902 100644 --- a/hw/twl92230.c +++ b/hw/twl92230.c @@ -876,8 +876,6 @@ static int menelaus_load(QEMUFile *f, void *opaque, int version_id) return 0; } -static int menelaus_iid = 0; - i2c_slave *twl92230_init(i2c_bus *bus, qemu_irq irq) { struct menelaus_s *s = (struct menelaus_s *) @@ -894,8 +892,7 @@ i2c_slave *twl92230_init(i2c_bus *bus, qemu_irq irq) menelaus_reset(&s->i2c); - register_savevm("menelaus", menelaus_iid ++, - 0, menelaus_save, menelaus_load, s); + register_savevm("menelaus", -1, 0, menelaus_save, menelaus_load, s); return &s->i2c; } diff --git a/hw/wm8750.c b/hw/wm8750.c index ee6790bb9..b175167ad 100644 --- a/hw/wm8750.c +++ b/hw/wm8750.c @@ -646,8 +646,6 @@ static int wm8750_load(QEMUFile *f, void *opaque, int version_id) return 0; } -static int wm8750_iid = 0; - i2c_slave *wm8750_init(i2c_bus *bus, AudioState *audio) { struct wm8750_s *s = (struct wm8750_s *) @@ -659,7 +657,7 @@ i2c_slave *wm8750_init(i2c_bus *bus, AudioState *audio) AUD_register_card(audio, CODEC, &s->card); wm8750_reset(&s->i2c); - register_savevm(CODEC, wm8750_iid ++, 0, wm8750_save, wm8750_load, s); + register_savevm(CODEC, -1, 0, wm8750_save, wm8750_load, s); return &s->i2c; } diff --git a/vl.c b/vl.c index 84eab32c5..cde008e9a 100644 --- a/vl.c +++ b/vl.c @@ -6060,6 +6060,8 @@ typedef struct SaveStateEntry { static SaveStateEntry *first_se; +/* TODO: Individual devices generally have very little idea about the rest + of the system, so instance_id should be removed/replaced. */ int register_savevm(const char *idstr, int instance_id, int version_id, @@ -6073,7 +6075,7 @@ int register_savevm(const char *idstr, if (!se) return -1; pstrcpy(se->idstr, sizeof(se->idstr), idstr); - se->instance_id = instance_id; + se->instance_id = (instance_id == -1) ? 0 : instance_id; se->version_id = version_id; se->save_state = save_state; se->load_state = load_state; @@ -6082,8 +6084,13 @@ int register_savevm(const char *idstr, /* add at the end of list */ pse = &first_se; - while (*pse != NULL) + while (*pse != NULL) { + if (instance_id == -1 + && strcmp(se->idstr, (*pse)->idstr) == 0 + && se->instance_id <= (*pse)->instance_id) + se->instance_id = (*pse)->instance_id + 1; pse = &(*pse)->next; + } *pse = se; return 0; } -- cgit v1.2.3 From 75f482aeeda361929262be918faf90fb75ab8e33 Mon Sep 17 00:00:00 2001 From: pbrook Date: Tue, 1 Jul 2008 21:53:33 +0000 Subject: Fix typo. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4819 c046a42c-6fe2-441c-8c8c-71466251a162 --- exec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exec.c b/exec.c index f02abe068..4f7a027d6 100644 --- a/exec.c +++ b/exec.c @@ -463,7 +463,7 @@ static int cpu_common_load(QEMUFile *f, void *opaque, int version_id) return -EINVAL; qemu_get_be32s(f, &env->halted); - qemu_put_be32s(f, &env->interrupt_request); + qemu_get_be32s(f, &env->interrupt_request); tlb_flush(env, 1); return 0; -- cgit v1.2.3 From c701b35b42d50537122486e47006d1c6ce952240 Mon Sep 17 00:00:00 2001 From: pbrook Date: Tue, 1 Jul 2008 23:16:53 +0000 Subject: Fix i2c save/restore. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4820 c046a42c-6fe2-441c-8c8c-71466251a162 --- hw/i2c.c | 49 +++++++++++++++++++++++++++---------------------- hw/i2c.h | 3 +-- hw/pxa2xx.c | 8 +++++--- 3 files changed, 33 insertions(+), 27 deletions(-) diff --git a/hw/i2c.c b/hw/i2c.c index e590801af..5d283fb4c 100644 --- a/hw/i2c.c +++ b/hw/i2c.c @@ -14,14 +14,38 @@ struct i2c_bus { i2c_slave *current_dev; i2c_slave *dev; + int saved_address; }; +static void i2c_bus_save(QEMUFile *f, void *opaque) +{ + i2c_bus *bus = (i2c_bus *)opaque; + + qemu_put_byte(f, bus->current_dev ? bus->current_dev->address : -1); +} + +static int i2c_bus_load(QEMUFile *f, void *opaque, int version_id) +{ + i2c_bus *bus = (i2c_bus *)opaque; + + if (version_id != 1) + return -EINVAL; + + /* The bus is loaded before attached devices, so load and save the + current device id. Devices will check themselves as loaded. */ + bus->saved_address = qemu_get_be32(f); + bus->current_dev = NULL; + + return 0; +} + /* Create a new I2C bus. */ i2c_bus *i2c_init_bus(void) { i2c_bus *bus; bus = (i2c_bus *)qemu_mallocz(sizeof(i2c_bus)); + register_savevm("i2c_bus", -1, 1, i2c_bus_save, i2c_bus_load, bus); return bus; } @@ -37,6 +61,7 @@ i2c_slave *i2c_slave_init(i2c_bus *bus, int address, int size) dev->address = address; dev->next = bus->dev; bus->dev = dev; + dev->bus = bus; return dev; } @@ -115,28 +140,6 @@ void i2c_nack(i2c_bus *bus) dev->event(dev, I2C_NACK); } -void i2c_bus_save(QEMUFile *f, i2c_bus *bus) -{ - qemu_put_byte(f, bus->current_dev ? bus->current_dev->address : 0x00); -} - -void i2c_bus_load(QEMUFile *f, i2c_bus *bus) -{ - i2c_slave *dev; - uint8_t address = qemu_get_byte(f); - - if (address) { - for (dev = bus->dev; dev; dev = dev->next) - if (dev->address == address) { - bus->current_dev = dev; - return; - } - - fprintf(stderr, "%s: I2C slave with address %02x disappeared\n", - __FUNCTION__, address); - } -} - void i2c_slave_save(QEMUFile *f, i2c_slave *dev) { qemu_put_byte(f, dev->address); @@ -145,4 +148,6 @@ void i2c_slave_save(QEMUFile *f, i2c_slave *dev) void i2c_slave_load(QEMUFile *f, i2c_slave *dev) { dev->address = qemu_get_byte(f); + if (dev->bus->saved_address == dev->address) + dev->bus->current_dev = dev; } diff --git a/hw/i2c.h b/hw/i2c.h index f297237b7..d3e4352b1 100644 --- a/hw/i2c.h +++ b/hw/i2c.h @@ -30,6 +30,7 @@ struct i2c_slave /* Remaining fields for internal use by the I2C code. */ int address; void *next; + i2c_bus *bus; }; i2c_bus *i2c_init_bus(void); @@ -41,8 +42,6 @@ void i2c_end_transfer(i2c_bus *bus); void i2c_nack(i2c_bus *bus); int i2c_send(i2c_bus *bus, uint8_t data); int i2c_recv(i2c_bus *bus); -void i2c_bus_save(QEMUFile *f, i2c_bus *bus); -void i2c_bus_load(QEMUFile *f, i2c_bus *bus); void i2c_slave_save(QEMUFile *f, i2c_slave *dev); void i2c_slave_load(QEMUFile *f, i2c_slave *dev); diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c index cb6670c35..fd663d9da 100644 --- a/hw/pxa2xx.c +++ b/hw/pxa2xx.c @@ -1466,7 +1466,6 @@ static void pxa2xx_i2c_save(QEMUFile *f, void *opaque) qemu_put_8s(f, &s->ibmr); qemu_put_8s(f, &s->data); - i2c_bus_save(f, s->bus); i2c_slave_save(f, &s->slave); } @@ -1474,12 +1473,14 @@ static int pxa2xx_i2c_load(QEMUFile *f, void *opaque, int version_id) { struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *) opaque; + if (version_id != 1) + return -EINVAL; + qemu_get_be16s(f, &s->control); qemu_get_be16s(f, &s->status); qemu_get_8s(f, &s->ibmr); qemu_get_8s(f, &s->data); - i2c_bus_load(f, s->bus); i2c_slave_load(f, &s->slave); return 0; } @@ -1488,6 +1489,7 @@ struct pxa2xx_i2c_s *pxa2xx_i2c_init(target_phys_addr_t base, qemu_irq irq, uint32_t page_size) { int iomemtype; + /* FIXME: Should the slave device really be on a separate bus? */ struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *) i2c_slave_init(i2c_init_bus(), 0, sizeof(struct pxa2xx_i2c_s)); @@ -1502,7 +1504,7 @@ struct pxa2xx_i2c_s *pxa2xx_i2c_init(target_phys_addr_t base, pxa2xx_i2c_writefn, s); cpu_register_physical_memory(s->base & ~page_size, page_size, iomemtype); - register_savevm("pxa2xx_i2c", base, 0, + register_savevm("pxa2xx_i2c", base, 1, pxa2xx_i2c_save, pxa2xx_i2c_load, s); return s; -- cgit v1.2.3 From 5e65a31037e03c9ccbc4df156ddb11b36108a0a6 Mon Sep 17 00:00:00 2001 From: blueswir1 Date: Wed, 2 Jul 2008 15:16:18 +0000 Subject: Add rigid and flexible disk geometry page support git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4821 c046a42c-6fe2-441c-8c8c-71466251a162 --- hw/scsi-disk.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index dcf03291d..16b32153b 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -532,7 +532,76 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag, outbuf[2] = 0x80; /* Readonly. */ } p += 4; - if ((page == 8 || page == 0x3f)) { + if (page == 4) { + int cylinders, heads, secs; + + /* Rigid disk device geometry page. */ + p[0] = 4; + p[1] = 0x16; + /* if a geometry hint is available, use it */ + bdrv_get_geometry_hint(s->bdrv, &cylinders, &heads, &secs); + p[2] = (cylinders >> 16) & 0xff; + p[3] = (cylinders >> 8) & 0xff; + p[4] = cylinders & 0xff; + p[5] = heads & 0xff; + /* Write precomp start cylinder, disabled */ + p[6] = (cylinders >> 16) & 0xff; + p[7] = (cylinders >> 8) & 0xff; + p[8] = cylinders & 0xff; + /* Reduced current start cylinder, disabled */ + p[9] = (cylinders >> 16) & 0xff; + p[10] = (cylinders >> 8) & 0xff; + p[11] = cylinders & 0xff; + /* Device step rate [ns], 200ns */ + p[12] = 0; + p[13] = 200; + /* Landing zone cylinder */ + p[14] = 0xff; + p[15] = 0xff; + p[16] = 0xff; + /* Medium rotation rate [rpm], 5400 rpm */ + p[20] = (5400 >> 8) & 0xff; + p[21] = 5400 & 0xff; + p += 0x16; + } else if (page == 5) { + int cylinders, heads, secs; + + /* Flexible disk device geometry page. */ + p[0] = 5; + p[1] = 0x1e; + /* Transfer rate [kbit/s], 5Mbit/s */ + p[2] = 5000 >> 8; + p[3] = 5000 & 0xff; + /* if a geometry hint is available, use it */ + bdrv_get_geometry_hint(s->bdrv, &cylinders, &heads, &secs); + p[4] = heads & 0xff; + p[5] = secs & 0xff; + p[6] = s->cluster_size * 2; + p[8] = (cylinders >> 8) & 0xff; + p[9] = cylinders & 0xff; + /* Write precomp start cylinder, disabled */ + p[10] = (cylinders >> 8) & 0xff; + p[11] = cylinders & 0xff; + /* Reduced current start cylinder, disabled */ + p[12] = (cylinders >> 8) & 0xff; + p[13] = cylinders & 0xff; + /* Device step rate [100us], 100us */ + p[14] = 0; + p[15] = 1; + /* Device step pulse width [us], 1us */ + p[16] = 1; + /* Device head settle delay [100us], 100us */ + p[17] = 0; + p[18] = 1; + /* Motor on delay [0.1s], 0.1s */ + p[19] = 1; + /* Motor off delay [0.1s], 0.1s */ + p[20] = 1; + /* Medium rotation rate [rpm], 5400 rpm */ + p[28] = (5400 >> 8) & 0xff; + p[29] = 5400 & 0xff; + p += 0x1e; + } else if ((page == 8 || page == 0x3f)) { /* Caching page. */ memset(p,0,20); p[0] = 8; -- cgit v1.2.3 From 9277bc72cf9be32f7a7c1a6353d29da34bafe0d0 Mon Sep 17 00:00:00 2001 From: blueswir1 Date: Wed, 2 Jul 2008 15:17:21 +0000 Subject: Fix NetBSD keyboard problem git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4822 c046a42c-6fe2-441c-8c8c-71466251a162 --- hw/slavio_serial.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hw/slavio_serial.c b/hw/slavio_serial.c index 97891cc52..9f5843af6 100644 --- a/hw/slavio_serial.c +++ b/hw/slavio_serial.c @@ -260,8 +260,7 @@ static uint32_t get_queue(void *opaque) static int slavio_serial_update_irq_chn(ChannelState *s) { - if ((s->wregs[W_INTR] & INTR_INTALL) && // interrupts enabled - (((s->wregs[W_INTR] & INTR_TXINT) && s->txint == 1) || + if ((((s->wregs[W_INTR] & INTR_TXINT) && s->txint == 1) || // tx ints enabled, pending ((((s->wregs[W_INTR] & INTR_RXMODEMSK) == INTR_RXINT1ST) || ((s->wregs[W_INTR] & INTR_RXMODEMSK) == INTR_RXINTALL)) && -- cgit v1.2.3 From ab19b0ecfddf94ae2053b973cea5a58c8dac0363 Mon Sep 17 00:00:00 2001 From: pbrook Date: Wed, 2 Jul 2008 16:44:09 +0000 Subject: ARMv7-M interrupt stack alignment fix. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4823 c046a42c-6fe2-441c-8c8c-71466251a162 --- target-arm/helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-arm/helper.c b/target-arm/helper.c index 8e8543525..32c2c2e28 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -674,7 +674,7 @@ void do_interrupt_v7m(CPUARMState *env) /* ??? Should only do this if Configuration Control Register STACKALIGN bit is set. */ if (env->regs[13] & 4) { - env->regs[13] += 4; + env->regs[13] -= 4; xpsr |= 0x200; } /* Switch to the handler mode. */ -- cgit v1.2.3 From 23e39294034e13d29a0707483542bab850d601b4 Mon Sep 17 00:00:00 2001 From: pbrook Date: Wed, 2 Jul 2008 16:48:32 +0000 Subject: Save/restore for stellaris boards. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4824 c046a42c-6fe2-441c-8c8c-71466251a162 --- hw/arm_gic.c | 74 ++++++++++++++++ hw/arm_timer.c | 49 ++++++++++- hw/armv7m_nvic.c | 26 ++++++ hw/pl011.c | 53 ++++++++++- hw/pl022.c | 51 ++++++++++- hw/pl061.c | 58 +++++++++++- hw/ssd0303.c | 44 ++++++++++ hw/ssd0323.c | 49 +++++++++++ hw/ssi-sd.c | 38 ++++++++ hw/stellaris.c | 243 +++++++++++++++++++++++++++++++++++++++++++++++++-- hw/stellaris_enet.c | 63 +++++++++++++ hw/stellaris_input.c | 27 ++++++ 12 files changed, 761 insertions(+), 14 deletions(-) diff --git a/hw/arm_gic.c b/hw/arm_gic.c index 7f67c5276..54e99f4d6 100644 --- a/hw/arm_gic.c +++ b/hw/arm_gic.c @@ -650,6 +650,79 @@ static void gic_reset(gic_state *s) #endif } +static void gic_save(QEMUFile *f, void *opaque) +{ + gic_state *s = (gic_state *)opaque; + int i; + int j; + + qemu_put_be32(f, s->enabled); + for (i = 0; i < NCPU; i++) { + qemu_put_be32(f, s->cpu_enabled[i]); +#ifndef NVIC + qemu_put_be32(f, s->irq_target[i]); +#endif + for (j = 0; j < 32; j++) + qemu_put_be32(f, s->priority1[j][i]); + for (j = 0; j < GIC_NIRQ; j++) + qemu_put_be32(f, s->last_active[j][i]); + qemu_put_be32(f, s->priority_mask[i]); + qemu_put_be32(f, s->running_irq[i]); + qemu_put_be32(f, s->running_priority[i]); + qemu_put_be32(f, s->current_pending[i]); + } + for (i = 0; i < GIC_NIRQ - 32; i++) { + qemu_put_be32(f, s->priority2[i]); + } + for (i = 0; i < GIC_NIRQ; i++) { + qemu_put_byte(f, s->irq_state[i].enabled); + qemu_put_byte(f, s->irq_state[i].pending); + qemu_put_byte(f, s->irq_state[i].active); + qemu_put_byte(f, s->irq_state[i].level); + qemu_put_byte(f, s->irq_state[i].model); + qemu_put_byte(f, s->irq_state[i].trigger); + } +} + +static int gic_load(QEMUFile *f, void *opaque, int version_id) +{ + gic_state *s = (gic_state *)opaque; + int i; + int j; + + if (version_id != 1) + return -EINVAL; + + s->enabled = qemu_get_be32(f); + for (i = 0; i < NCPU; i++) { + s->cpu_enabled[i] = qemu_get_be32(f); +#ifndef NVIC + s->irq_target[i] = qemu_get_be32(f); +#endif + for (j = 0; j < 32; j++) + s->priority1[j][i] = qemu_get_be32(f); + for (j = 0; j < GIC_NIRQ; j++) + s->last_active[j][i] = qemu_get_be32(f); + s->priority_mask[i] = qemu_get_be32(f); + s->running_irq[i] = qemu_get_be32(f); + s->running_priority[i] = qemu_get_be32(f); + s->current_pending[i] = qemu_get_be32(f); + } + for (i = 0; i < GIC_NIRQ - 32; i++) { + s->priority2[i] = qemu_get_be32(f); + } + for (i = 0; i < GIC_NIRQ; i++) { + s->irq_state[i].enabled = qemu_get_byte(f); + s->irq_state[i].pending = qemu_get_byte(f); + s->irq_state[i].active = qemu_get_byte(f); + s->irq_state[i].level = qemu_get_byte(f); + s->irq_state[i].model = qemu_get_byte(f); + s->irq_state[i].trigger = qemu_get_byte(f); + } + + return 0; +} + static gic_state *gic_init(uint32_t base, qemu_irq *parent_irq) { gic_state *s; @@ -669,5 +742,6 @@ static gic_state *gic_init(uint32_t base, qemu_irq *parent_irq) iomemtype); s->base = base; gic_reset(s); + register_savevm("arm_gic", -1, 1, gic_save, gic_load, s); return s; } diff --git a/hw/arm_timer.c b/hw/arm_timer.c index 540d3dea1..5150fe9a5 100644 --- a/hw/arm_timer.c +++ b/hw/arm_timer.c @@ -143,6 +143,29 @@ static void arm_timer_tick(void *opaque) arm_timer_update(s); } +static void arm_timer_save(QEMUFile *f, void *opaque) +{ + arm_timer_state *s = (arm_timer_state *)opaque; + qemu_put_be32(f, s->control); + qemu_put_be32(f, s->limit); + qemu_put_be32(f, s->int_level); + qemu_put_ptimer(f, s->timer); +} + +static int arm_timer_load(QEMUFile *f, void *opaque, int version_id) +{ + arm_timer_state *s = (arm_timer_state *)opaque; + + if (version_id != 1) + return -EINVAL; + + s->control = qemu_get_be32(f); + s->limit = qemu_get_be32(f); + s->int_level = qemu_get_be32(f); + qemu_get_ptimer(f, s->timer); + return 0; +} + static void *arm_timer_init(uint32_t freq, qemu_irq irq) { arm_timer_state *s; @@ -155,7 +178,7 @@ static void *arm_timer_init(uint32_t freq, qemu_irq irq) bh = qemu_bh_new(arm_timer_tick, s); s->timer = ptimer_init(bh); - /* ??? Save/restore. */ + register_savevm("arm_timer", -1, 1, arm_timer_save, arm_timer_load, s); return s; } @@ -218,6 +241,25 @@ static CPUWriteMemoryFunc *sp804_writefn[] = { sp804_write }; +static void sp804_save(QEMUFile *f, void *opaque) +{ + sp804_state *s = (sp804_state *)opaque; + qemu_put_be32(f, s->level[0]); + qemu_put_be32(f, s->level[1]); +} + +static int sp804_load(QEMUFile *f, void *opaque, int version_id) +{ + sp804_state *s = (sp804_state *)opaque; + + if (version_id != 1) + return -EINVAL; + + s->level[0] = qemu_get_be32(f); + s->level[1] = qemu_get_be32(f); + return 0; +} + void sp804_init(uint32_t base, qemu_irq irq) { int iomemtype; @@ -235,7 +277,7 @@ void sp804_init(uint32_t base, qemu_irq irq) iomemtype = cpu_register_io_memory(0, sp804_readfn, sp804_writefn, s); cpu_register_physical_memory(base, 0x00001000, iomemtype); - /* ??? Save/restore. */ + register_savevm("sp804", -1, 1, sp804_save, sp804_load, s); } @@ -303,6 +345,7 @@ void icp_pit_init(uint32_t base, qemu_irq *pic, int irq) iomemtype = cpu_register_io_memory(0, icp_pit_readfn, icp_pit_writefn, s); cpu_register_physical_memory(base, 0x00001000, iomemtype); - /* ??? Save/restore. */ + /* This device has no state to save/restore. The component timers will + save themselves. */ } diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c index 37596d0cc..26e4c2f2f 100644 --- a/hw/armv7m_nvic.c +++ b/hw/armv7m_nvic.c @@ -368,6 +368,31 @@ static void nvic_writel(void *opaque, uint32_t offset, uint32_t value) } } +static void nvic_save(QEMUFile *f, void *opaque) +{ + nvic_state *s = (nvic_state *)opaque; + + qemu_put_be32(f, s->systick.control); + qemu_put_be32(f, s->systick.reload); + qemu_put_be64(f, s->systick.tick); + qemu_put_timer(f, s->systick.timer); +} + +static int nvic_load(QEMUFile *f, void *opaque, int version_id) +{ + nvic_state *s = (nvic_state *)opaque; + + if (version_id != 1) + return -EINVAL; + + s->systick.control = qemu_get_be32(f); + s->systick.reload = qemu_get_be32(f); + s->systick.tick = qemu_get_be64(f); + qemu_get_timer(f, s->systick.timer); + + return 0; +} + qemu_irq *armv7m_nvic_init(CPUState *env) { nvic_state *s; @@ -381,5 +406,6 @@ qemu_irq *armv7m_nvic_init(CPUState *env) if (env->v7m.nvic) cpu_abort(env, "CPU can only have one NVIC\n"); env->v7m.nvic = s; + register_savevm("armv7m_nvic", -1, 1, nvic_save, nvic_load, s); return s->gic->in; } diff --git a/hw/pl011.c b/hw/pl011.c index 667664499..bbef0a4c6 100644 --- a/hw/pl011.c +++ b/hw/pl011.c @@ -238,6 +238,57 @@ static CPUWriteMemoryFunc *pl011_writefn[] = { pl011_write }; +static void pl011_save(QEMUFile *f, void *opaque) +{ + pl011_state *s = (pl011_state *)opaque; + int i; + + qemu_put_be32(f, s->readbuff); + qemu_put_be32(f, s->flags); + qemu_put_be32(f, s->lcr); + qemu_put_be32(f, s->cr); + qemu_put_be32(f, s->dmacr); + qemu_put_be32(f, s->int_enabled); + qemu_put_be32(f, s->int_level); + for (i = 0; i < 16; i++) + qemu_put_be32(f, s->read_fifo[i]); + qemu_put_be32(f, s->ilpr); + qemu_put_be32(f, s->ibrd); + qemu_put_be32(f, s->fbrd); + qemu_put_be32(f, s->ifl); + qemu_put_be32(f, s->read_pos); + qemu_put_be32(f, s->read_count); + qemu_put_be32(f, s->read_trigger); +} + +static int pl011_load(QEMUFile *f, void *opaque, int version_id) +{ + pl011_state *s = (pl011_state *)opaque; + int i; + + if (version_id != 1) + return -EINVAL; + + s->readbuff = qemu_get_be32(f); + s->flags = qemu_get_be32(f); + s->lcr = qemu_get_be32(f); + s->cr = qemu_get_be32(f); + s->dmacr = qemu_get_be32(f); + s->int_enabled = qemu_get_be32(f); + s->int_level = qemu_get_be32(f); + for (i = 0; i < 16; i++) + s->read_fifo[i] = qemu_get_be32(f); + s->ilpr = qemu_get_be32(f); + s->ibrd = qemu_get_be32(f); + s->fbrd = qemu_get_be32(f); + s->ifl = qemu_get_be32(f); + s->read_pos = qemu_get_be32(f); + s->read_count = qemu_get_be32(f); + s->read_trigger = qemu_get_be32(f); + + return 0; +} + void pl011_init(uint32_t base, qemu_irq irq, CharDriverState *chr, enum pl011_type type) { @@ -260,6 +311,6 @@ void pl011_init(uint32_t base, qemu_irq irq, qemu_chr_add_handlers(chr, pl011_can_receive, pl011_receive, pl011_event, s); } - /* ??? Save/restore. */ + register_savevm("pl011_uart", -1, 1, pl011_save, pl011_load, s); } diff --git a/hw/pl022.c b/hw/pl022.c index 54a581b88..a9d20c517 100644 --- a/hw/pl022.c +++ b/hw/pl022.c @@ -244,6 +244,55 @@ static CPUWriteMemoryFunc *pl022_writefn[] = { pl022_write }; +static void pl022_save(QEMUFile *f, void *opaque) +{ + pl022_state *s = (pl022_state *)opaque; + int i; + + qemu_put_be32(f, s->cr0); + qemu_put_be32(f, s->cr1); + qemu_put_be32(f, s->bitmask); + qemu_put_be32(f, s->sr); + qemu_put_be32(f, s->cpsr); + qemu_put_be32(f, s->is); + qemu_put_be32(f, s->im); + qemu_put_be32(f, s->tx_fifo_head); + qemu_put_be32(f, s->rx_fifo_head); + qemu_put_be32(f, s->tx_fifo_len); + qemu_put_be32(f, s->rx_fifo_len); + for (i = 0; i < 8; i++) { + qemu_put_be16(f, s->tx_fifo[i]); + qemu_put_be16(f, s->rx_fifo[i]); + } +} + +static int pl022_load(QEMUFile *f, void *opaque, int version_id) +{ + pl022_state *s = (pl022_state *)opaque; + int i; + + if (version_id != 1) + return -EINVAL; + + s->cr0 = qemu_get_be32(f); + s->cr1 = qemu_get_be32(f); + s->bitmask = qemu_get_be32(f); + s->sr = qemu_get_be32(f); + s->cpsr = qemu_get_be32(f); + s->is = qemu_get_be32(f); + s->im = qemu_get_be32(f); + s->tx_fifo_head = qemu_get_be32(f); + s->rx_fifo_head = qemu_get_be32(f); + s->tx_fifo_len = qemu_get_be32(f); + s->rx_fifo_len = qemu_get_be32(f); + for (i = 0; i < 8; i++) { + s->tx_fifo[i] = qemu_get_be16(f); + s->rx_fifo[i] = qemu_get_be16(f); + } + + return 0; +} + void pl022_init(uint32_t base, qemu_irq irq, int (*xfer_cb)(void *, int), void * opaque) { @@ -259,7 +308,7 @@ void pl022_init(uint32_t base, qemu_irq irq, int (*xfer_cb)(void *, int), s->xfer_cb = xfer_cb; s->opaque = opaque; pl022_reset(s); - /* ??? Save/restore. */ + register_savevm("pl022_ssp", -1, 1, pl022_save, pl022_load, s); } diff --git a/hw/pl061.c b/hw/pl061.c index 3ac0a4c10..6db5e393b 100644 --- a/hw/pl061.c +++ b/hw/pl061.c @@ -240,6 +240,62 @@ static CPUWriteMemoryFunc *pl061_writefn[] = { pl061_write }; +static void pl061_save(QEMUFile *f, void *opaque) +{ + pl061_state *s = (pl061_state *)opaque; + + qemu_put_be32(f, s->locked); + qemu_put_be32(f, s->data); + qemu_put_be32(f, s->old_data); + qemu_put_be32(f, s->dir); + qemu_put_be32(f, s->isense); + qemu_put_be32(f, s->ibe); + qemu_put_be32(f, s->iev); + qemu_put_be32(f, s->im); + qemu_put_be32(f, s->istate); + qemu_put_be32(f, s->afsel); + qemu_put_be32(f, s->dr2r); + qemu_put_be32(f, s->dr4r); + qemu_put_be32(f, s->dr8r); + qemu_put_be32(f, s->odr); + qemu_put_be32(f, s->pur); + qemu_put_be32(f, s->pdr); + qemu_put_be32(f, s->slr); + qemu_put_be32(f, s->den); + qemu_put_be32(f, s->cr); + qemu_put_be32(f, s->float_high); +} + +static int pl061_load(QEMUFile *f, void *opaque, int version_id) +{ + pl061_state *s = (pl061_state *)opaque; + if (version_id != 1) + return -EINVAL; + + s->locked = qemu_get_be32(f); + s->data = qemu_get_be32(f); + s->old_data = qemu_get_be32(f); + s->dir = qemu_get_be32(f); + s->isense = qemu_get_be32(f); + s->ibe = qemu_get_be32(f); + s->iev = qemu_get_be32(f); + s->im = qemu_get_be32(f); + s->istate = qemu_get_be32(f); + s->afsel = qemu_get_be32(f); + s->dr2r = qemu_get_be32(f); + s->dr4r = qemu_get_be32(f); + s->dr8r = qemu_get_be32(f); + s->odr = qemu_get_be32(f); + s->pur = qemu_get_be32(f); + s->pdr = qemu_get_be32(f); + s->slr = qemu_get_be32(f); + s->den = qemu_get_be32(f); + s->cr = qemu_get_be32(f); + s->float_high = qemu_get_be32(f); + + return 0; +} + /* Returns an array of inputs. */ qemu_irq *pl061_init(uint32_t base, qemu_irq irq, qemu_irq **out) { @@ -256,7 +312,7 @@ qemu_irq *pl061_init(uint32_t base, qemu_irq irq, qemu_irq **out) if (out) *out = s->out; - /* ??? Save/restore. */ + register_savevm("pl061_gpio", -1, 1, pl061_save, pl061_load, s); return qemu_allocate_irqs(pl061_set_irq, s, 8); } diff --git a/hw/ssd0303.c b/hw/ssd0303.c index 1b178f262..7f0323768 100644 --- a/hw/ssd0303.c +++ b/hw/ssd0303.c @@ -261,6 +261,49 @@ static void ssd0303_invalidate_display(void * opaque) s->redraw = 1; } +static void ssd0303_save(QEMUFile *f, void *opaque) +{ + ssd0303_state *s = (ssd0303_state *)opaque; + + qemu_put_be32(f, s->row); + qemu_put_be32(f, s->col); + qemu_put_be32(f, s->start_line); + qemu_put_be32(f, s->mirror); + qemu_put_be32(f, s->flash); + qemu_put_be32(f, s->enabled); + qemu_put_be32(f, s->inverse); + qemu_put_be32(f, s->redraw); + qemu_put_be32(f, s->mode); + qemu_put_be32(f, s->cmd_state); + qemu_put_buffer(f, s->framebuffer, sizeof(s->framebuffer)); + + i2c_slave_save(f, &s->i2c); +} + +static int ssd0303_load(QEMUFile *f, void *opaque, int version_id) +{ + ssd0303_state *s = (ssd0303_state *)opaque; + + if (version_id != 1) + return -EINVAL; + + s->row = qemu_get_be32(f); + s->col = qemu_get_be32(f); + s->start_line = qemu_get_be32(f); + s->mirror = qemu_get_be32(f); + s->flash = qemu_get_be32(f); + s->enabled = qemu_get_be32(f); + s->inverse = qemu_get_be32(f); + s->redraw = qemu_get_be32(f); + s->mode = qemu_get_be32(f); + s->cmd_state = qemu_get_be32(f); + qemu_get_buffer(f, s->framebuffer, sizeof(s->framebuffer)); + + i2c_slave_load(f, &s->i2c); + + return 0; +} + void ssd0303_init(DisplayState *ds, i2c_bus *bus, int address) { ssd0303_state *s; @@ -274,4 +317,5 @@ void ssd0303_init(DisplayState *ds, i2c_bus *bus, int address) ssd0303_invalidate_display, NULL, NULL, s); qemu_console_resize(s->console, 96 * MAGNIFY, 16 * MAGNIFY); + register_savevm("ssd0303_oled", -1, 1, ssd0303_save, ssd0303_load, s); } diff --git a/hw/ssd0323.c b/hw/ssd0323.c index 3071596f0..11afca0c6 100644 --- a/hw/ssd0323.c +++ b/hw/ssd0323.c @@ -273,6 +273,53 @@ static void ssd0323_cd(void *opaque, int n, int level) s->mode = level ? SSD0323_DATA : SSD0323_CMD; } +static void ssd0323_save(QEMUFile *f, void *opaque) +{ + ssd0323_state *s = (ssd0323_state *)opaque; + int i; + + qemu_put_be32(f, s->cmd_len); + qemu_put_be32(f, s->cmd); + for (i = 0; i < 8; i++) + qemu_put_be32(f, s->cmd_data[i]); + qemu_put_be32(f, s->row); + qemu_put_be32(f, s->row_start); + qemu_put_be32(f, s->row_end); + qemu_put_be32(f, s->col); + qemu_put_be32(f, s->col_start); + qemu_put_be32(f, s->col_end); + qemu_put_be32(f, s->redraw); + qemu_put_be32(f, s->remap); + qemu_put_be32(f, s->mode); + qemu_put_buffer(f, s->framebuffer, sizeof(s->framebuffer)); +} + +static int ssd0323_load(QEMUFile *f, void *opaque, int version_id) +{ + ssd0323_state *s = (ssd0323_state *)opaque; + int i; + + if (version_id != 1) + return -EINVAL; + + s->cmd_len = qemu_get_be32(f); + s->cmd = qemu_get_be32(f); + for (i = 0; i < 8; i++) + s->cmd_data[i] = qemu_get_be32(f); + s->row = qemu_get_be32(f); + s->row_start = qemu_get_be32(f); + s->row_end = qemu_get_be32(f); + s->col = qemu_get_be32(f); + s->col_start = qemu_get_be32(f); + s->col_end = qemu_get_be32(f); + s->redraw = qemu_get_be32(f); + s->remap = qemu_get_be32(f); + s->mode = qemu_get_be32(f); + qemu_get_buffer(f, s->framebuffer, sizeof(s->framebuffer)); + + return 0; +} + void *ssd0323_init(DisplayState *ds, qemu_irq *cmd_p) { ssd0323_state *s; @@ -290,5 +337,7 @@ void *ssd0323_init(DisplayState *ds, qemu_irq *cmd_p) cmd = qemu_allocate_irqs(ssd0323_cd, s, 1); *cmd_p = *cmd; + register_savevm("ssd0323_oled", -1, 1, ssd0323_save, ssd0323_load, s); + return s; } diff --git a/hw/ssi-sd.c b/hw/ssi-sd.c index 8b45fc4d1..1c57f1f2d 100644 --- a/hw/ssi-sd.c +++ b/hw/ssi-sd.c @@ -190,6 +190,43 @@ int ssi_sd_xfer(void *opaque, int val) return 0xff; } +static void ssi_sd_save(QEMUFile *f, void *opaque) +{ + ssi_sd_state *s = (ssi_sd_state *)opaque; + int i; + + qemu_put_be32(f, s->mode); + qemu_put_be32(f, s->cmd); + for (i = 0; i < 4; i++) + qemu_put_be32(f, s->cmdarg[i]); + for (i = 0; i < 5; i++) + qemu_put_be32(f, s->response[i]); + qemu_put_be32(f, s->arglen); + qemu_put_be32(f, s->response_pos); + qemu_put_be32(f, s->stopping); +} + +static int ssi_sd_load(QEMUFile *f, void *opaque, int version_id) +{ + ssi_sd_state *s = (ssi_sd_state *)opaque; + int i; + + if (version_id != 1) + return -EINVAL; + + s->mode = qemu_get_be32(f); + s->cmd = qemu_get_be32(f); + for (i = 0; i < 4; i++) + s->cmdarg[i] = qemu_get_be32(f); + for (i = 0; i < 5; i++) + s->response[i] = qemu_get_be32(f); + s->arglen = qemu_get_be32(f); + s->response_pos = qemu_get_be32(f); + s->stopping = qemu_get_be32(f); + + return 0; +} + void *ssi_sd_init(BlockDriverState *bs) { ssi_sd_state *s; @@ -197,6 +234,7 @@ void *ssi_sd_init(BlockDriverState *bs) s = (ssi_sd_state *)qemu_mallocz(sizeof(ssi_sd_state)); s->mode = SSI_SD_CMD; s->sd = sd_init(bs, 1); + register_savevm("ssi_sd", -1, 1, ssi_sd_save, ssi_sd_load, s); return s; } diff --git a/hw/stellaris.c b/hw/stellaris.c index a32f86fe9..999cb5059 100644 --- a/hw/stellaris.c +++ b/hw/stellaris.c @@ -286,6 +286,65 @@ static CPUWriteMemoryFunc *gptm_writefn[] = { gptm_write }; +static void gptm_save(QEMUFile *f, void *opaque) +{ + gptm_state *s = (gptm_state *)opaque; + + qemu_put_be32(f, s->config); + qemu_put_be32(f, s->mode[0]); + qemu_put_be32(f, s->mode[1]); + qemu_put_be32(f, s->control); + qemu_put_be32(f, s->state); + qemu_put_be32(f, s->mask); + qemu_put_be32(f, s->mode[0]); + qemu_put_be32(f, s->mode[0]); + qemu_put_be32(f, s->load[0]); + qemu_put_be32(f, s->load[1]); + qemu_put_be32(f, s->match[0]); + qemu_put_be32(f, s->match[1]); + qemu_put_be32(f, s->prescale[0]); + qemu_put_be32(f, s->prescale[1]); + qemu_put_be32(f, s->match_prescale[0]); + qemu_put_be32(f, s->match_prescale[1]); + qemu_put_be32(f, s->rtc); + qemu_put_be64(f, s->tick[0]); + qemu_put_be64(f, s->tick[1]); + qemu_put_timer(f, s->timer[0]); + qemu_put_timer(f, s->timer[1]); +} + +static int gptm_load(QEMUFile *f, void *opaque, int version_id) +{ + gptm_state *s = (gptm_state *)opaque; + + if (version_id != 1) + return -EINVAL; + + s->config = qemu_get_be32(f); + s->mode[0] = qemu_get_be32(f); + s->mode[1] = qemu_get_be32(f); + s->control = qemu_get_be32(f); + s->state = qemu_get_be32(f); + s->mask = qemu_get_be32(f); + s->mode[0] = qemu_get_be32(f); + s->mode[0] = qemu_get_be32(f); + s->load[0] = qemu_get_be32(f); + s->load[1] = qemu_get_be32(f); + s->match[0] = qemu_get_be32(f); + s->match[1] = qemu_get_be32(f); + s->prescale[0] = qemu_get_be32(f); + s->prescale[1] = qemu_get_be32(f); + s->match_prescale[0] = qemu_get_be32(f); + s->match_prescale[1] = qemu_get_be32(f); + s->rtc = qemu_get_be32(f); + s->tick[0] = qemu_get_be64(f); + s->tick[1] = qemu_get_be64(f); + qemu_get_timer(f, s->timer[0]); + qemu_get_timer(f, s->timer[1]); + + return 0; +} + static void stellaris_gptm_init(uint32_t base, qemu_irq irq, qemu_irq trigger) { int iomemtype; @@ -302,7 +361,7 @@ static void stellaris_gptm_init(uint32_t base, qemu_irq irq, qemu_irq trigger) cpu_register_physical_memory(base, 0x00001000, iomemtype); s->timer[0] = qemu_new_timer(vm_clock, gptm_tick, &s->opaque[0]); s->timer[1] = qemu_new_timer(vm_clock, gptm_tick, &s->opaque[1]); - /* ??? Save/restore. */ + register_savevm("stellaris_gptm", -1, 1, gptm_save, gptm_load, s); } @@ -452,6 +511,11 @@ static uint32_t ssys_read(void *opaque, target_phys_addr_t offset) } } +static void ssys_calculate_system_clock(ssys_state *s) +{ + system_clock_scale = 5 * (((s->rcc >> 23) & 0xf) + 1); +} + static void ssys_write(void *opaque, target_phys_addr_t offset, uint32_t value) { ssys_state *s = (ssys_state *)opaque; @@ -484,7 +548,7 @@ static void ssys_write(void *opaque, target_phys_addr_t offset, uint32_t value) s->int_status |= (1 << 6); } s->rcc = value; - system_clock_scale = 5 * (((s->rcc >> 23) & 0xf) + 1); + ssys_calculate_system_clock(s); break; case 0x100: /* RCGC0 */ s->rcgc[0] = value; @@ -548,6 +612,58 @@ static void ssys_reset(void *opaque) s->dcgc[0] = 1; } +static void ssys_save(QEMUFile *f, void *opaque) +{ + ssys_state *s = (ssys_state *)opaque; + + qemu_put_be32(f, s->pborctl); + qemu_put_be32(f, s->ldopctl); + qemu_put_be32(f, s->int_mask); + qemu_put_be32(f, s->int_status); + qemu_put_be32(f, s->resc); + qemu_put_be32(f, s->rcc); + qemu_put_be32(f, s->rcgc[0]); + qemu_put_be32(f, s->rcgc[1]); + qemu_put_be32(f, s->rcgc[2]); + qemu_put_be32(f, s->scgc[0]); + qemu_put_be32(f, s->scgc[1]); + qemu_put_be32(f, s->scgc[2]); + qemu_put_be32(f, s->dcgc[0]); + qemu_put_be32(f, s->dcgc[1]); + qemu_put_be32(f, s->dcgc[2]); + qemu_put_be32(f, s->clkvclr); + qemu_put_be32(f, s->ldoarst); +} + +static int ssys_load(QEMUFile *f, void *opaque, int version_id) +{ + ssys_state *s = (ssys_state *)opaque; + + if (version_id != 1) + return -EINVAL; + + s->pborctl = qemu_get_be32(f); + s->ldopctl = qemu_get_be32(f); + s->int_mask = qemu_get_be32(f); + s->int_status = qemu_get_be32(f); + s->resc = qemu_get_be32(f); + s->rcc = qemu_get_be32(f); + s->rcgc[0] = qemu_get_be32(f); + s->rcgc[1] = qemu_get_be32(f); + s->rcgc[2] = qemu_get_be32(f); + s->scgc[0] = qemu_get_be32(f); + s->scgc[1] = qemu_get_be32(f); + s->scgc[2] = qemu_get_be32(f); + s->dcgc[0] = qemu_get_be32(f); + s->dcgc[1] = qemu_get_be32(f); + s->dcgc[2] = qemu_get_be32(f); + s->clkvclr = qemu_get_be32(f); + s->ldoarst = qemu_get_be32(f); + ssys_calculate_system_clock(s); + + return 0; +} + static void stellaris_sys_init(uint32_t base, qemu_irq irq, stellaris_board_info * board, uint8_t *macaddr) @@ -567,7 +683,7 @@ static void stellaris_sys_init(uint32_t base, qemu_irq irq, ssys_writefn, s); cpu_register_physical_memory(base, 0x00001000, iomemtype); ssys_reset(s); - /* ??? Save/restore. */ + register_savevm("stellaris_sys", -1, 1, ssys_save, ssys_load, s); } @@ -737,6 +853,37 @@ static CPUWriteMemoryFunc *stellaris_i2c_writefn[] = { stellaris_i2c_write }; +static void stellaris_i2c_save(QEMUFile *f, void *opaque) +{ + stellaris_i2c_state *s = (stellaris_i2c_state *)opaque; + + qemu_put_be32(f, s->msa); + qemu_put_be32(f, s->mcs); + qemu_put_be32(f, s->mdr); + qemu_put_be32(f, s->mtpr); + qemu_put_be32(f, s->mimr); + qemu_put_be32(f, s->mris); + qemu_put_be32(f, s->mcr); +} + +static int stellaris_i2c_load(QEMUFile *f, void *opaque, int version_id) +{ + stellaris_i2c_state *s = (stellaris_i2c_state *)opaque; + + if (version_id != 1) + return -EINVAL; + + s->msa = qemu_get_be32(f); + s->mcs = qemu_get_be32(f); + s->mdr = qemu_get_be32(f); + s->mtpr = qemu_get_be32(f); + s->mimr = qemu_get_be32(f); + s->mris = qemu_get_be32(f); + s->mcr = qemu_get_be32(f); + + return 0; +} + static void stellaris_i2c_init(uint32_t base, qemu_irq irq, i2c_bus *bus) { stellaris_i2c_state *s; @@ -752,6 +899,8 @@ static void stellaris_i2c_init(uint32_t base, qemu_irq irq, i2c_bus *bus) cpu_register_physical_memory(base, 0x00001000, iomemtype); /* ??? For now we only implement the master interface. */ stellaris_i2c_reset(s); + register_savevm("stellaris_i2c", -1, 1, + stellaris_i2c_save, stellaris_i2c_load, s); } /* Analogue to Digital Converter. This is only partially implemented, @@ -785,6 +934,7 @@ typedef struct } fifo[4]; uint32_t ssmux[4]; uint32_t ssctl[4]; + uint32_t noise; qemu_irq irq; } stellaris_adc_state; @@ -833,17 +983,16 @@ static void stellaris_adc_update(stellaris_adc_state *s) static void stellaris_adc_trigger(void *opaque, int irq, int level) { stellaris_adc_state *s = (stellaris_adc_state *)opaque; - /* Some applications use the ADC as a random number source, so introduce - some variation into the signal. */ - static uint32_t noise = 0; if ((s->actss & 1) == 0) { return; } - noise = noise * 314159 + 1; + /* Some applications use the ADC as a random number source, so introduce + some variation into the signal. */ + s->noise = s->noise * 314159 + 1; /* ??? actual inputs not implemented. Return an arbitrary value. */ - stellaris_adc_fifo_write(s, 0, 0x200 + ((noise >> 16) & 7)); + stellaris_adc_fifo_write(s, 0, 0x200 + ((s->noise >> 16) & 7)); s->ris |= 1; stellaris_adc_update(s); } @@ -983,6 +1132,61 @@ static CPUWriteMemoryFunc *stellaris_adc_writefn[] = { stellaris_adc_write }; +static void stellaris_adc_save(QEMUFile *f, void *opaque) +{ + stellaris_adc_state *s = (stellaris_adc_state *)opaque; + int i; + int j; + + qemu_put_be32(f, s->actss); + qemu_put_be32(f, s->ris); + qemu_put_be32(f, s->im); + qemu_put_be32(f, s->emux); + qemu_put_be32(f, s->ostat); + qemu_put_be32(f, s->ustat); + qemu_put_be32(f, s->sspri); + qemu_put_be32(f, s->sac); + for (i = 0; i < 4; i++) { + qemu_put_be32(f, s->fifo[i].state); + for (j = 0; j < 16; j++) { + qemu_put_be32(f, s->fifo[i].data[j]); + } + qemu_put_be32(f, s->ssmux[i]); + qemu_put_be32(f, s->ssctl[i]); + } + qemu_put_be32(f, s->noise); +} + +static int stellaris_adc_load(QEMUFile *f, void *opaque, int version_id) +{ + stellaris_adc_state *s = (stellaris_adc_state *)opaque; + int i; + int j; + + if (version_id != 1) + return -EINVAL; + + s->actss = qemu_get_be32(f); + s->ris = qemu_get_be32(f); + s->im = qemu_get_be32(f); + s->emux = qemu_get_be32(f); + s->ostat = qemu_get_be32(f); + s->ustat = qemu_get_be32(f); + s->sspri = qemu_get_be32(f); + s->sac = qemu_get_be32(f); + for (i = 0; i < 4; i++) { + s->fifo[i].state = qemu_get_be32(f); + for (j = 0; j < 16; j++) { + s->fifo[i].data[j] = qemu_get_be32(f); + } + s->ssmux[i] = qemu_get_be32(f); + s->ssctl[i] = qemu_get_be32(f); + } + s->noise = qemu_get_be32(f); + + return 0; +} + static qemu_irq stellaris_adc_init(uint32_t base, qemu_irq irq) { stellaris_adc_state *s; @@ -998,6 +1202,8 @@ static qemu_irq stellaris_adc_init(uint32_t base, qemu_irq irq) cpu_register_physical_memory(base, 0x00001000, iomemtype); stellaris_adc_reset(s); qi = qemu_allocate_irqs(stellaris_adc_trigger, s, 1); + register_savevm("stellaris_adc", -1, 1, + stellaris_adc_save, stellaris_adc_load, s); return qi[0]; } @@ -1029,6 +1235,25 @@ static int stellaris_ssi_bus_xfer(void *opaque, int val) return s->xfer_cb[s->current_dev](s->opaque[s->current_dev], val); } +static void stellaris_ssi_bus_save(QEMUFile *f, void *opaque) +{ + stellaris_ssi_bus_state *s = (stellaris_ssi_bus_state *)opaque; + + qemu_put_be32(f, s->current_dev); +} + +static int stellaris_ssi_bus_load(QEMUFile *f, void *opaque, int version_id) +{ + stellaris_ssi_bus_state *s = (stellaris_ssi_bus_state *)opaque; + + if (version_id != 1) + return -EINVAL; + + s->current_dev = qemu_get_be32(f); + + return 0; +} + static void *stellaris_ssi_bus_init(qemu_irq *irqp, ssi_xfer_cb cb0, void *opaque0, ssi_xfer_cb cb1, void *opaque1) @@ -1043,6 +1268,8 @@ static void *stellaris_ssi_bus_init(qemu_irq *irqp, s->opaque[1] = opaque1; qi = qemu_allocate_irqs(stellaris_ssi_bus_select, s, 1); *irqp = *qi; + register_savevm("stellaris_ssi_bus", -1, 1, + stellaris_ssi_bus_save, stellaris_ssi_bus_load, s); return s; } diff --git a/hw/stellaris_enet.c b/hw/stellaris_enet.c index 31711b9d6..8057f80f3 100644 --- a/hw/stellaris_enet.c +++ b/hw/stellaris_enet.c @@ -326,6 +326,67 @@ static void stellaris_enet_reset(stellaris_enet_state *s) s->tx_frame_len = -1; } +static void stellaris_enet_save(QEMUFile *f, void *opaque) +{ + stellaris_enet_state *s = (stellaris_enet_state *)opaque; + int i; + + qemu_put_be32(f, s->ris); + qemu_put_be32(f, s->im); + qemu_put_be32(f, s->rctl); + qemu_put_be32(f, s->tctl); + qemu_put_be32(f, s->thr); + qemu_put_be32(f, s->mctl); + qemu_put_be32(f, s->mdv); + qemu_put_be32(f, s->mtxd); + qemu_put_be32(f, s->mrxd); + qemu_put_be32(f, s->np); + qemu_put_be32(f, s->tx_frame_len); + qemu_put_be32(f, s->tx_fifo_len); + qemu_put_buffer(f, s->tx_fifo, sizeof(s->tx_fifo)); + for (i = 0; i < 31; i++) { + qemu_put_be32(f, s->rx[i].len); + qemu_put_buffer(f, s->rx[i].data, sizeof(s->rx[i].data)); + + } + qemu_put_be32(f, s->next_packet); + qemu_put_be32(f, s->rx_fifo - s->rx[s->next_packet].data); + qemu_put_be32(f, s->rx_fifo_len); +} + +static int stellaris_enet_load(QEMUFile *f, void *opaque, int version_id) +{ + stellaris_enet_state *s = (stellaris_enet_state *)opaque; + int i; + + if (version_id != 1) + return -EINVAL; + + s->ris = qemu_get_be32(f); + s->im = qemu_get_be32(f); + s->rctl = qemu_get_be32(f); + s->tctl = qemu_get_be32(f); + s->thr = qemu_get_be32(f); + s->mctl = qemu_get_be32(f); + s->mdv = qemu_get_be32(f); + s->mtxd = qemu_get_be32(f); + s->mrxd = qemu_get_be32(f); + s->np = qemu_get_be32(f); + s->tx_frame_len = qemu_get_be32(f); + s->tx_fifo_len = qemu_get_be32(f); + qemu_get_buffer(f, s->tx_fifo, sizeof(s->tx_fifo)); + for (i = 0; i < 31; i++) { + s->rx[i].len = qemu_get_be32(f); + qemu_get_buffer(f, s->rx[i].data, sizeof(s->rx[i].data)); + + } + s->next_packet = qemu_get_be32(f); + s->rx_fifo = s->rx[s->next_packet].data + qemu_get_be32(f); + s->rx_fifo_len = qemu_get_be32(f); + + return 0; +} + void stellaris_enet_init(NICInfo *nd, uint32_t base, qemu_irq irq) { stellaris_enet_state *s; @@ -344,4 +405,6 @@ void stellaris_enet_init(NICInfo *nd, uint32_t base, qemu_irq irq) stellaris_enet_can_receive, s); stellaris_enet_reset(s); + register_savevm("stellaris_enet", -1, 1, + stellaris_enet_save, stellaris_enet_load, s); } diff --git a/hw/stellaris_input.c b/hw/stellaris_input.c index 461868b2e..aef4ce0c6 100644 --- a/hw/stellaris_input.c +++ b/hw/stellaris_input.c @@ -47,6 +47,31 @@ static void stellaris_gamepad_put_key(void * opaque, int keycode) s->extension = 0; } +static void stellaris_gamepad_save(QEMUFile *f, void *opaque) +{ + gamepad_state *s = (gamepad_state *)opaque; + int i; + + qemu_put_be32(f, s->extension); + for (i = 0; i < s->num_buttons; i++) + qemu_put_byte(f, s->buttons[i].pressed); +} + +static int stellaris_gamepad_load(QEMUFile *f, void *opaque, int version_id) +{ + gamepad_state *s = (gamepad_state *)opaque; + int i; + + if (version_id != 1) + return -EINVAL; + + s->extension = qemu_get_be32(f); + for (i = 0; i < s->num_buttons; i++) + s->buttons[i].pressed = qemu_get_byte(f); + + return 0; +} + /* Returns an array 5 ouput slots. */ void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode) { @@ -61,6 +86,8 @@ void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode) } s->num_buttons = n; qemu_add_kbd_event_handler(stellaris_gamepad_put_key, s); + register_savevm("stellaris_gamepad", -1, 1, + stellaris_gamepad_save, stellaris_gamepad_load, s); } -- cgit v1.2.3 From 902e2b5141d1c4229387be7c06a54c0241ae3773 Mon Sep 17 00:00:00 2001 From: malc Date: Wed, 2 Jul 2008 18:03:12 +0000 Subject: Add NULL argument to SNDCTL_DSP_NONBLOCK ioctl call Comes from here: http://cvsweb.netbsd.org/bsdweb.cgi/pkgsrc/emulators/qemu/patches/patch-am?rev=1.2&content-type=text/x-cvsweb-markup http://manuals.opensound.com/developer/SNDCTL_DSP_NONBLOCK.html No explanation for NULL given. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4825 c046a42c-6fe2-441c-8c8c-71466251a162 --- audio/ossaudio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/audio/ossaudio.c b/audio/ossaudio.c index a29b4bc17..613e189db 100644 --- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -237,7 +237,7 @@ static int oss_open (int in, struct oss_params *req, goto err; } - if (ioctl (fd, SNDCTL_DSP_NONBLOCK)) { + if (ioctl (fd, SNDCTL_DSP_NONBLOCK, NULL)) { oss_logerr2 (errno, typ, "Failed to set non-blocking mode\n"); goto err; } -- cgit v1.2.3 From 923e45211c783bbcd307e7074eccc0f27faddc65 Mon Sep 17 00:00:00 2001 From: malc Date: Wed, 2 Jul 2008 18:13:46 +0000 Subject: Fix test arguments (Jeremy C. Reed) git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4826 c046a42c-6fe2-441c-8c8c-71466251a162 --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index e763d0ef7..110ae823a 100755 --- a/configure +++ b/configure @@ -1042,7 +1042,7 @@ for drv in $audio_drv_list; do echo " &${drv}_audio_driver, \\" >>$config_h def=CONFIG_`echo $drv | tr '[:lower:]' '[:upper:]'` echo "$def=yes" >> $config_mak - if test "$drv" == "fmod"; then + if test "$drv" = "fmod"; then echo "CONFIG_FMOD_LIB=$fmod_lib" >> $config_mak echo "CONFIG_FMOD_INC=$fmod_inc" >> $config_mak fi -- cgit v1.2.3 From b8e59f18de9ebd0286e14ff42db217b34d4f8272 Mon Sep 17 00:00:00 2001 From: malc Date: Wed, 2 Jul 2008 21:03:08 +0000 Subject: Pulseaudio driver git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4827 c046a42c-6fe2-441c-8c8c-71466251a162 --- Makefile | 5 + Makefile.target | 4 + audio/audio_int.h | 1 + audio/paaudio.c | 515 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ configure | 8 +- 5 files changed, 532 insertions(+), 1 deletion(-) create mode 100644 audio/paaudio.c diff --git a/Makefile b/Makefile index fc56a4b6e..22d1dee10 100644 --- a/Makefile +++ b/Makefile @@ -98,6 +98,11 @@ AUDIO_PT = yes AUDIO_PT_INT = yes AUDIO_OBJS += esdaudio.o endif +ifdef CONFIG_PA +AUDIO_PT = yes +AUDIO_PT_INT = yes +AUDIO_OBJS += paaudio.o +endif ifdef AUDIO_PT LDFLAGS += -pthread endif diff --git a/Makefile.target b/Makefile.target index fc8132adc..8a709b4e3 100644 --- a/Makefile.target +++ b/Makefile.target @@ -270,6 +270,7 @@ libqemu.a: $(LIBOBJS) $(AR) rcs $@ $(LIBOBJS) translate.o: translate.c cpu.h $(OPC_H) +translate.o: CFLAGS:=${CFLAGS} -O1 #-fno-unit-at-a-time translate-all.o: translate-all.c cpu.h $(OPC_H) @@ -480,6 +481,9 @@ endif ifdef CONFIG_ESD LIBS += -lesd endif +ifdef CONFIG_PA +LIBS += -lpulse-simple +endif ifdef CONFIG_DSOUND LIBS += -lole32 -ldxguid endif diff --git a/audio/audio_int.h b/audio/audio_int.h index f96960201..d4cefb34a 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -203,6 +203,7 @@ extern struct audio_driver alsa_audio_driver; extern struct audio_driver coreaudio_audio_driver; extern struct audio_driver dsound_audio_driver; extern struct audio_driver esd_audio_driver; +extern struct audio_driver pa_audio_driver; extern volume_t nominal_volume; void audio_pcm_init_info (struct audio_pcm_info *info, audsettings_t *as); diff --git a/audio/paaudio.c b/audio/paaudio.c new file mode 100644 index 000000000..b5d390c2d --- /dev/null +++ b/audio/paaudio.c @@ -0,0 +1,515 @@ +/* public domain */ +#include "qemu-common.h" +#include "audio.h" + +#include +#include + +#define AUDIO_CAP "pulseaudio" +#include "audio_int.h" +#include "audio_pt_int.h" + +typedef struct { + HWVoiceOut hw; + int done; + int live; + int decr; + int rpos; + pa_simple *s; + void *pcm_buf; + struct audio_pt pt; +} PAVoiceOut; + +typedef struct { + HWVoiceIn hw; + int done; + int dead; + int incr; + int wpos; + pa_simple *s; + void *pcm_buf; + struct audio_pt pt; +} PAVoiceIn; + +static struct { + int samples; + int divisor; + char *server; + char *sink; + char *source; +} conf = { + 1024, + 2, + NULL, + NULL, + NULL +}; + +static void GCC_FMT_ATTR (2, 3) qpa_logerr (int err, const char *fmt, ...) +{ + va_list ap; + + va_start (ap, fmt); + AUD_vlog (AUDIO_CAP, fmt, ap); + va_end (ap); + + AUD_log (AUDIO_CAP, "Reason: %s\n", pa_strerror (err)); +} + +static void *qpa_thread_out (void *arg) +{ + PAVoiceOut *pa = arg; + HWVoiceOut *hw = &pa->hw; + int threshold; + + threshold = conf.divisor ? hw->samples / conf.divisor : 0; + + if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) { + return NULL; + } + + for (;;) { + int decr, to_mix, rpos; + + for (;;) { + if (pa->done) { + goto exit; + } + + if (pa->live > threshold) { + break; + } + + if (audio_pt_wait (&pa->pt, AUDIO_FUNC)) { + goto exit; + } + } + + decr = to_mix = pa->live; + rpos = hw->rpos; + + if (audio_pt_unlock (&pa->pt, AUDIO_FUNC)) { + return NULL; + } + + while (to_mix) { + int error; + int chunk = audio_MIN (to_mix, hw->samples - rpos); + st_sample_t *src = hw->mix_buf + rpos; + + hw->clip (pa->pcm_buf, src, chunk); + + if (pa_simple_write (pa->s, pa->pcm_buf, + chunk << hw->info.shift, &error) < 0) { + qpa_logerr (error, "pa_simple_write failed\n"); + return NULL; + } + + rpos = (rpos + chunk) % hw->samples; + to_mix -= chunk; + } + + if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) { + return NULL; + } + + pa->rpos = rpos; + pa->live -= decr; + pa->decr += decr; + } + + exit: + audio_pt_unlock (&pa->pt, AUDIO_FUNC); + return NULL; +} + +static int qpa_run_out (HWVoiceOut *hw) +{ + int live, decr; + PAVoiceOut *pa = (PAVoiceOut *) hw; + + if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) { + return 0; + } + + live = audio_pcm_hw_get_live_out (hw); + decr = audio_MIN (live, pa->decr); + pa->decr -= decr; + pa->live = live - decr; + hw->rpos = pa->rpos; + if (pa->live > 0) { + audio_pt_unlock_and_signal (&pa->pt, AUDIO_FUNC); + } + else { + audio_pt_unlock (&pa->pt, AUDIO_FUNC); + } + return decr; +} + +static int qpa_write (SWVoiceOut *sw, void *buf, int len) +{ + return audio_pcm_sw_write (sw, buf, len); +} + +/* capture */ +static void *qpa_thread_in (void *arg) +{ + PAVoiceIn *pa = arg; + HWVoiceIn *hw = &pa->hw; + int threshold; + + threshold = conf.divisor ? hw->samples / conf.divisor : 0; + + if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) { + return NULL; + } + + for (;;) { + int incr, to_grab, wpos; + + for (;;) { + if (pa->done) { + goto exit; + } + + if (pa->dead > threshold) { + break; + } + + if (audio_pt_wait (&pa->pt, AUDIO_FUNC)) { + goto exit; + } + } + + incr = to_grab = pa->dead; + wpos = hw->wpos; + + if (audio_pt_unlock (&pa->pt, AUDIO_FUNC)) { + return NULL; + } + + while (to_grab) { + int error; + int chunk = audio_MIN (to_grab, hw->samples - wpos); + void *buf = advance (pa->pcm_buf, wpos); + + if (pa_simple_read (pa->s, buf, + chunk << hw->info.shift, &error) < 0) { + qpa_logerr (error, "pa_simple_read failed\n"); + return NULL; + } + + hw->conv (hw->conv_buf + wpos, buf, chunk, &nominal_volume); + wpos = (wpos + chunk) % hw->samples; + to_grab -= chunk; + } + + if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) { + return NULL; + } + + pa->wpos = wpos; + pa->dead -= incr; + pa->incr += incr; + } + + exit: + audio_pt_unlock (&pa->pt, AUDIO_FUNC); + return NULL; +} + +static int qpa_run_in (HWVoiceIn *hw) +{ + int live, incr, dead; + PAVoiceIn *pa = (PAVoiceIn *) hw; + + if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) { + return 0; + } + + live = audio_pcm_hw_get_live_in (hw); + dead = hw->samples - live; + incr = audio_MIN (dead, pa->incr); + pa->incr -= incr; + pa->dead = dead - incr; + hw->wpos = pa->wpos; + if (pa->dead > 0) { + audio_pt_unlock_and_signal (&pa->pt, AUDIO_FUNC); + } + else { + audio_pt_unlock (&pa->pt, AUDIO_FUNC); + } + return incr; +} + +static int qpa_read (SWVoiceIn *sw, void *buf, int len) +{ + return audio_pcm_sw_read (sw, buf, len); +} + +static pa_sample_format_t audfmt_to_pa (audfmt_e afmt, int endianness) +{ + int format; + + switch (afmt) { + case AUD_FMT_S8: + case AUD_FMT_U8: + format = PA_SAMPLE_U8; + break; + case AUD_FMT_S16: + case AUD_FMT_U16: + format = endianness ? PA_SAMPLE_S16BE : PA_SAMPLE_S16LE; + break; + case AUD_FMT_S32: + case AUD_FMT_U32: + format = endianness ? PA_SAMPLE_S32BE : PA_SAMPLE_S32LE; + break; + default: + dolog ("Internal logic error: Bad audio format %d\n", afmt); + format = PA_SAMPLE_U8; + break; + } + return format; +} + +static audfmt_e pa_to_audfmt (pa_sample_format_t fmt, int *endianness) +{ + switch (fmt) { + case PA_SAMPLE_U8: + return AUD_FMT_U8; + case PA_SAMPLE_S16BE: + *endianness = 1; + return AUD_FMT_S16; + case PA_SAMPLE_S16LE: + *endianness = 0; + return AUD_FMT_S16; + case PA_SAMPLE_S32BE: + *endianness = 1; + return AUD_FMT_S32; + case PA_SAMPLE_S32LE: + *endianness = 0; + return AUD_FMT_S32; + default: + dolog ("Internal logic error: Bad pa_sample_format %d\n", fmt); + return AUD_FMT_U8; + } +} + +static int qpa_init_out (HWVoiceOut *hw, audsettings_t *as) +{ + int error; + static pa_sample_spec ss; + audsettings_t obt_as = *as; + PAVoiceOut *pa = (PAVoiceOut *) hw; + + ss.format = audfmt_to_pa (as->fmt, as->endianness); + ss.channels = as->nchannels; + ss.rate = as->freq; + + obt_as.fmt = pa_to_audfmt (ss.format, &obt_as.endianness); + + pa->s = pa_simple_new ( + conf.server, + "qemu", + PA_STREAM_PLAYBACK, + conf.sink, + "pcm.playback", + &ss, + NULL, /* channel map */ + NULL, /* buffering attributes */ + &error + ); + if (!pa->s) { + qpa_logerr (error, "pa_simple_new for playback failed\n"); + goto fail1; + } + + audio_pcm_init_info (&hw->info, &obt_as); + hw->samples = conf.samples; + pa->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift); + if (!pa->pcm_buf) { + dolog ("Could not allocate buffer (%d bytes)\n", + hw->samples << hw->info.shift); + goto fail2; + } + + if (audio_pt_init (&pa->pt, qpa_thread_out, hw, AUDIO_CAP, AUDIO_FUNC)) { + goto fail3; + } + + return 0; + + fail3: + free (pa->pcm_buf); + pa->pcm_buf = NULL; + fail2: + pa_simple_free (pa->s); + pa->s = NULL; + fail1: + return -1; +} + +static int qpa_init_in (HWVoiceIn *hw, audsettings_t *as) +{ + int error; + static pa_sample_spec ss; + audsettings_t obt_as = *as; + PAVoiceIn *pa = (PAVoiceIn *) hw; + + ss.format = audfmt_to_pa (as->fmt, as->endianness); + ss.channels = as->nchannels; + ss.rate = as->freq; + + obt_as.fmt = pa_to_audfmt (ss.format, &obt_as.endianness); + + pa->s = pa_simple_new ( + conf.server, + "qemu", + PA_STREAM_RECORD, + conf.source, + "pcm.capture", + &ss, + NULL, /* channel map */ + NULL, /* buffering attributes */ + &error + ); + if (!pa->s) { + qpa_logerr (error, "pa_simple_new for capture failed\n"); + goto fail1; + } + + audio_pcm_init_info (&hw->info, &obt_as); + hw->samples = conf.samples; + pa->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift); + if (!pa->pcm_buf) { + dolog ("Could not allocate buffer (%d bytes)\n", + hw->samples << hw->info.shift); + goto fail2; + } + + if (audio_pt_init (&pa->pt, qpa_thread_in, hw, AUDIO_CAP, AUDIO_FUNC)) { + goto fail3; + } + + return 0; + + fail3: + free (pa->pcm_buf); + pa->pcm_buf = NULL; + fail2: + pa_simple_free (pa->s); + pa->s = NULL; + fail1: + return -1; +} + +static void qpa_fini_out (HWVoiceOut *hw) +{ + void *ret; + PAVoiceOut *pa = (PAVoiceOut *) hw; + + audio_pt_lock (&pa->pt, AUDIO_FUNC); + pa->done = 1; + audio_pt_unlock_and_signal (&pa->pt, AUDIO_FUNC); + audio_pt_join (&pa->pt, &ret, AUDIO_FUNC); + + if (pa->s) { + pa_simple_free (pa->s); + pa->s = NULL; + } + + audio_pt_fini (&pa->pt, AUDIO_FUNC); + qemu_free (pa->pcm_buf); + pa->pcm_buf = NULL; +} + +static void qpa_fini_in (HWVoiceIn *hw) +{ + void *ret; + PAVoiceIn *pa = (PAVoiceIn *) hw; + + audio_pt_lock (&pa->pt, AUDIO_FUNC); + pa->done = 1; + audio_pt_unlock_and_signal (&pa->pt, AUDIO_FUNC); + audio_pt_join (&pa->pt, &ret, AUDIO_FUNC); + + if (pa->s) { + pa_simple_free (pa->s); + pa->s = NULL; + } + + audio_pt_fini (&pa->pt, AUDIO_FUNC); + qemu_free (pa->pcm_buf); + pa->pcm_buf = NULL; +} + +static int qpa_ctl_out (HWVoiceOut *hw, int cmd, ...) +{ + (void) hw; + (void) cmd; + return 0; +} + +static int qpa_ctl_in (HWVoiceIn *hw, int cmd, ...) +{ + (void) hw; + (void) cmd; + return 0; +} + +/* common */ +static void *qpa_audio_init (void) +{ + return &conf; +} + +static void qpa_audio_fini (void *opaque) +{ + (void) opaque; +} + +struct audio_option qpa_options[] = { + {"SAMPLES", AUD_OPT_INT, &conf.samples, + "buffer size in samples", NULL, 0}, + + {"DIVISOR", AUD_OPT_INT, &conf.divisor, + "threshold divisor", NULL, 0}, + + {"SERVER", AUD_OPT_STR, &conf.server, + "server address", NULL, 0}, + + {"SINK", AUD_OPT_STR, &conf.sink, + "sink device name", NULL, 0}, + + {"SOURCE", AUD_OPT_STR, &conf.source, + "source device name", NULL, 0}, + + {NULL, 0, NULL, NULL, NULL, 0} +}; + +struct audio_pcm_ops qpa_pcm_ops = { + qpa_init_out, + qpa_fini_out, + qpa_run_out, + qpa_write, + qpa_ctl_out, + qpa_init_in, + qpa_fini_in, + qpa_run_in, + qpa_read, + qpa_ctl_in +}; + +struct audio_driver pa_audio_driver = { + INIT_FIELD (name = ) "pa", + INIT_FIELD (descr = ) "http://www.pulseaudio.org/", + INIT_FIELD (options = ) qpa_options, + INIT_FIELD (init = ) qpa_audio_init, + INIT_FIELD (fini = ) qpa_audio_fini, + INIT_FIELD (pcm_ops = ) &qpa_pcm_ops, + INIT_FIELD (can_be_default = ) 0, + INIT_FIELD (max_voices_out = ) INT_MAX, + INIT_FIELD (max_voices_in = ) INT_MAX, + INIT_FIELD (voice_size_out = ) sizeof (PAVoiceOut), + INIT_FIELD (voice_size_in = ) sizeof (PAVoiceIn) +}; diff --git a/configure b/configure index 110ae823a..51be6e7ff 100755 --- a/configure +++ b/configure @@ -196,7 +196,7 @@ SunOS) ;; *) audio_drv_list="oss" -audio_possible_drivers="oss alsa sdl esd" +audio_possible_drivers="oss alsa sdl esd pa" linux="yes" linux_user="yes" if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then @@ -767,6 +767,12 @@ for drv in $audio_drv_list; do esd) audio_drv_probe $drv esd.h -lesd 'return esd_play_stream(0, 0, "", 0);' ;; + + pa) + audio_drv_probe $drv pulse/simple.h -lpulse-simple \ + "pa_simple *s = NULL; pa_simple_free(s); return 0;" + ;; + esac done -- cgit v1.2.3 From 96935aa4e3610c86f393cfd7d61331ba97f258fe Mon Sep 17 00:00:00 2001 From: malc Date: Wed, 2 Jul 2008 21:16:22 +0000 Subject: Add -MT Unbreaks dependency generation for audio, slirp and tests git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4828 c046a42c-6fe2-441c-8c8c-71466251a162 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 22d1dee10..a4dcc5845 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ VPATH=$(SRC_PATH):$(SRC_PATH)/hw CFLAGS += $(OS_CFLAGS) $(ARCH_CFLAGS) LDFLAGS += $(OS_LDFLAGS) $(ARCH_LDFLAGS) -CPPFLAGS += -I. -I$(SRC_PATH) -MMD -MP +CPPFLAGS += -I. -I$(SRC_PATH) -MMD -MP -MT $@ CPPFLAGS += -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE LIBS= ifdef CONFIG_STATIC -- cgit v1.2.3 From 975b092bd908029fb32e7372d8ae4de0d7412754 Mon Sep 17 00:00:00 2001 From: ths Date: Wed, 2 Jul 2008 21:18:00 +0000 Subject: Cleanup qemu-nbd related code, by Laurent Vivier. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4829 c046a42c-6fe2-441c-8c8c-71466251a162 --- nbd.c | 4 ++-- qemu-doc.texi | 6 ++++++ qemu-nbd.c | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/nbd.c b/nbd.c index c7d63d348..c138d362e 100644 --- a/nbd.c +++ b/nbd.c @@ -388,8 +388,8 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset, o } if (len > sizeof(data)) { - LOG("len (%u) is larger than max len (%u)", - len, sizeof(data)); + LOG("len (%u) is larger than max len (%lu)", + len, (unsigned long)sizeof(data)); errno = EINVAL; return -1; } diff --git a/qemu-doc.texi b/qemu-doc.texi index cda403faa..3e53d887c 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -1318,6 +1318,7 @@ snapshots. * disk_images_snapshot_mode:: Snapshot mode * vm_snapshots:: VM snapshots * qemu_img_invocation:: qemu-img Invocation +* qemu_nbd_invocation:: qemu-nbd Invocation * host_drives:: Using host drives * disk_images_fat_images:: Virtual FAT disk images @end menu @@ -1400,6 +1401,11 @@ state is not saved or restored properly (in particular USB). @include qemu-img.texi +@node qemu_nbd_invocation +@subsection @code{qemu-nbd} Invocation + +@include qemu-nbd.texi + @node host_drives @subsection Using host drives diff --git a/qemu-nbd.c b/qemu-nbd.c index 3fb3d0c70..0feafca08 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -21,7 +21,6 @@ #include "block_int.h" #include "nbd.h" -#include #include #include #include @@ -168,6 +167,7 @@ int main(int argc, char **argv) { "partition", 1, 0, 'P' }, { "snapshot", 0, 0, 's' }, { "verbose", 0, 0, 'v' }, + { NULL, 0, 0, 0 } }; int ch; int opt_ind = 0; -- cgit v1.2.3 From 69dd867364a5554a6f2ae6d0e2dc7c67690c067f Mon Sep 17 00:00:00 2001 From: malc Date: Wed, 2 Jul 2008 21:25:53 +0000 Subject: Remove stray local "speedup" hack git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4830 c046a42c-6fe2-441c-8c8c-71466251a162 --- Makefile.target | 1 - 1 file changed, 1 deletion(-) diff --git a/Makefile.target b/Makefile.target index 8a709b4e3..73adbb15e 100644 --- a/Makefile.target +++ b/Makefile.target @@ -270,7 +270,6 @@ libqemu.a: $(LIBOBJS) $(AR) rcs $@ $(LIBOBJS) translate.o: translate.c cpu.h $(OPC_H) -translate.o: CFLAGS:=${CFLAGS} -O1 #-fno-unit-at-a-time translate-all.o: translate-all.c cpu.h $(OPC_H) -- cgit v1.2.3 From 8114e9e8fd2610b96a808cdf703127eb26eb5278 Mon Sep 17 00:00:00 2001 From: ths Date: Thu, 3 Jul 2008 03:57:14 +0000 Subject: Fix ATAPI read drive structure command, by Alex Williamson. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4831 c046a42c-6fe2-441c-8c8c-71466251a162 --- hw/ide.c | 183 +++++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 144 insertions(+), 39 deletions(-) diff --git a/hw/ide.c b/hw/ide.c index 91244be91..337621df8 100644 --- a/hw/ide.c +++ b/hw/ide.c @@ -351,6 +351,7 @@ #define ASC_ILLEGAL_OPCODE 0x20 #define ASC_LOGICAL_BLOCK_OOR 0x21 #define ASC_INV_FIELD_IN_CMD_PACKET 0x24 +#define ASC_INCOMPATIBLE_FORMAT 0x30 #define ASC_MEDIUM_NOT_PRESENT 0x3a #define ASC_SAVING_PARAMETERS_NOT_SUPPORTED 0x39 @@ -434,6 +435,22 @@ typedef struct IDEState { int media_changed; } IDEState; +/* XXX: DVDs that could fit on a CD will be reported as a CD */ +static inline int media_present(IDEState *s) +{ + return (s->nb_sectors > 0); +} + +static inline int media_is_dvd(IDEState *s) +{ + return (media_present(s) && s->nb_sectors > CD_MAX_SECTORS); +} + +static inline int media_is_cd(IDEState *s) +{ + return (media_present(s) && s->nb_sectors <= CD_MAX_SECTORS); +} + #define BM_STATUS_DMAING 0x01 #define BM_STATUS_ERROR 0x02 #define BM_STATUS_INT 0x04 @@ -1364,6 +1381,93 @@ static inline uint8_t ide_atapi_set_profile(uint8_t *buf, uint8_t *index, return 4; } +static int ide_dvd_read_structure(IDEState *s, int format, + const uint8_t *packet, uint8_t *buf) +{ + switch (format) { + case 0x0: /* Physical format information */ + { + int layer = packet[6]; + uint64_t total_sectors; + + if (layer != 0) + return -ASC_INV_FIELD_IN_CMD_PACKET; + + bdrv_get_geometry(s->bs, &total_sectors); + total_sectors >>= 2; + if (total_sectors == 0) + return -ASC_MEDIUM_NOT_PRESENT; + + buf[4] = 1; /* DVD-ROM, part version 1 */ + buf[5] = 0xf; /* 120mm disc, minimum rate unspecified */ + buf[6] = 1; /* one layer, read-only (per MMC-2 spec) */ + buf[7] = 0; /* default densities */ + + /* FIXME: 0x30000 per spec? */ + cpu_to_ube32(buf + 8, 0); /* start sector */ + cpu_to_ube32(buf + 12, total_sectors - 1); /* end sector */ + cpu_to_ube32(buf + 16, total_sectors - 1); /* l0 end sector */ + + /* Size of buffer, not including 2 byte size field */ + cpu_to_be16wu((uint16_t *)buf, 2048 + 2); + + /* 2k data + 4 byte header */ + return (2048 + 4); + } + + case 0x01: /* DVD copyright information */ + buf[4] = 0; /* no copyright data */ + buf[5] = 0; /* no region restrictions */ + + /* Size of buffer, not including 2 byte size field */ + cpu_to_be16wu((uint16_t *)buf, 4 + 2); + + /* 4 byte header + 4 byte data */ + return (4 + 4); + + case 0x03: /* BCA information - invalid field for no BCA info */ + return -ASC_INV_FIELD_IN_CMD_PACKET; + + case 0x04: /* DVD disc manufacturing information */ + /* Size of buffer, not including 2 byte size field */ + cpu_to_be16wu((uint16_t *)buf, 2048 + 2); + + /* 2k data + 4 byte header */ + return (2048 + 4); + + case 0xff: + /* + * This lists all the command capabilities above. Add new ones + * in order and update the length and buffer return values. + */ + + buf[4] = 0x00; /* Physical format */ + buf[5] = 0x40; /* Not writable, is readable */ + cpu_to_be16wu((uint16_t *)(buf + 6), 2048 + 4); + + buf[8] = 0x01; /* Copyright info */ + buf[9] = 0x40; /* Not writable, is readable */ + cpu_to_be16wu((uint16_t *)(buf + 10), 4 + 4); + + buf[12] = 0x03; /* BCA info */ + buf[13] = 0x40; /* Not writable, is readable */ + cpu_to_be16wu((uint16_t *)(buf + 14), 188 + 4); + + buf[16] = 0x04; /* Manufacturing info */ + buf[17] = 0x40; /* Not writable, is readable */ + cpu_to_be16wu((uint16_t *)(buf + 18), 2048 + 4); + + /* Size of buffer, not including 2 byte size field */ + cpu_to_be16wu((uint16_t *)buf, 16 + 2); + + /* data written + 4 byte header */ + return (16 + 4); + + default: /* TODO: formats beyond DVD-ROM requires */ + return -ASC_INV_FIELD_IN_CMD_PACKET; + } +} + static void ide_atapi_cmd(IDEState *s) { const uint8_t *packet; @@ -1651,42 +1755,48 @@ static void ide_atapi_cmd(IDEState *s) case GPCMD_READ_DVD_STRUCTURE: { int media = packet[1]; - int layer = packet[6]; - int format = packet[2]; - uint64_t total_sectors; - - if (media != 0 || layer != 0) - { - ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, - ASC_INV_FIELD_IN_CMD_PACKET); - } - - switch (format) { - case 0: - bdrv_get_geometry(s->bs, &total_sectors); - total_sectors >>= 2; - if (total_sectors == 0) { - ide_atapi_cmd_error(s, SENSE_NOT_READY, - ASC_MEDIUM_NOT_PRESENT); - break; - } + int format = packet[7]; + int ret; - memset(buf, 0, 2052); + max_len = ube16_to_cpu(packet + 8); - buf[4] = 1; // DVD-ROM, part version 1 - buf[5] = 0xf; // 120mm disc, maximum rate unspecified - buf[6] = 0; // one layer, embossed data - buf[7] = 0; + if (format < 0xff) { + if (media_is_cd(s)) { + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, + ASC_INCOMPATIBLE_FORMAT); + break; + } else if (!media_present(s)) { + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, + ASC_INV_FIELD_IN_CMD_PACKET); + break; + } + } - cpu_to_ube32(buf + 8, 0); - cpu_to_ube32(buf + 12, total_sectors - 1); - cpu_to_ube32(buf + 16, total_sectors - 1); + memset(buf, 0, max_len > IDE_DMA_BUF_SECTORS * 512 + 4 ? + IDE_DMA_BUF_SECTORS * 512 + 4 : max_len); - cpu_to_be16wu((uint16_t *)buf, 2048 + 4); + switch (format) { + case 0x00 ... 0x7f: + case 0xff: + if (media == 0) { + ret = ide_dvd_read_structure(s, format, packet, buf); - ide_atapi_cmd_reply(s, 2048 + 3, 2048 + 4); - break; + if (ret < 0) + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, -ret); + else + ide_atapi_cmd_reply(s, ret, max_len); + break; + } + /* TODO: BD support, fall through for now */ + + /* Generic disk structures */ + case 0x80: /* TODO: AACS volume identifier */ + case 0x81: /* TODO: AACS media serial number */ + case 0x82: /* TODO: AACS media identifier */ + case 0x83: /* TODO: AACS media key block */ + case 0x90: /* TODO: List of recognized format layers */ + case 0xc0: /* TODO: Write protection status */ default: ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET); @@ -1741,16 +1851,11 @@ static void ide_atapi_cmd(IDEState *s) /* * the number of sectors from the media tells us which profile * to use as current. 0 means there is no media - * - * XXX: fails to detect correctly DVDs with less data burned - * than what a CD can hold */ - if (s -> nb_sectors) { - if (s -> nb_sectors > CD_MAX_SECTORS) - cpu_to_ube16(buf + 6, MMC_PROFILE_DVD_ROM); - else - cpu_to_ube16(buf + 6, MMC_PROFILE_CD_ROM); - } + if (media_is_dvd(s)) + cpu_to_ube16(buf + 6, MMC_PROFILE_DVD_ROM); + else if (media_is_cd(s)) + cpu_to_ube16(buf + 6, MMC_PROFILE_CD_ROM); buf[10] = 0x02 | 0x01; /* persistent and current */ len = 12; /* headers: 8 + 4 */ -- cgit v1.2.3 From 2c90d79488a255f27d43f7ac3edffc8f01aaae51 Mon Sep 17 00:00:00 2001 From: ths Date: Thu, 3 Jul 2008 04:13:24 +0000 Subject: Fix constant truncation, spotted by Jindrich Makovicka. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4832 c046a42c-6fe2-441c-8c8c-71466251a162 --- target-i386/helper.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/target-i386/helper.c b/target-i386/helper.c index 1625007e7..852f093e9 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -827,12 +827,12 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) /* XXX: This value should match the one returned by CPUID * and in exec.c */ #if defined(USE_KQEMU) -#define PHYS_ADDR_MASK 0xfffff000L +#define PHYS_ADDR_MASK 0xfffff000LL #else # if defined(TARGET_X86_64) -# define PHYS_ADDR_MASK 0xfffffff000L +# define PHYS_ADDR_MASK 0xfffffff000LL # else -# define PHYS_ADDR_MASK 0xffffff000L +# define PHYS_ADDR_MASK 0xffffff000LL # endif #endif -- cgit v1.2.3 From f8d39c01c376dc91f66936cfaf5dae3d44e9d268 Mon Sep 17 00:00:00 2001 From: ths Date: Thu, 3 Jul 2008 10:01:15 +0000 Subject: Bail out if -append or -initrd is specified without -kernel, by Sebastian Herbszt. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4833 c046a42c-6fe2-441c-8c8c-71466251a162 --- vl.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/vl.c b/vl.c index cde008e9a..c8db57983 100644 --- a/vl.c +++ b/vl.c @@ -8580,6 +8580,16 @@ int main(int argc, char **argv) nb_drives_opt == 0) help(1); + if (!linux_boot && *kernel_cmdline != '\0') { + fprintf(stderr, "-append only allowed with -kernel option\n"); + exit(1); + } + + if (!linux_boot && initrd_filename != NULL) { + fprintf(stderr, "-initrd only allowed with -kernel option\n"); + exit(1); + } + /* boot to floppy or the default cd if no hard disk defined yet */ if (!boot_devices[0]) { boot_devices = "cad"; -- cgit v1.2.3 From cd831bd7874916c4eb3f0f47218e4a65c46bb905 Mon Sep 17 00:00:00 2001 From: ths Date: Thu, 3 Jul 2008 10:23:51 +0000 Subject: Merge NBD client/server, by Laurent Vivier. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4834 c046a42c-6fe2-441c-8c8c-71466251a162 --- nbd.c | 74 ++++++++++++++++++++++++++++--- nbd.h | 5 ++- qemu-nbd.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- qemu-nbd.texi | 6 +++ 4 files changed, 213 insertions(+), 11 deletions(-) diff --git a/nbd.c b/nbd.c index c138d362e..9f8fda924 100644 --- a/nbd.c +++ b/nbd.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -183,6 +184,65 @@ error: return -1; } +int unix_socket_incoming(const char *path) +{ + int s; + struct sockaddr_un addr; + int serrno; + + s = socket(PF_UNIX, SOCK_STREAM, 0); + if (s == -1) { + return -1; + } + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + pstrcpy(addr.sun_path, sizeof(addr.sun_path), path); + + if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) { + goto error; + } + + if (listen(s, 128) == -1) { + goto error; + } + + return s; +error: + serrno = errno; + close(s); + errno = serrno; + return -1; +} + +int unix_socket_outgoing(const char *path) +{ + int s; + struct sockaddr_un addr; + int serrno; + + s = socket(PF_UNIX, SOCK_STREAM, 0); + if (s == -1) { + return -1; + } + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + pstrcpy(addr.sun_path, sizeof(addr.sun_path), path); + + if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) { + goto error; + } + + return s; +error: + serrno = errno; + close(s); + errno = serrno; + return -1; +} + + /* Basic flow Server Client @@ -225,12 +285,10 @@ int nbd_negotiate(BlockDriverState *bs, int csock, off_t size) return 0; } -int nbd_receive_negotiate(int fd, int csock) +int nbd_receive_negotiate(int csock, off_t *size, size_t *blocksize) { char buf[8 + 8 + 8 + 128]; uint64_t magic; - off_t size; - size_t blocksize; TRACE("Receiving negotation."); @@ -241,8 +299,8 @@ int nbd_receive_negotiate(int fd, int csock) } magic = be64_to_cpup((uint64_t*)(buf + 8)); - size = be64_to_cpup((uint64_t*)(buf + 16)); - blocksize = 1024; + *size = be64_to_cpup((uint64_t*)(buf + 16)); + *blocksize = 1024; TRACE("Magic is %c%c%c%c%c%c%c%c", isprint(buf[0]) ? buf[0] : '.', @@ -254,7 +312,7 @@ int nbd_receive_negotiate(int fd, int csock) isprint(buf[6]) ? buf[6] : '.', isprint(buf[7]) ? buf[7] : '.'); TRACE("Magic is 0x%" PRIx64, magic); - TRACE("Size is %" PRIu64, size); + TRACE("Size is %" PRIu64, *size); if (memcmp(buf, "NBDMAGIC", 8) != 0) { LOG("Invalid magic received"); @@ -269,7 +327,11 @@ int nbd_receive_negotiate(int fd, int csock) errno = EINVAL; return -1; } + return 0; +} +int nbd_init(int fd, int csock, off_t size, size_t blocksize) +{ TRACE("Setting block size to %lu", (unsigned long)blocksize); if (ioctl(fd, NBD_SET_BLKSIZE, blocksize) == -1) { diff --git a/nbd.h b/nbd.h index 5e583540a..4bb185bf8 100644 --- a/nbd.h +++ b/nbd.h @@ -27,9 +27,12 @@ #include "block_int.h" int tcp_socket_incoming(const char *address, uint16_t port); +int unix_socket_outgoing(const char *path); +int unix_socket_incoming(const char *path); int nbd_negotiate(BlockDriverState *bs, int csock, off_t size); -int nbd_receive_negotiate(int fd, int csock); +int nbd_receive_negotiate(int csock, off_t *size, size_t *blocksize); +int nbd_init(int fd, int csock, off_t size, size_t blocksize); int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset, off_t *offset, bool readonly); int nbd_client(int fd, int csock); int nbd_disconnect(int fd); diff --git a/qemu-nbd.c b/qemu-nbd.c index 0feafca08..3bcf87984 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -1,4 +1,4 @@ -/*\ +/* * Copyright (C) 2005 Anthony Liguori * * Network Block Device @@ -25,10 +25,14 @@ #include #include #include +#include #include #include #include #include +#include + +#define SOCKET_PATH "/var/lock/qemu-nbd-%s" int verbose; @@ -41,14 +45,18 @@ static void usage(const char *name) " -p, --port=PORT port to listen on (default `1024')\n" " -o, --offset=OFFSET offset into the image\n" " -b, --bind=IFACE interface to bind to (default `0.0.0.0')\n" +" -k, --socket=PATH path to the unix socket\n" +" (default '"SOCKET_PATH"')\n" " -r, --read-only export read-only\n" " -P, --partition=NUM only expose partition NUM\n" +" -c, --connect=DEV connect FILE to the local NBD device DEV\n" +" -d, --disconnect disconnect the specified device\n" " -v, --verbose display extra debugging information\n" " -h, --help display this help and exit\n" " -V, --version output version information and exit\n" "\n" "Report bugs to \n" - , name); + , name, "DEVICE"); } static void version(const char *name) @@ -144,27 +152,51 @@ static int find_partition(BlockDriverState *bs, int partition, return -1; } +static void show_parts(const char *device) +{ + if (fork() == 0) { + int nbd; + + /* linux just needs an open() to trigger + * the partition table update + * but remember to load the module with max_part != 0 : + * modprobe nbd max_part=63 + */ + nbd = open(device, O_RDWR); + if (nbd != -1) + close(nbd); + exit(0); + } +} + int main(int argc, char **argv) { BlockDriverState *bs; off_t dev_offset = 0; off_t offset = 0; bool readonly = false; + bool disconnect = false; const char *bindto = "0.0.0.0"; int port = 1024; int sock, csock; struct sockaddr_in addr; socklen_t addr_len = sizeof(addr); off_t fd_size; - const char *sopt = "hVbo:p:rsP:v"; + char *device = NULL; + char *socket = NULL; + char sockpath[128]; + const char *sopt = "hVbo:p:rsP:c:dvk:"; struct option lopt[] = { { "help", 0, 0, 'h' }, { "version", 0, 0, 'V' }, { "bind", 1, 0, 'b' }, { "port", 1, 0, 'p' }, + { "socket", 1, 0, 'k' }, { "offset", 1, 0, 'o' }, { "read-only", 0, 0, 'r' }, { "partition", 1, 0, 'P' }, + { "connect", 1, 0, 'c' }, + { "disconnect", 0, 0, 'd' }, { "snapshot", 0, 0, 's' }, { "verbose", 0, 0, 'v' }, { NULL, 0, 0, 0 } @@ -175,6 +207,8 @@ int main(int argc, char **argv) char *end; bool snapshot = false; int partition = -1; + int fd; + int ret; while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) { switch (ch) { @@ -213,6 +247,17 @@ int main(int argc, char **argv) if (partition < 1 || partition > 8) errx(EINVAL, "Invalid partition %d", partition); break; + case 'k': + socket = optarg; + if (socket[0] != '/') + errx(EINVAL, "socket path must be absolute\n"); + break; + case 'd': + disconnect = true; + break; + case 'c': + device = optarg; + break; case 'v': verbose = 1; break; @@ -236,6 +281,20 @@ int main(int argc, char **argv) argv[0]); } + if (disconnect) { + fd = open(argv[optind], O_RDWR); + if (fd == -1) + errx(errno, "Cannot open %s", argv[optind]); + + nbd_disconnect(fd); + + close(fd); + + printf("%s disconnected\n", argv[optind]); + + return 0; + } + bdrv_init(); bs = bdrv_new("hda"); @@ -251,7 +310,77 @@ int main(int argc, char **argv) find_partition(bs, partition, &dev_offset, &fd_size)) errx(errno, "Could not find partition %d", partition); - sock = tcp_socket_incoming(bindto, port); + if (device) { + pid_t pid; + if (!verbose) + daemon(0, 0); /* detach client and server */ + + if (socket == NULL) { + sprintf(sockpath, SOCKET_PATH, basename(device)); + socket = sockpath; + } + + pid = fork(); + if (pid < 0) + return 1; + if (pid != 0) { + off_t size; + size_t blocksize; + + ret = 0; + bdrv_close(bs); + + do { + sock = unix_socket_outgoing(socket); + if (sock == -1) { + if (errno != ENOENT && errno != ECONNREFUSED) + goto out; + sleep(1); /* wait children */ + } + } while (sock == -1); + + fd = open(device, O_RDWR); + if (fd == -1) { + ret = 1; + goto out; + } + + ret = nbd_receive_negotiate(sock, &size, &blocksize); + if (ret == -1) { + ret = 1; + goto out; + } + + ret = nbd_init(fd, sock, size, blocksize); + if (ret == -1) { + ret = 1; + goto out; + } + + printf("NBD device %s is now connected to file %s\n", + device, argv[optind]); + + /* update partition table */ + + show_parts(device); + + nbd_client(fd, sock); + close(fd); + out: + kill(pid, SIGTERM); + unlink(socket); + + return ret; + } + /* children */ + } + + if (socket) { + sock = unix_socket_incoming(socket); + } else { + sock = tcp_socket_incoming(bindto, port); + } + if (sock == -1) return 1; @@ -270,6 +399,8 @@ int main(int argc, char **argv) close(csock); close(sock); bdrv_close(bs); + if (socket) + unlink(socket); return 0; } diff --git a/qemu-nbd.texi b/qemu-nbd.texi index 7b6d0cbb5..37b68f5fc 100644 --- a/qemu-nbd.texi +++ b/qemu-nbd.texi @@ -20,10 +20,16 @@ Export Qemu disk image using NBD protocol. offset into the image @item -b, --bind=IFACE interface to bind to (default `0.0.0.0') +@item -k, --socket=PATH + Use a unix socket with path PATH @item -r, --read-only export read-only @item -P, --partition=NUM only expose partition NUM +@item -c, --connect + connect FILE to NBD device DEV +@item -d, --disconnect + disconnect the specified device @item -v, --verbose display extra debugging information @item -h, --help -- cgit v1.2.3 From 23fb600b87bbf51e6a55230d3e98e4984f59ea9d Mon Sep 17 00:00:00 2001 From: malc Date: Thu, 3 Jul 2008 11:29:15 +0000 Subject: Fix typo git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4835 c046a42c-6fe2-441c-8c8c-71466251a162 --- audio/alsaaudio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index c926cae38..ba80deac1 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -621,7 +621,7 @@ static int alsa_init_out (HWVoiceOut *hw, audsettings_t *as) req.nchannels = as->nchannels; req.period_size = conf.period_size_out; req.buffer_size = conf.buffer_size_out; - req.size_in_usec = conf.size_in_usec_in; + req.size_in_usec = conf.size_in_usec_out; if (alsa_open (0, &req, &obt, &handle)) { return -1; -- cgit v1.2.3 From 2f7264888ab4a9595a40bd045f58101e5ccd2f0a Mon Sep 17 00:00:00 2001 From: ths Date: Thu, 3 Jul 2008 11:47:46 +0000 Subject: Add a parameter to disable host cache, by Laurent Vivier. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4836 c046a42c-6fe2-441c-8c8c-71466251a162 --- Makefile | 5 ++++- block-raw-posix.c | 16 ++++++++-------- nbd.c | 14 +++++--------- nbd.h | 3 ++- qemu-nbd.c | 22 +++++++++++++++++----- qemu-nbd.texi | 4 ++++ 6 files changed, 40 insertions(+), 24 deletions(-) diff --git a/Makefile b/Makefile index a4dcc5845..aabae78cd 100644 --- a/Makefile +++ b/Makefile @@ -177,8 +177,11 @@ qemu-img-%.o: %.c %.o: %.c $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $< +qemu-nbd-%.o: %.c + $(CC) $(CFLAGS) $(CPPFLAGS) -DQEMU_NBD -c -o $@ $< + qemu-nbd$(EXESUF): qemu-nbd.o nbd.o qemu-img-block.o \ - $(QEMU_IMG_BLOCK_OBJS) + osdep.o qemu-nbd-block-raw-posix.o $(BLOCK_OBJS) $(CC) $(LDFLAGS) -o $@ $^ -lz $(LIBS) # dyngen host tool diff --git a/block-raw-posix.c b/block-raw-posix.c index fd40dda44..81382b525 100644 --- a/block-raw-posix.c +++ b/block-raw-posix.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ #include "qemu-common.h" -#ifndef QEMU_IMG +#if !defined(QEMU_IMG) && !defined(QEMU_NBD) #include "qemu-timer.h" #include "exec-all.h" #endif @@ -59,7 +59,7 @@ //#define DEBUG_FLOPPY //#define DEBUG_BLOCK -#if defined(DEBUG_BLOCK) && !defined(QEMU_IMG) +#if defined(DEBUG_BLOCK) && !defined(QEMU_IMG) && !defined(QEMU_NBD) #define DEBUG_BLOCK_PRINT(formatCstr, args...) do { if (loglevel != 0) \ { fprintf(logfile, formatCstr, ##args); fflush(logfile); } } while (0) #else @@ -434,7 +434,7 @@ static int aio_initialized = 0; static void aio_signal_handler(int signum) { -#ifndef QEMU_IMG +#if !defined(QEMU_IMG) && !defined(QEMU_NBD) CPUState *env = cpu_single_env; if (env) { /* stop the currently executing cpu because a timer occured */ @@ -544,7 +544,7 @@ void qemu_aio_wait(void) sigset_t set; int nb_sigs; -#ifndef QEMU_IMG +#if !defined(QEMU_IMG) && !defined(QEMU_NBD) if (qemu_bh_poll()) return; #endif @@ -586,7 +586,7 @@ static RawAIOCB *raw_aio_setup(BlockDriverState *bs, return acb; } -#ifndef QEMU_IMG +#if !defined(QEMU_IMG) && !defined(QEMU_NBD) static void raw_aio_em_cb(void* opaque) { RawAIOCB *acb = opaque; @@ -605,7 +605,7 @@ static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs, * If O_DIRECT is used and the buffer is not aligned fall back * to synchronous IO. */ -#if defined(O_DIRECT) && !defined(QEMU_IMG) +#if defined(O_DIRECT) && !defined(QEMU_IMG) && !defined(QEMU_NBD) BDRVRawState *s = bs->opaque; if (unlikely(s->aligned_buf != NULL && ((uintptr_t) buf % 512))) { @@ -638,7 +638,7 @@ static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs, * If O_DIRECT is used and the buffer is not aligned fall back * to synchronous IO. */ -#if defined(O_DIRECT) && !defined(QEMU_IMG) +#if defined(O_DIRECT) && !defined(QEMU_IMG) && !defined(QEMU_NBD) BDRVRawState *s = bs->opaque; if (unlikely(s->aligned_buf != NULL && ((uintptr_t) buf % 512))) { @@ -941,7 +941,7 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags) return 0; } -#if defined(__linux__) && !defined(QEMU_IMG) +#if defined(__linux__) && !defined(QEMU_IMG) && !defined(QEMU_NBD) /* Note: we do not have a reliable method to detect if the floppy is present. The current method is to try to open the floppy at every diff --git a/nbd.c b/nbd.c index 9f8fda924..49ee7dfad 100644 --- a/nbd.c +++ b/nbd.c @@ -404,13 +404,9 @@ int nbd_client(int fd, int csock) return ret; } -int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset, off_t *offset, bool readonly) +int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset, + off_t *offset, bool readonly, uint8_t *data, int data_size) { -#ifndef _REENTRANT - static uint8_t data[1024 * 1024]; // keep this off of the stack -#else - uint8_t data[1024 * 1024]; -#endif uint8_t buf[4 + 4 + 8 + 8 + 4]; uint32_t magic; uint32_t type; @@ -449,9 +445,9 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset, o return -1; } - if (len > sizeof(data)) { - LOG("len (%u) is larger than max len (%lu)", - len, (unsigned long)sizeof(data)); + if (len > data_size) { + LOG("len (%u) is larger than max len (%u)", + len, data_size); errno = EINVAL; return -1; } diff --git a/nbd.h b/nbd.h index 4bb185bf8..01e4a6af1 100644 --- a/nbd.h +++ b/nbd.h @@ -33,7 +33,8 @@ int unix_socket_incoming(const char *path); int nbd_negotiate(BlockDriverState *bs, int csock, off_t size); int nbd_receive_negotiate(int csock, off_t *size, size_t *blocksize); int nbd_init(int fd, int csock, off_t size, size_t blocksize); -int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset, off_t *offset, bool readonly); +int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset, + off_t *offset, bool readonly, uint8_t *data, int data_size); int nbd_client(int fd, int csock); int nbd_disconnect(int fd); diff --git a/qemu-nbd.c b/qemu-nbd.c index 3bcf87984..bac0e4f16 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -34,6 +34,8 @@ #define SOCKET_PATH "/var/lock/qemu-nbd-%s" +#define NBD_BUFFER_SIZE (1024*1024) + int verbose; static void usage(const char *name) @@ -49,6 +51,8 @@ static void usage(const char *name) " (default '"SOCKET_PATH"')\n" " -r, --read-only export read-only\n" " -P, --partition=NUM only expose partition NUM\n" +" -s, --snapshot use snapshot file\n" +" -n, --nocache disable host cache\n" " -c, --connect=DEV connect FILE to the local NBD device DEV\n" " -d, --disconnect disconnect the specified device\n" " -v, --verbose display extra debugging information\n" @@ -185,7 +189,7 @@ int main(int argc, char **argv) char *device = NULL; char *socket = NULL; char sockpath[128]; - const char *sopt = "hVbo:p:rsP:c:dvk:"; + const char *sopt = "hVbo:p:rsnP:c:dvk:"; struct option lopt[] = { { "help", 0, 0, 'h' }, { "version", 0, 0, 'V' }, @@ -198,6 +202,7 @@ int main(int argc, char **argv) { "connect", 1, 0, 'c' }, { "disconnect", 0, 0, 'd' }, { "snapshot", 0, 0, 's' }, + { "nocache", 0, 0, 'n' }, { "verbose", 0, 0, 'v' }, { NULL, 0, 0, 0 } }; @@ -205,15 +210,19 @@ int main(int argc, char **argv) int opt_ind = 0; int li; char *end; - bool snapshot = false; + int flags = 0; int partition = -1; int fd; int ret; + uint8_t *data; while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) { switch (ch) { case 's': - snapshot = true; + flags |= BDRV_O_SNAPSHOT; + break; + case 'n': + flags |= BDRV_O_DIRECT; break; case 'b': bindto = optarg; @@ -301,7 +310,7 @@ int main(int argc, char **argv) if (bs == NULL) return 1; - if (bdrv_open(bs, argv[optind], snapshot) == -1) + if (bdrv_open(bs, argv[optind], flags) == -1) return 1; fd_size = bs->total_sectors * 512; @@ -394,7 +403,10 @@ int main(int argc, char **argv) if (nbd_negotiate(bs, csock, fd_size) == -1) return 1; - while (nbd_trip(bs, csock, fd_size, dev_offset, &offset, readonly) == 0); + data = qemu_memalign(512, NBD_BUFFER_SIZE); + while (nbd_trip(bs, csock, fd_size, dev_offset, &offset, readonly, + data, NBD_BUFFER_SIZE) == 0); + qemu_free(data); close(csock); close(sock); diff --git a/qemu-nbd.texi b/qemu-nbd.texi index 37b68f5fc..3a4cb9254 100644 --- a/qemu-nbd.texi +++ b/qemu-nbd.texi @@ -26,6 +26,10 @@ Export Qemu disk image using NBD protocol. export read-only @item -P, --partition=NUM only expose partition NUM +@item -s, --snapshot + use snapshot file +@item -n, --nocache + disable host cache @item -c, --connect connect FILE to NBD device DEV @item -d, --disconnect -- cgit v1.2.3 From 3b05a8e91bf15e1858f3f3618069dbc78e55b88e Mon Sep 17 00:00:00 2001 From: ths Date: Thu, 3 Jul 2008 12:45:02 +0000 Subject: Allow to share a disk image via nbd, by Laurent Vivier. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4837 c046a42c-6fe2-441c-8c8c-71466251a162 --- qemu-nbd.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++------------- qemu-nbd.texi | 2 ++ 2 files changed, 77 insertions(+), 21 deletions(-) diff --git a/qemu-nbd.c b/qemu-nbd.c index bac0e4f16..605d4e324 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -55,6 +55,7 @@ static void usage(const char *name) " -n, --nocache disable host cache\n" " -c, --connect=DEV connect FILE to the local NBD device DEV\n" " -d, --disconnect disconnect the specified device\n" +" -e, --shared=NUM device can be shared by NUM clients (default '1')\n" " -v, --verbose display extra debugging information\n" " -h, --help display this help and exit\n" " -V, --version output version information and exit\n" @@ -182,14 +183,13 @@ int main(int argc, char **argv) bool disconnect = false; const char *bindto = "0.0.0.0"; int port = 1024; - int sock, csock; struct sockaddr_in addr; socklen_t addr_len = sizeof(addr); off_t fd_size; char *device = NULL; char *socket = NULL; char sockpath[128]; - const char *sopt = "hVbo:p:rsnP:c:dvk:"; + const char *sopt = "hVbo:p:rsnP:c:dvk:e:"; struct option lopt[] = { { "help", 0, 0, 'h' }, { "version", 0, 0, 'V' }, @@ -203,6 +203,7 @@ int main(int argc, char **argv) { "disconnect", 0, 0, 'd' }, { "snapshot", 0, 0, 's' }, { "nocache", 0, 0, 'n' }, + { "shared", 1, 0, 'e' }, { "verbose", 0, 0, 'v' }, { NULL, 0, 0, 0 } }; @@ -212,9 +213,15 @@ int main(int argc, char **argv) char *end; int flags = 0; int partition = -1; - int fd; int ret; + int shared = 1; uint8_t *data; + fd_set fds; + int *sharing_fds; + int fd; + int i; + int nb_fds = 0; + int max_fd; while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) { switch (ch) { @@ -267,6 +274,15 @@ int main(int argc, char **argv) case 'c': device = optarg; break; + case 'e': + shared = strtol(optarg, &end, 0); + if (*end) { + errx(EINVAL, "Invalid shared device number '%s'", optarg); + } + if (shared < 1) { + errx(EINVAL, "Shared device number must be greater than 0\n"); + } + break; case 'v': verbose = 1; break; @@ -320,8 +336,10 @@ int main(int argc, char **argv) errx(errno, "Could not find partition %d", partition); if (device) { - pid_t pid; - if (!verbose) + pid_t pid; + int sock; + + if (!verbose) daemon(0, 0); /* detach client and server */ if (socket == NULL) { @@ -384,33 +402,69 @@ int main(int argc, char **argv) /* children */ } + sharing_fds = qemu_malloc((shared + 1) * sizeof(int)); + if (sharing_fds == NULL) + errx(ENOMEM, "Cannot allocate sharing fds"); + if (socket) { - sock = unix_socket_incoming(socket); + sharing_fds[0] = unix_socket_incoming(socket); } else { - sock = tcp_socket_incoming(bindto, port); + sharing_fds[0] = tcp_socket_incoming(bindto, port); } - if (sock == -1) + if (sharing_fds[0] == -1) return 1; + max_fd = sharing_fds[0]; + nb_fds++; - csock = accept(sock, - (struct sockaddr *)&addr, - &addr_len); - if (csock == -1) - return 1; + data = qemu_memalign(512, NBD_BUFFER_SIZE); + if (data == NULL) + errx(ENOMEM, "Cannot allocate data buffer"); - /* new fd_size is calculated by find_partition */ - if (nbd_negotiate(bs, csock, fd_size) == -1) - return 1; + do { - data = qemu_memalign(512, NBD_BUFFER_SIZE); - while (nbd_trip(bs, csock, fd_size, dev_offset, &offset, readonly, - data, NBD_BUFFER_SIZE) == 0); + FD_ZERO(&fds); + for (i = 0; i < nb_fds; i++) + FD_SET(sharing_fds[i], &fds); + + ret = select(max_fd + 1, &fds, NULL, NULL, NULL); + if (ret == -1) + break; + + if (FD_ISSET(sharing_fds[0], &fds)) + ret--; + for (i = 1; i < nb_fds && ret; i++) { + if (FD_ISSET(sharing_fds[i], &fds)) { + if (nbd_trip(bs, sharing_fds[i], fd_size, dev_offset, + &offset, readonly, data, NBD_BUFFER_SIZE) != 0) { + close(sharing_fds[i]); + nb_fds--; + sharing_fds[i] = sharing_fds[nb_fds]; + i--; + } + ret--; + } + } + /* new connection ? */ + if (FD_ISSET(sharing_fds[0], &fds)) { + if (nb_fds < shared + 1) { + sharing_fds[nb_fds] = accept(sharing_fds[0], + (struct sockaddr *)&addr, + &addr_len); + if (sharing_fds[nb_fds] != -1 && + nbd_negotiate(bs, sharing_fds[nb_fds], fd_size) != -1) { + if (sharing_fds[nb_fds] > max_fd) + max_fd = sharing_fds[nb_fds]; + nb_fds++; + } + } + } + } while (nb_fds > 1); qemu_free(data); - close(csock); - close(sock); + close(sharing_fds[0]); bdrv_close(bs); + qemu_free(sharing_fds); if (socket) unlink(socket); diff --git a/qemu-nbd.texi b/qemu-nbd.texi index 3a4cb9254..b196a3471 100644 --- a/qemu-nbd.texi +++ b/qemu-nbd.texi @@ -34,6 +34,8 @@ Export Qemu disk image using NBD protocol. connect FILE to NBD device DEV @item -d, --disconnect disconnect the specified device +@item -e, --shared=NUM + device can be shared by NUM clients (default '1') @item -v, --verbose display extra debugging information @item -h, --help -- cgit v1.2.3 From 75818250ba0f61d9e3008b11d8c63b7b46d80ba2 Mon Sep 17 00:00:00 2001 From: ths Date: Thu, 3 Jul 2008 13:41:03 +0000 Subject: Allow QEMU to connect directly to an NBD server, by Laurent Vivier. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4838 c046a42c-6fe2-441c-8c8c-71466251a162 --- Makefile | 8 +-- block-nbd.c | 194 +++++++++++++++++++++++++++++++++++++++++++++++++++++ block.c | 1 + block.h | 1 + nbd.c | 211 +++++++++++++++++++++++++++++++++++++++------------------- nbd.h | 26 +++++++- qemu-doc.texi | 35 ++++++++++ qemu-nbd.c | 10 ++- qemu-nbd.texi | 2 + 9 files changed, 412 insertions(+), 76 deletions(-) create mode 100644 block-nbd.c diff --git a/Makefile b/Makefile index aabae78cd..adb36c69e 100644 --- a/Makefile +++ b/Makefile @@ -42,7 +42,7 @@ recurse-all: $(SUBDIR_RULES) BLOCK_OBJS=cutils.o qemu-malloc.o BLOCK_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o BLOCK_OBJS+=block-dmg.o block-bochs.o block-vpc.o block-vvfat.o -BLOCK_OBJS+=block-qcow2.o block-parallels.o +BLOCK_OBJS+=block-qcow2.o block-parallels.o block-nbd.o ###################################################################### # libqemu_common.a: Target independent part of system emulation. The @@ -50,7 +50,7 @@ BLOCK_OBJS+=block-qcow2.o block-parallels.o # system emulation, i.e. a single QEMU executable should support all # CPUs and machines. -OBJS=$(BLOCK_OBJS) +OBJS=nbd.o $(BLOCK_OBJS) OBJS+=readline.o console.o OBJS+=block.o @@ -159,7 +159,7 @@ libqemu_user.a: $(USER_OBJS) rm -f $@ $(AR) rcs $@ $(USER_OBJS) -QEMU_IMG_BLOCK_OBJS = $(BLOCK_OBJS) +QEMU_IMG_BLOCK_OBJS = nbd.o $(BLOCK_OBJS) ifdef CONFIG_WIN32 QEMU_IMG_BLOCK_OBJS += qemu-img-block-raw-win32.o else @@ -180,7 +180,7 @@ qemu-img-%.o: %.c qemu-nbd-%.o: %.c $(CC) $(CFLAGS) $(CPPFLAGS) -DQEMU_NBD -c -o $@ $< -qemu-nbd$(EXESUF): qemu-nbd.o nbd.o qemu-img-block.o \ +qemu-nbd$(EXESUF): qemu-nbd.o qemu-nbd-nbd.o qemu-img-block.o \ osdep.o qemu-nbd-block-raw-posix.o $(BLOCK_OBJS) $(CC) $(LDFLAGS) -o $@ $^ -lz $(LIBS) diff --git a/block-nbd.c b/block-nbd.c new file mode 100644 index 000000000..f35005015 --- /dev/null +++ b/block-nbd.c @@ -0,0 +1,194 @@ +/* + * QEMU Block driver for NBD + * + * Copyright (C) 2008 Bull S.A.S. + * Author: Laurent Vivier + * + * Some parts: + * Copyright (C) 2007 Anthony Liguori + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu-common.h" +#include "nbd.h" + +#include +#include +#include +#include +#include +#include +#include + +typedef struct BDRVNBDState { + int sock; + off_t size; + size_t blocksize; +} BDRVNBDState; + +static int nbd_open(BlockDriverState *bs, const char* filename, int flags) +{ + BDRVNBDState *s = bs->opaque; + const char *host; + const char *unixpath; + int sock; + off_t size; + size_t blocksize; + int ret; + + if ((flags & BDRV_O_CREAT)) + return -EINVAL; + + if (!strstart(filename, "nbd:", &host)) + return -EINVAL; + + if (strstart(host, "unix:", &unixpath)) { + + if (unixpath[0] != '/') + return -EINVAL; + + sock = unix_socket_outgoing(unixpath); + + } else { + uint16_t port; + char *p, *r; + char hostname[128]; + + pstrcpy(hostname, 128, host); + + p = strchr(hostname, ':'); + if (p == NULL) + return -EINVAL; + + *p = '\0'; + p++; + + port = strtol(p, &r, 0); + if (r == p) + return -EINVAL; + sock = tcp_socket_outgoing(hostname, port); + } + + if (sock == -1) + return -errno; + + ret = nbd_receive_negotiate(sock, &size, &blocksize); + if (ret == -1) + return -errno; + + s->sock = sock; + s->size = size; + s->blocksize = blocksize; + + return 0; +} + +static int nbd_read(BlockDriverState *bs, int64_t sector_num, + uint8_t *buf, int nb_sectors) +{ + BDRVNBDState *s = bs->opaque; + struct nbd_request request; + struct nbd_reply reply; + + request.type = NBD_CMD_READ; + request.handle = (uint64_t)(intptr_t)bs; + request.from = sector_num * 512;; + request.len = nb_sectors * 512; + + if (nbd_send_request(s->sock, &request) == -1) + return -errno; + + if (nbd_receive_reply(s->sock, &reply) == -1) + return -errno; + + if (reply.error !=0) + return -reply.error; + + if (reply.handle != request.handle) + return -EIO; + + if (nbd_wr_sync(s->sock, buf, request.len, 1) != request.len) + return -EIO; + + return 0; +} + +static int nbd_write(BlockDriverState *bs, int64_t sector_num, + const uint8_t *buf, int nb_sectors) +{ + BDRVNBDState *s = bs->opaque; + struct nbd_request request; + struct nbd_reply reply; + + request.type = NBD_CMD_WRITE; + request.handle = (uint64_t)(intptr_t)bs; + request.from = sector_num * 512;; + request.len = nb_sectors * 512; + + if (nbd_send_request(s->sock, &request) == -1) + return -errno; + + if (nbd_wr_sync(s->sock, (uint8_t*)buf, request.len, 0) != request.len) + return -EIO; + + if (nbd_receive_reply(s->sock, &reply) == -1) + return -errno; + + if (reply.error !=0) + return -reply.error; + + if (reply.handle != request.handle) + return -EIO; + + return 0; +} + +static void nbd_close(BlockDriverState *bs) +{ + BDRVNBDState *s = bs->opaque; + struct nbd_request request; + + request.type = NBD_CMD_DISC; + request.handle = (uint64_t)(intptr_t)bs; + request.from = 0; + request.len = 0; + nbd_send_request(s->sock, &request); + + close(s->sock); +} + +static int64_t nbd_getlength(BlockDriverState *bs) +{ + BDRVNBDState *s = bs->opaque; + + return s->size; +} + +BlockDriver bdrv_nbd = { + "nbd", + sizeof(BDRVNBDState), + NULL, /* no probe for protocols */ + nbd_open, + nbd_read, + nbd_write, + nbd_close, + .bdrv_getlength = nbd_getlength, + .protocol_name = "nbd", +}; diff --git a/block.c b/block.c index 2aaefe832..544176f1d 100644 --- a/block.c +++ b/block.c @@ -1332,6 +1332,7 @@ void bdrv_init(void) bdrv_register(&bdrv_vvfat); bdrv_register(&bdrv_qcow2); bdrv_register(&bdrv_parallels); + bdrv_register(&bdrv_nbd); } void *qemu_aio_get(BlockDriverState *bs, BlockDriverCompletionFunc *cb, diff --git a/block.h b/block.h index e18f4532a..fa741b55a 100644 --- a/block.h +++ b/block.h @@ -16,6 +16,7 @@ extern BlockDriver bdrv_vpc; extern BlockDriver bdrv_vvfat; extern BlockDriver bdrv_qcow2; extern BlockDriver bdrv_parallels; +extern BlockDriver bdrv_nbd; typedef struct BlockDriverInfo { /* in bytes, 0 if irrelevant */ diff --git a/nbd.c b/nbd.c index 49ee7dfad..306d1fa28 100644 --- a/nbd.c +++ b/nbd.c @@ -1,4 +1,4 @@ -/*\ +/* * Copyright (C) 2005 Anthony Liguori * * Network Block Device @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -\*/ + */ #include "nbd.h" @@ -31,17 +31,21 @@ #include #include +#if defined(QEMU_NBD) extern int verbose; +#else +static int verbose = 0; +#endif + +#define TRACE(msg, ...) do { \ + if (verbose) LOG(msg, ## __VA_ARGS__); \ +} while(0) #define LOG(msg, ...) do { \ fprintf(stderr, "%s:%s():L%d: " msg "\n", \ __FILE__, __FUNCTION__, __LINE__, ## __VA_ARGS__); \ } while(0) -#define TRACE(msg, ...) do { \ - if (verbose) LOG(msg, ## __VA_ARGS__); \ -} while(0) - /* This is all part of the "official" NBD API */ #define NBD_REQUEST_MAGIC 0x25609513 @@ -59,10 +63,10 @@ extern int verbose; /* That's all folks */ -#define read_sync(fd, buffer, size) wr_sync(fd, buffer, size, true) -#define write_sync(fd, buffer, size) wr_sync(fd, buffer, size, false) +#define read_sync(fd, buffer, size) nbd_wr_sync(fd, buffer, size, true) +#define write_sync(fd, buffer, size) nbd_wr_sync(fd, buffer, size, false) -static size_t wr_sync(int fd, void *buffer, size_t size, bool do_read) +size_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read) { size_t offset = 0; @@ -76,7 +80,7 @@ static size_t wr_sync(int fd, void *buffer, size_t size, bool do_read) } /* recoverable error */ - if (len == -1 && errno == EAGAIN) { + if (len == -1 && (errno == EAGAIN || errno == EINTR)) { continue; } @@ -96,7 +100,7 @@ static size_t wr_sync(int fd, void *buffer, size_t size, bool do_read) return offset; } -static int tcp_socket_outgoing(const char *address, uint16_t port) +int tcp_socket_outgoing(const char *address, uint16_t port) { int s; struct in_addr in; @@ -404,16 +408,31 @@ int nbd_client(int fd, int csock) return ret; } -int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset, - off_t *offset, bool readonly, uint8_t *data, int data_size) +int nbd_send_request(int csock, struct nbd_request *request) { uint8_t buf[4 + 4 + 8 + 8 + 4]; - uint32_t magic; - uint32_t type; - uint64_t from; - uint32_t len; - TRACE("Reading request."); + cpu_to_be32w((uint32_t*)buf, NBD_REQUEST_MAGIC); + cpu_to_be32w((uint32_t*)(buf + 4), request->type); + cpu_to_be64w((uint64_t*)(buf + 8), request->handle); + cpu_to_be64w((uint64_t*)(buf + 16), request->from); + cpu_to_be32w((uint32_t*)(buf + 24), request->len); + + TRACE("Sending request to client"); + + if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) { + LOG("writing to socket failed"); + errno = EINVAL; + return -1; + } + return 0; +} + + +static int nbd_receive_request(int csock, struct nbd_request *request) +{ + uint8_t buf[4 + 4 + 8 + 8 + 4]; + uint32_t magic; if (read_sync(csock, buf, sizeof(buf)) != sizeof(buf)) { LOG("read failed"); @@ -422,97 +441,158 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset, } /* Request - [ 0 .. 3] magic (NBD_REQUEST_MAGIC) - [ 4 .. 7] type (0 == READ, 1 == WRITE) - [ 8 .. 15] handle - [16 .. 23] from - [24 .. 27] len + [ 0 .. 3] magic (NBD_REQUEST_MAGIC) + [ 4 .. 7] type (0 == READ, 1 == WRITE) + [ 8 .. 15] handle + [16 .. 23] from + [24 .. 27] len */ magic = be32_to_cpup((uint32_t*)buf); - type = be32_to_cpup((uint32_t*)(buf + 4)); - from = be64_to_cpup((uint64_t*)(buf + 16)); - len = be32_to_cpup((uint32_t*)(buf + 24)); + request->type = be32_to_cpup((uint32_t*)(buf + 4)); + request->handle = be64_to_cpup((uint64_t*)(buf + 8)); + request->from = be64_to_cpup((uint64_t*)(buf + 16)); + request->len = be32_to_cpup((uint32_t*)(buf + 24)); TRACE("Got request: " "{ magic = 0x%x, .type = %d, from = %" PRIu64" , len = %u }", - magic, type, from, len); - + magic, request->type, request->from, request->len); if (magic != NBD_REQUEST_MAGIC) { LOG("invalid magic (got 0x%x)", magic); errno = EINVAL; return -1; } +} + +int nbd_receive_reply(int csock, struct nbd_reply *reply) +{ + uint8_t buf[4 + 4 + 8]; + uint32_t magic; + + memset(buf, 0xAA, sizeof(buf)); + + if (read_sync(csock, buf, sizeof(buf)) != sizeof(buf)) { + LOG("read failed"); + errno = EINVAL; + return -1; + } + + /* Reply + [ 0 .. 3] magic (NBD_REPLY_MAGIC) + [ 4 .. 7] error (0 == no error) + [ 7 .. 15] handle + */ + + magic = be32_to_cpup((uint32_t*)buf); + reply->error = be32_to_cpup((uint32_t*)(buf + 4)); + reply->handle = be64_to_cpup((uint64_t*)(buf + 8)); + + TRACE("Got reply: " + "{ magic = 0x%x, .error = %d, handle = %" PRIu64" }", + magic, reply->error, reply->handle); + + if (magic != NBD_REPLY_MAGIC) { + LOG("invalid magic (got 0x%x)", magic); + errno = EINVAL; + return -1; + } + return 0; +} + +static int nbd_send_reply(int csock, struct nbd_reply *reply) +{ + uint8_t buf[4 + 4 + 8]; + + /* Reply + [ 0 .. 3] magic (NBD_REPLY_MAGIC) + [ 4 .. 7] error (0 == no error) + [ 7 .. 15] handle + */ + cpu_to_be32w((uint32_t*)buf, NBD_REPLY_MAGIC); + cpu_to_be32w((uint32_t*)(buf + 4), reply->error); + cpu_to_be64w((uint64_t*)(buf + 8), reply->handle); + + TRACE("Sending response to client"); + + if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) { + LOG("writing to socket failed"); + errno = EINVAL; + return -1; + } + return 0; +} - if (len > data_size) { +int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset, + off_t *offset, bool readonly, uint8_t *data, int data_size) +{ + struct nbd_request request; + struct nbd_reply reply; + + TRACE("Reading request."); + + if (nbd_receive_request(csock, &request) == -1) + return -1; + + if (request.len > data_size) { LOG("len (%u) is larger than max len (%u)", - len, data_size); + request.len, data_size); errno = EINVAL; return -1; } - if ((from + len) < from) { + if ((request.from + request.len) < request.from) { LOG("integer overflow detected! " "you're probably being attacked"); errno = EINVAL; return -1; } - if ((from + len) > size) { + if ((request.from + request.len) > size) { LOG("From: %" PRIu64 ", Len: %u, Size: %" PRIu64 ", Offset: %" PRIu64 "\n", - from, len, size, dev_offset); + request.from, request.len, size, dev_offset); LOG("requested operation past EOF--bad client?"); errno = EINVAL; return -1; } - /* Reply - [ 0 .. 3] magic (NBD_REPLY_MAGIC) - [ 4 .. 7] error (0 == no error) - [ 7 .. 15] handle - */ - cpu_to_be32w((uint32_t*)buf, NBD_REPLY_MAGIC); - cpu_to_be32w((uint32_t*)(buf + 4), 0); - TRACE("Decoding type"); - switch (type) { - case 0: + reply.handle = request.handle; + reply.error = 0; + + switch (request.type) { + case NBD_CMD_READ: TRACE("Request type is READ"); - if (bdrv_read(bs, (from + dev_offset) / 512, data, len / 512) == -1) { + if (bdrv_read(bs, (request.from + dev_offset) / 512, data, + request.len / 512) == -1) { LOG("reading from file failed"); errno = EINVAL; return -1; } - *offset += len; - - TRACE("Read %u byte(s)", len); + *offset += request.len; - TRACE("Sending OK response"); + TRACE("Read %u byte(s)", request.len); - if (write_sync(csock, buf, 16) != 16) { - LOG("writing to socket failed"); - errno = EINVAL; + if (nbd_send_reply(csock, &reply) == -1) return -1; - } TRACE("Sending data to client"); - if (write_sync(csock, data, len) != len) { + if (write_sync(csock, data, request.len) != request.len) { LOG("writing to socket failed"); errno = EINVAL; return -1; } break; - case 1: + case NBD_CMD_WRITE: TRACE("Request type is WRITE"); - TRACE("Reading %u byte(s)", len); + TRACE("Reading %u byte(s)", request.len); - if (read_sync(csock, data, len) != len) { + if (read_sync(csock, data, request.len) != request.len) { LOG("reading from socket failed"); errno = EINVAL; return -1; @@ -520,34 +600,29 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset, if (readonly) { TRACE("Server is read-only, return error"); - - cpu_to_be32w((uint32_t*)(buf + 4), 1); + reply.error = 1; } else { TRACE("Writing to device"); - if (bdrv_write(bs, (from + dev_offset) / 512, data, len / 512) == -1) { + if (bdrv_write(bs, (request.from + dev_offset) / 512, + data, request.len / 512) == -1) { LOG("writing to file failed"); errno = EINVAL; return -1; } - *offset += len; + *offset += request.len; } - TRACE("Sending response to client"); - - if (write_sync(csock, buf, 16) != 16) { - LOG("writing to socket failed"); - errno = EINVAL; + if (nbd_send_reply(csock, &reply) == -1) return -1; - } break; - case 2: + case NBD_CMD_DISC: TRACE("Request type is DISCONNECT"); errno = 0; return 1; default: - LOG("invalid request type (%u) received", type); + LOG("invalid request type (%u) received", request.type); errno = EINVAL; return -1; } diff --git a/nbd.h b/nbd.h index 01e4a6af1..55ba1ba01 100644 --- a/nbd.h +++ b/nbd.h @@ -1,4 +1,4 @@ -/*\ +/* * Copyright (C) 2005 Anthony Liguori * * Network Block Device @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -\*/ + */ #ifndef NBD_H #define NBD_H @@ -26,6 +26,26 @@ #include #include "block_int.h" +struct nbd_request { + uint32_t type; + uint64_t handle; + uint64_t from; + uint32_t len; +}; + +struct nbd_reply { + uint32_t error; + uint64_t handle; +}; + +enum { + NBD_CMD_READ = 0, + NBD_CMD_WRITE = 1, + NBD_CMD_DISC = 2 +}; + +size_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read); +int tcp_socket_outgoing(const char *address, uint16_t port); int tcp_socket_incoming(const char *address, uint16_t port); int unix_socket_outgoing(const char *path); int unix_socket_incoming(const char *path); @@ -33,6 +53,8 @@ int unix_socket_incoming(const char *path); int nbd_negotiate(BlockDriverState *bs, int csock, off_t size); int nbd_receive_negotiate(int csock, off_t *size, size_t *blocksize); int nbd_init(int fd, int csock, off_t size, size_t blocksize); +int nbd_send_request(int csock, struct nbd_request *request); +int nbd_receive_reply(int csock, struct nbd_reply *reply); int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset, off_t *offset, bool readonly, uint8_t *data, int data_size); int nbd_client(int fd, int csock); diff --git a/qemu-doc.texi b/qemu-doc.texi index 3e53d887c..ec02685fc 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -1321,6 +1321,7 @@ snapshots. * qemu_nbd_invocation:: qemu-nbd Invocation * host_drives:: Using host drives * disk_images_fat_images:: Virtual FAT disk images +* disk_images_nbd:: NBD access @end menu @node disk_images_quickstart @@ -1503,6 +1504,40 @@ What you should @emph{never} do: @item write to the FAT directory on the host system while accessing it with the guest system. @end itemize +@node disk_images_nbd +@subsection NBD access + +QEMU can access directly to block device exported using the Network Block Device +protocol. + +@example +qemu linux.img -hdb nbd:my_nbd_server.mydomain.org:1024 +@end example + +If the NBD server is located on the same host, you can use an unix socket instead +of an inet socket: + +@example +qemu linux.img -hdb nbd:unix:/tmp/my_socket +@end example + +In this case, the block device must be exported using qemu-nbd: + +@example +qemu-nbd --socket=/tmp/my_socket my_disk.qcow2 +@end example + +The use of qemu-nbd allows to share a disk between several guests: +@example +qemu-nbd --socket=/tmp/my_socket --share=2 my_disk.qcow2 +@end example + +and then you can use it with two guests: +@example +qemu linux1.img -hdb nbd:unix:/tmp/my_socket +qemu linux2.img -hdb nbd:unix:/tmp/my_socket +@end example + @node pcsys_network @section Network emulation diff --git a/qemu-nbd.c b/qemu-nbd.c index 605d4e324..45464a0c8 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -56,6 +56,7 @@ static void usage(const char *name) " -c, --connect=DEV connect FILE to the local NBD device DEV\n" " -d, --disconnect disconnect the specified device\n" " -e, --shared=NUM device can be shared by NUM clients (default '1')\n" +" -t, --persistent don't exit on the last connection\n" " -v, --verbose display extra debugging information\n" " -h, --help display this help and exit\n" " -V, --version output version information and exit\n" @@ -189,7 +190,7 @@ int main(int argc, char **argv) char *device = NULL; char *socket = NULL; char sockpath[128]; - const char *sopt = "hVbo:p:rsnP:c:dvk:e:"; + const char *sopt = "hVbo:p:rsnP:c:dvk:e:t"; struct option lopt[] = { { "help", 0, 0, 'h' }, { "version", 0, 0, 'V' }, @@ -204,6 +205,7 @@ int main(int argc, char **argv) { "snapshot", 0, 0, 's' }, { "nocache", 0, 0, 'n' }, { "shared", 1, 0, 'e' }, + { "persistent", 0, 0, 't' }, { "verbose", 0, 0, 'v' }, { NULL, 0, 0, 0 } }; @@ -222,6 +224,7 @@ int main(int argc, char **argv) int i; int nb_fds = 0; int max_fd; + int persistent = 0; while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) { switch (ch) { @@ -283,6 +286,9 @@ int main(int argc, char **argv) errx(EINVAL, "Shared device number must be greater than 0\n"); } break; + case 't': + persistent = 1; + break; case 'v': verbose = 1; break; @@ -459,7 +465,7 @@ int main(int argc, char **argv) } } } - } while (nb_fds > 1); + } while (persistent || nb_fds > 1); qemu_free(data); close(sharing_fds[0]); diff --git a/qemu-nbd.texi b/qemu-nbd.texi index b196a3471..ff2f20792 100644 --- a/qemu-nbd.texi +++ b/qemu-nbd.texi @@ -36,6 +36,8 @@ Export Qemu disk image using NBD protocol. disconnect the specified device @item -e, --shared=NUM device can be shared by NUM clients (default '1') +@item -t, --persistent + don't exit on the last connection @item -v, --verbose display extra debugging information @item -h, --help -- cgit v1.2.3 From 06e80fc92715ca720d23526f6d3db8c78fd8971c Mon Sep 17 00:00:00 2001 From: ths Date: Thu, 3 Jul 2008 16:40:06 +0000 Subject: Silence compiler warning. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4839 c046a42c-6fe2-441c-8c8c-71466251a162 --- target-arm/translate.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target-arm/translate.c b/target-arm/translate.c index 2831432e7..e03de44d5 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -8808,6 +8808,7 @@ void cpu_dump_state(CPUState *env, FILE *f, int flags) { int i; +#if 0 union { uint32_t i; float s; @@ -8819,6 +8820,7 @@ void cpu_dump_state(CPUState *env, FILE *f, float64 f64; double d; } d0; +#endif uint32_t psr; for(i=0;i<16;i++) { -- cgit v1.2.3 From 551bd27f22638c854c43d7e6417d549764311c31 Mon Sep 17 00:00:00 2001 From: ths Date: Thu, 3 Jul 2008 17:57:36 +0000 Subject: Convert remaining __builtin_expect to likely/unlikely, by Jan Kiszka. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4840 c046a42c-6fe2-441c-8c8c-71466251a162 --- cpu-exec.c | 6 +++--- exec-all.h | 4 ++-- softmmu_header.h | 12 ++++++------ target-arm/op_helper.c | 2 +- target-arm/translate.c | 4 ++-- target-cris/op_helper.c | 2 +- target-cris/translate.c | 2 +- target-m68k/op_helper.c | 2 +- target-m68k/translate.c | 4 ++-- 9 files changed, 19 insertions(+), 19 deletions(-) diff --git a/cpu-exec.c b/cpu-exec.c index 6b46bd2c9..8cc723d35 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -224,8 +224,8 @@ static inline TranslationBlock *tb_find_fast(void) #error unsupported CPU #endif tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)]; - if (__builtin_expect(!tb || tb->pc != pc || tb->cs_base != cs_base || - tb->flags != flags, 0)) { + if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base || + tb->flags != flags)) { tb = tb_find_slow(pc, cs_base, flags); } return tb; @@ -360,7 +360,7 @@ int cpu_exec(CPUState *env1) next_tb = 0; /* force lookup of first TB */ for(;;) { interrupt_request = env->interrupt_request; - if (__builtin_expect(interrupt_request, 0) && + if (unlikely(interrupt_request) && likely(!(env->singlestep_enabled & SSTEP_NOIRQ))) { if (interrupt_request & CPU_INTERRUPT_DEBUG) { env->interrupt_request &= ~CPU_INTERRUPT_DEBUG; diff --git a/exec-all.h b/exec-all.h index 4469e95c8..943297755 100644 --- a/exec-all.h +++ b/exec-all.h @@ -357,8 +357,8 @@ static inline target_ulong get_phys_addr_code(CPUState *env1, target_ulong addr) page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); mmu_idx = cpu_mmu_index(env1); - if (__builtin_expect(env1->tlb_table[mmu_idx][page_index].addr_code != - (addr & TARGET_PAGE_MASK), 0)) { + if (unlikely(env1->tlb_table[mmu_idx][page_index].addr_code != + (addr & TARGET_PAGE_MASK))) { ldub_code(addr); } pd = env1->tlb_table[mmu_idx][page_index].addr_code & ~TARGET_PAGE_MASK; diff --git a/softmmu_header.h b/softmmu_header.h index 481051e68..512e5a2e4 100644 --- a/softmmu_header.h +++ b/softmmu_header.h @@ -231,8 +231,8 @@ static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr) addr = ptr; page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); mmu_idx = CPU_MMU_INDEX; - if (__builtin_expect(env->tlb_table[mmu_idx][page_index].ADDR_READ != - (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) { + if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ != + (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) { res = glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, mmu_idx); } else { physaddr = addr + env->tlb_table[mmu_idx][page_index].addend; @@ -252,8 +252,8 @@ static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr) addr = ptr; page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); mmu_idx = CPU_MMU_INDEX; - if (__builtin_expect(env->tlb_table[mmu_idx][page_index].ADDR_READ != - (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) { + if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ != + (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) { res = (DATA_STYPE)glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, mmu_idx); } else { physaddr = addr + env->tlb_table[mmu_idx][page_index].addend; @@ -277,8 +277,8 @@ static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE addr = ptr; page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); mmu_idx = CPU_MMU_INDEX; - if (__builtin_expect(env->tlb_table[mmu_idx][page_index].addr_write != - (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) { + if (unlikely(env->tlb_table[mmu_idx][page_index].addr_write != + (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) { glue(glue(__st, SUFFIX), MMUSUFFIX)(addr, v, mmu_idx); } else { physaddr = addr + env->tlb_table[mmu_idx][page_index].addend; diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index 5d9fd8488..5b5581f2c 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -97,7 +97,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) saved_env = env; env = cpu_single_env; ret = cpu_arm_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); - if (__builtin_expect(ret, 0)) { + if (unlikely(ret)) { if (retaddr) { /* now we have a real cpu fault */ pc = (unsigned long)retaddr; diff --git a/target-arm/translate.c b/target-arm/translate.c index e03de44d5..a3aabd26d 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -3393,7 +3393,7 @@ static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest) static inline void gen_jmp (DisasContext *s, uint32_t dest) { - if (__builtin_expect(s->singlestep_enabled, 0)) { + if (unlikely(s->singlestep_enabled)) { /* An indirect jump so that we still trigger the debug exception. */ if (s->thumb) dest |= 1; @@ -8703,7 +8703,7 @@ static inline int gen_intermediate_code_internal(CPUState *env, /* At this stage dc->condjmp will only be set when the skipped instruction was a conditional branch or trap, and the PC has already been written. */ - if (__builtin_expect(env->singlestep_enabled, 0)) { + if (unlikely(env->singlestep_enabled)) { /* Make sure the pc is updated, and raise a debug exception. */ if (dc->condjmp) { gen_set_condexec(dc); diff --git a/target-cris/op_helper.c b/target-cris/op_helper.c index 148c1e08f..fcf80705e 100644 --- a/target-cris/op_helper.c +++ b/target-cris/op_helper.c @@ -61,7 +61,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) D(fprintf(logfile, "%s pc=%x tpc=%x ra=%x\n", __func__, env->pc, env->debug1, retaddr)); ret = cpu_cris_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); - if (__builtin_expect(ret, 0)) { + if (unlikely(ret)) { if (retaddr) { /* now we have a real cpu fault */ pc = (unsigned long)retaddr; diff --git a/target-cris/translate.c b/target-cris/translate.c index 81b61326f..d971d1d2b 100644 --- a/target-cris/translate.c +++ b/target-cris/translate.c @@ -3191,7 +3191,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, cris_evaluate_flags (dc); - if (__builtin_expect(env->singlestep_enabled, 0)) { + if (unlikely(env->singlestep_enabled)) { tcg_gen_movi_tl(env_pc, npc); t_gen_raise_exception(EXCP_DEBUG); } else { diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c index f2e9f0359..aa36a3356 100644 --- a/target-m68k/op_helper.c +++ b/target-m68k/op_helper.c @@ -61,7 +61,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) saved_env = env; env = cpu_single_env; ret = cpu_m68k_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); - if (__builtin_expect(ret, 0)) { + if (unlikely(ret)) { if (retaddr) { /* now we have a real cpu fault */ pc = (unsigned long)retaddr; diff --git a/target-m68k/translate.c b/target-m68k/translate.c index e808db5e8..9486c31d7 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -873,7 +873,7 @@ static void gen_jmp_tb(DisasContext *s, int n, uint32_t dest) TranslationBlock *tb; tb = s->tb; - if (__builtin_expect (s->singlestep_enabled, 0)) { + if (unlikely(s->singlestep_enabled)) { gen_exception(s, dest, EXCP_DEBUG); } else if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) || (s->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) { @@ -2991,7 +2991,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, if (tb->cflags & CF_LAST_IO) gen_io_end(); - if (__builtin_expect(env->singlestep_enabled, 0)) { + if (unlikely(env->singlestep_enabled)) { /* Make sure the pc is updated, and raise a debug exception. */ if (!dc->is_jmp) { gen_flush_cc_op(dc); -- cgit v1.2.3 From 8c5e95d807b355200287ae32cda9b929dd8ed467 Mon Sep 17 00:00:00 2001 From: malc Date: Thu, 3 Jul 2008 18:51:23 +0000 Subject: Mask LL portion of B to 24 bits in tcg_out_b (Thanks to Thiemo Seufer) git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4841 c046a42c-6fe2-441c-8c8c-71466251a162 --- tcg/ppc/tcg-target.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c index 39319903c..c69a39eb9 100644 --- a/tcg/ppc/tcg-target.c +++ b/tcg/ppc/tcg-target.c @@ -415,7 +415,7 @@ static void tcg_out_b (TCGContext *s, int mask, tcg_target_long target) disp = target - (tcg_target_long) s->code_ptr; if ((disp << 6) >> 6 == disp) - tcg_out32 (s, B | disp | mask); + tcg_out32 (s, B | (disp & 0x3fffffc) | mask); else { tcg_out_movi (s, TCG_TYPE_I32, 0, (tcg_target_long) target); tcg_out32 (s, MTSPR | RS (0) | CTR); -- cgit v1.2.3 From 64eaabda73382b5b826dcd426200edc7c6c47d8b Mon Sep 17 00:00:00 2001 From: ths Date: Thu, 3 Jul 2008 19:54:19 +0000 Subject: Clarified filename handling, by Johannes Schindelin. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4842 c046a42c-6fe2-441c-8c8c-71466251a162 --- block-vvfat.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/block-vvfat.c b/block-vvfat.c index f5ae4f164..2dd1f2488 100644 --- a/block-vvfat.c +++ b/block-vvfat.c @@ -1410,7 +1410,12 @@ static void schedule_mkdir(BDRVVVFATState* s, uint32_t cluster, char* path) } typedef struct { - unsigned char name[1024]; + /* + * Since the sequence number is at most 0x3f, and the filename + * length is at most 13 times the sequence number, the maximal + * filename length is 0x3f * 13 bytes. + */ + unsigned char name[0x3f * 13 + 1]; int checksum, len; int sequence_number; } long_file_name; -- cgit v1.2.3 From 59fdb018127f7bf5ca259a89e465895d0256a8cf Mon Sep 17 00:00:00 2001 From: ths Date: Thu, 3 Jul 2008 19:55:47 +0000 Subject: Fix parse_long_name, by Tristan Gingold. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4843 c046a42c-6fe2-441c-8c8c-71466251a162 --- block-vvfat.c | 1 + 1 file changed, 1 insertion(+) diff --git a/block-vvfat.c b/block-vvfat.c index 2dd1f2488..08d426bbd 100644 --- a/block-vvfat.c +++ b/block-vvfat.c @@ -1440,6 +1440,7 @@ static int parse_long_name(long_file_name* lfn, lfn->sequence_number = pointer[0] & 0x3f; lfn->checksum = pointer[13]; lfn->name[0] = 0; + lfn->name[lfn->sequence_number * 13] = 0; } else if ((pointer[0] & 0x3f) != --lfn->sequence_number) return -1; else if (pointer[13] != lfn->checksum) -- cgit v1.2.3 From 706b0a15876ccdd7b702c46a6c1d25ff68fcd5b9 Mon Sep 17 00:00:00 2001 From: ths Date: Thu, 3 Jul 2008 21:36:35 +0000 Subject: Avoid compiler warning. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4844 c046a42c-6fe2-441c-8c8c-71466251a162 --- cpu-all.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpu-all.h b/cpu-all.h index 0b19ac9e3..d350b3068 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -667,7 +667,7 @@ static inline void stfq_be_p(void *ptr, float64 v) /* All direct uses of g2h and h2g need to go away for usermode softmmu. */ #define g2h(x) ((void *)((unsigned long)(x) + GUEST_BASE)) -#define h2g(x) ((target_ulong)(x - GUEST_BASE)) +#define h2g(x) ((target_ulong)((unsigned long)(x) - GUEST_BASE)) #define saddr(x) g2h(x) #define laddr(x) g2h(x) -- cgit v1.2.3 From e924c485737c38f6d6e4f3ebd65705733e837356 Mon Sep 17 00:00:00 2001 From: malc Date: Thu, 3 Jul 2008 23:49:14 +0000 Subject: Fuse EQ and NE handling in tcg_out_brcond2 git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4845 c046a42c-6fe2-441c-8c8c-71466251a162 --- tcg/ppc/tcg-target.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c index c69a39eb9..0dcf61225 100644 --- a/tcg/ppc/tcg-target.c +++ b/tcg/ppc/tcg-target.c @@ -987,14 +987,11 @@ static void tcg_out_brcond2 (TCGContext *s, const TCGArg *args, switch (cond) { case TCG_COND_EQ: - tcg_out_cmp (s, TCG_COND_EQ, args[0], args[2], const_args[2], 6); - tcg_out_cmp (s, TCG_COND_EQ, args[1], args[3], const_args[3], 7); - tcg_out32 (s, CRAND | BT (7, CR_EQ) | BA (6, CR_EQ) | BB (7, CR_EQ)); - break; case TCG_COND_NE: - tcg_out_cmp (s, TCG_COND_NE, args[0], args[2], const_args[2], 6); - tcg_out_cmp (s, TCG_COND_NE, args[1], args[3], const_args[3], 7); - tcg_out32 (s, CRNAND | BT (7, CR_EQ) | BA (6, CR_EQ) | BB (7, CR_EQ)); + op = (cond == TCG_COND_EQ) ? CRAND : CRNAND; + tcg_out_cmp (s, cond, args[0], args[2], const_args[2], 6); + tcg_out_cmp (s, cond, args[1], args[3], const_args[3], 7); + tcg_out32 (s, op | BT (7, CR_EQ) | BA (6, CR_EQ) | BB (7, CR_EQ)); break; case TCG_COND_LT: case TCG_COND_LE: -- cgit v1.2.3 From d94888e35b064df49c8059dfe1f67563e011579e Mon Sep 17 00:00:00 2001 From: malc Date: Fri, 4 Jul 2008 11:53:53 +0000 Subject: Add missing return git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4846 c046a42c-6fe2-441c-8c8c-71466251a162 --- nbd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/nbd.c b/nbd.c index 306d1fa28..e9308ee04 100644 --- a/nbd.c +++ b/nbd.c @@ -463,6 +463,7 @@ static int nbd_receive_request(int csock, struct nbd_request *request) errno = EINVAL; return -1; } + return 0; } int nbd_receive_reply(int csock, struct nbd_reply *reply) -- cgit v1.2.3 From db8baf145dd5f8e0729ab79741fcd9a292b5a322 Mon Sep 17 00:00:00 2001 From: malc Date: Sat, 5 Jul 2008 13:40:58 +0000 Subject: Avoid signedness warnings git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4847 c046a42c-6fe2-441c-8c8c-71466251a162 --- hw/gus.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/hw/gus.c b/hw/gus.c index 9ff00d791..0ab55a63b 100644 --- a/hw/gus.c +++ b/hw/gus.c @@ -222,32 +222,30 @@ int GUS_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len) static void GUS_save (QEMUFile *f, void *opaque) { - int32_t val; GUSState *s = opaque; - val = s->pos; qemu_put_be32s (f, &val); - val = s->left; qemu_put_be32s (f, &val); - val = s->shift; qemu_put_be32s (f, &val); - val = s->irqs; qemu_put_be32s (f, &val); - val = s->samples; qemu_put_be32s (f, &val); - qemu_put_be64s (f, &s->last_ticks); + qemu_put_be32 (f, s->pos); + qemu_put_be32 (f, s->left); + qemu_put_be32 (f, s->shift); + qemu_put_be32 (f, s->irqs); + qemu_put_be32 (f, s->samples); + qemu_put_be64 (f, s->last_ticks); qemu_put_buffer (f, s->himem, sizeof (s->himem)); } static int GUS_load (QEMUFile *f, void *opaque, int version_id) { - int32_t val; GUSState *s = opaque; if (version_id != 2) return -EINVAL; - qemu_get_be32s (f, &val); s->pos = val; - qemu_get_be32s (f, &val); s->left = val; - qemu_get_be32s (f, &val); s->shift = val; - qemu_get_be32s (f, &val); s->irqs = val; - qemu_get_be32s (f, &val); s->samples = val; - qemu_get_be64s (f, &s->last_ticks); + s->pos = qemu_get_be32 (f); + s->left = qemu_get_be32 (f); + s->shift = qemu_get_be32 (f); + s->irqs = qemu_get_be32 (f); + s->samples = qemu_get_be32 (f); + s->last_ticks = qemu_get_be64 (f); qemu_get_buffer (f, s->himem, sizeof (s->himem)); return 0; } -- cgit v1.2.3 From 295abf3616506e6e121d86e2d1a4b4ef8c9dd632 Mon Sep 17 00:00:00 2001 From: malc Date: Sat, 5 Jul 2008 13:41:02 +0000 Subject: Remove >= asserts on unsigned inputs git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4848 c046a42c-6fe2-441c-8c8c-71466251a162 --- block-vvfat.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/block-vvfat.c b/block-vvfat.c index 08d426bbd..9394fbd69 100644 --- a/block-vvfat.c +++ b/block-vvfat.c @@ -93,7 +93,6 @@ static inline void array_free(array_t* array) /* does not automatically grow */ static inline void* array_get(array_t* array,unsigned int index) { - assert(index >= 0); assert(index < array->next); return array->pointer + index * array->item_size; } @@ -195,7 +194,6 @@ static int array_remove(array_t* array,int index) static int array_index(array_t* array, void* pointer) { size_t offset = (char*)pointer - array->pointer; - assert(offset >= 0); assert((offset % array->item_size) == 0); assert(offset/array->item_size < array->next); return offset/array->item_size; @@ -2238,7 +2236,6 @@ static int commit_one_file(BDRVVVFATState* s, assert((size - offset == 0 && fat_eof(s, c)) || (size > offset && c >=2 && !fat_eof(s, c))); - assert(size >= 0); ret = vvfat_read(s->bs, cluster2sector(s, c), (uint8_t*)cluster, (rest_size + 0x1ff) / 0x200); -- cgit v1.2.3 From cea9d0b39bf1dca0c81f77dce68274fbc569c906 Mon Sep 17 00:00:00 2001 From: malc Date: Sat, 5 Jul 2008 13:41:04 +0000 Subject: Remove static Also avoids GCC warning about old style declaration git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4849 c046a42c-6fe2-441c-8c8c-71466251a162 --- hw/dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/dma.c b/hw/dma.c index f192c63d1..bbdecc522 100644 --- a/hw/dma.c +++ b/hw/dma.c @@ -450,7 +450,7 @@ static int dma_phony_handler (void *opaque, int nchan, int dma_pos, int dma_len) static void dma_init2(struct dma_cont *d, int base, int dshift, int page_base, int pageh_base) { - const static int page_port_list[] = { 0x1, 0x2, 0x3, 0x7 }; + const int page_port_list[] = { 0x1, 0x2, 0x3, 0x7 }; int i; d->dshift = dshift; -- cgit v1.2.3 From d70040bcae822db0515eae055f1842164c2697a9 Mon Sep 17 00:00:00 2001 From: pbrook Date: Sat, 5 Jul 2008 17:03:54 +0000 Subject: Re-add static qualifier. Fix annother occurance of "const static". git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4850 c046a42c-6fe2-441c-8c8c-71466251a162 --- hw/dma.c | 2 +- target-i386/translate.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/dma.c b/hw/dma.c index bbdecc522..00c6332b4 100644 --- a/hw/dma.c +++ b/hw/dma.c @@ -450,7 +450,7 @@ static int dma_phony_handler (void *opaque, int nchan, int dma_pos, int dma_len) static void dma_init2(struct dma_cont *d, int base, int dshift, int page_base, int pageh_base) { - const int page_port_list[] = { 0x1, 0x2, 0x3, 0x7 }; + static const int page_port_list[] = { 0x1, 0x2, 0x3, 0x7 }; int i; d->dshift = dshift; diff --git a/target-i386/translate.c b/target-i386/translate.c index f7313ea8e..bfb2801d2 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -5475,7 +5475,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) case 0x18 ... 0x1b: { int op1, l1; - const static uint8_t fcmov_cc[8] = { + static const uint8_t fcmov_cc[8] = { (JCC_B << 1), (JCC_Z << 1), (JCC_BE << 1), -- cgit v1.2.3 From 63742cf887a161aba6cbe53a60161aa47db9a4bb Mon Sep 17 00:00:00 2001 From: ths Date: Sat, 5 Jul 2008 21:51:47 +0000 Subject: Change MIPS machine default to Malta. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4851 c046a42c-6fe2-441c-8c8c-71466251a162 --- target-mips/machine.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target-mips/machine.c b/target-mips/machine.c index 20fa58791..f73b9e2f5 100644 --- a/target-mips/machine.c +++ b/target-mips/machine.c @@ -3,11 +3,11 @@ void register_machines(void) { - qemu_register_machine(&mips_machine); - qemu_register_machine(&mips_magnum_machine); qemu_register_machine(&mips_malta_machine); + qemu_register_machine(&mips_magnum_machine); qemu_register_machine(&mips_pica61_machine); qemu_register_machine(&mips_mipssim_machine); + qemu_register_machine(&mips_machine); } void cpu_save(QEMUFile *f, void *opaque) -- cgit v1.2.3 From c7e8a937b7cb531a9b8ca4d1b91a3571bf44f276 Mon Sep 17 00:00:00 2001 From: ths Date: Sat, 5 Jul 2008 21:54:32 +0000 Subject: Fix typo in comment. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4852 c046a42c-6fe2-441c-8c8c-71466251a162 --- target-mips/translate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index 803a48f32..f92326339 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -8021,7 +8021,7 @@ void dump_fpu (CPUState *env) #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS) /* Debug help: The architecture requires 32bit code to maintain proper - sign-extened values on 64bit machines. */ + sign-extended values on 64bit machines. */ #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff)) -- cgit v1.2.3 From 6a1ef8309e23f9149ec6f4d676bb6bfc1a30b876 Mon Sep 17 00:00:00 2001 From: ths Date: Mon, 7 Jul 2008 19:29:49 +0000 Subject: Improve jp106 keyboard support, by Akio Takebe. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4853 c046a42c-6fe2-441c-8c8c-71466251a162 --- keymaps/ja | 1 + vnc_keysym.h | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/keymaps/ja b/keymaps/ja index 6947cb124..9d90a78c8 100644 --- a/keymaps/ja +++ b/keymaps/ja @@ -101,6 +101,7 @@ yen 0x7d bar 0x7d shift underscore 0x73 shift Henkan_Mode 0x79 +Katakana_Real 0x70 Katakana 0x70 Muhenkan 0x7b Henkan_Mode_Real 0x79 diff --git a/vnc_keysym.h b/vnc_keysym.h index 5c4710444..b6a172de9 100644 --- a/vnc_keysym.h +++ b/vnc_keysym.h @@ -289,11 +289,14 @@ static name2keysym_t name2keysym[]={ /* localized keys */ {"BackApostrophe", 0xff21}, {"Muhenkan", 0xff22}, -{"Katakana", 0xff25}, -{"Zenkaku_Hankaku", 0xff29}, +{"Katakana", 0xff27}, +{"Hankaku", 0xff29}, +{"Zenkaku_Hankaku", 0xff2a}, {"Henkan_Mode_Real", 0xff23}, {"Henkan_Mode_Ultra", 0xff3e}, {"backslash_ja", 0xffa5}, +{"Katakana_Real", 0xff25}, +{"Eisu_toggle", 0xff30}, {0,0}, }; -- cgit v1.2.3 From d795eb86d73c61351c70f7a9714b40e8a5c49e3d Mon Sep 17 00:00:00 2001 From: blueswir1 Date: Mon, 7 Jul 2008 19:34:45 +0000 Subject: Fix 64 bit constant generation git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4854 c046a42c-6fe2-441c-8c8c-71466251a162 --- tcg/sparc/tcg-target.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index 492ed3d9a..58f86d35a 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -304,11 +304,10 @@ static inline void tcg_out_movi(TCGContext *s, TCGType type, { #if defined(__sparc_v9__) && !defined(__sparc_v8plus__) if (!check_fit_tl(arg, 32) && (arg & ~0xffffffffULL) != 0) { - // XXX ret may be I5, need another temp - tcg_out_movi_imm32(s, TCG_REG_I5, arg >> 32); - tcg_out_arithi(s, TCG_REG_I5, TCG_REG_I5, 32, SHIFT_SLLX); + tcg_out_movi_imm32(s, TCG_REG_I4, arg >> 32); + tcg_out_arithi(s, TCG_REG_I4, TCG_REG_I4, 32, SHIFT_SLLX); tcg_out_movi_imm32(s, ret, arg); - tcg_out_arith(s, ret, ret, TCG_REG_I5, ARITH_OR); + tcg_out_arith(s, ret, ret, TCG_REG_I4, ARITH_OR); } else #endif tcg_out_movi_imm32(s, ret, arg); @@ -1137,6 +1136,9 @@ void tcg_target_init(TCGContext *s) tcg_regset_clear(s->reserved_regs); tcg_regset_set_reg(s->reserved_regs, TCG_REG_G0); +#if defined(__sparc_v9__) && !defined(__sparc_v8plus__) + tcg_regset_set_reg(s->reserved_regs, TCG_REG_I4); // for internal use +#endif tcg_regset_set_reg(s->reserved_regs, TCG_REG_I5); // for internal use tcg_regset_set_reg(s->reserved_regs, TCG_REG_I6); tcg_regset_set_reg(s->reserved_regs, TCG_REG_I7); -- cgit v1.2.3 From d643ccca01d1c23191e37ed852beadfa1f94c77f Mon Sep 17 00:00:00 2001 From: bellard Date: Mon, 7 Jul 2008 20:15:54 +0000 Subject: 64 bit signed comparison fix (Juergen Lock) git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4855 c046a42c-6fe2-441c-8c8c-71466251a162 --- tcg/i386/tcg-target.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index cf453b3e4..a7bd74861 100644 --- a/tcg/i386/tcg-target.c +++ b/tcg/i386/tcg-target.c @@ -360,22 +360,22 @@ static void tcg_out_brcond2(TCGContext *s, case TCG_COND_LT: tcg_out_brcond(s, TCG_COND_LT, args[1], args[3], const_args[3], args[5]); tcg_out_jxx(s, JCC_JNE, label_next); - tcg_out_brcond(s, TCG_COND_LT, args[0], args[2], const_args[2], args[5]); + tcg_out_brcond(s, TCG_COND_LTU, args[0], args[2], const_args[2], args[5]); break; case TCG_COND_LE: tcg_out_brcond(s, TCG_COND_LT, args[1], args[3], const_args[3], args[5]); tcg_out_jxx(s, JCC_JNE, label_next); - tcg_out_brcond(s, TCG_COND_LE, args[0], args[2], const_args[2], args[5]); + tcg_out_brcond(s, TCG_COND_LEU, args[0], args[2], const_args[2], args[5]); break; case TCG_COND_GT: tcg_out_brcond(s, TCG_COND_GT, args[1], args[3], const_args[3], args[5]); tcg_out_jxx(s, JCC_JNE, label_next); - tcg_out_brcond(s, TCG_COND_GT, args[0], args[2], const_args[2], args[5]); + tcg_out_brcond(s, TCG_COND_GTU, args[0], args[2], const_args[2], args[5]); break; case TCG_COND_GE: tcg_out_brcond(s, TCG_COND_GT, args[1], args[3], const_args[3], args[5]); tcg_out_jxx(s, JCC_JNE, label_next); - tcg_out_brcond(s, TCG_COND_GE, args[0], args[2], const_args[2], args[5]); + tcg_out_brcond(s, TCG_COND_GEU, args[0], args[2], const_args[2], args[5]); break; case TCG_COND_LTU: tcg_out_brcond(s, TCG_COND_LTU, args[1], args[3], const_args[3], args[5]); -- cgit v1.2.3 From 28e1071183b2bfd27628b7dc1600cf9a3556a6ce Mon Sep 17 00:00:00 2001 From: bellard Date: Mon, 7 Jul 2008 20:25:41 +0000 Subject: fix cvtsq2s[sd] (Juergen Lock) git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4856 c046a42c-6fe2-441c-8c8c-71466251a162 --- target-i386/translate.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/target-i386/translate.c b/target-i386/translate.c index bfb2801d2..7dc317171 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -3340,8 +3340,12 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) op1_offset = offsetof(CPUX86State,xmm_regs[reg]); tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); sse_op2 = sse_op_table3[(s->dflag == 2) * 2 + ((b >> 8) - 2)]; - tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); - tcg_gen_helper_0_2(sse_op2, cpu_ptr0, cpu_tmp2_i32); + if (ot == OT_LONG) { + tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); + tcg_gen_helper_0_2(sse_op2, cpu_ptr0, cpu_tmp2_i32); + } else { + tcg_gen_helper_0_2(sse_op2, cpu_ptr0, cpu_T[0]); + } break; case 0x02c: /* cvttps2pi */ case 0x12c: /* cvttpd2pi */ -- cgit v1.2.3 From b115bb3febe985bbc81d4dcfd82966fe94c54277 Mon Sep 17 00:00:00 2001 From: pbrook Date: Mon, 7 Jul 2008 23:01:25 +0000 Subject: Eliminate spurous screen updates. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4857 c046a42c-6fe2-441c-8c8c-71466251a162 --- hw/ssd0303.c | 94 ++++++++++++++++++++++++------------------------ hw/ssd0323.c | 114 ++++++++++++++++++++++++++++++----------------------------- 2 files changed, 106 insertions(+), 102 deletions(-) diff --git a/hw/ssd0303.c b/hw/ssd0303.c index 7f0323768..b0b099f0d 100644 --- a/hw/ssd0303.c +++ b/hw/ssd0303.c @@ -203,55 +203,57 @@ static void ssd0303_update_display(void *opaque) int dest_width; uint8_t mask; - if (s->redraw) { - switch (s->ds->depth) { - case 0: - return; - case 15: - dest_width = 2; - break; - case 16: - dest_width = 2; - break; - case 24: - dest_width = 3; - break; - case 32: - dest_width = 4; - break; - default: - BADF("Bad color depth\n"); - return; - } - dest_width *= MAGNIFY; - memset(colortab, 0xff, dest_width); - memset(colortab + dest_width, 0, dest_width); - if (s->flash) { - colors[0] = colortab; - colors[1] = colortab; - } else if (s->inverse) { - colors[0] = colortab; - colors[1] = colortab + dest_width; - } else { - colors[0] = colortab + dest_width; - colors[1] = colortab; + if (!s->redraw) + return; + + switch (s->ds->depth) { + case 0: + return; + case 15: + dest_width = 2; + break; + case 16: + dest_width = 2; + break; + case 24: + dest_width = 3; + break; + case 32: + dest_width = 4; + break; + default: + BADF("Bad color depth\n"); + return; + } + dest_width *= MAGNIFY; + memset(colortab, 0xff, dest_width); + memset(colortab + dest_width, 0, dest_width); + if (s->flash) { + colors[0] = colortab; + colors[1] = colortab; + } else if (s->inverse) { + colors[0] = colortab; + colors[1] = colortab + dest_width; + } else { + colors[0] = colortab + dest_width; + colors[1] = colortab; + } + dest = s->ds->data; + for (y = 0; y < 16; y++) { + line = (y + s->start_line) & 63; + src = s->framebuffer + 132 * (line >> 3) + 36; + mask = 1 << (line & 7); + for (x = 0; x < 96; x++) { + memcpy(dest, colors[(*src & mask) != 0], dest_width); + dest += dest_width; + src++; } - dest = s->ds->data; - for (y = 0; y < 16; y++) { - line = (y + s->start_line) & 63; - src = s->framebuffer + 132 * (line >> 3) + 36; - mask = 1 << (line & 7); - for (x = 0; x < 96; x++) { - memcpy(dest, colors[(*src & mask) != 0], dest_width); - dest += dest_width; - src++; - } - for (x = 1; x < MAGNIFY; x++) { - memcpy(dest, dest - dest_width * 96, dest_width * 96); - dest += dest_width * 96; - } + for (x = 1; x < MAGNIFY; x++) { + memcpy(dest, dest - dest_width * 96, dest_width * 96); + dest += dest_width * 96; } } + s->redraw = 0; dpy_update(s->ds, 0, 0, 96 * MAGNIFY, 16 * MAGNIFY); } diff --git a/hw/ssd0323.c b/hw/ssd0323.c index 11afca0c6..e496fe784 100644 --- a/hw/ssd0323.c +++ b/hw/ssd0323.c @@ -184,78 +184,80 @@ static void ssd0323_update_display(void *opaque) char *p; int dest_width; - if (s->redraw) { + if (!s->redraw) + return; + + switch (s->ds->depth) { + case 0: + return; + case 15: + dest_width = 2; + break; + case 16: + dest_width = 2; + break; + case 24: + dest_width = 3; + break; + case 32: + dest_width = 4; + break; + default: + BADF("Bad color depth\n"); + return; + } + p = colortab; + for (i = 0; i < 16; i++) { + int n; + colors[i] = p; switch (s->ds->depth) { - case 0: - return; case 15: - dest_width = 2; + n = i * 2 + (i >> 3); + p[0] = n | (n << 5); + p[1] = (n << 2) | (n >> 3); break; case 16: - dest_width = 2; + n = i * 2 + (i >> 3); + p[0] = n | (n << 6) | ((n << 1) & 0x20); + p[1] = (n << 3) | (n >> 2); break; case 24: - dest_width = 3; - break; case 32: - dest_width = 4; + n = (i << 4) | i; + p[0] = p[1] = p[2] = n; break; default: BADF("Bad color depth\n"); return; } - p = colortab; - for (i = 0; i < 16; i++) { - int n; - colors[i] = p; - switch (s->ds->depth) { - case 15: - n = i * 2 + (i >> 3); - p[0] = n | (n << 5); - p[1] = (n << 2) | (n >> 3); - break; - case 16: - n = i * 2 + (i >> 3); - p[0] = n | (n << 6) | ((n << 1) & 0x20); - p[1] = (n << 3) | (n >> 2); - break; - case 24: - case 32: - n = (i << 4) | i; - p[0] = p[1] = p[2] = n; - break; - default: - BADF("Bad color depth\n"); - return; - } - p += dest_width; - } - /* TODO: Implement row/column remapping. */ - dest = s->ds->data; - for (y = 0; y < 64; y++) { - line = y; - src = s->framebuffer + 64 * line; - for (x = 0; x < 64; x++) { - int val; - val = *src >> 4; - for (i = 0; i < MAGNIFY; i++) { - memcpy(dest, colors[val], dest_width); - dest += dest_width; - } - val = *src & 0xf; - for (i = 0; i < MAGNIFY; i++) { - memcpy(dest, colors[val], dest_width); - dest += dest_width; - } - src++; + p += dest_width; + } + /* TODO: Implement row/column remapping. */ + dest = s->ds->data; + for (y = 0; y < 64; y++) { + line = y; + src = s->framebuffer + 64 * line; + for (x = 0; x < 64; x++) { + int val; + val = *src >> 4; + for (i = 0; i < MAGNIFY; i++) { + memcpy(dest, colors[val], dest_width); + dest += dest_width; } - for (i = 1; i < MAGNIFY; i++) { - memcpy(dest, dest - dest_width * MAGNIFY * 128, - dest_width * 128 * MAGNIFY); - dest += dest_width * 128 * MAGNIFY; + val = *src & 0xf; + for (i = 0; i < MAGNIFY; i++) { + memcpy(dest, colors[val], dest_width); + dest += dest_width; } + src++; + } + for (i = 1; i < MAGNIFY; i++) { + memcpy(dest, dest - dest_width * MAGNIFY * 128, + dest_width * 128 * MAGNIFY); + dest += dest_width * 128 * MAGNIFY; } } + s->redraw = 0; dpy_update(s->ds, 0, 0, 128 * MAGNIFY, 64 * MAGNIFY); } -- cgit v1.2.3 From f7350b47dab4b2c84b67fa8cc003494b3ef7a032 Mon Sep 17 00:00:00 2001 From: blueswir1 Date: Tue, 8 Jul 2008 15:51:32 +0000 Subject: Implement some Ultrasparc cache ASIs used by SILO git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4858 c046a42c-6fe2-441c-8c8c-71466251a162 --- target-sparc/op_helper.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c index f15cc224b..54db5f4e4 100644 --- a/target-sparc/op_helper.c +++ b/target-sparc/op_helper.c @@ -1687,6 +1687,16 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) } break; } + case 0x46: // D-cache data + case 0x47: // D-cache tag access + case 0x4e: // E-cache tag data + case 0x66: // I-cache instruction access + case 0x67: // I-cache tag access + case 0x6e: // I-cache predecode + case 0x6f: // I-cache LRU etc. + case 0x76: // E-cache tag + case 0x7e: // E-cache tag + break; case 0x59: // D-MMU 8k TSB pointer case 0x5a: // D-MMU 64k TSB pointer case 0x5b: // D-MMU data pointer @@ -2040,6 +2050,16 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size) case 0x49: // Interrupt data receive // XXX return; + case 0x46: // D-cache data + case 0x47: // D-cache tag access + case 0x4e: // E-cache tag data + case 0x66: // I-cache instruction access + case 0x67: // I-cache tag access + case 0x6e: // I-cache predecode + case 0x6f: // I-cache LRU etc. + case 0x76: // E-cache tag + case 0x7e: // E-cache tag + return; case 0x51: // I-MMU 8k TSB pointer, RO case 0x52: // I-MMU 64k TSB pointer, RO case 0x56: // I-MMU tag read, RO -- cgit v1.2.3 From 48bbf11bcb6c5d95a281c025a13836c6fa699feb Mon Sep 17 00:00:00 2001 From: blueswir1 Date: Tue, 8 Jul 2008 18:35:02 +0000 Subject: Fix r4641 (invalid token "=<" in a preprocessor expression) git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4859 c046a42c-6fe2-441c-8c8c-71466251a162 --- cpu-exec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpu-exec.c b/cpu-exec.c index 8cc723d35..44a92ac33 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -1359,7 +1359,7 @@ int cpu_signal_handler(int host_signum, void *pinfo, unsigned long pc; int is_write; -#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ =< 3)) +#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) pc = uc->uc_mcontext.gregs[R15]; #else pc = uc->uc_mcontext.arm_pc; -- cgit v1.2.3 From bd5921b43222acc511aada131882f284333ef16b Mon Sep 17 00:00:00 2001 From: malc Date: Tue, 8 Jul 2008 18:57:05 +0000 Subject: Fix typo git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4860 c046a42c-6fe2-441c-8c8c-71466251a162 --- block-nbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block-nbd.c b/block-nbd.c index f35005015..88b61999f 100644 --- a/block-nbd.c +++ b/block-nbd.c @@ -2,7 +2,7 @@ * QEMU Block driver for NBD * * Copyright (C) 2008 Bull S.A.S. - * Author: Laurent Vivier + * Author: Laurent Vivier * * Some parts: * Copyright (C) 2007 Anthony Liguori -- cgit v1.2.3 From b6d96beda3a6cbf20a2d04a609eff78adebd8859 Mon Sep 17 00:00:00 2001 From: ths Date: Wed, 9 Jul 2008 11:05:10 +0000 Subject: Use temporary registers for the MIPS FPU emulation. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4861 c046a42c-6fe2-441c-8c8c-71466251a162 --- target-mips/cpu.h | 8 +- target-mips/exec.h | 23 - target-mips/helper.h | 106 +-- target-mips/op_helper.c | 980 +++++++++++++++++---------- target-mips/translate.c | 1716 ++++++++++++++++++++++++++++++++--------------- 5 files changed, 1849 insertions(+), 984 deletions(-) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index e747bc888..3ec867a72 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -171,20 +171,14 @@ typedef struct CPUMIPSState CPUMIPSState; struct CPUMIPSState { TCState active_tc; - /* temporary hack for FP globals */ -#ifndef USE_HOST_FLOAT_REGS - fpr_t ft0; - fpr_t ft1; - fpr_t ft2; -#endif CPUMIPSMVPContext *mvp; CPUMIPSTLBContext *tlb; CPUMIPSFPUContext *fpu; uint32_t current_tc; uint32_t SEGBITS; - target_ulong SEGMask; uint32_t PABITS; + target_ulong SEGMask; target_ulong PAMask; int32_t CP0_Index; diff --git a/target-mips/exec.h b/target-mips/exec.h index a7014eea1..8600e79c5 100644 --- a/target-mips/exec.h +++ b/target-mips/exec.h @@ -10,29 +10,6 @@ register struct CPUMIPSState *env asm(AREG0); -#if defined (USE_HOST_FLOAT_REGS) -#error "implement me." -#else -#define FDT0 (env->ft0.fd) -#define FDT1 (env->ft1.fd) -#define FDT2 (env->ft2.fd) -#define FST0 (env->ft0.fs[FP_ENDIAN_IDX]) -#define FST1 (env->ft1.fs[FP_ENDIAN_IDX]) -#define FST2 (env->ft2.fs[FP_ENDIAN_IDX]) -#define FSTH0 (env->ft0.fs[!FP_ENDIAN_IDX]) -#define FSTH1 (env->ft1.fs[!FP_ENDIAN_IDX]) -#define FSTH2 (env->ft2.fs[!FP_ENDIAN_IDX]) -#define DT0 (env->ft0.d) -#define DT1 (env->ft1.d) -#define DT2 (env->ft2.d) -#define WT0 (env->ft0.w[FP_ENDIAN_IDX]) -#define WT1 (env->ft1.w[FP_ENDIAN_IDX]) -#define WT2 (env->ft2.w[FP_ENDIAN_IDX]) -#define WTH0 (env->ft0.w[!FP_ENDIAN_IDX]) -#define WTH1 (env->ft1.w[!FP_ENDIAN_IDX]) -#define WTH2 (env->ft2.w[!FP_ENDIAN_IDX]) -#endif - #include "cpu.h" #include "exec-all.h" diff --git a/target-mips/helper.h b/target-mips/helper.h index 7dfc25958..9d4ca82c5 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -159,67 +159,85 @@ DEF_HELPER(target_ulong, do_yield, (target_ulong t0)) DEF_HELPER(target_ulong, do_cfc1, (uint32_t reg)) DEF_HELPER(void, do_ctc1, (target_ulong t0, uint32_t reg)) -DEF_HELPER(void, do_float_cvtd_s, (void)) -DEF_HELPER(void, do_float_cvtd_w, (void)) -DEF_HELPER(void, do_float_cvtd_l, (void)) -DEF_HELPER(void, do_float_cvtl_d, (void)) -DEF_HELPER(void, do_float_cvtl_s, (void)) -DEF_HELPER(void, do_float_cvtps_pw, (void)) -DEF_HELPER(void, do_float_cvtpw_ps, (void)) -DEF_HELPER(void, do_float_cvts_d, (void)) -DEF_HELPER(void, do_float_cvts_w, (void)) -DEF_HELPER(void, do_float_cvts_l, (void)) -DEF_HELPER(void, do_float_cvts_pl, (void)) -DEF_HELPER(void, do_float_cvts_pu, (void)) -DEF_HELPER(void, do_float_cvtw_s, (void)) -DEF_HELPER(void, do_float_cvtw_d, (void)) +DEF_HELPER(uint64_t, do_float_cvtd_s, (uint32_t fst0)) +DEF_HELPER(uint64_t, do_float_cvtd_w, (uint32_t wt0)) +DEF_HELPER(uint64_t, do_float_cvtd_l, (uint64_t dt0)) +DEF_HELPER(uint64_t, do_float_cvtl_d, (uint64_t fd0)) +DEF_HELPER(uint64_t, do_float_cvtl_s, (uint32_t fst0)) +DEF_HELPER(uint64_t, do_float_cvtps_pw, (uint64_t dt0)) +DEF_HELPER(uint64_t, do_float_cvtpw_ps, (uint64_t fdt0)) +DEF_HELPER(uint32_t, do_float_cvts_d, (uint64_t fd0)) +DEF_HELPER(uint32_t, do_float_cvts_w, (uint32_t wt0)) +DEF_HELPER(uint32_t, do_float_cvts_l, (uint64_t dt0)) +DEF_HELPER(uint32_t, do_float_cvts_pl, (uint32_t wt0)) +DEF_HELPER(uint32_t, do_float_cvts_pu, (uint32_t wth0)) +DEF_HELPER(uint32_t, do_float_cvtw_s, (uint32_t fst0)) +DEF_HELPER(uint32_t, do_float_cvtw_d, (uint64_t fd0)) -DEF_HELPER(void, do_float_addr_ps, (void)) -DEF_HELPER(void, do_float_mulr_ps, (void)) +DEF_HELPER(uint64_t, do_float_addr_ps, (uint64_t fdt0, uint64_t fdt1)) +DEF_HELPER(uint64_t, do_float_mulr_ps, (uint64_t fdt0, uint64_t fdt1)) -#define FOP_PROTO(op) \ -DEF_HELPER(void, do_float_ ## op ## _s, (void)) \ -DEF_HELPER(void, do_float_ ## op ## _d, (void)) +#define FOP_PROTO(op) \ +DEF_HELPER(uint64_t, do_float_ ## op ## l_s, (uint32_t fst0)) \ +DEF_HELPER(uint64_t, do_float_ ## op ## l_d, (uint64_t fdt0)) \ +DEF_HELPER(uint32_t, do_float_ ## op ## w_s, (uint32_t fst0)) \ +DEF_HELPER(uint32_t, do_float_ ## op ## w_d, (uint64_t fdt0)) +FOP_PROTO(round) +FOP_PROTO(trunc) +FOP_PROTO(ceil) +FOP_PROTO(floor) +#undef FOP_PROTO + +#define FOP_PROTO(op) \ +DEF_HELPER(uint32_t, do_float_ ## op ## _s, (uint32_t fst0)) \ +DEF_HELPER(uint64_t, do_float_ ## op ## _d, (uint64_t fdt0)) FOP_PROTO(sqrt) -FOP_PROTO(roundl) -FOP_PROTO(roundw) -FOP_PROTO(truncl) -FOP_PROTO(truncw) -FOP_PROTO(ceill) -FOP_PROTO(ceilw) -FOP_PROTO(floorl) -FOP_PROTO(floorw) FOP_PROTO(rsqrt) FOP_PROTO(recip) #undef FOP_PROTO -#define FOP_PROTO(op) \ -DEF_HELPER(void, do_float_ ## op ## _s, (void)) \ -DEF_HELPER(void, do_float_ ## op ## _d, (void)) \ -DEF_HELPER(void, do_float_ ## op ## _ps, (void)) +#define FOP_PROTO(op) \ +DEF_HELPER(uint32_t, do_float_ ## op ## _s, (uint32_t fst0)) \ +DEF_HELPER(uint64_t, do_float_ ## op ## _d, (uint64_t fdt0)) \ +DEF_HELPER(uint64_t, do_float_ ## op ## _ps, (uint64_t fdt0)) +FOP_PROTO(abs) +FOP_PROTO(chs) +FOP_PROTO(recip1) +FOP_PROTO(rsqrt1) +#undef FOP_PROTO + +#define FOP_PROTO(op) \ +DEF_HELPER(uint32_t, do_float_ ## op ## _s, (uint32_t fst0, uint32_t fst2)) \ +DEF_HELPER(uint64_t, do_float_ ## op ## _d, (uint64_t fdt0, uint64_t fdt2)) \ +DEF_HELPER(uint64_t, do_float_ ## op ## _ps, (uint64_t fdt0, uint64_t fdt2)) FOP_PROTO(add) FOP_PROTO(sub) FOP_PROTO(mul) FOP_PROTO(div) -FOP_PROTO(abs) -FOP_PROTO(chs) +FOP_PROTO(recip2) +FOP_PROTO(rsqrt2) +#undef FOP_PROTO + +#define FOP_PROTO(op) \ +DEF_HELPER(uint32_t, do_float_ ## op ## _s, (uint32_t fst0, uint32_t fst1, \ + uint32_t fst2)) \ +DEF_HELPER(uint64_t, do_float_ ## op ## _d, (uint64_t fdt0, uint64_t fdt1, \ + uint64_t fdt2)) \ +DEF_HELPER(uint64_t, do_float_ ## op ## _ps, (uint64_t fdt0, uint64_t fdt1, \ + uint64_t fdt2)) FOP_PROTO(muladd) FOP_PROTO(mulsub) FOP_PROTO(nmuladd) FOP_PROTO(nmulsub) -FOP_PROTO(recip1) -FOP_PROTO(recip2) -FOP_PROTO(rsqrt1) -FOP_PROTO(rsqrt2) #undef FOP_PROTO -#define FOP_PROTO(op) \ -DEF_HELPER(void, do_cmp_d_ ## op, (long cc)) \ -DEF_HELPER(void, do_cmpabs_d_ ## op, (long cc)) \ -DEF_HELPER(void, do_cmp_s_ ## op, (long cc)) \ -DEF_HELPER(void, do_cmpabs_s_ ## op, (long cc)) \ -DEF_HELPER(void, do_cmp_ps_ ## op, (long cc)) \ -DEF_HELPER(void, do_cmpabs_ps_ ## op, (long cc)) +#define FOP_PROTO(op) \ +DEF_HELPER(void, do_cmp_d_ ## op, (uint64_t fdt0, uint64_t fdt1, int cc)) \ +DEF_HELPER(void, do_cmpabs_d_ ## op, (uint64_t fdt0, uint64_t fdt1, int cc)) \ +DEF_HELPER(void, do_cmp_s_ ## op, (uint32_t fst0, uint32_t fst1, int cc)) \ +DEF_HELPER(void, do_cmpabs_s_ ## op, (uint32_t fst0, uint32_t fst1, int cc)) \ +DEF_HELPER(void, do_cmp_ps_ ## op, (uint64_t fdt0, uint64_t fdt1, int cc)) \ +DEF_HELPER(void, do_cmpabs_ps_ ## op, (uint64_t fdt0, uint64_t fdt1, int cc)) FOP_PROTO(f) FOP_PROTO(un) FOP_PROTO(eq) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 309856344..008fb2c0b 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -2121,380 +2121,555 @@ static always_inline void update_fcr31(void) "d" suffix, 32bit integer "w", 64bit integer "l", paired single "ps", paired single lower "pl", paired single upper "pu". */ -#define FLOAT_OP(name, p) void do_float_##name##_##p(void) - /* unary operations, modifying fp status */ -#define FLOAT_UNOP(name) \ -FLOAT_OP(name, d) \ -{ \ - FDT2 = float64_ ## name(FDT0, &env->fpu->fp_status); \ -} \ -FLOAT_OP(name, s) \ -{ \ - FST2 = float32_ ## name(FST0, &env->fpu->fp_status); \ -} -FLOAT_UNOP(sqrt) -#undef FLOAT_UNOP +uint64_t do_float_sqrt_d(uint64_t fdt0) +{ + return float64_sqrt(fdt0, &env->fpu->fp_status); +} + +uint32_t do_float_sqrt_s(uint32_t fst0) +{ + return float32_sqrt(fst0, &env->fpu->fp_status); +} -FLOAT_OP(cvtd, s) +uint64_t do_float_cvtd_s(uint32_t fst0) { + uint64_t fdt2; + set_float_exception_flags(0, &env->fpu->fp_status); - FDT2 = float32_to_float64(FST0, &env->fpu->fp_status); + fdt2 = float32_to_float64(fst0, &env->fpu->fp_status); update_fcr31(); + return fdt2; } -FLOAT_OP(cvtd, w) + +uint64_t do_float_cvtd_w(uint32_t wt0) { + uint64_t fdt2; + set_float_exception_flags(0, &env->fpu->fp_status); - FDT2 = int32_to_float64(WT0, &env->fpu->fp_status); + fdt2 = int32_to_float64(wt0, &env->fpu->fp_status); update_fcr31(); + return fdt2; } -FLOAT_OP(cvtd, l) + +uint64_t do_float_cvtd_l(uint64_t dt0) { + uint64_t fdt2; + set_float_exception_flags(0, &env->fpu->fp_status); - FDT2 = int64_to_float64(DT0, &env->fpu->fp_status); + fdt2 = int64_to_float64(dt0, &env->fpu->fp_status); update_fcr31(); + return fdt2; } -FLOAT_OP(cvtl, d) + +uint64_t do_float_cvtl_d(uint64_t fdt0) { + uint64_t dt2; + set_float_exception_flags(0, &env->fpu->fp_status); - DT2 = float64_to_int64(FDT0, &env->fpu->fp_status); + dt2 = float64_to_int64(fdt0, &env->fpu->fp_status); update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) - DT2 = FLOAT_SNAN64; + dt2 = FLOAT_SNAN64; + return dt2; } -FLOAT_OP(cvtl, s) + +uint64_t do_float_cvtl_s(uint32_t fst0) { + uint64_t dt2; + set_float_exception_flags(0, &env->fpu->fp_status); - DT2 = float32_to_int64(FST0, &env->fpu->fp_status); + dt2 = float32_to_int64(fst0, &env->fpu->fp_status); update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) - DT2 = FLOAT_SNAN64; + dt2 = FLOAT_SNAN64; + return dt2; } -FLOAT_OP(cvtps, pw) +uint64_t do_float_cvtps_pw(uint64_t dt0) { + uint32_t fst2; + uint32_t fsth2; + set_float_exception_flags(0, &env->fpu->fp_status); - FST2 = int32_to_float32(WT0, &env->fpu->fp_status); - FSTH2 = int32_to_float32(WTH0, &env->fpu->fp_status); + fst2 = int32_to_float32(dt0 & 0XFFFFFFFF, &env->fpu->fp_status); + fsth2 = int32_to_float32(dt0 >> 32, &env->fpu->fp_status); update_fcr31(); + return ((uint64_t)fsth2 << 32) | fst2; } -FLOAT_OP(cvtpw, ps) + +uint64_t do_float_cvtpw_ps(uint64_t fdt0) { + uint32_t wt2; + uint32_t wth2; + set_float_exception_flags(0, &env->fpu->fp_status); - WT2 = float32_to_int32(FST0, &env->fpu->fp_status); - WTH2 = float32_to_int32(FSTH0, &env->fpu->fp_status); + wt2 = float32_to_int32(fdt0 & 0XFFFFFFFF, &env->fpu->fp_status); + wth2 = float32_to_int32(fdt0 >> 32, &env->fpu->fp_status); update_fcr31(); - if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) - WT2 = FLOAT_SNAN32; + if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) { + wt2 = FLOAT_SNAN32; + wth2 = FLOAT_SNAN32; + } + return ((uint64_t)wth2 << 32) | wt2; } -FLOAT_OP(cvts, d) + +uint32_t do_float_cvts_d(uint64_t fdt0) { + uint32_t fst2; + set_float_exception_flags(0, &env->fpu->fp_status); - FST2 = float64_to_float32(FDT0, &env->fpu->fp_status); + fst2 = float64_to_float32(fdt0, &env->fpu->fp_status); update_fcr31(); + return fst2; } -FLOAT_OP(cvts, w) + +uint32_t do_float_cvts_w(uint32_t wt0) { + uint32_t fst2; + set_float_exception_flags(0, &env->fpu->fp_status); - FST2 = int32_to_float32(WT0, &env->fpu->fp_status); + fst2 = int32_to_float32(wt0, &env->fpu->fp_status); update_fcr31(); + return fst2; } -FLOAT_OP(cvts, l) + +uint32_t do_float_cvts_l(uint64_t dt0) { + uint32_t fst2; + set_float_exception_flags(0, &env->fpu->fp_status); - FST2 = int64_to_float32(DT0, &env->fpu->fp_status); + fst2 = int64_to_float32(dt0, &env->fpu->fp_status); update_fcr31(); + return fst2; } -FLOAT_OP(cvts, pl) + +uint32_t do_float_cvts_pl(uint32_t wt0) { + uint32_t wt2; + set_float_exception_flags(0, &env->fpu->fp_status); - WT2 = WT0; + wt2 = wt0; update_fcr31(); + return wt2; } -FLOAT_OP(cvts, pu) + +uint32_t do_float_cvts_pu(uint32_t wth0) { + uint32_t wt2; + set_float_exception_flags(0, &env->fpu->fp_status); - WT2 = WTH0; + wt2 = wth0; update_fcr31(); + return wt2; } -FLOAT_OP(cvtw, s) + +uint32_t do_float_cvtw_s(uint32_t fst0) { + uint32_t wt2; + set_float_exception_flags(0, &env->fpu->fp_status); - WT2 = float32_to_int32(FST0, &env->fpu->fp_status); + wt2 = float32_to_int32(fst0, &env->fpu->fp_status); update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) - WT2 = FLOAT_SNAN32; + wt2 = FLOAT_SNAN32; + return wt2; } -FLOAT_OP(cvtw, d) + +uint32_t do_float_cvtw_d(uint64_t fdt0) { + uint32_t wt2; + set_float_exception_flags(0, &env->fpu->fp_status); - WT2 = float64_to_int32(FDT0, &env->fpu->fp_status); + wt2 = float64_to_int32(fdt0, &env->fpu->fp_status); update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) - WT2 = FLOAT_SNAN32; + wt2 = FLOAT_SNAN32; + return wt2; } -FLOAT_OP(roundl, d) +uint64_t do_float_roundl_d(uint64_t fdt0) { + uint64_t dt2; + set_float_rounding_mode(float_round_nearest_even, &env->fpu->fp_status); - DT2 = float64_to_int64(FDT0, &env->fpu->fp_status); + dt2 = float64_to_int64(fdt0, &env->fpu->fp_status); RESTORE_ROUNDING_MODE; update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) - DT2 = FLOAT_SNAN64; + dt2 = FLOAT_SNAN64; + return dt2; } -FLOAT_OP(roundl, s) + +uint64_t do_float_roundl_s(uint32_t fst0) { + uint64_t dt2; + set_float_rounding_mode(float_round_nearest_even, &env->fpu->fp_status); - DT2 = float32_to_int64(FST0, &env->fpu->fp_status); + dt2 = float32_to_int64(fst0, &env->fpu->fp_status); RESTORE_ROUNDING_MODE; update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) - DT2 = FLOAT_SNAN64; + dt2 = FLOAT_SNAN64; + return dt2; } -FLOAT_OP(roundw, d) + +uint32_t do_float_roundw_d(uint64_t fdt0) { + uint32_t wt2; + set_float_rounding_mode(float_round_nearest_even, &env->fpu->fp_status); - WT2 = float64_to_int32(FDT0, &env->fpu->fp_status); + wt2 = float64_to_int32(fdt0, &env->fpu->fp_status); RESTORE_ROUNDING_MODE; update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) - WT2 = FLOAT_SNAN32; + wt2 = FLOAT_SNAN32; + return wt2; } -FLOAT_OP(roundw, s) + +uint32_t do_float_roundw_s(uint32_t fst0) { + uint32_t wt2; + set_float_rounding_mode(float_round_nearest_even, &env->fpu->fp_status); - WT2 = float32_to_int32(FST0, &env->fpu->fp_status); + wt2 = float32_to_int32(fst0, &env->fpu->fp_status); RESTORE_ROUNDING_MODE; update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) - WT2 = FLOAT_SNAN32; + wt2 = FLOAT_SNAN32; + return wt2; } -FLOAT_OP(truncl, d) +uint64_t do_float_truncl_d(uint64_t fdt0) { - DT2 = float64_to_int64_round_to_zero(FDT0, &env->fpu->fp_status); + uint64_t dt2; + + dt2 = float64_to_int64_round_to_zero(fdt0, &env->fpu->fp_status); update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) - DT2 = FLOAT_SNAN64; + dt2 = FLOAT_SNAN64; + return dt2; } -FLOAT_OP(truncl, s) + +uint64_t do_float_truncl_s(uint32_t fst0) { - DT2 = float32_to_int64_round_to_zero(FST0, &env->fpu->fp_status); + uint64_t dt2; + + dt2 = float32_to_int64_round_to_zero(fst0, &env->fpu->fp_status); update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) - DT2 = FLOAT_SNAN64; + dt2 = FLOAT_SNAN64; + return dt2; } -FLOAT_OP(truncw, d) + +uint32_t do_float_truncw_d(uint64_t fdt0) { - WT2 = float64_to_int32_round_to_zero(FDT0, &env->fpu->fp_status); + uint32_t wt2; + + wt2 = float64_to_int32_round_to_zero(fdt0, &env->fpu->fp_status); update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) - WT2 = FLOAT_SNAN32; + wt2 = FLOAT_SNAN32; + return wt2; } -FLOAT_OP(truncw, s) + +uint32_t do_float_truncw_s(uint32_t fst0) { - WT2 = float32_to_int32_round_to_zero(FST0, &env->fpu->fp_status); + uint32_t wt2; + + wt2 = float32_to_int32_round_to_zero(fst0, &env->fpu->fp_status); update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) - WT2 = FLOAT_SNAN32; + wt2 = FLOAT_SNAN32; + return wt2; } -FLOAT_OP(ceill, d) +uint64_t do_float_ceill_d(uint64_t fdt0) { + uint64_t dt2; + set_float_rounding_mode(float_round_up, &env->fpu->fp_status); - DT2 = float64_to_int64(FDT0, &env->fpu->fp_status); + dt2 = float64_to_int64(fdt0, &env->fpu->fp_status); RESTORE_ROUNDING_MODE; update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) - DT2 = FLOAT_SNAN64; + dt2 = FLOAT_SNAN64; + return dt2; } -FLOAT_OP(ceill, s) + +uint64_t do_float_ceill_s(uint32_t fst0) { + uint64_t dt2; + set_float_rounding_mode(float_round_up, &env->fpu->fp_status); - DT2 = float32_to_int64(FST0, &env->fpu->fp_status); + dt2 = float32_to_int64(fst0, &env->fpu->fp_status); RESTORE_ROUNDING_MODE; update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) - DT2 = FLOAT_SNAN64; + dt2 = FLOAT_SNAN64; + return dt2; } -FLOAT_OP(ceilw, d) + +uint32_t do_float_ceilw_d(uint64_t fdt0) { + uint32_t wt2; + set_float_rounding_mode(float_round_up, &env->fpu->fp_status); - WT2 = float64_to_int32(FDT0, &env->fpu->fp_status); + wt2 = float64_to_int32(fdt0, &env->fpu->fp_status); RESTORE_ROUNDING_MODE; update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) - WT2 = FLOAT_SNAN32; + wt2 = FLOAT_SNAN32; + return wt2; } -FLOAT_OP(ceilw, s) + +uint32_t do_float_ceilw_s(uint32_t fst0) { + uint32_t wt2; + set_float_rounding_mode(float_round_up, &env->fpu->fp_status); - WT2 = float32_to_int32(FST0, &env->fpu->fp_status); + wt2 = float32_to_int32(fst0, &env->fpu->fp_status); RESTORE_ROUNDING_MODE; update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) - WT2 = FLOAT_SNAN32; + wt2 = FLOAT_SNAN32; + return wt2; } -FLOAT_OP(floorl, d) +uint64_t do_float_floorl_d(uint64_t fdt0) { + uint64_t dt2; + set_float_rounding_mode(float_round_down, &env->fpu->fp_status); - DT2 = float64_to_int64(FDT0, &env->fpu->fp_status); + dt2 = float64_to_int64(fdt0, &env->fpu->fp_status); RESTORE_ROUNDING_MODE; update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) - DT2 = FLOAT_SNAN64; + dt2 = FLOAT_SNAN64; + return dt2; } -FLOAT_OP(floorl, s) + +uint64_t do_float_floorl_s(uint32_t fst0) { + uint64_t dt2; + set_float_rounding_mode(float_round_down, &env->fpu->fp_status); - DT2 = float32_to_int64(FST0, &env->fpu->fp_status); + dt2 = float32_to_int64(fst0, &env->fpu->fp_status); RESTORE_ROUNDING_MODE; update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) - DT2 = FLOAT_SNAN64; + dt2 = FLOAT_SNAN64; + return dt2; } -FLOAT_OP(floorw, d) + +uint32_t do_float_floorw_d(uint64_t fdt0) { + uint32_t wt2; + set_float_rounding_mode(float_round_down, &env->fpu->fp_status); - WT2 = float64_to_int32(FDT0, &env->fpu->fp_status); + wt2 = float64_to_int32(fdt0, &env->fpu->fp_status); RESTORE_ROUNDING_MODE; update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) - WT2 = FLOAT_SNAN32; + wt2 = FLOAT_SNAN32; + return wt2; } -FLOAT_OP(floorw, s) + +uint32_t do_float_floorw_s(uint32_t fst0) { + uint32_t wt2; + set_float_rounding_mode(float_round_down, &env->fpu->fp_status); - WT2 = float32_to_int32(FST0, &env->fpu->fp_status); + wt2 = float32_to_int32(fst0, &env->fpu->fp_status); RESTORE_ROUNDING_MODE; update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) - WT2 = FLOAT_SNAN32; + wt2 = FLOAT_SNAN32; + return wt2; } /* unary operations, not modifying fp status */ -#define FLOAT_UNOP(name) \ -FLOAT_OP(name, d) \ -{ \ - FDT2 = float64_ ## name(FDT0); \ -} \ -FLOAT_OP(name, s) \ -{ \ - FST2 = float32_ ## name(FST0); \ -} \ -FLOAT_OP(name, ps) \ -{ \ - FST2 = float32_ ## name(FST0); \ - FSTH2 = float32_ ## name(FSTH0); \ +#define FLOAT_UNOP(name) \ +uint64_t do_float_ ## name ## _d(uint64_t fdt0) \ +{ \ + return float64_ ## name(fdt0); \ +} \ +uint32_t do_float_ ## name ## _s(uint32_t fst0) \ +{ \ + return float32_ ## name(fst0); \ +} \ +uint64_t do_float_ ## name ## _ps(uint64_t fdt0) \ +{ \ + uint32_t wt0; \ + uint32_t wth0; \ + \ + wt0 = float32_ ## name(fdt0 & 0XFFFFFFFF); \ + wth0 = float32_ ## name(fdt0 >> 32); \ + return ((uint64_t)wth0 << 32) | wt0; \ } FLOAT_UNOP(abs) FLOAT_UNOP(chs) #undef FLOAT_UNOP /* MIPS specific unary operations */ -FLOAT_OP(recip, d) +uint64_t do_float_recip_d(uint64_t fdt0) { + uint64_t fdt2; + set_float_exception_flags(0, &env->fpu->fp_status); - FDT2 = float64_div(FLOAT_ONE64, FDT0, &env->fpu->fp_status); + fdt2 = float64_div(FLOAT_ONE64, fdt0, &env->fpu->fp_status); update_fcr31(); + return fdt2; } -FLOAT_OP(recip, s) + +uint32_t do_float_recip_s(uint32_t fst0) { + uint32_t fst2; + set_float_exception_flags(0, &env->fpu->fp_status); - FST2 = float32_div(FLOAT_ONE32, FST0, &env->fpu->fp_status); + fst2 = float32_div(FLOAT_ONE32, fst0, &env->fpu->fp_status); update_fcr31(); + return fst2; } -FLOAT_OP(rsqrt, d) +uint64_t do_float_rsqrt_d(uint64_t fdt0) { + uint64_t fdt2; + set_float_exception_flags(0, &env->fpu->fp_status); - FDT2 = float64_sqrt(FDT0, &env->fpu->fp_status); - FDT2 = float64_div(FLOAT_ONE64, FDT2, &env->fpu->fp_status); + fdt2 = float64_sqrt(fdt0, &env->fpu->fp_status); + fdt2 = float64_div(FLOAT_ONE64, fdt2, &env->fpu->fp_status); update_fcr31(); + return fdt2; } -FLOAT_OP(rsqrt, s) + +uint32_t do_float_rsqrt_s(uint32_t fst0) { + uint32_t fst2; + set_float_exception_flags(0, &env->fpu->fp_status); - FST2 = float32_sqrt(FST0, &env->fpu->fp_status); - FST2 = float32_div(FLOAT_ONE32, FST2, &env->fpu->fp_status); + fst2 = float32_sqrt(fst0, &env->fpu->fp_status); + fst2 = float32_div(FLOAT_ONE32, fst2, &env->fpu->fp_status); update_fcr31(); + return fst2; } -FLOAT_OP(recip1, d) +uint64_t do_float_recip1_d(uint64_t fdt0) { + uint64_t fdt2; + set_float_exception_flags(0, &env->fpu->fp_status); - FDT2 = float64_div(FLOAT_ONE64, FDT0, &env->fpu->fp_status); + fdt2 = float64_div(FLOAT_ONE64, fdt0, &env->fpu->fp_status); update_fcr31(); + return fdt2; } -FLOAT_OP(recip1, s) + +uint32_t do_float_recip1_s(uint32_t fst0) { + uint32_t fst2; + set_float_exception_flags(0, &env->fpu->fp_status); - FST2 = float32_div(FLOAT_ONE32, FST0, &env->fpu->fp_status); + fst2 = float32_div(FLOAT_ONE32, fst0, &env->fpu->fp_status); update_fcr31(); + return fst2; } -FLOAT_OP(recip1, ps) + +uint64_t do_float_recip1_ps(uint64_t fdt0) { + uint32_t fst2; + uint32_t fsth2; + set_float_exception_flags(0, &env->fpu->fp_status); - FST2 = float32_div(FLOAT_ONE32, FST0, &env->fpu->fp_status); - FSTH2 = float32_div(FLOAT_ONE32, FSTH0, &env->fpu->fp_status); + fst2 = float32_div(FLOAT_ONE32, fdt0 & 0XFFFFFFFF, &env->fpu->fp_status); + fsth2 = float32_div(FLOAT_ONE32, fdt0 >> 32, &env->fpu->fp_status); update_fcr31(); + return ((uint64_t)fsth2 << 32) | fst2; } -FLOAT_OP(rsqrt1, d) +uint64_t do_float_rsqrt1_d(uint64_t fdt0) { + uint64_t fdt2; + set_float_exception_flags(0, &env->fpu->fp_status); - FDT2 = float64_sqrt(FDT0, &env->fpu->fp_status); - FDT2 = float64_div(FLOAT_ONE64, FDT2, &env->fpu->fp_status); + fdt2 = float64_sqrt(fdt0, &env->fpu->fp_status); + fdt2 = float64_div(FLOAT_ONE64, fdt2, &env->fpu->fp_status); update_fcr31(); + return fdt2; } -FLOAT_OP(rsqrt1, s) + +uint32_t do_float_rsqrt1_s(uint32_t fst0) { + uint32_t fst2; + set_float_exception_flags(0, &env->fpu->fp_status); - FST2 = float32_sqrt(FST0, &env->fpu->fp_status); - FST2 = float32_div(FLOAT_ONE32, FST2, &env->fpu->fp_status); + fst2 = float32_sqrt(fst0, &env->fpu->fp_status); + fst2 = float32_div(FLOAT_ONE32, fst2, &env->fpu->fp_status); update_fcr31(); + return fst2; } -FLOAT_OP(rsqrt1, ps) + +uint64_t do_float_rsqrt1_ps(uint64_t fdt0) { + uint32_t fst2; + uint32_t fsth2; + set_float_exception_flags(0, &env->fpu->fp_status); - FST2 = float32_sqrt(FST0, &env->fpu->fp_status); - FSTH2 = float32_sqrt(FSTH0, &env->fpu->fp_status); - FST2 = float32_div(FLOAT_ONE32, FST2, &env->fpu->fp_status); - FSTH2 = float32_div(FLOAT_ONE32, FSTH2, &env->fpu->fp_status); + fst2 = float32_sqrt(fdt0 & 0XFFFFFFFF, &env->fpu->fp_status); + fsth2 = float32_sqrt(fdt0 >> 32, &env->fpu->fp_status); + fst2 = float32_div(FLOAT_ONE32, fst2, &env->fpu->fp_status); + fsth2 = float32_div(FLOAT_ONE32, fsth2, &env->fpu->fp_status); update_fcr31(); + return ((uint64_t)fsth2 << 32) | fst2; } +#define FLOAT_OP(name, p) void do_float_##name##_##p(void) + /* binary operations */ -#define FLOAT_BINOP(name) \ -FLOAT_OP(name, d) \ -{ \ +#define FLOAT_BINOP(name) \ +uint64_t do_float_ ## name ## _d(uint64_t fdt0, uint64_t fdt1) \ +{ \ + uint64_t dt2; \ + \ set_float_exception_flags(0, &env->fpu->fp_status); \ - FDT2 = float64_ ## name (FDT0, FDT1, &env->fpu->fp_status); \ + dt2 = float64_ ## name (fdt0, fdt1, &env->fpu->fp_status); \ update_fcr31(); \ if (GET_FP_CAUSE(env->fpu->fcr31) & FP_INVALID) \ - DT2 = FLOAT_QNAN64; \ -} \ -FLOAT_OP(name, s) \ -{ \ + dt2 = FLOAT_QNAN64; \ + return dt2; \ +} \ + \ +uint32_t do_float_ ## name ## _s(uint32_t fst0, uint32_t fst1) \ +{ \ + uint32_t wt2; \ + \ set_float_exception_flags(0, &env->fpu->fp_status); \ - FST2 = float32_ ## name (FST0, FST1, &env->fpu->fp_status); \ + wt2 = float32_ ## name (fst0, fst1, &env->fpu->fp_status); \ update_fcr31(); \ if (GET_FP_CAUSE(env->fpu->fcr31) & FP_INVALID) \ - WT2 = FLOAT_QNAN32; \ -} \ -FLOAT_OP(name, ps) \ -{ \ + wt2 = FLOAT_QNAN32; \ + return wt2; \ +} \ + \ +uint64_t do_float_ ## name ## _ps(uint64_t fdt0, uint64_t fdt1) \ +{ \ + uint32_t fst0 = fdt0 & 0XFFFFFFFF; \ + uint32_t fsth0 = fdt0 >> 32; \ + uint32_t fst1 = fdt1 & 0XFFFFFFFF; \ + uint32_t fsth1 = fdt1 >> 32; \ + uint32_t wt2; \ + uint32_t wth2; \ + \ set_float_exception_flags(0, &env->fpu->fp_status); \ - FST2 = float32_ ## name (FST0, FST1, &env->fpu->fp_status); \ - FSTH2 = float32_ ## name (FSTH0, FSTH1, &env->fpu->fp_status); \ - update_fcr31(); \ + wt2 = float32_ ## name (fst0, fst1, &env->fpu->fp_status); \ + wth2 = float32_ ## name (fsth0, fsth1, &env->fpu->fp_status); \ + update_fcr31(); \ if (GET_FP_CAUSE(env->fpu->fcr31) & FP_INVALID) { \ - WT2 = FLOAT_QNAN32; \ - WTH2 = FLOAT_QNAN32; \ - } \ + wt2 = FLOAT_QNAN32; \ + wth2 = FLOAT_QNAN32; \ + } \ + return ((uint64_t)wth2 << 32) | wt2; \ } + FLOAT_BINOP(add) FLOAT_BINOP(sub) FLOAT_BINOP(mul) @@ -2502,146 +2677,210 @@ FLOAT_BINOP(div) #undef FLOAT_BINOP /* ternary operations */ -#define FLOAT_TERNOP(name1, name2) \ -FLOAT_OP(name1 ## name2, d) \ -{ \ - FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status); \ - FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status); \ -} \ -FLOAT_OP(name1 ## name2, s) \ -{ \ - FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \ - FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \ -} \ -FLOAT_OP(name1 ## name2, ps) \ -{ \ - FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \ - FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \ - FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \ - FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \ +#define FLOAT_TERNOP(name1, name2) \ +uint64_t do_float_ ## name1 ## name2 ## _d(uint64_t fdt0, uint64_t fdt1, \ + uint64_t fdt2) \ +{ \ + fdt0 = float64_ ## name1 (fdt0, fdt1, &env->fpu->fp_status); \ + return float64_ ## name2 (fdt0, fdt2, &env->fpu->fp_status); \ +} \ + \ +uint32_t do_float_ ## name1 ## name2 ## _s(uint32_t fst0, uint32_t fst1, \ + uint32_t fst2) \ +{ \ + fst0 = float32_ ## name1 (fst0, fst1, &env->fpu->fp_status); \ + return float32_ ## name2 (fst0, fst2, &env->fpu->fp_status); \ +} \ + \ +uint64_t do_float_ ## name1 ## name2 ## _ps(uint64_t fdt0, uint64_t fdt1, \ + uint64_t fdt2) \ +{ \ + uint32_t fst0 = fdt0 & 0XFFFFFFFF; \ + uint32_t fsth0 = fdt0 >> 32; \ + uint32_t fst1 = fdt1 & 0XFFFFFFFF; \ + uint32_t fsth1 = fdt1 >> 32; \ + uint32_t fst2 = fdt2 & 0XFFFFFFFF; \ + uint32_t fsth2 = fdt2 >> 32; \ + \ + fst0 = float32_ ## name1 (fst0, fst1, &env->fpu->fp_status); \ + fsth0 = float32_ ## name1 (fsth0, fsth1, &env->fpu->fp_status); \ + fst2 = float32_ ## name2 (fst0, fst2, &env->fpu->fp_status); \ + fsth2 = float32_ ## name2 (fsth0, fsth2, &env->fpu->fp_status); \ + return ((uint64_t)fsth2 << 32) | fst2; \ } + FLOAT_TERNOP(mul, add) FLOAT_TERNOP(mul, sub) #undef FLOAT_TERNOP /* negated ternary operations */ -#define FLOAT_NTERNOP(name1, name2) \ -FLOAT_OP(n ## name1 ## name2, d) \ -{ \ - FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status); \ - FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status); \ - FDT2 = float64_chs(FDT2); \ -} \ -FLOAT_OP(n ## name1 ## name2, s) \ -{ \ - FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \ - FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \ - FST2 = float32_chs(FST2); \ -} \ -FLOAT_OP(n ## name1 ## name2, ps) \ -{ \ - FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \ - FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \ - FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \ - FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \ - FST2 = float32_chs(FST2); \ - FSTH2 = float32_chs(FSTH2); \ +#define FLOAT_NTERNOP(name1, name2) \ +uint64_t do_float_n ## name1 ## name2 ## _d(uint64_t fdt0, uint64_t fdt1, \ + uint64_t fdt2) \ +{ \ + fdt0 = float64_ ## name1 (fdt0, fdt1, &env->fpu->fp_status); \ + fdt2 = float64_ ## name2 (fdt0, fdt2, &env->fpu->fp_status); \ + return float64_chs(fdt2); \ +} \ + \ +uint32_t do_float_n ## name1 ## name2 ## _s(uint32_t fst0, uint32_t fst1, \ + uint32_t fst2) \ +{ \ + fst0 = float32_ ## name1 (fst0, fst1, &env->fpu->fp_status); \ + fst2 = float32_ ## name2 (fst0, fst2, &env->fpu->fp_status); \ + return float32_chs(fst2); \ +} \ + \ +uint64_t do_float_n ## name1 ## name2 ## _ps(uint64_t fdt0, uint64_t fdt1,\ + uint64_t fdt2) \ +{ \ + uint32_t fst0 = fdt0 & 0XFFFFFFFF; \ + uint32_t fsth0 = fdt0 >> 32; \ + uint32_t fst1 = fdt1 & 0XFFFFFFFF; \ + uint32_t fsth1 = fdt1 >> 32; \ + uint32_t fst2 = fdt2 & 0XFFFFFFFF; \ + uint32_t fsth2 = fdt2 >> 32; \ + \ + fst0 = float32_ ## name1 (fst0, fst1, &env->fpu->fp_status); \ + fsth0 = float32_ ## name1 (fsth0, fsth1, &env->fpu->fp_status); \ + fst2 = float32_ ## name2 (fst0, fst2, &env->fpu->fp_status); \ + fsth2 = float32_ ## name2 (fsth0, fsth2, &env->fpu->fp_status); \ + fst2 = float32_chs(fst2); \ + fsth2 = float32_chs(fsth2); \ + return ((uint64_t)fsth2 << 32) | fst2; \ } + FLOAT_NTERNOP(mul, add) FLOAT_NTERNOP(mul, sub) #undef FLOAT_NTERNOP /* MIPS specific binary operations */ -FLOAT_OP(recip2, d) +uint64_t do_float_recip2_d(uint64_t fdt0, uint64_t fdt2) { set_float_exception_flags(0, &env->fpu->fp_status); - FDT2 = float64_mul(FDT0, FDT2, &env->fpu->fp_status); - FDT2 = float64_chs(float64_sub(FDT2, FLOAT_ONE64, &env->fpu->fp_status)); + fdt2 = float64_mul(fdt0, fdt2, &env->fpu->fp_status); + fdt2 = float64_chs(float64_sub(fdt2, FLOAT_ONE64, &env->fpu->fp_status)); update_fcr31(); + return fdt2; } -FLOAT_OP(recip2, s) + +uint32_t do_float_recip2_s(uint32_t fst0, uint32_t fst2) { set_float_exception_flags(0, &env->fpu->fp_status); - FST2 = float32_mul(FST0, FST2, &env->fpu->fp_status); - FST2 = float32_chs(float32_sub(FST2, FLOAT_ONE32, &env->fpu->fp_status)); + fst2 = float32_mul(fst0, fst2, &env->fpu->fp_status); + fst2 = float32_chs(float32_sub(fst2, FLOAT_ONE32, &env->fpu->fp_status)); update_fcr31(); + return fst2; } -FLOAT_OP(recip2, ps) + +uint64_t do_float_recip2_ps(uint64_t fdt0, uint64_t fdt2) { + uint32_t fst0 = fdt0 & 0XFFFFFFFF; + uint32_t fsth0 = fdt0 >> 32; + uint32_t fst2 = fdt2 & 0XFFFFFFFF; + uint32_t fsth2 = fdt2 >> 32; + set_float_exception_flags(0, &env->fpu->fp_status); - FST2 = float32_mul(FST0, FST2, &env->fpu->fp_status); - FSTH2 = float32_mul(FSTH0, FSTH2, &env->fpu->fp_status); - FST2 = float32_chs(float32_sub(FST2, FLOAT_ONE32, &env->fpu->fp_status)); - FSTH2 = float32_chs(float32_sub(FSTH2, FLOAT_ONE32, &env->fpu->fp_status)); + fst2 = float32_mul(fst0, fst2, &env->fpu->fp_status); + fsth2 = float32_mul(fsth0, fsth2, &env->fpu->fp_status); + fst2 = float32_chs(float32_sub(fst2, FLOAT_ONE32, &env->fpu->fp_status)); + fsth2 = float32_chs(float32_sub(fsth2, FLOAT_ONE32, &env->fpu->fp_status)); update_fcr31(); + return ((uint64_t)fsth2 << 32) | fst2; } -FLOAT_OP(rsqrt2, d) +uint64_t do_float_rsqrt2_d(uint64_t fdt0, uint64_t fdt2) { set_float_exception_flags(0, &env->fpu->fp_status); - FDT2 = float64_mul(FDT0, FDT2, &env->fpu->fp_status); - FDT2 = float64_sub(FDT2, FLOAT_ONE64, &env->fpu->fp_status); - FDT2 = float64_chs(float64_div(FDT2, FLOAT_TWO64, &env->fpu->fp_status)); + fdt2 = float64_mul(fdt0, fdt2, &env->fpu->fp_status); + fdt2 = float64_sub(fdt2, FLOAT_ONE64, &env->fpu->fp_status); + fdt2 = float64_chs(float64_div(fdt2, FLOAT_TWO64, &env->fpu->fp_status)); update_fcr31(); + return fdt2; } -FLOAT_OP(rsqrt2, s) + +uint32_t do_float_rsqrt2_s(uint32_t fst0, uint32_t fst2) { set_float_exception_flags(0, &env->fpu->fp_status); - FST2 = float32_mul(FST0, FST2, &env->fpu->fp_status); - FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fpu->fp_status); - FST2 = float32_chs(float32_div(FST2, FLOAT_TWO32, &env->fpu->fp_status)); + fst2 = float32_mul(fst0, fst2, &env->fpu->fp_status); + fst2 = float32_sub(fst2, FLOAT_ONE32, &env->fpu->fp_status); + fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, &env->fpu->fp_status)); update_fcr31(); + return fst2; } -FLOAT_OP(rsqrt2, ps) + +uint64_t do_float_rsqrt2_ps(uint64_t fdt0, uint64_t fdt2) { + uint32_t fst0 = fdt0 & 0XFFFFFFFF; + uint32_t fsth0 = fdt0 >> 32; + uint32_t fst2 = fdt2 & 0XFFFFFFFF; + uint32_t fsth2 = fdt2 >> 32; + set_float_exception_flags(0, &env->fpu->fp_status); - FST2 = float32_mul(FST0, FST2, &env->fpu->fp_status); - FSTH2 = float32_mul(FSTH0, FSTH2, &env->fpu->fp_status); - FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fpu->fp_status); - FSTH2 = float32_sub(FSTH2, FLOAT_ONE32, &env->fpu->fp_status); - FST2 = float32_chs(float32_div(FST2, FLOAT_TWO32, &env->fpu->fp_status)); - FSTH2 = float32_chs(float32_div(FSTH2, FLOAT_TWO32, &env->fpu->fp_status)); + fst2 = float32_mul(fst0, fst2, &env->fpu->fp_status); + fsth2 = float32_mul(fsth0, fsth2, &env->fpu->fp_status); + fst2 = float32_sub(fst2, FLOAT_ONE32, &env->fpu->fp_status); + fsth2 = float32_sub(fsth2, FLOAT_ONE32, &env->fpu->fp_status); + fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, &env->fpu->fp_status)); + fsth2 = float32_chs(float32_div(fsth2, FLOAT_TWO32, &env->fpu->fp_status)); update_fcr31(); + return ((uint64_t)fsth2 << 32) | fst2; } -FLOAT_OP(addr, ps) +uint64_t do_float_addr_ps(uint64_t fdt0, uint64_t fdt1) { + uint32_t fst0 = fdt0 & 0XFFFFFFFF; + uint32_t fsth0 = fdt0 >> 32; + uint32_t fst1 = fdt1 & 0XFFFFFFFF; + uint32_t fsth1 = fdt1 >> 32; + uint32_t fst2; + uint32_t fsth2; + set_float_exception_flags(0, &env->fpu->fp_status); - FST2 = float32_add (FST0, FSTH0, &env->fpu->fp_status); - FSTH2 = float32_add (FST1, FSTH1, &env->fpu->fp_status); + fst2 = float32_add (fst0, fsth0, &env->fpu->fp_status); + fsth2 = float32_add (fst1, fsth1, &env->fpu->fp_status); update_fcr31(); + return ((uint64_t)fsth2 << 32) | fst2; } -FLOAT_OP(mulr, ps) +uint64_t do_float_mulr_ps(uint64_t fdt0, uint64_t fdt1) { + uint32_t fst0 = fdt0 & 0XFFFFFFFF; + uint32_t fsth0 = fdt0 >> 32; + uint32_t fst1 = fdt1 & 0XFFFFFFFF; + uint32_t fsth1 = fdt1 >> 32; + uint32_t fst2; + uint32_t fsth2; + set_float_exception_flags(0, &env->fpu->fp_status); - FST2 = float32_mul (FST0, FSTH0, &env->fpu->fp_status); - FSTH2 = float32_mul (FST1, FSTH1, &env->fpu->fp_status); + fst2 = float32_mul (fst0, fsth0, &env->fpu->fp_status); + fsth2 = float32_mul (fst1, fsth1, &env->fpu->fp_status); update_fcr31(); + return ((uint64_t)fsth2 << 32) | fst2; } /* compare operations */ -#define FOP_COND_D(op, cond) \ -void do_cmp_d_ ## op (long cc) \ -{ \ - int c = cond; \ - update_fcr31(); \ - if (c) \ - SET_FP_COND(cc, env->fpu); \ - else \ - CLEAR_FP_COND(cc, env->fpu); \ -} \ -void do_cmpabs_d_ ## op (long cc) \ -{ \ - int c; \ - FDT0 = float64_abs(FDT0); \ - FDT1 = float64_abs(FDT1); \ - c = cond; \ - update_fcr31(); \ - if (c) \ - SET_FP_COND(cc, env->fpu); \ - else \ - CLEAR_FP_COND(cc, env->fpu); \ +#define FOP_COND_D(op, cond) \ +void do_cmp_d_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \ +{ \ + int c = cond; \ + update_fcr31(); \ + if (c) \ + SET_FP_COND(cc, env->fpu); \ + else \ + CLEAR_FP_COND(cc, env->fpu); \ +} \ +void do_cmpabs_d_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \ +{ \ + int c; \ + fdt0 = float64_abs(fdt0); \ + fdt1 = float64_abs(fdt1); \ + c = cond; \ + update_fcr31(); \ + if (c) \ + SET_FP_COND(cc, env->fpu); \ + else \ + CLEAR_FP_COND(cc, env->fpu); \ } int float64_is_unordered(int sig, float64 a, float64 b STATUS_PARAM) @@ -2660,46 +2899,46 @@ int float64_is_unordered(int sig, float64 a, float64 b STATUS_PARAM) /* NOTE: the comma operator will make "cond" to eval to false, * but float*_is_unordered() is still called. */ -FOP_COND_D(f, (float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status), 0)) -FOP_COND_D(un, float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status)) -FOP_COND_D(eq, !float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status) && float64_eq(FDT0, FDT1, &env->fpu->fp_status)) -FOP_COND_D(ueq, float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status) || float64_eq(FDT0, FDT1, &env->fpu->fp_status)) -FOP_COND_D(olt, !float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status) && float64_lt(FDT0, FDT1, &env->fpu->fp_status)) -FOP_COND_D(ult, float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status) || float64_lt(FDT0, FDT1, &env->fpu->fp_status)) -FOP_COND_D(ole, !float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status) && float64_le(FDT0, FDT1, &env->fpu->fp_status)) -FOP_COND_D(ule, float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status) || float64_le(FDT0, FDT1, &env->fpu->fp_status)) +FOP_COND_D(f, (float64_is_unordered(0, fdt1, fdt0, &env->fpu->fp_status), 0)) +FOP_COND_D(un, float64_is_unordered(0, fdt1, fdt0, &env->fpu->fp_status)) +FOP_COND_D(eq, !float64_is_unordered(0, fdt1, fdt0, &env->fpu->fp_status) && float64_eq(fdt0, fdt1, &env->fpu->fp_status)) +FOP_COND_D(ueq, float64_is_unordered(0, fdt1, fdt0, &env->fpu->fp_status) || float64_eq(fdt0, fdt1, &env->fpu->fp_status)) +FOP_COND_D(olt, !float64_is_unordered(0, fdt1, fdt0, &env->fpu->fp_status) && float64_lt(fdt0, fdt1, &env->fpu->fp_status)) +FOP_COND_D(ult, float64_is_unordered(0, fdt1, fdt0, &env->fpu->fp_status) || float64_lt(fdt0, fdt1, &env->fpu->fp_status)) +FOP_COND_D(ole, !float64_is_unordered(0, fdt1, fdt0, &env->fpu->fp_status) && float64_le(fdt0, fdt1, &env->fpu->fp_status)) +FOP_COND_D(ule, float64_is_unordered(0, fdt1, fdt0, &env->fpu->fp_status) || float64_le(fdt0, fdt1, &env->fpu->fp_status)) /* NOTE: the comma operator will make "cond" to eval to false, * but float*_is_unordered() is still called. */ -FOP_COND_D(sf, (float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status), 0)) -FOP_COND_D(ngle,float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status)) -FOP_COND_D(seq, !float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status) && float64_eq(FDT0, FDT1, &env->fpu->fp_status)) -FOP_COND_D(ngl, float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status) || float64_eq(FDT0, FDT1, &env->fpu->fp_status)) -FOP_COND_D(lt, !float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status) && float64_lt(FDT0, FDT1, &env->fpu->fp_status)) -FOP_COND_D(nge, float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status) || float64_lt(FDT0, FDT1, &env->fpu->fp_status)) -FOP_COND_D(le, !float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status) && float64_le(FDT0, FDT1, &env->fpu->fp_status)) -FOP_COND_D(ngt, float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status) || float64_le(FDT0, FDT1, &env->fpu->fp_status)) - -#define FOP_COND_S(op, cond) \ -void do_cmp_s_ ## op (long cc) \ -{ \ - int c = cond; \ - update_fcr31(); \ - if (c) \ - SET_FP_COND(cc, env->fpu); \ - else \ - CLEAR_FP_COND(cc, env->fpu); \ -} \ -void do_cmpabs_s_ ## op (long cc) \ -{ \ - int c; \ - FST0 = float32_abs(FST0); \ - FST1 = float32_abs(FST1); \ - c = cond; \ - update_fcr31(); \ - if (c) \ - SET_FP_COND(cc, env->fpu); \ - else \ - CLEAR_FP_COND(cc, env->fpu); \ +FOP_COND_D(sf, (float64_is_unordered(1, fdt1, fdt0, &env->fpu->fp_status), 0)) +FOP_COND_D(ngle,float64_is_unordered(1, fdt1, fdt0, &env->fpu->fp_status)) +FOP_COND_D(seq, !float64_is_unordered(1, fdt1, fdt0, &env->fpu->fp_status) && float64_eq(fdt0, fdt1, &env->fpu->fp_status)) +FOP_COND_D(ngl, float64_is_unordered(1, fdt1, fdt0, &env->fpu->fp_status) || float64_eq(fdt0, fdt1, &env->fpu->fp_status)) +FOP_COND_D(lt, !float64_is_unordered(1, fdt1, fdt0, &env->fpu->fp_status) && float64_lt(fdt0, fdt1, &env->fpu->fp_status)) +FOP_COND_D(nge, float64_is_unordered(1, fdt1, fdt0, &env->fpu->fp_status) || float64_lt(fdt0, fdt1, &env->fpu->fp_status)) +FOP_COND_D(le, !float64_is_unordered(1, fdt1, fdt0, &env->fpu->fp_status) && float64_le(fdt0, fdt1, &env->fpu->fp_status)) +FOP_COND_D(ngt, float64_is_unordered(1, fdt1, fdt0, &env->fpu->fp_status) || float64_le(fdt0, fdt1, &env->fpu->fp_status)) + +#define FOP_COND_S(op, cond) \ +void do_cmp_s_ ## op (uint32_t fst0, uint32_t fst1, int cc) \ +{ \ + int c = cond; \ + update_fcr31(); \ + if (c) \ + SET_FP_COND(cc, env->fpu); \ + else \ + CLEAR_FP_COND(cc, env->fpu); \ +} \ +void do_cmpabs_s_ ## op (uint32_t fst0, uint32_t fst1, int cc) \ +{ \ + int c; \ + fst0 = float32_abs(fst0); \ + fst1 = float32_abs(fst1); \ + c = cond; \ + update_fcr31(); \ + if (c) \ + SET_FP_COND(cc, env->fpu); \ + else \ + CLEAR_FP_COND(cc, env->fpu); \ } flag float32_is_unordered(int sig, float32 a, float32 b STATUS_PARAM) @@ -2718,93 +2957,98 @@ flag float32_is_unordered(int sig, float32 a, float32 b STATUS_PARAM) /* NOTE: the comma operator will make "cond" to eval to false, * but float*_is_unordered() is still called. */ -FOP_COND_S(f, (float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status), 0)) -FOP_COND_S(un, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status)) -FOP_COND_S(eq, !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) && float32_eq(FST0, FST1, &env->fpu->fp_status)) -FOP_COND_S(ueq, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) || float32_eq(FST0, FST1, &env->fpu->fp_status)) -FOP_COND_S(olt, !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) && float32_lt(FST0, FST1, &env->fpu->fp_status)) -FOP_COND_S(ult, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) || float32_lt(FST0, FST1, &env->fpu->fp_status)) -FOP_COND_S(ole, !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) && float32_le(FST0, FST1, &env->fpu->fp_status)) -FOP_COND_S(ule, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) || float32_le(FST0, FST1, &env->fpu->fp_status)) +FOP_COND_S(f, (float32_is_unordered(0, fst1, fst0, &env->fpu->fp_status), 0)) +FOP_COND_S(un, float32_is_unordered(0, fst1, fst0, &env->fpu->fp_status)) +FOP_COND_S(eq, !float32_is_unordered(0, fst1, fst0, &env->fpu->fp_status) && float32_eq(fst0, fst1, &env->fpu->fp_status)) +FOP_COND_S(ueq, float32_is_unordered(0, fst1, fst0, &env->fpu->fp_status) || float32_eq(fst0, fst1, &env->fpu->fp_status)) +FOP_COND_S(olt, !float32_is_unordered(0, fst1, fst0, &env->fpu->fp_status) && float32_lt(fst0, fst1, &env->fpu->fp_status)) +FOP_COND_S(ult, float32_is_unordered(0, fst1, fst0, &env->fpu->fp_status) || float32_lt(fst0, fst1, &env->fpu->fp_status)) +FOP_COND_S(ole, !float32_is_unordered(0, fst1, fst0, &env->fpu->fp_status) && float32_le(fst0, fst1, &env->fpu->fp_status)) +FOP_COND_S(ule, float32_is_unordered(0, fst1, fst0, &env->fpu->fp_status) || float32_le(fst0, fst1, &env->fpu->fp_status)) /* NOTE: the comma operator will make "cond" to eval to false, * but float*_is_unordered() is still called. */ -FOP_COND_S(sf, (float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status), 0)) -FOP_COND_S(ngle,float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status)) -FOP_COND_S(seq, !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) && float32_eq(FST0, FST1, &env->fpu->fp_status)) -FOP_COND_S(ngl, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) || float32_eq(FST0, FST1, &env->fpu->fp_status)) -FOP_COND_S(lt, !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) && float32_lt(FST0, FST1, &env->fpu->fp_status)) -FOP_COND_S(nge, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) || float32_lt(FST0, FST1, &env->fpu->fp_status)) -FOP_COND_S(le, !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) && float32_le(FST0, FST1, &env->fpu->fp_status)) -FOP_COND_S(ngt, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) || float32_le(FST0, FST1, &env->fpu->fp_status)) - -#define FOP_COND_PS(op, condl, condh) \ -void do_cmp_ps_ ## op (long cc) \ -{ \ - int cl = condl; \ - int ch = condh; \ - update_fcr31(); \ - if (cl) \ - SET_FP_COND(cc, env->fpu); \ - else \ - CLEAR_FP_COND(cc, env->fpu); \ - if (ch) \ - SET_FP_COND(cc + 1, env->fpu); \ - else \ - CLEAR_FP_COND(cc + 1, env->fpu); \ -} \ -void do_cmpabs_ps_ ## op (long cc) \ -{ \ - int cl, ch; \ - FST0 = float32_abs(FST0); \ - FSTH0 = float32_abs(FSTH0); \ - FST1 = float32_abs(FST1); \ - FSTH1 = float32_abs(FSTH1); \ - cl = condl; \ - ch = condh; \ - update_fcr31(); \ - if (cl) \ - SET_FP_COND(cc, env->fpu); \ - else \ - CLEAR_FP_COND(cc, env->fpu); \ - if (ch) \ - SET_FP_COND(cc + 1, env->fpu); \ - else \ - CLEAR_FP_COND(cc + 1, env->fpu); \ +FOP_COND_S(sf, (float32_is_unordered(1, fst1, fst0, &env->fpu->fp_status), 0)) +FOP_COND_S(ngle,float32_is_unordered(1, fst1, fst0, &env->fpu->fp_status)) +FOP_COND_S(seq, !float32_is_unordered(1, fst1, fst0, &env->fpu->fp_status) && float32_eq(fst0, fst1, &env->fpu->fp_status)) +FOP_COND_S(ngl, float32_is_unordered(1, fst1, fst0, &env->fpu->fp_status) || float32_eq(fst0, fst1, &env->fpu->fp_status)) +FOP_COND_S(lt, !float32_is_unordered(1, fst1, fst0, &env->fpu->fp_status) && float32_lt(fst0, fst1, &env->fpu->fp_status)) +FOP_COND_S(nge, float32_is_unordered(1, fst1, fst0, &env->fpu->fp_status) || float32_lt(fst0, fst1, &env->fpu->fp_status)) +FOP_COND_S(le, !float32_is_unordered(1, fst1, fst0, &env->fpu->fp_status) && float32_le(fst0, fst1, &env->fpu->fp_status)) +FOP_COND_S(ngt, float32_is_unordered(1, fst1, fst0, &env->fpu->fp_status) || float32_le(fst0, fst1, &env->fpu->fp_status)) + +#define FOP_COND_PS(op, condl, condh) \ +void do_cmp_ps_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \ +{ \ + uint32_t fst0 = float32_abs(fdt0 & 0XFFFFFFFF); \ + uint32_t fsth0 = float32_abs(fdt0 >> 32); \ + uint32_t fst1 = float32_abs(fdt1 & 0XFFFFFFFF); \ + uint32_t fsth1 = float32_abs(fdt1 >> 32); \ + int cl = condl; \ + int ch = condh; \ + \ + update_fcr31(); \ + if (cl) \ + SET_FP_COND(cc, env->fpu); \ + else \ + CLEAR_FP_COND(cc, env->fpu); \ + if (ch) \ + SET_FP_COND(cc + 1, env->fpu); \ + else \ + CLEAR_FP_COND(cc + 1, env->fpu); \ +} \ +void do_cmpabs_ps_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \ +{ \ + uint32_t fst0 = float32_abs(fdt0 & 0XFFFFFFFF); \ + uint32_t fsth0 = float32_abs(fdt0 >> 32); \ + uint32_t fst1 = float32_abs(fdt1 & 0XFFFFFFFF); \ + uint32_t fsth1 = float32_abs(fdt1 >> 32); \ + int cl = condl; \ + int ch = condh; \ + \ + update_fcr31(); \ + if (cl) \ + SET_FP_COND(cc, env->fpu); \ + else \ + CLEAR_FP_COND(cc, env->fpu); \ + if (ch) \ + SET_FP_COND(cc + 1, env->fpu); \ + else \ + CLEAR_FP_COND(cc + 1, env->fpu); \ } /* NOTE: the comma operator will make "cond" to eval to false, * but float*_is_unordered() is still called. */ -FOP_COND_PS(f, (float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status), 0), - (float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status), 0)) -FOP_COND_PS(un, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status), - float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status)) -FOP_COND_PS(eq, !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) && float32_eq(FST0, FST1, &env->fpu->fp_status), - !float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status) && float32_eq(FSTH0, FSTH1, &env->fpu->fp_status)) -FOP_COND_PS(ueq, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) || float32_eq(FST0, FST1, &env->fpu->fp_status), - float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status) || float32_eq(FSTH0, FSTH1, &env->fpu->fp_status)) -FOP_COND_PS(olt, !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) && float32_lt(FST0, FST1, &env->fpu->fp_status), - !float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status) && float32_lt(FSTH0, FSTH1, &env->fpu->fp_status)) -FOP_COND_PS(ult, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) || float32_lt(FST0, FST1, &env->fpu->fp_status), - float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status) || float32_lt(FSTH0, FSTH1, &env->fpu->fp_status)) -FOP_COND_PS(ole, !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) && float32_le(FST0, FST1, &env->fpu->fp_status), - !float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status) && float32_le(FSTH0, FSTH1, &env->fpu->fp_status)) -FOP_COND_PS(ule, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) || float32_le(FST0, FST1, &env->fpu->fp_status), - float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status) || float32_le(FSTH0, FSTH1, &env->fpu->fp_status)) +FOP_COND_PS(f, (float32_is_unordered(0, fst1, fst0, &env->fpu->fp_status), 0), + (float32_is_unordered(0, fsth1, fsth0, &env->fpu->fp_status), 0)) +FOP_COND_PS(un, float32_is_unordered(0, fst1, fst0, &env->fpu->fp_status), + float32_is_unordered(0, fsth1, fsth0, &env->fpu->fp_status)) +FOP_COND_PS(eq, !float32_is_unordered(0, fst1, fst0, &env->fpu->fp_status) && float32_eq(fst0, fst1, &env->fpu->fp_status), + !float32_is_unordered(0, fsth1, fsth0, &env->fpu->fp_status) && float32_eq(fsth0, fsth1, &env->fpu->fp_status)) +FOP_COND_PS(ueq, float32_is_unordered(0, fst1, fst0, &env->fpu->fp_status) || float32_eq(fst0, fst1, &env->fpu->fp_status), + float32_is_unordered(0, fsth1, fsth0, &env->fpu->fp_status) || float32_eq(fsth0, fsth1, &env->fpu->fp_status)) +FOP_COND_PS(olt, !float32_is_unordered(0, fst1, fst0, &env->fpu->fp_status) && float32_lt(fst0, fst1, &env->fpu->fp_status), + !float32_is_unordered(0, fsth1, fsth0, &env->fpu->fp_status) && float32_lt(fsth0, fsth1, &env->fpu->fp_status)) +FOP_COND_PS(ult, float32_is_unordered(0, fst1, fst0, &env->fpu->fp_status) || float32_lt(fst0, fst1, &env->fpu->fp_status), + float32_is_unordered(0, fsth1, fsth0, &env->fpu->fp_status) || float32_lt(fsth0, fsth1, &env->fpu->fp_status)) +FOP_COND_PS(ole, !float32_is_unordered(0, fst1, fst0, &env->fpu->fp_status) && float32_le(fst0, fst1, &env->fpu->fp_status), + !float32_is_unordered(0, fsth1, fsth0, &env->fpu->fp_status) && float32_le(fsth0, fsth1, &env->fpu->fp_status)) +FOP_COND_PS(ule, float32_is_unordered(0, fst1, fst0, &env->fpu->fp_status) || float32_le(fst0, fst1, &env->fpu->fp_status), + float32_is_unordered(0, fsth1, fsth0, &env->fpu->fp_status) || float32_le(fsth0, fsth1, &env->fpu->fp_status)) /* NOTE: the comma operator will make "cond" to eval to false, * but float*_is_unordered() is still called. */ -FOP_COND_PS(sf, (float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status), 0), - (float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status), 0)) -FOP_COND_PS(ngle,float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status), - float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status)) -FOP_COND_PS(seq, !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) && float32_eq(FST0, FST1, &env->fpu->fp_status), - !float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status) && float32_eq(FSTH0, FSTH1, &env->fpu->fp_status)) -FOP_COND_PS(ngl, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) || float32_eq(FST0, FST1, &env->fpu->fp_status), - float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status) || float32_eq(FSTH0, FSTH1, &env->fpu->fp_status)) -FOP_COND_PS(lt, !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) && float32_lt(FST0, FST1, &env->fpu->fp_status), - !float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status) && float32_lt(FSTH0, FSTH1, &env->fpu->fp_status)) -FOP_COND_PS(nge, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) || float32_lt(FST0, FST1, &env->fpu->fp_status), - float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status) || float32_lt(FSTH0, FSTH1, &env->fpu->fp_status)) -FOP_COND_PS(le, !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) && float32_le(FST0, FST1, &env->fpu->fp_status), - !float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status) && float32_le(FSTH0, FSTH1, &env->fpu->fp_status)) -FOP_COND_PS(ngt, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) || float32_le(FST0, FST1, &env->fpu->fp_status), - float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status) || float32_le(FSTH0, FSTH1, &env->fpu->fp_status)) +FOP_COND_PS(sf, (float32_is_unordered(1, fst1, fst0, &env->fpu->fp_status), 0), + (float32_is_unordered(1, fsth1, fsth0, &env->fpu->fp_status), 0)) +FOP_COND_PS(ngle,float32_is_unordered(1, fst1, fst0, &env->fpu->fp_status), + float32_is_unordered(1, fsth1, fsth0, &env->fpu->fp_status)) +FOP_COND_PS(seq, !float32_is_unordered(1, fst1, fst0, &env->fpu->fp_status) && float32_eq(fst0, fst1, &env->fpu->fp_status), + !float32_is_unordered(1, fsth1, fsth0, &env->fpu->fp_status) && float32_eq(fsth0, fsth1, &env->fpu->fp_status)) +FOP_COND_PS(ngl, float32_is_unordered(1, fst1, fst0, &env->fpu->fp_status) || float32_eq(fst0, fst1, &env->fpu->fp_status), + float32_is_unordered(1, fsth1, fsth0, &env->fpu->fp_status) || float32_eq(fsth0, fsth1, &env->fpu->fp_status)) +FOP_COND_PS(lt, !float32_is_unordered(1, fst1, fst0, &env->fpu->fp_status) && float32_lt(fst0, fst1, &env->fpu->fp_status), + !float32_is_unordered(1, fsth1, fsth0, &env->fpu->fp_status) && float32_lt(fsth0, fsth1, &env->fpu->fp_status)) +FOP_COND_PS(nge, float32_is_unordered(1, fst1, fst0, &env->fpu->fp_status) || float32_lt(fst0, fst1, &env->fpu->fp_status), + float32_is_unordered(1, fsth1, fsth0, &env->fpu->fp_status) || float32_lt(fsth0, fsth1, &env->fpu->fp_status)) +FOP_COND_PS(le, !float32_is_unordered(1, fst1, fst0, &env->fpu->fp_status) && float32_le(fst0, fst1, &env->fpu->fp_status), + !float32_is_unordered(1, fsth1, fsth0, &env->fpu->fp_status) && float32_le(fsth0, fsth1, &env->fpu->fp_status)) +FOP_COND_PS(ngt, float32_is_unordered(1, fst1, fst0, &env->fpu->fp_status) || float32_le(fst0, fst1, &env->fpu->fp_status), + float32_is_unordered(1, fsth1, fsth0, &env->fpu->fp_status) || float32_le(fsth0, fsth1, &env->fpu->fp_status)) diff --git a/target-mips/translate.c b/target-mips/translate.c index f92326339..bdc0f7b21 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -425,9 +425,6 @@ enum { /* global register indices */ static TCGv cpu_env, bcond, btarget, current_fpu; -/* FPU TNs, global for now. */ -static TCGv fpu32_T[3], fpu64_T[3], fpu32h_T[3]; - #include "gen-icount.h" static inline void tcg_gen_helper_0_i(void *func, TCGv arg) @@ -723,36 +720,39 @@ static inline void get_fp_cond (TCGv t) tcg_temp_free(r_tmp2); } -#define FOP_CONDS(type, fmt) \ -static GenOpFunc1 * fcmp ## type ## _ ## fmt ## _table[16] = { \ - do_cmp ## type ## _ ## fmt ## _f, \ - do_cmp ## type ## _ ## fmt ## _un, \ - do_cmp ## type ## _ ## fmt ## _eq, \ - do_cmp ## type ## _ ## fmt ## _ueq, \ - do_cmp ## type ## _ ## fmt ## _olt, \ - do_cmp ## type ## _ ## fmt ## _ult, \ - do_cmp ## type ## _ ## fmt ## _ole, \ - do_cmp ## type ## _ ## fmt ## _ule, \ - do_cmp ## type ## _ ## fmt ## _sf, \ - do_cmp ## type ## _ ## fmt ## _ngle, \ - do_cmp ## type ## _ ## fmt ## _seq, \ - do_cmp ## type ## _ ## fmt ## _ngl, \ - do_cmp ## type ## _ ## fmt ## _lt, \ - do_cmp ## type ## _ ## fmt ## _nge, \ - do_cmp ## type ## _ ## fmt ## _le, \ - do_cmp ## type ## _ ## fmt ## _ngt, \ -}; \ -static inline void gen_cmp ## type ## _ ## fmt(int n, long cc) \ -{ \ - tcg_gen_helper_0_i(fcmp ## type ## _ ## fmt ## _table[n], cc); \ +typedef void (fcmp_fun32)(uint32_t, uint32_t, int); +typedef void (fcmp_fun64)(uint64_t, uint64_t, int); + +#define FOP_CONDS(fcmp_fun, type, arg0, arg1, fmt) \ +static fcmp_fun * fcmp ## type ## _ ## fmt ## _table[16] = { \ + do_cmp ## type ## _ ## fmt ## _f, \ + do_cmp ## type ## _ ## fmt ## _un, \ + do_cmp ## type ## _ ## fmt ## _eq, \ + do_cmp ## type ## _ ## fmt ## _ueq, \ + do_cmp ## type ## _ ## fmt ## _olt, \ + do_cmp ## type ## _ ## fmt ## _ult, \ + do_cmp ## type ## _ ## fmt ## _ole, \ + do_cmp ## type ## _ ## fmt ## _ule, \ + do_cmp ## type ## _ ## fmt ## _sf, \ + do_cmp ## type ## _ ## fmt ## _ngle, \ + do_cmp ## type ## _ ## fmt ## _seq, \ + do_cmp ## type ## _ ## fmt ## _ngl, \ + do_cmp ## type ## _ ## fmt ## _lt, \ + do_cmp ## type ## _ ## fmt ## _nge, \ + do_cmp ## type ## _ ## fmt ## _le, \ + do_cmp ## type ## _ ## fmt ## _ngt, \ +}; \ +static inline void gen_cmp ## type ## _ ## fmt(int n, arg0 a, arg1 b, int cc) \ +{ \ + tcg_gen_helper_0_2i(fcmp ## type ## _ ## fmt ## _table[n], a, b, cc); \ } -FOP_CONDS(, d) -FOP_CONDS(abs, d) -FOP_CONDS(, s) -FOP_CONDS(abs, s) -FOP_CONDS(, ps) -FOP_CONDS(abs, ps) +FOP_CONDS(fcmp_fun64, , uint64_t, uint64_t, d) +FOP_CONDS(fcmp_fun64, abs, uint64_t, uint64_t, d) +FOP_CONDS(fcmp_fun32, , uint32_t, uint32_t, s) +FOP_CONDS(fcmp_fun32, abs, uint32_t, uint32_t, s) +FOP_CONDS(fcmp_fun64, , uint64_t, uint64_t, ps) +FOP_CONDS(fcmp_fun64, abs, uint64_t, uint64_t, ps) #undef FOP_CONDS /* Tests */ @@ -1234,23 +1234,43 @@ static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft, memory access. */ switch (opc) { case OPC_LWC1: - tcg_gen_qemu_ld32s(fpu32_T[0], t0, ctx->mem_idx); - gen_store_fpr32(fpu32_T[0], ft); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + + tcg_gen_qemu_ld32s(fp0, t0, ctx->mem_idx); + gen_store_fpr32(fp0, ft); + tcg_temp_free(fp0); + } opn = "lwc1"; break; case OPC_SWC1: - gen_load_fpr32(fpu32_T[0], ft); - tcg_gen_qemu_st32(fpu32_T[0], t0, ctx->mem_idx); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32(fp0, ft); + tcg_gen_qemu_st32(fp0, t0, ctx->mem_idx); + tcg_temp_free(fp0); + } opn = "swc1"; break; case OPC_LDC1: - tcg_gen_qemu_ld64(fpu64_T[0], t0, ctx->mem_idx); - gen_store_fpr64(ctx, fpu64_T[0], ft); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + + tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx); + gen_store_fpr64(ctx, fp0, ft); + tcg_temp_free(fp0); + } opn = "ldc1"; break; case OPC_SDC1: - gen_load_fpr64(ctx, fpu64_T[0], ft); - tcg_gen_qemu_st64(fpu64_T[0], t0, ctx->mem_idx); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, ft); + tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx); + tcg_temp_free(fp0); + } opn = "sdc1"; break; default: @@ -5318,11 +5338,17 @@ static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd, case 2: /* XXX: For now we support only a single FPU context. */ if (h == 0) { - gen_load_fpr32(fpu32_T[0], rt); - tcg_gen_ext_i32_tl(t0, fpu32_T[0]); + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32(fp0, rt); + tcg_gen_ext_i32_tl(t0, fp0); + tcg_temp_free(fp0); } else { - gen_load_fpr32h(fpu32h_T[0], rt); - tcg_gen_ext_i32_tl(t0, fpu32h_T[0]); + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32h(fp0, rt); + tcg_gen_ext_i32_tl(t0, fp0); + tcg_temp_free(fp0); } break; case 3: @@ -5487,11 +5513,17 @@ static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt, case 2: /* XXX: For now we support only a single FPU context. */ if (h == 0) { - tcg_gen_trunc_tl_i32(fpu32_T[0], t0); - gen_store_fpr32(fpu32_T[0], rd); + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + + tcg_gen_trunc_tl_i32(fp0, t0); + gen_store_fpr32(fp0, rd); + tcg_temp_free(fp0); } else { - tcg_gen_trunc_tl_i32(fpu32h_T[0], t0); - gen_store_fpr32h(fpu32h_T[0], rd); + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + + tcg_gen_trunc_tl_i32(fp0, t0); + gen_store_fpr32h(fp0, rd); + tcg_temp_free(fp0); } break; case 3: @@ -5873,15 +5905,25 @@ static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs) switch (opc) { case OPC_MFC1: - gen_load_fpr32(fpu32_T[0], fs); - tcg_gen_ext_i32_tl(t0, fpu32_T[0]); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32(fp0, fs); + tcg_gen_ext_i32_tl(t0, fp0); + tcg_temp_free(fp0); + } gen_store_gpr(t0, rt); opn = "mfc1"; break; case OPC_MTC1: gen_load_gpr(t0, rt); - tcg_gen_trunc_tl_i32(fpu32_T[0], t0); - gen_store_fpr32(fpu32_T[0], fs); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + + tcg_gen_trunc_tl_i32(fp0, t0); + gen_store_fpr32(fp0, fs); + tcg_temp_free(fp0); + } opn = "mtc1"; break; case OPC_CFC1: @@ -5895,27 +5937,47 @@ static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs) opn = "ctc1"; break; case OPC_DMFC1: - gen_load_fpr64(ctx, fpu64_T[0], fs); - tcg_gen_mov_tl(t0, fpu64_T[0]); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + tcg_gen_mov_tl(t0, fp0); + tcg_temp_free(fp0); + } gen_store_gpr(t0, rt); opn = "dmfc1"; break; case OPC_DMTC1: gen_load_gpr(t0, rt); - tcg_gen_mov_tl(fpu64_T[0], t0); - gen_store_fpr64(ctx, fpu64_T[0], fs); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + + tcg_gen_mov_tl(fp0, t0); + gen_store_fpr64(ctx, fp0, fs); + tcg_temp_free(fp0); + } opn = "dmtc1"; break; case OPC_MFHC1: - gen_load_fpr32h(fpu32h_T[0], fs); - tcg_gen_ext_i32_tl(t0, fpu32h_T[0]); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32h(fp0, fs); + tcg_gen_ext_i32_tl(t0, fp0); + tcg_temp_free(fp0); + } gen_store_gpr(t0, rt); opn = "mfhc1"; break; case OPC_MTHC1: gen_load_gpr(t0, rt); - tcg_gen_trunc_tl_i32(fpu32h_T[0], t0); - gen_store_fpr32h(fpu32h_T[0], fs); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + + tcg_gen_trunc_tl_i32(fp0, t0); + gen_store_fpr32h(fp0, fs); + tcg_temp_free(fp0); + } opn = "mthc1"; break; default: @@ -5967,11 +6029,13 @@ static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf) tcg_temp_free(t0); } -static inline void gen_movcf_s (int cc, int tf) +static inline void gen_movcf_s (int fs, int fd, int cc, int tf) { uint32_t ccbit; int cond; - TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32); + TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_I32); + TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32); + TCGv fp1 = tcg_temp_local_new(TCG_TYPE_I32); int l1 = gen_new_label(); if (cc) @@ -5984,19 +6048,26 @@ static inline void gen_movcf_s (int cc, int tf) else cond = TCG_COND_NE; + gen_load_fpr32(fp0, fs); + gen_load_fpr32(fp1, fd); tcg_gen_ld_i32(r_tmp1, current_fpu, offsetof(CPUMIPSFPUContext, fcr31)); tcg_gen_andi_i32(r_tmp1, r_tmp1, ccbit); tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1); - tcg_gen_movi_i32(fpu32_T[2], fpu32_T[0]); + tcg_gen_movi_i32(fp1, fp0); + tcg_temp_free(fp0); gen_set_label(l1); tcg_temp_free(r_tmp1); + gen_store_fpr32(fp1, fd); + tcg_temp_free(fp1); } -static inline void gen_movcf_d (int cc, int tf) +static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf) { uint32_t ccbit; int cond; - TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32); + TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_I32); + TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I64); + TCGv fp1 = tcg_temp_local_new(TCG_TYPE_I64); int l1 = gen_new_label(); if (cc) @@ -6009,19 +6080,28 @@ static inline void gen_movcf_d (int cc, int tf) else cond = TCG_COND_NE; + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, fd); tcg_gen_ld_i32(r_tmp1, current_fpu, offsetof(CPUMIPSFPUContext, fcr31)); tcg_gen_andi_i32(r_tmp1, r_tmp1, ccbit); tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1); - tcg_gen_movi_i64(fpu64_T[2], fpu64_T[0]); + tcg_gen_movi_i64(fp1, fp0); + tcg_temp_free(fp0); gen_set_label(l1); tcg_temp_free(r_tmp1); + gen_store_fpr64(ctx, fp1, fd); + tcg_temp_free(fp1); } -static inline void gen_movcf_ps (int cc, int tf) +static inline void gen_movcf_ps (int fs, int fd, int cc, int tf) { int cond; TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_I32); TCGv r_tmp2 = tcg_temp_local_new(TCG_TYPE_I32); + TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32); + TCGv fph0 = tcg_temp_local_new(TCG_TYPE_I32); + TCGv fp1 = tcg_temp_local_new(TCG_TYPE_I32); + TCGv fph1 = tcg_temp_local_new(TCG_TYPE_I32); int l1 = gen_new_label(); int l2 = gen_new_label(); @@ -6030,18 +6110,28 @@ static inline void gen_movcf_ps (int cc, int tf) else cond = TCG_COND_NE; + gen_load_fpr32(fp0, fs); + gen_load_fpr32h(fph0, fs); + gen_load_fpr32(fp1, fd); + gen_load_fpr32h(fph1, fd); get_fp_cond(r_tmp1); tcg_gen_shri_i32(r_tmp1, r_tmp1, cc); tcg_gen_andi_i32(r_tmp2, r_tmp1, 0x1); tcg_gen_brcondi_i32(cond, r_tmp2, 0, l1); - tcg_gen_movi_i32(fpu32_T[2], fpu32_T[0]); + tcg_gen_movi_i32(fp1, fp0); + tcg_temp_free(fp0); gen_set_label(l1); tcg_gen_andi_i32(r_tmp2, r_tmp1, 0x2); tcg_gen_brcondi_i32(cond, r_tmp2, 0, l2); - tcg_gen_movi_i32(fpu32h_T[2], fpu32h_T[0]); + tcg_gen_movi_i32(fph1, fph0); + tcg_temp_free(fph0); gen_set_label(l2); tcg_temp_free(r_tmp1); tcg_temp_free(r_tmp2); + gen_store_fpr32(fp1, fd); + gen_store_fpr32h(fph1, fd); + tcg_temp_free(fp1); + tcg_temp_free(fph1); } @@ -6090,224 +6180,381 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, switch (ctx->opcode & FOP(0x3f, 0x1f)) { case FOP(0, 16): - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32(fpu32_T[1], ft); - tcg_gen_helper_0_0(do_float_add_s); - gen_store_fpr32(fpu32_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32(fp0, fs); + gen_load_fpr32(fp1, ft); + tcg_gen_helper_1_2(do_float_add_s, fp0, fp0, fp1); + tcg_temp_free(fp1); + gen_store_fpr32(fp0, fd); + tcg_temp_free(fp0); + } opn = "add.s"; optype = BINOP; break; case FOP(1, 16): - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32(fpu32_T[1], ft); - tcg_gen_helper_0_0(do_float_sub_s); - gen_store_fpr32(fpu32_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32(fp0, fs); + gen_load_fpr32(fp1, ft); + tcg_gen_helper_1_2(do_float_sub_s, fp0, fp0, fp1); + tcg_temp_free(fp1); + gen_store_fpr32(fp0, fd); + tcg_temp_free(fp0); + } opn = "sub.s"; optype = BINOP; break; case FOP(2, 16): - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32(fpu32_T[1], ft); - tcg_gen_helper_0_0(do_float_mul_s); - gen_store_fpr32(fpu32_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32(fp0, fs); + gen_load_fpr32(fp1, ft); + tcg_gen_helper_1_2(do_float_mul_s, fp0, fp0, fp1); + tcg_temp_free(fp1); + gen_store_fpr32(fp0, fd); + tcg_temp_free(fp0); + } opn = "mul.s"; optype = BINOP; break; case FOP(3, 16): - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32(fpu32_T[1], ft); - tcg_gen_helper_0_0(do_float_div_s); - gen_store_fpr32(fpu32_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32(fp0, fs); + gen_load_fpr32(fp1, ft); + tcg_gen_helper_1_2(do_float_div_s, fp0, fp0, fp1); + tcg_temp_free(fp1); + gen_store_fpr32(fp0, fd); + tcg_temp_free(fp0); + } opn = "div.s"; optype = BINOP; break; case FOP(4, 16): - gen_load_fpr32(fpu32_T[0], fs); - tcg_gen_helper_0_0(do_float_sqrt_s); - gen_store_fpr32(fpu32_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32(fp0, fs); + tcg_gen_helper_1_1(do_float_sqrt_s, fp0, fp0); + gen_store_fpr32(fp0, fd); + tcg_temp_free(fp0); + } opn = "sqrt.s"; break; case FOP(5, 16): - gen_load_fpr32(fpu32_T[0], fs); - tcg_gen_helper_0_0(do_float_abs_s); - gen_store_fpr32(fpu32_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32(fp0, fs); + tcg_gen_helper_1_1(do_float_abs_s, fp0, fp0); + gen_store_fpr32(fp0, fd); + tcg_temp_free(fp0); + } opn = "abs.s"; break; case FOP(6, 16): - gen_load_fpr32(fpu32_T[0], fs); - gen_store_fpr32(fpu32_T[0], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32(fp0, fs); + gen_store_fpr32(fp0, fd); + tcg_temp_free(fp0); + } opn = "mov.s"; break; case FOP(7, 16): - gen_load_fpr32(fpu32_T[0], fs); - tcg_gen_helper_0_0(do_float_chs_s); - gen_store_fpr32(fpu32_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32(fp0, fs); + tcg_gen_helper_1_1(do_float_chs_s, fp0, fp0); + gen_store_fpr32(fp0, fd); + tcg_temp_free(fp0); + } opn = "neg.s"; break; case FOP(8, 16): check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], fs); - tcg_gen_helper_0_0(do_float_roundl_s); - gen_store_fpr64(ctx, fpu64_T[2], fd); + { + TCGv fp32 = tcg_temp_new(TCG_TYPE_I32); + TCGv fp64 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr32(fp32, fs); + tcg_gen_helper_1_1(do_float_roundl_s, fp64, fp32); + tcg_temp_free(fp32); + gen_store_fpr64(ctx, fp64, fd); + tcg_temp_free(fp64); + } opn = "round.l.s"; break; case FOP(9, 16): check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], fs); - tcg_gen_helper_0_0(do_float_truncl_s); - gen_store_fpr64(ctx, fpu64_T[2], fd); + { + TCGv fp32 = tcg_temp_new(TCG_TYPE_I32); + TCGv fp64 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr32(fp32, fs); + tcg_gen_helper_1_1(do_float_truncl_s, fp64, fp32); + tcg_temp_free(fp32); + gen_store_fpr64(ctx, fp64, fd); + tcg_temp_free(fp64); + } opn = "trunc.l.s"; break; case FOP(10, 16): check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], fs); - tcg_gen_helper_0_0(do_float_ceill_s); - gen_store_fpr64(ctx, fpu64_T[2], fd); + { + TCGv fp32 = tcg_temp_new(TCG_TYPE_I32); + TCGv fp64 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr32(fp32, fs); + tcg_gen_helper_1_1(do_float_ceill_s, fp64, fp32); + tcg_temp_free(fp32); + gen_store_fpr64(ctx, fp64, fd); + tcg_temp_free(fp64); + } opn = "ceil.l.s"; break; case FOP(11, 16): check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], fs); - tcg_gen_helper_0_0(do_float_floorl_s); - gen_store_fpr64(ctx, fpu64_T[2], fd); + { + TCGv fp32 = tcg_temp_new(TCG_TYPE_I32); + TCGv fp64 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr32(fp32, fs); + tcg_gen_helper_1_1(do_float_floorl_s, fp64, fp32); + tcg_temp_free(fp32); + gen_store_fpr64(ctx, fp64, fd); + tcg_temp_free(fp64); + } opn = "floor.l.s"; break; case FOP(12, 16): - gen_load_fpr32(fpu32_T[0], fs); - tcg_gen_helper_0_0(do_float_roundw_s); - gen_store_fpr32(fpu32_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32(fp0, fs); + tcg_gen_helper_1_1(do_float_roundw_s, fp0, fp0); + gen_store_fpr32(fp0, fd); + tcg_temp_free(fp0); + } opn = "round.w.s"; break; case FOP(13, 16): - gen_load_fpr32(fpu32_T[0], fs); - tcg_gen_helper_0_0(do_float_truncw_s); - gen_store_fpr32(fpu32_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32(fp0, fs); + tcg_gen_helper_1_1(do_float_truncw_s, fp0, fp0); + gen_store_fpr32(fp0, fd); + tcg_temp_free(fp0); + } opn = "trunc.w.s"; break; case FOP(14, 16): - gen_load_fpr32(fpu32_T[0], fs); - tcg_gen_helper_0_0(do_float_ceilw_s); - gen_store_fpr32(fpu32_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32(fp0, fs); + tcg_gen_helper_1_1(do_float_ceilw_s, fp0, fp0); + gen_store_fpr32(fp0, fd); + tcg_temp_free(fp0); + } opn = "ceil.w.s"; break; case FOP(15, 16): - gen_load_fpr32(fpu32_T[0], fs); - tcg_gen_helper_0_0(do_float_floorw_s); - gen_store_fpr32(fpu32_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32(fp0, fs); + tcg_gen_helper_1_1(do_float_floorw_s, fp0, fp0); + gen_store_fpr32(fp0, fd); + tcg_temp_free(fp0); + } opn = "floor.w.s"; break; case FOP(17, 16): - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32(fpu32_T[2], fd); - gen_movcf_s((ft >> 2) & 0x7, ft & 0x1); - gen_store_fpr32(fpu32_T[2], fd); + gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1); opn = "movcf.s"; break; case FOP(18, 16): - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32(fpu32_T[2], fd); { int l1 = gen_new_label(); TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL); + TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32); gen_load_gpr(t0, ft); tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1); tcg_temp_free(t0); - tcg_gen_mov_i32(fpu32_T[2], fpu32_T[0]); + gen_load_fpr32(fp0, fs); + gen_store_fpr32(fp0, fd); + tcg_temp_free(fp0); gen_set_label(l1); } - gen_store_fpr32(fpu32_T[2], fd); opn = "movz.s"; break; case FOP(19, 16): - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32(fpu32_T[2], fd); { int l1 = gen_new_label(); TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL); + TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32); gen_load_gpr(t0, ft); tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); tcg_temp_free(t0); - tcg_gen_mov_i32(fpu32_T[2], fpu32_T[0]); + gen_load_fpr32(fp0, fs); + gen_store_fpr32(fp0, fd); + tcg_temp_free(fp0); gen_set_label(l1); } - gen_store_fpr32(fpu32_T[2], fd); opn = "movn.s"; break; case FOP(21, 16): check_cop1x(ctx); - gen_load_fpr32(fpu32_T[0], fs); - tcg_gen_helper_0_0(do_float_recip_s); - gen_store_fpr32(fpu32_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32(fp0, fs); + tcg_gen_helper_1_1(do_float_recip_s, fp0, fp0); + gen_store_fpr32(fp0, fd); + tcg_temp_free(fp0); + } opn = "recip.s"; break; case FOP(22, 16): check_cop1x(ctx); - gen_load_fpr32(fpu32_T[0], fs); - tcg_gen_helper_0_0(do_float_rsqrt_s); - gen_store_fpr32(fpu32_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32(fp0, fs); + tcg_gen_helper_1_1(do_float_rsqrt_s, fp0, fp0); + gen_store_fpr32(fp0, fd); + tcg_temp_free(fp0); + } opn = "rsqrt.s"; break; case FOP(28, 16): check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32(fpu32_T[2], fd); - tcg_gen_helper_0_0(do_float_recip2_s); - gen_store_fpr32(fpu32_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32(fp0, fs); + gen_load_fpr32(fp1, fd); + tcg_gen_helper_1_2(do_float_recip2_s, fp0, fp0, fp1); + tcg_temp_free(fp1); + gen_store_fpr32(fp0, fd); + tcg_temp_free(fp0); + } opn = "recip2.s"; break; case FOP(29, 16): check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], fs); - tcg_gen_helper_0_0(do_float_recip1_s); - gen_store_fpr32(fpu32_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32(fp0, fs); + tcg_gen_helper_1_1(do_float_recip1_s, fp0, fp0); + gen_store_fpr32(fp0, fd); + tcg_temp_free(fp0); + } opn = "recip1.s"; break; case FOP(30, 16): check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], fs); - tcg_gen_helper_0_0(do_float_rsqrt1_s); - gen_store_fpr32(fpu32_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32(fp0, fs); + tcg_gen_helper_1_1(do_float_rsqrt1_s, fp0, fp0); + gen_store_fpr32(fp0, fd); + tcg_temp_free(fp0); + } opn = "rsqrt1.s"; break; case FOP(31, 16): check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32(fpu32_T[2], ft); - tcg_gen_helper_0_0(do_float_rsqrt2_s); - gen_store_fpr32(fpu32_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32(fp0, fs); + gen_load_fpr32(fp1, ft); + tcg_gen_helper_1_2(do_float_rsqrt2_s, fp0, fp0, fp1); + tcg_temp_free(fp1); + gen_store_fpr32(fp0, fd); + tcg_temp_free(fp0); + } opn = "rsqrt2.s"; break; case FOP(33, 16): check_cp1_registers(ctx, fd); - gen_load_fpr32(fpu32_T[0], fs); - tcg_gen_helper_0_0(do_float_cvtd_s); - gen_store_fpr64(ctx, fpu64_T[2], fd); + { + TCGv fp32 = tcg_temp_new(TCG_TYPE_I32); + TCGv fp64 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr32(fp32, fs); + tcg_gen_helper_1_1(do_float_cvtd_s, fp64, fp32); + tcg_temp_free(fp32); + gen_store_fpr64(ctx, fp64, fd); + tcg_temp_free(fp64); + } opn = "cvt.d.s"; break; case FOP(36, 16): - gen_load_fpr32(fpu32_T[0], fs); - tcg_gen_helper_0_0(do_float_cvtw_s); - gen_store_fpr32(fpu32_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32(fp0, fs); + tcg_gen_helper_1_1(do_float_cvtw_s, fp0, fp0); + gen_store_fpr32(fp0, fd); + tcg_temp_free(fp0); + } opn = "cvt.w.s"; break; case FOP(37, 16): check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], fs); - tcg_gen_helper_0_0(do_float_cvtl_s); - gen_store_fpr64(ctx, fpu64_T[2], fd); + { + TCGv fp32 = tcg_temp_new(TCG_TYPE_I32); + TCGv fp64 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr32(fp32, fs); + tcg_gen_helper_1_1(do_float_cvtl_s, fp64, fp32); + tcg_temp_free(fp32); + gen_store_fpr64(ctx, fp64, fd); + tcg_temp_free(fp64); + } opn = "cvt.l.s"; break; case FOP(38, 16): check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32(fpu32_T[1], ft); - tcg_gen_extu_i32_i64(fpu64_T[0], fpu32_T[0]); - tcg_gen_extu_i32_i64(fpu64_T[1], fpu32_T[1]); - tcg_gen_shli_i64(fpu64_T[1], fpu64_T[1], 32); - tcg_gen_or_i64(fpu64_T[2], fpu64_T[0], fpu64_T[1]); - gen_store_fpr64(ctx, fpu64_T[2], fd); + { + TCGv fp64_0 = tcg_temp_new(TCG_TYPE_I64); + TCGv fp64_1 = tcg_temp_new(TCG_TYPE_I64); + TCGv fp32_0 = tcg_temp_new(TCG_TYPE_I32); + TCGv fp32_1 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32(fp32_0, fs); + gen_load_fpr32(fp32_1, ft); + tcg_gen_extu_i32_i64(fp64_0, fp32_0); + tcg_gen_extu_i32_i64(fp64_1, fp32_1); + tcg_temp_free(fp32_0); + tcg_temp_free(fp32_1); + tcg_gen_shli_i64(fp64_1, fp64_1, 32); + tcg_gen_or_i64(fp64_0, fp64_0, fp64_1); + tcg_temp_free(fp64_1); + gen_store_fpr64(ctx, fp64_0, fd); + tcg_temp_free(fp64_0); + } opn = "cvt.ps.s"; break; case FOP(48, 16): @@ -6326,217 +6573,351 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, case FOP(61, 16): case FOP(62, 16): case FOP(63, 16): - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32(fpu32_T[1], ft); - if (ctx->opcode & (1 << 6)) { - check_cop1x(ctx); - gen_cmpabs_s(func-48, cc); - opn = condnames_abs[func-48]; - } else { - gen_cmp_s(func-48, cc); - opn = condnames[func-48]; + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32(fp0, fs); + gen_load_fpr32(fp1, ft); + if (ctx->opcode & (1 << 6)) { + check_cop1x(ctx); + gen_cmpabs_s(func-48, fp0, fp1, cc); + opn = condnames_abs[func-48]; + } else { + gen_cmp_s(func-48, fp0, fp1, cc); + opn = condnames[func-48]; + } + tcg_temp_free(fp0); + tcg_temp_free(fp1); } break; case FOP(0, 17): check_cp1_registers(ctx, fs | ft | fd); - gen_load_fpr64(ctx, fpu64_T[0], fs); - gen_load_fpr64(ctx, fpu64_T[1], ft); - tcg_gen_helper_0_0(do_float_add_d); - gen_store_fpr64(ctx, fpu64_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, ft); + tcg_gen_helper_1_2(do_float_add_d, fp0, fp0, fp1); + tcg_temp_free(fp1); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "add.d"; optype = BINOP; break; case FOP(1, 17): check_cp1_registers(ctx, fs | ft | fd); - gen_load_fpr64(ctx, fpu64_T[0], fs); - gen_load_fpr64(ctx, fpu64_T[1], ft); - tcg_gen_helper_0_0(do_float_sub_d); - gen_store_fpr64(ctx, fpu64_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, ft); + tcg_gen_helper_1_2(do_float_sub_d, fp0, fp0, fp1); + tcg_temp_free(fp1); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "sub.d"; optype = BINOP; break; case FOP(2, 17): check_cp1_registers(ctx, fs | ft | fd); - gen_load_fpr64(ctx, fpu64_T[0], fs); - gen_load_fpr64(ctx, fpu64_T[1], ft); - tcg_gen_helper_0_0(do_float_mul_d); - gen_store_fpr64(ctx, fpu64_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, ft); + tcg_gen_helper_1_2(do_float_mul_d, fp0, fp0, fp1); + tcg_temp_free(fp1); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "mul.d"; optype = BINOP; break; case FOP(3, 17): check_cp1_registers(ctx, fs | ft | fd); - gen_load_fpr64(ctx, fpu64_T[0], fs); - gen_load_fpr64(ctx, fpu64_T[1], ft); - tcg_gen_helper_0_0(do_float_div_d); - gen_store_fpr64(ctx, fpu64_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, ft); + tcg_gen_helper_1_2(do_float_div_d, fp0, fp0, fp1); + tcg_temp_free(fp1); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "div.d"; optype = BINOP; break; case FOP(4, 17): check_cp1_registers(ctx, fs | fd); - gen_load_fpr64(ctx, fpu64_T[0], fs); - tcg_gen_helper_0_0(do_float_sqrt_d); - gen_store_fpr64(ctx, fpu64_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + tcg_gen_helper_1_1(do_float_sqrt_d, fp0, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "sqrt.d"; break; case FOP(5, 17): check_cp1_registers(ctx, fs | fd); - gen_load_fpr64(ctx, fpu64_T[0], fs); - tcg_gen_helper_0_0(do_float_abs_d); - gen_store_fpr64(ctx, fpu64_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + tcg_gen_helper_1_1(do_float_abs_d, fp0, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "abs.d"; break; case FOP(6, 17): check_cp1_registers(ctx, fs | fd); - gen_load_fpr64(ctx, fpu64_T[0], fs); - gen_store_fpr64(ctx, fpu64_T[0], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "mov.d"; break; case FOP(7, 17): check_cp1_registers(ctx, fs | fd); - gen_load_fpr64(ctx, fpu64_T[0], fs); - tcg_gen_helper_0_0(do_float_chs_d); - gen_store_fpr64(ctx, fpu64_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + tcg_gen_helper_1_1(do_float_chs_d, fp0, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "neg.d"; break; case FOP(8, 17): check_cp1_64bitmode(ctx); - gen_load_fpr64(ctx, fpu64_T[0], fs); - tcg_gen_helper_0_0(do_float_roundl_d); - gen_store_fpr64(ctx, fpu64_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + tcg_gen_helper_1_1(do_float_roundl_d, fp0, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "round.l.d"; break; case FOP(9, 17): check_cp1_64bitmode(ctx); - gen_load_fpr64(ctx, fpu64_T[0], fs); - tcg_gen_helper_0_0(do_float_truncl_d); - gen_store_fpr64(ctx, fpu64_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + tcg_gen_helper_1_1(do_float_truncl_d, fp0, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "trunc.l.d"; break; case FOP(10, 17): check_cp1_64bitmode(ctx); - gen_load_fpr64(ctx, fpu64_T[0], fs); - tcg_gen_helper_0_0(do_float_ceill_d); - gen_store_fpr64(ctx, fpu64_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + tcg_gen_helper_1_1(do_float_ceill_d, fp0, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "ceil.l.d"; break; case FOP(11, 17): check_cp1_64bitmode(ctx); - gen_load_fpr64(ctx, fpu64_T[0], fs); - tcg_gen_helper_0_0(do_float_floorl_d); - gen_store_fpr64(ctx, fpu64_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + tcg_gen_helper_1_1(do_float_floorl_d, fp0, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "floor.l.d"; break; case FOP(12, 17): check_cp1_registers(ctx, fs); - gen_load_fpr64(ctx, fpu64_T[0], fs); - tcg_gen_helper_0_0(do_float_roundw_d); - gen_store_fpr32(fpu32_T[2], fd); + { + TCGv fp32 = tcg_temp_new(TCG_TYPE_I32); + TCGv fp64 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp64, fs); + tcg_gen_helper_1_1(do_float_roundw_d, fp32, fp64); + tcg_temp_free(fp64); + gen_store_fpr32(fp32, fd); + tcg_temp_free(fp32); + } opn = "round.w.d"; break; case FOP(13, 17): check_cp1_registers(ctx, fs); - gen_load_fpr64(ctx, fpu64_T[0], fs); - tcg_gen_helper_0_0(do_float_truncw_d); - gen_store_fpr32(fpu32_T[2], fd); + { + TCGv fp32 = tcg_temp_new(TCG_TYPE_I32); + TCGv fp64 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp64, fs); + tcg_gen_helper_1_1(do_float_truncw_d, fp32, fp64); + tcg_temp_free(fp64); + gen_store_fpr32(fp32, fd); + tcg_temp_free(fp32); + } opn = "trunc.w.d"; break; case FOP(14, 17): check_cp1_registers(ctx, fs); - gen_load_fpr64(ctx, fpu64_T[0], fs); - tcg_gen_helper_0_0(do_float_ceilw_d); - gen_store_fpr32(fpu32_T[2], fd); + { + TCGv fp32 = tcg_temp_new(TCG_TYPE_I32); + TCGv fp64 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp64, fs); + tcg_gen_helper_1_1(do_float_ceilw_d, fp32, fp64); + tcg_temp_free(fp64); + gen_store_fpr32(fp32, fd); + tcg_temp_free(fp32); + } opn = "ceil.w.d"; break; case FOP(15, 17): check_cp1_registers(ctx, fs); - gen_load_fpr64(ctx, fpu64_T[0], fs); - tcg_gen_helper_0_0(do_float_floorw_d); - gen_store_fpr32(fpu32_T[2], fd); + { + TCGv fp32 = tcg_temp_new(TCG_TYPE_I32); + TCGv fp64 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp64, fs); + tcg_gen_helper_1_1(do_float_floorw_d, fp32, fp64); + tcg_temp_free(fp64); + gen_store_fpr32(fp32, fd); + tcg_temp_free(fp32); + } opn = "floor.w.d"; break; case FOP(17, 17): - gen_load_fpr64(ctx, fpu64_T[0], fs); - gen_load_fpr64(ctx, fpu64_T[2], fd); - gen_movcf_d((ft >> 2) & 0x7, ft & 0x1); - gen_store_fpr64(ctx, fpu64_T[2], fd); + gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1); opn = "movcf.d"; break; case FOP(18, 17): - gen_load_fpr64(ctx, fpu64_T[0], fs); - gen_load_fpr64(ctx, fpu64_T[2], fd); { int l1 = gen_new_label(); TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL); + TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I64); gen_load_gpr(t0, ft); tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1); tcg_temp_free(t0); - tcg_gen_mov_i64(fpu64_T[2], fpu64_T[0]); + gen_load_fpr64(ctx, fp0, fs); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); gen_set_label(l1); } - gen_store_fpr64(ctx, fpu64_T[2], fd); opn = "movz.d"; break; case FOP(19, 17): - gen_load_fpr64(ctx, fpu64_T[0], fs); - gen_load_fpr64(ctx, fpu64_T[2], fd); { int l1 = gen_new_label(); TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL); + TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I64); gen_load_gpr(t0, ft); tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); tcg_temp_free(t0); - tcg_gen_mov_i64(fpu64_T[2], fpu64_T[0]); + gen_load_fpr64(ctx, fp0, fs); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); gen_set_label(l1); } - gen_store_fpr64(ctx, fpu64_T[2], fd); opn = "movn.d"; break; case FOP(21, 17): check_cp1_64bitmode(ctx); - gen_load_fpr64(ctx, fpu64_T[0], fs); - tcg_gen_helper_0_0(do_float_recip_d); - gen_store_fpr64(ctx, fpu64_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + tcg_gen_helper_1_1(do_float_recip_d, fp0, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "recip.d"; break; case FOP(22, 17): check_cp1_64bitmode(ctx); - gen_load_fpr64(ctx, fpu64_T[0], fs); - tcg_gen_helper_0_0(do_float_rsqrt_d); - gen_store_fpr64(ctx, fpu64_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + tcg_gen_helper_1_1(do_float_rsqrt_d, fp0, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "rsqrt.d"; break; case FOP(28, 17): check_cp1_64bitmode(ctx); - gen_load_fpr64(ctx, fpu64_T[0], fs); - gen_load_fpr64(ctx, fpu64_T[2], ft); - tcg_gen_helper_0_0(do_float_recip2_d); - gen_store_fpr64(ctx, fpu64_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, ft); + tcg_gen_helper_1_2(do_float_recip2_d, fp0, fp0, fp1); + tcg_temp_free(fp1); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "recip2.d"; break; case FOP(29, 17): check_cp1_64bitmode(ctx); - gen_load_fpr64(ctx, fpu64_T[0], fs); - tcg_gen_helper_0_0(do_float_recip1_d); - gen_store_fpr64(ctx, fpu64_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + tcg_gen_helper_1_1(do_float_recip1_d, fp0, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "recip1.d"; break; case FOP(30, 17): check_cp1_64bitmode(ctx); - gen_load_fpr64(ctx, fpu64_T[0], fs); - tcg_gen_helper_0_0(do_float_rsqrt1_d); - gen_store_fpr64(ctx, fpu64_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + tcg_gen_helper_1_1(do_float_rsqrt1_d, fp0, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "rsqrt1.d"; break; case FOP(31, 17): check_cp1_64bitmode(ctx); - gen_load_fpr64(ctx, fpu64_T[0], fs); - gen_load_fpr64(ctx, fpu64_T[2], ft); - tcg_gen_helper_0_0(do_float_rsqrt2_d); - gen_store_fpr64(ctx, fpu64_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, ft); + tcg_gen_helper_1_2(do_float_rsqrt2_d, fp0, fp0, fp1); + tcg_temp_free(fp1); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "rsqrt2.d"; break; case FOP(48, 17): @@ -6555,303 +6936,434 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, case FOP(61, 17): case FOP(62, 17): case FOP(63, 17): - gen_load_fpr64(ctx, fpu64_T[0], fs); - gen_load_fpr64(ctx, fpu64_T[1], ft); - if (ctx->opcode & (1 << 6)) { - check_cop1x(ctx); - check_cp1_registers(ctx, fs | ft); - gen_cmpabs_d(func-48, cc); - opn = condnames_abs[func-48]; - } else { - check_cp1_registers(ctx, fs | ft); - gen_cmp_d(func-48, cc); - opn = condnames[func-48]; + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, ft); + if (ctx->opcode & (1 << 6)) { + check_cop1x(ctx); + check_cp1_registers(ctx, fs | ft); + gen_cmpabs_d(func-48, fp0, fp1, cc); + opn = condnames_abs[func-48]; + } else { + check_cp1_registers(ctx, fs | ft); + gen_cmp_d(func-48, fp0, fp1, cc); + opn = condnames[func-48]; + } + tcg_temp_free(fp0); + tcg_temp_free(fp1); } break; case FOP(32, 17): check_cp1_registers(ctx, fs); - gen_load_fpr64(ctx, fpu64_T[0], fs); - tcg_gen_helper_0_0(do_float_cvts_d); - gen_store_fpr32(fpu32_T[2], fd); + { + TCGv fp32 = tcg_temp_new(TCG_TYPE_I32); + TCGv fp64 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp64, fs); + tcg_gen_helper_1_1(do_float_cvts_d, fp32, fp64); + tcg_temp_free(fp64); + gen_store_fpr32(fp32, fd); + tcg_temp_free(fp32); + } opn = "cvt.s.d"; break; case FOP(36, 17): check_cp1_registers(ctx, fs); - gen_load_fpr64(ctx, fpu64_T[0], fs); - tcg_gen_helper_0_0(do_float_cvtw_d); - gen_store_fpr32(fpu32_T[2], fd); + { + TCGv fp32 = tcg_temp_new(TCG_TYPE_I32); + TCGv fp64 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp64, fs); + tcg_gen_helper_1_1(do_float_cvtw_d, fp32, fp64); + tcg_temp_free(fp64); + gen_store_fpr32(fp32, fd); + tcg_temp_free(fp32); + } opn = "cvt.w.d"; break; case FOP(37, 17): check_cp1_64bitmode(ctx); - gen_load_fpr64(ctx, fpu64_T[0], fs); - tcg_gen_helper_0_0(do_float_cvtl_d); - gen_store_fpr64(ctx, fpu64_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + tcg_gen_helper_1_1(do_float_cvtl_d, fp0, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "cvt.l.d"; break; case FOP(32, 20): - gen_load_fpr32(fpu32_T[0], fs); - tcg_gen_helper_0_0(do_float_cvts_w); - gen_store_fpr32(fpu32_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32(fp0, fs); + tcg_gen_helper_1_1(do_float_cvts_w, fp0, fp0); + gen_store_fpr32(fp0, fd); + tcg_temp_free(fp0); + } opn = "cvt.s.w"; break; case FOP(33, 20): check_cp1_registers(ctx, fd); - gen_load_fpr32(fpu32_T[0], fs); - tcg_gen_helper_0_0(do_float_cvtd_w); - gen_store_fpr64(ctx, fpu64_T[2], fd); + { + TCGv fp32 = tcg_temp_new(TCG_TYPE_I32); + TCGv fp64 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr32(fp32, fs); + tcg_gen_helper_1_1(do_float_cvtd_w, fp64, fp32); + tcg_temp_free(fp32); + gen_store_fpr64(ctx, fp64, fd); + tcg_temp_free(fp64); + } opn = "cvt.d.w"; break; case FOP(32, 21): check_cp1_64bitmode(ctx); - gen_load_fpr64(ctx, fpu64_T[0], fs); - tcg_gen_helper_0_0(do_float_cvts_l); - gen_store_fpr32(fpu32_T[2], fd); + { + TCGv fp32 = tcg_temp_new(TCG_TYPE_I32); + TCGv fp64 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp64, fs); + tcg_gen_helper_1_1(do_float_cvts_l, fp32, fp64); + tcg_temp_free(fp64); + gen_store_fpr32(fp32, fd); + tcg_temp_free(fp32); + } opn = "cvt.s.l"; break; case FOP(33, 21): check_cp1_64bitmode(ctx); - gen_load_fpr64(ctx, fpu64_T[0], fs); - tcg_gen_helper_0_0(do_float_cvtd_l); - gen_store_fpr64(ctx, fpu64_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + tcg_gen_helper_1_1(do_float_cvtd_l, fp0, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "cvt.d.l"; break; case FOP(38, 20): check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32h(fpu32h_T[0], fs); - tcg_gen_helper_0_0(do_float_cvtps_pw); - gen_store_fpr32(fpu32_T[2], fd); - gen_store_fpr32h(fpu32h_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + tcg_gen_helper_1_1(do_float_cvtps_pw, fp0, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "cvt.ps.pw"; break; case FOP(0, 22): check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32h(fpu32h_T[0], fs); - gen_load_fpr32(fpu32_T[1], ft); - gen_load_fpr32h(fpu32h_T[1], ft); - tcg_gen_helper_0_0(do_float_add_ps); - gen_store_fpr32(fpu32_T[2], fd); - gen_store_fpr32h(fpu32h_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, ft); + tcg_gen_helper_1_2(do_float_add_ps, fp0, fp0, fp1); + tcg_temp_free(fp1); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "add.ps"; break; case FOP(1, 22): check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32h(fpu32h_T[0], fs); - gen_load_fpr32(fpu32_T[1], ft); - gen_load_fpr32h(fpu32h_T[1], ft); - tcg_gen_helper_0_0(do_float_sub_ps); - gen_store_fpr32(fpu32_T[2], fd); - gen_store_fpr32h(fpu32h_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, ft); + tcg_gen_helper_1_2(do_float_sub_ps, fp0, fp0, fp1); + tcg_temp_free(fp1); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "sub.ps"; break; case FOP(2, 22): check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32h(fpu32h_T[0], fs); - gen_load_fpr32(fpu32_T[1], ft); - gen_load_fpr32h(fpu32h_T[1], ft); - tcg_gen_helper_0_0(do_float_mul_ps); - gen_store_fpr32(fpu32_T[2], fd); - gen_store_fpr32h(fpu32h_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, ft); + tcg_gen_helper_1_2(do_float_mul_ps, fp0, fp0, fp1); + tcg_temp_free(fp1); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "mul.ps"; break; case FOP(5, 22): check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32h(fpu32h_T[0], fs); - tcg_gen_helper_0_0(do_float_abs_ps); - gen_store_fpr32(fpu32_T[2], fd); - gen_store_fpr32h(fpu32h_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + tcg_gen_helper_1_1(do_float_abs_ps, fp0, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "abs.ps"; break; case FOP(6, 22): check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32h(fpu32h_T[0], fs); - gen_store_fpr32(fpu32_T[0], fd); - gen_store_fpr32h(fpu32h_T[0], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "mov.ps"; break; case FOP(7, 22): check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32h(fpu32h_T[0], fs); - tcg_gen_helper_0_0(do_float_chs_ps); - gen_store_fpr32(fpu32_T[2], fd); - gen_store_fpr32h(fpu32h_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + tcg_gen_helper_1_1(do_float_chs_ps, fp0, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "neg.ps"; break; case FOP(17, 22): check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32h(fpu32h_T[0], fs); - gen_load_fpr32(fpu32_T[2], fd); - gen_load_fpr32h(fpu32h_T[2], fd); - gen_movcf_ps((ft >> 2) & 0x7, ft & 0x1); - gen_store_fpr32(fpu32_T[2], fd); - gen_store_fpr32h(fpu32h_T[2], fd); + gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1); opn = "movcf.ps"; break; case FOP(18, 22): check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32h(fpu32h_T[0], fs); - gen_load_fpr32(fpu32_T[2], fd); - gen_load_fpr32h(fpu32h_T[2], fd); { int l1 = gen_new_label(); TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL); + TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32); + TCGv fph0 = tcg_temp_local_new(TCG_TYPE_I32); gen_load_gpr(t0, ft); tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1); tcg_temp_free(t0); - tcg_gen_mov_i32(fpu32_T[2], fpu32_T[0]); - tcg_gen_mov_i32(fpu32h_T[2], fpu32h_T[0]); + gen_load_fpr32(fp0, fs); + gen_load_fpr32h(fph0, fs); + gen_store_fpr32(fp0, fd); + gen_store_fpr32h(fph0, fd); + tcg_temp_free(fp0); + tcg_temp_free(fph0); gen_set_label(l1); } - gen_store_fpr32(fpu32_T[2], fd); - gen_store_fpr32h(fpu32h_T[2], fd); opn = "movz.ps"; break; case FOP(19, 22): check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32h(fpu32h_T[0], fs); - gen_load_fpr32(fpu32_T[2], fd); - gen_load_fpr32h(fpu32h_T[2], fd); { int l1 = gen_new_label(); TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL); + TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32); + TCGv fph0 = tcg_temp_local_new(TCG_TYPE_I32); gen_load_gpr(t0, ft); tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); tcg_temp_free(t0); - tcg_gen_mov_i32(fpu32_T[2], fpu32_T[0]); - tcg_gen_mov_i32(fpu32h_T[2], fpu32h_T[0]); + gen_load_fpr32(fp0, fs); + gen_load_fpr32h(fph0, fs); + gen_store_fpr32(fp0, fd); + gen_store_fpr32h(fph0, fd); + tcg_temp_free(fp0); + tcg_temp_free(fph0); gen_set_label(l1); } - gen_store_fpr32(fpu32_T[2], fd); - gen_store_fpr32h(fpu32h_T[2], fd); opn = "movn.ps"; break; case FOP(24, 22): check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], ft); - gen_load_fpr32h(fpu32h_T[0], ft); - gen_load_fpr32(fpu32_T[1], fs); - gen_load_fpr32h(fpu32h_T[1], fs); - tcg_gen_helper_0_0(do_float_addr_ps); - gen_store_fpr32(fpu32_T[2], fd); - gen_store_fpr32h(fpu32h_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, ft); + gen_load_fpr64(ctx, fp1, fs); + tcg_gen_helper_1_2(do_float_addr_ps, fp0, fp0, fp1); + tcg_temp_free(fp1); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "addr.ps"; break; case FOP(26, 22): check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], ft); - gen_load_fpr32h(fpu32h_T[0], ft); - gen_load_fpr32(fpu32_T[1], fs); - gen_load_fpr32h(fpu32h_T[1], fs); - tcg_gen_helper_0_0(do_float_mulr_ps); - gen_store_fpr32(fpu32_T[2], fd); - gen_store_fpr32h(fpu32h_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, ft); + gen_load_fpr64(ctx, fp1, fs); + tcg_gen_helper_1_2(do_float_mulr_ps, fp0, fp0, fp1); + tcg_temp_free(fp1); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "mulr.ps"; break; case FOP(28, 22): check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32h(fpu32h_T[0], fs); - gen_load_fpr32(fpu32_T[2], fd); - gen_load_fpr32h(fpu32h_T[2], fd); - tcg_gen_helper_0_0(do_float_recip2_ps); - gen_store_fpr32(fpu32_T[2], fd); - gen_store_fpr32h(fpu32h_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, fd); + tcg_gen_helper_1_2(do_float_recip2_ps, fp0, fp0, fp1); + tcg_temp_free(fp1); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "recip2.ps"; break; case FOP(29, 22): check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32h(fpu32h_T[0], fs); - tcg_gen_helper_0_0(do_float_recip1_ps); - gen_store_fpr32(fpu32_T[2], fd); - gen_store_fpr32h(fpu32h_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + tcg_gen_helper_1_1(do_float_recip1_ps, fp0, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "recip1.ps"; break; case FOP(30, 22): check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32h(fpu32h_T[0], fs); - tcg_gen_helper_0_0(do_float_rsqrt1_ps); - gen_store_fpr32(fpu32_T[2], fd); - gen_store_fpr32h(fpu32h_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + tcg_gen_helper_1_1(do_float_rsqrt1_ps, fp0, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "rsqrt1.ps"; break; case FOP(31, 22): check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32h(fpu32h_T[0], fs); - gen_load_fpr32(fpu32_T[2], ft); - gen_load_fpr32h(fpu32h_T[2], ft); - tcg_gen_helper_0_0(do_float_rsqrt2_ps); - gen_store_fpr32(fpu32_T[2], fd); - gen_store_fpr32h(fpu32h_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, ft); + tcg_gen_helper_1_2(do_float_rsqrt2_ps, fp0, fp0, fp1); + tcg_temp_free(fp1); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "rsqrt2.ps"; break; case FOP(32, 22): check_cp1_64bitmode(ctx); - gen_load_fpr32h(fpu32h_T[0], fs); - tcg_gen_helper_0_0(do_float_cvts_pu); - gen_store_fpr32(fpu32_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32h(fp0, fs); + tcg_gen_helper_1_1(do_float_cvts_pu, fp0, fp0); + gen_store_fpr32(fp0, fd); + tcg_temp_free(fp0); + } opn = "cvt.s.pu"; break; case FOP(36, 22): check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32h(fpu32h_T[0], fs); - tcg_gen_helper_0_0(do_float_cvtpw_ps); - gen_store_fpr32(fpu32_T[2], fd); - gen_store_fpr32h(fpu32h_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + tcg_gen_helper_1_1(do_float_cvtpw_ps, fp0, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "cvt.pw.ps"; break; case FOP(40, 22): check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], fs); - tcg_gen_helper_0_0(do_float_cvts_pl); - gen_store_fpr32(fpu32_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32(fp0, fs); + tcg_gen_helper_1_1(do_float_cvts_pl, fp0, fp0); + gen_store_fpr32(fp0, fd); + tcg_temp_free(fp0); + } opn = "cvt.s.pl"; break; case FOP(44, 22): check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32(fpu32_T[1], ft); - gen_store_fpr32h(fpu32_T[0], fd); - gen_store_fpr32(fpu32_T[1], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32(fp0, fs); + gen_load_fpr32(fp1, ft); + gen_store_fpr32h(fp0, fd); + gen_store_fpr32(fp1, fd); + tcg_temp_free(fp0); + tcg_temp_free(fp1); + } opn = "pll.ps"; break; case FOP(45, 22): check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32h(fpu32h_T[1], ft); - gen_store_fpr32(fpu32h_T[1], fd); - gen_store_fpr32h(fpu32_T[0], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32(fp0, fs); + gen_load_fpr32h(fp1, ft); + gen_store_fpr32(fp1, fd); + gen_store_fpr32h(fp0, fd); + tcg_temp_free(fp0); + tcg_temp_free(fp1); + } opn = "plu.ps"; break; case FOP(46, 22): check_cp1_64bitmode(ctx); - gen_load_fpr32h(fpu32h_T[0], fs); - gen_load_fpr32(fpu32_T[1], ft); - gen_store_fpr32(fpu32_T[1], fd); - gen_store_fpr32h(fpu32h_T[0], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32h(fp0, fs); + gen_load_fpr32(fp1, ft); + gen_store_fpr32(fp1, fd); + gen_store_fpr32h(fp0, fd); + tcg_temp_free(fp0); + tcg_temp_free(fp1); + } opn = "pul.ps"; break; case FOP(47, 22): check_cp1_64bitmode(ctx); - gen_load_fpr32h(fpu32h_T[0], fs); - gen_load_fpr32h(fpu32h_T[1], ft); - gen_store_fpr32(fpu32h_T[1], fd); - gen_store_fpr32h(fpu32h_T[0], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32h(fp0, fs); + gen_load_fpr32h(fp1, ft); + gen_store_fpr32(fp1, fd); + gen_store_fpr32h(fp0, fd); + tcg_temp_free(fp0); + tcg_temp_free(fp1); + } opn = "puu.ps"; break; case FOP(48, 22): @@ -6871,16 +7383,21 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, case FOP(62, 22): case FOP(63, 22): check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32h(fpu32h_T[0], fs); - gen_load_fpr32(fpu32_T[1], ft); - gen_load_fpr32h(fpu32h_T[1], ft); - if (ctx->opcode & (1 << 6)) { - gen_cmpabs_ps(func-48, cc); - opn = condnames_abs[func-48]; - } else { - gen_cmp_ps(func-48, cc); - opn = condnames[func-48]; + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, ft); + if (ctx->opcode & (1 << 6)) { + gen_cmpabs_ps(func-48, fp0, fp1, cc); + opn = condnames_abs[func-48]; + } else { + gen_cmp_ps(func-48, fp0, fp1, cc); + opn = condnames[func-48]; + } + tcg_temp_free(fp0); + tcg_temp_free(fp1); } break; default: @@ -6924,44 +7441,74 @@ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc, switch (opc) { case OPC_LWXC1: check_cop1x(ctx); - tcg_gen_qemu_ld32s(fpu32_T[0], t0, ctx->mem_idx); - gen_store_fpr32(fpu32_T[0], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + + tcg_gen_qemu_ld32s(fp0, t0, ctx->mem_idx); + gen_store_fpr32(fp0, fd); + tcg_temp_free(fp0); + } opn = "lwxc1"; break; case OPC_LDXC1: check_cop1x(ctx); check_cp1_registers(ctx, fd); - tcg_gen_qemu_ld64(fpu64_T[0], t0, ctx->mem_idx); - gen_store_fpr64(ctx, fpu64_T[0], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + + tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "ldxc1"; break; case OPC_LUXC1: check_cp1_64bitmode(ctx); tcg_gen_andi_tl(t0, t0, ~0x7); - tcg_gen_qemu_ld64(fpu64_T[0], t0, ctx->mem_idx); - gen_store_fpr64(ctx, fpu64_T[0], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + + tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free(fp0); + } opn = "luxc1"; break; case OPC_SWXC1: check_cop1x(ctx); - gen_load_fpr32(fpu32_T[0], fs); - tcg_gen_qemu_st32(fpu32_T[0], t0, ctx->mem_idx); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32(fp0, fs); + tcg_gen_qemu_st32(fp0, t0, ctx->mem_idx); + tcg_temp_free(fp0); + } opn = "swxc1"; store = 1; break; case OPC_SDXC1: check_cop1x(ctx); check_cp1_registers(ctx, fs); - gen_load_fpr64(ctx, fpu64_T[0], fs); - tcg_gen_qemu_st64(fpu64_T[0], t0, ctx->mem_idx); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx); + tcg_temp_free(fp0); + } opn = "sdxc1"; store = 1; break; case OPC_SUXC1: check_cp1_64bitmode(ctx); - gen_load_fpr64(ctx, fpu64_T[0], fs); tcg_gen_andi_tl(t0, t0, ~0x7); - tcg_gen_qemu_st64(fpu64_T[0], t0, ctx->mem_idx); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx); + tcg_temp_free(fp0); + } opn = "suxc1"; store = 1; break; @@ -6988,162 +7535,260 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, check_cp1_64bitmode(ctx); { TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL); + TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32); + TCGv fph0 = tcg_temp_local_new(TCG_TYPE_I32); + TCGv fp1 = tcg_temp_local_new(TCG_TYPE_I32); + TCGv fph1 = tcg_temp_local_new(TCG_TYPE_I32); int l1 = gen_new_label(); int l2 = gen_new_label(); gen_load_gpr(t0, fr); tcg_gen_andi_tl(t0, t0, 0x7); - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32h(fpu32h_T[0], fs); - gen_load_fpr32(fpu32_T[1], ft); - gen_load_fpr32h(fpu32h_T[1], ft); + gen_load_fpr32(fp0, fs); + gen_load_fpr32h(fph0, fs); + gen_load_fpr32(fp1, ft); + gen_load_fpr32h(fph1, ft); tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1); - tcg_gen_mov_i32(fpu32_T[2], fpu32_T[0]); - tcg_gen_mov_i32(fpu32h_T[2], fpu32h_T[0]); + gen_store_fpr32(fp0, fd); + gen_store_fpr32h(fph0, fd); tcg_gen_br(l2); gen_set_label(l1); tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2); tcg_temp_free(t0); #ifdef TARGET_WORDS_BIGENDIAN - tcg_gen_mov_i32(fpu32h_T[2], fpu32_T[0]); - tcg_gen_mov_i32(fpu32_T[2], fpu32h_T[1]); + gen_store_fpr32(fph1, fd); + gen_store_fpr32h(fp0, fd); #else - tcg_gen_mov_i32(fpu32h_T[2], fpu32_T[1]); - tcg_gen_mov_i32(fpu32_T[2], fpu32h_T[0]); + gen_store_fpr32(fph0, fd); + gen_store_fpr32h(fp1, fd); #endif gen_set_label(l2); + tcg_temp_free(fp0); + tcg_temp_free(fph0); + tcg_temp_free(fp1); + tcg_temp_free(fph1); } - gen_store_fpr32(fpu32_T[2], fd); - gen_store_fpr32h(fpu32h_T[2], fd); opn = "alnv.ps"; break; case OPC_MADD_S: check_cop1x(ctx); - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32(fpu32_T[1], ft); - gen_load_fpr32(fpu32_T[2], fr); - tcg_gen_helper_0_0(do_float_muladd_s); - gen_store_fpr32(fpu32_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I32); + TCGv fp2 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32(fp0, fs); + gen_load_fpr32(fp1, ft); + gen_load_fpr32(fp2, fr); + tcg_gen_helper_1_3(do_float_muladd_s, fp2, fp0, fp1, fp2); + tcg_temp_free(fp0); + tcg_temp_free(fp1); + gen_store_fpr32(fp2, fd); + tcg_temp_free(fp2); + } opn = "madd.s"; break; case OPC_MADD_D: check_cop1x(ctx); check_cp1_registers(ctx, fd | fs | ft | fr); - gen_load_fpr64(ctx, fpu64_T[0], fs); - gen_load_fpr64(ctx, fpu64_T[1], ft); - gen_load_fpr64(ctx, fpu64_T[2], fr); - tcg_gen_helper_0_0(do_float_muladd_d); - gen_store_fpr64(ctx, fpu64_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I64); + TCGv fp2 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, ft); + gen_load_fpr64(ctx, fp2, fr); + tcg_gen_helper_1_3(do_float_muladd_d, fp2, fp0, fp1, fp2); + tcg_temp_free(fp0); + tcg_temp_free(fp1); + gen_store_fpr64(ctx, fp2, fd); + tcg_temp_free(fp2); + } opn = "madd.d"; break; case OPC_MADD_PS: check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32h(fpu32h_T[0], fs); - gen_load_fpr32(fpu32_T[1], ft); - gen_load_fpr32h(fpu32h_T[1], ft); - gen_load_fpr32(fpu32_T[2], fr); - gen_load_fpr32h(fpu32h_T[2], fr); - tcg_gen_helper_0_0(do_float_muladd_ps); - gen_store_fpr32(fpu32_T[2], fd); - gen_store_fpr32h(fpu32h_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I64); + TCGv fp2 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, ft); + gen_load_fpr64(ctx, fp2, fr); + tcg_gen_helper_1_3(do_float_muladd_ps, fp2, fp0, fp1, fp2); + tcg_temp_free(fp0); + tcg_temp_free(fp1); + gen_store_fpr64(ctx, fp2, fd); + tcg_temp_free(fp2); + } opn = "madd.ps"; break; case OPC_MSUB_S: check_cop1x(ctx); - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32(fpu32_T[1], ft); - gen_load_fpr32(fpu32_T[2], fr); - tcg_gen_helper_0_0(do_float_mulsub_s); - gen_store_fpr32(fpu32_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I32); + TCGv fp2 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32(fp0, fs); + gen_load_fpr32(fp1, ft); + gen_load_fpr32(fp2, fr); + tcg_gen_helper_1_3(do_float_mulsub_s, fp2, fp0, fp1, fp2); + tcg_temp_free(fp0); + tcg_temp_free(fp1); + gen_store_fpr32(fp2, fd); + tcg_temp_free(fp2); + } opn = "msub.s"; break; case OPC_MSUB_D: check_cop1x(ctx); check_cp1_registers(ctx, fd | fs | ft | fr); - gen_load_fpr64(ctx, fpu64_T[0], fs); - gen_load_fpr64(ctx, fpu64_T[1], ft); - gen_load_fpr64(ctx, fpu64_T[2], fr); - tcg_gen_helper_0_0(do_float_mulsub_d); - gen_store_fpr64(ctx, fpu64_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I64); + TCGv fp2 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, ft); + gen_load_fpr64(ctx, fp2, fr); + tcg_gen_helper_1_3(do_float_mulsub_d, fp2, fp0, fp1, fp2); + tcg_temp_free(fp0); + tcg_temp_free(fp1); + gen_store_fpr64(ctx, fp2, fd); + tcg_temp_free(fp2); + } opn = "msub.d"; break; case OPC_MSUB_PS: check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32h(fpu32h_T[0], fs); - gen_load_fpr32(fpu32_T[1], ft); - gen_load_fpr32h(fpu32h_T[1], ft); - gen_load_fpr32(fpu32_T[2], fr); - gen_load_fpr32h(fpu32h_T[2], fr); - tcg_gen_helper_0_0(do_float_mulsub_ps); - gen_store_fpr32(fpu32_T[2], fd); - gen_store_fpr32h(fpu32h_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I64); + TCGv fp2 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, ft); + gen_load_fpr64(ctx, fp2, fr); + tcg_gen_helper_1_3(do_float_mulsub_ps, fp2, fp0, fp1, fp2); + tcg_temp_free(fp0); + tcg_temp_free(fp1); + gen_store_fpr64(ctx, fp2, fd); + tcg_temp_free(fp2); + } opn = "msub.ps"; break; case OPC_NMADD_S: check_cop1x(ctx); - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32(fpu32_T[1], ft); - gen_load_fpr32(fpu32_T[2], fr); - tcg_gen_helper_0_0(do_float_nmuladd_s); - gen_store_fpr32(fpu32_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I32); + TCGv fp2 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32(fp0, fs); + gen_load_fpr32(fp1, ft); + gen_load_fpr32(fp2, fr); + tcg_gen_helper_1_3(do_float_nmuladd_s, fp2, fp0, fp1, fp2); + tcg_temp_free(fp0); + tcg_temp_free(fp1); + gen_store_fpr32(fp2, fd); + tcg_temp_free(fp2); + } opn = "nmadd.s"; break; case OPC_NMADD_D: check_cop1x(ctx); check_cp1_registers(ctx, fd | fs | ft | fr); - gen_load_fpr64(ctx, fpu64_T[0], fs); - gen_load_fpr64(ctx, fpu64_T[1], ft); - gen_load_fpr64(ctx, fpu64_T[2], fr); - tcg_gen_helper_0_0(do_float_nmuladd_d); - gen_store_fpr64(ctx, fpu64_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I64); + TCGv fp2 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, ft); + gen_load_fpr64(ctx, fp2, fr); + tcg_gen_helper_1_3(do_float_nmuladd_d, fp2, fp0, fp1, fp2); + tcg_temp_free(fp0); + tcg_temp_free(fp1); + gen_store_fpr64(ctx, fp2, fd); + tcg_temp_free(fp2); + } opn = "nmadd.d"; break; case OPC_NMADD_PS: check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32h(fpu32h_T[0], fs); - gen_load_fpr32(fpu32_T[1], ft); - gen_load_fpr32h(fpu32h_T[1], ft); - gen_load_fpr32(fpu32_T[2], fr); - gen_load_fpr32h(fpu32h_T[2], fr); - tcg_gen_helper_0_0(do_float_nmuladd_ps); - gen_store_fpr32(fpu32_T[2], fd); - gen_store_fpr32h(fpu32h_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I64); + TCGv fp2 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, ft); + gen_load_fpr64(ctx, fp2, fr); + tcg_gen_helper_1_3(do_float_nmuladd_ps, fp2, fp0, fp1, fp2); + tcg_temp_free(fp0); + tcg_temp_free(fp1); + gen_store_fpr64(ctx, fp2, fd); + tcg_temp_free(fp2); + } opn = "nmadd.ps"; break; case OPC_NMSUB_S: check_cop1x(ctx); - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32(fpu32_T[1], ft); - gen_load_fpr32(fpu32_T[2], fr); - tcg_gen_helper_0_0(do_float_nmulsub_s); - gen_store_fpr32(fpu32_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I32); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I32); + TCGv fp2 = tcg_temp_new(TCG_TYPE_I32); + + gen_load_fpr32(fp0, fs); + gen_load_fpr32(fp1, ft); + gen_load_fpr32(fp2, fr); + tcg_gen_helper_1_3(do_float_nmulsub_s, fp2, fp0, fp1, fp2); + tcg_temp_free(fp0); + tcg_temp_free(fp1); + gen_store_fpr32(fp2, fd); + tcg_temp_free(fp2); + } opn = "nmsub.s"; break; case OPC_NMSUB_D: check_cop1x(ctx); check_cp1_registers(ctx, fd | fs | ft | fr); - gen_load_fpr64(ctx, fpu64_T[0], fs); - gen_load_fpr64(ctx, fpu64_T[1], ft); - gen_load_fpr64(ctx, fpu64_T[2], fr); - tcg_gen_helper_0_0(do_float_nmulsub_d); - gen_store_fpr64(ctx, fpu64_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I64); + TCGv fp2 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, ft); + gen_load_fpr64(ctx, fp2, fr); + tcg_gen_helper_1_3(do_float_nmulsub_d, fp2, fp0, fp1, fp2); + tcg_temp_free(fp0); + tcg_temp_free(fp1); + gen_store_fpr64(ctx, fp2, fd); + tcg_temp_free(fp2); + } opn = "nmsub.d"; break; case OPC_NMSUB_PS: check_cp1_64bitmode(ctx); - gen_load_fpr32(fpu32_T[0], fs); - gen_load_fpr32h(fpu32h_T[0], fs); - gen_load_fpr32(fpu32_T[1], ft); - gen_load_fpr32h(fpu32h_T[1], ft); - gen_load_fpr32(fpu32_T[2], fr); - gen_load_fpr32h(fpu32h_T[2], fr); - tcg_gen_helper_0_0(do_float_nmulsub_ps); - gen_store_fpr32(fpu32_T[2], fd); - gen_store_fpr32h(fpu32h_T[2], fd); + { + TCGv fp0 = tcg_temp_new(TCG_TYPE_I64); + TCGv fp1 = tcg_temp_new(TCG_TYPE_I64); + TCGv fp2 = tcg_temp_new(TCG_TYPE_I64); + + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, ft); + gen_load_fpr64(ctx, fp2, fr); + tcg_gen_helper_1_3(do_float_nmulsub_ps, fp2, fp0, fp1, fp2); + tcg_temp_free(fp0); + tcg_temp_free(fp1); + gen_store_fpr64(ctx, fp2, fd); + tcg_temp_free(fp2); + } opn = "nmsub.ps"; break; default: @@ -7994,9 +8639,6 @@ void fpu_dump_state(CPUState *env, FILE *f, fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n", env->fpu->fcr0, env->fpu->fcr31, is_fpu64, env->fpu->fp_status, get_float_exception_flags(&env->fpu->fp_status)); - fpu_fprintf(f, "FT0: "); printfpr(&env->ft0); - fpu_fprintf(f, "FT1: "); printfpr(&env->ft1); - fpu_fprintf(f, "FT2: "); printfpr(&env->ft2); for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) { fpu_fprintf(f, "%3s: ", fregnames[i]); printfpr(&env->fpu->fpr[i]); @@ -8102,16 +8744,6 @@ static void mips_tcg_init(void) #define DEF_HELPER(ret, name, params) tcg_register_helper(name, #name); #include "helper.h" - fpu32_T[0] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0, offsetof(CPUState, ft0.w[FP_ENDIAN_IDX]), "WT0"); - fpu32_T[1] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0, offsetof(CPUState, ft1.w[FP_ENDIAN_IDX]), "WT1"); - fpu32_T[2] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0, offsetof(CPUState, ft2.w[FP_ENDIAN_IDX]), "WT2"); - fpu64_T[0] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0, offsetof(CPUState, ft0.d), "DT0"); - fpu64_T[1] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0, offsetof(CPUState, ft1.d), "DT1"); - fpu64_T[2] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0, offsetof(CPUState, ft2.d), "DT2"); - fpu32h_T[0] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0, offsetof(CPUState, ft0.w[!FP_ENDIAN_IDX]), "WTH0"); - fpu32h_T[1] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0, offsetof(CPUState, ft1.w[!FP_ENDIAN_IDX]), "WTH1"); - fpu32h_T[2] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0, offsetof(CPUState, ft2.w[!FP_ENDIAN_IDX]), "WTH2"); - inited = 1; } -- cgit v1.2.3 From 266910c4346a24dff83ec01c7e1fa87eb938243f Mon Sep 17 00:00:00 2001 From: pbrook Date: Wed, 9 Jul 2008 15:31:50 +0000 Subject: Avoid decremented overflow. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4862 c046a42c-6fe2-441c-8c8c-71466251a162 --- exec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exec.c b/exec.c index 4f7a027d6..5b43172f3 100644 --- a/exec.c +++ b/exec.c @@ -1432,7 +1432,7 @@ void cpu_interrupt(CPUState *env, int mask) signals are used primarily to interrupt blocking syscalls. */ #else if (use_icount) { - env->icount_decr.u16.high = 0x8000; + env->icount_decr.u16.high = 0xffff; #ifndef CONFIG_USER_ONLY /* CPU_INTERRUPT_EXIT isn't a real interrupt. It just means an async event happened and we need to process it. */ -- cgit v1.2.3 From a7bb29ba877e4f80f0029b99256e974d87460cab Mon Sep 17 00:00:00 2001 From: malc Date: Wed, 9 Jul 2008 19:25:24 +0000 Subject: Call proper function when trying to set period size git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4863 c046a42c-6fe2-441c-8c8c-71466251a162 --- audio/alsaaudio.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index ba80deac1..4d47aa006 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -385,12 +385,14 @@ static int alsa_open (int in, struct alsa_params_req *req, obt = ptime; } else { + int dir = 0; snd_pcm_uframes_t psize = req->period_size; - err = snd_pcm_hw_params_set_buffer_size_near ( + err = snd_pcm_hw_params_set_period_size_near ( handle, hw_params, - &psize + &psize, + &dir ); obt = psize; } -- cgit v1.2.3 From 64333899dc98682b72b696db8c062f25f220680c Mon Sep 17 00:00:00 2001 From: malc Date: Wed, 9 Jul 2008 19:25:28 +0000 Subject: Warn about rejected buffer/period size/time when it was specified by the user git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4864 c046a42c-6fe2-441c-8c8c-71466251a162 --- audio/alsaaudio.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 4d47aa006..867e15b41 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -67,6 +67,7 @@ struct alsa_params_req { snd_pcm_format_t fmt; int nchannels; int size_in_usec; + int override_mask; unsigned int buffer_size; unsigned int period_size; }; @@ -364,7 +365,7 @@ static int alsa_open (int in, struct alsa_params_req *req, goto err; } - if (obt - req->buffer_size) + if ((req->override_mask & 2) && (obt - req->buffer_size)) dolog ("Requested buffer %s %u was rejected, using %lu\n", size_in_usec ? "time" : "size", req->buffer_size, obt); } @@ -403,7 +404,7 @@ static int alsa_open (int in, struct alsa_params_req *req, goto err; } - if (obt - req->period_size) + if ((req->override_mask & 1) && (obt - req->period_size)) dolog ("Requested period %s %u was rejected, using %lu\n", size_in_usec ? "time" : "size", req->period_size, obt); } @@ -624,6 +625,8 @@ static int alsa_init_out (HWVoiceOut *hw, audsettings_t *as) req.period_size = conf.period_size_out; req.buffer_size = conf.buffer_size_out; req.size_in_usec = conf.size_in_usec_out; + req.override_mask = !!conf.period_size_out_overridden + | (!!conf.buffer_size_out_overridden << 1); if (alsa_open (0, &req, &obt, &handle)) { return -1; @@ -702,6 +705,8 @@ static int alsa_init_in (HWVoiceIn *hw, audsettings_t *as) req.period_size = conf.period_size_in; req.buffer_size = conf.buffer_size_in; req.size_in_usec = conf.size_in_usec_in; + req.override_mask = !!conf.period_size_in_overridden + | (!!conf.buffer_size_in_overridden << 1); if (alsa_open (1, &req, &obt, &handle)) { return -1; -- cgit v1.2.3 From adf7d8fb44a47e3b4d7cdbf1f1c229b853ad97ed Mon Sep 17 00:00:00 2001 From: malc Date: Wed, 9 Jul 2008 19:25:30 +0000 Subject: Restore old value of buffer_size This brings latency down to acceptable levels when using dmix git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4865 c046a42c-6fe2-441c-8c8c-71466251a162 --- audio/alsaaudio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 867e15b41..a79cc403c 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -58,6 +58,7 @@ static struct { int period_size_out_overridden; int verbose; } conf = { + .buffer_size_out = 1024, .pcm_name_out = "default", .pcm_name_in = "default", }; -- cgit v1.2.3