Patchwork [RFC] NeXT emulation on QEMU

login
register
mail settings
Submitter Bryce Lanham
Date Aug. 17, 2011, 7:19 p.m.
Message ID <CAKbio+n-ukkVKapf=5+KFQH=ov5HfR3g6SJT3_hSSSKx=3VqvA@mail.gmail.com>
Download mbox | patch
Permalink /patch/110345/
State New
Headers show

Comments

Bryce Lanham - Aug. 17, 2011, 7:19 p.m.
Hi,

I have been working on adding NeXT black hardware support to QEMU for
Google Summer of Code. While only a base level of hardware is
implemented, I need to have the code in upstream before the end of the
program. I based my work off of Laurent Vivier's work on the m68k
core, so that work would also need to be upstreamed as well.

It's a bit rough, and could use a bit of polishing, but Natalia wants
to have this upstream by the Monday deadline. I wanted to post this
earlier, but I've been sick the past couple of days.

Bryce Lanham
Peter Maydell - Aug. 17, 2011, 8:03 p.m.
On 17 August 2011 20:19, Bryce Lanham <blanham@gmail.com> wrote:
> I have been working on adding NeXT black hardware support to QEMU for
> Google Summer of Code. While only a base level of hardware is
> implemented, I need to have the code in upstream before the end of the
> program. I based my work off of Laurent Vivier's work on the m68k
> core, so that work would also need to be upstreamed as well.

You've messed something up in your patch generation process here:
there are a lot of changes which have no relation to NeXT support,
like:

> diff --git bswap.h bswap.h
> index f41bebe..13fd5cf 100644
> --- bswap.h
> +++ bswap.h
> @@ -533,7 +533,7 @@ static inline int lduw_be_p(const void *ptr)
>                   : "m" (*(uint16_t *)ptr));
>     return val;
>  #else
> -    const uint8_t *b = ptr;
> +    const uint8_t *b = (const uint8_t *)ptr;
>     return ((b[0] << 8) | b[1]);
>  #endif
>  }

and:

> diff --git fpu/softfloat.c fpu/softfloat.c
> index 7951a0e..dbce683 100644
> --- fpu/softfloat.c
> +++ fpu/softfloat.c
> @@ -768,7 +768,9 @@ static floatx80
>                ) {
>                 return packFloatx80( zSign, 0x7FFE, ~ roundMask );
>             }
> -            return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
> +            return packFloatx80( zSign,
> +                                floatx80_default_inf_high,
> +                                floatx80_default_inf_low );
>         }
>         if ( zExp <= 0 ) {
>             isTiny =

just to pick a few early examples.

Please fix this and try again; this isn't reviewable as it stands,
I'm afraid.

Large new features like a new platform and devices should
also ideally be split into coherent logical patches for ease of
review. http://wiki.qemu.org/Contribute/SubmitAPatch has a few
further remarks. I'd also suggest using git-format-patch / git-send-email
to get the patch mail formatting right.

-- PMM

Patch

diff --git .gitignore .gitignore
index 59c343c..fed07c5 100644
--- .gitignore
+++ .gitignore
@@ -71,3 +71,12 @@  cscope.*
 tags
 TAGS
 *~
+tests/m68k/fabs
+tests/m68k/fdiv
+tests/m68k/fmove
+tests/m68k/fmovecr
+tests/m68k/fmovem
+tests/m68k/fmul
+tests/m68k/fsub
+tests/m68k/fgetexp
+tests/m68k/fscale
diff --git Makefile.target Makefile.target
index 096214a..af02b41 100644
--- Makefile.target
+++ Makefile.target
@@ -25,6 +25,7 @@  include $(SRC_PATH)/Makefile.objs
 ifdef CONFIG_USER_ONLY
 # user emulator name
 QEMU_PROG=qemu-$(TARGET_ARCH2)
+USER_TOOLS=$(TARGET_TOOLS)
 else
 # system emulator name
 ifeq ($(TARGET_ARCH), i386)
@@ -32,9 +33,10 @@  QEMU_PROG=qemu$(EXESUF)
 else
 QEMU_PROG=qemu-system-$(TARGET_ARCH2)$(EXESUF)
 endif
+USER_TOOLS=
 endif

-PROGS=$(QEMU_PROG)
+PROGS=$(QEMU_PROG) $(USER_TOOLS)
 STPFILES=

 ifndef CONFIG_HAIKU
@@ -64,6 +66,10 @@  else
 stap:
 endif

+qemu-wrapper.o: $(SRC_PATH)/linux-user/qemu-wrapper.c
+qemu-wrapper$(EXESUF): qemu-wrapper.o
+
+
 all: $(PROGS) stap

 # Dummy command so that make thinks it has done something
@@ -367,6 +373,8 @@  obj-sh4-y += ide/mmio.o

 obj-m68k-y = an5206.o mcf5206.o mcf_uart.o mcf_intc.o mcf5208.o mcf_fec.o
 obj-m68k-y += m68k-semi.o dummy_m68k.o
+obj-m68k-y += m68k_mac.o
+obj-m68k-y += next-cube.o next-kbd.o next-fb.o next-net.o framebuffer.o

 obj-s390x-y = s390-virtio-bus.o s390-virtio.o

diff --git bswap.h bswap.h
index f41bebe..13fd5cf 100644
--- bswap.h
+++ bswap.h
@@ -533,7 +533,7 @@  static inline int lduw_be_p(const void *ptr)
                   : "m" (*(uint16_t *)ptr));
     return val;
 #else
-    const uint8_t *b = ptr;
+    const uint8_t *b = (const uint8_t *)ptr;
     return ((b[0] << 8) | b[1]);
 #endif
 }
@@ -548,7 +548,7 @@  static inline int ldsw_be_p(const void *ptr)
                   : "m" (*(uint16_t *)ptr));
     return (int16_t)val;
 #else
-    const uint8_t *b = ptr;
+    const uint8_t *b = (const uint8_t *)ptr;
     return (int16_t)((b[0] << 8) | b[1]);
 #endif
 }
@@ -563,7 +563,7 @@  static inline int ldl_be_p(const void *ptr)
                   : "m" (*(uint32_t *)ptr));
     return val;
 #else
-    const uint8_t *b = ptr;
+    const uint8_t *b = (const uint8_t *)ptr;
     return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
 #endif
 }
diff --git configure configure
index 6873e13..b635a6b 100755
--- configure
+++ configure
@@ -135,6 +135,7 @@  kvm="no"
 gprof="no"
 debug_tcg="no"
 debug_mon="no"
+emulop="no"
 debug="no"
 strip_opt="yes"
 bigendian="no"
@@ -531,6 +532,10 @@  for opt do
   ;;
   --target-list=*) target_list="$optarg"
   ;;
+  --*-default-cpu=*)
+    tmp=`expr "x$opt" : 'x--\(.*\)-default-cpu=.*'`
+    eval ${tmp}_default_cpu="$optarg"
+  ;;
   --enable-trace-backend=*) trace_backend="$optarg"
   ;;
   --with-trace-file=*) trace_file="$optarg"
@@ -579,6 +584,10 @@  for opt do
   ;;
   --disable-debug-tcg) debug_tcg="no"
   ;;
+  --enable-emulop) emulop="yes"
+  ;;
+  --disable-emulop) emulop="no"
+  ;;
   --enable-debug-mon) debug_mon="yes"
   ;;
   --disable-debug-mon) debug_mon="no"
@@ -927,6 +936,7 @@  echo "                           use %M for cpu
name [$interp_prefix]"
 echo "  --target-list=LIST       set target list (default: build everything)"
 echo "Available targets: $default_target_list" | \
     fold -s -w 53 | sed -e 's/^/                           /'
+echo "  --ARCH-default-cpu=CPU   set the default cpu for a given architecture"
 echo ""
 echo "Advanced options (experts only):"
 echo "  --source-path=PATH       path of source code [$source_path]"
@@ -1042,6 +1052,8 @@  echo "  --disable-usb-redir      disable usb
network redirection support"
 echo "  --enable-usb-redir       enable usb network redirection support"
 echo "  --disable-guest-agent    disable building of the QEMU Guest Agent"
 echo "  --enable-guest-agent     enable building of the QEMU Guest Agent"
+echo "  --enable-emulop          enable emulation tester helper"
+echo "  --disable-emulop         disable emulation tester helper"
 echo ""
 echo "NOTE: The object files are built at the place where configure
is launched"
 exit 1
@@ -2635,6 +2647,14 @@  if test "$softmmu" = yes ; then
     fi
   fi
 fi
+target_tools=
+if test "$linux_user" = yes ; then
+  for target in $target_list ; do
+    case $target in
+      *-linux-user) target_tools="qemu-wrapper\$(EXESUF) $target_tools" ;;
+    esac
+  done
+fi

 # Mac OS X ships with a broken assembler
 roms=
@@ -2670,6 +2690,7 @@  echo "host CPU          $cpu"
 echo "host big endian   $bigendian"
 echo "target list       $target_list"
 echo "tcg debug enabled $debug_tcg"
+echo "emulop enabled    $emulop"
 echo "Mon debug enabled $debug_mon"
 echo "gprof enabled     $gprof"
 echo "sparse enabled    $sparse"
@@ -3078,6 +3099,7 @@  fi
 echo "CONFIG_TRACE_FILE=$trace_file" >> $config_host_mak

 echo "TOOLS=$tools" >> $config_host_mak
+echo "TARGET_TOOLS=$target_tools" >> $config_host_mak
 echo "ROMS=$roms" >> $config_host_mak
 echo "MAKE=$make" >> $config_host_mak
 echo "INSTALL=$install" >> $config_host_mak
@@ -3135,6 +3157,7 @@  target_dir="$target"
 config_target_mak=$target_dir/config-target.mak
 target_arch2=`echo $target | cut -d '-' -f 1`
 target_bigendian="no"
+target_default_cpu="any"

 case "$target_arch2" in
   armeb|lm32|m68k|microblaze|mips|mipsn32|mips64|ppc|ppcemb|ppc64|ppc64abi32|s390x|sh4eb|sparc|sparc64|sparc32plus)
@@ -3211,11 +3234,13 @@  TARGET_ABI_DIR=""
 case "$target_arch2" in
   i386)
     target_phys_bits=64
+    target_default_cpu="qemu32"
   ;;
   x86_64)
     TARGET_BASE_ARCH=i386
     target_phys_bits=64
     target_long_alignment=8
+    target_default_cpu="qemu64"
   ;;
   alpha)
     target_phys_bits=64
@@ -3233,6 +3258,7 @@  case "$target_arch2" in
   cris)
     target_nptl="yes"
     target_phys_bits=32
+    target_default_cpu=""
   ;;
   lm32)
     target_phys_bits=32
@@ -3258,12 +3284,14 @@  case "$target_arch2" in
     echo "TARGET_ABI_MIPSO32=y" >> $config_target_mak
     target_nptl="yes"
     target_phys_bits=64
+    target_default_cpu="24Kf"
   ;;
   mipsn32|mipsn32el)
     TARGET_ARCH=mipsn32
     TARGET_BASE_ARCH=mips
     echo "TARGET_ABI_MIPSN32=y" >> $config_target_mak
     target_phys_bits=64
+    target_default_cpu="20Kc"
   ;;
   mips64|mips64el)
     TARGET_ARCH=mips64
@@ -3271,12 +3299,14 @@  case "$target_arch2" in
     echo "TARGET_ABI_MIPSN64=y" >> $config_target_mak
     target_phys_bits=64
     target_long_alignment=8
+    target_default_cpu="20Kc"
   ;;
   ppc)
     gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml
power-spe.xml"
     target_phys_bits=32
     target_nptl="yes"
     target_libs_softmmu="$fdt_libs"
+    target_default_cpu="750"
   ;;
   ppcemb)
     TARGET_BASE_ARCH=ppc
@@ -3285,6 +3315,7 @@  case "$target_arch2" in
     target_phys_bits=64
     target_nptl="yes"
     target_libs_softmmu="$fdt_libs"
+    target_default_cpu="750"
   ;;
   ppc64)
     TARGET_BASE_ARCH=ppc
@@ -3293,6 +3324,7 @@  case "$target_arch2" in
     target_phys_bits=64
     target_long_alignment=8
     target_libs_softmmu="$fdt_libs"
+    target_default_cpu="970fx"
   ;;
   ppc64abi32)
     TARGET_ARCH=ppc64
@@ -3302,6 +3334,7 @@  case "$target_arch2" in
     gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml
power-spe.xml"
     target_phys_bits=64
     target_libs_softmmu="$fdt_libs"
+    target_default_cpu="750"
   ;;
   sh4|sh4eb)
     TARGET_ARCH=sh4
@@ -3311,11 +3344,13 @@  case "$target_arch2" in
   ;;
   sparc)
     target_phys_bits=64
+    target_default_cpu="Fujitsu MB86904"
   ;;
   sparc64)
     TARGET_BASE_ARCH=sparc
     target_phys_bits=64
     target_long_alignment=8
+    target_default_cpu="TI UltraSparc II"
   ;;
   sparc32plus)
     TARGET_ARCH=sparc64
@@ -3323,6 +3358,7 @@  case "$target_arch2" in
     TARGET_ABI_DIR=sparc
     echo "TARGET_ABI32=y" >> $config_target_mak
     target_phys_bits=64
+    target_default_cpu="Fujitsu MB86904"
   ;;
   s390x)
     target_nptl="yes"
@@ -3337,10 +3373,15 @@  case "$target_arch2" in
     exit 1
   ;;
 esac
+tmp_target_default_cpu=`eval echo \\$${target_arch2}_default_cpu`
+if [ "x$tmp_target_default_cpu" != "x" ] ; then
+  target_default_cpu="$tmp_target_default_cpu"
+fi
 echo "TARGET_SHORT_ALIGNMENT=$target_short_alignment" >> $config_target_mak
 echo "TARGET_INT_ALIGNMENT=$target_int_alignment" >> $config_target_mak
 echo "TARGET_LONG_ALIGNMENT=$target_long_alignment" >> $config_target_mak
 echo "TARGET_LLONG_ALIGNMENT=$target_llong_alignment" >> $config_target_mak
+echo "TARGET_DEFAULT_CPU=\"$target_default_cpu\"" >> $config_target_mak
 echo "TARGET_ARCH=$TARGET_ARCH" >> $config_target_mak
 target_arch_name="`echo $TARGET_ARCH | tr '[:lower:]' '[:upper:]'`"
 echo "TARGET_$target_arch_name=y" >> $config_target_mak
@@ -3415,6 +3456,9 @@  if test ! -z "$gdb_xml_files" ; then
   echo "TARGET_XML_FILES=$list" >> $config_target_mak
 fi

+if test "$target_user_only" = "yes" -a  "$target_arch2" = "m68k" -a
"$emulop" = "yes" ; then
+  echo "CONFIG_EMULOP=y" >> $config_target_mak
+fi
 if test "$target_user_only" = "yes" -a "$bflt" = "yes"; then
   echo "TARGET_HAS_BFLT=y" >> $config_target_mak
 fi
diff --git fpu/softfloat-specialize.h fpu/softfloat-specialize.h
index c165205..4a4863c 100644
--- fpu/softfloat-specialize.h
+++ fpu/softfloat-specialize.h
@@ -85,9 +85,14 @@  const float64 float64_default_nan =
const_float64(LIT64( 0xFFF8000000000000 ));
 #define floatx80_default_nan_high 0x7FFF
 #define floatx80_default_nan_low  LIT64( 0xBFFFFFFFFFFFFFFF )
 #else
+#if defined(TARGET_M68K)
+#define floatx80_default_nan_high 0x7FFF
+#define floatx80_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
+#else
 #define floatx80_default_nan_high 0xFFFF
 #define floatx80_default_nan_low  LIT64( 0xC000000000000000 )
 #endif
+#endif

 const floatx80 floatx80_default_nan = make_floatx80(floatx80_default_nan_high,
                                                     floatx80_default_nan_low);
@@ -387,6 +392,26 @@  static int pickNaN(flag aIsQNaN, flag aIsSNaN,
flag bIsQNaN, flag bIsSNaN,
         return 1;
     }
 }
+#elif defined(TARGET_M68K)
+static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
+                   flag aIsLargerSignificand)
+{
+    /* If either operand, but not both operands, of an operation is a
+     * nonsignaling NAN, then that NAN is returned as the result. If both
+     * operands are nonsignaling NANs, then the destination operand
+     * nonsignaling NAN is returned as the result.
+     */
+
+    if (aIsSNaN) {
+        return 0;
+    } else if (bIsSNaN) {
+        return 1;
+    } else if (bIsQNaN) {
+        return 1;
+    } else {
+        return 0;
+    }
+}
 #else
 static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
                     flag aIsLargerSignificand)
diff --git fpu/softfloat.c fpu/softfloat.c
index 7951a0e..dbce683 100644
--- fpu/softfloat.c
+++ fpu/softfloat.c
@@ -768,7 +768,9 @@  static floatx80
                ) {
                 return packFloatx80( zSign, 0x7FFE, ~ roundMask );
             }
-            return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+            return packFloatx80( zSign,
+				 floatx80_default_inf_high,
+				 floatx80_default_inf_low );
         }
         if ( zExp <= 0 ) {
             isTiny =
@@ -1583,7 +1585,9 @@  floatx80 float32_to_floatx80( float32 a STATUS_PARAM )
     aSign = extractFloat32Sign( a );
     if ( aExp == 0xFF ) {
         if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a
STATUS_VAR ) STATUS_VAR );
-        return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+        return packFloatx80( aSign,
+			     floatx80_default_inf_high,
+			     floatx80_default_inf_low);
     }
     if ( aExp == 0 ) {
         if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 );
@@ -2924,7 +2928,9 @@  floatx80 float64_to_floatx80( float64 a STATUS_PARAM )
     aSign = extractFloat64Sign( a );
     if ( aExp == 0x7FF ) {
         if ( aSig ) return commonNaNToFloatx80( float64ToCommonNaN( a
STATUS_VAR ) STATUS_VAR );
-        return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+        return packFloatx80( aSign,
+			     floatx80_default_inf_high,
+			     floatx80_default_inf_low );
     }
     if ( aExp == 0 ) {
         if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 );
@@ -3870,8 +3876,8 @@  int64 floatx80_to_int64( floatx80 a STATUS_PARAM )
         if ( shiftCount ) {
             float_raise( float_flag_invalid STATUS_VAR);
             if (    ! aSign
-                 || (    ( aExp == 0x7FFF )
-                      && ( aSig != LIT64( 0x8000000000000000 ) ) )
+                 || (    ( aExp == floatx80_default_inf_high )
+                      && ( aSig != floatx80_default_inf_low ) )
                ) {
                 return LIT64( 0x7FFFFFFFFFFFFFFF );
             }
@@ -4114,7 +4120,9 @@  static floatx80 addFloatx80Sigs( floatx80 a,
floatx80 b, flag zSign STATUS_PARAM
     else if ( expDiff < 0 ) {
         if ( bExp == 0x7FFF ) {
             if ( (uint64_t) ( bSig<<1 ) ) return
propagateFloatx80NaN( a, b STATUS_VAR );
-            return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+            return packFloatx80( zSign,
+				 floatx80_default_inf_high,
+				 floatx80_default_inf_low );
         }
         if ( aExp == 0 ) ++expDiff;
         shift64ExtraRightJamming( aSig, 0, - expDiff, &aSig, &zSig1 );
@@ -4191,7 +4199,8 @@  static floatx80 subFloatx80Sigs( floatx80 a,
floatx80 b, flag zSign STATUS_PARAM
  bExpBigger:
     if ( bExp == 0x7FFF ) {
         if ( (uint64_t) ( bSig<<1 ) ) return propagateFloatx80NaN( a,
b STATUS_VAR );
-        return packFloatx80( zSign ^ 1, 0x7FFF, LIT64( 0x8000000000000000 ) );
+        return packFloatx80( zSign ^ 1, floatx80_default_inf_high,
+					floatx80_default_inf_low );
     }
     if ( aExp == 0 ) ++expDiff;
     shift128RightJamming( aSig, 0, - expDiff, &aSig, &zSig1 );
@@ -4285,7 +4294,8 @@  floatx80 floatx80_mul( floatx80 a, floatx80 b
STATUS_PARAM )
             return propagateFloatx80NaN( a, b STATUS_VAR );
         }
         if ( ( bExp | bSig ) == 0 ) goto invalid;
-        return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+        return packFloatx80( zSign, floatx80_default_inf_high,
+			            floatx80_default_inf_low );
     }
     if ( bExp == 0x7FFF ) {
         if ( (uint64_t) ( bSig<<1 ) ) return propagateFloatx80NaN( a,
b STATUS_VAR );
@@ -4296,7 +4306,8 @@  floatx80 floatx80_mul( floatx80 a, floatx80 b
STATUS_PARAM )
             z.high = floatx80_default_nan_high;
             return z;
         }
-        return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+        return packFloatx80( zSign, floatx80_default_inf_high,
+				    floatx80_default_inf_high );
     }
     if ( aExp == 0 ) {
         if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 );
@@ -4345,7 +4356,8 @@  floatx80 floatx80_div( floatx80 a, floatx80 b
STATUS_PARAM )
             if ( (uint64_t) ( bSig<<1 ) ) return
propagateFloatx80NaN( a, b STATUS_VAR );
             goto invalid;
         }
-        return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+        return packFloatx80( zSign, floatx80_default_inf_high,
+				    floatx80_default_inf_low );
     }
     if ( bExp == 0x7FFF ) {
         if ( (uint64_t) ( bSig<<1 ) ) return propagateFloatx80NaN( a,
b STATUS_VAR );
@@ -4361,7 +4373,8 @@  floatx80 floatx80_div( floatx80 a, floatx80 b
STATUS_PARAM )
                 return z;
             }
             float_raise( float_flag_divbyzero STATUS_VAR);
-            return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+            return packFloatx80( zSign, floatx80_default_inf_high,
+					floatx80_default_inf_low );
         }
         normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
     }
@@ -5071,7 +5084,8 @@  floatx80 float128_to_floatx80( float128 a STATUS_PARAM )
         if ( aSig0 | aSig1 ) {
             return commonNaNToFloatx80( float128ToCommonNaN( a
STATUS_VAR ) STATUS_VAR );
         }
-        return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+        return packFloatx80( aSign, floatx80_default_inf_high,
+				    floatx80_default_inf_low );
     }
     if ( aExp == 0 ) {
         if ( ( aSig0 | aSig1 ) == 0 ) return packFloatx80( aSign, 0, 0 );
diff --git fpu/softfloat.h fpu/softfloat.h
index 3bb7d8f..7a1fa7e 100644
--- fpu/softfloat.h
+++ fpu/softfloat.h
@@ -532,12 +532,23 @@  INLINE int floatx80_is_any_nan(floatx80 a)
 #define floatx80_pi make_floatx80(0x4000, 0xc90fdaa22168c235LL)
 #define floatx80_half make_floatx80(0x3ffe, 0x8000000000000000LL)
 #define floatx80_infinity make_floatx80(0x7fff, 0x8000000000000000LL)
+#define floatx80_e make_floatx80(0x4000, 0xadf85458a2bb4a9aULL)
+#define floatx80_log2e make_floatx80(0x3fff, 0xb8aa3b295c17f0bcULL)
+#define floatx80_10 make_floatx80(0x4002, 0xa000000000000000ULL)

 /*----------------------------------------------------------------------------
 | The pattern for a default generated extended double-precision NaN.
 *----------------------------------------------------------------------------*/
 extern const floatx80 floatx80_default_nan;

+#if defined(TARGET_M68K)
+#define floatx80_default_inf_high 0x7FFF
+#define floatx80_default_inf_low  LIT64( 0x0000000000000000 )
+#else
+#define floatx80_default_inf_high 0x7FFF
+#define floatx80_default_inf_low  LIT64( 0x8000000000000000 )
+#endif
+
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE quadruple-precision conversion routines.
 *----------------------------------------------------------------------------*/
diff --git gdb-xml/m68k-fp.xml gdb-xml/m68k-fp.xml
new file mode 100644
index 0000000..64290d1
--- /dev/null
+++ gdb-xml/m68k-fp.xml
@@ -0,0 +1,21 @@ 
+<?xml version="1.0"?>
+<!-- Copyright (C) 2008 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.coldfire.fp">
+  <reg name="fp0" bitsize="96" type="float" group="float"/>
+  <reg name="fp1" bitsize="96" type="float" group="float"/>
+  <reg name="fp2" bitsize="96" type="float" group="float"/>
+  <reg name="fp3" bitsize="96" type="float" group="float"/>
+  <reg name="fp4" bitsize="96" type="float" group="float"/>
+  <reg name="fp5" bitsize="96" type="float" group="float"/>
+  <reg name="fp6" bitsize="96" type="float" group="float"/>
+  <reg name="fp7" bitsize="96" type="float" group="float"/>
+
+  <reg name="fpcontrol" bitsize="32" group="float"/>
+  <reg name="fpstatus" bitsize="32" group="float"/>,
+  <reg name="fpiaddr" bitsize="32" type="code_ptr" group="float"/>
+</feature>
diff --git hw/m68k_mac.c hw/m68k_mac.c
new file mode 100644
index 0000000..c1daff0
--- /dev/null
+++ hw/m68k_mac.c
@@ -0,0 +1,176 @@ 
+/*
+ * QEMU Motorla 680x0 Macintosh hardware System Emulator
+ *
+ * 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 "hw.h"
+#include "boards.h"
+#include "elf.h"
+#include "loader.h"
+
+static void q800_init(ram_addr_t ram_size,
+                       const char *boot_device,
+                       const char *kernel_filename,
+                       const char *kernel_cmdline,
+                       const char *initrd_filename,
+                       const char *cpu_model)
+{
+    CPUState *env = NULL;
+    int linux_boot;
+    ram_addr_t ram_offset;
+    int32_t kernel_size;
+    uint64_t elf_entry;
+#if 0
+    char *filename;
+    qemu_irq *pic, **heathrow_irqs;
+    int i;
+    ram_addr_t bios_offset;
+    uint32_t kernel_base, initrd_base;
+    int32_t initrd_size;
+    PCIBus *pci_bus;
+    MacIONVRAMState *nvr;
+    int bios_size;
+    int pic_mem_index, nvram_mem_index, dbdma_mem_index, cuda_mem_index;
+    int escc_mem_index, ide_mem_index[2];
+    uint16_t ppc_boot_device;
+    DriveInfo * hd[MAX_IDE_BUS * MAX_IDE_DEVS];
+    void *fw_cfg;
+    void *dbdma;
+#endif
+
+    linux_boot = (kernel_filename != NULL);
+
+    /* init CPUs */
+    if (cpu_model == NULL) {
+        cpu_model = "m68040";
+    }
+    env = cpu_init(cpu_model);
+    if (!env) {
+            hw_error("qemu: unable to find m68k CPU definition\n");
+            exit(1);
+    }
+    qemu_register_reset((QEMUResetHandler *)&cpu_reset, env);
+
+    ram_offset = qemu_ram_alloc(NULL, "m68k_mac.ram", ram_size);
+    cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
+
+#if 0
+    /* allocate and load BIOS */
+    bios_offset = qemu_ram_alloc(NULL, "ppc_heathrow.bios", BIOS_SIZE);
+    if (bios_name == NULL) {
+        bios_name = PROM_FILENAME;
+    }
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+    cpu_register_physical_memory(PROM_ADDR, BIOS_SIZE,
+                                 bios_offset | IO_MEM_ROM);
+
+    /* Load OpenBIOS (ELF) */
+    if (filename) {
+        bios_size = load_elf(filename, 0, NULL, NULL, NULL, NULL,
+                             1, ELF_MACHINE, 0);
+        qemu_free(filename);
+    } else {
+        bios_size = -1;
+    }
+    if (bios_size < 0 || bios_size > BIOS_SIZE) {
+        hw_error("qemu: could not load PowerPC bios '%s'\n", bios_name);
+        exit(1);
+    }
+#endif
+
+    if (linux_boot) {
+
+        kernel_size = load_elf(kernel_filename, NULL, NULL,
+                               &elf_entry, NULL, NULL, 1,
+                               ELF_MACHINE, 0);
+        if (kernel_size < 0) {
+            hw_error("qemu: could not load kernel '%s'\n",
+                      kernel_filename);
+            exit(1);
+        }
+        env->pc = elf_entry;
+#if 0
+        /* load initrd */
+        if (initrd_filename) {
+            initrd_base = INITRD_LOAD_ADDR;
+            initrd_size = load_image_targphys(initrd_filename, initrd_base,
+                                              ram_size - initrd_base);
+            if (initrd_size < 0) {
+                hw_error("qemu: could not load initial ram disk '%s'\n",
+                         initrd_filename);
+                exit(1);
+            }
+        } else {
+            initrd_base = 0;
+            initrd_size = 0;
+        }
+#endif
+    }
+
+#if 0
+    /* XXX: we register only 1 output pin for heathrow PIC */
+    heathrow_irqs = qemu_mallocz(smp_cpus * sizeof(qemu_irq *));
+    heathrow_irqs[0] =
+        qemu_mallocz(smp_cpus * sizeof(qemu_irq)*1);
+    /* Connect the heathrow PIC outputs to the 6xx bus */
+    for (i = 0; i < smp_cpus; i++) {
+        switch (PPC_INPUT(env)) {
+        case PPC_FLAGS_INPUT_6xx:
+            heathrow_irqs[i] = heathrow_irqs[0] + (i * 1);
+            heathrow_irqs[i][0] =
+                ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT];
+            break;
+        default:
+            hw_error("Bus model not supported on OldWorld Mac machine\n");
+        }
+    }
+
+    escc_mem_index = escc_init(0x80013000, pic[0x0f], pic[0x10], serial_hds[0],
+                               serial_hds[1], ESCC_CLOCK, 4);
+
+    /* cuda also initialize ADB */
+    cuda_init(&cuda_mem_index, pic[0x12]);
+
+    adb_kbd_init(&adb_bus);
+    adb_mouse_init(&adb_bus);
+
+    macio_init(pci_bus, PCI_DEVICE_ID_APPLE_343S1201, 1, pic_mem_index,
+               dbdma_mem_index, cuda_mem_index, nvr, 2, ide_mem_index,
+               escc_mem_index);
+
+    if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8) {
+        graphic_depth = 15;
+    }
+#endif
+}
+
+static QEMUMachine q800_machine = {
+    .name = "q800",
+    .desc = "Macintosh Quadra 800",
+    .init = q800_init,
+    .max_cpus = 1,
+    .is_default = 1,
+};
+
+static void q800_machine_init(void)
+{
+    qemu_register_machine(&q800_machine);
+}
+
+machine_init(q800_machine_init);
diff --git hw/mcf5208.c hw/mcf5208.c
index 78fbc5f..8425bca 100644
--- hw/mcf5208.c
+++ hw/mcf5208.c
@@ -295,7 +295,7 @@  static QEMUMachine mcf5208evb_machine = {
     .name = "mcf5208evb",
     .desc = "MCF5206EVB",
     .init = mcf5208evb_init,
-    .is_default = 1,
+    .is_default = 0,
 };

 static void mcf5208evb_machine_init(void)
diff --git hw/next-cube.c hw/next-cube.c
new file mode 100644
index 0000000..ba58066
--- /dev/null
+++ hw/next-cube.c
@@ -0,0 +1,474 @@ 
+/*
+ * Next Cube System Driver
+ * Copyright (c) 2011 Bryce Lanham
+ *
+ * Based on dummy_m68k.c Copyright (c) 2007 CodeSourcery.
+ *
+ * This code is licensed under the GPL
+ */
+
+/*
+ *
+ *
+ *
+ * */
+
+#include "hw.h"
+#include "next-fb.h"
+#include "next-kbd.h"
+#include "next-net.h"
+
+#include "monitor.h"
+#include "sysemu.h"
+#include "boards.h"
+#include "console.h"
+#include "loader.h"//probably not needed
+#include "elf.h"
+#include "esp.h" //SCSI ESP should work out of the box
+#include "escc.h" //ZILOG 8530 Serial Emulation
+#define ENTRY 0x0100001e
+
+/* Board init.  */
+#define ROM_FILE "rom66.bin"
+/* these need to be in machine state */
+uint32_t scr1 = 0;
+uint32_t scr2 = 0;
+uint32_t int_status = 4;//from previous
+uint32_t int_mask = 0;
+uint32_t event_test = 0;
+/* Thanks to NeXT forums for this */
+uint8_t rtc_ram3[32]={
+0x94,0x0f,0x40,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0xfb,0x6d,0x00,0x00,0x7B,0x00,
+0x00,0x00,0x65,0x6e,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x13
+};
+uint8_t *rtc_ram;
+uint8_t rtc_ram2[32]={
+0x94,0x0f,0x40,0x03,0x00,0x00,0x00,0x00,
+0x00,0x00,0xfb,0x6d,0x00,0x00,0x4b,0x00,
+0x41,0x00,0x20,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x84,0x7e,
+};
+
+next_state_t next_state;
+
+static uint32_t mmio_readb(void*opaque, target_phys_addr_t addr);
+static uint32_t mmio_readw(void*opaque, target_phys_addr_t addr);
+static uint32_t mmio_readl(void*opaque, target_phys_addr_t addr);
+
+static void mmio_writeb(void*opaque, target_phys_addr_t addr, uint32_t val);
+static void mmio_writew(void*opaque, target_phys_addr_t addr, uint32_t val);
+static void mmio_writel(void*opaque, target_phys_addr_t addr, uint32_t val);
+static CPUReadMemoryFunc *mmio_read[3] = {
+	mmio_readb,
+	mmio_readw,
+	mmio_readl
+};
+
+static CPUWriteMemoryFunc *mmio_write[3] = {
+	mmio_writeb,
+	mmio_writew,
+	mmio_writel
+};
+static uint32_t mmio_readb(void*opaque, target_phys_addr_t addr)
+{
+	switch(addr)
+	{
+		case 0xc002:
+		return (scr1 >> 8) & 0xFF;
+		case 0xc0008:
+		return 0xff;//hack to hide memory error
+		default:
+	        fprintf(stderr,"MMIO Read B @ %x\n",addr);
+        return 0x0;
+    }
+}
+static uint32_t mmio_readw(void*opaque, target_phys_addr_t addr)
+{
+	switch(addr)
+	{
+        default:
+	    fprintf(stderr,"MMIO Read W @ %x\n",addr);
+        return 0x0;
+    }
+}
+
+static uint32_t mmio_readl(void*opaque, target_phys_addr_t addr)
+{
+
+	switch(addr)
+	{
+        case 0x7000:
+	//	fprintf(stderr,"INTSTAT\n");
+        return int_status;
+	
+    	case 0x7800:
+		//fprintf(stderr,"INTMASK\n");
+		return int_mask;
+	
+    	case 0xc000:
+	//	fprintf(stderr, "SCR1 Read: @ %X\n",((CPUM68KState *)opaque)->pc);
+		return scr1;
+	
+    	case 0xd000:
+	//	fprintf(stderr, "SCR2 Read: @ %X %X\n",((CPUM68KState *)opaque)->pc,scr2);
+		return scr2;
+		
+		case 0xc0000:
+		return 0x01;	
+       	
+		case 0xc0034:
+		return 0x560;
+ 		
+		default:
+		fprintf(stderr,"MMIO Read L @ %x\n",addr);
+		return 0x0;
+	}
+}
+static void mmio_writeb(void*opaque, target_phys_addr_t addr, uint32_t val)
+{
+	
+	switch(addr)
+	{
+		default:
+		fprintf(stderr,"MMIO Write B @ %x with %x\n",addr,val);
+	}
+
+}
+static void mmio_writew(void*opaque, target_phys_addr_t addr, uint32_t val)
+{
+	fprintf(stderr,"MMIO Write W\n"	);
+}
+int led = 0;
+
+static void mmio_writel(void*opaque, target_phys_addr_t addr, uint32_t val)
+{
+	static int phase = 0;
+	static uint8_t old_scr2;
+	static uint8_t rtc_command = 0;
+	static uint8_t rtc_value = 0;
+	static uint8_t rtc_status = 0x90;
+	static uint8_t rtc_return = 0;
+	uint8_t scr2_2;
+    switch(addr)
+	{
+		case 0x10:
+        break;
+        case 0x7000:
+		fprintf(stderr,"INT Status old: %x new: %x\n",int_status,val);
+        int_status = val;
+		break;
+		case 0x7800:
+		fprintf(stderr,"INT Status old: %x new: %x\n",int_mask,val);
+		int_mask  = val;
+		break;
+		case 0xc000:
+		fprintf(stderr, "SCR1 Write: %x @ %X\n",val,((CPUM68KState *)opaque)->pc);
+		break;
+		case 0xd000:
+		//old_scr2 = val;
+		scr2_2 = (val >> 8) & 0xFF;
+			if(val &0x1)
+		{	
+			printf("fault!\n");
+			led++;
+			if(led == 10)
+			{
+				fprintf(stderr,"LED flashing, possible fault, pausing emulation\n");
+				led = 0;
+				vm_stop(VMSTOP_DEBUG);
+			}
+
+		}
+		
+		if (scr2_2& 0x1) {
+		//	fprintf(stderr,"RTC %x phase %i\n",scr2_2,phase);
+			if (phase==-1) phase=0;
+				// if we are in going down clock... do something
+				#define SCR2_RTCLK 0x2
+				#define SCR2_RTDATA 0x4
+				if (((old_scr2&SCR2_RTCLK)!=(scr2_2&SCR2_RTCLK)) &&
((scr2_2&SCR2_RTCLK)==0) ) {
+					if (phase<8)
+						rtc_command=(rtc_command<<1)|((scr2_2&SCR2_RTDATA)?1:0);
+					if ((phase>=8) && (phase<16)) {
+						rtc_value=(rtc_value<<1)|((scr2_2&SCR2_RTDATA)?1:0);
+			
+					// if we read RAM register, output RT_DATA bit
+					if (rtc_command<=0x1F) {
+						scr2_2=scr2_2&(~SCR2_RTDATA);
+					if (rtc_ram[rtc_command]&(0x80>>(phase-8)))
+						scr2_2 |=SCR2_RTDATA;
+				
+					rtc_return=(rtc_return<<1)|((scr2_2&SCR2_RTDATA)?1:0);
+				}
+					// read the status 0x30
+					if (rtc_command==0x30) {
+						scr2_2=scr2_2&(~SCR2_RTDATA);
+						// for now status = 0x98 (new rtc + FTU)
+						if (rtc_status&(0x80>>(phase-8)))
+							scr2_2|=SCR2_RTDATA;
+					
+						rtc_return=(rtc_return<<1)|((scr2_2&SCR2_RTDATA)?1:0);
+					}
+					// read the status 0x31
+					if (rtc_command==0x31) {
+						scr2_2=scr2_2&(~SCR2_RTDATA);
+					// for now 0x00
+					if (0x00&(0x80>>(phase-8)))
+						scr2_2|=SCR2_RTDATA;
+					rtc_return=(rtc_return<<1)|((scr2_2&SCR2_RTDATA)?1:0);
+				}
+			
+				if ((rtc_command>=0x20) && (rtc_command<=0x2F)) {
+					scr2_2=scr2_2&(~SCR2_RTDATA);
+					// for now 0x00
+					if (0x00&(0x80>>(phase-8)))
+						scr2_2|=SCR2_RTDATA;
+					rtc_return=(rtc_return<<1)|((scr2_2&SCR2_RTDATA)?1:0);
+				}
+			
+			}
+		
+			phase++;
+				if (phase==16) {
+		//	fprintf(stderr,"SCR2 RTC command complete %x %x %x at PC=$%08x\n",
+		//	rtc_command,rtc_value,rtc_return,0);
+						if ((rtc_command>=0x80) && (rtc_command<=0x9F))
+                        {
+							rtc_ram[rtc_command-0x80]=rtc_value;
+                            #ifdef READ_RTC
+							FILE *fp = fopen("rtc.ram","wb+");
+                            int ret = fwrite(rtc_ram,1,32,fp);
+							if(ret != 32)
+									abort();
+                            fclose(fp);
+							#endif
+                        }
+						// write to x30 register
+						if (rtc_command==0xB1) {
+						// clear FTU
+						if (rtc_value & 0x04) {
+							rtc_status=rtc_status&(~0x18);
+							int_status=int_status&(~0x04);
+						}
+					}		
+				}
+			}
+		} else {
+						// else end or abort
+						phase=-1;
+						rtc_command=0;
+						rtc_value=0;
+		}
+		scr2 = val & 0xFFFF00FF;
+		scr2 |= scr2_2<< 8;	
+		old_scr2 = scr2_2;
+
+		break;
+		case 0xc0034:
+	//	if(val == 0x90000560)
+	//	vm_stop(VMSTOP_DEBUG);
+		default:
+			fprintf(stderr,"MMIO Write l @ %x with %x\n",addr,val);
+
+	}
+}
+
+
+static uint32_t scr_readb(void*opaque, target_phys_addr_t addr);
+static uint32_t scr_readw(void*opaque, target_phys_addr_t addr);
+static uint32_t scr_readl(void*opaque, target_phys_addr_t addr);
+static CPUReadMemoryFunc *scr_read[3] = {
+	scr_readb,
+	scr_readw,
+	scr_readl
+
+};
+
+static void scr_writeb(void*opaque, target_phys_addr_t addr, uint32_t value);
+static void scr_writew(void*opaque, target_phys_addr_t addr, uint32_t value);
+static void scr_writel(void*opaque, target_phys_addr_t addr, uint32_t value);
+static CPUWriteMemoryFunc * const scr_write[3] = {
+	scr_writeb,
+	scr_writew,
+	scr_writel
+};
+
+static uint32_t scr_readb(void*opaque, target_phys_addr_t addr)
+{
+ //   CPUState *s = (CPUState *)opaque;
+    switch(addr)
+    {
+
+        case 0x14000: case 0x14005:
+        fprintf(stderr,"SCSI read b\n");
+        return 0x0;
+
+        case 0x14104://FDD
+      //  return 0x0;
+
+        case 0x14108:
+        return 0x0;
+
+        case 0x18001:
+	//	fprintf(stderr, "SCC @ %X\n",((CPUM68KState *)opaque)->pc);
+        return 0;
+        case 0x1a000:
+    //    return 0;
+        case 0x1a001:
+     //   return 0;
+        case 0x1a002:
+       // return 0;
+        case 0x1a003:
+     //   fprintf(stderr,"event #%x @ %x\n",addr &0x3,s->pc);
+       // event_test++;
+      // if(event_test == 200) event_test = 0;
+        return event_test;
+        default:
+        fprintf(stderr,"BMAP Read B @ %x\n",addr);
+        return 0;
+    }
+    return 0;
+}
+static uint32_t scr_readw(void*opaque, target_phys_addr_t addr)
+{
+	fprintf(stderr,"S Read W @ %x\n",addr);
+	return 0;
+}
+static uint32_t scr_readl(void*opaque, target_phys_addr_t addr)
+{
+	fprintf(stderr,"SRead L @ %x\n",addr);
+	return 0;
+}
+static void scr_writeb(void*opaque, target_phys_addr_t addr, uint32_t value)
+{
+    switch(addr)
+    {
+        case 0x10000: break;//Screen brightness
+        case 0x18000:
+        case 0x18001:
+        case 0x18004:
+        break;
+    	default:
+        fprintf(stderr,"BMAP Write B @ %x with %x\n",addr,value);
+    }
+}
+static void scr_writew(void*opaque, target_phys_addr_t addr, uint32_t value)
+{
+	fprintf(stderr,"SWrite w @ %x with %x\n",addr,value);
+}
+static void scr_writel(void*opaque, target_phys_addr_t addr, uint32_t value)
+{
+
+	fprintf(stderr,"SWrite l @ %x with %x\n",addr,value);
+}
+
+/* need to make more defines, put them into a header */
+#define RAM_SIZE 0x4000000
+
+void serial_irq(void *opaque, int n, int level);
+static void next_cube_init(ram_addr_t ram_size,
+                     const char *boot_device,
+                     const char *kernel_filename, const char *kernel_cmdline,
+                     const char *initrd_filename, const char *cpu_model)
+{
+    /* Initialize the cpu core */
+    CPUState *env = cpu_init("m68040");
+    if (env == NULL) {
+        fprintf(stderr, "Unable to find m68k CPU definition\n");
+        exit(1);
+    }
+
+    /* Initialize CPU registers.  */
+    env->vbr = 0;
+    env->pc  = 0x100001e; //technically should read vector
+    env->sr  = 0x2700;
+
+    /* Set internal registers to initial values */
+	scr1 = 0x01000220;
+    scr2 = 0x00ff8880;
+
+    int_mask = 0x88027640;
+    int_status= 0x200;
+
+    /* Load RTC ram,  needs to be in a function probably */
+    {
+	   	rtc_ram = malloc(32);
+       	#ifdef LOAD_RTC
+        FILE *fp = fopen("rtc.ram","rb");
+        if(fread(rtc_ram,1,32,fp) != 32)
+            abort();
+        fclose(fp);
+		#endif
+        memcpy(rtc_ram,rtc_ram2,32);
+    }
+
+
+    /* 64MB RAM starting at 0x4000000  */
+    cpu_register_physical_memory(0x4000000, RAM_SIZE,
+        qemu_ram_alloc(NULL, "next-cube.ram", RAM_SIZE) | IO_MEM_RAM);
+
+	/* Framebuffer */
+    nextfb_init(&next_state);
+
+    /* MMIO */
+	cpu_register_physical_memory((uint32_t)0x2000000,0xD0000,
+        cpu_register_io_memory(mmio_read,mmio_write, (void
*)env,DEVICE_NATIVE_ENDIAN));
+
+    /* BMAP */ //acts as a catch-all for now
+    cpu_register_physical_memory((uint32_t)0x2100000,0x3A7FF,
+        cpu_register_io_memory(scr_read,scr_write, (void
*)env,DEVICE_NATIVE_ENDIAN));
+
+    /* KBD */
+    nextkbd_init((void *)env);
+
+    /* Serial */
+   	//CharDriverState *console = text_console_init(NULL);
+  	//qemu_irq *serial = qemu_allocate_irqs(serial_irq, env, 2);
+  	//escc_init(0x2118000, serial[0], serial[1],
+    //        console, NULL,   (9600*384),0);
+
+  	
+    /* Load ROM here */	
+    if(get_image_size(ROM_FILE) != 0x20000)
+    {
+        fprintf(stderr,"Failed to load rom file!\n");
+        exit(1);
+    }
+
+    rom_add_file_fixed(ROM_FILE,0x1000000,0);
+    rom_add_file_fixed(ROM_FILE,0x000000,1);
+	cpu_register_physical_memory((uint32_t)0x1000000, 0x20000,
+        qemu_ram_alloc(NULL, "next.rom", 0x20000) | IO_MEM_ROM);
+		cpu_register_physical_memory((uint32_t)0x000000, 0x20000,
+        qemu_ram_alloc(NULL, "nex.rom", 0x20000) | IO_MEM_ROM);
+
+	/* Ethernet */
+    nextnet_init((void *)env);
+
+
+}
+
+void serial_irq(void *opaque, int n, int level)
+{
+  //  fprintf(stderr,"IRQQQQQ\n");
+ //   int_status |= 0xFFFFFF00;
+//	int_status |= 1<<17;
+//CPUM68KState *env = (CPUM68KState *)opaque;
+//env->exception_index = 10;
+//m68k_set_irq_level((CPUM68KState *)opaque, 5,29);//25);
+
+}
+static QEMUMachine next_machine = {
+    .name = "next-cube",
+    .desc = "NeXT Cube",
+    .init = next_cube_init,
+};
+
+static void next_machine_init(void)
+{
+    qemu_register_machine(&next_machine);
+}
+
+machine_init(next_machine_init);
diff --git hw/next-cube.h hw/next-cube.h
new file mode 100644
index 0000000..e69de29
diff --git hw/next-fb.c hw/next-fb.c
new file mode 100644
index 0000000..0cccae3
--- /dev/null
+++ hw/next-fb.c
@@ -0,0 +1,102 @@ 
+/*
+ * NeXT Cube/Staion Framebuffer Emulation
+ *
+ * Copyright (c) 2011 Bryce Lanham
+ *
+ * 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 "hw.h"
+#include "loader.h"
+#include "console.h"
+#include "framebuffer.h"
+#define BITS 8
+#include "pixel_ops.h"
+#include "next-fb.h"
+/*
+typedef struct NextVGAState {
+    VGACommonState vga;
+    target_phys_addr_t vram_base;
+	};*/
+//need a function to register the mm i/o for fb and to register vram
+
+void nextfb_draw_line(void *opaque, uint8_t *d, const uint8_t *s, int
width, int pitch)
+{
+    uint32_t pal[4] = {0xFFFFFFFF, 0xFFAAAAAA, 0xFF555555,0xFF000000};
+    uint32_t*buf = qemu_malloc(1120*4);
+    int i = 0;
+    for(;i<280; i++)
+    {
+        int j=i*4;
+        uint8_t src = s[i];
+        buf[j+3]= pal[src & 0x3];
+        src >>=2;
+        buf[j+2]= pal[src & 0x3];
+        src >>=2;
+        buf[j+1]= pal[src & 0x3];
+        src >>=2;
+        buf[j+0]= pal[src & 0x3];
+    }
+	
+    memcpy(d,buf,1120*4);
+	free(buf);
+}
+
+
+static void nextfb_update(void * opaque)
+{
+	next_state_t *s = (next_state_t *)opaque;
+	DisplaySurface *info = s->ds->surface;
+
+	
+	
+	int dest_width = 4;
+	int src_width;
+	int first = 0;
+	int last  = 0;
+	src_width = s->cols = 1120;
+	src_width = 288;
+	dest_width = 1120;
+  	dest_width = info->linesize;
+	framebuffer_update_display(s->ds,
+							0xB000000,1120,832,
+							src_width,dest_width, 0,
+							1,
+							nextfb_draw_line,
+							NULL,
+							&first, &last);
+
+	dpy_update(s->ds,0,0,1120,832);	
+}
+
+static void nextfb_invalidate(void *opaque)
+{
+}
+
+void nextfb_init(next_state_t *s)
+{
+    s->ds = graphic_console_init(nextfb_update,nextfb_invalidate,
NULL, NULL, s);
+	qemu_console_resize(s->ds,1120,832);	
+	s->cols = 1120;
+	s->rows = 832;
+	s->invalidate = 1;
+
+    cpu_register_physical_memory(0xB000000, 0x1CB100,
+        qemu_ram_alloc(NULL,"next-vram.ram",0x1CB100) | IO_MEM_RAM);
+
+}
diff --git hw/next-fb.h hw/next-fb.h
new file mode 100644
index 0000000..9d2b547
--- /dev/null
+++ hw/next-fb.h
@@ -0,0 +1,14 @@ 
+typedef struct {
+	DisplayState *ds;
+	uint32_t base;
+	uint32_t pitch;
+	uint32_t cols;
+	uint32_t rows;
+	int invalidate;
+
+
+} next_state_t;
+
+void nextfb_draw_line(void *opaque, uint8_t *d, const uint8_t *s, int
width, int pitch);
+
+void nextfb_init(next_state_t *s);
diff --git hw/next-kbd.c hw/next-kbd.c
new file mode 100644
index 0000000..31bda7d
--- /dev/null
+++ hw/next-kbd.c
@@ -0,0 +1,243 @@ 
+/*
+ * QEMU NeXT Keyboard/Mouse emulation
+ *
+ * Copyright (c) 2011 Bryce Lanham
+ *
+ * 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.
+ */
+
+/* This is admittedly hackish, but works well enough for basic input
+   Mouse support will be added once we can boot something that needs
+	the mouse. */
+
+#include "hw.h"
+#include "console.h"
+#include "next-kbd.h"
+
+/* debug NeXT keyboard */
+//#define DEBUG_KBD
+
+#ifdef DEBUG_KBD
+#define DPRINTF(fmt, ...)                                       \
+    do { printf("KBD: " fmt , ## __VA_ARGS__); } while (0);
+#else
+#define DPRINTF(fmt, ...)
+#endif
+/* follwoing defintions from next68k netbsd */
+#define CSR_INT 0x00800000
+#define CSR_DATA 0x00400000
+
+#define KD_KEYMASK              0x007f
+#define KD_DIRECTION            0x0080 /* pressed or released */
+#define KD_CNTL                 0x0100
+#define KD_LSHIFT               0x0200
+#define KD_RSHIFT               0x0400
+#define KD_LCOMM                0x0800
+#define KD_RCOMM                0x1000
+#define KD_LALT                 0x2000
+#define KD_RALT                 0x4000
+#define KD_VALID                0x8000 /* only set for scancode keys ? */
+#define KD_MODS                 0x4f00
+
+#define KBD_QUEUE_SIZE 256
+
+typedef struct {
+    uint8_t data[KBD_QUEUE_SIZE];
+    int rptr, wptr, count;
+} KBDQueue;
+
+
+typedef struct KBDState {
+    KBDQueue queue;
+    uint8_t blank;
+    int shift;//make this an unsigned short, and set it to the modifier value
+
+} KBDState;
+KBDState *kbd_env;
+static void nextkbd_event(void *opaque, int ch);
+
+static void queue_code(void *opaque, int code);
+static uint32_t kbd_read_byte(void *opaque, target_phys_addr_t addr);
+static uint32_t kbd_read_word(void *opaque, target_phys_addr_t addr);
+static uint32_t kbd_read_long(void *opaque, target_phys_addr_t addr);
+
+static void kbd_write_byte(void *opaque, target_phys_addr_t addr,
uint32_t val);
+static void kbd_write_word(void *opaque, target_phys_addr_t addr,
uint32_t val);
+static void kbd_write_long(void *opaque, target_phys_addr_t addr,
uint32_t val);
+
+static CPUWriteMemoryFunc *kbd_write[3] = {
+    kbd_write_byte,
+    kbd_write_word,
+    kbd_write_long
+};
+static CPUReadMemoryFunc *kbd_read[3] = {
+    kbd_read_byte,
+    kbd_read_word,
+    kbd_read_long
+};
+
+
+
+
+void nextkbd_init(void *opaque)
+{
+	KBDState *s = qemu_mallocz(sizeof(KBDState));
+
+	s->shift = 0;
+	
+	int kbd_addr = cpu_register_io_memory(kbd_read,kbd_write, (void
*)s,DEVICE_NATIVE_ENDIAN);
+	
+	cpu_register_physical_memory((uint32_t)0x200e000,0x1000,kbd_addr);//from
netbsd's cpu.h
+
+    qemu_add_kbd_event_handler(nextkbd_event, s);
+}
+
+static uint32_t kbd_read_byte(void *opaque, target_phys_addr_t addr)
+{
+    addr = addr & 0xe003;
+    switch(addr)
+    {
+    	
+        case 0xe000:
+		return 0x80|0x20;
+		
+        case 0xe001:
+		return 0x80|0x40|0x20|0x10;
+		
+        case 0xe002:
+		return 0x40|0x10|0x2|0x1;
+
+        default:
+        DPRINTF("RB ADDR %x\n",addr);
+        return 0;
+    }
+    return 0;
+}
+static uint32_t kbd_read_word(void *opaque, target_phys_addr_t addr)
+{
+    DPRINTF("RW ADDR %x\n",addr);
+    return 0;
+}
+static uint32_t kbd_read_long(void *opaque, target_phys_addr_t addr)
+{
+    int key = 0;
+    KBDState *s = (KBDState *)opaque;
+    KBDQueue *q = &s->queue;
+    switch(addr & 0xe00f)
+	{
+    	case 0xe000:
+	//	fprintf(stderr,"KB L Read: @ %X\n",((CPUM68KState *)opaque)->pc);
+		return 0xA0F09300;
+
+        case 0xe008:
+        /* get keycode from buffer */
+        if(q->count > 0)
+        {
+
+        key = q->data[q->rptr];
+        if (++q->rptr == KBD_QUEUE_SIZE)
+            q->rptr = 0;
+
+            q->count--;
+
+
+            if(s->shift)
+            key |= KD_LSHIFT;
+            if(key & 0x80)
+            return 0;
+            else
+            return 0x10000000 | KD_VALID | key;
+        }
+        else
+            return 0;
+    //    return 0x10009026;		
+
+        default:
+        DPRINTF("RL ADDR %x\n",addr);
+        return 0;
+    }
+}
+
+static void kbd_write_byte(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+    //DPRINTF("WB ADDR %x\n",addr);
+}
+static void kbd_write_word(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+    DPRINTF("WW ADDR %x\n",addr);
+}
+static void kbd_write_long(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+   // DPRINTF("WL ADDR %x\n",addr);
+}
+
+
+static void nextkbd_event(void *opaque, int ch)
+{
+    /*will want to set vars for caps/num lock*/
+    /*if (ch & 0x80) -> key release */
+   /* there's also e0 escaped scancodes that might need to be handled */
+     DPRINTF("EVENT %X\n",ch);
+
+    queue_code(opaque, ch);
+
+}
+
+static const unsigned char next_keycodes[128] = {
+  0,    0x49, 0x4A,  0x4B,  0x4C,  0x4D,  0x50,  0x4F,  0x4E,  0x1E,
0x1F,  0x20,  0x1D,  0x1C, 0x1B,  0,
+  0x42, 0x43, 0x44,  0x45,  0x48,  0x47,  0x46,  0x06,  0x07,  0x08,
0x0,  0,  0x2A,  0, 0x39,  0x3A,
+  0x3B,  0x3C,  0x3D,  0x40,  0x3F,  0x3E,  0x2D,  0x2C,  0x2B,
0x26,  0,  0,  0x31,  0x32, 0x33,  0x34,
+  0x35,  0x37,  0x36,  0x2e,  0x2f,  0x30,  0,  0,  0,  0x38,  0,  0,
 0,  0, 0,  0,
+  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 0,  0,
+  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 0,  0,
+  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 0,  0,
+  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 0,  0
+};
+
+static void queue_code(void *opaque, int code)
+{
+
+    KBDState *s = (KBDState *)opaque;
+    KBDQueue *q = &s->queue;
+    int key = code & 0x7F;
+    int release = code & 0x80;
+      if(code == 0x2A)
+            {
+                s->shift = 1;
+                return;
+            }
+            else if(code == (0x2A | 0x80))
+            {
+                s->shift = 0;
+                return;
+            }
+
+
+
+
+    if (q->count >= KBD_QUEUE_SIZE)
+        return;
+
+    q->data[q->wptr] = next_keycodes[key] | release;
+    if (++q->wptr == KBD_QUEUE_SIZE)
+        q->wptr = 0;
+    q->count++;
+    //s->update_irq(s->update_arg, 1);
+    s->blank += 1;
+}
diff --git hw/next-kbd.h hw/next-kbd.h
new file mode 100644
index 0000000..efee144
--- /dev/null
+++ hw/next-kbd.h
@@ -0,0 +1,2 @@ 
+
+void nextkbd_init(void *opaque);
diff --git hw/next-net.c hw/next-net.c
new file mode 100644
index 0000000..94739a1
--- /dev/null
+++ hw/next-net.c
@@ -0,0 +1,513 @@ 
+/*
+ * QEMU NeXT Network (MB8795) emulation
+ *
+ * Copyright (c) 2011 Bryce Lanham
+ *
+ * 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 "sysemu.h"//only needed for vm_stop
+#include "hw.h"
+#include "net.h"
+#include "next-net.h"
+#include "sysbus.h"
+/* debug NeXT ethernet */
+#define DEBUG_NET
+
+#ifdef DEBUG_NET
+#define DPRINTF(fmt, ...)                                       \
+    do { printf("NET: " fmt , ## __VA_ARGS__); } while (0);
+#else
+#define DPRINTF(fmt, ...)
+#endif
+
+/* IRQs should be moved to header later */
+#define TX_I_DMA 0
+#define RX_I_DMA 1
+#define TX_I 	 2
+#define RX_I     3
+/* names could be better */
+typedef struct NextDMA {
+	uint32_t csr;
+	uint32_t savedbase;
+	uint32_t savedlimit;
+	
+    uint32_t baser;
+    uint32_t base;
+    uint32_t limit;
+    uint32_t chainbase;
+    uint32_t chainlimit;
+	uint32_t basew;
+
+	
+} NextDMA;
+
+typedef struct NextNetState {
+    uint8_t mac[6];
+
+    qemu_irq *irq;
+
+    NICState *nic;
+    NICConf c;
+	
+    NextDMA tx_dma;
+	uint8_t tx_stat;
+	uint8_t tx_mask;
+    uint8_t tx_mode;
+	
+    NextDMA rx_dma;
+    uint8_t rx_stat;
+    uint8_t rx_mask;
+    uint8_t rx_mode;
+
+    uint8_t rst_mode;
+
+} NextNetState;
+
+NextNetState nextnet_state;
+
+void *env_g;
+
+void nextnet_irq(void *opaque, int n, int level);
+static int nextnet_can_rx(VLANClientState *nc);
+static ssize_t nextnet_rx(VLANClientState *nc, const uint8_t *buf,
size_t size);
+static void nextnet_cleanup(VLANClientState *nc);
+
+static NetClientInfo nextnet_info = {
+    .type = NET_CLIENT_TYPE_NIC,
+    .size = sizeof(NICState),
+    .can_receive = nextnet_can_rx,
+    .receive = nextnet_rx,
+    .cleanup = nextnet_cleanup,
+};
+/* these need to be somewhere else */
+extern uint32_t int_status;//should be set in a global irq handler
+extern uint32_t int_mask;
+extern uint32_t event_test;
+
+void nextnet_reset(NextNetState *s);
+void nextnet_reset(NextNetState *s)
+{
+
+
+}
+
+static uint32_t net_readb(void*opaque, target_phys_addr_t addr);
+static uint32_t net_readw(void*opaque, target_phys_addr_t addr);
+static uint32_t net_readl(void*opaque, target_phys_addr_t addr);
+static CPUReadMemoryFunc *net_read[3] = {
+	net_readb,
+	net_readw,
+	net_readl
+};
+
+static void net_writeb(void*opaque, target_phys_addr_t addr, uint32_t value);
+static void net_writew(void*opaque, target_phys_addr_t addr, uint32_t value);
+static void net_writel(void*opaque, target_phys_addr_t addr, uint32_t value);
+static CPUWriteMemoryFunc * const net_write[3] = {
+	net_writeb,
+	net_writew,
+	net_writel
+};
+
+
+void nextnet_init(void *opaque)
+{
+    NextNetState *s = &nextnet_state;
+	CPUState *env = (CPUState *)opaque;
+    env_g = opaque;//used this as a global during testing, should be removed
+
+	/*register device register space */
+    cpu_register_physical_memory((uint32_t)0x2106000,0x1000,
+        cpu_register_io_memory(net_read,net_write, (void
*)&nextnet_state,DEVICE_NATIVE_ENDIAN));
+  cpu_register_physical_memory((uint32_t)0x2006000,0x1000,
+        cpu_register_io_memory(net_read,net_write, (void
*)&nextnet_state,DEVICE_NATIVE_ENDIAN));
+
+
+    /* and ethernet control/status registers *///including DMA for
now, will seperate out later
+    cpu_register_physical_memory((uint32_t)0x2000110,0x4400,
+        cpu_register_io_memory(net_read,net_write, (void
*)&nextnet_state,DEVICE_NATIVE_ENDIAN));
+
+    /* connect to virtual lan */
+    s->c.vlan = qemu_find_vlan(0,1);
+
+    /* register nic */
+    s->nic = qemu_new_nic(&nextnet_info,&s->c, "NeXT MB8795\0", NULL, s);
+
+    /* this needs to be read, will have to load rom file i guess */
+    uint8_t mac[6] = {0,0,0xf,0,0xf3,0x2};
+    memcpy(&s->mac,mac,6); 	
+
+	/* allocate TX/RX and DMA irqs - will be global later */
+    s->irq = qemu_allocate_irqs(nextnet_irq, env, 4);
+
+    /* this sets the nic's info */
+    qemu_format_nic_info_str(&s->nic->nc, mac);
+
+
+}
+/* It is likely that all register reads are bytes, while all CSR r/w
are longs */
+static uint32_t net_readb(void*opaque, target_phys_addr_t addr)
+{
+    NextNetState *s = (NextNetState *)opaque;
+
+//	CPUState *env = (CPUState *)env_g;
+    switch(addr)
+    {
+        case 0x6000://TXSTAT
+            // DPRINTF("TXSTAT \tRead\n");
+            return s->tx_stat;
+
+        case 0x6001:
+            DPRINTF("TXMASK \tRead\n");
+            return s->tx_mask;
+
+        case 0x6002:
+          //  DPRINTF("RXSTAT \tRead  %x @ %x\n",s->rx_stat,env->pc);
+            return s->rx_stat;
+
+        case 0x6003:
+          //  DPRINTF("RXMASK \tRead\n");
+            return s->rx_mask;
+
+        case 0x6004:
+            DPRINTF("TXMODE \tRead\n");
+            return s->tx_mode;
+
+        case 0x6005:
+          //  DPRINTF("RXMODE \tRead\n");
+            return s->rx_mode;
+
+        case 0x6006:
+            DPRINTF("RSTMODE \tRead\n");
+            return s->rst_mode;
+
+        default:
+            fprintf(stderr,"NET Read B @ %x\n",addr);
+            return 0;
+    }
+}
+static uint32_t net_readw(void*opaque, target_phys_addr_t addr)
+{
+	fprintf(stderr,"S Read W @ %x\n",addr);
+	return 0;
+}
+static uint32_t net_readl(void*opaque, target_phys_addr_t addr)
+{
+    NextNetState *s = (NextNetState *)opaque;
+	CPUState *env = (CPUState *)env_g;
+	switch(addr)
+    {
+        case 0x110:
+
+            //DPRINTF("TXCSR Read\n");
+            return s->tx_dma.csr;
+        case 0x4100:
+            fprintf(stderr,"SAVEDBASE Read\n");
+            return s->tx_dma.savedbase;
+		case 0x4104:
+            fprintf(stderr,"SAVELIMIT Read\n");
+			return s->tx_dma.savedlimit;
+		case 0x4114:
+            fprintf(stderr,"TXLIMIT Read\n");
+			return s->tx_dma.limit;
+		case 0x4310:
+            fprintf(stderr,"TXBASE Read\n");
+			/* FUTURE :return nextdma_read(device, addr); */	
+			return s->tx_dma.basew;
+
+		case 0x150:
+           // fprintf(stderr,"RXCSR Read %x\n",s->rx_dma.csr);
+            return s->rx_dma.csr;
+
+		case 0x4140:
+			return s->rx_dma.savedbase;
+        case 0x4144:
+            DPRINTF("SAVELIMIT %x @ %x\n",s->rx_dma.savedlimit,env->pc);
+            return s->rx_dma.savedlimit;
+		
+        default:
+        fprintf(stderr,"NET Read l @ %x\n",addr);
+        return 0;
+    }
+}
+#define NET_TXSTAT_CLEAR 0xFF
+#define NET_RXSTAT_CLEAR 0xFF
+static void net_writeb(void*opaque, target_phys_addr_t addr, uint32_t value)
+{
+//	CPUState *env = (CPUState *)env_g;
+    NextNetState *s = (NextNetState *)opaque;
+    switch(addr)
+    {
+    	case 0x6000:
+            DPRINTF("TXSTAT \tWrite: %x\n",value);
+            if(value == NET_TXSTAT_CLEAR)
+               s->tx_stat = 0x80;
+            else
+                s->tx_stat = value;
+            break;
+        case 0x6001:
+            DPRINTF("TXMASK \tWrite: %x\n",value);
+            s->tx_mask = value;
+            break;
+        case 0x6002:
+         //   DPRINTF("RXSTAT \tWrite: %x @ %x\n",value,env->pc);
+            if(value == NET_RXSTAT_CLEAR)
+                s->rx_stat = 0;
+            else
+                s->rx_stat = value;
+            break;
+        case 0x6003:
+        //    DPRINTF("RXMASK \tWrite: %x\n",value);
+            s->rx_mask = value;
+            break;
+        case 0x6004:
+            DPRINTF("TXMODE \tWrite: %x\n",value);
+            s->tx_mode = value;
+            break;
+        case 0x6005:
+          //  DPRINTF("RXMODE \tWrite: %x\n",value);
+            s->rx_mode = value;
+            break;
+        case 0x6006:
+            DPRINTF("RSTMODE \tWrite: %x\n",value);
+            s->rst_mode = value;
+            break;
+        case 0x600d:
+        s->mac[(addr&0xF)-8] = value;
+        DPRINTF("Set MAC ADDR %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
+            s->mac[0],s->mac[1],s->mac[2],s->mac[3],s->mac[4],s->mac[5]);
+        qemu_macaddr_default_if_unset((MACAddr *)&s->mac);
+        break;
+        case 0x6008:case 0x6009:case 0x600a: case 0x600b: case 0x600c:
+        s->mac[(addr&0xF)-8] = value;
+        break;
+        case 0x6010:case 0x6011: case 0x6012: case 0x6013: case 0x6014:
+     //   break;
+        default:
+        fprintf(stderr,"NET Write B @ %x with %x\n",addr,value);
+    }
+}
+static void net_writew(void*opaque, target_phys_addr_t addr, uint32_t value)
+{
+	fprintf(stderr,"NET W w @ %x with %x\n",addr,value);
+}
+#define DMA_ENABLE		0x01000000
+#define DMA_SUPDATE		0x02000000
+#define DMA_COMPLETE	0x08000000
+
+#define DMA_M2DEV       0x0
+#define DMA_SETENABLE   0x00010000
+#define DMA_SETSUPDATE  0x00020000
+#define DMA_DEV2M		0x00040000
+#define DMA_CLRCOMPLETE 0x00080000
+#define DMA_RESET		0x00100000
+static void net_writel(void*opaque, target_phys_addr_t addr, uint32_t value)
+{
+	static int tx_count = 0;
+    NextNetState *s = (NextNetState *)opaque;
+	switch(addr)
+    {
+        case 0x110:
+        {
+				
+								
+				if(value & DMA_SETENABLE)
+				{
+                tx_count++;
+			//	if(tx_count % 4) return;
+				size_t len = (0xFFFFFFF & s->tx_dma.limit) - s->tx_dma.base;
+              DPRINTF("TXDMA ENABLE: %x len: %zu\n",s->tx_dma.base, len);
+				DPRINTF("TX Enable\n");
+                uint8_t buf[1600];//needs to be in dma struct?
+                cpu_physical_memory_read(s->tx_dma.base, buf, len);
+
+				qemu_send_packet(&s->nic->nc, buf,len);
+               	s->tx_dma.csr |= DMA_COMPLETE | DMA_SUPDATE;
+			    s->tx_stat =  0x80;
+			//	if(tx_count > 1510) vm_stop(VMSTOP_DEBUG);
+				
+    			qemu_set_irq(s->irq[TX_I_DMA],3);
+
+				}
+				if(value & DMA_SETSUPDATE)
+					s->tx_dma.csr |= DMA_SUPDATE;	
+		
+				if(value & DMA_CLRCOMPLETE)
+					s->tx_dma.csr &= ~DMA_COMPLETE;
+
+				if(value & DMA_RESET)
+					s->tx_dma.csr &= ~(DMA_COMPLETE | DMA_SUPDATE | DMA_ENABLE);	
+		}
+        break;
+
+        case 0x4100:
+        DPRINTF("Write l @ %x with %x\n",addr,value);
+			s->tx_dma.savedbase = value;
+		    break;
+		
+		case 0x4104:
+        DPRINTF("Write l @ %x with %x\n",addr,value);
+			s->tx_dma.savedlimit = value;
+		    break;
+		case 0x4110:
+        DPRINTF("Write l @ %x with %x\n",addr,value);
+			s->tx_dma.base = value;
+			break;	
+        case 0x4114:
+        DPRINTF("Write l @ %x with %x\n",addr,value);
+			s->tx_dma.limit = value;
+		    break;
+		
+        case 0x4310:
+        DPRINTF("Write l @ %x with %x\n",addr,value);
+			s->tx_dma.base = value;
+			/* FUTURE :nextdma_write(device, addr, value); */	
+            break;
+
+        case 0x150:
+            	if(value & DMA_DEV2M)
+                {
+                    DPRINTF("RX Dev to Memory\n");
+				}	
+				
+                if(value & DMA_SETENABLE)
+                    s->rx_dma.csr |= DMA_ENABLE;
+
+				if(value & DMA_SETSUPDATE)
+					s->rx_dma.csr |= DMA_SUPDATE;	
+		
+				if(value & DMA_CLRCOMPLETE)
+					s->rx_dma.csr &= ~DMA_COMPLETE;
+
+				if(value & DMA_RESET)
+					s->rx_dma.csr &= ~(DMA_COMPLETE | DMA_SUPDATE | DMA_ENABLE);				
+				//
+	
+				DPRINTF("RXCSR \tWrite: %x\n",value);
+	        	break;
+
+        case 0x4150:
+
+       // DPRINTF("Write l @ %x with %x\n",addr,value);
+            s->rx_dma.base = value;
+		//	s->rx_dma.savedbase = value;
+            break;
+
+        case 0x4154:
+            s->rx_dma.limit = value;
+       // DPRINTF("Write l @ %x with %x\n",addr,value);
+            break;
+
+        case 0x4158:
+            s->rx_dma.chainbase = value;
+       // DPRINTF("Write l @ %x with %x\n",addr,value);
+            break;
+
+        case 0x415c:
+            s->rx_dma.chainlimit = value;
+       // DPRINTF("Write l @ %x with %x\n",addr,value);
+            //DPRINTF("Pointer write %x w %x\n",addr,value);
+            break;
+        default:
+        DPRINTF("Write l @ %x with %x\n",addr,value);
+    }
+
+}
+
+static int nextnet_can_rx(VLANClientState *nc)
+{
+    NextNetState *s = DO_UPCAST(NICState, nc, nc)->opaque;
+    if(s->rx_mode & 0x3)
+		return 1;
+	else
+		return -1;
+}
+
+static ssize_t nextnet_rx(VLANClientState *nc, const uint8_t *buf, size_t size)
+{
+	NextNetState *s = DO_UPCAST(NICState, nc, nc)->opaque;
+
+	DPRINTF("received packet %zu\n",size);
+
+	/* Ethernet DMA is supposedly 32 byte aligned */	
+	if((size % 32) != 0)
+	{
+		size -= size % 32;
+		size += 32;
+	}
+	
+	/* write the packet into memory */
+	cpu_physical_memory_write(s->rx_dma.base,buf,size);
+	
+	/* saved limit is checked to calculate packet size
+		by both the rom and netbsd */
+	s->rx_dma.savedlimit = (s->rx_dma.base + size);
+	s->rx_dma.savedbase = (s->rx_dma.base);
+	
+	/*32 bytes under savedbase seems to be some kind of register
+	of which the purpose is unknown as of yet*/
+	//stl_phys(s->rx_dma.base-32,0xFFFFFFFF);
+	
+	if((s->rx_dma.csr & DMA_SUPDATE)){	
+		s->rx_dma.base = s->rx_dma.chainbase;
+		s->rx_dma.limit = s->rx_dma.chainlimit;
+	}
+	//we received a packet
+    s->rx_stat = 0x80;
+	
+	//Set dma registers and raise an irq
+	s->rx_dma.csr |= DMA_COMPLETE; //DON'T CHANGE THIS!!!!
+   	qemu_set_irq(s->irq[RX_I_DMA],6);
+
+	return size;
+}
+
+static void nextnet_cleanup(VLANClientState *nc)
+{
+}
+
+/* level and vector values taken from Plan 9 source */
+void nextnet_irq(void *opaque, int n, int level)
+{
+    CPUM68KState *s = (CPUM68KState *)opaque;
+    switch(n)
+	{
+		case TX_I:
+			int_status = 1<<10;
+			m68k_set_irq_level(s,3,27);
+			break;
+		
+		case RX_I:
+			int_status = 1<<9;
+			m68k_set_irq_level(s,3,27);
+			break;
+		
+		case TX_I_DMA:
+			int_status = 1<<28;
+			m68k_set_irq_level(s,6,30);
+            break;
+		
+		case RX_I_DMA:
+			int_status = 1<<27;
+			m68k_set_irq_level(s,6,30);
+			break;
+	}
+
+	
+}		
diff --git hw/next-net.h hw/next-net.h
new file mode 100644
index 0000000..28b7358
--- /dev/null
+++ hw/next-net.h
@@ -0,0 +1,2 @@ 
+
+void nextnet_init(void *opaque);
diff --git linux-user/main.c linux-user/main.c
index 8e15474..62aa983 100644
--- linux-user/main.c
+++ linux-user/main.c
@@ -2815,8 +2815,10 @@  static void usage(void)
            "-strace      log system calls\n"
            "\n"
            "Environment variables:\n"
-           "QEMU_STRACE       Print system calls and arguments
similar to the\n"
-           "                  'strace' program.  Enable by setting to
any value.\n"
+           "QEMU_STRACE        Print system calls and arguments
similar to the\n"
+           "                   'strace' program.  Enable by setting
to any value.\n"
+           "QEMU_DEBUG=options Activate log. Use same options as '-d'
options\n"
+           "QEMU_GDB=port      Wait gdb connection to port\n"
            "You can use -E and -U options to set/unset environment variables\n"
            "for target process.  It is possible to provide several variables\n"
            "by repeating the option.  For example:\n"
@@ -2872,7 +2874,7 @@  int main(int argc, char **argv, char **envp)
     const char *filename;
     const char *cpu_model;
     const char *log_file = DEBUG_LOGFILE;
-    const char *log_mask = NULL;
+    const char *log_mask = getenv("QEMU_DEBUG");
     struct target_pt_regs regs1, *regs = &regs1;
     struct image_info info1, *info = &info1;
     struct linux_binprm bprm;
@@ -2919,6 +2921,12 @@  int main(int argc, char **argv, char **envp)
 #if defined(cpudef_setup)
     cpudef_setup(); /* parse cpu definitions in target config file (TBD) */
 #endif
+    if (getenv("QEMU_GDB")) {
+      gdbstub_port = atoi(getenv("QEMU_GDB"));
+    }
+    /* don't propagate QEMU_DEBUG and _GDB to children */
+    unsetenv("QEMU_DEBUG");
+    unsetenv("QEMU_GDB");

     optind = 1;
     for(;;) {
@@ -3083,39 +3091,7 @@  int main(int argc, char **argv, char **envp)
     init_paths(interp_prefix);

     if (cpu_model == NULL) {
-#if defined(TARGET_I386)
-#ifdef TARGET_X86_64
-        cpu_model = "qemu64";
-#else
-        cpu_model = "qemu32";
-#endif
-#elif defined(TARGET_ARM)
-        cpu_model = "any";
-#elif defined(TARGET_UNICORE32)
-        cpu_model = "any";
-#elif defined(TARGET_M68K)
-        cpu_model = "any";
-#elif defined(TARGET_SPARC)
-#ifdef TARGET_SPARC64
-        cpu_model = "TI UltraSparc II";
-#else
-        cpu_model = "Fujitsu MB86904";
-#endif
-#elif defined(TARGET_MIPS)
-#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64)
-        cpu_model = "20Kc";
-#else
-        cpu_model = "24Kf";
-#endif
-#elif defined(TARGET_PPC)
-#ifdef TARGET_PPC64
-        cpu_model = "970fx";
-#else
-        cpu_model = "750";
-#endif
-#else
-        cpu_model = "any";
-#endif
+        cpu_model = TARGET_DEFAULT_CPU;
     }
     tcg_exec_init(0);
     cpu_exec_init_all();
diff --git linux-user/qemu-wrapper.c linux-user/qemu-wrapper.c
new file mode 100644
index 0000000..6926a6c
--- /dev/null
+++ linux-user/qemu-wrapper.c
@@ -0,0 +1,97 @@ 
+/*
+ * qemu-wrapper
+ *
+ * Copyright (c) 2011 Laurent Vivier
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * HOWTO
+ *
+ * for instance, for m68k target.
+ *
+ * copy qemu-wrapper and qemu-m68 into the m68k filesystem:
+ *
+ *   cd m68k-linux-user
+ *   sudo cp qemu-m68k qemu-wrapper /m68k/usr/bin/qemu-wrapper
+ *
+ * update binfmts:
+ *
+ * update-binfmts --install m68k /usr/bin/qemu-wrapper \
+ *                 --magic \
+ * \x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x04 \
+ *                 --mask \
+ * \xff\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff
+ *
+ * chroot the m68k filesystem:
+ *
+ * sudo QEMU_CPU=m68020 chroot /m68k
+ *
+ *                ******** IMPORTANT NOTE ********
+ *
+ * qemu-m68k and qemu-wrapper must be linked staticaly:
+ *
+ *   ./configure --target-list=m68k-linux-user --static
+ *
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "config-target.h"
+
+int main(int argc, char **argv, char **envp) {
+	char *wrapper[argc + 7];
+	int current = 0;
+	char *cpu, *debug, *port;
+
+	wrapper[current] = argv[0];
+	current++;
+
+	cpu = getenv("QEMU_CPU");
+	if (cpu) {
+		wrapper[current] = (char*)"-cpu";
+		current++;
+		wrapper[current] = cpu;
+		current++;
+	}
+
+	debug = getenv("QEMU_DEBUG");
+	if (debug) {
+		wrapper[current] = (char*)"-d";
+		current++;
+		wrapper[current] = debug;
+		current++;
+	}
+	unsetenv("QEMU_DEBUG");
+
+	port = getenv("QEMU_GDB");
+	if (port) {
+		wrapper[current] = (char*)"-g";
+		current++;
+		wrapper[current] = port;
+		current++;
+	}
+	unsetenv("QEMU_GDB");
+
+	memcpy(&wrapper[current], &argv[1], sizeof(*argv) * (argc - 1));
+	current += argc - 1;
+
+	wrapper[current] = NULL;
+
+	return execve("/usr/bin/qemu-" TARGET_ARCH, wrapper, envp);
+}
diff --git linux-user/qemu.h linux-user/qemu.h
index 627c8b3..ae87149 100644
--- linux-user/qemu.h
+++ linux-user/qemu.h
@@ -87,6 +87,7 @@  struct vm86_saved_state {
 struct sigqueue {
     struct sigqueue *next;
     target_siginfo_t info;
+    pid_t pid;
 };

 struct emulated_sigtable {
diff --git linux-user/signal.c linux-user/signal.c
index 07ad07a..0ba11bd 100644
--- linux-user/signal.c
+++ linux-user/signal.c
@@ -472,6 +472,7 @@  int queue_signal(CPUState *env, int sig,
target_siginfo_t *info)
         *pq = q;
         q->info = *info;
         q->next = NULL;
+        q->pid = getpid();
         k->pending = 1;
         /* signal that a new signal is pending */
         ts->signal_pending = 1;
@@ -5231,21 +5232,34 @@  void process_pending_signals(CPUState *cpu_env)
     target_sigset_t target_old_set;
     struct emulated_sigtable *k;
     struct target_sigaction *sa;
-    struct sigqueue *q;
-    TaskState *ts = cpu_env->opaque;
+    struct sigqueue *q, *q_prev;
+    TaskState *ts = thread_env->opaque;

     if (!ts->signal_pending)
         return;

-    /* FIXME: This is not threadsafe.  */
     k = ts->sigtab;
+    int signal_pending = 0;
     for(sig = 1; sig <= TARGET_NSIG; sig++) {
         if (k->pending)
-            goto handle_signal;
+        {
+            q = k->first;
+            q_prev = NULL;
+            while (q)
+            {
+                if (q->pid == getpid())
+                    goto handle_signal;
+                else
+                    signal_pending = 1;
+                q_prev = q;
+                q = q->next;
+            }
+        }
         k++;
     }
+
     /* if no signal is pending, just return */
-    ts->signal_pending = 0;
+    ts->signal_pending = signal_pending;
     return;

  handle_signal:
@@ -5253,9 +5267,18 @@  void process_pending_signals(CPUState *cpu_env)
     fprintf(stderr, "qemu: process signal %d\n", sig);
 #endif
     /* dequeue signal */
-    q = k->first;
-    k->first = q->next;
-    if (!k->first)
+    if (q_prev == k->first)
+    {
+        q = k->first;
+        k->first = q->next;
+        if (!k->first)
+        {
+            k->pending = 0;
+        }
+    }
+    else if (q_prev)
+        q_prev->next = q->next;
+    else
         k->pending = 0;

     sig = gdb_handlesig (cpu_env, sig);
diff --git linux-user/syscall_defs.h linux-user/syscall_defs.h
index a117407..aa94a14 100644
--- linux-user/syscall_defs.h
+++ linux-user/syscall_defs.h
@@ -2058,6 +2058,24 @@  struct target_statfs64 {
 #define TARGET_O_NOFOLLOW	0x10000	/* don't follow links */
 #define TARGET_O_NOATIME	0x100000
 #define TARGET_O_NDELAY	TARGET_O_NONBLOCK
+#elif defined (TARGET_M68K)
+#define TARGET_O_ACCMODE          0003
+#define TARGET_O_RDONLY             00
+#define TARGET_O_WRONLY             01
+#define TARGET_O_RDWR               02
+#define TARGET_O_CREAT            0100 /* not fcntl */
+#define TARGET_O_EXCL             0200 /* not fcntl */
+#define TARGET_O_NOCTTY           0400 /* not fcntl */
+#define TARGET_O_TRUNC           01000 /* not fcntl */
+#define TARGET_O_APPEND          02000
+#define TARGET_O_NONBLOCK        04000
+#define TARGET_O_NDELAY        TARGET_O_NONBLOCK
+#define TARGET_O_SYNC           010000
+#define TARGET_FASYNC           020000 /* fcntl, for BSD compatibility */
+#define TARGET_O_DIRECTORY      040000 /* must be a directory */
+#define TARGET_O_NOFOLLOW      0100000 /* don't follow links */
+#define TARGET_O_DIRECT        0200000 /* direct disk access hint */
+#define TARGET_O_LARGEFILE     0400000
 #else
 #define TARGET_O_ACCMODE          0003
 #define TARGET_O_RDONLY             00
diff --git qemu-doc.texi qemu-doc.texi
index 31199f6..2193463 100644
--- qemu-doc.texi
+++ qemu-doc.texi
@@ -2293,6 +2293,10 @@  space emulator hasn't implemented ptrace).  At
the moment this is
 incomplete.  All system calls that don't have a specific argument
 format are printed with information for six arguments.  Many
 flag-style arguments don't have decoders and will show up as numbers.
+@item QEMU_DEBUG=options
+Activate log. Use same options as '-d' options.
+@item QEMU_GDB=port
+Wait gdb connection to port.
 @end table

 @node Other binaries
diff --git scripts/set_binfmt_m68k scripts/set_binfmt_m68k
new file mode 100755
index 0000000..fb3d720
--- /dev/null
+++ scripts/set_binfmt_m68k
@@ -0,0 +1,8 @@ 
+#!/bin/bash
+
+name="m68k"
+magic="\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x04"
+mask="\xff\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff"
+
+update-binfmts --install $name /usr/bin/qemu-m68k \
+               --magic $magic --mask $mask
diff --git target-m68k/cpu.h target-m68k/cpu.h
index 0667f82..006ecdc 100644
--- target-m68k/cpu.h
+++ target-m68k/cpu.h
@@ -54,9 +54,42 @@ 

 #define EXCP_RTE            0x100
 #define EXCP_HALT_INSN      0x101
+#ifdef CONFIG_EMULOP
+#define EXCP_EXEC_RETURN    0x20000
+#endif

 #define NB_MMU_MODES 2

+#define TARGET_PHYS_ADDR_SPACE_BITS 32
+#define TARGET_VIRT_ADDR_SPACE_BITS 32
+
+#ifdef CONFIG_USER_ONLY
+/* Linux uses 4k pages.  */
+#define TARGET_PAGE_BITS 12
+#else
+/* Smallest TLB entry size is 1k.  */
+#define TARGET_PAGE_BITS 10
+#endif
+
+#include "cpu-all.h"
+
+typedef uint32_t CPUM68K_SingleU;
+typedef uint64_t CPUM68K_DoubleU;
+
+typedef struct {
+    uint32_t high;
+    uint64_t low;
+} __attribute__((packed)) CPUM68K_XDoubleU;
+
+typedef struct {
+   uint8_t high[2];
+   uint8_t low[10];
+} __attribute__((packed)) CPUM68K_PDoubleU;
+
+typedef CPU_LDoubleU FPReg;
+#define PRIxFPH PRIx16
+#define PRIxFPL PRIx64
+
 typedef struct CPUM68KState {
     uint32_t dregs[8];
     uint32_t aregs[8];
@@ -66,15 +99,18 @@  typedef struct CPUM68KState {
     /* SSP and USP.  The current_sp is stored in aregs[7], the other here.  */
     int current_sp;
     uint32_t sp[2];
-
     /* Condition flags.  */
     uint32_t cc_op;
     uint32_t cc_dest;
     uint32_t cc_src;
     uint32_t cc_x;
-
-    float64 fregs[8];
-    float64 fp_result;
+	/* Control Registers */
+	uint32_t sfc;
+	uint32_t dfc;
+	uint32_t itt0,itt1;
+	uint32_t dtt0,dtt1;
+	/* FPU Registers */
+    FPReg fregs[8];
     uint32_t fpcr;
     uint32_t fpsr;
     float_status fp_status;
@@ -87,14 +123,25 @@  typedef struct CPUM68KState {
     uint32_t macsr;
     uint32_t mac_mask;

+    /* Temporary storage for FPU */
+
+    uint32_t fp0h;
+    uint64_t fp0l;
+    uint32_t fp1h;
+    uint64_t fp1l;
+
     /* Temporary storage for DIV helpers.  */
     uint32_t div1;
     uint32_t div2;

+    /* Upper 32 bits of a 64bit operand for quad MUL/DIV.  */
+    uint32_t quadh;
+
     /* MMU status.  */
     struct {
         uint32_t ar;
-    } mmu;
+    	uint32_t tc;
+	} mmu;

     /* Control registers.  */
     uint32_t vbr;
@@ -131,13 +178,23 @@  void cpu_m68k_flush_flags(CPUM68KState *, int);
 enum {
     CC_OP_DYNAMIC, /* Use env->cc_op  */
     CC_OP_FLAGS, /* CC_DEST = CVZN, CC_SRC = unused */
+    CC_OP_LOGICB, /* CC_DEST = result, CC_SRC = unused */
+    CC_OP_LOGICW, /* CC_DEST = result, CC_SRC = unused */
     CC_OP_LOGIC, /* CC_DEST = result, CC_SRC = unused */
+    CC_OP_ADDB,   /* CC_DEST = result, CC_SRC = source */
+    CC_OP_ADDW,   /* CC_DEST = result, CC_SRC = source */
     CC_OP_ADD,   /* CC_DEST = result, CC_SRC = source */
+    CC_OP_SUBB,   /* CC_DEST = result, CC_SRC = source */
+    CC_OP_SUBW,   /* CC_DEST = result, CC_SRC = source */
     CC_OP_SUB,   /* CC_DEST = result, CC_SRC = source */
-    CC_OP_CMPB,  /* CC_DEST = result, CC_SRC = source */
-    CC_OP_CMPW,  /* CC_DEST = result, CC_SRC = source */
+    CC_OP_ADDXB,  /* CC_DEST = result, CC_SRC = source */
+    CC_OP_ADDXW,  /* CC_DEST = result, CC_SRC = source */
     CC_OP_ADDX,  /* CC_DEST = result, CC_SRC = source */
+    CC_OP_SUBXB,  /* CC_DEST = result, CC_SRC = source */
+    CC_OP_SUBXW,  /* CC_DEST = result, CC_SRC = source */
     CC_OP_SUBX,  /* CC_DEST = result, CC_SRC = source */
+    CC_OP_SHIFTB, /* CC_DEST = result, CC_SRC = carry */
+    CC_OP_SHIFTW, /* CC_DEST = result, CC_SRC = carry */
     CC_OP_SHIFT, /* CC_DEST = result, CC_SRC = carry */
 };

@@ -182,6 +239,7 @@  void do_m68k_semihosting(CPUM68KState *env, int nr);
    ISA revisions mentioned.  */

 enum m68k_features {
+    M68K_FEATURE_M68000,
     M68K_FEATURE_CF_ISA_A,
     M68K_FEATURE_CF_ISA_B, /* (ISA B or C).  */
     M68K_FEATURE_CF_ISA_APLUSC, /* BIT/BITREV, FF1, STRLDSR (ISA A+ or C).  */
@@ -192,7 +250,14 @@  enum m68k_features {
     M68K_FEATURE_CF_EMAC_B, /* Revision B EMAC (dual accumulate).  */
     M68K_FEATURE_USP, /* User Stack Pointer.  (ISA A+, B or C).  */
     M68K_FEATURE_EXT_FULL, /* 68020+ full extension word.  */
-    M68K_FEATURE_WORD_INDEX /* word sized address index registers.  */
+    M68K_FEATURE_WORD_INDEX, /* word sized address index registers.  */
+    M68K_FEATURE_SCALED_INDEX, /* scaled address index registers.  */
+    M68K_FEATURE_LONG_MULDIV,	/* 32 bit multiply/divide. */
+    M68K_FEATURE_QUAD_MULDIV,	/* 64 bit multiply/divide. */
+    M68K_FEATURE_BCCL,		/* Long conditional branches.  */
+    M68K_FEATURE_BITFIELD,	/* Bit field insns.  */
+    M68K_FEATURE_FPU,
+    M68K_FEATURE_CAS
 };

 static inline int m68k_feature(CPUM68KState *env, int feature)
@@ -204,17 +269,6 @@  void m68k_cpu_list(FILE *f, fprintf_function cpu_fprintf);

 void register_m68k_insns (CPUM68KState *env);

-#ifdef CONFIG_USER_ONLY
-/* Linux uses 8k pages.  */
-#define TARGET_PAGE_BITS 13
-#else
-/* Smallest TLB entry size is 1k.  */
-#define TARGET_PAGE_BITS 10
-#endif
-
-#define TARGET_PHYS_ADDR_SPACE_BITS 32
-#define TARGET_VIRT_ADDR_SPACE_BITS 32
-
 #define cpu_init cpu_m68k_init
 #define cpu_exec cpu_m68k_exec
 #define cpu_gen_code cpu_m68k_gen_code
@@ -243,8 +297,6 @@  static inline void cpu_clone_regs(CPUState *env,
target_ulong newsp)
 }
 #endif

-#include "cpu-all.h"
-
 static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
                                         target_ulong *cs_base, int *flags)
 {
@@ -267,4 +319,5 @@  static inline void cpu_pc_from_tb(CPUState *env,
TranslationBlock *tb)
     env->pc = tb->pc;
 }

+
 #endif
diff --git target-m68k/helper.c target-m68k/helper.c
index 7ca75fb..5fa5b06 100644
--- target-m68k/helper.c
+++ target-m68k/helper.c
@@ -27,10 +27,32 @@ 
 #include "gdbstub.h"

 #include "helpers.h"
+#include <math.h>
+
+#if 0
+#define DBG_FPUH(...) do { fprintf(stderr, "0x%08x: ", env->pc);
fprintf(stderr, __VA_ARGS__); } while(0)
+#define DBG_FPU(...) do { fprintf(stderr, __VA_ARGS__); } while(0)
+#else
+#define DBG_FPUH(...)
+#define DBG_FPU(...)
+#endif
+static inline float FLOAT(float32 x)
+{
+    return *(float *)&x;
+}
+static inline double DOUBLE(float64 x)
+{
+    return *(double *)&x;
+}

 #define SIGNBIT (1u << 31)

 enum m68k_cpuid {
+    M68K_CPUID_M68000,
+    M68K_CPUID_M68020,
+    M68K_CPUID_M68030,
+    M68K_CPUID_M68040,
+    M68K_CPUID_M68060,
     M68K_CPUID_M5206,
     M68K_CPUID_M5208,
     M68K_CPUID_CFV4E,
@@ -45,6 +67,11 @@  struct m68k_def_t {
 };

 static m68k_def_t m68k_cpu_defs[] = {
+    {"m68000", M68K_CPUID_M68000},
+    {"m68020", M68K_CPUID_M68020},
+    {"m68030", M68K_CPUID_M68030},
+    {"m68040", M68K_CPUID_M68040},
+    {"m68060", M68K_CPUID_M68060},
     {"m5206", M68K_CPUID_M5206},
     {"m5208", M68K_CPUID_M5208},
     {"cfv4e", M68K_CPUID_CFV4E},
@@ -52,19 +79,61 @@  static m68k_def_t m68k_cpu_defs[] = {
     {NULL, 0},
 };

+/* modulo 33 table */
+const uint8_t rox32_table[64] = {
+    0, 1, 2, 3, 4, 5, 6, 7,
+    8, 9,10,11,12,13,14,15,
+   16,17,18,19,20,21,22,23,
+   24,25,26,27,28,29,30,31,
+   32, 0, 1, 2, 3, 4, 5, 6,
+    7, 8, 9,10,11,12,13,14,
+   15,16,17,18,19,20,21,22,
+   23,24,25,26,27,28,29,30,
+};
+
+/* modulo 17 table */
+const uint8_t rox16_table[64] = {
+    0, 1, 2, 3, 4, 5, 6, 7,
+    8, 9,10,11,12,13,14,15,
+   16, 0, 1, 2, 3, 4, 5, 6,
+    7, 8, 9,10,11,12,13,14,
+   15,16, 0, 1, 2, 3, 4, 5,
+    6, 7, 8, 9,10,11,12,13,
+   14,15,16, 0, 1, 2, 3, 4,
+    5, 6, 7, 8, 9,10,11,12,
+};
+
+/* modulo 9 table */
+const uint8_t rox8_table[64] = {
+    0, 1, 2, 3, 4, 5, 6, 7,
+    8, 0, 1, 2, 3, 4, 5, 6,
+    7, 8, 0, 1, 2, 3, 4, 5,
+    6, 7, 8, 0, 1, 2, 3, 4,
+    5, 6, 7, 8, 0, 1, 2, 3,
+    4, 5, 6, 7, 8, 0, 1, 2,
+    3, 4, 5, 6, 7, 8, 0, 1,
+    2, 3, 4, 5, 6, 7, 8, 0,
+};
+
 void m68k_cpu_list(FILE *f, fprintf_function cpu_fprintf)
 {
     unsigned int i;

     for (i = 0; m68k_cpu_defs[i].name; i++) {
+        if (strcmp(m68k_cpu_defs[i].name, TARGET_DEFAULT_CPU) == 0) {
+            (*cpu_fprintf)(f, " >");
+        } else {
+            (*cpu_fprintf)(f, "  ");
+        }
         (*cpu_fprintf)(f, "%s\n", m68k_cpu_defs[i].name);
     }
 }

-static int fpu_gdb_get_reg(CPUState *env, uint8_t *mem_buf, int n)
+static int cf_fpu_gdb_get_reg(CPUState *env, uint8_t *mem_buf, int n)
 {
     if (n < 8) {
-        stfq_p(mem_buf, env->fregs[n]);
+        float_status s;
+        stfq_p(mem_buf, floatx80_to_float64(env->fregs[n].d, &s));
         return 8;
     }
     if (n < 11) {
@@ -75,10 +144,11 @@  static int fpu_gdb_get_reg(CPUState *env, uint8_t
*mem_buf, int n)
     return 0;
 }

-static int fpu_gdb_set_reg(CPUState *env, uint8_t *mem_buf, int n)
+static int cf_fpu_gdb_set_reg(CPUState *env, uint8_t *mem_buf, int n)
 {
     if (n < 8) {
-        env->fregs[n] = ldfq_p(mem_buf);
+        float_status s;
+        env->fregs[n].d = float64_to_floatx80(ldfq_p(mem_buf), &s);
         return 8;
     }
     if (n < 11) {
@@ -88,6 +158,36 @@  static int fpu_gdb_set_reg(CPUState *env, uint8_t
*mem_buf, int n)
     return 0;
 }

+static int m68k_fpu_gdb_get_reg(CPUState *env, uint8_t *mem_buf, int n)
+{
+    if (n < 8) {
+        stw_be_p(mem_buf, env->fregs[n].l.upper);
+        memset(mem_buf + 2, 0, 2);
+        stq_be_p(mem_buf + 4, env->fregs[n].l.lower);
+        return 12;
+    }
+    if (n < 11) {
+        /* FP control registers (not implemented)  */
+        memset(mem_buf, 0, 4);
+        return 4;
+    }
+    return 0;
+}
+
+static int m68k_fpu_gdb_set_reg(CPUState *env, uint8_t *mem_buf, int n)
+{
+    if (n < 8) {
+        env->fregs[n].l.upper = lduw_be_p(mem_buf);
+        env->fregs[n].l.lower = ldq_be_p(mem_buf + 4);
+        return 12;
+    }
+    if (n < 11) {
+        /* FP control registers (not implemented)  */
+        return 4;
+    }
+    return 0;
+}
+
 static void m68k_set_feature(CPUM68KState *env, int feature)
 {
     env->features |= (1u << feature);
@@ -105,12 +205,32 @@  static int cpu_m68k_set_model(CPUM68KState *env,
const char *name)
         return -1;

     switch (def->id) {
+    case M68K_CPUID_M68020:
+    case M68K_CPUID_M68030:
+    case M68K_CPUID_M68040:
+        m68k_set_feature(env, M68K_FEATURE_QUAD_MULDIV);
+    case M68K_CPUID_M68060:
+        m68k_set_feature(env, M68K_FEATURE_BRAL);
+        m68k_set_feature(env, M68K_FEATURE_BCCL);
+        m68k_set_feature(env, M68K_FEATURE_BITFIELD);
+        m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
+        m68k_set_feature(env, M68K_FEATURE_SCALED_INDEX);
+        m68k_set_feature(env, M68K_FEATURE_LONG_MULDIV);
+        m68k_set_feature(env, M68K_FEATURE_FPU);
+        m68k_set_feature(env, M68K_FEATURE_CAS);
+    case M68K_CPUID_M68000:
+        m68k_set_feature(env, M68K_FEATURE_M68000);
+        m68k_set_feature(env, M68K_FEATURE_USP);
+        m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
+        break;
     case M68K_CPUID_M5206:
         m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
+        m68k_set_feature(env, M68K_FEATURE_SCALED_INDEX);
         break;
     case M68K_CPUID_M5208:
         m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
         m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
+        m68k_set_feature(env, M68K_FEATURE_SCALED_INDEX);
         m68k_set_feature(env, M68K_FEATURE_BRAL);
         m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
         m68k_set_feature(env, M68K_FEATURE_USP);
@@ -118,16 +238,19 @@  static int cpu_m68k_set_model(CPUM68KState *env,
const char *name)
     case M68K_CPUID_CFV4E:
         m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
         m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
+        m68k_set_feature(env, M68K_FEATURE_SCALED_INDEX);
         m68k_set_feature(env, M68K_FEATURE_BRAL);
         m68k_set_feature(env, M68K_FEATURE_CF_FPU);
         m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
         m68k_set_feature(env, M68K_FEATURE_USP);
         break;
     case M68K_CPUID_ANY:
+        m68k_set_feature(env, M68K_FEATURE_M68000);
         m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
         m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
         m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
         m68k_set_feature(env, M68K_FEATURE_BRAL);
+        m68k_set_feature(env, M68K_FEATURE_BCCL);
         m68k_set_feature(env, M68K_FEATURE_CF_FPU);
         /* MAC and EMAC are mututally exclusive, so pick EMAC.
            It's mostly backwards compatible.  */
@@ -135,35 +258,47 @@  static int cpu_m68k_set_model(CPUM68KState *env,
const char *name)
         m68k_set_feature(env, M68K_FEATURE_CF_EMAC_B);
         m68k_set_feature(env, M68K_FEATURE_USP);
         m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
+        m68k_set_feature(env, M68K_FEATURE_SCALED_INDEX);
         m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
+        m68k_set_feature(env, M68K_FEATURE_BITFIELD);
+        m68k_set_feature(env, M68K_FEATURE_LONG_MULDIV);
+        m68k_set_feature(env, M68K_FEATURE_QUAD_MULDIV);
+        m68k_set_feature(env, M68K_FEATURE_CAS);
         break;
     }

     register_m68k_insns(env);
-    if (m68k_feature (env, M68K_FEATURE_CF_FPU)) {
-        gdb_register_coprocessor(env, fpu_gdb_get_reg, fpu_gdb_set_reg,
-                                 11, "cf-fp.xml", 18);
-    }
     /* TODO: Add [E]MAC registers.  */
     return 0;
 }

 void cpu_reset(CPUM68KState *env)
 {
+    int i;
+
     if (qemu_loglevel_mask(CPU_LOG_RESET)) {
         qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
         log_cpu_state(env, 0);
     }

+#if defined(CONFIG_USER_ONLY)
     memset(env, 0, offsetof(CPUM68KState, breakpoints));
-#if !defined (CONFIG_USER_ONLY)
+    /* TODO: We should set PC from the interrupt vector.  */
+    env->pc = 0;
+#else
     env->sr = 0x2700;
 #endif
     m68k_switch_sp(env);
-    /* ??? FP regs should be initialized to NaN.  */
+
+    for (i = 0; i < 8; i++) {
+        env->fregs[i].d = floatx80_default_nan;
+    }
+    env->fp0h = floatx80_default_nan.high;
+    env->fp0l = floatx80_default_nan.low;
+    env->fp1h = floatx80_default_nan.high;
+    env->fp1l = floatx80_default_nan.low;
+
     env->cc_op = CC_OP_FLAGS;
-    /* TODO: We should set PC from the interrupt vector.  */
-    env->pc = 0;
     tlb_flush(env, 1);
 }

@@ -175,7 +310,6 @@  CPUM68KState *cpu_m68k_init(const char *cpu_model)
     env = qemu_mallocz(sizeof(CPUM68KState));
     cpu_exec_init(env);
     if (!inited) {
-        inited = 1;
         m68k_tcg_init();
     }

@@ -187,7 +321,18 @@  CPUM68KState *cpu_m68k_init(const char *cpu_model)
     }

     cpu_reset(env);
+    if (!inited) {
+    if (m68k_feature (env, M68K_FEATURE_CF_FPU)) {
+        gdb_register_coprocessor(env, cf_fpu_gdb_get_reg, cf_fpu_gdb_set_reg,
+                                 11, "cf-fp.xml", 18);
+    }
+    if (m68k_feature (env, M68K_FEATURE_FPU)) {
+        gdb_register_coprocessor(env, m68k_fpu_gdb_get_reg,
+				 m68k_fpu_gdb_set_reg, 11, "m68k-fp.xml", 18);
+    }
+    }
     qemu_init_vcpu(env);
+    inited = 1;
     return env;
 }

@@ -203,24 +348,56 @@  void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
     uint32_t dest;
     uint32_t tmp;

-#define HIGHBIT 0x80000000u
+#define HIGHBIT(type) (1u << (sizeof(type) * 8 - 1))

-#define SET_NZ(x) do { \
-    if ((x) == 0) \
+#define SET_NZ(x, type) do { \
+    if ((type)(x) == 0) \
         flags |= CCF_Z; \
-    else if ((int32_t)(x) < 0) \
+    else if ((type)(x) < 0) \
         flags |= CCF_N; \
     } while (0)

 #define SET_FLAGS_SUB(type, utype) do { \
-    SET_NZ((type)dest); \
+    SET_NZ(dest, type); \
     tmp = dest + src; \
     if ((utype) tmp < (utype) src) \
         flags |= CCF_C; \
-    if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \
+    if (HIGHBIT(type) & (tmp ^ dest) & (tmp ^ src)) \
         flags |= CCF_V; \
     } while (0)

+#define SET_FLAGS_ADD(type, utype) do { \
+    SET_NZ(dest, type); \
+    if ((utype) dest < (utype) src) \
+        flags |= CCF_C; \
+    tmp = dest - src; \
+    if (HIGHBIT(type) & (src ^ dest) & ~(tmp ^ src)) \
+        flags |= CCF_V; \
+    } while (0)
+
+#define SET_FLAGS_ADDX(type, utype) do { \
+    SET_NZ(dest, type); \
+    if ((utype) dest <= (utype) src) \
+        flags |= CCF_C; \
+    tmp = dest - src - 1; \
+    if (HIGHBIT(type) & (src ^ dest) & ~(tmp ^ src)) \
+        flags |= CCF_V; \
+    } while (0)
+
+#define SET_FLAGS_SUBX(type, utype) do { \
+    SET_NZ(dest, type); \
+    tmp = dest + src + 1; \
+    if ((utype) tmp <= (utype) src) \
+        flags |= CCF_C; \
+    if (HIGHBIT(type) & (tmp ^ dest) & (tmp ^ src)) \
+        flags |= CCF_V; \
+    } while (0)
+
+#define SET_FLAGS_SHIFT(type) do { \
+    SET_NZ(dest, type); \
+    flags |= src; \
+    } while(0)
+
     flags = 0;
     src = env->cc_src;
     dest = env->cc_dest;
@@ -228,46 +405,66 @@  void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
     case CC_OP_FLAGS:
         flags = dest;
         break;
+    case CC_OP_LOGICB:
+        SET_NZ(dest, int8_t);
+        goto set_x;
+        break;
+    case CC_OP_LOGICW:
+        SET_NZ(dest, int16_t);
+        goto set_x;
+        break;
     case CC_OP_LOGIC:
-        SET_NZ(dest);
+        SET_NZ(dest, int32_t);
+set_x:
+        if (env->cc_x && m68k_feature(env, M68K_FEATURE_M68000)) {
+            /* Unlike m68k, coldfire always clears the overflow bit.  */
+            flags |= CCF_X;
+        }
+        break;
+    case CC_OP_ADDB:
+        SET_FLAGS_ADD(int8_t, uint8_t);
+        break;
+    case CC_OP_ADDW:
+        SET_FLAGS_ADD(int16_t, uint16_t);
         break;
     case CC_OP_ADD:
-        SET_NZ(dest);
-        if (dest < src)
-            flags |= CCF_C;
-        tmp = dest - src;
-        if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
-            flags |= CCF_V;
+        SET_FLAGS_ADD(int32_t, uint32_t);
+        break;
+    case CC_OP_SUBB:
+        SET_FLAGS_SUB(int8_t, uint8_t);
+        break;
+    case CC_OP_SUBW:
+        SET_FLAGS_SUB(int16_t, uint16_t);
         break;
     case CC_OP_SUB:
         SET_FLAGS_SUB(int32_t, uint32_t);
         break;
-    case CC_OP_CMPB:
-        SET_FLAGS_SUB(int8_t, uint8_t);
+    case CC_OP_ADDXB:
+        SET_FLAGS_ADDX(int8_t, uint8_t);
         break;
-    case CC_OP_CMPW:
-        SET_FLAGS_SUB(int16_t, uint16_t);
+    case CC_OP_ADDXW:
+        SET_FLAGS_ADDX(int16_t, uint16_t);
         break;
     case CC_OP_ADDX:
-        SET_NZ(dest);
-        if (dest <= src)
-            flags |= CCF_C;
-        tmp = dest - src - 1;
-        if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
-            flags |= CCF_V;
+        SET_FLAGS_ADDX(int32_t, uint32_t);
+        break;
+    case CC_OP_SUBXB:
+        SET_FLAGS_SUBX(int8_t, uint8_t);
+        break;
+    case CC_OP_SUBXW:
+        SET_FLAGS_SUBX(int16_t, uint16_t);
         break;
     case CC_OP_SUBX:
-        SET_NZ(dest);
-        tmp = dest + src + 1;
-        if (tmp <= src)
-            flags |= CCF_C;
-        if (HIGHBIT & (tmp ^ dest) & (tmp ^ src))
-            flags |= CCF_V;
+        SET_FLAGS_SUBX(int32_t, uint32_t);
         break;
+    case CC_OP_SHIFTB:
+        SET_FLAGS_SHIFT(int8_t);
+	break;
+    case CC_OP_SHIFTW:
+        SET_FLAGS_SHIFT(int16_t);
+	break;
     case CC_OP_SHIFT:
-        SET_NZ(dest);
-        if (src)
-            flags |= CCF_C;
+        SET_FLAGS_SHIFT(int32_t);
         break;
     default:
         cpu_abort(env, "Bad CC_OP %d", cc_op);
@@ -276,16 +473,32 @@  void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
     env->cc_dest = flags;
 }

-void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
+void HELPER(movec_to)(CPUM68KState * env, uint32_t reg, uint32_t val)
 {
     switch (reg) {
     case 0x02: /* CACR */
         env->cacr = val;
         m68k_switch_sp(env);
         break;
-    case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
-        /* TODO: Implement Access Control Registers.  */
-        break;
+    case 0x03: /* MMU Translation Control */
+		env->mmu.tc = val;
+		break;
+    /*Translation/Access Control Registers*/
+	case 0x04:
+		env->itt0 = val;
+		return;
+	case 0x05:
+		env->itt1 = val;
+		break;
+	case 0x06:
+		env->dtt0 = val;
+		break;
+	case 0x07:
+		env->dtt1 = val;
+		break;
+    case 0x800: /* USP */
+		env->sp[M68K_USP] = val;
+		break;
     case 0x801: /* VBR */
         env->vbr = val;
         break;
@@ -296,6 +509,36 @@  void HELPER(movec)(CPUM68KState *env, uint32_t
reg, uint32_t val)
     }
 }

+uint32_t HELPER(movec_from)(CPUM68KState * env, uint32_t reg)
+{
+    switch (reg) {
+ 	case 0x00: /* SFC */
+        return env->sfc;
+    case 0x01: /* DFC */
+        return env->dfc;
+    case 0x02: /* CACR */
+        return env->cacr;
+    case 0x03: /*MMU TC*/
+        return env->mmu.tc;
+    case 0x04:
+        return env->itt0;
+	case 0x05:
+		return env->itt1;
+	case 0x06:
+		return env->dtt0;
+    case 0x07:
+        return env->dtt1;
+    case 0x800:/*USP*/
+        return env->sp[M68K_USP];
+    case 0x801: /* VBR */
+        return env->vbr;
+    /* TODO: Implement control registers.  */
+    default:
+        cpu_abort(env, "Unimplemented control register read 0x%x\n",
+                  reg);
+    }
+}
+
 void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
 {
     uint32_t acc;
@@ -404,6 +647,37 @@  uint32_t HELPER(ff1)(uint32_t x)
     return n;
 }

+uint32_t HELPER(bfffo)(uint32_t arg, uint32_t width)
+{
+    int n;
+    uint32_t mask;
+    mask = 0x80000000;
+    for (n = 0; n < width; n++) {
+       if (arg & mask)
+           break;
+       mask >>= 1;
+    }
+    return n;
+}
+
+uint32_t HELPER(rol32)(uint32_t val, uint32_t shift)
+{
+    uint32_t result;
+    if (shift == 0 || shift == 32)
+        return val;
+    result = (val << shift) | (val >> (32 - shift));
+    return result;
+}
+
+uint32_t HELPER(ror32)(uint32_t val, uint32_t shift)
+{
+    uint32_t result;
+    if (shift == 0 || shift == 32)
+        return val;
+    result = (val >> shift) | (val << (32 - shift));
+    return result;
+}
+
 uint32_t HELPER(sats)(uint32_t val, uint32_t ccr)
 {
     /* The result has the opposite sign to the original value.  */
@@ -412,7 +686,53 @@  uint32_t HELPER(sats)(uint32_t val, uint32_t ccr)
     return val;
 }

-uint32_t HELPER(subx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
+uint32_t HELPER(subx8_cc)(CPUState *env, uint32_t op1, uint32_t op2)
+{
+    uint8_t res;
+    uint32_t old_flags;
+
+    old_flags = env->cc_dest;
+    if (env->cc_x) {
+        env->cc_x = ((uint8_t)op1 <= (uint8_t)op2);
+        env->cc_op = CC_OP_SUBXB;
+        res = (uint8_t)op1 - ((uint8_t)op2 + 1);
+    } else {
+        env->cc_x = ((uint8_t)op1 < (uint8_t)op2);
+        env->cc_op = CC_OP_SUBB;
+        res = (uint8_t)op1 - (uint8_t)op2;
+    }
+    env->cc_dest = res;
+    env->cc_src = (uint8_t)op2;
+    cpu_m68k_flush_flags(env, env->cc_op);
+    /* !Z is sticky.  */
+    env->cc_dest &= (old_flags | ~CCF_Z);
+    return (op1 & 0xffffff00) | res;
+}
+
+uint32_t HELPER(subx16_cc)(CPUState *env, uint32_t op1, uint32_t op2)
+{
+    uint16_t res;
+    uint32_t old_flags;
+
+    old_flags = env->cc_dest;
+    if (env->cc_x) {
+        env->cc_x = ((uint16_t)op1 <= (uint16_t)op2);
+        env->cc_op = CC_OP_SUBXW;
+        res = (uint16_t)op1 - ((uint16_t)op2 + 1);
+    } else {
+        env->cc_x = ((uint16_t)op1 < (uint16_t)op2);
+        env->cc_op = CC_OP_SUBW;
+        res = (uint16_t)op1 - (uint16_t)op2;
+    }
+    env->cc_dest = res;
+    env->cc_src = (uint16_t)op2;
+    cpu_m68k_flush_flags(env, env->cc_op);
+    /* !Z is sticky.  */
+    env->cc_dest &= (old_flags | ~CCF_Z);
+    return (op1 & 0xffff0000) | res;
+}
+
+uint32_t HELPER(subx32_cc)(CPUState *env, uint32_t op1, uint32_t op2)
 {
     uint32_t res;
     uint32_t old_flags;
@@ -435,7 +755,53 @@  uint32_t HELPER(subx_cc)(CPUState *env, uint32_t
op1, uint32_t op2)
     return res;
 }

-uint32_t HELPER(addx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
+uint32_t HELPER(addx8_cc)(CPUState *env, uint32_t op1, uint32_t op2)
+{
+    uint8_t res;
+    uint32_t old_flags;
+
+    old_flags = env->cc_dest;
+    if (env->cc_x) {
+        res = (uint8_t)op1 + (uint8_t)op2 + 1;
+        env->cc_x = (res <= (uint8_t)op2);
+        env->cc_op = CC_OP_ADDXB;
+    } else {
+        res = (uint8_t)op1 + (uint8_t)op2;
+        env->cc_x = (res < (uint8_t)op2);
+        env->cc_op = CC_OP_ADDB;
+    }
+    env->cc_dest = res;
+    env->cc_src = (uint8_t)op2;
+    cpu_m68k_flush_flags(env, env->cc_op);
+    /* !Z is sticky.  */
+    env->cc_dest &= (old_flags | ~CCF_Z);
+    return (op1 & 0xffffff00) | res;
+}
+
+uint32_t HELPER(addx16_cc)(CPUState *env, uint32_t op1, uint32_t op2)
+{
+    uint16_t res;
+    uint32_t old_flags;
+
+    old_flags = env->cc_dest;
+    if (env->cc_x) {
+        res = (uint16_t)op1 + (uint16_t)op2 + 1;
+        env->cc_x = (res <= (uint16_t)op2);
+        env->cc_op = CC_OP_ADDXW;
+    } else {
+        res = (uint16_t)op1 + (uint16_t)op2;
+        env->cc_x = (res < (uint16_t)op2);
+        env->cc_op = CC_OP_ADDW;
+    }
+    env->cc_dest = res;
+    env->cc_src = (uint16_t)op2;
+    cpu_m68k_flush_flags(env, env->cc_op);
+    /* !Z is sticky.  */
+    env->cc_dest &= (old_flags | ~CCF_Z);
+    return (op1 & 0xffff0000) | res;
+}
+
+uint32_t HELPER(addx32_cc)(CPUState *env, uint32_t op1, uint32_t op2)
 {
     uint32_t res;
     uint32_t old_flags;
@@ -458,7 +824,17 @@  uint32_t HELPER(addx_cc)(CPUState *env, uint32_t
op1, uint32_t op2)
     return res;
 }

-uint32_t HELPER(xflag_lt)(uint32_t a, uint32_t b)
+uint32_t HELPER(xflag_lt_i8)(uint32_t a, uint32_t b)
+{
+    return (uint8_t)a < (uint8_t)b;
+}
+
+uint32_t HELPER(xflag_lt_i16)(uint32_t a, uint32_t b)
+{
+    return (uint16_t)a < (uint16_t)b;
+}
+
+uint32_t HELPER(xflag_lt_i32)(uint32_t a, uint32_t b)
 {
     return a < b;
 }
@@ -469,167 +845,983 @@  void HELPER(set_sr)(CPUState *env, uint32_t val)
     m68k_switch_sp(env);
 }

-uint32_t HELPER(shl_cc)(CPUState *env, uint32_t val, uint32_t shift)
+#define HELPER_SHL(type, bits) \
+uint32_t HELPER(glue(glue(shl, bits),_cc))(CPUState *env, uint32_t
val, uint32_t shift) \
+{ \
+    type result; \
+    uint32_t cf; \
+    shift &= 63; \
+    if (shift == 0) { \
+        result = (type)val; \
+        cf = 0; \
+    } else if (shift < bits) { \
+        result = (type)val << shift; \
+        cf = ((type)val >> (bits - shift)) & 1; \
+    } else if (shift == bits) { \
+        result = 0; \
+        cf = val & 1; \
+    } else /* shift > bits */ { \
+        result = 0; \
+        cf = 0; \
+    } \
+    env->cc_src = cf ? CCF_C : 0; \
+    if (shift) env->cc_x = (cf != 0); \
+    env->cc_dest = result; \
+    return result; \
+}
+
+HELPER_SHL(uint8_t, 8)
+HELPER_SHL(uint16_t, 16)
+HELPER_SHL(uint32_t, 32)
+
+#define HELPER_SHR(type, bits) \
+uint32_t HELPER(glue(glue(shr, bits), _cc))(CPUState *env, uint32_t
val, uint32_t shift) \
+{ \
+    type result; \
+    uint32_t cf; \
+    shift &= 63; \
+    if (shift == 0) { \
+        result = (type)val; \
+        cf = 0; \
+    } else if (shift < bits) { \
+        result = (type)val >> shift; \
+        cf = ((type)val >> (shift - 1)) & 1; \
+    } else if (shift == bits) { \
+        result = 0; \
+        cf = (type)val >> (bits - 1); \
+    } else /* shift > bits */ { \
+        result = 0; \
+        cf = 0; \
+    } \
+    env->cc_src = cf ? CCF_C : 0; \
+    if (shift) env->cc_x = (cf != 0); \
+    env->cc_dest = result; \
+    return result; \
+}
+
+HELPER_SHR(uint8_t, 8)
+HELPER_SHR(uint16_t, 16)
+HELPER_SHR(uint32_t, 32)
+
+#define HELPER_SAL(type, bits) \
+uint32_t HELPER(glue(glue(sal, bits),_cc))(CPUState *env, uint32_t
val, uint32_t shift) \
+{ \
+    type result; \
+    uint32_t cf; \
+    uint32_t vf; \
+    uint32_t m; \
+    shift &= 63; \
+    if (shift == 0) { \
+        vf = 0; \
+    } else if (shift < bits) { \
+        m = ((1llu << (shift + 1)) - 1) << (bits - shift - 1); \
+        vf = (val & m) != m && (val & m) != 0; \
+    } else {\
+        m = (1llu << bits) - 1; \
+        vf = (val & m) != 0; \
+    }\
+    if (shift == 0) { \
+        result = (type)val; \
+        cf = 0; \
+    } else if (shift < bits) { \
+        result = (type)val << shift; \
+        cf = ((type)val >> (bits - shift)) & 1; \
+    } else if (shift == bits) { \
+        result = 0; \
+        cf = val & 1; \
+    } else /* shift > bits */ { \
+        result = 0; \
+        cf = 0; \
+    } \
+    env->cc_src = (cf ? CCF_C : 0) | (vf ? CCF_V : 0); \
+    if (shift) env->cc_x = (cf != 0); \
+    env->cc_dest = result; \
+    return result; \
+}
+
+HELPER_SAL(int8_t, 8)
+HELPER_SAL(int16_t, 16)
+HELPER_SAL(int32_t, 32)
+
+#define HELPER_SAR(type, bits) \
+uint32_t HELPER(glue(glue(sar, bits), _cc))(CPUState *env, uint32_t
val, uint32_t shift)					\
+{ \
+    type result; \
+    uint32_t cf; \
+    shift &= 63; \
+    if (shift == 0) { \
+        result = (type)val; \
+        cf = 0; \
+    } else if (shift < bits) { \
+        result = (type)val >> shift; \
+        cf = ((type)val >> (shift - 1)) & 1; \
+    } else /* shift >= bits */ { \
+        result = (type)val >> (bits - 1); \
+        cf = (type)val >> (bits - 1); \
+    } \
+    env->cc_src = cf ? CCF_C : 0; \
+    if (shift) env->cc_x = (cf != 0); \
+    env->cc_dest = result; \
+    return result; \
+}
+
+HELPER_SAR(int8_t, 8)
+HELPER_SAR(int16_t, 16)
+HELPER_SAR(int32_t, 32)
+
+#define HELPER_ROL(type, bits) \
+uint32_t HELPER(glue(glue(rol,bits),_cc))(CPUState *env, uint32_t
val, uint32_t shift) \
+{ \
+    type result; \
+    uint32_t flags; \
+    int count = shift & (bits - 1); \
+    if (count) \
+       result = ((type)val << count) | ((type)val >> (bits - count)); \
+    else \
+       result = (type)val; \
+    flags = 0; \
+    if (result == 0) \
+       flags |= CCF_Z; \
+    if (result & (1 << (bits - 1))) \
+       flags |= CCF_N; \
+    if (shift && result & 1) \
+       flags |= CCF_C; \
+    env->cc_dest = flags; \
+    return result; \
+}
+
+HELPER_ROL(uint8_t, 8)
+HELPER_ROL(uint16_t, 16)
+HELPER_ROL(uint32_t, 32)
+
+#define HELPER_ROR(type, bits) \
+uint32_t HELPER(glue(glue(ror,bits),_cc))(CPUState *env, uint32_t
val, uint32_t shift) \
+{ \
+    type result; \
+    uint32_t flags; \
+    int count = shift & (bits - 1); \
+    if (count) \
+       result = ((type)val >> count) | ((type)val << (bits - count)); \
+    else \
+       result = (type)val; \
+    flags = 0; \
+    if (result == 0) \
+       flags |= CCF_Z; \
+    if (result & (1 << (bits - 1))) \
+       flags |= CCF_N; \
+    if (shift && result & (1 << (bits - 1))) \
+       flags |= CCF_C; \
+    env->cc_dest = flags; \
+    return result; \
+}
+
+HELPER_ROR(uint8_t, 8)
+HELPER_ROR(uint16_t, 16)
+HELPER_ROR(uint32_t, 32)
+
+#define HELPER_ROXR(type, bits) \
+uint32_t HELPER(glue(glue(roxr,bits),_cc))(CPUState *env, uint32_t
val, uint32_t shift) \
+{ \
+    type result; \
+    uint32_t flags; \
+    int count = shift; \
+    if (bits == 8) count = rox8_table[count]; \
+    if (bits == 16) count = rox16_table[count]; \
+    if (bits == 32) count = rox32_table[count]; \
+    if (count) { \
+       if (count == bits)\
+           result = ((type)env->cc_x << (bits - count));\
+       else \
+           result = ((type)val >> count) | ((type)env->cc_x << (bits
- count));\
+       if (count > 1) \
+           result |= (type)val << (bits + 1 - count); \
+       env->cc_x = ((type)val >> (count - 1)) & 1; \
+    } else \
+       result = (type)val; \
+    flags = 0; \
+    if (result == 0) \
+       flags |= CCF_Z; \
+    if (result & (1 << (bits - 1))) \
+       flags |= CCF_N; \
+    if (env->cc_x) \
+       flags |= CCF_C; \
+    env->cc_dest = flags; \
+    return result; \
+}
+
+HELPER_ROXR(uint8_t, 8)
+HELPER_ROXR(uint16_t, 16)
+HELPER_ROXR(uint32_t, 32)
+
+#define HELPER_ROXL(type, bits) \
+uint32_t HELPER(glue(glue(roxl,bits),_cc))(CPUState *env, uint32_t
val, uint32_t shift) \
+{ \
+    type result; \
+    uint32_t flags; \
+    int count; \
+    count = shift; \
+    if (bits == 8) count = rox8_table[count]; \
+    if (bits == 16) count = rox16_table[count]; \
+    if (bits == 32) count = rox32_table[count]; \
+    if (count) { \
+       if (count == bits) \
+           result = ((type)env->cc_x << (count - 1)); \
+       else \
+           result = ((type)val << count) | ((type)env->cc_x << (count - 1)); \
+       if (count > 1) \
+           result |= (type)val >> (bits + 1 - count); \
+       env->cc_x = ((type)val >> (bits - count)) & 1; \
+    } else \
+       result = (type)val; \
+    flags = 0; \
+    if (result == 0) \
+       flags |= CCF_Z; \
+    if (result & (1 << (bits - 1))) \
+       flags |= CCF_N; \
+    if (env->cc_x) \
+       flags |= CCF_C; \
+    env->cc_dest = flags; \
+    return result; \
+}
+
+HELPER_ROXL(uint8_t, 8)
+HELPER_ROXL(uint16_t, 16)
+HELPER_ROXL(uint32_t, 32)
+
+/* FPU helpers.  */
+
+static const floatx80 fpu_rom[128] = {
+    [0x00] = floatx80_pi,                                       /* Pi */
+
+    [0x0b] = { .high = 0x3ffd, .low = 0x9a209a84fbcff798ULL },  /* Log10(2) */
+    [0x0c] = floatx80_e,                                        /* e        */
+    [0x0d] = floatx80_log2e,                                    /* Log2(e)  */
+    [0x0e] = { .high = 0x3ffd, .low = 0xde5bd8a937287195ULL },  /* Log10(e) */
+    [0x0f] = floatx80_zero,                                     /* Zero     */
+
+    [0x30] = floatx80_ln2,                                      /* ln(2)    */
+    [0x31] = { .high = 0x4000, .low = 0x935d8dddaaa8ac17ULL },  /* ln(10)   */
+    [0x32] = floatx80_one,                                      /* 10^0     */
+    [0x33] = floatx80_10,                                       /* 10^1     */
+    [0x34] = { .high = 0x4005, .low = 0xc800000000000000ULL },  /* 10^2     */
+    [0x35] = { .high = 0x400c, .low = 0x9c40000000000000ULL },  /* 10^4     */
+    [0x36] = { .high = 0x4019, .low = 0xbebc200000000000ULL },  /* 10^8     */
+    [0x37] = { .high = 0x4034, .low = 0x8e1bc9bf04000000ULL },  /* 10^16    */
+    [0x38] = { .high = 0x4069, .low = 0x9dc5ada82b70b59eULL },  /* 10^32    */
+    [0x39] = { .high = 0x40d3, .low = 0xc2781f49ffcfa6d5ULL },  /* 10^64    */
+    [0x3a] = { .high = 0x41a8, .low = 0x93ba47c980e98ce0ULL },  /* 10^128   */
+    [0x3b] = { .high = 0x4351, .low = 0xaa7eebfb9df9de8eULL },  /* 10^256   */
+    [0x3c] = { .high = 0x46a3, .low = 0xe319a0aea60e91c7ULL },  /* 10^512   */
+    [0x3d] = { .high = 0x4d48, .low = 0xc976758681750c17ULL },  /* 10^1024  */
+    [0x3e] = { .high = 0x5a92, .low = 0x9e8b3b5dc53d5de5ULL },  /* 10^2048  */
+    [0x3f] = { .high = 0x7525, .low = 0xc46052028a20979bULL },  /* 10^4096  */
+};
+
+static inline floatx80 FP0_to_floatx80(CPUState *env)
 {
-    uint32_t result;
-    uint32_t cf;
-
-    shift &= 63;
-    if (shift == 0) {
-        result = val;
-        cf = env->cc_src & CCF_C;
-    } else if (shift < 32) {
-        result = val << shift;
-        cf = (val >> (32 - shift)) & 1;
-    } else if (shift == 32) {
-        result = 0;
-        cf = val & 1;
-    } else /* shift > 32 */ {
-        result = 0;
-        cf = 0;
-    }
-    env->cc_src = cf;
-    env->cc_x = (cf != 0);
-    env->cc_dest = result;
-    return result;
+    floatx80 res;
+
+    res.high = env->fp0h;
+    res.low = env->fp0l;
+
+    return res;
 }

-uint32_t HELPER(shr_cc)(CPUState *env, uint32_t val, uint32_t shift)
+static inline void floatx80_to_FP0(CPUState *env, floatx80 res)
 {
-    uint32_t result;
-    uint32_t cf;
-
-    shift &= 63;
-    if (shift == 0) {
-        result = val;
-        cf = env->cc_src & CCF_C;
-    } else if (shift < 32) {
-        result = val >> shift;
-        cf = (val >> (shift - 1)) & 1;
-    } else if (shift == 32) {
-        result = 0;
-        cf = val >> 31;
-    } else /* shift > 32 */ {
-        result = 0;
-        cf = 0;
-    }
-    env->cc_src = cf;
-    env->cc_x = (cf != 0);
-    env->cc_dest = result;
-    return result;
+    env->fp0h = res.high;
+    env->fp0l = res.low;
 }

-uint32_t HELPER(sar_cc)(CPUState *env, uint32_t val, uint32_t shift)
+static inline void floatx80_to_FP1(CPUState *env, floatx80 res)
 {
-    uint32_t result;
-    uint32_t cf;
-
-    shift &= 63;
-    if (shift == 0) {
-        result = val;
-        cf = (env->cc_src & CCF_C) != 0;
-    } else if (shift < 32) {
-        result = (int32_t)val >> shift;
-        cf = (val >> (shift - 1)) & 1;
-    } else /* shift >= 32 */ {
-        result = (int32_t)val >> 31;
-        cf = val >> 31;
-    }
-    env->cc_src = cf;
-    env->cc_x = cf;
-    env->cc_dest = result;
-    return result;
+    env->fp1h = res.high;
+    env->fp1l = res.low;
 }

-/* FPU helpers.  */
-uint32_t HELPER(f64_to_i32)(CPUState *env, float64 val)
+static inline int32_t FP0_to_int32(CPUState *env)
+{
+    return env->fp0h;
+}
+
+static inline void int32_to_FP0(CPUState *env, int32_t val)
+{
+    env->fp0h = val;
+}
+
+static inline float32 FP0_to_float32(CPUState *env)
+{
+    return *(float32*)&env->fp0h;
+}
+
+static inline void float32_to_FP0(CPUState *env, float32 val)
+{
+
+    env->fp0h = *(uint32_t*)&val;
+}
+
+static inline float64 FP0_to_float64(CPUState *env)
+{
+    return *(float64*)&env->fp0l;
+}
+
+static inline void float64_to_FP0(CPUState *env, float64 val)
+{
+    env->fp0l = *(uint64_t*)&val;
+}
+
+static inline floatx80 FP1_to_floatx80(CPUState *env)
+{
+    floatx80 res;
+
+    res.high = env->fp1h;
+    res.low = env->fp1l;
+
+    return res;
+}
+
+static inline long double floatx80_to_ldouble(floatx80 val)
+{
+	if (floatx80_is_infinity(val)) {
+		if (floatx80_is_neg(val)) {
+			return -__builtin_infl();
+		}
+		return __builtin_infl();
+	}
+	if (floatx80_is_any_nan(val)) {
+		char low[20];
+		sprintf(low, "0x%016"PRIx64, val.low);
+
+		return nanl(low);
+	}
+
+	return *(long double *)&val;
+}
+
+static inline floatx80 ldouble_to_floatx80(long double val)
+{
+	floatx80 res;
+
+	if (isinf(val)) {
+		res.high = floatx80_default_nan.high;
+		res.low = 0;
+	}
+	if (isinf(val) < 0) {
+		res.high |= 0x8000;
+	}
+	if (isnan(val)) {
+		res.high = floatx80_default_nan.high;
+		res.low = *(uint64_t*)((char *)&val + 4);
+	}
+	return *(floatx80*)&val;
+}
+
+void HELPER(const_FP0)(CPUState *env, uint32_t offset)
+{
+    env->fp0h = fpu_rom[offset].high;
+    env->fp0l = fpu_rom[offset].low;
+    DBG_FPUH("ROM[0x%02x] %"PRIxFPH" %"PRIxFPL" %.17Lg\n",
+            offset, env->fp0h, env->fp0l,
floatx80_to_ldouble(FP0_to_floatx80(env)));
+}
+
+static inline void restore_precision_mode(CPUState *env)
+{
+    int rounding_precision;
+
+    rounding_precision = (env->fpcr >> 6) & 0x03;
+
+    switch (rounding_precision) {
+    case 0: /* extended */
+        set_floatx80_rounding_precision(80, &env->fp_status);
+        break;
+    case 1: /* single */
+        set_floatx80_rounding_precision(32, &env->fp_status);
+        break;
+    case 2: /* double */
+        set_floatx80_rounding_precision(64, &env->fp_status);
+        break;
+    case 3: /* reserved */
+    default:
+        break;
+    }
+}
+
+static inline void restore_rounding_mode(CPUState *env)
+{
+    int rounding_mode;
+
+    rounding_mode = (env->fpcr >> 4) & 0x03;
+
+    switch (rounding_mode) {
+    case 0: /* round to nearest */
+        set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
+        break;
+    case 1: /* round to zero */
+        set_float_rounding_mode(float_round_to_zero, &env->fp_status);
+        break;
+    case 2: /* round toward minus infinity */
+        set_float_rounding_mode(float_round_down, &env->fp_status);
+        break;
+    case 3: /* round toward positive infinity */
+        set_float_rounding_mode(float_round_up, &env->fp_status);
+        break;
+    }
+}
+
+void HELPER(set_fpcr)(CPUState *env, uint32_t val)
+{
+    DBG_FPUH("set_fpcr %04x\n", val);
+
+    env->fpcr = val & 0xffff;
+
+    restore_precision_mode(env);
+    restore_rounding_mode(env);
+}
+
+void HELPER(exts32_FP0)(CPUState *env)
+{
+    floatx80 res;
+
+    DBG_FPUH("exts32_FP0 %d", FP0_to_int32(env));
+
+    res = int32_to_floatx80(FP0_to_int32(env), &env->fp_status);
+
+    DBG_FPU(" = %Lg\n", floatx80_to_ldouble(res));
+    floatx80_to_FP0(env, res);
+}
+
+void HELPER(extf32_FP0)(CPUState *env)
+{
+    floatx80 res;
+
+    DBG_FPUH("extf32_FP0 %f", FLOAT(FP0_to_float32(env)));
+    res = float32_to_floatx80(FP0_to_float32(env), &env->fp_status);
+    DBG_FPU(" = %Lg\n", floatx80_to_ldouble(res));
+
+    floatx80_to_FP0(env, res);
+}
+
+void HELPER(extf64_FP0)(CPUState *env)
+{
+    floatx80 res;
+    uint64_t val;
+
+    val = FP0_to_float64(env);
+    DBG_FPUH("extf64_FP0 0x%016"PRIx64", %g", val, *(double*)&val);
+    res = float64_to_floatx80(val, &env->fp_status);
+    DBG_FPU(" = %Lg\n", floatx80_to_ldouble(res));
+
+    floatx80_to_FP0(env, res);
+}
+
+void HELPER(extp96_FP0)(CPUState *env)
+{
+}
+
+void HELPER(reds32_FP0)(CPUState *env)
+{
+    floatx80 val;
+    int32_t res;
+
+    val = FP0_to_floatx80(env);
+    DBG_FPUH("reds32_FP0 %Lg (%08x %016"PRIx64")",
+	      floatx80_to_ldouble(val), env->fp0h, env->fp0l);
+    res = floatx80_to_int32(val, &env->fp_status);
+    DBG_FPU(" = %d\n", res);
+
+    int32_to_FP0(env, res);
+}
+
+void HELPER(redf32_FP0)(CPUState *env)
+{
+    floatx80 val;
+    float32 res;
+
+    val = FP0_to_floatx80(env);
+    DBG_FPUH("redf32_FP0 %Lg", floatx80_to_ldouble(val));
+    res = floatx80_to_float32(val, &env->fp_status);
+    DBG_FPU(" = %f\n", FLOAT(res));
+
+    float32_to_FP0(env, res);
+}
+
+void HELPER(redf64_FP0)(CPUState *env)
+{
+    floatx80 val;
+    float64 res;
+
+    val = FP0_to_floatx80(env);
+    DBG_FPUH("redf64_FP0 %Lg", floatx80_to_ldouble(val));
+    res = floatx80_to_float64(val, &env->fp_status);
+    DBG_FPU(" = %g\n", *(double*)&res);
+
+    float64_to_FP0(env, res);
+}
+
+void HELPER(redp96_FP0)(CPUState *env)
+{
+    DBG_FPUH("redp96_FP0\n");
+}
+
+void HELPER(iround_FP0)(CPUState *env)
+{
+    floatx80 res;
+
+    res = FP0_to_floatx80(env);
+
+    DBG_FPUH("iround_FP0 %Lg", floatx80_to_ldouble(res));
+
+    res = floatx80_round_to_int(res, &env->fp_status);
+
+    DBG_FPU(" = %Lg\n", floatx80_to_ldouble(res));
+
+    floatx80_to_FP0(env, res);
+}
+
+void HELPER(sinh_FP0)(CPUState *env)
 {
-    return float64_to_int32(val, &env->fp_status);
+    floatx80 res;
+    long double val;
+
+    res = FP0_to_floatx80(env);
+    val = floatx80_to_ldouble(res);
+
+    DBG_FPUH("sinh_FP0 %Lg", val);
+    val = sinhl(val);
+    DBG_FPU(" = %Lg", val);
+    res = ldouble_to_floatx80(val);
+    floatx80_to_FP0(env, res);
 }

-float32 HELPER(f64_to_f32)(CPUState *env, float64 val)
+void HELPER(itrunc_FP0)(CPUState *env)
 {
-    return float64_to_float32(val, &env->fp_status);
+    floatx80 res;
+
+    res = FP0_to_floatx80(env);
+    DBG_FPUH("itrunc_FP0 %Lg", floatx80_to_ldouble(res));
+
+    set_float_rounding_mode(float_round_to_zero, &env->fp_status);
+    res = floatx80_round_to_int(res, &env->fp_status);
+    restore_rounding_mode(env);
+
+    DBG_FPU(" = %Lg\n", floatx80_to_ldouble(res));
+
+    floatx80_to_FP0(env, res);
 }

-float64 HELPER(i32_to_f64)(CPUState *env, uint32_t val)
+void HELPER(sqrt_FP0)(CPUState *env)
 {
-    return int32_to_float64(val, &env->fp_status);
+    floatx80 res;
+
+    res = FP0_to_floatx80(env);
+    DBG_FPUH("sqrt_FP0 %Lg", floatx80_to_ldouble(res));
+    res = floatx80_sqrt(res, &env->fp_status);
+    DBG_FPU("  = %Lg\n", floatx80_to_ldouble(res));
+
+    floatx80_to_FP0(env, res);
 }

-float64 HELPER(f32_to_f64)(CPUState *env, float32 val)
+void HELPER(lognp1_FP0)(CPUState *env)
 {
-    return float32_to_float64(val, &env->fp_status);
+    floatx80 val;
+    long double res;
+
+    val = FP0_to_floatx80(env);
+    DBG_FPUH("lognp1_FP0 %Lg", floatx80_to_ldouble(val));
+    res = logl(floatx80_to_ldouble(val) + 1.0);
+    DBG_FPU(" = %Lg\n", res);
+
+    floatx80_to_FP0(env, ldouble_to_floatx80(res));
 }

-float64 HELPER(iround_f64)(CPUState *env, float64 val)
+void HELPER(ln_FP0)(CPUState *env)
 {
-    return float64_round_to_int(val, &env->fp_status);
+    floatx80 val;
+    long double res;
+
+    val = FP0_to_floatx80(env);
+    DBG_FPUH("ln_FP0 %Lg", floatx80_to_ldouble(val));
+    res = logl(floatx80_to_ldouble(val));
+    DBG_FPU(" = %Lg\n", res);
+
+    floatx80_to_FP0(env, ldouble_to_floatx80(res));
 }

-float64 HELPER(itrunc_f64)(CPUState *env, float64 val)
+void HELPER(log10_FP0)(CPUState *env)
 {
-    return float64_trunc_to_int(val, &env->fp_status);
+    floatx80 val;
+    long double res;
+
+    val = FP0_to_floatx80(env);
+    DBG_FPUH("log10_FP0 %Lg", floatx80_to_ldouble(val));
+    res = log10l(floatx80_to_ldouble(val));
+    DBG_FPU(" = %Lg\n", res);
+
+    floatx80_to_FP0(env, ldouble_to_floatx80(res));
 }

-float64 HELPER(sqrt_f64)(CPUState *env, float64 val)
+void HELPER(atan_FP0)(CPUState *env)
 {
-    return float64_sqrt(val, &env->fp_status);
+    floatx80 res;
+    long double val;
+
+    res = FP0_to_floatx80(env);
+    val = floatx80_to_ldouble(res);
+
+    DBG_FPUH("atan_FP0 %Lg", val);
+    val = atanl(val);
+    DBG_FPU(" = %Lg", val);
+    res = ldouble_to_floatx80(val);
+    floatx80_to_FP0(env, res);
 }

-float64 HELPER(abs_f64)(float64 val)
+void HELPER(asin_FP0)(CPUState *env)
 {
-    return float64_abs(val);
+    floatx80 res;
+    long double val;
+
+    res = FP0_to_floatx80(env);
+    val = floatx80_to_ldouble(res);
+
+    DBG_FPUH("asin_FP0 %Lg", val);
+    val = asinl(val);
+    DBG_FPU(" = %Lg", val);
+    res = ldouble_to_floatx80(val);
+    floatx80_to_FP0(env, res);
 }

-float64 HELPER(chs_f64)(float64 val)
+void HELPER(atanh_FP0)(CPUState *env)
 {
-    return float64_chs(val);
+    floatx80 res;
+    long double val;
+
+    res = FP0_to_floatx80(env);
+    val = floatx80_to_ldouble(res);
+
+    DBG_FPUH("atanh_FP0 %Lg", val);
+    val = atanhl(val);
+    DBG_FPU(" = %Lg", val);
+    res = ldouble_to_floatx80(val);
+    floatx80_to_FP0(env, res);
 }

-float64 HELPER(add_f64)(CPUState *env, float64 a, float64 b)
+void HELPER(sin_FP0)(CPUState *env)
 {
-    return float64_add(a, b, &env->fp_status);
+    floatx80 res;
+    long double val;
+
+    res = FP0_to_floatx80(env);
+    val = floatx80_to_ldouble(res);
+
+    DBG_FPUH("sin_FP0 %Lg", val);
+    val = sinl(val);
+    DBG_FPU(" = %Lg", val);
+    res = ldouble_to_floatx80(val);
+    floatx80_to_FP0(env, res);
 }

-float64 HELPER(sub_f64)(CPUState *env, float64 a, float64 b)
+void HELPER(tanh_FP0)(CPUState *env)
 {
-    return float64_sub(a, b, &env->fp_status);
+    floatx80 res;
+    long double val;
+
+    res = FP0_to_floatx80(env);
+    val = floatx80_to_ldouble(res);
+
+    DBG_FPUH("tanh_FP0 %Lg", val);
+    val = tanhl(val);
+    DBG_FPU(" = %Lg", val);
+    res = ldouble_to_floatx80(val);
+    floatx80_to_FP0(env, res);
 }

-float64 HELPER(mul_f64)(CPUState *env, float64 a, float64 b)
+void HELPER(tan_FP0)(CPUState *env)
 {
-    return float64_mul(a, b, &env->fp_status);
+    floatx80 res;
+    long double val;
+
+    res = FP0_to_floatx80(env);
+    val = floatx80_to_ldouble(res);
+
+    DBG_FPUH("tan_FP0 %Lg", val);
+    val = tanl(val);
+    DBG_FPU(" = %Lg", val);
+    res = ldouble_to_floatx80(val);
+    floatx80_to_FP0(env, res);
+}
+
+void HELPER(exp_FP0)(CPUState *env)
+{
+    floatx80 f;
+    long double res;
+
+    f = FP0_to_floatx80(env);
+
+    DBG_FPUH("exp_FP0 %Lg", floatx80_to_ldouble(f));
+
+    res = expl(floatx80_to_ldouble(f));
+
+    DBG_FPU(" = %Lg\n", res);
+    floatx80_to_FP0(env, ldouble_to_floatx80(res));
+}
+
+void HELPER(exp2_FP0)(CPUState *env)
+{
+    floatx80 f;
+    long double res;
+
+    f = FP0_to_floatx80(env);
+
+    DBG_FPUH("exp2_FP0 %Lg", floatx80_to_ldouble(f));
+
+    res = exp2l(floatx80_to_ldouble(f));
+
+    DBG_FPU(" = %Lg\n", res);
+    floatx80_to_FP0(env, ldouble_to_floatx80(res));
 }

-float64 HELPER(div_f64)(CPUState *env, float64 a, float64 b)
+void HELPER(exp10_FP0)(CPUState *env)
 {
-    return float64_div(a, b, &env->fp_status);
+    floatx80 res;
+    long double val;
+
+    res = FP0_to_floatx80(env);
+    val = floatx80_to_ldouble(res);
+
+    DBG_FPUH("exp2_FP0 %Lg", val);
+    val = exp10l(val);
+    DBG_FPU(" = %Lg", val);
+    res = ldouble_to_floatx80(val);
+    floatx80_to_FP0(env, res);
+}
+
+void HELPER(abs_FP0)(CPUState *env)
+{
+    floatx80 res;
+
+    res = FP0_to_floatx80(env);
+    DBG_FPUH("abs_FP0 %Lg", floatx80_to_ldouble(res));
+    res = floatx80_abs(res);
+    DBG_FPU(" = %Lg\n", floatx80_to_ldouble(res));
+
+    floatx80_to_FP0(env, res);
 }

-float64 HELPER(sub_cmp_f64)(CPUState *env, float64 a, float64 b)
+void HELPER(cosh_FP0)(CPUState *env)
+{
+    floatx80 res;
+    long double val;
+
+    res = FP0_to_floatx80(env);
+    val = floatx80_to_ldouble(res);
+
+    DBG_FPUH("cosh_FP0 %Lg", val);
+    val = coshl(val);
+    DBG_FPU(" = %Lg", val);
+    res = ldouble_to_floatx80(val);
+    floatx80_to_FP0(env, res);
+}
+
+void HELPER(chs_FP0)(CPUState *env)
+{
+    floatx80 res;
+
+    res = FP0_to_floatx80(env);
+    DBG_FPUH("chs_FP0 %Lg", floatx80_to_ldouble(res));
+    res = floatx80_chs(res);
+    DBG_FPU(" = %Lg\n", floatx80_to_ldouble(res));
+
+    floatx80_to_FP0(env, res);
+}
+
+void HELPER(acos_FP0)(CPUState *env)
+{
+    floatx80 res;
+    long double val;
+
+    res = FP0_to_floatx80(env);
+    val = floatx80_to_ldouble(res);
+
+    DBG_FPUH("acos_FP0 %Lg", val);
+    val = acosl(val);
+    DBG_FPU(" = %Lg", val);
+    res = ldouble_to_floatx80(val);
+    floatx80_to_FP0(env, res);
+}
+
+void HELPER(cos_FP0)(CPUState *env)
+{
+    floatx80 res;
+    long double val;
+
+    res = FP0_to_floatx80(env);
+    val = floatx80_to_ldouble(res);
+
+    DBG_FPUH("cos_FP0 %Lg", val);
+    val = cosl(val);
+    DBG_FPU(" = %Lg", val);
+    res = ldouble_to_floatx80(val);
+    floatx80_to_FP0(env, res);
+}
+
+void HELPER(getexp_FP0)(CPUState *env)
+{
+    int32_t exp;
+    floatx80 res;
+
+    DBG_FPUH("getexp_FP0 %Lg", floatx80_to_ldouble(FP0_to_floatx80(env)));
+
+    DBG_FPU(" fp0h 0x%08x fp0l 0x%016" PRIx64, env->fp0h, env->fp0l);
+
+    exp = (env->fp0h & 0x7fff) - 0x3fff;
+
+    res = int32_to_floatx80(exp, &env->fp_status);
+
+    DBG_FPU(" = %Lg", floatx80_to_ldouble(res));
+    floatx80_to_FP0(env, res);
+}
+
+void HELPER(scale_FP0_FP1)(CPUState *env)
+{
+    int32_t scale;
+    int32_t exp;
+
+    DBG_FPUH("scale_FP0 %Lg", floatx80_to_ldouble(FP0_to_floatx80(env)));
+
+    DBG_FPU(" fp0h 0x%08x fp0l 0x%016" PRIx64, env->fp0h, env->fp0l);
+
+    scale = floatx80_to_int32(FP0_to_floatx80(env), &env->fp_status);
+
+    exp = (env->fp1h & 0x7fff) + scale;
+
+    env->fp0h = (env->fp1h & 0x8000) | (exp & 0x7fff);
+    env->fp0l = env->fp1l;
+    DBG_FPU(" = %Lg", floatx80_to_ldouble(FP0_to_floatx80(env)));
+}
+
+void HELPER(add_FP0_FP1)(CPUState *env)
+{
+    floatx80 res;
+
+    DBG_FPUH("add_FP0_FP1 %Lg %Lg", floatx80_to_ldouble(FP0_to_floatx80(env)),
+            floatx80_to_ldouble(FP1_to_floatx80(env)));
+    res = floatx80_add(FP0_to_floatx80(env), FP1_to_floatx80(env),
+                      &env->fp_status);
+    DBG_FPU(" = %Lg\n", floatx80_to_ldouble(res));
+
+    floatx80_to_FP0(env, res);
+}
+
+void HELPER(sub_FP0_FP1)(CPUState *env)
+{
+    floatx80 res;
+
+    DBG_FPUH("sub_FP0 %Lg %Lg", floatx80_to_ldouble(FP0_to_floatx80(env)),
+            floatx80_to_ldouble(FP1_to_floatx80(env)));
+    res = floatx80_sub(FP1_to_floatx80(env), FP0_to_floatx80(env),
+                       &env->fp_status);
+    DBG_FPU(" = %Lg\n", floatx80_to_ldouble(res));
+
+    floatx80_to_FP0(env, res);
+}
+
+void HELPER(mul_FP0_FP1)(CPUState *env)
+{
+    floatx80 res;
+
+    DBG_FPUH("mul_FP0_FP1 %Lg %Lg",
+            floatx80_to_ldouble(FP0_to_floatx80(env)),
floatx80_to_ldouble(FP1_to_floatx80(env)));
+    res = floatx80_mul(FP0_to_floatx80(env), FP1_to_floatx80(env),
+                       &env->fp_status);
+    DBG_FPU(" = %Lg\n", floatx80_to_ldouble(res));
+
+    floatx80_to_FP0(env, res);
+}
+
+void HELPER(div_FP0_FP1)(CPUState *env)
+{
+    floatx80 res;
+
+    DBG_FPUH("div_FP0_FP1 %Lg %Lg",
+            floatx80_to_ldouble(FP0_to_floatx80(env)),
floatx80_to_ldouble(FP1_to_floatx80(env)));
+    res = floatx80_div(FP1_to_floatx80(env), FP0_to_floatx80(env),
+                       &env->fp_status);
+    DBG_FPU(" = %Lg\n", floatx80_to_ldouble(res));
+
+    floatx80_to_FP0(env, res);
+}
+
+void HELPER(mod_FP0_FP1)(CPUState *env)
+{
+    floatx80 res;
+    long double src, dst;
+
+    src = floatx80_to_ldouble(FP0_to_floatx80(env));
+    dst = floatx80_to_ldouble(FP1_to_floatx80(env));
+
+    DBG_FPUH("mod_FP0_FP1 %Lg %Lg", src, dst);
+    dst = fmodl(dst, src);
+    DBG_FPU(" = %Lg\n", dst);
+
+    res = ldouble_to_floatx80(dst);
+    floatx80_to_FP0(env, res);
+}
+
+void HELPER(sincos_FP0_FP1)(CPUState *env)
+{
+    floatx80 res;
+    long double val, valsin, valcos;
+
+    res = FP0_to_floatx80(env);
+    val = floatx80_to_ldouble(res);
+
+    DBG_FPUH("sincos_FP0 %Lg", val);
+    sincosl(val, &valsin, &valcos);
+    DBG_FPU(" = %Lg, %Lg", valsin, valcos);
+    res = ldouble_to_floatx80(valsin);
+    floatx80_to_FP0(env, res);
+    res = ldouble_to_floatx80(valcos);
+    floatx80_to_FP1(env, res);
+}
+
+void HELPER(fcmp_FP0_FP1)(CPUState *env)
 {
     /* ??? This may incorrectly raise exceptions.  */
     /* ??? Should flush denormals to zero.  */
-    float64 res;
-    res = float64_sub(a, b, &env->fp_status);
-    if (float64_is_quiet_nan(res)) {
+    floatx80 res;
+    DBG_FPUH("cmp_FP0_FP1 %Lg %Lg", floatx80_to_ldouble(FP0_to_floatx80(env)),
+            floatx80_to_ldouble(FP1_to_floatx80(env)));
+    res = floatx80_sub(FP1_to_floatx80(env), FP0_to_floatx80(env),
+                       &env->fp_status);
+    if (floatx80_is_any_nan(res)) {
         /* +/-inf compares equal against itself, but sub returns nan.  */
-        if (!float64_is_quiet_nan(a)
-            && !float64_is_quiet_nan(b)) {
-            res = float64_zero;
-            if (float64_lt_quiet(a, res, &env->fp_status))
-                res = float64_chs(res);
+        if (!floatx80_is_any_nan(FP0_to_floatx80(env))
+            && !floatx80_is_any_nan(FP1_to_floatx80(env))) {
+            res = floatx80_zero;
+            if (floatx80_lt_quiet(FP1_to_floatx80(env), res, &env->fp_status))
+                res = floatx80_chs(res);
         }
     }
-    return res;
+    DBG_FPU(" = %Lg\n", floatx80_to_ldouble(res));
+    floatx80_to_FP0(env, res);
 }

-uint32_t HELPER(compare_f64)(CPUState *env, float64 val)
+uint32_t HELPER(compare_FP0)(CPUState *env)
 {
-    return float64_compare_quiet(val, float64_zero, &env->fp_status);
+    uint32_t res;
+
+    DBG_FPUH("compare_FP0 %Lg", floatx80_to_ldouble(FP0_to_floatx80(env)));
+    res = float64_compare_quiet(floatx80_to_float64(FP0_to_floatx80(env),
+                                                    &env->fp_status),
+				float64_zero, &env->fp_status);
+    DBG_FPU(" = %d\n", res);
+    return res;
 }

+void HELPER(fmovem)(CPUState *env, uint32_t opsize, uint32_t mode,
uint32_t mask)
+{
+    fprintf(stderr, "MISSING HELPER fmovem\n");
+}
 /* MAC unit.  */
 /* FIXME: The MAC unit implementation is a bit of a mess.  Some helpers
    take values,  others take register numbers and manipulate the contents
@@ -921,3 +2113,132 @@  void HELPER(set_mac_extu)(CPUState *env,
uint32_t val, uint32_t acc)
     res |= (uint64_t)(val & 0xffff0000) << 16;
     env->macc[acc + 1] = res;
 }
+
+/* load from a bitfield */
+
+uint64_t HELPER(bitfield_load)(uint32_t addr, uint32_t offset, uint32_t width)
+{
+    uint8_t data[8];
+    uint64_t bitfield;
+    int size;
+    int i;
+
+    size = (offset + width + 7) >> 3;
+#if defined(CONFIG_USER_ONLY)
+    cpu_memory_rw_debug(NULL, (target_ulong)addr, data, size, 0);
+#else
+    cpu_physical_memory_rw(addr, data, size, 0);
+#endif
+
+    bitfield = data[0];
+    for (i = 1; i < 8; i++)
+        bitfield = (bitfield << 8) | data[i];
+
+    return bitfield;
+}
+
+/* store to a bitfield */
+
+void HELPER(bitfield_store)(uint32_t addr, uint32_t offset, uint32_t width,
+                            uint64_t bitfield)
+{
+    uint8_t data[8];
+    int size;
+    int i;
+
+    size = (offset + width + 7) >> 3;
+
+    for (i = 0; i < 8; i++) {
+        data[7 - i] = bitfield;
+        bitfield >>= 8;
+    }
+
+#if defined(CONFIG_USER_ONLY)
+    cpu_memory_rw_debug(NULL, (target_ulong)addr, data, size, 1);
+#else
+    cpu_physical_memory_rw(addr, data, size, 1);
+#endif
+}
+
+uint32_t HELPER(abcd_cc)(CPUState *env, uint32_t src, uint32_t dest)
+{
+    uint16_t hi, lo;
+    uint16_t res;
+    uint32_t flags;
+
+    flags = env->cc_dest;
+    flags &= ~(CCF_C|CCF_X);
+
+    lo = (src & 0x0f) + (dest & 0x0f);
+    if (env->cc_x)
+        lo ++;
+    hi = (src & 0xf0) + (dest & 0xf0);
+
+    res = hi + lo;
+    if (lo > 9)
+        res += 0x06;
+
+    /* C and X flags: set if decimal carry, cleared otherwise */
+
+    if ((res & 0x3F0) > 0x90) {
+        res += 0x60;
+        flags |= CCF_C|CCF_X;
+    }
+
+    /* Z flag: cleared if nonzero */
+
+    if (res & 0xff)
+        flags &= ~CCF_Z;
+
+    dest = (dest & 0xffffff00) | (res & 0xff);
+
+    env->cc_x = (flags & CCF_X) != 0;
+    env->cc_dest = flags;
+
+    return dest;
+}
+
+uint32_t HELPER(sbcd_cc)(CPUState *env, uint32_t src, uint32_t dest)
+{
+    uint16_t hi, lo;
+    uint16_t res;
+    uint32_t flags;
+    int bcd = 0, carry = 0;
+
+    flags = env->cc_dest;
+    flags &= ~(CCF_C|CCF_X);
+
+    if (env->cc_x)
+        carry = 1;
+
+    lo = (dest & 0x0f) - (src & 0x0f) - carry;
+    hi = (dest & 0xf0) - (src & 0xf0);
+
+    res = hi + lo;
+    if (lo & 0xf0) {
+        res -= 0x06;
+        bcd = 0x06;
+    }
+
+    if ((((dest & 0xff) - (src & 0xff) - carry) & 0x100) > 0xff) {
+        res -= 0x60;
+    }
+
+    /* C and X flags: set if decimal carry, cleared otherwise */
+
+    if ((((dest & 0xff) - (src & 0xff) - (bcd + carry)) & 0x300) > 0xff) {
+        flags |= CCF_C|CCF_X;
+    }
+
+    /* Z flag: cleared if nonzero */
+
+    if (res & 0xff)
+        flags &= ~CCF_Z;
+
+    dest = (dest & 0xffffff00) | (res & 0xff);
+
+    env->cc_x = (flags & CCF_X) != 0;
+    env->cc_dest = flags;
+
+    return dest;
+}
diff --git target-m68k/helpers.h target-m68k/helpers.h
index cb8a0c7..d321874 100644
--- target-m68k/helpers.h
+++ target-m68k/helpers.h
@@ -2,33 +2,98 @@ 

 DEF_HELPER_1(bitrev, i32, i32)
 DEF_HELPER_1(ff1, i32, i32)
+DEF_HELPER_2(bfffo, i32, i32, i32)
+DEF_HELPER_2(rol32, i32, i32, i32)
+DEF_HELPER_2(ror32, i32, i32, i32)
 DEF_HELPER_2(sats, i32, i32, i32)
 DEF_HELPER_2(divu, void, env, i32)
 DEF_HELPER_2(divs, void, env, i32)
-DEF_HELPER_3(addx_cc, i32, env, i32, i32)
-DEF_HELPER_3(subx_cc, i32, env, i32, i32)
-DEF_HELPER_3(shl_cc, i32, env, i32, i32)
-DEF_HELPER_3(shr_cc, i32, env, i32, i32)
-DEF_HELPER_3(sar_cc, i32, env, i32, i32)
-DEF_HELPER_2(xflag_lt, i32, i32, i32)
+DEF_HELPER_1(divu64, void, env)
+DEF_HELPER_1(divs64, void, env)
+DEF_HELPER_3(mulu32_cc, i32, env, i32, i32)
+DEF_HELPER_3(muls32_cc, i32, env, i32, i32)
+DEF_HELPER_3(mulu64, i32, env, i32, i32)
+DEF_HELPER_3(muls64, i32, env, i32, i32)
+DEF_HELPER_3(addx8_cc, i32, env, i32, i32)
+DEF_HELPER_3(addx16_cc, i32, env, i32, i32)
+DEF_HELPER_3(addx32_cc, i32, env, i32, i32)
+DEF_HELPER_3(subx8_cc, i32, env, i32, i32)
+DEF_HELPER_3(subx16_cc, i32, env, i32, i32)
+DEF_HELPER_3(subx32_cc, i32, env, i32, i32)
+DEF_HELPER_3(shl8_cc, i32, env, i32, i32)
+DEF_HELPER_3(shl16_cc, i32, env, i32, i32)
+DEF_HELPER_3(shl32_cc, i32, env, i32, i32)
+DEF_HELPER_3(shr8_cc, i32, env, i32, i32)
+DEF_HELPER_3(shr16_cc, i32, env, i32, i32)
+DEF_HELPER_3(shr32_cc, i32, env, i32, i32)
+DEF_HELPER_3(sal8_cc, i32, env, i32, i32)
+DEF_HELPER_3(sal16_cc, i32, env, i32, i32)
+DEF_HELPER_3(sal32_cc, i32, env, i32, i32)
+DEF_HELPER_3(sar8_cc, i32, env, i32, i32)
+DEF_HELPER_3(sar16_cc, i32, env, i32, i32)
+DEF_HELPER_3(sar32_cc, i32, env, i32, i32)
+DEF_HELPER_3(rol8_cc, i32, env, i32, i32)
+DEF_HELPER_3(rol16_cc, i32, env, i32, i32)
+DEF_HELPER_3(rol32_cc, i32, env, i32, i32)
+DEF_HELPER_3(ror8_cc, i32, env, i32, i32)
+DEF_HELPER_3(ror16_cc, i32, env, i32, i32)
+DEF_HELPER_3(ror32_cc, i32, env, i32, i32)
+DEF_HELPER_3(roxr8_cc, i32, env, i32, i32)
+DEF_HELPER_3(roxr16_cc, i32, env, i32, i32)
+DEF_HELPER_3(roxr32_cc, i32, env, i32, i32)
+DEF_HELPER_3(roxl8_cc, i32, env, i32, i32)
+DEF_HELPER_3(roxl16_cc, i32, env, i32, i32)
+DEF_HELPER_3(roxl32_cc, i32, env, i32, i32)
+DEF_HELPER_2(xflag_lt_i8, i32, i32, i32)
+DEF_HELPER_2(xflag_lt_i16, i32, i32, i32)
+DEF_HELPER_2(xflag_lt_i32, i32, i32, i32)
 DEF_HELPER_2(set_sr, void, env, i32)
-DEF_HELPER_3(movec, void, env, i32, i32)
+DEF_HELPER_3(movec_to, void, env, i32, i32)
+DEF_HELPER_2(movec_from, i32, env, i32)

-DEF_HELPER_2(f64_to_i32, f32, env, f64)
-DEF_HELPER_2(f64_to_f32, f32, env, f64)
-DEF_HELPER_2(i32_to_f64, f64, env, i32)
-DEF_HELPER_2(f32_to_f64, f64, env, f32)
-DEF_HELPER_2(iround_f64, f64, env, f64)
-DEF_HELPER_2(itrunc_f64, f64, env, f64)
-DEF_HELPER_2(sqrt_f64, f64, env, f64)
-DEF_HELPER_1(abs_f64, f64, f64)
-DEF_HELPER_1(chs_f64, f64, f64)
-DEF_HELPER_3(add_f64, f64, env, f64, f64)
-DEF_HELPER_3(sub_f64, f64, env, f64, f64)
-DEF_HELPER_3(mul_f64, f64, env, f64, f64)
-DEF_HELPER_3(div_f64, f64, env, f64, f64)
-DEF_HELPER_3(sub_cmp_f64, f64, env, f64, f64)
-DEF_HELPER_2(compare_f64, i32, env, f64)
+DEF_HELPER_1(exts32_FP0, void, env)
+DEF_HELPER_1(extf32_FP0, void, env)
+DEF_HELPER_1(extf64_FP0, void, env)
+DEF_HELPER_1(redf32_FP0, void, env)
+DEF_HELPER_1(redf64_FP0, void, env)
+DEF_HELPER_1(extp96_FP0, void, env)
+DEF_HELPER_1(reds32_FP0, void, env)
+DEF_HELPER_1(redp96_FP0, void, env)
+
+DEF_HELPER_4(fmovem, void, env, i32, i32, i32)
+DEF_HELPER_2(set_fpcr, void, env, i32)
+DEF_HELPER_2(const_FP0, void, env, i32)
+DEF_HELPER_1(iround_FP0, void, env)
+DEF_HELPER_1(sinh_FP0, void, env)
+DEF_HELPER_1(itrunc_FP0, void, env)
+DEF_HELPER_1(sqrt_FP0, void, env)
+DEF_HELPER_1(lognp1_FP0, void, env)
+DEF_HELPER_1(atan_FP0, void, env)
+DEF_HELPER_1(asin_FP0, void, env)
+DEF_HELPER_1(atanh_FP0, void, env)
+DEF_HELPER_1(sin_FP0, void, env)
+DEF_HELPER_1(tanh_FP0, void, env)
+DEF_HELPER_1(tan_FP0, void, env)
+DEF_HELPER_1(exp_FP0, void, env)
+DEF_HELPER_1(exp2_FP0, void, env)
+DEF_HELPER_1(exp10_FP0, void, env)
+DEF_HELPER_1(ln_FP0, void, env)
+DEF_HELPER_1(log10_FP0, void, env)
+DEF_HELPER_1(abs_FP0, void, env)
+DEF_HELPER_1(cosh_FP0, void, env)
+DEF_HELPER_1(chs_FP0, void, env)
+DEF_HELPER_1(acos_FP0, void, env)
+DEF_HELPER_1(cos_FP0, void, env)
+DEF_HELPER_1(getexp_FP0, void, env)
+DEF_HELPER_1(scale_FP0_FP1, void, env)
+DEF_HELPER_1(add_FP0_FP1, void, env)
+DEF_HELPER_1(sub_FP0_FP1, void, env)
+DEF_HELPER_1(mul_FP0_FP1, void, env)
+DEF_HELPER_1(div_FP0_FP1, void, env)
+DEF_HELPER_1(mod_FP0_FP1, void, env)
+DEF_HELPER_1(sincos_FP0_FP1, void, env)
+DEF_HELPER_1(fcmp_FP0_FP1, void, env)
+DEF_HELPER_1(compare_FP0, i32, env)

 DEF_HELPER_3(mac_move, void, env, i32, i32)
 DEF_HELPER_3(macmulf, i64, env, i32, i32)
@@ -51,4 +116,9 @@  DEF_HELPER_3(set_mac_extu, void, env, i32, i32)
 DEF_HELPER_2(flush_flags, void, env, i32)
 DEF_HELPER_1(raise_exception, void, i32)

+DEF_HELPER_3(bitfield_load, i64, i32, i32, i32);
+DEF_HELPER_4(bitfield_store, void, i32, i32, i32, i64);
+
+DEF_HELPER_3(abcd_cc, i32, env, i32, i32);
+DEF_HELPER_3(sbcd_cc, i32, env, i32, i32);
 #include "def-helper.h"
diff --git target-m68k/m68k-qreg.h target-m68k/m68k-qreg.h
deleted file mode 100644
index c224d5e..0000000
--- target-m68k/m68k-qreg.h
+++ /dev/null
@@ -1,11 +0,0 @@ 
-enum {
-#define DEFO32(name, offset) QREG_##name,
-#define DEFR(name, reg, mode) QREG_##name,
-#define DEFF64(name, offset) QREG_##name,
-    QREG_NULL,
-#include "qregs.def"
-    TARGET_NUM_QREGS = 0x100
-#undef DEFO32
-#undef DEFR
-#undef DEFF64
-};
diff --git target-m68k/op_helper.c target-m68k/op_helper.c
index c66fa0c..6c3144e 100644
--- target-m68k/op_helper.c
+++ target-m68k/op_helper.c
@@ -213,12 +213,18 @@  void HELPER(divu)(CPUState *env, uint32_t word)
     /* Avoid using a PARAM1 of zero.  This breaks dyngen because it uses
        the address of a symbol, and gcc knows symbols can't have address
        zero.  */
-    if (word && quot > 0xffff)
-        flags |= CCF_V;
-    if (quot == 0)
-        flags |= CCF_Z;
-    else if ((int32_t)quot < 0)
-        flags |= CCF_N;
+    if (word && quot > 0xffff) {
+	/* real 68040 keep Z and N on overflow,
+         * whereas documentation says "undefined"
+         */
+        flags |= CCF_V | (env->cc_dest & (CCF_Z|CCF_N));
+    } else {
+        if (quot == 0)
+            flags |= CCF_Z;
+        else if ((int16_t)quot < 0)
+            flags |= CCF_N;
+    }
+
     env->div1 = quot;
     env->div2 = rem;
     env->cc_dest = flags;
@@ -239,13 +245,148 @@  void HELPER(divs)(CPUState *env, uint32_t word)
     quot = num / den;
     rem = num % den;
     flags = 0;
-    if (word && quot != (int16_t)quot)
-        flags |= CCF_V;
-    if (quot == 0)
-        flags |= CCF_Z;
-    else if (quot < 0)
-        flags |= CCF_N;
+    if (word && quot != (int16_t)quot) {
+	/* real 68040 keep Z and N on overflow,
+         * whereas documentation says "undefined"
+         */
+        flags |= CCF_V | (env->cc_dest & (CCF_Z|CCF_N));
+    } else {
+        if (quot == 0)
+            flags |= CCF_Z;
+        else if ((int16_t)quot < 0)
+            flags |= CCF_N;
+    }
+
     env->div1 = quot;
     env->div2 = rem;
     env->cc_dest = flags;
 }
+
+void HELPER(divu64)(CPUState *env)
+{
+    uint32_t num;
+    uint32_t den;
+    uint64_t quot;
+    uint32_t rem;
+    uint32_t flags;
+    uint64_t quad;
+
+    num = env->div1;
+    den = env->div2;
+    /* ??? This needs to make sure the throwing location is accurate.  */
+    if (den == 0)
+        raise_exception(EXCP_DIV0);
+    quad = num | ((uint64_t)env->quadh << 32);
+    quot = quad / den;
+    rem = quad % den;
+    if (quot > 0xffffffffULL) {
+        flags = (env->cc_dest & ~ CCF_C) | CCF_V;
+    } else {
+        flags = 0;
+        if (quot == 0)
+            flags |= CCF_Z;
+        else if ((int32_t)quot < 0)
+            flags |= CCF_N;
+        env->div1 = quot;
+        env->quadh = rem;
+    }
+    env->cc_dest = flags;
+}
+
+void HELPER(divs64)(CPUState *env)
+{
+    uint32_t num;
+    int32_t den;
+    int64_t quot;
+    int32_t rem;
+    int32_t flags;
+    int64_t quad;
+
+    num = env->div1;
+    den = env->div2;
+    if (den == 0)
+        raise_exception(EXCP_DIV0);
+    quad = num | ((int64_t)env->quadh << 32);
+    quot = quad / (int64_t)den;
+    rem = quad % (int64_t)den;
+
+    if ((quot & 0xffffffff80000000ULL) &&
+        (quot & 0xffffffff80000000ULL) != 0xffffffff80000000ULL) {
+	flags = (env->cc_dest & ~ CCF_C) | CCF_V;
+    } else {
+        flags = 0;
+        if (quot == 0)
+	    flags |= CCF_Z;
+        else if ((int32_t)quot < 0)
+	    flags |= CCF_N;
+        env->div1 = quot;
+        env->quadh = rem;
+    }
+    env->cc_dest = flags;
+}
+
+uint32_t HELPER(mulu32_cc)(CPUState *env, uint32_t op1, uint32_t op2)
+{
+    uint64_t res = (uint32_t)op1 * op2;
+    uint32_t flags;
+
+    flags = 0;
+    if (res >> 32)
+       flags |= CCF_V;
+    if ((uint32_t)res == 0)
+       flags |= CCF_Z;
+    if ((int32_t)res < 0)
+       flags |= CCF_N;
+    env->cc_dest = flags;
+
+    return res;
+}
+
+uint32_t HELPER(muls32_cc)(CPUState *env, uint32_t op1, uint32_t op2)
+{
+    int64_t res = (int32_t)op1 * (int32_t)op2;
+    uint32_t flags;
+
+    flags = 0;
+    if (res != (int64_t)(int32_t)res)
+       flags |= CCF_V;
+    if ((uint32_t)res == 0)
+       flags |= CCF_Z;
+    if ((int32_t)res < 0)
+       flags |= CCF_N;
+    env->cc_dest = flags;
+
+    return res;
+}
+
+uint32_t HELPER(mulu64)(CPUState *env, uint32_t op1, uint32_t op2)
+{
+    uint64_t res = (uint64_t)op1 * op2;
+    uint32_t flags;
+
+    env->quadh = res >> 32;
+    flags = 0;
+    if (res == 0)
+       flags |= CCF_Z;
+    if ((int64_t)res < 0)
+       flags |= CCF_N;
+    env->cc_dest = flags;
+
+    return res;
+}
+
+uint32_t HELPER(muls64)(CPUState *env, uint32_t op1, uint32_t op2)
+{
+    int64_t res = (uint64_t)(int32_t)op1 * (int32_t)op2;
+    uint32_t flags;
+
+    env->quadh = res >> 32;
+    flags = 0;
+    if (res == 0)
+       flags |= CCF_Z;
+    if (res < 0)
+       flags |= CCF_N;
+    env->cc_dest = flags;
+
+    return res;
+}
diff --git target-m68k/qregs.def target-m68k/qregs.def
index 49400c4..13a8e5c 100644
--- target-m68k/qregs.def
+++ target-m68k/qregs.def
@@ -1,4 +1,5 @@ 
-DEFF64(FP_RESULT, fp_result)
+DEFF96(FP0, fp0)
+DEFF96(FP1, fp1)
 DEFO32(PC, pc)
 DEFO32(SR, sr)
 DEFO32(CC_OP, cc_op)
@@ -7,6 +8,7 @@  DEFO32(CC_SRC, cc_src)
 DEFO32(CC_X, cc_x)
 DEFO32(DIV1, div1)
 DEFO32(DIV2, div2)
+DEFO32(QUADH, quadh)
 DEFO32(EXCEPTION, exception_index)
 DEFO32(HALTED, halted)
 DEFO32(MACSR, macsr)
diff --git target-m68k/translate.c target-m68k/translate.c
index 0e7f1fe..e2c88fc 100644
--- target-m68k/translate.c
+++ target-m68k/translate.c
@@ -29,36 +29,34 @@ 
 #include "tcg-op.h"
 #include "qemu-log.h"

+#include "sysemu.h"
+
 #include "helpers.h"
 #define GEN_HELPER 1
 #include "helpers.h"

 //#define DEBUG_DISPATCH 1

-/* Fake floating point.  */
-#define tcg_gen_mov_f64 tcg_gen_mov_i64
-#define tcg_gen_qemu_ldf64 tcg_gen_qemu_ld64
-#define tcg_gen_qemu_stf64 tcg_gen_qemu_st64
-
 #define DEFO32(name, offset) static TCGv QREG_##name;
 #define DEFO64(name, offset) static TCGv_i64 QREG_##name;
-#define DEFF64(name, offset) static TCGv_i64 QREG_##name;
+#define DEFF96(name, offset) static TCGv_i32 QREG_##name##H; static
TCGv_i64 QREG_##name##L;
 #include "qregs.def"
 #undef DEFO32
 #undef DEFO64
-#undef DEFF64
+#undef DEFF96

 static TCGv_ptr cpu_env;

-static char cpu_reg_names[3*8*3 + 5*4];
+static char cpu_reg_names[2*8*3 + 5*4];
 static TCGv cpu_dregs[8];
 static TCGv cpu_aregs[8];
-static TCGv_i64 cpu_fregs[8];
 static TCGv_i64 cpu_macc[4];
+static TCGv QEMU_FPSR;
+static TCGv QEMU_FPCR;

-#define DREG(insn, pos) cpu_dregs[((insn) >> (pos)) & 7]
-#define AREG(insn, pos) cpu_aregs[((insn) >> (pos)) & 7]
-#define FREG(insn, pos) cpu_fregs[((insn) >> (pos)) & 7]
+#define REG(insn, pos) (((insn) >> (pos)) & 7)
+#define DREG(insn, pos) cpu_dregs[REG(insn, pos)]
+#define AREG(insn, pos) cpu_aregs[REG(insn, pos)]
 #define MACREG(acc) cpu_macc[acc]
 #define QREG_SP cpu_aregs[7]

@@ -76,11 +74,14 @@  void m68k_tcg_init(void)

 #define DEFO32(name,  offset) QREG_##name =
tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUState, offset), #name);
 #define DEFO64(name,  offset) QREG_##name =
tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUState, offset), #name);
-#define DEFF64(name,  offset) DEFO64(name, offset)
+#define DEFF96(name,  offset) do { \
+QREG_##name##H = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUState,
offset##h), #name); \
+QREG_##name##L = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUState,
offset##l), #name); \
+} while (0);
 #include "qregs.def"
 #undef DEFO32
 #undef DEFO64
-#undef DEFF64
+#undef DEFF96

     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");

@@ -94,10 +95,6 @@  void m68k_tcg_init(void)
         cpu_aregs[i] = tcg_global_mem_new(TCG_AREG0,
                                           offsetof(CPUM68KState, aregs[i]), p);
         p += 3;
-        sprintf(p, "F%d", i);
-        cpu_fregs[i] = tcg_global_mem_new_i64(TCG_AREG0,
-                                          offsetof(CPUM68KState, fregs[i]), p);
-        p += 3;
     }
     for (i = 0; i < 4; i++) {
         sprintf(p, "ACC%d", i);
@@ -106,6 +103,11 @@  void m68k_tcg_init(void)
         p += 5;
     }

+    QEMU_FPSR = tcg_global_mem_new(TCG_AREG0, offsetof(CPUM68KState, fpsr),
+                                   "FPSR");
+    QEMU_FPCR = tcg_global_mem_new(TCG_AREG0, offsetof(CPUM68KState, fpcr),
+                                   "FPCR");
+
     NULL_QREG = tcg_global_mem_new(TCG_AREG0, -4, "NULL");
     store_dummy = tcg_global_mem_new(TCG_AREG0, -8, "NULL");

@@ -150,11 +152,13 @@  typedef struct DisasContext {
 static void *gen_throws_exception;
 #define gen_last_qop NULL

-#define OS_BYTE 0
-#define OS_WORD 1
-#define OS_LONG 2
-#define OS_SINGLE 4
-#define OS_DOUBLE 5
+#define OS_BYTE     1
+#define OS_WORD     2
+#define OS_LONG     3
+#define OS_SINGLE   4
+#define OS_DOUBLE   5
+#define OS_EXTENDED 6
+#define OS_PACKED   7

 typedef void (*disas_proc)(DisasContext *, uint16_t);

@@ -170,6 +174,81 @@  typedef void (*disas_proc)(DisasContext *, uint16_t);
   static void disas_##name (DisasContext *s, uint16_t insn)
 #endif

+/* Update the CPU env CC_OP state.  */
+static inline void gen_flush_cc_op(DisasContext *s)
+{
+    if (s->cc_op != CC_OP_DYNAMIC)
+        tcg_gen_movi_i32(QREG_CC_OP, s->cc_op);
+}
+
+
+/* Generate a jump to an immediate address.  */
+static void gen_jmp_im(DisasContext *s, uint32_t dest)
+{
+    gen_flush_cc_op(s);
+    tcg_gen_movi_i32(QREG_PC, dest);
+    s->is_jmp = DISAS_JUMP;
+}
+
+static void gen_exception(DisasContext *s, uint32_t where, int nr)
+{
+    if(((where &0xFFF0) != 0x24F0) && ((where &0xFF00) != 0x5100))
+//	fprintf(stderr,"Exception! %x  @ 0x%X 0x%X\n",nr,where,s->pc);
+//	vm_stop(VMSTOP_DEBUG);	
+gen_flush_cc_op(s);
+    if(nr == 0x10002)
+		gen_jmp_im(s,where);
+//	else
+//	gen_jmp_im(s, s->env->vbr + nr*4);
+    gen_helper_raise_exception(tcg_const_i32(nr));
+}
+
+static inline void gen_addr_fault(DisasContext *s)
+{
+   fprintf(stderr,"address fault\n");
+   gen_exception(s, s->insn_pc, EXCP_ADDRESS);
+}
+
+static void gen_op_load_fpr_FP0(int freg)
+{
+    tcg_gen_ld16u_i32(QREG_FP0H, cpu_env,
+                      offsetof(CPUM68KState, fregs[freg]) +
+                      offsetof(FPReg, d.high));
+    tcg_gen_ld_i64(QREG_FP0L, cpu_env,
+                   offsetof(CPUM68KState, fregs[freg]) +
+                   offsetof(FPReg, d.low));
+}
+
+static void gen_op_store_fpr_FP0(int freg)
+{
+    tcg_gen_st16_i32(QREG_FP0H, cpu_env,
+                     offsetof(CPUM68KState, fregs[freg]) +
+                     offsetof(FPReg, d.high));
+    tcg_gen_st_i64(QREG_FP0L, cpu_env,
+                   offsetof(CPUM68KState, fregs[freg]) +
+                   offsetof(FPReg, d.low));
+}
+
+static void gen_op_store_fpr_FP1(int freg)
+{
+    tcg_gen_st16_i32(QREG_FP1H, cpu_env,
+                     offsetof(CPUM68KState, fregs[freg]) +
+                     offsetof(FPReg, d.high));
+    tcg_gen_st_i64(QREG_FP1L, cpu_env,
+                   offsetof(CPUM68KState, fregs[freg]) +
+                   offsetof(FPReg, d.low));
+}
+
+static void gen_op_load_fpr_FP1(int freg)
+{
+    tcg_gen_ld16u_i32(QREG_FP1H, cpu_env,
+                      offsetof(CPUM68KState, fregs[freg]) +
+                      offsetof(FPReg, d.high));
+    tcg_gen_ld_i64(QREG_FP1L, cpu_env,
+                   offsetof(CPUM68KState, fregs[freg]) +
+                   offsetof(FPReg, d.low));
+}
+
 /* Generate a load from the specified address.  Narrow values are
    sign extended to full register width.  */
 static inline TCGv gen_load(DisasContext * s, int opsize, TCGv addr, int sign)
@@ -192,7 +271,6 @@  static inline TCGv gen_load(DisasContext * s, int
opsize, TCGv addr, int sign)
             tcg_gen_qemu_ld16u(tmp, addr, index);
         break;
     case OS_LONG:
-    case OS_SINGLE:
         tcg_gen_qemu_ld32u(tmp, addr, index);
         break;
     default:
@@ -202,17 +280,6 @@  static inline TCGv gen_load(DisasContext * s, int
opsize, TCGv addr, int sign)
     return tmp;
 }

-static inline TCGv_i64 gen_load64(DisasContext * s, TCGv addr)
-{
-    TCGv_i64 tmp;
-    int index = IS_USER(s);
-    s->is_mem = 1;
-    tmp = tcg_temp_new_i64();
-    tcg_gen_qemu_ldf64(tmp, addr, index);
-    gen_throws_exception = gen_last_qop;
-    return tmp;
-}
-
 /* Generate a store.  */
 static inline void gen_store(DisasContext *s, int opsize, TCGv addr, TCGv val)
 {
@@ -226,7 +293,6 @@  static inline void gen_store(DisasContext *s, int
opsize, TCGv addr, TCGv val)
         tcg_gen_qemu_st16(val, addr, index);
         break;
     case OS_LONG:
-    case OS_SINGLE:
         tcg_gen_qemu_st32(val, addr, index);
         break;
     default:
@@ -235,14 +301,6 @@  static inline void gen_store(DisasContext *s, int
opsize, TCGv addr, TCGv val)
     gen_throws_exception = gen_last_qop;
 }

-static inline void gen_store64(DisasContext *s, TCGv addr, TCGv_i64 val)
-{
-    int index = IS_USER(s);
-    s->is_mem = 1;
-    tcg_gen_qemu_stf64(val, addr, index);
-    gen_throws_exception = gen_last_qop;
-}
-
 typedef enum {
     EA_STORE,
     EA_LOADU,
@@ -262,16 +320,39 @@  static TCGv gen_ldst(DisasContext *s, int
opsize, TCGv addr, TCGv val,
     }
 }

-/* Read a 32-bit immediate constant.  */
-static inline uint32_t read_im32(DisasContext *s)
+/* Read an 8-bit immediate constant */
+static inline uint32_t read_im8(DisasContext *s)
 {
     uint32_t im;
-    im = ((uint32_t)lduw_code(s->pc)) << 16;
+    im = ldsb_code(s->pc + 1);
     s->pc += 2;
-    im |= lduw_code(s->pc);
+    return im;
+}
+/* Read a 16-bit immediate constant */
+static inline uint32_t read_im16(DisasContext *s)
+{
+    uint32_t im;
+    im = ldsw_code(s->pc);
     s->pc += 2;
     return im;
 }
+/* Read a 32-bit immediate constant.  */
+static inline uint32_t read_im32(DisasContext *s)
+{
+    uint32_t im;
+    im = read_im16(s) << 16;
+    im |= 0xffff & read_im16(s);
+    return im;
+}
+
+/* Read a 64-bit immediate constant.  */
+static inline uint64_t read_im64(DisasContext *s)
+{
+    uint64_t im;
+    im = (uint64_t)read_im32(s) << 32;
+    im |= (uint64_t)read_im32(s);
+    return im;
+}

 /* Calculate and address index.  */
 static TCGv gen_addr_index(uint16_t ext, TCGv tmp)
@@ -309,6 +390,9 @@  static TCGv gen_lea_indexed(DisasContext *s, int
opsize, TCGv base)
     if ((ext & 0x800) == 0 && !m68k_feature(s->env, M68K_FEATURE_WORD_INDEX))
         return NULL_QREG;

+    if (!m68k_feature(s->env, M68K_FEATURE_SCALED_INDEX))
+        ext &= ~(3 << 9);
+
     if (ext & 0x100) {
         /* full extension word format */
         if (!m68k_feature(s->env, M68K_FEATURE_EXT_FULL))
@@ -317,7 +401,7 @@  static TCGv gen_lea_indexed(DisasContext *s, int
opsize, TCGv base)
         if ((ext & 0x30) > 0x10) {
             /* base displacement */
             if ((ext & 0x30) == 0x20) {
-                bd = (int16_t)lduw_code(s->pc);
+                bd = ldsw_code(s->pc);
                 s->pc += 2;
             } else {
                 bd = read_im32(s);
@@ -366,7 +450,7 @@  static TCGv gen_lea_indexed(DisasContext *s, int
opsize, TCGv base)
             if ((ext & 3) > 1) {
                 /* outer displacement */
                 if ((ext & 3) == 2) {
-                    od = (int16_t)lduw_code(s->pc);
+                    od = ldsw_code(s->pc);
                     s->pc += 2;
                 } else {
                     od = read_im32(s);
@@ -395,13 +479,6 @@  static TCGv gen_lea_indexed(DisasContext *s, int
opsize, TCGv base)
     return add;
 }

-/* Update the CPU env CC_OP state.  */
-static inline void gen_flush_cc_op(DisasContext *s)
-{
-    if (s->cc_op != CC_OP_DYNAMIC)
-        tcg_gen_movi_i32(QREG_CC_OP, s->cc_op);
-}
-
 /* Evaluate all the CC flags.  */
 static inline void gen_flush_flags(DisasContext *s)
 {
@@ -412,10 +489,28 @@  static inline void gen_flush_flags(DisasContext *s)
     s->cc_op = CC_OP_FLAGS;
 }

-static void gen_logic_cc(DisasContext *s, TCGv val)
+#define SET_CC_OP(opsize, op) do { \
+    switch (opsize) { \
+    case OS_BYTE: s->cc_op = CC_OP_##op##B; break; \
+    case OS_WORD: s->cc_op = CC_OP_##op##W; break; \
+    case OS_LONG: s->cc_op = CC_OP_##op; break; \
+    default: abort(); \
+    } \
+} while (0)
+
+#define SET_X_FLAG(opsize, a, b) do { \
+    switch (opsize) { \
+    case OS_BYTE: gen_helper_xflag_lt_i8(QREG_CC_X, a, b); break; \
+    case OS_WORD: gen_helper_xflag_lt_i16(QREG_CC_X, a, b); break; \
+    case OS_LONG: gen_helper_xflag_lt_i32(QREG_CC_X, a, b); break; \
+    default: abort(); \
+    } \
+} while (0)
+
+static void gen_logic_cc(DisasContext *s, TCGv val, int opsize)
 {
     tcg_gen_mov_i32(QREG_CC_DEST, val);
-    s->cc_op = CC_OP_LOGIC;
+    SET_CC_OP(opsize, LOGIC);
 }

 static void gen_update_cc_add(TCGv dest, TCGv src)
@@ -432,12 +527,38 @@  static inline int opsize_bytes(int opsize)
     case OS_LONG: return 4;
     case OS_SINGLE: return 4;
     case OS_DOUBLE: return 8;
+    case OS_EXTENDED: return 12;
+    case OS_PACKED: return 12;
     default:
         qemu_assert(0, "bad operand size");
         return 0;
     }
 }

+static inline int insn_opsize(int insn, int pos)
+{
+    switch ((insn >> pos) & 3) {
+    case 0: return OS_BYTE;
+    case 1: return OS_WORD;
+    case 2: return OS_LONG;
+    default: abort();
+    }
+}
+
+static inline int ext_opsize(int ext, int pos)
+{
+    switch ((ext >> pos) & 7) {
+    case 0: return OS_LONG;
+    case 1: return OS_SINGLE;
+    case 2: return OS_EXTENDED;
+    case 3: return OS_PACKED;
+    case 4: return OS_WORD;
+    case 5: return OS_DOUBLE;
+    case 6: return OS_BYTE;
+    default: abort();
+    }
+}
+
 /* Assign value to a register.  If the width is less than the register width
    only the low part of the register is set.  */
 static void gen_partset_reg(int opsize, TCGv reg, TCGv val)
@@ -487,7 +608,6 @@  static inline TCGv gen_extend(TCGv val, int
opsize, int sign)
             tcg_gen_ext16u_i32(tmp, val);
         break;
     case OS_LONG:
-    case OS_SINGLE:
         tmp = val;
         break;
     default:
@@ -520,8 +640,7 @@  static TCGv gen_lea(DisasContext *s, uint16_t
insn, int opsize)
     case 5: /* Indirect displacement.  */
         reg = AREG(insn, 0);
         tmp = tcg_temp_new();
-        ext = lduw_code(s->pc);
-        s->pc += 2;
+        ext = read_im16(s);
         tcg_gen_addi_i32(tmp, reg, (int16_t)ext);
         return tmp;
     case 6: /* Indirect index + displacement.  */
@@ -672,6 +791,294 @@  static TCGv gen_ea(DisasContext *s, uint16_t
insn, int opsize, TCGv val,
     return NULL_QREG;
 }

+static inline void gen_extend_FP0(int opsize)
+{
+    switch (opsize) {
+    case OS_BYTE:
+        tcg_gen_ext8s_i32(QREG_FP0H, QREG_FP0H);
+        gen_helper_exts32_FP0(cpu_env);
+        break;
+    case OS_WORD:
+        tcg_gen_ext16s_i32(QREG_FP0H, QREG_FP0H);
+        gen_helper_exts32_FP0(cpu_env);
+        break;
+    case OS_LONG:
+        gen_helper_exts32_FP0(cpu_env);
+        break;
+    case OS_SINGLE:
+        gen_helper_extf32_FP0(cpu_env);
+        break;
+    case OS_DOUBLE:
+        gen_helper_extf64_FP0(cpu_env);
+        break;
+    case OS_EXTENDED:
+        tcg_gen_shri_i32(QREG_FP0H, QREG_FP0H, 16);
+        break;
+    case OS_PACKED:
+        gen_helper_extp96_FP0(cpu_env);
+        break;
+    default:
+        qemu_assert(0, "FPU: Bad operand size");
+    }
+}
+
+static inline void gen_reduce_FP0(int opsize)
+{
+    switch (opsize) {
+    case OS_BYTE:
+    case OS_WORD:
+    case OS_LONG:
+        gen_helper_reds32_FP0(cpu_env);
+        break;
+    case OS_SINGLE:
+        gen_helper_redf32_FP0(cpu_env);
+        break;
+    case OS_DOUBLE:
+        gen_helper_redf64_FP0(cpu_env);
+        break;
+    case OS_EXTENDED:
+        tcg_gen_shli_i32(QREG_FP0H, QREG_FP0H, 16);
+        break;
+    case OS_PACKED:
+        gen_helper_redp96_FP0(cpu_env);
+        break;
+    default:
+        qemu_assert(0, "FPU: Bad operand size");
+    }
+}
+
+static inline void gen_load_FP0(DisasContext * s, int opsize, TCGv addr)
+{
+    TCGv tmp;
+    int index = IS_USER(s);
+    s->is_mem = 1;
+    switch(opsize) {
+    case OS_BYTE:
+        tcg_gen_qemu_ld8s(QREG_FP0H, addr, index);
+        gen_helper_exts32_FP0(cpu_env);
+        break;
+    case OS_WORD:
+        tcg_gen_qemu_ld16s(QREG_FP0H, addr, index);
+        gen_helper_exts32_FP0(cpu_env);
+        break;
+    case OS_LONG:
+        tcg_gen_qemu_ld32u(QREG_FP0H, addr, index);
+        gen_helper_exts32_FP0(cpu_env);
+        break;
+    case OS_SINGLE:
+        tcg_gen_qemu_ld32u(QREG_FP0H, addr, index);
+        gen_helper_extf32_FP0(cpu_env);
+        break;
+    case OS_DOUBLE:
+        tcg_gen_qemu_ld64(QREG_FP0L, addr, index);
+        gen_helper_extf64_FP0(cpu_env);
+        break;
+    case OS_EXTENDED:
+        tcg_gen_qemu_ld32u(QREG_FP0H, addr, index);
+        tcg_gen_shri_i32(QREG_FP0H, QREG_FP0H, 16);
+        tmp = tcg_temp_new();
+        tcg_gen_addi_i32(tmp, addr, 4);
+        tcg_gen_qemu_ld64(QREG_FP0L, tmp, index);
+        tcg_temp_free(tmp);
+        break;
+    case OS_PACKED:
+        tcg_gen_qemu_ld32u(QREG_FP0H, addr, index);
+        tmp = tcg_temp_new();
+        tcg_gen_addi_i32(tmp, addr, 4);
+        tcg_gen_qemu_ld64(QREG_FP0L, tmp, index);
+        tcg_temp_free(tmp);
+        gen_helper_extp96_FP0(cpu_env);
+        break;
+    default:
+        qemu_assert(0, "Bad operand size");
+    }
+    gen_throws_exception = gen_last_qop;
+}
+
+static inline void gen_store_FP0(DisasContext *s, int opsize, TCGv addr)
+{
+    TCGv tmp;
+    int index = IS_USER(s);
+    s->is_mem = 1;
+    switch(opsize) {
+    case OS_BYTE:
+        gen_helper_reds32_FP0(cpu_env);
+        tcg_gen_qemu_st8(QREG_FP0H, addr, index);
+        break;
+    case OS_WORD:
+        gen_helper_reds32_FP0(cpu_env);
+        tcg_gen_qemu_st16(QREG_FP0H, addr, index);
+        break;
+    case OS_LONG:
+        gen_helper_reds32_FP0(cpu_env);
+        tcg_gen_qemu_st32(QREG_FP0H, addr, index);
+        break;
+    case OS_SINGLE:
+        gen_helper_redf32_FP0(cpu_env);
+        tcg_gen_qemu_st32(QREG_FP0H, addr, index);
+        break;
+    case OS_DOUBLE:
+        gen_helper_redf64_FP0(cpu_env);
+        tcg_gen_qemu_st64(QREG_FP0L, addr, index);
+        break;
+    case OS_EXTENDED:
+        tcg_gen_shli_i32(QREG_FP0H, QREG_FP0H, 16);
+        tcg_gen_qemu_st32(QREG_FP0H, addr, index);
+        tmp = tcg_temp_new();
+        tcg_gen_addi_i32(tmp, addr, 4);
+        tcg_gen_qemu_st64(QREG_FP0L, tmp, index);
+        tcg_temp_free(tmp);
+        break;
+    case OS_PACKED:
+        gen_helper_redp96_FP0(cpu_env);
+        tcg_gen_qemu_st32(QREG_FP0H, addr, index);
+        tmp = tcg_temp_new();
+        tcg_gen_addi_i32(tmp, addr, 4);
+        tcg_gen_qemu_st64(QREG_FP0L, tmp, index);
+        tcg_temp_free(tmp);
+        break;
+    default:
+        qemu_assert(0, "Bad operand size");
+    }
+    gen_throws_exception = gen_last_qop;
+}
+
+static void gen_op_load_ea_FP0(DisasContext *s, uint16_t insn, int opsize)
+{
+    TCGv reg;
+    TCGv addr;
+    uint64_t val;
+
+    switch ((insn >> 3) & 7) {
+    case 0: /* Data register direct.  */
+        tcg_gen_mov_i32(QREG_FP0H, DREG(insn, 0));
+        gen_extend_FP0(opsize);
+        break;
+    case 1:  /* Address register direct.  */
+        gen_addr_fault(s);
+        break;
+    case 2: /* Indirect register */
+        gen_load_FP0(s, opsize, AREG(insn, 0));
+        break;
+    case 3: /* Indirect postincrement.  */
+        reg = AREG(insn, 0);
+        gen_load_FP0(s, opsize, reg);
+        tcg_gen_addi_i32(reg, reg, opsize_bytes(opsize));
+        break;
+    case 4: /* Indirect predecrememnt.  */
+        addr = gen_lea(s, insn, opsize);
+        gen_load_FP0(s, opsize, addr);
+        tcg_gen_mov_i32(AREG(insn, 0), addr);
+        break;
+    case 5: /* Indirect displacement.  */
+    case 6: /* Indirect index + displacement.  */
+        addr = gen_lea(s, insn, opsize);
+        gen_load_FP0(s, opsize, addr);
+        break;
+    case 7: /* Other */
+        switch (insn & 7) {
+        case 0: /* Absolute short.  */
+        case 1: /* Absolute long.  */
+        case 2: /* pc displacement  */
+        case 3: /* pc index+displacement.  */
+            addr = gen_lea(s, insn, opsize);
+            gen_load_FP0(s, opsize, addr);
+            break;
+        case 4: /* Immediate.  */
+            switch (opsize) {
+            case OS_BYTE:
+                val = read_im8(s);
+                tcg_gen_movi_i32(QREG_FP0H, val);
+                break;
+            case OS_WORD:
+                val = read_im16(s);
+                tcg_gen_movi_i32(QREG_FP0H, val);
+                break;
+            case OS_LONG:
+                val = read_im32(s);
+                tcg_gen_movi_i32(QREG_FP0H, val);
+                break;
+            case OS_SINGLE:
+                val = read_im32(s);
+                tcg_gen_movi_i32(QREG_FP0H, val);
+                break;
+            case OS_DOUBLE:
+                val = read_im64(s);
+                tcg_gen_movi_i64(QREG_FP0L, val);
+                break;
+            case OS_EXTENDED:
+                val = read_im32(s);
+                tcg_gen_movi_i32(QREG_FP0H, val);
+                val = read_im64(s);
+                tcg_gen_movi_i64(QREG_FP0L, val);
+                break;
+            case OS_PACKED:
+                val = read_im32(s);
+                tcg_gen_movi_i32(QREG_FP0H, val);
+                val = read_im64(s);
+                tcg_gen_movi_i64(QREG_FP0L, val);
+                break;
+            default:
+                qemu_assert(0, "Bad immediate operand");
+            }
+            gen_extend_FP0(opsize);
+            break;
+        default:
+            qemu_assert(0, "Bad FP addressing mode");
+        }
+    }
+}
+
+static void gen_op_store_ea_FP0(DisasContext *s, uint16_t insn, int opsize)
+{
+    TCGv reg;
+    TCGv addr;
+
+    switch ((insn >> 3) & 7) {
+    case 0: /* Data register direct.  */
+        gen_reduce_FP0(opsize);
+        tcg_gen_mov_i32(DREG(insn, 0), QREG_FP0H);
+        break;
+    case 1:  /* Address register direct.  */
+        gen_addr_fault(s);
+        break;
+    case 2: /* Indirect register */
+        reg = AREG(insn, 0);
+        gen_store_FP0(s, opsize, reg);
+        break;
+    case 3: /* Indirect postincrement.  */
+        reg = AREG(insn, 0);
+        gen_store_FP0(s, opsize, reg);
+        tcg_gen_addi_i32(reg, reg, opsize_bytes(opsize));
+        break;
+    case 4: /* Indirect predecrememnt.  */
+        addr = gen_lea(s, insn, opsize);
+        gen_store_FP0(s, opsize, addr);
+        tcg_gen_mov_i32(AREG(insn, 0), addr);
+        break;
+    case 5: /* Indirect displacement.  */
+    case 6: /* Indirect index + displacement.  */
+        addr = gen_lea(s, insn, opsize);
+        gen_store_FP0(s, opsize, addr);
+        break;
+    case 7: /* Other */
+        switch (insn & 7) {
+        case 0: /* Absolute short.  */
+        case 1: /* Absolute long.  */
+            addr = gen_lea(s, insn, opsize);
+            gen_store_FP0(s, opsize, addr);
+            break;
+        case 2: /* pc displacement  */
+        case 3: /* pc index+displacement.  */
+        case 4: /* Immediate.  */
+            gen_addr_fault(s);
+            break;
+        default:
+            qemu_assert(0, "Bad FP addressing mode");
+        }
+    }
+}
+
 /* This generates a conditional branch, clobbering all temporaries.  */
 static void gen_jmpcc(DisasContext *s, int cond, int l1)
 {
@@ -801,14 +1208,6 @@  static void gen_lookup_tb(DisasContext *s)
     s->is_jmp = DISAS_UPDATE;
 }

-/* Generate a jump to an immediate address.  */
-static void gen_jmp_im(DisasContext *s, uint32_t dest)
-{
-    gen_flush_cc_op(s);
-    tcg_gen_movi_i32(QREG_PC, dest);
-    s->is_jmp = DISAS_JUMP;
-}
-
 /* Generate a jump to the address in qreg DEST.  */
 static void gen_jmp(DisasContext *s, TCGv dest)
 {
@@ -817,18 +1216,6 @@  static void gen_jmp(DisasContext *s, TCGv dest)
     s->is_jmp = DISAS_JUMP;
 }

-static void gen_exception(DisasContext *s, uint32_t where, int nr)
-{
-    gen_flush_cc_op(s);
-    gen_jmp_im(s, where);
-    gen_helper_raise_exception(tcg_const_i32(nr));
-}
-
-static inline void gen_addr_fault(DisasContext *s)
-{
-    gen_exception(s, s->insn_pc, EXCP_ADDRESS);
-}
-
 #define SRC_EA(result, opsize, op_sign, addrp) do { \
     result = gen_ea(s, insn, opsize, NULL_QREG, addrp, op_sign ?
EA_LOADS : EA_LOADU); \
     if (IS_NULL_QREG(result)) { \
@@ -865,6 +1252,48 @@  static void gen_jmp_tb(DisasContext *s, int n,
uint32_t dest)
     s->is_jmp = DISAS_TB_JUMP;
 }

+DISAS_INSN(scc_mem)
+{
+    int l1;
+    int cond;
+    TCGv dest;
+
+    l1 = gen_new_label();
+    cond = (insn >> 8) & 0xf;
+    dest = tcg_temp_local_new();
+    tcg_gen_movi_i32(dest, 0);
+    gen_jmpcc(s, cond ^ 1, l1);
+    tcg_gen_movi_i32(dest, 0xff);
+    gen_set_label(l1);
+    DEST_EA(insn, OS_BYTE, dest, NULL);
+    tcg_temp_free(dest);
+}
+
+DISAS_INSN(dbcc)
+{
+    int l1;
+    TCGv reg;
+    TCGv tmp;
+    int16_t offset;
+    uint32_t base;
+
+    reg = DREG(insn, 0);
+    base = s->pc;
+    offset = ldsw_code(s->pc);
+    s->pc += 2;
+    l1 = gen_new_label();
+    gen_jmpcc(s, (insn >> 8) & 0xf, l1);
+
+    tmp = tcg_temp_new();
+    tcg_gen_ext16s_i32(tmp, reg);
+    tcg_gen_addi_i32(tmp, tmp, -1);
+    gen_partset_reg(OS_WORD, reg, tmp);
+    tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, -1, l1);
+    gen_jmp_tb(s, 1, base + offset);
+    gen_set_label(l1);
+    gen_jmp_tb(s, 0, s->pc);
+}
+
 DISAS_INSN(undef_mac)
 {
     gen_exception(s, s->pc - 2, EXCP_LINEA);
@@ -899,38 +1328,45 @@  DISAS_INSN(mulw)
     SRC_EA(src, OS_WORD, sign, NULL);
     tcg_gen_mul_i32(tmp, tmp, src);
     tcg_gen_mov_i32(reg, tmp);
-    /* Unlike m68k, coldfire always clears the overflow bit.  */
-    gen_logic_cc(s, tmp);
+    gen_logic_cc(s, tmp, OS_WORD);
 }

 DISAS_INSN(divw)
 {
-    TCGv reg;
+    TCGv dest;
     TCGv tmp;
     TCGv src;
     int sign;
+    int l1;

     sign = (insn & 0x100) != 0;
-    reg = DREG(insn, 9);
-    if (sign) {
-        tcg_gen_ext16s_i32(QREG_DIV1, reg);
-    } else {
-        tcg_gen_ext16u_i32(QREG_DIV1, reg);
-    }
+
+    /* dest.l / src.w */
+
+    dest = DREG(insn, 9);
+    tcg_gen_mov_i32(QREG_DIV1, dest);
+
     SRC_EA(src, OS_WORD, sign, NULL);
     tcg_gen_mov_i32(QREG_DIV2, src);
+
+    /* div1 / div2 */
+
     if (sign) {
         gen_helper_divs(cpu_env, tcg_const_i32(1));
     } else {
         gen_helper_divu(cpu_env, tcg_const_i32(1));
     }

+    s->cc_op = CC_OP_FLAGS;
+
+    l1 = gen_new_label();
+    gen_jmpcc(s, 9 /* V */, l1);
     tmp = tcg_temp_new();
     src = tcg_temp_new();
     tcg_gen_ext16u_i32(tmp, QREG_DIV1);
     tcg_gen_shli_i32(src, QREG_DIV2, 16);
-    tcg_gen_or_i32(reg, tmp, src);
-    s->cc_op = CC_OP_FLAGS;
+    tcg_gen_or_i32(dest, tmp, src);
+    gen_set_label(l1);
 }

 DISAS_INSN(divl)
@@ -940,10 +1376,27 @@  DISAS_INSN(divl)
     TCGv reg;
     uint16_t ext;

-    ext = lduw_code(s->pc);
-    s->pc += 2;
-    if (ext & 0x87f8) {
-        gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
+    ext = read_im16(s);
+    if (ext & 0x400) {
+        if (!m68k_feature(s->env, M68K_FEATURE_QUAD_MULDIV)) {
+            gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
+            return;
+        }
+        num = DREG(ext, 12);
+        reg = DREG(ext, 0);
+        tcg_gen_mov_i32(QREG_DIV1, num);
+        tcg_gen_mov_i32(QREG_QUADH, reg);
+        SRC_EA(den, OS_LONG, 0, NULL);
+        tcg_gen_mov_i32(QREG_DIV2, den);
+        if (ext & 0x0800) {
+            gen_helper_divs64(cpu_env);
+        } else {
+            gen_helper_divu64(cpu_env);
+        }
+        tcg_gen_mov_i32(num, QREG_DIV1);
+        if (!TCGV_EQUAL(num, reg))
+            tcg_gen_mov_i32(reg, QREG_QUADH);
+        s->cc_op = CC_OP_FLAGS;
         return;
     }
     num = DREG(ext, 12);
@@ -956,16 +1409,90 @@  DISAS_INSN(divl)
     } else {
         gen_helper_divu(cpu_env, tcg_const_i32(0));
     }
-    if ((ext & 7) == ((ext >> 12) & 7)) {
+    if (TCGV_EQUAL(num, reg) ||
+        m68k_feature(s->env, M68K_FEATURE_LONG_MULDIV)) {
         /* div */
-        tcg_gen_mov_i32 (reg, QREG_DIV1);
-    } else {
+        tcg_gen_mov_i32 (num, QREG_DIV1);
+    }
+    if (!TCGV_EQUAL(num, reg)) {
         /* rem */
         tcg_gen_mov_i32 (reg, QREG_DIV2);
     }
     s->cc_op = CC_OP_FLAGS;
 }

+DISAS_INSN(abcd_reg)
+{
+    TCGv src;
+    TCGv dest;
+
+    src = DREG(insn, 0);
+    dest = DREG(insn, 9);
+    gen_helper_abcd_cc(dest, cpu_env, src, dest);
+}
+
+DISAS_INSN(abcd_mem)
+{
+    TCGv src;
+    TCGv addr_src;
+    TCGv dest;
+    TCGv addr_dest;
+
+    addr_src = AREG(insn, 0);
+    tcg_gen_subi_i32(addr_src, addr_src, OS_BYTE);
+    src = gen_load(s, OS_BYTE, addr_src, 0);
+
+    addr_dest = AREG(insn, 9);
+    tcg_gen_subi_i32(addr_dest, addr_dest, OS_BYTE);
+    dest = gen_load(s, OS_BYTE, addr_dest, 0);
+
+    gen_helper_abcd_cc(dest, cpu_env, src, dest);
+
+    gen_store(s, OS_BYTE, addr_dest, dest);
+}
+
+DISAS_INSN(sbcd_reg)
+{
+    TCGv src;
+    TCGv dest;
+
+    src = DREG(insn, 0);
+    dest = DREG(insn, 9);
+    gen_helper_sbcd_cc(dest, cpu_env, src, dest);
+}
+
+DISAS_INSN(sbcd_mem)
+{
+    TCGv src;
+    TCGv addr_src;
+    TCGv dest;
+    TCGv addr_dest;
+
+    addr_src = AREG(insn, 0);
+    tcg_gen_subi_i32(addr_src, addr_src, OS_BYTE);
+    src = gen_load(s, OS_BYTE, addr_src, 0);
+
+    addr_dest = AREG(insn, 9);
+    tcg_gen_subi_i32(addr_dest, addr_dest, OS_BYTE);
+    dest = gen_load(s, OS_BYTE, addr_dest, 0);
+
+    gen_helper_sbcd_cc(dest, cpu_env, src, dest);
+
+    gen_store(s, OS_BYTE, addr_dest, dest);
+}
+
+DISAS_INSN(nbcd)
+{
+    TCGv dest;
+    TCGv addr;
+
+    SRC_EA(dest, OS_BYTE, -1, &addr);
+
+    gen_helper_sbcd_cc(dest, cpu_env, dest, tcg_const_i32(0));
+
+    DEST_EA(insn, OS_BYTE, dest, &addr);
+}
+
 DISAS_INSN(addsub)
 {
     TCGv reg;
@@ -974,31 +1501,33 @@  DISAS_INSN(addsub)
     TCGv tmp;
     TCGv addr;
     int add;
+    int opsize;

     add = (insn & 0x4000) != 0;
+    opsize = insn_opsize(insn, 6);
     reg = DREG(insn, 9);
     dest = tcg_temp_new();
     if (insn & 0x100) {
-        SRC_EA(tmp, OS_LONG, 0, &addr);
+        SRC_EA(tmp, opsize, -1, &addr);
         src = reg;
     } else {
         tmp = reg;
-        SRC_EA(src, OS_LONG, 0, NULL);
+        SRC_EA(src, opsize, -1, NULL);
     }
     if (add) {
         tcg_gen_add_i32(dest, tmp, src);
-        gen_helper_xflag_lt(QREG_CC_X, dest, src);
-        s->cc_op = CC_OP_ADD;
+        SET_X_FLAG(opsize, dest, src);
+        SET_CC_OP(opsize, ADD);
     } else {
-        gen_helper_xflag_lt(QREG_CC_X, tmp, src);
+        SET_X_FLAG(opsize, tmp, src);
         tcg_gen_sub_i32(dest, tmp, src);
-        s->cc_op = CC_OP_SUB;
+        SET_CC_OP(opsize, SUB);
     }
     gen_update_cc_add(dest, src);
     if (insn & 0x100) {
-        DEST_EA(insn, OS_LONG, dest, &addr);
+        DEST_EA(insn, opsize, dest, &addr);
     } else {
-        tcg_gen_mov_i32(reg, dest);
+        gen_partset_reg(opsize, reg, dest);
     }
 }

@@ -1070,7 +1599,7 @@  DISAS_INSN(sats)
     reg = DREG(insn, 0);
     gen_flush_flags(s);
     gen_helper_sats(reg, reg, QREG_CC_DEST);
-    gen_logic_cc(s, reg);
+    gen_logic_cc(s, reg, OS_LONG);
 }

 static void gen_push(DisasContext *s, TCGv val)
@@ -1091,9 +1620,10 @@  DISAS_INSN(movem)
     TCGv reg;
     TCGv tmp;
     int is_load;
+    int opsize;
+    int32_t incr;

-    mask = lduw_code(s->pc);
-    s->pc += 2;
+    mask = read_im16(s);
     tmp = gen_lea(s, insn, OS_LONG);
     if (IS_NULL_QREG(tmp)) {
         gen_addr_fault(s);
@@ -1102,21 +1632,40 @@  DISAS_INSN(movem)
     addr = tcg_temp_new();
     tcg_gen_mov_i32(addr, tmp);
     is_load = ((insn & 0x0400) != 0);
-    for (i = 0; i < 16; i++, mask >>= 1) {
-        if (mask & 1) {
-            if (i < 8)
-                reg = DREG(i, 0);
-            else
-                reg = AREG(i, 0);
-            if (is_load) {
-                tmp = gen_load(s, OS_LONG, addr, 0);
-                tcg_gen_mov_i32(reg, tmp);
-            } else {
-                gen_store(s, OS_LONG, addr, reg);
-            }
-            if (mask != 1)
-                tcg_gen_addi_i32(addr, addr, 4);
-        }
+    opsize = (insn & 0x40) != 0 ? OS_LONG : OS_WORD;
+    incr = opsize_bytes(opsize);
+    if (!is_load && (insn & 070) == 040) {
+       for (i = 15; i >= 0; i--, mask >>= 1) {
+           if (mask & 1) {
+               if (i < 8)
+                   reg = DREG(i, 0);
+               else
+                   reg = AREG(i, 0);
+               gen_store(s, opsize, addr, reg);
+               if (mask != 1)
+                   tcg_gen_subi_i32(addr, addr, incr);
+           }
+       }
+       tcg_gen_mov_i32(AREG(insn, 0), addr);
+    } else {
+       for (i = 0; i < 16; i++, mask >>= 1) {
+           if (mask & 1) {
+               if (i < 8)
+                   reg = DREG(i, 0);
+               else
+                   reg = AREG(i, 0);
+               if (is_load) {
+                   tmp = gen_load(s, opsize, addr, 1);
+                   tcg_gen_mov_i32(reg, tmp);
+               } else {
+                   gen_store(s, opsize, addr, reg);
+               }
+               if (mask != 1 || (insn & 070) == 030)
+                   tcg_gen_addi_i32(addr, addr, incr);
+           }
+       }
+       if ((insn & 070) == 030)
+           tcg_gen_mov_i32(AREG(insn, 0), addr);
     }
 }

@@ -1136,8 +1685,7 @@  DISAS_INSN(bitop_im)
         opsize = OS_LONG;
     op = (insn >> 6) & 3;

-    bitnum = lduw_code(s->pc);
-    s->pc += 2;
+    bitnum = read_im16(s);
     if (bitnum & 0xff00) {
         disas_undef(s, insn);
         return;
@@ -1189,50 +1737,128 @@  DISAS_INSN(arith_im)
     TCGv src1;
     TCGv dest;
     TCGv addr;
+    int opsize;

     op = (insn >> 9) & 7;
-    SRC_EA(src1, OS_LONG, 0, (op == 6) ? NULL : &addr);
-    im = read_im32(s);
+    opsize = insn_opsize(insn, 6);
+    switch (opsize) {
+    case OS_BYTE:
+        im = read_im8(s);
+        break;
+    case OS_WORD:
+        im = read_im16(s);
+        break;
+    case OS_LONG:
+        im = read_im32(s);
+        break;
+    default:
+       abort();
+    }
+    SRC_EA(src1, opsize, -1, (op == 6) ? NULL : &addr);
     dest = tcg_temp_new();
     switch (op) {
     case 0: /* ori */
         tcg_gen_ori_i32(dest, src1, im);
-        gen_logic_cc(s, dest);
+        gen_logic_cc(s, dest, opsize);
         break;
     case 1: /* andi */
         tcg_gen_andi_i32(dest, src1, im);
-        gen_logic_cc(s, dest);
+        gen_logic_cc(s, dest, opsize);
         break;
     case 2: /* subi */
         tcg_gen_mov_i32(dest, src1);
-        gen_helper_xflag_lt(QREG_CC_X, dest, tcg_const_i32(im));
+        SET_X_FLAG(opsize, dest, tcg_const_i32(im));
         tcg_gen_subi_i32(dest, dest, im);
         gen_update_cc_add(dest, tcg_const_i32(im));
-        s->cc_op = CC_OP_SUB;
+        SET_CC_OP(opsize, SUB);
         break;
     case 3: /* addi */
         tcg_gen_mov_i32(dest, src1);
         tcg_gen_addi_i32(dest, dest, im);
         gen_update_cc_add(dest, tcg_const_i32(im));
-        gen_helper_xflag_lt(QREG_CC_X, dest, tcg_const_i32(im));
-        s->cc_op = CC_OP_ADD;
+        SET_X_FLAG(opsize, dest, tcg_const_i32(im));
+	SET_CC_OP(opsize, ADD);
         break;
     case 5: /* eori */
         tcg_gen_xori_i32(dest, src1, im);
-        gen_logic_cc(s, dest);
+        gen_logic_cc(s, dest, opsize);
         break;
     case 6: /* cmpi */
         tcg_gen_mov_i32(dest, src1);
         tcg_gen_subi_i32(dest, dest, im);
         gen_update_cc_add(dest, tcg_const_i32(im));
-        s->cc_op = CC_OP_SUB;
+        SET_CC_OP(opsize, SUB);
         break;
     default:
         abort();
     }
     if (op != 6) {
-        DEST_EA(insn, OS_LONG, dest, &addr);
+        DEST_EA(insn, opsize, dest, &addr);
+    }
+}
+
+DISAS_INSN(cas)
+{
+    int opsize;
+    TCGv dest;
+    TCGv tmp;
+    TCGv cmp;
+    TCGv update;
+    TCGv taddr;
+    TCGv addr;
+    TCGv res;
+    uint16_t ext;
+    int l1, l2;
+
+    if ((insn & 0x3f) == 0x3c) {
+        /* CAS2: Not yet implemented */
+        gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
+    }
+
+    switch((insn >> 9) & 3) {
+    case 1:
+        opsize = OS_BYTE;
+        break;
+    case 2:
+        opsize = OS_WORD;
+        break;
+    case 3:
+        opsize = OS_LONG;
+        break;
+    default:
+        abort();
+    }
+
+    ext = read_im16(s);
+    taddr = gen_lea(s, insn, opsize);
+    if (IS_NULL_QREG(taddr)) {
+        gen_addr_fault(s);
+        return;
     }
+
+    cmp = DREG(ext, 0);
+    update = DREG(ext, 6);
+    tmp = gen_load(s, opsize, taddr, 0);
+    dest = tcg_temp_local_new();
+    tcg_gen_mov_i32(dest, tmp);
+    addr = tcg_temp_local_new ();
+    tcg_gen_mov_i32(addr, taddr);
+
+    res = tcg_temp_new();
+    tcg_gen_sub_i32(res, dest, cmp);
+    gen_logic_cc(s, res, opsize);
+
+    l1 = gen_new_label();
+    l2 = gen_new_label();
+
+    gen_jmpcc(s, 6 /* !Z */, l1);
+    gen_store(s, opsize, addr, update);
+    tcg_gen_br(l2);
+    gen_set_label(l1);
+    tcg_gen_mov_i32(cmp, dest);
+    gen_set_label(l2);
+    tcg_temp_free(dest);
+    tcg_temp_free(addr);
 }

 DISAS_INSN(byterev)
@@ -1276,17 +1902,34 @@  DISAS_INSN(move)
         dest_ea = ((insn >> 9) & 7) | (op << 3);
         DEST_EA(dest_ea, opsize, src, NULL);
         /* This will be correct because loads sign extend.  */
-        gen_logic_cc(s, src);
+        gen_logic_cc(s, src, opsize);
     }
 }

 DISAS_INSN(negx)
 {
-    TCGv reg;
+    TCGv src;
+    TCGv dest;
+    TCGv addr;
+    int opsize;

+    opsize = insn_opsize(insn, 6);
     gen_flush_flags(s);
-    reg = DREG(insn, 0);
-    gen_helper_subx_cc(reg, cpu_env, tcg_const_i32(0), reg);
+    SRC_EA(src, opsize, -1, &addr);
+    dest = tcg_temp_new();
+    switch(opsize) {
+    case OS_BYTE:
+        gen_helper_subx8_cc(dest, cpu_env, tcg_const_i32(0), src);
+        break;
+    case OS_WORD:
+        gen_helper_subx16_cc(dest, cpu_env, tcg_const_i32(0), src);
+        break;
+    case OS_LONG:
+        gen_helper_subx32_cc(dest, cpu_env, tcg_const_i32(0), src);
+        break;
+    }
+    s->cc_op = CC_OP_FLAGS;
+    DEST_EA(insn, opsize, dest, &addr);
 }

 DISAS_INSN(lea)
@@ -1307,21 +1950,9 @@  DISAS_INSN(clr)
 {
     int opsize;

-    switch ((insn >> 6) & 3) {
-    case 0: /* clr.b */
-        opsize = OS_BYTE;
-        break;
-    case 1: /* clr.w */
-        opsize = OS_WORD;
-        break;
-    case 2: /* clr.l */
-        opsize = OS_LONG;
-        break;
-    default:
-        abort();
-    }
+    opsize = insn_opsize(insn, 6);
     DEST_EA(insn, opsize, tcg_const_i32(0), NULL);
-    gen_logic_cc(s, tcg_const_i32(0));
+    gen_logic_cc(s, tcg_const_i32(0), opsize);
 }

 static TCGv gen_get_ccr(DisasContext *s)
@@ -1347,17 +1978,19 @@  DISAS_INSN(move_from_ccr)

 DISAS_INSN(neg)
 {
-    TCGv reg;
     TCGv src1;
+    TCGv dest;
+    TCGv addr;
+    int opsize;

-    reg = DREG(insn, 0);
-    src1 = tcg_temp_new();
-    tcg_gen_mov_i32(src1, reg);
-    tcg_gen_neg_i32(reg, src1);
-    s->cc_op = CC_OP_SUB;
-    gen_update_cc_add(reg, src1);
-    gen_helper_xflag_lt(QREG_CC_X, tcg_const_i32(0), src1);
-    s->cc_op = CC_OP_SUB;
+    opsize = insn_opsize(insn, 6);
+    SRC_EA(src1, opsize, -1, &addr);
+    dest = tcg_temp_new();
+    tcg_gen_neg_i32(dest, src1);
+    SET_CC_OP(opsize, SUB);
+    gen_update_cc_add(dest, src1);
+    SET_X_FLAG(opsize, tcg_const_i32(0), dest);
+    DEST_EA(insn, opsize, dest, &addr);
 }

 static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only)
@@ -1389,8 +2022,7 @@  static void gen_set_sr(DisasContext *s, uint16_t
insn, int ccr_only)
     else if ((insn & 0x3f) == 0x3c)
       {
         uint16_t val;
-        val = lduw_code(s->pc);
-        s->pc += 2;
+        val = read_im16(s);
         gen_set_sr_im(s, val, ccr_only);
       }
     else
@@ -1404,11 +2036,17 @@  DISAS_INSN(move_to_ccr)

 DISAS_INSN(not)
 {
-    TCGv reg;
+    TCGv src1;
+    TCGv dest;
+    TCGv addr;
+    int opsize;

-    reg = DREG(insn, 0);
-    tcg_gen_not_i32(reg, reg);
-    gen_logic_cc(s, reg);
+    opsize = insn_opsize(insn, 6);
+    SRC_EA(src1, opsize, -1, &addr);
+    dest = tcg_temp_new();
+    tcg_gen_not_i32(dest, src1);
+    DEST_EA(insn, opsize, dest, &addr);
+    gen_logic_cc(s, dest, opsize);
 }

 DISAS_INSN(swap)
@@ -1423,7 +2061,12 @@  DISAS_INSN(swap)
     tcg_gen_shli_i32(src1, reg, 16);
     tcg_gen_shri_i32(src2, reg, 16);
     tcg_gen_or_i32(reg, src1, src2);
-    gen_logic_cc(s, reg);
+    gen_logic_cc(s, reg, OS_LONG);
+}
+
+DISAS_INSN(bkpt)
+{
+    gen_exception(s, s->pc - 2, EXCP_DEBUG);
 }

 DISAS_INSN(pea)
@@ -1455,7 +2098,7 @@  DISAS_INSN(ext)
         gen_partset_reg(OS_WORD, reg, tmp);
     else
         tcg_gen_mov_i32(reg, tmp);
-    gen_logic_cc(s, tmp);
+    gen_logic_cc(s, tmp, OS_LONG);
 }

 DISAS_INSN(tst)
@@ -1463,21 +2106,9 @@  DISAS_INSN(tst)
     int opsize;
     TCGv tmp;

-    switch ((insn >> 6) & 3) {
-    case 0: /* tst.b */
-        opsize = OS_BYTE;
-        break;
-    case 1: /* tst.w */
-        opsize = OS_WORD;
-        break;
-    case 2: /* tst.l */
-        opsize = OS_LONG;
-        break;
-    default:
-        abort();
-    }
-    SRC_EA(tmp, opsize, 1, NULL);
-    gen_logic_cc(s, tmp);
+    opsize = insn_opsize(insn, 6);
+    SRC_EA(tmp, opsize, -1, NULL);
+    gen_logic_cc(s, tmp, opsize);
 }

 DISAS_INSN(pulse)
@@ -1487,6 +2118,7 @@  DISAS_INSN(pulse)

 DISAS_INSN(illegal)
 {
+    fprintf(stderr,"test\n");
     gen_exception(s, s->pc - 2, EXCP_ILLEGAL);
 }

@@ -1499,7 +2131,7 @@  DISAS_INSN(tas)

     dest = tcg_temp_new();
     SRC_EA(src1, OS_BYTE, 1, &addr);
-    gen_logic_cc(s, src1);
+    gen_logic_cc(s, src1, OS_BYTE);
     tcg_gen_ori_i32(dest, src1, 0x80);
     DEST_EA(insn, OS_BYTE, dest, &addr);
 }
@@ -1510,22 +2142,43 @@  DISAS_INSN(mull)
     TCGv reg;
     TCGv src1;
     TCGv dest;
+    TCGv regh;

     /* The upper 32 bits of the product are discarded, so
        muls.l and mulu.l are functionally equivalent.  */
-    ext = lduw_code(s->pc);
-    s->pc += 2;
-    if (ext & 0x87ff) {
-        gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
-        return;
+    ext = read_im16(s);
+    if (ext & 0x400) {
+       if (!m68k_feature(s->env, M68K_FEATURE_QUAD_MULDIV)) {
+           gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
+           return;
+       }
+       reg = DREG(ext, 12);
+       regh = DREG(ext, 0);
+       SRC_EA(src1, OS_LONG, 0, NULL);
+       dest = tcg_temp_new();
+       if (ext & 0x800)
+           gen_helper_muls64(dest, cpu_env, src1, reg);
+       else
+           gen_helper_mulu64(dest, cpu_env, src1, reg);
+       tcg_gen_mov_i32(reg, dest);
+       tcg_gen_mov_i32(regh, QREG_QUADH);
+       s->cc_op = CC_OP_FLAGS;
+       return;
     }
     reg = DREG(ext, 12);
     SRC_EA(src1, OS_LONG, 0, NULL);
     dest = tcg_temp_new();
-    tcg_gen_mul_i32(dest, src1, reg);
+    if (m68k_feature(s->env, M68K_FEATURE_M68000)) {
+       if (ext & 0x800)
+           gen_helper_muls32_cc(dest, cpu_env, src1, reg);
+       else
+           gen_helper_mulu32_cc(dest, cpu_env, src1, reg);
+       s->cc_op = CC_OP_FLAGS;
+    } else {
+       tcg_gen_mul_i32(dest, src1, reg);
+    }
+    gen_logic_cc(s, dest, OS_LONG);
     tcg_gen_mov_i32(reg, dest);
-    /* Unlike m68k, coldfire always clears the overflow bit.  */
-    gen_logic_cc(s, dest);
 }

 DISAS_INSN(link)
@@ -1534,8 +2187,23 @@  DISAS_INSN(link)
     TCGv reg;
     TCGv tmp;

-    offset = ldsw_code(s->pc);
-    s->pc += 2;
+    offset = read_im16(s);
+    reg = AREG(insn, 0);
+    tmp = tcg_temp_new();
+    tcg_gen_subi_i32(tmp, QREG_SP, 4);
+    gen_store(s, OS_LONG, tmp, reg);
+    if ((insn & 7) != 7)
+        tcg_gen_mov_i32(reg, tmp);
+    tcg_gen_addi_i32(QREG_SP, tmp, offset);
+}
+
+DISAS_INSN(linkl)
+{
+    int32_t offset;
+    TCGv reg;
+    TCGv tmp;
+
+    offset = read_im32(s);
     reg = AREG(insn, 0);
     tmp = tcg_temp_new();
     tcg_gen_subi_i32(tmp, QREG_SP, 4);
@@ -1597,8 +2265,14 @@  DISAS_INSN(addsubq)
     TCGv dest;
     int val;
     TCGv addr;
+    int opsize;

-    SRC_EA(src1, OS_LONG, 0, &addr);
+    if ((insn & 070) == 010) {
+        /* Operation on address register is always long.  */
+        opsize = OS_LONG;
+    } else
+        opsize = insn_opsize(insn, 6);
+    SRC_EA(src1, opsize, -1, &addr);
     val = (insn >> 9) & 7;
     if (val == 0)
         val = 8;
@@ -1615,17 +2289,17 @@  DISAS_INSN(addsubq)
     } else {
         src2 = tcg_const_i32(val);
         if (insn & 0x0100) {
-            gen_helper_xflag_lt(QREG_CC_X, dest, src2);
+            SET_X_FLAG(opsize, dest, src2);
             tcg_gen_subi_i32(dest, dest, val);
-            s->cc_op = CC_OP_SUB;
+            SET_CC_OP(opsize, SUB);
         } else {
             tcg_gen_addi_i32(dest, dest, val);
-            gen_helper_xflag_lt(QREG_CC_X, dest, src2);
-            s->cc_op = CC_OP_ADD;
+            SET_X_FLAG(opsize, dest, src2);
+            SET_CC_OP(opsize, ADD);
         }
         gen_update_cc_add(dest, src2);
     }
-    DEST_EA(insn, OS_LONG, dest, &addr);
+    DEST_EA(insn, opsize, dest, &addr);
 }

 DISAS_INSN(tpf)
@@ -1684,7 +2358,7 @@  DISAS_INSN(moveq)

     val = (int8_t)insn;
     tcg_gen_movi_i32(DREG(insn, 9), val);
-    gen_logic_cc(s, tcg_const_i32(val));
+    gen_logic_cc(s, tcg_const_i32(val), OS_LONG);
 }

 DISAS_INSN(mvzs)
@@ -1700,7 +2374,7 @@  DISAS_INSN(mvzs)
     SRC_EA(src, opsize, (insn & 0x80) == 0, NULL);
     reg = DREG(insn, 9);
     tcg_gen_mov_i32(reg, src);
-    gen_logic_cc(s, src);
+    gen_logic_cc(s, src, opsize);
 }

 DISAS_INSN(or)
@@ -1709,19 +2383,21 @@  DISAS_INSN(or)
     TCGv dest;
     TCGv src;
     TCGv addr;
+    int opsize;

+    opsize = insn_opsize(insn, 6);
     reg = DREG(insn, 9);
     dest = tcg_temp_new();
     if (insn & 0x100) {
-        SRC_EA(src, OS_LONG, 0, &addr);
+        SRC_EA(src, opsize, -1, &addr);
         tcg_gen_or_i32(dest, src, reg);
-        DEST_EA(insn, OS_LONG, dest, &addr);
+        DEST_EA(insn, opsize, dest, &addr);
     } else {
-        SRC_EA(src, OS_LONG, 0, NULL);
+        SRC_EA(src, opsize, -1, NULL);
         tcg_gen_or_i32(dest, src, reg);
-        tcg_gen_mov_i32(reg, dest);
+        gen_partset_reg(opsize, reg, dest);
     }
-    gen_logic_cc(s, dest);
+    gen_logic_cc(s, dest, opsize);
 }

 DISAS_INSN(suba)
@@ -1729,65 +2405,99 @@  DISAS_INSN(suba)
     TCGv src;
     TCGv reg;

-    SRC_EA(src, OS_LONG, 0, NULL);
+    SRC_EA(src, (insn & 0x100) ? OS_LONG : OS_WORD, -1, NULL);
     reg = AREG(insn, 9);
     tcg_gen_sub_i32(reg, reg, src);
 }

-DISAS_INSN(subx)
+DISAS_INSN(subx_reg)
 {
     TCGv reg;
     TCGv src;
+    int opsize;
+
+    opsize = insn_opsize(insn, 6);

     gen_flush_flags(s);
     reg = DREG(insn, 9);
     src = DREG(insn, 0);
-    gen_helper_subx_cc(reg, cpu_env, reg, src);
-}
-
-DISAS_INSN(mov3q)
-{
-    TCGv src;
-    int val;
-
-    val = (insn >> 9) & 7;
+    switch(opsize) {
+    case OS_BYTE:
+        gen_helper_subx8_cc(reg, cpu_env, reg, src);
+        break;
+    case OS_WORD:
+        gen_helper_subx16_cc(reg, cpu_env, reg, src);
+        break;
+    case OS_LONG:
+        gen_helper_subx32_cc(reg, cpu_env, reg, src);
+        break;
+    }
+    s->cc_op = CC_OP_FLAGS;
+}
+
+DISAS_INSN(subx_mem)
+{
+    TCGv src;
+    TCGv addr_src;
+    TCGv reg;
+    TCGv addr_reg;
+    int opsize;
+
+    opsize = insn_opsize(insn, 6);
+
+    gen_flush_flags(s);
+
+    addr_src = AREG(insn, 0);
+    tcg_gen_subi_i32(addr_src, addr_src, opsize);
+    src = gen_load(s, opsize, addr_src, 0);
+
+    addr_reg = AREG(insn, 9);
+    tcg_gen_subi_i32(addr_reg, addr_reg, opsize);
+    reg = gen_load(s, opsize, addr_reg, 0);
+
+    switch(opsize) {
+    case OS_BYTE:
+        gen_helper_subx8_cc(reg, cpu_env, reg, src);
+        break;
+    case OS_WORD:
+        gen_helper_subx16_cc(reg, cpu_env, reg, src);
+        break;
+    case OS_LONG:
+        gen_helper_subx32_cc(reg, cpu_env, reg, src);
+        break;
+    }
+    s->cc_op = CC_OP_FLAGS;
+
+    gen_store(s, opsize, addr_reg, reg);
+}
+
+DISAS_INSN(mov3q)
+{
+    TCGv src;
+    int val;
+
+    val = (insn >> 9) & 7;
     if (val == 0)
         val = -1;
     src = tcg_const_i32(val);
-    gen_logic_cc(s, src);
+    gen_logic_cc(s, src, OS_LONG);
     DEST_EA(insn, OS_LONG, src, NULL);
 }

 DISAS_INSN(cmp)
 {
-    int op;
     TCGv src;
     TCGv reg;
     TCGv dest;
     int opsize;

-    op = (insn >> 6) & 3;
-    switch (op) {
-    case 0: /* cmp.b */
-        opsize = OS_BYTE;
-        s->cc_op = CC_OP_CMPB;
-        break;
-    case 1: /* cmp.w */
-        opsize = OS_WORD;
-        s->cc_op = CC_OP_CMPW;
-        break;
-    case 2: /* cmp.l */
-        opsize = OS_LONG;
-        s->cc_op = CC_OP_SUB;
-        break;
-    default:
-        abort();
-    }
-    SRC_EA(src, opsize, 1, NULL);
+    opsize = insn_opsize(insn, 6);
+    SRC_EA(src, opsize, -1, NULL);
     reg = DREG(insn, 9);
     dest = tcg_temp_new();
     tcg_gen_sub_i32(dest, reg, src);
     gen_update_cc_add(dest, src);
+    SET_CC_OP(opsize, SUB);
 }

 DISAS_INSN(cmpa)
@@ -1807,7 +2517,7 @@  DISAS_INSN(cmpa)
     dest = tcg_temp_new();
     tcg_gen_sub_i32(dest, reg, src);
     gen_update_cc_add(dest, src);
-    s->cc_op = CC_OP_SUB;
+    SET_CC_OP(OS_LONG, SUB);
 }

 DISAS_INSN(eor)
@@ -1816,13 +2526,34 @@  DISAS_INSN(eor)
     TCGv reg;
     TCGv dest;
     TCGv addr;
+    int opsize;
+
+    opsize = insn_opsize(insn, 6);
+
+    if (((insn >> 3) & 7) == 1 ) {
+        /* cmpm */
+        reg = AREG(insn, 0);
+        src = gen_load(s, opsize, reg, 1);
+        tcg_gen_addi_i32(reg, reg, opsize_bytes(opsize));
+
+        reg = AREG(insn, 9);
+        dest = gen_load(s, opsize, reg, 1);
+        tcg_gen_addi_i32(reg, reg, opsize_bytes(opsize));

-    SRC_EA(src, OS_LONG, 0, &addr);
+        reg = tcg_temp_new();
+        tcg_gen_sub_i32(reg, dest, src);
+        gen_update_cc_add(reg, src);
+        SET_CC_OP(opsize, SUB);
+
+        return;
+    }
+
+    SRC_EA(src, opsize, -1, &addr);
     reg = DREG(insn, 9);
     dest = tcg_temp_new();
     tcg_gen_xor_i32(dest, src, reg);
-    gen_logic_cc(s, dest);
-    DEST_EA(insn, OS_LONG, dest, &addr);
+    gen_logic_cc(s, dest, opsize);
+    DEST_EA(insn, opsize, dest, &addr);
 }

 DISAS_INSN(and)
@@ -1831,19 +2562,52 @@  DISAS_INSN(and)
     TCGv reg;
     TCGv dest;
     TCGv addr;
+    int opsize;
+    int exg_mode;

-    reg = DREG(insn, 9);
     dest = tcg_temp_new();
+
+    /* exg */
+
+    exg_mode = insn & 0x1f8;
+    if (exg_mode == 0x140) {
+        /* exchange Dx and Dy */
+        src = DREG(insn, 9);
+        reg = DREG(insn, 0);
+        tcg_gen_mov_i32(dest, src);
+        tcg_gen_mov_i32(src, reg);
+        tcg_gen_mov_i32(reg, dest);
+        return;
+    } else if (exg_mode == 0x148) {
+        /* exchange Ax and Ay */
+        src = AREG(insn, 9);
+        reg = AREG(insn, 0);
+        tcg_gen_mov_i32(dest, src);
+        tcg_gen_mov_i32(src, reg);
+        tcg_gen_mov_i32(reg, dest);
+        return;
+    } else if (exg_mode == 0x188) {
+        /* exchange Dx and Ay */
+        src = DREG(insn, 9);
+        reg = AREG(insn, 0);
+        tcg_gen_mov_i32(dest, src);
+        tcg_gen_mov_i32(src, reg);
+        tcg_gen_mov_i32(reg, dest);
+        return;
+    }
+    /* and */
+    opsize = insn_opsize(insn, 6);
+    reg = DREG(insn, 9);
     if (insn & 0x100) {
-        SRC_EA(src, OS_LONG, 0, &addr);
+        SRC_EA(src, opsize, -1, &addr);
         tcg_gen_and_i32(dest, src, reg);
-        DEST_EA(insn, OS_LONG, dest, &addr);
+        DEST_EA(insn, opsize, dest, &addr);
     } else {
-        SRC_EA(src, OS_LONG, 0, NULL);
+        SRC_EA(src, opsize, -1, NULL);
         tcg_gen_and_i32(dest, src, reg);
-        tcg_gen_mov_i32(reg, dest);
+        gen_partset_reg(opsize, reg, dest);
     }
-    gen_logic_cc(s, dest);
+    gen_logic_cc(s, dest, opsize);
 }

 DISAS_INSN(adda)
@@ -1851,24 +2615,138 @@  DISAS_INSN(adda)
     TCGv src;
     TCGv reg;

-    SRC_EA(src, OS_LONG, 0, NULL);
+    SRC_EA(src, (insn & 0x100) ? OS_LONG : OS_WORD, -1, NULL);
     reg = AREG(insn, 9);
     tcg_gen_add_i32(reg, reg, src);
 }

-DISAS_INSN(addx)
+DISAS_INSN(addx_reg)
 {
     TCGv reg;
     TCGv src;
+    int opsize;
+
+    opsize = insn_opsize(insn, 6);

     gen_flush_flags(s);
     reg = DREG(insn, 9);
     src = DREG(insn, 0);
-    gen_helper_addx_cc(reg, cpu_env, reg, src);
+    switch(opsize) {
+    case OS_BYTE:
+        gen_helper_addx8_cc(reg, cpu_env, reg, src);
+        break;
+    case OS_WORD:
+        gen_helper_addx16_cc(reg, cpu_env, reg, src);
+        break;
+    case OS_LONG:
+        gen_helper_addx32_cc(reg, cpu_env, reg, src);
+        break;
+    }
+    s->cc_op = CC_OP_FLAGS;
+}
+
+DISAS_INSN(addx_mem)
+{
+    TCGv src;
+    TCGv addr_src;
+    TCGv reg;
+    TCGv addr_reg;
+    int opsize;
+
+    opsize = insn_opsize(insn, 6);
+
+    gen_flush_flags(s);
+
+    addr_src = AREG(insn, 0);
+    tcg_gen_subi_i32(addr_src, addr_src, opsize);
+    src = gen_load(s, opsize, addr_src, 0);
+
+    addr_reg = AREG(insn, 9);
+    tcg_gen_subi_i32(addr_reg, addr_reg, opsize);
+    reg = gen_load(s, opsize, addr_reg, 0);
+
+    switch(opsize) {
+    case OS_BYTE:
+        gen_helper_addx8_cc(reg, cpu_env, reg, src);
+        break;
+    case OS_WORD:
+        gen_helper_addx16_cc(reg, cpu_env, reg, src);
+        break;
+    case OS_LONG:
+        gen_helper_addx32_cc(reg, cpu_env, reg, src);
+        break;
+    }
     s->cc_op = CC_OP_FLAGS;
+
+    gen_store(s, opsize, addr_reg, reg);
+}
+
+/* TODO: This could be implemented without helper functions.  */
+DISAS_INSN(shift8_im)
+{
+    TCGv reg;
+    int tmp;
+    TCGv shift;
+    TCGv dest;
+
+    reg = DREG(insn, 0);
+    tmp = (insn >> 9) & 7;
+    if (tmp == 0)
+        tmp = 8;
+    shift = tcg_const_i32(tmp);
+    dest = tcg_temp_new_i32();
+    /* No need to flush flags becuse we know we will set C flag.  */
+    if (insn & 0x100) {
+        if (insn & 8) {
+            gen_helper_shl8_cc(dest, cpu_env, reg, shift);
+        } else {
+            gen_helper_sal8_cc(dest, cpu_env, reg, shift);
+        }
+    } else {
+        if (insn & 8) {
+            gen_helper_shr8_cc(dest, cpu_env, reg, shift);
+        } else {
+            gen_helper_sar8_cc(dest, cpu_env, reg, shift);
+        }
+    }
+    s->cc_op = CC_OP_SHIFTB;
+    gen_partset_reg(OS_BYTE, reg, dest);
 }

 /* TODO: This could be implemented without helper functions.  */
+DISAS_INSN(shift16_im)
+{
+    TCGv reg;
+    int tmp;
+    TCGv shift;
+    TCGv dest;
+
+    reg = DREG(insn, 0);
+    tmp = (insn >> 9) & 7;
+    if (tmp == 0)
+        tmp = 8;
+    shift = tcg_const_i32(tmp);
+    dest = tcg_temp_new_i32();
+    /* No need to flush flags becuse we know we will set C flag.  */
+    if (insn & 0x100) {
+        if (insn & 8) {
+            gen_helper_shl16_cc(dest, cpu_env, reg, shift);
+        } else {
+            gen_helper_sal16_cc(dest, cpu_env, reg, shift);
+        }
+    } else {
+        if (insn & 8) {
+            gen_helper_shr16_cc(dest, cpu_env, reg, shift);
+        } else {
+            gen_helper_sar16_cc(dest, cpu_env, reg, shift);
+        }
+    }
+    s->cc_op = CC_OP_SHIFTW;
+    gen_partset_reg(OS_WORD, reg, dest);
+}
+
+
+/* TODO: This could be implemented without helper functions.  */
 DISAS_INSN(shift_im)
 {
     TCGv reg;
@@ -1882,43 +2760,662 @@  DISAS_INSN(shift_im)
     shift = tcg_const_i32(tmp);
     /* No need to flush flags becuse we know we will set C flag.  */
     if (insn & 0x100) {
-        gen_helper_shl_cc(reg, cpu_env, reg, shift);
+        if (insn & 8) {
+            gen_helper_shl32_cc(reg, cpu_env, reg, shift);
+        } else {
+            gen_helper_sal32_cc(reg, cpu_env, reg, shift);
+        }
+    } else {
+        if (insn & 8) {
+            gen_helper_shr32_cc(reg, cpu_env, reg, shift);
+        } else {
+            gen_helper_sar32_cc(reg, cpu_env, reg, shift);
+        }
+    }
+    s->cc_op = CC_OP_SHIFT;
+}
+
+DISAS_INSN(shift8_reg)
+{
+    TCGv reg;
+    TCGv shift;
+    TCGv dest;
+    TCGv tmp;
+
+    reg = DREG(insn, 0);
+    shift = DREG(insn, 9);
+    tmp = tcg_temp_new_i32();
+    tcg_gen_andi_i32(tmp, shift, 63);
+    dest = tcg_temp_new_i32();
+    /* Shift by zero leaves C flag unmodified.   */
+    gen_flush_flags(s);
+    if (insn & 0x100) {
+        if (insn & 8) {
+            gen_helper_shl8_cc(dest, cpu_env, reg, tmp);
+        } else {
+            gen_helper_sal8_cc(dest, cpu_env, reg, tmp);
+        }
+    } else {
+        if (insn & 8) {
+            gen_helper_shr8_cc(dest, cpu_env, reg, tmp);
+        } else {
+            gen_helper_sar8_cc(dest, cpu_env, reg, tmp);
+        }
+    }
+    s->cc_op = CC_OP_SHIFTB;
+    gen_partset_reg(OS_BYTE, reg, dest);
+}
+
+DISAS_INSN(shift16_reg)
+{
+    TCGv reg;
+    TCGv shift;
+    TCGv dest;
+    TCGv tmp;
+
+    reg = DREG(insn, 0);
+    shift = DREG(insn, 9);
+    tmp = tcg_temp_new_i32();
+    tcg_gen_andi_i32(tmp, shift, 63);
+    dest = tcg_temp_new_i32();
+    /* Shift by zero leaves C flag unmodified.   */
+    gen_flush_flags(s);
+    if (insn & 0x100) {
+        if (insn & 8) {
+            gen_helper_shl16_cc(dest, cpu_env, reg, tmp);
+        } else {
+            gen_helper_sal16_cc(dest, cpu_env, reg, tmp);
+        }
+    } else {
+        if (insn & 8) {
+            gen_helper_shr16_cc(dest, cpu_env, reg, tmp);
+        } else {
+            gen_helper_sar16_cc(dest, cpu_env, reg, tmp);
+        }
+    }
+    s->cc_op = CC_OP_SHIFTW;
+    gen_partset_reg(OS_WORD, reg, dest);
+}
+
+DISAS_INSN(shift_reg)
+{
+    TCGv reg;
+    TCGv shift;
+
+    reg = DREG(insn, 0);
+    shift = DREG(insn, 9);
+    /* Shift by zero leaves C flag unmodified.   */
+    gen_flush_flags(s);
+    if (insn & 0x100) {
+        if (insn & 8) {
+            gen_helper_shl32_cc(reg, cpu_env, reg, shift);
+        } else {
+            gen_helper_sal32_cc(reg, cpu_env, reg, shift);
+        }
+    } else {
+        if (insn & 8) {
+            gen_helper_shr32_cc(reg, cpu_env, reg, shift);
+        } else {
+            gen_helper_sar32_cc(reg, cpu_env, reg, shift);
+        }
+    }
+    s->cc_op = CC_OP_SHIFT;
+}
+
+DISAS_INSN(shift_mem)
+{
+    TCGv src;
+    TCGv dest;
+    TCGv addr;
+    TCGv shift;
+
+    SRC_EA(src, OS_WORD, 0, &addr);
+    dest = tcg_temp_new_i32();
+    shift = tcg_const_i32(1);
+    if (insn & 0x100) {
+        gen_helper_shl16_cc(dest, cpu_env, src, shift);
     } else {
         if (insn & 8) {
-            gen_helper_shr_cc(reg, cpu_env, reg, shift);
+            gen_helper_shr16_cc(dest, cpu_env, src, shift);
+        } else {
+            gen_helper_sar16_cc(dest, cpu_env, src, shift);
+        }
+    }
+    s->cc_op = CC_OP_SHIFTW;
+    DEST_EA(insn, OS_WORD, dest, &addr);
+}
+
+DISAS_INSN(rotate_im)
+{
+    TCGv reg;
+    TCGv shift;
+    int tmp;
+
+    reg = DREG(insn, 0);
+    tmp = (insn >> 9) & 7;
+    if (tmp == 0)
+       tmp = 8;
+    shift = tcg_const_i32(tmp);
+    if (insn & 8) {
+       if (insn & 0x100) {
+           gen_helper_rol32_cc(reg, cpu_env, reg, shift);
+       } else {
+           gen_helper_ror32_cc(reg, cpu_env, reg, shift);
+       }
+    } else {
+        if (insn & 0x100) {
+            gen_helper_roxl32_cc(reg, cpu_env, reg, shift);
+        } else {
+            gen_helper_roxr32_cc(reg, cpu_env, reg, shift);
+        }
+    }
+    s->cc_op = CC_OP_FLAGS;
+}
+
+DISAS_INSN(rotate8_im)
+{
+    TCGv reg;
+    TCGv dest;
+    TCGv shift;
+    int tmp;
+
+    reg = DREG(insn, 0);
+    tmp = (insn >> 9) & 7;
+    if (tmp == 0)
+       tmp = 8;
+    dest = tcg_temp_new_i32();
+    shift = tcg_const_i32(tmp);
+    if (insn & 8) {
+       if (insn & 0x100) {
+           gen_helper_rol8_cc(dest, cpu_env, reg, shift);
+       } else {
+           gen_helper_ror8_cc(dest, cpu_env, reg, shift);
+       }
+    } else {
+        if (insn & 0x100) {
+            gen_helper_roxl8_cc(dest, cpu_env, reg, shift);
+        } else {
+            gen_helper_roxr8_cc(dest, cpu_env, reg, shift);
+        }
+    }
+    s->cc_op = CC_OP_FLAGS;
+    gen_partset_reg(OS_BYTE, reg, dest);
+}
+
+DISAS_INSN(rotate16_im)
+{
+    TCGv reg;
+    TCGv dest;
+    TCGv shift;
+    int tmp;
+
+    reg = DREG(insn, 0);
+    tmp = (insn >> 9) & 7;
+    if (tmp == 0)
+       tmp = 8;
+    dest = tcg_temp_new_i32();
+    shift = tcg_const_i32(tmp);
+    if (insn & 8) {
+       if (insn & 0x100) {
+           gen_helper_rol16_cc(dest, cpu_env, reg, shift);
+       } else {
+           gen_helper_ror16_cc(dest, cpu_env, reg, shift);
+       }
+    } else {
+        if (insn & 0x100) {
+            gen_helper_roxl16_cc(dest, cpu_env, reg, shift);
+        } else {
+            gen_helper_roxr16_cc(dest, cpu_env, reg, shift);
+        }
+    }
+    s->cc_op = CC_OP_FLAGS;
+    gen_partset_reg(OS_WORD, reg, dest);
+}
+
+DISAS_INSN(rotate_reg)
+{
+    TCGv reg;
+    TCGv src;
+    TCGv tmp;
+
+    reg = DREG(insn, 0);
+    src = DREG(insn, 9);
+    tmp = tcg_temp_new_i32();
+    tcg_gen_andi_i32(tmp, src, 63);
+    if (insn & 8) {
+       if (insn & 0x100) {
+           gen_helper_rol32_cc(reg, cpu_env, reg, tmp);
+       } else {
+           gen_helper_ror32_cc(reg, cpu_env, reg, tmp);
+       }
+    } else {
+        if (insn & 0x100) {
+            gen_helper_roxl32_cc(reg, cpu_env, reg, tmp);
+        } else {
+            gen_helper_roxr32_cc(reg, cpu_env, reg, tmp);
+        }
+    }
+    s->cc_op = CC_OP_FLAGS;
+}
+
+DISAS_INSN(rotate8_reg)
+{
+    TCGv reg;
+    TCGv src;
+    TCGv dest;
+    TCGv tmp;
+
+    reg = DREG(insn, 0);
+    src = DREG(insn, 9);
+    tmp = tcg_temp_new_i32();
+    tcg_gen_andi_i32(tmp, src, 63);
+    dest = tcg_temp_new_i32();
+    if (insn & 8) {
+       if (insn & 0x100) {
+           gen_helper_rol8_cc(dest, cpu_env, reg, tmp);
+       } else {
+           gen_helper_ror8_cc(dest, cpu_env, reg, tmp);
+       }
+    } else {
+        if (insn & 0x100) {
+            gen_helper_roxl8_cc(dest, cpu_env, reg, tmp);
+        } else {
+            gen_helper_roxr8_cc(dest, cpu_env, reg, tmp);
+        }
+    }
+    s->cc_op = CC_OP_FLAGS;
+    gen_partset_reg(OS_BYTE, reg, dest);
+}
+
+DISAS_INSN(rotate16_reg)
+{
+    TCGv reg;
+    TCGv src;
+    TCGv dest;
+    TCGv tmp;
+
+    reg = DREG(insn, 0);
+    src = DREG(insn, 9);
+    tmp = tcg_temp_new_i32();
+    tcg_gen_andi_i32(tmp, src, 63);
+    dest = tcg_temp_new_i32();
+    if (insn & 8) {
+       if (insn & 0x100) {
+           gen_helper_rol16_cc(dest, cpu_env, reg, tmp);
+       } else {
+           gen_helper_ror16_cc(dest, cpu_env, reg, tmp);
+       }
+    } else {
+        if (insn & 0x100) {
+            gen_helper_roxl16_cc(dest, cpu_env, reg, tmp);
+        } else {
+            gen_helper_roxr16_cc(dest, cpu_env, reg, tmp);
+        }
+    }
+    s->cc_op = CC_OP_FLAGS;
+    gen_partset_reg(OS_WORD, reg, dest);
+}
+
+DISAS_INSN(rotate_mem)
+{
+    TCGv src;
+    TCGv dest;
+    TCGv addr;
+    TCGv shift;
+
+    SRC_EA(src, OS_WORD, 0, &addr);
+    dest = tcg_temp_new_i32();
+    shift = tcg_const_i32(1);
+    if (insn & 8) {
+       if (insn & 0x100) {
+           gen_helper_rol16_cc(dest, cpu_env, src, shift);
+       } else {
+           gen_helper_ror16_cc(dest, cpu_env, src, shift);
+       }
+    } else {
+        if (insn & 0x100) {
+            gen_helper_roxl16_cc(dest, cpu_env, src, shift);
         } else {
-            gen_helper_sar_cc(reg, cpu_env, reg, shift);
+            gen_helper_roxr16_cc(dest, cpu_env, src, shift);
         }
     }
-    s->cc_op = CC_OP_SHIFT;
-}
+    s->cc_op = CC_OP_FLAGS;
+    DEST_EA(insn, OS_WORD, dest, &addr);
+}
+
+static void bitfield_param(uint16_t ext, TCGv *offset, TCGv *width, TCGv *mask)
+{
+    TCGv tmp;
+
+    /* offset */
+
+    if (ext & 0x0800) {
+        *offset = tcg_temp_new_i32();
+        tcg_gen_mov_i32(*offset, DREG(ext, 6));
+    } else {
+        *offset = tcg_temp_new_i32();
+        tcg_gen_movi_i32(*offset, (ext >> 6) & 31);
+    }
+
+    /* width */
+
+    if (ext & 0x0020) {
+        *width = tcg_temp_new_i32();
+        tcg_gen_subi_i32(*width, DREG(ext, 0), 1);
+        tcg_gen_andi_i32(*width, *width, 31);
+        tcg_gen_addi_i32(*width, *width, 1);
+    } else {
+        *width = tcg_temp_new_i32();
+        tcg_gen_movi_i32(*width, ((ext - 1) & 31) + 1);
+    }
+
+    /* mask */
+
+    tmp = tcg_temp_new_i32();
+    tcg_gen_sub_i32(tmp, tcg_const_i32(32), *width);
+    *mask = tcg_temp_new_i32();
+    tcg_gen_shl_i32(*mask, tcg_const_i32(0xffffffff), tmp);
+}
+
+DISAS_INSN(bitfield_reg)
+{
+    uint16_t ext;
+    TCGv tmp;
+    TCGv tmp1;
+    TCGv reg;
+    TCGv offset;
+    TCGv width;
+    int op;
+    TCGv reg2;
+    TCGv mask;
+
+    reg = DREG(insn, 0);
+    op = (insn >> 8) & 7;
+    ext = read_im16(s);
+
+    bitfield_param(ext, &offset, &width, &mask);
+
+    if (ext & 0x0800)
+        tcg_gen_andi_i32(offset, offset, 31);
+    gen_helper_ror32(mask, mask, offset);
+
+    /* reg & mask */
+
+    tmp = tcg_temp_new_i32();
+    tcg_gen_and_i32(tmp, reg, mask);
+
+    tmp1 = tcg_temp_new_i32();
+    gen_helper_rol32(tmp1, tmp, offset);
+
+    reg2 = DREG(ext, 12);
+    if (op == 7) {
+        TCGv tmp2;
+
+        tmp2 = tcg_temp_new_i32();
+        tcg_gen_sub_i32(tmp2, tcg_const_i32(32), width);
+        tcg_gen_shl_i32(tmp2, reg2, tmp2);
+        tcg_gen_and_i32(tmp2, tmp2, mask);
+        gen_logic_cc(s, tmp2, OS_LONG);
+
+        tcg_temp_free_i32(tmp1);
+    } else {
+        gen_logic_cc(s, tmp1, OS_LONG);
+    }
+
+    switch (op) {
+    case 0: /* bftst */
+        break;
+    case 1: /* bfextu */
+        tcg_gen_add_i32(tmp1, offset, width);
+        tcg_gen_andi_i32(tmp1, tmp1, 31);
+        gen_helper_rol32(reg2, tmp, tmp1);
+        break;
+    case 2: /* bfchg */
+        tcg_gen_xor_i32(reg, reg, mask);
+        break;
+    case 3: /* bfexts */
+        gen_helper_rol32(reg2, tmp, offset);
+        tcg_gen_sub_i32(width, tcg_const_i32(32), width);
+        tcg_gen_sar_i32(reg2, reg2, width);
+        break;
+    case 4: /* bfclr */
+        tcg_gen_not_i32(mask, mask);
+        tcg_gen_and_i32(reg, reg, mask);
+        break;
+    case 5: /* bfffo */
+        gen_helper_rol32(reg2, tmp, offset);
+        gen_helper_bfffo(tmp, tmp, width);
+        tcg_gen_add_i32(reg2, tmp, offset);
+        break;
+    case 6: /* bfset */
+        tcg_gen_or_i32(reg, reg, mask);
+        break;
+    case 7: /* bfins */
+        tcg_gen_shl_i32(tmp1, tcg_const_i32(1), width);
+        tcg_gen_subi_i32(tmp1, tmp1, 1);
+        tcg_gen_and_i32(tmp, reg2, tmp1);
+        tcg_gen_add_i32(tmp1, offset, width);
+        tcg_gen_andi_i32(tmp1, tmp1, 31);
+        gen_helper_ror32(tmp, tmp, tmp1);
+        tcg_gen_not_i32(mask, mask);
+        tcg_gen_and_i32(reg, reg, mask);
+        tcg_gen_or_i32(reg, reg, tmp);
+        break;
+    }
+}
+
+static TCGv gen_bitfield_cc(DisasContext *s,
+                            TCGv offset, TCGv mask_cc, TCGv_i64 bitfield)
+{
+    TCGv dest;
+    TCGv_i64 tmp64;
+
+    /* move bitfield to a 32bit */
+
+    tmp64 = tcg_temp_new_i64();
+
+    tcg_gen_extu_i32_i64(tmp64, offset);
+
+    /* tmp64 = bitfield << offset */
+
+    tcg_gen_shl_i64(tmp64, bitfield, tmp64);
+
+    /* tmp = (bitfield << offset) >> 32 */
+
+    tcg_gen_shri_i64(tmp64, tmp64, 32ULL);
+    dest = tcg_temp_new_i32();
+    tcg_gen_trunc_i64_i32(dest, tmp64);
+    tcg_gen_and_i32(dest, dest, mask_cc);
+
+    return dest;
+}
+
+static TCGv_i64 gen_bitfield_mask(TCGv offset, TCGv width)
+{
+    TCGv tmp;
+    TCGv_i64 mask;
+    TCGv_i64 shift;
+
+    mask = tcg_temp_new_i64();
+
+    /* mask = (1u << width) - 1; */
+
+    tcg_gen_extu_i32_i64(mask, width);
+    tcg_gen_shl_i64(mask, tcg_const_i64(1), mask);
+    tcg_gen_subi_i64(mask, mask, 1);
+
+    /* shift = 64 - (width + offset); */
+
+    tmp = tcg_temp_new_i32();
+    tcg_gen_add_i32(tmp, offset, width);
+    tcg_gen_sub_i32(tmp, tcg_const_i32(64), tmp);
+    shift = tcg_temp_new_i64();
+    tcg_gen_extu_i32_i64(shift, tmp);
+
+    /* mask <<= shift */
+
+    tcg_gen_shl_i64(mask, mask, shift);
+
+    return mask;
+}
+
+static void gen_bitfield_ins(TCGv offset, TCGv width, TCGv src,
+                                 TCGv_i64 val)
+{
+    TCGv_i64 insert;
+    TCGv_i64 shift;
+    TCGv tmp;
+
+    tmp = tcg_temp_new_i32();
+
+    /* tmp = (1u << width) - 1; */
+
+    /* width is between 1 and 32
+     * tcg_gen_shl_i32() cannot manage value 32
+     */
+    tcg_gen_subi_i32(tmp, width, 1);
+    tcg_gen_shl_i32(tmp, tcg_const_i32(2), tmp);
+    tcg_gen_subi_i32(tmp, tmp, 1);
+
+    /* tmp = tmp & src; */
+
+    tcg_gen_and_i32(tmp, tmp, src);
+
+    /* insert = (i64)tmp; */
+
+    insert = tcg_temp_new_i64();
+    tcg_gen_extu_i32_i64(insert, tmp);
+
+    /* tmp = 64 - (width + offset); */
+
+    tcg_gen_add_i32(tmp, offset, width);
+    tcg_gen_sub_i32(tmp, tcg_const_i32(64), tmp);
+    shift = tcg_temp_new_i64();
+    tcg_gen_extu_i32_i64(shift, tmp);
+
+    /* insert <<= shift */
+
+    tcg_gen_shl_i64(insert, insert, shift);
+
+    /* val |=  select */
+
+    tcg_gen_or_i64(val, val, insert);
+}
+
+DISAS_INSN(bitfield_mem)
+{
+    uint16_t ext;
+    int op;
+    TCGv_i64 bitfield;
+    TCGv_i64 mask_bitfield;
+    TCGv mask_cc;
+    TCGv shift;
+    TCGv val;
+    TCGv src;
+    TCGv offset;
+    TCGv width;
+    TCGv reg;
+    TCGv tmp;
+
+    op = (insn >> 8) & 7;
+    ext = read_im16(s);
+    src = gen_lea(s, insn, OS_LONG);
+    if (IS_NULL_QREG(src)) {
+       gen_addr_fault(s);
+       return;
+    }

-DISAS_INSN(shift_reg)
-{
-    TCGv reg;
-    TCGv shift;
+    bitfield_param(ext, &offset, &width, &mask_cc);

-    reg = DREG(insn, 0);
-    shift = DREG(insn, 9);
-    /* Shift by zero leaves C flag unmodified.   */
-    gen_flush_flags(s);
-    if (insn & 0x100) {
-        gen_helper_shl_cc(reg, cpu_env, reg, shift);
+    /* adjust src and offset */
+
+    /* src += offset >> 3; */
+
+    tmp = tcg_temp_new_i32();
+    tcg_gen_shri_i32(tmp, offset, 3);
+    tcg_gen_add_i32(src, src, tmp);
+
+    /* offset &= 7; */
+
+    tcg_gen_andi_i32(offset, offset, 7);
+
+    /* load */
+
+    bitfield = tcg_temp_new_i64();
+    gen_helper_bitfield_load(bitfield, src, offset, width);
+
+    /* compute CC and move bitfield into a 32bit */
+
+    val = gen_bitfield_cc(s, offset, mask_cc, bitfield);
+
+    /* execute operation */
+
+    reg = DREG(ext, 12);
+
+    if (op == 7) {
+        TCGv tmp1;
+
+        tmp1 = tcg_temp_new_i32();
+        tcg_gen_sub_i32(tmp1, tcg_const_i32(32), width);
+        tcg_gen_shl_i32(tmp1, reg, tmp1);
+        tcg_gen_and_i32(tmp1, tmp1, mask_cc);
+        gen_logic_cc(s, tmp1, OS_LONG);
+
+        tcg_temp_free_i32(tmp1);
     } else {
-        if (insn & 8) {
-            gen_helper_shr_cc(reg, cpu_env, reg, shift);
-        } else {
-            gen_helper_sar_cc(reg, cpu_env, reg, shift);
-        }
+        gen_logic_cc(s, val, OS_LONG);
+    }
+
+    switch (op) {
+    case 0: /* bftst */
+        break;
+    case 1: /* bfextu */
+        shift = tcg_temp_new_i32();
+        tcg_gen_sub_i32(shift, tcg_const_i32(32), width);
+        tcg_gen_shr_i32(reg, val, shift);
+        break;
+    case 2: /* bfchg */
+        mask_bitfield = gen_bitfield_mask(offset, width);
+        tcg_gen_xor_i64(bitfield, bitfield, mask_bitfield);
+        gen_helper_bitfield_store(src, offset, width, bitfield);
+        break;
+    case 3: /* bfexts */
+        shift = tcg_temp_new_i32();
+        tcg_gen_sub_i32(shift, tcg_const_i32(32), width);
+        tcg_gen_sar_i32(reg, val, shift);
+        break;
+    case 4: /* bfclr */
+        mask_bitfield = gen_bitfield_mask(offset, width);
+        tcg_gen_not_i64(mask_bitfield, mask_bitfield);
+        tcg_gen_and_i64(bitfield, bitfield, mask_bitfield);
+        gen_helper_bitfield_store(src, offset, width, bitfield);
+        break;
+    case 5: /* bfffo */
+        gen_helper_bfffo(val, val, width);
+        tcg_gen_add_i32(reg, val, offset);
+        break;
+    case 6: /* bfset */
+        mask_bitfield = gen_bitfield_mask(offset, width);
+        tcg_gen_or_i64(bitfield, bitfield, mask_bitfield);
+        gen_helper_bitfield_store(src, offset, width, bitfield);
+        break;
+    case 7: /* bfins */
+        /* clear */
+        mask_bitfield = gen_bitfield_mask(offset, width);
+        tcg_gen_not_i64(mask_bitfield, mask_bitfield);
+        tcg_gen_and_i64(bitfield, bitfield, mask_bitfield);
+        /* insert */
+        gen_bitfield_ins(offset, width, reg, bitfield);
+        gen_helper_bitfield_store(src, offset, width, bitfield);
+        break;
     }
-    s->cc_op = CC_OP_SHIFT;
 }

 DISAS_INSN(ff1)
 {
     TCGv reg;
     reg = DREG(insn, 0);
-    gen_logic_cc(s, reg);
+    gen_logic_cc(s, reg, OS_LONG);
     gen_helper_ff1(reg, reg);
 }

@@ -1940,14 +3437,12 @@  DISAS_INSN(strldsr)
     uint32_t addr;

     addr = s->pc - 2;
-    ext = lduw_code(s->pc);
-    s->pc += 2;
+    ext = read_im16(s);
     if (ext != 0x46FC) {
         gen_exception(s, addr, EXCP_UNSUPPORTED);
         return;
     }
-    ext = lduw_code(s->pc);
-    s->pc += 2;
+    ext = read_im16(s);
     if (IS_USER(s) || (ext & SR_S) == 0) {
         gen_exception(s, addr, EXCP_PRIVILEGE);
         return;
@@ -1958,7 +3453,6 @@  DISAS_INSN(strldsr)

 DISAS_INSN(move_from_sr)
 {
-    TCGv reg;
     TCGv sr;

     if (IS_USER(s)) {
@@ -1966,8 +3460,7 @@  DISAS_INSN(move_from_sr)
         return;
     }
     sr = gen_get_sr(s);
-    reg = DREG(insn, 0);
-    gen_partset_reg(OS_WORD, reg, sr);
+    DEST_EA(insn, OS_WORD, sr, NULL);
 }

 DISAS_INSN(move_to_sr)
@@ -2014,8 +3507,7 @@  DISAS_INSN(stop)
         return;
     }

-    ext = lduw_code(s->pc);
-    s->pc += 2;
+    ext = read_im16(s);

     gen_set_sr_im(s, ext, 0);
     tcg_gen_movi_i32(QREG_HALTED, 1);
@@ -2041,15 +3533,18 @@  DISAS_INSN(movec)
         return;
     }

-    ext = lduw_code(s->pc);
-    s->pc += 2;
+    ext = read_im16(s);

     if (ext & 0x8000) {
         reg = AREG(ext, 12);
     } else {
         reg = DREG(ext, 12);
     }
-    gen_helper_movec(cpu_env, tcg_const_i32(ext & 0xfff), reg);
+    if (insn & 1) {
+        gen_helper_movec_to(cpu_env, tcg_const_i32(ext & 0xfff), reg);
+    } else {
+        gen_helper_movec_from(reg, cpu_env, tcg_const_i32(ext & 0xfff));
+    }
     gen_lookup_tb(s);
 }

@@ -2088,7 +3583,71 @@  DISAS_INSN(wdebug)

 DISAS_INSN(trap)
 {
-    gen_exception(s, s->pc - 2, EXCP_TRAP0 + (insn & 0xf));
+	gen_exception(s, s->pc - 2, EXCP_TRAP0 + (insn & 0xf));
+}
+
+static void gen_op_fmovem(DisasContext *s, uint32_t insn, uint32_t ext)
+{
+    int opsize;
+    uint16_t mask;
+    int i;
+    uint32_t mode;
+    int32_t incr;
+    TCGv addr, tmp;
+    int is_load;
+
+    if (m68k_feature(s->env, M68K_FEATURE_FPU))
+        opsize = OS_EXTENDED;
+    else
+        opsize = OS_DOUBLE;  // FIXME
+
+    mode = (ext >> 11) & 0x3;
+    if ((mode & 0x1) == 1) {
+        gen_helper_fmovem(cpu_env, tcg_const_i32(opsize),
+                          tcg_const_i32(mode), DREG(ext, 0));
+        return;
+    }
+
+    tmp = gen_lea(s, insn, opsize);
+    if (IS_NULL_QREG(tmp)) {
+        gen_addr_fault(s);
+        return;
+    }
+
+    addr = tcg_temp_new();
+    tcg_gen_mov_i32(addr, tmp);
+    is_load = ((ext & 0x2000) == 0);
+    incr = opsize_bytes(opsize);
+    mask = ext & 0x00FF;
+
+    if (!is_load && (mode & 2) == 0) {
+        for (i = 7; i >= 0; i--, mask <<= 1) {
+            if (mask & 0x80) {
+                gen_op_load_fpr_FP0(i);
+                gen_store_FP0(s, opsize, addr);
+                if ((mask & 0xff) != 0x80)
+                    tcg_gen_subi_i32(addr, addr, incr);
+            }
+        }
+        tcg_gen_mov_i32(AREG(insn, 0), addr);
+    } else{
+        for (i = 0; i < 8; i++, mask <<=1) {
+            if (mask & 0x80) {
+                if (is_load) {
+                    gen_load_FP0(s, opsize, addr);
+                    gen_op_store_fpr_FP0(i);
+                } else {
+                    gen_op_load_fpr_FP0(i);
+                    gen_store_FP0(s, opsize, addr);
+                }
+               if ((mask & 0xff) != 0x80 || (insn & 070) == 030)
+                   tcg_gen_addi_i32(addr, addr, incr);
+            }
+        }
+        if ((insn & 070) == 030)
+            tcg_gen_mov_i32(AREG(insn, 0), addr);
+    }
+    tcg_temp_free_i32(addr);
 }

 /* ??? FP exceptions are not implemented.  Most exceptions are deferred until
@@ -2096,86 +3655,40 @@  DISAS_INSN(trap)
 DISAS_INSN(fpu)
 {
     uint16_t ext;
-    int32_t offset;
+    uint8_t rom_offset;
     int opmode;
-    TCGv_i64 src;
-    TCGv_i64 dest;
-    TCGv_i64 res;
-    TCGv tmp32;
     int round;
     int set_dest;
     int opsize;
+    TCGv val;

-    ext = lduw_code(s->pc);
-    s->pc += 2;
+    ext = read_im16(s);
     opmode = ext & 0x7f;
     switch ((ext >> 13) & 7) {
-    case 0: case 2:
+    case 0:
         break;
     case 1:
         goto undef;
-    case 3: /* fmove out */
-        src = FREG(ext, 7);
-        tmp32 = tcg_temp_new_i32();
-        /* fmove */
-        /* ??? TODO: Proper behavior on overflow.  */
-        switch ((ext >> 10) & 7) {
-        case 0:
-            opsize = OS_LONG;
-            gen_helper_f64_to_i32(tmp32, cpu_env, src);
-            break;
-        case 1:
-            opsize = OS_SINGLE;
-            gen_helper_f64_to_f32(tmp32, cpu_env, src);
-            break;
-        case 4:
-            opsize = OS_WORD;
-            gen_helper_f64_to_i32(tmp32, cpu_env, src);
-            break;
-        case 5: /* OS_DOUBLE */
-            tcg_gen_mov_i32(tmp32, AREG(insn, 0));
-            switch ((insn >> 3) & 7) {
-            case 2:
-            case 3:
-                break;
-            case 4:
-                tcg_gen_addi_i32(tmp32, tmp32, -8);
-                break;
-            case 5:
-                offset = ldsw_code(s->pc);
-                s->pc += 2;
-                tcg_gen_addi_i32(tmp32, tmp32, offset);
-                break;
-            default:
-                goto undef;
-            }
-            gen_store64(s, tmp32, src);
-            switch ((insn >> 3) & 7) {
-            case 3:
-                tcg_gen_addi_i32(tmp32, tmp32, 8);
-                tcg_gen_mov_i32(AREG(insn, 0), tmp32);
-                break;
-            case 4:
-                tcg_gen_mov_i32(AREG(insn, 0), tmp32);
-                break;
-            }
-            tcg_temp_free_i32(tmp32);
+    case 2:
+        if ( insn == 0xf200 && (ext & 0xfc00) == 0x5c00) {
+            /* fmovecr */
+            rom_offset = ext & 0x7f;
+            gen_helper_const_FP0(cpu_env, tcg_const_i32(rom_offset));
+            gen_op_store_fpr_FP0(REG(ext, 7));
             return;
-        case 6:
-            opsize = OS_BYTE;
-            gen_helper_f64_to_i32(tmp32, cpu_env, src);
-            break;
-        default:
-            goto undef;
         }
-        DEST_EA(insn, opsize, tmp32, NULL);
-        tcg_temp_free_i32(tmp32);
+        break;
+    case 3: /* fmove out */
+        opsize = ext_opsize(ext, 10);
+        gen_op_load_fpr_FP0(REG(ext, 7));
+        gen_op_store_ea_FP0(s, insn, opsize);
         return;
     case 4: /* fmove to control register.  */
         switch ((ext >> 10) & 7) {
         case 4: /* FPCR */
-            /* Not implemented.  Ignore writes.  */
-            break;
+            SRC_EA(val, OS_LONG, 0, NULL);
+            gen_helper_set_fpcr(cpu_env, val);
+            return;
         case 1: /* FPIAR */
         case 2: /* FPSR */
         default:
@@ -2186,173 +3699,162 @@  DISAS_INSN(fpu)
     case 5: /* fmove from control register.  */
         switch ((ext >> 10) & 7) {
         case 4: /* FPCR */
-            /* Not implemented.  Always return zero.  */
-            tmp32 = tcg_const_i32(0);
-            break;
+            DEST_EA(insn, OS_LONG, QEMU_FPCR, NULL);
+            return;
         case 1: /* FPIAR */
+            cpu_abort(NULL, "Unimplemented: fmove from control FPIAR");
+            goto undef;
         case 2: /* FPSR */
+            DEST_EA(insn, OS_LONG, QEMU_FPSR, NULL);
+            return;
         default:
             cpu_abort(NULL, "Unimplemented: fmove from control %d",
                       (ext >> 10) & 7);
             goto undef;
         }
-        DEST_EA(insn, OS_LONG, tmp32, NULL);
         break;
     case 6: /* fmovem */
     case 7:
-        {
-            TCGv addr;
-            uint16_t mask;
-            int i;
-            if ((ext & 0x1f00) != 0x1000 || (ext & 0xff) == 0)
-                goto undef;
-            tmp32 = gen_lea(s, insn, OS_LONG);
-            if (IS_NULL_QREG(tmp32)) {
-                gen_addr_fault(s);
-                return;
-            }
-            addr = tcg_temp_new_i32();
-            tcg_gen_mov_i32(addr, tmp32);
-            mask = 0x80;
-            for (i = 0; i < 8; i++) {
-                if (ext & mask) {
-                    s->is_mem = 1;
-                    dest = FREG(i, 0);
-                    if (ext & (1 << 13)) {
-                        /* store */
-                        tcg_gen_qemu_stf64(dest, addr, IS_USER(s));
-                    } else {
-                        /* load */
-                        tcg_gen_qemu_ldf64(dest, addr, IS_USER(s));
-                    }
-                    if (ext & (mask - 1))
-                        tcg_gen_addi_i32(addr, addr, 8);
-                }
-                mask >>= 1;
-            }
-            tcg_temp_free_i32(addr);
-        }
+        if ((ext & 0xf00) != 0 || (ext & 0xff) == 0)
+            goto undef;
+        if ((ext & 0x1000) == 0 && !m68k_feature(s->env, M68K_FEATURE_FPU))
+            goto undef;
+        gen_op_fmovem(s, insn, ext);
         return;
     }
     if (ext & (1 << 14)) {
-        /* Source effective address.  */
-        switch ((ext >> 10) & 7) {
-        case 0: opsize = OS_LONG; break;
-        case 1: opsize = OS_SINGLE; break;
-        case 4: opsize = OS_WORD; break;
-        case 5: opsize = OS_DOUBLE; break;
-        case 6: opsize = OS_BYTE; break;
-        default:
-            goto undef;
-        }
-        if (opsize == OS_DOUBLE) {
-            tmp32 = tcg_temp_new_i32();
-            tcg_gen_mov_i32(tmp32, AREG(insn, 0));
-            switch ((insn >> 3) & 7) {
-            case 2:
-            case 3:
-                break;
-            case 4:
-                tcg_gen_addi_i32(tmp32, tmp32, -8);
-                break;
-            case 5:
-                offset = ldsw_code(s->pc);
-                s->pc += 2;
-                tcg_gen_addi_i32(tmp32, tmp32, offset);
-                break;
-            case 7:
-                offset = ldsw_code(s->pc);
-                offset += s->pc - 2;
-                s->pc += 2;
-                tcg_gen_addi_i32(tmp32, tmp32, offset);
-                break;
-            default:
-                goto undef;
-            }
-            src = gen_load64(s, tmp32);
-            switch ((insn >> 3) & 7) {
-            case 3:
-                tcg_gen_addi_i32(tmp32, tmp32, 8);
-                tcg_gen_mov_i32(AREG(insn, 0), tmp32);
-                break;
-            case 4:
-                tcg_gen_mov_i32(AREG(insn, 0), tmp32);
-                break;
-            }
-            tcg_temp_free_i32(tmp32);
-        } else {
-            SRC_EA(tmp32, opsize, 1, NULL);
-            src = tcg_temp_new_i64();
-            switch (opsize) {
-            case OS_LONG:
-            case OS_WORD:
-            case OS_BYTE:
-                gen_helper_i32_to_f64(src, cpu_env, tmp32);
-                break;
-            case OS_SINGLE:
-                gen_helper_f32_to_f64(src, cpu_env, tmp32);
-                break;
-            }
-        }
+        opsize = ext_opsize(ext, 10);
+        gen_op_load_ea_FP0(s, insn, opsize);
     } else {
         /* Source register.  */
-        src = FREG(ext, 10);
+        opsize = OS_EXTENDED;
+        gen_op_load_fpr_FP0(REG(ext, 10));
     }
-    dest = FREG(ext, 7);
-    res = tcg_temp_new_i64();
-    if (opmode != 0x3a)
-        tcg_gen_mov_f64(res, dest);
     round = 1;
     set_dest = 1;
     switch (opmode) {
     case 0: case 0x40: case 0x44: /* fmove */
-        tcg_gen_mov_f64(res, src);
         break;
     case 1: /* fint */
-        gen_helper_iround_f64(res, cpu_env, src);
+        gen_helper_iround_FP0(cpu_env);
         round = 0;
         break;
+    case 2: /* fsinh */
+        gen_helper_sinh_FP0(cpu_env);
+        break;
     case 3: /* fintrz */
-        gen_helper_itrunc_f64(res, cpu_env, src);
+        gen_helper_itrunc_FP0(cpu_env);
         round = 0;
         break;
     case 4: case 0x41: case 0x45: /* fsqrt */
-        gen_helper_sqrt_f64(res, cpu_env, src);
+        gen_helper_sqrt_FP0(cpu_env);
+        break;
+    case 6:                          /* flognp1 */
+        gen_helper_lognp1_FP0(cpu_env);
+        break;
+    case 0x09:                       /* ftanh */
+        gen_helper_tanh_FP0(cpu_env);
+        break;
+    case 0x0a:                       /* fatan */
+        gen_helper_atan_FP0(cpu_env);
+        break;
+    case 0x0c:                       /* fasin */
+        gen_helper_asin_FP0(cpu_env);
+        break;
+    case 0x0d:                       /* fatanh */
+        gen_helper_atanh_FP0(cpu_env);
+        break;
+    case 0x0e:                       /* fsin */
+        gen_helper_sin_FP0(cpu_env);
+        break;
+    case 0x0f:                       /* ftan */
+        gen_helper_tan_FP0(cpu_env);
+        break;
+    case 0x10:                       /* fetox */
+        gen_helper_exp_FP0(cpu_env);
+        break;
+    case 0x11:                       /* ftwotox */
+        gen_helper_exp2_FP0(cpu_env);
+        break;
+    case 0x12:                       /* ftentox */
+        gen_helper_exp10_FP0(cpu_env);
+        break;
+    case 0x14:                       /* flogn */
+        gen_helper_ln_FP0(cpu_env);
+        break;
+    case 0x15:                       /* flog10 */
+        gen_helper_log10_FP0(cpu_env);
         break;
     case 0x18: case 0x58: case 0x5c: /* fabs */
-        gen_helper_abs_f64(res, src);
+        gen_helper_abs_FP0(cpu_env);
+        break;
+    case 0x19:
+        gen_helper_cosh_FP0(cpu_env);
         break;
     case 0x1a: case 0x5a: case 0x5e: /* fneg */
-        gen_helper_chs_f64(res, src);
+        gen_helper_chs_FP0(cpu_env);
+        break;
+    case 0x1c:                       /* facos */
+        gen_helper_acos_FP0(cpu_env);
+        break;
+    case 0x1d:                       /* fcos */
+        gen_helper_cos_FP0(cpu_env);
+        break;
+    case 0x1e:                       /* fgetexp */
+        gen_helper_getexp_FP0(cpu_env);
         break;
     case 0x20: case 0x60: case 0x64: /* fdiv */
-        gen_helper_div_f64(res, cpu_env, res, src);
+        gen_op_load_fpr_FP1(REG(ext, 7));
+        gen_helper_div_FP0_FP1(cpu_env);
+        break;
+    case 0x21:                       /* fmod */
+        gen_op_load_fpr_FP1(REG(ext, 7));
+        gen_helper_mod_FP0_FP1(cpu_env);
         break;
     case 0x22: case 0x62: case 0x66: /* fadd */
-        gen_helper_add_f64(res, cpu_env, res, src);
+        gen_op_load_fpr_FP1(REG(ext, 7));
+        gen_helper_add_FP0_FP1(cpu_env);
         break;
     case 0x23: case 0x63: case 0x67: /* fmul */
-        gen_helper_mul_f64(res, cpu_env, res, src);
+        gen_op_load_fpr_FP1(REG(ext, 7));
+        gen_helper_mul_FP0_FP1(cpu_env);
+        break;
+    case 0x24:                      /* fsgldiv */
+        gen_op_load_fpr_FP1(REG(ext, 7));
+        gen_helper_div_FP0_FP1(cpu_env);
+        break;
+    case 0x26:                       /* fscale */
+        gen_op_load_fpr_FP1(REG(ext, 7));
+        gen_helper_scale_FP0_FP1(cpu_env);
+        break;
+    case 0x27:                      /* fsglmul */
+        gen_op_load_fpr_FP1(REG(ext, 7));
+        gen_helper_mul_FP0_FP1(cpu_env);
         break;
     case 0x28: case 0x68: case 0x6c: /* fsub */
-        gen_helper_sub_f64(res, cpu_env, res, src);
+        gen_op_load_fpr_FP1(REG(ext, 7));
+        gen_helper_sub_FP0_FP1(cpu_env);
+        break;
+    case 0x30: case 0x31: case 0x32:
+    case 0x33: case 0x34: case 0x35:
+    case 0x36: case 0x37:
+        gen_helper_sincos_FP0_FP1(cpu_env);
+        gen_op_store_fpr_FP0(REG(ext, 7));	/* sin */
+        gen_op_store_fpr_FP1(REG(ext, 0));	/* cos */
         break;
     case 0x38: /* fcmp */
-        gen_helper_sub_cmp_f64(res, cpu_env, res, src);
+        gen_op_load_fpr_FP1(REG(ext, 7));
+        gen_helper_fcmp_FP0_FP1(cpu_env);
         set_dest = 0;
         round = 0;
         break;
     case 0x3a: /* ftst */
-        tcg_gen_mov_f64(res, src);
         set_dest = 0;
         round = 0;
         break;
     default:
         goto undef;
     }
-    if (ext & (1 << 14)) {
-        tcg_temp_free_i64(src);
-    }
     if (round) {
         if (opmode & 0x40) {
             if ((opmode & 0x4) != 0)
@@ -2362,16 +3864,16 @@  DISAS_INSN(fpu)
         }
     }
     if (round) {
+#if 0
         TCGv tmp = tcg_temp_new_i32();
         gen_helper_f64_to_f32(tmp, cpu_env, res);
         gen_helper_f32_to_f64(res, cpu_env, tmp);
         tcg_temp_free_i32(tmp);
+#endif
     }
-    tcg_gen_mov_f64(QREG_FP_RESULT, res);
     if (set_dest) {
-        tcg_gen_mov_f64(dest, res);
+        gen_op_store_fpr_FP0(REG(ext, 7));
     }
-    tcg_temp_free_i64(res);
     return;
 undef:
     /* FIXME: Is this right for offset addressing modes?  */
@@ -2379,27 +3881,15 @@  undef:
     disas_undef_fpu(s, insn);
 }

-DISAS_INSN(fbcc)
+static void gen_fjmpcc(DisasContext *s, int cond, int l1)
 {
-    uint32_t offset;
-    uint32_t addr;
     TCGv flag;
-    int l1;
-
-    addr = s->pc;
-    offset = ldsw_code(s->pc);
-    s->pc += 2;
-    if (insn & (1 << 6)) {
-        offset = (offset << 16) | lduw_code(s->pc);
-        s->pc += 2;
-    }

-    l1 = gen_new_label();
     /* TODO: Raise BSUN exception.  */
     flag = tcg_temp_new();
-    gen_helper_compare_f64(flag, cpu_env, QREG_FP_RESULT);
+    gen_helper_compare_FP0(flag, cpu_env);
     /* Jump to l1 if condition is true.  */
-    switch (insn & 0xf) {
+    switch (cond) {
     case 0: /* f */
         break;
     case 1: /* eq (=0) */
@@ -2421,12 +3911,12 @@  DISAS_INSN(fbcc)
         tcg_gen_andi_i32(flag, flag, 1);
         tcg_gen_brcond_i32(TCG_COND_NE, flag, tcg_const_i32(0), l1);
         break;
-    case 7: /* or (=2) */
-        tcg_gen_brcond_i32(TCG_COND_EQ, flag, tcg_const_i32(2), l1);
-        break;
-    case 8: /* un (<2) */
+    case 7: /* or (<2) */
         tcg_gen_brcond_i32(TCG_COND_LT, flag, tcg_const_i32(2), l1);
         break;
+    case 8: /* un (=2) */
+        tcg_gen_brcond_i32(TCG_COND_EQ, flag, tcg_const_i32(2), l1);
+        break;
     case 9: /* ueq (=0 or =2) */
         tcg_gen_andi_i32(flag, flag, 1);
         tcg_gen_brcond_i32(TCG_COND_EQ, flag, tcg_const_i32(0), l1);
@@ -2450,21 +3940,91 @@  DISAS_INSN(fbcc)
         tcg_gen_br(l1);
         break;
     }
+}
+
+DISAS_INSN(fbcc)
+{
+    uint32_t offset;
+    uint32_t addr;
+    int l1;
+
+    addr = s->pc;
+    offset = ldsw_code(s->pc);
+    s->pc += 2;
+    if (insn & (1 << 6)) {
+        offset = (offset << 16) | lduw_code(s->pc);
+        s->pc += 2;
+    }
+
+    l1 = gen_new_label();
+    gen_fjmpcc(s, insn & 0xf, l1);
     gen_jmp_tb(s, 0, s->pc);
     gen_set_label(l1);
     gen_jmp_tb(s, 1, addr + offset);
 }

+DISAS_INSN(fscc_mem)
+{
+    int l1, l2;
+    TCGv taddr;
+    TCGv addr;
+    uint16_t ext;
+
+    ext = read_im16(s);
+
+    taddr = gen_lea(s, insn, OS_BYTE);
+    if (IS_NULL_QREG(taddr)) {
+        gen_addr_fault(s);
+        return;
+    }
+    addr = tcg_temp_local_new ();
+    tcg_gen_mov_i32(addr, taddr);
+    l1 = gen_new_label();
+    l2 = gen_new_label();
+    gen_fjmpcc(s, ext & 0xf, l1);
+    gen_store(s, OS_BYTE, addr, tcg_const_i32(0x00));
+    tcg_gen_br(l2);
+    gen_set_label(l1);
+    gen_store(s, OS_BYTE, addr, tcg_const_i32(0xff));
+    gen_set_label(l2);
+    tcg_temp_free(addr);
+}
+
+DISAS_INSN(fscc_reg)
+{
+    int l1;
+    TCGv reg;
+    uint16_t ext;
+
+    ext = read_im16(s);
+
+    reg = DREG(insn, 0);
+
+    l1 = gen_new_label();
+    tcg_gen_ori_i32(reg, reg, 0x000000ff);
+    gen_fjmpcc(s, ext & 0xf, l1);
+    tcg_gen_andi_i32(reg, reg, 0xffffff00);
+    gen_set_label(l1);
+}
+
 DISAS_INSN(frestore)
 {
     /* TODO: Implement frestore.  */
-    qemu_assert(0, "FRESTORE not implemented");
+ //   qemu_assert(0, "FRESTORE not implemented");
+  // cpu_abort(cpu_single_env, "Illegal instruction: %04x @ %08x",
+    //          insn, s->pc - 2);
+
+
 }

 DISAS_INSN(fsave)
 {
     /* TODO: Implement fsave.  */
-    qemu_assert(0, "FSAVE not implemented");
+  //  qemu_assert(0, "FSAVE not implemented");
+  // cpu_abort(cpu_single_env, "Illegal instruction: %04x @ %08x",
+           //   insn, s->pc - 2);
+
+
 }

 static inline TCGv gen_mac_extract_word(DisasContext *s, TCGv val, int upper)
@@ -2512,8 +4072,7 @@  DISAS_INSN(mac)
         s->done_mac = 1;
     }

-    ext = lduw_code(s->pc);
-    s->pc += 2;
+    ext = read_im16(s);

     acc = ((insn >> 7) & 1) | ((ext >> 3) & 2);
     dual = ((insn & 0x30) != 0 && (ext & 3) != 0);
@@ -2780,6 +4339,13 @@  DISAS_INSN(to_mext)
         gen_helper_set_mac_extu(cpu_env, val, acc);
 }

+#ifdef CONFIG_EMULOP
+DISAS_INSN(emulop_exec_return)
+{
+    gen_exception(s, s->pc - 2, EXCP_EXEC_RETURN);
+}
+#endif
+
 static disas_proc opcode_table[65536];

 static void
@@ -2815,6 +4381,71 @@  register_opcode (disas_proc proc, uint16_t
opcode, uint16_t mask)
   }
 }

+/* my instructions start here */
+DISAS_INSN(cinva)
+{
+/* Cache invalidate (NOP)*/
+}
+
+DISAS_INSN(pflush)
+{
+	int opmode = (insn>>3) & 0x3;
+	switch(opmode)
+	{
+		case 0x0:
+		case 0x1:
+		fprintf(stderr,"entry\n");
+		break;
+		case 0x2:
+		case 0x3:
+		fprintf(stderr,"all\n");
+		break;
+
+	}
+	
+
+}
+DISAS_INSN(move16)
+{
+	TCGv src;
+	TCGv s_addr;
+	TCGv d_addr;
+	uint16_t im;
+	if(insn & 0x8){
+		
+				vm_stop(VMSTOP_DEBUG);
+        //abort();
+	}else if(insn & 0x10){
+
+				vm_stop(VMSTOP_DEBUG);
+		//abort();
+
+	}else{
+
+        d_addr = tcg_temp_new();
+        s_addr = tcg_temp_new();	
+		
+        s_addr = AREG(insn,0);
+        src = gen_load(s, OS_LONG, s_addr, 0);
+
+        im = read_im16(s);
+        d_addr = AREG(im,12);
+
+        gen_store(s, OS_LONG, d_addr, src);
+
+        int i = 0;
+        for(;i <3; i++)
+        {
+            tcg_gen_addi_i32(d_addr,d_addr,4);
+            tcg_gen_addi_i32(s_addr,s_addr,4);
+
+            src = gen_load(s, OS_LONG, s_addr, 0);
+            gen_store(s, OS_LONG, d_addr, src);
+        }
+	}
+}
+
+
 /* Register m68k opcode handlers.  Order is important.
    Later insn override earlier ones.  */
 void register_m68k_insns (CPUM68KState *env)
@@ -2824,85 +4455,163 @@  void register_m68k_insns (CPUM68KState *env)
         register_opcode(disas_##name, 0x##opcode, 0x##mask); \
     } while(0)
     INSN(undef,     0000, 0000, CF_ISA_A);
+    INSN(undef,     0000, 0000, M68000);
     INSN(arith_im,  0080, fff8, CF_ISA_A);
+    INSN(arith_im,  0000, ff00, M68000);
+    INSN(undef,     00c0, ffc0, M68000);
     INSN(bitrev,    00c0, fff8, CF_ISA_APLUSC);
     INSN(bitop_reg, 0100, f1c0, CF_ISA_A);
+    INSN(bitop_reg, 0100, f1c0, M68000);
     INSN(bitop_reg, 0140, f1c0, CF_ISA_A);
+    INSN(bitop_reg, 0140, f1c0, M68000);
     INSN(bitop_reg, 0180, f1c0, CF_ISA_A);
+    INSN(bitop_reg, 0180, f1c0, M68000);
     INSN(bitop_reg, 01c0, f1c0, CF_ISA_A);
+    INSN(bitop_reg, 01c0, f1c0, M68000);
     INSN(arith_im,  0280, fff8, CF_ISA_A);
+    INSN(arith_im,  0200, ff00, M68000);
+    INSN(undef,     02c0, ffc0, M68000);
     INSN(byterev,   02c0, fff8, CF_ISA_APLUSC);
     INSN(arith_im,  0480, fff8, CF_ISA_A);
+    INSN(arith_im,  0400, ff00, M68000);
+    INSN(undef,     04c0, ffc0, M68000);
+    INSN(arith_im,  0600, ff00, M68000);
+    INSN(undef,     06c0, ffc0, M68000);
     INSN(ff1,       04c0, fff8, CF_ISA_APLUSC);
     INSN(arith_im,  0680, fff8, CF_ISA_A);
     INSN(bitop_im,  0800, ffc0, CF_ISA_A);
+    INSN(bitop_im,  0800, ffc0, M68000);
     INSN(bitop_im,  0840, ffc0, CF_ISA_A);
+    INSN(bitop_im,  0840, ffc0, M68000);
     INSN(bitop_im,  0880, ffc0, CF_ISA_A);
+    INSN(bitop_im,  0880, ffc0, M68000);
+    INSN(cas,       08c0, f9c0, CAS);
     INSN(bitop_im,  08c0, ffc0, CF_ISA_A);
+    INSN(bitop_im,  08c0, ffc0, M68000);
     INSN(arith_im,  0a80, fff8, CF_ISA_A);
+    INSN(arith_im,  0a00, ff00, M68000);
+    INSN(undef,     0ac0, ffc0, M68000);
     INSN(arith_im,  0c00, ff38, CF_ISA_A);
+    INSN(arith_im,  0c00, ff00, M68000);
+    INSN(undef,     0cc0, ffc0, M68000);
     INSN(move,      1000, f000, CF_ISA_A);
+    INSN(move,      1000, f000, M68000);
     INSN(move,      2000, f000, CF_ISA_A);
+    INSN(move,      2000, f000, M68000);
     INSN(move,      3000, f000, CF_ISA_A);
+    INSN(move,      3000, f000, M68000);
     INSN(strldsr,   40e7, ffff, CF_ISA_APLUSC);
     INSN(negx,      4080, fff8, CF_ISA_A);
+    INSN(negx,      4000, ff00, M68000);
+    INSN(undef,     40c0, ffc0, M68000);
     INSN(move_from_sr, 40c0, fff8, CF_ISA_A);
+    INSN(move_from_sr, 40c0, ffc0, M68000);
     INSN(lea,       41c0, f1c0, CF_ISA_A);
+    INSN(lea,       41c0, f1c0, M68000);
     INSN(clr,       4200, ff00, CF_ISA_A);
+    INSN(clr,       4200, ff00, M68000);
     INSN(undef,     42c0, ffc0, CF_ISA_A);
+    INSN(undef,     42c0, ffc0, M68000);
     INSN(move_from_ccr, 42c0, fff8, CF_ISA_A);
     INSN(neg,       4480, fff8, CF_ISA_A);
+    INSN(neg,       4400, ff00, M68000);
+    INSN(undef,     44c0, ffc0, M68000);
     INSN(move_to_ccr, 44c0, ffc0, CF_ISA_A);
+    INSN(move_to_ccr, 44c0, ffc0, M68000);
     INSN(not,       4680, fff8, CF_ISA_A);
+    INSN(not,       4600, ff00, M68000);
+    INSN(move_to_sr, 46c0, ffc0, M68000);
     INSN(move_to_sr, 46c0, ffc0, CF_ISA_A);
+    INSN(nbcd,      4800, ffc0, M68000);
+    INSN(linkl,     4808, fff8, M68000);
     INSN(pea,       4840, ffc0, CF_ISA_A);
+    INSN(pea,       4840, ffc0, M68000);
     INSN(swap,      4840, fff8, CF_ISA_A);
+    INSN(swap,      4840, fff8, M68000);
+    INSN(bkpt,      4848, fff8, M68000);
     INSN(movem,     48c0, fbc0, CF_ISA_A);
+    INSN(movem,     48c0, fbc0, M68000);
     INSN(ext,       4880, fff8, CF_ISA_A);
+    INSN(ext,       4880, fff8, M68000);
     INSN(ext,       48c0, fff8, CF_ISA_A);
+    INSN(ext,       48c0, fff8, M68000);
     INSN(ext,       49c0, fff8, CF_ISA_A);
+    INSN(ext,       49c0, fff8, M68000);
     INSN(tst,       4a00, ff00, CF_ISA_A);
+    INSN(tst,       4a00, ff00, M68000);
     INSN(tas,       4ac0, ffc0, CF_ISA_B);
+    INSN(tas,       4ac0, ffc0, M68000);
     INSN(halt,      4ac8, ffff, CF_ISA_A);
     INSN(pulse,     4acc, ffff, CF_ISA_A);
     INSN(illegal,   4afc, ffff, CF_ISA_A);
+    INSN(illegal,   4afc, ffff, M68000);
     INSN(mull,      4c00, ffc0, CF_ISA_A);
+    INSN(mull,      4c00, ffc0, LONG_MULDIV);
     INSN(divl,      4c40, ffc0, CF_ISA_A);
+    INSN(divl,      4c40, ffc0, LONG_MULDIV);
     INSN(sats,      4c80, fff8, CF_ISA_B);
     INSN(trap,      4e40, fff0, CF_ISA_A);
+    INSN(trap,      4e40, fff0, M68000);
     INSN(link,      4e50, fff8, CF_ISA_A);
+    INSN(link,      4e50, fff8, M68000);
     INSN(unlk,      4e58, fff8, CF_ISA_A);
+    INSN(unlk,      4e58, fff8, M68000);
     INSN(move_to_usp, 4e60, fff8, USP);
     INSN(move_from_usp, 4e68, fff8, USP);
     INSN(nop,       4e71, ffff, CF_ISA_A);
+    INSN(nop,       4e71, ffff, M68000);
     INSN(stop,      4e72, ffff, CF_ISA_A);
+    INSN(stop,      4e72, ffff, M68000);
     INSN(rte,       4e73, ffff, CF_ISA_A);
+    INSN(rte,       4e73, ffff, M68000);
     INSN(rts,       4e75, ffff, CF_ISA_A);
-    INSN(movec,     4e7b, ffff, CF_ISA_A);
+    INSN(rts,       4e75, ffff, M68000);
+    INSN(movec,     4e7a, fffe, CF_ISA_A);
+    INSN(movec,     4e7a, fffe, M68000);
     INSN(jump,      4e80, ffc0, CF_ISA_A);
+    INSN(jump,      4e80, ffc0, M68000);
     INSN(jump,      4ec0, ffc0, CF_ISA_A);
-    INSN(addsubq,   5180, f1c0, CF_ISA_A);
+    INSN(jump,      4ec0, ffc0, M68000);
+    INSN(addsubq,   5080, f0c0, CF_ISA_A);
+    INSN(addsubq,   5000, f080, M68000);
+    INSN(addsubq,   5080, f0c0, M68000);
     INSN(scc,       50c0, f0f8, CF_ISA_A);
-    INSN(addsubq,   5080, f1c0, CF_ISA_A);
+    INSN(scc_mem,   50c0, f0c0, M68000);
+    INSN(scc,       50c0, f0f8, M68000);
+    INSN(dbcc,      50c8, f0f8, M68000);
     INSN(tpf,       51f8, fff8, CF_ISA_A);

     /* Branch instructions.  */
     INSN(branch,    6000, f000, CF_ISA_A);
+    INSN(branch,    6000, f000, M68000);
     /* Disable long branch instructions, then add back the ones we want.  */
     INSN(undef,     60ff, f0ff, CF_ISA_A); /* All long branches.  */
+    INSN(undef,     60ff, f0ff, M68000); /* All long branches.  */
     INSN(branch,    60ff, f0ff, CF_ISA_B);
     INSN(undef,     60ff, ffff, CF_ISA_B); /* bra.l */
     INSN(branch,    60ff, ffff, BRAL);
+    INSN(branch,    60ff, f0ff, BCCL);

     INSN(moveq,     7000, f100, CF_ISA_A);
+    INSN(moveq,     7000, f100, M68000);
     INSN(mvzs,      7100, f100, CF_ISA_B);
     INSN(or,        8000, f000, CF_ISA_A);
+    INSN(or,        8000, f000, M68000);
     INSN(divw,      80c0, f0c0, CF_ISA_A);
+    INSN(divw,      80c0, f0c0, M68000);
+    INSN(sbcd_reg,  8100, f1f8, M68000);
+    INSN(sbcd_mem,  8108, f1f8, M68000);
     INSN(addsub,    9000, f000, CF_ISA_A);
-    INSN(subx,      9180, f1f8, CF_ISA_A);
+    INSN(addsub,    9000, f000, M68000);
+    INSN(undef,     90c0, f0c0, CF_ISA_A);
+    INSN(subx_reg,  9180, f1f8, CF_ISA_A);
+    INSN(subx_reg,  9100, f138, M68000);
+    INSN(subx_mem,  9108, f138, M68000);
     INSN(suba,      91c0, f1c0, CF_ISA_A);
+    INSN(suba,      90c0, f0c0, M68000);

     INSN(undef_mac, a000, f000, CF_ISA_A);
+    INSN(undef_mac, a000, f000, M68000);
     INSN(mac,       a000, f100, CF_EMAC);
     INSN(from_mac,  a180, f9b0, CF_EMAC);
     INSN(move_mac,  a110, f9fc, CF_EMAC);
@@ -2921,23 +4630,69 @@  void register_m68k_insns (CPUM68KState *env)
     INSN(cmpa,      b0c0, f1c0, CF_ISA_B); /* cmpa.w */
     INSN(cmp,       b080, f1c0, CF_ISA_A);
     INSN(cmpa,      b1c0, f1c0, CF_ISA_A);
+    INSN(cmp,       b000, f100, M68000);
+    INSN(eor,       b100, f100, M68000);
+    INSN(cmpa,      b0c0, f0c0, M68000);
     INSN(eor,       b180, f1c0, CF_ISA_A);
     INSN(and,       c000, f000, CF_ISA_A);
+    INSN(and,       c000, f000, M68000);
     INSN(mulw,      c0c0, f0c0, CF_ISA_A);
+    INSN(mulw,      c0c0, f0c0, M68000);
+    INSN(abcd_reg,  c100, f1f8, M68000);
+    INSN(abcd_mem,  c108, f1f8, M68000);
     INSN(addsub,    d000, f000, CF_ISA_A);
-    INSN(addx,      d180, f1f8, CF_ISA_A);
+    INSN(addsub,    d000, f000, M68000);
+    INSN(undef,     d0c0, f0c0, CF_ISA_A);
+    INSN(addx_reg,      d180, f1f8, CF_ISA_A);
+    INSN(addx_reg,  d100, f138, M68000);
+    INSN(addx_mem,  d108, f138, M68000);
     INSN(adda,      d1c0, f1c0, CF_ISA_A);
+    INSN(adda,      d0c0, f0c0, M68000);
+    /* Bit ops */
     INSN(shift_im,  e080, f0f0, CF_ISA_A);
     INSN(shift_reg, e0a0, f0f0, CF_ISA_A);
+    INSN(shift8_im, e000, f0f0, M68000);
+    INSN(shift16_im, e040, f0f0, M68000);
+    INSN(shift_im,  e080, f0f0, M68000);
+    INSN(shift8_reg, e020, f0f0, M68000);
+    INSN(shift16_reg, e060, f0f0, M68000);
+    INSN(shift_reg, e0a0, f0f0, M68000);
+    INSN(shift_mem, e0c0, fcc0, M68000);
+    INSN(rotate_im, e090, f0f0, M68000);
+    INSN(rotate8_im, e010, f0f0, M68000);
+    INSN(rotate16_im, e050, f0f0, M68000);
+    INSN(rotate_reg, e0b0, f0f0, M68000);
+    INSN(rotate8_reg, e030, f0f0, M68000);
+    INSN(rotate16_reg,e070, f0f0, M68000);
+    INSN(rotate_mem, e4c0, fcc0, M68000);
+    INSN(bitfield_mem,e8c0, f8c0, BITFIELD);
+    INSN(bitfield_reg,e8c0, f8f8, BITFIELD);
+    /* FPU */
     INSN(undef_fpu, f000, f000, CF_ISA_A);
+    INSN(undef_fpu, f000, f000, M68000);
     INSN(fpu,       f200, ffc0, CF_FPU);
     INSN(fbcc,      f280, ffc0, CF_FPU);
     INSN(frestore,  f340, ffc0, CF_FPU);
     INSN(fsave,     f340, ffc0, CF_FPU);
-    INSN(intouch,   f340, ffc0, CF_ISA_A);
+    INSN(fpu,       f200, ffc0, FPU);
+    INSN(fscc_mem,  f240, ffc0, FPU);
+    INSN(fscc_reg,  f240, fff8, FPU);
+    INSN(fbcc,      f280, ffc0, FPU);
+    INSN(frestore,  f300, ffc0, FPU);
+    INSN(fsave,     f340, ffc0, FPU);
+	INSN(intouch,   f340, ffc0, CF_ISA_A);
+    /* MMU */
     INSN(cpushl,    f428, ff38, CF_ISA_A);
-    INSN(wddata,    fb00, ff00, CF_ISA_A);
+    INSN(cpushl,    f478, ff78, M68000);
+	INSN(cinva,		f4d8, f4d8, M68000);
+	INSN(pflush,   	f500, f500, M68000);
+
+    INSN(move16,	f600, f600, M68000);
+	INSN(wddata,    fb00, ff00, CF_ISA_A);
     INSN(wdebug,    fbc0, ffc0, CF_ISA_A);
+#ifdef CONFIG_EMULOP
+    INSN(emulop_exec_return, 7100, ffff, M68000);
+#endif
 #undef INSN
 }

@@ -2947,8 +4702,10 @@  static void disas_m68k_insn(CPUState * env,
DisasContext *s)
 {
     uint16_t insn;

-    insn = lduw_code(s->pc);
-    s->pc += 2;
+    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
+        tcg_gen_debug_insn_start(s->pc);
+
+    insn = read_im16(s);

     opcode_table[insn](s, insn);
 }
@@ -3073,9 +4830,6 @@  gen_intermediate_code_internal(CPUState *env,
TranslationBlock *tb,
         tb->size = dc->pc - pc_start;
         tb->icount = num_insns;
     }
-
-    //optimize_flags();
-    //expand_target_qops();
 }

 void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
@@ -3093,20 +4847,18 @@  void cpu_dump_state(CPUState *env, FILE *f,
fprintf_function cpu_fprintf,
 {
     int i;
     uint16_t sr;
-    CPU_DoubleU u;
     for (i = 0; i < 8; i++)
       {
-        u.d = env->fregs[i];
-        cpu_fprintf (f, "D%d = %08x   A%d = %08x   F%d = %08x%08x (%12g)\n",
+        cpu_fprintf (f, "D%d = %08x   A%d = %08x   "
+                        "F%d = %" PRIxFPH " %" PRIxFPL "\n",
                      i, env->dregs[i], i, env->aregs[i],
-                     i, u.l.upper, u.l.lower, *(double *)&u.d);
+                     i, env->fregs[i].d.high, env->fregs[i].d.low);
       }
     cpu_fprintf (f, "PC = %08x   ", env->pc);
     sr = env->sr;
     cpu_fprintf (f, "SR = %04x %c%c%c%c%c ", sr, (sr & 0x10) ? 'X' : '-',
                  (sr & CCF_N) ? 'N' : '-', (sr & CCF_Z) ? 'Z' : '-',
                  (sr & CCF_V) ? 'V' : '-', (sr & CCF_C) ? 'C' : '-');
-    cpu_fprintf (f, "FPRESULT = %12g\n", *(double *)&env->fp_result);
 }

 void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
diff --git tests/m68k/Makefile tests/m68k/Makefile
new file mode 100644
index 0000000..27525d3
--- /dev/null
+++ tests/m68k/Makefile
@@ -0,0 +1,12 @@ 
+TESTS=fmovecr fmove fmovem fsub fdiv fmul fabs fgetexp fscale flogn fetox \
+      bfins inf
+
+all: $(TESTS)
+
+%: %.S
+	m68k-linux-gnu-gcc  -m68040 -nostartfiles  -nodefaultlibs  -nostdlib -o $@ $<
+
+.PHONY: clean
+
+clean:
+	rm -f $(TESTS)
diff --git tests/m68k/bfins.S tests/m68k/bfins.S
new file mode 100644
index 0000000..a0b27f9
--- /dev/null
+++ tests/m68k/bfins.S
@@ -0,0 +1,23 @@ 
+	.include "trap.i"
+
+	.data
+.A:	.long 0
+	.text
+	.globl _start
+_start:
+	move.l #0,%d1
+	move.l #1,%d0
+	bfins %d0,%d1,4,4
+	move.l #3,%d0
+	bfins %d0,%d1,8,2
+	move.l #0,%d0
+	bfins %d0,%d1,8,16
+
+	move.l #1,%d0
+	lea .A,%a0
+	bfins %d0,(%a0),4,4
+	move.l #3,%d0
+	bfins %d0,(%a0),8,2
+	move.l #0,%d0
+	bfins %d0,(%a0),8,16
+	exit 0
diff --git tests/m68k/fabs.S tests/m68k/fabs.S
new file mode 100644
index 0000000..cbe2a4a
--- /dev/null
+++ tests/m68k/fabs.S
@@ -0,0 +1,9 @@ 
+	.include "trap.i"
+
+	.text
+	.globl _start
+_start:
+	fabs.b #-55, %fp0
+	fmove.l #-1024, %fp1
+	fabs.x %fp1
+	exit 0
diff --git tests/m68k/fdiv.S tests/m68k/fdiv.S
new file mode 100644
index 0000000..a5e3656
--- /dev/null
+++ tests/m68k/fdiv.S
@@ -0,0 +1,10 @@ 
+	.include "trap.i"
+
+	.text
+	.globl _start
+_start:
+# Pi
+	fmove.b #10, %fp0
+	fmove.b #3, %fp1
+	fdiv.x  %fp1, %fp0
+	exit 0
diff --git tests/m68k/fetox.S tests/m68k/fetox.S
new file mode 100644
index 0000000..302072b
--- /dev/null
+++ tests/m68k/fetox.S
@@ -0,0 +1,8 @@ 
+	.include "trap.i"
+
+	.text
+	.globl _start
+_start:
+	fmove.l #1,%fp0		// 1
+	fetox.x %fp0,%fp0	// e
+	exit 0
diff --git tests/m68k/fgetexp.S tests/m68k/fgetexp.S
new file mode 100644
index 0000000..d17f7ab
--- /dev/null
+++ tests/m68k/fgetexp.S
@@ -0,0 +1,8 @@ 
+	.include "trap.i"
+
+	.text
+	.globl _start
+_start:
+	fmove.l #4096, %fp0
+	fgetexp.x %fp0, %fp1
+	exit 0
diff --git tests/m68k/flogn.S tests/m68k/flogn.S
new file mode 100644
index 0000000..a27835e
--- /dev/null
+++ tests/m68k/flogn.S
@@ -0,0 +1,8 @@ 
+	.include "trap.i"
+
+	.text
+	.globl _start
+_start:
+	fmovecr.x #0x0C,%fp0	// e
+	flogn.x %fp0,%fp0	// 1
+	exit 0
diff --git tests/m68k/fmove.S tests/m68k/fmove.S
new file mode 100644
index 0000000..d08c866
--- /dev/null
+++ tests/m68k/fmove.S
@@ -0,0 +1,60 @@ 
+	.include "trap.i"
+
+	.data
+tmp:	.long 0x88776655
+pi:	.long 0x40000000, 0xc90fdaa2, 0x2168C235
+store:   .long 0, 0, 0
+
+	.text
+	.globl _start
+_start:
+	lea pi,%a0
+	move.l (%a0), %d0
+	fmove.x (%a0), %fp4
+	fmove.b %fp4, store
+	fmove.w %fp4, store
+	fmove.l %fp4, store
+	fmove.s %fp4, store
+	fmove.d %fp4, store
+	fmove.x %fp4, store
+	# Dn
+
+	move.l #-1, %d3
+	fmove.b %d3, %fp0
+	fmove.w %d3, %fp1
+	fmove.l %d3, %fp2
+	fmove.s %d3, %fp3
+
+	move.l #1, %d1
+	fmove.b %d1, %fp0
+	fmove.w %d1, %fp1
+	fmove.l %d1, %fp2
+	fmove.s %d1, %fp3
+
+	move.l #0x11223344, %d1
+	fmove.b %d1, %fp1
+	fmove.w %d1, %fp2
+	fmove.l %d1, %fp3
+	fmove.s %d1, %fp4
+
+	# (A0)
+
+	lea tmp,%a0
+	fmove.b (%a0), %fp0
+	fmove.w (%a0), %fp1
+	fmove.l (%a0), %fp2
+	fmove.l (%a0), %fp3
+	lea pi,%a0
+	fmove.x (%a0), %fp4
+
+	# immediate values
+
+	fmove.b #0xFF,%fp0
+	fmove.w #0xFABC,%fp1
+	fmove.l #0xFABCDEFA,%fp2
+	fmove.s #0xDEADBEAF,%fp3
+	fmove.d #0f4.29497E+09,%fp4
+	fmove.x #0xFABCDEFADEADBEAF12345678,%fp5
+	fmove.p #0xFABCDEFADEADBEAF12345678,%fp6
+
+	exit 0
diff --git tests/m68k/fmovecr.S tests/m68k/fmovecr.S
new file mode 100644
index 0000000..c6cd82b
--- /dev/null
+++ tests/m68k/fmovecr.S
@@ -0,0 +1,29 @@ 
+	.include "trap.i"
+
+	.text
+	.globl _start
+_start:
+	fmovecr.x #0x00,%fp0
+	fmovecr.x #0x0B,%fp0
+	fmovecr.x #0x0C,%fp0
+	fmovecr.x #0x0D,%fp0
+	fmovecr.x #0x0E,%fp0
+	fmovecr.x #0x0F,%fp0
+	fmovecr.x #0x30,%fp0
+	fmovecr.x #0x31,%fp0
+	fmovecr.x #0x32,%fp0
+	fmovecr.x #0x33,%fp0
+	fmovecr.x #0x34,%fp0
+	fmovecr.x #0x35,%fp0
+	fmovecr.x #0x36,%fp0
+	fmovecr.x #0x37,%fp0
+	fmovecr.x #0x38,%fp0
+	fmovecr.x #0x39,%fp0
+	fmovecr.x #0x3A,%fp0
+	fmovecr.x #0x3B,%fp0
+	fmovecr.x #0x3c,%fp0
+	fmovecr.x #0x3d,%fp0
+	fmovecr.x #0x3e,%fp0
+	fmovecr.x #0x3f,%fp0
+
+	exit 0
diff --git tests/m68k/fmovem.S tests/m68k/fmovem.S
new file mode 100644
index 0000000..35da35f
--- /dev/null
+++ tests/m68k/fmovem.S
@@ -0,0 +1,17 @@ 
+	.include "trap.i"
+
+	.data
+pi:	.long 0x40000000
+	.long 0xc90fdaa2
+	.long 0x2168C235
+ln2:	.long 0x3ffe0000
+	.long 0xb17217f7
+	.long 0xd1cf79ac
+
+	.text
+	.globl _start
+_start:
+	lea pi,%a0
+	fmovem.x (%a0), %fp2-%fp3
+	fmovem.x (%a0)+, %fp0-%fp1
+	exit 0
diff --git tests/m68k/fmul.S tests/m68k/fmul.S
new file mode 100644
index 0000000..1b989fc
--- /dev/null
+++ tests/m68k/fmul.S
@@ -0,0 +1,9 @@ 
+	.include "trap.i"
+
+	.text
+	.globl _start
+_start:
+	fmove.b #255, %fp0
+	fmove.w #1023, %fp1
+	fmul.x  %fp1, %fp0
+	exit 0
diff --git tests/m68k/fscale.S tests/m68k/fscale.S
new file mode 100644
index 0000000..f6a5c62
--- /dev/null
+++ tests/m68k/fscale.S
@@ -0,0 +1,9 @@ 
+	.include "trap.i"
+
+	.text
+	.globl _start
+_start:
+	fmove.l #2, %fp0
+	fmovecr.x #0x00,%fp1
+	fscale.x %fp0, %fp1
+	exit 0
diff --git tests/m68k/fsub.S tests/m68k/fsub.S
new file mode 100644
index 0000000..cf1a77a
--- /dev/null
+++ tests/m68k/fsub.S
@@ -0,0 +1,11 @@ 
+	.include "trap.i"
+
+	.text
+	.globl _start
+_start:
+# Pi
+	fmovecr.x #0x00, %fp0
+	fmove.b   #3, %fp1
+# 0.1415926535897932
+	fsub.x      %fp1, %fp0
+	exit 0
diff --git tests/m68k/inf.S tests/m68k/inf.S
new file mode 100644
index 0000000..2b2de84
--- /dev/null
+++ tests/m68k/inf.S
@@ -0,0 +1,17 @@ 
+	.include "trap.i"
+
+	.data
+X:	.long 0x7ffe0000, 0x80000000, 0x00000000
+
+	.text
+	.globl _start
+_start:
+	fmove.x X, %fp0
+	fmove.x X, %fp1
+	fadd.x %fp0, %fp1
+	fmul.l #2,%fp0
+	fcmp.x %fp0, %fp1
+	fbeq a
+	nop
+a:
+	exit 0
diff --git tests/m68k/trap.i tests/m68k/trap.i
new file mode 100644
index 0000000..ce7aa1e
--- /dev/null
+++ tests/m68k/trap.i
@@ -0,0 +1,5 @@ 
+.macro exit value
+        move.l #\value,%d1
+        move.l #1, %d0
+        trap #0
+.endm