mirror of
https://github.com/ctm/syn68k.git
synced 2025-04-02 18:29:33 +00:00
Syn68k from an svn export
This commit is contained in:
commit
eac71db488
5
AUTHORS
Normal file
5
AUTHORS
Normal 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
24
COPYING
Normal 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
6
ChangeLog
Normal 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
3
Makefile.am
Normal 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
488
Makefile.common.in
Normal 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
6
NEWS
Normal 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
6
README
Normal 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
41
TODO
Normal 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
42
TODO.variables
Normal 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
10
autogen.sh
Executable 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
|
24
config/Makefile.common.alpha
Normal file
24
config/Makefile.common.alpha
Normal 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
|
7
config/Makefile.common.alpha.orig
Normal file
7
config/Makefile.common.alpha.orig
Normal file
@ -0,0 +1,7 @@
|
||||
CC = cc
|
||||
OFILE_DIR = obj/alpha
|
||||
LIBDIR = ../lib/alpha
|
||||
LIBS =
|
||||
HOSTCPU = alpha
|
||||
RANLIB = /bin/ranlib
|
||||
LDFLAGS = -taso
|
18
config/Makefile.common.i386-msdos-go32
Normal file
18
config/Makefile.common.i386-msdos-go32
Normal 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
|
17
config/Makefile.common.i386-next-mach-o.dynamic
Normal file
17
config/Makefile.common.i386-next-mach-o.dynamic
Normal 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
|
17
config/Makefile.common.i386-next-mach-o.static
Normal file
17
config/Makefile.common.i386-next-mach-o.static
Normal 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
|
18
config/Makefile.common.i386-pc-mingw32
Normal file
18
config/Makefile.common.i386-pc-mingw32
Normal 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
|
18
config/Makefile.common.i486-cygwin32
Normal file
18
config/Makefile.common.i486-cygwin32
Normal 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
|
21
config/Makefile.common.i486-cygwin32.debug
Normal file
21
config/Makefile.common.i486-cygwin32.debug
Normal 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
|
17
config/Makefile.common.i486-linux-a.out
Normal file
17
config/Makefile.common.i486-linux-a.out
Normal 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
|
23
config/Makefile.common.i486-linux-a.out-debug
Normal file
23
config/Makefile.common.i486-linux-a.out-debug
Normal 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
|
17
config/Makefile.common.i486-linux-elf
Normal file
17
config/Makefile.common.i486-linux-elf
Normal 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
|
20
config/Makefile.common.i486-linux-elf-nonnative
Normal file
20
config/Makefile.common.i486-linux-elf-nonnative
Normal 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
|
||||
|
17
config/Makefile.common.i486-linux-elf.debug
Normal file
17
config/Makefile.common.i486-linux-elf.debug
Normal 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)
|
18
config/Makefile.common.i486-linux-glibc
Normal file
18
config/Makefile.common.i486-linux-glibc
Normal 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
|
19
config/Makefile.common.i486-linux-glibc-ccr8
Normal file
19
config/Makefile.common.i486-linux-glibc-ccr8
Normal 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
|
19
config/Makefile.common.i486-linux-glibc-debug
Normal file
19
config/Makefile.common.i486-linux-glibc-debug
Normal 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)
|
20
config/Makefile.common.i486-linux-glibc-nonnative
Normal file
20
config/Makefile.common.i486-linux-glibc-nonnative
Normal 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
|
||||
|
19
config/Makefile.common.i486-linux-glibc-slowccr
Normal file
19
config/Makefile.common.i486-linux-glibc-slowccr
Normal 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
|
25
config/Makefile.common.i486-linux-slam
Normal file
25
config/Makefile.common.i486-linux-slam
Normal 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 =
|
||||
|
||||
|
||||
|
18
config/Makefile.common.i486-new-cygwin32
Normal file
18
config/Makefile.common.i486-new-cygwin32
Normal 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
|
21
config/Makefile.common.i486-new-cygwin32.debug
Normal file
21
config/Makefile.common.i486-new-cygwin32.debug
Normal 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
|
17
config/Makefile.common.i486-next-ns3
Normal file
17
config/Makefile.common.i486-next-ns3
Normal 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
|
18
config/Makefile.common.i586-cygwin32
Normal file
18
config/Makefile.common.i586-cygwin32
Normal 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
|
18
config/Makefile.common.i586-cygwin32.debug
Normal file
18
config/Makefile.common.i586-cygwin32.debug
Normal 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
|
5
config/Makefile.common.i860
Normal file
5
config/Makefile.common.i860
Normal file
@ -0,0 +1,5 @@
|
||||
CC = gcc
|
||||
OFILE_DIR = obj/i860
|
||||
LIBDIR = ../lib/i860
|
||||
LIBS = -L/usr/ucblib -lucb
|
||||
HOSTCPU = i860
|
13
config/Makefile.common.m68k-next-ns3
Normal file
13
config/Makefile.common.m68k-next-ns3
Normal 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
|
21
config/Makefile.common.powerpc-linux-glibc
Normal file
21
config/Makefile.common.powerpc-linux-glibc
Normal 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
|
21
config/Makefile.common.powerpc-linux-glibc-debug
Normal file
21
config/Makefile.common.powerpc-linux-glibc-debug
Normal 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
143
configure.ac
Normal 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
55
include/safe_alloca.h
Normal 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
290
include/syn68k_private.h.in
Normal 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
681
include/syn68k_public.h
Normal 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
15
profile/Makefile.am
Normal 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
37
profile/amode.c
Normal 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
43
profile/frequency.c
Normal 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
6
profile/include/amode.h
Normal 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
16
profile/include/bucket.h
Normal 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_ */
|
6
profile/include/frequency.h
Normal file
6
profile/include/frequency.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef _frequency_h_
|
||||
#define _frequency_h_
|
||||
|
||||
extern void generate_frequency_report (void);
|
||||
|
||||
#endif /* Not _frequency_h_ */
|
9
profile/include/readprofile.h
Normal file
9
profile/include/readprofile.h
Normal 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
23
profile/main.c
Normal 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
147
profile/makebucket.c
Normal 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
39
profile/readprofile.c
Normal 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
412
runtime/68k.defines.scm
Normal 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
6525
runtime/68k.scm
Normal file
File diff suppressed because it is too large
Load Diff
78
runtime/Makefile.am
Normal file
78
runtime/Makefile.am
Normal 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
6
runtime/TODO
Normal 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
60
runtime/alloc.c
Normal 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
119
runtime/backpatch.c
Normal 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
312
runtime/block.c
Normal 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
283
runtime/blockinfo.c
Normal 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
186
runtime/callback.c
Normal 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
11
runtime/checksum.c
Normal 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
49
runtime/deathqueue.c
Normal 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
268
runtime/destroyblock.c
Normal 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
83
runtime/diagnostics.c
Normal 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
48
runtime/dosinterrupts.c
Normal 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
177
runtime/fold.pl
Executable 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
227
runtime/hash.c
Normal 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
36
runtime/i486-cleanup.pl
Executable 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
69
runtime/i486-optimize.pl
Executable 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
10
runtime/include/alloc.h
Normal 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_ */
|
21
runtime/include/backpatch.h
Normal file
21
runtime/include/backpatch.h
Normal 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
62
runtime/include/block.h
Normal 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_ */
|
18
runtime/include/blockinfo.h
Normal file
18
runtime/include/blockinfo.h
Normal 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_ */
|
23
runtime/include/callback.h
Normal file
23
runtime/include/callback.h
Normal 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
252
runtime/include/ccfuncs.h
Normal 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_ */
|
68
runtime/include/checksum.h
Normal file
68
runtime/include/checksum.h
Normal 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_ */
|
10
runtime/include/deathqueue.h
Normal file
10
runtime/include/deathqueue.h
Normal 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_ */
|
10
runtime/include/destroyblock.h
Normal file
10
runtime/include/destroyblock.h
Normal 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_ */
|
13
runtime/include/diagnostics.h
Normal file
13
runtime/include/diagnostics.h
Normal 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
28
runtime/include/hash.h
Normal 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_ */
|
8
runtime/include/interrupt.h
Normal file
8
runtime/include/interrupt.h
Normal 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_ */
|
9
runtime/include/mapping.h
Normal file
9
runtime/include/mapping.h
Normal 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
300
runtime/include/native.h
Normal 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
13
runtime/include/profile.h
Normal 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_ */
|
20
runtime/include/rangetree.h
Normal file
20
runtime/include/rangetree.h
Normal 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_ */
|
26
runtime/include/recompile.h
Normal file
26
runtime/include/recompile.h
Normal 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_ */
|
30
runtime/include/translate.h
Normal file
30
runtime/include/translate.h
Normal 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
61
runtime/include/trap.h
Normal 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
128
runtime/init.c
Normal 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
103
runtime/interrupt.c
Normal 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
684
runtime/native.c
Normal 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 */
|
80
runtime/native/i386/Makefile.am
Normal file
80
runtime/native/i386/Makefile.am
Normal 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
|
844
runtime/native/i386/analyze.c
Normal file
844
runtime/native/i386/analyze.c
Normal 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;
|
||||
}
|
617
runtime/native/i386/host-native.c
Normal file
617
runtime/native/i386/host-native.c
Normal 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
|
84
runtime/native/i386/host-native.h
Normal file
84
runtime/native/i386/host-native.h
Normal 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_ */
|
3105
runtime/native/i386/i386-aux.c
Normal file
3105
runtime/native/i386/i386-aux.c
Normal file
File diff suppressed because it is too large
Load Diff
660
runtime/native/i386/i386-aux.h
Normal file
660
runtime/native/i386/i386-aux.h
Normal 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_*/
|
665
runtime/native/i386/i386-isa.h
Normal file
665
runtime/native/i386/i386-isa.h
Normal 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_ */
|
89
runtime/native/i386/main.c
Normal file
89
runtime/native/i386/main.c
Normal 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
Loading…
x
Reference in New Issue
Block a user