Syn68k from an svn export

This commit is contained in:
Clifford T. Matthews 2008-09-26 08:25:10 -06:00
commit eac71db488
248 changed files with 69602 additions and 0 deletions

5
AUTHORS Normal file
View File

@ -0,0 +1,5 @@
$Id: AUTHORS 61 2004-12-21 23:44:50Z ctm $
Matthew J. Hostetter
minor contributions by Clifford T. Matthews <ctm@ardi.com>

24
COPYING Normal file
View File

@ -0,0 +1,24 @@
$Id: COPYING 52 2004-12-16 02:08:47Z ctm $
Copyright 1994-2004 Abacus Research & Development, Inc.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

6
ChangeLog Normal file
View File

@ -0,0 +1,6 @@
$Id: ChangeLog 74 2004-12-30 03:38:55Z ctm $
2004-12-28 Clifford T. Matthews <ctm@ardi.com>
* Still in the process of switching to GNU build system.

3
Makefile.am Normal file
View File

@ -0,0 +1,3 @@
# $Id: Makefile.am 61 2004-12-21 23:44:50Z ctm $
SUBDIRS = syngen runtime test profile

488
Makefile.common.in Normal file
View File

@ -0,0 +1,488 @@
#CC = @CC@
CC = gcc
ifneq "$(findstring cygwin, $(SYN68K_TARGET))" ""
CC += -m486
endif
LIB_CC = @CC@
INCLUDE_DIR=$(topdir)/include
CFLAGS = -O2 -g -Wall -I$(INCLUDE_DIR) $(LOCAL_CFLAGS)
RANLIB = /usr/bin/ranlib
#RANLIB = @RANLIB@
LIBS =
SYN68K_TARGET=@host@
OFILE_DIR = .
LIBDIR = .
HOSTCPU = $(SYN68K_TARGET)
host-native=native/i386
#-----------------------------------------------------------------
#Makefile.common.alpha-redhat-linux
#-----------------------------------------------------------------
ifeq "$(SYN68K_TARGET)" "alpha-redhat-linux"
LIB_CFLAGS = -O2 -g -Wall -I$(INCLUDE_DIR) $(LOCAL_CFLAGS)
# NOTE: QUADALIGN DOESN'T WORK RIGHT NOW
# LIB_CFLAGS = -g -Wall -I$(INCLUDE_DIR) $(LOCAL_CFLAGS) -DQUADALIGN
# OPTIMIZE = ./i486-optimize.pl
# CLEANUP = ./i486-cleanup.pl
# LDFLAGS = -Lhost-native
# LDFLAGS = -taso
SYN68K_CFLAGS = $(LIB_CFLAGS) -O2 -fomit-frame-pointer
# SYN68K_CFLAGS = -g -Wall -DQUADALIGN
NO_NATIVE = TRUE
endif
#-----------------------------------------------------------------
#Makefile.common.alpha.orig
#-----------------------------------------------------------------
# ifeq "$(SYN68K_TARGET)" ""
# CC = cc
# OFILE_DIR = obj/alpha
# LIBDIR = ../lib/alpha
# HOSTCPU = alpha
# RANLIB = /bin/ranlib
# LDFLAGS = -taso
# endif
#-----------------------------------------------------------------
#Makefile.common.i386-msdos-go32
#-----------------------------------------------------------------
ifeq "$(SYN68K_TARGET)" "i386-msdos-go32"
LIB_CC = i386-msdos-go32-gcc -m486
LIB_CFLAGS = -O2 -g -Wall -I$(INCLUDE_DIR) $(LOCAL_CFLAGS)
AR = ar
AS = i386-msdos-go32-gcc -x assembler
RANLIB = ranlib
LDFLAGS = -Ttext 0 -Tdata 200000
CLEANUP = ./i486-cleanup.pl
OPTIMIZE = ./i486-optimize.pl
SYN68K_CFLAGS = -O2 -fomit-frame-pointer
endif
#-----------------------------------------------------------------
#Makefile.common.i386-next-mach-o.dynamic
#-----------------------------------------------------------------
ifeq "$(SYN68K_TARGET)" "i386-next-mach-o.dynamic"
LIB_CFLAGS = -O2 -g -Wall -I$(INCLUDE_DIR) $(LOCAL_CFLAGS)
OFILE_DIR = obj/i386-next-mach-o
LIBDIR = $(topdir)/lib/i386-next-mach-o
HOSTCPU = i386-next-mach-o
RANLIB = /bin/ranlib
OPTIMIZE = ./i486-optimize.pl
CLEANUP = ./i486-cleanup.pl
LDFLAGS =
SYN68K_CFLAGS = -O2 -fomit-frame-pointer
endif
#-----------------------------------------------------------------
#Makefile.common.i386-next-mach-o.static
#-----------------------------------------------------------------
ifeq "$(SYN68K_TARGET)" "i386-next-mach-o.static"
CFLAGS = -static -O2 -g -Wall -I$(INCLUDE_DIR) $(LOCAL_CFLAGS)
LIB_CFLAGS = -static -O2 -g -Wall -I$(INCLUDE_DIR) $(LOCAL_CFLAGS)
OFILE_DIR = obj/i386-next-mach-o
LIBDIR = $(topdir)/lib/i386-next-mach-o
HOSTCPU = i386-next-mach-o
RANLIB = /bin/ranlib
OPTIMIZE = ./i486-optimize.pl
CLEANUP = ./i486-cleanup.pl
LDFLAGS =
SYN68K_CFLAGS = -O2 -fomit-frame-pointer
endif
#-----------------------------------------------------------------
#Makefile.common.i486-pc-cygwin32
#-----------------------------------------------------------------
ifeq "$(SYN68K_TARGET)" "i486-pc-cygwin32"
CC = gcc -m486
LIB_CC = i486-pc-cygwin32-gcc -m486
LIB_CFLAGS = -O2 -g -Wall -I$(INCLUDE_DIR) $(LOCAL_CFLAGS) -Dfree=free_hack
AR = ar
AS = i486-pc-cygwin32-gcc -x assembler
RANLIB = i486-pc-cygwin32-ranlib
CLEANUP = ./i486-cleanup.pl
OPTIMIZE = ./i486-optimize.pl
SYN68K_CFLAGS = -O2 -fomit-frame-pointer -Dfree=free_hack
endif
#-----------------------------------------------------------------
#Makefile.common.i486-cygwin32-debug
#-----------------------------------------------------------------
# NOTE: we define __CHECKER__ so that we get a frame pointer and other
# good stuff. We're not actually using checker. D'oh.
ifeq "$(SYN68K_TARGET)" "i486-cygwin32-debug"
CC = gcc -m486
LIB_CC = i486-pc-cygwin32-gcc -m486
LIB_CFLAGS = -g -I$(INCLUDE_DIR) $(LOCAL_CFLAGS) -D__CHECKER__ -Dfree=free_hack
AR = ar
AS = i486-pc-cygwin32-gcc -x assembler
RANLIB = i486-pc-cygwin32-ranlib
CLEANUP = ./i486-cleanup.pl
# OPTIMIZE = ./i486-optimize.pl
SYN68K_CFLAGS = $(LIB_CFLAGS) -O
LDFLAGS = -Lhost-native
endif
#-----------------------------------------------------------------
#Makefile.common.i486-linux-a.out
#-----------------------------------------------------------------
ifeq "$(SYN68K_TARGET)" "i486-linux-a.out"
LIB_CC = gcc -b i486-linuxaout
LIB_CFLAGS = -O2 -g -Wall -I$(INCLUDE_DIR) $(LOCAL_CFLAGS)
OPTIMIZE = ./i486-optimize.pl
CLEANUP = ./i486-cleanup.pl
LDFLAGS = -Lhost-native
SYN68K_CFLAGS = -O2 -fomit-frame-pointer
endif
#-----------------------------------------------------------------
#Makefile.common.i486-linux-a.out-debug
#-----------------------------------------------------------------
# NOTE: we define __CHECKER__ so that we get a frame pointer and other
# good stuff. We're not actually using checker. D'oh.
ifeq "$(SYN68K_TARGET)" "i486-linux-a.out-debug"
LIB_CC = gcc -b i486-linuxaout
LIB_CFLAGS = -g -I$(INCLUDE_DIR) $(LOCAL_CFLAGS) -D__CHECKER__
SYN68K_CFLAGS = $(LIB_CFLAGS) -O
OFILE_DIR = obj/i486-linux-debug
LIBDIR = $(topdir)/lib/i486-linux-debug
HOSTCPU = i486-linux-debug
AR = ar
RANLIB = ranlib
# don't optimize syn68k.s when compiling with checker
# OPTIMIZE = ./i486-optimize.pl
CLEANUP = ./i486-cleanup.pl
LDFLAGS = -Lhost-native
endif
#-----------------------------------------------------------------
#Makefile.common.i486-linux-elf
#-----------------------------------------------------------------
ifeq "$(SYN68K_TARGET)" "i486-linux-elf"
LIB_CFLAGS = -O2 -g -Wall -I$(INCLUDE_DIR) $(LOCAL_CFLAGS)
OPTIMIZE = ./i486-optimize.pl
CLEANUP = ./i486-cleanup.pl
LDFLAGS = -Lhost-native
SYN68K_CFLAGS = -O2 -fomit-frame-pointer
endif
#-----------------------------------------------------------------
#Makefile.common.i486-linux-elf-debug
#-----------------------------------------------------------------
ifeq "$(SYN68K_TARGET)" "i486-linux-elf-debug"
CFLAGS = -g -Wall -I$(INCLUDE_DIR) $(LOCAL_CFLAGS)
LIB_CFLAGS = -g -Wall -I$(INCLUDE_DIR) $(LOCAL_CFLAGS) -D__CHECKER__
OPTIMIZE = ./i486-optimize.pl
CLEANUP = ./i486-cleanup.pl
LDFLAGS = -Lhost-native
SYN68K_CFLAGS = $(LIB_CFLAGS)
endif
#-----------------------------------------------------------------
#Makefile.common.i486-linux-glibc-nonnative
#-----------------------------------------------------------------
ifeq "$(SYN68K_TARGET)" "i486-linux-glibc-nonnative"
LIB_CFLAGS = -g -Wall -I$(INCLUDE_DIR) $(LOCAL_CFLAGS) -D__CHECKER__
OFILE_DIR = obj/i486-linux-glibc-nonnative
LIBDIR = $(topdir)/lib/i486-linux-glibc-nonnative
HOSTCPU = i486-linux-elf
# OPTIMIZE = ./i486-optimize.pl
# CLEANUP = ./i486-cleanup.pl
# LDFLAGS = -Lhost-native
SYN68K_CFLAGS = -O
host-native=native/null
NO_NATIVE = TRUE
endif
#-----------------------------------------------------------------
#Makefile.common.i486-linux-glibc
#-----------------------------------------------------------------
var_host=@host_alias@
ifeq "$(var_host)" ""
LIB_CFLAGS = -O2 -g -Wall -I$(INCLUDE_DIR) $(LOCAL_CFLAGS)
LIB_CC = @CC@
LIB_CFLAGS = -O6 -finline-functions -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
CLEANUP = ./i486-cleanup.pl
OPTIMIZE = ./i486-optimize.pl
SYN68K_CFLAGS = -O2 -fomit-frame-pointer
endif
#-----------------------------------------------------------------
#Makefile.common.i486-linux-glibc-ccr8
#-----------------------------------------------------------------
# NOTE: we define __CHECKER__ so that we get a frame pointer and other
# good stuff. We're not actually using checker. D'oh.
ifeq "$(SYN68K_TARGET)" "i486-linux-glibc-ccr8"
LIB_CFLAGS = -g -I$(INCLUDE_DIR) $(LOCAL_CFLAGS) -D__CHECKER__ -DNO_FAST_CC_FUNCS
# OPTIMIZE = ./i486-optimize.pl
CLEANUP = ./i486-cleanup.pl
LDFLAGS = -Lhost-native
SYN68K_CFLAGS = $(LIB_CFLAGS) -O
endif
#-----------------------------------------------------------------
#Makefile.common.i486-linux-glibc-debug
#-----------------------------------------------------------------
# NOTE: we define __CHECKER__ so that we get a frame pointer and other
# good stuff. We're not actually using checker. D'oh.
ifeq "$(SYN68K_TARGET)" "i486-linux-glibc-debug"
LIB_CFLAGS = -g -I$(INCLUDE_DIR) $(LOCAL_CFLAGS) -D__CHECKER__
# OPTIMIZE = ./i486-optimize.pl
CLEANUP = ./i486-cleanup.pl
LDFLAGS = -Lhost-native
SYN68K_CFLAGS = $(LIB_CFLAGS)
endif
#-----------------------------------------------------------------
#Makefile.common.i486-linux-glibc-nonnative
#-----------------------------------------------------------------
ifeq "$(SYN68K_TARGET)" "i486-linux-glibc-nonnative"
CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS) -D__CHECKER__ -DNONNATIVE
LIB_CFLAGS = -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS) -D__CHECKER__ -DNONNATIVE
# OPTIMIZE = ./i486-optimize.pl
CLEANUP = ./i486-cleanup.pl
# LDFLAGS = -Lhost-native
SYN68K_CFLAGS = -DNONNATIVE -g -D__CHECKER__
host-native=native/null
NO_NATIVE = TRUE
endif
#-----------------------------------------------------------------
#Makefile.common.i486-linux-glibc-slowccr
#-----------------------------------------------------------------
# NOTE: we define __CHECKER__ so that we get a frame pointer and other
# good stuff. We're not actually using checker. D'oh.
ifeq "$(SYN68K_TARGET)" "i486-linux-glibc-slowccr"
LIB_CFLAGS = -g -I$(INCLUDE_DIR) $(LOCAL_CFLAGS) -D__CHECKER__ -DNO_CCR_SPEEDUPS
# OPTIMIZE = ./i486-optimize.pl
CLEANUP = ./i486-cleanup.pl
LDFLAGS = -Lhost-native
SYN68K_CFLAGS = $(LIB_CFLAGS) -O
endif
#-----------------------------------------------------------------
#Makefile.common.i486-linux-slam
#-----------------------------------------------------------------
ifeq "$(SYN68K_TARGET)" "i486-linux-slam"
LIB_CC = checkergcc
LIB_CFLAGS = -g -I$(INCLUDE_DIR) $(LOCAL_CFLAGS)
SYN68K_FLAGS = $(LIB_CFLAGS)
OFILE_DIR = obj/i486-linux
LIBDIR = $(topdir)/lib/i486-linux
HOSTCPU = i486-linux
AR = /usr/local/lib/checker/ar
RANLIB = /usr/local/lib/checker/ranlib
# don't optimize syn68k.s when compiling with checker
# OPTIMIZE = ./i486-optimize.pl
CLEANUP = ./i486-cleanup.pl
LDFLAGS = -Lhost-native
SYN68K_CFLAGS =
endif
#-----------------------------------------------------------------
#Makefile.common.i486-pc-new-cygwin32
#-----------------------------------------------------------------
ifeq "$(SYN68K_TARGET)" "i486-pc-new-cygwin32"
CC = gcc -m486
LIB_CC = i486-pc-cygwin32-gcc -m486 -I/usr/local/i486-pc-cygwin32/include/mingw32
LIB_CFLAGS = -O6 -finline-functions -g -Wall -I$(INCLUDE_DIR) $(LOCAL_CFLAGS)
AR = ar
AS = i486-pc-cygwin32-gcc -x assembler
RANLIB = i486-pc-cygwin32-ranlib
CLEANUP = ./i486-cleanup.pl
OPTIMIZE = ./i486-optimize.pl
SYN68K_CFLAGS = -O2 -fomit-frame-pointer
endif
#-----------------------------------------------------------------
#Makefile.common.i486-pc-new-cygwin32-debug
#-----------------------------------------------------------------
# NOTE: we define __CHECKER__ so that we get a frame pointer and other
# good stuff. We're not actually using checker. D'oh.
ifeq "$(SYN68K_TARGET)" "i486-pc-new-cygwin32-debug"
CC = gcc -m486
LIB_CC = i486-pc-cygwin32-gcc -m486 -I/usr/local/i486-pc-cygwin32/include/mingw32
LIB_CFLAGS = -g -I$(INCLUDE_DIR) $(LOCAL_CFLAGS) -D__CHECKER__
AR = ar
AS = i486-pc-cygwin32-gcc -x assembler
RANLIB = i486-pc-cygwin32-ranlib
CLEANUP = ./i486-cleanup.pl
# OPTIMIZE = ./i486-optimize.pl
SYN68K_CFLAGS = $(LIB_CFLAGS) -O
LDFLAGS = -Lhost-native
endif
#-----------------------------------------------------------------
#Makefile.common.i486-next-ns3
#-----------------------------------------------------------------
ifeq "$(SYN68K_TARGET)" "i486-next-ns3"
LIB_CFLAGS = -O2 -g -Wall -I$(INCLUDE_DIR) $(LOCAL_CFLAGS)
RANLIB = /bin/ranlib
OPTIMIZE = ./i486-optimize.pl
CLEANUP = ./i486-cleanup.pl
LDFLAGS =
SYN68K_CFLAGS = -O2 -fomit-frame-pointer
endif
#-----------------------------------------------------------------
#Makefile.common.i586-cygwin32
#-----------------------------------------------------------------
ifeq "$(SYN68K_TARGET)" "i586-cygwin32"
CC = gcc -m486
LIB_CC = i586-cygwin32-gcc -m486
LIB_CFLAGS = -O2 -g -Wall -I$(INCLUDE_DIR) $(LOCAL_CFLAGS)
AR = ar
AS = i586-cygwin32-gcc -x assembler
RANLIB = i586-cygwin32-ranlib
CLEANUP = ./i486-cleanup.pl
OPTIMIZE = ./i486-optimize.pl
SYN68K_CFLAGS = -O2 -fomit-frame-pointer
endif
#-----------------------------------------------------------------
#Makefile.common.i586-cygwin32-debug
#-----------------------------------------------------------------
ifeq "$(SYN68K_TARGET)" "i586-cygwin32-debug"
CC = gcc -m486
LIB_CC = i486-pc-cygwin32-gcc -m486
LIB_CFLAGS = -g -Wall -I$(INCLUDE_DIR) $(LOCAL_CFLAGS) -D__CHECKER__
AR = ar
AS = i486-pc-cygwin32-gcc -x assembler
RANLIB = i486-pc-cygwin32-ranlib
CLEANUP = ./i486-cleanup.pl
OPTIMIZE = ./i486-optimize.pl
SYN68K_CFLAGS = -O
endif
#-----------------------------------------------------------------
#Makefile.common.i860
#-----------------------------------------------------------------
ifeq "$(SYN68K_TARGET)" "i860"
OFILE_DIR = obj/i860
LIBDIR = ../lib/i860
LIBS = -L/usr/ucblib -lucb
HOSTCPU = i860
endif
#-----------------------------------------------------------------
#Makefile.common.m68k-next-ns3
#-----------------------------------------------------------------
ifeq "$(SYN68K_TARGET)" "m68k-next-ns3"
LIB_CFLAGS = -O2 -g -Wall -I$(INCLUDE_DIR) $(LOCAL_CFLAGS)
RANLIB = /bin/ranlib -c
host-native=native/null
endif
#-----------------------------------------------------------------
#Makefile.common.powerpc-linux-glibc
#-----------------------------------------------------------------
# NOTE: we define __CHECKER__ so that we get a frame pointer and other
# good stuff. We're not actually using checker. D'oh.
ifeq "$(SYN68K_TARGET)" "powerpc-linux-glibc"
LIB_CFLAGS = -O2 -g -Wall -I$(INCLUDE_DIR) $(LOCAL_CFLAGS)
# OPTIMIZE = ./powerpc-optimize.pl
# CLEANUP = ./powerpc-cleanup.pl
# LDFLAGS = -Lhost-native
SYN68K_CFLAGS = $(LIB_CFLAGS) -O2 -fomit-frame-pointer
NO_NATIVE = TRUE
endif
#-----------------------------------------------------------------
#Makefile.common.powerpc-linux-glibc-debug
#-----------------------------------------------------------------
# NOTE: we define __CHECKER__ so that we get a frame pointer and other
# good stuff. We're not actually using checker. D'oh.
ifeq "$(SYN68K_TARGET)" "powerpc-linux-glibc-debug"
LIB_CFLAGS = -g -I$(INCLUDE_DIR) $(LOCAL_CFLAGS) -D__CHECKER__
OFILE_DIR = obj/powerpc-linux-glibc-debug
LIBDIR = $(topdir)/lib/powerpc-linux-glibc-debug
HOSTCPU = powerpc-linux-elf-debug
# OPTIMIZE = ./powerpc-optimize.pl
# CLEANUP = ./powerpc-cleanup.pl
# LDFLAGS = -Lhost-native
SYN68K_CFLAGS = $(LIB_CFLAGS) -O
NO_NATIVE = TRUE
endif
#-----------------------------------------------------------------
#Makefile.common.i386-pc-mingw32
#-----------------------------------------------------------------
#ifeq "$(SYN68K_TARGET)" "i386-pc-mingw32"
#LIB_CC = i386-pc-mingw32-gcc
#LIB_CFLAGS = -O6 -finline-functions -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
#AR = ar
#AS = i386-pc-mingw32-gcc -x assembler
#RANLIB = i386-pc-mingw32-ranlib
#CLEANUP = ./i486-cleanup.pl
#OPTIMIZE = ./i486-optimize.pl
#SYN68K_CFLAGS = -O2 -fomit-frame-pointer
#endif
#---
var_host_os=@host_os@
ifeq "$(var_host_os)" "mingw32"
LIB_CC = @host@-gcc
LIB_CFLAGS = -O6 -finline-functions -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
AR = ar
AS = i386-pc-mingw32-gcc -x assembler
RANLIB = @host@-ranlib
CLEANUP = ./i486-cleanup.pl
OPTIMIZE = ./i486-optimize.pl
SYN68K_CFLAGS = -O2 -fomit-frame-pointer
endif

6
NEWS Normal file
View File

@ -0,0 +1,6 @@
$Id: NEWS 74 2004-12-30 03:38:55Z ctm $
Syn68k now uses automake for all the Makefiles, but we do enough
things on our own that we're not getting proper dependency tracking
and most likely make clean doesn't work as well as it could.

6
README Normal file
View File

@ -0,0 +1,6 @@
$Id: README 77 2005-01-04 23:51:13Z ctm $
Syn68k has not been actively worked on for about ten years. A few
mods have been made here and there to keep up with changes in gcc.

41
TODO Normal file
View File

@ -0,0 +1,41 @@
$Id: TODO 77 2005-01-04 23:51:13Z ctm $
Make it so that we can install libsyn68k.a and the .h files
Make so we can build the various debug versions, non-native, etc.
Figure out exactly which variables Makefile.common.in sets, then
get rid of Makefile.common.in
see TODO.variables
figure out what to do concerning bswap
Look into what else from syn68k we can delete
Makefile.common.in
config
Make sure make clean really does a make clean
Make sure we get proper dependencies (if possible)
make sure syn68k builds on a powerpc (either the
old yellow dog linux on sybil, or on Mac OS X on sybil)
non-native
figure out *exactly* which options should be available
via configure
clean the junk out of test (mostly old test results)
build some semi-canonical test results to use for
comparing on other platforms
write-up what is needed to do testing on a real m68k
need a .spec file so we can build syn68k and syn68k-devel
RPMS

42
TODO.variables Normal file
View File

@ -0,0 +1,42 @@
$Id: TODO.variables 55 2004-12-16 22:00:22Z ctm $
These are some rough notes associated with Makefile.common. These notes should
go away after syn68k is fully transitioned to using the GNU build system
NOTE: Need to know the difference between the cross-compiler and the
local compiler
AR
AS
RANLIB
CC should probably be CC_FOR_BUILD
CFLAGS should probably be CFLAGS_FOR_BUILD
CLEANUP i486-cleanup.pl, if we're x86 and we don't have no-native set
OPTIMIZE i486-optimize.pl, if we're x86 and we don't have no-native set
HOSTCPU UNUSED
INCLUDE_DIR
LDFLAGS
LIBDIR
LIBS
LIB_CC should probably be CC
LIB_CFLAGS should probably be LIB_CFLAGS
NO_NATIVE
OFILE_DIR
SYN68K_CFLAGS
SYN68K_TARGET
host-native
var_host
var_host_os

10
autogen.sh Executable file
View File

@ -0,0 +1,10 @@
#! /bin/bash
# $Id: autogen.sh 65 2004-12-24 19:51:17Z ctm $
set -o errexit -o nounset -o noclobber
aclocal
autoheader
automake --add-missing
autoconf

View File

@ -0,0 +1,24 @@
CC = gcc
CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
LIB_CC = gcc
LIB_CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
# NOTE: QUADALIGN DOESN'T WORK RIGHT NOW
# LIB_CFLAGS = -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS) -DQUADALIGN
OFILE_DIR = obj/alpha-redhat-linux
LIBDIR = $(topdir)/lib/alpha-redhat-linux
LIBS =
HOSTCPU = alpha-redhat-linux
RANLIB = /usr/bin/ranlib
# OPTIMIZE = ./i486-optimize.pl
# CLEANUP = ./i486-cleanup.pl
# LDFLAGS = -Lhost-native
# LDFLAGS = -taso
SYN68K_CFLAGS = $(LIB_CFLAGS) -O2 -fomit-frame-pointer
# SYN68K_CFLAGS = -g -Wall -DQUADALIGN
NO_NATIVE = TRUE

View File

@ -0,0 +1,7 @@
CC = cc
OFILE_DIR = obj/alpha
LIBDIR = ../lib/alpha
LIBS =
HOSTCPU = alpha
RANLIB = /bin/ranlib
LDFLAGS = -taso

View File

@ -0,0 +1,18 @@
CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
LIB_CC = i386-msdos-go32-gcc -m486
LIB_CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
OFILE_DIR = obj/i386-msdos-go32
LIBDIR = $(topdir)/lib/i386-msdos-go32
LIBS =
HOSTCPU = i386-msdos-go32
AR = ar
AS = i386-msdos-go32-gcc -x assembler
RANLIB = ranlib
LDFLAGS = -Ttext 0 -Tdata 200000
CLEANUP = ./i486-cleanup.pl
OPTIMIZE = ./i486-optimize.pl
SYN68K_CFLAGS = -O2 -fomit-frame-pointer

View File

@ -0,0 +1,17 @@
CC = gcc
CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
LIB_CC = gcc
LIB_CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
OFILE_DIR = obj/i386-next-mach-o
LIBDIR = $(topdir)/lib/i386-next-mach-o
LIBS =
HOSTCPU = i386-next-mach-o
RANLIB = /bin/ranlib
OPTIMIZE = ./i486-optimize.pl
CLEANUP = ./i486-cleanup.pl
LDFLAGS =
SYN68K_CFLAGS = -O2 -fomit-frame-pointer

View File

@ -0,0 +1,17 @@
CC = gcc
CFLAGS = -static -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
LIB_CC = gcc
LIB_CFLAGS = -static -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
OFILE_DIR = obj/i386-next-mach-o
LIBDIR = $(topdir)/lib/i386-next-mach-o
LIBS =
HOSTCPU = i386-next-mach-o
RANLIB = /bin/ranlib
OPTIMIZE = ./i486-optimize.pl
CLEANUP = ./i486-cleanup.pl
LDFLAGS =
SYN68K_CFLAGS = -O2 -fomit-frame-pointer

View File

@ -0,0 +1,18 @@
CC = gcc
CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
LIB_CC = i386-pc-mingw32-gcc
LIB_CFLAGS = -O6 -finline-functions -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
OFILE_DIR = obj/i386-pc-mingw32
LIBDIR = $(topdir)/lib/i386-pc-mingw32
LIBS =
HOSTCPU = i386-pc-mingw32
AR = ar
AS = i386-pc-mingw32-gcc -x assembler
RANLIB = i386-pc-mingw32-ranlib
CLEANUP = ./i486-cleanup.pl
OPTIMIZE = ./i486-optimize.pl
SYN68K_CFLAGS = -O2 -fomit-frame-pointer

View File

@ -0,0 +1,18 @@
CC = gcc -m486
CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
LIB_CC = i486-pc-cygwin32-gcc -m486
LIB_CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS) -Dfree=free_hack
OFILE_DIR = obj/i486-pc-cygwin32
LIBDIR = $(topdir)/lib/i486-pc-cygwin32
LIBS =
HOSTCPU = i486-pc-cygwin32
AR = ar
AS = i486-pc-cygwin32-gcc -x assembler
RANLIB = i486-pc-cygwin32-ranlib
CLEANUP = ./i486-cleanup.pl
OPTIMIZE = ./i486-optimize.pl
SYN68K_CFLAGS = -O2 -fomit-frame-pointer -Dfree=free_hack

View File

@ -0,0 +1,21 @@
# NOTE: we define __CHECKER__ so that we get a frame pointer and other
# good stuff. We're not actually using checker. D'oh.
CC = gcc -m486
CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
LIB_CC = i486-pc-cygwin32-gcc -m486
LIB_CFLAGS = -g -I$(topdir)/include $(LOCAL_CFLAGS) -D__CHECKER__ -Dfree=free_hack
OFILE_DIR = obj/i486-pc-cygwin32-debug
LIBDIR = $(topdir)/lib/i486-pc-cygwin32-debug
LIBS =
HOSTCPU = i486-pc-cygwin32-debug
AR = ar
AS = i486-pc-cygwin32-gcc -x assembler
RANLIB = i486-pc-cygwin32-ranlib
CLEANUP = ./i486-cleanup.pl
# OPTIMIZE = ./i486-optimize.pl
SYN68K_CFLAGS = $(LIB_CFLAGS) -O
LDFLAGS = -Lhost-native

View File

@ -0,0 +1,17 @@
CC = gcc
CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
LIB_CC = gcc -b i486-linuxaout
LIB_CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
OFILE_DIR = obj/i486-linux-a.out
LIBDIR = $(topdir)/lib/i486-linux-a.out
LIBS =
HOSTCPU = i486-linux-a.out
RANLIB = /usr/bin/ranlib
OPTIMIZE = ./i486-optimize.pl
CLEANUP = ./i486-cleanup.pl
LDFLAGS = -Lhost-native
SYN68K_CFLAGS = -O2 -fomit-frame-pointer

View File

@ -0,0 +1,23 @@
# NOTE: we define __CHECKER__ so that we get a frame pointer and other
# good stuff. We're not actually using checker. D'oh.
CC = gcc
CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
LIB_CC = gcc -b i486-linuxaout
LIB_CFLAGS = -g -I$(topdir)/include $(LOCAL_CFLAGS) -D__CHECKER__
SYN68K_CFLAGS = $(LIB_CFLAGS) -O
OFILE_DIR = obj/i486-linux-debug
LIBDIR = $(topdir)/lib/i486-linux-debug
LIBS =
HOSTCPU = i486-linux-debug
AR = ar
RANLIB = ranlib
# don't optimize syn68k.s when compiling with checker
# OPTIMIZE = ./i486-optimize.pl
CLEANUP = ./i486-cleanup.pl
LDFLAGS = -Lhost-native

View File

@ -0,0 +1,17 @@
CC = gcc
CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
LIB_CC = gcc
LIB_CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
OFILE_DIR = obj/i486-linux-elf
LIBDIR = $(topdir)/lib/i486-linux-elf
LIBS =
HOSTCPU = i486-linux-elf
RANLIB = /usr/bin/ranlib
OPTIMIZE = ./i486-optimize.pl
CLEANUP = ./i486-cleanup.pl
LDFLAGS = -Lhost-native
SYN68K_CFLAGS = -O2 -fomit-frame-pointer

View File

@ -0,0 +1,20 @@
CC = gcc
CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
LIB_CC = gcc
LIB_CFLAGS = -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS) -D__CHECKER__
OFILE_DIR = obj/i486-linux-elf-nonnative
LIBDIR = $(topdir)/lib/i486-linux-elf-nonnative
LIBS =
HOSTCPU = i486-linux-elf
RANLIB = /usr/bin/ranlib
# OPTIMIZE = ./i486-optimize.pl
# CLEANUP = ./i486-cleanup.pl
# LDFLAGS = -Lhost-native
SYN68K_CFLAGS = -O
NO_NATIVE = TRUE

View File

@ -0,0 +1,17 @@
CC = gcc
CFLAGS = -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
LIB_CC = gcc
LIB_CFLAGS = -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS) -D__CHECKER__
OFILE_DIR = obj/i486-linux-elf-debug
LIBDIR = $(topdir)/lib/i486-linux-elf-debug
LIBS =
HOSTCPU = i486-linux-elf-debug
RANLIB = /usr/bin/ranlib
OPTIMIZE = ./i486-optimize.pl
CLEANUP = ./i486-cleanup.pl
LDFLAGS = -Lhost-native
SYN68K_CFLAGS = $(LIB_CFLAGS)

View File

@ -0,0 +1,18 @@
CC = gcc
CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
LIB_CC = gcc
LIB_CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
OFILE_DIR = obj/i486-linux-glibc
LIBDIR = $(topdir)/lib/i486-linux-glibc
LIBS =
HOSTCPU = i486-linux-glibc
RANLIB = /usr/bin/ranlib
OPTIMIZE = ./i486-optimize.pl
CLEANUP = ./i486-cleanup.pl
LDFLAGS = -Lhost-native
SYN68K_CFLAGS = -O2 -fomit-frame-pointer

View File

@ -0,0 +1,19 @@
# NOTE: we define __CHECKER__ so that we get a frame pointer and other
# good stuff. We're not actually using checker. D'oh.
CC = gcc
CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
LIB_CC = gcc
LIB_CFLAGS = -g -I$(topdir)/include $(LOCAL_CFLAGS) -D__CHECKER__ -DNO_FAST_CC_FUNCS
OFILE_DIR = obj/i486-linux-glibc-ccr8
LIBDIR = $(topdir)/lib/i486-linux-glibc-ccr8
LIBS =
HOSTCPU = i486-linux-glibc-ccr8
RANLIB = /usr/bin/ranlib
# OPTIMIZE = ./i486-optimize.pl
CLEANUP = ./i486-cleanup.pl
LDFLAGS = -Lhost-native
SYN68K_CFLAGS = $(LIB_CFLAGS) -O

View File

@ -0,0 +1,19 @@
# NOTE: we define __CHECKER__ so that we get a frame pointer and other
# good stuff. We're not actually using checker. D'oh.
CC = gcc
CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
LIB_CC = gcc
LIB_CFLAGS = -g -I$(topdir)/include $(LOCAL_CFLAGS) -D__CHECKER__
OFILE_DIR = obj/i486-linux-glibc-debug
LIBDIR = $(topdir)/lib/i486-linux-glibc-debug
LIBS =
HOSTCPU = i486-linux-glibc-debug
RANLIB = /usr/bin/ranlib
# OPTIMIZE = ./i486-optimize.pl
CLEANUP = ./i486-cleanup.pl
LDFLAGS = -Lhost-native
SYN68K_CFLAGS = $(LIB_CFLAGS)

View File

@ -0,0 +1,20 @@
CC = gcc
CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS) -D__CHECKER__ -DNONNATIVE
LIB_CC = gcc
LIB_CFLAGS = -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS) -D__CHECKER__ -DNONNATIVE
OFILE_DIR = obj/i486-linux-glibc-nonnative
LIBDIR = $(topdir)/lib/i486-linux-glibc-nonnative
LIBS =
HOSTCPU = i486-linux-glibc
RANLIB = /usr/bin/ranlib
# OPTIMIZE = ./i486-optimize.pl
CLEANUP = ./i486-cleanup.pl
# LDFLAGS = -Lhost-native
SYN68K_CFLAGS = -DNONNATIVE -g -D__CHECKER__
NO_NATIVE = TRUE

View File

@ -0,0 +1,19 @@
# NOTE: we define __CHECKER__ so that we get a frame pointer and other
# good stuff. We're not actually using checker. D'oh.
CC = gcc
CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
LIB_CC = gcc
LIB_CFLAGS = -g -I$(topdir)/include $(LOCAL_CFLAGS) -D__CHECKER__ -DNO_CCR_SPEEDUPS
OFILE_DIR = obj/i486-linux-glibc-slowccr
LIBDIR = $(topdir)/lib/i486-linux-glibc-slowccr
LIBS =
HOSTCPU = i486-linux-glibc-slowccr
RANLIB = /usr/bin/ranlib
# OPTIMIZE = ./i486-optimize.pl
CLEANUP = ./i486-cleanup.pl
LDFLAGS = -Lhost-native
SYN68K_CFLAGS = $(LIB_CFLAGS) -O

View File

@ -0,0 +1,25 @@
CC = gcc
CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
LIB_CC = checkergcc
LIB_CFLAGS = -g -I$(topdir)/include $(LOCAL_CFLAGS)
SYN68K_FLAGS = $(LIB_CFLAGS)
OFILE_DIR = obj/i486-linux
LIBDIR = $(topdir)/lib/i486-linux
LIBS =
HOSTCPU = i486-linux
AR = /usr/local/lib/checker/ar
RANLIB = /usr/local/lib/checker/ranlib
# don't optimize syn68k.s when compiling with checker
# OPTIMIZE = ./i486-optimize.pl
CLEANUP = ./i486-cleanup.pl
LDFLAGS = -Lhost-native
SYN68K_CFLAGS =

View File

@ -0,0 +1,18 @@
CC = gcc -m486
CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
LIB_CC = i486-pc-cygwin32-gcc -m486 -I/usr/local/i486-pc-cygwin32/include/mingw32
LIB_CFLAGS = -O6 -finline-functions -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
OFILE_DIR = obj/i486-pc-new-cygwin32
LIBDIR = $(topdir)/lib/i486-pc-new-cygwin32
LIBS =
HOSTCPU = i486-pc-new-cygwin32
AR = ar
AS = i486-pc-cygwin32-gcc -x assembler
RANLIB = i486-pc-cygwin32-ranlib
CLEANUP = ./i486-cleanup.pl
OPTIMIZE = ./i486-optimize.pl
SYN68K_CFLAGS = -O2 -fomit-frame-pointer

View File

@ -0,0 +1,21 @@
# NOTE: we define __CHECKER__ so that we get a frame pointer and other
# good stuff. We're not actually using checker. D'oh.
CC = gcc -m486
CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
LIB_CC = i486-pc-cygwin32-gcc -m486 -I/usr/local/i486-pc-cygwin32/include/mingw32
LIB_CFLAGS = -g -I$(topdir)/include $(LOCAL_CFLAGS) -D__CHECKER__
OFILE_DIR = obj/i486-pc-new-cygwin32-debug
LIBDIR = $(topdir)/lib/i486-pc-new-cygwin32-debug
LIBS =
HOSTCPU = i486-pc-new-cygwin32-debug
AR = ar
AS = i486-pc-cygwin32-gcc -x assembler
RANLIB = i486-pc-cygwin32-ranlib
CLEANUP = ./i486-cleanup.pl
# OPTIMIZE = ./i486-optimize.pl
SYN68K_CFLAGS = $(LIB_CFLAGS) -O
LDFLAGS = -Lhost-native

View File

@ -0,0 +1,17 @@
CC = gcc
CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
LIB_CC = gcc
LIB_CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
OFILE_DIR = obj/i486-next-ns3
LIBDIR = $(topdir)/lib/i486-next-ns3
LIBS =
HOSTCPU = i486-next-ns3
RANLIB = /bin/ranlib
OPTIMIZE = ./i486-optimize.pl
CLEANUP = ./i486-cleanup.pl
LDFLAGS =
SYN68K_CFLAGS = -O2 -fomit-frame-pointer

View File

@ -0,0 +1,18 @@
CC = gcc -m486
CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
LIB_CC = i586-cygwin32-gcc -m486
LIB_CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
OFILE_DIR = obj/i586-cygwin32
LIBDIR = $(topdir)/lib/i586-cygwin32
LIBS =
HOSTCPU = i586-cygwin32
AR = ar
AS = i586-cygwin32-gcc -x assembler
RANLIB = i586-cygwin32-ranlib
CLEANUP = ./i486-cleanup.pl
OPTIMIZE = ./i486-optimize.pl
SYN68K_CFLAGS = -O2 -fomit-frame-pointer

View File

@ -0,0 +1,18 @@
CC = gcc -m486
CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
LIB_CC = i486-pc-cygwin32-gcc -m486
LIB_CFLAGS = -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS) -D__CHECKER__
OFILE_DIR = obj/i586-cygwin32-debug
LIBDIR = $(topdir)/lib/i586-cygwin32-debug
LIBS =
HOSTCPU = i586-cygwin32-debug
AR = ar
AS = i486-pc-cygwin32-gcc -x assembler
RANLIB = i486-pc-cygwin32-ranlib
CLEANUP = ./i486-cleanup.pl
OPTIMIZE = ./i486-optimize.pl
SYN68K_CFLAGS = -O

View File

@ -0,0 +1,5 @@
CC = gcc
OFILE_DIR = obj/i860
LIBDIR = ../lib/i860
LIBS = -L/usr/ucblib -lucb
HOSTCPU = i860

View File

@ -0,0 +1,13 @@
CC = gcc
CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
LIB_CC = gcc
LIB_CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
OFILE_DIR = obj/m68k-next-ns3
LIBDIR = $(topdir)/lib/m68k-next-ns3
LIBS =
RANLIB = /bin/ranlib -c
HOSTCPU = m68k-next-ns3

View File

@ -0,0 +1,21 @@
# NOTE: we define __CHECKER__ so that we get a frame pointer and other
# good stuff. We're not actually using checker. D'oh.
CC = gcc
CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
LIB_CC = gcc
LIB_CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
OFILE_DIR = obj/powerpc-linux-glibc
LIBDIR = $(topdir)/lib/powerpc-linux-glibc
LIBS =
HOSTCPU = powerpc-linux-glibc
RANLIB = /usr/bin/ranlib
# OPTIMIZE = ./powerpc-optimize.pl
# CLEANUP = ./powerpc-cleanup.pl
# LDFLAGS = -Lhost-native
SYN68K_CFLAGS = $(LIB_CFLAGS) -O2 -fomit-frame-pointer
NO_NATIVE = TRUE

View File

@ -0,0 +1,21 @@
# NOTE: we define __CHECKER__ so that we get a frame pointer and other
# good stuff. We're not actually using checker. D'oh.
CC = gcc
CFLAGS = -O2 -g -Wall -I$(topdir)/include $(LOCAL_CFLAGS)
LIB_CC = gcc
LIB_CFLAGS = -g -I$(topdir)/include $(LOCAL_CFLAGS) -D__CHECKER__
OFILE_DIR = obj/powerpc-linux-glibc-debug
LIBDIR = $(topdir)/lib/powerpc-linux-glibc-debug
LIBS =
HOSTCPU = powerpc-linux-elf-debug
RANLIB = /usr/bin/ranlib
# OPTIMIZE = ./powerpc-optimize.pl
# CLEANUP = ./powerpc-cleanup.pl
# LDFLAGS = -Lhost-native
SYN68K_CFLAGS = $(LIB_CFLAGS) -O
NO_NATIVE = TRUE

143
configure.ac Normal file
View File

@ -0,0 +1,143 @@
# $Id: configure.ac 72 2004-12-28 15:57:12Z ctm $
AC_INIT(syn68k, 1.0, ctm@ardi.com)
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([syngen/main.c])
AC_CONFIG_HEADER([config.h])
# Checks for programs.
AC_PROG_CC
AC_PROG_RANLIB
AM_PROG_AS
AC_CHECK_PROG([PERL], [perl], [perl])
AC_ARG_VAR([PERL], [perl for preening assembly])
#SUBDIRS="syngen runtime test profile"
#configdirs="syngen runtime test profile"
AC_CANONICAL_BUILD
AC_CANONICAL_HOST
AC_MSG_CHECKING([(non-cross) C compiler for building tools])
if test "$cross_compiling" = "yes"; then
CC_FOR_BUILD="${CC_FOR_BUILD-gcc}"
else
CC_FOR_BUILD="${CC_FOR_BUILD-$CC}"
fi
AC_MSG_RESULT([$CC_FOR_BUILD])
AC_ARG_VAR(CC_FOR_BUILD,[C compiler for building tools])
CFLAGS_FOR_BUILD="${CFLAGS_FOR_BUILD-}"
AC_ARG_VAR(CFLAGS_FOR_BUILD,[C flags for building tools])
AC_MSG_CHECKING([Syn68k C flags (TODO: FIXME)])
SYN68K_CFLAGS="${SYN68K_CFLAGS--O2 -fomit-frame-pointer}"
AC_MSG_RESULT([$SYN68K_CFLAGS])
AC_ARG_VAR(SYN68K_CFLAGS,[Syn68k C flags (TODO: FIXME)])
AC_MSG_CHECKING([cleanup script])
CLEANUP="${CLEANUP-./i486-cleanup.pl}"
AC_MSG_RESULT([$CLEANUP])
AC_ARG_VAR(CLEANUP,[cleanup script])
AC_MSG_CHECKING([optimization script])
OPTIMIZE="${OPTIMIZE-./i486-optimize.pl}"
AC_MSG_RESULT([$OPTIMIZE])
AC_ARG_VAR(OPTIMIZE,[optimization script])
if test "$host_alias" = ""; then
host=i486-linux-glibc
fi
case $host_cpu in
i?86)
host_cpu_class=i386;;
*)
host_cpu_class=$host_cpu;;
esac
AC_SUBST(host_cpu_class)
HOST_NATIVE="native/i386"
AC_SUBST(HOST_NATIVE)
AC_ARG_ENABLE([native],
AC_HELP_STRING([--enable-native],
[native or nonnative (default is native)]),
[var_native=$enable_native], [var_native=no] )
if test "$var_native" = "yes"; then
NO_NATIVE=TRUE
else
NO_NATIVE=FALSE
fi
AC_SUBST(NO_NATIVE)
AC_ARG_ENABLE([debug],
AC_HELP_STRING([--enable-debug],
[use debug -g (default is yes)]),
[var_debug=$enable_debug] ,[var_debug=yes] )
if test "$var_debug" = "no" ; then
DEBUGFLAG=""
else
DEBUGFLAG="-g"
fi
AC_SUBST(DEBUGFLAG)
#AC_MSG_NOTICE([])
AC_ARG_WITH(ccrversion,
[ --with-ccrversion=<ccr8>
Specify ccr version],
[ccrversion=$withval],
[ccrversion]="")
case "$ccrversion" in
ccr8)
CCRFLAG=ccr8 ;;
*)
CCRFLAG="" ;;
esac
# Checks for libraries.
#AC_CHECK_LIB([], [])
# Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS([stddef.h stdlib.h string.h sys/param.h unistd.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_C_INLINE
AC_TYPE_SIZE_T
AC_C_VOLATILE
# Checks for library functions.
AC_FUNC_ALLOCA
AC_FUNC_ERROR_AT_LINE
AC_FUNC_MEMCMP
AC_FUNC_MMAP
AC_FUNC_MALLOC
AC_FUNC_REALLOC
AC_FUNC_VPRINTF
AC_CHECK_FUNCS([getpagesize memmove memset strchr strdup strerror strstr])
#if test -n "$configdirs"; then
# AC_CONFIG_SUBDIRS($configdirs)
#fi
#AC_SUBST(SUBDIRS)
AM_CONDITIONAL([M68K_HOSTCPU], [test "$host_alias" = "m68k-next-ns3"])
AC_CONFIG_FILES([Makefile
syngen/Makefile
test/Makefile
profile/Makefile
runtime/Makefile
runtime/native/i386/Makefile
include/syn68k_private.h])
dnl runtime/native/null/Makefile
AC_OUTPUT

55
include/safe_alloca.h Normal file
View File

@ -0,0 +1,55 @@
#if !defined(__safe_alloca__)
#define __safe_alloca__
#include <assert.h>
#if !defined(NDEBUG)
#define FIREWALL_START 0x940504FE
#define FIREWALL_STOP_0 0xEE
#define FIREWALL_STOP_1 0x41
#define FIREWALL_STOP_2 0x51
#define FIREWALL_STOP_3 0x59
/*
* I don't like this implementation, but it works.
*/
#define SAFE_DECL() \
unsigned long ___newsize; \
unsigned char *___tempptr
#define SAFE_alloca(size) \
( \
___newsize = (size) + 3 * sizeof(long), \
___tempptr = alloca(___newsize), \
((long *)___tempptr)[0] = ___newsize, \
((long *)___tempptr)[1] = FIREWALL_START, \
___tempptr[___newsize-4] = FIREWALL_STOP_0, \
___tempptr[___newsize-3] = FIREWALL_STOP_1, \
___tempptr[___newsize-2] = FIREWALL_STOP_2, \
___tempptr[___newsize-1] = FIREWALL_STOP_3, \
(void *) (___tempptr + 2 * sizeof(long)) \
)
#define ASSERT_SAFE(var) \
do { \
___tempptr = (unsigned char *) (var); \
___tempptr -= 2 * sizeof(long); \
assert(((long *)___tempptr)[1] == FIREWALL_START); \
___newsize = ((long *)___tempptr)[0]; \
assert(___tempptr[___newsize-4] == FIREWALL_STOP_0); \
assert(___tempptr[___newsize-3] == FIREWALL_STOP_1); \
assert(___tempptr[___newsize-2] == FIREWALL_STOP_2); \
assert(___tempptr[___newsize-1] == FIREWALL_STOP_3); \
} while (0)
#else /* defined(NDEBUG) */
#define SAFE_DECL() unsigned long ___newsize
#define SAFE_alloca(size) alloca(size)
#define ASSERT_SAFE(var) do {} while (0)
#endif /* defined(NDEBUG) */
#endif /* !defined(__safe_alloca__) */

290
include/syn68k_private.h.in Normal file
View File

@ -0,0 +1,290 @@
/* This file contains information needed by both the compile time and runtime
* portions of the 68k emulator.
*/
#ifndef _syn68k_private_h_
#define _syn68k_private_h_
/* $Id: syn68k_private.h.in 72 2004-12-28 15:57:12Z ctm $ */
#include "syn68k_public.h"
#include <signal.h>
#define ALL_CCS 0x1F
/* Note: these are _not_ the order in which the bits appear in the ccr.
* For historical reasons, we keep track of them alphabetically.
*/
#define M68K_CC_NONE 0
#define M68K_CCC 0x10
#define M68K_CCN 0x8
#define M68K_CCV 0x4
#define M68K_CCX 0x2
#define M68K_CCZ 0x1
#define M68K_CC_ALL 0x1F
/* Shorthand for some common combinations. */
#define M68K_CC_CNVZ (M68K_CCC | M68K_CCN | M68K_CCV | M68K_CCZ)
#define M68K_CC_CNVXZ (M68K_CCC | M68K_CCN | M68K_CCV | M68K_CCX | M68K_CCZ)
/* For machines with few registers, it is worth our while to put the 68000
* registers into an array and random access them.
*
* It's been a while since this was defined -- if it's not defined, we might
* not be able to build.
*/
# define M68K_REGS_IN_ARRAY
/* If a machine rounds all divisions towards zero and the remainder always
* has the same sign as the dividend, #define this for better speed. It
* should work even if you leave it undefined though. If you have problems
* with divide, try undef'ing this to use the slower but safer version.
*/
#if @host_cpu_class@ == i386 /* ||defined(mc68000) || defined(i386) || defined(__alpha) || defined (powerpc) || defined (__ppc__) */
# define M68K_DIVISION_BEHAVIOR
#endif
#if defined(__alpha)
/* #define TEMPS_AT_TOP */
#endif
/* Use faster threaded code if the needed gcc extensions are present.*/
#if defined (__GNUC__ ) && (__GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 4)) && !defined (NONDIRECT)
# define USE_DIRECT_DISPATCH
#endif
/* #define this if support exists for generating native code in some
* situations.
*/
#if defined (USE_DIRECT_DISPATCH) && @host_cpu_class@ == i386 && !defined (NONNATIVE)
# define GENERATE_NATIVE_CODE
#endif
#if defined (SYNCHRONOUS_INTERRUPTS) && !defined (GENERATE_NATIVE_CODE)
/* This is easy to fix, but I have more pressing things to work on.
* The problem is that, without native code, there is no synthetic opcode
* at the beginning of each block that checks for an interrupt.
* The proper way to rectify this is to return to the good old days
* when all synthetic opcodes that could branch backwards would check
* for an interrupt. With native code, we check at the beginning of
* each block, not on branches (it's much easier that way), so you do
* NOT want to check for interrupts on backwards synthetic branches
* if GENERATE_NATIVE_CODE is defined.
*
* NOTE: I (ctm) fixed this, although I don't guarantee that my fix is
* as fast as Mat's would have been.
*/
#endif
#ifdef USE_DIRECT_DISPATCH
extern const void *direct_dispatch_table[];
#endif
#ifdef SYNCHRONOUS_INTERRUPTS
# define BLOCK_INTERRUPTS(save) (save = 0)
# define RESTORE_INTERRUPTS(save)
#else /* !SYNCHRONOUS_INTERRUPTS */
# ifdef MSDOS
extern int dos_block_interrupts (void);
extern void dos_restore_interrupts (int);
# define BLOCK_INTERRUPTS(save) (save = dos_block_interrupts ())
# define RESTORE_INTERRUPTS(save) dos_restore_interrupts (save)
# else /* Not MSDOS */
# define SIGNALS_TO_BLOCK (sigmask(SIGALRM) | sigmask(SIGURG) \
| sigmask(SIGVTALRM) | sigmask(SIGIO))
# define BLOCK_INTERRUPTS(save) (save = sigblock (SIGNALS_TO_BLOCK));
# define RESTORE_INTERRUPTS(save) sigsetmask (save)
# endif /* Not MSDOS */
#endif /* !SYNCHRONOUS_INTERRUPTS */
/* Data types. */
#if !defined(FALSE) && !defined(TRUE)
typedef enum { FALSE, TRUE, NO = 0, YES = 1 } BOOL;
#else /* defined(FALSE) || defined(TRUE) */
typedef enum { NO = 0, YES = 1 } BOOL;
#endif /* defined(FALSE) || defined(TRUE) */
#ifndef NULL
#define NULL ((void *)0)
#endif
#define PTR_BYTES (sizeof (void *))
#define PTR_WORDS (PTR_BYTES / sizeof (uint16))
#define OPCODE_BYTES PTR_BYTES
#define OPCODE_WORDS PTR_WORDS
/* Many 68k opcodes have useful operands which will not be implicit in the
* synthetic opcode. The translator will extract these operands, translate
* them to a useful form, and place them in the interpreted instruction
* stream (in order). This struct describes both the location of these
* operands in the 68k instruction stream and how to translate them to
* a form useful to the interpreter. Only 32 bit, word aligned bitfields
* are allowed to span multiple words. Note: foo.index == MAGIC_END_INDEX
* && foo.length == MAGIC_END_LENGTH implies the end of the bitfield list.
*/
#define MAGIC_END_INDEX 126
#define MAGIC_END_LENGTH 30
#define IS_TERMINATING_BITFIELD(p) ((p)->index == MAGIC_END_INDEX \
&& (p)->length == MAGIC_END_LENGTH)
typedef struct {
uint16 rev_amode :1; /* If 1, swap high 3 bits w/low 3 bits for 6 bit # */
uint16 index :7; /* # of bits into instruction for this bitfield. */
uint16 length :5; /* Length, in bits, of this bitfield, minus 1. */
uint16 sign_extend :1; /* Boolean: sign extend the resulting number? */
uint16 make_native_endian :1; /* Swap bytes if we're little endian? */
uint16 words :1; /* # of words to expand this number into, minus 1. */
} BitfieldInfo;
#define MAX_BITFIELDS 4
/* This struct contains information needed to map from 68k opcodes to
* synthetic cpu opcodes. Typically you would have one of these structs
* for each cc bit variant of each 68k opcode, although of course the
* point of the design of this structure is that sequences of these can
* be shared by many distinct 68k opcode bit patterns.
*/
typedef struct {
uint32 sequence_parity :1; /* Identifies contiguous blocks of these. */
/* CC bit information. */
uint32 cc_may_set :5; /* CC bits not necessarily left alone. */
uint32 cc_may_not_set :5; /* CC bits not necessarily changed. */
uint32 cc_needed :5; /* CC bits which must be valid for this. */
/* 68k opcode information. */
uint32 instruction_words :4; /* # of 16 bit words taken by 68k opcode. */
uint32 ends_block :1; /* Boolean: does this end a basic block? */
uint32 next_block_dynamic :1; /* Boolean: next block known runtime only. */
/* Are there addressing modes, and did we expand them? */
uint32 amode_size :2; /* 0:none, 1:byte, 2:word, 3:long. */
uint32 reversed_amode_size :2; /* 0:none, 1:byte, 2:word, 3:long. */
uint32 amode_expanded :1; /* If has amode, was it expanded? */
uint32 reversed_amode_expanded :1; /* If has reversed_amode, " " " ? */
/* Bit pattern mapping information. This lets us compute the synthetic
* opcode from the 68k opcode.
*/
uint32 opcode_shift_count :4; /* # of bits by which to >> 68k opcode. */
uint16 opcode_and_bits; /* Mask with which to & 68k opcode. */
uint16 opcode_add_bits; /* Bits to add to 68k opcode. */
/* Actual bitfield extraction/translation information. */
BitfieldInfo bitfield[MAX_BITFIELDS]; /* Bitfields to parse & translate. */
#ifdef GENERATE_NATIVE_CODE
# ifdef SYNGEN
const char *guest_code_descriptor; /* We only know its name here. */
# else /* !SYNGEN */
const struct _guest_code_descriptor_t *guest_code_descriptor;
# endif /* !SYNGEN */
#endif /* GENERATE_NATIVE_CODE */
} OpcodeMappingInfo;
#ifndef QUADALIGN
# define READUL_UNSWAPPED(addr) (*(uint32 *) SYN68K_TO_US(addr))
# define READUL_UNSWAPPED_US(addr) (*(uint32 *) (addr))
#else
# ifdef BIGENDIAN
# define READUL_UNSWAPPED(addr) \
({ const uint16 *_p = (const uint16 *)SYN68K_TO_US(addr); (uint32)(_p[0] << 16) | _p[1]; })
# define READUL_UNSWAPPED_US(addr) \
({ const uint16 *_p = (const uint16 *)(addr); (uint32)(_p[0] << 16) | _p[1]; })
# else
#if defined(__GNUC__)
typedef struct { uint32 l __attribute__((packed)); } hidden_l;
#define READUL_UNSWAPPED(addr) (((hidden_l *)(SYN68K_TO_US(addr)))->l)
#define READUL_UNSWAPPED_US(addr) (((hidden_l *)(addr))->l)
#else
static uint32 _readul_unswapped(const uint16 *p)
{
return (uint32)(p[1] << 16) | p[0];
}
#define READUL_UNSWAPPED(addr) _readul_unswapped((const uint16 *) (SYN68K_TO_US(addr)))
#define READUL_UNSWAPPED_US(addr) _readul_unswapped((const uint16 *) (addr))
#endif
# endif
#endif
#define READSL_UNSWAPPED(addr) ((int32) READUL_UNSWAPPED (addr))
#ifndef QUADALIGN
# define WRITEUL_UNSWAPPED(p,v) (*(uint32 *)(p) = (v))
#else
# ifdef BIGENDIAN
# define WRITEUL_UNSWAPPED(p, v) \
({ \
uint32 _tmp = (v); \
uint16 *_x = (uint16 *)(p); \
_x[0] = _tmp >> 16; \
_x[1] = _tmp; \
_tmp; \
})
# else
#if defined(__GNUC__)
#define WRITEUL_UNSWAPPED(addr, v) (((hidden_l *)(addr))->l = (v))
#else
static uint32 _writeul_unswapped(uint16 *p, uint32 tmp)
{
p[0] = tmp;
p[1] = tmp >> 16;
return tmp;
}
#define WRITEUL_UNSWAPPED(p, v) _writeul_unswapped((uint16 *) (p), (v))
#endif
# endif
#endif
#define WRITESL_UNSWAPPED(p,v) ((int32) WRITEUL_UNSWAPPED (p, v))
/* FIXME - could be more efficient going one byte at a time on
* LITTLEENDIAN QUADALIGN machines.
*/
#define WRITE_LONG(p,v) (WRITEUL_UNSWAPPED ((p), SWAPUL_IFLE (v)))
#define WRITE_WORD(p,v) ((void) (*(uint16 *)(p) = SWAPUW_IFLE (v)))
#ifndef QUADALIGN
# define WRITE_PTR(p,v) (*(char **)(p) = (char *)(v))
#else
# define WRITE_PTR(p,v) \
{ void *ptr = (v); memcpy ((uint16 *)(p), &ptr, sizeof ptr); }
#endif
#define COMPUTE_SR_FROM_CPU_STATE() \
(cpu_state.sr | (cpu_state.ccc != 0) | ((cpu_state.ccv != 0) << 1) \
| ((cpu_state.ccnz == 0) << 2) | ((cpu_state.ccn != 0) << 3) \
| ((cpu_state.ccx != 0) << 4))
#if !defined(__alpha)
#define DEREF(typ, addr) (*(typ *)addr)
#else
typedef struct { int8 n __attribute__((packed)); } HIDDEN_int8;
typedef struct { uint8 n __attribute__((packed)); } HIDDEN_uint8;
typedef struct { int16 n __attribute__((packed)); } HIDDEN_int16;
typedef struct { uint16 n __attribute__((packed)); } HIDDEN_uint16;
typedef struct { int32 n __attribute__((packed)); } HIDDEN_int32;
typedef struct { uint32 n __attribute__((packed)); } HIDDEN_uint32;
#define DEREF(typ, addr) (((HIDDEN_ ## typ *)addr)->n)
#endif
#endif /* Not _syn68k_private_h_ */

681
include/syn68k_public.h Normal file
View File

@ -0,0 +1,681 @@
#if !defined (_syn68k_public_h_)
#define _syn68k_public_h_
/* $Id: syn68k_public.h 83 2005-05-12 02:33:41Z ctm $ */
#include <setjmp.h>
/* Decide whether we are big or little endian here. Add more machines as
* they are supported.
*/
#if !defined(BIGENDIAN) && !defined(LITTLEENDIAN)
# if defined(__BIG_ENDIAN__) || defined(m68k) || defined(mc68000) \
|| defined(sparc) || defined(powerpc) || defined (__ppc__)
# define BIGENDIAN /* ARDI naming convention, why rock the boat? */
# elif defined(__alpha) || defined(i860) || defined(vax) || defined(i386)
# define LITTLEENDIAN
# else
# error "Unknown CPU type"
# endif
#endif
/* Define this for CPUs that require n byte data be aligned
* on addresses congruent to zero modulo n. The name "QUADALIGN"
* is another ARDI convention, why rock the boat?
*/
/*
* Alpha not quad aligned right now because that breaks Mat's code and the
* alpha can get by, for now.
*/
#if !defined (QUADALIGN)
# if defined(sparc) || /* defined(__alpha) || */ defined (i860) || defined(mips)
# define QUADALIGN
# elif !defined(m68k) && !defined(mc68000) && !defined(i386) \
&& !defined(vax) && !defined(__alpha) && !defined(powerpc) \
&& !defined (__ppc__)
# error Unknown CPU type
# endif
#endif
/* Turn this on if you want to enable destroying only blocks with checksum
* mismatches.
*/
#define CHECKSUM_BLOCKS
/* Turn this on if you want syn68k to poll for interrupts, instead of
* being interrupted by the real OS.
*/
#define SYNCHRONOUS_INTERRUPTS
/* Turn this on if you want to let the BIOS event wait manage the low
* memory interrupt flag.
*/
#if 0 && defined (MSDOS) && defined (SYNCHRONOUS_INTERRUPTS)
# define USE_BIOS_TIMER
#endif
#if !defined (INT_TYPES_TYPEDEFED)
/* Portability typedefs for signed and unsigned n-bit numbers. */
typedef signed char int8;
typedef unsigned char uint8;
typedef signed short int16;
typedef unsigned short uint16;
#if !defined(__alpha)
typedef signed long int32;
typedef unsigned long uint32;
#else /* defined(__alpha) */
typedef signed int int32;
typedef unsigned int uint32;
#endif /* defined(__alpha) */
#if defined (__GNUC__) /* Hack to compile mapindex.c on hokibox. */
typedef signed long long int64;
typedef unsigned long long uint64;
#endif
#endif /* !INT_TYPES_TYPEDEFED */
/* Typedef for address in 68k space. */
typedef uint32 syn68k_addr_t;
/* Integral type big enough to hold a pointer. Presumably we'll need to use
* unsigned long long on machines with 64 bit pointers.
*/
typedef unsigned long ptr_sized_uint;
/* Because a 68k register can be referenced as a byte, word, or int32,
* we represent them as a union of these types. Although not guaranteed
* to be portable, operations on appropriate byte- and word- union elements
* should leave the other bytes unaffected (just as they do on the 68k).
* on the 68k).
*/
#if defined (LITTLEENDIAN)
typedef union {
struct { uint32 n; } ul;
struct { int32 n; } sl;
struct { uint16 n, hi; } uw;
struct { int16 n, hi; } sw;
struct { uint8 n, b1, b2, b3; } ub;
struct { int8 n, b1, b2, b3; } sb;
} M68kReg;
#else
typedef union {
struct { uint32 n; } ul;
struct { int32 n; } sl;
struct { uint16 hi, n; } uw;
struct { int16 hi, n; } sw;
struct { uint8 b3, b2, b1, n; } ub;
struct { int8 b3, b2, b1, n; } sb;
} M68kReg;
#endif
/* Function type that handles callbacks (and therefore traps). */
typedef syn68k_addr_t (*callback_handler_t)(syn68k_addr_t, void *);
typedef struct {
syn68k_addr_t callback_address;
callback_handler_t func;
void *arg;
} TrapHandlerInfo;
#if (defined(i386) || defined(m68k)) && !defined (NO_CCR_SPEEDUPS)
#define CCR_ELEMENT_8_BITS
#endif
#if defined (CCR_ELEMENT_8_BITS)
typedef uint8 CCRElement; /* So we can setb, etc. them directly. */
#else /* !CCR_ELEMENT_8_BITS */
typedef int32 CCRElement;
#endif /* !CCR_ELEMENT_8_BITS */
typedef struct {
syn68k_addr_t tag;
const uint16 *code;
} jsr_stack_elt_t;
#define JSR_STACK_SIZE 8
typedef struct {
M68kReg regs[16]; /* d0...d7 followed by a0...a7 */
CCRElement ccnz, ccn, ccc, ccv, ccx; /* 0 or non-0, NOT 0 or 1! */
#if defined (MINIMAL_CPU_STATE)
uint8 filler[3]; /* So we can copy small cpu states w/out boundary cruft. */
#else /* !MINIMAL_CPU_STATE */
char *amode_p, *reversed_amode_p; /* Used in interpreter. */
#if !defined (USE_BIOS_TIMER) && defined (SYNCHRONOUS_INTERRUPTS)
volatile int32 interrupt_status_changed; /* High bit set when interrupted. */
#endif
jmp_buf *setjmp_buf;
jsr_stack_elt_t jsr_stack[JSR_STACK_SIZE];
unsigned jsr_stack_byte_index; /* # of **BYTES** into jsr stack for top. */
volatile uint16 sr; /* Status register, except cc bits (low 5 bits) == 0. */
syn68k_addr_t vbr; /* Vector base register (in 68k address space). */
uint32 cacr, caar; /* Cache Control Register/Cache Address Register. */
uint32 usp, msp, isp; /* Various stack pointers. Whichever one is
* currently in use can only be found in a7;
* the value here will be outdated. */
volatile uint8 interrupt_pending[8]; /* 1 if interrupt pending. */
volatile TrapHandlerInfo trap_handler_info[64];
#endif /* !MINIMAL_CPU_STATE */
} CPUState;
/* This lets us put syn68k.c's global register variable before the
* inline functions in this file, since that is an error.
*/
#if defined (GLOBAL_REGISTER_DECLS)
GLOBAL_REGISTER_DECLS
#endif
#define EM_DREG(X) (cpu_state.regs[X].ul.n)
#define EM_AREG(X) (cpu_state.regs[8 + (X)].ul.n)
#define EM_D0 EM_DREG (0)
#define EM_D1 EM_DREG (1)
#define EM_D2 EM_DREG (2)
#define EM_D3 EM_DREG (3)
#define EM_D4 EM_DREG (4)
#define EM_D5 EM_DREG (5)
#define EM_D6 EM_DREG (6)
#define EM_D7 EM_DREG (7)
#define EM_A0 EM_AREG (0)
#define EM_A1 EM_AREG (1)
#define EM_A2 EM_AREG (2)
#define EM_A3 EM_AREG (3)
#define EM_A4 EM_AREG (4)
#define EM_A5 EM_AREG (5)
#define EM_A6 EM_AREG (6)
#define EM_A7 EM_AREG (7)
#define EM_FP EM_A6
#define EM_SP EM_A7
/* We need a range of "magic" addresses where we know legitimate 68k
* code will be stored. When code at those addresses is "executed" by
* the 68k, we will instead take special actions. We want those
* addresses to be dereferenceable so we'll overlay them over a big
* block of legitimate memory that can never contain m68k code.
* We'll start a few bytes into the array in case anyone examines
* memory before the array.
*/
extern uint16 callback_dummy_address_space[];
#define CALLBACK_SLOP 16
#define MAGIC_ADDRESS_BASE \
((syn68k_addr_t) US_TO_SYN68K((unsigned long) (&callback_dummy_address_space[CALLBACK_SLOP])))
#define MAGIC_EXIT_EMULATOR_ADDRESS (MAGIC_ADDRESS_BASE + 0)
#define MAGIC_RTE_ADDRESS (MAGIC_ADDRESS_BASE + 2)
/* Address bits that have meaning, for the CLEAN() macro, below. */
#define LEGAL_ADDRESS_BITS 0xFFFFFFFFUL
/* Here is a macro to "clean" an address; if you make it mask out the
* nasty bits, you risk a noticeable performance downgrade.
*/
#if 1
# define CLEAN(addr) ((ptr_sized_uint)(addr))
#else
# define CLEAN(addr) (((ptr_sized_uint)(addr)) & LEGAL_ADDRESS_BITS)
#endif
#if !defined (__alpha)
extern uint32 ROMlib_offset;
#else
extern unsigned long ROMlib_offset;
#endif
/* Handy macros to convert back and forth between address spaces. */
#if !defined (__alpha)
#define SYN68K_TO_US(addr) ((uint16 *) ((unsigned long)addr + ROMlib_offset)) /* uint16 * only the default. */
#else
#define SYN68K_TO_US(addr) ((uint16 *) ((unsigned long)(uint32)addr + ROMlib_offset)) /* uint16 * only the default. */
#endif
#if !defined (__alpha)
#define US_TO_SYN68K(addr) (/*(syn68k_addr_t)*/(int32) (addr) - ROMlib_offset)
#else
#define US_TO_SYN68K(addr) ((uint32) ((long) (addr) - ROMlib_offset))
#endif
/* These macros should not be used within Syn68k, but are needed in
ROMlib for translations of addresses where it's important to preserve
the address 0 as 0 */
#define SYN68K_TO_US_CHECK0(addr) ({ typeof(addr) t; t = addr; t ? SYN68K_TO_US(t) : (uint16 *) 0; })
#define US_TO_SYN68K_CHECK0(addr) ({ typeof(addr) t; t = addr; t ? US_TO_SYN68K(t) : (int32) 0; })
/* Macros for byte swapping + specifying signedness. On a big endian
* machine, these macros are dummies and don't actually swap bytes.
* You may wish to replace these with the most efficient inline assembly
* you can get, as these macros are performance-critical.
* The "_IFLE" suffix stands for "if little endian".
*/
/* Byte swapping macros. */
#define SWAPUB(val) ((uint8) (val)) /* Here for symmetry. */
#define SWAPSB(val) ((int8) (val))
#if defined (CWV) && defined (CLV)
#define ROMlib_SwapShort(n) CWV ((uint16) (n))
#define ROMlib_SwapLong(n) CLV ((uint32) (n))
#define SWAPUW(n) CWV ((uint16) (n))
#define SWAPUL(n) CLV ((uint32) (n))
#elif defined(i386)
static inline uint16
ROMlib_SwapShort (unsigned short us) __attribute__ ((const));
static inline uint16
ROMlib_SwapShort (unsigned short us)
{
uint16 retval;
asm ("rorw $8,%w0" : "=r" (retval) : "0" (us) : "cc");
return retval;
}
static inline uint32
ROMlib_SwapLong (uint32 ul) __attribute__ ((const));
static inline uint32
ROMlib_SwapLong (uint32 ul)
{
uint32 retval;
#if defined (NeXT) || defined (USE_BSWAP) || defined (ALWAYS_ON_I486)
asm ("bswap %0" : "=r" (retval) : "0" (ul));
#else
asm ("rorw $8,%w0\n\t"
"rorl $16,%k0\n\t"
"rorw $8,%w0"
: "=r" (retval) : "0" (ul) : "cc");
#endif
return retval;
}
# define SWAPUW(val) ROMlib_SwapShort(val)
# define SWAPUL(val) ROMlib_SwapLong(val)
#elif 0 && defined(__alpha)
static inline unsigned short const
ROMlib_SwapShort (unsigned short us)
{
unsigned short retval;
asm("extbl %1, 1, $2\n\t" /* r2 = 0x0A */
"sll %1, 8, %0\n\t" /* %0 = 0xB0 */
"or %0, $2, %0" /* %0 = 0xBA */
: "=r" (retval) : "r" (us) : "$2");
return retval;
}
static inline uint32 const
ROMlib_SwapLong (uint32 ul)
{
uint32 retval;
asm("extbl %1, 3, $2\n\t" /* r2 = 0x000A */
"sll %1, 24, $3\n\t" /* r3 = 0xD000 */
"srl %1, 8, $5\n\t" /* r5 = 0x0ABC */
"and %1, 65280, %0\n\t" /* %0 = 0x00C0 */
"or $2, $3, $4\n\t" /* r4 = 0xD00A */
"and $5, 65280, $6\n\t" /* r6 = 0x00B0 */
"sll %0, 8, %0\n\t" /* %0 = 0x0C00 */
"or $4, $6, $7\n\t" /* r7 = 0xD0BA */
"or $7, %0, %0" /* %0 = 0xDCBA */
: "=r" (retval) : "r" (ul) : "$2", "$3", "$4", "$5", "$6", "$7");
return retval;
}
# define SWAPUW(val) ROMlib_SwapShort(val)
# define SWAPUL(val) ROMlib_SwapLong(val)
#elif defined(LITTLEENDIAN)
#if defined(__GNUC__)
# define SWAPUW(val) ({ uint16 _v = (val); (uint16) ((_v >> 8) | (_v << 8)); })
# define SWAPUL(val) \
({ uint32 _v = (val); \
(uint32) ((_v >> 24) | (_v << 24) | ((_v >> 8) & 0xFF00) \
| ((_v & 0xFF00) << 8)); \
})
#else
static uint16 _swapuw(uint16 v)
{
return (v >> 8) | (v << 8);
}
#define SWAPUW(val) _swapuw(val)
static uint32 _swapul(uint32 v)
{
return (v >> 24) | (v << 24) | ((v >> 8) & 0xFF00) | ((v & 0xFF00) << 8);
}
#define SWAPUL(val) _swapul(val)
#endif
#define ROMlib_SwapShort(val) SWAPUW(val)
#define ROMlib_SwapLong(val) SWAPUL(val)
#endif
#define SWAPSW(val) ((int16) SWAPUW (val))
#define SWAPSL(val) ((int32) SWAPUL (val))
#define SWAPUB_IFLE(n) ((uint8) (n)) /* Here for symmetry. */
#define SWAPSB_IFLE(n) ((int8) (n))
#if defined (BIGENDIAN)
# define SWAPUW_IFLE(n) ((uint16) (n))
# define SWAPSW_IFLE(n) ((int16) (n))
# define SWAPUL_IFLE(n) ((uint32) (n))
# define SWAPSL_IFLE(n) ((int32) (n))
#else /* LITTLEENDIAN */
# define SWAPUW_IFLE(n) SWAPUW(n)
# define SWAPSW_IFLE(n) SWAPSW(n)
# define SWAPUL_IFLE(n) SWAPUL(n)
# define SWAPSL_IFLE(n) SWAPSL(n)
#endif
/* The "slow" variants are here to facilitate compile-time reduction of
* swapped constants. The non-slow versions may use inline assembly, which
* the C compiler won't be able to deal with, but the slow versions are
* guaranteed to use standard C operators. You would only want to use the
* slow versions for swapping constants.
*/
#define SLOW_SWAPUB(val) ((uint8) (val)) /* Here for symmetry. */
#define SLOW_SWAPSB(val) ((int8) (val))
#if defined(__GNUC__)
#define SLOW_SWAPUW(val) \
({ uint16 _v = (val); (uint16) ((_v >> 8) | (_v << 8)); })
#else
#define SLOW_SWAPUW(v) ((uint16) (((v) >> 8) | ((v) << 8)))
#endif
#define SLOW_SWAPSW(val) ((int16) SLOW_SWAPUW (val))
#if defined(__GNUC__)
#define SLOW_SWAPUL(val) \
({ uint32 _v = (val); \
(uint32) ((_v >> 24) | (_v << 24) | ((_v >> 8) & 0xFF00) \
| ((_v & 0xFF00) << 8)); \
})
#else
#define SLOW_SWAPUL(v) ((uint32) (((v) >> 24) | \
((v) << 24) | \
(((v) >> 8) & 0xFF00) | \
(((v) & 0xFF00) << 8)))
#endif
#define SLOW_SWAPSL(val) ((int32) SLOW_SWAPUL (val))
#define SLOW_SWAPUB_IFLE(n) ((uint8) (n)) /* Here for symmetry. */
#define SLOW_SWAPSB_IFLE(n) ((int8) (n))
#if defined (BIGENDIAN)
# define SLOW_SWAPUW_IFLE(n) ((uint16) (n))
# define SLOW_SWAPSW_IFLE(n) ((int16) (n))
# define SLOW_SWAPUL_IFLE(n) ((uint32) (n))
# define SLOW_SWAPSL_IFLE(n) ((int32) (n))
#else /* LITTLEENDIAN */
# define SLOW_SWAPUW_IFLE(n) SLOW_SWAPUW(n)
# define SLOW_SWAPSW_IFLE(n) SLOW_SWAPSW(n)
# define SLOW_SWAPUL_IFLE(n) SLOW_SWAPUL(n)
# define SLOW_SWAPSL_IFLE(n) SLOW_SWAPSL(n)
#endif
/* Handy memory access macros. These implicity refer to the 68k addr space
except for the _US variants that refer to the native address space.*/
/* Memory reads. */
#define READUB(addr) (*(const uint8 *) SYN68K_TO_US (CLEAN (addr)))
#define READUW(addr) SWAPUW_IFLE (*(const uint16 *)SYN68K_TO_US (CLEAN (addr)))
#if defined (BIGENDIAN) && defined (QUADALIGN)
# define READUL(addr) \
({ const uint16 *_p = SYN68K_TO_US (CLEAN (addr)); \
(uint32) ((_p[0] << 16) | _p[1]); \
})
# define READUL_US(addr) \
({ const uint16 *_p = CLEAN (addr); \
(uint32) ((_p[0] << 16) | _p[1]); \
})
#elif defined (BIGENDIAN) && !defined (QUADALIGN)
# define READUL(addr) (*(uint32 *) SYN68K_TO_US (CLEAN (addr)))
# define READUL_US(addr) (*(uint32 *) CLEAN (addr))
#elif !defined (BIGENDIAN) && defined (QUADALIGN)
#if defined(__GNUC__)
# define READUL(addr) \
({ const uint8 *_p = (const uint8 *) SYN68K_TO_US (CLEAN (addr)); \
(uint32) ((_p[0] << 24) | (_p[1] << 16) | (_p[2] << 8) | _p[3]); \
})
# define READUL_US(addr) \
({ const uint8 *_p = (const uint8 *) CLEAN (addr); \
(uint32) ((_p[0] << 24) | (_p[1] << 16) | (_p[2] << 8) | _p[3]); \
})
#else
static uint32 _readul(syn68k_addr_t addr)
{
const uint8 *p;
p = (const uint8 *) SYN68K_TO_US (CLEAN (addr));
return (uint32) ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
}
#define READUL(addr) _readul(addr)
static uint32 _readul_us(syn68k_addr_t addr)
{
const uint8 *p;
p = (const uint8 *) CLEAN (addr);
return (uint32) ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
}
#define READUL_US(addr) _readul_us(addr)
#endif
#else /* !defined (BIGENDIAN) && !defined (QUADALIGN) */
# define READUL(addr) SWAPUL (*(uint32 *) SYN68K_TO_US (CLEAN (addr)))
# define READUL_US(addr) SWAPUL (*(uint32 *) CLEAN (addr))
#endif
#define READSB(addr) ((int8) READUB (addr))
#define READSW(addr) ((int16) READUW (addr))
#define READSL(addr) ((int32) READUL (addr))
/* Memory writes. */
#define WRITEUB(addr, val) (*(uint8 *) SYN68K_TO_US (CLEAN (addr)) = (val))
#if defined (BIGENDIAN)
# define WRITEUW(addr, val) (*(uint16 *) SYN68K_TO_US (CLEAN (addr)) = (val))
#else
# define WRITEUW(addr, val) \
(*(uint16 *) SYN68K_TO_US (CLEAN (addr)) = SWAPUW (val))
#endif
#if defined (BIGENDIAN) && defined (QUADALIGN)
# define WRITEUL(addr, val) \
do { uint32 _v = (val); \
uint16 *_p = (uint16 *) SYN68K_TO_US (CLEAN (addr)); \
_p[0] = _v >> 16; \
_p[1] = _v; \
} while (0)
#elif defined (BIGENDIAN) && !defined (QUADALIGN)
# define WRITEUL(addr, val) (*(uint32 *) (SYN68K_TO_US (CLEAN (addr))) = (val))
#elif !defined (BIGENDIAN) && defined (QUADALIGN)
# define WRITEUL(addr, val) \
do { uint32 _v = (val); \
uint8 *_p = (uint8 *) SYN68K_TO_US (CLEAN (addr)); \
_p[0] = _v >> 24; \
_p[1] = _v >> 16; \
_p[2] = _v >> 8; \
_p[3] = _v; \
} while (0)
#else /* !defined (BIGENDIAN) && !defined (QUADALIGN) */
# define WRITEUL(addr, val) \
(*(uint32 *) SYN68K_TO_US (CLEAN (addr)) = SWAPUL (val))
#endif
#define WRITESB(addr, val) WRITEUB ((addr), (uint8) (val))
#define WRITESW(addr, val) WRITEUW ((addr), (uint16) (val))
#define WRITESL(addr, val) WRITEUL ((addr), (uint32) (val))
/* Pop instructions. */
#define POPUB() (EM_A7 += 2, READUB (EM_A7 - 2))
#define POPUW() (EM_A7 += 2, READUW (EM_A7 - 2))
#define POPUL() (EM_A7 += 4, READUL (EM_A7 - 4))
#define POPSB() ((int8) POPUB ())
#define POPSW() ((int16) POPUW ())
#define POPSL() ((int32) POPUL ())
#define POPADDR() POPUL()
/* Push instructions */
#define PUSHUB(val) WRITEUB (EM_A7 -= 2, (val))
#define PUSHUW(val) WRITEUW (EM_A7 -= 2, (val))
#define PUSHUL(val) WRITEUL (EM_A7 -= 4, (val))
#define PUSHSB(val) PUSHUB ((uint8) (val))
#define PUSHSW(val) PUSHUW ((uint16) (val))
#define PUSHSL(val) PUSHUL ((uint32) (val))
#define PUSHADDR(val) PUSHUL (val)
#if !defined (CALL_EMULATOR)
#define CALL_EMULATOR(addr) \
do {PUSHADDR (MAGIC_EXIT_EMULATOR_ADDRESS); \
(interpret_code (hash_lookup_code_and_create_if_needed (addr)));} while (0)
#endif
/* Global struct describing the CPU state. */
extern CPUState cpu_state;
/* I hate to put this here, but we want our interrupt polling to
* be extremely fast so we can check for interrupts anywhere in
* executor that might be time consuming.
*/
#if defined (SYNCHRONOUS_INTERRUPTS)
#define M68K_TIMER_PRIORITY 4
#define M68K_TIMER_VECTOR (24 + M68K_TIMER_PRIORITY)
#define INTERRUPT_STATUS_CHANGED (-1)
#define INTERRUPT_STATUS_UNCHANGED 0x7FFFFFFF
#if defined (USE_BIOS_TIMER)
extern uint16 dos_memory_selector;
extern uint32 dos_interrupt_flag_addr;
# ifdef SYN68K_C
/* If we're in syn68k.c, we know that %fs holds the dos mem selector value. */
# define FETCH_INTERRUPT_STATUS() \
({ \
int32 n; \
asm ("movl %%fs:(%1),%0" \
: "=r" (n) \
: "r" (dos_interrupt_flag_addr)); \
n; \
})
# define SET_INTERRUPT_STATUS(n) \
asm ("movl %0,%%fs:(%1)" \
: : "g" (n), "r" (dos_interrupt_flag_addr))
# else /* !SYN68K_C */
/* Temporarily use %fs to reference DOS memory. */
# define FETCH_INTERRUPT_STATUS() \
({ \
int32 n; \
asm ("pushl %%fs\n\t" \
"movw %2,%%fs\n\t" \
"movl %%fs:(%1),%0\n\t" \
"popl %%fs" \
: "=r" (n) \
: "r" (dos_interrupt_flag_addr), "g" (dos_memory_selector)); \
n; \
})
# define SET_INTERRUPT_STATUS(n) \
asm ("pushl %%fs\n\t" \
"movw %2,%%fs\n\t" \
"movl %0,%%fs:(%1)\n\t" \
"popl %%fs" \
: : "g" (n), "r" (dos_interrupt_flag_addr), \
"g" (dos_memory_selector))
# endif /* !SYN68K_C */
#else /* !USE_BIOS_TIMER */
#define FETCH_INTERRUPT_STATUS() cpu_state.interrupt_status_changed
#define SET_INTERRUPT_STATUS(n) \
((void) (cpu_state.interrupt_status_changed = (n)))
#endif /* !USE_BIOS_TIMER */
#define INTERRUPT_PENDING() (FETCH_INTERRUPT_STATUS () < 0)
#endif /* SYNCHRONOUS_INTERRUPTS */
/* Functions to be called from outside the emulator. */
extern void initialize_68k_emulator (void (*while_busy)(int), int native_p,
uint32 trap_vector_storage[64],
uint32 dos_int_flag_addr);
#if defined (SYNCHRONOUS_INTERRUPTS)
extern void interrupt_generate (unsigned priority);
extern void interrupt_note_if_present (void);
/* called from `host_interrupt_status_changed' assembly stub in
host-native.c */
extern syn68k_addr_t interrupt_process_any_pending (syn68k_addr_t pc)
asm ("_interrupt_process_any_pending");
#endif /* SYNCHRONOUS_INTERRUPTS */
extern void interpret_code (const uint16 *code);
/* called from asm; hence the need for the asm label, see
`host_interrupt_status_changed' stub asm in host-native.c */
extern const uint16 *hash_lookup_code_and_create_if_needed (syn68k_addr_t adr)
asm ("_hash_lookup_code_and_create_if_needed");
extern unsigned long destroy_blocks (syn68k_addr_t low_m68k_address,
uint32 num_bytes);
extern syn68k_addr_t callback_install (callback_handler_t func,
void *arbitrary_argument);
extern void callback_remove (syn68k_addr_t m68k_address);
extern void trap_install_handler (unsigned trap_number,
callback_handler_t func,
void *arbitrary_argument);
extern void trap_remove_handler (unsigned trap_number);
extern void *callback_argument (syn68k_addr_t callback_address);
extern callback_handler_t callback_function (syn68k_addr_t callback_address);
extern void dump_profile (const char *file);
#if defined (CHECKSUM_BLOCKS)
extern unsigned long destroy_blocks_with_checksum_mismatch
(syn68k_addr_t low_m68k_address, uint32 num_bytes);
#endif
extern void m68kaddr (const uint16 *pc);
#endif /* Not _syn68k_public_h_ */

15
profile/Makefile.am Normal file
View File

@ -0,0 +1,15 @@
CC=@CC_FOR_BUILD@
noinst_PROGRAMS = makebucket profile
EXEEXT =
profile_SOURCES = bucket.c main.c readprofile.c amode.c frequency.c
makebucket_SOURCES = makebucket.c amode.c
AM_CFLAGS = -g -Wall -I$(srcdir)/include -I$(srcdir)/../include
all:
echo "Doing nothing, we don't use this any more"
bucket.c: makebucket ../runtime/profileinfo.gz
./makebucket ../runtime/profileinfo.gz > bucket.c

37
profile/amode.c Normal file
View File

@ -0,0 +1,37 @@
#include "amode.h"
#include <assert.h>
const char *
amode_to_string (int amode)
{
static const char *amode_string[64] = {
#if 0
"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
"a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
"a0@", "a1@", "a2@", "a3@", "a4@", "a5@", "a6@", "a7@",
"a0@+", "a1@+", "a2@+", "a3@+", "a4@+", "a5@+", "a6@+", "a7@+",
"a0@-", "a1@-", "a2@-", "a3@-", "a4@-", "a5@-", "a6@-", "a7@-",
"a0@(d16)", "a1@(d16)", "a2@(d16)", "a3@(d16)",
"a4@(d16)", "a5@(d16)", "a6@(d16)", "a7@(d16)",
"[mode 6/a0]", "[mode 6/a1]", "[mode 6/a2]", "[mode 6/a3]",
"[mode 6/a4]", "[mode 6/a5]", "[mode 6/a6]", "[mode 6/a7]",
"abs.w", "abs.l", "pc@(d16)", "[amode 7/3]",
"#<data>", "[undefined]", "[undefined]", "[undefined]",
#else /* We want more general categories. */
"dn", "dn", "dn", "dn", "dn", "dn", "dn", "dn",
"an", "an", "an", "an", "an", "an", "an", "an",
"an@", "an@", "an@", "an@", "an@", "an@", "an@", "an@",
"an@+", "an@+", "an@+", "an@+", "an@+", "an@+", "an@+", "an@+",
"an@-", "an@-", "an@-", "an@-", "an@-", "an@-", "an@-", "an@-",
"an@(d16)", "an@(d16)", "an@(d16)", "an@(d16)",
"an@(d16)", "an@(d16)", "an@(d16)", "an@(d16)",
"[mode 6/an]", "[mode 6/an]", "[mode 6/an]", "[mode 6/an]",
"[mode 6/an]", "[mode 6/an]", "[mode 6/an]", "[mode 6/an]",
"abs.w", "abs.l", "pc@(d16)", "[amode 7/3]",
"#<data>", "[undefined]", "[undefined]", "[undefined]",
#endif
};
assert (amode >= 0 && amode < 64);
return amode_string[amode];
}

43
profile/frequency.c Normal file
View File

@ -0,0 +1,43 @@
#include "bucket.h"
#include "frequency.h"
#include "readprofile.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
static void
fill_buckets ()
{
int i;
for (i = 65535; i >= 0; i--)
bucket[bucket_map[i]].count += instruction_count[i];
}
/* qsort helper function. Place larger counts first. */
static int
compare_buckets (const void *b1, const void *b2)
{
int diff = ((const Bucket *)b2)->count - ((const Bucket *)b1)->count;
if (diff != 0)
return diff;
/* Sort alphabetically if the counts are the same. */
return strcmp (((const Bucket *)b1)->name, ((const Bucket *)b2)->name);
}
void
generate_frequency_report ()
{
int i;
fill_buckets ();
qsort (bucket, num_buckets, sizeof bucket[0], compare_buckets);
puts ("count\topcode\n"
"-------\t-----------");
for (i = 0; i < num_buckets && bucket[i].count != 0; i++)
printf ("%lu\t%s\n", bucket[i].count, bucket[i].name);
}

6
profile/include/amode.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef _amode_h_
#define _amode_h_
extern const char *amode_to_string (int amode);
#endif /* Not _amode_h_ */

16
profile/include/bucket.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef _bucket_h_
#define _bucket_h_
#define NO_AMODE (-1)
typedef struct {
const char *name; /* Descriptive name for instruction. */
unsigned short litmask, litbits; /* Mask/values for fixed bits in 68k op. */
unsigned long count; /* Frequency of execution. */
} Bucket;
extern Bucket bucket[];
extern const unsigned short bucket_map[65536];
extern const int num_buckets;
#endif /* Not _bucket_h_ */

View File

@ -0,0 +1,6 @@
#ifndef _frequency_h_
#define _frequency_h_
extern void generate_frequency_report (void);
#endif /* Not _frequency_h_ */

View File

@ -0,0 +1,9 @@
#ifndef read_profile_h
#define read_profile_h
typedef enum { BO_BIG_ENDIAN, BO_LITTLE_ENDIAN } ByteOrder;
extern unsigned long instruction_count[65536];
extern void read_profile (const char *filename);
#endif /* Not read_profile_h */

23
profile/main.c Normal file
View File

@ -0,0 +1,23 @@
#include <stdlib.h>
#include <stdio.h>
#include "readprofile.h"
#include "frequency.h"
int
main (int argc, char *argv[])
{
/* Check arguments. */
if (argc != 2)
{
fprintf (stderr, "Usage: %s <profile file>\n", argv[0]);
exit (1);
}
/* Read in the profile file. */
read_profile (argv[1]);
/* Process it. */
generate_frequency_report ();
return EXIT_SUCCESS;
}

147
profile/makebucket.c Normal file
View File

@ -0,0 +1,147 @@
#include "bucket.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
#include "amode.h"
#if 0
#define IS_MOVE(n, x) (((n) & 0xC000) == 0 && (((n) & 0x3000) != 0) \
&& !strncmp ((x), "move", 4))
#endif
int
main (int argc, char *argv[])
{
int num_buckets;
static unsigned short bucket_map[65536];
static Bucket bucket[65536];
static struct {
unsigned char has_amode, has_reversed_amode;
const char *name;
} amode_info[65536];
int num_amode_infos = 0;
int pass;
int i;
if (argc != 2)
{
fprintf (stderr, "Usage: %s <file>", argv[0]);
exit (-1);
}
num_buckets = 1;
bucket[0].name = "unmapped_spew";
for (pass = 2; pass >= 0; pass--)
{
FILE *fp;
char cmd[1024];
sprintf (cmd, "zcat %s", argv[1]);
fp = popen (cmd, "r");
assert (fp != NULL);
while (!feof (fp))
{
int opcode, has_amode, has_reversed_amode, litmask, litbits;
char name[1024]; /* Fixed length arrays usually bad, but not here. */
if (fscanf (fp, " %d %d %d %d %d %s", &opcode, &has_amode,
&has_reversed_amode, &litmask, &litbits, name) != 6)
break;
/* Make sure we have the right # of amodes for this pass. */
if (has_amode + has_reversed_amode != pass)
continue;
/* See if anything else with the same root name exists, and if it
* does, assume we have at least as many addressing modes as that
* guy. Why? Well, the syngen process loses info about the
* existence of amodes/reverse amodes in favor of rewriting the
* 68k.scm code you give it to special case amodes like registers.
* This hack will try to determine if there were originally amodes
* in this opcode.
*/
for (i = num_amode_infos - 1; i >= 0; i--)
if (!strcmp (amode_info[i].name, name))
{
has_amode |= amode_info[i].has_amode;
has_reversed_amode |= amode_info[i].has_reversed_amode;
break;
}
/* If we didn't find a match, add a new entry to the table and
* remember what amodes it has.
*/
if (i < 0)
{
amode_info[num_amode_infos].has_amode = has_amode;
amode_info[num_amode_infos].has_reversed_amode
= has_reversed_amode;
amode_info[num_amode_infos].name
= strcpy (malloc (strlen (name) + 1), name);
num_amode_infos++;
}
/* Generate the canonical name. */
if (has_amode)
sprintf (name + strlen (name), " %s",
amode_to_string (opcode & 0x3F));
if (has_reversed_amode)
sprintf (name + strlen (name), ", %s",
amode_to_string (((opcode >> 9) & 7)
| ((opcode >> 3) & 0x38)));
/* Look for a bucket with the same canonical name.
* Isn't O(n^2) great?
*/
for (i = num_buckets - 1; i >= 0; i--)
if (!strcmp (bucket[i].name, name)
&& bucket[i].litmask == litmask
&& bucket[i].litbits == litbits)
{
bucket_map[opcode] = i;
break;
}
/* Did we fail to find a matching bucket? If so, make a new one. */
if (i < 0)
{
Bucket *b = &bucket[num_buckets++];
b->name = strcpy (malloc (strlen (name) + 1), name);
b->litbits = litbits;
b->litmask = litmask;
b->count = 0;
bucket_map[opcode] = b - bucket;
}
}
pclose (fp);
}
printf ("#include \"bucket.h\"\n"
"\n"
"Bucket bucket[%d] = {\n",
num_buckets);
for (i = 0; i < num_buckets; i++)
printf (" { \"%s\", 0 },\n", bucket[i].name);
puts ("};\n"
"\n"
"const unsigned short bucket_map[65536] = {");
for (i = 0; i < 65536; i++)
{
if (i % 8 == 0)
fputs ("\n ", stdout);
printf (" 0x%04X,", (unsigned) bucket_map[i]);
}
printf ("\n"
"};\n"
"const int num_buckets = %d;\n",
num_buckets);
return EXIT_SUCCESS;
}

39
profile/readprofile.c Normal file
View File

@ -0,0 +1,39 @@
#include "readprofile.h"
#include "syn68k_public.h"
#include <stdio.h>
#include <stdlib.h>
unsigned long instruction_count[65536];
void
read_profile (const char *filename)
{
FILE *fp;
fp = fopen (filename, "rb");
if (fp == NULL)
{
perror ("Unable to open file");
exit (-1);
}
/* Read in the data. */
if (fread (instruction_count, sizeof (unsigned long), 65536, fp) != 65536)
{
fprintf (stderr, "Premature end of file!\n");
exit (-3);
}
/* Byte swap if necessary. */
#ifdef LITTLEENDIAN
{
unsigned long *p = instruction_count;
int i;
for (i = 65535; i >= 0; p++, i--)
*p = SWAPUL (*p);
}
#endif
fclose (fp);
}

412
runtime/68k.defines.scm Normal file
View File

@ -0,0 +1,412 @@
; All = No restrictions
; Alt = No #, No PC
; Data = No An
; DataNoIMM = No An, No #
; DataAlt = No An, No #, No PC
; MemAlt = No Dn, No An, No #, No PC
; Ctrl = No Dn, No An, No (An)+, No -(An), No #
; Move = Source: All, Dest: DataAlt
; Moveb = Source: Data, Dest: DataAlt
; CtrlAltOrPreDec = No Dn, No An, No (An)+, No #, No PC
; CtrlOrPostInc = No Dn, No An, No -(An), No #
; DRegOrCtrl = No An, No (An)+, No -(An), No #
; DRegOrCtrlAlt = No An, No (An)+, No -(An), No #, No PC
; Each of these macros must evaluate to a number between 0 and 0xFF if
; the appropriate sign bit is set, else 0.
(define (SIGN_BYTE expr) (& expr 0x80))
(define (SIGN_WORD expr) (>> (<< (cast "uint32" expr) 16) 31))
(define (SIGN_LONG expr) (>> expr 31))
(define (SET_C_N_V_NZ c n v nz)
(list
"\n#ifdef CCR_ELEMENT_8_BITS\n"
(assign (dereful (call "US_TO_SYN68K" "&cpu_state.ccnz")) (| (<< nz 24)
(| (<< n 16)
(| (<< c 8)
v))))
"\n#else\n"
(assign ccnz nz)
(assign ccn n)
(assign ccc c)
(assign ccv v)
"\n#endif\n"))
(define (SET_N_NZ n nz)
(list
"\n#ifdef CCR_ELEMENT_8_BITS\n"
(assign (derefuw (call "US_TO_SYN68K" "&cpu_state.ccnz")) (| (<< nz 8) n))
"\n#else\n"
(assign ccnz nz)
(assign ccn n)
"\n#endif\n"))
; These macros set the n and z bits based on whether the value of an
; expression of a certain size is negative or zero, respectively.
(define (ASSIGN_NNZ_BYTE expr)
(assign ccn (SIGN_BYTE (assign ccnz expr))))
(define (ASSIGN_NNZ_WORD expr)
(list
"\n#ifdef CCR_ELEMENT_8_BITS\n"
"{ uint16 assign_tmp"
(assign "assign_tmp" expr)
(assign ccnz (<> "assign_tmp" 0))
(assign ccn (>> "assign_tmp" 15))
"}"
"\n#else\n"
(assign ccn (& 0x8000 (assign ccnz expr)))
"\n#endif\n"))
(define (ASSIGN_NNZ_LONG expr)
(list
"\n#ifdef CCR_ELEMENT_8_BITS\n"
"{ uint32 assign_tmp"
(assign "assign_tmp" expr)
(assign ccnz (<> "assign_tmp" 0))
(assign ccn (>> "assign_tmp" 31))
"}"
"\n#else\n"
(assign ccn (>> (assign ccnz expr) 31))
"\n#endif\n"))
(define (ASSIGN_C_N_V_NZ_BYTE expr)
(list
"\n#ifdef FAST_CC_FUNCS\n"
(call "inline_compute_c_n_v_nz_byte" expr)
"\n#else\n"
(ASSIGN_NNZ_BYTE expr)
(assign ccc (assign ccv 0))
"\n#endif\n"))
(define (ASSIGN_C_N_V_NZ_WORD expr)
(list
"\n#ifdef FAST_CC_FUNCS\n"
(call "inline_compute_c_n_v_nz_word" expr)
"\n#else\n"
(ASSIGN_NNZ_WORD expr)
(assign ccc (assign ccv 0))
"\n#endif\n"))
(define (ASSIGN_C_N_V_NZ_LONG expr)
(list
"\n#ifdef FAST_CC_FUNCS\n"
(call "inline_compute_c_n_v_nz_long" expr)
"\n#else\n"
(ASSIGN_NNZ_LONG expr)
(assign ccc (assign ccv 0))
"\n#endif\n"))
; Macros for common addressing modes.
(define amode_control
(union "xxxxxxxxxxx10xxx" "xxxxxxxxxx101xxx" "xxxxxxxxxx1110xx"))
(define amode_memory
(union amode_control "xxxxxxxxxx011xxx" "xxxxxxxxxx100xxx"
"xxxxxxxxxx111100"))
(define amode_reg "xxxxxxxxxx00xxxx")
(define amode_dreg "xxxxxxxxxx000xxx")
(define amode_data (union amode_memory amode_dreg))
(define amode_alterable
(union "xxxxxxxxxx0xxxxx" "xxxxxxxxxxx0xxxx"
"xxxxxxxxxxxx0xxx" "xxxxxxxxxx11100x"))
(define amode_alterable_memory
(intersect amode_alterable amode_memory))
(define amode_alterable_control
(intersect amode_alterable amode_control))
(define amode_implicit "xxxxxxxxxxxxxxxx")
(define amode_immediate "xxxxxxxxxx111100")
(define amode_alterable_data
(intersect amode_alterable amode_data))
(define amode_all_combinations (union amode_data "xxxxxxxxxx001xxx"))
; Not strictly an addressing mode, but handy when you want the two reg
; fields to be the same register.
(define amode_same_reg
(union "xxxx000xxxxxx000" "xxxx001xxxxxx001" "xxxx010xxxxxx010"
"xxxx011xxxxxx011" "xxxx100xxxxxx100" "xxxx101xxxxxx101"
"xxxx110xxxxxx110" "xxxx111xxxxxx111"))
;(define dont_expand "----------------")
;(define fully_expand "xxxxxxxxxxxxxxxx")
(define dont_expand (list))
(define fully_expand (list "xxxxxxxxxxxxxxxx"))
(define BYTE 1)
(define WORD 2)
(define LONG 4)
(define IMM 0)
(define ABSW 1)
(define ABSL 2)
(define REG 3)
(define GREG 4)
(define AREG 5)
(define IND 6)
(define PREDEC 7)
(define POSTINC 8)
(define INDOFF 9)
(define INDIX 10)
(define (amode_name mode)
(switch mode
((+ IMM 0) "imm")
((+ ABSW 0) "abs")
((+ ABSL 0) "abs")
((+ REG 0) "reg")
((+ GREG 0) "reg")
((+ AREG 0) "areg")
((+ IND 0) "ind")
((+ PREDEC 0) "predec")
((+ POSTINC 0) "postinc")
((+ INDOFF 0) "indoff")
((+ INDIX 0) "indix")
(default "?? unknown amode ??")))
(define (no_reg_op_p mode)
(or (= mode IMM) (or (= mode ABSW) (= mode ABSL))))
(define (src_val s_amode d_amode size force_unsigned_p)
(if (= size BYTE)
(switch s_amode
((+ IMM 0)
(if (no_reg_op_p d_amode)
$1.ub
$2.ub))
((+ ABSW 0)
(if (no_reg_op_p d_amode)
(derefub $1.sw)
(derefub $2.sw)))
((+ ABSL 0)
(if (no_reg_op_p d_amode)
(derefub $1.ul)
(derefub $2.ul)))
((+ REG 0)
(if (no_reg_op_p d_amode)
$1.dub
$2.dub))
((+ GREG 0)
(if (no_reg_op_p d_amode)
$1.gub
$2.gub))
((+ IND 0)
(if (no_reg_op_p d_amode)
(derefub $1.aul)
(derefub $2.aul)))
((+ PREDEC 0)
(if (no_reg_op_p d_amode)
(derefub $1.aul)
(derefub $2.aul)))
((+ POSTINC 0)
(if (no_reg_op_p d_amode)
(derefub $1.aul)
(derefub $2.aul)))
((+ INDOFF 0)
(if (no_reg_op_p d_amode)
(derefub (+ $1.asl $2.sw))
(derefub (+ $2.asl $3.sw))))
((+ INDIX 0)
(if (no_reg_op_p d_amode)
$1.msb
$2.msb)))
(if (= size WORD)
(switch s_amode
((+ IMM 0)
(if force_unsigned_p
(if (no_reg_op_p d_amode)
$1.uw
$2.uw)
(if (no_reg_op_p d_amode)
$1.sw
$2.sw)))
((+ ABSW 0)
(if force_unsigned_p
(if (no_reg_op_p d_amode)
(derefuw $1.sw)
(derefuw $2.sw))
(if (no_reg_op_p d_amode)
(derefsw $1.sw)
(derefsw $2.sw))))
((+ ABSL 0)
(if force_unsigned_p
(if (no_reg_op_p d_amode)
(derefuw $1.ul)
(derefuw $2.ul))
(if (no_reg_op_p d_amode)
(derefsw $1.ul)
(derefsw $2.ul))))
((+ AREG 0)
(if force_unsigned_p
(if (no_reg_op_p d_amode)
$1.auw
$2.auw)
(if (no_reg_op_p d_amode)
$1.asw
$2.asw)))
((+ REG 0)
(if force_unsigned_p
(if (no_reg_op_p d_amode)
$1.duw
$2.duw)
(if (no_reg_op_p d_amode)
$1.dsw
$2.dsw)))
((+ GREG 0)
(if force_unsigned_p
(if (no_reg_op_p d_amode)
$1.guw
$2.guw)
(if (no_reg_op_p d_amode)
$1.gsw
$2.gsw)))
((+ IND 0)
(if force_unsigned_p
(if (no_reg_op_p d_amode)
(derefuw $1.aul)
(derefuw $2.aul))
(if (no_reg_op_p d_amode)
(derefsw $1.aul)
(derefsw $2.aul))))
((+ PREDEC 0)
(if force_unsigned_p
(if (no_reg_op_p d_amode)
(derefuw $1.aul)
(derefuw $2.aul))
(if (no_reg_op_p d_amode)
(derefsw $1.aul)
(derefsw $2.aul))))
((+ POSTINC 0)
(if force_unsigned_p
(if (no_reg_op_p d_amode)
(derefuw $1.aul)
(derefuw $2.aul))
(if (no_reg_op_p d_amode)
(derefsw $1.aul)
(derefsw $2.aul))))
((+ INDOFF 0)
(if force_unsigned_p
(if (no_reg_op_p d_amode)
(derefuw (+ $1.asl $2.sw))
(derefuw (+ $2.asl $3.sw)))
(if (no_reg_op_p d_amode)
(derefsw (+ $1.asl $2.sw))
(derefsw (+ $2.asl $3.sw)))))
((+ INDIX 0)
(if (no_reg_op_p d_amode)
$1.msw
$2.msw)))
(switch s_amode ; LONG op
((+ IMM 0)
(if (no_reg_op_p d_amode)
$1.ul
$2.ul))
((+ ABSW 0)
(if (no_reg_op_p d_amode)
(dereful $1.sw)
(dereful $2.sw)))
((+ ABSL 0)
(if (no_reg_op_p d_amode)
(dereful $1.ul)
(dereful $2.ul)))
((+ AREG 0)
(if (no_reg_op_p d_amode)
$1.asl
$2.asl))
((+ REG 0)
(if (no_reg_op_p d_amode)
$1.dul
$2.dul))
((+ GREG 0)
(if (no_reg_op_p d_amode)
$1.gul
$2.gul))
((+ IND 0)
(if (no_reg_op_p d_amode)
(dereful $1.aul)
(dereful $2.aul)))
((+ PREDEC 0)
(if (no_reg_op_p d_amode)
(dereful $1.aul)
(dereful $2.aul)))
((+ POSTINC 0)
(if (no_reg_op_p d_amode)
(dereful $1.aul)
(dereful $2.aul)))
((+ INDOFF 0)
(if (no_reg_op_p d_amode)
(dereful (+ $1.asl $2.sw))
(dereful (+ $2.asl $3.sw))))
((+ INDIX 0)
(if (no_reg_op_p d_amode)
$1.msl
$2.msl))))))
(define (dst_val s_amode d_amode size)
(if (= size BYTE)
(switch d_amode
((+ ABSW 0)
(if (or (= s_amode INDOFF) (= s_amode INDIX))
(derefub $3.sw)
(derefub $2.sw)))
((+ ABSL 0)
(if (or (= s_amode INDOFF) (= s_amode INDIX))
(derefub $3.ul)
(derefub $2.ul)))
((+ REG 0) $1.dub)
((+ GREG 0) $1.gub)
((+ IND 0) (derefub $1.aul))
((+ PREDEC 0) (derefub $1.aul))
((+ POSTINC 0) (derefub $1.aul))
((+ INDOFF 0)
(if (or (= s_amode INDOFF) (= s_amode INDIX))
(derefub (+ $1.asl $4.sw))
(derefub (+ $1.asl $3.sw))))
((+ INDIX 0) $1.rub))
(if (= size WORD)
(switch d_amode
((+ ABSW 0)
(if (or (= s_amode INDOFF) (= s_amode INDIX))
(derefuw $3.sw)
(derefuw $2.sw)))
((+ ABSL 0)
(if (or (= s_amode INDOFF) (= s_amode INDIX))
(derefuw $3.ul)
(derefuw $2.ul)))
((+ REG 0) $1.duw)
((+ GREG 0) $1.guw)
((+ AREG 0) $1.asl) ; Yes, a long! Word moves are sexted.
((+ IND 0) (derefuw $1.aul))
((+ PREDEC 0) (derefuw $1.aul))
((+ POSTINC 0) (derefuw $1.aul))
((+ INDOFF 0)
(if (or (= s_amode INDOFF) (= s_amode INDIX))
(derefuw (+ $1.asl $4.sw))
(derefuw (+ $1.asl $3.sw))))
((+ INDIX 0) $1.ruw))
(switch d_amode ; LONG op
((+ ABSW 0)
(if (or (= s_amode INDOFF) (= s_amode INDIX))
(dereful $3.sw)
(dereful $2.sw)))
((+ ABSL 0)
(if (or (= s_amode INDOFF) (= s_amode INDIX))
(dereful $3.ul)
(dereful $2.ul)))
((+ REG 0) $1.dul)
((+ AREG 0) $1.aul)
((+ GREG 0) $1.gul)
((+ IND 0) (dereful $1.aul))
((+ PREDEC 0) (dereful $1.aul))
((+ POSTINC 0) (dereful $1.aul))
((+ INDOFF 0)
(if (or (= s_amode INDOFF) (= s_amode INDIX))
(dereful (+ $1.asl $4.sw))
(dereful (+ $1.asl $3.sw))))
((+ INDIX 0) $1.rul)))))
; For add/sub/cmp/and/or/eor...reuse the tricky code above.
(define (ea_val amode size force_unsigned_p)
(src_val amode REG size force_unsigned_p))

6525
runtime/68k.scm Normal file

File diff suppressed because it is too large Load Diff

78
runtime/Makefile.am Normal file
View File

@ -0,0 +1,78 @@
host_native=@HOST_NATIVE@
SYN68K_CFLAGS=@SYN68K_CFLAGS@
CLEANUP=@CLEANUP@
OPTIMIZE=@OPTIMIZE@
CFLAGS += -DRUNTIME
LOCAL_INCLUDES =
LOCAL_INCLUDES += -I$(srcdir)/include \
-I$(srcdir)/../include -I$(srcdir) -I../include
LOCAL_CFLAGS = -DRUNTIME -Iinclude
all: libsyn68k.a
%.o:%.c
$(CC) $(CFLAGS) -c $(LOCAL_INCLUDES) $< -o $@
OBJS = block.o diagnostics.o hash.o rangetree.o translate.o alloc.o \
blockinfo.o trap.o destroyblock.o callback.o init.o interrupt.o \
profile.o dosinterrupts.o deathqueue.o checksum.o native.o \
backpatch.o recompile.o \
mapindex.o mapinfo.o syn68k.o
mapinfo.o: $(host_native)/host-xlate.h
$(host_native)/host-xlate.h:
$(MAKE) -C $(host_native) host-xlate.h
.PHONY: $(host_native)/subdir-stmp
$(host_native)/subdir-stmp:
$(MAKE) -C $(host_native) subdir-stmp
libsyn68k.a: $(OBJS) $(host_native)/subdir-stmp
$(RM) libsyn68k.a
$(AR) cq $@ $(OBJS) \
$(addprefix $(host_native)/, \
$(shell cat $(host_native)/subdir-stmp))
$(RANLIB) $@
# Syn68k uses inline assembly that confuses various gcc stack optimizations.
# Under gcc 2.x -fno-defer-pop is sufficient to get gcc to do the right thing
# with our code. Under gcc 3.x we need to also add -maccumulate-outgoing-args.
# Since we don't know what gcc we have until we try to execute CC, we
# do a test right here to figure out if the c-compiler understands
# -maccumulate-outgoing-args. If it does, we use it.
#
# A better solution would be to put something into our asm to form a
# barrier that gcc won't try to do stack optimizations across. I haven't yet
# scoured the gcc 3 documentation or source code to see if there's something
# obvious that can be used.
syn68k.o: syn68k.c
outgoing=;\
$(CC) -maccumulate-outgoing-args -c -x c /dev/null 2> /dev/null \
&& outgoing=-maccumulate-outgoing-args; \
$(CC) -S $(SYN68K_CFLAGS) -Wall -static -fno-defer-pop -Wno-unused\
$(LOCAL_INCLUDES) $$outgoing syn68k.c -o ./syn68k.s
if [ x"$(CLEANUP)" != x ] ; then \
$(PERL) $(srcdir)/$(CLEANUP) < syn68k.s > syn68k.s.new && \
mv syn68k.s.new syn68k.s ; fi
if [ x"$(OPTIMIZE)" != x ] ; then \
$(PERL) $(srcdir)/$(OPTIMIZE) < syn68k.s > syn68k.s.new && \
mv syn68k.s.new syn68k.s ; fi
$(CC) -xassembler-with-cpp -c ./syn68k.s -o syn68k.o
$(RM) ./syn68k.s
syn68k.c mapindex.c mapinfo.c profileinfo.gz: ../syngen/syngen syn68k_header.c 68k.scm 68k.defines.scm\
../include/syn68k_private.h \
../runtime/include/hash.h \
../runtime/include/interrupt.h \
../runtime/include/trap.h
cp -p $(srcdir)/68k.scm $(srcdir)/syn68k_header.c $(srcdir)/68k.defines.scm .
../syngen/syngen -v 68k.scm
gzip -1f profileinfo

6
runtime/TODO Normal file
View File

@ -0,0 +1,6 @@
2) Make generate_amode_fetch() in translate.c have the parameter m68k_operand
be a syn68k_addr_t instead of a uint16 *, and then ditch all of the
US_TO_SYN68K's that become superfluous.
PERFORMANCE TWEAKS:

60
runtime/alloc.c Normal file
View File

@ -0,0 +1,60 @@
#include "alloc.h"
#include "destroyblock.h"
#include <stdio.h>
#include <stdlib.h>
void *
xmalloc (size_t size)
{
void *p;
while ((p = malloc (size)) == NULL)
{
if (!destroy_any_block ())
{
fprintf (stderr, "Out of memory. Tried to alloc 0x%lX bytes.\n",
(unsigned long) size);
exit (-1);
}
}
return p;
}
void *
xrealloc (void *old, size_t new_size)
{
void *p;
while ((p = realloc (old, new_size)) == NULL && new_size)
{
if (!destroy_any_block ())
{
fprintf (stderr, "Out of memory. Tried to realloc 0x%lX bytes.\n",
(unsigned long) new_size);
exit (-1);
}
}
return p;
}
void *
xcalloc (size_t num_elems, size_t byte_size)
{
void *p;
while ((p = calloc (num_elems, byte_size)) == NULL)
{
if (!destroy_any_block ())
{
fprintf (stderr, "Out of memory. Tried to calloc 0x%lX bytes.\n",
(unsigned long) (num_elems * byte_size));
exit (-1);
}
}
return p;
}

119
runtime/backpatch.c Normal file
View File

@ -0,0 +1,119 @@
#include "syn68k_private.h"
#include "backpatch.h"
#include "alloc.h"
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
void
backpatch_apply_and_free (Block *b, backpatch_t *p)
{
ptr_sized_uint value;
uint32 first_byte;
int length;
BOOL found_p;
backpatch_t **bp;
char *base;
/* Find the backpatch in the block's list and remove it. */
for (bp = &b->backpatch, found_p = FALSE; *bp != NULL; bp = &(*bp)->next)
if (*bp == p)
{
*bp = p->next;
found_p = TRUE;
break;
}
#ifdef DEBUG
/* Make sure we actually found it in the list. */
if (!found_p)
abort ();
#endif
if (p->target == NULL)
base = (char *)0;
else
base = (char *)p->target->compiled_code;
/* First, compute the value to write out to memory. */
first_byte = p->offset_location / 8;
length = p->num_bits;
if (p->relative_p)
{
value = ((base + p->const_offset)
- ((char *)b->compiled_code + first_byte));
}
else
{
value = ((ptr_sized_uint)(base + p->const_offset));
}
#ifndef QUADALIGN
if ((p->offset_location & 7) == 0)
{
if (length == 32)
*(uint32 *)((char *)b->compiled_code + first_byte) = value;
else if (length == 16)
*(uint16 *)((char *)b->compiled_code + first_byte) = value;
else if (length == 8)
*(uint8 *)((char *)b->compiled_code + first_byte) = value;
#if defined (__alpha)
else if (length == 64)
*(uint64 *)((char *)b->compiled_code + first_byte) = value;
#endif
else
abort ();
}
else
{
abort ();
}
#else /* QUADALIGN */
/* The whole guy had better fit in one long! */
if ((p->offset_location & ~31)
== ((p->offset_location + length - 1) & ~31))
{
uint32 *ptr = (uint32 *)((char *)b->compiled_code + first_byte);
if (length == 32)
*ptr = value;
else
{
int offset = p->offset_location & 31;
#error "Write this case"
#ifdef LITTLEENDIAN
*ptr = (*ptr & ) | ;
#else /* !LITTLEENDIAN */
*ptr = (*ptr & ) | ;
#endif /* !LITTLEENDIAN */
}
}
else
abort ();
#endif /* QUADALIGN */
free (p);
}
void
backpatch_add (Block *b, int offset_location, int num_bits, BOOL relative_p,
int const_offset, Block *target)
{
backpatch_t *p;
#ifdef DEBUG
if (num_bits == 0)
abort ();
#endif
p = (backpatch_t *) xmalloc (sizeof *p);
p->next = b->backpatch;
p->offset_location = offset_location;
p->num_bits = num_bits;
p->relative_p = relative_p;
p->const_offset = const_offset;
p->target = target;
/* Prepend this guy to the block's list. */
b->backpatch = p;
}

312
runtime/block.c Normal file
View File

@ -0,0 +1,312 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include "block.h"
#include "alloc.h"
#include "diagnostics.h"
#include "deathqueue.h"
#include "checksum.h"
static Block *free_blocks = NULL;
/* Returns a new, empty Block. All fields of the block are initialized to
* zero. If DEBUG is #define'd, the magic field will be set to
* BLOCK_MAGIC_VALUE.
*/
Block *
block_new ()
{
Block *b;
if (free_blocks != NULL)
{
b = free_blocks;
free_blocks = b->child[0];
}
else
{
#define BLOCK_CHUNK_SIZE (16384 / sizeof (Block))
static Block *block_chunk;
static int block_chunk_index = BLOCK_CHUNK_SIZE;
if (block_chunk_index >= BLOCK_CHUNK_SIZE)
{
block_chunk = xmalloc (BLOCK_CHUNK_SIZE * sizeof (Block));
block_chunk_index = 0;
}
b = &block_chunk[block_chunk_index++];
}
memset (b, 0, sizeof *b);
#ifdef DEBUG
b->magic = BLOCK_MAGIC_VALUE;
#endif
return b;
}
/* Free the block and all storage associated with it. */
void
block_free (Block *b)
{
free (b->parent);
if (b->compiled_code != NULL) /* Avoid freeing -2 or anything. */
free ((void *) (b->compiled_code - b->malloc_code_offset));
/* Prepend this block to the linked list of free ones. */
b->child[0] = free_blocks;
free_blocks = b;
}
/* Adds PARENT to B's parent list. If PARENT is already a member of B's
* parent list, no action is taken.
*/
void
block_add_parent (Block *b, Block *parent)
{
int i;
BOOL immortal;
for (i = b->num_parents - 1; i >= 0; i--)
if (b->parent[i] == parent)
return;
++b->num_parents;
/* Protect this block from getting nuked if the realloc runs out of memory.*/
immortal = b->immortal;
b->immortal = TRUE;
b->parent = (Block **)xrealloc (b->parent,b->num_parents * sizeof (Block *));
b->parent[b->num_parents - 1] = parent;
/* Restore immortality state. */
b->immortal = immortal;
}
/* Removes PARENT from B's parent list. If PARENT is not already a member
* of B's parent list, no action is taken. If RECLAIM_MEMORY is true, then
* the parents list will be realloc'd to take as little memory as possible.
*/
void
block_remove_parent (Block *b, Block *parent, BOOL reclaim_memory)
{
int i;
for (i = b->num_parents - 1; i >= 0; i--)
if (b->parent[i] == parent)
{
--b->num_parents;
b->parent[i] = b->parent[b->num_parents];
if (reclaim_memory)
{
/* Protect this block from getting nuked by xrealloc. */
BOOL immortal = b->immortal;
b->immortal = TRUE;
b->parent = (Block **) xrealloc (b->parent, (b->num_parents
* sizeof (Block *)));
b->immortal = immortal;
}
break;
}
}
/* Adds CHILD to B's child list. If CHILD is already a member of B's
* child list, no action will be taken. Note that it is illegal to ever
* have more than two children at a time.
*/
void
block_add_child (Block *b, Block *child)
{
#ifdef DEBUG
/* Make sure they aren't trying to add a third child. */
assert (b->num_children <= 1);
#endif
b->child[b->num_children] = child;
++b->num_children;
}
/* Removes CHILD from B's child list. If CHILD is not a member of B's
* child list, no action will be taken.
*/
void
block_remove_child (Block *b, Block *child)
{
if (b->num_children != 0 && b->child[0] == child)
b->child[0] = b->child[1];
else if (b->num_children != 2 || b->child[1] != child)
return;
--b->num_children;
b->child[b->num_children] = NULL; /* Not strictly necessary. */
}
/* Applies a function F to each of B's parents. This function will receive
* a pointer to the parent block and AUX, which you can specify.
*/
void
block_do_for_each_parent (Block *b, void (*f)(Block *, void *), void *aux)
{
int i;
for (i = 0; i < b->num_parents; i++)
f (b->parent[i], aux);
}
#ifdef DEBUG
/* Debugging function, prints out all blocks whose checksums have changed
* and their addresses.
*/
unsigned long
block_changed_checksum ()
{
Block *b;
unsigned long num_diff;
num_diff = 0;
for (b = death_queue_head; b != NULL; b = b->death_queue_next)
if (compute_block_checksum (b) != b->checksum)
{
++num_diff;
printf ("m68k code checksum differs for block [0x%lX, 0x%lX]\n",
(unsigned long) b->m68k_start_address,
(unsigned long) (b->m68k_start_address
+ b->m68k_code_length - 1));
}
return num_diff;
}
/* Checks a block for internal consistency. If it appears to be OK,
* returns YES. Else it prints out appropriate error messages to stderr
* and returns NO.
*/
BOOL
block_verify (Block *b)
{
BOOL ok = YES;
#ifdef DEBUG
if (b->magic != BLOCK_MAGIC_VALUE)
{
fprintf (stderr, "Internal inconsistency: Block 0x%lX magic value "
"incorrect: 0x%lX, should be 0x%lX.\n",
b->m68k_start_address, b->magic, BLOCK_MAGIC_VALUE);
ok = NO;
}
#endif
#ifdef BLOCK_CHECKSUM
if (b->checksum != compute_block_checksum (b))
{
fprintf (stderr, "m68k checksum for block 0x%lX failed; "
"self-modifying code?\n",
b->m68k_start_address);
}
#endif
/* Check to see if child pointers are OK. */
switch (b->num_children) {
case 0:
break;
case 1:
if (b->child[0] == NULL)
{
fprintf (stderr, "Internal inconsistency: Block 0x%lX has 1 child, "
"child ptr 0 is NULL!\n", b->m68k_start_address);
ok = NO;
}
break;
case 2:
if (b->child[0] == NULL || b->child[1] == NULL)
{
fprintf (stderr, "Internal inconsistency: Block 0x%lX has two "
"children (%p, %p) yet both are not non-NULL!\n",
b->m68k_start_address, (void *) b->child[0],
(void *) b->child[1]);
ok = NO;
}
break;
default:
fprintf (stderr, "Internal inconsistency: Block 0x%lX has an illegal "
"# of children (%d)!\n", b->m68k_start_address, b->num_children);
ok = NO;
break;
}
{
int i, j;
for (i = 0; i < b->num_parents; i++)
{
Block *parent = b->parent[i];
if (parent == NULL)
{
fprintf (stderr, "Internal inconsistency: Block 0x%lX has "
"parent[%d] == NULL!\n",
b->m68k_start_address, i);
ok = NO;
}
else
{
for (j = i + 1; j < b->num_parents; j++)
if (parent == b->parent[j])
{
fprintf (stderr, "Internal inconsistency: Block 0x%lX "
"has parent[%d] == parent[%d] == %p!\n",
b->m68k_start_address, i, j,
(void *) b->parent[i]);
ok = NO;
}
/* Make sure our parent claims us as a child. */
for (j = parent->num_children - 1; j >= 0; j--)
if (parent->child[j] == b)
break;
if (j < 0)
{
fprintf (stderr, "Internal inconsistency: Block 0x%lX "
"has a parent that doesn't claims it as a child!\n",
b->m68k_start_address);
ok = NO;
}
}
}
for (i = 0; i < b->num_children; i++)
{
Block *child = b->child[i];
for (j = child->num_parents - 1; j >= 0; j--)
if (child->parent[j] == b)
break;
if (j < 0)
{
fprintf (stderr, "Internal inconsistency: Block 0x%lX has a child "
"that doesn't claim it as a parent!\n",
b->m68k_start_address);
ok = NO;
}
}
}
if (!ok)
abort ();
return ok;
}
#endif

283
runtime/blockinfo.c Normal file
View File

@ -0,0 +1,283 @@
#include "syn68k_private.h"
#include "block.h"
#include "mapping.h"
#include "rangetree.h"
#include "blockinfo.h"
#include "alloc.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
static void determine_next_block_addresses (const uint16 *code,
TempBlockInfo *temp,
const OpcodeMappingInfo *map);
/* This function takes a block and a pointer to some m68k code and computes
* the length of the block and various cc bit information about the block.
* The info is stored in the block struct.
*/
void
compute_block_info (Block *b, const uint16 *code, TempBlockInfo *temp)
{
const uint16 *start_code = code, *old_code;
int clobbered = 0, may_set = 0, may_not_set = ALL_CCS, needed = 0;
int next_array_size;
const OpcodeMappingInfo *map = NULL;
/* Initialize the next offset array. This lets us step through this
* code forwards when we actually get around to compiling it.
*/
temp->num_68k_instrs = 0;
next_array_size = 16;
temp->next_instr_offset = (int8 *) xmalloc (next_array_size * sizeof (int8));
/* Loop over all instructions in the block and determine information
* about how this block deals with CC bits.
*/
old_code = code;
do
{
int insn_size;
unsigned m68k_op;
m68k_op = READUW (US_TO_SYN68K (code));
map = &opcode_map_info[opcode_map_index[m68k_op]];
#if 0
if (opcode_map_index[m68k_op] == 0)
{
fprintf (stderr, "m68kop 0x%04X unimplemented!\n", m68k_op);
abort ();
}
#endif
insn_size = instruction_size (code, map);
if (insn_size <= 0)
{
map = &opcode_map_info[opcode_map_index[0x4AFC]]; /* illegal */
insn_size = 1;
}
/* Update cc bit info for this block. */
clobbered |= (map->cc_may_set
& ~(map->cc_may_not_set | map->cc_needed | needed));
needed |= map->cc_needed & may_not_set;
may_set |= map->cc_may_set;
may_not_set &= map->cc_may_not_set;
/* Grow next instruction offset array iff necessary. We'll
* leave one extra element for after this loop ends.
*/
if (temp->num_68k_instrs >= next_array_size - 1)
{
next_array_size *= 2;
temp->next_instr_offset = (int8 *) xrealloc (temp->next_instr_offset,
next_array_size
* sizeof (int8));
}
/* Remember offset to next instruction. */
temp->next_instr_offset[temp->num_68k_instrs++] = insn_size;
/* Move on to the next instruction. */
old_code = code;
code += insn_size;
}
while (!map->ends_block);
/* Terminate the array with a 0 offset. */
temp->next_instr_offset[temp->num_68k_instrs] = 0;
/* Figure out where this block goes (if possible). */
determine_next_block_addresses (old_code, temp, map);
/* Record the block information we've computed. */
b->cc_clobbered = clobbered;
b->cc_may_not_set = may_not_set;
b->cc_needed = needed;
b->m68k_start_address = US_TO_SYN68K (start_code);
b->m68k_code_length = (code - start_code) * sizeof (uint16);
}
static void
determine_next_block_addresses (const uint16 *code, TempBlockInfo *temp,
const OpcodeMappingInfo *map)
{
uint16 m68kop = READUW (US_TO_SYN68K (code));
BOOL is_bsr = ((m68kop >> 8) == 0x61);
BOOL is_fixed_jsr = ((m68kop & 0xFFFE) == 0x4EB8 /* jsr abs{w,l}? */
|| m68kop == 0x4EBA); /* jsr pc@d16? */
#ifdef DEBUG
temp->child[0] = temp->child[1] = US_TO_SYN68K (NULL);
#endif
/* First see if we can even tell where the child block is. */
if (map->next_block_dynamic && !is_bsr && !is_fixed_jsr)
{
temp->num_child_blocks = 0;
return;
}
/* Is it a Bcc? */
if ((m68kop >> 12) == 6)
{
uint32 t1, t2;
t1 = (uint32) (code + 1);
/* Compute branch target. */
if ((m68kop & 0xFF) == 0)
{
t1 += READSW (US_TO_SYN68K (code + 1));
t2 = (uint32) (code + 2);
}
else if ((m68kop & 0xFF) == 0xFF)
{
t1 += READSL (US_TO_SYN68K (code + 1));
t2 = (uint32) (code + 3);
}
else
{
t1 += ((int8 *)code)[1];
t2 = (uint32) (code + 1);
}
/* Is it a bsr or bra? If so, only one destination address. In the
* case of bsr, we compute the target address but officially pretend
* we don't know where it's going.
*/
if ((m68kop & 0xFE00) == 0x6000)
{
temp->child[0] = t1;
temp->num_child_blocks = !is_bsr;
return;
}
temp->child[0] = t2;
temp->child[1] = t1;
temp->num_child_blocks = 2;
return;
}
/* Is it a dbcc? */
if ((m68kop >> 12) == 5)
{
temp->child[0] = (uint32) (code + 2);
if ((m68kop >> 8) == 0x50) /* dbt? */
{
temp->num_child_blocks = 1;
return;
}
temp->child[1] = ((int32 ) (code + 1)
+ READSW (US_TO_SYN68K (code + 1)));
temp->num_child_blocks = 2;
return;
}
switch (m68kop)
{
case 0x4EF8: /* Is it a jmp _abs.w? */
temp->child[0] =
(uint32) SYN68K_TO_US (READSW (US_TO_SYN68K (code + 1)));
temp->num_child_blocks = 1;
return;
case 0x4EB8: /* Is it a jsr _abs.w? */
temp->child[0] =
(uint32) SYN68K_TO_US (READSW (US_TO_SYN68K (code + 1)));
temp->num_child_blocks = 0; /* Pretend we don't know the dest. */
return;
case 0x4EF9: /* Is it a jmp _abs.l? */
temp->child[0] =
(uint32) SYN68K_TO_US (READUL (US_TO_SYN68K (code + 1)));
temp->num_child_blocks = 1;
return;
case 0x4EB9: /* Is it a jsr _abs.l? */
temp->child[0] =
(uint32) SYN68K_TO_US (READUL (US_TO_SYN68K (code + 1)));
temp->num_child_blocks = 0;
return;
case 0x4EBA: /* Is it a pc-relative jsr? */
temp->child[0] = (uint32) ((READSW (US_TO_SYN68K (code + 1))
+ code + 1));
temp->num_child_blocks = 0;
return;
}
/* Strange, unknown block ender. Probably something capable of trapping.
* Assume that the subsequent instruction is the target.
*/
temp->child[0] = (uint32) (code + map->instruction_words);
temp->num_child_blocks = 1;
}
int
amode_size (int amode, const uint16 *code, int ref_size)
{
uint16 c = READUW (US_TO_SYN68K (code));
switch (amode) {
case 0x28: case 0x29: case 0x2A: case 0x2B: /* Addressing mode 5 */
case 0x2C: case 0x2D: case 0x2E: case 0x2F:
return 1;
case 0x38: /* 111/000 (xxx).W */
return 1;
case 0x39: /* 111/001 (xxx).L */
return 2;
case 0x3C: /* 111/100 #<data> */
return ref_size == 4 ? 2 : 1; /* Bytes still take 1 full word. */
case 0x30: case 0x31: case 0x32: case 0x33: /* Addressing mode 6. */
case 0x34: case 0x35: case 0x36: case 0x37:
case 0x3B: /* Addressing mode 111/011 */
if (!(c & 0x100)) /* 8 bit displacement. */
return 1;
else if ((c & 0xF) == 0x0)
return ((c >> 4) & 3);
return ((c >> 4) & 3) + (c & 3) - 1;
case 0x3A: /* 111/010 (d16,PC) */
return 1;
default:
return 0;
}
}
/* Given a pointer to an m68k opcode, returns the total number of words
* that instruction occupies, including operands and memory taken by
* complex addressing modes.
*/
int
instruction_size (const uint16 *code, const OpcodeMappingInfo *map)
{
int size;
int m68kop = READUW (US_TO_SYN68K (code));
/* See if we have a conditional branch format operand instruction. */
if ((m68kop >> 12) == 6)
{
if ((m68kop & 0xFF) == 0)
size = 2;
else if ((m68kop & 0xFF) == 0xFF)
size = 3;
else
size = 1;
}
else
{
size = map->instruction_words;
/* If we have an addressing mode, compute how many words it takes. */
if (map->amode_size != 0)
size += amode_size (m68kop & 0x3F, code + size, map->amode_size);
/* If we have a rev. addressing mode, compute how many words it takes. */
if (map->reversed_amode_size != 0) /* Is there a rev. addressing mode? */
size += amode_size (((m68kop >> 9) & 0x7) | ((m68kop >> 3) & 0x38),
code + size, map->reversed_amode_size);
}
return size;
}

186
runtime/callback.c Normal file
View File

@ -0,0 +1,186 @@
#include "callback.h"
#include "rangetree.h"
#include "block.h"
#include "alloc.h"
#include "hash.h"
#include "destroyblock.h"
#include "deathqueue.h"
#include "checksum.h"
#include "translate.h"
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct {
callback_handler_t func;
void *arg;
} CallBackInfo;
CallBackInfo *callback;
int num_callback_slots;
int lowest_free_callback_slot;
/* We just use this array to reserve some dereferenceable address
* space to hold the callbacks, because we need memory locations we
* know can never contain 68k code. We don't actually store anything
* there.
*/
uint16 callback_dummy_address_space[MAX_CALLBACKS + CALLBACK_SLOP];
void
callback_init (void)
{
callback = NULL;
num_callback_slots = 0;
lowest_free_callback_slot = 0;
}
/* Installs a given callback function at a given 68k address. If the 68k
* ever executes code at that address, the callback function will be called
* and provided with the 68k address of the callback and an arbitrary
* 32 bit argument. If some block is already present at the specified
* address, does nothing and returns 0. Otherwise, returns 1.
*/
int
callback_compile (Block *parent, syn68k_addr_t m68k_address, Block **new)
{
Block *b;
uint16 *code;
uint32 ix = (m68k_address - CALLBACK_STUB_BASE) / sizeof (uint16);
const CallBackInfo *callback_info = &callback[ix];
/* Make sure a callback is actually installed. */
if (ix >= num_callback_slots || callback_info->func == NULL)
{
*new = NULL;
return 0;
}
b = *new = make_artificial_block (parent, m68k_address,
OPCODE_WORDS + PTR_WORDS + PTR_WORDS + 2,
&code);
/* Create the synthetic code for the callback. */
#ifdef USE_DIRECT_DISPATCH
*(const void **)code = direct_dispatch_table[0xB3]; /* callback opcode. */
#else
*(void **)code = (void *)0xB3; /* Magical callback synthetic opcode. */
#endif
*((callback_handler_t *) (code + OPCODE_WORDS)) = callback_info->func;
*(void **)(code + OPCODE_WORDS + PTR_WORDS) = callback_info->arg;
*(syn68k_addr_t *)(code + OPCODE_WORDS + PTR_WORDS + PTR_WORDS)
= m68k_address;
/* Insert block into the universe of blocks. */
hash_insert (b);
range_tree_insert (b);
/* Add this block to the end of the death queue. */
death_queue_enqueue (b);
b->immortal = FALSE;
return ALL_CCS;
}
/* Installs a callback stub in the 68k space and returns the 68k address
* it chose for this stub. Any 68k code that hits this stub will call
* the specified callback function. func must never be NULL.
*/
syn68k_addr_t
callback_install (callback_handler_t func, void *arbitrary_argument)
{
uint32 slot;
int old_sigmask;
BLOCK_INTERRUPTS (old_sigmask);
slot = lowest_free_callback_slot;
if (lowest_free_callback_slot >= num_callback_slots)
{
if (num_callback_slots >= MAX_CALLBACKS)
{
fprintf (stderr, "Internal error: syn68k out of callback slots!\n");
abort ();
}
++num_callback_slots;
callback = (CallBackInfo *) xrealloc (callback, (num_callback_slots
* sizeof callback[0]));
}
/* Remember the callback they are specifying. */
callback[slot].func = func;
callback[slot].arg = arbitrary_argument;
/* Move lowest free callback slot to next lowest slot. */
for (lowest_free_callback_slot++; ; lowest_free_callback_slot++)
if (lowest_free_callback_slot >= num_callback_slots
|| callback[lowest_free_callback_slot].func == NULL)
break;
/* Reenable interrupts. */
RESTORE_INTERRUPTS (old_sigmask);
return CALLBACK_STUB_BASE + (slot * sizeof (uint16));
}
void *
callback_argument (syn68k_addr_t callback_address)
{
uint32 ix = (callback_address - CALLBACK_STUB_BASE) / sizeof (uint16);
if (ix >= num_callback_slots)
return NULL;
return callback[ix].arg;
}
callback_handler_t
callback_function (syn68k_addr_t callback_address)
{
uint32 ix = (callback_address - CALLBACK_STUB_BASE) / sizeof (uint16);
if (ix >= num_callback_slots)
return NULL;
return callback[ix].func;
}
void
callback_remove (syn68k_addr_t m68k_address)
{
uint32 ix;
Block *b;
int old_sigmask;
BLOCK_INTERRUPTS (old_sigmask);
/* Fetch the block at that address. */
b = hash_lookup (m68k_address);
if (b != NULL)
destroy_block (b);
ix = (m68k_address - CALLBACK_STUB_BASE) / sizeof (uint16);
if (ix < num_callback_slots)
{
if (ix == num_callback_slots - 1)
{
--num_callback_slots;
callback = (CallBackInfo *) xrealloc (callback,
(num_callback_slots
* sizeof callback[0]));
}
else
{
callback[ix].func = NULL;
if (ix < lowest_free_callback_slot)
lowest_free_callback_slot = ix;
}
}
RESTORE_INTERRUPTS (old_sigmask);
}

11
runtime/checksum.c Normal file
View File

@ -0,0 +1,11 @@
#define INLINE_CHECKSUM
#include "checksum.h"
#ifdef CHECKSUM_BLOCKS
uint32
compute_block_checksum (const Block *b)
{
return inline_compute_block_checksum (b);
}
#endif /* CHECKSUM_BLOCKS */

49
runtime/deathqueue.c Normal file
View File

@ -0,0 +1,49 @@
#include "deathqueue.h"
Block *death_queue_head = NULL, *death_queue_tail = NULL;
/* Appends a block to the end of the doubly-linked death queue. */
void
death_queue_enqueue (Block *b)
{
b->death_queue_prev = death_queue_tail;
b->death_queue_next = NULL;
if (death_queue_tail == NULL)
death_queue_head = b;
else
death_queue_tail->death_queue_next = b;
death_queue_tail = b;
}
/* Removes a block from the end of the doubly-linked death queue. */
void
death_queue_dequeue (Block *b)
{
Block *p, *n;
p = b->death_queue_prev;
n = b->death_queue_next;
if (p == NULL)
{
if (death_queue_head == b) /* Verify this just to be safe. */
death_queue_head = n;
}
else
p->death_queue_next = n;
if (n == NULL)
{
if (death_queue_tail == b) /* Verify this just to be safe. */
death_queue_tail = p;
}
else
n->death_queue_prev = p;
b->death_queue_prev = b->death_queue_next = NULL;
}

268
runtime/destroyblock.c Normal file
View File

@ -0,0 +1,268 @@
#include "destroyblock.h"
#include "deathqueue.h"
#include "alloc.h"
#include "hash.h"
#include "rangetree.h"
#include "translate.h"
#define INLINE_CHECKSUM /* Get the fast, inline version. */
#include "checksum.h"
#include <assert.h>
#include <signal.h>
#include <string.h>
/* Temp hack */
#include <stdio.h>
static Block *current_block_in_death_queue;
/* This routine destroys a block and any known parents of this block (and
* so on recursively). Returns the total number of blocks actually destroyed.
*/
unsigned long
destroy_block (Block *b)
{
unsigned long num_destroyed;
int i;
/* If the block is immortal, refuse to destroy it. FIXME? */
if (b->immortal)
return 0;
/* Be paranoid, to avoid freeing this block multiple times. */
b->immortal = TRUE;
/* Call the user-defined function to let them know we're busy. */
if (call_while_busy_func != NULL)
call_while_busy_func (1);
/* Make sure no children claim us as a parent to prevent bad things
* happening on recursion.
*/
for (i = b->num_children - 1; i >= 0; i--)
if (b->child[i] != NULL)
block_remove_parent (b->child[i], b, FALSE);
/* Destroy all of our parents. This should not be able to recurse
* around to us again since none of our children now claim us as a parent.
*/
num_destroyed = 0;
while (b->num_parents != 0)
{
--b->num_parents;
num_destroyed += destroy_block (b->parent[b->num_parents]);
}
range_tree_remove (b);
hash_remove (b);
/* Maintain current_block_in_death_queue so we can safely traverse the
* death queue destroying everyone. Otherwise, we'd lose our place in the
* queue when we destroyed a bunch of blocks.
*/
if (b == current_block_in_death_queue)
current_block_in_death_queue = b->death_queue_next;
/* Remove this block from the death queue. */
assert (death_queue_head != NULL);
death_queue_dequeue (b);
block_free (b);
return num_destroyed + 1; /* Account for the one we just freed. */
}
/* This routine calls destroy_block() for all blocks which came from m68k
* code intersecting the specified range of addresses. Returns the total
* number of blocks destroyed.
*/
#ifdef CHECKSUM_BLOCKS
static unsigned long
destroy_blocks_maybe_checksum (syn68k_addr_t low_m68k_address,
uint32 num_bytes, BOOL checksum_blocks)
#else
static unsigned long
destroy_blocks (syn68k_addr_t low_m68k_address, uint32 num_bytes)
#endif
{
Block *b;
int old_sigmask;
unsigned long total_destroyed;
BLOCK_INTERRUPTS (old_sigmask);
total_destroyed = 0;
/* Special case destroying all blocks. This happens often in HyperCard. */
if (low_m68k_address == 0 && num_bytes == (uint32)~0)
{
if (!checksum_blocks)
{
for (b = death_queue_head; b != NULL; )
{
unsigned long ndest;
current_block_in_death_queue = b;
ndest = destroy_block (b);
if (ndest != 0)
{
total_destroyed += ndest;
b = current_block_in_death_queue; /* Has advanced. */
}
else
b = b->death_queue_next;
}
}
else
{
for (b = death_queue_head; b != NULL; )
{
if (b->checksum != inline_compute_block_checksum (b))
{
unsigned long ndest;
current_block_in_death_queue = b;
ndest = destroy_block (b);
if (ndest != 0)
{
total_destroyed += ndest;
b = current_block_in_death_queue; /* Has advanced. */
}
else
b = b->death_queue_next;
}
else
b = b->death_queue_next;
}
}
}
else /* Destroy only selected range. */
{
syn68k_addr_t end = low_m68k_address + num_bytes - 1;
syn68k_addr_t next_addr;
/* Loop over blocks in the specified range and destroy them. */
for (b = range_tree_first_to_intersect (low_m68k_address, end);
b != NULL && b->m68k_start_address <= end;
b = range_tree_find_first_at_or_after (next_addr))
{
next_addr = b->m68k_start_address + 1;
#ifdef CHECKSUM_BLOCKS
if (!checksum_blocks
|| b->checksum != inline_compute_block_checksum (b))
#endif /* CHECKSUM_BLOCKS */
{
total_destroyed += destroy_block (b);
}
}
}
/* Smash the jsr stack if we destroyed any blocks. */
if (total_destroyed > 0)
memset (&cpu_state.jsr_stack, -1, sizeof cpu_state.jsr_stack);
RESTORE_INTERRUPTS (old_sigmask);
/* Call the user-defined function to let them know we're not busy. */
if (call_while_busy_func != NULL)
call_while_busy_func (0);
return total_destroyed;
}
#ifdef CHECKSUM_BLOCKS
/* Always destroys blocks in the specified range. */
unsigned long
destroy_blocks (syn68k_addr_t low_m68k_address, uint32 num_bytes)
{
return destroy_blocks_maybe_checksum (low_m68k_address, num_bytes, FALSE);
}
/* Only destroys blocks in the specified range if their m68k checksums fail. */
unsigned long
destroy_blocks_with_checksum_mismatch (syn68k_addr_t low_m68k_address,
uint32 num_bytes)
{
return destroy_blocks_maybe_checksum (low_m68k_address, num_bytes, TRUE);
}
#endif /* CHECKSUM_BLOCKS */
static BOOL
immortal_self_or_ancestor_aux (Block *b)
{
int i;
if (!b->recursive_mark)
{
if (b->immortal)
return TRUE;
b->recursive_mark = TRUE;
for (i = b->num_parents - 1; i >= 0; i--)
if (immortal_self_or_ancestor_aux (b->parent[i]))
return TRUE;
}
return FALSE;
}
static void
clear_recursive_marks (Block *b)
{
int i;
if (!b->recursive_mark)
return;
b->recursive_mark = FALSE;
for (i = b->num_parents - 1; i >= 0; i--)
clear_recursive_marks (b->parent[i]);
}
static BOOL
immortal_self_or_ancestor (Block *b)
{
BOOL val = immortal_self_or_ancestor_aux (b);
clear_recursive_marks (b);
return val;
}
/* Call this only when you are out of memory. This routine selects
* one or more blocks to destroy and destroys them, freeing up their
* memory. Returns the number of blocks actually freed. Can only
* destroy blocks that are not immortal and have no immortal
* ancestors, and will destroy the oldest such block (and all of its
* ancestors) that it finds.
*/
unsigned long
destroy_any_block ()
{
Block *kill;
/* Find a block to slaughter. Prefer someone with no parents*/
for (kill = death_queue_head; kill != NULL; kill = kill->death_queue_next)
if (!immortal_self_or_ancestor (kill))
break;
if (kill != NULL)
{
unsigned long num_destroyed;
num_destroyed = destroy_block (kill);
assert (num_destroyed != 0);
memset (&cpu_state.jsr_stack, -1, sizeof cpu_state.jsr_stack);
/* Call the user-defined function to let them know we're not busy. */
if (call_while_busy_func != NULL)
call_while_busy_func (0);
return num_destroyed;
}
return 0;
}

83
runtime/diagnostics.c Normal file
View File

@ -0,0 +1,83 @@
#include "diagnostics.h"
#include "deathqueue.h"
void
print_cc_bits (FILE *stream, int bits)
{
int i;
for (i = 4; i >= 0; i--)
if (bits & (1 << i))
putc ("ZXVNC"[i], stream);
else putc ('-', stream);
}
void
hexdump (const uint16 *addr, int num_words)
{
while (num_words--)
printf ("\t0x%04X\n", (unsigned) *addr++);
}
void
dump_cpu_state (void)
{
int i;
for (i = 0; i < 16; i++)
{
#if !defined(__alpha)
printf ("%c%d = 0x%08lX ", "da"[i >> 3], i % 8, cpu_state.regs[i].ul.n);
#else
printf ("%c%d = 0x%08X ", "da"[i >> 3], i % 8, cpu_state.regs[i].ul.n);
#endif
if ((i & 3) == 3)
fputs ("\n\t", stdout);
}
printf ("c:%d n:%d v:%d x:%d z:%d\n",
!!cpu_state.ccc, !!cpu_state.ccn, !!cpu_state.ccv, !!cpu_state.ccx,
!cpu_state.ccnz);
putchar ('\n');
}
/* Given a PC (either synthetic or native), tries to find the m68k
* block corresponding to that PC and prints it out. For debugging.
*/
void
m68kaddr (const uint16 *pc)
{
const Block *b, *best_block;
unsigned long best_error;
best_error = 0xFFFFFFFF;
best_block = NULL;
for (b = death_queue_head; b != NULL; b = b->death_queue_next)
{
if (b->compiled_code <= pc)
{
unsigned long error = pc - b->compiled_code;
if (error < best_error)
{
best_error = error;
best_block = b;
}
}
}
if (best_block == NULL)
{
puts ("No matching m68k block found.");
}
else
{
printf ("Best guess m68k block start address 0x%lx, offset %lu bytes, "
"block (Block *)%p\n",
(unsigned long) best_block->m68k_start_address,
best_error, (void *) best_block);
}
}

48
runtime/dosinterrupts.c Normal file
View File

@ -0,0 +1,48 @@
#ifdef MSDOS
#include "syn68k_private.h"
#ifndef SYNCHRONOUS_INTERRUPTS
int
dos_block_interrupts ()
{
unsigned long iflag;
asm ("pushfl\n\t" /* We save the old eflags, which has interrupt mask bit. */
"popl %0\n\t"
"shrl $9,%0\n\t"
"andl $1,%0\n\t"
"jz 1f\n\t" /* Avoid CLI overhead under DPMI. */
"cli\n"
"1:"
: "=r" (iflag)
: : "cc");
return iflag;
}
void
dos_restore_interrupts (int onoff)
{
unsigned long current_iflag;
asm ("pushfl\n\t" /* We save the old eflags, which has interrupt mask bit. */
"popl %0\n\t"
"shrl $9,%0\n\t"
"andl $1,%0"
: "=r" (current_iflag)
: : "cc");
if (onoff != current_iflag)
{
/* Only execute these when necessary, to avoid DPMI overhead. */
if (onoff)
asm ("sti");
else
asm ("cli");
}
}
#endif /* !SYNCHRONOUS_INTERRUPTS */
#endif /* MSDOS */

177
runtime/fold.pl Executable file
View File

@ -0,0 +1,177 @@
#!/usr/bin/perl
$* = 1; # Enable multi-line patterns
print STDERR "Parsing file...";
# Read the entire file into core, splitting it up into pseudo-basic blocks
while (<>){
next if /^\s*$/; # Skip blank lines
if (/\s*\.align/ || !$started)
{
if ($current_block)
{
push (@blocks, $current_block);
push (@block_names, $current_block_name);
}
$current_block = $_;
$current_block_name = "";
$started = 1;
}
elsif ($current_block && !$current_block_name && /^\w.*:$/)
{
$current_block .= "xx#BLOCK_NAME_HERE\n";
$current_block_name = $_;
chop $current_block_name;
$current_block_name =~ s/://g;
}
elsif ($current_block)
{
# Note: we don't add the name of the block to the block itself.
$current_block .= $_;
}
}
# Clean up any stuff left around at end of file
if ($current_block)
{
push (@blocks, $current_block);
push (@block_names, $current_block_name);
}
print STDERR "done.\n";
sub eliminate_duplicates
{
local (%blocks_found, $old, $new, $old_name, $new_name, $b, $bname, $n,
$x, $clobbered_blocks, $clobbered_lines, @clobbered_old,
@clobbered_new, @clobbered_old_s68k, @clobbered_new_s68k,
@clobbered_old_non_s68k, @clobbered_new_non_s68k);
print STDERR "Pass $pass:\t";
# Loop over all the blocks, looking for duplicates.
$new = 0;
$clobbered_blocks = 0;
$clobbered_lines = 0;
foreach $old (0 .. $#blocks)
{
$b = $blocks[$old];
$bname = $block_names[$old];
# If this block is redundant, add it to the clobbered list.
if ($bname && $blocks_found{$b})
{
# Create regexps for the old/new to replace
$old_name = $bname; $old_name =~ s/(\W)/\\$1/g;
$new_name = $blocks_found{$b}; $new_name =~ s/(\W)/\\$1/g;
push (@clobbered_old, $old_name);
push (@clobbered_new, $new_name);
$clobbered_blocks++;
$clobbered_lines += split (' ', $b);
}
else # Save this block
{
$blocks[$new] = $b;
$block_names[$new] = $bname;
$blocks_found{$b} = $bname;
$new++;
}
}
# Print out a status report.
print STDERR "eliminating $clobbered_blocks/", $#blocks + 1, " blocks ",
"($clobbered_lines lines)...";
# If we found something to clobber, clean everything up.
if ($clobbered_blocks)
{
# Truncate the blocks array to the new number of blocks.
$#blocks = $new - 1;
$#block_names = $new - 1;
# Divide up the replace strings into two classes, for speed.
foreach $n (0 .. $#clobbered_old)
{
if (@clobbered_old[$n] =~ /_S68K_/)
{
push (@clobbered_old_s68k, @clobbered_old[$n]);
push (@clobbered_new_s68k, @clobbered_new[$n]);
}
else
{
push (@clobbered_old_non_s68k, @clobbered_old[$n]);
push (@clobbered_new_non_s68k, @clobbered_new[$n]);
}
}
foreach $n (0 .. $#blocks)
{
# Dump out this block if it's unique or special.
if (!$block_names[$n]
|| $blocks_found{@blocks[$n]} eq $block_names[$n])
{
$b = $blocks[$n];
$b =~ s/xx#BLOCK_NAME_HERE/$block_names[$n]:/g;
# Replace any _S68K_ labels (if there are any here).
if ($b =~ /_S68K_/)
{
foreach $x (0 .. $#clobbered_old_s68k)
{
$old_name = $clobbered_old_s68k[x];
$new_name = $clobbered_new_s68k[x];
if ($b =~ /$old_name/)
{
$b =~ s/$old_name,/$new_name,/g;
$b =~ s/$old_name$/$new_name$/g;
# If we didn't eliminate the old label, fail!
die "I'm afraid to replace \"$old_name\" in this ",
"block:\n", $b if ($b =~ /$old_name/);
}
}
}
# Replace any non-_S68K_ labels.
foreach $x (0 .. $#clobbered_old_non_s68k)
{
$old_name = $clobbered_old_non_s68k[x];
$new_name = $clobbered_new_non_s68k[x];
if ($b =~ /$old_name/)
{
$b =~ s/$old_name,/$new_name,/g;
$b =~ s/$old_name$/$new_name$/g;
# If we didn't eliminate the old label, fail!
die "I'm afraid to replace \"$old_name\" in this ",
"block:\n", $b if ($b =~ /$old_name/);
}
}
$blocks[$n] = $b;
}
}
}
print STDERR "done.\n";
return $clobbered_blocks;
}
# Keep eliminating duplicates until nothing changes.
$pass = 1;
while (&eliminate_duplicates ())
{
$pass++;
}
# Print out all of the blocks.
foreach $n (0 .. $#blocks)
{
print $blocks[$n];
}

227
runtime/hash.c Normal file
View File

@ -0,0 +1,227 @@
/*
* hash.c - Routines for manipulating a hash table that maps 68k addresses
* to the basic block that begins at that address. This exists
* in addition to the range tree because runtime lookups are much
* faster.
*/
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include "hash.h"
#include "alloc.h"
#include "translate.h"
/* Fixed size hash table, indexed by BLOCK_HASH (block->m68k_start_address). */
Block *block_hash_table[NUM_HASH_BUCKETS];
/* Initializes the hash table. Call this before calling any other hash
* functions, and call it exactly once.
*/
void
hash_init ()
{
memset (block_hash_table, 0, sizeof block_hash_table);
}
/* Removes all blocks from the hash table and deallocates all space used by
* the hash table.
*/
void
hash_destroy ()
{
Block *b, *next;
int i;
/* Remove all Blocks from the hash table. */
for (i = 0; i < NUM_HASH_BUCKETS; i++)
for (b = block_hash_table[i]; b != NULL; b = next)
{
next = b->next_in_hash_bucket;
b->next_in_hash_bucket = NULL;
}
memset (block_hash_table, 0, sizeof block_hash_table);
}
/* Finds the block associated with a given 68k address and returns a pointer
* to that block. Returns NULL iff no block starting at that address exists.
* Note that it is possible the address specified may fall inside a block of
* compiled code but not at the beginning; this routine will not detect that
* situation. If you want to know what block contains a given address when
* that address may not refer to the first byte of a block, call the slower
* range_tree_lookup (addr) function found in rangetree.c
*/
Block *
hash_lookup (syn68k_addr_t addr)
{
Block *bucket = block_hash_table[BLOCK_HASH (addr)];
for (; bucket != NULL; bucket = bucket->next_in_hash_bucket)
if (bucket->m68k_start_address == addr)
return bucket;
return NULL;
}
/* Similar to hash_lookup(), but this returns a pointer to the compiled
* code associated with a given 68k address instead of to the block associated
* with that code. If no compiled code exists for that block, code is
* compiled for that block and a pointer to the new code is returned. This
* function is guaranteed to return a non-NULL pointer to valid code.
*/
const uint16 *
hash_lookup_code_and_create_if_needed (syn68k_addr_t addr)
{
Block *b, *bucket, **bucket_ptr;
int old_sigmask;
bucket_ptr = &block_hash_table[BLOCK_HASH (addr)];
bucket = *bucket_ptr;
/* If there's anything in this bucket, check for a match. */
if (bucket != NULL)
{
Block *prev, *next;
/* See if we get a match in the first element. */
if (bucket->m68k_start_address == addr)
return bucket->compiled_code;
/* See if we get a match in a later element. If we do, move it
* to the head of the list, since it is likely to be referenced
* again.
*/
for (prev = bucket; (next = prev->next_in_hash_bucket) != NULL;
prev = next)
{
if (next->m68k_start_address == addr)
{
BLOCK_INTERRUPTS (old_sigmask);
prev->next_in_hash_bucket = next->next_in_hash_bucket;
next->next_in_hash_bucket = bucket;
*bucket_ptr = next;
RESTORE_INTERRUPTS (old_sigmask);
return next->compiled_code;
}
}
}
BLOCK_INTERRUPTS (old_sigmask);
generate_block (NULL, addr, &b, FALSE);
RESTORE_INTERRUPTS (old_sigmask);
/* Call the user-defined function to let them know we're done. */
if (call_while_busy_func != NULL)
call_while_busy_func (0);
return b->compiled_code;
}
/* Inserts a given block into the hash table based on it's m68k_start_address.
* Inserting a block twice is illegal but is not checked for.
*/
void
hash_insert (Block *b)
{
uint32 addr = b->m68k_start_address;
Block **bucket = &block_hash_table[BLOCK_HASH (addr)];
/* Prepend this block to the beginning of the list. */
b->next_in_hash_bucket = *bucket;
*bucket = b;
}
/* Removes a given block from the hash table. If it's not in the hash
* table, no action is taken.
*/
void
hash_remove (Block *b)
{
Block **bucket = &block_hash_table[BLOCK_HASH (b->m68k_start_address)];
for (; *bucket != NULL; bucket = &(*bucket)->next_in_hash_bucket)
if (*bucket == b)
{
*bucket = b->next_in_hash_bucket;
break;
}
}
#ifdef DEBUG
/* Runs through and checks the hash table for consistency. Returns YES
* if everything is OK, NO if something is bad (in which case it prints
* out appropriate errors to stderr.)
*/
BOOL
hash_verify ()
{
BOOL ok = YES;
int i;
Block *b, *b2;
for (i = 0; i < NUM_HASH_BUCKETS; i++)
for (b = block_hash_table[i]; b != NULL; b = b->next_in_hash_bucket)
{
if (!block_verify (b))
ok = NO;
if (BLOCK_HASH (b->m68k_start_address) != i)
{
fprintf (stderr, "Internal inconsistency: Block 0x%lX seems to "
"have ended up in hash bucket %d instead of hash "
"bucket %d where it belongs.\n",
b->m68k_start_address, i,
BLOCK_HASH (b->m68k_start_address));
ok = NO;
}
for (b2 = b->next_in_hash_bucket; b2; b2 = b2->next_in_hash_bucket)
if (b->m68k_start_address == b2->m68k_start_address)
{
fprintf (stderr, "Internal inconsistency: More than one block "
"in the hash table has the same m68k_start_address "
"(0x%lX).\n", b->m68k_start_address);
ok = NO;
break;
}
}
return ok;
}
#endif
#ifdef DEBUG
void
hash_stats ()
{
int i, max = 0, sum = 0;
for (i = 0; i < NUM_HASH_BUCKETS; i++)
{
int n;
Block *b;
for (n = 0, b = block_hash_table[i]; b != NULL; n++,
b = b->next_in_hash_bucket);
if (n > max)
max = n;
sum += n;
}
printf ("Hash stats: %d entries, %.2f average per bucket, %d in deepest "
"bucket.\n",
sum, (double) sum / NUM_HASH_BUCKETS, max);
}
#endif

36
runtime/i486-cleanup.pl Executable file
View File

@ -0,0 +1,36 @@
#!/usr/bin/perl -ni
# This perl script strips out the extra cruft created as a side effect of
# splitting syn68k.c into many functions. This will make the resulting
# syn68k.o file smaller and also force the real branch targets to be
# aligned optimally.
# Delete the header for each function
if (/^\.globl _s68k_handle_opcode_0x/ .. /^[#\/]APP$/)
{
print if (/^[#\/]APP/ || /^L/);
}
# Delete the trailer for each function
elsif (/^_S68K_DONE_WITH/ .. /^\s*ret$/)
{
print if (!/\s*movl %ebp,%esp$/
&& !/\s*leal\s*(-?\d+)?\(%ebp\),%esp$/
&& !/\s*movl\s*(-?\d+)?\(%ebp\),%edi$/
&& !/\s*popl/
&& !/\s*ret$/
&& !/^_S68K_DONE_WITH/
&& !/s68k_handle_opcode/);
}
elsif (/^\s*lods/)
{
die "lods not allowed; we're punting cld's these days.";
}
# elsif (/^\s*call/ && !/s68k_handle_opcode/)
# { # no longer necessary since we punted lodsl
# print "$_\tcld\n";
# }
elsif (!/s68k_handle_opcode/)
{
print;
}

69
runtime/i486-optimize.pl Executable file
View File

@ -0,0 +1,69 @@
#!/usr/bin/perl -ni
chop;
next if (/^[\#\/](NO_)?APP/ || /^\s*$/);
$cur = $_;
$first_changed = 0;
# First we handle mapping cases like:
# _S68K_HANDLE_0x00B5:
# movw _cpu_state+4,%ax
# movw (%esi),%bx
#
# to:
#
# _S68K_HANDLE_0x00B5:
# movl _cpu_state+4,%eax
# movl (%esi),%ebx
#
# Because we know cpu_state and %esi-relative pointers will be long-aligned,
# and long ops are faster and more pairable than word ops.
if ($prev_first_changed
&& ((($mem, $reg) = /^\s*movw (_cpu_state\+?\d*),%(ax|bx|cx|dx|di)$/)
|| (($mem, $reg) = /^\s*movw (\d*\(%esi\)),%(ax|bx|cx|dx|di)$/))
&& ($prev !~ /$reg/)) {
$cur = "\tmovl " . $mem . ",%e" . $reg;
}
if ($prev =~ /^_S68K_HANDLE_/) {
if ((($mem, $reg) = /^\s*mov[wl] (_cpu_state\+?\d*),%e?(ax|bx|cx|dx|di)$/)
|| (($mem, $reg) = /^\s*mov[wl] (\d*\(%esi\)),%e?(ax|bx|cx|dx|di)$/)) {
$cur = "\tmovl " . $mem . ",%e" . $reg;
$first_changed = 1;
}
}
# Next we'll handle brain damage like:
# movl %eax,_cpu_state+80
# movl _cpu_state+80,%eax
#
# by deleting the second line. Yes, this really happens.
# We have to be conservative here so we don't botch cases like:
# movb _cpu_state(%eax),%al
# movb %al,_cpu_state(%eax)
if (((($size1, $src1, $dst1)
= ($prev =~ /^\s+mov([bwl])\s+(_cpu_state\+?\d*),\s*(%[a-z]+)$/))
|| (($size1, $src1, $dst1)
= ($prev =~ /^\s+mov([bwl])\s+(%[a-z]+),\s*(_cpu_state\+?\d*)$/))
|| (($size1, $src1, $dst1)
= ($prev =~ /^\s+mov([bwl])\s+(-?\d*\(%ebp\)),\s*(%[a-z]+)$/))
|| (($size1, $src1, $dst1)
= ($prev =~ /^\s+mov([bwl])\s+(%[a-z]+),\s*(-?\d*\(%ebp\))$/)))
&& (($size2, $src2, $dst2)
= /^\s+mov([bwl])\s+([^,]+),\s*([^,]+)$/)
&& ($size1 eq $size2)
&& ($src1 eq $dst2)
&& ($src2 eq $dst1)) {
# This second line is completely useless, so delete it.
$cur = "";
}
if (!($cur eq "")) {
print $cur . "\n";
}
$prev = $cur;
$prev_first_changed = $first_changed;

10
runtime/include/alloc.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef _alloc_h_
#define _alloc_h_
#include <stddef.h> /* typedef size_t */
extern void *xmalloc (size_t size);
extern void *xrealloc (void *old, size_t new_size);
extern void *xcalloc (size_t num_elems, size_t byte_size);
#endif /* Not _alloc_h_ */

View File

@ -0,0 +1,21 @@
#ifndef _backpatch_h_
#define _backpatch_h_
typedef struct _backpatch_t
{
struct _backpatch_t *next; /* Next in linked list. */
int32 offset_location; /* Bit index from block to index start. */
int32 const_offset; /* Add this to src addr. */
int8 num_bits; /* Number of bits to be patched. */
int8 relative_p; /* Boolean: relative offset? */
struct _Block *target; /* Target block; we jmp to its code ptr. */
} backpatch_t;
extern void backpatch_apply_and_free (struct _Block *b, backpatch_t *p);
extern void backpatch_add (struct _Block *b, int offset_location, int num_bits,
BOOL relative_p, int const_offset,
struct _Block *target);
#include "block.h"
#endif /* !_backpatch_h_ */

62
runtime/include/block.h Normal file
View File

@ -0,0 +1,62 @@
#ifndef _block_h_
#define _block_h_
#define BLOCK_MAGIC_VALUE 0xDEADBABEUL
#include "syn68k_private.h" /* To typedef uint16 and uint32. */
#include "backpatch.h"
struct _Block {
struct _Block *next_in_hash_bucket; /* Next Block in this hash bucket. */
const uint16 *compiled_code; /* Memory containing compiled code. */
#ifdef GENERATE_NATIVE_CODE
uint32 num_times_called; /* # of times nonnative code called. */
#endif
struct _Block *death_queue_prev; /* Prev block to be nuked if mem needed. */
struct _Block *death_queue_next; /* Next block to be nuked if mem needed. */
struct _Block *range_tree_left; /* Left child in range tree. */
struct _Block *range_tree_right; /* Right " " " " (see rangetree.c) */
struct _Block *range_tree_parent; /* Parent in r-tree (see rangetree.c) */
struct _Block **parent; /* Array of ptrs to parent blocks. */
struct _Block *child[2]; /* Array of ptrs to child blocks. */
syn68k_addr_t m68k_start_address; /* Starting address of 68k code. */
#ifdef CHECKSUM_BLOCKS
uint32 checksum; /* Checksum of m68k code for this block. */
#endif
uint32 m68k_code_length; /* Length of 68k code, in _bytes_. */
uint32 range_tree_color :1; /* Either RED or BLACK. */
uint32 cc_clobbered :5; /* CC bits modified before use. */
uint32 cc_may_not_set :5; /* CC bits that may be changed. */
uint32 cc_needed :5; /* CC bits whose values we need. */
uint32 num_children :2; /* # of blocks that this feeds to. */
uint32 immortal :1; /* Can't be freed to save space. */
uint32 recursive_mark :1; /* 1 means hit during this recursion. */
#ifdef GENERATE_NATIVE_CODE
uint32 recompile_me :1; /* Recompile me as native (temp. flag). */
#endif /* GENERATE_NATIVE_CODE */
uint16 malloc_code_offset:3; /* Pass compiled_code - this to free(). */
uint16 num_parents :13; /* # of blocks that feed into this one. */
backpatch_t *backpatch; /* Linked list of backpatches to apply. */
#ifdef DEBUG /* to ptr to the specified child block. */
uint32 magic;
#endif
};
typedef struct _Block Block;
/* Function prototypes. */
extern Block *block_new (void);
extern void block_free (Block *b);
extern void block_add_parent (Block *b, Block *parent);
extern void block_remove_parent (Block *b, Block *parent, BOOL reclaim_memory);
extern void block_add_child (Block *b, Block *child);
extern void block_remove_child (Block *b, Block *child);
extern void block_do_for_each_parent (Block *b, void (*f)(Block *, void *),
void *aux);
#ifdef DEBUG
extern BOOL block_verify (Block *b);
extern void dump_block (const Block *b);
#endif
#endif /* Not _block_h_ */

View File

@ -0,0 +1,18 @@
#ifndef _blockinfo_h_
#define _blockinfo_h_
#include "block.h"
typedef struct {
uint32 child[2]; /* m68k addresses of m68k code following this blk. */
int16 num_child_blocks; /* # of child addrs we can know at translate time. */
uint16 num_68k_instrs;
int8 *next_instr_offset; /* word offset to next instr; 0 iff last instr. */
} TempBlockInfo;
extern void compute_block_info (Block *b, const uint16 *code,
TempBlockInfo *temp);
extern int amode_size (int amode, const uint16 *code, int ref_size);
extern int instruction_size (const uint16 *code, const OpcodeMappingInfo *map);
#endif /* Not _blockinfo_h_ */

View File

@ -0,0 +1,23 @@
#ifndef _callback_h_
#define _callback_h_
#include "syn68k_private.h"
#include "block.h"
#define MAX_CALLBACKS 4352 /* Arbitrary...4096 plus some slop. */
#define CALLBACK_STUB_BASE (MAGIC_ADDRESS_BASE + 128)
#define CALLBACK_STUB_LENGTH (MAX_CALLBACKS * sizeof (uint16))
#define IS_CALLBACK(n) (((syn68k_addr_t) (n)) - CALLBACK_STUB_BASE \
< CALLBACK_STUB_LENGTH)
extern void callback_init (void);
extern syn68k_addr_t callback_install (callback_handler_t func,
void *arbitrary_argument);
extern void callback_remove (syn68k_addr_t m68k_address);
extern int callback_compile (Block *parent, uint32 m68k_address, Block **new);
extern void *callback_argument (syn68k_addr_t callback_address);
extern callback_handler_t callback_function (syn68k_addr_t callback_address);
#endif /* Not callback_h_ */

252
runtime/include/ccfuncs.h Normal file
View File

@ -0,0 +1,252 @@
#ifndef _ccfuncs_h_
#define _ccfuncs_h_
/* This file contains fast versions of addb, addw, addl, subb, subw,
* subl, cmpb, cmpw, and cmpl that compute cc bits using native
* hardware. If the current host has these functions, FAST_CC_FUNCS
* will be defined. The add and subtract functions return the sum or
* difference, respectively.
*/
#if defined (i386) && !defined (NO_FAST_CC_FUNCS)
#if !defined (CCR_ELEMENT_8_BITS)
# warning "The fast i386 cc funcs assume CCR_ELEMENT_8_BITS is defined; punting them."
#else /* defined (CCR_ELEMENT_8_BITS) */
/* Indicate that we have the fast inline functions. */
#define FAST_CC_FUNCS
static inline void
inline_cmpb (uint8 n1, uint8 n2)
{
asm ("cmpb %b4,%b5\n\t"
"setne %3\n\t"
"sets %1\n\t"
"setb %0\n\t" /* setc */
"seto %2"
: "=m" (cpu_state.ccc), "=m" (cpu_state.ccn),
"=m" (cpu_state.ccv), "=m" (cpu_state.ccnz)
: "g" (n1), "ri" (n2)
: "cc");
}
static inline void
inline_cmpw (uint16 n1, uint16 n2)
{
asm ("cmpw %w4,%w5\n\t"
"setne %3\n\t"
"sets %1\n\t"
"setb %0\n\t" /* setc */
"seto %2"
: "=m" (cpu_state.ccc), "=m" (cpu_state.ccn),
"=m" (cpu_state.ccv), "=m" (cpu_state.ccnz)
: "g" (n1), "ri" (n2)
: "cc");
}
/* This seems to be a popular instruction. */
static inline void
inline_cmpw_cz (uint16 n1, uint16 n2)
{
asm ("cmpw %w2,%w3\n\t"
"setne %1\n\t"
"setb %0" /* setc */
: "=m" (cpu_state.ccc), "=m" (cpu_state.ccnz)
: "g" (n1), "ri" (n2)
: "cc");
}
static inline void
inline_cmpl (uint32 n1, uint32 n2)
{
asm ("cmpl %4,%5\n\t"
"setne %3\n\t"
"sets %1\n\t"
"setb %0\n\t" /* setc */
"seto %2"
: "=m" (cpu_state.ccc), "=m" (cpu_state.ccn),
"=m" (cpu_state.ccv), "=m" (cpu_state.ccnz)
: "g" (n1), "ri" (n2)
: "cc");
}
#define INLINE_ADDB_NOSWAP(n1, n2) \
asm ("addb %b7,%b0\n\t" \
"setne %5\n\t" \
"sets %3\n\t" \
"setb %1\n\t" /* setc */ \
"seto %4\n\t" \
"setb %2" /* setc */ \
: "=g" (n2), "=m" (cpu_state.ccc), "=m" (cpu_state.ccx), \
"=m" (cpu_state.ccn), "=m" (cpu_state.ccv), "=m" (cpu_state.ccnz) \
: "0" (n2), "bi" (n1) \
: "cc")
static inline uint8
inline_addb (uint8 n1, uint8 n2)
{
INLINE_ADDB_NOSWAP (n1, n2);
return n2;
}
#define INLINE_ADDW_NOSWAP(n1, n2) \
asm ("addw %w7,%w0\n\t" \
"setne %5\n\t" \
"sets %3\n\t" \
"setb %1\n\t" /* setc */ \
"seto %4\n\t" \
"setb %2" /* setc */ \
: "=g" (n2), "=m" (cpu_state.ccc), "=m" (cpu_state.ccx), \
"=m" (cpu_state.ccn), "=m" (cpu_state.ccv), "=m" (cpu_state.ccnz) \
: "0" (n2), "ri" (n1) \
: "cc")
static inline uint16
inline_addw (uint16 n1, uint16 n2)
{
INLINE_ADDW_NOSWAP (n1, n2);
return n2;
}
#define INLINE_ADDL_NOSWAP(n1, n2) \
asm ("addl %k7,%k0\n\t" \
"setne %5\n\t" \
"sets %3\n\t" \
"setb %1\n\t" /* setc */ \
"seto %4\n\t" \
"setb %2" /* setc */ \
: "=g" (n2), "=m" (cpu_state.ccc), "=m" (cpu_state.ccx), \
"=m" (cpu_state.ccn), "=m" (cpu_state.ccv), "=m" (cpu_state.ccnz) \
: "0" (n2), "ri" (n1) \
: "cc")
static inline uint32
inline_addl (uint32 n1, uint32 n2)
{
INLINE_ADDL_NOSWAP (n1, n2);
return n2;
}
#define INLINE_SUBB_NOSWAP(n1, n2) \
asm ("subb %b7,%b0\n\t" \
"setne %5\n\t" \
"sets %3\n\t" \
"setb %1\n\t" /* setc */ \
"seto %4\n\t" \
"setb %2" /* setc */ \
: "=g" (n2), "=m" (cpu_state.ccc), "=m" (cpu_state.ccx), \
"=m" (cpu_state.ccn), "=m" (cpu_state.ccv), "=m" (cpu_state.ccnz) \
: "0" (n2), "bi" (n1) \
: "cc")
static inline uint8
inline_subb (uint8 n1, uint8 n2)
{
INLINE_SUBB_NOSWAP (n1, n2);
return n2;
}
#define INLINE_SUBW_NOSWAP(n1, n2) \
asm ("subw %w7,%w0\n\t" \
"setne %5\n\t" \
"sets %3\n\t" \
"setb %1\n\t" /* setc */ \
"seto %4\n\t" \
"setb %2" /* setc */ \
: "=g" (n2), "=m" (cpu_state.ccc), "=m" (cpu_state.ccx), \
"=m" (cpu_state.ccn), "=m" (cpu_state.ccv), "=m" (cpu_state.ccnz) \
: "0" (n2), "ri" (n1) \
: "cc")
static inline uint16
inline_subw (uint16 n1, uint16 n2)
{
INLINE_SUBW_NOSWAP (n1, n2);
return n2;
}
#define INLINE_SUBL_NOSWAP(n1, n2) \
asm ("subl %k7,%k0\n\t" \
"setne %5\n\t" \
"sets %3\n\t" \
"setb %1\n\t" /* setc */ \
"seto %4\n\t" \
"setb %2" /* setc */ \
: "=g" (n2), "=m" (cpu_state.ccc), "=m" (cpu_state.ccx), \
"=m" (cpu_state.ccn), "=m" (cpu_state.ccv), "=m" (cpu_state.ccnz) \
: "0" (n2), "ri" (n1) \
: "cc")
static inline uint32
inline_subl (uint32 n1, uint32 n2)
{
INLINE_SUBL_NOSWAP (n1, n2);
return n2;
}
/* This function computes the c, n, v, and nz bits based on a byte.
* c and v are always cleared, nz is set iff the byte is nonzero,
* n is set iff the high bit of the byte is set.
*/
static inline void inline_compute_c_n_v_nz_byte (uint8 n) \
{ \
asm ("movb %b0,%h0\n\t" \
"andl $0x000080FF,%k0\n\t" \
"movl %k0,%1" \
: "=abcd" (n), "=m" (cpu_state.ccnz), "=m" (cpu_state.ccn), \
"=m" (cpu_state.ccc), "=m" (cpu_state.ccv) \
: "0" (n) \
: "cc"); \
}
/* This function computes the c, n, v, and nz bits based on a word.
* c and v are always cleared, nz is set iff the word is nonzero,
* n is set iff the high bit of the word is set.
*/
static inline void inline_compute_c_n_v_nz_word(uint16 n) \
{ \
asm ("orb %h0,%b0\n\t" \
"andl $0x000080FF,%k0\n\t" \
"movl %k0,%1" \
: "=abcd" (n), "=m" (cpu_state.ccnz), "=m" (cpu_state.ccn), \
"=m" (cpu_state.ccc), "=m" (cpu_state.ccv) \
: "0" (n) \
: "cc"); \
}
/* This function computes the c, n, v, and nz bits based on a long.
* c and v are always cleared, nz is set iff the long is nonzero,
* n is set iff the high bit of the long is set.
*/
#define inline_compute_c_n_v_nz_long(n) \
asm ("movl $0,%0\n\t" /* movl is faster than movw. */ \
"testl %k4,%k4\n\t" \
"setne %0\n\t" \
"sets %1" \
: "=m" (cpu_state.ccnz), "=m" (cpu_state.ccn), \
"=m" (cpu_state.ccc), "=m" (cpu_state.ccv) \
: "r" ((uint32)(n)) \
: "cc")
#endif /* defined (CCR_ELEMENT_8_BITS) */
#endif /* i386 */
#endif /* !_ccfuncs_h_ */

View File

@ -0,0 +1,68 @@
#ifndef _checksum_h_
#define _checksum_h_
#include "syn68k_private.h"
#ifdef CHECKSUM_BLOCKS
#include "block.h"
extern uint32 compute_block_checksum (const Block *b);
#ifdef INLINE_CHECKSUM
#include "callback.h"
static __inline__ uint32
inline_compute_block_checksum (const Block *b)
{
const uint16 *code;
uint32 sum;
long n;
syn68k_addr_t start;
/* Don't actually checksum the bytes at a callback! */
start = b->m68k_start_address;
if (IS_CALLBACK (start))
return (start
+ (unsigned long) callback_argument (start)
+ (unsigned long) callback_function (start));
else if (start >= MAGIC_ADDRESS_BASE
&& start < CALLBACK_STUB_BASE)
return 0;
code = SYN68K_TO_US (start);
for (sum = 0, n = b->m68k_code_length / sizeof (uint16); --n >= 0; )
{
/* Bizarre but fast checksum. A good checksum like CRC is
* probably too slow.
*/
#if defined (__GNUC__) && defined(i386)
uint32 tmp1, tmp2;
/* This is taking lots of CPU time for HyperCard, and gcc was generating
* lousy code, so I've hand-coded and hand-scheduled this for the
* Pentium. This should do the same thing as the C code below.
*/
asm ("movl %0,%2\n\t"
"movl %0,%1\n\t"
"sall $5,%2\n\t"
"shrl $14,%1\n\t"
"addl %0,%2\n\t"
"xorl %2,%1\n\t"
"xorw (%4,%5,2),%w0\n\t"
"xorl %1,%0"
: "=r" (sum), "=&r" (tmp1), "=&r" (tmp2)
: "0" (sum), "r" (code), "r" (n)
: "cc");
#else /* !__GNUC__ || !i386 */
sum = (sum >> 14) ^ (sum * 33) ^ code[n];
#endif /* !__GNUC__ || !i386 */
}
return sum;
}
#endif /* INLINE_CHECKSUM */
#endif /* CHECKSUM_BLOCKS */
#endif /* Not _checksum_h_ */

View File

@ -0,0 +1,10 @@
#ifndef _deathqueue_h_
#define _deathqueue_h_
#include "block.h"
extern Block *death_queue_head, *death_queue_tail;
extern void death_queue_enqueue (Block *b);
extern void death_queue_dequeue (Block *b);
#endif /* Not _deathqueue_h_ */

View File

@ -0,0 +1,10 @@
#ifndef _destroyblock_h_
#define _destroyblock_h_
#include "block.h"
extern unsigned long destroy_block (Block *b);
extern unsigned long destroy_blocks (syn68k_addr_t low_m68k_address, uint32 num_bytes);
extern unsigned long destroy_any_block (void);
#endif /* Not _destroyblock_h_ */

View File

@ -0,0 +1,13 @@
#ifndef _diagnostics_h_
#define _diagnostics_h_
#include <stdio.h>
#include "syn68k_private.h"
#include "block.h"
extern void print_cc_bits (FILE *stream, int bits);
extern void hexdump (const uint16 *addr, int num_words);
extern void dump_cpu_state (void);
extern Block *which_block (uint16 *code);
#endif /* Not _diagnostics_h_ */

28
runtime/include/hash.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef _hash_h_
#define _hash_h_
#include "block.h"
#define LOG_NUM_BUCKETS 12
#define NUM_HASH_BUCKETS (1UL << LOG_NUM_BUCKETS)
/* This hash function assumes the low bit conveys no information (== 0). */
#define BLOCK_HASH(x) ((unsigned)((((x) ^ ((x) >> LOG_NUM_BUCKETS)) >> 1) \
% NUM_HASH_BUCKETS))
extern Block *block_hash_table[NUM_HASH_BUCKETS];
extern void hash_init (void);
extern void hash_destroy (void);
extern Block *hash_lookup (uint32 addr);
/* defined in `syn68k_public.h'
extern const uint16 *hash_lookup_code_and_create_if_needed (uint32 addr); */
extern const uint16 *hash_lookup_code_and_create_if_needed (uint32 addr);
extern void hash_insert (Block *b);
extern void hash_remove (Block *b);
#ifdef DEBUG
extern BOOL hash_verify (void);
extern void hash_stats (void);
#endif
#endif /* Not _hash_h_ */

View File

@ -0,0 +1,8 @@
#ifndef _interrupt_h_
#define _interrupt_h_
#include "syn68k_private.h"
/* Everything that would normally be here is in syn68k_public.h */
#endif /* Not _interrupt_h_ */

View File

@ -0,0 +1,9 @@
#ifndef _mapping_h_
#define _mapping_h_
#include "syn68k_private.h"
extern const uint16 opcode_map_index[];
extern const OpcodeMappingInfo opcode_map_info[];
#endif /* Not _mapping_h_ */

300
runtime/include/native.h Normal file
View File

@ -0,0 +1,300 @@
#ifndef _native_h_
#define _native_h_
#ifdef GENERATE_NATIVE_CODE
#include "syn68k_private.h"
#include "../native/i386/host-native.h"
#include "block.h"
/* Define a type for a bit mask for host registers. Each host register
* will get one bit in this mask.
*/
#if NUM_HOST_REGS <= 8
typedef uint8 host_reg_mask_t;
#elif NUM_HOST_REGS <= 16
typedef uint16 host_reg_mask_t;
#else /* NUM_HOST_REGS > 16 */
typedef uint32 host_reg_mask_t;
#endif /* NUM_HOST_REGS > 16 */
#define NUM_GUEST_REGS 16
typedef uint16 guest_reg_mask_t;
/* This enum describes the different types of register caching requests. */
typedef enum
{
REQUEST_REG, /* Needs host reg, cache if necessary. */
REQUEST_SPARE_REG, /* Give me any spare reg, value unimportant. */
} request_type_t;
/* Host registers may not always be left in canonical "native" byte order.
* For efficiency, we lazily perform certain transformations like
* byte swapping and offsetting. Registers in memory slots are _always_
* in MAP_NATIVE byte order.
*/
typedef enum
{
MAP_NATIVE, /* Host byte order. */
MAP_OFFSET, /* Host byte order, but offset by a constant. */
#ifdef LITTLEENDIAN
MAP_SWAP16, /* Host byte order but with low two bytes swapped. */
MAP_SWAP32, /* All four bytes are swapped. */
#endif /* LITTLEENDIAN */
} value_mapping_t;
#define MAP_NATIVE_MASK (1L << MAP_NATIVE)
#define MAP_OFFSET_MASK (1L << MAP_OFFSET)
#ifdef LITTLEENDIAN
# define MAP_SWAP16_MASK (1L << MAP_SWAP16)
# define MAP_SWAP32_MASK (1L << MAP_SWAP32)
#endif /* LITTLEENDIAN */
#ifdef LITTLEENDIAN
# define MAP_ALL_MASK \
(MAP_NATIVE_MASK | MAP_OFFSET_MASK | MAP_SWAP16_MASK | MAP_SWAP32_MASK)
#else
# define MAP_ALL_MASK (MAP_NATIVE_MASK | MAP_OFFSET_MASK)
#endif
#ifdef LITTLEENDIAN
#define ROS_DIRTY_BIT 4
#else /* !LITTLEENDIAN */
#define ROS_DIRTY_BIT 2
#endif /* !LITTLEENDIAN */
typedef enum
{
ROS_NATIVE = MAP_NATIVE,
ROS_OFFSET = MAP_OFFSET,
#ifdef LITTLEENDIAN
ROS_SWAP16 = MAP_SWAP16,
ROS_SWAP32 = MAP_SWAP32,
#endif /* LITTLEENDIAN */
ROS_NATIVE_DIRTY = MAP_NATIVE | ROS_DIRTY_BIT,
ROS_OFFSET_DIRTY = MAP_OFFSET | ROS_DIRTY_BIT,
#ifdef LITTLEENDIAN
ROS_SWAP16_DIRTY = MAP_SWAP16 | ROS_DIRTY_BIT,
ROS_SWAP32_DIRTY = MAP_SWAP32 | ROS_DIRTY_BIT,
#endif /* LITTLEENDIAN */
ROS_UNTOUCHED,
ROS_UNTOUCHED_DIRTY, /* Same mapping as before, but now it's dirty. */
ROS_INVALID,
} reg_output_state_t;
/* This describes constraints for how to transform an input
* register operand to either a host register or a pointer to the memory
* slot for that register. If you can't match the constraints, you can't
* generate native code from this descriptor.
*/
typedef struct
{
#ifdef __GNUC__
BOOL legitimate_p :1; /* 0 ==> dummy entry that just terminates array. */
#else /* !__GNUC__ */
uint8 legitimate_p :1;
#endif /* !__GNUC__ */
uint8 add8_p :1; /* Add 8 to this operand? (address register)*/
uint8 operand_num :2; /* Which operand contains the guest reg #. */
uint8 acceptable_mapping :4; /* Bit mask of acceptable value_mapping_t's.*/
/* Information about the register on input. */
#ifdef __GNUC__
request_type_t request_type :8; /* See above enum for what this means. */
reg_output_state_t output_state :8;
#else /* !__GNUC__ */
uint8 request_type;
uint8 output_state;
#endif /* !__GNUC__ */
host_reg_mask_t regset; /* Specifies set of allowable host regs. */
} reg_operand_info_t;
#define MAX_REG_OPERANDS 2
#define MAX_COMPILE_FUNCS 5
#define USE_SCRATCH_REG (-1)
#define USE_BLOCK (-2)
#define USE_ZERO (-3)
#define USE_MINUS_ONE (-4)
#define USE_M68K_PC (-5)
#define USE_M68K_PC_PLUS_TWO (-6)
#define USE_M68K_PC_PLUS_FOUR (-7)
#define USE_0xFFFF (-8)
#define MAX_M68K_OPERANDS 4
typedef struct
{
int8 operand_num[MAX_M68K_OPERANDS];
} oporder_t;
typedef struct
{
#ifdef RUNTIME
int (*func)(); /* Returns nonzero->abort. */
#else /* !RUNTIME */
char *func;
#endif /* !RUNTIME */
oporder_t order;
} compile_func_t;
typedef struct _guest_code_descriptor_t
{
#ifndef RUNTIME
const char *name; /* Used while programmatically generating these. */
BOOL static_p;
#endif
reg_operand_info_t reg_op_info[MAX_REG_OPERANDS + 1];
uint8 cc_in; /* Bit mask: must be cached on input. */
uint8 cc_out; /* Bit mask: valid & cached on output. */
host_reg_mask_t scratch_reg; /* If nonzero, allocate a scratch reg. */
compile_func_t compile_func[MAX_COMPILE_FUNCS];
#ifdef RUNTIME
const
#endif
struct _guest_code_descriptor_t *next; /* Next in linked list. */
} guest_code_descriptor_t;
#define NO_REG (-1)
typedef struct
{
int8 host_reg; /* Which host register cached in, or NO_REG. */
#ifdef __GNUC__
value_mapping_t mapping :8; /* If cached, how to map value to canon value. */
BOOL dirty_without_offset_p :8; /* Must be spilled even if nonzero offset? */
#else /* !__GNUC__ */
uint8 mapping;
uint8 dirty_without_offset_p;
#endif /* !__GNUC__ */
int32 offset; /* Add to reg to get canon value if ST_OFFSET. */
} guest_reg_status_t;
typedef struct
{
guest_reg_status_t guest_reg_status[NUM_GUEST_REGS];
int8 host_reg_to_guest_reg[NUM_HOST_REGS]; /* Might be NO_REG. */
uint8 cached_cc; /* CC bits that are cached. */
uint8 dirty_cc; /* CC bits that are dirty. */
} cache_info_t;
#define COMMON_ARGS \
cache_info_t *c, host_code_t **codep, unsigned cc_spill_if_changed, \
unsigned cc_to_compute, int scratch_reg
#define COMMON_TYPES \
cache_info_t *, host_code_t **, unsigned, unsigned, int
#define COMMON_ARG_NAMES \
c, codep, cc_spill_if_changed, cc_to_compute, scratch_reg
extern void native_code_init (void);
extern void host_native_code_init (void);
extern void host_backpatch_native_to_synth_stub (Block *b,
host_code_t *stub,
uint32 *synth_opcode);
#ifdef SYNCHRONOUS_INTERRUPTS
extern void host_backpatch_check_interrupt_stub (Block *b, host_code_t *stub);
#endif
extern BOOL generate_native_code (const guest_code_descriptor_t *first_desc,
cache_info_t *cache_info,
const int32 *orig_operands,
host_code_t **code,
uint8 cc_input, uint8 cc_live,
uint8 cc_to_set,
BOOL ends_block_p, Block *block,
const uint16 *m68k_code);
extern int host_setup_cached_reg (COMMON_ARGS, int guest_reg,
unsigned acceptable_mappings,
host_reg_mask_t acceptable_regs);
extern int host_movel_reg_reg (COMMON_ARGS, int32 src_reg, int32 dst_reg);
#ifndef host_alloc_reg
extern int host_alloc_reg (cache_info_t *c, host_code_t **code,
unsigned cc_spill_if_changed,
host_reg_mask_t legal);
#endif
#ifndef host_cache_reg
extern void host_cache_reg (cache_info_t *c, host_code_t **code,
unsigned cc_spill_if_changed,
int guest_reg, int host_reg);
#endif
#ifndef host_unoffset_reg
extern void host_unoffset_reg (cache_info_t *c, host_code_t **code,
unsigned cc_spill_if_changed,
int guest_reg);
#endif
#ifndef host_unoffset_regs
extern void host_unoffset_regs (cache_info_t *c, host_code_t **code,
unsigned cc_spill_if_changed);
#endif
#ifndef host_spill_reg
extern inline void host_spill_reg (cache_info_t *c, host_code_t **code,
unsigned cc_dont_touch, int guest_reg);
#endif
#ifndef host_spill_regs
extern void host_spill_regs (cache_info_t *c, host_code_t **code,
unsigned cc_spill_if_changed);
#endif
#ifndef host_spill_cc_bits
extern void host_spill_cc_bits (cache_info_t *c, host_code_t **code,
unsigned cc);
#endif
extern void make_dirty_regs_native (cache_info_t *c, host_code_t **codep,
unsigned cc_spill_if_changed);
#define SPILL_CC_BITS(c, code, cc) \
do { if (cc) host_spill_cc_bits (c, code, cc); } while (0)
#ifdef LITTLEENDIAN
extern int host_swap16 (COMMON_ARGS, int32 host_reg);
extern int host_swap16_to_32 (COMMON_ARGS, int32 host_reg);
extern int host_swap32 (COMMON_ARGS, int32 host_reg);
extern int host_swap32_to_16 (COMMON_ARGS, int32 host_reg);
#else /* !LITTLEENDIAN */
#define host_swap16(COMMON_ARG_NAMES) 0
#define host_swap16_to_32(COMMON_ARG_NAMES) 0
#define host_swap32(COMMON_ARG_NAMES) 0
#define host_swap32_to_16(COMMON_ARG_NAMES) 0
#endif /* !LITTLEENDIAN */
#define HOST_CODE_T_BITS (sizeof (host_code_t) * 8)
extern cache_info_t empty_cache_info;
#define NATIVE_START_BYTE_OFFSET (sizeof (void *) + sizeof (Block *))
#define NATIVE_CODE_TRIED(b) \
(*(Block **)((b)->compiled_code + PTR_WORDS) == NULL)
extern host_code_t native_to_synth_stub[];
#ifdef SYNCHRONOUS_INTERRUPTS
extern host_code_t check_interrupt_stub[];
#endif
#define NATIVE_PREAMBLE_WORDS \
((((CHECK_INTERRUPT_STUB_BYTES + NATIVE_TO_SYNTH_STUB_BYTES + 1) / 2) + 1) \
& ~1)
#endif /* GENERATE_NATIVE_CODE */
#endif /* !native_h_ */

13
runtime/include/profile.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef _profile_h_
#define _profile_h_
#ifdef PROFILE
#include "block.h"
extern void profile_block (Block *b);
extern void dump_profile (const char *file);
#endif
#endif /* Not _profile_h_ */

View File

@ -0,0 +1,20 @@
#ifndef _rangetree_h
#define _rangetree_h
#include "syn68k_private.h"
#include "block.h"
extern void range_tree_init (void);
extern void range_tree_destroy (void);
extern void range_tree_insert (Block *b);
extern void range_tree_remove (Block *b);
extern Block *range_tree_lookup (syn68k_addr_t h);
extern Block *range_tree_find_first_at_or_after (syn68k_addr_t addr);
extern Block *range_tree_first_to_intersect (syn68k_addr_t low,
syn68k_addr_t high);
#ifdef DEBUG
extern BOOL range_tree_verify (void);
extern void range_tree_dump (void);
#endif
#endif /* Not _rangetree_h_ */

View File

@ -0,0 +1,26 @@
#ifndef _recompile_h_
#define _recompile_h_
#ifdef GENERATE_NATIVE_CODE
#include "block.h"
#include "deathqueue.h"
extern void recompile_block_as_native (Block *b);
extern double native_fraction (void);
/* This is the number of times a nonnative block must be called before
* we scrap it and recompile it as native.
*/
#define RECOMPILE_CUTOFF 50
/* This is how many times a descendent of a nonnative block about to be
* recompiled must have been called before we decide to smash it as
* well. Smashing nearby blocks avoids extra recompiles.
*/
#define RECOMPILE_CHILD_CUTOFF 35
#endif /* GENERATE_NATIVE_CODE */
#endif /* !_recompile_h_ */

View File

@ -0,0 +1,30 @@
#ifndef _translate_h
#define _translate_h_
#include "block.h"
extern void (*call_while_busy_func)(int);
typedef struct {
BOOL valid;
BOOL reversed;
const uint16 *m68koperand;
int amode;
int size;
} AmodeFetchInfo;
extern int generate_block (Block *parent, uint32 m68k_address, Block **new
/* #ifdef GENERATE_NATIVE_CODE */
, BOOL try_native_p
/* #endif */ /* GENERATE_NATIVE_CODE */
);
extern Block *make_artificial_block (Block *parent, syn68k_addr_t m68k_address,
int extra_words, uint16 **extra_start);
#ifdef GENERATE_NATIVE_CODE
extern int native_code_p;
#endif /* GENERATE_NATIVE_CODE */
extern int emulation_depth;
#endif /* Not _translate_h_ */

61
runtime/include/trap.h Normal file
View File

@ -0,0 +1,61 @@
#ifndef _trap_h_
#define _trap_h_
#include "syn68k_private.h"
extern syn68k_addr_t trap_direct (uint32 trap_number,
syn68k_addr_t exception_pc,
syn68k_addr_t exception_address);
extern uint32 trap_forwarded (syn68k_addr_t m68k_address, void *arg);
extern void trap_init (void);
extern void trap_install_handler (unsigned trap_number,
callback_handler_t func,
void *arbitrary_argument);
extern void trap_remove_handler (unsigned trap_number);
extern uint32 *trap_vector_array;
#define SR_SUPERVISOR_BIT 0x2000
#define SR_MASTER_BIT 0x1000
#define USE_USP(sr) (!((sr) & SR_SUPERVISOR_BIT))
#define USE_MSP(sr) (((sr) & (SR_SUPERVISOR_BIT | SR_MASTER_BIT)) \
== (SR_SUPERVISOR_BIT | SR_MASTER_BIT))
#define USE_ISP(sr) (((sr) & (SR_SUPERVISOR_BIT | SR_MASTER_BIT)) \
== SR_SUPERVISOR_BIT)
#define FETCH_USP() (USE_USP (cpu_state.sr) ? EM_A7 : cpu_state.usp)
#define FETCH_MSP() (USE_MSP (cpu_state.sr) ? EM_A7 : cpu_state.msp)
#define FETCH_ISP() (USE_ISP (cpu_state.sr) ? EM_A7 : cpu_state.isp)
#define SET_USP(n) \
(USE_USP (cpu_state.sr) ? (EM_A7 = (n)) : (cpu_state.usp = (n)))
#define SET_MSP(n) \
(USE_MSP (cpu_state.sr) ? (EM_A7 = (n)) : (cpu_state.msp = (n)))
#define SET_ISP(n) \
(USE_ISP (cpu_state.sr) ? (EM_A7 = (n)) : (cpu_state.isp = (n)))
#define SWITCH_A7(old_sr, new_sr) \
do \
{ \
if (((old_sr) ^ (new_sr)) & (SR_SUPERVISOR_BIT | SR_MASTER_BIT)) \
{ \
/* Save away the old a7. */ \
if (USE_USP (old_sr)) \
cpu_state.usp = EM_A7; \
else if (USE_MSP (old_sr)) \
cpu_state.msp = EM_A7; \
else \
cpu_state.isp = EM_A7; \
\
/* Load up the new value. */ \
if (USE_USP (new_sr)) \
EM_A7 = cpu_state.usp; \
else if (USE_MSP (new_sr)) \
EM_A7 = cpu_state.msp; \
else \
EM_A7 = cpu_state.isp; \
} \
} while (0)
#endif /* Not _trap_h_ */

128
runtime/init.c Normal file
View File

@ -0,0 +1,128 @@
#include "syn68k_private.h"
#include "hash.h"
#include "rangetree.h"
#include "callback.h"
#include "trap.h"
#include "alloc.h"
#include "mapping.h"
#include "translate.h"
#include "native.h"
#include "checksum.h"
#include "deathqueue.h"
#include "interrupt.h"
#ifdef USE_BIOS_TIMER
#include "go32.h"
#include "dpmi.h"
#endif /* USE_BIOS_TIMER */
#include <assert.h>
#include <string.h>
/* Global CPU state struct. */
CPUState cpu_state;
/* This function initializes syn68k. Call it exactly once, before any
* other syn68k calls. DOS_INT_FLAG_ADDR is the conventional memory
* offset of the 32 bit synchronous interrupt flag. Just pass in zero
* for the non-MSDOS and non-SYNCHRONOUS_INTERRUPTS cases.
*/
void
initialize_68k_emulator (void (*while_busy)(int), int native_p,
uint32 trap_vector_storage[64],
uint32 dos_int_flag_addr)
{
static uint16 rte =
#ifdef LITTLEENDIAN
0x734E;
#else
0x4E73;
#endif
Block *b;
uint16 *code;
#ifdef __CHECKER__
/* Checker can't work with native code. */
native_p = FALSE;
#endif
/* Zero out CPU state (not necessary since statics are 0'd) */
memset (&cpu_state, 0, sizeof cpu_state);
memset (&cpu_state.jsr_stack, -1, sizeof cpu_state.jsr_stack);
/* Record the function to periodically call while we are busy doing stuff. */
call_while_busy_func = while_busy;
#ifdef GENERATE_NATIVE_CODE
native_code_p = native_p;
#endif
trap_vector_array = trap_vector_storage;
/* Set up the status register & interrupt stack pointer. */
cpu_state.sr = 0x2000; /* supervisor/interrupt mode (this appears
* to be what programs really expect, e.g.
* PGA Tour Golf does movew #8192,sr).
*/
cpu_state.usp = 0xDEADF00D; /* Never use this stack pointer! */
cpu_state.msp = 0xDEAD0666; /* Never use this stack pointer! */
#ifdef USE_BIOS_TIMER
dos_memory_selector = _go32_conventional_mem_selector ();
assert (dos_int_flag_addr != 0);
dos_interrupt_flag_addr = dos_int_flag_addr;
#endif /* USE_BIOS_TIMER */
#ifdef SYNCHRONOUS_INTERRUPTS
SET_INTERRUPT_STATUS (INTERRUPT_STATUS_UNCHANGED);
#endif
/* Call various initialization routines. */
hash_init ();
range_tree_init ();
callback_init ();
trap_init ();
#ifdef GENERATE_NATIVE_CODE
native_code_init ();
#endif /* GENERATE_NATIVE_CODE */
/* Create the magical block that exits the emulator if you ever
* jump to it. Don't add it to the death queue, since we never want
* this block to go away.
*/
b = make_artificial_block (NULL, MAGIC_EXIT_EMULATOR_ADDRESS,
OPCODE_WORDS, &code);
#ifdef USE_DIRECT_DISPATCH
*(const void **)code = direct_dispatch_table[0];
#else
*(const void **)code = (const void *)0; /* Exit emulator opc. */
#endif
hash_insert (b);
range_tree_insert (b);
/* Create the magical block that contains an RTE. */
b = NULL;
#if !defined (__alpha)
generate_block (NULL, US_TO_SYN68K (&rte), &b, TRUE);
#else
{
typeof (ROMlib_offset) save_offset;
save_offset = ROMlib_offset;
ROMlib_offset = &rte; /* so the RTE will be reachable with 32 bit addr */
generate_block (NULL, US_TO_SYN68K (&rte), &b, TRUE);
ROMlib_offset = save_offset;
}
#endif
assert (b != NULL);
hash_remove (b);
range_tree_remove (b);
death_queue_dequeue (b);
b->m68k_start_address = MAGIC_RTE_ADDRESS;
b->m68k_code_length = 1;
b->checksum = compute_block_checksum (b);
b->immortal = TRUE;
hash_insert (b);
range_tree_insert (b);
}

103
runtime/interrupt.c Normal file
View File

@ -0,0 +1,103 @@
#include "interrupt.h"
#ifdef SYNCHRONOUS_INTERRUPTS
#include "trap.h"
#ifdef USE_BIOS_TIMER
uint16 dos_memory_selector;
uint32 dos_interrupt_flag_addr;
#endif
void
interrupt_generate (unsigned priority)
{
/* Calling this with a weird priority will just note that an interrupt
* should be checked for.
*/
if (priority >= 1 && priority <= 7)
cpu_state.interrupt_pending[priority] = TRUE;
SET_INTERRUPT_STATUS (INTERRUPT_STATUS_CHANGED);
}
/* This function turns on the global "check for an interrupt" bit if
* any interrupts are currently pending.
*/
void
interrupt_note_if_present ()
{
int i;
for (i = 1; i <= 7; i++)
if (cpu_state.interrupt_pending[i])
{
SET_INTERRUPT_STATUS (INTERRUPT_STATUS_CHANGED);
break;
}
}
/* This function looks to see if any interrupts of high enough
* priority are pending, and if they are it processes the highest
* priority interrupt. It adjusts the machine state appropriately for
* the interrupt and returns the 68k PC at which execution should
* resume. The INTERRUPT_PC parameter specifies the address
* of the 68k instruction about to be executed when the interrupt
* was detected.
*/
syn68k_addr_t
interrupt_process_any_pending (syn68k_addr_t interrupt_pc)
{
int priority;
syn68k_addr_t continuation_pc;
int cpu_priority;
/* First note that the interrupt has been processed. The RTE
* will end up causing another check when it reloads the SR, so
* we shouldn't miss any interrupts.
*/
SET_INTERRUPT_STATUS (INTERRUPT_STATUS_UNCHANGED);
/* Determine if any interrupt with high enough priority is pending. */
cpu_priority = (cpu_state.sr >> 8) & 7;
if (cpu_state.interrupt_pending[7])
priority = 7; /* Priority 7 interrupt cannot be masked. */
else
{
for (priority = 6; priority > cpu_priority; priority--)
if (cpu_state.interrupt_pending[priority])
break;
if (priority <= cpu_priority)
priority = -1;
}
#ifdef USE_BIOS_TIMER
/* The BIOS has no way of specifying the interrupt priority when
* an interrupt comes in. Therefore if we don't see any other
* explicitly specified interrupts, we'll assume it must have been
* a timer interrupt and act accordingly.
*/
if (priority == -1 && cpu_priority < M68K_TIMER_PRIORITY)
priority = M68K_TIMER_PRIORITY;
#endif
/* Did we find an interrupt of high enough priority? */
if (priority != -1)
{
/* Process the interrupt. */
cpu_state.interrupt_pending[priority] = 0;
continuation_pc = trap_direct (24 + priority, interrupt_pc, 0);
}
else
{
/* Nothing interesting after all, so just return unchanged. */
continuation_pc = interrupt_pc;
}
return continuation_pc;
}
#endif /* SYNCHRONOUS_INTERRUPTS */

684
runtime/native.c Normal file
View File

@ -0,0 +1,684 @@
#include "syn68k_private.h"
#ifdef GENERATE_NATIVE_CODE
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include "native.h"
#ifdef DEBUG
#include <stdio.h>
#endif
static void host_uncache_reg (cache_info_t *c, int guest_reg);
/* This is just a default template to copy whenever you need to set up
* an empty cache. Never modify it (except when it's initially set up,
* of course).
*/
cache_info_t empty_cache_info;
void
native_code_init ()
{
int i;
/* Set up an empty cache info struct that we can just copy whenever
* we need to set up an empty cache.
*/
memset (&empty_cache_info, 0, sizeof empty_cache_info);
for (i = 0; i < NUM_GUEST_REGS; i++)
{
guest_reg_status_t *r = &empty_cache_info.guest_reg_status[i];
r->host_reg = NO_REG;
r->mapping = MAP_NATIVE;
r->dirty_without_offset_p = FALSE;
r->offset = 0;
}
for (i = 0; i < NUM_HOST_REGS; i++)
empty_cache_info.host_reg_to_guest_reg[i] = NO_REG;
empty_cache_info.cached_cc = M68K_CC_NONE;
empty_cache_info.dirty_cc = M68K_CC_NONE;
host_native_code_init ();
}
#ifdef DEBUG
static void
verify_cache_consistency (const cache_info_t *c)
{
int h, g;
for (h = 0; h < NUM_HOST_REGS; h++)
{
g = c->host_reg_to_guest_reg[h];
if (g != NO_REG)
if (c->guest_reg_status[g].host_reg != h)
{
fprintf (stderr, "Internal error! register/cc cache internally "
"inconsistent. Host reg %d claims to be in guest reg "
"%d, but guest reg %d claims to be cached in host reg "
"%d. Wedging.\n",
h, g, g, c->guest_reg_status[g].host_reg);
while (1)
;
}
}
for (g = 0; g < NUM_GUEST_REGS; g++)
{
h = c->guest_reg_status[g].host_reg;
if (h != NO_REG)
if (c->host_reg_to_guest_reg[h] != g)
{
fprintf (stderr, "Internal error! register/cc cache internally "
"inconsistent. Guest reg %d claims to be cached in "
"host reg %d, but host reg %d claims to be cacheing "
"guest reg %d. Wedging.\n",
g, h, h, c->host_reg_to_guest_reg[h]);
while (1)
;
}
}
#ifdef i386
/* Make sure data registers only go into byte-addressable host regs. */
for (g = 0; g < 8; g++)
{
h = c->guest_reg_status[g].host_reg;
if (h != NO_REG && !((1L << h) & REGSET_BYTE))
{
fprintf (stderr, "Internal error! Put data register d%d into "
"a non-byte accessible host register (%d). Wedging.\n",
g, h);
while (1)
;
}
}
#endif /* i386 */
}
#endif /* DEBUG */
int
host_setup_cached_reg (COMMON_ARGS, int guest_reg,
unsigned acceptable_mappings,
host_reg_mask_t acceptable_regs)
{
guest_reg_status_t *r;
int host_reg;
r = &c->guest_reg_status[guest_reg];
host_reg = r->host_reg;
if (host_reg == NO_REG)
{
host_reg = host_alloc_reg (c, codep, cc_spill_if_changed,
acceptable_regs);
if (host_reg == NO_REG)
return NO_REG;
host_cache_reg (c, codep, cc_spill_if_changed, guest_reg, host_reg);
}
else if (!((1L << host_reg) & acceptable_regs))
{
int new_reg;
/* If they are demanding a register other than the one it's in,
* move it to an acceptable one.
*/
new_reg = host_alloc_reg (c, codep, cc_spill_if_changed,
acceptable_regs);
if (new_reg == NO_REG)
return NO_REG;
if (host_movel_reg_reg (COMMON_ARG_NAMES, host_reg, new_reg))
return NO_REG;
r->host_reg = new_reg;
c->host_reg_to_guest_reg[host_reg] = NO_REG;
c->host_reg_to_guest_reg[new_reg] = guest_reg;
host_reg = new_reg;
}
/* If the register's mapping is already acceptable, then we're done. */
if ((1L << r->mapping) & acceptable_mappings)
return host_reg;
switch (r->mapping)
{
case MAP_NATIVE:
if (acceptable_mappings & MAP_OFFSET_MASK)
{
r->offset = 0;
r->mapping = MAP_OFFSET;
}
#ifdef LITTLEENDIAN
else if (acceptable_mappings & MAP_SWAP16_MASK)
{
host_swap16 (c, codep, cc_spill_if_changed,
M68K_CC_NONE, NO_REG, host_reg);
r->mapping = MAP_SWAP16;
}
else if (acceptable_mappings & MAP_SWAP32_MASK)
{
host_swap32 (c, codep, cc_spill_if_changed,
M68K_CC_NONE, NO_REG, host_reg);
r->mapping = MAP_SWAP32;
}
#endif /* LITTLEENDIAN */
else
return NO_REG;
break;
case MAP_OFFSET:
if (acceptable_mappings
& (MAP_NATIVE_MASK
#ifdef LITTLEENDIAN
| MAP_SWAP16_MASK | MAP_SWAP32_MASK
))
#endif /* LITTLEENDIAN */
{
host_unoffset_reg (c, codep, cc_spill_if_changed,
guest_reg);
if (acceptable_mappings & MAP_NATIVE_MASK)
r->mapping = MAP_NATIVE;
#ifdef LITTLEENDIAN
else if (acceptable_mappings & MAP_SWAP16_MASK)
{
host_swap16 (c, codep, cc_spill_if_changed,
M68K_CC_NONE, NO_REG, host_reg);
r->mapping = MAP_SWAP16;
}
else /* if (acceptable_mappings & MAP_SWAP32_MASK) */
{
host_swap32 (c, codep, cc_spill_if_changed,
M68K_CC_NONE, NO_REG, host_reg);
r->mapping = MAP_SWAP32;
}
#endif /* LITTLEENDIAN */
}
else
return NO_REG;
break;
#ifdef LITTLEENDIAN
case MAP_SWAP16:
if (acceptable_mappings & MAP_NATIVE_MASK)
{
host_swap16 (c, codep, cc_spill_if_changed,
M68K_CC_NONE, NO_REG, host_reg);
r->mapping = MAP_NATIVE;
}
else if (acceptable_mappings & MAP_OFFSET_MASK)
{
host_swap16 (c, codep, cc_spill_if_changed,
M68K_CC_NONE, NO_REG, host_reg);
r->offset = 0;
r->mapping = MAP_OFFSET;
}
else if (acceptable_mappings & MAP_SWAP32_MASK)
{
host_swap16_to_32 (c, codep, cc_spill_if_changed,
M68K_CC_NONE, NO_REG, host_reg);
r->mapping = MAP_SWAP32;
}
else
return NO_REG;
break;
case MAP_SWAP32:
if (acceptable_mappings & MAP_NATIVE_MASK)
{
host_swap32 (c, codep, cc_spill_if_changed,
M68K_CC_NONE, NO_REG, host_reg);
r->mapping = MAP_NATIVE;
}
else if (acceptable_mappings & MAP_OFFSET_MASK)
{
host_swap32 (c, codep, cc_spill_if_changed,
M68K_CC_NONE, NO_REG, host_reg);
r->offset = 0;
r->mapping = MAP_OFFSET;
}
else if (acceptable_mappings & MAP_SWAP16_MASK)
{
host_swap32_to_16 (c, codep, cc_spill_if_changed,
M68K_CC_NONE, NO_REG, host_reg);
r->mapping = MAP_SWAP16;
}
else
return NO_REG;
break;
#endif /* LITTLEENDIAN */
default:
abort ();
}
return host_reg;
}
#ifdef GCD_RANGE
#warning "Temp debugging stuff!"
const guest_code_descriptor_t *lowest_gcd = 0;
const guest_code_descriptor_t *highest_gcd = (guest_code_descriptor_t *)~0;
#endif
/* Generates native code for the specified list of guest_code_descriptor_t's
* at the address pointed to by *code if possible. If successful, returns
* TRUE and updates *code to point just past the end of the newly generated
* code. Otherwise, returns FALSE and *code is unaffected. cc_to_compute
* should always be a subset of cc_live.
*/
BOOL
generate_native_code (const guest_code_descriptor_t *first_desc,
cache_info_t *cache_info,
const int32 *orig_operands,
host_code_t **code,
uint8 cc_input, uint8 cc_live, uint8 cc_to_compute,
BOOL ends_block_p,
Block *block,
const uint16 *m68k_code)
{
const guest_code_descriptor_t *desc;
const reg_operand_info_t *op;
host_code_t *orig_code;
cache_info_t orig_cache_info;
guest_reg_status_t *r;
int i, guest_reg, host_reg, scratch_reg;
unsigned cc_dont_touch, cc_dont_touch_during_setup;
backpatch_t *orig_backpatch, *bp, *bp_next, *old_first_backpatch;
#ifdef GCD_RANGE
#warning "Temp debugging stuff!"
if (first_desc < lowest_gcd || first_desc > highest_gcd)
return 0;
#endif
/* Save these away in case we realize a mistake and we have to start over. */
orig_code = *code;
orig_cache_info = *cache_info;
orig_backpatch = block->backpatch;
block->backpatch = NULL;
#ifdef DEBUG
verify_cache_consistency (cache_info);
#endif
/* Compute those cc bits we are not allowed to modify (without spilling). */
cc_dont_touch = cc_live & cache_info->cached_cc & ~cc_to_compute;
cc_dont_touch_during_setup = ((cc_dont_touch | cc_input)
& cache_info->cached_cc);
/* See if we find any match in the list of code descriptors, and fill
* in the operands array.
*/
for (desc = first_desc; desc != NULL; desc = desc->next)
{
int32 operands[MAX_BITFIELDS], canonical_operands[MAX_BITFIELDS];
host_reg_mask_t locked_host_reg;
uint8 acceptable_mapping[NUM_GUEST_REGS];
/* If insufficient cc bits are cached, bail out quickly. */
if ((cache_info->cached_cc & desc->cc_in) != desc->cc_in)
goto failure_no_copy;
/* If this guy doesn't compute enough cc bits, bail out quickly. */
if ((cc_to_compute & desc->cc_out) != cc_to_compute)
goto failure_no_copy;
/* Create the "canonical" set of operands to use. Right now this
* means just adding 8 to address register operands.
*/
memcpy (canonical_operands, orig_operands, sizeof canonical_operands);
for (op = desc->reg_op_info; op->legitimate_p; op++)
{
if (op->add8_p)
{
int opnum = op->operand_num;
canonical_operands[opnum] = (orig_operands[opnum] & 7) + 8;
}
}
/* Figure out exactly which mappings are acceptable for every
* guest register mentioned. If one of them has no acceptable
* mapping, bail out.
*/
memset (acceptable_mapping, MAP_ALL_MASK, sizeof acceptable_mapping);
for (op = desc->reg_op_info; op->legitimate_p; op++)
{
int guest_reg = canonical_operands[op->operand_num];
assert (guest_reg >= 0 && guest_reg < NUM_GUEST_REGS);
acceptable_mapping[guest_reg] &= op->acceptable_mapping;
if (acceptable_mapping[guest_reg] == 0)
goto failure;
}
/* Default to new operands being the same as the old operands. */
memcpy (operands, canonical_operands, sizeof operands);
locked_host_reg = (host_reg_mask_t)~ALLOCATABLE_REG_MASK;
#if 0
/* I think this is causing extra unoffsetting. */
/* If this instruction actually computes live cc bits, un-offset
* registers NOW. Otherwise, we might be forced to un-offset the
* registers between a compare and a conditional branch (for example),
* and the process of offsetting is less efficient if we can't
* step on cc bits.
*/
if (cc_live & cc_to_compute & desc->cc_out)
host_unoffset_regs (cache_info, code, cc_dont_touch);
#endif
/* Cache registers as necessary and with the appropriate byte order. */
for (op = desc->reg_op_info; op->legitimate_p; op++)
{
unsigned acceptable;
guest_reg = canonical_operands[op->operand_num];
assert (guest_reg >= 0 && guest_reg < NUM_GUEST_REGS);
r = &cache_info->guest_reg_status[guest_reg];
host_reg = r->host_reg;
switch (op->request_type)
{
case REQUEST_REG:
acceptable = acceptable_mapping[guest_reg];
/* Allocate a register, if necessary. */
if (host_reg == NO_REG)
{
host_reg = host_alloc_reg (cache_info, code,
cc_dont_touch_during_setup,
op->regset & ~locked_host_reg);
if (host_reg == NO_REG)
goto failure;
operands[op->operand_num] = host_reg;
host_cache_reg (cache_info, code, cc_dont_touch_during_setup,
guest_reg, host_reg);
}
/* Map to an acceptable byte order or offset and
* particular register.
*/
if (!((1L << r->mapping) & acceptable)
|| !(op->regset & (1L << host_reg)))
{
host_reg = host_setup_cached_reg (cache_info, code,
cc_dont_touch_during_setup,
M68K_CC_NONE, NO_REG,
guest_reg, acceptable,
(op->regset
& ~locked_host_reg));
if (host_reg == NO_REG)
goto failure;
}
operands[op->operand_num] = host_reg;
locked_host_reg |= (1L << host_reg);
break;
case REQUEST_SPARE_REG:
/* Allocate a register, if necessary. */
if (host_reg == NO_REG)
{
host_reg = host_alloc_reg (cache_info, code,
cc_dont_touch_during_setup,
op->regset & ~locked_host_reg);
/* If we failed to find one, bail out! */
if (host_reg == NO_REG)
goto failure;
r->host_reg = host_reg;
r->mapping = MAP_NATIVE; /* default */
r->dirty_without_offset_p = FALSE;
cache_info->host_reg_to_guest_reg[host_reg] = guest_reg;
}
locked_host_reg |= (1L << host_reg);
operands[op->operand_num] = host_reg;
break;
default:
abort ();
}
}
/* If insufficient cc bits are cached at this point, we failed. */
if ((cache_info->cached_cc & desc->cc_in) != desc->cc_in)
goto failure;
#ifdef LITTLEENDIAN
/* If they are computing live cc bits, and we have swapped dirty
* registers lying around, let's swap them back now. That way we
* won't be forced to swap right before a conditional branch and
* throw away our hard-earned cc bits. This is a heuristic; it
* is not necessary for correct behavior.
*/
if (cc_live & cc_to_compute & desc->cc_out)
{
int hr;
for (hr = NUM_HOST_REGS - 1; hr >= 0; hr--)
if (!(locked_host_reg & (1L << hr)))
{
int gr = cache_info->host_reg_to_guest_reg[hr];
if (gr != NO_REG)
{
guest_reg_status_t *grs;
grs = &cache_info->guest_reg_status[gr];
if (grs->dirty_without_offset_p)
{
if (grs->mapping == MAP_SWAP16)
{
host_swap16 (cache_info, code,
cc_dont_touch_during_setup,
M68K_CC_NONE, NO_REG, hr);
grs->mapping = MAP_NATIVE;
}
else if (grs->mapping == MAP_SWAP32
#ifdef i386
&& !have_i486_p /* bswap doesn't touch ccs */
#endif
)
{
host_swap32 (cache_info, code,
cc_dont_touch_during_setup,
M68K_CC_NONE, NO_REG, hr);
grs->mapping = MAP_NATIVE;
}
}
}
}
}
#endif /* LITTLEENDIAN */
/* Allocate a scratch register if one was requested. */
if (desc->scratch_reg != 0)
{
scratch_reg = host_alloc_reg (cache_info, code,
cc_dont_touch_during_setup,
desc->scratch_reg & ~locked_host_reg);
if (scratch_reg == NO_REG)
goto failure;
locked_host_reg |= 1L << scratch_reg;
}
else
scratch_reg = NO_REG;
/* Crank out the native code. Note that we may pass in more
* arguments than the function is expecting because our function
* pointer can point to handlers that care about different numbers
* of operands; technically that's invalid C, but it will work on
* any reasonable machine. If any of the compiler functions
* return nonzero, we abort this compile and try something else.
*/
old_first_backpatch = NULL;
for (i = 0; i < MAX_COMPILE_FUNCS; i++)
{
const oporder_t *order;
void *ops[4];
int j, (*f)();
host_code_t *code_start;
int32 offset;
f = desc->compile_func[i].func;
if (f == NULL)
break;
/* Scramble the operands appropriately. */
order = &desc->compile_func[i].order;
for (j = 0; j < MAX_M68K_OPERANDS; j++)
{
int n = order->operand_num[j];
if (n >= 0)
ops[j] = (void *)operands[n];
else
{
switch (n)
{
case USE_SCRATCH_REG:
assert (scratch_reg != NO_REG);
ops[j] = (void *)scratch_reg;
break;
case USE_BLOCK:
ops[j] = (void *)block;
break;
case USE_MINUS_ONE:
ops[j] = (void *)-1;
break;
case USE_ZERO:
ops[j] = (void *)0;
break;
case USE_0xFFFF:
ops[j] = (void *)0xFFFF;
break;
case USE_M68K_PC:
ops[j] = (void *)m68k_code;
break;
case USE_M68K_PC_PLUS_TWO:
ops[j] = (void *)m68k_code + 2;
break;
case USE_M68K_PC_PLUS_FOUR:
ops[j] = (void *)m68k_code + 4;
break;
default:
abort ();
}
}
}
code_start = *code;
if ((*f)(cache_info, code, cc_dont_touch, cc_to_compute,
scratch_reg, ops[0], ops[1], ops[2], ops[3]))
goto failure;
/* Check for new backpatches. If we found any, adjust their
* starting addresses to be relative to the start of all native
* code generated here, rather than just the native code generated
* by the last function call.
*/
offset = ((char *)code_start - (char *)orig_code) * 8;
for (bp = block->backpatch; bp != old_first_backpatch; bp = bp->next)
bp->offset_location += offset;
old_first_backpatch = block->backpatch;
}
/* Update the cache_info to reflect the new cached register status. */
if (!ends_block_p) /* Don't bother if the cache is dead anyway. */
{
/* Update the cached register information. */
for (op = desc->reg_op_info; op->legitimate_p; op++)
{
guest_reg = canonical_operands[op->operand_num];
assert (guest_reg >= 0 && guest_reg < NUM_GUEST_REGS);
r = &cache_info->guest_reg_status[guest_reg];
host_reg = r->host_reg;
switch (op->output_state)
{
case ROS_UNTOUCHED:
break;
case ROS_UNTOUCHED_DIRTY:
r->dirty_without_offset_p = TRUE;
break;
case ROS_INVALID:
host_uncache_reg (cache_info, guest_reg);
break;
case ROS_NATIVE:
case ROS_OFFSET:
case ROS_NATIVE_DIRTY:
case ROS_OFFSET_DIRTY:
#ifdef LITTLEENDIAN
case ROS_SWAP16:
case ROS_SWAP32:
case ROS_SWAP16_DIRTY:
case ROS_SWAP32_DIRTY:
#endif /* LITTLEENDIAN */
r->mapping = (op->output_state & 3);
r->dirty_without_offset_p = !!(op->output_state
& ROS_DIRTY_BIT);
break;
default:
abort ();
}
}
}
#ifdef DEBUG
verify_cache_consistency (cache_info);
#endif
/* Prepend all new backpatches to the final list. */
for (bp = block->backpatch; bp != NULL; bp = bp_next)
{
bp_next = bp->next;
bp->next = orig_backpatch;
orig_backpatch = bp;
}
block->backpatch = orig_backpatch;
/* Success! */
return TRUE;
failure:
/* No luck with this description; reset everything and try the next.
* Note that we have to restore everything even if we have no
* descriptions left to try, since our caller needs to know what
* they should spill if they transition to synthetic code.
*/
*code = orig_code;
*cache_info = orig_cache_info;
failure_no_copy:
for (bp = block->backpatch; bp != NULL; bp = bp_next)
{
bp_next = bp->next;
free (bp);
}
block->backpatch = NULL;
}
#ifdef DEBUG
verify_cache_consistency (cache_info);
#endif
/* We failed to generate the desired native code. */
block->backpatch = orig_backpatch;
return FALSE;
}
static void
host_uncache_reg (cache_info_t *c, int guest_reg)
{
guest_reg_status_t *r;
int host_reg;
r = &c->guest_reg_status[guest_reg];
host_reg = r->host_reg;
if (host_reg != NO_REG)
{
c->host_reg_to_guest_reg[host_reg] = NO_REG;
r->host_reg = NO_REG;
}
}
#endif /* GENERATE_NATIVE_CODE */

View File

@ -0,0 +1,80 @@
CC_FOR_BUILD=@CC_FOR_BUILD@
CFLAGS_FOR_BUILD=@CFLAGS_FOR_BUILD@
LOCAL_INCLUDES =
runtimedir = $(top_srcdir)/runtime
LOCAL_INCLUDES += -I$(srcdir)/include \
-I$(runtimedir)/include \
-I$(runtimedir)/../include -I$(srcdir) -I. -I../../../include
# these objects must be compiled with LIB_CC
MISC_OBJS = host-native.o host-xlate.o i386-aux.o xlate-aux.o
# these objects must be compiled with CC
TEMPLATE_OBJS = main.o template.o process.o
ANALYZE_OBJS = analyze.o template.o
XLATE_OBJS = xlatemain.o xlatetable.o xlate.o
host-native.o: host-native.c
$(CC) $(CFLAGS) -c $(LOCAL_INCLUDES) -o $(@F) $<
host-xlate.o: host-xlate.c
$(CC) $(CFLAGS) -c $(LOCAL_INCLUDES) -o $(@F) $<
i386-aux.o: i386-aux.c
$(CC) $(CFLAGS) -c $(LOCAL_INCLUDES) -o $(@F) $<
xlate-aux.o: xlate-aux.c
$(CC) $(CFLAGS) -c $(LOCAL_INCLUDES) -o $(@F) $<
xlatemain.o: xlatemain.c
$(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) -c $(LOCAL_INCLUDES) -o $(@F) $<
xlatetable.o: xlatetable.c
$(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) -c $(LOCAL_INCLUDES) -o $(@F) $<
xlate.o: xlate.c
$(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) -c $(LOCAL_INCLUDES) -o $(@F) $<
%.o:%.c
$(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) -c $(LOCAL_INCLUDES) -o $(@F) $<
## ifneq ($(NO_NATIVE), TRUE)
subdir-stmp: $(MISC_OBJS) src-stmp obj-stmp
echo $(MISC_OBJS) \
`ls _*.o` > subdir-stmp
## else
## subdir-stmp:
## > subdir-stmp
## endif
obj-stmp:
k=1; \
for i in i386_stubs/*; do \
$(CC) $(CFLAGS) $(LOCAL_INCLUDES) $$i -c -o _i386_$$k.o;\
k=`expr $$k + 1`; \
echo done processing $$i into _i386_$$k.o; \
done
touch obj-stmp
src-stmp: template
mkdir -p i386_stubs
./template "$(MAKE)"
$(RM) analyze
touch src-stmp
template: $(TEMPLATE_OBJS) analyze.c
$(CC_FOR_BUILD) $(TEMPLATE_OBJS) -o template
host-xlate.c host-xlate.h: xlate
./xlate
xlate: $(XLATE_OBJS)
$(CC_FOR_BUILD) $(XLATE_OBJS) -o xlate
analyze: $(ANALYZE_OBJS)
$(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) $(ANALYZE_OBJS) -o analyze
analyze.o: asmdata.h template.h
# Invoked only from ./template
nextobj:
#doesn't do anything

View File

@ -0,0 +1,844 @@
#include "template.h"
#include "asmdata.h"
#include "native.h"
#include "syn68k_private.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
typedef struct
{
int offset; /* Offset in bits from the start. */
int length; /* Number of bits long this field is. */
int operand_num; /* Which operand gets plugged in here. */
} oploc_t;
static const uint8 *compute_bits (int size, oploc_t *loc, int *loc_entries,
const char legal_p[NUM_SAMPLES]);
static void output_bits (const oploc_t *loc, int loc_entries,
const uint8 *bits, int size, const char *extra,
int indent);
static boolean_t generate_code (const char legal_p[NUM_SAMPLES],
const char *postamble,
boolean_t output_p, int indent);
static void code_for_bits (const char *b, int start, int length,
int indent, int offset, const oploc_t *loc);
int
main (int argc, char *argv[])
{
char legal_p[NUM_SAMPLES];
memset (legal_p, TRUE, sizeof legal_p);
/* beginning of ctm hack */
/* Starting with binutils-2.16.90.0.3, instructions like
lea 0x0(%eax),%eax
began compiling into the exact same byte sequence as
lea (%eax),%eax
That causes us to see a problem where one doesn't exist. If the code
for handling a 0 offset were working properly, there would be no need
for this hack, but it's not, so we simply go through and invalidate
all places where we have a 0 as the offset. This is not guaranteed to
work, but it does in practice and I'm not going to spend the time needed
to get proper handling of 0 offsets.
*/
{
int op;
for (op = 0; op < NUM_OPERANDS; op++)
{
if (TEMPLATE.operand[op].type == CONSTANT &&
strcmp(TEMPLATE.operand_name[op], "offset") == 0)
{
int s;
for (s = 0; s < NUM_SAMPLES; s++)
{
if (value[s][op] == 0)
legal_p[s] = FALSE;
}
}
}
}
/* end of ctm hack */
if (!generate_code (legal_p, "", TRUE, 2))
return EXIT_FAILURE;
return EXIT_SUCCESS;
}
#define SAMPLE_SIZE(n) (sample[n].end - sample[n].start)
/* Returns TRUE iff some legal samples have values for the specified
* operand in the given range and some do not.
*/
static boolean_t
operand_variety_p (int operand_num, long val_low, long val_high,
const char legal_p[NUM_SAMPLES])
{
boolean_t has_p, has_not_p;
int s;
has_p = has_not_p = FALSE;
for (s = 0; s < NUM_SAMPLES; s++)
if (legal_p[s])
{
if (value[s][operand_num] >= val_low
&& value[s][operand_num] <= val_high)
has_p = TRUE;
else
has_not_p = TRUE;
if (has_p && has_not_p)
return TRUE;
}
return FALSE;
}
static boolean_t
special_operand_p (int operand_num, long val_low, long val_high,
const char legal_p[NUM_SAMPLES])
{
int s;
boolean_t found_challenger_p;
found_challenger_p = FALSE;
for (s = 0; s < NUM_SAMPLES; s++)
if (legal_p[s]
&& value[s][operand_num] >= val_low
&& value[s][operand_num] <= val_high)
{
int s2, op;
/* Now see if every other sample differing _only_ in this value
* is of a different size.
*/
for (s2 = s + 1; s2 < NUM_SAMPLES; s2++)
{
if (!legal_p[s2])
continue;
/* See if s2 differs in operand_num but nothing else. */
for (op = 0; op < NUM_OPERANDS; op++)
{
if (op != operand_num)
{
if (value[s2][op] != value[s][op])
break;
}
else
{
if (value[s2][op] >= val_low
&& value[s2][op] <= val_high)
break;
}
}
if (op >= NUM_OPERANDS)
{
/* Yep, all other operands are the same and the operand is
* outside the specified range. If the size didn't
* change, this operand isn't the cause of any special case.
*/
if (SAMPLE_SIZE (s2) == SAMPLE_SIZE (s))
{
#if 0
printf ("operand %d, (%ld, %ld) disqualified by %d:%d\n",
operand_num, val_low, val_high, s, s2);
#endif
return FALSE;
}
found_challenger_p = TRUE;
}
}
}
/* If all or none of the legal samples have this attribute, then there's
* no reason to call it special.
*/
return found_challenger_p;
}
static void
filter (const char *old_legal_p, char *new_legal_p,
int operand_num, long val_low, long val_high, boolean_t match_p)
{
int s;
memset (new_legal_p, 0, NUM_SAMPLES * sizeof new_legal_p[0]);
for (s = 0; s < NUM_SAMPLES; s++)
if (old_legal_p[s]
&& (value[s][operand_num] >= val_low
&& value[s][operand_num] <= val_high) == match_p)
new_legal_p[s] = TRUE;
}
static void
spaces (int s)
{
while (s-- > 0)
putchar (' ');
}
static boolean_t
generate_code (const char legal_p[NUM_SAMPLES], const char *postamble,
boolean_t output_p, int indent)
{
int i, size;
boolean_t found_p, problem_p;
size = 0;
/* First see if every legal entry is the same size. */
for (i = 0, found_p = problem_p = FALSE; i < NUM_SAMPLES; i++)
if (legal_p[i])
{
int new_size;
new_size = SAMPLE_SIZE (i);
if (new_size != size)
{
if (found_p)
problem_p = TRUE;
else
{
size = new_size;
found_p = TRUE;
}
}
}
/* If they are all the same size, try to generate code for it. */
if (!problem_p)
{
oploc_t *loc;
int loc_entries;
const uint8 *example_bits;
loc = (oploc_t *) alloca (size * 8 * sizeof loc[0]); /* 1 per bit. */
example_bits = compute_bits (size, loc, &loc_entries, legal_p);
if (example_bits == NULL)
problem_p = TRUE;
else if (output_p)
{
output_bits (loc, loc_entries, example_bits, size, postamble,
indent);
}
}
/* problem_p may have changed, so check it again. */
if (problem_p)
{
char new_legal_p[NUM_SAMPLES];
int op;
/* For some reason we are unable to find a rule that generates all
* of the samples marked "legal". Therefore we need to figure out
* what is causing the special cases. There are three reasons for
* special cases, which may occur in conjunction with one another:
*
* (1) An immediate constant may be in the range -128 to 127.
* Most of the time this value can be stored as a sign-extended
* 8-bit constant.
* (2) An immediate constant may be the value 1.
* Shift and rotate instructions special case shifting by one bit.
* (3) An opcode uses %al/%ax/%eax in some way.
* Many opcodes special case this register and have a compact
* special version of the opcode that implicitly references it.
*/
for (op = 0; op < NUM_OPERANDS; op++)
{
if (TEMPLATE.operand[op].type == CONSTANT
&& special_operand_p (op, 1, 1, legal_p))
{
if (output_p)
{
spaces (indent);
printf ("if (%s == 1) {\n", TEMPLATE.operand_name[op]);
}
filter (legal_p, new_legal_p, op, 1, 1, TRUE);
if (!generate_code (new_legal_p, postamble, output_p,
indent + 2))
return FALSE;
if (output_p)
{
spaces (indent);
puts ("} else {");
}
filter (legal_p, new_legal_p, op, 1, 1, FALSE);
if (!generate_code (new_legal_p, postamble, output_p,
indent + 2))
return FALSE;
if (output_p)
{
spaces (indent);
puts ("}");
}
break;
}
else if (TEMPLATE.operand[op].type == CONSTANT
&& special_operand_p (op, 0, 0, legal_p))
{
if (output_p)
{
spaces (indent);
printf ("if (%s == 0) {\n", TEMPLATE.operand_name[op]);
}
filter (legal_p, new_legal_p, op, 0, 0, TRUE);
if (!generate_code (new_legal_p, postamble, output_p,
indent + 2))
return FALSE;
if (output_p)
{
spaces (indent);
puts ("} else {");
}
filter (legal_p, new_legal_p, op, 0, 0, FALSE);
if (!generate_code (new_legal_p, postamble, output_p,
indent + 2))
return FALSE;
if (output_p)
{
spaces (indent);
puts ("}");
}
break;
}
else if (TEMPLATE.operand[op].type == CONSTANT
&& TEMPLATE.operand[op].size != SIZE_8
&& special_operand_p (op, -128, 127, legal_p))
{
if (output_p)
{
spaces (indent);
printf ("if ((unsigned long)(%s + 128) < 256) {\n",
TEMPLATE.operand_name[op]);
}
filter (legal_p, new_legal_p, op, -128, 127, TRUE);
if (!generate_code (new_legal_p, postamble, output_p,
indent + 2))
return FALSE;
if (output_p)
{
spaces (indent);
puts ("} else {");
}
filter (legal_p, new_legal_p, op, -128, 127, FALSE);
if (!generate_code (new_legal_p, postamble, output_p,
indent + 2))
return FALSE;
if (output_p)
{
spaces (indent);
puts ("}");
}
break;
}
else if (TEMPLATE.operand[op].type == REGISTER
&& special_operand_p (op, 0, 0, legal_p))
{
if (output_p)
{
spaces (indent);
printf ("if (%s == 0) {\n", TEMPLATE.operand_name[op]);
}
filter (legal_p, new_legal_p, op, 0, 0, TRUE);
if (!generate_code (new_legal_p, postamble, output_p,
indent + 2))
return FALSE;
if (output_p)
{
spaces (indent);
puts ("} else {");
}
filter (legal_p, new_legal_p, op, 0, 0, FALSE);
if (!generate_code (new_legal_p, postamble, output_p,
indent + 2))
return FALSE;
if (output_p)
{
spaces (indent);
puts ("}\n");
}
break;
}
}
if (op >= NUM_OPERANDS)
{
/* Wow, nothing worked. This happens sometimes when invoking
* one special case disables another. The workaround for this
* is to actually try special casing (even though it didn't look
* necessary) and see if that works.
*/
for (op = 0; op < NUM_OPERANDS; op++)
{
if (TEMPLATE.operand[op].type == REGISTER
&& operand_variety_p (op, 0, 0, legal_p))
{
boolean_t good;
/* Test out and see if special casing register %al/%ax/%eax
* solves the problem.
*/
filter (legal_p, new_legal_p, op, 0, 0, TRUE);
good = generate_code (new_legal_p, postamble, FALSE, indent);
filter (legal_p, new_legal_p, op, 0, 0, FALSE);
good &= generate_code (new_legal_p, postamble, FALSE,
indent);
/* If it does, then actually go ahead and crank it out. */
if (good)
{
filter (legal_p, new_legal_p, op, 0, 0, TRUE);
if (output_p)
{
spaces (indent);
printf ("if (%s == 0) {\n",
TEMPLATE.operand_name[op]);
}
if (!generate_code (new_legal_p, postamble, output_p,
indent + 2))
return FALSE;
if (output_p)
{
spaces (indent);
puts ("} else {");
}
filter (legal_p, new_legal_p, op, 0, 0, FALSE);
if (!generate_code (new_legal_p, postamble, output_p,
indent + 2))
return FALSE;
if (output_p)
{
spaces (indent);
puts ("}");
}
break;
}
}
else if (TEMPLATE.operand[op].type == CONSTANT
&& operand_variety_p (op, -128, 127, legal_p))
{
boolean_t good;
/* Test out and see if special casing register %al/%ax/%eax
* solves the problem.
*/
filter (legal_p, new_legal_p, op, -128, 127, TRUE);
good = generate_code (new_legal_p, postamble, FALSE,
indent);
filter (legal_p, new_legal_p, op, -128, 127, FALSE);
good &= generate_code (new_legal_p, postamble, FALSE,
indent);
/* If it does, then actually go ahead and crank it out. */
if (good)
{
filter (legal_p, new_legal_p, op, -128, 127, TRUE);
if (output_p)
{
spaces (indent);
printf ("if ((unsigned long)(%s + 128) < 256) {\n",
TEMPLATE.operand_name[op]);
}
if (!generate_code (new_legal_p, postamble, output_p,
indent + 2))
return FALSE;
if (output_p)
{
spaces (indent);
puts ("} else {");
}
filter (legal_p, new_legal_p, op, -128, 127, FALSE);
if (!generate_code (new_legal_p, postamble, output_p,
indent + 2))
return FALSE;
if (output_p)
{
spaces (indent);
puts ("}");
}
break;
}
}
}
/* If even that failed, complain. */
if (op >= NUM_OPERANDS)
{
if (output_p)
fprintf (stderr, "Unable to derive rules for %s!\n",
TEMPLATE.macro_name);
return FALSE;
}
}
}
return TRUE;
}
static void
output_bits (const oploc_t *loc, int loc_entries, const uint8 *bits,
int size, const char *extra, int indent)
{
int ix, bit, blen, len, offset;
char b[1024], *n;
/* Fill in a string with all of the literal bits and operands characters. */
blen = size * 8;
n = b;
for (bit = 0; bit < blen; bit++)
{
int op;
for (op = 0; op < loc_entries; op++)
if (loc[op].offset <= bit
&& (loc[op].offset + loc[op].length > bit))
{
if (loc[op].operand_num >= NUM_OPERANDS)
abort ();
else
*n++ = 'a' + op;
break;
}
/* If we found no operand that overlaps these bits,
* then output the literal bit we know about.
*/
if (op >= loc_entries)
*n++ = ((bits[bit / 8] & (1 << (bit & 7))) ? '1' : '0');
}
*n = '\0';
offset = 0;
for (ix = 0; ix < blen; ix += len)
{
int try;
#ifdef QUADALIGN
len = MIN (32, HOST_CODE_T_BITS);
#else /* !QUADALIGN */
len = 32;
#endif /* !QUADALIGN */
len = MIN (blen - ix, len);
/* Make sure it's a power of 2. */
if (len & (len - 1))
{
if (len > 16)
len = 16;
else if (len > 8)
len = 8;
}
/* Choose the largest sequence we can that doesn't split up
* an operand field.
*/
try = len;
while (try >= 8
&& b[ix + try - 1] == b[ix + try]
&& b[ix + try] != '0' && b[ix + try] != '1')
try /= 2;
/* If we are forced to split an operand anyway, might as well
* crank out as many bits as possible. Therefore we'll only
* override len if we found a size without a split.
*/
if (b[ix + try - 1] != b[ix + try]
|| b[ix + try] == '0' || b[ix + try] == '1')
len = try;
assert (len % 8 == 0);
/* Crank out the code for this piece. */
code_for_bits (b, ix, len, indent, offset, loc);
offset += len / 8;
}
if (offset != 0)
{
spaces (indent);
if (offset % sizeof (host_code_t) == 0)
printf ("code += %d;\n", (int) (offset / sizeof (host_code_t)));
else
printf ("code = (host_code_t *)((char *)code + %d);\n", offset);
}
}
/* Given a string like "10000101aaaa10100" and the character 'a', this
* returns the index into the string where the first 'a' is found, and
* the number of contiguous 'a's at that index. Returns TRUE if such
* a sequence is found, else FALSE.
*/
static int
find_field (const char *string, int c, int *first, int *length)
{
const char *s;
int l;
for (s = string; *s != '\0' && *s != c; s++)
;
if (*s == '\0')
return FALSE;
*first = s - string;
for (l = 1; s[l] == c; l++)
;
*length = l;
return TRUE;
}
/* This generates a sequence of cstmts to create the code for a given
* bit string and set of operands.
*/
static void
code_for_bits (const char *b, int start, int length, int indent,
int offset, const oploc_t *loc)
{
uint32 literal_bits;
int n, end;
uint32 length_mask;
int first_done_p;
/* Sanity check. */
assert (length >= HOST_CODE_T_BITS && length % HOST_CODE_T_BITS == 0
&& length > 0 && length <= 32);
/* Construct a mask that indicates which bits will actually be output. */
length_mask = 0xFFFFFFFF >> (32 - length);
/* Compute the literal bits (1's and 0's) and put them in a mask.
* All non-literal bits will be treated as zeros.
*/
for (n = 0, literal_bits = 0; n < length; n++)
{
#ifndef LITTLEENDIAN
literal_bits = (literal_bits << 1) | (b[start + n] == '1');
#else /* LITTLEENDIAN */
literal_bits |= (uint32) (b[start + n] == '1') << n;
#endif /* LITTLEENDIAN */
}
/* Output the assignment operator. */
spaces (indent);
if (length == HOST_CODE_T_BITS)
{
if (offset % sizeof (host_code_t) == 0)
printf ("code[%d] =", (int) (offset / sizeof (host_code_t)));
else
printf ("*(host_code_t *)(%scode + %d) =",
(sizeof (host_code_t) == 1) ? "" : "(char *)", offset);
}
else
{
if (offset == 0)
printf ("*(uint%d *)code =", length);
else
printf ("*(uint%d *)(%scode + %d) =", length,
(sizeof (host_code_t) == 1) ? "" : "(char *)", offset);
}
/* Output the base constant. */
if (literal_bits != 0)
{
printf (" 0x%lX", (unsigned long) literal_bits);
first_done_p = TRUE;
}
else
{
putchar (' ');
first_done_p = FALSE;
}
/* Loop over all of the operands. */
end = start + length;
for (n = 0; n < 26; n++)
{
int field_start, field_length, field_end;
/* See if this operand overlaps the bits we are cranking out. */
if (find_field (b, n + 'a', &field_start, &field_length)
&& field_start + field_length > start
&& field_start < start + length)
{
uint32 mask;
int shift;
field_end = field_start + field_length;
if (first_done_p)
fputs (" | ", stdout);
/* Compute a mask for the field of interest. */
mask = 0xFFFFFFFF >> (32 - field_length);
#ifndef LITTLEENDIAN
shift = end - field_end;
#else /* LITTLEENDIAN */
shift = field_start - start;
#endif /* LITTLEENDIAN */
if (shift != 0)
fputs ("(", stdout);
/* Mask out all but the relevant bits if necessary. There's
* no need to mask if we are shifting the value so far that
* the masked bits are shifted out of the resulting value
* anyway.
*/
if ((shift >= 0 && ((~mask << shift) & length_mask) != 0)
|| (shift < 0 && ((~mask >> -shift) & length_mask) != 0))
{
assert (TEMPLATE.operand_name[loc[n].operand_num] != NULL);
printf ("(%s & 0x%lX)",
TEMPLATE.operand_name[loc[n].operand_num],
(unsigned long) mask);
}
else
{
fputs (TEMPLATE.operand_name[loc[n].operand_num], stdout);
}
/* Shift the bits to where they belong (computed above). */
if (shift != 0)
{
if (shift > 0)
printf (" << %d)", shift);
else
printf (" >> %d)", -shift);
}
first_done_p = TRUE;
}
}
/* If all bits are zero, actually output a 0. */
if (literal_bits == 0 && !first_done_p)
fputs ("0", stdout);
puts (";");
}
static const uint8 *
compute_bits (int size, oploc_t *loc, int *loc_entries,
const char legal_p[NUM_SAMPLES])
{
uint8 *fixed;
const uint8 *bits;
int s, bit, op, num_bits, entries;
/* Set up defaults. */
*loc_entries = entries = 0;
/* Allocate a bit array for which bits change as the operands change. */
fixed = (uint8 *) alloca (size);
memset (fixed, ~0, size);
/* Identify which bits change and which remain fixed. */
bits = NULL;
for (s = 0; s < NUM_SAMPLES; s++)
if (legal_p[s])
{
int byte;
if (bits == NULL)
bits = sample[s].start;
else
for (byte = 0; byte < size; byte++)
fixed[byte] &= ~(bits[byte] ^ sample[s].start[byte]);
}
/* If we found nothing of this size, return NULL. */
if (bits == NULL)
return NULL;
/* Now we must fill in the changed bits with the operands we've got. */
for (bit = 0, num_bits = size * 8; bit < num_bits; )
{
int most_consecutive, best_op;
/* Find the next non-fixed bit. */
for (; bit < num_bits && (fixed[bit / 8] & (1 << (bit & 7))); bit++)
;
/* Find an operand whose values account for the most consecutive
* bits starting at this offset.
*/
if (bit >= num_bits)
break;
most_consecutive = best_op = 0;
for (op = 0; op < NUM_OPERANDS; op++)
{
int consec = 40;
for (s = 0; consec > 0 && s < NUM_SAMPLES; s++)
{
int c;
if (!legal_p[s])
continue;
for (c = 0; c < 32 && bit + c < num_bits; c++)
if ((((sample[s].start[(bit + c) / 8] >> ((bit + c) & 7)) & 1)
!= ((value[s][op] >> c) & 1))
|| (fixed[(bit + c) / 8] & (1 << ((bit + c) & 7))))
break;
if (c < consec)
consec = c;
}
if (consec <= 32 && consec > most_consecutive)
{
most_consecutive = consec;
best_op = op;
}
}
if (most_consecutive == 0)
{
#if 0
fprintf (stderr, "Unable to account for bit %d of %s "
"(size == %d)!\n",
bit, TEMPLATE.macro_name, size);
most_consecutive = 1; /* Keep going. */
best_op = 1000;
#else
return NULL;
#endif
}
assert (best_op < NUM_OPERANDS);
loc[entries].offset = bit;
loc[entries].length = most_consecutive;
loc[entries].operand_num = best_op;
entries++;
bit += most_consecutive;
}
*loc_entries = entries;
return bits;
}

View File

@ -0,0 +1,617 @@
#include "syn68k_private.h"
#ifdef GENERATE_NATIVE_CODE
#include "native.h"
#include "i386-isa.h"
#include "interrupt.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#ifndef offsetof
#define offsetof(t, f) ((int32) &(((t *) 0)->f))
#endif
/* Set to TRUE if we are on an i486 or better, which means we can use
* the bswap instruction.
*/
uint8 have_i486_p;
/* This stub will get copied to the native code entry point for a block,
* and then backpatched if it's actually used.
*/
host_code_t native_to_synth_stub[] =
{
0xBE, 0x78, 0x56, 0x34, 0x12, /* movl $0x12345678,%esi */
0xE9, 0x79, 0x56, 0x34, 0x12, /* jmp $0x12345679 */
};
void
host_backpatch_native_to_synth_stub (Block *b, host_code_t *stub,
uint32 *synth_opcode)
{
assert (!memcmp (stub, native_to_synth_stub, NATIVE_TO_SYNTH_STUB_BYTES));
assert (sizeof native_to_synth_stub == NATIVE_TO_SYNTH_STUB_BYTES);
/* Fill in the new synthetic PC so it points to the operands of
* the first synthetic instruction.
*/
*(uint32 *)(stub + 1) = ((uint32) synth_opcode) + 4;
/* Fill in the jmp's relative offset so that it jumps to the
* handler code for this synthetic opcode. The branch is relative
* to the _end_ of the bytes for the jmp instruction.
*/
*(uint32 *)(stub + 6) = *synth_opcode - (((uint32) stub) + 10);
}
#ifdef SYNCHRONOUS_INTERRUPTS
/* These stubs use comparisons with %ebp as a hack. Since our
* interrupt changed flag is either -1 or LONG_MAX, as long as
* %ebp is somewhere in between it will work. This makes the code
* slightly more compact and faster (since the alternative is to use a
* constant zero, and instructions with two constants take longer to
* decode). We verify below that INTERRUPT_STATUS_CHANGED < %ebp and
* INTERRUPT_STATUS_UNCHANGED >= %ebp. We overwrite some of the
* constant operands when we backpatch the stub.
*/
#ifdef USE_BIOS_TIMER
host_code_t check_interrupt_stub[] =
{
0x64, 0x39, 0x2D, 0x78, 0x56, 0x34, 0x12, /* cmpl %ebp,%fs:0x12345678 */
0xB8, 0x78, 0x56, 0x34, 0x12, /* movl $my_m68k_pc,%eax */
0x0F, 0x88, 0x78, 0x56, 0x34, 0x12, /* js host_interrupt_... */
};
#else /* !USE_BIOS_TIMER */
host_code_t check_interrupt_stub[] =
{
#ifdef __CHECKER__
0x83, 0x3D, 0x78, 0x56, 0x34, 0x12, 0x00, /* cmpl $0,0x12345678 */
0xB8, 0x78, 0x56, 0x34, 0x12, /* movl $my_m68k_pc,%eax */
0x0F, 0x88, 0x78, 0x56, 0x34, 0x12, /* js host_interrupt_... */
#else /* !__CHECKER__ */
/* The "0x99" here is really "0xNN" and gets replaced below. */
0x39, 0x6D, 0x99, /* cmpl %ebp,0xNN(%ebp) */
0xB8, 0x78, 0x56, 0x34, 0x12, /* movl $my_m68k_pc,%eax */
0x0F, 0x88, 0x78, 0x56, 0x34, 0x12, /* js host_interrupt_... */
#endif /* !__CHECKER__ */
};
#endif /* !USE_BIOS_TIMER */
/* This is just here to fool the C compiler. */
extern host_code_t host_interrupt_status_changed[]
asm ("_host_interrupt_status_changed");
/* This is the stub called from the emulator when the interrupt status
* changes. %eax contains the m68k PC of the instruction about to be
* executed when the interrupt was detected. This stub calls
* interrupt_process_any_pending() to handle the interrupt; that function
* returns the m68k pc at which execution should resume. Note that we
* don't recursively enter the emulator here, we just adjust the m68k PC
* and jump back into the fray.
*/
asm (".text\n\t"
".align 4\n"
"_host_interrupt_status_changed:\n\t"
#ifdef USE_BIOS_TIMER
"pushl %fs\n\t"
#endif
"pushl %eax\n\t"
"call _interrupt_process_any_pending\n\t"
"pushl %eax\n\t"
"call _hash_lookup_code_and_create_if_needed\n\t"
"movl %eax,%esi\n\t"
"addl $8,%esp\n\t"
"movl (%eax),%eax\n\t"
"addl $4,%esi\n\t"
#ifdef USE_BIOS_TIMER
"popl %fs\n\t"
#endif
"jmp *%eax");
void
host_backpatch_check_interrupt_stub (Block *b, host_code_t *stub)
{
assert (!memcmp (stub, check_interrupt_stub, CHECK_INTERRUPT_STUB_BYTES));
assert (sizeof check_interrupt_stub == CHECK_INTERRUPT_STUB_BYTES);
/* No need to replace the flag's address; this part of
* check_interrupt_stub[] was already patched in host_native_code_init.
*/
/* Move this block's m68k start address into %eax. */
*(uint32 *)(stub + CHECK_INTERRUPT_STUB_BYTES - 10) = b->m68k_start_address;
/* Fill in the conditional branch's relative offset to cause it
* to branch to the interrupt handler.
*/
*(uint32 *)(stub + CHECK_INTERRUPT_STUB_BYTES - 4)
= (((int32) host_interrupt_status_changed)
- (((int32) stub) + CHECK_INTERRUPT_STUB_BYTES));
}
#endif /* SYNCHRONOUS_INTERRUPTS */
void
host_native_code_init ()
{
uint32 scratch1, scratch2;
#ifdef __GNUC__
uint8 i486_p;
/* Adapted from _Assembly Language: For Real Programmers Only_ p. 561.
* This code determines if we are on an i486 or higher. We care because
* those chips have the "bswap" instruction for byte swapping.
*/
asm ("pushfl\n\t"
"pushfl\n\t"
"popl %0\n\t"
"xorl $0x40000,%0\n\t"
"pushl %0\n\t"
"popfl\n\t"
"pushfl\n\t"
"popl %1\n\t"
"cmpl %0,%1\n\t"
"jnz 1f\n\t"
"xorl $0x40000,%0\n\t"
"pushl %0\n\t"
"popfl\n\t"
"pushfl\n\t"
"popl %1\n\t"
"cmpl %0,%1\n"
"1:\n\t"
"setz %b2\n\t"
"popfl"
: "=r" (scratch1), "=r" (scratch2), "=abcd" (i486_p));
have_i486_p = i486_p;
#else /* !__GNUC__ */
#warning "We don't know if we're on an i486!"
have_i486_p = FALSE; /* Assume the worst. */
#endif /* !__GNUC__ */
#ifdef SYNCHRONOUS_INTERRUPTS
#ifndef __CHECKER__
/* This is for the %ebp hack we use in the check_interrupt stub. */
assert (INTERRUPT_STATUS_CHANGED < ((int32) &cpu_state)
&& INTERRUPT_STATUS_UNCHANGED >= ((int32) &cpu_state));
#endif
#ifdef USE_BIOS_TIMER
*(uint32 *)(&check_interrupt_stub[3]) = dos_interrupt_flag_addr;
#else /* !USE_BIOS_TIMER */
assert (offsetof (CPUState, interrupt_status_changed) < 128);
# ifdef __CHECKER__
*(void **)(&check_interrupt_stub[2]) = &cpu_state.interrupt_status_changed;
# else /* !__CHECKER__ */
check_interrupt_stub[2] = offsetof (CPUState, interrupt_status_changed);
# endif /* !__CHECKER__ */
#endif /* !USE_BIOS_TIMER */
#endif /* SYNCHRONOUS_INTERRUPTS */
}
int
host_alloc_reg (cache_info_t *c, host_code_t **codep,
unsigned cc_spill_if_changed,
host_reg_mask_t legal)
{
static int last_smashed = 0; /* Explained below. */
guest_reg_status_t *r;
int i, reg;
/* First do a quick check for a totally free register. We want
* to try the higher registers first, because they are less in demand,
* and if this guy actually wants one, let's give it to him.
*/
for (i = NUM_HOST_REGS - 1; i >= 0; i--)
if (legal & (1L << i))
{
if (c->host_reg_to_guest_reg[i] == NO_REG)
return i;
}
/* Nope, didn't find any empty ones! Look for a non-dirty one. If we
* don't find that, take anything we can get. We keep a static variable
* around to keep track of the last cached register we took from someone.
* This way we can cycle through instead of continually hammering
* one recently used register.
*/
reg = NO_REG;
for (i = last_smashed - 1; i >= 0; i--)
if (legal & (1L << i))
{
r = &c->guest_reg_status[c->host_reg_to_guest_reg[i]];
if (!r->dirty_without_offset_p
&& (r->mapping != MAP_OFFSET || r->offset == 0))
goto found_it;
if (reg == NO_REG)
reg = i;
}
for (i = NUM_HOST_REGS - 1; i >= last_smashed; i--)
if (legal & (1L << i))
{
r = &c->guest_reg_status[c->host_reg_to_guest_reg[i]];
if (!r->dirty_without_offset_p
&& (r->mapping != MAP_OFFSET || r->offset == 0))
goto found_it;
if (reg == NO_REG)
reg = i;
}
if (reg == NO_REG)
return NO_REG;
i = reg;
found_it:
last_smashed = i;
host_spill_reg (c, codep, cc_spill_if_changed, c->host_reg_to_guest_reg[i]);
return i;
}
int
host_movel_reg_reg (COMMON_ARGS, int32 src_reg, int32 dst_reg)
{
return i386_movl_reg_reg (COMMON_ARG_NAMES, src_reg, dst_reg);
}
void
host_cache_reg (cache_info_t *c, host_code_t **codep,
unsigned cc_spill_if_changed, int guest_reg,
int host_reg)
{
guest_reg_status_t *r;
/* Load up the register. */
/* NOTE: you cannot use %ebp as the base without any constant offset
* on the i386. That is a special "escape" which means something else.
* You must use an explicit 0 offset if that's what you want.
*/
i386_movl_indoff_reg (c, codep, cc_spill_if_changed, M68K_CC_NONE, NO_REG,
offsetof (CPUState, regs[guest_reg].ul.n),
REG_EBP, host_reg);
/* Set up the guest reg info. */
r = &c->guest_reg_status[guest_reg];
r->host_reg = host_reg;
r->mapping = MAP_NATIVE;
r->dirty_without_offset_p = FALSE;
/* Keep track of what this host register is doing. */
c->host_reg_to_guest_reg[host_reg] = guest_reg;
}
void
host_unoffset_reg (cache_info_t *c, host_code_t **codep,
unsigned cc_spill_if_changed,
int guest_reg)
{
guest_reg_status_t *r;
int host_reg;
r = &c->guest_reg_status[guest_reg];
host_reg = r->host_reg;
if (host_reg != NO_REG && r->mapping == MAP_OFFSET)
{
int32 offset = r->offset;
if (offset != 0)
{
if (!cc_spill_if_changed)
{
if (offset == 1)
i386_incl_reg (c, codep, cc_spill_if_changed, M68K_CC_NONE,
NO_REG, host_reg);
else if (offset == -1)
i386_decl_reg (c, codep, cc_spill_if_changed, M68K_CC_NONE,
NO_REG, host_reg);
else if (offset < 0) /* Same speed but more readable. */
i386_subl_imm_reg (c, codep, cc_spill_if_changed, M68K_CC_NONE,
NO_REG, -offset, host_reg);
else
i386_addl_imm_reg (c, codep, cc_spill_if_changed, M68K_CC_NONE,
NO_REG, offset, host_reg);
}
else /* We can offset without spilling any cc's with leal. */
{
i386_leal_indoff (c, codep, M68K_CC_NONE, M68K_CC_NONE,
NO_REG, offset, host_reg, host_reg);
}
r->dirty_without_offset_p = TRUE;
}
r->mapping = MAP_NATIVE;
}
}
void
host_unoffset_regs (cache_info_t *c, host_code_t **codep,
unsigned cc_spill_if_changed)
{
int i;
for (i = NUM_GUEST_REGS - 1; i >= 0; i--)
host_unoffset_reg (c, codep, cc_spill_if_changed, i);
}
/* This canonicalizes all registers so they are ready to simply
* be written out to memory.
*/
inline void
make_dirty_regs_native (cache_info_t *c, host_code_t **codep,
unsigned cc_spill_if_changed)
{
int i;
for (i = NUM_GUEST_REGS - 1; i >= 0; i--)
{
guest_reg_status_t *r;
int host_reg;
r = &c->guest_reg_status[i];
host_reg = r->host_reg;
if (host_reg != NO_REG)
{
switch (r->mapping)
{
case MAP_NATIVE:
break;
case MAP_OFFSET:
if (r->offset != 0)
{
if (!cc_spill_if_changed)
{
if (r->offset == 1)
i386_incl_reg (c, codep, cc_spill_if_changed,
M68K_CC_NONE, NO_REG, host_reg);
else if (r->offset == -1)
i386_decl_reg (c, codep, cc_spill_if_changed,
M68K_CC_NONE, NO_REG, host_reg);
else
i386_addl_imm_reg (c, codep, cc_spill_if_changed,
M68K_CC_NONE, NO_REG, r->offset,
host_reg);
}
else /* We can offset without spilling any cc's with leal. */
{
i386_leal_indoff (c, codep, M68K_CC_NONE,
M68K_CC_NONE, NO_REG, r->offset,
host_reg, host_reg);
}
r->dirty_without_offset_p = TRUE;
}
break;
case MAP_SWAP16:
if (r->dirty_without_offset_p)
HOST_SWAP16 (host_reg);
break;
case MAP_SWAP32:
if (r->dirty_without_offset_p)
HOST_SWAP32 (host_reg);
break;
default:
abort ();
}
r->mapping = MAP_NATIVE;
}
}
}
inline void
host_spill_reg (cache_info_t *c, host_code_t **codep,
unsigned cc_spill_if_changed,
int guest_reg)
{
guest_reg_status_t *r;
int host_reg;
r = &c->guest_reg_status[guest_reg];
host_reg = r->host_reg;
if (host_reg != NO_REG)
{
if (r->dirty_without_offset_p
|| (r->mapping == MAP_OFFSET && r->offset != 0))
{
/* Canonicalize the cached register before spilling it out. */
switch (r->mapping)
{
case MAP_NATIVE:
break;
case MAP_OFFSET:
host_unoffset_reg (c, codep, cc_spill_if_changed, guest_reg);
break;
case MAP_SWAP16:
HOST_SWAP16 (host_reg);
break;
case MAP_SWAP32:
host_swap32 (c, codep, cc_spill_if_changed, M68K_CC_NONE, NO_REG,
host_reg);
break;
default:
abort ();
}
/* NOTE: you cannot use %ebp as the base without any
* constant offset on the i386. That is a special "escape"
* which means something else. You must use an explicit 0
* offset if that's what you want.
*/
i386_movl_reg_indoff (c, codep, cc_spill_if_changed, M68K_CC_NONE,
NO_REG, host_reg,
offsetof (CPUState, regs[guest_reg].ul.n),
REG_EBP);
r->mapping = MAP_NATIVE;
r->dirty_without_offset_p = FALSE;
}
c->host_reg_to_guest_reg[host_reg] = NO_REG;
r->host_reg = NO_REG;
}
}
void
host_spill_regs (cache_info_t *c, host_code_t **codep,
unsigned cc_spill_if_changed)
{
int i;
/* Canonicalize all of the registers, and then spill all the dirty ones.
* Doing it this way gives us slightly better Pentium pairability,
* since instead of code like:
* addl $4,%edi
* movl %edi,_a0
* addl $4,%esi
* movl %esi,_a1
* rorw $8,%eax
* movl %eax,_d0
*
* we get:
*
* addl $4,%edi
* addl $4,%esi
* rorw $8,%eax
* movl %edi,_a0
* movl %esi,_a1
* movl %eax,_d0
*
* Not a huge win, since the spill of the previous guy can overlap with
* the canonicalization of the next one, but this is a relatively
* cheap optimization.
*/
make_dirty_regs_native (c, codep, cc_spill_if_changed);
for (i = NUM_GUEST_REGS - 1; i >= 0; i--)
{
guest_reg_status_t *r;
int host_reg;
r = &c->guest_reg_status[i];
host_reg = r->host_reg;
if (host_reg != NO_REG)
{
if (r->dirty_without_offset_p)
{
/* NOTE: you cannot use %ebp as the base without any
* constant offset on the i386. That is a special "escape"
* which means something else. You must use an explicit 0
* offset if that's what you want.
*/
i386_movl_reg_indoff (c, codep, cc_spill_if_changed,
M68K_CC_NONE, NO_REG, host_reg,
offsetof (CPUState, regs[i].ul.n),
REG_EBP);
r->dirty_without_offset_p = FALSE;
}
c->host_reg_to_guest_reg[host_reg] = NO_REG;
r->host_reg = NO_REG;
}
}
}
void
host_spill_cc_bits (cache_info_t *c, host_code_t **codep, unsigned spill_cc)
{
unsigned cc;
assert (!(spill_cc & ~M68K_CC_ALL));
cc = spill_cc & c->cached_cc & c->dirty_cc;
if (cc)
{
if (cc & M68K_CCZ)
i386_setnz_indoff (c, codep, 0, 0, NO_REG,
offsetof (CPUState, ccnz), REG_EBP);
if (cc & M68K_CCN)
i386_sets_indoff (c, codep, 0, 0, NO_REG,
offsetof (CPUState, ccn), REG_EBP);
if (cc & M68K_CCC)
i386_setc_indoff (c, codep, 0, 0, NO_REG,
offsetof (CPUState, ccc), REG_EBP);
if (cc & M68K_CCV)
i386_seto_indoff (c, codep, 0, 0, NO_REG,
offsetof (CPUState, ccv), REG_EBP);
if (cc & M68K_CCX)
i386_setc_indoff (c, codep, 0, 0, NO_REG,
offsetof (CPUState, ccx), REG_EBP);
c->dirty_cc &= ~cc;
}
/* We typically call this when we are about to clobber cc bits, so we
* should mark them as not being cached. In special circumstances,
* like conditional branches, we'll want to remember that the cc bits
* _are_ actually cached.
*/
c->cached_cc &= ~spill_cc;
}
int
host_swap16 (COMMON_ARGS, int32 host_reg)
{
HOST_SWAP16 (host_reg);
return 0;
}
int
host_swap16_to_32 (COMMON_ARGS, int32 host_reg)
{
i386_rorl_imm_reg (c, codep, cc_spill_if_changed, M68K_CC_NONE, NO_REG, 16,
host_reg);
return i386_rorw_imm_reg (c, codep, 0, M68K_CC_NONE, NO_REG, 8,
host_reg);
}
int
host_swap32 (COMMON_ARGS, int32 host_reg)
{
if (have_i486_p)
{
i386_bswap (c, codep, cc_spill_if_changed, M68K_CC_NONE, NO_REG,
host_reg);
}
else
{
i386_rorw_imm_reg (c, codep, cc_spill_if_changed, M68K_CC_NONE, NO_REG,
8, host_reg);
i386_rorl_imm_reg (c, codep, M68K_CC_NONE, M68K_CC_NONE, NO_REG,
16, host_reg);
i386_rorw_imm_reg (c, codep, M68K_CC_NONE, M68K_CC_NONE, NO_REG,
8, host_reg);
}
return 0;
}
int
host_swap32_to_16 (COMMON_ARGS, int32 host_reg)
{
i386_rorw_imm_reg (c, codep, cc_spill_if_changed, M68K_CC_NONE, NO_REG,
8, host_reg);
return i386_rorl_imm_reg (c, codep, 0, M68K_CC_NONE, NO_REG,
16, host_reg);
}
#endif

View File

@ -0,0 +1,84 @@
#ifndef _HOST_NATIVE_H_
#define _HOST_NATIVE_H_
#define REG_EAX 0
#define REG_ECX 1
#define REG_EDX 2
#define REG_EBX 3
#define REG_ESP 4
#define REG_EBP 5
#define REG_ESI 6
#define REG_EDI 7
#define REG_AX 0
#define REG_CX 1
#define REG_DX 2
#define REG_BX 3
#define REG_SP 4
#define REG_BP 5
#define REG_SI 6
#define REG_DI 7
#define REG_AL 0
#define REG_CL 1
#define REG_DL 2
#define REG_BL 3
#define REG_AH 4
#define REG_CH 5
#define REG_DH 6
#define REG_BH 7
/* Don't allow %ebp or %esp. These registers are strange because in
* some situations they are used as "escape" registers on the i386.
* We could work around this by only allowing them when they are legal,
* but legend has it that we can't use either under DPMI because of
* a strange stack segment value.
*/
#define ALLOCATABLE_REG_MASK ((host_reg_mask_t) ( (1 << REG_EAX) \
| (1 << REG_EBX) \
| (1 << REG_ECX) \
| (1 << REG_EDX) \
| (1 << REG_ESI) \
| (1 << REG_EDI)))
/* Any of the 6 regs we free up to use. */
#define REGSET_ALL ALLOCATABLE_REG_MASK
/* Only those regs which are byte-addressable: %eax, %ebx, %ecx, %edx. */
#define REGSET_BYTE ((host_reg_mask_t) ( (1 << REG_EAX) \
| (1 << REG_EBX) \
| (1 << REG_ECX) \
| (1 << REG_EDX)))
#define REGSET_EMPTY 0
#define NUM_HOST_REGS 8
typedef uint8 host_code_t;
extern uint8 have_i486_p;
#define NATIVE_TO_SYNTH_STUB_BYTES 10
#define NATIVE_TO_SYNTH_STUB_WORDS \
(((NATIVE_TO_SYNTH_STUB_BYTES + 1) / 2 + 1) & ~1)/* Must be even # of words. */
#ifdef SYNCHRONOUS_INTERRUPTS
# ifdef USE_BIOS_TIMER
# define CHECK_INTERRUPT_STUB_BYTES 18
# else /* !USE_BIOS_TIMER */
# if defined (__CHECKER__)
# define CHECK_INTERRUPT_STUB_BYTES 18
# else /* !__CHECKER__ */
# define CHECK_INTERRUPT_STUB_BYTES 14
# endif /* !__CHECKER__ */
# endif /* !USE_BIOS_TIMER */
#else
# define CHECK_INTERRUPT_STUB_BYTES 0
#endif /* !SYNCHRONOUS_INTERRUPTS */
#define HOST_SWAP16(r) \
i386_rorw_imm_reg (c, codep, cc_spill_if_changed, M68K_CC_NONE, NO_REG, 8, (r))
#define HOST_SWAP32(r) \
host_swap32 (c, codep, cc_spill_if_changed, M68K_CC_NONE, NO_REG, (r))
#endif /* !_HOST_NATIVE_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,660 @@
#ifndef _I386_AUX_H_
#define _I386_AUX_H_
#include "syn68k_private.h"
#include "native.h"
extern int host_testb_reg (COMMON_ARGS, int32 reg);
extern int host_testw_reg (COMMON_ARGS, int32 reg);
extern int host_testl_reg (COMMON_ARGS, int32 reg);
#define host_testb_swapped_reg host_testb_reg
extern int host_testw_swapped_reg (COMMON_ARGS, int32 reg);
extern int host_testl_swapped_reg (COMMON_ARGS, int32 reg);
extern int host_swap16_sext_test_reg (COMMON_ARGS, int32 reg);
extern int host_andb_imm_reg (COMMON_ARGS, int32 val, int32 reg);
extern int host_andw_imm_reg (COMMON_ARGS, int32 val, int32 reg);
extern int host_andl_imm_reg (COMMON_ARGS, int32 val, int32 reg);
extern int host_orb_imm_reg (COMMON_ARGS, int32 val, int32 reg);
extern int host_orw_imm_reg (COMMON_ARGS, int32 val, int32 reg);
extern int host_orl_imm_reg (COMMON_ARGS, int32 val, int32 reg);
extern int host_xorb_imm_reg (COMMON_ARGS, int32 val, int32 reg);
extern int host_xorw_imm_reg (COMMON_ARGS, int32 val, int32 reg);
extern int host_xorl_imm_reg (COMMON_ARGS, int32 val, int32 reg);
extern int host_andb_ind_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_andw_ind_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_andl_ind_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_orb_ind_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_orw_ind_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_orl_ind_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_cmpb_ind_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_cmpw_ind_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_cmpl_ind_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_andb_predec_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_andw_predec_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_andl_predec_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_orb_predec_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_orw_predec_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_orl_predec_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_cmpb_predec_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_cmpw_predec_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_cmpl_predec_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_andb_postinc_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_andw_postinc_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_andl_postinc_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_orb_postinc_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_orw_postinc_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_orl_postinc_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_cmpb_postinc_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_cmpw_postinc_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_cmpl_postinc_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_andb_indoff_reg (COMMON_ARGS, int32 offset, int32 addr_reg,
int32 reg);
extern int host_andw_indoff_reg (COMMON_ARGS, int32 offset, int32 addr_reg,
int32 reg);
extern int host_andl_indoff_reg (COMMON_ARGS, int32 offset, int32 addr_reg,
int32 reg);
extern int host_orb_indoff_reg (COMMON_ARGS, int32 offset, int32 addr_reg,
int32 reg);
extern int host_orw_indoff_reg (COMMON_ARGS, int32 offset, int32 addr_reg,
int32 reg);
extern int host_orl_indoff_reg (COMMON_ARGS, int32 offset, int32 addr_reg,
int32 reg);
extern int host_cmpb_indoff_reg (COMMON_ARGS, int32 offset, int32 addr_reg,
int32 reg);
extern int host_cmpw_indoff_reg (COMMON_ARGS, int32 offset, int32 addr_reg,
int32 reg);
extern int host_cmpl_indoff_reg (COMMON_ARGS, int32 offset, int32 addr_reg,
int32 reg);
extern int host_addb_ind_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_subb_ind_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_addb_predec_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_subb_predec_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_addb_postinc_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_subb_postinc_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_addb_indoff_reg (COMMON_ARGS, int32 offset, int32 addr_reg,
int32 reg);
extern int host_subb_indoff_reg (COMMON_ARGS, int32 offset, int32 addr_reg,
int32 reg);
extern int host_andb_ind_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_andw_ind_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_andl_ind_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_orb_ind_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_orw_ind_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_orl_ind_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_cmpb_ind_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_cmpw_ind_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_cmpl_ind_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_andb_predec_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_andw_predec_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_andl_predec_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_orb_predec_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_orw_predec_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_orl_predec_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_cmpb_predec_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_cmpw_predec_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_cmpl_predec_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_andb_postinc_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_andw_postinc_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_andl_postinc_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_orb_postinc_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_orw_postinc_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_orl_postinc_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_cmpb_postinc_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_cmpw_postinc_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_cmpl_postinc_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_andb_indoff_reg (COMMON_ARGS, int32 offset, int32 addr_reg,
int32 reg);
extern int host_andw_indoff_reg (COMMON_ARGS, int32 offset, int32 addr_reg,
int32 reg);
extern int host_andl_indoff_reg (COMMON_ARGS, int32 offset, int32 addr_reg,
int32 reg);
extern int host_orb_indoff_reg (COMMON_ARGS, int32 offset, int32 addr_reg,
int32 reg);
extern int host_orw_indoff_reg (COMMON_ARGS, int32 offset, int32 addr_reg,
int32 reg);
extern int host_orl_indoff_reg (COMMON_ARGS, int32 offset, int32 addr_reg,
int32 reg);
extern int host_cmpb_indoff_reg (COMMON_ARGS, int32 offset, int32 addr_reg,
int32 reg);
extern int host_cmpw_indoff_reg (COMMON_ARGS, int32 offset, int32 addr_reg,
int32 reg);
extern int host_cmpl_indoff_reg (COMMON_ARGS, int32 offset, int32 addr_reg,
int32 reg);
extern int host_addb_ind_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_subb_ind_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_addb_predec_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_subb_predec_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_addb_postinc_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_subb_postinc_reg (COMMON_ARGS, int32 addr_reg, int32 reg);
extern int host_addb_indoff_reg (COMMON_ARGS, int32 offset, int32 addr_reg,
int32 reg);
extern int host_subb_indoff_reg (COMMON_ARGS, int32 offset, int32 addr_reg,
int32 reg);
extern int host_andb_reg_ind (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_andw_reg_ind (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_andl_reg_ind (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_orb_reg_ind (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_orw_reg_ind (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_orl_reg_ind (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_xorb_reg_ind (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_xorw_reg_ind (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_xorl_reg_ind (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_cmpb_reg_ind (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_cmpw_reg_ind (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_cmpl_reg_ind (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_andb_reg_predec (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_andw_reg_predec (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_andl_reg_predec (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_orb_reg_predec (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_orw_reg_predec (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_orl_reg_predec (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_xorb_reg_predec (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_xorw_reg_predec (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_xorl_reg_predec (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_cmpb_reg_predec (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_cmpw_reg_predec (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_cmpl_reg_predec (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_andb_reg_postinc (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_andw_reg_postinc (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_andl_reg_postinc (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_orb_reg_postinc (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_orw_reg_postinc (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_orl_reg_postinc (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_xorb_reg_postinc (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_xorw_reg_postinc (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_xorl_reg_postinc (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_cmpb_reg_postinc (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_cmpw_reg_postinc (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_cmpl_reg_postinc (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_andb_reg_indoff (COMMON_ARGS, int32 reg, int32 offset,
int32 addr_reg);
extern int host_andw_reg_indoff (COMMON_ARGS, int32 reg, int32 offset,
int32 addr_reg);
extern int host_andl_reg_indoff (COMMON_ARGS, int32 reg, int32 offset,
int32 addr_reg);
extern int host_orb_reg_indoff (COMMON_ARGS, int32 reg, int32 offset,
int32 addr_reg);
extern int host_orw_reg_indoff (COMMON_ARGS, int32 reg, int32 offset,
int32 addr_reg);
extern int host_orl_reg_indoff (COMMON_ARGS, int32 reg, int32 offset,
int32 addr_reg);
extern int host_xorb_reg_indoff (COMMON_ARGS, int32 reg, int32 offset,
int32 addr_reg);
extern int host_xorw_reg_indoff (COMMON_ARGS, int32 reg, int32 offset,
int32 addr_reg);
extern int host_xorl_reg_indoff (COMMON_ARGS, int32 reg, int32 offset,
int32 addr_reg);
extern int host_cmpb_reg_indoff (COMMON_ARGS, int32 reg, int32 offset,
int32 addr_reg);
extern int host_cmpw_reg_indoff (COMMON_ARGS, int32 reg, int32 offset,
int32 addr_reg);
extern int host_cmpl_reg_indoff (COMMON_ARGS, int32 reg, int32 offset,
int32 addr_reg);
extern int host_addb_reg_ind (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_subb_reg_ind (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_addb_reg_predec (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_subb_reg_predec (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_addb_reg_postinc (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_subb_reg_postinc (COMMON_ARGS, int32 reg, int32 addr_reg);
extern int host_addb_reg_indoff (COMMON_ARGS, int32 reg, int32 offset,
int32 addr_reg);
extern int host_subb_reg_indoff (COMMON_ARGS, int32 reg, int32 offset,
int32 addr_reg);
extern int host_andb_imm_abs (COMMON_ARGS, int32 val, int32 addr);
extern int host_andw_imm_abs (COMMON_ARGS, int32 val, int32 addr);
extern int host_andl_imm_abs (COMMON_ARGS, int32 val, int32 addr);
extern int host_orb_imm_abs (COMMON_ARGS, int32 val, int32 addr);
extern int host_orw_imm_abs (COMMON_ARGS, int32 val, int32 addr);
extern int host_orl_imm_abs (COMMON_ARGS, int32 val, int32 addr);
extern int host_xorb_imm_abs (COMMON_ARGS, int32 val, int32 addr);
extern int host_xorw_imm_abs (COMMON_ARGS, int32 val, int32 addr);
extern int host_xorl_imm_abs (COMMON_ARGS, int32 val, int32 addr);
extern int host_cmpb_imm_abs (COMMON_ARGS, int32 val, int32 addr);
extern int host_cmpw_imm_abs (COMMON_ARGS, int32 val, int32 addr);
extern int host_cmpl_imm_abs (COMMON_ARGS, int32 val, int32 addr);
extern int host_andb_imm_ind (COMMON_ARGS, int32 val, int32 addr);
extern int host_orb_imm_ind (COMMON_ARGS, int32 val, int32 addr);
extern int host_xorb_imm_ind (COMMON_ARGS, int32 val, int32 addr);
extern int host_addb_imm_ind (COMMON_ARGS, int32 val, int32 addr);
extern int host_subb_imm_ind (COMMON_ARGS, int32 val, int32 addr);
extern int host_cmpb_imm_ind (COMMON_ARGS, int32 val, int32 addr);
extern int host_cmpw_imm_ind (COMMON_ARGS, int32 val, int32 addr);
extern int host_cmpl_imm_ind (COMMON_ARGS, int32 val, int32 addr);
extern int host_andw_imm_ind (COMMON_ARGS, int32 val, int32 addr);
extern int host_orw_imm_ind (COMMON_ARGS, int32 val, int32 addr);
extern int host_xorw_imm_ind (COMMON_ARGS, int32 val, int32 addr);
extern int host_andl_imm_ind (COMMON_ARGS, int32 val, int32 addr);
extern int host_orl_imm_ind (COMMON_ARGS, int32 val, int32 addr);
extern int host_xorl_imm_ind (COMMON_ARGS, int32 val, int32 addr);
extern int host_andb_imm_indoff (COMMON_ARGS, int32 val, int32 offset,
int32 addr_reg);
extern int host_orb_imm_indoff (COMMON_ARGS, int32 val, int32 offset,
int32 addr_reg);
extern int host_xorb_imm_indoff (COMMON_ARGS, int32 val, int32 offset,
int32 addr_reg);
extern int host_addb_imm_indoff (COMMON_ARGS, int32 val, int32 offset,
int32 addr_reg);
extern int host_subb_imm_indoff (COMMON_ARGS, int32 val, int32 offset,
int32 addr_reg);
extern int host_cmpb_imm_indoff (COMMON_ARGS, int32 val, int32 offset,
int32 addr_reg);
extern int host_cmpw_imm_indoff (COMMON_ARGS, int32 val, int32 offset,
int32 addr_reg);
extern int host_cmpl_imm_indoff (COMMON_ARGS, int32 val, int32 offset,
int32 addr_reg);
extern int host_andw_imm_indoff (COMMON_ARGS, int32 val, int32 offset,
int32 addr_reg);
extern int host_orw_imm_indoff (COMMON_ARGS, int32 val, int32 offset,
int32 addr_reg);
extern int host_xorw_imm_indoff (COMMON_ARGS, int32 val, int32 offset,
int32 addr_reg);
extern int host_andl_imm_indoff (COMMON_ARGS, int32 val, int32 offset,
int32 addr_reg);
extern int host_orl_imm_indoff (COMMON_ARGS, int32 val, int32 offset,
int32 addr_reg);
extern int host_xorl_imm_indoff (COMMON_ARGS, int32 val, int32 offset,
int32 addr_reg);
extern int host_andb_imm_predec (COMMON_ARGS, int32 val, int32 addr);
extern int host_orb_imm_predec (COMMON_ARGS, int32 val, int32 addr);
extern int host_xorb_imm_predec (COMMON_ARGS, int32 val, int32 addr);
extern int host_addb_imm_predec (COMMON_ARGS, int32 val, int32 addr);
extern int host_subb_imm_predec (COMMON_ARGS, int32 val, int32 addr);
extern int host_cmpb_imm_predec (COMMON_ARGS, int32 val, int32 addr);
extern int host_cmpw_imm_predec (COMMON_ARGS, int32 val, int32 addr);
extern int host_cmpl_imm_predec (COMMON_ARGS, int32 val, int32 addr);
extern int host_andw_imm_predec (COMMON_ARGS, int32 val, int32 addr);
extern int host_orw_imm_predec (COMMON_ARGS, int32 val, int32 addr);
extern int host_xorw_imm_predec (COMMON_ARGS, int32 val, int32 addr);
extern int host_andl_imm_predec (COMMON_ARGS, int32 val, int32 addr);
extern int host_orl_imm_predec (COMMON_ARGS, int32 val, int32 addr);
extern int host_xorl_imm_predec (COMMON_ARGS, int32 val, int32 addr);
extern int host_andb_imm_postinc (COMMON_ARGS, int32 val, int32 addr);
extern int host_orb_imm_postinc (COMMON_ARGS, int32 val, int32 addr);
extern int host_xorb_imm_postinc (COMMON_ARGS, int32 val, int32 addr);
extern int host_addb_imm_postinc (COMMON_ARGS, int32 val, int32 addr);
extern int host_subb_imm_postinc (COMMON_ARGS, int32 val, int32 addr);
extern int host_cmpb_imm_postinc (COMMON_ARGS, int32 val, int32 addr);
extern int host_cmpw_imm_postinc (COMMON_ARGS, int32 val, int32 addr);
extern int host_cmpl_imm_postinc (COMMON_ARGS, int32 val, int32 addr);
extern int host_andw_imm_postinc (COMMON_ARGS, int32 val, int32 addr);
extern int host_orw_imm_postinc (COMMON_ARGS, int32 val, int32 addr);
extern int host_xorw_imm_postinc (COMMON_ARGS, int32 val, int32 addr);
extern int host_andl_imm_postinc (COMMON_ARGS, int32 val, int32 addr);
extern int host_orl_imm_postinc (COMMON_ARGS, int32 val, int32 addr);
extern int host_xorl_imm_postinc (COMMON_ARGS, int32 val, int32 addr);
extern int host_negb_ind (COMMON_ARGS, int32 addr);
extern int host_negb_predec (COMMON_ARGS, int32 addr);
extern int host_negb_postinc (COMMON_ARGS, int32 addr);
extern int host_negb_indoff (COMMON_ARGS, int32 offset, int32 addr);
extern int host_movew_reg_abs_swap (COMMON_ARGS, int32 src_reg, int32 addr);
extern int host_movel_reg_abs_swap (COMMON_ARGS, int32 src_reg, int32 addr);
extern int host_movew_abs_reg_swap (COMMON_ARGS, int32 addr, int32 dst_reg);
extern int host_movel_abs_reg_swap (COMMON_ARGS, int32 addr, int32 dst_reg);
extern int host_moveb_imm_reg (COMMON_ARGS, int32 val, int32 reg);
extern int host_movew_imm_reg (COMMON_ARGS, int32 val, int32 reg);
extern int host_movel_imm_reg (COMMON_ARGS, int32 val, int32 reg);
extern int host_moveb_imm_abs (COMMON_ARGS, int32 val, int32 addr);
extern int host_movew_imm_abs (COMMON_ARGS, int32 val, int32 addr);
extern int host_movel_imm_abs (COMMON_ARGS, int32 val, int32 addr);
extern int host_moveb_imm_ind (COMMON_ARGS, int32 val, int32 addr);
extern int host_movew_imm_ind (COMMON_ARGS, int32 val, int32 addr);
extern int host_movel_imm_ind (COMMON_ARGS, int32 val, int32 addr);
extern int host_moveb_imm_indoff (COMMON_ARGS, int32 val, int32 offset,
int32 addr_reg);
extern int host_movew_imm_indoff (COMMON_ARGS, int32 val, int32 offset,
int32 addr_reg);
extern int host_movel_imm_indoff (COMMON_ARGS, int32 val, int32 offset,
int32 addr_reg);
extern int host_moveb_imm_predec (COMMON_ARGS, int32 val, int32 addr);
extern int host_movew_imm_predec (COMMON_ARGS, int32 val, int32 addr);
extern int host_movel_imm_predec (COMMON_ARGS, int32 val, int32 addr);
extern int host_moveb_imm_postinc (COMMON_ARGS, int32 val, int32 addr);
extern int host_movew_imm_postinc (COMMON_ARGS, int32 val, int32 addr);
extern int host_movel_imm_postinc (COMMON_ARGS, int32 val, int32 addr);
extern int host_moveb_reg_ind (COMMON_ARGS, int32 src_reg, int32 addr);
extern int host_movew_reg_ind (COMMON_ARGS, int32 src_reg, int32 addr);
extern int host_movel_reg_ind (COMMON_ARGS, int32 src_reg, int32 addr);
extern int host_moveb_reg_indoff (COMMON_ARGS, int32 src_reg, int32 offset,
int32 addr_reg);
extern int host_movew_reg_indoff (COMMON_ARGS, int32 src_reg, int32 offset,
int32 addr_reg);
extern int host_movel_reg_indoff (COMMON_ARGS, int32 src_reg, int32 offset,
int32 addr_reg);
extern int host_moveb_reg_predec (COMMON_ARGS, int32 src_reg, int32 addr);
extern int host_movew_reg_predec (COMMON_ARGS, int32 src_reg, int32 addr);
extern int host_movel_reg_predec (COMMON_ARGS, int32 src_reg, int32 addr);
extern int host_moveb_reg_postinc (COMMON_ARGS, int32 src_reg, int32 addr);
extern int host_movew_reg_postinc (COMMON_ARGS, int32 src_reg, int32 addr);
extern int host_movel_reg_postinc (COMMON_ARGS, int32 src_reg, int32 addr);
extern int host_movew_reg_ind_swap (COMMON_ARGS, int32 src_reg, int32 addr);
extern int host_movel_reg_ind_swap (COMMON_ARGS, int32 src_reg, int32 addr);
extern int host_movew_reg_indoff_swap (COMMON_ARGS, int32 src_reg,
int32 offset, int32 addr_reg);
extern int host_movel_reg_indoff_swap (COMMON_ARGS, int32 src_reg,
int32 offset, int32 addr_reg);
extern int host_movew_reg_predec_swap (COMMON_ARGS, int32 src_reg, int32 addr);
extern int host_movel_reg_predec_swap (COMMON_ARGS, int32 src_reg, int32 addr);
extern int host_movew_reg_postinc_swap (COMMON_ARGS, int32 src_reg,
int32 addr);
extern int host_movel_reg_postinc_swap (COMMON_ARGS, int32 src_reg,
int32 addr);
extern int host_moveb_ind_reg (COMMON_ARGS, int32 addr_reg, int32 dst_reg);
extern int host_movew_ind_reg (COMMON_ARGS, int32 addr_reg, int32 dst_reg);
extern int host_movel_ind_reg (COMMON_ARGS, int32 addr_reg, int32 dst_reg);
extern int host_moveb_indoff_reg (COMMON_ARGS, int32 offset, int32 addr_reg,
int32 dst_reg);
extern int host_movew_indoff_reg (COMMON_ARGS, int32 offset, int32 addr_reg,
int32 dst_reg);
extern int host_movel_indoff_reg (COMMON_ARGS, int32 offset, int32 addr_reg,
int32 dst_reg);
extern int host_moveb_predec_reg (COMMON_ARGS, int32 addr_reg, int32 dst_reg);
extern int host_movew_predec_reg (COMMON_ARGS, int32 addr_reg, int32 dst_reg);
extern int host_movel_predec_reg (COMMON_ARGS, int32 addr_reg, int32 dst_reg);
extern int host_moveb_postinc_reg (COMMON_ARGS, int32 addr_reg, int32 dst_reg);
extern int host_movew_postinc_reg (COMMON_ARGS, int32 addr_reg, int32 dst_reg);
extern int host_movel_postinc_reg (COMMON_ARGS, int32 addr_reg, int32 dst_reg);
extern int host_movew_ind_reg_swap (COMMON_ARGS, int32 addr_reg,
int32 dst_reg);
extern int host_movel_ind_reg_swap (COMMON_ARGS, int32 addr_reg,
int32 dst_reg);
extern int host_movew_indoff_reg_swap (COMMON_ARGS, int32 offset,
int32 addr_reg, int32 dst_reg);
extern int host_movel_indoff_reg_swap (COMMON_ARGS, int32 offset,
int32 addr_reg, int32 dst_reg);
extern int host_movew_predec_reg_swap (COMMON_ARGS, int32 addr_reg,
int32 dst_reg);
extern int host_movel_predec_reg_swap (COMMON_ARGS, int32 addr_reg,
int32 dst_reg);
extern int host_movew_postinc_reg_swap (COMMON_ARGS, int32 addr_reg,
int32 dst_reg);
extern int host_movel_postinc_reg_swap (COMMON_ARGS, int32 addr_reg,
int32 dst_reg);
extern int host_cmpmb_postinc_postinc (COMMON_ARGS, int32 reg1, int32 reg2);
extern int host_cmpmw_postinc_postinc (COMMON_ARGS, int32 reg1, int32 reg2);
extern int host_cmpml_postinc_postinc (COMMON_ARGS, int32 reg1, int32 reg2);
extern int host_addl_imm_reg (COMMON_ARGS, int32 val, int32 host_reg);
extern int host_subl_imm_reg (COMMON_ARGS, int32 val, int32 host_reg);
extern int host_cmpl_imm_reg (COMMON_ARGS, int32 val, int32 host_reg);
extern int host_bclr_imm_reg (COMMON_ARGS, int32 bitnum, int32 reg);
extern int host_bset_imm_reg (COMMON_ARGS, int32 bitnum, int32 reg);
extern int host_bchg_imm_reg (COMMON_ARGS, int32 bitnum, int32 reg);
extern int host_btst_imm_reg (COMMON_ARGS, int32 bitnum, int32 reg);
extern int host_addl_reg_reg (COMMON_ARGS, int32 reg1, int32 reg2);
extern int host_subl_reg_reg (COMMON_ARGS, int32 reg1, int32 reg2);
extern int host_cmpl_reg_reg (COMMON_ARGS, int32 reg1, int32 reg2);
extern int host_bcc (COMMON_ARGS, Block *b);
extern int host_bcs (COMMON_ARGS, Block *b);
extern int host_beq (COMMON_ARGS, Block *b);
extern int host_bge (COMMON_ARGS, Block *b);
extern int host_bgt (COMMON_ARGS, Block *b);
extern int host_bhi (COMMON_ARGS, Block *b);
extern int host_ble (COMMON_ARGS, Block *b);
extern int host_bls (COMMON_ARGS, Block *b);
extern int host_blt (COMMON_ARGS, Block *b);
extern int host_bmi (COMMON_ARGS, Block *b);
extern int host_bne (COMMON_ARGS, Block *b);
extern int host_bpl (COMMON_ARGS, Block *b);
extern int host_bvc (COMMON_ARGS, Block *b);
extern int host_bvs (COMMON_ARGS, Block *b);
extern int host_jmp (COMMON_ARGS, Block *b);
extern int host_dbra (COMMON_ARGS, int32 guest_reg, Block *b);
extern int host_swap (COMMON_ARGS, int32 reg);
extern int host_extbw (COMMON_ARGS, int32 reg);
extern int host_extwl (COMMON_ARGS, int32 reg);
extern int host_extbl (COMMON_ARGS, int32 reg);
extern int host_unlk (COMMON_ARGS, int32 reg, int32 a7_reg);
extern int host_link (COMMON_ARGS, int32 offset, int32 reg, int32 a7_reg);
extern int host_moveml_reg_predec (COMMON_ARGS, int32 host_addr_reg,
int32 reg_mask);
extern int host_moveml_postinc_reg (COMMON_ARGS, int32 host_addr_reg,
int32 reg_mask);
extern int host_pea_indoff (COMMON_ARGS, int32 offset, int32 host_reg,
int32 a7_reg);
extern int host_leal_indoff_areg (COMMON_ARGS, int32 offset, int32 base_reg,
int32 dst_reg);
extern int host_rts (COMMON_ARGS, Block *b, int32 a7_reg);
extern int host_jsr_abs (COMMON_ARGS, int32 a7_reg, int32 target_addr,
Block *b, uint16 *m68k_code);
extern int host_jsr_pcd16 (COMMON_ARGS, int32 a7_reg, Block *b,
uint16 *m68k_code);
extern int host_jsr_d16 (COMMON_ARGS, int32 a7_reg, int32 base_addr_reg,
Block *b, uint16 *m68k_code);
extern int host_bsr (COMMON_ARGS, int32 a7_reg, Block *b, uint16 *m68k_code);
extern int host_moveb_imm_indix (COMMON_ARGS, int32 val, int32 base_addr_reg,
uint16 *m68k_addr);
extern int host_movew_imm_indix (COMMON_ARGS, int32 val, int32 base_addr_reg,
uint16 *m68k_addr);
extern int host_movel_imm_indix (COMMON_ARGS, int32 val, int32 base_addr_reg,
uint16 *m68k_addr);
extern int host_cmpb_imm_indix (COMMON_ARGS, int32 val, int32 base_addr_reg,
uint16 *m68k_addr);
extern int host_cmpw_imm_indix (COMMON_ARGS, int32 val, int32 base_addr_reg,
uint16 *m68k_addr);
extern int host_cmpl_imm_indix (COMMON_ARGS, int32 val, int32 base_addr_reg,
uint16 *m68k_addr);
extern int host_addb_imm_indix (COMMON_ARGS, int32 val, int32 base_addr_reg,
uint16 *m68k_addr);
extern int host_addw_imm_indix (COMMON_ARGS, int32 val, int32 base_addr_reg,
uint16 *m68k_addr);
extern int host_addl_imm_indix (COMMON_ARGS, int32 val, int32 base_addr_reg,
uint16 *m68k_addr);
extern int host_subb_imm_indix (COMMON_ARGS, int32 val, int32 base_addr_reg,
uint16 *m68k_addr);
extern int host_subw_imm_indix (COMMON_ARGS, int32 val, int32 base_addr_reg,
uint16 *m68k_addr);
extern int host_subl_imm_indix (COMMON_ARGS, int32 val, int32 base_addr_reg,
uint16 *m68k_addr);
extern int host_moveb_reg_indix (COMMON_ARGS, int32 val, int32 base_addr_reg,
uint16 *m68k_addr);
extern int host_movew_reg_indix (COMMON_ARGS, int32 val, int32 base_addr_reg,
uint16 *m68k_addr);
extern int host_movel_reg_indix (COMMON_ARGS, int32 val, int32 base_addr_reg,
uint16 *m68k_addr);
extern int host_moveb_indix_reg (COMMON_ARGS, int32 base_addr_reg,
int32 dst_reg, uint16 *m68k_addr);
extern int host_movew_indix_reg (COMMON_ARGS, int32 base_addr_reg,
int32 dst_reg, uint16 *m68k_addr);
extern int host_movel_indix_reg (COMMON_ARGS, int32 base_addr_reg,
int32 dst_reg, uint16 *m68k_addr);
extern int host_cmpb_indix_reg (COMMON_ARGS, int32 base_addr_reg,
int32 dst_reg, uint16 *m68k_addr);
extern int host_cmpw_indix_reg (COMMON_ARGS, int32 base_addr_reg,
int32 dst_reg, uint16 *m68k_addr);
extern int host_cmpl_indix_reg (COMMON_ARGS, int32 base_addr_reg,
int32 dst_reg, uint16 *m68k_addr);
extern int host_leal_indix_reg (COMMON_ARGS, int32 base_addr_reg,
int32 dst_reg, uint16 *m68k_addr);
extern int host_divsw (COMMON_ARGS, uint16 *m68k_addr, uint16 *next_addr,
Block *b, int32 might_overflow_i386_p);
extern int host_divsw_imm_reg (COMMON_ARGS, int32 val);
extern int host_andb_reg_abs (COMMON_ARGS, int32 src, int32 dst_addr);
extern int host_andw_reg_abs (COMMON_ARGS, int32 src, int32 dst_addr);
extern int host_andl_reg_abs (COMMON_ARGS, int32 src, int32 dst_addr);
extern int host_orb_reg_abs (COMMON_ARGS, int32 src, int32 dst_addr);
extern int host_orw_reg_abs (COMMON_ARGS, int32 src, int32 dst_addr);
extern int host_orl_reg_abs (COMMON_ARGS, int32 src, int32 dst_addr);
extern int host_xorb_reg_abs (COMMON_ARGS, int32 src, int32 dst_addr);
extern int host_xorw_reg_abs (COMMON_ARGS, int32 src, int32 dst_addr);
extern int host_xorl_reg_abs (COMMON_ARGS, int32 src, int32 dst_addr);
extern int host_cmpb_reg_abs (COMMON_ARGS, int32 src, int32 dst_addr);
extern int host_cmpw_reg_abs (COMMON_ARGS, int32 src, int32 dst_addr);
extern int host_cmpl_reg_abs (COMMON_ARGS, int32 src, int32 dst_addr);
extern int host_moveb_reg_abs (COMMON_ARGS, int32 src, int32 dst_addr);
extern int host_movew_reg_abs (COMMON_ARGS, int32 src, int32 dst_addr);
extern int host_movel_reg_abs (COMMON_ARGS, int32 src, int32 dst_addr);
extern int host_addb_reg_abs (COMMON_ARGS, int32 src, int32 dst_addr);
extern int host_subb_reg_abs (COMMON_ARGS, int32 src, int32 dst_addr);
extern int host_andb_abs_reg (COMMON_ARGS, int32 src_addr, int32 dst);
extern int host_andw_abs_reg (COMMON_ARGS, int32 src_addr, int32 dst);
extern int host_andl_abs_reg (COMMON_ARGS, int32 src_addr, int32 dst);
extern int host_orb_abs_reg (COMMON_ARGS, int32 src_addr, int32 dst);
extern int host_orw_abs_reg (COMMON_ARGS, int32 src_addr, int32 dst);
extern int host_orl_abs_reg (COMMON_ARGS, int32 src_addr, int32 dst);
extern int host_xorb_abs_reg (COMMON_ARGS, int32 src_addr, int32 dst);
extern int host_xorw_abs_reg (COMMON_ARGS, int32 src_addr, int32 dst);
extern int host_xorl_abs_reg (COMMON_ARGS, int32 src_addr, int32 dst);
extern int host_cmpb_abs_reg (COMMON_ARGS, int32 src_addr, int32 dst);
extern int host_cmpw_abs_reg (COMMON_ARGS, int32 src_addr, int32 dst);
extern int host_cmpl_abs_reg (COMMON_ARGS, int32 src_addr, int32 dst);
extern int host_addb_abs_reg (COMMON_ARGS, int32 src_addr, int32 dst);
extern int host_subb_abs_reg (COMMON_ARGS, int32 src_addr, int32 dst);
extern int host_moveb_abs_reg (COMMON_ARGS, int32 src, int32 dst_addr);
extern int host_movew_abs_reg (COMMON_ARGS, int32 src, int32 dst_addr);
extern int host_movel_abs_reg (COMMON_ARGS, int32 src, int32 dst_addr);
extern int host_addb_imm_abs (COMMON_ARGS, int32 src, int32 dst_addr);
extern int host_subb_imm_abs (COMMON_ARGS, int32 src, int32 dst_addr);
extern int host_negb_abs (COMMON_ARGS, int32 dst_addr);
#endif /* !_I386_AUX_H_*/

View File

@ -0,0 +1,665 @@
/* This file is machine-generated; DO NOT EDIT! */
#ifndef _I386_ISA_H_
#define _I386_ISA_H_
#ifdef GENERATE_NATIVE_CODE
extern int i386_addb_reg_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_addw_reg_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_addl_reg_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_addb_imm_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_addw_imm_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_addl_imm_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_addb_imm_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_addw_imm_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_addl_imm_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_addb_reg_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_addw_reg_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_addl_reg_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_addb_abs_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_addw_abs_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_addl_abs_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_addb_reg_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_addw_reg_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_addl_reg_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_addb_ind_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_addw_ind_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_addl_ind_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_addb_reg_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_addw_reg_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_addl_reg_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_addb_indoff_reg (COMMON_ARGS, int32 offset, int32 src, int32 dst);
extern int i386_addw_indoff_reg (COMMON_ARGS, int32 offset, int32 src, int32 dst);
extern int i386_addl_indoff_reg (COMMON_ARGS, int32 offset, int32 src, int32 dst);
extern int i386_addb_imm_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_addw_imm_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_addl_imm_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_addb_imm_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_addw_imm_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_addl_imm_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_subb_reg_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_subw_reg_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_subl_reg_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_subb_imm_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_subw_imm_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_subl_imm_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_subb_imm_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_subw_imm_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_subl_imm_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_subb_reg_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_subw_reg_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_subl_reg_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_subb_abs_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_subw_abs_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_subl_abs_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_subb_reg_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_subw_reg_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_subl_reg_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_subb_ind_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_subw_ind_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_subl_ind_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_subb_reg_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_subw_reg_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_subl_reg_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_subb_indoff_reg (COMMON_ARGS, int32 offset, int32 src, int32 dst);
extern int i386_subw_indoff_reg (COMMON_ARGS, int32 offset, int32 src, int32 dst);
extern int i386_subl_indoff_reg (COMMON_ARGS, int32 offset, int32 src, int32 dst);
extern int i386_subb_imm_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_subw_imm_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_subl_imm_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_subb_imm_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_subw_imm_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_subl_imm_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_andb_reg_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_andw_reg_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_andl_reg_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_andb_imm_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_andw_imm_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_andl_imm_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_andb_imm_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_andw_imm_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_andl_imm_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_andb_reg_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_andw_reg_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_andl_reg_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_andb_abs_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_andw_abs_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_andl_abs_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_andb_reg_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_andw_reg_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_andl_reg_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_andb_ind_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_andw_ind_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_andl_ind_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_andb_reg_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_andw_reg_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_andl_reg_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_andb_indoff_reg (COMMON_ARGS, int32 offset, int32 src, int32 dst);
extern int i386_andw_indoff_reg (COMMON_ARGS, int32 offset, int32 src, int32 dst);
extern int i386_andl_indoff_reg (COMMON_ARGS, int32 offset, int32 src, int32 dst);
extern int i386_andb_imm_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_andw_imm_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_andl_imm_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_andb_imm_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_andw_imm_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_andl_imm_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_orb_reg_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_orw_reg_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_orl_reg_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_orb_imm_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_orw_imm_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_orl_imm_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_orb_imm_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_orw_imm_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_orl_imm_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_orb_reg_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_orw_reg_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_orl_reg_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_orb_abs_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_orw_abs_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_orl_abs_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_orb_reg_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_orw_reg_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_orl_reg_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_orb_ind_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_orw_ind_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_orl_ind_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_orb_reg_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_orw_reg_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_orl_reg_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_orb_indoff_reg (COMMON_ARGS, int32 offset, int32 src, int32 dst);
extern int i386_orw_indoff_reg (COMMON_ARGS, int32 offset, int32 src, int32 dst);
extern int i386_orl_indoff_reg (COMMON_ARGS, int32 offset, int32 src, int32 dst);
extern int i386_orb_imm_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_orw_imm_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_orl_imm_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_orb_imm_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_orw_imm_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_orl_imm_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_xorb_reg_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_xorw_reg_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_xorl_reg_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_xorb_imm_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_xorw_imm_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_xorl_imm_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_xorb_imm_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_xorw_imm_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_xorl_imm_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_xorb_reg_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_xorw_reg_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_xorl_reg_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_xorb_abs_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_xorw_abs_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_xorl_abs_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_xorb_reg_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_xorw_reg_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_xorl_reg_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_xorb_ind_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_xorw_ind_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_xorl_ind_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_xorb_reg_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_xorw_reg_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_xorl_reg_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_xorb_indoff_reg (COMMON_ARGS, int32 offset, int32 src, int32 dst);
extern int i386_xorw_indoff_reg (COMMON_ARGS, int32 offset, int32 src, int32 dst);
extern int i386_xorl_indoff_reg (COMMON_ARGS, int32 offset, int32 src, int32 dst);
extern int i386_xorb_imm_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_xorw_imm_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_xorl_imm_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_xorb_imm_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_xorw_imm_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_xorl_imm_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_cmpb_reg_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_cmpw_reg_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_cmpl_reg_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_cmpb_imm_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_cmpw_imm_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_cmpl_imm_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_cmpb_imm_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_cmpw_imm_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_cmpl_imm_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_cmpb_reg_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_cmpw_reg_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_cmpl_reg_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_cmpb_abs_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_cmpw_abs_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_cmpl_abs_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_cmpb_reg_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_cmpw_reg_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_cmpl_reg_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_cmpb_ind_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_cmpw_ind_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_cmpl_ind_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_cmpb_reg_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_cmpw_reg_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_cmpl_reg_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_cmpb_indoff_reg (COMMON_ARGS, int32 offset, int32 src, int32 dst);
extern int i386_cmpw_indoff_reg (COMMON_ARGS, int32 offset, int32 src, int32 dst);
extern int i386_cmpl_indoff_reg (COMMON_ARGS, int32 offset, int32 src, int32 dst);
extern int i386_cmpb_imm_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_cmpw_imm_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_cmpl_imm_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_cmpb_imm_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_cmpw_imm_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_cmpl_imm_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_testb_reg_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_testw_reg_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_testl_reg_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_testb_imm_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_testw_imm_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_testl_imm_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_testb_imm_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_testw_imm_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_testl_imm_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_testb_reg_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_testw_reg_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_testl_reg_abs (COMMON_ARGS, int32 src, int32 dst);
extern int i386_testb_abs_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_testw_abs_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_testl_abs_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_testb_reg_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_testw_reg_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_testl_reg_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_testb_ind_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_testw_ind_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_testl_ind_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_testb_reg_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_testw_reg_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_testl_reg_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_testb_indoff_reg (COMMON_ARGS, int32 offset, int32 src, int32 dst);
extern int i386_testw_indoff_reg (COMMON_ARGS, int32 offset, int32 src, int32 dst);
extern int i386_testl_indoff_reg (COMMON_ARGS, int32 offset, int32 src, int32 dst);
extern int i386_testb_imm_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_testw_imm_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_testl_imm_ind (COMMON_ARGS, int32 src, int32 dst);
extern int i386_testb_imm_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_testw_imm_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_testl_imm_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst);
extern int i386_adcb_reg_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_adcw_reg_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_adcl_reg_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_cmpb_imm_indix (COMMON_ARGS, int32 src, int32 offset, int32 dst, int32 index);
extern int i386_cmpw_imm_indix (COMMON_ARGS, int32 src, int32 offset, int32 dst, int32 index);
extern int i386_cmpl_imm_indix (COMMON_ARGS, int32 src, int32 offset, int32 dst, int32 index);
extern int i386_cmpb_imm_indix_no_offset (COMMON_ARGS, int32 src, int32 dst, int32 index);
extern int i386_cmpw_imm_indix_no_offset (COMMON_ARGS, int32 src, int32 dst, int32 index);
extern int i386_cmpl_imm_indix_no_offset (COMMON_ARGS, int32 src, int32 dst, int32 index);
extern int i386_cmpb_imm_indix_scale2 (COMMON_ARGS, int32 src, int32 offset, int32 dst, int32 index);
extern int i386_cmpw_imm_indix_scale2 (COMMON_ARGS, int32 src, int32 offset, int32 dst, int32 index);
extern int i386_cmpl_imm_indix_scale2 (COMMON_ARGS, int32 src, int32 offset, int32 dst, int32 index);
extern int i386_cmpb_imm_indix_scale2_no_offset (COMMON_ARGS, int32 src, int32 dst, int32 index);
extern int i386_cmpw_imm_indix_scale2_no_offset (COMMON_ARGS, int32 src, int32 dst, int32 index);
extern int i386_cmpl_imm_indix_scale2_no_offset (COMMON_ARGS, int32 src, int32 dst, int32 index);
extern int i386_cmpb_imm_indix_scale4 (COMMON_ARGS, int32 src, int32 offset, int32 dst, int32 index);
extern int i386_cmpw_imm_indix_scale4 (COMMON_ARGS, int32 src, int32 offset, int32 dst, int32 index);
extern int i386_cmpl_imm_indix_scale4 (COMMON_ARGS, int32 src, int32 offset, int32 dst, int32 index);
extern int i386_cmpb_imm_indix_scale4_no_offset (COMMON_ARGS, int32 src, int32 dst, int32 index);
extern int i386_cmpw_imm_indix_scale4_no_offset (COMMON_ARGS, int32 src, int32 dst, int32 index);
extern int i386_cmpl_imm_indix_scale4_no_offset (COMMON_ARGS, int32 src, int32 dst, int32 index);
extern int i386_cmpb_imm_indix_scale8 (COMMON_ARGS, int32 src, int32 offset, int32 dst, int32 index);
extern int i386_cmpw_imm_indix_scale8 (COMMON_ARGS, int32 src, int32 offset, int32 dst, int32 index);
extern int i386_cmpl_imm_indix_scale8 (COMMON_ARGS, int32 src, int32 offset, int32 dst, int32 index);
extern int i386_cmpb_imm_indix_scale8_no_offset (COMMON_ARGS, int32 src, int32 dst, int32 index);
extern int i386_cmpw_imm_indix_scale8_no_offset (COMMON_ARGS, int32 src, int32 dst, int32 index);
extern int i386_cmpl_imm_indix_scale8_no_offset (COMMON_ARGS, int32 src, int32 dst, int32 index);
extern int i386_cmpb_indix_reg (COMMON_ARGS, int32 offset, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_cmpw_indix_reg (COMMON_ARGS, int32 offset, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_cmpl_indix_reg (COMMON_ARGS, int32 offset, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_cmpb_indix_reg_no_offset (COMMON_ARGS, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_cmpw_indix_reg_no_offset (COMMON_ARGS, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_cmpl_indix_reg_no_offset (COMMON_ARGS, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_cmpb_indix_reg_scale2 (COMMON_ARGS, int32 offset, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_cmpw_indix_reg_scale2 (COMMON_ARGS, int32 offset, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_cmpl_indix_reg_scale2 (COMMON_ARGS, int32 offset, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_cmpb_indix_reg_scale2_no_offset (COMMON_ARGS, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_cmpw_indix_reg_scale2_no_offset (COMMON_ARGS, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_cmpl_indix_reg_scale2_no_offset (COMMON_ARGS, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_cmpb_indix_reg_scale4 (COMMON_ARGS, int32 offset, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_cmpw_indix_reg_scale4 (COMMON_ARGS, int32 offset, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_cmpl_indix_reg_scale4 (COMMON_ARGS, int32 offset, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_cmpb_indix_reg_scale4_no_offset (COMMON_ARGS, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_cmpw_indix_reg_scale4_no_offset (COMMON_ARGS, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_cmpl_indix_reg_scale4_no_offset (COMMON_ARGS, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_cmpb_indix_reg_scale8 (COMMON_ARGS, int32 offset, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_cmpw_indix_reg_scale8 (COMMON_ARGS, int32 offset, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_cmpl_indix_reg_scale8 (COMMON_ARGS, int32 offset, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_cmpb_indix_reg_scale8_no_offset (COMMON_ARGS, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_cmpw_indix_reg_scale8_no_offset (COMMON_ARGS, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_cmpl_indix_reg_scale8_no_offset (COMMON_ARGS, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_addb_imm_indix (COMMON_ARGS, int32 src, int32 offset, int32 dst, int32 index);
extern int i386_addb_imm_indix_no_offset (COMMON_ARGS, int32 src, int32 dst, int32 index);
extern int i386_addb_imm_indix_scale2 (COMMON_ARGS, int32 src, int32 offset, int32 dst, int32 index);
extern int i386_addb_imm_indix_scale2_no_offset (COMMON_ARGS, int32 src, int32 dst, int32 index);
extern int i386_addb_imm_indix_scale4 (COMMON_ARGS, int32 src, int32 offset, int32 dst, int32 index);
extern int i386_addb_imm_indix_scale4_no_offset (COMMON_ARGS, int32 src, int32 dst, int32 index);
extern int i386_addb_imm_indix_scale8 (COMMON_ARGS, int32 src, int32 offset, int32 dst, int32 index);
extern int i386_addb_imm_indix_scale8_no_offset (COMMON_ARGS, int32 src, int32 dst, int32 index);
extern int i386_addb_indix_reg (COMMON_ARGS, int32 offset, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_addb_indix_reg_no_offset (COMMON_ARGS, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_addb_indix_reg_scale2 (COMMON_ARGS, int32 offset, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_addb_indix_reg_scale2_no_offset (COMMON_ARGS, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_addb_indix_reg_scale4 (COMMON_ARGS, int32 offset, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_addb_indix_reg_scale4_no_offset (COMMON_ARGS, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_addb_indix_reg_scale8 (COMMON_ARGS, int32 offset, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_addb_indix_reg_scale8_no_offset (COMMON_ARGS, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_subb_imm_indix (COMMON_ARGS, int32 src, int32 offset, int32 dst, int32 index);
extern int i386_subb_imm_indix_no_offset (COMMON_ARGS, int32 src, int32 dst, int32 index);
extern int i386_subb_imm_indix_scale2 (COMMON_ARGS, int32 src, int32 offset, int32 dst, int32 index);
extern int i386_subb_imm_indix_scale2_no_offset (COMMON_ARGS, int32 src, int32 dst, int32 index);
extern int i386_subb_imm_indix_scale4 (COMMON_ARGS, int32 src, int32 offset, int32 dst, int32 index);
extern int i386_subb_imm_indix_scale4_no_offset (COMMON_ARGS, int32 src, int32 dst, int32 index);
extern int i386_subb_imm_indix_scale8 (COMMON_ARGS, int32 src, int32 offset, int32 dst, int32 index);
extern int i386_subb_imm_indix_scale8_no_offset (COMMON_ARGS, int32 src, int32 dst, int32 index);
extern int i386_subb_indix_reg (COMMON_ARGS, int32 offset, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_subb_indix_reg_no_offset (COMMON_ARGS, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_subb_indix_reg_scale2 (COMMON_ARGS, int32 offset, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_subb_indix_reg_scale2_no_offset (COMMON_ARGS, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_subb_indix_reg_scale4 (COMMON_ARGS, int32 offset, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_subb_indix_reg_scale4_no_offset (COMMON_ARGS, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_subb_indix_reg_scale8 (COMMON_ARGS, int32 offset, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_subb_indix_reg_scale8_no_offset (COMMON_ARGS, int32 base_addr_reg, int32 index, int32 dst_val);
extern int i386_negb_reg (COMMON_ARGS, int32 dst);
extern int i386_negw_reg (COMMON_ARGS, int32 dst);
extern int i386_negl_reg (COMMON_ARGS, int32 dst);
extern int i386_negb_abs (COMMON_ARGS, int32 dst);
extern int i386_negw_abs (COMMON_ARGS, int32 dst);
extern int i386_negl_abs (COMMON_ARGS, int32 dst);
extern int i386_negb_ind (COMMON_ARGS, int32 dst_addr_reg);
extern int i386_negw_ind (COMMON_ARGS, int32 dst_addr_reg);
extern int i386_negl_ind (COMMON_ARGS, int32 dst_addr_reg);
extern int i386_negb_indoff (COMMON_ARGS, int32 offset, int32 dst_addr_reg);
extern int i386_negw_indoff (COMMON_ARGS, int32 offset, int32 dst_addr_reg);
extern int i386_negl_indoff (COMMON_ARGS, int32 offset, int32 dst_addr_reg);
extern int i386_notb_reg (COMMON_ARGS, int32 dst);
extern int i386_notw_reg (COMMON_ARGS, int32 dst);
extern int i386_notl_reg (COMMON_ARGS, int32 dst);
extern int i386_notb_abs (COMMON_ARGS, int32 dst);
extern int i386_notw_abs (COMMON_ARGS, int32 dst);
extern int i386_notl_abs (COMMON_ARGS, int32 dst);
extern int i386_notb_ind (COMMON_ARGS, int32 dst_addr_reg);
extern int i386_notw_ind (COMMON_ARGS, int32 dst_addr_reg);
extern int i386_notl_ind (COMMON_ARGS, int32 dst_addr_reg);
extern int i386_notb_indoff (COMMON_ARGS, int32 offset, int32 dst_addr_reg);
extern int i386_notw_indoff (COMMON_ARGS, int32 offset, int32 dst_addr_reg);
extern int i386_notl_indoff (COMMON_ARGS, int32 offset, int32 dst_addr_reg);
extern int i386_incb_reg (COMMON_ARGS, int32 dst);
extern int i386_incw_reg (COMMON_ARGS, int32 dst);
extern int i386_incl_reg (COMMON_ARGS, int32 dst);
extern int i386_incb_abs (COMMON_ARGS, int32 dst);
extern int i386_incw_abs (COMMON_ARGS, int32 dst);
extern int i386_incl_abs (COMMON_ARGS, int32 dst);
extern int i386_incb_ind (COMMON_ARGS, int32 dst_addr_reg);
extern int i386_incw_ind (COMMON_ARGS, int32 dst_addr_reg);
extern int i386_incl_ind (COMMON_ARGS, int32 dst_addr_reg);
extern int i386_incb_indoff (COMMON_ARGS, int32 offset, int32 dst_addr_reg);
extern int i386_incw_indoff (COMMON_ARGS, int32 offset, int32 dst_addr_reg);
extern int i386_incl_indoff (COMMON_ARGS, int32 offset, int32 dst_addr_reg);
extern int i386_decb_reg (COMMON_ARGS, int32 dst);
extern int i386_decw_reg (COMMON_ARGS, int32 dst);
extern int i386_decl_reg (COMMON_ARGS, int32 dst);
extern int i386_decb_abs (COMMON_ARGS, int32 dst);
extern int i386_decw_abs (COMMON_ARGS, int32 dst);
extern int i386_decl_abs (COMMON_ARGS, int32 dst);
extern int i386_decb_ind (COMMON_ARGS, int32 dst_addr_reg);
extern int i386_decw_ind (COMMON_ARGS, int32 dst_addr_reg);
extern int i386_decl_ind (COMMON_ARGS, int32 dst_addr_reg);
extern int i386_decb_indoff (COMMON_ARGS, int32 offset, int32 dst_addr_reg);
extern int i386_decw_indoff (COMMON_ARGS, int32 offset, int32 dst_addr_reg);
extern int i386_decl_indoff (COMMON_ARGS, int32 offset, int32 dst_addr_reg);
extern int i386_bswap (COMMON_ARGS, int32 dst_reg);
extern int i386_call_abs (COMMON_ARGS, int32 addr);
extern int i386_cbtw (COMMON_ARGS);
extern int i386_cwtl (COMMON_ARGS);
extern int i386_cltd (COMMON_ARGS);
extern int i386_clc (COMMON_ARGS);
extern int i386_stc (COMMON_ARGS);
extern int i386_cld (COMMON_ARGS);
extern int i386_std (COMMON_ARGS);
extern int i386_cli (COMMON_ARGS);
extern int i386_sti (COMMON_ARGS);
extern int i386_divb (COMMON_ARGS, int32 divisor);
extern int i386_divw (COMMON_ARGS, int32 divisor);
extern int i386_divl (COMMON_ARGS, int32 divisor);
extern int i386_divb_abs (COMMON_ARGS, int32 divisor);
extern int i386_divw_abs (COMMON_ARGS, int32 divisor);
extern int i386_divl_abs (COMMON_ARGS, int32 divisor);
extern int i386_idivb (COMMON_ARGS, int32 divisor);
extern int i386_idivw (COMMON_ARGS, int32 divisor);
extern int i386_idivl (COMMON_ARGS, int32 divisor);
extern int i386_idivb_abs (COMMON_ARGS, int32 divisor);
extern int i386_idivw_abs (COMMON_ARGS, int32 divisor);
extern int i386_idivl_abs (COMMON_ARGS, int32 divisor);
extern int i386_jc (COMMON_ARGS, int32 target);
extern int i386_jbe (COMMON_ARGS, int32 target);
extern int i386_jz (COMMON_ARGS, int32 target);
extern int i386_jl (COMMON_ARGS, int32 target);
extern int i386_jle (COMMON_ARGS, int32 target);
extern int i386_jnc (COMMON_ARGS, int32 target);
extern int i386_jnbe (COMMON_ARGS, int32 target);
extern int i386_jnz (COMMON_ARGS, int32 target);
extern int i386_jge (COMMON_ARGS, int32 target);
extern int i386_jnle (COMMON_ARGS, int32 target);
extern int i386_jno (COMMON_ARGS, int32 target);
extern int i386_jo (COMMON_ARGS, int32 target);
extern int i386_jns (COMMON_ARGS, int32 target);
extern int i386_js (COMMON_ARGS, int32 target);
extern int i386_jmp (COMMON_ARGS, int32 target);
extern int i386_jmp_reg (COMMON_ARGS, int32 target);
extern int i386_lahf (COMMON_ARGS);
extern int i386_leaw_indoff (COMMON_ARGS, int32 offset, int32 base, int32 dst);
extern int i386_leal_indoff (COMMON_ARGS, int32 offset, int32 base, int32 dst);
extern int i386_leal_indix_reg (COMMON_ARGS, int32 offset, int32 base, int32 index, int32 dst);
extern int i386_leal_indix_reg_scale2 (COMMON_ARGS, int32 offset, int32 base, int32 index, int32 dst);
extern int i386_leal_indix_reg_scale4 (COMMON_ARGS, int32 offset, int32 base, int32 index, int32 dst);
extern int i386_leal_indix_reg_scale8 (COMMON_ARGS, int32 offset, int32 base, int32 index, int32 dst);
extern int i386_leal_indix_reg_no_offset (COMMON_ARGS, int32 base, int32 index, int32 dst);
extern int i386_leal_indix_reg_scale2_no_offset (COMMON_ARGS, int32 base, int32 index, int32 dst);
extern int i386_leal_indix_reg_scale4_no_offset (COMMON_ARGS, int32 base, int32 index, int32 dst);
extern int i386_leal_indix_reg_scale8_no_offset (COMMON_ARGS, int32 base, int32 index, int32 dst);
extern int i386_movswl_abs_reg (COMMON_ARGS, int32 src_addr, int32 dst_reg);
extern int i386_movswl_indoff_reg (COMMON_ARGS, int32 offset, int32 src_addr, int32 dst_reg);
extern int i386_movsbl_reg_reg (COMMON_ARGS, int32 src_reg, int32 dst_reg);
extern int i386_movswl_reg_reg (COMMON_ARGS, int32 src_reg, int32 dst_reg);
extern int i386_movzwl_abs_reg (COMMON_ARGS, int32 src_addr, int32 dst_reg);
extern int i386_movzwl_indoff_reg (COMMON_ARGS, int32 offset, int32 src_addr, int32 dst_reg);
extern int i386_movzbl_reg_reg (COMMON_ARGS, int32 src_reg, int32 dst_reg);
extern int i386_movzwl_reg_reg (COMMON_ARGS, int32 src_reg, int32 dst_reg);
extern int i386_movb_reg_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_movw_reg_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_movl_reg_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_movb_reg_abs (COMMON_ARGS, int32 src, int32 dst_addr);
extern int i386_movw_reg_abs (COMMON_ARGS, int32 src, int32 dst_addr);
extern int i386_movl_reg_abs (COMMON_ARGS, int32 src, int32 dst_addr);
extern int i386_movb_abs_reg (COMMON_ARGS, int32 src_addr, int32 dst);
extern int i386_movw_abs_reg (COMMON_ARGS, int32 src_addr, int32 dst);
extern int i386_movl_abs_reg (COMMON_ARGS, int32 src_addr, int32 dst);
extern int i386_movb_imm_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_movw_imm_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_movl_imm_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_movb_imm_abs (COMMON_ARGS, int32 src, int32 dst_addr);
extern int i386_movw_imm_abs (COMMON_ARGS, int32 src, int32 dst_addr);
extern int i386_movl_imm_abs (COMMON_ARGS, int32 src, int32 dst_addr);
extern int i386_movb_imm_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst_addr);
extern int i386_movw_imm_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst_addr);
extern int i386_movl_imm_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst_addr);
extern int i386_movb_imm_ind (COMMON_ARGS, int32 src, int32 dst_addr);
extern int i386_movw_imm_ind (COMMON_ARGS, int32 src, int32 dst_addr);
extern int i386_movl_imm_ind (COMMON_ARGS, int32 src, int32 dst_addr);
extern int i386_movb_reg_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst_addr);
extern int i386_movw_reg_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst_addr);
extern int i386_movl_reg_indoff (COMMON_ARGS, int32 src, int32 offset, int32 dst_addr);
extern int i386_movb_reg_ind (COMMON_ARGS, int32 src, int32 dst_addr);
extern int i386_movw_reg_ind (COMMON_ARGS, int32 src, int32 dst_addr);
extern int i386_movl_reg_ind (COMMON_ARGS, int32 src, int32 dst_addr);
extern int i386_movb_indoff_reg (COMMON_ARGS, int32 offset, int32 src, int32 dst);
extern int i386_movw_indoff_reg (COMMON_ARGS, int32 offset, int32 src, int32 dst);
extern int i386_movl_indoff_reg (COMMON_ARGS, int32 offset, int32 src, int32 dst);
extern int i386_movb_ind_reg (COMMON_ARGS, int32 src_addr, int32 dst);
extern int i386_movw_ind_reg (COMMON_ARGS, int32 src_addr, int32 dst);
extern int i386_movl_ind_reg (COMMON_ARGS, int32 src_addr, int32 dst);
extern int i386_movb_imm_indix (COMMON_ARGS, int32 const_val, int32 offset, int32 base, int32 index);
extern int i386_movw_imm_indix (COMMON_ARGS, int32 const_val, int32 offset, int32 base, int32 index);
extern int i386_movl_imm_indix (COMMON_ARGS, int32 const_val, int32 offset, int32 base, int32 index);
extern int i386_movb_imm_indix_scale2 (COMMON_ARGS, int32 const_val, int32 offset, int32 base, int32 index);
extern int i386_movw_imm_indix_scale2 (COMMON_ARGS, int32 const_val, int32 offset, int32 base, int32 index);
extern int i386_movl_imm_indix_scale2 (COMMON_ARGS, int32 const_val, int32 offset, int32 base, int32 index);
extern int i386_movb_imm_indix_scale4 (COMMON_ARGS, int32 const_val, int32 offset, int32 base, int32 index);
extern int i386_movw_imm_indix_scale4 (COMMON_ARGS, int32 const_val, int32 offset, int32 base, int32 index);
extern int i386_movl_imm_indix_scale4 (COMMON_ARGS, int32 const_val, int32 offset, int32 base, int32 index);
extern int i386_movb_imm_indix_scale8 (COMMON_ARGS, int32 const_val, int32 offset, int32 base, int32 index);
extern int i386_movw_imm_indix_scale8 (COMMON_ARGS, int32 const_val, int32 offset, int32 base, int32 index);
extern int i386_movl_imm_indix_scale8 (COMMON_ARGS, int32 const_val, int32 offset, int32 base, int32 index);
extern int i386_movb_imm_indix_no_offset (COMMON_ARGS, int32 const_val, int32 base, int32 index);
extern int i386_movw_imm_indix_no_offset (COMMON_ARGS, int32 const_val, int32 base, int32 index);
extern int i386_movl_imm_indix_no_offset (COMMON_ARGS, int32 const_val, int32 base, int32 index);
extern int i386_movb_imm_indix_scale2_no_offset (COMMON_ARGS, int32 const_val, int32 base, int32 index);
extern int i386_movw_imm_indix_scale2_no_offset (COMMON_ARGS, int32 const_val, int32 base, int32 index);
extern int i386_movl_imm_indix_scale2_no_offset (COMMON_ARGS, int32 const_val, int32 base, int32 index);
extern int i386_movb_imm_indix_scale4_no_offset (COMMON_ARGS, int32 const_val, int32 base, int32 index);
extern int i386_movw_imm_indix_scale4_no_offset (COMMON_ARGS, int32 const_val, int32 base, int32 index);
extern int i386_movl_imm_indix_scale4_no_offset (COMMON_ARGS, int32 const_val, int32 base, int32 index);
extern int i386_movb_imm_indix_scale8_no_offset (COMMON_ARGS, int32 const_val, int32 base, int32 index);
extern int i386_movw_imm_indix_scale8_no_offset (COMMON_ARGS, int32 const_val, int32 base, int32 index);
extern int i386_movl_imm_indix_scale8_no_offset (COMMON_ARGS, int32 const_val, int32 base, int32 index);
extern int i386_movb_reg_indix (COMMON_ARGS, int32 src_reg, int32 offset, int32 base, int32 index);
extern int i386_movw_reg_indix (COMMON_ARGS, int32 src_reg, int32 offset, int32 base, int32 index);
extern int i386_movl_reg_indix (COMMON_ARGS, int32 src_reg, int32 offset, int32 base, int32 index);
extern int i386_movb_reg_indix_scale2 (COMMON_ARGS, int32 src_reg, int32 offset, int32 base, int32 index);
extern int i386_movw_reg_indix_scale2 (COMMON_ARGS, int32 src_reg, int32 offset, int32 base, int32 index);
extern int i386_movl_reg_indix_scale2 (COMMON_ARGS, int32 src_reg, int32 offset, int32 base, int32 index);
extern int i386_movb_reg_indix_scale4 (COMMON_ARGS, int32 src_reg, int32 offset, int32 base, int32 index);
extern int i386_movw_reg_indix_scale4 (COMMON_ARGS, int32 src_reg, int32 offset, int32 base, int32 index);
extern int i386_movl_reg_indix_scale4 (COMMON_ARGS, int32 src_reg, int32 offset, int32 base, int32 index);
extern int i386_movb_reg_indix_scale8 (COMMON_ARGS, int32 src_reg, int32 offset, int32 base, int32 index);
extern int i386_movw_reg_indix_scale8 (COMMON_ARGS, int32 src_reg, int32 offset, int32 base, int32 index);
extern int i386_movl_reg_indix_scale8 (COMMON_ARGS, int32 src_reg, int32 offset, int32 base, int32 index);
extern int i386_movb_reg_indix_no_offset (COMMON_ARGS, int32 src_reg, int32 base, int32 index);
extern int i386_movw_reg_indix_no_offset (COMMON_ARGS, int32 src_reg, int32 base, int32 index);
extern int i386_movl_reg_indix_no_offset (COMMON_ARGS, int32 src_reg, int32 base, int32 index);
extern int i386_movb_reg_indix_scale2_no_offset (COMMON_ARGS, int32 src_reg, int32 base, int32 index);
extern int i386_movw_reg_indix_scale2_no_offset (COMMON_ARGS, int32 src_reg, int32 base, int32 index);
extern int i386_movl_reg_indix_scale2_no_offset (COMMON_ARGS, int32 src_reg, int32 base, int32 index);
extern int i386_movb_reg_indix_scale4_no_offset (COMMON_ARGS, int32 src_reg, int32 base, int32 index);
extern int i386_movw_reg_indix_scale4_no_offset (COMMON_ARGS, int32 src_reg, int32 base, int32 index);
extern int i386_movl_reg_indix_scale4_no_offset (COMMON_ARGS, int32 src_reg, int32 base, int32 index);
extern int i386_movb_reg_indix_scale8_no_offset (COMMON_ARGS, int32 src_reg, int32 base, int32 index);
extern int i386_movw_reg_indix_scale8_no_offset (COMMON_ARGS, int32 src_reg, int32 base, int32 index);
extern int i386_movl_reg_indix_scale8_no_offset (COMMON_ARGS, int32 src_reg, int32 base, int32 index);
extern int i386_movb_indix_reg (COMMON_ARGS, int32 offset, int32 base, int32 index, int32 dst);
extern int i386_movw_indix_reg (COMMON_ARGS, int32 offset, int32 base, int32 index, int32 dst);
extern int i386_movl_indix_reg (COMMON_ARGS, int32 offset, int32 base, int32 index, int32 dst);
extern int i386_movb_indix_reg_scale2 (COMMON_ARGS, int32 offset, int32 base, int32 index, int32 dst);
extern int i386_movw_indix_reg_scale2 (COMMON_ARGS, int32 offset, int32 base, int32 index, int32 dst);
extern int i386_movl_indix_reg_scale2 (COMMON_ARGS, int32 offset, int32 base, int32 index, int32 dst);
extern int i386_movb_indix_reg_scale4 (COMMON_ARGS, int32 offset, int32 base, int32 index, int32 dst);
extern int i386_movw_indix_reg_scale4 (COMMON_ARGS, int32 offset, int32 base, int32 index, int32 dst);
extern int i386_movl_indix_reg_scale4 (COMMON_ARGS, int32 offset, int32 base, int32 index, int32 dst);
extern int i386_movb_indix_reg_scale8 (COMMON_ARGS, int32 offset, int32 base, int32 index, int32 dst);
extern int i386_movw_indix_reg_scale8 (COMMON_ARGS, int32 offset, int32 base, int32 index, int32 dst);
extern int i386_movl_indix_reg_scale8 (COMMON_ARGS, int32 offset, int32 base, int32 index, int32 dst);
extern int i386_movb_indix_reg_no_offset (COMMON_ARGS, int32 base, int32 index, int32 dst);
extern int i386_movw_indix_reg_no_offset (COMMON_ARGS, int32 base, int32 index, int32 dst);
extern int i386_movl_indix_reg_no_offset (COMMON_ARGS, int32 base, int32 index, int32 dst);
extern int i386_movb_indix_reg_scale2_no_offset (COMMON_ARGS, int32 base, int32 index, int32 dst);
extern int i386_movw_indix_reg_scale2_no_offset (COMMON_ARGS, int32 base, int32 index, int32 dst);
extern int i386_movl_indix_reg_scale2_no_offset (COMMON_ARGS, int32 base, int32 index, int32 dst);
extern int i386_movb_indix_reg_scale4_no_offset (COMMON_ARGS, int32 base, int32 index, int32 dst);
extern int i386_movw_indix_reg_scale4_no_offset (COMMON_ARGS, int32 base, int32 index, int32 dst);
extern int i386_movl_indix_reg_scale4_no_offset (COMMON_ARGS, int32 base, int32 index, int32 dst);
extern int i386_movb_indix_reg_scale8_no_offset (COMMON_ARGS, int32 base, int32 index, int32 dst);
extern int i386_movw_indix_reg_scale8_no_offset (COMMON_ARGS, int32 base, int32 index, int32 dst);
extern int i386_movl_indix_reg_scale8_no_offset (COMMON_ARGS, int32 base, int32 index, int32 dst);
extern int i386_imull_imm_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_imull_reg_reg (COMMON_ARGS, int32 src, int32 dst);
extern int i386_popw (COMMON_ARGS, int32 dst_reg);
extern int i386_popl (COMMON_ARGS, int32 dst_reg);
extern int i386_pushw (COMMON_ARGS, int32 src_reg);
extern int i386_pushl (COMMON_ARGS, int32 src_reg);
extern int i386_pushw_imm (COMMON_ARGS, int32 const_val);
extern int i386_pushl_imm (COMMON_ARGS, int32 const_val);
extern int i386_pushfl (COMMON_ARGS);
extern int i386_rolb_reg (COMMON_ARGS, int32 dst_reg);
extern int i386_rolw_reg (COMMON_ARGS, int32 dst_reg);
extern int i386_roll_reg (COMMON_ARGS, int32 dst_reg);
extern int i386_rolb_abs (COMMON_ARGS, int32 dst_addr);
extern int i386_rolw_abs (COMMON_ARGS, int32 dst_addr);
extern int i386_roll_abs (COMMON_ARGS, int32 dst_addr);
extern int i386_rolb_imm_reg (COMMON_ARGS, int32 shift_const, int32 dst_reg);
extern int i386_rolw_imm_reg (COMMON_ARGS, int32 shift_const, int32 dst_reg);
extern int i386_roll_imm_reg (COMMON_ARGS, int32 shift_const, int32 dst_reg);
extern int i386_rolb_imm_abs (COMMON_ARGS, int32 shift_const, int32 dst_addr);
extern int i386_rolw_imm_abs (COMMON_ARGS, int32 shift_const, int32 dst_addr);
extern int i386_roll_imm_abs (COMMON_ARGS, int32 shift_const, int32 dst_addr);
extern int i386_rorb_reg (COMMON_ARGS, int32 dst_reg);
extern int i386_rorw_reg (COMMON_ARGS, int32 dst_reg);
extern int i386_rorl_reg (COMMON_ARGS, int32 dst_reg);
extern int i386_rorb_abs (COMMON_ARGS, int32 dst_addr);
extern int i386_rorw_abs (COMMON_ARGS, int32 dst_addr);
extern int i386_rorl_abs (COMMON_ARGS, int32 dst_addr);
extern int i386_rorb_imm_reg (COMMON_ARGS, int32 shift_const, int32 dst_reg);
extern int i386_rorw_imm_reg (COMMON_ARGS, int32 shift_const, int32 dst_reg);
extern int i386_rorl_imm_reg (COMMON_ARGS, int32 shift_const, int32 dst_reg);
extern int i386_rorb_imm_abs (COMMON_ARGS, int32 shift_const, int32 dst_addr);
extern int i386_rorw_imm_abs (COMMON_ARGS, int32 shift_const, int32 dst_addr);
extern int i386_rorl_imm_abs (COMMON_ARGS, int32 shift_const, int32 dst_addr);
extern int i386_shlb_reg (COMMON_ARGS, int32 dst_reg);
extern int i386_shlw_reg (COMMON_ARGS, int32 dst_reg);
extern int i386_shll_reg (COMMON_ARGS, int32 dst_reg);
extern int i386_shlb_abs (COMMON_ARGS, int32 dst_addr);
extern int i386_shlw_abs (COMMON_ARGS, int32 dst_addr);
extern int i386_shll_abs (COMMON_ARGS, int32 dst_addr);
extern int i386_shlb_imm_reg (COMMON_ARGS, int32 shift_const, int32 dst_reg);
extern int i386_shlw_imm_reg (COMMON_ARGS, int32 shift_const, int32 dst_reg);
extern int i386_shll_imm_reg (COMMON_ARGS, int32 shift_const, int32 dst_reg);
extern int i386_shlb_imm_abs (COMMON_ARGS, int32 shift_const, int32 dst_addr);
extern int i386_shlw_imm_abs (COMMON_ARGS, int32 shift_const, int32 dst_addr);
extern int i386_shll_imm_abs (COMMON_ARGS, int32 shift_const, int32 dst_addr);
extern int i386_shrb_reg (COMMON_ARGS, int32 dst_reg);
extern int i386_shrw_reg (COMMON_ARGS, int32 dst_reg);
extern int i386_shrl_reg (COMMON_ARGS, int32 dst_reg);
extern int i386_shrb_abs (COMMON_ARGS, int32 dst_addr);
extern int i386_shrw_abs (COMMON_ARGS, int32 dst_addr);
extern int i386_shrl_abs (COMMON_ARGS, int32 dst_addr);
extern int i386_shrb_imm_reg (COMMON_ARGS, int32 shift_const, int32 dst_reg);
extern int i386_shrw_imm_reg (COMMON_ARGS, int32 shift_const, int32 dst_reg);
extern int i386_shrl_imm_reg (COMMON_ARGS, int32 shift_const, int32 dst_reg);
extern int i386_shrb_imm_abs (COMMON_ARGS, int32 shift_const, int32 dst_addr);
extern int i386_shrw_imm_abs (COMMON_ARGS, int32 shift_const, int32 dst_addr);
extern int i386_shrl_imm_abs (COMMON_ARGS, int32 shift_const, int32 dst_addr);
extern int i386_sarb_reg (COMMON_ARGS, int32 dst_reg);
extern int i386_sarw_reg (COMMON_ARGS, int32 dst_reg);
extern int i386_sarl_reg (COMMON_ARGS, int32 dst_reg);
extern int i386_sarb_abs (COMMON_ARGS, int32 dst_addr);
extern int i386_sarw_abs (COMMON_ARGS, int32 dst_addr);
extern int i386_sarl_abs (COMMON_ARGS, int32 dst_addr);
extern int i386_sarb_imm_reg (COMMON_ARGS, int32 shift_const, int32 dst_reg);
extern int i386_sarw_imm_reg (COMMON_ARGS, int32 shift_const, int32 dst_reg);
extern int i386_sarl_imm_reg (COMMON_ARGS, int32 shift_const, int32 dst_reg);
extern int i386_sarb_imm_abs (COMMON_ARGS, int32 shift_const, int32 dst_addr);
extern int i386_sarw_imm_abs (COMMON_ARGS, int32 shift_const, int32 dst_addr);
extern int i386_sarl_imm_abs (COMMON_ARGS, int32 shift_const, int32 dst_addr);
extern int i386_sahf (COMMON_ARGS);
extern int i386_setc_reg (COMMON_ARGS, int32 dst_reg);
extern int i386_setc_ind (COMMON_ARGS, int32 addr);
extern int i386_setc_indoff (COMMON_ARGS, int32 offset, int32 addr);
extern int i386_setc_abs (COMMON_ARGS, int32 dst_addr);
extern int i386_setbe_reg (COMMON_ARGS, int32 dst_reg);
extern int i386_setbe_ind (COMMON_ARGS, int32 addr);
extern int i386_setbe_indoff (COMMON_ARGS, int32 offset, int32 addr);
extern int i386_setbe_abs (COMMON_ARGS, int32 dst_addr);
extern int i386_setz_reg (COMMON_ARGS, int32 dst_reg);
extern int i386_setz_ind (COMMON_ARGS, int32 addr);
extern int i386_setz_indoff (COMMON_ARGS, int32 offset, int32 addr);
extern int i386_setz_abs (COMMON_ARGS, int32 dst_addr);
extern int i386_setl_reg (COMMON_ARGS, int32 dst_reg);
extern int i386_setl_ind (COMMON_ARGS, int32 addr);
extern int i386_setl_indoff (COMMON_ARGS, int32 offset, int32 addr);
extern int i386_setl_abs (COMMON_ARGS, int32 dst_addr);
extern int i386_setle_reg (COMMON_ARGS, int32 dst_reg);
extern int i386_setle_ind (COMMON_ARGS, int32 addr);
extern int i386_setle_indoff (COMMON_ARGS, int32 offset, int32 addr);
extern int i386_setle_abs (COMMON_ARGS, int32 dst_addr);
extern int i386_setnb_reg (COMMON_ARGS, int32 dst_reg);
extern int i386_setnb_ind (COMMON_ARGS, int32 addr);
extern int i386_setnb_indoff (COMMON_ARGS, int32 offset, int32 addr);
extern int i386_setnb_abs (COMMON_ARGS, int32 dst_addr);
extern int i386_setnc_reg (COMMON_ARGS, int32 dst_reg);
extern int i386_setnc_ind (COMMON_ARGS, int32 addr);
extern int i386_setnc_indoff (COMMON_ARGS, int32 offset, int32 addr);
extern int i386_setnc_abs (COMMON_ARGS, int32 dst_addr);
extern int i386_setnbe_reg (COMMON_ARGS, int32 dst_reg);
extern int i386_setnbe_ind (COMMON_ARGS, int32 addr);
extern int i386_setnbe_indoff (COMMON_ARGS, int32 offset, int32 addr);
extern int i386_setnbe_abs (COMMON_ARGS, int32 dst_addr);
extern int i386_setnz_reg (COMMON_ARGS, int32 dst_reg);
extern int i386_setnz_ind (COMMON_ARGS, int32 addr);
extern int i386_setnz_indoff (COMMON_ARGS, int32 offset, int32 addr);
extern int i386_setnz_abs (COMMON_ARGS, int32 dst_addr);
extern int i386_setge_reg (COMMON_ARGS, int32 dst_reg);
extern int i386_setge_ind (COMMON_ARGS, int32 addr);
extern int i386_setge_indoff (COMMON_ARGS, int32 offset, int32 addr);
extern int i386_setge_abs (COMMON_ARGS, int32 dst_addr);
extern int i386_setnle_reg (COMMON_ARGS, int32 dst_reg);
extern int i386_setnle_ind (COMMON_ARGS, int32 addr);
extern int i386_setnle_indoff (COMMON_ARGS, int32 offset, int32 addr);
extern int i386_setnle_abs (COMMON_ARGS, int32 dst_addr);
extern int i386_setno_reg (COMMON_ARGS, int32 dst_reg);
extern int i386_setno_ind (COMMON_ARGS, int32 addr);
extern int i386_setno_indoff (COMMON_ARGS, int32 offset, int32 addr);
extern int i386_setno_abs (COMMON_ARGS, int32 dst_addr);
extern int i386_seto_reg (COMMON_ARGS, int32 dst_reg);
extern int i386_seto_ind (COMMON_ARGS, int32 addr);
extern int i386_seto_indoff (COMMON_ARGS, int32 offset, int32 addr);
extern int i386_seto_abs (COMMON_ARGS, int32 dst_addr);
extern int i386_setns_reg (COMMON_ARGS, int32 dst_reg);
extern int i386_setns_ind (COMMON_ARGS, int32 addr);
extern int i386_setns_indoff (COMMON_ARGS, int32 offset, int32 addr);
extern int i386_setns_abs (COMMON_ARGS, int32 dst_addr);
extern int i386_sets_reg (COMMON_ARGS, int32 dst_reg);
extern int i386_sets_ind (COMMON_ARGS, int32 addr);
extern int i386_sets_indoff (COMMON_ARGS, int32 offset, int32 addr);
extern int i386_sets_abs (COMMON_ARGS, int32 dst_addr);
#endif /* GENERATE_NATIVE_CODE */
#endif /* !_I386_ISA_H_ */

View File

@ -0,0 +1,89 @@
#include "template.h"
#include "process.h"
#include <stdlib.h>
int
main (int argc, char *argv[])
{
#ifdef GENERATE_NATIVE_CODE
FILE *fp, *header_fp;
int i, success, swapop_p;
success = SUCCESS; /* default */
if (argc != 2)
{
fprintf (stderr, "Usage: %s <make>\n", argv[0]);
exit (EXIT_FAILURE);
}
header_fp = fopen ("i386-isa.h", "w");
if (header_fp == NULL)
{
fprintf (stderr, "Unable to open \"i386-isa.h\" for writing.\n");
exit (-1);
}
fputs ("/* This file is machine-generated; DO NOT EDIT! */\n"
"\n"
"#ifndef _I386_ISA_H_\n"
"#define _I386_ISA_H_\n"
"\n"
"#ifdef GENERATE_NATIVE_CODE\n"
"\n",
header_fp);
swapop_p = FALSE;
for (i = 0; success == SUCCESS && template[i].macro_name != NULL;
i += swapop_p, swapop_p = !swapop_p)
{
char cmd[1024], c_file[1024], o_file[1024];
/* Only bother swapping those that have exactly two operands. */
/* Swapop hack is no longer useful. */
if (swapop_p /* && count_operands (template[i].code) != 2 */)
continue;
if (!swapop_p)
{
printf ("Processing %s...", template[i].macro_name);
fflush (stdout);
}
sprintf (c_file, "i386_stubs/_%s.c", template[i].macro_name);
sprintf (o_file, "_i386_%d.o", i * 2 + swapop_p);/* Short for archive. */
fp = fopen (c_file, "w");
if (fp == NULL)
{
fprintf (stderr, "Unable to open file \"%s\" for writing.\n",
c_file);
exit (EXIT_FAILURE);
}
if (process_template (fp, header_fp, &template[i], argv[1], swapop_p)
== FAILURE)
success = FAILURE;
if (!swapop_p)
puts ("done.");
if (template[i + 1].macro_name != NULL)
putc ('\n', fp); /* Add an extra blank line. */
fclose (fp);
sprintf (cmd, "%s -s nextobj NEW_C_FILE=%s NEW_O_FILE=%s > /dev/null",
argv[1], c_file, o_file);
if (system (cmd))
{
fprintf (stderr, "Unable to make \"%s\".\n", c_file);
success = FAILURE;
}
}
fputs ("#endif /* GENERATE_NATIVE_CODE */\n"
"\n"
"#endif /* !_I386_ISA_H_ */\n", header_fp);
fclose (header_fp);
return (success == SUCCESS) ? EXIT_SUCCESS : EXIT_FAILURE;
#else /* !GENERATE_NATIVE_CODE */
return EXIT_SUCCESS;
#endif /* !GENERATE_NATIVE_CODE */
}

Some files were not shown because too many files have changed in this diff Show More