Commit e6e5906b6e0a81718066ca43aef57515026c6624

Authored by pbrook
1 parent 223b8a40

ColdFire target.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2196 c046a42c-6fe2-441c-8c8c-71466251a162
Makefile.target
... ... @@ -197,6 +197,9 @@ OBJS+=nwfpe/fpa11.o nwfpe/fpa11_cpdo.o \
197 197 nwfpe/fpa11_cpdt.o nwfpe/fpa11_cprt.o nwfpe/fpopcode.o nwfpe/single_cpdo.o \
198 198 nwfpe/double_cpdo.o nwfpe/extended_cpdo.o arm-semi.o
199 199 endif
  200 +ifeq ($(TARGET_ARCH), m68k)
  201 +OBJS+= m68k-sim.o m68k-semi.o
  202 +endif
200 203 SRCS:= $(OBJS:.o=.c)
201 204 OBJS+= libqemu.a
202 205  
... ... @@ -241,6 +244,10 @@ ifeq ($(TARGET_BASE_ARCH), sh4)
241 244 LIBOBJS+= op_helper.o helper.o
242 245 endif
243 246  
  247 +ifeq ($(TARGET_BASE_ARCH), m68k)
  248 +LIBOBJS+= helper.o
  249 +endif
  250 +
244 251 # NOTE: the disassembler code is only needed for debugging
245 252 LIBOBJS+=disas.o
246 253 ifeq ($(findstring i386, $(TARGET_ARCH) $(ARCH)),i386)
... ...
configure
... ... @@ -362,7 +362,7 @@ if test -z "$target_list" ; then
362 362 fi
363 363 # the following are Linux specific
364 364 if [ "$user" = "yes" ] ; then
365   - target_list="i386-user arm-user armeb-user sparc-user ppc-user mips-user mipsel-user $target_list"
  365 + target_list="i386-user arm-user armeb-user sparc-user ppc-user mips-user mipsel-user m68k-user $target_list"
366 366 fi
367 367 else
368 368 target_list=`echo "$target_list" | sed -e 's/,/ /g'`
... ... @@ -727,6 +727,7 @@ target_bigendian="no"
727 727 [ "$target_cpu" = "ppc64" ] && target_bigendian=yes
728 728 [ "$target_cpu" = "mips" ] && target_bigendian=yes
729 729 [ "$target_cpu" = "sh4eb" ] && target_bigendian=yes
  730 +[ "$target_cpu" = "m68k" ] && target_bigendian=yes
730 731 target_softmmu="no"
731 732 if expr $target : '.*-softmmu' > /dev/null ; then
732 733 target_softmmu="yes"
... ... @@ -822,6 +823,11 @@ elif test "$target_cpu" = "sh4" -o "$target_cpu" = "sh4eb" ; then
822 823 echo "#define TARGET_ARCH \"sh4\"" >> $config_h
823 824 echo "#define TARGET_SH4 1" >> $config_h
824 825 bflt="yes"
  826 +elif test "$target_cpu" = "m68k" ; then
  827 + echo "TARGET_ARCH=m68k" >> $config_mak
  828 + echo "#define TARGET_ARCH \"m68k\"" >> $config_h
  829 + echo "#define TARGET_M68K 1" >> $config_h
  830 + bflt="yes"
825 831 else
826 832 echo "Unsupported target CPU"
827 833 exit 1
... ... @@ -839,7 +845,7 @@ if test "$target_user_only" = "yes" ; then
839 845 echo "#define CONFIG_USER_ONLY 1" >> $config_h
840 846 fi
841 847  
842   -if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" -o "$target_cpu" = "sparc" -o "$target_cpu" = "sparc64"; then
  848 +if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" -o "$target_cpu" = "sparc" -o "$target_cpu" = "sparc64" -o "$target_cpu" = "m68k"; then
843 849 echo "CONFIG_SOFTFLOAT=yes" >> $config_mak
844 850 echo "#define CONFIG_SOFTFLOAT 1" >> $config_h
845 851 fi
... ...
cpu-all.h
... ... @@ -725,6 +725,13 @@ void page_unprotect_range(target_ulong data, target_ulong data_size);
725 725 #define cpu_gen_code cpu_ppc_gen_code
726 726 #define cpu_signal_handler cpu_ppc_signal_handler
727 727  
  728 +#elif defined(TARGET_M68K)
  729 +#define CPUState CPUM68KState
  730 +#define cpu_init cpu_m68k_init
  731 +#define cpu_exec cpu_m68k_exec
  732 +#define cpu_gen_code cpu_m68k_gen_code
  733 +#define cpu_signal_handler cpu_m68k_signal_handler
  734 +
728 735 #elif defined(TARGET_MIPS)
729 736 #define CPUState CPUMIPSState
730 737 #define cpu_init cpu_mips_init
... ...
cpu-exec.c
... ... @@ -40,14 +40,14 @@ int tb_invalidated_flag;
40 40 //#define DEBUG_EXEC
41 41 //#define DEBUG_SIGNAL
42 42  
43   -#if defined(TARGET_ARM) || defined(TARGET_SPARC)
  43 +#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_M68K)
44 44 /* XXX: unify with i386 target */
45 45 void cpu_loop_exit(void)
46 46 {
47 47 longjmp(env->jmp_env, 1);
48 48 }
49 49 #endif
50   -#if !(defined(TARGET_SPARC) || defined(TARGET_SH4))
  50 +#if !(defined(TARGET_SPARC) || defined(TARGET_SH4) || defined(TARGET_M68K))
51 51 #define reg_T2
52 52 #endif
53 53  
... ... @@ -194,6 +194,10 @@ static inline TranslationBlock *tb_find_fast(void)
194 194 flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK);
195 195 cs_base = 0;
196 196 pc = env->PC;
  197 +#elif defined(TARGET_M68K)
  198 + flags = env->fpcr & M68K_FPCR_PREC;
  199 + cs_base = 0;
  200 + pc = env->pc;
197 201 #elif defined(TARGET_SH4)
198 202 flags = env->sr & (SR_MD | SR_RB);
199 203 cs_base = 0; /* XXXXX */
... ... @@ -370,6 +374,10 @@ int cpu_exec(CPUState *env1)
370 374 saved_regwptr = REGWPTR;
371 375 #endif
372 376 #elif defined(TARGET_PPC)
  377 +#elif defined(TARGET_M68K)
  378 + env->cc_op = CC_OP_FLAGS;
  379 + env->cc_dest = env->sr & 0xf;
  380 + env->cc_x = (env->sr >> 4) & 1;
373 381 #elif defined(TARGET_MIPS)
374 382 #elif defined(TARGET_SH4)
375 383 /* XXXXX */
... ... @@ -632,6 +640,12 @@ int cpu_exec(CPUState *env1)
632 640 cpu_dump_state(env, logfile, fprintf, 0);
633 641 #elif defined(TARGET_PPC)
634 642 cpu_dump_state(env, logfile, fprintf, 0);
  643 +#elif defined(TARGET_M68K)
  644 + cpu_m68k_flush_flags(env, env->cc_op);
  645 + env->cc_op = CC_OP_FLAGS;
  646 + env->sr = (env->sr & 0xffe0)
  647 + | env->cc_dest | (env->cc_x << 4);
  648 + cpu_dump_state(env, logfile, fprintf, 0);
635 649 #elif defined(TARGET_MIPS)
636 650 cpu_dump_state(env, logfile, fprintf, 0);
637 651 #elif defined(TARGET_SH4)
... ... @@ -846,6 +860,11 @@ int cpu_exec(CPUState *env1)
846 860 REGWPTR = saved_regwptr;
847 861 #endif
848 862 #elif defined(TARGET_PPC)
  863 +#elif defined(TARGET_M68K)
  864 + cpu_m68k_flush_flags(env, env->cc_op);
  865 + env->cc_op = CC_OP_FLAGS;
  866 + env->sr = (env->sr & 0xffe0)
  867 + | env->cc_dest | (env->cc_x << 4);
849 868 #elif defined(TARGET_MIPS)
850 869 #elif defined(TARGET_SH4)
851 870 /* XXXXX */
... ... @@ -1103,6 +1122,45 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1103 1122 return 1;
1104 1123 }
1105 1124  
  1125 +#elif defined(TARGET_M68K)
  1126 +static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
  1127 + int is_write, sigset_t *old_set,
  1128 + void *puc)
  1129 +{
  1130 + TranslationBlock *tb;
  1131 + int ret;
  1132 +
  1133 + if (cpu_single_env)
  1134 + env = cpu_single_env; /* XXX: find a correct solution for multithread */
  1135 +#if defined(DEBUG_SIGNAL)
  1136 + printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
  1137 + pc, address, is_write, *(unsigned long *)old_set);
  1138 +#endif
  1139 + /* XXX: locking issue */
  1140 + if (is_write && page_unprotect(address, pc, puc)) {
  1141 + return 1;
  1142 + }
  1143 + /* see if it is an MMU fault */
  1144 + ret = cpu_m68k_handle_mmu_fault(env, address, is_write, 1, 0);
  1145 + if (ret < 0)
  1146 + return 0; /* not an MMU fault */
  1147 + if (ret == 0)
  1148 + return 1; /* the MMU fault was handled without causing real CPU fault */
  1149 + /* now we have a real cpu fault */
  1150 + tb = tb_find_pc(pc);
  1151 + if (tb) {
  1152 + /* the PC is inside the translated code. It means that we have
  1153 + a virtual CPU fault */
  1154 + cpu_restore_state(tb, env, pc, puc);
  1155 + }
  1156 + /* we restore the process signal mask as the sigreturn should
  1157 + do it (XXX: use sigsetjmp) */
  1158 + sigprocmask(SIG_SETMASK, old_set, NULL);
  1159 + cpu_loop_exit();
  1160 + /* never comes here */
  1161 + return 1;
  1162 +}
  1163 +
1106 1164 #elif defined (TARGET_MIPS)
1107 1165 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1108 1166 int is_write, sigset_t *old_set,
... ...
... ... @@ -186,6 +186,8 @@ void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
186 186 disasm_info.mach = bfd_mach_ppc;
187 187 #endif
188 188 print_insn = print_insn_ppc;
  189 +#elif defined(TARGET_M68K)
  190 + print_insn = print_insn_m68k;
189 191 #elif defined(TARGET_MIPS)
190 192 #ifdef TARGET_WORDS_BIGENDIAN
191 193 print_insn = print_insn_big_mips;
... ... @@ -385,6 +387,8 @@ void monitor_disas(CPUState *env,
385 387 disasm_info.mach = bfd_mach_ppc;
386 388 #endif
387 389 print_insn = print_insn_ppc;
  390 +#elif defined(TARGET_M68K)
  391 + print_insn = print_insn_m68k;
388 392 #elif defined(TARGET_MIPS)
389 393 #ifdef TARGET_WORDS_BIGENDIAN
390 394 print_insn = print_insn_big_mips;
... ...
fpu/softfloat-native.c
... ... @@ -221,6 +221,11 @@ float128 float64_to_float128( float64 a STATUS_PARAM)
221 221 /*----------------------------------------------------------------------------
222 222 | Software IEC/IEEE double-precision operations.
223 223 *----------------------------------------------------------------------------*/
  224 +float64 float64_trunc_to_int( float64 a STATUS_PARAM )
  225 +{
  226 + return trunc(a);
  227 +}
  228 +
224 229 float64 float64_round_to_int( float64 a STATUS_PARAM )
225 230 {
226 231 #if defined(__arm__)
... ... @@ -289,6 +294,17 @@ char float64_is_signaling_nan( float64 a1)
289 294  
290 295 }
291 296  
  297 +char float64_is_nan( float64 a1 )
  298 +{
  299 + float64u u;
  300 + uint64_t a;
  301 + u.f = a1;
  302 + a = u.i;
  303 +
  304 + return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) );
  305 +
  306 +}
  307 +
292 308 #ifdef FLOATX80
293 309  
294 310 /*----------------------------------------------------------------------------
... ...
fpu/softfloat-native.h
... ... @@ -214,6 +214,7 @@ float128 float64_to_float128( float64 STATUS_PARAM );
214 214 | Software IEC/IEEE double-precision operations.
215 215 *----------------------------------------------------------------------------*/
216 216 float64 float64_round_to_int( float64 STATUS_PARAM );
  217 +float64 float64_trunc_to_int( float64 STATUS_PARAM );
217 218 INLINE float64 float64_add( float64 a, float64 b STATUS_PARAM)
218 219 {
219 220 return a + b;
... ... @@ -265,6 +266,7 @@ INLINE char float64_unordered( float64 a, float64 b STATUS_PARAM)
265 266 char float64_compare( float64, float64 STATUS_PARAM );
266 267 char float64_compare_quiet( float64, float64 STATUS_PARAM );
267 268 char float64_is_signaling_nan( float64 );
  269 +flag float64_is_nan( float64 );
268 270  
269 271 INLINE float64 float64_abs(float64 a)
270 272 {
... ...
fpu/softfloat.c
... ... @@ -2483,6 +2483,17 @@ float64 float64_round_to_int( float64 a STATUS_PARAM )
2483 2483  
2484 2484 }
2485 2485  
  2486 +float64 float64_trunc_to_int( float64 a STATUS_PARAM)
  2487 +{
  2488 + int oldmode;
  2489 + float64 res;
  2490 + oldmode = STATUS(float_rounding_mode);
  2491 + STATUS(float_rounding_mode) = float_round_to_zero;
  2492 + res = float64_round_to_int(a STATUS_VAR);
  2493 + STATUS(float_rounding_mode) = oldmode;
  2494 + return res;
  2495 +}
  2496 +
2486 2497 /*----------------------------------------------------------------------------
2487 2498 | Returns the result of adding the absolute values of the double-precision
2488 2499 | floating-point values `a' and `b'. If `zSign' is 1, the sum is negated
... ...
fpu/softfloat.h
... ... @@ -237,6 +237,7 @@ char float32_lt_quiet( float32, float32 STATUS_PARAM );
237 237 char float32_compare( float32, float32 STATUS_PARAM );
238 238 char float32_compare_quiet( float32, float32 STATUS_PARAM );
239 239 char float32_is_signaling_nan( float32 );
  240 +flag float64_is_nan( float64 a );
240 241  
241 242 INLINE float32 float32_abs(float32 a)
242 243 {
... ... @@ -269,6 +270,7 @@ float128 float64_to_float128( float64 STATUS_PARAM );
269 270 | Software IEC/IEEE double-precision operations.
270 271 *----------------------------------------------------------------------------*/
271 272 float64 float64_round_to_int( float64 STATUS_PARAM );
  273 +float64 float64_trunc_to_int( float64 STATUS_PARAM );
272 274 float64 float64_add( float64, float64 STATUS_PARAM );
273 275 float64 float64_sub( float64, float64 STATUS_PARAM );
274 276 float64 float64_mul( float64, float64 STATUS_PARAM );
... ...
gdbstub.c
... ... @@ -434,6 +434,73 @@ static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
434 434 ptr += 8 * 12 + 4;
435 435 cpsr_write (env, tswapl(*(uint32_t *)ptr), 0xffffffff);
436 436 }
  437 +#elif defined (TARGET_M68K)
  438 +static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
  439 +{
  440 + int i;
  441 + uint8_t *ptr;
  442 + CPU_DoubleU u;
  443 +
  444 + ptr = mem_buf;
  445 + /* D0-D7 */
  446 + for (i = 0; i < 8; i++) {
  447 + *(uint32_t *)ptr = tswapl(env->dregs[i]);
  448 + ptr += 4;
  449 + }
  450 + /* A0-A7 */
  451 + for (i = 0; i < 8; i++) {
  452 + *(uint32_t *)ptr = tswapl(env->aregs[i]);
  453 + ptr += 4;
  454 + }
  455 + *(uint32_t *)ptr = tswapl(env->sr);
  456 + ptr += 4;
  457 + *(uint32_t *)ptr = tswapl(env->pc);
  458 + ptr += 4;
  459 + /* F0-F7. The 68881/68040 have 12-bit extended precision registers.
  460 + ColdFire has 8-bit double precision registers. */
  461 + for (i = 0; i < 8; i++) {
  462 + u.d = env->fregs[i];
  463 + *(uint32_t *)ptr = tswap32(u.l.upper);
  464 + *(uint32_t *)ptr = tswap32(u.l.lower);
  465 + }
  466 + /* FP control regs (not implemented). */
  467 + memset (ptr, 0, 3 * 4);
  468 + ptr += 3 * 4;
  469 +
  470 + return ptr - mem_buf;
  471 +}
  472 +
  473 +static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
  474 +{
  475 + int i;
  476 + uint8_t *ptr;
  477 + CPU_DoubleU u;
  478 +
  479 + ptr = mem_buf;
  480 + /* D0-D7 */
  481 + for (i = 0; i < 8; i++) {
  482 + env->dregs[i] = tswapl(*(uint32_t *)ptr);
  483 + ptr += 4;
  484 + }
  485 + /* A0-A7 */
  486 + for (i = 0; i < 8; i++) {
  487 + env->aregs[i] = tswapl(*(uint32_t *)ptr);
  488 + ptr += 4;
  489 + }
  490 + env->sr = tswapl(*(uint32_t *)ptr);
  491 + ptr += 4;
  492 + env->pc = tswapl(*(uint32_t *)ptr);
  493 + ptr += 4;
  494 + /* F0-F7. The 68881/68040 have 12-bit extended precision registers.
  495 + ColdFire has 8-bit double precision registers. */
  496 + for (i = 0; i < 8; i++) {
  497 + u.l.upper = tswap32(*(uint32_t *)ptr);
  498 + u.l.lower = tswap32(*(uint32_t *)ptr);
  499 + env->fregs[i] = u.d;
  500 + }
  501 + /* FP control regs (not implemented). */
  502 + ptr += 3 * 4;
  503 +}
437 504 #elif defined (TARGET_MIPS)
438 505 static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
439 506 {
... ...
hw/pl110.c
... ... @@ -185,10 +185,11 @@ static void pl110_update_display(void *opaque)
185 185 addr = base;
186 186  
187 187 dirty = cpu_physical_memory_get_dirty(addr, VGA_DIRTY_FLAG);
  188 + new_dirty = dirty;
188 189 for (i = 0; i < s->rows; i++) {
189   - new_dirty = 0;
190   - if ((addr & TARGET_PAGE_MASK) + src_width >= TARGET_PAGE_SIZE) {
  190 + if ((addr & ~TARGET_PAGE_MASK) + src_width >= TARGET_PAGE_SIZE) {
191 191 uint32_t tmp;
  192 + new_dirty = 0;
192 193 for (tmp = 0; tmp < src_width; tmp += TARGET_PAGE_SIZE) {
193 194 new_dirty |= cpu_physical_memory_get_dirty(addr + tmp,
194 195 VGA_DIRTY_FLAG);
... ...
linux-user/elfload.c
... ... @@ -288,6 +288,31 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
288 288  
289 289 #endif
290 290  
  291 +#ifdef TARGET_M68K
  292 +
  293 +#define ELF_START_MMAP 0x80000000
  294 +
  295 +#define elf_check_arch(x) ( (x) == EM_68K )
  296 +
  297 +#define ELF_CLASS ELFCLASS32
  298 +#define ELF_DATA ELFDATA2MSB
  299 +#define ELF_ARCH EM_68K
  300 +
  301 +/* ??? Does this need to do anything?
  302 +#define ELF_PLAT_INIT(_r) */
  303 +
  304 +static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
  305 +{
  306 + regs->usp = infop->start_stack;
  307 + regs->sr = 0;
  308 + regs->pc = infop->entry;
  309 +}
  310 +
  311 +#define USE_ELF_CORE_DUMP
  312 +#define ELF_EXEC_PAGESIZE 8192
  313 +
  314 +#endif
  315 +
291 316 #ifndef ELF_PLATFORM
292 317 #define ELF_PLATFORM (NULL)
293 318 #endif
... ...
linux-user/m68k-semi.c 0 โ†’ 100644
  1 +/*
  2 + * m68k/ColdFire Semihosting ssycall interface
  3 + *
  4 + * Copyright (c) 2005 CodeSourcery, LLC. Written by Paul Brook.
  5 + *
  6 + * This program is free software; you can redistribute it and/or modify
  7 + * it under the terms of the GNU General Public License as published by
  8 + * the Free Software Foundation; either version 2 of the License, or
  9 + * (at your option) any later version.
  10 + *
  11 + * This program is distributed in the hope that it will be useful,
  12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14 + * GNU General Public License for more details.
  15 + *
  16 + * You should have received a copy of the GNU General Public License
  17 + * along with this program; if not, write to the Free Software
  18 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19 + */
  20 +
  21 +#include <sys/types.h>
  22 +#include <sys/stat.h>
  23 +#include <errno.h>
  24 +#include <fcntl.h>
  25 +#include <unistd.h>
  26 +#include <stdlib.h>
  27 +#include <stdio.h>
  28 +#include <sys/time.h>
  29 +#include <time.h>
  30 +
  31 +#include "qemu.h"
  32 +
  33 +#define HOSTED_EXIT 0
  34 +#define HOSTED_PUTCHAR 1 /* Obsolete */
  35 +#define HOSTED_OPEN 2
  36 +#define HOSTED_CLOSE 3
  37 +#define HOSTED_READ 4
  38 +#define HOSTED_WRITE 5
  39 +#define HOSTED_LSEEK 6
  40 +#define HOSTED_RENAME 7
  41 +#define HOSTED_UNLINK 8
  42 +#define HOSTED_STAT 9
  43 +#define HOSTED_FSTAT 10
  44 +#define HOSTED_GETTIMEOFDAY 11
  45 +#define HOSTED_ISATTY 12
  46 +#define HOSTED_SYSTEM 13
  47 +
  48 +typedef uint32_t gdb_mode_t;
  49 +typedef uint32_t gdb_time_t;
  50 +
  51 +struct m68k_gdb_stat {
  52 + uint32_t gdb_st_dev; /* device */
  53 + uint32_t gdb_st_ino; /* inode */
  54 + gdb_mode_t gdb_st_mode; /* protection */
  55 + uint32_t gdb_st_nlink; /* number of hard links */
  56 + uint32_t gdb_st_uid; /* user ID of owner */
  57 + uint32_t gdb_st_gid; /* group ID of owner */
  58 + uint32_t gdb_st_rdev; /* device type (if inode device) */
  59 + uint64_t gdb_st_size; /* total size, in bytes */
  60 + uint64_t gdb_st_blksize; /* blocksize for filesystem I/O */
  61 + uint64_t gdb_st_blocks; /* number of blocks allocated */
  62 + gdb_time_t gdb_st_atime; /* time of last access */
  63 + gdb_time_t gdb_st_mtime; /* time of last modification */
  64 + gdb_time_t gdb_st_ctime; /* time of last change */
  65 +};
  66 +
  67 +struct gdb_timeval {
  68 + gdb_time_t tv_sec; /* second */
  69 + uint64_t tv_usec; /* microsecond */
  70 +};
  71 +
  72 +#define GDB_O_RDONLY 0x0
  73 +#define GDB_O_WRONLY 0x1
  74 +#define GDB_O_RDWR 0x2
  75 +#define GDB_O_APPEND 0x8
  76 +#define GDB_O_CREAT 0x200
  77 +#define GDB_O_TRUNC 0x400
  78 +#define GDB_O_EXCL 0x800
  79 +
  80 +static int translate_openflags(int flags)
  81 +{
  82 + int hf;
  83 +
  84 + if (flags & GDB_O_WRONLY)
  85 + hf = O_WRONLY;
  86 + else if (flags & GDB_O_RDWR)
  87 + hf = O_RDWR;
  88 + else
  89 + hf = O_RDONLY;
  90 +
  91 + if (flags & GDB_O_APPEND) hf |= O_APPEND;
  92 + if (flags & GDB_O_CREAT) hf |= O_CREAT;
  93 + if (flags & GDB_O_TRUNC) hf |= O_TRUNC;
  94 + if (flags & GDB_O_EXCL) hf |= O_EXCL;
  95 +
  96 + return hf;
  97 +}
  98 +
  99 +static void translate_stat(struct m68k_gdb_stat *p, struct stat *s)
  100 +{
  101 + p->gdb_st_dev = tswap16(s->st_dev);
  102 + p->gdb_st_ino = tswap16(s->st_ino);
  103 + p->gdb_st_mode = tswap32(s->st_mode);
  104 + p->gdb_st_nlink = tswap16(s->st_nlink);
  105 + p->gdb_st_uid = tswap16(s->st_uid);
  106 + p->gdb_st_gid = tswap16(s->st_gid);
  107 + p->gdb_st_rdev = tswap16(s->st_rdev);
  108 + p->gdb_st_size = tswap32(s->st_size);
  109 + p->gdb_st_atime = tswap32(s->st_atime);
  110 + p->gdb_st_mtime = tswap32(s->st_mtime);
  111 + p->gdb_st_ctime = tswap32(s->st_ctime);
  112 + p->gdb_st_blksize = tswap32(s->st_blksize);
  113 + p->gdb_st_blocks = tswap32(s->st_blocks);
  114 +}
  115 +
  116 +static inline uint32_t check_err(CPUM68KState *env, uint32_t code)
  117 +{
  118 + if (code == (uint32_t)-1) {
  119 + env->sr |= CCF_C;
  120 + } else {
  121 + env->sr &= ~CCF_C;
  122 + env->dregs[0] = code;
  123 + }
  124 + return code;
  125 +}
  126 +
  127 +#define ARG(x) tswap32(args[x])
  128 +void do_m68k_semihosting(CPUM68KState *env, int nr)
  129 +{
  130 + uint32_t *args;
  131 +
  132 + args = (uint32_t *)env->dregs[1];
  133 + switch (nr) {
  134 + case HOSTED_EXIT:
  135 + exit(env->dregs[0]);
  136 + case HOSTED_OPEN:
  137 + /* Assume name is NULL terminated. */
  138 + check_err(env, open((char *)ARG(0), translate_openflags(ARG(2)),
  139 + ARG(3)));
  140 + break;
  141 + case HOSTED_CLOSE:
  142 + {
  143 + /* Ignore attempts to close stdin/out/err. */
  144 + int fd = ARG(0);
  145 + if (fd > 2)
  146 + check_err(env, close(fd));
  147 + else
  148 + check_err(env, 0);
  149 + break;
  150 + }
  151 + case HOSTED_READ:
  152 + check_err(env, read(ARG(0), (void *)ARG(1), ARG(2)));
  153 + break;
  154 + case HOSTED_WRITE:
  155 + check_err(env, write(ARG(0), (void *)ARG(1), ARG(2)));
  156 + break;
  157 + case HOSTED_LSEEK:
  158 + {
  159 + uint64_t off;
  160 + off = (uint32_t)ARG(2) | ((uint64_t)ARG(1) << 32);
  161 + check_err(env, lseek(ARG(0), off, ARG(3)));
  162 + }
  163 + break;
  164 + case HOSTED_RENAME:
  165 + /* Assume names are NULL terminated. */
  166 + check_err(env, rename((char *)ARG(0), (char *)ARG(2)));
  167 + break;
  168 + case HOSTED_UNLINK:
  169 + /* Assume name is NULL terminated. */
  170 + check_err(env, unlink((char *)ARG(0)));
  171 + break;
  172 + case HOSTED_STAT:
  173 + /* Assume name is NULL terminated. */
  174 + {
  175 + struct stat s;
  176 + int rc;
  177 + rc = check_err(env, stat((char *)ARG(0), &s));
  178 + if (rc == 0) {
  179 + translate_stat((struct m68k_gdb_stat *)ARG(2), &s);
  180 + }
  181 + }
  182 + break;
  183 + case HOSTED_FSTAT:
  184 + {
  185 + struct stat s;
  186 + int rc;
  187 + rc = check_err(env, fstat(ARG(0), &s));
  188 + if (rc == 0) {
  189 + translate_stat((struct m68k_gdb_stat *)ARG(1), &s);
  190 + }
  191 + }
  192 + break;
  193 + case HOSTED_GETTIMEOFDAY:
  194 + {
  195 + struct timeval tv;
  196 + struct gdb_timeval *p;
  197 + int rc;
  198 + rc = check_err(env, gettimeofday(&tv, NULL));
  199 + if (rc != 0) {
  200 + p = (struct gdb_timeval *)ARG(0);
  201 + p->tv_sec = tswap32(tv.tv_sec);
  202 + p->tv_usec = tswap64(tv.tv_usec);
  203 + }
  204 + }
  205 + break;
  206 + case HOSTED_ISATTY:
  207 + check_err(env, isatty(ARG(0)));
  208 + break;
  209 + case HOSTED_SYSTEM:
  210 + /* Assume name is NULL terminated. */
  211 + check_err(env, system((char *)ARG(0)));
  212 + break;
  213 + default:
  214 + cpu_abort(env, "Unsupported semihosting syscall %d\n", nr);
  215 + }
  216 +}
... ...
linux-user/m68k-sim.c 0 โ†’ 100644
  1 +/*
  2 + * m68k simulator syscall interface
  3 + *
  4 + * Copyright (c) 2005 CodeSourcery, LLC. Written by Paul Brook.
  5 + *
  6 + * This program is free software; you can redistribute it and/or modify
  7 + * it under the terms of the GNU General Public License as published by
  8 + * the Free Software Foundation; either version 2 of the License, or
  9 + * (at your option) any later version.
  10 + *
  11 + * This program is distributed in the hope that it will be useful,
  12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14 + * GNU General Public License for more details.
  15 + *
  16 + * You should have received a copy of the GNU General Public License
  17 + * along with this program; if not, write to the Free Software
  18 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19 + */
  20 +
  21 +#include <sys/types.h>
  22 +#include <sys/stat.h>
  23 +#include <errno.h>
  24 +#include <fcntl.h>
  25 +#include <unistd.h>
  26 +#include <stdlib.h>
  27 +#include <stdio.h>
  28 +#include <time.h>
  29 +
  30 +#include "qemu.h"
  31 +
  32 +#define SYS_EXIT 1
  33 +#define SYS_READ 3
  34 +#define SYS_WRITE 4
  35 +#define SYS_OPEN 5
  36 +#define SYS_CLOSE 6
  37 +#define SYS_BRK 17
  38 +#define SYS_FSTAT 28
  39 +#define SYS_ISATTY 29
  40 +#define SYS_LSEEK 199
  41 +
  42 +struct m86k_sim_stat {
  43 + uint16_t sim_st_dev;
  44 + uint16_t sim_st_ino;
  45 + uint32_t sim_st_mode;
  46 + uint16_t sim_st_nlink;
  47 + uint16_t sim_st_uid;
  48 + uint16_t sim_st_gid;
  49 + uint16_t sim_st_rdev;
  50 + uint32_t sim_st_size;
  51 + uint32_t sim_st_atime;
  52 + uint32_t sim_st_mtime;
  53 + uint32_t sim_st_ctime;
  54 + uint32_t sim_st_blksize;
  55 + uint32_t sim_st_blocks;
  56 +};
  57 +
  58 +static inline uint32_t check_err(CPUM68KState *env, uint32_t code)
  59 +{
  60 + env->dregs[0] = code;
  61 + if (code == (uint32_t)-1) {
  62 + env->dregs[1] = errno;
  63 + } else {
  64 + env->dregs[1] = 0;
  65 + }
  66 + return code;
  67 +}
  68 +
  69 +#define SIM_O_APPEND 0x0008
  70 +#define SIM_O_CREAT 0x0200
  71 +#define SIM_O_TRUNC 0x0400
  72 +#define SIM_O_EXCL 0x0800
  73 +#define SIM_O_NONBLOCK 0x4000
  74 +#define SIM_O_NOCTTY 0x8000
  75 +#define SIM_O_SYNC 0x2000
  76 +
  77 +static int translate_openflags(int flags)
  78 +{
  79 + int hf;
  80 +
  81 + switch (flags & 3) {
  82 + case 0: hf = O_RDONLY; break;
  83 + case 1: hf = O_WRONLY; break;
  84 + case 2: hf = O_RDWR; break;
  85 + default: hf = O_RDWR; break;
  86 + }
  87 +
  88 + if (flags & SIM_O_APPEND) hf |= O_APPEND;
  89 + if (flags & SIM_O_CREAT) hf |= O_CREAT;
  90 + if (flags & SIM_O_TRUNC) hf |= O_TRUNC;
  91 + if (flags & SIM_O_EXCL) hf |= O_EXCL;
  92 + if (flags & SIM_O_NONBLOCK) hf |= O_NONBLOCK;
  93 + if (flags & SIM_O_NOCTTY) hf |= O_NOCTTY;
  94 + if (flags & SIM_O_SYNC) hf |= O_SYNC;
  95 +
  96 + return hf;
  97 +}
  98 +
  99 +#define ARG(x) tswap32(args[x])
  100 +void do_m68k_simcall(CPUM68KState *env, int nr)
  101 +{
  102 + uint32_t *args;
  103 +
  104 + args = (uint32_t *)(env->aregs[7] + 4);
  105 + switch (nr) {
  106 + case SYS_EXIT:
  107 + exit(ARG(0));
  108 + case SYS_READ:
  109 + check_err(env, read(ARG(0), (void *)ARG(1), ARG(2)));
  110 + break;
  111 + case SYS_WRITE:
  112 + check_err(env, write(ARG(0), (void *)ARG(1), ARG(2)));
  113 + break;
  114 + case SYS_OPEN:
  115 + check_err(env, open((char *)ARG(0), translate_openflags(ARG(1)),
  116 + ARG(2)));
  117 + break;
  118 + case SYS_CLOSE:
  119 + {
  120 + /* Ignore attempts to close stdin/out/err. */
  121 + int fd = ARG(0);
  122 + if (fd > 2)
  123 + check_err(env, close(fd));
  124 + else
  125 + check_err(env, 0);
  126 + break;
  127 + }
  128 + case SYS_BRK:
  129 + {
  130 + int32_t ret;
  131 +
  132 + ret = do_brk((void *)ARG(0));
  133 + if (ret == -ENOMEM)
  134 + ret = -1;
  135 + check_err(env, ret);
  136 + }
  137 + break;
  138 + case SYS_FSTAT:
  139 + {
  140 + struct stat s;
  141 + int rc;
  142 + struct m86k_sim_stat *p;
  143 + rc = check_err(env, fstat(ARG(0), &s));
  144 + if (rc == 0) {
  145 + p = (struct m86k_sim_stat *)ARG(1);
  146 + p->sim_st_dev = tswap16(s.st_dev);
  147 + p->sim_st_ino = tswap16(s.st_ino);
  148 + p->sim_st_mode = tswap32(s.st_mode);
  149 + p->sim_st_nlink = tswap16(s.st_nlink);
  150 + p->sim_st_uid = tswap16(s.st_uid);
  151 + p->sim_st_gid = tswap16(s.st_gid);
  152 + p->sim_st_rdev = tswap16(s.st_rdev);
  153 + p->sim_st_size = tswap32(s.st_size);
  154 + p->sim_st_atime = tswap32(s.st_atime);
  155 + p->sim_st_mtime = tswap32(s.st_mtime);
  156 + p->sim_st_ctime = tswap32(s.st_ctime);
  157 + p->sim_st_blksize = tswap32(s.st_blksize);
  158 + p->sim_st_blocks = tswap32(s.st_blocks);
  159 + }
  160 + }
  161 + break;
  162 + case SYS_ISATTY:
  163 + check_err(env, isatty(ARG(0)));
  164 + break;
  165 + case SYS_LSEEK:
  166 + check_err(env, lseek(ARG(0), (int32_t)ARG(1), ARG(2)));
  167 + break;
  168 + default:
  169 + cpu_abort(env, "Unsupported m68k sim syscall %d\n", nr);
  170 + }
  171 +}
... ...
linux-user/m68k/syscall.h 0 โ†’ 100644
  1 +
  2 +/* this struct defines the way the registers are stored on the
  3 + stack during a system call. */
  4 +
  5 +struct target_pt_regs {
  6 + target_long d1, d2, d3, d4, d5, d6, d7;
  7 + target_long a0, a1, a2, a3, a4, a5, a6;
  8 + target_ulong d0;
  9 + target_ulong usp;
  10 + target_ulong orig_d0;
  11 + int16_t stkadj;
  12 + uint16_t sr;
  13 + target_ulong pc;
  14 + uint16_t fntvex;
  15 + uint16_t __fill;
  16 +};
  17 +
  18 +
  19 +#define UNAME_MACHINE "m68k"
  20 +
  21 +void do_m68k_semihosting(CPUState *, int);
  22 +void do_m68k_simcall(CPUState *, int);
... ...
linux-user/m68k/syscall_nr.h 0 โ†’ 100644
  1 +/*
  2 + * This file contains the system call numbers.
  3 + */
  4 +
  5 +#define TARGET_NR_exit 1
  6 +#define TARGET_NR_fork 2
  7 +#define TARGET_NR_read 3
  8 +#define TARGET_NR_write 4
  9 +#define TARGET_NR_open 5
  10 +#define TARGET_NR_close 6
  11 +#define TARGET_NR_waitpid 7
  12 +#define TARGET_NR_creat 8
  13 +#define TARGET_NR_link 9
  14 +#define TARGET_NR_unlink 10
  15 +#define TARGET_NR_execve 11
  16 +#define TARGET_NR_chdir 12
  17 +#define TARGET_NR_time 13
  18 +#define TARGET_NR_mknod 14
  19 +#define TARGET_NR_chmod 15
  20 +#define TARGET_NR_chown 16
  21 +#define TARGET_NR_break 17
  22 +#define TARGET_NR_oldstat 18
  23 +#define TARGET_NR_lseek 19
  24 +#define TARGET_NR_getpid 20
  25 +#define TARGET_NR_mount 21
  26 +#define TARGET_NR_umount 22
  27 +#define TARGET_NR_setuid 23
  28 +#define TARGET_NR_getuid 24
  29 +#define TARGET_NR_stime 25
  30 +#define TARGET_NR_ptrace 26
  31 +#define TARGET_NR_alarm 27
  32 +#define TARGET_NR_oldfstat 28
  33 +#define TARGET_NR_pause 29
  34 +#define TARGET_NR_utime 30
  35 +#define TARGET_NR_stty 31
  36 +#define TARGET_NR_gtty 32
  37 +#define TARGET_NR_access 33
  38 +#define TARGET_NR_nice 34
  39 +#define TARGET_NR_ftime 35
  40 +#define TARGET_NR_sync 36
  41 +#define TARGET_NR_kill 37
  42 +#define TARGET_NR_rename 38
  43 +#define TARGET_NR_mkdir 39
  44 +#define TARGET_NR_rmdir 40
  45 +#define TARGET_NR_dup 41
  46 +#define TARGET_NR_pipe 42
  47 +#define TARGET_NR_times 43
  48 +#define TARGET_NR_prof 44
  49 +#define TARGET_NR_brk 45
  50 +#define TARGET_NR_setgid 46
  51 +#define TARGET_NR_getgid 47
  52 +#define TARGET_NR_signal 48
  53 +#define TARGET_NR_geteuid 49
  54 +#define TARGET_NR_getegid 50
  55 +#define TARGET_NR_acct 51
  56 +#define TARGET_NR_umount2 52
  57 +#define TARGET_NR_lock 53
  58 +#define TARGET_NR_ioctl 54
  59 +#define TARGET_NR_fcntl 55
  60 +#define TARGET_NR_mpx 56
  61 +#define TARGET_NR_setpgid 57
  62 +#define TARGET_NR_ulimit 58
  63 +#define TARGET_NR_oldolduname 59
  64 +#define TARGET_NR_umask 60
  65 +#define TARGET_NR_chroot 61
  66 +#define TARGET_NR_ustat 62
  67 +#define TARGET_NR_dup2 63
  68 +#define TARGET_NR_getppid 64
  69 +#define TARGET_NR_getpgrp 65
  70 +#define TARGET_NR_setsid 66
  71 +#define TARGET_NR_sigaction 67
  72 +#define TARGET_NR_sgetmask 68
  73 +#define TARGET_NR_ssetmask 69
  74 +#define TARGET_NR_setreuid 70
  75 +#define TARGET_NR_setregid 71
  76 +#define TARGET_NR_sigsuspend 72
  77 +#define TARGET_NR_sigpending 73
  78 +#define TARGET_NR_sethostname 74
  79 +#define TARGET_NR_setrlimit 75
  80 +#define TARGET_NR_getrlimit 76
  81 +#define TARGET_NR_getrusage 77
  82 +#define TARGET_NR_gettimeofday 78
  83 +#define TARGET_NR_settimeofday 79
  84 +#define TARGET_NR_getgroups 80
  85 +#define TARGET_NR_setgroups 81
  86 +#define TARGET_NR_select 82
  87 +#define TARGET_NR_symlink 83
  88 +#define TARGET_NR_oldlstat 84
  89 +#define TARGET_NR_readlink 85
  90 +#define TARGET_NR_uselib 86
  91 +#define TARGET_NR_swapon 87
  92 +#define TARGET_NR_reboot 88
  93 +#define TARGET_NR_readdir 89
  94 +#define TARGET_NR_mmap 90
  95 +#define TARGET_NR_munmap 91
  96 +#define TARGET_NR_truncate 92
  97 +#define TARGET_NR_ftruncate 93
  98 +#define TARGET_NR_fchmod 94
  99 +#define TARGET_NR_fchown 95
  100 +#define TARGET_NR_getpriority 96
  101 +#define TARGET_NR_setpriority 97
  102 +#define TARGET_NR_profil 98
  103 +#define TARGET_NR_statfs 99
  104 +#define TARGET_NR_fstatfs 100
  105 +#define TARGET_NR_ioperm 101
  106 +#define TARGET_NR_socketcall 102
  107 +#define TARGET_NR_syslog 103
  108 +#define TARGET_NR_setitimer 104
  109 +#define TARGET_NR_getitimer 105
  110 +#define TARGET_NR_stat 106
  111 +#define TARGET_NR_lstat 107
  112 +#define TARGET_NR_fstat 108
  113 +#define TARGET_NR_olduname 109
  114 +//#define TARGET_NR_iopl /* 110 */ not supported
  115 +#define TARGET_NR_vhangup 111
  116 +//#define TARGET_NR_idle /* 112 */ Obsolete
  117 +//#define TARGET_NR_vm86 /* 113 */ not supported
  118 +#define TARGET_NR_wait4 114
  119 +#define TARGET_NR_swapoff 115
  120 +#define TARGET_NR_sysinfo 116
  121 +#define TARGET_NR_ipc 117
  122 +#define TARGET_NR_fsync 118
  123 +#define TARGET_NR_sigreturn 119
  124 +#define TARGET_NR_clone 120
  125 +#define TARGET_NR_setdomainname 121
  126 +#define TARGET_NR_uname 122
  127 +#define TARGET_NR_cacheflush 123
  128 +#define TARGET_NR_adjtimex 124
  129 +#define TARGET_NR_mprotect 125
  130 +#define TARGET_NR_sigprocmask 126
  131 +#define TARGET_NR_create_module 127
  132 +#define TARGET_NR_init_module 128
  133 +#define TARGET_NR_delete_module 129
  134 +#define TARGET_NR_get_kernel_syms 130
  135 +#define TARGET_NR_quotactl 131
  136 +#define TARGET_NR_getpgid 132
  137 +#define TARGET_NR_fchdir 133
  138 +#define TARGET_NR_bdflush 134
  139 +#define TARGET_NR_sysfs 135
  140 +#define TARGET_NR_personality 136
  141 +#define TARGET_NR_afs_syscall 137 /* Syscall for Andrew File System */
  142 +#define TARGET_NR_setfsuid 138
  143 +#define TARGET_NR_setfsgid 139
  144 +#define TARGET_NR__llseek 140
  145 +#define TARGET_NR_getdents 141
  146 +#define TARGET_NR__newselect 142
  147 +#define TARGET_NR_flock 143
  148 +#define TARGET_NR_msync 144
  149 +#define TARGET_NR_readv 145
  150 +#define TARGET_NR_writev 146
  151 +#define TARGET_NR_getsid 147
  152 +#define TARGET_NR_fdatasync 148
  153 +#define TARGET_NR__sysctl 149
  154 +#define TARGET_NR_mlock 150
  155 +#define TARGET_NR_munlock 151
  156 +#define TARGET_NR_mlockall 152
  157 +#define TARGET_NR_munlockall 153
  158 +#define TARGET_NR_sched_setparam 154
  159 +#define TARGET_NR_sched_getparam 155
  160 +#define TARGET_NR_sched_setscheduler 156
  161 +#define TARGET_NR_sched_getscheduler 157
  162 +#define TARGET_NR_sched_yield 158
  163 +#define TARGET_NR_sched_get_priority_max 159
  164 +#define TARGET_NR_sched_get_priority_min 160
  165 +#define TARGET_NR_sched_rr_get_interval 161
  166 +#define TARGET_NR_nanosleep 162
  167 +#define TARGET_NR_mremap 163
  168 +#define TARGET_NR_setresuid 164
  169 +#define TARGET_NR_getresuid 165
  170 +#define TARGET_NR_getpagesize 166
  171 +#define TARGET_NR_query_module 167
  172 +#define TARGET_NR_poll 168
  173 +#define TARGET_NR_nfsservctl 169
  174 +#define TARGET_NR_setresgid 170
  175 +#define TARGET_NR_getresgid 171
  176 +#define TARGET_NR_prctl 172
  177 +#define TARGET_NR_rt_sigreturn 173
  178 +#define TARGET_NR_rt_sigaction 174
  179 +#define TARGET_NR_rt_sigprocmask 175
  180 +#define TARGET_NR_rt_sigpending 176
  181 +#define TARGET_NR_rt_sigtimedwait 177
  182 +#define TARGET_NR_rt_sigqueueinfo 178
  183 +#define TARGET_NR_rt_sigsuspend 179
  184 +#define TARGET_NR_pread64 180
  185 +#define TARGET_NR_pwrite64 181
  186 +#define TARGET_NR_lchown 182
  187 +#define TARGET_NR_getcwd 183
  188 +#define TARGET_NR_capget 184
  189 +#define TARGET_NR_capset 185
  190 +#define TARGET_NR_sigaltstack 186
  191 +#define TARGET_NR_sendfile 187
  192 +#define TARGET_NR_getpmsg 188 /* some people actually want streams */
  193 +#define TARGET_NR_putpmsg 189 /* some people actually want streams */
  194 +#define TARGET_NR_vfork 190
  195 +#define TARGET_NR_ugetrlimit 191
  196 +#define TARGET_NR_mmap2 192
  197 +#define TARGET_NR_truncate64 193
  198 +#define TARGET_NR_ftruncate64 194
  199 +#define TARGET_NR_stat64 195
  200 +#define TARGET_NR_lstat64 196
  201 +#define TARGET_NR_fstat64 197
  202 +#define TARGET_NR_chown32 198
  203 +#define TARGET_NR_getuid32 199
  204 +#define TARGET_NR_getgid32 200
  205 +#define TARGET_NR_geteuid32 201
  206 +#define TARGET_NR_getegid32 202
  207 +#define TARGET_NR_setreuid32 203
  208 +#define TARGET_NR_setregid32 204
  209 +#define TARGET_NR_getgroups32 205
  210 +#define TARGET_NR_setgroups32 206
  211 +#define TARGET_NR_fchown32 207
  212 +#define TARGET_NR_setresuid32 208
  213 +#define TARGET_NR_getresuid32 209
  214 +#define TARGET_NR_setresgid32 210
  215 +#define TARGET_NR_getresgid32 211
  216 +#define TARGET_NR_lchown32 212
  217 +#define TARGET_NR_setuid32 213
  218 +#define TARGET_NR_setgid32 214
  219 +#define TARGET_NR_setfsuid32 215
  220 +#define TARGET_NR_setfsgid32 216
  221 +#define TARGET_NR_pivot_root 217
  222 +#define TARGET_NR_getdents64 220
  223 +#define TARGET_NR_gettid 221
  224 +#define TARGET_NR_tkill 222
  225 +#define TARGET_NR_setxattr 223
  226 +#define TARGET_NR_lsetxattr 224
  227 +#define TARGET_NR_fsetxattr 225
  228 +#define TARGET_NR_getxattr 226
  229 +#define TARGET_NR_lgetxattr 227
  230 +#define TARGET_NR_fgetxattr 228
  231 +#define TARGET_NR_listxattr 229
  232 +#define TARGET_NR_llistxattr 230
  233 +#define TARGET_NR_flistxattr 231
  234 +#define TARGET_NR_removexattr 232
  235 +#define TARGET_NR_lremovexattr 233
  236 +#define TARGET_NR_fremovexattr 234
  237 +#define TARGET_NR_futex 235
  238 +#define TARGET_NR_sendfile64 236
  239 +#define TARGET_NR_mincore 237
  240 +#define TARGET_NR_madvise 238
  241 +#define TARGET_NR_fcntl64 239
  242 +#define TARGET_NR_readahead 240
  243 +#define TARGET_NR_io_setup 241
  244 +#define TARGET_NR_io_destroy 242
  245 +#define TARGET_NR_io_getevents 243
  246 +#define TARGET_NR_io_submit 244
  247 +#define TARGET_NR_io_cancel 245
  248 +#define TARGET_NR_fadvise64 246
  249 +#define TARGET_NR_exit_group 247
  250 +#define TARGET_NR_lookup_dcookie 248
  251 +#define TARGET_NR_epoll_create 249
  252 +#define TARGET_NR_epoll_ctl 250
  253 +#define TARGET_NR_epoll_wait 251
  254 +#define TARGET_NR_remap_file_pages 252
  255 +#define TARGET_NR_set_tid_address 253
  256 +#define TARGET_NR_timer_create 254
  257 +#define TARGET_NR_timer_settime 255
  258 +#define TARGET_NR_timer_gettime 256
  259 +#define TARGET_NR_timer_getoverrun 257
  260 +#define TARGET_NR_timer_delete 258
  261 +#define TARGET_NR_clock_settime 259
  262 +#define TARGET_NR_clock_gettime 260
  263 +#define TARGET_NR_clock_getres 261
  264 +#define TARGET_NR_clock_nanosleep 262
  265 +#define TARGET_NR_statfs64 263
  266 +#define TARGET_NR_fstatfs64 264
  267 +#define TARGET_NR_tgkill 265
  268 +#define TARGET_NR_utimes 266
  269 +#define TARGET_NR_fadvise64_64 267
  270 +#define TARGET_NR_mbind 268
  271 +#define TARGET_NR_get_mempolicy 269
  272 +#define TARGET_NR_set_mempolicy 270
  273 +#define TARGET_NR_mq_open 271
  274 +#define TARGET_NR_mq_unlink 272
  275 +#define TARGET_NR_mq_timedsend 273
  276 +#define TARGET_NR_mq_timedreceive 274
  277 +#define TARGET_NR_mq_notify 275
  278 +#define TARGET_NR_mq_getsetattr 276
  279 +#define TARGET_NR_waitid 277
  280 +#define TARGET_NR_vserver 278
  281 +#define TARGET_NR_add_key 279
  282 +#define TARGET_NR_request_key 280
  283 +#define TARGET_NR_keyctl 281
... ...
linux-user/m68k/termbits.h 0 โ†’ 100644
  1 +/* from asm/termbits.h */
  2 +/* NOTE: exactly the same as i386 */
  3 +
  4 +#define TARGET_NCCS 19
  5 +
  6 +struct target_termios {
  7 + unsigned int c_iflag; /* input mode flags */
  8 + unsigned int c_oflag; /* output mode flags */
  9 + unsigned int c_cflag; /* control mode flags */
  10 + unsigned int c_lflag; /* local mode flags */
  11 + unsigned char c_line; /* line discipline */
  12 + unsigned char c_cc[TARGET_NCCS]; /* control characters */
  13 +};
  14 +
  15 +/* c_iflag bits */
  16 +#define TARGET_IGNBRK 0000001
  17 +#define TARGET_BRKINT 0000002
  18 +#define TARGET_IGNPAR 0000004
  19 +#define TARGET_PARMRK 0000010
  20 +#define TARGET_INPCK 0000020
  21 +#define TARGET_ISTRIP 0000040
  22 +#define TARGET_INLCR 0000100
  23 +#define TARGET_IGNCR 0000200
  24 +#define TARGET_ICRNL 0000400
  25 +#define TARGET_IUCLC 0001000
  26 +#define TARGET_IXON 0002000
  27 +#define TARGET_IXANY 0004000
  28 +#define TARGET_IXOFF 0010000
  29 +#define TARGET_IMAXBEL 0020000
  30 +
  31 +/* c_oflag bits */
  32 +#define TARGET_OPOST 0000001
  33 +#define TARGET_OLCUC 0000002
  34 +#define TARGET_ONLCR 0000004
  35 +#define TARGET_OCRNL 0000010
  36 +#define TARGET_ONOCR 0000020
  37 +#define TARGET_ONLRET 0000040
  38 +#define TARGET_OFILL 0000100
  39 +#define TARGET_OFDEL 0000200
  40 +#define TARGET_NLDLY 0000400
  41 +#define TARGET_NL0 0000000
  42 +#define TARGET_NL1 0000400
  43 +#define TARGET_CRDLY 0003000
  44 +#define TARGET_CR0 0000000
  45 +#define TARGET_CR1 0001000
  46 +#define TARGET_CR2 0002000
  47 +#define TARGET_CR3 0003000
  48 +#define TARGET_TABDLY 0014000
  49 +#define TARGET_TAB0 0000000
  50 +#define TARGET_TAB1 0004000
  51 +#define TARGET_TAB2 0010000
  52 +#define TARGET_TAB3 0014000
  53 +#define TARGET_XTABS 0014000
  54 +#define TARGET_BSDLY 0020000
  55 +#define TARGET_BS0 0000000
  56 +#define TARGET_BS1 0020000
  57 +#define TARGET_VTDLY 0040000
  58 +#define TARGET_VT0 0000000
  59 +#define TARGET_VT1 0040000
  60 +#define TARGET_FFDLY 0100000
  61 +#define TARGET_FF0 0000000
  62 +#define TARGET_FF1 0100000
  63 +
  64 +/* c_cflag bit meaning */
  65 +#define TARGET_CBAUD 0010017
  66 +#define TARGET_B0 0000000 /* hang up */
  67 +#define TARGET_B50 0000001
  68 +#define TARGET_B75 0000002
  69 +#define TARGET_B110 0000003
  70 +#define TARGET_B134 0000004
  71 +#define TARGET_B150 0000005
  72 +#define TARGET_B200 0000006
  73 +#define TARGET_B300 0000007
  74 +#define TARGET_B600 0000010
  75 +#define TARGET_B1200 0000011
  76 +#define TARGET_B1800 0000012
  77 +#define TARGET_B2400 0000013
  78 +#define TARGET_B4800 0000014
  79 +#define TARGET_B9600 0000015
  80 +#define TARGET_B19200 0000016
  81 +#define TARGET_B38400 0000017
  82 +#define TARGET_EXTA B19200
  83 +#define TARGET_EXTB B38400
  84 +#define TARGET_CSIZE 0000060
  85 +#define TARGET_CS5 0000000
  86 +#define TARGET_CS6 0000020
  87 +#define TARGET_CS7 0000040
  88 +#define TARGET_CS8 0000060
  89 +#define TARGET_CSTOPB 0000100
  90 +#define TARGET_CREAD 0000200
  91 +#define TARGET_PARENB 0000400
  92 +#define TARGET_PARODD 0001000
  93 +#define TARGET_HUPCL 0002000
  94 +#define TARGET_CLOCAL 0004000
  95 +#define TARGET_CBAUDEX 0010000
  96 +#define TARGET_B57600 0010001
  97 +#define TARGET_B115200 0010002
  98 +#define TARGET_B230400 0010003
  99 +#define TARGET_B460800 0010004
  100 +#define TARGET_CIBAUD 002003600000 /* input baud rate (not used) */
  101 +#define TARGET_CRTSCTS 020000000000 /* flow control */
  102 +
  103 +/* c_lflag bits */
  104 +#define TARGET_ISIG 0000001
  105 +#define TARGET_ICANON 0000002
  106 +#define TARGET_XCASE 0000004
  107 +#define TARGET_ECHO 0000010
  108 +#define TARGET_ECHOE 0000020
  109 +#define TARGET_ECHOK 0000040
  110 +#define TARGET_ECHONL 0000100
  111 +#define TARGET_NOFLSH 0000200
  112 +#define TARGET_TOSTOP 0000400
  113 +#define TARGET_ECHOCTL 0001000
  114 +#define TARGET_ECHOPRT 0002000
  115 +#define TARGET_ECHOKE 0004000
  116 +#define TARGET_FLUSHO 0010000
  117 +#define TARGET_PENDIN 0040000
  118 +#define TARGET_IEXTEN 0100000
  119 +
  120 +/* c_cc character offsets */
  121 +#define TARGET_VINTR 0
  122 +#define TARGET_VQUIT 1
  123 +#define TARGET_VERASE 2
  124 +#define TARGET_VKILL 3
  125 +#define TARGET_VEOF 4
  126 +#define TARGET_VTIME 5
  127 +#define TARGET_VMIN 6
  128 +#define TARGET_VSWTC 7
  129 +#define TARGET_VSTART 8
  130 +#define TARGET_VSTOP 9
  131 +#define TARGET_VSUSP 10
  132 +#define TARGET_VEOL 11
  133 +#define TARGET_VREPRINT 12
  134 +#define TARGET_VDISCARD 13
  135 +#define TARGET_VWERASE 14
  136 +#define TARGET_VLNEXT 15
  137 +#define TARGET_VEOL2 16
  138 +
  139 +/* ioctls */
  140 +
  141 +#define TARGET_TCGETS 0x5401
  142 +#define TARGET_TCSETS 0x5402
  143 +#define TARGET_TCSETSW 0x5403
  144 +#define TARGET_TCSETSF 0x5404
  145 +#define TARGET_TCGETA 0x5405
  146 +#define TARGET_TCSETA 0x5406
  147 +#define TARGET_TCSETAW 0x5407
  148 +#define TARGET_TCSETAF 0x5408
  149 +#define TARGET_TCSBRK 0x5409
  150 +#define TARGET_TCXONC 0x540A
  151 +#define TARGET_TCFLSH 0x540B
  152 +
  153 +#define TARGET_TIOCEXCL 0x540C
  154 +#define TARGET_TIOCNXCL 0x540D
  155 +#define TARGET_TIOCSCTTY 0x540E
  156 +#define TARGET_TIOCGPGRP 0x540F
  157 +#define TARGET_TIOCSPGRP 0x5410
  158 +#define TARGET_TIOCOUTQ 0x5411
  159 +#define TARGET_TIOCSTI 0x5412
  160 +#define TARGET_TIOCGWINSZ 0x5413
  161 +#define TARGET_TIOCSWINSZ 0x5414
  162 +#define TARGET_TIOCMGET 0x5415
  163 +#define TARGET_TIOCMBIS 0x5416
  164 +#define TARGET_TIOCMBIC 0x5417
  165 +#define TARGET_TIOCMSET 0x5418
  166 +#define TARGET_TIOCGSOFTCAR 0x5419
  167 +#define TARGET_TIOCSSOFTCAR 0x541A
  168 +#define TARGET_FIONREAD 0x541B
  169 +#define TARGET_TIOCINQ TARGET_FIONREAD
  170 +#define TARGET_TIOCLINUX 0x541C
  171 +#define TARGET_TIOCCONS 0x541D
  172 +#define TARGET_TIOCGSERIAL 0x541E
  173 +#define TARGET_TIOCSSERIAL 0x541F
  174 +#define TARGET_TIOCPKT 0x5420
  175 +#define TARGET_FIONBIO 0x5421
  176 +#define TARGET_TIOCNOTTY 0x5422
  177 +#define TARGET_TIOCSETD 0x5423
  178 +#define TARGET_TIOCGETD 0x5424
  179 +#define TARGET_TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
  180 +#define TARGET_TIOCTTYGSTRUCT 0x5426 /* For debugging only */
  181 +#define TARGET_TIOCSBRK 0x5427 /* BSD compatibility */
  182 +#define TARGET_TIOCCBRK 0x5428 /* BSD compatibility */
  183 +#define TARGET_TIOCGSID 0x5429 /* Return the session ID of FD */
  184 +#define TARGET_TIOCGPTN TARGET_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
  185 +#define TARGET_TIOCSPTLCK TARGET_IOW('T',0x31, int) /* Lock/unlock Pty */
  186 +
  187 +#define TARGET_FIONCLEX 0x5450 /* these numbers need to be adjusted. */
  188 +#define TARGET_FIOCLEX 0x5451
  189 +#define TARGET_FIOASYNC 0x5452
  190 +#define TARGET_TIOCSERCONFIG 0x5453
  191 +#define TARGET_TIOCSERGWILD 0x5454
  192 +#define TARGET_TIOCSERSWILD 0x5455
  193 +#define TARGET_TIOCGLCKTRMIOS 0x5456
  194 +#define TARGET_TIOCSLCKTRMIOS 0x5457
  195 +#define TARGET_TIOCSERGSTRUCT 0x5458 /* For debugging only */
  196 +#define TARGET_TIOCSERGETLSR 0x5459 /* Get line status register */
  197 +#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config */
  198 +#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */
  199 +
  200 +#define TARGET_TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
  201 +#define TARGET_TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
  202 +#define TARGET_TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */
  203 +#define TARGET_TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */
  204 +
  205 +/* Used for packet mode */
  206 +#define TARGET_TIOCPKT_DATA 0
  207 +#define TARGET_TIOCPKT_FLUSHREAD 1
  208 +#define TARGET_TIOCPKT_FLUSHWRITE 2
  209 +#define TARGET_TIOCPKT_STOP 4
  210 +#define TARGET_TIOCPKT_START 8
  211 +#define TARGET_TIOCPKT_NOSTOP 16
  212 +#define TARGET_TIOCPKT_DOSTOP 32
  213 +
  214 +#define TARGET_TIOCSER_TEMT 0x01 /* Transmitter physically empty */
  215 +
... ...
linux-user/main.c
... ... @@ -1412,6 +1412,98 @@ void cpu_loop (CPUState *env)
1412 1412 }
1413 1413 #endif
1414 1414  
  1415 +#ifdef TARGET_M68K
  1416 +
  1417 +void cpu_loop(CPUM68KState *env)
  1418 +{
  1419 + int trapnr;
  1420 + unsigned int n;
  1421 + target_siginfo_t info;
  1422 + TaskState *ts = env->opaque;
  1423 +
  1424 + for(;;) {
  1425 + trapnr = cpu_m68k_exec(env);
  1426 + switch(trapnr) {
  1427 + case EXCP_ILLEGAL:
  1428 + {
  1429 + if (ts->sim_syscalls) {
  1430 + uint16_t nr;
  1431 + nr = lduw(env->pc + 2);
  1432 + env->pc += 4;
  1433 + do_m68k_simcall(env, nr);
  1434 + } else {
  1435 + goto do_sigill;
  1436 + }
  1437 + }
  1438 + break;
  1439 + case EXCP_HALTED:
  1440 + /* Semihosing syscall. */
  1441 + env->pc += 2;
  1442 + do_m68k_semihosting(env, env->dregs[0]);
  1443 + break;
  1444 + case EXCP_LINEA:
  1445 + case EXCP_LINEF:
  1446 + case EXCP_UNSUPPORTED:
  1447 + do_sigill:
  1448 + info.si_signo = SIGILL;
  1449 + info.si_errno = 0;
  1450 + info.si_code = TARGET_ILL_ILLOPN;
  1451 + info._sifields._sigfault._addr = env->pc;
  1452 + queue_signal(info.si_signo, &info);
  1453 + break;
  1454 + case EXCP_TRAP0:
  1455 + {
  1456 + ts->sim_syscalls = 0;
  1457 + n = env->dregs[0];
  1458 + env->pc += 2;
  1459 + env->dregs[0] = do_syscall(env,
  1460 + n,
  1461 + env->dregs[1],
  1462 + env->dregs[2],
  1463 + env->dregs[3],
  1464 + env->dregs[4],
  1465 + env->dregs[5],
  1466 + env->dregs[6]);
  1467 + }
  1468 + break;
  1469 + case EXCP_INTERRUPT:
  1470 + /* just indicate that signals should be handled asap */
  1471 + break;
  1472 + case EXCP_ACCESS:
  1473 + {
  1474 + info.si_signo = SIGSEGV;
  1475 + info.si_errno = 0;
  1476 + /* XXX: check env->error_code */
  1477 + info.si_code = TARGET_SEGV_MAPERR;
  1478 + info._sifields._sigfault._addr = env->mmu.ar;
  1479 + queue_signal(info.si_signo, &info);
  1480 + }
  1481 + break;
  1482 + case EXCP_DEBUG:
  1483 + {
  1484 + int sig;
  1485 +
  1486 + sig = gdb_handlesig (env, TARGET_SIGTRAP);
  1487 + if (sig)
  1488 + {
  1489 + info.si_signo = sig;
  1490 + info.si_errno = 0;
  1491 + info.si_code = TARGET_TRAP_BRKPT;
  1492 + queue_signal(info.si_signo, &info);
  1493 + }
  1494 + }
  1495 + break;
  1496 + default:
  1497 + fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
  1498 + trapnr);
  1499 + cpu_dump_state(env, stderr, fprintf, 0);
  1500 + abort();
  1501 + }
  1502 + process_pending_signals(env);
  1503 + }
  1504 +}
  1505 +#endif /* TARGET_M68K */
  1506 +
1415 1507 void usage(void)
1416 1508 {
1417 1509 printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003-2005 Fabrice Bellard\n"
... ... @@ -1685,6 +1777,35 @@ int main(int argc, char **argv)
1685 1777 env->gpr[i] = regs->gpr[i];
1686 1778 }
1687 1779 }
  1780 +#elif defined(TARGET_M68K)
  1781 + {
  1782 + m68k_def_t *def;
  1783 + def = m68k_find_by_name("cfv4e");
  1784 + if (def == NULL) {
  1785 + cpu_abort(cpu_single_env,
  1786 + "Unable to find m68k CPU definition\n");
  1787 + }
  1788 + cpu_m68k_register(cpu_single_env, def);
  1789 + env->pc = regs->pc;
  1790 + env->dregs[0] = regs->d0;
  1791 + env->dregs[1] = regs->d1;
  1792 + env->dregs[2] = regs->d2;
  1793 + env->dregs[3] = regs->d3;
  1794 + env->dregs[4] = regs->d4;
  1795 + env->dregs[5] = regs->d5;
  1796 + env->dregs[6] = regs->d6;
  1797 + env->dregs[7] = regs->d7;
  1798 + env->aregs[0] = regs->a0;
  1799 + env->aregs[1] = regs->a1;
  1800 + env->aregs[2] = regs->a2;
  1801 + env->aregs[3] = regs->a3;
  1802 + env->aregs[4] = regs->a4;
  1803 + env->aregs[5] = regs->a5;
  1804 + env->aregs[6] = regs->a6;
  1805 + env->aregs[7] = regs->usp;
  1806 + env->sr = regs->sr;
  1807 + ts->sim_syscalls = 1;
  1808 + }
1688 1809 #elif defined(TARGET_MIPS)
1689 1810 {
1690 1811 int i;
... ...
linux-user/mmap.c
... ... @@ -209,7 +209,7 @@ long target_mmap(target_ulong start, target_ulong len, int prot,
209 209 last_start += HOST_PAGE_ALIGN(len);
210 210 }
211 211 #endif
212   - if (qemu_host_page_size != qemu_real_host_page_size) {
  212 + if (0 && qemu_host_page_size != qemu_real_host_page_size) {
213 213 /* NOTE: this code is only for debugging with '-p' option */
214 214 /* ??? Can also occur when TARGET_PAGE_SIZE > host page size. */
215 215 /* reserve a memory area */
... ...
linux-user/qemu.h
... ... @@ -74,6 +74,9 @@ typedef struct TaskState {
74 74 uint32_t v86flags;
75 75 uint32_t v86mask;
76 76 #endif
  77 +#ifdef TARGET_M68K
  78 + int sim_syscalls;
  79 +#endif
77 80 int used; /* non zero if used */
78 81 struct image_info *info;
79 82 uint8_t stack[0];
... ...
linux-user/syscall.c
... ... @@ -69,7 +69,8 @@
69 69  
70 70 //#define DEBUG
71 71  
72   -#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC)
  72 +#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) \
  73 + || defined(TARGET_M68K)
73 74 /* 16 bit uid wrappers emulation */
74 75 #define USE_UID16
75 76 #endif
... ... @@ -1645,6 +1646,12 @@ int do_fork(CPUState *env, unsigned int flags, unsigned long newsp)
1645 1646 new_env->regwptr[0] = 0;
1646 1647 /* XXXXX */
1647 1648 printf ("HELPME: %s:%d\n", __FILE__, __LINE__);
  1649 +#elif defined(TARGET_M68K)
  1650 + if (!newsp)
  1651 + newsp = env->aregs[7];
  1652 + new_env->aregs[7] = newsp;
  1653 + new_env->dregs[0] = 0;
  1654 + /* ??? is this sufficient? */
1648 1655 #elif defined(TARGET_MIPS)
1649 1656 printf ("HELPME: %s:%d\n", __FILE__, __LINE__);
1650 1657 #elif defined(TARGET_PPC)
... ... @@ -2604,7 +2611,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
2604 2611 case TARGET_NR_readdir:
2605 2612 goto unimplemented;
2606 2613 case TARGET_NR_mmap:
2607   -#if defined(TARGET_I386) || defined(TARGET_ARM)
  2614 +#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_M68K)
2608 2615 {
2609 2616 target_ulong *v;
2610 2617 target_ulong v1, v2, v3, v4, v5, v6;
... ...
linux-user/syscall_defs.h
... ... @@ -48,7 +48,8 @@
48 48 #define TARGET_IOC_NRBITS 8
49 49 #define TARGET_IOC_TYPEBITS 8
50 50  
51   -#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SH4)
  51 +#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SH4) \
  52 + || defined(TARGET_M68K)
52 53  
53 54 #define TARGET_IOC_SIZEBITS 14
54 55 #define TARGET_IOC_DIRBITS 2
... ... @@ -293,7 +294,7 @@ struct target_sigaction;
293 294 int do_sigaction(int sig, const struct target_sigaction *act,
294 295 struct target_sigaction *oact);
295 296  
296   -#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_MIPS) || defined (TARGET_SH4)
  297 +#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_MIPS) || defined (TARGET_SH4) || defined(TARGET_M68K)
297 298  
298 299 #if defined(TARGET_SPARC)
299 300 #define TARGET_SA_NOCLDSTOP 8u
... ... @@ -1070,6 +1071,68 @@ struct target_stat64 {
1070 1071 target_ulong __unused5;
1071 1072 };
1072 1073  
  1074 +#elif defined(TARGET_M68K)
  1075 +
  1076 +struct target_stat {
  1077 + unsigned short st_dev;
  1078 + unsigned short __pad1;
  1079 + target_ulong st_ino;
  1080 + unsigned short st_mode;
  1081 + unsigned short st_nlink;
  1082 + unsigned short st_uid;
  1083 + unsigned short st_gid;
  1084 + unsigned short st_rdev;
  1085 + unsigned short __pad2;
  1086 + target_ulong st_size;
  1087 + target_ulong st_blksize;
  1088 + target_ulong st_blocks;
  1089 + target_ulong target_st_atime;
  1090 + target_ulong __unused1;
  1091 + target_ulong target_st_mtime;
  1092 + target_ulong __unused2;
  1093 + target_ulong target_st_ctime;
  1094 + target_ulong __unused3;
  1095 + target_ulong __unused4;
  1096 + target_ulong __unused5;
  1097 +};
  1098 +
  1099 +/* This matches struct stat64 in glibc2.1, hence the absolutely
  1100 + * insane amounts of padding around dev_t's.
  1101 + */
  1102 +struct target_stat64 {
  1103 + unsigned long long st_dev;
  1104 + unsigned char __pad1[2];
  1105 +
  1106 +#define TARGET_STAT64_HAS_BROKEN_ST_INO 1
  1107 + target_ulong __st_ino;
  1108 +
  1109 + unsigned int st_mode;
  1110 + unsigned int st_nlink;
  1111 +
  1112 + target_ulong st_uid;
  1113 + target_ulong st_gid;
  1114 +
  1115 + unsigned long long st_rdev;
  1116 + unsigned char __pad3[2];
  1117 +
  1118 + long long st_size;
  1119 + target_ulong st_blksize;
  1120 +
  1121 + target_ulong __pad4; /* future possible st_blocks high bits */
  1122 + target_ulong st_blocks; /* Number 512-byte blocks allocated. */
  1123 +
  1124 + target_ulong target_st_atime;
  1125 + target_ulong target_st_atime_nsec;
  1126 +
  1127 + target_ulong target_st_mtime;
  1128 + target_ulong target_st_mtime_nsec;
  1129 +
  1130 + target_ulong target_st_ctime;
  1131 + target_ulong target_st_ctime_nsec;
  1132 +
  1133 + unsigned long long st_ino;
  1134 +} __attribute__((packed));
  1135 +
1073 1136 #elif defined(TARGET_MIPS)
1074 1137  
1075 1138 struct target_stat {
... ...
qemu-doc.texi
... ... @@ -81,7 +81,7 @@ For system emulation, the following hardware targets are supported:
81 81 @item ARM Versatile baseboard (ARM926E)
82 82 @end itemize
83 83  
84   -For user emulation, x86, PowerPC, ARM, MIPS, and Sparc32/64 CPUs are supported.
  84 +For user emulation, x86, PowerPC, ARM, MIPS, Sparc32/64 and ColdFire(m68k) CPUs are supported.
85 85  
86 86 @node Installation
87 87 @chapter Installation
... ... @@ -1768,6 +1768,10 @@ Act as if the host page size was &#39;pagesize&#39; bytes
1768 1768 binaries (as implemented by the arm-elf and arm-eabi Newlib/GDB
1769 1769 configurations), and arm-uclinux bFLT format binaries.
1770 1770  
  1771 +@command{qemu-m68k} is capable of running semihosted binaries using the BDM
  1772 +(m5xxx-ram-hosted.ld) or m68k-sim (sim.ld) syscall interfaces, and
  1773 +coldfire uClinux bFLT format binaries.
  1774 +
1771 1775 The binary format is detected automatically.
1772 1776  
1773 1777 @node compilation
... ...
target-m68k/cpu.h 0 โ†’ 100644
  1 +/*
  2 + * m68k virtual CPU header
  3 + *
  4 + * Copyright (c) 2005-2006 CodeSourcery
  5 + * Written by Paul Brook
  6 + *
  7 + * This library is free software; you can redistribute it and/or
  8 + * modify it under the terms of the GNU Lesser General Public
  9 + * License as published by the Free Software Foundation; either
  10 + * version 2 of the License, or (at your option) any later version.
  11 + *
  12 + * This library is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15 + * General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU Lesser General Public
  18 + * License along with this library; if not, write to the Free Software
  19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20 + */
  21 +#ifndef CPU_M68K_H
  22 +#define CPU_M68K_H
  23 +
  24 +#define TARGET_LONG_BITS 32
  25 +
  26 +#include "cpu-defs.h"
  27 +
  28 +#include "softfloat.h"
  29 +
  30 +#define MAX_QREGS 32
  31 +
  32 +#define TARGET_HAS_ICE 1
  33 +
  34 +#define EXCP_ACCESS 2 /* Access (MMU) error. */
  35 +#define EXCP_ADDRESS 3 /* Address error. */
  36 +#define EXCP_ILLEGAL 4 /* Illegal instruction. */
  37 +#define EXCP_DIV0 5 /* Divide by zero */
  38 +#define EXCP_PRIVILEGE 8 /* Privilege violation. */
  39 +#define EXCP_TRACE 9
  40 +#define EXCP_LINEA 10 /* Unimplemented line-A (MAC) opcode. */
  41 +#define EXCP_LINEF 11 /* Unimplemented line-F (FPU) opcode. */
  42 +#define EXCP_DEBUGNBP 12 /* Non-breakpoint debug interrupt. */
  43 +#define EXCP_DEBEGBP 13 /* Breakpoint debug interrupt. */
  44 +#define EXCP_FORMAT 14 /* RTE format error. */
  45 +#define EXCP_UNINITIALIZED 15
  46 +#define EXCP_TRAP0 32 /* User trap #0. */
  47 +#define EXCP_TRAP15 47 /* User trap #15. */
  48 +#define EXCP_UNSUPPORTED 61
  49 +#define EXCP_ICE 13
  50 +
  51 +typedef struct CPUM68KState {
  52 + uint32_t dregs[8];
  53 + uint32_t aregs[8];
  54 + uint32_t pc;
  55 + uint32_t sr;
  56 +
  57 + /* Condition flags. */
  58 + uint32_t cc_op;
  59 + uint32_t cc_dest;
  60 + uint32_t cc_src;
  61 + uint32_t cc_x;
  62 +
  63 + float64 fregs[8];
  64 + float64 fp_result;
  65 + uint32_t fpcr;
  66 + uint32_t fpsr;
  67 + float_status fp_status;
  68 +
  69 + /* Temporary storage for DIV helpers. */
  70 + uint32_t div1;
  71 + uint32_t div2;
  72 +
  73 + /* MMU status. */
  74 + struct {
  75 + uint32_t ar;
  76 + } mmu;
  77 + /* ??? remove this. */
  78 + uint32_t t1;
  79 +
  80 + /* exception/interrupt handling */
  81 + jmp_buf jmp_env;
  82 + int exception_index;
  83 + int interrupt_request;
  84 + int user_mode_only;
  85 + uint32_t address;
  86 +
  87 + uint32_t qregs[MAX_QREGS];
  88 +
  89 + CPU_COMMON
  90 +} CPUM68KState;
  91 +
  92 +CPUM68KState *cpu_m68k_init(void);
  93 +int cpu_m68k_exec(CPUM68KState *s);
  94 +void cpu_m68k_close(CPUM68KState *s);
  95 +/* you can call this signal handler from your SIGBUS and SIGSEGV
  96 + signal handlers to inform the virtual CPU of exceptions. non zero
  97 + is returned if the signal was handled by the virtual CPU. */
  98 +struct siginfo;
  99 +int cpu_m68k_signal_handler(int host_signum, struct siginfo *info,
  100 + void *puc);
  101 +void cpu_m68k_flush_flags(CPUM68KState *, int);
  102 +
  103 +enum {
  104 + CC_OP_DYNAMIC, /* Use env->cc_op */
  105 + CC_OP_FLAGS, /* CC_DEST = CVZN, CC_SRC = unused */
  106 + CC_OP_LOGIC, /* CC_DEST = result, CC_SRC = unused */
  107 + CC_OP_ADD, /* CC_DEST = result, CC_SRC = source */
  108 + CC_OP_SUB, /* CC_DEST = result, CC_SRC = source */
  109 + CC_OP_CMPB, /* CC_DEST = result, CC_SRC = source */
  110 + CC_OP_CMPW, /* CC_DEST = result, CC_SRC = source */
  111 + CC_OP_ADDX, /* CC_DEST = result, CC_SRC = source */
  112 + CC_OP_SUBX, /* CC_DEST = result, CC_SRC = source */
  113 + CC_OP_SHL, /* CC_DEST = source, CC_SRC = shift */
  114 + CC_OP_SHR, /* CC_DEST = source, CC_SRC = shift */
  115 + CC_OP_SAR, /* CC_DEST = source, CC_SRC = shift */
  116 +};
  117 +
  118 +#define CCF_C 0x01
  119 +#define CCF_V 0x02
  120 +#define CCF_Z 0x04
  121 +#define CCF_N 0x08
  122 +#define CCF_X 0x01
  123 +
  124 +typedef struct m68k_def_t m68k_def_t;
  125 +
  126 +m68k_def_t *m68k_find_by_name(const char *);
  127 +void cpu_m68k_register(CPUM68KState *, m68k_def_t *);
  128 +
  129 +#define M68K_FPCR_PREC (1 << 6)
  130 +
  131 +#ifdef CONFIG_USER_ONLY
  132 +/* Linux uses 8k pages. */
  133 +#define TARGET_PAGE_BITS 13
  134 +#else
  135 +/* Smallest TLB entry size is 1k. */
  136 +#define TARGET_PAGE_BITS 10
  137 +#endif
  138 +#include "cpu-all.h"
  139 +
  140 +#endif
... ...
target-m68k/exec.h 0 โ†’ 100644
  1 +/*
  2 + * m68k execution defines
  3 + *
  4 + * Copyright (c) 2005-2006 CodeSourcery
  5 + * Written by Paul Brook
  6 + *
  7 + * This library is free software; you can redistribute it and/or
  8 + * modify it under the terms of the GNU Lesser General Public
  9 + * License as published by the Free Software Foundation; either
  10 + * version 2 of the License, or (at your option) any later version.
  11 + *
  12 + * This library is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15 + * General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU Lesser General Public
  18 + * License along with this library; if not, write to the Free Software
  19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20 + */
  21 +#include "dyngen-exec.h"
  22 +
  23 +register struct CPUM68KState *env asm(AREG0);
  24 +/* This is only used for tb lookup. */
  25 +register uint32_t T0 asm(AREG1);
  26 +/* ??? We don't use T1, but common code expects it to exist */
  27 +#define T1 env->t1
  28 +
  29 +#include "cpu.h"
  30 +#include "exec-all.h"
  31 +
  32 +static inline void env_to_regs(void)
  33 +{
  34 +}
  35 +
  36 +static inline void regs_to_env(void)
  37 +{
  38 +}
  39 +
  40 +int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
  41 + int is_user, int is_softmmu);
  42 +
  43 +
  44 +void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op);
  45 +float64 helper_sub_cmpf64(CPUM68KState *env, float64 src0, float64 src1);
  46 +
  47 +void cpu_loop_exit(void);
... ...
target-m68k/helper.c 0 โ†’ 100644
  1 +/*
  2 + * m68k op helpers
  3 + *
  4 + * Copyright (c) 2006 CodeSourcery
  5 + * Written by Paul Brook
  6 + *
  7 + * This library is free software; you can redistribute it and/or
  8 + * modify it under the terms of the GNU Lesser General Public
  9 + * License as published by the Free Software Foundation; either
  10 + * version 2 of the License, or (at your option) any later version.
  11 + *
  12 + * This library is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15 + * General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU Lesser General Public
  18 + * License along with this library; if not, write to the Free Software
  19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20 + */
  21 +
  22 +#include <stdio.h>
  23 +
  24 +#include "config.h"
  25 +#include "cpu.h"
  26 +#include "exec-all.h"
  27 +
  28 +void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
  29 +{
  30 + int flags;
  31 + uint32_t src;
  32 + uint32_t dest;
  33 + uint32_t tmp;
  34 +
  35 +#define HIGHBIT 0x80000000u
  36 +
  37 +#define SET_NZ(x) do { \
  38 + if ((x) == 0) \
  39 + flags |= CCF_Z; \
  40 + else if ((int32_t)(x) < 0) \
  41 + flags |= CCF_N; \
  42 + } while (0)
  43 +
  44 +#define SET_FLAGS_SUB(type, utype) do { \
  45 + SET_NZ((type)dest); \
  46 + tmp = dest + src; \
  47 + if ((utype) tmp < (utype) src) \
  48 + flags |= CCF_C; \
  49 + if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \
  50 + flags |= CCF_V; \
  51 + } while (0)
  52 +
  53 + flags = 0;
  54 + src = env->cc_src;
  55 + dest = env->cc_dest;
  56 + switch (cc_op) {
  57 + case CC_OP_FLAGS:
  58 + flags = dest;
  59 + break;
  60 + case CC_OP_LOGIC:
  61 + SET_NZ(dest);
  62 + break;
  63 + case CC_OP_ADD:
  64 + SET_NZ(dest);
  65 + if (dest < src)
  66 + flags |= CCF_C;
  67 + tmp = dest - src;
  68 + if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
  69 + flags |= CCF_V;
  70 + break;
  71 + case CC_OP_SUB:
  72 + SET_FLAGS_SUB(int32_t, uint32_t);
  73 + break;
  74 + case CC_OP_CMPB:
  75 + SET_FLAGS_SUB(int8_t, uint8_t);
  76 + break;
  77 + case CC_OP_CMPW:
  78 + SET_FLAGS_SUB(int16_t, uint16_t);
  79 + break;
  80 + case CC_OP_ADDX:
  81 + SET_NZ(dest);
  82 + if (dest <= src)
  83 + flags |= CCF_C;
  84 + tmp = dest - src - 1;
  85 + if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
  86 + flags |= CCF_V;
  87 + break;
  88 + case CC_OP_SUBX:
  89 + SET_NZ(dest);
  90 + tmp = dest + src + 1;
  91 + if (tmp <= src)
  92 + flags |= CCF_C;
  93 + if (HIGHBIT & (tmp ^ dest) & (tmp ^ src))
  94 + flags |= CCF_V;
  95 + break;
  96 + case CC_OP_SHL:
  97 + if (src >= 32) {
  98 + SET_NZ(0);
  99 + } else {
  100 + tmp = dest << src;
  101 + SET_NZ(tmp);
  102 + }
  103 + if (src && src <= 32 && (dest & (1 << (32 - src))))
  104 + flags |= CCF_C;
  105 + break;
  106 + case CC_OP_SHR:
  107 + if (src >= 32) {
  108 + SET_NZ(0);
  109 + } else {
  110 + tmp = dest >> src;
  111 + SET_NZ(tmp);
  112 + }
  113 + if (src && src <= 32 && ((dest >> (src - 1)) & 1))
  114 + flags |= CCF_C;
  115 + break;
  116 + case CC_OP_SAR:
  117 + if (src >= 32) {
  118 + SET_NZ(-1);
  119 + } else {
  120 + tmp = (int32_t)dest >> src;
  121 + SET_NZ(tmp);
  122 + }
  123 + if (src && src <= 32 && (((int32_t)dest >> (src - 1)) & 1))
  124 + flags |= CCF_C;
  125 + break;
  126 + default:
  127 + cpu_abort(env, "Bad CC_OP %d", cc_op);
  128 + }
  129 + env->cc_op = CC_OP_FLAGS;
  130 + env->cc_dest = flags;
  131 +}
  132 +
  133 +float64 helper_sub_cmpf64(CPUM68KState *env, float64 src0, float64 src1)
  134 +{
  135 + /* ??? This may incorrectly raise exceptions. */
  136 + /* ??? Should flush denormals to zero. */
  137 + float64 res;
  138 + res = float64_sub(src0, src1, &env->fp_status);
  139 + if (float64_is_nan(res)) {
  140 + /* +/-inf compares equal against itself, but sub returns nan. */
  141 + if (!float64_is_nan(src0)
  142 + && !float64_is_nan(src1)) {
  143 + res = 0;
  144 + if (float64_lt_quiet(src0, res, &env->fp_status))
  145 + res = float64_chs(res);
  146 + }
  147 + }
  148 + return res;
  149 +}
... ...
target-m68k/m68k-qreg.h 0 โ†’ 100644
  1 +enum {
  2 +#define DEFO32(name, offset) QREG_##name,
  3 +#define DEFR(name, reg, mode) QREG_##name,
  4 +#define DEFF64(name, offset) QREG_##name,
  5 + QREG_NULL,
  6 +#include "qregs.def"
  7 + TARGET_NUM_QREGS = 0x100
  8 +#undef DEFO32
  9 +#undef DEFR
  10 +#undef DEFF64
  11 +};
  12 +
... ...
target-m68k/op-hacks.h 0 โ†’ 100644
  1 +/* Various hacks to make code written for a dynamic code generator work
  2 + with regular QEMU. */
  3 +
  4 +static int free_qreg;
  5 +
  6 +#define QMODE_I32 1
  7 +#define QMODE_F32 1
  8 +#define QMODE_F64 2
  9 +
  10 +static inline int gen_new_qreg(int mode)
  11 +{
  12 + int qreg;
  13 +
  14 + qreg = free_qreg;
  15 + free_qreg += mode;
  16 + if (free_qreg > MAX_QREGS) {
  17 + fprintf(stderr, "qreg overflow\n");
  18 + abort();
  19 + }
  20 + return qreg + TARGET_NUM_QREGS;
  21 +}
  22 +
  23 +static inline int gen_im32(uint32_t i)
  24 +{
  25 + int qreg = gen_new_qreg(QMODE_I32);
  26 + gen_op_mov32_im(qreg, i);
  27 + return qreg;
  28 +}
  29 +
  30 +static inline void gen_op_ldf32(int dest, int addr)
  31 +{
  32 + gen_op_ld32(dest, addr);
  33 +}
  34 +
  35 +static inline void gen_op_stf32(int addr, int dest)
  36 +{
  37 + gen_op_st32(addr, dest);
  38 +}
  39 +
  40 +static inline void gen_op_pack_32_f32(int dest, int src)
  41 +{
  42 + gen_op_mov32(dest, src);
  43 +}
  44 +
  45 +static inline void gen_op_pack_f32_32(int dest, int src)
  46 +{
  47 + gen_op_mov32(dest, src);
  48 +}
  49 +
  50 +static inline void gen_op_flags_set(void)
  51 +{
  52 + /* Dummy op. */
  53 +}
  54 +
  55 +static inline void gen_op_shl_im_cc(int val, int shift)
  56 +{
  57 + gen_op_shl_cc(val, gen_im32(shift));
  58 +}
  59 +
  60 +static inline void gen_op_shr_im_cc(int val, int shift)
  61 +{
  62 + gen_op_shr_cc(val, gen_im32(shift));
  63 +}
  64 +
  65 +static inline void gen_op_sar_im_cc(int val, int shift)
  66 +{
  67 + gen_op_sar_cc(val, gen_im32(shift));
  68 +}
  69 +
  70 +#ifdef USE_DIRECT_JUMP
  71 +#define TBPARAM(x)
  72 +#else
  73 +#define TBPARAM(x) (long)(x)
  74 +#endif
  75 +
  76 +static inline void gen_op_goto_tb(int dummy, int n, long tb)
  77 +{
  78 + if (n == 0) {
  79 + gen_op_goto_tb0(TBPARAM(tb));
  80 + } else {
  81 + gen_op_goto_tb1(TBPARAM(tb));
  82 + }
  83 +}
... ...
target-m68k/op.c 0 โ†’ 100644
  1 +/*
  2 + * m68k micro operations
  3 + *
  4 + * Copyright (c) 2006 CodeSourcery
  5 + * Written by Paul Brook
  6 + *
  7 + * This library is free software; you can redistribute it and/or
  8 + * modify it under the terms of the GNU Lesser General Public
  9 + * License as published by the Free Software Foundation; either
  10 + * version 2 of the License, or (at your option) any later version.
  11 + *
  12 + * This library is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15 + * General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU Lesser General Public
  18 + * License along with this library; if not, write to the Free Software
  19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20 + */
  21 +
  22 +#include "exec.h"
  23 +#include "m68k-qreg.h"
  24 +
  25 +#ifndef offsetof
  26 +#define offsetof(type, field) ((size_t) &((type *)0)->field)
  27 +#endif
  28 +
  29 +static long qreg_offsets[] = {
  30 +#define DEFO32(name, offset) offsetof(CPUState, offset),
  31 +#define DEFR(name, reg, mode) -1,
  32 +#define DEFF64(name, offset) offsetof(CPUState, offset),
  33 + 0,
  34 +#include "qregs.def"
  35 +};
  36 +
  37 +#define CPU_FP_STATUS env->fp_status
  38 +
  39 +#define RAISE_EXCEPTION(n) do { \
  40 + env->exception_index = n; \
  41 + cpu_loop_exit(); \
  42 + } while(0)
  43 +
  44 +#define get_op helper_get_op
  45 +#define set_op helper_set_op
  46 +#define get_opf64 helper_get_opf64
  47 +#define set_opf64 helper_set_opf64
  48 +uint32_t
  49 +get_op(int qreg)
  50 +{
  51 + if (qreg == QREG_T0) {
  52 + return T0;
  53 + } else if (qreg < TARGET_NUM_QREGS) {
  54 + return *(uint32_t *)(((long)env) + qreg_offsets[qreg]);
  55 + } else {
  56 + return env->qregs[qreg - TARGET_NUM_QREGS];
  57 + }
  58 +}
  59 +
  60 +void set_op(int qreg, uint32_t val)
  61 +{
  62 + if (qreg == QREG_T0) {
  63 + T0 = val;
  64 + } else if (qreg < TARGET_NUM_QREGS) {
  65 + *(uint32_t *)(((long)env) + qreg_offsets[qreg]) = val;
  66 + } else {
  67 + env->qregs[qreg - TARGET_NUM_QREGS] = val;
  68 + }
  69 +}
  70 +
  71 +float64 get_opf64(int qreg)
  72 +{
  73 + if (qreg < TARGET_NUM_QREGS) {
  74 + return *(float64 *)(((long)env) + qreg_offsets[qreg]);
  75 + } else {
  76 + return *(float64 *)&env->qregs[qreg - TARGET_NUM_QREGS];
  77 + }
  78 +}
  79 +
  80 +void set_opf64(int qreg, float64 val)
  81 +{
  82 + if (qreg < TARGET_NUM_QREGS) {
  83 + *(float64 *)(((long)env) + qreg_offsets[qreg]) = val;
  84 + } else {
  85 + *(float64 *)&env->qregs[qreg - TARGET_NUM_QREGS] = val;
  86 + }
  87 +}
  88 +
  89 +#define OP(name) void OPPROTO op_##name (void)
  90 +
  91 +OP(mov32)
  92 +{
  93 + set_op(PARAM1, get_op(PARAM2));
  94 + FORCE_RET();
  95 +}
  96 +
  97 +OP(mov32_im)
  98 +{
  99 + set_op(PARAM1, PARAM2);
  100 + FORCE_RET();
  101 +}
  102 +
  103 +OP(movf64)
  104 +{
  105 + set_opf64(PARAM1, get_opf64(PARAM2));
  106 + FORCE_RET();
  107 +}
  108 +
  109 +OP(zerof64)
  110 +{
  111 + set_opf64(PARAM1, 0);
  112 + FORCE_RET();
  113 +}
  114 +
  115 +OP(add32)
  116 +{
  117 + uint32_t op2 = get_op(PARAM2);
  118 + uint32_t op3 = get_op(PARAM3);
  119 + set_op(PARAM1, op2 + op3);
  120 + FORCE_RET();
  121 +}
  122 +
  123 +OP(sub32)
  124 +{
  125 + uint32_t op2 = get_op(PARAM2);
  126 + uint32_t op3 = get_op(PARAM3);
  127 + set_op(PARAM1, op2 - op3);
  128 + FORCE_RET();
  129 +}
  130 +
  131 +OP(mul32)
  132 +{
  133 + uint32_t op2 = get_op(PARAM2);
  134 + uint32_t op3 = get_op(PARAM3);
  135 + set_op(PARAM1, op2 * op3);
  136 + FORCE_RET();
  137 +}
  138 +
  139 +OP(not32)
  140 +{
  141 + uint32_t arg = get_op(PARAM2);
  142 + set_op(PARAM1, ~arg);
  143 + FORCE_RET();
  144 +}
  145 +
  146 +OP(neg32)
  147 +{
  148 + uint32_t arg = get_op(PARAM2);
  149 + set_op(PARAM1, -arg);
  150 + FORCE_RET();
  151 +}
  152 +
  153 +OP(bswap32)
  154 +{
  155 + uint32_t arg = get_op(PARAM2);
  156 + arg = (arg >> 24) | (arg << 24)
  157 + | ((arg >> 16) & 0xff00) | ((arg << 16) & 0xff0000);
  158 + set_op(PARAM1, arg);
  159 + FORCE_RET();
  160 +}
  161 +
  162 +OP(btest)
  163 +{
  164 + uint32_t op1 = get_op(PARAM1);
  165 + uint32_t op2 = get_op(PARAM2);
  166 + if (op1 & op2)
  167 + env->cc_dest &= ~CCF_Z;
  168 + else
  169 + env->cc_dest |= CCF_Z;
  170 + FORCE_RET();
  171 +}
  172 +
  173 +OP(addx_cc)
  174 +{
  175 + uint32_t op1 = get_op(PARAM1);
  176 + uint32_t op2 = get_op(PARAM2);
  177 + uint32_t res;
  178 + if (env->cc_x) {
  179 + env->cc_x = (op1 <= op2);
  180 + env->cc_op = CC_OP_SUBX;
  181 + res = op1 - (op2 + 1);
  182 + } else {
  183 + env->cc_x = (op1 < op2);
  184 + env->cc_op = CC_OP_SUB;
  185 + res = op1 - op2;
  186 + }
  187 + set_op(PARAM1, res);
  188 + FORCE_RET();
  189 +}
  190 +
  191 +OP(subx_cc)
  192 +{
  193 + uint32_t op1 = get_op(PARAM1);
  194 + uint32_t op2 = get_op(PARAM2);
  195 + uint32_t res;
  196 + if (env->cc_x) {
  197 + res = op1 + op2 + 1;
  198 + env->cc_x = (res <= op2);
  199 + env->cc_op = CC_OP_ADDX;
  200 + } else {
  201 + res = op1 + op2;
  202 + env->cc_x = (res < op2);
  203 + env->cc_op = CC_OP_ADD;
  204 + }
  205 + set_op(PARAM1, res);
  206 + FORCE_RET();
  207 +}
  208 +
  209 +/* Logic ops. */
  210 +
  211 +OP(and32)
  212 +{
  213 + uint32_t op2 = get_op(PARAM2);
  214 + uint32_t op3 = get_op(PARAM3);
  215 + set_op(PARAM1, op2 & op3);
  216 + FORCE_RET();
  217 +}
  218 +
  219 +OP(or32)
  220 +{
  221 + uint32_t op2 = get_op(PARAM2);
  222 + uint32_t op3 = get_op(PARAM3);
  223 + set_op(PARAM1, op2 | op3);
  224 + FORCE_RET();
  225 +}
  226 +
  227 +OP(xor32)
  228 +{
  229 + uint32_t op2 = get_op(PARAM2);
  230 + uint32_t op3 = get_op(PARAM3);
  231 + set_op(PARAM1, op2 ^ op3);
  232 + FORCE_RET();
  233 +}
  234 +
  235 +/* Shifts. */
  236 +OP(shl32)
  237 +{
  238 + uint32_t op2 = get_op(PARAM2);
  239 + uint32_t op3 = get_op(PARAM3);
  240 + uint32_t result;
  241 + result = op2 << op3;
  242 + set_op(PARAM1, result);
  243 + FORCE_RET();
  244 +}
  245 +
  246 +OP(shl_cc)
  247 +{
  248 + uint32_t op1 = get_op(PARAM1);
  249 + uint32_t op2 = get_op(PARAM2);
  250 + uint32_t result;
  251 + result = op1 << op2;
  252 + set_op(PARAM1, result);
  253 + env->cc_x = (op1 << (op2 - 1)) & 1;
  254 + FORCE_RET();
  255 +}
  256 +
  257 +OP(shr32)
  258 +{
  259 + uint32_t op2 = get_op(PARAM2);
  260 + uint32_t op3 = get_op(PARAM3);
  261 + uint32_t result;
  262 + result = op2 >> op3;
  263 + set_op(PARAM1, result);
  264 + FORCE_RET();
  265 +}
  266 +
  267 +OP(shr_cc)
  268 +{
  269 + uint32_t op1 = get_op(PARAM1);
  270 + uint32_t op2 = get_op(PARAM2);
  271 + uint32_t result;
  272 + result = op1 >> op2;
  273 + set_op(PARAM1, result);
  274 + env->cc_x = (op1 >> (op2 - 1)) & 1;
  275 + FORCE_RET();
  276 +}
  277 +
  278 +OP(sar_cc)
  279 +{
  280 + int32_t op1 = get_op(PARAM1);
  281 + uint32_t op2 = get_op(PARAM2);
  282 + uint32_t result;
  283 + result = op1 >> op2;
  284 + set_op(PARAM1, result);
  285 + env->cc_x = (op1 >> (op2 - 1)) & 1;
  286 + FORCE_RET();
  287 +}
  288 +
  289 +/* Value extend. */
  290 +
  291 +OP(ext8u32)
  292 +{
  293 + uint32_t op2 = get_op(PARAM2);
  294 + set_op(PARAM1, (uint8_t)op2);
  295 + FORCE_RET();
  296 +}
  297 +
  298 +OP(ext8s32)
  299 +{
  300 + uint32_t op2 = get_op(PARAM2);
  301 + set_op(PARAM1, (int8_t)op2);
  302 + FORCE_RET();
  303 +}
  304 +
  305 +OP(ext16u32)
  306 +{
  307 + uint32_t op2 = get_op(PARAM2);
  308 + set_op(PARAM1, (uint16_t)op2);
  309 + FORCE_RET();
  310 +}
  311 +
  312 +OP(ext16s32)
  313 +{
  314 + uint32_t op2 = get_op(PARAM2);
  315 + set_op(PARAM1, (int16_t)op2);
  316 + FORCE_RET();
  317 +}
  318 +
  319 +/* Load/store ops. */
  320 +OP(ld8u32)
  321 +{
  322 + uint32_t addr = get_op(PARAM2);
  323 + set_op(PARAM1, ldub(addr));
  324 + FORCE_RET();
  325 +}
  326 +
  327 +OP(ld8s32)
  328 +{
  329 + uint32_t addr = get_op(PARAM2);
  330 + set_op(PARAM1, ldsb(addr));
  331 + FORCE_RET();
  332 +}
  333 +
  334 +OP(ld16u32)
  335 +{
  336 + uint32_t addr = get_op(PARAM2);
  337 + set_op(PARAM1, lduw(addr));
  338 + FORCE_RET();
  339 +}
  340 +
  341 +OP(ld16s32)
  342 +{
  343 + uint32_t addr = get_op(PARAM2);
  344 + set_op(PARAM1, ldsw(addr));
  345 + FORCE_RET();
  346 +}
  347 +
  348 +OP(ld32)
  349 +{
  350 + uint32_t addr = get_op(PARAM2);
  351 + set_op(PARAM1, ldl(addr));
  352 + FORCE_RET();
  353 +}
  354 +
  355 +OP(st8)
  356 +{
  357 + uint32_t addr = get_op(PARAM1);
  358 + stb(addr, get_op(PARAM2));
  359 + FORCE_RET();
  360 +}
  361 +
  362 +OP(st16)
  363 +{
  364 + uint32_t addr = get_op(PARAM1);
  365 + stw(addr, get_op(PARAM2));
  366 + FORCE_RET();
  367 +}
  368 +
  369 +OP(st32)
  370 +{
  371 + uint32_t addr = get_op(PARAM1);
  372 + stl(addr, get_op(PARAM2));
  373 + FORCE_RET();
  374 +}
  375 +
  376 +OP(ldf64)
  377 +{
  378 + uint32_t addr = get_op(PARAM2);
  379 + set_opf64(PARAM1, ldfq(addr));
  380 + FORCE_RET();
  381 +}
  382 +
  383 +OP(stf64)
  384 +{
  385 + uint32_t addr = get_op(PARAM1);
  386 + stfq(addr, get_opf64(PARAM2));
  387 + FORCE_RET();
  388 +}
  389 +
  390 +OP(flush_flags)
  391 +{
  392 + int cc_op = PARAM1;
  393 + if (cc_op == CC_OP_DYNAMIC)
  394 + cc_op = env->cc_op;
  395 + cpu_m68k_flush_flags(env, cc_op);
  396 + FORCE_RET();
  397 +}
  398 +
  399 +OP(divu)
  400 +{
  401 + uint32_t num;
  402 + uint32_t den;
  403 + uint32_t quot;
  404 + uint32_t rem;
  405 + uint32_t flags;
  406 +
  407 + num = env->div1;
  408 + den = env->div2;
  409 + /* ??? This needs to make sure the throwing location is accurate. */
  410 + if (den == 0)
  411 + RAISE_EXCEPTION(EXCP_DIV0);
  412 + quot = num / den;
  413 + rem = num % den;
  414 + flags = 0;
  415 + if (PARAM1 && quot > 0xffff)
  416 + flags |= CCF_V;
  417 + if (quot == 0)
  418 + flags |= CCF_Z;
  419 + else if ((int32_t)quot < 0)
  420 + flags |= CCF_N;
  421 + env->div1 = quot;
  422 + env->div2 = rem;
  423 + env->cc_dest = flags;
  424 + FORCE_RET();
  425 +}
  426 +
  427 +OP(divs)
  428 +{
  429 + int32_t num;
  430 + int32_t den;
  431 + int32_t quot;
  432 + int32_t rem;
  433 + int32_t flags;
  434 +
  435 + num = env->div1;
  436 + den = env->div2;
  437 + if (den == 0)
  438 + RAISE_EXCEPTION(EXCP_DIV0);
  439 + quot = num / den;
  440 + rem = num % den;
  441 + flags = 0;
  442 + if (PARAM1 && quot != (int16_t)quot)
  443 + flags |= CCF_V;
  444 + if (quot == 0)
  445 + flags |= CCF_Z;
  446 + else if (quot < 0)
  447 + flags |= CCF_N;
  448 + env->div1 = quot;
  449 + env->div2 = rem;
  450 + env->cc_dest = flags;
  451 + FORCE_RET();
  452 +}
  453 +
  454 +OP(raise_exception)
  455 +{
  456 + RAISE_EXCEPTION(PARAM1);
  457 + FORCE_RET();
  458 +}
  459 +
  460 +/* Floating point comparison sets flags differently to other instructions. */
  461 +
  462 +OP(sub_cmpf64)
  463 +{
  464 + float64 src0;
  465 + float64 src1;
  466 + src0 = get_opf64(PARAM2);
  467 + src1 = get_opf64(PARAM3);
  468 + set_opf64(PARAM1, helper_sub_cmpf64(env, src0, src1));
  469 + FORCE_RET();
  470 +}
  471 +
  472 +OP(update_xflag_tst)
  473 +{
  474 + uint32_t op1 = get_op(PARAM1);
  475 + env->cc_x = op1;
  476 + FORCE_RET();
  477 +}
  478 +
  479 +OP(update_xflag_lt)
  480 +{
  481 + uint32_t op1 = get_op(PARAM1);
  482 + uint32_t op2 = get_op(PARAM2);
  483 + env->cc_x = (op1 < op2);
  484 + FORCE_RET();
  485 +}
  486 +
  487 +OP(get_xflag)
  488 +{
  489 + set_op(PARAM1, env->cc_x);
  490 + FORCE_RET();
  491 +}
  492 +
  493 +OP(logic_cc)
  494 +{
  495 + uint32_t op1 = get_op(PARAM1);
  496 + env->cc_dest = op1;
  497 + FORCE_RET();
  498 +}
  499 +
  500 +OP(update_cc_add)
  501 +{
  502 + uint32_t op1 = get_op(PARAM1);
  503 + uint32_t op2 = get_op(PARAM2);
  504 + env->cc_dest = op1;
  505 + env->cc_src = op2;
  506 + FORCE_RET();
  507 +}
  508 +
  509 +OP(fp_result)
  510 +{
  511 + env->fp_result = get_opf64(PARAM1);
  512 + FORCE_RET();
  513 +}
  514 +
  515 +OP(jmp)
  516 +{
  517 + GOTO_LABEL_PARAM(1);
  518 +}
  519 +
  520 +/* These ops involve a function call, which probably requires a stack frame
  521 + and breaks things on some hosts. */
  522 +OP(jmp_z32)
  523 +{
  524 + uint32_t arg = get_op(PARAM1);
  525 + if (arg == 0)
  526 + GOTO_LABEL_PARAM(2);
  527 + FORCE_RET();
  528 +}
  529 +
  530 +OP(jmp_nz32)
  531 +{
  532 + uint32_t arg = get_op(PARAM1);
  533 + if (arg != 0)
  534 + GOTO_LABEL_PARAM(2);
  535 + FORCE_RET();
  536 +}
  537 +
  538 +OP(jmp_s32)
  539 +{
  540 + int32_t arg = get_op(PARAM1);
  541 + if (arg < 0)
  542 + GOTO_LABEL_PARAM(2);
  543 + FORCE_RET();
  544 +}
  545 +
  546 +OP(jmp_ns32)
  547 +{
  548 + int32_t arg = get_op(PARAM1);
  549 + if (arg >= 0)
  550 + GOTO_LABEL_PARAM(2);
  551 + FORCE_RET();
  552 +}
  553 +
  554 +void OPPROTO op_goto_tb0(void)
  555 +{
  556 + GOTO_TB(op_goto_tb0, PARAM1, 0);
  557 +}
  558 +
  559 +void OPPROTO op_goto_tb1(void)
  560 +{
  561 + GOTO_TB(op_goto_tb1, PARAM1, 1);
  562 +}
  563 +
  564 +OP(exit_tb)
  565 +{
  566 + EXIT_TB();
  567 +}
  568 +
  569 +
  570 +/* Floating point. */
  571 +OP(f64_to_i32)
  572 +{
  573 + set_op(PARAM1, float64_to_int32(get_opf64(PARAM2), &CPU_FP_STATUS));
  574 + FORCE_RET();
  575 +}
  576 +
  577 +OP(f64_to_f32)
  578 +{
  579 + union {
  580 + float32 f;
  581 + uint32_t i;
  582 + } u;
  583 + u.f = float64_to_float32(get_opf64(PARAM2), &CPU_FP_STATUS);
  584 + set_op(PARAM1, u.i);
  585 + FORCE_RET();
  586 +}
  587 +
  588 +OP(i32_to_f64)
  589 +{
  590 + set_opf64(PARAM1, int32_to_float64(get_op(PARAM2), &CPU_FP_STATUS));
  591 + FORCE_RET();
  592 +}
  593 +
  594 +OP(f32_to_f64)
  595 +{
  596 + union {
  597 + float32 f;
  598 + uint32_t i;
  599 + } u;
  600 + u.i = get_op(PARAM2);
  601 + set_opf64(PARAM1, float32_to_float64(u.f, &CPU_FP_STATUS));
  602 + FORCE_RET();
  603 +}
  604 +
  605 +OP(absf64)
  606 +{
  607 + float64 op0 = get_opf64(PARAM2);
  608 + set_opf64(PARAM1, float64_abs(op0));
  609 + FORCE_RET();
  610 +}
  611 +
  612 +OP(chsf64)
  613 +{
  614 + float64 op0 = get_opf64(PARAM2);
  615 + set_opf64(PARAM1, float64_chs(op0));
  616 + FORCE_RET();
  617 +}
  618 +
  619 +OP(sqrtf64)
  620 +{
  621 + float64 op0 = get_opf64(PARAM2);
  622 + set_opf64(PARAM1, float64_sqrt(op0, &CPU_FP_STATUS));
  623 + FORCE_RET();
  624 +}
  625 +
  626 +OP(addf64)
  627 +{
  628 + float64 op0 = get_opf64(PARAM2);
  629 + float64 op1 = get_opf64(PARAM3);
  630 + set_opf64(PARAM1, float64_add(op0, op1, &CPU_FP_STATUS));
  631 + FORCE_RET();
  632 +}
  633 +
  634 +OP(subf64)
  635 +{
  636 + float64 op0 = get_opf64(PARAM2);
  637 + float64 op1 = get_opf64(PARAM3);
  638 + set_opf64(PARAM1, float64_sub(op0, op1, &CPU_FP_STATUS));
  639 + FORCE_RET();
  640 +}
  641 +
  642 +OP(mulf64)
  643 +{
  644 + float64 op0 = get_opf64(PARAM2);
  645 + float64 op1 = get_opf64(PARAM3);
  646 + set_opf64(PARAM1, float64_mul(op0, op1, &CPU_FP_STATUS));
  647 + FORCE_RET();
  648 +}
  649 +
  650 +OP(divf64)
  651 +{
  652 + float64 op0 = get_opf64(PARAM2);
  653 + float64 op1 = get_opf64(PARAM3);
  654 + set_opf64(PARAM1, float64_div(op0, op1, &CPU_FP_STATUS));
  655 + FORCE_RET();
  656 +}
  657 +
  658 +OP(iround_f64)
  659 +{
  660 + float64 op0 = get_opf64(PARAM2);
  661 + set_opf64(PARAM1, float64_round_to_int(op0, &CPU_FP_STATUS));
  662 + FORCE_RET();
  663 +}
  664 +
  665 +OP(itrunc_f64)
  666 +{
  667 + float64 op0 = get_opf64(PARAM2);
  668 + set_opf64(PARAM1, float64_trunc_to_int(op0, &CPU_FP_STATUS));
  669 + FORCE_RET();
  670 +}
  671 +
  672 +OP(compare_quietf64)
  673 +{
  674 + float64 op0 = get_opf64(PARAM2);
  675 + float64 op1 = get_opf64(PARAM3);
  676 + set_op(PARAM1, float64_compare_quiet(op0, op1, &CPU_FP_STATUS));
  677 + FORCE_RET();
  678 +}
... ...
target-m68k/qregs.def 0 โ†’ 100644
  1 +DEFO32(D0, dregs[0])
  2 +DEFO32(D1, dregs[1])
  3 +DEFO32(D2, dregs[2])
  4 +DEFO32(D3, dregs[3])
  5 +DEFO32(D4, dregs[4])
  6 +DEFO32(D5, dregs[5])
  7 +DEFO32(D6, dregs[6])
  8 +DEFO32(D7, dregs[7])
  9 +DEFO32(A0, aregs[0])
  10 +DEFO32(A1, aregs[1])
  11 +DEFO32(A2, aregs[2])
  12 +DEFO32(A3, aregs[3])
  13 +DEFO32(A4, aregs[4])
  14 +DEFO32(A5, aregs[5])
  15 +DEFO32(A6, aregs[6])
  16 +DEFO32(SP, aregs[7]) /* A7 */
  17 +DEFF64(F0, fregs[0])
  18 +DEFF64(F1, fregs[1])
  19 +DEFF64(F2, fregs[2])
  20 +DEFF64(F3, fregs[3])
  21 +DEFF64(F4, fregs[4])
  22 +DEFF64(F5, fregs[5])
  23 +DEFF64(F6, fregs[6])
  24 +DEFF64(F7, fregs[7])
  25 +DEFF64(FP_RESULT, fp_result)
  26 +DEFO32(PC, pc)
  27 +DEFO32(CC_OP, cc_op)
  28 +DEFR(T0, AREG1, QMODE_I32)
  29 +DEFO32(CC_DEST, cc_dest)
  30 +DEFO32(CC_SRC, cc_src)
  31 +DEFO32(CC_X, cc_x)
  32 +DEFO32(DIV1, div1)
  33 +DEFO32(DIV2, div2)
  34 +DEFO32(EXCEPTION, exception_index)
... ...
target-m68k/translate.c 0 โ†’ 100644
  1 +/*
  2 + * m68k translation
  3 + *
  4 + * Copyright (c) 2005-2006 CodeSourcery
  5 + * Written by Paul Brook
  6 + *
  7 + * This library is free software; you can redistribute it and/or
  8 + * modify it under the terms of the GNU Lesser General Public
  9 + * License as published by the Free Software Foundation; either
  10 + * version 2 of the License, or (at your option) any later version.
  11 + *
  12 + * This library is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15 + * General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU Lesser General Public
  18 + * License along with this library; if not, write to the Free Software
  19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20 + */
  21 +#include <stdarg.h>
  22 +#include <stdlib.h>
  23 +#include <stdio.h>
  24 +#include <string.h>
  25 +#include <inttypes.h>
  26 +
  27 +#include "config.h"
  28 +#include "cpu.h"
  29 +#include "exec-all.h"
  30 +#include "disas.h"
  31 +#include "m68k-qreg.h"
  32 +
  33 +static inline void qemu_assert(int cond, const char *msg)
  34 +{
  35 + if (!cond) {
  36 + fprintf (stderr, "badness: %s\n", msg);
  37 + abort();
  38 + }
  39 +}
  40 +
  41 +/* internal defines */
  42 +typedef struct DisasContext {
  43 + target_ulong pc;
  44 + int is_jmp;
  45 + int cc_op;
  46 + uint32_t fpcr;
  47 + struct TranslationBlock *tb;
  48 + int singlestep_enabled;
  49 +} DisasContext;
  50 +
  51 +#define DISAS_JUMP_NEXT 4
  52 +
  53 +/* XXX: move that elsewhere */
  54 +/* ??? Fix exceptions. */
  55 +static void *gen_throws_exception;
  56 +#define gen_last_qop NULL
  57 +
  58 +static uint16_t *gen_opc_ptr;
  59 +static uint32_t *gen_opparam_ptr;
  60 +extern FILE *logfile;
  61 +extern int loglevel;
  62 +
  63 +enum {
  64 +#define DEF(s, n, copy_size) INDEX_op_ ## s,
  65 +#include "opc.h"
  66 +#undef DEF
  67 + NB_OPS,
  68 +};
  69 +
  70 +#include "gen-op.h"
  71 +#include "op-hacks.h"
  72 +
  73 +#define OS_BYTE 0
  74 +#define OS_WORD 1
  75 +#define OS_LONG 2
  76 +#define OS_SINGLE 4
  77 +#define OS_DOUBLE 5
  78 +
  79 +#define DREG(insn, pos) (((insn >> pos) & 7) + QREG_D0)
  80 +#define AREG(insn, pos) (((insn >> pos) & 7) + QREG_A0)
  81 +#define FREG(insn, pos) (((insn >> pos) & 7) + QREG_F0)
  82 +
  83 +#define M68K_INSN_CF_A (1 << 0)
  84 +#define M68K_INSN_CF_B (1 << 1)
  85 +#define M68K_INSN_CF_C (1 << 2)
  86 +#define M68K_INSN_CF_MAC (1 << 3)
  87 +#define M68K_INSN_CF_EMAC (1 << 4)
  88 +#define M68K_INSN_CF_FPU (1 << 5)
  89 +
  90 +struct m68k_def_t {
  91 + const char * name;
  92 + uint32_t insns;
  93 +};
  94 +
  95 +static m68k_def_t m68k_cpu_defs[] = {
  96 + {"m5206", M68K_INSN_CF_A},
  97 + {"cfv4e", M68K_INSN_CF_A | M68K_INSN_CF_B | M68K_INSN_CF_C
  98 + | M68K_INSN_CF_MAC | M68K_INSN_CF_EMAC | M68K_INSN_CF_FPU},
  99 + {NULL, 0},
  100 +};
  101 +
  102 +typedef void (*disas_proc)(DisasContext *, uint16_t);
  103 +
  104 +#define DISAS_INSN(name) \
  105 + static void disas_##name (DisasContext *s, uint16_t insn)
  106 +
  107 +/* Generate a load from the specified address. Narrow values are
  108 + sign extended to full register width. */
  109 +static inline int gen_load(int opsize, int addr, int sign)
  110 +{
  111 + int tmp;
  112 + switch(opsize) {
  113 + case OS_BYTE:
  114 + tmp = gen_new_qreg(QMODE_I32);
  115 + if (sign)
  116 + gen_op_ld8s32(tmp, addr);
  117 + else
  118 + gen_op_ld8u32(tmp, addr);
  119 + break;
  120 + case OS_WORD:
  121 + tmp = gen_new_qreg(QMODE_I32);
  122 + if (sign)
  123 + gen_op_ld16s32(tmp, addr);
  124 + else
  125 + gen_op_ld16u32(tmp, addr);
  126 + break;
  127 + case OS_LONG:
  128 + tmp = gen_new_qreg(QMODE_I32);
  129 + gen_op_ld32(tmp, addr);
  130 + break;
  131 + case OS_SINGLE:
  132 + tmp = gen_new_qreg(QMODE_F32);
  133 + gen_op_ldf32(tmp, addr);
  134 + break;
  135 + case OS_DOUBLE:
  136 + tmp = gen_new_qreg(QMODE_F64);
  137 + gen_op_ldf64(tmp, addr);
  138 + break;
  139 + default:
  140 + qemu_assert(0, "bad load size");
  141 + }
  142 + gen_throws_exception = gen_last_qop;
  143 + return tmp;
  144 +}
  145 +
  146 +/* Generate a store. */
  147 +static inline void gen_store(int opsize, int addr, int val)
  148 +{
  149 + switch(opsize) {
  150 + case OS_BYTE:
  151 + gen_op_st8(addr, val);
  152 + break;
  153 + case OS_WORD:
  154 + gen_op_st16(addr, val);
  155 + break;
  156 + case OS_LONG:
  157 + gen_op_st32(addr, val);
  158 + break;
  159 + case OS_SINGLE:
  160 + gen_op_stf32(addr, val);
  161 + break;
  162 + case OS_DOUBLE:
  163 + gen_op_stf64(addr, val);
  164 + break;
  165 + default:
  166 + qemu_assert(0, "bad store size");
  167 + }
  168 + gen_throws_exception = gen_last_qop;
  169 +}
  170 +
  171 +/* Generate an unsigned load if VAL is 0 a signed load if val is -1,
  172 + otherwise generate a store. */
  173 +static int gen_ldst(int opsize, int addr, int val)
  174 +{
  175 + if (val > 0) {
  176 + gen_store(opsize, addr, val);
  177 + return 0;
  178 + } else {
  179 + return gen_load(opsize, addr, val != 0);
  180 + }
  181 +}
  182 +
  183 +/* Handle a base + index + displacement effective addresss. A base of
  184 + -1 means pc-relative. */
  185 +static int gen_lea_indexed(DisasContext *s, int opsize, int base)
  186 +{
  187 + int scale;
  188 + uint32_t offset;
  189 + uint16_t ext;
  190 + int add;
  191 + int tmp;
  192 +
  193 + offset = s->pc;
  194 + ext = lduw(s->pc);
  195 + s->pc += 2;
  196 + tmp = ((ext >> 12) & 7) + ((ext & 0x8000) ? QREG_A0 : QREG_D0);
  197 + /* ??? Check W/L bit. */
  198 + scale = (ext >> 9) & 3;
  199 + if (scale == 0) {
  200 + add = tmp;
  201 + } else {
  202 + add = gen_new_qreg(QMODE_I32);
  203 + gen_op_shl32(add, tmp, gen_im32(scale));
  204 + }
  205 + tmp = gen_new_qreg(QMODE_I32);
  206 + if (base != -1) {
  207 + gen_op_add32(tmp, base, gen_im32((int8_t)ext));
  208 + gen_op_add32(tmp, tmp, add);
  209 + } else {
  210 + gen_op_add32(tmp, add, gen_im32(offset + (int8_t)ext));
  211 + }
  212 + return tmp;
  213 +}
  214 +
  215 +/* Read a 32-bit immediate constant. */
  216 +static inline uint32_t read_im32(DisasContext *s)
  217 +{
  218 + uint32_t im;
  219 + im = ((uint32_t)lduw(s->pc)) << 16;
  220 + s->pc += 2;
  221 + im |= lduw(s->pc);
  222 + s->pc += 2;
  223 + return im;
  224 +}
  225 +
  226 +
  227 +/* Update the CPU env CC_OP state. */
  228 +static inline void gen_flush_cc_op(DisasContext *s)
  229 +{
  230 + if (s->cc_op != CC_OP_DYNAMIC)
  231 + gen_op_mov32(QREG_CC_OP, gen_im32(s->cc_op));
  232 +}
  233 +
  234 +/* Evaluate all the CC flags. */
  235 +static inline void gen_flush_flags(DisasContext *s)
  236 +{
  237 + if (s->cc_op == CC_OP_FLAGS)
  238 + return;
  239 + gen_op_flush_flags(s->cc_op);
  240 + s->cc_op = CC_OP_FLAGS;
  241 +}
  242 +
  243 +static inline int opsize_bytes(int opsize)
  244 +{
  245 + switch (opsize) {
  246 + case OS_BYTE: return 1;
  247 + case OS_WORD: return 2;
  248 + case OS_LONG: return 4;
  249 + case OS_SINGLE: return 4;
  250 + case OS_DOUBLE: return 8;
  251 + default:
  252 + qemu_assert(0, "bad operand size");
  253 + }
  254 +}
  255 +
  256 +/* Assign value to a register. If the width is less than the register width
  257 + only the low part of the register is set. */
  258 +static void gen_partset_reg(int opsize, int reg, int val)
  259 +{
  260 + int tmp;
  261 + switch (opsize) {
  262 + case OS_BYTE:
  263 + gen_op_and32(reg, reg, gen_im32(0xffffff00));
  264 + tmp = gen_new_qreg(QMODE_I32);
  265 + gen_op_and32(tmp, val, gen_im32(0xff));
  266 + gen_op_or32(reg, reg, tmp);
  267 + break;
  268 + case OS_WORD:
  269 + gen_op_and32(reg, reg, gen_im32(0xffff0000));
  270 + tmp = gen_new_qreg(QMODE_I32);
  271 + gen_op_and32(tmp, val, gen_im32(0xffff));
  272 + gen_op_or32(reg, reg, tmp);
  273 + break;
  274 + case OS_LONG:
  275 + gen_op_mov32(reg, val);
  276 + break;
  277 + case OS_SINGLE:
  278 + gen_op_pack_32_f32(reg, val);
  279 + break;
  280 + default:
  281 + qemu_assert(0, "Bad operand size");
  282 + break;
  283 + }
  284 +}
  285 +
  286 +/* Sign or zero extend a value. */
  287 +static inline int gen_extend(int val, int opsize, int sign)
  288 +{
  289 + int tmp;
  290 +
  291 + switch (opsize) {
  292 + case OS_BYTE:
  293 + tmp = gen_new_qreg(QMODE_I32);
  294 + if (sign)
  295 + gen_op_ext8s32(tmp, val);
  296 + else
  297 + gen_op_ext8u32(tmp, val);
  298 + break;
  299 + case OS_WORD:
  300 + tmp = gen_new_qreg(QMODE_I32);
  301 + if (sign)
  302 + gen_op_ext16s32(tmp, val);
  303 + else
  304 + gen_op_ext16u32(tmp, val);
  305 + break;
  306 + case OS_LONG:
  307 + tmp = val;
  308 + break;
  309 + case OS_SINGLE:
  310 + tmp = gen_new_qreg(QMODE_F32);
  311 + gen_op_pack_f32_32(tmp, val);
  312 + break;
  313 + default:
  314 + qemu_assert(0, "Bad operand size");
  315 + }
  316 + return tmp;
  317 +}
  318 +
  319 +/* Generate code for an "effective address". Does not adjust the base
  320 + register for autoincrememnt addressing modes. */
  321 +static int gen_lea(DisasContext *s, uint16_t insn, int opsize)
  322 +{
  323 + int reg;
  324 + int tmp;
  325 + uint16_t ext;
  326 + uint32_t offset;
  327 +
  328 + reg = insn & 7;
  329 + switch ((insn >> 3) & 7) {
  330 + case 0: /* Data register direct. */
  331 + case 1: /* Address register direct. */
  332 + /* ??? generate bad addressing mode fault. */
  333 + qemu_assert(0, "invalid addressing mode");
  334 + case 2: /* Indirect register */
  335 + case 3: /* Indirect postincrement. */
  336 + reg += QREG_A0;
  337 + return reg;
  338 + case 4: /* Indirect predecrememnt. */
  339 + reg += QREG_A0;
  340 + tmp = gen_new_qreg(QMODE_I32);
  341 + gen_op_sub32(tmp, reg, gen_im32(opsize_bytes(opsize)));
  342 + return tmp;
  343 + case 5: /* Indirect displacement. */
  344 + reg += QREG_A0;
  345 + tmp = gen_new_qreg(QMODE_I32);
  346 + ext = lduw(s->pc);
  347 + s->pc += 2;
  348 + gen_op_add32(tmp, reg, gen_im32((int16_t)ext));
  349 + return tmp;
  350 + case 6: /* Indirect index + displacement. */
  351 + reg += QREG_A0;
  352 + return gen_lea_indexed(s, opsize, reg);
  353 + case 7: /* Other */
  354 + switch (reg) {
  355 + case 0: /* Absolute short. */
  356 + offset = ldsw(s->pc);
  357 + s->pc += 2;
  358 + return gen_im32(offset);
  359 + case 1: /* Absolute long. */
  360 + offset = read_im32(s);
  361 + return gen_im32(offset);
  362 + case 2: /* pc displacement */
  363 + tmp = gen_new_qreg(QMODE_I32);
  364 + offset = s->pc;
  365 + offset += ldsw(s->pc);
  366 + s->pc += 2;
  367 + return gen_im32(offset);
  368 + case 3: /* pc index+displacement. */
  369 + return gen_lea_indexed(s, opsize, -1);
  370 + case 4: /* Immediate. */
  371 + default:
  372 + /* ??? generate bad addressing mode fault. */
  373 + qemu_assert(0, "invalid addressing mode");
  374 + }
  375 + }
  376 + /* Should never happen. */
  377 + return -1;
  378 +}
  379 +
  380 +/* Helper function for gen_ea. Reuse the computed address between the
  381 + for read/write operands. */
  382 +static inline int gen_ea_once(DisasContext *s, uint16_t insn, int opsize,
  383 + int val, int *addrp)
  384 +{
  385 + int tmp;
  386 +
  387 + if (addrp && val > 0) {
  388 + tmp = *addrp;
  389 + } else {
  390 + tmp = gen_lea(s, insn, opsize);
  391 + if (addrp)
  392 + *addrp = tmp;
  393 + }
  394 + return gen_ldst(opsize, tmp, val);
  395 +}
  396 +
  397 +/* Generate code to load/store a value ito/from an EA. If VAL > 0 this is
  398 + a write otherwise it is a read (0 == sign extend, -1 == zero extend).
  399 + ADDRP is non-null for readwrite operands. */
  400 +static int gen_ea(DisasContext *s, uint16_t insn, int opsize, int val,
  401 + int *addrp)
  402 +{
  403 + int reg;
  404 + int result;
  405 + uint32_t offset;
  406 +
  407 + reg = insn & 7;
  408 + switch ((insn >> 3) & 7) {
  409 + case 0: /* Data register direct. */
  410 + reg += QREG_D0;
  411 + if (val > 0) {
  412 + gen_partset_reg(opsize, reg, val);
  413 + return 0;
  414 + } else {
  415 + return gen_extend(reg, opsize, val);
  416 + }
  417 + case 1: /* Address register direct. */
  418 + reg += QREG_A0;
  419 + if (val > 0) {
  420 + gen_op_mov32(reg, val);
  421 + return 0;
  422 + } else {
  423 + return gen_extend(reg, opsize, val);
  424 + }
  425 + case 2: /* Indirect register */
  426 + reg += QREG_A0;
  427 + return gen_ldst(opsize, reg, val);
  428 + case 3: /* Indirect postincrement. */
  429 + reg += QREG_A0;
  430 + result = gen_ldst(opsize, reg, val);
  431 + /* ??? This is not exception safe. The instruction may still
  432 + fault after this point. */
  433 + if (val > 0 || !addrp)
  434 + gen_op_add32(reg, reg, gen_im32(opsize_bytes(opsize)));
  435 + return result;
  436 + case 4: /* Indirect predecrememnt. */
  437 + {
  438 + int tmp;
  439 + if (addrp && val > 0) {
  440 + tmp = *addrp;
  441 + } else {
  442 + tmp = gen_lea(s, insn, opsize);
  443 + if (addrp)
  444 + *addrp = tmp;
  445 + }
  446 + result = gen_ldst(opsize, tmp, val);
  447 + /* ??? This is not exception safe. The instruction may still
  448 + fault after this point. */
  449 + if (val > 0 || !addrp) {
  450 + reg += QREG_A0;
  451 + gen_op_mov32(reg, tmp);
  452 + }
  453 + }
  454 + return result;
  455 + case 5: /* Indirect displacement. */
  456 + case 6: /* Indirect index + displacement. */
  457 + return gen_ea_once(s, insn, opsize, val, addrp);
  458 + case 7: /* Other */
  459 + switch (reg) {
  460 + case 0: /* Absolute short. */
  461 + case 1: /* Absolute long. */
  462 + case 2: /* pc displacement */
  463 + case 3: /* pc index+displacement. */
  464 + return gen_ea_once(s, insn, opsize, val, addrp);
  465 + case 4: /* Immediate. */
  466 + /* Sign extend values for consistency. */
  467 + switch (opsize) {
  468 + case OS_BYTE:
  469 + if (val)
  470 + offset = ldsb(s->pc + 1);
  471 + else
  472 + offset = ldub(s->pc + 1);
  473 + s->pc += 2;
  474 + break;
  475 + case OS_WORD:
  476 + if (val)
  477 + offset = ldsw(s->pc);
  478 + else
  479 + offset = lduw(s->pc);
  480 + s->pc += 2;
  481 + break;
  482 + case OS_LONG:
  483 + offset = read_im32(s);
  484 + break;
  485 + default:
  486 + qemu_assert(0, "Bad immediate operand");
  487 + }
  488 + return gen_im32(offset);
  489 + default:
  490 + qemu_assert(0, "invalid addressing mode");
  491 + }
  492 + }
  493 + /* Should never happen. */
  494 + return -1;
  495 +}
  496 +
  497 +static void gen_logic_cc(DisasContext *s, int val)
  498 +{
  499 + gen_op_logic_cc(val);
  500 + s->cc_op = CC_OP_LOGIC;
  501 +}
  502 +
  503 +static void gen_jmpcc(DisasContext *s, int cond, int l1)
  504 +{
  505 + int tmp;
  506 +
  507 + gen_flush_flags(s);
  508 + switch (cond) {
  509 + case 0: /* T */
  510 + gen_op_jmp(l1);
  511 + break;
  512 + case 1: /* F */
  513 + break;
  514 + case 2: /* HI (!C && !Z) */
  515 + tmp = gen_new_qreg(QMODE_I32);
  516 + gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_C | CCF_Z));
  517 + gen_op_jmp_z32(tmp, l1);
  518 + break;
  519 + case 3: /* LS (C || Z) */
  520 + tmp = gen_new_qreg(QMODE_I32);
  521 + gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_C | CCF_Z));
  522 + gen_op_jmp_nz32(tmp, l1);
  523 + break;
  524 + case 4: /* CC (!C) */
  525 + tmp = gen_new_qreg(QMODE_I32);
  526 + gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_C));
  527 + gen_op_jmp_z32(tmp, l1);
  528 + break;
  529 + case 5: /* CS (C) */
  530 + tmp = gen_new_qreg(QMODE_I32);
  531 + gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_C));
  532 + gen_op_jmp_nz32(tmp, l1);
  533 + break;
  534 + case 6: /* NE (!Z) */
  535 + tmp = gen_new_qreg(QMODE_I32);
  536 + gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_Z));
  537 + gen_op_jmp_z32(tmp, l1);
  538 + break;
  539 + case 7: /* EQ (Z) */
  540 + tmp = gen_new_qreg(QMODE_I32);
  541 + gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_Z));
  542 + gen_op_jmp_nz32(tmp, l1);
  543 + break;
  544 + case 8: /* VC (!V) */
  545 + tmp = gen_new_qreg(QMODE_I32);
  546 + gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_V));
  547 + gen_op_jmp_z32(tmp, l1);
  548 + break;
  549 + case 9: /* VS (V) */
  550 + tmp = gen_new_qreg(QMODE_I32);
  551 + gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_V));
  552 + gen_op_jmp_nz32(tmp, l1);
  553 + break;
  554 + case 10: /* PL (!N) */
  555 + tmp = gen_new_qreg(QMODE_I32);
  556 + gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_N));
  557 + gen_op_jmp_z32(tmp, l1);
  558 + break;
  559 + case 11: /* MI (N) */
  560 + tmp = gen_new_qreg(QMODE_I32);
  561 + gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_N));
  562 + gen_op_jmp_nz32(tmp, l1);
  563 + break;
  564 + case 12: /* GE (!(N ^ V)) */
  565 + tmp = gen_new_qreg(QMODE_I32);
  566 + gen_op_shr32(tmp, QREG_CC_DEST, gen_im32(2));
  567 + gen_op_xor32(tmp, tmp, QREG_CC_DEST);
  568 + gen_op_and32(tmp, tmp, gen_im32(CCF_V));
  569 + gen_op_jmp_z32(tmp, l1);
  570 + break;
  571 + case 13: /* LT (N ^ V) */
  572 + tmp = gen_new_qreg(QMODE_I32);
  573 + gen_op_shr32(tmp, QREG_CC_DEST, gen_im32(2));
  574 + gen_op_xor32(tmp, tmp, QREG_CC_DEST);
  575 + gen_op_and32(tmp, tmp, gen_im32(CCF_V));
  576 + gen_op_jmp_nz32(tmp, l1);
  577 + break;
  578 + case 14: /* GT (!(Z || (N ^ V))) */
  579 + {
  580 + int l2;
  581 + l2 = gen_new_label();
  582 + tmp = gen_new_qreg(QMODE_I32);
  583 + gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_Z));
  584 + gen_op_jmp_nz32(tmp, l2);
  585 + tmp = gen_new_qreg(QMODE_I32);
  586 + gen_op_shr32(tmp, QREG_CC_DEST, gen_im32(2));
  587 + gen_op_xor32(tmp, tmp, QREG_CC_DEST);
  588 + gen_op_and32(tmp, tmp, gen_im32(CCF_V));
  589 + gen_op_jmp_nz32(tmp, l2);
  590 + gen_op_jmp(l1);
  591 + gen_set_label(l2);
  592 + }
  593 + break;
  594 + case 15: /* LE (Z || (N ^ V)) */
  595 + tmp = gen_new_qreg(QMODE_I32);
  596 + gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_Z));
  597 + gen_op_jmp_nz32(tmp, l1);
  598 + tmp = gen_new_qreg(QMODE_I32);
  599 + gen_op_shr32(tmp, QREG_CC_DEST, gen_im32(2));
  600 + gen_op_xor32(tmp, tmp, QREG_CC_DEST);
  601 + gen_op_and32(tmp, tmp, gen_im32(CCF_V));
  602 + gen_op_jmp_nz32(tmp, l1);
  603 + break;
  604 + default:
  605 + /* Should ever happen. */
  606 + abort();
  607 + }
  608 +}
  609 +
  610 +DISAS_INSN(scc)
  611 +{
  612 + int l1;
  613 + int cond;
  614 + int reg;
  615 +
  616 + l1 = gen_new_label();
  617 + cond = (insn >> 8) & 0xf;
  618 + reg = DREG(insn, 0);
  619 + gen_op_and32(reg, reg, gen_im32(0xffffff00));
  620 + gen_jmpcc(s, cond ^ 1, l1);
  621 + gen_op_or32(reg, reg, gen_im32(0xff));
  622 + gen_set_label(l1);
  623 +}
  624 +
  625 +/* Generate a jump to to the address in qreg DEST. */
  626 +static void gen_jmp(DisasContext *s, int dest)
  627 +{
  628 + gen_flush_cc_op(s);
  629 + gen_op_mov32(QREG_PC, dest);
  630 + s->is_jmp = DISAS_JUMP;
  631 +}
  632 +
  633 +static void gen_exception(DisasContext *s, uint32_t where, int nr)
  634 +{
  635 + gen_flush_cc_op(s);
  636 + gen_jmp(s, gen_im32(where));
  637 + gen_op_raise_exception(nr);
  638 +}
  639 +
  640 +/* Generate a jump to an immediate address. */
  641 +static void gen_jmp_tb(DisasContext *s, int n, uint32_t dest)
  642 +{
  643 + TranslationBlock *tb;
  644 +
  645 + tb = s->tb;
  646 + if (__builtin_expect (s->singlestep_enabled, 0)) {
  647 + gen_exception(s, dest, EXCP_DEBUG);
  648 + } else if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
  649 + (s->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
  650 + gen_op_goto_tb(0, n, (long)tb);
  651 + gen_op_mov32(QREG_PC, gen_im32(dest));
  652 + gen_op_mov32(QREG_T0, gen_im32((long)tb + n));
  653 + gen_op_exit_tb();
  654 + } else {
  655 + gen_jmp(s, gen_im32(dest));
  656 + gen_op_mov32(QREG_T0, gen_im32(0));
  657 + gen_op_exit_tb();
  658 + }
  659 + s->is_jmp = DISAS_TB_JUMP;
  660 +}
  661 +
  662 +DISAS_INSN(undef_mac)
  663 +{
  664 + gen_exception(s, s->pc - 2, EXCP_LINEA);
  665 +}
  666 +
  667 +DISAS_INSN(undef_fpu)
  668 +{
  669 + gen_exception(s, s->pc - 2, EXCP_LINEF);
  670 +}
  671 +
  672 +DISAS_INSN(undef)
  673 +{
  674 + gen_exception(s, s->pc - 2, EXCP_UNSUPPORTED);
  675 + cpu_abort(cpu_single_env, "Illegal instruction: %04x @ %08x",
  676 + insn, s->pc - 2);
  677 +}
  678 +
  679 +DISAS_INSN(mulw)
  680 +{
  681 + int reg;
  682 + int tmp;
  683 + int src;
  684 + int sign;
  685 +
  686 + sign = (insn & 0x100) != 0;
  687 + reg = DREG(insn, 9);
  688 + tmp = gen_new_qreg(QMODE_I32);
  689 + if (sign)
  690 + gen_op_ext16s32(tmp, reg);
  691 + else
  692 + gen_op_ext16u32(tmp, reg);
  693 + src = gen_ea(s, insn, OS_WORD, sign ? -1 : 0, NULL);
  694 + gen_op_mul32(tmp, tmp, src);
  695 + gen_op_mov32(reg, tmp);
  696 + /* Unlike m68k, coldfire always clears the overflow bit. */
  697 + gen_logic_cc(s, tmp);
  698 +}
  699 +
  700 +DISAS_INSN(divw)
  701 +{
  702 + int reg;
  703 + int tmp;
  704 + int src;
  705 + int sign;
  706 +
  707 + sign = (insn & 0x100) != 0;
  708 + reg = DREG(insn, 9);
  709 + if (sign) {
  710 + gen_op_ext16s32(QREG_DIV1, reg);
  711 + } else {
  712 + gen_op_ext16u32(QREG_DIV1, reg);
  713 + }
  714 + src = gen_ea(s, insn, OS_WORD, sign ? -1 : 0, NULL);
  715 + gen_op_mov32(QREG_DIV2, src);
  716 + if (sign) {
  717 + gen_op_divs(1);
  718 + } else {
  719 + gen_op_divu(1);
  720 + }
  721 +
  722 + tmp = gen_new_qreg(QMODE_I32);
  723 + src = gen_new_qreg(QMODE_I32);
  724 + gen_op_ext16u32(tmp, QREG_DIV1);
  725 + gen_op_shl32(src, QREG_DIV2, gen_im32(16));
  726 + gen_op_or32(reg, tmp, src);
  727 + gen_op_flags_set();
  728 + s->cc_op = CC_OP_FLAGS;
  729 +}
  730 +
  731 +DISAS_INSN(divl)
  732 +{
  733 + int num;
  734 + int den;
  735 + int reg;
  736 + uint16_t ext;
  737 +
  738 + ext = lduw(s->pc);
  739 + s->pc += 2;
  740 + if (ext & 0x87f8) {
  741 + gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
  742 + return;
  743 + }
  744 + num = DREG(ext, 12);
  745 + reg = DREG(ext, 0);
  746 + gen_op_mov32(QREG_DIV1, num);
  747 + den = gen_ea(s, insn, OS_LONG, 0, NULL);
  748 + gen_op_mov32(QREG_DIV2, den);
  749 + if (ext & 0x0800) {
  750 + gen_op_divs(0);
  751 + } else {
  752 + gen_op_divu(0);
  753 + }
  754 + if (num == reg) {
  755 + /* div */
  756 + gen_op_mov32 (reg, QREG_DIV1);
  757 + } else {
  758 + /* rem */
  759 + gen_op_mov32 (reg, QREG_DIV2);
  760 + }
  761 + gen_op_flags_set();
  762 + s->cc_op = CC_OP_FLAGS;
  763 +}
  764 +
  765 +DISAS_INSN(addsub)
  766 +{
  767 + int reg;
  768 + int dest;
  769 + int src;
  770 + int tmp;
  771 + int addr;
  772 + int add;
  773 +
  774 + add = (insn & 0x4000) != 0;
  775 + reg = DREG(insn, 9);
  776 + dest = gen_new_qreg(QMODE_I32);
  777 + if (insn & 0x100) {
  778 + tmp = gen_ea(s, insn, OS_LONG, 0, &addr);
  779 + src = reg;
  780 + } else {
  781 + tmp = reg;
  782 + src = gen_ea(s, insn, OS_LONG, 0, NULL);
  783 + }
  784 + if (add) {
  785 + gen_op_add32(dest, tmp, src);
  786 + gen_op_update_xflag_lt(dest, src);
  787 + s->cc_op = CC_OP_ADD;
  788 + } else {
  789 + gen_op_update_xflag_lt(tmp, src);
  790 + gen_op_sub32(dest, tmp, src);
  791 + s->cc_op = CC_OP_SUB;
  792 + }
  793 + gen_op_update_cc_add(dest, src);
  794 + if (insn & 0x100) {
  795 + gen_ea(s, insn, OS_LONG, dest, &addr);
  796 + } else {
  797 + gen_op_mov32(reg, dest);
  798 + }
  799 +}
  800 +
  801 +
  802 +/* Reverse the order of the bits in REG. */
  803 +DISAS_INSN(bitrev)
  804 +{
  805 + int val;
  806 + int tmp1;
  807 + int tmp2;
  808 + int reg;
  809 +
  810 + val = gen_new_qreg(QMODE_I32);
  811 + tmp1 = gen_new_qreg(QMODE_I32);
  812 + tmp2 = gen_new_qreg(QMODE_I32);
  813 + reg = DREG(insn, 0);
  814 + gen_op_mov32(val, reg);
  815 + /* Reverse bits within each nibble. */
  816 + gen_op_shl32(tmp1, val, gen_im32(3));
  817 + gen_op_and32(tmp1, tmp1, gen_im32(0x88888888));
  818 + gen_op_shl32(tmp2, val, gen_im32(1));
  819 + gen_op_and32(tmp2, tmp2, gen_im32(0x44444444));
  820 + gen_op_or32(tmp1, tmp1, tmp2);
  821 + gen_op_shr32(tmp2, val, gen_im32(1));
  822 + gen_op_and32(tmp2, tmp2, gen_im32(0x22222222));
  823 + gen_op_or32(tmp1, tmp1, tmp2);
  824 + gen_op_shr32(tmp2, val, gen_im32(3));
  825 + gen_op_and32(tmp2, tmp2, gen_im32(0x11111111));
  826 + gen_op_or32(tmp1, tmp1, tmp2);
  827 + /* Reverse nibbles withing bytes. */
  828 + gen_op_shl32(val, tmp1, gen_im32(4));
  829 + gen_op_and32(val, val, gen_im32(0xf0f0f0f0));
  830 + gen_op_shr32(tmp2, tmp1, gen_im32(4));
  831 + gen_op_and32(tmp2, tmp2, gen_im32(0x0f0f0f0f));
  832 + gen_op_or32(val, val, tmp2);
  833 + /* Reverse bytes. */
  834 + gen_op_bswap32(reg, val);
  835 + gen_op_mov32(reg, val);
  836 +}
  837 +
  838 +DISAS_INSN(bitop_reg)
  839 +{
  840 + int opsize;
  841 + int op;
  842 + int src1;
  843 + int src2;
  844 + int tmp;
  845 + int addr;
  846 + int dest;
  847 +
  848 + if ((insn & 0x38) != 0)
  849 + opsize = OS_BYTE;
  850 + else
  851 + opsize = OS_LONG;
  852 + op = (insn >> 6) & 3;
  853 + src1 = gen_ea(s, insn, opsize, 0, op ? &addr: NULL);
  854 + src2 = DREG(insn, 9);
  855 + dest = gen_new_qreg(QMODE_I32);
  856 +
  857 + gen_flush_flags(s);
  858 + tmp = gen_new_qreg(QMODE_I32);
  859 + if (opsize == OS_BYTE)
  860 + gen_op_and32(tmp, src2, gen_im32(7));
  861 + else
  862 + gen_op_and32(tmp, src2, gen_im32(31));
  863 + src2 = tmp;
  864 + tmp = gen_new_qreg(QMODE_I32);
  865 + gen_op_shl32(tmp, gen_im32(1), src2);
  866 +
  867 + gen_op_btest(src1, tmp);
  868 + switch (op) {
  869 + case 1: /* bchg */
  870 + gen_op_xor32(dest, src1, tmp);
  871 + break;
  872 + case 2: /* bclr */
  873 + gen_op_not32(tmp, tmp);
  874 + gen_op_and32(dest, src1, tmp);
  875 + break;
  876 + case 3: /* bset */
  877 + gen_op_or32(dest, src1, tmp);
  878 + break;
  879 + default: /* btst */
  880 + break;
  881 + }
  882 + if (op)
  883 + gen_ea(s, insn, opsize, dest, &addr);
  884 +}
  885 +
  886 +DISAS_INSN(sats)
  887 +{
  888 + int reg;
  889 + int tmp;
  890 + int l1;
  891 +
  892 + reg = DREG(insn, 0);
  893 + tmp = gen_new_qreg(QMODE_I32);
  894 + gen_flush_flags(s);
  895 + gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_V));
  896 + l1 = gen_new_label();
  897 + gen_op_jmp_z32(tmp, l1);
  898 + tmp = gen_new_qreg(QMODE_I32);
  899 + gen_op_shr32(tmp, reg, gen_im32(31));
  900 + gen_op_xor32(tmp, tmp, gen_im32(0x80000000));
  901 + gen_op_mov32(reg, tmp);
  902 + gen_set_label(l1);
  903 + gen_logic_cc(s, tmp);
  904 +}
  905 +
  906 +static void gen_push(int val)
  907 +{
  908 + int tmp;
  909 +
  910 + tmp = gen_new_qreg(QMODE_I32);
  911 + gen_op_sub32(tmp, QREG_SP, gen_im32(4));
  912 + gen_store(OS_LONG, tmp, val);
  913 + gen_op_mov32(QREG_SP, tmp);
  914 +}
  915 +
  916 +DISAS_INSN(movem)
  917 +{
  918 + int addr;
  919 + int i;
  920 + uint16_t mask;
  921 + int reg;
  922 + int tmp;
  923 + int is_load;
  924 +
  925 + mask = lduw(s->pc);
  926 + s->pc += 2;
  927 + tmp = gen_lea(s, insn, OS_LONG);
  928 + addr = gen_new_qreg(QMODE_I32);
  929 + gen_op_mov32(addr, tmp);
  930 + is_load = ((insn & 0x0400) != 0);
  931 + for (i = 0; i < 16; i++, mask >>= 1) {
  932 + if (mask & 1) {
  933 + if (i < 8)
  934 + reg = DREG(i, 0);
  935 + else
  936 + reg = AREG(i, 0);
  937 + if (is_load) {
  938 + tmp = gen_load(OS_LONG, addr, 0);
  939 + gen_op_mov32(reg, tmp);
  940 + } else {
  941 + gen_store(OS_LONG, addr, reg);
  942 + }
  943 + if (mask != 1)
  944 + gen_op_add32(addr, addr, gen_im32(4));
  945 + }
  946 + }
  947 +}
  948 +
  949 +DISAS_INSN(bitop_im)
  950 +{
  951 + int opsize;
  952 + int op;
  953 + int src1;
  954 + uint32_t mask;
  955 + int bitnum;
  956 + int tmp;
  957 + int addr;
  958 + int dest;
  959 +
  960 + if ((insn & 0x38) != 0)
  961 + opsize = OS_BYTE;
  962 + else
  963 + opsize = OS_LONG;
  964 + op = (insn >> 6) & 3;
  965 +
  966 + bitnum = lduw(s->pc);
  967 + s->pc += 2;
  968 + if (bitnum & 0xff00) {
  969 + disas_undef(s, insn);
  970 + return;
  971 + }
  972 +
  973 + src1 = gen_ea(s, insn, opsize, 0, op ? &addr: NULL);
  974 +
  975 + gen_flush_flags(s);
  976 + tmp = gen_new_qreg(QMODE_I32);
  977 + if (opsize == OS_BYTE)
  978 + bitnum &= 7;
  979 + else
  980 + bitnum &= 31;
  981 + mask = 1 << bitnum;
  982 +
  983 + gen_op_btest(src1, gen_im32(mask));
  984 + if (op)
  985 + dest = gen_new_qreg(QMODE_I32);
  986 + else
  987 + dest = -1;
  988 +
  989 + switch (op) {
  990 + case 1: /* bchg */
  991 + gen_op_xor32(dest, src1, gen_im32(mask));
  992 + break;
  993 + case 2: /* bclr */
  994 + gen_op_and32(dest, src1, gen_im32(~mask));
  995 + break;
  996 + case 3: /* bset */
  997 + gen_op_or32(dest, src1, gen_im32(mask));
  998 + break;
  999 + default: /* btst */
  1000 + break;
  1001 + }
  1002 + if (op)
  1003 + gen_ea(s, insn, opsize, dest, &addr);
  1004 +}
  1005 +
  1006 +DISAS_INSN(arith_im)
  1007 +{
  1008 + int op;
  1009 + int src1;
  1010 + int dest;
  1011 + int src2;
  1012 + int addr;
  1013 +
  1014 + op = (insn >> 9) & 7;
  1015 + src1 = gen_ea(s, insn, OS_LONG, 0, (op == 6) ? NULL : &addr);
  1016 + src2 = gen_im32(read_im32(s));
  1017 + dest = gen_new_qreg(QMODE_I32);
  1018 + switch (op) {
  1019 + case 0: /* ori */
  1020 + gen_op_or32(dest, src1, src2);
  1021 + gen_logic_cc(s, dest);
  1022 + break;
  1023 + case 1: /* andi */
  1024 + gen_op_and32(dest, src1, src2);
  1025 + gen_logic_cc(s, dest);
  1026 + break;
  1027 + case 2: /* subi */
  1028 + gen_op_mov32(dest, src1);
  1029 + gen_op_update_xflag_lt(dest, src2);
  1030 + gen_op_sub32(dest, dest, src2);
  1031 + gen_op_update_cc_add(dest, src2);
  1032 + s->cc_op = CC_OP_SUB;
  1033 + break;
  1034 + case 3: /* addi */
  1035 + gen_op_mov32(dest, src1);
  1036 + gen_op_add32(dest, dest, src2);
  1037 + gen_op_update_cc_add(dest, src2);
  1038 + gen_op_update_xflag_lt(dest, src2);
  1039 + s->cc_op = CC_OP_ADD;
  1040 + break;
  1041 + case 5: /* eori */
  1042 + gen_op_xor32(dest, src1, src2);
  1043 + gen_logic_cc(s, dest);
  1044 + break;
  1045 + case 6: /* cmpi */
  1046 + gen_op_mov32(dest, src1);
  1047 + gen_op_sub32(dest, dest, src2);
  1048 + gen_op_update_cc_add(dest, src2);
  1049 + s->cc_op = CC_OP_SUB;
  1050 + break;
  1051 + default:
  1052 + abort();
  1053 + }
  1054 + if (op != 6) {
  1055 + gen_ea(s, insn, OS_LONG, dest, &addr);
  1056 + }
  1057 +}
  1058 +
  1059 +DISAS_INSN(byterev)
  1060 +{
  1061 + int reg;
  1062 +
  1063 + reg = DREG(insn, 0);
  1064 + gen_op_bswap32(reg, reg);
  1065 +}
  1066 +
  1067 +DISAS_INSN(move)
  1068 +{
  1069 + int src;
  1070 + int dest;
  1071 + int op;
  1072 + int opsize;
  1073 +
  1074 + switch (insn >> 12) {
  1075 + case 1: /* move.b */
  1076 + opsize = OS_BYTE;
  1077 + break;
  1078 + case 2: /* move.l */
  1079 + opsize = OS_LONG;
  1080 + break;
  1081 + case 3: /* move.w */
  1082 + opsize = OS_WORD;
  1083 + break;
  1084 + default:
  1085 + abort();
  1086 + }
  1087 + src = gen_ea(s, insn, opsize, -1, NULL);
  1088 + op = (insn >> 6) & 7;
  1089 + if (op == 1) {
  1090 + /* movea */
  1091 + /* The value will already have been sign extended. */
  1092 + dest = AREG(insn, 9);
  1093 + gen_op_mov32(dest, src);
  1094 + } else {
  1095 + /* normal move */
  1096 + uint16_t dest_ea;
  1097 + dest_ea = ((insn >> 9) & 7) | (op << 3);
  1098 + gen_ea(s, dest_ea, opsize, src, NULL);
  1099 + /* This will be correct because loads sign extend. */
  1100 + gen_logic_cc(s, src);
  1101 + }
  1102 +}
  1103 +
  1104 +DISAS_INSN(negx)
  1105 +{
  1106 + int reg;
  1107 + int dest;
  1108 + int tmp;
  1109 +
  1110 + gen_flush_flags(s);
  1111 + reg = DREG(insn, 0);
  1112 + dest = gen_new_qreg(QMODE_I32);
  1113 + gen_op_mov32 (dest, gen_im32(0));
  1114 + gen_op_subx_cc(dest, reg);
  1115 + /* !Z is sticky. */
  1116 + tmp = gen_new_qreg(QMODE_I32);
  1117 + gen_op_mov32 (tmp, QREG_CC_DEST);
  1118 + gen_op_update_cc_add(dest, reg);
  1119 + gen_op_mov32(reg, dest);
  1120 + s->cc_op = CC_OP_DYNAMIC;
  1121 + gen_flush_flags(s);
  1122 + gen_op_or32(tmp, tmp, gen_im32(~CCF_Z));
  1123 + gen_op_and32(QREG_CC_DEST, QREG_CC_DEST, tmp);
  1124 + s->cc_op = CC_OP_FLAGS;
  1125 +}
  1126 +
  1127 +DISAS_INSN(lea)
  1128 +{
  1129 + int reg;
  1130 + int tmp;
  1131 +
  1132 + reg = AREG(insn, 9);
  1133 + tmp = gen_lea(s, insn, OS_LONG);
  1134 + gen_op_mov32(reg, tmp);
  1135 +}
  1136 +
  1137 +DISAS_INSN(clr)
  1138 +{
  1139 + int opsize;
  1140 +
  1141 + switch ((insn >> 6) & 3) {
  1142 + case 0: /* clr.b */
  1143 + opsize = OS_BYTE;
  1144 + break;
  1145 + case 1: /* clr.w */
  1146 + opsize = OS_WORD;
  1147 + break;
  1148 + case 2: /* clr.l */
  1149 + opsize = OS_LONG;
  1150 + break;
  1151 + default:
  1152 + abort();
  1153 + }
  1154 + gen_ea (s, insn, opsize, gen_im32(0), NULL);
  1155 + gen_logic_cc(s, gen_im32(0));
  1156 +}
  1157 +
  1158 +DISAS_INSN(move_from_ccr)
  1159 +{
  1160 + int reg;
  1161 + int dest;
  1162 +
  1163 + gen_flush_flags(s);
  1164 + dest = gen_new_qreg(QMODE_I32);
  1165 + gen_op_get_xflag(dest);
  1166 + gen_op_shl32(dest, dest, gen_im32(4));
  1167 + gen_op_or32(dest, dest, QREG_CC_DEST);
  1168 + reg = DREG(insn, 0);
  1169 + gen_partset_reg(OS_WORD, reg, dest);
  1170 +}
  1171 +
  1172 +DISAS_INSN(neg)
  1173 +{
  1174 + int reg;
  1175 + int src1;
  1176 +
  1177 + reg = DREG(insn, 0);
  1178 + src1 = gen_new_qreg(QMODE_I32);
  1179 + gen_op_mov32(src1, reg);
  1180 + gen_op_neg32(reg, src1);
  1181 + s->cc_op = CC_OP_SUB;
  1182 + gen_op_update_cc_add(reg, src1);
  1183 + gen_op_update_xflag_lt(gen_im32(0), src1);
  1184 + s->cc_op = CC_OP_SUB;
  1185 +}
  1186 +
  1187 +DISAS_INSN(move_to_ccr)
  1188 +{
  1189 + int src1;
  1190 + int reg;
  1191 +
  1192 + s->cc_op = CC_OP_FLAGS;
  1193 + if ((insn & 0x38) == 0)
  1194 + {
  1195 + src1 = gen_new_qreg(QMODE_I32);
  1196 + reg = DREG(insn, 0);
  1197 + gen_op_and32(src1, reg, gen_im32(0xf));
  1198 + gen_op_logic_cc(src1);
  1199 + gen_op_shr32(src1, reg, gen_im32(4));
  1200 + gen_op_and32(src1, src1, gen_im32(1));
  1201 + gen_op_update_xflag_tst(src1);
  1202 + }
  1203 + else if ((insn & 0x3f) != 0x3c)
  1204 + {
  1205 + uint8_t val;
  1206 + val = ldsb(s->pc);
  1207 + s->pc += 2;
  1208 + gen_op_logic_cc(gen_im32(val & 0xf));
  1209 + gen_op_update_xflag_tst(gen_im32((val & 0x10) >> 4));
  1210 + }
  1211 + else
  1212 + disas_undef(s, insn);
  1213 +}
  1214 +
  1215 +DISAS_INSN(not)
  1216 +{
  1217 + int reg;
  1218 +
  1219 + reg = DREG(insn, 0);
  1220 + gen_op_not32(reg, reg);
  1221 + gen_logic_cc(s, reg);
  1222 +}
  1223 +
  1224 +DISAS_INSN(swap)
  1225 +{
  1226 + int dest;
  1227 + int src1;
  1228 + int src2;
  1229 + int reg;
  1230 +
  1231 + dest = gen_new_qreg(QMODE_I32);
  1232 + src1 = gen_new_qreg(QMODE_I32);
  1233 + src2 = gen_new_qreg(QMODE_I32);
  1234 + reg = DREG(insn, 0);
  1235 + gen_op_shl32(src1, reg, gen_im32(16));
  1236 + gen_op_shr32(src2, reg, gen_im32(16));
  1237 + gen_op_or32(dest, src1, src2);
  1238 + gen_op_mov32(reg, dest);
  1239 + gen_logic_cc(s, dest);
  1240 +}
  1241 +
  1242 +DISAS_INSN(pea)
  1243 +{
  1244 + int tmp;
  1245 +
  1246 + tmp = gen_lea(s, insn, OS_LONG);
  1247 + gen_push(tmp);
  1248 +}
  1249 +
  1250 +DISAS_INSN(ext)
  1251 +{
  1252 + int reg;
  1253 + int op;
  1254 + int tmp;
  1255 +
  1256 + reg = DREG(insn, 0);
  1257 + op = (insn >> 6) & 7;
  1258 + tmp = gen_new_qreg(QMODE_I32);
  1259 + if (op == 3)
  1260 + gen_op_ext16s32(tmp, reg);
  1261 + else
  1262 + gen_op_ext8s32(tmp, reg);
  1263 + if (op == 2)
  1264 + gen_partset_reg(OS_WORD, reg, tmp);
  1265 + else
  1266 + gen_op_mov32(reg, tmp);
  1267 + gen_logic_cc(s, tmp);
  1268 +}
  1269 +
  1270 +DISAS_INSN(tst)
  1271 +{
  1272 + int opsize;
  1273 + int tmp;
  1274 +
  1275 + switch ((insn >> 6) & 3) {
  1276 + case 0: /* tst.b */
  1277 + opsize = OS_BYTE;
  1278 + break;
  1279 + case 1: /* tst.w */
  1280 + opsize = OS_WORD;
  1281 + break;
  1282 + case 2: /* tst.l */
  1283 + opsize = OS_LONG;
  1284 + break;
  1285 + default:
  1286 + abort();
  1287 + }
  1288 + tmp = gen_ea(s, insn, opsize, -1, NULL);
  1289 + gen_logic_cc(s, tmp);
  1290 +}
  1291 +
  1292 +DISAS_INSN(pulse)
  1293 +{
  1294 + /* Implemented as a NOP. */
  1295 +}
  1296 +
  1297 +DISAS_INSN(illegal)
  1298 +{
  1299 + gen_exception(s, s->pc - 2, EXCP_ILLEGAL);
  1300 +}
  1301 +
  1302 +/* ??? This should be atomic. */
  1303 +DISAS_INSN(tas)
  1304 +{
  1305 + int dest;
  1306 + int src1;
  1307 + int addr;
  1308 +
  1309 + dest = gen_new_qreg(QMODE_I32);
  1310 + src1 = gen_ea(s, insn, OS_BYTE, -1, &addr);
  1311 + gen_logic_cc(s, src1);
  1312 + gen_op_or32(dest, src1, gen_im32(0x80));
  1313 + gen_ea(s, insn, OS_BYTE, dest, &addr);
  1314 +}
  1315 +
  1316 +DISAS_INSN(mull)
  1317 +{
  1318 + uint16_t ext;
  1319 + int reg;
  1320 + int src1;
  1321 + int dest;
  1322 +
  1323 + /* The upper 32 bits of the product are discarded, so
  1324 + muls.l and mulu.l are functionally equivalent. */
  1325 + ext = lduw(s->pc);
  1326 + s->pc += 2;
  1327 + if (ext & 0x87ff) {
  1328 + gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
  1329 + return;
  1330 + }
  1331 + reg = DREG(ext, 12);
  1332 + src1 = gen_ea(s, insn, OS_LONG, 0, NULL);
  1333 + dest = gen_new_qreg(QMODE_I32);
  1334 + gen_op_mul32(dest, src1, reg);
  1335 + gen_op_mov32(reg, dest);
  1336 + /* Unlike m68k, coldfire always clears the overflow bit. */
  1337 + gen_logic_cc(s, dest);
  1338 +}
  1339 +
  1340 +DISAS_INSN(link)
  1341 +{
  1342 + int16_t offset;
  1343 + int reg;
  1344 + int tmp;
  1345 +
  1346 + offset = ldsw(s->pc);
  1347 + s->pc += 2;
  1348 + reg = AREG(insn, 0);
  1349 + tmp = gen_new_qreg(QMODE_I32);
  1350 + gen_op_sub32(tmp, QREG_SP, gen_im32(4));
  1351 + gen_store(OS_LONG, tmp, reg);
  1352 + if (reg != QREG_SP)
  1353 + gen_op_mov32(reg, tmp);
  1354 + gen_op_add32(QREG_SP, tmp, gen_im32(offset));
  1355 +}
  1356 +
  1357 +DISAS_INSN(unlk)
  1358 +{
  1359 + int src;
  1360 + int reg;
  1361 + int tmp;
  1362 +
  1363 + src = gen_new_qreg(QMODE_I32);
  1364 + reg = AREG(insn, 0);
  1365 + gen_op_mov32(src, reg);
  1366 + tmp = gen_load(OS_LONG, src, 0);
  1367 + gen_op_mov32(reg, tmp);
  1368 + gen_op_add32(QREG_SP, src, gen_im32(4));
  1369 +}
  1370 +
  1371 +DISAS_INSN(nop)
  1372 +{
  1373 +}
  1374 +
  1375 +DISAS_INSN(rts)
  1376 +{
  1377 + int tmp;
  1378 +
  1379 + tmp = gen_load(OS_LONG, QREG_SP, 0);
  1380 + gen_op_add32(QREG_SP, QREG_SP, gen_im32(4));
  1381 + gen_jmp(s, tmp);
  1382 +}
  1383 +
  1384 +DISAS_INSN(jump)
  1385 +{
  1386 + int tmp;
  1387 +
  1388 + /* Load the target address first to ensure correct exception
  1389 + behavior. */
  1390 + tmp = gen_lea(s, insn, OS_LONG);
  1391 + if ((insn & 0x40) == 0) {
  1392 + /* jsr */
  1393 + gen_push(gen_im32(s->pc));
  1394 + }
  1395 + gen_jmp(s, tmp);
  1396 +}
  1397 +
  1398 +DISAS_INSN(addsubq)
  1399 +{
  1400 + int src1;
  1401 + int src2;
  1402 + int dest;
  1403 + int val;
  1404 + int addr;
  1405 +
  1406 + src1 = gen_ea(s, insn, OS_LONG, 0, &addr);
  1407 + val = (insn >> 9) & 7;
  1408 + if (val == 0)
  1409 + val = 8;
  1410 + src2 = gen_im32(val);
  1411 + dest = gen_new_qreg(QMODE_I32);
  1412 + gen_op_mov32(dest, src1);
  1413 + if ((insn & 0x38) == 0x08) {
  1414 + /* Don't update condition codes if the destination is an
  1415 + address register. */
  1416 + if (insn & 0x0100) {
  1417 + gen_op_sub32(dest, dest, src2);
  1418 + } else {
  1419 + gen_op_add32(dest, dest, src2);
  1420 + }
  1421 + } else {
  1422 + if (insn & 0x0100) {
  1423 + gen_op_update_xflag_lt(dest, src2);
  1424 + gen_op_sub32(dest, dest, src2);
  1425 + s->cc_op = CC_OP_SUB;
  1426 + } else {
  1427 + gen_op_add32(dest, dest, src2);
  1428 + gen_op_update_xflag_lt(dest, src2);
  1429 + s->cc_op = CC_OP_ADD;
  1430 + }
  1431 + gen_op_update_cc_add(dest, src2);
  1432 + }
  1433 + gen_ea(s, insn, OS_LONG, dest, &addr);
  1434 +}
  1435 +
  1436 +DISAS_INSN(tpf)
  1437 +{
  1438 + switch (insn & 7) {
  1439 + case 2: /* One extension word. */
  1440 + s->pc += 2;
  1441 + break;
  1442 + case 3: /* Two extension words. */
  1443 + s->pc += 4;
  1444 + break;
  1445 + case 4: /* No extension words. */
  1446 + break;
  1447 + default:
  1448 + disas_undef(s, insn);
  1449 + }
  1450 +}
  1451 +
  1452 +DISAS_INSN(branch)
  1453 +{
  1454 + int32_t offset;
  1455 + uint32_t base;
  1456 + int op;
  1457 + int l1;
  1458 +
  1459 + base = s->pc;
  1460 + op = (insn >> 8) & 0xf;
  1461 + offset = (int8_t)insn;
  1462 + if (offset == 0) {
  1463 + offset = ldsw(s->pc);
  1464 + s->pc += 2;
  1465 + } else if (offset == -1) {
  1466 + offset = read_im32(s);
  1467 + }
  1468 + if (op == 1) {
  1469 + /* bsr */
  1470 + gen_push(gen_im32(s->pc));
  1471 + }
  1472 + gen_flush_cc_op(s);
  1473 + if (op > 1) {
  1474 + /* Bcc */
  1475 + l1 = gen_new_label();
  1476 + gen_jmpcc(s, ((insn >> 8) & 0xf) ^ 1, l1);
  1477 + gen_jmp_tb(s, 1, base + offset);
  1478 + gen_set_label(l1);
  1479 + gen_jmp_tb(s, 0, s->pc);
  1480 + } else {
  1481 + /* Unconditional branch. */
  1482 + gen_jmp_tb(s, 0, base + offset);
  1483 + }
  1484 +}
  1485 +
  1486 +DISAS_INSN(moveq)
  1487 +{
  1488 + int tmp;
  1489 +
  1490 + tmp = gen_im32((int8_t)insn);
  1491 + gen_op_mov32(DREG(insn, 9), tmp);
  1492 + gen_logic_cc(s, tmp);
  1493 +}
  1494 +
  1495 +DISAS_INSN(mvzs)
  1496 +{
  1497 + int opsize;
  1498 + int src;
  1499 + int reg;
  1500 +
  1501 + if (insn & 0x40)
  1502 + opsize = OS_WORD;
  1503 + else
  1504 + opsize = OS_BYTE;
  1505 + src = gen_ea(s, insn, opsize, (insn & 0x80) ? 0 : -1, NULL);
  1506 + reg = DREG(insn, 9);
  1507 + gen_op_mov32(reg, src);
  1508 + gen_logic_cc(s, src);
  1509 +}
  1510 +
  1511 +DISAS_INSN(or)
  1512 +{
  1513 + int reg;
  1514 + int dest;
  1515 + int src;
  1516 + int addr;
  1517 +
  1518 + reg = DREG(insn, 9);
  1519 + dest = gen_new_qreg(QMODE_I32);
  1520 + if (insn & 0x100) {
  1521 + src = gen_ea(s, insn, OS_LONG, 0, &addr);
  1522 + gen_op_or32(dest, src, reg);
  1523 + gen_ea(s, insn, OS_LONG, dest, &addr);
  1524 + } else {
  1525 + src = gen_ea(s, insn, OS_LONG, 0, NULL);
  1526 + gen_op_or32(dest, src, reg);
  1527 + gen_op_mov32(reg, dest);
  1528 + }
  1529 + gen_logic_cc(s, dest);
  1530 +}
  1531 +
  1532 +DISAS_INSN(suba)
  1533 +{
  1534 + int src;
  1535 + int reg;
  1536 +
  1537 + src = gen_ea(s, insn, OS_LONG, 0, NULL);
  1538 + reg = AREG(insn, 9);
  1539 + gen_op_sub32(reg, reg, src);
  1540 +}
  1541 +
  1542 +DISAS_INSN(subx)
  1543 +{
  1544 + int reg;
  1545 + int src;
  1546 + int dest;
  1547 + int tmp;
  1548 +
  1549 + gen_flush_flags(s);
  1550 + reg = DREG(insn, 9);
  1551 + src = DREG(insn, 0);
  1552 + dest = gen_new_qreg(QMODE_I32);
  1553 + gen_op_mov32 (dest, reg);
  1554 + gen_op_subx_cc(dest, src);
  1555 + /* !Z is sticky. */
  1556 + tmp = gen_new_qreg(QMODE_I32);
  1557 + gen_op_mov32 (tmp, QREG_CC_DEST);
  1558 + gen_op_update_cc_add(dest, src);
  1559 + gen_op_mov32(reg, dest);
  1560 + s->cc_op = CC_OP_DYNAMIC;
  1561 + gen_flush_flags(s);
  1562 + gen_op_or32(tmp, tmp, gen_im32(~CCF_Z));
  1563 + gen_op_and32(QREG_CC_DEST, QREG_CC_DEST, tmp);
  1564 + s->cc_op = CC_OP_FLAGS;
  1565 +}
  1566 +
  1567 +DISAS_INSN(mov3q)
  1568 +{
  1569 + int src;
  1570 + int val;
  1571 +
  1572 + val = (insn >> 9) & 7;
  1573 + if (val == 0)
  1574 + val = -1;
  1575 + src = gen_im32(val);
  1576 + gen_logic_cc(s, src);
  1577 + gen_ea(s, insn, OS_LONG, src, NULL);
  1578 +}
  1579 +
  1580 +DISAS_INSN(cmp)
  1581 +{
  1582 + int op;
  1583 + int src;
  1584 + int reg;
  1585 + int dest;
  1586 + int opsize;
  1587 +
  1588 + op = (insn >> 6) & 3;
  1589 + switch (op) {
  1590 + case 0: /* cmp.b */
  1591 + opsize = OS_BYTE;
  1592 + s->cc_op = CC_OP_CMPB;
  1593 + break;
  1594 + case 1: /* cmp.w */
  1595 + opsize = OS_WORD;
  1596 + s->cc_op = CC_OP_CMPW;
  1597 + break;
  1598 + case 2: /* cmp.l */
  1599 + opsize = OS_LONG;
  1600 + s->cc_op = CC_OP_SUB;
  1601 + break;
  1602 + default:
  1603 + abort();
  1604 + }
  1605 + src = gen_ea(s, insn, opsize, -1, NULL);
  1606 + reg = DREG(insn, 9);
  1607 + dest = gen_new_qreg(QMODE_I32);
  1608 + gen_op_sub32(dest, reg, src);
  1609 + gen_op_update_cc_add(dest, src);
  1610 +}
  1611 +
  1612 +DISAS_INSN(cmpa)
  1613 +{
  1614 + int opsize;
  1615 + int src;
  1616 + int reg;
  1617 + int dest;
  1618 +
  1619 + if (insn & 0x100) {
  1620 + opsize = OS_LONG;
  1621 + } else {
  1622 + opsize = OS_WORD;
  1623 + }
  1624 + src = gen_ea(s, insn, opsize, -1, NULL);
  1625 + reg = AREG(insn, 9);
  1626 + dest = gen_new_qreg(QMODE_I32);
  1627 + gen_op_sub32(dest, reg, src);
  1628 + gen_op_update_cc_add(dest, src);
  1629 + s->cc_op = CC_OP_SUB;
  1630 +}
  1631 +
  1632 +DISAS_INSN(eor)
  1633 +{
  1634 + int src;
  1635 + int reg;
  1636 + int dest;
  1637 + int addr;
  1638 +
  1639 + src = gen_ea(s, insn, OS_LONG, 0, &addr);
  1640 + reg = DREG(insn, 9);
  1641 + dest = gen_new_qreg(QMODE_I32);
  1642 + gen_op_xor32(dest, src, reg);
  1643 + gen_logic_cc(s, dest);
  1644 + gen_ea(s, insn, OS_LONG, dest, &addr);
  1645 +}
  1646 +
  1647 +DISAS_INSN(and)
  1648 +{
  1649 + int src;
  1650 + int reg;
  1651 + int dest;
  1652 + int addr;
  1653 +
  1654 + reg = DREG(insn, 9);
  1655 + dest = gen_new_qreg(QMODE_I32);
  1656 + if (insn & 0x100) {
  1657 + src = gen_ea(s, insn, OS_LONG, 0, &addr);
  1658 + gen_op_and32(dest, src, reg);
  1659 + gen_ea(s, insn, OS_LONG, dest, &addr);
  1660 + } else {
  1661 + src = gen_ea(s, insn, OS_LONG, 0, NULL);
  1662 + gen_op_and32(dest, src, reg);
  1663 + gen_op_mov32(reg, dest);
  1664 + }
  1665 + gen_logic_cc(s, dest);
  1666 +}
  1667 +
  1668 +DISAS_INSN(adda)
  1669 +{
  1670 + int src;
  1671 + int reg;
  1672 +
  1673 + src = gen_ea(s, insn, OS_LONG, 0, NULL);
  1674 + reg = AREG(insn, 9);
  1675 + gen_op_add32(reg, reg, src);
  1676 +}
  1677 +
  1678 +DISAS_INSN(addx)
  1679 +{
  1680 + int reg;
  1681 + int src;
  1682 + int dest;
  1683 + int tmp;
  1684 +
  1685 + gen_flush_flags(s);
  1686 + reg = DREG(insn, 9);
  1687 + src = DREG(insn, 0);
  1688 + dest = gen_new_qreg(QMODE_I32);
  1689 + gen_op_mov32 (dest, reg);
  1690 + gen_op_addx_cc(dest, src);
  1691 + /* !Z is sticky. */
  1692 + tmp = gen_new_qreg(QMODE_I32);
  1693 + gen_op_mov32 (tmp, QREG_CC_DEST);
  1694 + gen_op_update_cc_add(dest, src);
  1695 + gen_op_mov32(reg, dest);
  1696 + s->cc_op = CC_OP_DYNAMIC;
  1697 + gen_flush_flags(s);
  1698 + gen_op_or32(tmp, tmp, gen_im32(~CCF_Z));
  1699 + gen_op_and32(QREG_CC_DEST, QREG_CC_DEST, tmp);
  1700 + s->cc_op = CC_OP_FLAGS;
  1701 +}
  1702 +
  1703 +DISAS_INSN(shift_im)
  1704 +{
  1705 + int reg;
  1706 + int tmp;
  1707 +
  1708 + reg = DREG(insn, 0);
  1709 + tmp = (insn >> 9) & 7;
  1710 + if (tmp == 0)
  1711 + tmp = 8;
  1712 + if (insn & 0x100) {
  1713 + gen_op_shl_im_cc(reg, tmp);
  1714 + s->cc_op = CC_OP_SHL;
  1715 + } else {
  1716 + if (insn & 8) {
  1717 + gen_op_shr_im_cc(reg, tmp);
  1718 + s->cc_op = CC_OP_SHR;
  1719 + } else {
  1720 + gen_op_sar_im_cc(reg, tmp);
  1721 + s->cc_op = CC_OP_SAR;
  1722 + }
  1723 + }
  1724 +}
  1725 +
  1726 +DISAS_INSN(shift_reg)
  1727 +{
  1728 + int reg;
  1729 + int src;
  1730 + int tmp;
  1731 +
  1732 + reg = DREG(insn, 0);
  1733 + src = DREG(insn, 9);
  1734 + tmp = gen_new_qreg(QMODE_I32);
  1735 + gen_op_and32(tmp, src, gen_im32(63));
  1736 + if (insn & 0x100) {
  1737 + gen_op_shl_cc(reg, tmp);
  1738 + s->cc_op = CC_OP_SHL;
  1739 + } else {
  1740 + if (insn & 8) {
  1741 + gen_op_shr_cc(reg, tmp);
  1742 + s->cc_op = CC_OP_SHR;
  1743 + } else {
  1744 + gen_op_sar_cc(reg, tmp);
  1745 + s->cc_op = CC_OP_SAR;
  1746 + }
  1747 + }
  1748 +}
  1749 +
  1750 +DISAS_INSN(ff1)
  1751 +{
  1752 + cpu_abort(NULL, "Unimplemented insn: ff1");
  1753 +}
  1754 +
  1755 +DISAS_INSN(strldsr)
  1756 +{
  1757 + uint16_t ext;
  1758 + uint32_t addr;
  1759 +
  1760 + addr = s->pc - 2;
  1761 + ext = lduw(s->pc);
  1762 + s->pc += 2;
  1763 + if (ext != 0x46FC)
  1764 + gen_exception(s, addr, EXCP_UNSUPPORTED);
  1765 + else
  1766 + gen_exception(s, addr, EXCP_PRIVILEGE);
  1767 +}
  1768 +
  1769 +DISAS_INSN(move_from_sr)
  1770 +{
  1771 + gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
  1772 +}
  1773 +
  1774 +DISAS_INSN(move_to_sr)
  1775 +{
  1776 + gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
  1777 +}
  1778 +
  1779 +DISAS_INSN(move_from_usp)
  1780 +{
  1781 + gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
  1782 +}
  1783 +
  1784 +DISAS_INSN(move_to_usp)
  1785 +{
  1786 + gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
  1787 +}
  1788 +
  1789 +DISAS_INSN(halt)
  1790 +{
  1791 + gen_exception(s, s->pc, EXCP_HLT);
  1792 +}
  1793 +
  1794 +DISAS_INSN(stop)
  1795 +{
  1796 + gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
  1797 +}
  1798 +
  1799 +DISAS_INSN(rte)
  1800 +{
  1801 + gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
  1802 +}
  1803 +
  1804 +DISAS_INSN(movec)
  1805 +{
  1806 + gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
  1807 +}
  1808 +
  1809 +DISAS_INSN(intouch)
  1810 +{
  1811 + gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
  1812 +}
  1813 +
  1814 +DISAS_INSN(cpushl)
  1815 +{
  1816 + gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
  1817 +}
  1818 +
  1819 +DISAS_INSN(wddata)
  1820 +{
  1821 + gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
  1822 +}
  1823 +
  1824 +DISAS_INSN(wdebug)
  1825 +{
  1826 + gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
  1827 +}
  1828 +
  1829 +DISAS_INSN(trap)
  1830 +{
  1831 + gen_exception(s, s->pc - 2, EXCP_TRAP0 + (insn & 0xf));
  1832 +}
  1833 +
  1834 +/* ??? FP exceptions are not implemented. Most exceptions are deferred until
  1835 + immediately before the next FP instruction is executed. */
  1836 +DISAS_INSN(fpu)
  1837 +{
  1838 + uint16_t ext;
  1839 + int opmode;
  1840 + int src;
  1841 + int dest;
  1842 + int res;
  1843 + int round;
  1844 + int opsize;
  1845 +
  1846 + ext = lduw(s->pc);
  1847 + s->pc += 2;
  1848 + opmode = ext & 0x7f;
  1849 + switch ((ext >> 13) & 7) {
  1850 + case 0: case 2:
  1851 + break;
  1852 + case 1:
  1853 + goto undef;
  1854 + case 3: /* fmove out */
  1855 + src = FREG(ext, 7);
  1856 + /* fmove */
  1857 + /* ??? TODO: Proper behavior on overflow. */
  1858 + switch ((ext >> 10) & 7) {
  1859 + case 0:
  1860 + opsize = OS_LONG;
  1861 + res = gen_new_qreg(QMODE_I32);
  1862 + gen_op_f64_to_i32(res, src);
  1863 + break;
  1864 + case 1:
  1865 + opsize = OS_SINGLE;
  1866 + res = gen_new_qreg(QMODE_F32);
  1867 + gen_op_f64_to_f32(res, src);
  1868 + break;
  1869 + case 4:
  1870 + opsize = OS_WORD;
  1871 + res = gen_new_qreg(QMODE_I32);
  1872 + gen_op_f64_to_i32(res, src);
  1873 + break;
  1874 + case 5:
  1875 + opsize = OS_DOUBLE;
  1876 + res = src;
  1877 + break;
  1878 + case 6:
  1879 + opsize = OS_BYTE;
  1880 + res = gen_new_qreg(QMODE_I32);
  1881 + gen_op_f64_to_i32(res, src);
  1882 + break;
  1883 + default:
  1884 + goto undef;
  1885 + }
  1886 + gen_ea(s, insn, opsize, res, NULL);
  1887 + return;
  1888 + case 4: /* fmove to control register. */
  1889 + switch ((ext >> 10) & 7) {
  1890 + case 4: /* FPCR */
  1891 + /* Not implemented. Ignore writes. */
  1892 + break;
  1893 + case 1: /* FPIAR */
  1894 + case 2: /* FPSR */
  1895 + default:
  1896 + cpu_abort(NULL, "Unimplemented: fmove to control %d",
  1897 + (ext >> 10) & 7);
  1898 + }
  1899 + break;
  1900 + case 5: /* fmove from control register. */
  1901 + switch ((ext >> 10) & 7) {
  1902 + case 4: /* FPCR */
  1903 + /* Not implemented. Always return zero. */
  1904 + res = gen_im32(0);
  1905 + break;
  1906 + case 1: /* FPIAR */
  1907 + case 2: /* FPSR */
  1908 + default:
  1909 + cpu_abort(NULL, "Unimplemented: fmove from control %d",
  1910 + (ext >> 10) & 7);
  1911 + goto undef;
  1912 + }
  1913 + gen_ea(s, insn, OS_LONG, res, NULL);
  1914 + break;
  1915 + case 6: /* fmovem */
  1916 + case 7:
  1917 + {
  1918 + int addr;
  1919 + uint16_t mask;
  1920 + if ((ext & 0x1f00) != 0x1000 || (ext & 0xff) == 0)
  1921 + goto undef;
  1922 + src = gen_lea(s, insn, OS_LONG);
  1923 + addr = gen_new_qreg(QMODE_I32);
  1924 + gen_op_mov32(addr, src);
  1925 + mask = 0x80;
  1926 + dest = QREG_F0;
  1927 + while (mask) {
  1928 + if (ext & mask) {
  1929 + if (ext & (1 << 13)) {
  1930 + /* store */
  1931 + gen_op_stf64(addr, dest);
  1932 + } else {
  1933 + /* load */
  1934 + gen_op_ldf64(dest, addr);
  1935 + }
  1936 + if (ext & (mask - 1))
  1937 + gen_op_add32(addr, addr, gen_im32(8));
  1938 + }
  1939 + mask >>= 1;
  1940 + dest++;
  1941 + }
  1942 + }
  1943 + return;
  1944 + }
  1945 + if (ext & (1 << 14)) {
  1946 + int tmp;
  1947 +
  1948 + /* Source effective address. */
  1949 + switch ((ext >> 10) & 7) {
  1950 + case 0: opsize = OS_LONG; break;
  1951 + case 1: opsize = OS_SINGLE; break;
  1952 + case 4: opsize = OS_WORD; break;
  1953 + case 5: opsize = OS_DOUBLE; break;
  1954 + case 6: opsize = OS_BYTE; break;
  1955 + default:
  1956 + goto undef;
  1957 + }
  1958 + tmp = gen_ea(s, insn, opsize, -1, NULL);
  1959 + if (opsize == OS_DOUBLE) {
  1960 + src = tmp;
  1961 + } else {
  1962 + src = gen_new_qreg(QMODE_F64);
  1963 + switch (opsize) {
  1964 + case OS_LONG:
  1965 + case OS_WORD:
  1966 + case OS_BYTE:
  1967 + gen_op_i32_to_f64(src, tmp);
  1968 + break;
  1969 + case OS_SINGLE:
  1970 + gen_op_f32_to_f64(src, tmp);
  1971 + break;
  1972 + }
  1973 + }
  1974 + } else {
  1975 + /* Source register. */
  1976 + src = FREG(ext, 10);
  1977 + }
  1978 + dest = FREG(ext, 7);
  1979 + res = gen_new_qreg(QMODE_F64);
  1980 + if (opmode != 0x3a)
  1981 + gen_op_movf64(res, dest);
  1982 + round = 1;
  1983 + switch (opmode) {
  1984 + case 0: case 0x40: case 0x44: /* fmove */
  1985 + gen_op_movf64(res, src);
  1986 + break;
  1987 + case 1: /* fint */
  1988 + gen_op_iround_f64(res, src);
  1989 + round = 0;
  1990 + break;
  1991 + case 3: /* fintrz */
  1992 + gen_op_itrunc_f64(res, src);
  1993 + round = 0;
  1994 + break;
  1995 + case 4: case 0x41: case 0x45: /* fsqrt */
  1996 + gen_op_sqrtf64(res, src);
  1997 + break;
  1998 + case 0x18: case 0x58: case 0x5c: /* fabs */
  1999 + gen_op_absf64(res, src);
  2000 + break;
  2001 + case 0x1a: case 0x5a: case 0x5e: /* fneg */
  2002 + gen_op_chsf64(res, src);
  2003 + break;
  2004 + case 0x20: case 0x60: case 0x64: /* fdiv */
  2005 + gen_op_divf64(res, res, src);
  2006 + break;
  2007 + case 0x22: case 0x62: case 0x66: /* fadd */
  2008 + gen_op_addf64(res, res, src);
  2009 + break;
  2010 + case 0x23: case 0x63: case 0x67: /* fmul */
  2011 + gen_op_mulf64(res, res, src);
  2012 + break;
  2013 + case 0x28: case 0x68: case 0x6c: /* fsub */
  2014 + gen_op_subf64(res, res, src);
  2015 + break;
  2016 + case 0x38: /* fcmp */
  2017 + gen_op_sub_cmpf64(res, res, src);
  2018 + dest = 0;
  2019 + round = 0;
  2020 + break;
  2021 + case 0x3a: /* ftst */
  2022 + gen_op_movf64(res, src);
  2023 + dest = 0;
  2024 + round = 0;
  2025 + break;
  2026 + default:
  2027 + goto undef;
  2028 + }
  2029 + if (round) {
  2030 + if (opmode & 0x40) {
  2031 + if ((opmode & 0x4) != 0)
  2032 + round = 0;
  2033 + } else if ((s->fpcr & M68K_FPCR_PREC) == 0) {
  2034 + round = 0;
  2035 + }
  2036 + }
  2037 + if (round) {
  2038 + int tmp;
  2039 +
  2040 + tmp = gen_new_qreg(QMODE_F32);
  2041 + gen_op_f64_to_f32(tmp, res);
  2042 + gen_op_f32_to_f64(res, tmp);
  2043 + }
  2044 + gen_op_fp_result(res);
  2045 + if (dest) {
  2046 + gen_op_movf64(dest, res);
  2047 + }
  2048 + return;
  2049 +undef:
  2050 + s->pc -= 2;
  2051 + disas_undef_fpu(s, insn);
  2052 +}
  2053 +
  2054 +DISAS_INSN(fbcc)
  2055 +{
  2056 + uint32_t offset;
  2057 + uint32_t addr;
  2058 + int flag;
  2059 + int zero;
  2060 + int l1;
  2061 +
  2062 + addr = s->pc;
  2063 + offset = ldsw(s->pc);
  2064 + s->pc += 2;
  2065 + if (insn & (1 << 6)) {
  2066 + offset = (offset << 16) | lduw(s->pc);
  2067 + s->pc += 2;
  2068 + }
  2069 +
  2070 + l1 = gen_new_label();
  2071 + /* TODO: Raise BSUN exception. */
  2072 + flag = gen_new_qreg(QMODE_I32);
  2073 + zero = gen_new_qreg(QMODE_F64);
  2074 + gen_op_zerof64(zero);
  2075 + gen_op_compare_quietf64(flag, QREG_FP_RESULT, zero);
  2076 + /* Jump to l1 if condition is true. */
  2077 + switch (insn & 0xf) {
  2078 + case 0: /* f */
  2079 + break;
  2080 + case 1: /* eq (=0) */
  2081 + gen_op_jmp_z32(flag, l1);
  2082 + break;
  2083 + case 2: /* ogt (=1) */
  2084 + gen_op_sub32(flag, flag, gen_im32(1));
  2085 + gen_op_jmp_z32(flag, l1);
  2086 + break;
  2087 + case 3: /* oge (=0 or =1) */
  2088 + gen_op_jmp_z32(flag, l1);
  2089 + gen_op_sub32(flag, flag, gen_im32(1));
  2090 + gen_op_jmp_z32(flag, l1);
  2091 + break;
  2092 + case 4: /* olt (=-1) */
  2093 + gen_op_jmp_s32(flag, l1);
  2094 + break;
  2095 + case 5: /* ole (=-1 or =0) */
  2096 + gen_op_jmp_s32(flag, l1);
  2097 + gen_op_jmp_z32(flag, l1);
  2098 + break;
  2099 + case 6: /* ogl (=-1 or =1) */
  2100 + gen_op_jmp_s32(flag, l1);
  2101 + gen_op_sub32(flag, flag, gen_im32(1));
  2102 + gen_op_jmp_z32(flag, l1);
  2103 + break;
  2104 + case 7: /* or (=2) */
  2105 + gen_op_sub32(flag, flag, gen_im32(2));
  2106 + gen_op_jmp_z32(flag, l1);
  2107 + break;
  2108 + case 8: /* un (<2) */
  2109 + gen_op_sub32(flag, flag, gen_im32(2));
  2110 + gen_op_jmp_s32(flag, l1);
  2111 + break;
  2112 + case 9: /* ueq (=0 or =2) */
  2113 + gen_op_jmp_z32(flag, l1);
  2114 + gen_op_sub32(flag, flag, gen_im32(2));
  2115 + gen_op_jmp_z32(flag, l1);
  2116 + break;
  2117 + case 10: /* ugt (>0) */
  2118 + /* ??? Add jmp_gtu. */
  2119 + gen_op_sub32(flag, flag, gen_im32(1));
  2120 + gen_op_jmp_ns32(flag, l1);
  2121 + break;
  2122 + case 11: /* uge (>=0) */
  2123 + gen_op_jmp_ns32(flag, l1);
  2124 + break;
  2125 + case 12: /* ult (=-1 or =2) */
  2126 + gen_op_jmp_s32(flag, l1);
  2127 + gen_op_sub32(flag, flag, gen_im32(2));
  2128 + gen_op_jmp_z32(flag, l1);
  2129 + break;
  2130 + case 13: /* ule (!=1) */
  2131 + gen_op_sub32(flag, flag, gen_im32(1));
  2132 + gen_op_jmp_nz32(flag, l1);
  2133 + break;
  2134 + case 14: /* ne (!=0) */
  2135 + gen_op_jmp_nz32(flag, l1);
  2136 + break;
  2137 + case 15: /* t */
  2138 + gen_op_mov32(flag, gen_im32(1));
  2139 + break;
  2140 + }
  2141 + gen_jmp_tb(s, 0, s->pc);
  2142 + gen_set_label(l1);
  2143 + gen_jmp_tb(s, 1, addr + offset);
  2144 +}
  2145 +
  2146 +static disas_proc opcode_table[65536];
  2147 +
  2148 +static void
  2149 +register_opcode (disas_proc proc, uint16_t opcode, uint16_t mask)
  2150 +{
  2151 + int i;
  2152 + int from;
  2153 + int to;
  2154 +
  2155 + /* Sanity check. All set bits must be included in the mask. */
  2156 + if (opcode & ~mask)
  2157 + abort();
  2158 + /* This could probably be cleverer. For now just optimize the case where
  2159 + the top bits are known. */
  2160 + /* Find the first zero bit in the mask. */
  2161 + i = 0x8000;
  2162 + while ((i & mask) != 0)
  2163 + i >>= 1;
  2164 + /* Iterate over all combinations of this and lower bits. */
  2165 + if (i == 0)
  2166 + i = 1;
  2167 + else
  2168 + i <<= 1;
  2169 + from = opcode & ~(i - 1);
  2170 + to = from + i;
  2171 + for (i = from; i < to; i++)
  2172 + {
  2173 + if ((i & mask) == opcode)
  2174 + opcode_table[i] = proc;
  2175 + }
  2176 +}
  2177 +
  2178 +/* Register m68k opcode handlers. Order is important.
  2179 + Later insn override earlier ones. */
  2180 +static void
  2181 +register_m68k_insns (m68k_def_t *def)
  2182 +{
  2183 + uint32_t iflags;
  2184 +
  2185 + iflags = def->insns;
  2186 +#define INSN(name, opcode, mask, isa) \
  2187 + if (iflags & M68K_INSN_##isa) \
  2188 + register_opcode(disas_##name, 0x##opcode, 0x##mask)
  2189 + INSN(undef, 0000, 0000, CF_A);
  2190 + INSN(arith_im, 0080, fff8, CF_A);
  2191 + INSN(bitrev, 00c0, fff8, CF_C);
  2192 + INSN(bitop_reg, 0100, f1c0, CF_A);
  2193 + INSN(bitop_reg, 0140, f1c0, CF_A);
  2194 + INSN(bitop_reg, 0180, f1c0, CF_A);
  2195 + INSN(bitop_reg, 01c0, f1c0, CF_A);
  2196 + INSN(arith_im, 0280, fff8, CF_A);
  2197 + INSN(byterev, 02c0, fff8, CF_A);
  2198 + INSN(arith_im, 0480, fff8, CF_A);
  2199 + INSN(ff1, 04c0, fff8, CF_C);
  2200 + INSN(arith_im, 0680, fff8, CF_A);
  2201 + INSN(bitop_im, 0800, ffc0, CF_A);
  2202 + INSN(bitop_im, 0840, ffc0, CF_A);
  2203 + INSN(bitop_im, 0880, ffc0, CF_A);
  2204 + INSN(bitop_im, 08c0, ffc0, CF_A);
  2205 + INSN(arith_im, 0a80, fff8, CF_A);
  2206 + INSN(arith_im, 0c00, ff38, CF_A);
  2207 + INSN(move, 1000, f000, CF_A);
  2208 + INSN(move, 2000, f000, CF_A);
  2209 + INSN(move, 3000, f000, CF_A);
  2210 + INSN(strldsr, 40e7, ffff, CF_A);
  2211 + INSN(negx, 4080, fff8, CF_A);
  2212 + INSN(move_from_sr, 40c0, fff8, CF_A);
  2213 + INSN(lea, 41c0, f1c0, CF_A);
  2214 + INSN(clr, 4200, ff00, CF_A);
  2215 + INSN(undef, 42c0, ffc0, CF_A);
  2216 + INSN(move_from_ccr, 42c0, fff8, CF_A);
  2217 + INSN(neg, 4480, fff8, CF_A);
  2218 + INSN(move_to_ccr, 44c0, ffc0, CF_A);
  2219 + INSN(not, 4680, fff8, CF_A);
  2220 + INSN(move_to_sr, 46c0, ffc0, CF_A);
  2221 + INSN(pea, 4840, ffc0, CF_A);
  2222 + INSN(swap, 4840, fff8, CF_A);
  2223 + INSN(movem, 48c0, fbc0, CF_A);
  2224 + INSN(ext, 4880, fff8, CF_A);
  2225 + INSN(ext, 48c0, fff8, CF_A);
  2226 + INSN(ext, 49c0, fff8, CF_A);
  2227 + INSN(tst, 4a00, ff00, CF_A);
  2228 + INSN(tas, 4ac0, ffc0, CF_B);
  2229 + INSN(halt, 4ac8, ffff, CF_A);
  2230 + INSN(pulse, 4acc, ffff, CF_A);
  2231 + INSN(illegal, 4afc, ffff, CF_A);
  2232 + INSN(mull, 4c00, ffc0, CF_A);
  2233 + INSN(divl, 4c40, ffc0, CF_A);
  2234 + INSN(sats, 4c80, fff8, CF_B);
  2235 + INSN(trap, 4e40, fff0, CF_A);
  2236 + INSN(link, 4e50, fff8, CF_A);
  2237 + INSN(unlk, 4e58, fff8, CF_A);
  2238 + INSN(move_to_usp, 4e60, fff8, CF_B);
  2239 + INSN(move_from_usp, 4e68, fff8, CF_B);
  2240 + INSN(nop, 4e71, ffff, CF_A);
  2241 + INSN(stop, 4e72, ffff, CF_A);
  2242 + INSN(rte, 4e73, ffff, CF_A);
  2243 + INSN(rts, 4e75, ffff, CF_A);
  2244 + INSN(movec, 4e7b, ffff, CF_A);
  2245 + INSN(jump, 4e80, ffc0, CF_A);
  2246 + INSN(jump, 4ec0, ffc0, CF_A);
  2247 + INSN(addsubq, 5180, f1c0, CF_A);
  2248 + INSN(scc, 50c0, f0f8, CF_A);
  2249 + INSN(addsubq, 5080, f1c0, CF_A);
  2250 + INSN(tpf, 51f8, fff8, CF_A);
  2251 + INSN(branch, 6000, f000, CF_A);
  2252 + INSN(moveq, 7000, f100, CF_A);
  2253 + INSN(mvzs, 7100, f100, CF_B);
  2254 + INSN(or, 8000, f000, CF_A);
  2255 + INSN(divw, 80c0, f0c0, CF_A);
  2256 + INSN(addsub, 9000, f000, CF_A);
  2257 + INSN(subx, 9180, f1f8, CF_A);
  2258 + INSN(suba, 91c0, f1c0, CF_A);
  2259 + INSN(undef_mac, a000, f000, CF_A);
  2260 + INSN(mov3q, a140, f1c0, CF_B);
  2261 + INSN(cmp, b000, f1c0, CF_B); /* cmp.b */
  2262 + INSN(cmp, b040, f1c0, CF_B); /* cmp.w */
  2263 + INSN(cmpa, b0c0, f1c0, CF_B); /* cmpa.w */
  2264 + INSN(cmp, b080, f1c0, CF_A);
  2265 + INSN(cmpa, b1c0, f1c0, CF_A);
  2266 + INSN(eor, b180, f1c0, CF_A);
  2267 + INSN(and, c000, f000, CF_A);
  2268 + INSN(mulw, c0c0, f0c0, CF_A);
  2269 + INSN(addsub, d000, f000, CF_A);
  2270 + INSN(addx, d180, f1f8, CF_A);
  2271 + INSN(adda, d1c0, f1c0, CF_A);
  2272 + INSN(shift_im, e080, f0f0, CF_A);
  2273 + INSN(shift_reg, e0a0, f0f0, CF_A);
  2274 + INSN(undef_fpu, f000, f000, CF_A);
  2275 + INSN(fpu, f200, ffc0, CF_FPU);
  2276 + INSN(fbcc, f280, ffc0, CF_FPU);
  2277 + INSN(intouch, f340, ffc0, CF_A);
  2278 + INSN(cpushl, f428, ff38, CF_A);
  2279 + INSN(wddata, fb00, ff00, CF_A);
  2280 + INSN(wdebug, fbc0, ffc0, CF_A);
  2281 +#undef INSN
  2282 +}
  2283 +
  2284 +/* ??? Some of this implementation is not exception safe. We should always
  2285 + write back the result to memory before setting the condition codes. */
  2286 +static void disas_m68k_insn(CPUState * env, DisasContext *s)
  2287 +{
  2288 + uint16_t insn;
  2289 +
  2290 + insn = lduw(s->pc);
  2291 + s->pc += 2;
  2292 +
  2293 + opcode_table[insn](s, insn);
  2294 +}
  2295 +
  2296 +#if 0
  2297 +/* Save the result of a floating point operation. */
  2298 +static void expand_op_fp_result(qOP *qop)
  2299 +{
  2300 + gen_op_movf64(QREG_FP_RESULT, qop->args[0]);
  2301 +}
  2302 +
  2303 +/* Dummy op to indicate that the flags have been set. */
  2304 +static void expand_op_flags_set(qOP *qop)
  2305 +{
  2306 +}
  2307 +
  2308 +/* Convert the confition codes into CC_OP_FLAGS format. */
  2309 +static void expand_op_flush_flags(qOP *qop)
  2310 +{
  2311 + int cc_opreg;
  2312 +
  2313 + if (qop->args[0] == CC_OP_DYNAMIC)
  2314 + cc_opreg = QREG_CC_OP;
  2315 + else
  2316 + cc_opreg = gen_im32(qop->args[0]);
  2317 + gen_op_helper32(QREG_NULL, cc_opreg, HELPER_flush_flags);
  2318 +}
  2319 +
  2320 +/* Set CC_DEST after a logical or direct flag setting operation. */
  2321 +static void expand_op_logic_cc(qOP *qop)
  2322 +{
  2323 + gen_op_mov32(QREG_CC_DEST, qop->args[0]);
  2324 +}
  2325 +
  2326 +/* Set CC_SRC and CC_DEST after an arithmetic operation. */
  2327 +static void expand_op_update_cc_add(qOP *qop)
  2328 +{
  2329 + gen_op_mov32(QREG_CC_DEST, qop->args[0]);
  2330 + gen_op_mov32(QREG_CC_SRC, qop->args[1]);
  2331 +}
  2332 +
  2333 +/* Update the X flag. */
  2334 +static void expand_op_update_xflag(qOP *qop)
  2335 +{
  2336 + int arg0;
  2337 + int arg1;
  2338 +
  2339 + arg0 = qop->args[0];
  2340 + arg1 = qop->args[1];
  2341 + if (arg1 == QREG_NULL) {
  2342 + /* CC_X = arg0. */
  2343 + gen_op_mov32(QREG_CC_X, arg0);
  2344 + } else {
  2345 + /* CC_X = arg0 < (unsigned)arg1. */
  2346 + gen_op_set_ltu32(QREG_CC_X, arg0, arg1);
  2347 + }
  2348 +}
  2349 +
  2350 +/* Set arg0 to the contents of the X flag. */
  2351 +static void expand_op_get_xflag(qOP *qop)
  2352 +{
  2353 + gen_op_mov32(qop->args[0], QREG_CC_X);
  2354 +}
  2355 +
  2356 +/* Expand a shift by immediate. The ISA only allows shifts by 1-8, so we
  2357 + already know the shift is within range. */
  2358 +static inline void expand_shift_im(qOP *qop, int right, int arith)
  2359 +{
  2360 + int val;
  2361 + int reg;
  2362 + int tmp;
  2363 + int im;
  2364 +
  2365 + reg = qop->args[0];
  2366 + im = qop->args[1];
  2367 + tmp = gen_im32(im);
  2368 + val = gen_new_qreg(QMODE_I32);
  2369 + gen_op_mov32(val, reg);
  2370 + gen_op_mov32(QREG_CC_DEST, val);
  2371 + gen_op_mov32(QREG_CC_SRC, tmp);
  2372 + if (right) {
  2373 + if (arith) {
  2374 + gen_op_sar32(reg, val, tmp);
  2375 + } else {
  2376 + gen_op_shr32(reg, val, tmp);
  2377 + }
  2378 + if (im == 1)
  2379 + tmp = QREG_NULL;
  2380 + else
  2381 + tmp = gen_im32(im - 1);
  2382 + } else {
  2383 + gen_op_shl32(reg, val, tmp);
  2384 + tmp = gen_im32(32 - im);
  2385 + }
  2386 + if (tmp != QREG_NULL)
  2387 + gen_op_shr32(val, val, tmp);
  2388 + gen_op_and32(QREG_CC_X, val, gen_im32(1));
  2389 +}
  2390 +
  2391 +static void expand_op_shl_im_cc(qOP *qop)
  2392 +{
  2393 + expand_shift_im(qop, 0, 0);
  2394 +}
  2395 +
  2396 +static void expand_op_shr_im_cc(qOP *qop)
  2397 +{
  2398 + expand_shift_im(qop, 1, 0);
  2399 +}
  2400 +
  2401 +static void expand_op_sar_im_cc(qOP *qop)
  2402 +{
  2403 + expand_shift_im(qop, 1, 1);
  2404 +}
  2405 +
  2406 +/* Expand a shift by register. */
  2407 +/* ??? This gives incorrect answers for shifts by 0 or >= 32 */
  2408 +static inline void expand_shift_reg(qOP *qop, int right, int arith)
  2409 +{
  2410 + int val;
  2411 + int reg;
  2412 + int shift;
  2413 + int tmp;
  2414 +
  2415 + reg = qop->args[0];
  2416 + shift = qop->args[1];
  2417 + val = gen_new_qreg(QMODE_I32);
  2418 + gen_op_mov32(val, reg);
  2419 + gen_op_mov32(QREG_CC_DEST, val);
  2420 + gen_op_mov32(QREG_CC_SRC, shift);
  2421 + tmp = gen_new_qreg(QMODE_I32);
  2422 + if (right) {
  2423 + if (arith) {
  2424 + gen_op_sar32(reg, val, shift);
  2425 + } else {
  2426 + gen_op_shr32(reg, val, shift);
  2427 + }
  2428 + gen_op_sub32(tmp, shift, gen_im32(1));
  2429 + } else {
  2430 + gen_op_shl32(reg, val, shift);
  2431 + gen_op_sub32(tmp, gen_im32(31), shift);
  2432 + }
  2433 + gen_op_shl32(val, val, tmp);
  2434 + gen_op_and32(QREG_CC_X, val, gen_im32(1));
  2435 +}
  2436 +
  2437 +static void expand_op_shl_cc(qOP *qop)
  2438 +{
  2439 + expand_shift_reg(qop, 0, 0);
  2440 +}
  2441 +
  2442 +static void expand_op_shr_cc(qOP *qop)
  2443 +{
  2444 + expand_shift_reg(qop, 1, 0);
  2445 +}
  2446 +
  2447 +static void expand_op_sar_cc(qOP *qop)
  2448 +{
  2449 + expand_shift_reg(qop, 1, 1);
  2450 +}
  2451 +
  2452 +/* Set the Z flag to (arg0 & arg1) == 0. */
  2453 +static void expand_op_btest(qOP *qop)
  2454 +{
  2455 + int tmp;
  2456 + int l1;
  2457 +
  2458 + l1 = gen_new_label();
  2459 + tmp = gen_new_qreg(QMODE_I32);
  2460 + gen_op_and32(tmp, qop->args[0], qop->args[1]);
  2461 + gen_op_and32(QREG_CC_DEST, QREG_CC_DEST, gen_im32(~(uint32_t)CCF_Z));
  2462 + gen_op_jmp_nz32(tmp, l1);
  2463 + gen_op_or32(QREG_CC_DEST, QREG_CC_DEST, gen_im32(CCF_Z));
  2464 + gen_op_label(l1);
  2465 +}
  2466 +
  2467 +/* arg0 += arg1 + CC_X */
  2468 +static void expand_op_addx_cc(qOP *qop)
  2469 +{
  2470 + int arg0 = qop->args[0];
  2471 + int arg1 = qop->args[1];
  2472 + int l1, l2;
  2473 +
  2474 + gen_op_add32 (arg0, arg0, arg1);
  2475 + l1 = gen_new_label();
  2476 + l2 = gen_new_label();
  2477 + gen_op_jmp_z32(QREG_CC_X, l1);
  2478 + gen_op_add32(arg0, arg0, gen_im32(1));
  2479 + gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_ADDX));
  2480 + gen_op_set_leu32(QREG_CC_X, arg0, arg1);
  2481 + gen_op_jmp(l2);
  2482 + gen_set_label(l1);
  2483 + gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_ADD));
  2484 + gen_op_set_ltu32(QREG_CC_X, arg0, arg1);
  2485 + gen_set_label(l2);
  2486 +}
  2487 +
  2488 +/* arg0 -= arg1 + CC_X */
  2489 +static void expand_op_subx_cc(qOP *qop)
  2490 +{
  2491 + int arg0 = qop->args[0];
  2492 + int arg1 = qop->args[1];
  2493 + int l1, l2;
  2494 +
  2495 + l1 = gen_new_label();
  2496 + l2 = gen_new_label();
  2497 + gen_op_jmp_z32(QREG_CC_X, l1);
  2498 + gen_op_set_leu32(QREG_CC_X, arg0, arg1);
  2499 + gen_op_sub32(arg0, arg0, gen_im32(1));
  2500 + gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_SUBX));
  2501 + gen_op_jmp(l2);
  2502 + gen_set_label(l1);
  2503 + gen_op_set_ltu32(QREG_CC_X, arg0, arg1);
  2504 + gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_SUB));
  2505 + gen_set_label(l2);
  2506 + gen_op_sub32 (arg0, arg0, arg1);
  2507 +}
  2508 +
  2509 +/* Expand target specific ops to generic qops. */
  2510 +static void expand_target_qops(void)
  2511 +{
  2512 + qOP *qop;
  2513 + qOP *next;
  2514 + int c;
  2515 +
  2516 + /* Copy the list of qops, expanding target specific ops as we go. */
  2517 + qop = gen_first_qop;
  2518 + gen_first_qop = NULL;
  2519 + gen_last_qop = NULL;
  2520 + for (; qop; qop = next) {
  2521 + c = qop->opcode;
  2522 + next = qop->next;
  2523 + if (c < FIRST_TARGET_OP) {
  2524 + qop->prev = gen_last_qop;
  2525 + qop->next = NULL;
  2526 + if (gen_last_qop)
  2527 + gen_last_qop->next = qop;
  2528 + else
  2529 + gen_first_qop = qop;
  2530 + gen_last_qop = qop;
  2531 + continue;
  2532 + }
  2533 + switch (c) {
  2534 +#define DEF(name, nargs, barrier) \
  2535 + case INDEX_op_##name: \
  2536 + expand_op_##name(qop); \
  2537 + break;
  2538 +#include "qop-target.def"
  2539 +#undef DEF
  2540 + default:
  2541 + cpu_abort(NULL, "Unexpanded target qop");
  2542 + }
  2543 + }
  2544 +}
  2545 +
  2546 +/* ??? Implement this. */
  2547 +static void
  2548 +optimize_flags(void)
  2549 +{
  2550 +}
  2551 +#endif
  2552 +
  2553 +/* generate intermediate code for basic block 'tb'. */
  2554 +int gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
  2555 + int search_pc)
  2556 +{
  2557 + DisasContext dc1, *dc = &dc1;
  2558 + uint16_t *gen_opc_end;
  2559 + int j, lj;
  2560 + target_ulong pc_start;
  2561 + int pc_offset;
  2562 + int last_cc_op;
  2563 +
  2564 + /* generate intermediate code */
  2565 + pc_start = tb->pc;
  2566 +
  2567 + dc->tb = tb;
  2568 +
  2569 + gen_opc_ptr = gen_opc_buf;
  2570 + gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
  2571 + gen_opparam_ptr = gen_opparam_buf;
  2572 +
  2573 + dc->is_jmp = DISAS_NEXT;
  2574 + dc->pc = pc_start;
  2575 + dc->cc_op = CC_OP_DYNAMIC;
  2576 + dc->singlestep_enabled = env->singlestep_enabled;
  2577 + dc->fpcr = env->fpcr;
  2578 + nb_gen_labels = 0;
  2579 + lj = -1;
  2580 + do {
  2581 + free_qreg = 0;
  2582 + pc_offset = dc->pc - pc_start;
  2583 + gen_throws_exception = NULL;
  2584 + if (env->nb_breakpoints > 0) {
  2585 + for(j = 0; j < env->nb_breakpoints; j++) {
  2586 + if (env->breakpoints[j] == dc->pc) {
  2587 + gen_exception(dc, dc->pc, EXCP_DEBUG);
  2588 + dc->is_jmp = DISAS_JUMP;
  2589 + break;
  2590 + }
  2591 + }
  2592 + if (dc->is_jmp)
  2593 + break;
  2594 + }
  2595 + if (search_pc) {
  2596 + j = gen_opc_ptr - gen_opc_buf;
  2597 + if (lj < j) {
  2598 + lj++;
  2599 + while (lj < j)
  2600 + gen_opc_instr_start[lj++] = 0;
  2601 + }
  2602 + gen_opc_pc[lj] = dc->pc;
  2603 + gen_opc_instr_start[lj] = 1;
  2604 + }
  2605 + last_cc_op = dc->cc_op;
  2606 + disas_m68k_insn(env, dc);
  2607 + } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
  2608 + !env->singlestep_enabled &&
  2609 + (pc_offset) < (TARGET_PAGE_SIZE - 32));
  2610 +
  2611 + if (__builtin_expect(env->singlestep_enabled, 0)) {
  2612 + /* Make sure the pc is updated, and raise a debug exception. */
  2613 + if (!dc->is_jmp) {
  2614 + gen_flush_cc_op(dc);
  2615 + gen_op_mov32(QREG_PC, gen_im32((long)dc->pc));
  2616 + }
  2617 + gen_op_raise_exception(EXCP_DEBUG);
  2618 + } else {
  2619 + switch(dc->is_jmp) {
  2620 + case DISAS_NEXT:
  2621 + gen_flush_cc_op(dc);
  2622 + gen_jmp_tb(dc, 0, dc->pc);
  2623 + break;
  2624 + default:
  2625 + case DISAS_JUMP:
  2626 + case DISAS_UPDATE:
  2627 + gen_flush_cc_op(dc);
  2628 + /* indicate that the hash table must be used to find the next TB */
  2629 + gen_op_mov32(QREG_T0, gen_im32(0));
  2630 + gen_op_exit_tb();
  2631 + break;
  2632 + case DISAS_TB_JUMP:
  2633 + /* nothing more to generate */
  2634 + break;
  2635 + }
  2636 + }
  2637 + *gen_opc_ptr = INDEX_op_end;
  2638 +
  2639 +#ifdef DEBUG_DISAS
  2640 + if (loglevel & CPU_LOG_TB_IN_ASM) {
  2641 + fprintf(logfile, "----------------\n");
  2642 + fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
  2643 + target_disas(logfile, pc_start, dc->pc - pc_start, 0);
  2644 + fprintf(logfile, "\n");
  2645 + if (loglevel & (CPU_LOG_TB_OP)) {
  2646 + fprintf(logfile, "OP:\n");
  2647 + dump_ops(gen_opc_buf, gen_opparam_buf);
  2648 + fprintf(logfile, "\n");
  2649 + }
  2650 + }
  2651 +#endif
  2652 + if (search_pc) {
  2653 + j = gen_opc_ptr - gen_opc_buf;
  2654 + lj++;
  2655 + while (lj <= j)
  2656 + gen_opc_instr_start[lj++] = 0;
  2657 + tb->size = 0;
  2658 + } else {
  2659 + tb->size = dc->pc - pc_start;
  2660 + }
  2661 +
  2662 + //optimize_flags();
  2663 + //expand_target_qops();
  2664 + return 0;
  2665 +}
  2666 +
  2667 +int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
  2668 +{
  2669 + return gen_intermediate_code_internal(env, tb, 0);
  2670 +}
  2671 +
  2672 +int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
  2673 +{
  2674 + return gen_intermediate_code_internal(env, tb, 1);
  2675 +}
  2676 +
  2677 +CPUM68KState *cpu_m68k_init(void)
  2678 +{
  2679 + CPUM68KState *env;
  2680 +
  2681 + env = malloc(sizeof(CPUM68KState));
  2682 + if (!env)
  2683 + return NULL;
  2684 + cpu_exec_init(env);
  2685 +
  2686 + memset(env, 0, sizeof(CPUM68KState));
  2687 + /* ??? FP regs should be initialized to NaN. */
  2688 + cpu_single_env = env;
  2689 + env->cc_op = CC_OP_FLAGS;
  2690 + return env;
  2691 +}
  2692 +
  2693 +void cpu_m68k_close(CPUM68KState *env)
  2694 +{
  2695 + free(env);
  2696 +}
  2697 +
  2698 +m68k_def_t *m68k_find_by_name(const char *name)
  2699 +{
  2700 + m68k_def_t *def;
  2701 +
  2702 + def = m68k_cpu_defs;
  2703 + while (def->name)
  2704 + {
  2705 + if (strcmp(def->name, name) == 0)
  2706 + return def;
  2707 + def++;
  2708 + }
  2709 + return NULL;
  2710 +}
  2711 +
  2712 +void cpu_m68k_register(CPUM68KState *env, m68k_def_t *def)
  2713 +{
  2714 + register_m68k_insns(def);
  2715 +}
  2716 +
  2717 +void cpu_dump_state(CPUState *env, FILE *f,
  2718 + int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
  2719 + int flags)
  2720 +{
  2721 + int i;
  2722 + uint16_t sr;
  2723 + CPU_DoubleU u;
  2724 + for (i = 0; i < 8; i++)
  2725 + {
  2726 + u.d = env->fregs[i];
  2727 + cpu_fprintf (f, "D%d = %08x A%d = %08x F%d = %08x%08x (%12g)\n",
  2728 + i, env->dregs[i], i, env->aregs[i],
  2729 + i, u.l.upper, u.l.lower, u.d);
  2730 + }
  2731 + cpu_fprintf (f, "PC = %08x ", env->pc);
  2732 + sr = env->sr;
  2733 + cpu_fprintf (f, "SR = %04x %c%c%c%c%c ", sr, (sr & 0x10) ? 'X' : '-',
  2734 + (sr & CCF_N) ? 'N' : '-', (sr & CCF_Z) ? 'Z' : '-',
  2735 + (sr & CCF_V) ? 'V' : '-', (sr & CCF_C) ? 'C' : '-');
  2736 + cpu_fprintf (f, "FPRESULT = %12g\n", env->fp_result);
  2737 +}
  2738 +
  2739 +/* ??? */
  2740 +target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
  2741 +{
  2742 + return addr;
  2743 +}
  2744 +
  2745 +#if defined(CONFIG_USER_ONLY)
  2746 +
  2747 +int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
  2748 + int is_user, int is_softmmu)
  2749 +{
  2750 + env->exception_index = EXCP_ACCESS;
  2751 + env->mmu.ar = address;
  2752 + return 1;
  2753 +}
  2754 +
  2755 +#else
  2756 +
  2757 +#error not implemented
  2758 +
  2759 +#endif
... ...
translate-all.c
... ... @@ -302,6 +302,8 @@ int cpu_restore_state(TranslationBlock *tb,
302 302 }
303 303 env->access_type = type;
304 304 }
  305 +#elif defined(TARGET_M68K)
  306 + env->pc = gen_opc_pc[j];
305 307 #elif defined(TARGET_MIPS)
306 308 env->PC = gen_opc_pc[j];
307 309 env->hflags &= ~MIPS_HFLAG_BMASK;
... ...