mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-04-09 04:59:31 -06:00
started a new database-backed runtime from scratch
This commit is contained in:
@@ -1,9 +0,0 @@
|
||||
libpgf is written by:
|
||||
|
||||
Krasimir Angelov <krasimir@chalmers.se>
|
||||
Lauri Alanko <lealanko@ling.helsinki.fi>
|
||||
|
||||
with some contributions from:
|
||||
|
||||
Prasanth Kolachina <prasanth.kolachina@cse.gu.se>
|
||||
Bjørnar Luteberget <luteberget@gmail.com>
|
||||
@@ -1,91 +0,0 @@
|
||||
project(libpgf)
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
set(GNU_LIGHTNING_ARCH "i386" CACHE STRING "Target architecture for GNU Lightning JIT")
|
||||
#set(ADD_CFLAGS "-Wall -Wextra -Wno-missing-field-initializers -Wno-unused-parameter -Wno-unused-value" CACHE STRING "Additional C compiler options")
|
||||
#set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-no-undefined")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 ${ADD_CFLAGS}")
|
||||
|
||||
set(GNU_LIGHTNING_ARCH_HEADERS
|
||||
pgf/lightning/${GNU_LIGHTNING_ARCH}/asm.h
|
||||
pgf/lightning/${GNU_LIGHTNING_ARCH}/fp.h
|
||||
pgf/lightning/${GNU_LIGHTNING_ARCH}/core.h
|
||||
pgf/lightning/${GNU_LIGHTNING_ARCH}/funcs.h
|
||||
)
|
||||
|
||||
file(COPY ${GNU_LIGHTNING_ARCH_HEADERS}
|
||||
DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/pgf/lightning/)
|
||||
|
||||
|
||||
include_directories(.)
|
||||
include_directories(./pgf)
|
||||
|
||||
|
||||
set(libgu_la_SOURCES
|
||||
gu/assert.c
|
||||
gu/bits.c
|
||||
gu/choice.c
|
||||
gu/defs.c
|
||||
gu/seq.c
|
||||
gu/enum.c
|
||||
gu/exn.c
|
||||
gu/file.c
|
||||
gu/fun.c
|
||||
gu/hash.c
|
||||
gu/in.c
|
||||
gu/map.c
|
||||
gu/mem.c
|
||||
gu/out.c
|
||||
gu/prime.c
|
||||
gu/string.c
|
||||
gu/utf8.c
|
||||
gu/ucs.c
|
||||
gu/variant.c
|
||||
)
|
||||
|
||||
set(libpgf_la_SOURCES
|
||||
pgf/data.c
|
||||
pgf/data.h
|
||||
pgf/expr.c
|
||||
pgf/expr.h
|
||||
pgf/parser.c
|
||||
pgf/lookup.c
|
||||
pgf/jit.c
|
||||
pgf/parseval.c
|
||||
pgf/literals.c
|
||||
pgf/literals.h
|
||||
pgf/reader.h
|
||||
pgf/reader.c
|
||||
pgf/linearizer.c
|
||||
pgf/typechecker.c
|
||||
pgf/reasoner.c
|
||||
pgf/evaluator.c
|
||||
pgf/hopu.c
|
||||
pgf/printer.c
|
||||
pgf/graphviz.c
|
||||
pgf/aligner.c
|
||||
pgf/pgf.c
|
||||
pgf/pgf.h
|
||||
)
|
||||
|
||||
set(libsg_la_SOURCES
|
||||
sg/sqlite3Btree.c
|
||||
sg/sg.c
|
||||
)
|
||||
|
||||
|
||||
add_library(gu SHARED ${libgu_la_SOURCES})
|
||||
#set_property(TARGET gu PROPERTY C_STANDARD 99)
|
||||
#set_property(TARGET gu PROPERTY WINDOWS_EXPORT_ALL_SYMBOLS true)
|
||||
target_compile_definitions(gu PRIVATE COMPILING_GU=1)
|
||||
|
||||
add_library(pgf SHARED ${libpgf_la_SOURCES})
|
||||
#set_property(TARGET pgf PROPERTY C_STANDARD 99)
|
||||
#set_property(TARGET pgf PROPERTY WINDOWS_EXPORT_ALL_SYMBOLS true)
|
||||
target_compile_definitions(pgf PRIVATE COMPILING_PGF=1)
|
||||
target_link_libraries(pgf gu)
|
||||
if(UNIX)
|
||||
target_link_libraries(pgf m)
|
||||
endif(UNIX)
|
||||
|
||||
install(TARGETS gu pgf DESTINATION lib)
|
||||
@@ -1,165 +0,0 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
@@ -1,63 +0,0 @@
|
||||
General Note
|
||||
------------
|
||||
|
||||
If you want to use the statistical ranking in the parser then you
|
||||
have to compile your grammar with the option '-probs=grammar.probs',
|
||||
where grammar.probs must contain a tab separated file with
|
||||
the probabilities for all functions in the abstract syntax.
|
||||
In order to enable the named entity recongizer for the ParseEngAbs
|
||||
grammar you also have to add the option '-literal=Symb' while compiling.
|
||||
|
||||
|
||||
For Linux users
|
||||
---------------
|
||||
|
||||
You will need the packages: autoconf, automake, libtool, make
|
||||
|
||||
- On Ubuntu: $ apt-get install autotools-dev
|
||||
- On Fedora: $ dnf install autoconf automake libtool
|
||||
|
||||
The compilation steps are:
|
||||
|
||||
$ autoreconf -i
|
||||
$ ./configure
|
||||
$ make
|
||||
$ make install
|
||||
|
||||
|
||||
For Mac OSX users
|
||||
-----------------
|
||||
|
||||
The following is what I did to make it work on MacOSX 10.8:
|
||||
|
||||
- Install XCode and XCode command line tools
|
||||
- Install Homebrew: https://brew.sh
|
||||
|
||||
$ brew install automake autoconf libtool
|
||||
$ glibtoolize
|
||||
$ autoreconf -i
|
||||
$ ./configure
|
||||
$ make
|
||||
$ make install
|
||||
|
||||
|
||||
For Windows users
|
||||
-----------------
|
||||
|
||||
- Install MinGW: http://www.mingw.org/. From the installer you need
|
||||
to select at least the following packages:
|
||||
- Mingw-developer-toolkit
|
||||
- Mingw-base
|
||||
- Msys-base
|
||||
After the installation, don't forget to fix the fstab file. See here:
|
||||
http://www.mingw.org/wiki/Getting_Started
|
||||
|
||||
- From the MSYS shell (c:/MinGW/msys/1.0/msys.bat) go to the directory
|
||||
which contains the INSTALL file and do:
|
||||
|
||||
$ autoreconf -i
|
||||
$ ./configure
|
||||
$ make
|
||||
$ make install
|
||||
|
||||
The compiled binaries should be now in c:/MinGW/msys/1.0/local/bin.
|
||||
@@ -1,92 +1,24 @@
|
||||
lib_LTLIBRARIES = libgu.la libpgf.la
|
||||
lib_LTLIBRARIES = libpgf.la
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = libgu.pc libpgf.pc
|
||||
pkgconfig_DATA = libpgf.pc
|
||||
|
||||
configincludedir = $(libdir)/libgu/include
|
||||
|
||||
guincludedir=$(includedir)/gu
|
||||
guinclude_HEADERS = \
|
||||
gu/assert.h \
|
||||
gu/bits.h \
|
||||
gu/choice.h \
|
||||
gu/defs.h \
|
||||
gu/enum.h \
|
||||
gu/exn.h \
|
||||
gu/file.h \
|
||||
gu/fun.h \
|
||||
gu/hash.h \
|
||||
gu/in.h \
|
||||
gu/map.h \
|
||||
gu/mem.h \
|
||||
gu/out.h \
|
||||
gu/prime.h \
|
||||
gu/seq.h \
|
||||
gu/string.h \
|
||||
gu/sysdeps.h \
|
||||
gu/ucs.h \
|
||||
gu/utf8.h \
|
||||
gu/variant.h
|
||||
|
||||
pgfincludedir=$(includedir)/pgf
|
||||
pgfincludedir=$(includedir)
|
||||
pgfinclude_HEADERS = \
|
||||
pgf/expr.h \
|
||||
pgf/linearizer.h \
|
||||
pgf/literals.h \
|
||||
pgf/graphviz.h \
|
||||
pgf/pgf.h \
|
||||
pgf/data.h
|
||||
|
||||
libgu_la_SOURCES = \
|
||||
gu/assert.c \
|
||||
gu/bits.c \
|
||||
gu/choice.c \
|
||||
gu/defs.c \
|
||||
gu/seq.c \
|
||||
gu/enum.c \
|
||||
gu/exn.c \
|
||||
gu/file.c \
|
||||
gu/fun.c \
|
||||
gu/hash.c \
|
||||
gu/in.c \
|
||||
gu/map.c \
|
||||
gu/mem.c \
|
||||
gu/out.c \
|
||||
gu/prime.c \
|
||||
gu/string.c \
|
||||
gu/utf8.c \
|
||||
gu/ucs.c \
|
||||
gu/variant.c
|
||||
libgu_la_LDFLAGS = -no-undefined
|
||||
pgf.h
|
||||
|
||||
libpgf_la_SOURCES = \
|
||||
pgf/data.c \
|
||||
pgf/data.h \
|
||||
pgf/expr.c \
|
||||
pgf/expr.h \
|
||||
pgf/scanner.c \
|
||||
pgf/parser.c \
|
||||
pgf/lookup.c \
|
||||
pgf/jit.c \
|
||||
pgf/parseval.c \
|
||||
pgf/literals.c \
|
||||
pgf/literals.h \
|
||||
pgf/reader.h \
|
||||
pgf/reader.c \
|
||||
pgf/writer.h \
|
||||
pgf/writer.c \
|
||||
pgf/linearizer.c \
|
||||
pgf/typechecker.c \
|
||||
pgf/reasoner.c \
|
||||
pgf/evaluator.c \
|
||||
pgf/hopu.c \
|
||||
pgf/printer.c \
|
||||
pgf/graphviz.c \
|
||||
pgf/aligner.c \
|
||||
pgf/pgf.c \
|
||||
pgf/pgf.h \
|
||||
db.cxx \
|
||||
db.h \
|
||||
pgf.cxx \
|
||||
reader.cxx \
|
||||
reader.h \
|
||||
data.h \
|
||||
expr.h \
|
||||
namespace.h \
|
||||
variant.h
|
||||
|
||||
libpgf_la_LDFLAGS = "-no-undefined"
|
||||
libpgf_la_LIBADD = libgu.la
|
||||
|
||||
bin_PROGRAMS =
|
||||
|
||||
@@ -94,5 +26,4 @@ AUTOMAKE_OPTIONS = foreign subdir-objects dist-bzip2
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
EXTRA_DIST = \
|
||||
libgu.pc.in \
|
||||
libpgf.pc.in
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
AC_INIT(Portable Grammar Format library, 0.1-pre,
|
||||
AC_INIT(Portable Grammar Format library, 3.0-pre,
|
||||
http://www.grammaticalframework.org/,
|
||||
libpgf)
|
||||
AC_PREREQ(2.58)
|
||||
|
||||
AC_CONFIG_SRCDIR([gu/mem.c])
|
||||
AC_CONFIG_AUX_DIR([scripts])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
@@ -21,9 +20,7 @@ AC_CHECK_LIB(m,nan)
|
||||
AC_PROG_MAKE_SET
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_LIBTOOL
|
||||
AC_PROG_CC
|
||||
AC_PROG_CC_C99
|
||||
AM_PROG_CC_C_O
|
||||
AC_PROG_CXX
|
||||
|
||||
[if [ "x$GCC" = "xyes" ]; then
|
||||
CFLAGS="$CFLAGS\
|
||||
@@ -34,29 +31,7 @@ AM_PROG_CC_C_O
|
||||
-Wno-unused-value"
|
||||
fi]
|
||||
|
||||
case "$target_cpu" in
|
||||
i?86) cpu=i386; AC_DEFINE(LIGHTNING_I386, 1,
|
||||
[Define if lightning is targeting the x86 architecture]) ;;
|
||||
x86_64) cpu=i386; AC_DEFINE(LIGHTNING_I386, 1,
|
||||
[Define if lightning is targeting the x86 architecture]) ;;
|
||||
sparc*) cpu=sparc; AC_DEFINE(LIGHTNING_SPARC, 1,
|
||||
[Define if lightning is targeting the sparc architecture]) ;;
|
||||
powerpc) cpu=ppc; AC_DEFINE(LIGHTNING_PPC, 1,
|
||||
[Define if lightning is targeting the powerpc architecture]) ;;
|
||||
arm*) cpu=arm; AC_DEFINE(LIGHTNING_ARM, 1,
|
||||
[Define if lightning is targeting the arm architecture]) ;;
|
||||
*) AC_MSG_ERROR([cpu $target_cpu not supported]) ;;
|
||||
esac
|
||||
|
||||
cpu_dir=pgf/lightning/$cpu
|
||||
AC_CONFIG_LINKS(pgf/lightning/asm.h:$cpu_dir/asm.h dnl
|
||||
pgf/lightning/fp.h:$cpu_dir/fp.h dnl
|
||||
pgf/lightning/core.h:$cpu_dir/core.h dnl
|
||||
pgf/lightning/funcs.h:$cpu_dir/funcs.h, [],
|
||||
[cpu_dir=$cpu_dir])
|
||||
|
||||
AC_CONFIG_FILES([Makefile
|
||||
libgu.pc
|
||||
libpgf.pc
|
||||
])
|
||||
|
||||
|
||||
64
src/runtime/c/data.h
Normal file
64
src/runtime/c/data.h
Normal file
@@ -0,0 +1,64 @@
|
||||
#ifndef PGF_DATA_H_
|
||||
#define PGF_DATA_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <iostream>
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "pgf.h"
|
||||
#include "db.h"
|
||||
#include "namespace.h"
|
||||
#include "expr.h"
|
||||
|
||||
class PGF_INTERNAL_DECL pgf_error : public std::runtime_error {
|
||||
public:
|
||||
pgf_error(const char *msg) : std::runtime_error(msg)
|
||||
{
|
||||
this->msg = msg;
|
||||
}
|
||||
|
||||
const char *what() const throw ()
|
||||
{
|
||||
return msg;
|
||||
}
|
||||
|
||||
private:
|
||||
const char *msg;
|
||||
};
|
||||
|
||||
struct PGF_INTERNAL_DECL PgfFlag {
|
||||
PgfLiteral value;
|
||||
char name[];
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
ref<char> name;
|
||||
Namespace<PgfFlag> aflags;
|
||||
} PgfAbstr;
|
||||
|
||||
struct PGF_INTERNAL_DECL PgfPGFRoot {
|
||||
uint16_t major_version;
|
||||
uint16_t minor_version;
|
||||
Namespace<PgfFlag> gflags;
|
||||
PgfAbstr abstract;
|
||||
//PgfConcrs* concretes;
|
||||
};
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wattributes"
|
||||
|
||||
struct PgfPGF : public PgfPGFRoot {
|
||||
DB db;
|
||||
|
||||
PGF_INTERNAL_DECL PgfPGF(const char* fpath) : db(fpath) {};
|
||||
PGF_INTERNAL_DECL ~PgfPGF() {};
|
||||
|
||||
PGF_INTERNAL_DECL void set_root();
|
||||
};
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#endif
|
||||
911
src/runtime/c/db.cxx
Normal file
911
src/runtime/c/db.cxx
Normal file
@@ -0,0 +1,911 @@
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <system_error>
|
||||
|
||||
#include "data.h"
|
||||
|
||||
thread_local unsigned char* current_base;
|
||||
thread_local DB* current_db;
|
||||
|
||||
#ifndef DEFAULT_TOP_PAD
|
||||
#define DEFAULT_TOP_PAD (0)
|
||||
#endif
|
||||
|
||||
#define ptr(ms,o) ((mchunk*) (((char*) (ms)) + (o)))
|
||||
#define ofs(ms,p) (((char*) (p)) - ((char*) (ms)))
|
||||
|
||||
struct mchunk {
|
||||
size_t mchunk_prev_size; /* Size of previous chunk (if free). */
|
||||
size_t mchunk_size; /* Size in bytes, including overhead. */
|
||||
|
||||
moffset fd; /* double links -- used only if free. */
|
||||
moffset bk;
|
||||
|
||||
/* Only used for large blocks: pointer to next larger size. */
|
||||
moffset fd_nextsize; /* double links -- used only if free. */
|
||||
moffset bk_nextsize;
|
||||
};
|
||||
|
||||
#define POOL_ALIGNMENT (2 * sizeof(size_t) < __alignof__ (long double) \
|
||||
? __alignof__ (long double) : 2 * sizeof(size_t))
|
||||
|
||||
/*
|
||||
Bins
|
||||
An array of bin headers for free chunks. Each bin is doubly
|
||||
linked. The bins are approximately proportionally (log) spaced.
|
||||
There are a lot of these bins (128). This may look excessive, but
|
||||
works very well in practice. Most bins hold sizes that are
|
||||
unusual as allocation request sizes, but are more usual for fragments
|
||||
and consolidated sets of chunks, which is what these bins hold, so
|
||||
they can be found quickly. All procedures maintain the invariant
|
||||
that no consolidated chunk physically borders another one, so each
|
||||
chunk in a list is known to be preceeded and followed by either
|
||||
inuse chunks or the ends of memory.
|
||||
Chunks in bins are kept in size order, with ties going to the
|
||||
approximately least recently used chunk. Ordering isn't needed
|
||||
for the small bins, which all contain the same-sized chunks, but
|
||||
facilitates best-fit allocation for larger chunks. These lists
|
||||
are just sequential. Keeping them in order almost never requires
|
||||
enough traversal to warrant using fancier ordered data
|
||||
structures.
|
||||
Chunks of the same size are linked with the most
|
||||
recently freed at the front, and allocations are taken from the
|
||||
back. This results in LRU (FIFO) allocation order, which tends
|
||||
to give each chunk an equal opportunity to be consolidated with
|
||||
adjacent freed chunks, resulting in larger free chunks and less
|
||||
fragmentation.
|
||||
To simplify use in double-linked lists, each bin header acts
|
||||
as an mchunk. This avoids special-casing for headers.
|
||||
But to conserve space and improve locality, we allocate
|
||||
only the fd/bk pointers of bins, and then use repositioning tricks
|
||||
to treat these as the fields of a mchunk*.
|
||||
*/
|
||||
|
||||
typedef struct mchunk mbin;
|
||||
|
||||
/* addressing -- note that bin_at(0) does not exist */
|
||||
#define bin_at(m, i) \
|
||||
(mbin*) (((char *) &((m)->bins[((i) - 1) * 2])) \
|
||||
- offsetof (mchunk, fd))
|
||||
/* analog of ++bin */
|
||||
#define next_bin(b) ((mbin*) ((char *) (b) + (sizeof(mchunk*) << 1)))
|
||||
/* Reminders about list directionality within bins */
|
||||
#define first(b) ((b)->fd)
|
||||
#define last(b) ((b)->bk)
|
||||
|
||||
/*
|
||||
Indexing
|
||||
Bins for sizes < 512 bytes contain chunks of all the same size, spaced
|
||||
8 bytes apart. Larger bins are approximately logarithmically spaced:
|
||||
64 bins of size 8
|
||||
32 bins of size 64
|
||||
16 bins of size 512
|
||||
8 bins of size 4096
|
||||
4 bins of size 32768
|
||||
2 bins of size 262144
|
||||
1 bin of size what's left
|
||||
There is actually a little bit of slop in the numbers in bin_index
|
||||
for the sake of speed. This makes no difference elsewhere.
|
||||
The bins top out around 1MB because we expect to service large
|
||||
requests via mmap.
|
||||
Bin 0 does not exist. Bin 1 is the unordered list; if that would be
|
||||
a valid chunk size the small bins are bumped up one.
|
||||
*/
|
||||
#define NBINS 128
|
||||
#define NSMALLBINS 64
|
||||
#define SMALLBIN_WIDTH POOL_ALIGNMENT
|
||||
#define SMALLBIN_CORRECTION (POOL_ALIGNMENT > 2 * sizeof(size_t))
|
||||
#define MIN_LARGE_SIZE ((NSMALLBINS - SMALLBIN_CORRECTION) * SMALLBIN_WIDTH)
|
||||
|
||||
#define in_smallbin_range(sz) \
|
||||
((unsigned long) (sz) < (unsigned long) MIN_LARGE_SIZE)
|
||||
#define smallbin_index(sz) \
|
||||
((SMALLBIN_WIDTH == 16 ? (((unsigned) (sz)) >> 4) : (((unsigned) (sz)) >> 3))\
|
||||
+ SMALLBIN_CORRECTION)
|
||||
#define largebin_index_32(sz) \
|
||||
(((((unsigned long) (sz)) >> 6) <= 38) ? 56 + (((unsigned long) (sz)) >> 6) :\
|
||||
((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
|
||||
((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
|
||||
((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
|
||||
((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
|
||||
126)
|
||||
#define largebin_index_32_big(sz) \
|
||||
(((((unsigned long) (sz)) >> 6) <= 45) ? 49 + (((unsigned long) (sz)) >> 6) :\
|
||||
((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
|
||||
((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
|
||||
((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
|
||||
((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
|
||||
126)
|
||||
// XXX It remains to be seen whether it is good to keep the widths of
|
||||
// XXX the buckets the same or whether it should be scaled by a factor
|
||||
// XXX of two as well.
|
||||
#define largebin_index_64(sz) \
|
||||
(((((unsigned long) (sz)) >> 6) <= 48) ? 48 + (((unsigned long) (sz)) >> 6) :\
|
||||
((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
|
||||
((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
|
||||
((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
|
||||
((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
|
||||
126)
|
||||
#define largebin_index(sz) \
|
||||
(sizeof(size_t) == 8 ? largebin_index_64 (sz) \
|
||||
: POOL_ALIGNMENT == 16 ? largebin_index_32_big (sz) \
|
||||
: largebin_index_32 (sz))
|
||||
|
||||
|
||||
/*
|
||||
Unsorted chunks
|
||||
All remainders from chunk splits, as well as all returned chunks,
|
||||
are first placed in the "unsorted" bin. They are then placed
|
||||
in regular bins after malloc gives them ONE chance to be used before
|
||||
binning. So, basically, the unsorted_chunks list acts as a queue,
|
||||
with chunks being placed on it in free (and pool_consolidate),
|
||||
and taken off (to be either used or placed in bins) in malloc.
|
||||
*/
|
||||
/* The otherwise unindexable 1-bin is used to hold unsorted chunks. */
|
||||
#define unsorted_chunks(M) (bin_at (M, 1))
|
||||
|
||||
/* conversion from malloc headers to user pointers, and back */
|
||||
#define chunk2mem(p) ((void*)((char*)(p) + 2*sizeof(size_t)))
|
||||
#define mem2chunk(mem) ((mchunk*)((char*)(mem) - 2*sizeof(size_t)))
|
||||
|
||||
#define MIN_CHUNK_SIZE (offsetof(mchunk, fd_nextsize))
|
||||
|
||||
#define MALLOC_ALIGN_MASK (2*sizeof(size_t) - 1)
|
||||
|
||||
/* The smallest size we can malloc is an aligned minimal chunk */
|
||||
#define MINSIZE \
|
||||
(unsigned long)(((MIN_CHUNK_SIZE+MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK))
|
||||
|
||||
/* pad request bytes into a usable size -- internal version */
|
||||
#define request2size(req) \
|
||||
(((req) + sizeof(size_t) + MALLOC_ALIGN_MASK < MINSIZE) ? \
|
||||
MINSIZE : \
|
||||
((req) + sizeof(size_t) + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)
|
||||
|
||||
/*
|
||||
--------------- Physical chunk operations ---------------
|
||||
*/
|
||||
/* size field is or'ed with PREV_INUSE when previous adjacent chunk in use */
|
||||
#define PREV_INUSE 0x1
|
||||
/* extract inuse bit of previous chunk */
|
||||
#define prev_inuse(p) ((p)->mchunk_size & PREV_INUSE)
|
||||
|
||||
/* Get size, ignoring use bits */
|
||||
#define chunksize(p) (p->mchunk_size & ~(PREV_INUSE))
|
||||
|
||||
/* Size of the chunk below P. Only valid if !prev_inuse (P). */
|
||||
#define prev_size(p) ((p)->mchunk_prev_size)
|
||||
|
||||
/* Treat space at ptr + offset as a chunk */
|
||||
#define chunk_at_offset(p, s) ((mchunk*) (((char *) (p)) + (s)))
|
||||
|
||||
/* check/set/clear inuse bits in known places */
|
||||
#define inuse_bit_at_offset(p, s) \
|
||||
(((mchunk*) (((char *) (p)) + (s)))->mchunk_size & PREV_INUSE)
|
||||
|
||||
#define set_inuse_bit_at_offset(p, s) \
|
||||
(((mchunk*) (((char *) (p)) + (s)))->mchunk_size |= PREV_INUSE)
|
||||
|
||||
#define clear_inuse_bit_at_offset(p, s) \
|
||||
(((mchunk*) (((char *) (p)) + (s)))->mchunk_size &= ~(PREV_INUSE))
|
||||
|
||||
/* Set size/use field */
|
||||
#define set_head(p, s) ((p)->mchunk_size = (s))
|
||||
/* Set size at footer (only when chunk is not in use) */
|
||||
#define set_foot(p, s) (((mchunk*) ((char *) (p) + (s)))->mchunk_prev_size = (s))
|
||||
|
||||
/*
|
||||
Binmap
|
||||
To help compensate for the large number of bins, a one-level index
|
||||
structure is used for bin-by-bin searching. `binmap' is a
|
||||
bitvector recording whether bins are definitely empty so they can
|
||||
be skipped over during during traversals. The bits are NOT always
|
||||
cleared as soon as bins are empty, but instead only
|
||||
when they are noticed to be empty during traversal in malloc.
|
||||
*/
|
||||
/* Conservatively use 32 bits per map word, even if on 64bit system */
|
||||
#define BINMAPSHIFT 5
|
||||
#define BITSPERMAP (1U << BINMAPSHIFT)
|
||||
#define BINMAPSIZE (NBINS / BITSPERMAP)
|
||||
|
||||
#define idx2block(i) ((i) >> BINMAPSHIFT)
|
||||
#define idx2bit(i) ((1U << ((i) & ((1U << BINMAPSHIFT) - 1))))
|
||||
#define mark_bin(ms, i) ((ms)->binmap[idx2block(i)] |= idx2bit (i))
|
||||
#define unmark_bin(ms, i) ((ms)->binmap[idx2block(i)] &= ~(idx2bit (i)))
|
||||
#define get_binmap(ms, i) ((ms)->binmap[idx2block(i)] & idx2bit (i))
|
||||
|
||||
/*
|
||||
Fastbins
|
||||
An array of lists holding recently freed small chunks. Fastbins
|
||||
are not doubly linked. It is faster to single-link them, and
|
||||
since chunks are never removed from the middles of these lists,
|
||||
double linking is not necessary. Also, unlike regular bins, they
|
||||
are not even processed in FIFO order (they use faster LIFO) since
|
||||
ordering doesn't much matter in the transient contexts in which
|
||||
fastbins are normally used.
|
||||
Chunks in fastbins keep their inuse bit set, so they cannot
|
||||
be consolidated with other free chunks. malloc_consolidate
|
||||
releases all chunks in fastbins and consolidates them with
|
||||
other free chunks.
|
||||
*/
|
||||
|
||||
#define DEFAULT_MXFAST (64 * sizeof(size_t) / 4)
|
||||
|
||||
/* offset 2 to use otherwise unindexable first 2 bins */
|
||||
#define fastbin_index(sz) \
|
||||
((((unsigned int) (sz)) >> (sizeof(size_t) == 8 ? 4 : 3)) - 2)
|
||||
/* The maximum fastbin request size we support */
|
||||
#define MAX_FAST_SIZE (80 * sizeof(size_t) / 4)
|
||||
#define NFASTBINS (fastbin_index (request2size (MAX_FAST_SIZE)) + 1)
|
||||
|
||||
/*
|
||||
FASTBIN_CONSOLIDATION_THRESHOLD is the size of a chunk in free()
|
||||
that triggers automatic consolidation of possibly-surrounding
|
||||
fastbin chunks. This is a heuristic, so the exact value should not
|
||||
matter too much. It is defined at half the default trim threshold as a
|
||||
compromise heuristic to only attempt consolidation if it is likely
|
||||
to lead to trimming. However, it is not dynamically tunable, since
|
||||
consolidation reduces fragmentation surrounding large chunks even
|
||||
if trimming is not used.
|
||||
*/
|
||||
#define FASTBIN_CONSOLIDATION_THRESHOLD (65536UL)
|
||||
|
||||
struct malloc_state
|
||||
{
|
||||
/* Set if the fastbin chunks contain recently inserted free blocks. */
|
||||
bool have_fastchunks;
|
||||
/* Fastbins */
|
||||
moffset fastbins[NFASTBINS];
|
||||
/* Base of the topmost chunk -- not otherwise kept in a bin */
|
||||
moffset top;
|
||||
/* The remainder from the most recent split of a small request */
|
||||
moffset last_remainder;
|
||||
/* Normal bins packed as described above */
|
||||
moffset bins[NBINS * 2 - 2];
|
||||
/* Bitmap of bins */
|
||||
unsigned int binmap[BINMAPSIZE];
|
||||
/* Reference to the root object */
|
||||
size_t root_offset;
|
||||
};
|
||||
|
||||
DB::DB(const char* pathname) {
|
||||
fd = open(pathname, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
|
||||
if (fd < 0)
|
||||
throw std::system_error(errno, std::generic_category());
|
||||
|
||||
size_t file_size = lseek(fd, 0, SEEK_END);
|
||||
|
||||
if (file_size == ((off_t) -1))
|
||||
throw std::system_error(errno, std::generic_category());
|
||||
|
||||
bool is_new = false;
|
||||
if (file_size == 0) {
|
||||
file_size = getpagesize();
|
||||
if (ftruncate(fd, file_size) < 0)
|
||||
throw std::system_error(errno, std::generic_category());
|
||||
is_new = true;
|
||||
}
|
||||
|
||||
ms = (malloc_state*)
|
||||
mmap(NULL, file_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (ms == MAP_FAILED)
|
||||
throw std::system_error(errno, std::generic_category());
|
||||
|
||||
if (is_new) {
|
||||
init_state(file_size);
|
||||
}
|
||||
|
||||
current_base = (unsigned char*) ms;
|
||||
current_db = this;
|
||||
}
|
||||
|
||||
DB::~DB() {
|
||||
size_t size =
|
||||
ms->top + size + sizeof(size_t);
|
||||
|
||||
munmap(ms,size);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
moffset DB::get_root_offset() {
|
||||
return ms->root_offset;
|
||||
}
|
||||
|
||||
void DB::set_root_offset(moffset root) {
|
||||
ms->root_offset = root;
|
||||
}
|
||||
|
||||
void
|
||||
DB::init_state(size_t size)
|
||||
{
|
||||
/* Init fastbins */
|
||||
ms->have_fastchunks = false;
|
||||
for (int i = 0; i < NFASTBINS; ++i) {
|
||||
ms->fastbins[i] = 0;
|
||||
}
|
||||
|
||||
mchunk* top_chunk =
|
||||
mem2chunk(((char*) ms) + sizeof(*ms) + sizeof(size_t));
|
||||
ms->top = ofs(ms,top_chunk);
|
||||
set_head(top_chunk, (size - sizeof(*ms)) | PREV_INUSE);
|
||||
|
||||
ms->last_remainder = 0;
|
||||
|
||||
/* Establish circular links for normal bins */
|
||||
for (int i = 1; i < NBINS; ++i) {
|
||||
mbin *bin = bin_at(ms, i);
|
||||
bin->fd = bin->bk = ofs(ms,bin);
|
||||
}
|
||||
|
||||
memset(ms->binmap, 0, sizeof(ms->binmap));
|
||||
|
||||
ms->root_offset = 0;
|
||||
}
|
||||
|
||||
/* Take a chunk off a bin list. */
|
||||
static void
|
||||
unlink_chunk (malloc_state* ms, mchunk* p)
|
||||
{
|
||||
mchunk* fd = ptr(ms,p->fd);
|
||||
mchunk* bk = ptr(ms,p->bk);
|
||||
fd->bk = ofs(ms,bk);
|
||||
bk->fd = ofs(ms,fd);
|
||||
if (!in_smallbin_range(p->mchunk_size) && p->fd_nextsize != 0) {
|
||||
if (fd->fd_nextsize == 0) {
|
||||
if (p->fd_nextsize == ofs(ms,p))
|
||||
fd->fd_nextsize = fd->bk_nextsize = ofs(ms,fd);
|
||||
else {
|
||||
fd->fd_nextsize = p->fd_nextsize;
|
||||
fd->bk_nextsize = p->bk_nextsize;
|
||||
ptr(ms,p->fd_nextsize)->bk_nextsize = ofs(ms,fd);
|
||||
ptr(ms,p->bk_nextsize)->fd_nextsize = ofs(ms,fd);
|
||||
}
|
||||
} else {
|
||||
ptr(ms,p->fd_nextsize)->bk_nextsize = p->bk_nextsize;
|
||||
ptr(ms,p->bk_nextsize)->fd_nextsize = p->fd_nextsize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
------------------------- malloc_consolidate -------------------------
|
||||
malloc_consolidate is a specialized version of free() that tears
|
||||
down chunks held in fastbins. Free itself cannot be used for this
|
||||
purpose since, among other things, it might place chunks back onto
|
||||
fastbins. So, instead, we need to use a minor variant of the same
|
||||
code.
|
||||
*/
|
||||
static void malloc_consolidate(malloc_state *ms)
|
||||
{
|
||||
moffset* fb; /* current fastbin being consolidated */
|
||||
moffset* maxfb; /* last fastbin (for loop control) */
|
||||
mchunk* p; /* current chunk being consolidated */
|
||||
mchunk* nextp; /* next chunk to consolidate */
|
||||
mchunk* unsorted_bin; /* bin header */
|
||||
mchunk* first_unsorted; /* chunk to link to */
|
||||
/* These have same use as in free() */
|
||||
mchunk* nextchunk;
|
||||
size_t size;
|
||||
size_t nextsize;
|
||||
size_t prevsize;
|
||||
int nextinuse;
|
||||
|
||||
ms->have_fastchunks = false;
|
||||
unsorted_bin = unsorted_chunks(ms);
|
||||
/*
|
||||
Remove each chunk from fast bin and consolidate it, placing it
|
||||
then in unsorted bin. Among other reasons for doing this,
|
||||
placing in unsorted bin avoids needing to calculate actual bins
|
||||
until malloc is sure that chunks aren't immediately going to be
|
||||
reused anyway.
|
||||
*/
|
||||
maxfb = &ms->fastbins[NFASTBINS - 1];
|
||||
fb = &ms->fastbins[0];
|
||||
do {
|
||||
p = ptr(ms,*fb);
|
||||
*fb = 0;
|
||||
if (p != NULL) {
|
||||
do {
|
||||
nextp = ptr(ms,p->fd);
|
||||
/* Slightly streamlined version of consolidation code in free() */
|
||||
size = chunksize(p);
|
||||
nextchunk = chunk_at_offset(p, size);
|
||||
nextsize = chunksize(nextchunk);
|
||||
if (!prev_inuse(p)) {
|
||||
prevsize = prev_size(p);
|
||||
size += prevsize;
|
||||
p = chunk_at_offset(p, -((long) prevsize));
|
||||
unlink_chunk (ms, p);
|
||||
}
|
||||
if (nextchunk != ptr(ms,ms->top)) {
|
||||
nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
|
||||
if (!nextinuse) {
|
||||
size += nextsize;
|
||||
unlink_chunk (ms, nextchunk);
|
||||
} else
|
||||
clear_inuse_bit_at_offset(nextchunk, 0);
|
||||
first_unsorted = ptr(ms,unsorted_bin->fd);
|
||||
unsorted_bin->fd = ofs(ms,p);
|
||||
first_unsorted->bk = ofs(ms,p);
|
||||
if (!in_smallbin_range(size)) {
|
||||
p->fd_nextsize = 0;
|
||||
p->bk_nextsize = 0;
|
||||
}
|
||||
set_head(p, size | PREV_INUSE);
|
||||
p->bk = ofs(ms,unsorted_bin);
|
||||
p->fd = ofs(ms,first_unsorted);
|
||||
set_foot(p, size);
|
||||
} else {
|
||||
size += nextsize;
|
||||
set_head(p, size | PREV_INUSE);
|
||||
ms->top = ofs(ms,p);
|
||||
}
|
||||
} while ((p = nextp) != 0);
|
||||
}
|
||||
} while (fb++ != maxfb);
|
||||
}
|
||||
|
||||
moffset
|
||||
DB::malloc(size_t bytes)
|
||||
{
|
||||
unsigned int idx; /* associated bin index */
|
||||
mbin* bin; /* associated bin */
|
||||
mchunk* victim; /* inspected/selected chunk */
|
||||
|
||||
mchunk* remainder; /* remainder from a split */
|
||||
unsigned long remainder_size; /* its size */
|
||||
|
||||
/*
|
||||
Convert request size to internal form by adding SIZE_SZ bytes
|
||||
overhead plus possibly more to obtain necessary alignment and/or
|
||||
to obtain a size of at least MINSIZE, the smallest allocatable
|
||||
size. Also, checked_request2size traps (returning 0) request sizes
|
||||
that are so large that they wrap around zero when padded and
|
||||
aligned.
|
||||
*/
|
||||
size_t nb = request2size(bytes);
|
||||
|
||||
if (nb <= DEFAULT_MXFAST) {
|
||||
idx = fastbin_index(nb);
|
||||
|
||||
if (ms->fastbins[idx] != 0) {
|
||||
victim = ptr(ms,ms->fastbins[idx]);
|
||||
ms->fastbins[idx] = victim->fd;
|
||||
return ofs(ms,chunk2mem(victim));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
If a small request, check regular bin. Since these "smallbins"
|
||||
hold one size each, no searching within bins is necessary.
|
||||
(For a large request, we need to wait until unsorted chunks are
|
||||
processed to find best fit. But for small ones, fits are exact
|
||||
anyway, so we can check now, which is faster.)
|
||||
*/
|
||||
if (in_smallbin_range (nb)) {
|
||||
idx = smallbin_index (nb);
|
||||
bin = bin_at (ms, idx);
|
||||
if ((victim = ptr(ms,last(bin))) != bin)
|
||||
{
|
||||
moffset bck = victim->bk;
|
||||
set_inuse_bit_at_offset (victim, nb);
|
||||
bin->bk = bck;
|
||||
ptr(ms,bck)->fd = ofs(ms,bin);
|
||||
return ofs(ms,chunk2mem(victim));
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
If this is a large request, consolidate fastbins before continuing.
|
||||
While it might look excessive to kill all fastbins before
|
||||
even seeing if there is space available, this avoids
|
||||
fragmentation problems normally associated with fastbins.
|
||||
Also, in practice, programs tend to have runs of either small or
|
||||
large requests, but less often mixtures, so consolidation is not
|
||||
invoked all that often in most programs. And the programs that
|
||||
it is called frequently in otherwise tend to fragment.
|
||||
*/
|
||||
|
||||
idx = largebin_index(nb);
|
||||
if (ms->have_fastchunks)
|
||||
malloc_consolidate(ms);
|
||||
}
|
||||
|
||||
/*
|
||||
Process recently freed or remaindered chunks, taking one only if
|
||||
it is exact fit, or, if this a small request, the chunk is remainder from
|
||||
the most recent non-exact fit. Place other traversed chunks in
|
||||
bins. Note that this step is the only place in any routine where
|
||||
chunks are placed in bins.
|
||||
The outer loop here is needed because we might not realize until
|
||||
near the end of malloc that we should have consolidated, so must
|
||||
do so and retry. This happens at most once, and only when we would
|
||||
otherwise need to expand memory to service a "small" request.
|
||||
*/
|
||||
for (;;)
|
||||
{
|
||||
size_t size;
|
||||
mchunk *fwd, *bck;
|
||||
|
||||
int iters = 0;
|
||||
while ((victim = ptr(ms,unsorted_chunks(ms)->bk)) != unsorted_chunks(ms)) {
|
||||
bck = ptr(ms,victim->bk);
|
||||
size = chunksize(victim);
|
||||
mchunk *next = chunk_at_offset(victim, size);
|
||||
|
||||
/*
|
||||
If a small request, try to use last remainder if it is the
|
||||
only chunk in unsorted bin. This helps promote locality for
|
||||
runs of consecutive small requests. This is the only
|
||||
exception to best-fit, and applies only when there is
|
||||
no exact fit for a small chunk.
|
||||
*/
|
||||
|
||||
if (in_smallbin_range(nb) &&
|
||||
bck == unsorted_chunks(ms) &&
|
||||
victim == ptr(ms,ms->last_remainder) &&
|
||||
(unsigned long) (size) > (unsigned long) (nb + MINSIZE)) {
|
||||
|
||||
/* split and reattach remainder */
|
||||
remainder_size = size - nb;
|
||||
remainder = chunk_at_offset(victim, nb);
|
||||
ms->last_remainder =
|
||||
unsorted_chunks(ms)->bk =
|
||||
unsorted_chunks(ms)->fd = ofs(ms,remainder);
|
||||
remainder->bk = remainder->fd = ofs(ms,unsorted_chunks(ms));
|
||||
if (!in_smallbin_range(remainder_size)) {
|
||||
remainder->fd_nextsize = 0;
|
||||
remainder->bk_nextsize = 0;
|
||||
}
|
||||
set_head(victim, nb | PREV_INUSE);
|
||||
set_head(remainder, remainder_size | PREV_INUSE);
|
||||
set_foot(remainder, remainder_size);
|
||||
return ofs(ms,chunk2mem(victim));
|
||||
}
|
||||
|
||||
/* remove from unsorted list */
|
||||
unsorted_chunks(ms)->bk = ofs(ms,bck);
|
||||
bck->fd = ofs(ms,unsorted_chunks(ms));
|
||||
|
||||
/* Take now instead of binning if exact fit */
|
||||
if (size == nb) {
|
||||
set_inuse_bit_at_offset(victim, size);
|
||||
return ofs(ms,chunk2mem(victim));
|
||||
}
|
||||
|
||||
/* place chunk in bin */
|
||||
size_t victim_index;
|
||||
if (in_smallbin_range(size)) {
|
||||
victim_index = smallbin_index(size);
|
||||
bck = bin_at(ms, victim_index);
|
||||
fwd = ptr(ms,bck->fd);
|
||||
} else {
|
||||
victim_index = largebin_index(size);
|
||||
bck = bin_at(ms, victim_index);
|
||||
fwd = ptr(ms,bck->fd);
|
||||
|
||||
/* maintain large bins in sorted order */
|
||||
if (fwd != bck) {
|
||||
/* Or with inuse bit to speed comparisons */
|
||||
size |= PREV_INUSE;
|
||||
/* if smaller than smallest, bypass loop below */
|
||||
if ((unsigned long) (size) < (unsigned long) ptr(ms,bck->bk)->mchunk_size) {
|
||||
fwd = bck;
|
||||
bck = ptr(ms,bck->bk);
|
||||
victim->fd_nextsize = fwd->fd;
|
||||
victim->bk_nextsize = ptr(ms,fwd->fd)->bk_nextsize;
|
||||
ptr(ms,fwd->fd)->bk_nextsize = ptr(ms,victim->bk_nextsize)->fd_nextsize = ofs(ms,victim);
|
||||
} else {
|
||||
while ((unsigned long) size < fwd->mchunk_size) {
|
||||
fwd = ptr(ms,fwd->fd_nextsize);
|
||||
}
|
||||
if ((unsigned long) size == (unsigned long) fwd->mchunk_size)
|
||||
/* Always insert in the second position. */
|
||||
fwd = ptr(ms,fwd->fd);
|
||||
else {
|
||||
victim->fd_nextsize = ofs(ms,fwd);
|
||||
victim->bk_nextsize = fwd->bk_nextsize;
|
||||
fwd->bk_nextsize = ofs(ms,victim);
|
||||
ptr(ms,victim->bk_nextsize)->fd_nextsize = ofs(ms,victim);
|
||||
}
|
||||
bck = ptr(ms,fwd->bk);
|
||||
}
|
||||
} else {
|
||||
victim->fd_nextsize = victim->bk_nextsize = ofs(ms,victim);
|
||||
}
|
||||
}
|
||||
|
||||
mark_bin(ms, victim_index);
|
||||
victim->bk = ofs(ms,bck);
|
||||
victim->fd = ofs(ms,fwd);
|
||||
fwd->bk = ofs(ms,victim);
|
||||
bck->fd = ofs(ms,victim);
|
||||
|
||||
#define MAX_ITERS 10000
|
||||
if (++iters >= MAX_ITERS)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
If a large request, scan through the chunks of current bin in
|
||||
sorted order to find smallest that fits. Use the skip list for this.
|
||||
*/
|
||||
if (!in_smallbin_range(nb)) {
|
||||
bin = bin_at(ms, idx);
|
||||
|
||||
/* skip scan if empty or largest chunk is too small */
|
||||
if ((victim = ptr(ms,first(bin))) != bin &&
|
||||
(unsigned long) victim->mchunk_size >= (unsigned long) (nb)) {
|
||||
size_t size;
|
||||
|
||||
victim = ptr(ms,victim->bk_nextsize);
|
||||
while (((unsigned long) (size = chunksize(victim)) <
|
||||
(unsigned long) (nb)))
|
||||
victim = ptr(ms,victim->bk_nextsize);
|
||||
|
||||
/* Avoid removing the first entry for a size so that the skip
|
||||
list does not have to be rerouted. */
|
||||
if (victim != ptr(ms,last(bin)) &&
|
||||
victim->mchunk_size == ptr(ms,victim->fd)->mchunk_size)
|
||||
victim = ptr(ms,victim->fd);
|
||||
|
||||
remainder_size = size - nb;
|
||||
unlink_chunk(ms, victim);
|
||||
|
||||
/* Exhaust */
|
||||
if (remainder_size < MINSIZE) {
|
||||
set_inuse_bit_at_offset(victim, size);
|
||||
} else { /* Split */
|
||||
remainder = chunk_at_offset(victim, nb);
|
||||
|
||||
/* We cannot assume the unsorted list is empty and therefore
|
||||
have to perform a complete insert here. */
|
||||
bck = unsorted_chunks(ms);
|
||||
fwd = ptr(ms,bck->fd);
|
||||
remainder->bk = ofs(ms,bck);
|
||||
remainder->fd = ofs(ms,fwd);
|
||||
bck->fd = fwd->bk = ofs(ms,remainder);
|
||||
if (!in_smallbin_range(remainder_size)) {
|
||||
remainder->fd_nextsize = 0;
|
||||
remainder->bk_nextsize = 0;
|
||||
}
|
||||
set_head (victim, nb | PREV_INUSE);
|
||||
set_head (remainder, remainder_size | PREV_INUSE);
|
||||
set_foot (remainder, remainder_size);
|
||||
}
|
||||
return ofs(ms,chunk2mem(victim));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Search for a chunk by scanning bins, starting with next largest
|
||||
bin. This search is strictly by best-fit; i.e., the smallest
|
||||
(with ties going to approximately the least recently used) chunk
|
||||
that fits is selected.
|
||||
The bitmap avoids needing to check that most blocks are nonempty.
|
||||
The particular case of skipping all bins during warm-up phases
|
||||
when no chunks have been returned yet is faster than it might look.
|
||||
*/
|
||||
|
||||
++idx;
|
||||
bin = bin_at(ms, idx);
|
||||
unsigned int block = idx2block(idx);
|
||||
unsigned int map = ms->binmap[block];
|
||||
unsigned int bit = idx2bit(idx);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/* Skip rest of block if there are no more set bits in this block. */
|
||||
if (bit > map || bit == 0) {
|
||||
do {
|
||||
if (++block >= BINMAPSIZE) /* out of bins */
|
||||
goto use_top;
|
||||
} while ((map = ms->binmap[block]) == 0);
|
||||
bin = bin_at(ms, (block << BINMAPSHIFT));
|
||||
bit = 1;
|
||||
}
|
||||
|
||||
/* Advance to bin with set bit. There must be one. */
|
||||
while ((bit & map) == 0) {
|
||||
bin = next_bin(bin);
|
||||
bit <<= 1;
|
||||
}
|
||||
/* Inspect the bin. It is likely to be non-empty */
|
||||
victim = ptr(ms,last(bin));
|
||||
/* If a false alarm (empty bin), clear the bit. */
|
||||
if (victim == bin) {
|
||||
ms->binmap[block] = map &= ~bit; /* Write through */
|
||||
bin = next_bin(bin);
|
||||
bit <<= 1;
|
||||
} else {
|
||||
size = chunksize(victim);
|
||||
/* We know the first chunk in this bin is big enough to use. */
|
||||
remainder_size = size - nb;
|
||||
/* unlink */
|
||||
unlink_chunk (ms, victim);
|
||||
/* Exhaust */
|
||||
if (remainder_size < MINSIZE) {
|
||||
set_inuse_bit_at_offset(victim, size);
|
||||
} else { /* Split */
|
||||
remainder = chunk_at_offset(victim, nb);
|
||||
/* We cannot assume the unsorted list is empty and therefore
|
||||
have to perform a complete insert here. */
|
||||
bck = unsorted_chunks(ms);
|
||||
fwd = ptr(ms,bck->fd);
|
||||
remainder->bk = ofs(ms,bck);
|
||||
remainder->fd = ofs(ms,fwd);
|
||||
bck->fd = fwd->bk = ofs(ms,remainder);
|
||||
|
||||
/* advertise as last remainder */
|
||||
if (in_smallbin_range(nb))
|
||||
ms->last_remainder = ofs(ms,remainder);
|
||||
if (!in_smallbin_range(remainder_size)) {
|
||||
remainder->fd_nextsize = 0;
|
||||
remainder->bk_nextsize = 0;
|
||||
}
|
||||
set_head (victim, nb | PREV_INUSE);
|
||||
set_head (remainder, remainder_size | PREV_INUSE);
|
||||
set_foot (remainder, remainder_size);
|
||||
}
|
||||
return ofs(ms,chunk2mem(victim));
|
||||
}
|
||||
}
|
||||
|
||||
use_top:
|
||||
/*
|
||||
If large enough, split off the chunk bordering the end of memory
|
||||
(held in ms->top). Note that this is in accord with the best-fit
|
||||
search rule. In effect, ms->top is treated as larger (and thus
|
||||
less well fitting) than any other available chunk since it can
|
||||
be extended to be as large as necessary (up to system
|
||||
limitations).
|
||||
We require that ms->top always exists (i.e., has size >=
|
||||
MINSIZE) after initialization, so if it would otherwise be
|
||||
exhausted by current request, it is replenished. (The main
|
||||
reason for ensuring it exists is that we may need MINSIZE space
|
||||
to put in fenceposts in sysmalloc.)
|
||||
*/
|
||||
victim = ptr(ms,ms->top);
|
||||
size = chunksize(victim);
|
||||
|
||||
if ((unsigned long) (size) >= (unsigned long) (nb + MINSIZE)) {
|
||||
remainder_size = size - nb;
|
||||
remainder = chunk_at_offset(victim, nb);
|
||||
ms->top = ofs(ms,remainder);
|
||||
set_head(victim, nb | PREV_INUSE);
|
||||
set_head(remainder, remainder_size | PREV_INUSE);
|
||||
return ofs(ms,chunk2mem(victim));
|
||||
} else if (ms->have_fastchunks) {
|
||||
malloc_consolidate (ms);
|
||||
/* restore original bin index */
|
||||
if (in_smallbin_range (nb))
|
||||
idx = smallbin_index (nb);
|
||||
else
|
||||
idx = largebin_index (nb);
|
||||
} else { /* Otherwise, relay to handle system-dependent cases */
|
||||
size_t page_size = getpagesize();
|
||||
size_t alloc_size =
|
||||
((nb + MINSIZE - size + page_size - 1) / page_size) * page_size;
|
||||
|
||||
size_t old_size =
|
||||
ms->top + size + sizeof(size_t);
|
||||
size_t new_size =
|
||||
old_size + alloc_size;
|
||||
|
||||
if (ftruncate(fd, new_size) < 0)
|
||||
throw std::system_error(errno, std::generic_category());
|
||||
|
||||
malloc_state* new_ms =
|
||||
(malloc_state*) mremap(ms, old_size, new_size, MREMAP_MAYMOVE);
|
||||
if (new_ms == MAP_FAILED)
|
||||
throw std::system_error(errno, std::generic_category());
|
||||
|
||||
ms = new_ms;
|
||||
current_base = (unsigned char*) ms;
|
||||
|
||||
victim = ptr(ms,ms->top);
|
||||
|
||||
size += alloc_size;
|
||||
|
||||
remainder_size = size - nb;
|
||||
remainder = chunk_at_offset(victim, nb);
|
||||
ms->top = ofs(ms,remainder);
|
||||
set_head(victim, nb | PREV_INUSE);
|
||||
set_head(remainder, remainder_size | PREV_INUSE);
|
||||
return ofs(ms,chunk2mem(victim));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DB::free(moffset o)
|
||||
{
|
||||
size_t size; /* its size */
|
||||
moffset *fb; /* associated fastbin */
|
||||
mchunk *nextchunk; /* next contiguous chunk */
|
||||
size_t nextsize; /* its size */
|
||||
int nextinuse; /* true if nextchunk is used */
|
||||
size_t prevsize; /* size of previous contiguous chunk */
|
||||
mchunk* bck; /* misc temp for linking */
|
||||
mchunk* fwd; /* misc temp for linking */
|
||||
|
||||
mchunk* p = ptr(ms,o);
|
||||
size = chunksize (p);
|
||||
|
||||
|
||||
/*
|
||||
If eligible, place chunk on a fastbin so it can be found
|
||||
and used quickly in malloc.
|
||||
*/
|
||||
if ((unsigned long)(size) <= (unsigned long)(DEFAULT_MXFAST)) {
|
||||
ms->have_fastchunks = true;
|
||||
unsigned int idx = fastbin_index(size);
|
||||
fb = &ms->fastbins[idx];
|
||||
/* Atomically link P to its fastbin: P->FD = *FB; *FB = P; */
|
||||
p->fd = *fb;
|
||||
*fb = ofs(ms,p);
|
||||
} else { /* Consolidate other chunks as they arrive. */
|
||||
nextchunk = chunk_at_offset(p, size);
|
||||
nextsize = chunksize(nextchunk);
|
||||
/* consolidate backward */
|
||||
if (!prev_inuse(p)) {
|
||||
prevsize = prev_size(p);
|
||||
size += prevsize;
|
||||
p = chunk_at_offset(p, -((long) prevsize));
|
||||
unlink_chunk (ms, p);
|
||||
}
|
||||
if (nextchunk != ptr(ms,ms->top)) {
|
||||
/* get and clear inuse bit */
|
||||
nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
|
||||
/* consolidate forward */
|
||||
if (!nextinuse) {
|
||||
unlink_chunk (ms, nextchunk);
|
||||
size += nextsize;
|
||||
} else
|
||||
clear_inuse_bit_at_offset(nextchunk, 0);
|
||||
/*
|
||||
Place the chunk in unsorted chunk list. Chunks are
|
||||
not placed into regular bins until after they have
|
||||
been given one chance to be used in malloc.
|
||||
*/
|
||||
bck = unsorted_chunks(ms);
|
||||
fwd = ptr(ms,bck->fd);
|
||||
p->fd = ofs(ms,fwd);
|
||||
p->bk = ofs(ms,bck);
|
||||
if (!in_smallbin_range(size)) {
|
||||
p->fd_nextsize = 0;
|
||||
p->bk_nextsize = 0;
|
||||
}
|
||||
bck->fd = ofs(ms,p);
|
||||
fwd->bk = ofs(ms,p);
|
||||
set_head(p, size | PREV_INUSE);
|
||||
set_foot(p, size);
|
||||
} else {
|
||||
/*
|
||||
If the chunk borders the current high end of memory,
|
||||
consolidate into top
|
||||
*/
|
||||
|
||||
size += nextsize;
|
||||
set_head(p, size | PREV_INUSE);
|
||||
ms->top = ofs(ms,p);
|
||||
}
|
||||
|
||||
/*
|
||||
If freeing a large space, consolidate possibly-surrounding
|
||||
chunks. Then, if the total unused topmost memory exceeds trim
|
||||
threshold, ask malloc_trim to reduce top.
|
||||
Unless max_fast is 0, we don't know if there are fastbins
|
||||
bordering top, so we cannot tell for sure whether threshold
|
||||
has been reached unless fastbins are consolidated. But we
|
||||
don't want to consolidate on each free. As a compromise,
|
||||
consolidation is performed if FASTBIN_CONSOLIDATION_THRESHOLD
|
||||
is reached.
|
||||
*/
|
||||
if ((unsigned long)(size) >= FASTBIN_CONSOLIDATION_THRESHOLD) {
|
||||
if (ms->have_fastchunks)
|
||||
malloc_consolidate(ms);
|
||||
}
|
||||
}
|
||||
}
|
||||
55
src/runtime/c/db.h
Normal file
55
src/runtime/c/db.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#ifndef DB_H
|
||||
#define DB_H
|
||||
|
||||
class DB;
|
||||
|
||||
extern thread_local PGF_INTERNAL_DECL unsigned char* current_base;
|
||||
extern thread_local PGF_INTERNAL_DECL DB* current_db;
|
||||
|
||||
typedef size_t moffset;
|
||||
|
||||
struct malloc_state;
|
||||
|
||||
template<class A> class ref {
|
||||
size_t offset;
|
||||
|
||||
public:
|
||||
ref<A>() { }
|
||||
ref<A>(size_t o) { offset = o; }
|
||||
inline A* operator->() const { return (A*) (current_base+offset); }
|
||||
inline operator A*() const { return (A*) (current_base+offset); }
|
||||
inline bool operator ==(ref<A>& other) const { return offset==other->offset; }
|
||||
inline operator size_t() { return offset; }
|
||||
};
|
||||
|
||||
class PGF_INTERNAL_DECL DB {
|
||||
int fd;
|
||||
malloc_state* ms;
|
||||
|
||||
public:
|
||||
DB(const char* pathname);
|
||||
~DB();
|
||||
|
||||
template<class A> ref<A> malloc() {
|
||||
return malloc(sizeof(A));
|
||||
}
|
||||
|
||||
moffset malloc(size_t bytes);
|
||||
|
||||
template<class A> ref<A> get_root() {
|
||||
return get_root_offset();
|
||||
}
|
||||
template<class A> void set_root(ref<A> root) {
|
||||
set_root_offset(root);
|
||||
}
|
||||
|
||||
private:
|
||||
void init_state(size_t size);
|
||||
|
||||
void free(moffset o);
|
||||
|
||||
moffset get_root_offset();
|
||||
void set_root_offset(moffset root);
|
||||
};
|
||||
|
||||
#endif
|
||||
30
src/runtime/c/expr.h
Normal file
30
src/runtime/c/expr.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef EXPR_H_
|
||||
#define EXPR_H_
|
||||
|
||||
#include "variant.h"
|
||||
|
||||
// PgfLiteral
|
||||
|
||||
typedef variant PgfLiteral;
|
||||
|
||||
|
||||
typedef enum {
|
||||
PGF_LITERAL_STR,
|
||||
PGF_LITERAL_INT,
|
||||
PGF_LITERAL_FLT,
|
||||
PGF_LITERAL_NUM_TAGS
|
||||
} PgfLiteralTag;
|
||||
|
||||
typedef struct {
|
||||
char val[0]; // a flexible array that contains the value
|
||||
} PgfLiteralStr;
|
||||
|
||||
typedef struct {
|
||||
int val;
|
||||
} PgfLiteralInt;
|
||||
|
||||
typedef struct {
|
||||
double val;
|
||||
} PgfLiteralFlt;
|
||||
|
||||
#endif /* EXPR_H_ */
|
||||
@@ -1,52 +0,0 @@
|
||||
#include <gu/assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
static const char*
|
||||
gu_assert_mode_descs[] = {
|
||||
[GU_ASSERT_PRECOND] = "precondition failed",
|
||||
[GU_ASSERT_POSTCOND] = "postcondition failed",
|
||||
[GU_ASSERT_ASSERTION] = "assertion failed",
|
||||
[GU_ASSERT_NEVER] = "control should not reach here",
|
||||
};
|
||||
|
||||
GU_API void
|
||||
gu_abort_v_(GuAssertMode mode,
|
||||
const char* file, const char* func, int line,
|
||||
const char* msg_fmt, va_list args)
|
||||
{
|
||||
const char* desc = gu_assert_mode_descs[mode];
|
||||
(void) fprintf(stderr, "%s (%s:%d): %s\n", func, file, line, desc);
|
||||
if (msg_fmt != NULL) {
|
||||
(void) fputc('\t', stderr);
|
||||
(void) vfprintf(stderr, msg_fmt, args);
|
||||
(void) fputc('\n', stderr);
|
||||
}
|
||||
abort();
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_abort_(GuAssertMode mode,
|
||||
const char* file, const char* func, int line,
|
||||
const char* msg_fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, msg_fmt);
|
||||
gu_abort_v_(mode, file, func, line, msg_fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_fatal(const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
fputs("Fatal error", stderr);
|
||||
if (fmt) {
|
||||
fputs(": ", stderr);
|
||||
(void) vfprintf(stderr, fmt, args);
|
||||
}
|
||||
fputc('\n', stderr);
|
||||
abort();
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
#ifndef GU_ASSERT_H_
|
||||
#define GU_ASSERT_H_
|
||||
|
||||
#include <gu/defs.h>
|
||||
|
||||
typedef enum {
|
||||
GU_ASSERT_PRECOND,
|
||||
GU_ASSERT_ASSERTION,
|
||||
GU_ASSERT_POSTCOND,
|
||||
GU_ASSERT_NEVER
|
||||
} GuAssertMode;
|
||||
|
||||
GU_API_DECL void
|
||||
gu_abort_v_(GuAssertMode mode,
|
||||
const char* file, const char* func, int line,
|
||||
const char* msg_fmt, va_list args);
|
||||
|
||||
GU_API_DECL void
|
||||
gu_abort_(GuAssertMode mode,
|
||||
const char* file, const char* func, int line,
|
||||
const char* msg_fmt, ...);
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define gu_assertion_(mode_, expr_, ...) \
|
||||
GU_BEGIN \
|
||||
if (!(expr_)) { \
|
||||
gu_abort_(mode_, __FILE__, __func__, __LINE__, __VA_ARGS__); \
|
||||
} \
|
||||
GU_END
|
||||
#else
|
||||
// this should prevent unused variable warnings when a variable is only used
|
||||
// in an assertion
|
||||
#define gu_assertion_(mode_, expr_, ...) \
|
||||
GU_BEGIN \
|
||||
(void) (sizeof (expr_)); \
|
||||
GU_END
|
||||
#endif
|
||||
|
||||
|
||||
#define gu_require(expr) \
|
||||
gu_assertion_(GU_ASSERT_PRECOND, expr, "%s", #expr)
|
||||
|
||||
#define gu_assert_msg(expr, ...) \
|
||||
gu_assertion_(GU_ASSERT_ASSERTION, expr, __VA_ARGS__)
|
||||
|
||||
#define gu_assert(expr) \
|
||||
gu_assert_msg(expr, "%s", #expr)
|
||||
|
||||
#define gu_ensure(expr) \
|
||||
gu_assertion_(GU_ASSERT_POSTCOND, expr, "%s", #expr)
|
||||
|
||||
#define gu_impossible_msg(...) \
|
||||
gu_assertion_(GU_ASSERT_ASSERTION, false, __VA_ARGS__)
|
||||
|
||||
#define gu_impossible() \
|
||||
gu_impossible_msg(NULL)
|
||||
|
||||
GU_API_DECL void
|
||||
gu_fatal(const char* fmt, ...);
|
||||
|
||||
#endif /* GU_ASSERT_H_ */
|
||||
@@ -1,76 +0,0 @@
|
||||
#include <gu/bits.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
GU_INTERNAL unsigned
|
||||
gu_ceil2e(unsigned u)
|
||||
{
|
||||
u--;
|
||||
u |= u >> 1;
|
||||
u |= u >> 2;
|
||||
u |= u >> 4;
|
||||
u |= u >> 8;
|
||||
#if UINT_MAX > UINT16_MAX
|
||||
u |= u >> 16;
|
||||
#endif
|
||||
#if UINT_MAX > UINT32_MAX
|
||||
u |= u >> 32;
|
||||
#endif
|
||||
u++;
|
||||
return u;
|
||||
}
|
||||
|
||||
GU_INTERNAL double
|
||||
gu_decode_double(uint64_t u)
|
||||
{
|
||||
bool sign = u >> 63;
|
||||
unsigned rawexp = u >> 52 & 0x7ff;
|
||||
uint64_t mantissa = u & 0xfffffffffffff;
|
||||
double ret;
|
||||
|
||||
if (rawexp == 0x7ff) {
|
||||
ret = (mantissa == 0) ? INFINITY : NAN;
|
||||
} else {
|
||||
uint64_t m = rawexp ? 1ULL << 52 | mantissa : mantissa << 1;
|
||||
ret = ldexp((double) m, rawexp - 1075);
|
||||
}
|
||||
return sign ? copysign(ret, -1.0) : ret;
|
||||
}
|
||||
|
||||
GU_INTERNAL uint64_t
|
||||
gu_encode_double(double d)
|
||||
{
|
||||
int sign = signbit(d) > 0;
|
||||
unsigned rawexp;
|
||||
uint64_t mantissa;
|
||||
|
||||
switch (fpclassify(d)) {
|
||||
case FP_NAN:
|
||||
rawexp = 0x7ff;
|
||||
mantissa = 1;
|
||||
break;
|
||||
case FP_INFINITE:
|
||||
rawexp = 0x7ff;
|
||||
mantissa = 0;
|
||||
break;
|
||||
default: {
|
||||
int exp;
|
||||
mantissa = (uint64_t) scalbn(frexp(d, &exp), 53);
|
||||
mantissa &= ~ (1ULL << 52);
|
||||
exp -= 53;
|
||||
|
||||
rawexp = exp + 1075;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t u = (((uint64_t) sign) << 63) |
|
||||
(((uint64_t) rawexp & 0x7ff) << 52) |
|
||||
mantissa;
|
||||
|
||||
return u;
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
#ifndef GU_BITS_H_
|
||||
#define GU_BITS_H_
|
||||
|
||||
#include <gu/defs.h>
|
||||
#include <gu/assert.h>
|
||||
|
||||
|
||||
#define GU_WORD_BITS (sizeof(GuWord) * CHAR_BIT)
|
||||
|
||||
|
||||
/*
|
||||
* Based on the Bit Twiddling Hacks collection by Sean Eron Anderson
|
||||
* <http://graphics.stanford.edu/~seander/bithacks.html>
|
||||
*/
|
||||
|
||||
GU_INTERNAL_DECL
|
||||
unsigned gu_ceil2e(unsigned i);
|
||||
|
||||
static inline int
|
||||
gu_sign(int i) {
|
||||
return (i > 0) - (i < 0);
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
gu_ceildiv(size_t size, size_t div)
|
||||
{
|
||||
return (size + div - 1) / div;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
gu_aligned(uintptr_t addr, size_t alignment)
|
||||
{
|
||||
//gu_require(alignment == gu_ceil2e(alignment));
|
||||
return (addr & (alignment - 1)) == 0;
|
||||
}
|
||||
|
||||
static inline uintptr_t
|
||||
gu_align_forward(uintptr_t addr, size_t alignment) {
|
||||
//gu_require(alignment == gu_ceil2e(alignment));
|
||||
uintptr_t mask = alignment - 1;
|
||||
return (addr + mask) & ~mask;
|
||||
}
|
||||
|
||||
static inline uintptr_t
|
||||
gu_align_backward(uintptr_t addr, size_t alignment) {
|
||||
//gu_require(alignment == gu_ceil2e(alignment));
|
||||
return addr & ~(alignment - 1);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
gu_bits_test(const GuWord* bitmap, int idx) {
|
||||
return !!(bitmap[idx / GU_WORD_BITS] & 1 << (idx % GU_WORD_BITS));
|
||||
}
|
||||
|
||||
static inline void
|
||||
gu_bits_set(GuWord* bitmap, int idx) {
|
||||
bitmap[idx / GU_WORD_BITS] |= ((GuWord) 1) << (idx % GU_WORD_BITS);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gu_bits_clear(GuWord* bitmap, int idx) {
|
||||
bitmap[idx / GU_WORD_BITS] &= ~(((GuWord) 1) << (idx % GU_WORD_BITS));
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
gu_bits_size(size_t n_bits) {
|
||||
return gu_ceildiv(n_bits, GU_WORD_BITS) * sizeof(GuWord);
|
||||
}
|
||||
|
||||
static inline void*
|
||||
gu_word_ptr(GuWord w)
|
||||
{
|
||||
return (void*) w;
|
||||
}
|
||||
|
||||
static inline GuWord
|
||||
gu_ptr_word(void* p)
|
||||
{
|
||||
return (GuWord) p;
|
||||
}
|
||||
|
||||
#define GuOpaque() struct { GuWord w_; }
|
||||
|
||||
typedef GuWord GuTagged;
|
||||
|
||||
#define GU_TAG_MAX (sizeof(GuWord) - 1)
|
||||
|
||||
static inline size_t
|
||||
gu_tagged_tag(GuTagged t) {
|
||||
return (int) (t & (sizeof(GuWord) - 1));
|
||||
}
|
||||
|
||||
static inline void*
|
||||
gu_tagged_ptr(GuTagged w) {
|
||||
return (void*) gu_align_backward(w, sizeof(GuWord));
|
||||
}
|
||||
|
||||
static inline GuTagged
|
||||
gu_tagged(void* ptr, size_t tag) {
|
||||
gu_require(tag < sizeof(GuWord));
|
||||
uintptr_t u = (uintptr_t) ptr;
|
||||
gu_require(gu_align_backward(u, sizeof(GuWord)) == u);
|
||||
return (GuWord) { u | tag };
|
||||
}
|
||||
|
||||
#include <gu/exn.h>
|
||||
|
||||
#define GU_DECODE_2C_(u_, t_, umax_, posmax_, tmin_, err_) \
|
||||
(((u_) <= (posmax_)) \
|
||||
? (t_) (u_) \
|
||||
: (tmin_) + ((t_) ((umax_) - (u_))) < 0 \
|
||||
? (t_) (-1 - ((t_) ((umax_) - (u_)))) \
|
||||
: (t_) (gu_raise(err_, GuIntDecodeExn), -1))
|
||||
|
||||
|
||||
static inline int8_t
|
||||
gu_decode_2c8(uint8_t u, GuExn* err)
|
||||
{
|
||||
return GU_DECODE_2C_(u, int8_t, UINT8_C(0xff),
|
||||
UINT8_C(0x7f), INT8_MIN, err);
|
||||
}
|
||||
|
||||
static inline int16_t
|
||||
gu_decode_2c16(uint16_t u, GuExn* err)
|
||||
{
|
||||
return GU_DECODE_2C_(u, int16_t, UINT16_C(0xffff),
|
||||
UINT16_C(0x7fff), INT16_MIN, err);
|
||||
}
|
||||
|
||||
static inline int32_t
|
||||
gu_decode_2c32(uint32_t u, GuExn* err)
|
||||
{
|
||||
return GU_DECODE_2C_(u, int32_t, UINT32_C(0xffffffff),
|
||||
UINT32_C(0x7fffffff), INT32_MIN, err);
|
||||
}
|
||||
|
||||
static inline int64_t
|
||||
gu_decode_2c64(uint64_t u, GuExn* err)
|
||||
{
|
||||
return GU_DECODE_2C_(u, int64_t, UINT64_C(0xffffffffffffffff),
|
||||
UINT64_C(0x7fffffffffffffff), INT64_MIN, err);
|
||||
}
|
||||
|
||||
GU_INTERNAL_DECL double
|
||||
gu_decode_double(uint64_t u);
|
||||
|
||||
GU_INTERNAL_DECL uint64_t
|
||||
gu_encode_double(double d);
|
||||
|
||||
#endif // GU_BITS_H_
|
||||
@@ -1,68 +0,0 @@
|
||||
#include <gu/choice.h>
|
||||
#include <gu/seq.h>
|
||||
#include <gu/assert.h>
|
||||
|
||||
struct GuChoice {
|
||||
GuBuf* path;
|
||||
size_t path_idx;
|
||||
};
|
||||
|
||||
GU_API GuChoice*
|
||||
gu_new_choice(GuPool* pool)
|
||||
{
|
||||
GuChoice* ch = gu_new(GuChoice, pool);
|
||||
ch->path = gu_new_buf(size_t, pool);
|
||||
ch->path_idx = 0;
|
||||
return ch;
|
||||
}
|
||||
|
||||
GU_API GuChoiceMark
|
||||
gu_choice_mark(GuChoice* ch)
|
||||
{
|
||||
gu_assert(ch->path_idx <= gu_buf_length(ch->path));
|
||||
return (GuChoiceMark){ch->path_idx};
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_choice_reset(GuChoice* ch, GuChoiceMark mark)
|
||||
{
|
||||
gu_assert(ch->path_idx <= gu_buf_length(ch->path));
|
||||
gu_require(mark.path_idx <= ch->path_idx );
|
||||
ch->path_idx = mark.path_idx;
|
||||
}
|
||||
|
||||
GU_API int
|
||||
gu_choice_next(GuChoice* ch, int n_choices)
|
||||
{
|
||||
gu_assert(n_choices >= 0);
|
||||
gu_assert(ch->path_idx <= gu_buf_length(ch->path));
|
||||
if (n_choices == 0) {
|
||||
return -1;
|
||||
}
|
||||
int i = 0;
|
||||
if (gu_buf_length(ch->path) > ch->path_idx) {
|
||||
i = (int) gu_buf_get(ch->path, size_t, ch->path_idx);
|
||||
gu_assert(i <= n_choices);
|
||||
} else {
|
||||
gu_buf_push(ch->path, size_t, n_choices);
|
||||
i = n_choices;
|
||||
}
|
||||
int ret = (i == 0) ? -1 : n_choices - i;
|
||||
ch->path_idx++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
GU_API bool
|
||||
gu_choice_advance(GuChoice* ch)
|
||||
{
|
||||
gu_assert(ch->path_idx <= gu_buf_length(ch->path));
|
||||
|
||||
while (gu_buf_length(ch->path) > ch->path_idx) {
|
||||
size_t last = gu_buf_pop(ch->path, size_t);
|
||||
if (last > 1) {
|
||||
gu_buf_push(ch->path, size_t, last-1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
#ifndef GU_CHOICE_H_
|
||||
#define GU_CHOICE_H_
|
||||
|
||||
#include <gu/mem.h>
|
||||
|
||||
typedef struct GuChoice GuChoice;
|
||||
|
||||
typedef struct GuChoiceMark GuChoiceMark;
|
||||
|
||||
GU_API_DECL GuChoice*
|
||||
gu_new_choice(GuPool* pool);
|
||||
|
||||
GU_API_DECL int
|
||||
gu_choice_next(GuChoice* ch, int n_choices);
|
||||
|
||||
GU_API_DECL GuChoiceMark
|
||||
gu_choice_mark(GuChoice* ch);
|
||||
|
||||
GU_API_DECL void
|
||||
gu_choice_reset(GuChoice* ch, GuChoiceMark mark);
|
||||
|
||||
GU_API_DECL bool
|
||||
gu_choice_advance(GuChoice* ch);
|
||||
|
||||
|
||||
// private
|
||||
|
||||
struct GuChoiceMark {
|
||||
size_t path_idx;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // GU_CHOICE_H_
|
||||
@@ -1,4 +0,0 @@
|
||||
#include <gu/defs.h>
|
||||
|
||||
void* const gu_null = NULL;
|
||||
GU_API GuStruct* const gu_null_struct = NULL;
|
||||
@@ -1,227 +0,0 @@
|
||||
/** @file
|
||||
*
|
||||
* Miscellaneous macros.
|
||||
*/
|
||||
|
||||
#ifndef GU_DEFS_H_
|
||||
#define GU_DEFS_H_
|
||||
|
||||
// MSVC requires explicit export/import of
|
||||
// symbols in DLLs. CMake takes care of this
|
||||
// for functions, but not for data/variables.
|
||||
#if defined(_MSC_VER)
|
||||
#if defined(COMPILING_GU)
|
||||
#define GU_API_DECL __declspec(dllexport)
|
||||
#define GU_API __declspec(dllexport)
|
||||
#else
|
||||
#define GU_API_DECL __declspec(dllimport)
|
||||
#define GU_API ERROR_NOT_COMPILING_LIBGU
|
||||
#endif
|
||||
|
||||
#define GU_INTERNAL_DECL
|
||||
#define GU_INTERNAL
|
||||
|
||||
#define restrict __restrict
|
||||
|
||||
#else
|
||||
|
||||
#define GU_API_DECL
|
||||
#define GU_API
|
||||
|
||||
#define GU_INTERNAL_DECL __attribute__ ((visibility ("hidden")))
|
||||
#define GU_INTERNAL __attribute__ ((visibility ("hidden")))
|
||||
#endif
|
||||
// end MSVC workaround
|
||||
|
||||
#include <stddef.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <gu/sysdeps.h>
|
||||
|
||||
#define gu_container(mem_p, container_type, member) \
|
||||
((container_type*)(((uint8_t*) (mem_p)) - offsetof(container_type, member)))
|
||||
/**< Find the address of a containing structure.
|
||||
*
|
||||
* If @c s has type @c t*, where @c t is a struct or union type with a
|
||||
* member @m, then <tt>GU_CONTAINER_P(&s->m, t, m) == s</tt>.
|
||||
*
|
||||
* @param mem_p Pointer to the member of a structure.
|
||||
* @param container_type The type of the containing structure.
|
||||
* @param member The name of the member of @a container_type
|
||||
* @return The address of the containing structure.
|
||||
*
|
||||
* @hideinitializer */
|
||||
|
||||
|
||||
#define gu_member_p(struct_p_, offset_) \
|
||||
((void*)&((uint8_t*)(struct_p_))[offset_])
|
||||
|
||||
#define gu_member(t_, struct_p_, offset_) \
|
||||
(*(t_*)gu_member_p(struct_p_, offset_))
|
||||
|
||||
#ifdef GU_ALIGNOF
|
||||
# define gu_alignof GU_ALIGNOF
|
||||
#elif defined(_MSC_VER)
|
||||
# define gu_alignof __alignof
|
||||
#else
|
||||
# define gu_alignof(t_) \
|
||||
((size_t)(offsetof(struct { char c_; t_ e_; }, e_)))
|
||||
#endif
|
||||
|
||||
#define GU_PLIT(type, expr) \
|
||||
((type[1]){ expr })
|
||||
|
||||
#define GU_LVALUE(type, expr) \
|
||||
(*((type[1]){ expr }))
|
||||
|
||||
#define GU_COMMA ,
|
||||
|
||||
#define GU_ARRAY_LEN(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
#define GU_ID(...) __VA_ARGS__
|
||||
|
||||
// This trick is by Laurent Deniau <laurent.deniau@cern.ch>
|
||||
#define GU_N_ARGS(...) \
|
||||
GU_N_ARGS_(__VA_ARGS__, \
|
||||
31,30,29,28,27,26,25,24, \
|
||||
23,22,21,20,19,18,17,16, \
|
||||
15,14,13,12,11,10,9,8, \
|
||||
7,6,5,4,3,2,1,0)
|
||||
#define GU_N_ARGS_(...) GU_N_ARGS__(__VA_ARGS__)
|
||||
#define GU_N_ARGS__(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p, \
|
||||
q,r,s,t,u,v,w,x,y,z,aa,ab,ac,ad,ae,N,...) \
|
||||
N
|
||||
|
||||
#define GU_ARG1(a1, ...) a1
|
||||
#define GU_ARG2(a1, a2, ...) a2
|
||||
|
||||
#define GU_BEGIN do {
|
||||
#define GU_END } while (false)
|
||||
|
||||
#define GU_NOP GU_BEGIN (void) 0; GU_END
|
||||
|
||||
/**< @hideinitializer */
|
||||
|
||||
//
|
||||
// Assert
|
||||
//
|
||||
|
||||
#define GU_MAX(a_, b_) ((a_) > (b_) ? (a_) : (b_))
|
||||
#define GU_MIN(a_, b_) ((a_) < (b_) ? (a_) : (b_))
|
||||
|
||||
static inline int
|
||||
gu_max(int a, int b) {
|
||||
return GU_MAX(a, b);
|
||||
}
|
||||
|
||||
static inline int
|
||||
gu_min(int a, int b) {
|
||||
return GU_MIN(a, b);
|
||||
}
|
||||
|
||||
#ifdef GU_ALIGNOF
|
||||
#define gu_flex_alignof gu_alignof
|
||||
#else
|
||||
#define gu_flex_alignof(t) 0
|
||||
#endif
|
||||
|
||||
static inline size_t
|
||||
gu_flex_size(size_t ssize, size_t offset, int n_elems, size_t e_size)
|
||||
{
|
||||
return GU_MAX(ssize, offset + n_elems * e_size);
|
||||
}
|
||||
|
||||
#define GU_FLEX_SIZE(type, flex_member, n_elems) \
|
||||
gu_flex_size(sizeof(type), offsetof(type, flex_member), \
|
||||
n_elems, sizeof(((type*)NULL)->flex_member[0]))
|
||||
|
||||
|
||||
// The following are directly from gmacros.h in GLib
|
||||
|
||||
#define GU_PASTE_ARGS(id1_,id2_) \
|
||||
id1_ ## id2_
|
||||
|
||||
#define GU_PASTE(id1_, id2_) \
|
||||
GU_PASTE_ARGS(id1_, id2_)
|
||||
|
||||
#define GU_STATIC_ASSERT(expr_) \
|
||||
typedef struct { \
|
||||
char static_assert[(expr_) ? 1 : -1]; \
|
||||
} GU_PASTE(GuStaticAssert_, __LINE__)
|
||||
|
||||
|
||||
#define GU_ENSURE_TYPE(T, EXPR) \
|
||||
((void)(sizeof(*(T*)NULL=(EXPR))),(EXPR))
|
||||
|
||||
#define GU_END_DECLS \
|
||||
extern void gu_dummy_(void)
|
||||
|
||||
extern void* const gu_null;
|
||||
|
||||
// Dummy struct used for generic struct pointers
|
||||
typedef struct GuStruct GuStruct;
|
||||
|
||||
GU_API_DECL extern GuStruct* const gu_null_struct;
|
||||
|
||||
typedef uintptr_t GuWord;
|
||||
|
||||
#define GU_WORD_MAX UINTPTR_MAX
|
||||
|
||||
// TODO: use max_align_t once C1X is supported
|
||||
typedef union {
|
||||
char c;
|
||||
short s;
|
||||
int i;
|
||||
long l;
|
||||
long long ll;
|
||||
intmax_t im;
|
||||
float f;
|
||||
double d;
|
||||
long double ld;
|
||||
void* p;
|
||||
void (*fp)();
|
||||
} GuMaxAlign;
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <malloc.h>
|
||||
#define gu_alloca(N) alloca(N)
|
||||
#else
|
||||
#define gu_alloca(N) \
|
||||
(((union { GuMaxAlign align_; uint8_t buf_[N]; }){{0}}).buf_)
|
||||
#endif
|
||||
|
||||
// For Doxygen
|
||||
#define GU_PRIVATE /** @private */
|
||||
|
||||
#ifdef GU_GNUC
|
||||
# define GU_LIKELY(EXPR) __builtin_expect(EXPR, 1)
|
||||
# define GU_UNLIKELY(EXPR) __builtin_expect(EXPR, 0)
|
||||
# define GU_IS_CONSTANT(EXPR) __builtin_constant_p(EXPR)
|
||||
#else
|
||||
# define GU_LIKELY(EXPR) (EXPR)
|
||||
# define GU_UNLIKELY(EXPR) (EXPR)
|
||||
# ifdef GU_OPTIMIZE_SIZE
|
||||
# define GU_IS_CONSTANT(EXPR) false
|
||||
# else
|
||||
# define GU_IS_CONSTANT(EXPR) true
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// Splint annotations
|
||||
#define GU_ONLY GU_SPLINT(only)
|
||||
#define GU_NULL GU_SPLINT(null)
|
||||
#define GU_NOTNULL GU_SPLINT(notnull)
|
||||
#define GU_RETURNED GU_SPLINT(returned)
|
||||
#define GU_ABSTRACT GU_SPLINT(abstract)
|
||||
#define GU_IMMUTABLE GU_SPLINT(immutable)
|
||||
#define GU_NOTREACHED GU_SPLINT(notreached)
|
||||
#define GU_UNUSED GU_SPLINT(unused) GU_GNUC_ATTR(unused)
|
||||
#define GU_OUT GU_SPLINT(out)
|
||||
#define GU_IN GU_SPLINT(in)
|
||||
#define GU_NORETURN GU_SPLINT(noreturn) GU_GNUC_ATTR(noreturn)
|
||||
#define GU_MODIFIES(x) GU_SPLINT(modifies x)
|
||||
|
||||
#endif // GU_DEFS_H_
|
||||
@@ -1,7 +0,0 @@
|
||||
#include <gu/enum.h>
|
||||
|
||||
GU_API void
|
||||
gu_enum_next(GuEnum* en, void* to, GuPool* pool)
|
||||
{
|
||||
en->next(en, to, pool);
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
#ifndef GU_ENUM_H_
|
||||
#define GU_ENUM_H_
|
||||
|
||||
#include <gu/mem.h>
|
||||
|
||||
typedef struct GuEnum GuEnum;
|
||||
|
||||
struct GuEnum {
|
||||
void (*next)(GuEnum* self, void* to, GuPool* pool);
|
||||
};
|
||||
|
||||
GU_API_DECL void
|
||||
gu_enum_next(GuEnum* en, void* to, GuPool* pool);
|
||||
|
||||
#ifdef GU_GNUC
|
||||
|
||||
#define gu_next(ENUM, T, POOL) \
|
||||
({ \
|
||||
T gu_next_tmp_; \
|
||||
gu_enum_next((ENUM), &gu_next_tmp_, (POOL)); \
|
||||
gu_next_tmp_; \
|
||||
})
|
||||
#else
|
||||
static inline void*
|
||||
gu_enum_next_(GuEnum* en, void* to, GuPool* pool)
|
||||
{
|
||||
gu_enum_next(en, to, pool);
|
||||
return to;
|
||||
}
|
||||
#define gu_next(ENUM, T, POOL) \
|
||||
(*(T*)gu_enum_next_((ENUM), &(T){0}, (POOL)))
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* GU_ENUM_H_ */
|
||||
@@ -1,78 +0,0 @@
|
||||
#include <gu/exn.h>
|
||||
#include <gu/assert.h>
|
||||
|
||||
|
||||
GU_API GuExn*
|
||||
gu_new_exn(GuPool* pool)
|
||||
{
|
||||
GuExn* exn = gu_new(GuExn, pool);
|
||||
exn->state = GU_EXN_OK;
|
||||
exn->caught = NULL;
|
||||
exn->data.pool = pool;
|
||||
exn->data.data = NULL;
|
||||
return exn;
|
||||
}
|
||||
|
||||
GU_API bool
|
||||
gu_exn_is_raised(GuExn* err) {
|
||||
return err && (err->state == GU_EXN_RAISED);
|
||||
}
|
||||
|
||||
GU_API bool
|
||||
gu_exn_caught_(GuExn* err, const char* type)
|
||||
{
|
||||
return (err->caught && strcmp(err->caught, type) == 0);
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_exn_block(GuExn* err)
|
||||
{
|
||||
if (err && err->state == GU_EXN_RAISED) {
|
||||
err->state = GU_EXN_BLOCKED;
|
||||
}
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_exn_unblock(GuExn* err)
|
||||
{
|
||||
if (err && err->state == GU_EXN_BLOCKED) {
|
||||
err->state = GU_EXN_RAISED;
|
||||
}
|
||||
}
|
||||
|
||||
GU_API GuExnData*
|
||||
gu_exn_raise_debug_(GuExn* err, const char* type,
|
||||
const char* filename, const char* func, int lineno)
|
||||
{
|
||||
gu_require(type);
|
||||
|
||||
GuExnState old_state = err->state;
|
||||
err->state = GU_EXN_RAISED;
|
||||
if (old_state == GU_EXN_OK) {
|
||||
err->caught = type;
|
||||
if (err->data.pool) {
|
||||
return &err->data;
|
||||
}
|
||||
}
|
||||
|
||||
// Exceptian had already been raised, possibly blocked, or no
|
||||
// exception value is required.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GU_API GuExnData*
|
||||
gu_exn_raise_(GuExn* base, const char* type)
|
||||
{
|
||||
return gu_exn_raise_debug_(base, type, NULL, NULL, -1);
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_raise_errno(GuExn* err)
|
||||
{
|
||||
GuExnData* err_data = gu_raise(err, GuErrno);
|
||||
if (err_data) {
|
||||
GuErrno* gu_errno = gu_new(GuErrno, err_data->pool);
|
||||
*gu_errno = errno;
|
||||
err_data->data = gu_errno;
|
||||
}
|
||||
}
|
||||
@@ -1,171 +0,0 @@
|
||||
#ifndef GU_EXN_H_
|
||||
#define GU_EXN_H_
|
||||
|
||||
#include <gu/mem.h>
|
||||
|
||||
/** @file
|
||||
*
|
||||
* @defgroup GuExn Exceptions
|
||||
* Defined in <gu/exn.h>.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/// An exception frame.
|
||||
typedef struct GuExn GuExn;
|
||||
|
||||
/// @private
|
||||
typedef enum {
|
||||
GU_EXN_RAISED,
|
||||
GU_EXN_OK,
|
||||
GU_EXN_BLOCKED
|
||||
} GuExnState;
|
||||
|
||||
typedef struct GuExnData GuExnData;
|
||||
|
||||
/// A structure for storing exception values.
|
||||
struct GuExnData
|
||||
/**
|
||||
* When an exception is raised, if there is an associated value, it
|
||||
* must be allocated from a pool that still exists when control
|
||||
* returns to the handler of that exception. This structure is used to
|
||||
* communicate the exception from the raiser to the handler: the
|
||||
* handler sets #pool when setting up the exception frame, and the
|
||||
* raiser uses that pool to allocate the value and stores that in
|
||||
* #data. When control returns to the handler, it reads the value from
|
||||
* there.
|
||||
*/
|
||||
{
|
||||
|
||||
/// The pool that the exception value should be allocated from.
|
||||
GuPool* pool;
|
||||
|
||||
/// The exception value.
|
||||
void* data;
|
||||
};
|
||||
|
||||
struct GuExn {
|
||||
/// @privatesection
|
||||
GuExnState state;
|
||||
const char* caught;
|
||||
GuExnData data;
|
||||
};
|
||||
|
||||
|
||||
/// @name Creating exception frames
|
||||
//@{
|
||||
|
||||
|
||||
/// Allocate a new local exception frame.
|
||||
#define gu_exn(pool_) &(GuExn){ \
|
||||
.state = GU_EXN_OK, \
|
||||
.caught = NULL, \
|
||||
.data = {.pool = pool_, .data = NULL} \
|
||||
}
|
||||
|
||||
|
||||
/// Allocate a new exception frame.
|
||||
GU_API_DECL GuExn*
|
||||
gu_new_exn(GuPool* pool);
|
||||
|
||||
|
||||
GU_API_DECL bool
|
||||
gu_exn_is_raised(GuExn* err);
|
||||
|
||||
static inline void
|
||||
gu_exn_clear(GuExn* err) {
|
||||
err->caught = NULL;
|
||||
err->state = GU_EXN_OK;
|
||||
}
|
||||
|
||||
#define gu_exn_caught(err, type) \
|
||||
(err->caught && strcmp(err->caught, #type) == 0)
|
||||
|
||||
GU_API_DECL bool
|
||||
gu_exn_caught_(GuExn* err, const char* type);
|
||||
|
||||
static inline const void*
|
||||
gu_exn_caught_data(GuExn* err)
|
||||
{
|
||||
return err->data.data;
|
||||
}
|
||||
|
||||
/// Temporarily block a raised exception.
|
||||
GU_API_DECL void
|
||||
gu_exn_block(GuExn* err);
|
||||
|
||||
/// Show again a blocked exception.
|
||||
GU_API_DECL void
|
||||
gu_exn_unblock(GuExn* err);
|
||||
|
||||
//@private
|
||||
GU_API_DECL GuExnData*
|
||||
gu_exn_raise_(GuExn* err, const char* type);
|
||||
|
||||
//@private
|
||||
GU_API_DECL GuExnData*
|
||||
gu_exn_raise_debug_(GuExn* err, const char* type,
|
||||
const char* filename, const char* func, int lineno);
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define gu_exn_raise(err_, type_) \
|
||||
gu_exn_raise_(err_, type_)
|
||||
#else
|
||||
#define gu_exn_raise(err_, type_) \
|
||||
gu_exn_raise_debug_(err_, type_, \
|
||||
__FILE__, __func__, __LINE__)
|
||||
#endif
|
||||
|
||||
/// Raise an exception.
|
||||
#define gu_raise(exn, T) \
|
||||
gu_exn_raise(exn, #T)
|
||||
/**<
|
||||
* @param exn The current exception frame.
|
||||
*
|
||||
* @param T The C type of the exception to raise.
|
||||
*
|
||||
* @return A #GuExnData object that can be used to store the exception value, or
|
||||
* \c NULL if no value is required.
|
||||
*
|
||||
* @note The associated #GuType object for type \p T must be visible.
|
||||
*/
|
||||
|
||||
#define gu_raise_new(error_, t_, pool_, expr_) \
|
||||
GU_BEGIN \
|
||||
GuExnData* gu_raise_err_ = gu_raise(error_, t_); \
|
||||
if (gu_raise_err_) { \
|
||||
GuPool* pool_ = gu_raise_err_->pool; \
|
||||
gu_raise_err_->data = expr_; \
|
||||
} \
|
||||
GU_END
|
||||
|
||||
/// Check the status of the current exception frame
|
||||
static inline bool
|
||||
gu_ok(GuExn* exn) {
|
||||
return !GU_UNLIKELY(gu_exn_is_raised(exn));
|
||||
}
|
||||
/**<
|
||||
* @return \c false if an exception has been raised in the frame \p exn
|
||||
* and it has not been blocked, \c true otherwise.
|
||||
*/
|
||||
|
||||
|
||||
/// Return from current function if an exception has been raised.
|
||||
#define gu_return_on_exn(exn_, retval_) \
|
||||
GU_BEGIN \
|
||||
if (gu_exn_is_raised(exn_)) return retval_; \
|
||||
GU_END
|
||||
/**<
|
||||
* @showinitializer
|
||||
*/
|
||||
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
typedef int GuErrno;
|
||||
|
||||
GU_API_DECL void
|
||||
gu_raise_errno(GuExn* err);
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif // GU_EXN_H_
|
||||
@@ -1,77 +0,0 @@
|
||||
#include <gu/file.h>
|
||||
|
||||
typedef struct GuFileOutStream GuFileOutStream;
|
||||
|
||||
struct GuFileOutStream {
|
||||
GuOutStream stream;
|
||||
FILE* file;
|
||||
};
|
||||
|
||||
static size_t
|
||||
gu_file_output(GuOutStream* stream, const uint8_t* buf, size_t len, GuExn* err)
|
||||
{
|
||||
GuFileOutStream* fos = gu_container(stream, GuFileOutStream, stream);
|
||||
errno = 0;
|
||||
size_t wrote = fwrite(buf, 1, len, fos->file);
|
||||
if (wrote < len) {
|
||||
if (ferror(fos->file)) {
|
||||
gu_raise_errno(err);
|
||||
}
|
||||
}
|
||||
return wrote;
|
||||
}
|
||||
|
||||
static void
|
||||
gu_file_flush(GuOutStream* stream, GuExn* err)
|
||||
{
|
||||
GuFileOutStream* fos = gu_container(stream, GuFileOutStream, stream);
|
||||
errno = 0;
|
||||
if (fflush(fos->file) != 0) {
|
||||
gu_raise_errno(err);
|
||||
}
|
||||
}
|
||||
|
||||
GU_API GuOut*
|
||||
gu_file_out(FILE* file, GuPool* pool)
|
||||
{
|
||||
GuFileOutStream* fos = gu_new(GuFileOutStream, pool);
|
||||
fos->stream.begin_buf = NULL;
|
||||
fos->stream.end_buf = NULL;
|
||||
fos->stream.output = gu_file_output;
|
||||
fos->stream.flush = gu_file_flush;
|
||||
fos->file = file;
|
||||
return gu_new_out(&fos->stream, pool);
|
||||
}
|
||||
|
||||
|
||||
typedef struct GuFileInStream GuFileInStream;
|
||||
|
||||
struct GuFileInStream {
|
||||
GuInStream stream;
|
||||
FILE* file;
|
||||
};
|
||||
|
||||
static size_t
|
||||
gu_file_input(GuInStream* stream, uint8_t* buf, size_t sz, GuExn* err)
|
||||
{
|
||||
GuFileInStream* fis = gu_container(stream, GuFileInStream, stream);
|
||||
errno = 0;
|
||||
size_t got = fread(buf, 1, sz, fis->file);
|
||||
if (got == 0) {
|
||||
if (ferror(fis->file)) {
|
||||
gu_raise_errno(err);
|
||||
}
|
||||
}
|
||||
return got;
|
||||
}
|
||||
|
||||
GU_API GuIn*
|
||||
gu_file_in(FILE* file, GuPool* pool)
|
||||
{
|
||||
GuFileInStream* fis = gu_new(GuFileInStream, pool);
|
||||
fis->stream.begin_buffer = NULL;
|
||||
fis->stream.end_buffer = NULL;
|
||||
fis->stream.input = gu_file_input;
|
||||
fis->file = file;
|
||||
return gu_new_in(&fis->stream, pool);
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
#ifndef GU_FILE_H_
|
||||
#define GU_FILE_H_
|
||||
|
||||
#include <gu/in.h>
|
||||
#include <gu/out.h>
|
||||
#include <stdio.h>
|
||||
|
||||
GU_API_DECL GuOut*
|
||||
gu_file_out(FILE* file, GuPool* pool);
|
||||
|
||||
GU_API_DECL GuIn*
|
||||
gu_file_in(FILE* file, GuPool* pool);
|
||||
|
||||
#endif // GU_FILE_H_
|
||||
@@ -1 +0,0 @@
|
||||
#include <gu/fun.h>
|
||||
@@ -1,71 +0,0 @@
|
||||
#ifndef GU_FUN_H_
|
||||
#define GU_FUN_H_
|
||||
|
||||
#include <gu/defs.h>
|
||||
|
||||
typedef void (*GuFn)();
|
||||
typedef void (*GuFn0)(GuFn* clo);
|
||||
typedef void (*GuFn1)(GuFn* clo, void* arg1);
|
||||
typedef void (*GuFn2)(GuFn* clo, void* arg1, void* arg2);
|
||||
|
||||
#define gu_fn(fn_) (&(GuFn){ fn_ })
|
||||
|
||||
static inline void
|
||||
gu_apply0(GuFn* fn) {
|
||||
(*fn)(fn);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gu_apply1(GuFn* fn, void* arg1) {
|
||||
(*fn)(fn, arg1);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gu_apply2(GuFn* fn, void* arg1, void* arg2) {
|
||||
(*fn)(fn, arg1, arg2);
|
||||
}
|
||||
|
||||
#define gu_apply(fn_, ...) \
|
||||
((fn_)->fn((fn_), __VA_ARGS__))
|
||||
|
||||
typedef struct GuClo0 GuClo0;
|
||||
|
||||
struct GuClo0 {
|
||||
GuFn fn;
|
||||
};
|
||||
|
||||
typedef struct GuClo1 GuClo1;
|
||||
|
||||
struct GuClo1 {
|
||||
GuFn fn;
|
||||
void *env1;
|
||||
};
|
||||
|
||||
typedef struct GuClo2 GuClo2;
|
||||
struct GuClo2 {
|
||||
GuFn fn;
|
||||
void *env1;
|
||||
void *env2;
|
||||
};
|
||||
|
||||
typedef struct GuClo3 GuClo3;
|
||||
struct GuClo3 {
|
||||
GuFn fn;
|
||||
void *env1;
|
||||
void *env2;
|
||||
void *env3;
|
||||
};
|
||||
|
||||
typedef const struct GuEquality GuEquality;
|
||||
|
||||
struct GuEquality {
|
||||
bool (*is_equal)(GuEquality* self, const void* a, const void* b);
|
||||
};
|
||||
|
||||
typedef const struct GuOrder GuOrder;
|
||||
|
||||
struct GuOrder {
|
||||
int (*compare)(GuOrder* self, const void* a, const void* b);
|
||||
};
|
||||
|
||||
#endif // GU_FUN_H_
|
||||
@@ -1,77 +0,0 @@
|
||||
#include <gu/hash.h>
|
||||
|
||||
GU_API GuHash
|
||||
gu_hash_bytes(GuHash h, const uint8_t* buf, size_t len)
|
||||
{
|
||||
for (size_t n = 0; n < len; n++) {
|
||||
h = gu_hash_byte(h, buf[n]);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
static bool
|
||||
gu_int_eq_fn(GuEquality* self, const void* p1, const void* p2)
|
||||
{
|
||||
(void) self;
|
||||
const int* ip1 = p1;
|
||||
const int* ip2 = p2;
|
||||
return *ip1 == *ip2;
|
||||
}
|
||||
|
||||
static GuHash
|
||||
gu_int_hash_fn(GuHasher* self, const void* p)
|
||||
{
|
||||
(void) self;
|
||||
return (GuHash) *(const int*) p;
|
||||
}
|
||||
|
||||
GU_API GuHasher gu_int_hasher[1] = {
|
||||
{
|
||||
{ gu_int_eq_fn },
|
||||
gu_int_hash_fn
|
||||
}
|
||||
};
|
||||
|
||||
static bool
|
||||
gu_addr_eq_fn(GuEquality* self, const void* p1, const void* p2)
|
||||
{
|
||||
(void) self;
|
||||
return (p1 == p2);
|
||||
}
|
||||
|
||||
static GuHash
|
||||
gu_addr_hash_fn(GuHasher* self, const void* p)
|
||||
{
|
||||
(void) self;
|
||||
return (GuHash) (uintptr_t) p;
|
||||
}
|
||||
|
||||
GU_API GuHasher gu_addr_hasher[1] = {
|
||||
{
|
||||
{ gu_addr_eq_fn },
|
||||
gu_addr_hash_fn
|
||||
}
|
||||
};
|
||||
|
||||
static bool
|
||||
gu_word_eq_fn(GuEquality* self, const void* p1, const void* p2)
|
||||
{
|
||||
(void) self;
|
||||
const GuWord* wp1 = p1;
|
||||
const GuWord* wp2 = p2;
|
||||
return (*wp1 == *wp2);
|
||||
}
|
||||
|
||||
static GuHash
|
||||
gu_word_hash_fn(GuHasher* self, const void* p)
|
||||
{
|
||||
(void) self;
|
||||
return (GuHash) (uintptr_t) p;
|
||||
}
|
||||
|
||||
GU_API GuHasher gu_word_hasher[1] = {
|
||||
{
|
||||
{ gu_word_eq_fn },
|
||||
gu_word_hash_fn
|
||||
}
|
||||
};
|
||||
@@ -1,40 +0,0 @@
|
||||
#ifndef GU_HASH_H_
|
||||
#define GU_HASH_H_
|
||||
|
||||
#include <gu/fun.h>
|
||||
|
||||
typedef GuWord GuHash;
|
||||
|
||||
static inline GuHash
|
||||
gu_hash_ptr(void* ptr)
|
||||
{
|
||||
return (GuHash) ptr;
|
||||
}
|
||||
|
||||
|
||||
static inline GuHash
|
||||
gu_hash_byte(GuHash h, uint8_t u)
|
||||
{
|
||||
// Paul Larson's simple byte hash
|
||||
return h * 101 + u;
|
||||
}
|
||||
|
||||
|
||||
GU_API_DECL GuHash
|
||||
gu_hash_bytes(GuHash h, const uint8_t* buf, size_t len);
|
||||
|
||||
typedef const struct GuHasher GuHasher;
|
||||
|
||||
struct GuHasher {
|
||||
GuEquality eq;
|
||||
GuHash (*hash)(GuHasher* self, const void* p);
|
||||
};
|
||||
|
||||
|
||||
GU_API_DECL extern GuHasher gu_int_hasher[1];
|
||||
|
||||
GU_API_DECL extern GuHasher gu_addr_hasher[1];
|
||||
|
||||
GU_API_DECL extern GuHasher gu_word_hasher[1];
|
||||
|
||||
#endif // GU_HASH_H_
|
||||
@@ -1,378 +0,0 @@
|
||||
#include <gu/in.h>
|
||||
#include <gu/bits.h>
|
||||
#include <math.h>
|
||||
|
||||
|
||||
static bool
|
||||
gu_in_is_buffering(GuIn* in)
|
||||
{
|
||||
return (in->buf_end != NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gu_in_end_buffering(GuIn* in, GuExn* err)
|
||||
{
|
||||
if (!gu_in_is_buffering(in)) {
|
||||
return;
|
||||
}
|
||||
if (in->stream->end_buffer) {
|
||||
size_t len = ((ptrdiff_t) in->buf_size) + in->buf_curr;
|
||||
in->stream->end_buffer(in->stream, len, err);
|
||||
}
|
||||
in->buf_curr = 0;
|
||||
in->buf_size = 0;
|
||||
in->buf_end = NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
gu_in_begin_buffering(GuIn* in, GuExn* err)
|
||||
{
|
||||
if (gu_in_is_buffering(in)) {
|
||||
if (in->buf_curr < 0) {
|
||||
return true;
|
||||
} else {
|
||||
gu_in_end_buffering(in, err);
|
||||
if (!gu_ok(err)) return false;
|
||||
}
|
||||
}
|
||||
if (!in->stream->begin_buffer) {
|
||||
return false;
|
||||
}
|
||||
size_t sz = 0;
|
||||
const uint8_t* new_buf =
|
||||
in->stream->begin_buffer(in->stream, &sz, err);
|
||||
if (new_buf) {
|
||||
in->buf_end = &new_buf[sz];
|
||||
in->buf_curr = -(ptrdiff_t) sz;
|
||||
in->buf_size = sz;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static size_t
|
||||
gu_in_input(GuIn* in, uint8_t* dst, size_t sz, GuExn* err)
|
||||
{
|
||||
if (sz == 0) {
|
||||
return 0;
|
||||
}
|
||||
gu_in_end_buffering(in, err);
|
||||
if (!gu_ok(err)) {
|
||||
return 0;
|
||||
}
|
||||
GuInStream* stream = in->stream;
|
||||
if (stream->input) {
|
||||
return stream->input(stream, dst, sz, err);
|
||||
}
|
||||
gu_raise(err, GuEOF);
|
||||
return 0;
|
||||
}
|
||||
|
||||
GU_API size_t
|
||||
gu_in_some(GuIn* in, uint8_t* dst, size_t sz, GuExn* err)
|
||||
{
|
||||
gu_require(sz <= PTRDIFF_MAX);
|
||||
if (!gu_in_begin_buffering(in, err)) {
|
||||
if (!gu_ok(err)) return 0;
|
||||
return gu_in_input(in, dst, sz, err);
|
||||
}
|
||||
size_t real_sz = GU_MIN(sz, (size_t)(-in->buf_curr));
|
||||
memcpy(dst, &in->buf_end[in->buf_curr], real_sz);
|
||||
in->buf_curr += real_sz;
|
||||
return real_sz;
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_in_bytes_(GuIn* in, uint8_t* dst, size_t sz, GuExn* err)
|
||||
{
|
||||
for (;;) {
|
||||
size_t avail_sz = GU_MIN(sz, (size_t)(-in->buf_curr));
|
||||
memcpy(dst, &in->buf_end[in->buf_curr], avail_sz);
|
||||
in->buf_curr += avail_sz;
|
||||
dst += avail_sz;
|
||||
sz -= avail_sz;
|
||||
|
||||
if (sz == 0)
|
||||
break;
|
||||
|
||||
if (!gu_in_begin_buffering(in, err)) {
|
||||
gu_in_input(in, dst, sz, err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GU_API const uint8_t*
|
||||
gu_in_begin_span(GuIn* in, size_t *sz_out, GuExn* err)
|
||||
{
|
||||
if (!gu_in_begin_buffering(in, err)) {
|
||||
return NULL;
|
||||
}
|
||||
*sz_out = (size_t) -in->buf_curr;
|
||||
return &in->buf_end[in->buf_curr];
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_in_end_span(GuIn* in, size_t consumed)
|
||||
{
|
||||
gu_require(consumed <= (size_t) -in->buf_curr);
|
||||
in->buf_curr += (ptrdiff_t) consumed;
|
||||
}
|
||||
|
||||
GU_API uint8_t
|
||||
gu_in_u8_(GuIn* in, GuExn* err)
|
||||
{
|
||||
if (gu_in_begin_buffering(in, err) && in->buf_curr < 0) {
|
||||
return in->buf_end[in->buf_curr++];
|
||||
}
|
||||
uint8_t u = 0;
|
||||
size_t r = gu_in_input(in, &u, 1, err);
|
||||
if (r < 1) {
|
||||
gu_raise(err, GuEOF);
|
||||
return 0;
|
||||
}
|
||||
return u;
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
gu_in_be(GuIn* in, GuExn* err, int n)
|
||||
{
|
||||
uint8_t buf[8];
|
||||
gu_in_bytes(in, buf, n, err);
|
||||
uint64_t u = 0;
|
||||
for (int i = 0; i < n; i++) {
|
||||
u = u << 8 | buf[i];
|
||||
}
|
||||
return u;
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
gu_in_le(GuIn* in, GuExn* err, int n)
|
||||
{
|
||||
uint8_t buf[8];
|
||||
gu_in_bytes(in, buf, n, err);
|
||||
uint64_t u = 0;
|
||||
for (int i = n-1; i >= 0; i--) {
|
||||
u = u << 8 | buf[i];
|
||||
}
|
||||
return u;
|
||||
}
|
||||
|
||||
GU_API int8_t
|
||||
gu_in_s8(GuIn* in, GuExn* err)
|
||||
{
|
||||
return gu_decode_2c8(gu_in_u8(in, err), err);
|
||||
}
|
||||
|
||||
|
||||
GU_API uint16_t
|
||||
gu_in_u16le(GuIn* in, GuExn* err)
|
||||
{
|
||||
return gu_in_le(in, err, 2);
|
||||
}
|
||||
|
||||
GU_API int16_t
|
||||
gu_in_s16le(GuIn* in, GuExn* err)
|
||||
{
|
||||
return gu_decode_2c16(gu_in_u16le(in, err), err);
|
||||
}
|
||||
|
||||
GU_API uint16_t
|
||||
gu_in_u16be(GuIn* in, GuExn* err)
|
||||
{
|
||||
return gu_in_be(in, err, 2);
|
||||
}
|
||||
|
||||
GU_API int16_t
|
||||
gu_in_s16be(GuIn* in, GuExn* err)
|
||||
{
|
||||
return gu_decode_2c16(gu_in_u16be(in, err), err);
|
||||
}
|
||||
|
||||
GU_API uint32_t
|
||||
gu_in_u32le(GuIn* in, GuExn* err)
|
||||
{
|
||||
return gu_in_le(in, err, 4);
|
||||
}
|
||||
|
||||
GU_API int32_t
|
||||
gu_in_s32le(GuIn* in, GuExn* err)
|
||||
{
|
||||
return gu_decode_2c32(gu_in_u32le(in, err), err);
|
||||
}
|
||||
|
||||
GU_API uint32_t
|
||||
gu_in_u32be(GuIn* in, GuExn* err)
|
||||
{
|
||||
return gu_in_be(in, err, 4);
|
||||
}
|
||||
|
||||
GU_API int32_t
|
||||
gu_in_s32be(GuIn* in, GuExn* err)
|
||||
{
|
||||
return gu_decode_2c32(gu_in_u32be(in, err), err);
|
||||
}
|
||||
|
||||
GU_API uint64_t
|
||||
gu_in_u64le(GuIn* in, GuExn* err)
|
||||
{
|
||||
return gu_in_le(in, err, 8);
|
||||
}
|
||||
|
||||
GU_API int64_t
|
||||
gu_in_s64le(GuIn* in, GuExn* err)
|
||||
{
|
||||
return gu_decode_2c64(gu_in_u64le(in, err), err);
|
||||
}
|
||||
|
||||
GU_API uint64_t
|
||||
gu_in_u64be(GuIn* in, GuExn* err)
|
||||
{
|
||||
return gu_in_be(in, err, 8);
|
||||
}
|
||||
|
||||
GU_API int64_t
|
||||
gu_in_s64be(GuIn* in, GuExn* err)
|
||||
{
|
||||
return gu_decode_2c64(gu_in_u64be(in, err), err);
|
||||
}
|
||||
|
||||
GU_API double
|
||||
gu_in_f64le(GuIn* in, GuExn* err)
|
||||
{
|
||||
return gu_decode_double(gu_in_u64le(in, err));
|
||||
}
|
||||
|
||||
GU_API double
|
||||
gu_in_f64be(GuIn* in, GuExn* err)
|
||||
{
|
||||
return gu_decode_double(gu_in_u64be(in, err));
|
||||
}
|
||||
|
||||
static void
|
||||
gu_in_fini(GuFinalizer* fin)
|
||||
{
|
||||
GuIn* in = gu_container(fin, GuIn, fini);
|
||||
GuPool* pool = gu_local_pool();
|
||||
GuExn* err = gu_exn(pool);
|
||||
gu_in_end_buffering(in, err);
|
||||
gu_pool_free(pool);
|
||||
}
|
||||
|
||||
GU_API GuIn*
|
||||
gu_new_in(GuInStream* stream, GuPool* pool)
|
||||
{
|
||||
gu_require(stream != NULL);
|
||||
|
||||
GuIn* in = gu_new(GuIn, pool);
|
||||
in->buf_end = NULL;
|
||||
in->buf_curr = 0;
|
||||
in->buf_size = 0;
|
||||
in->stream = stream;
|
||||
in->fini.fn = gu_in_fini;
|
||||
return in;
|
||||
}
|
||||
|
||||
typedef struct GuBufferedInStream GuBufferedInStream;
|
||||
|
||||
struct GuBufferedInStream {
|
||||
GuInStream stream;
|
||||
size_t alloc;
|
||||
size_t have;
|
||||
size_t curr;
|
||||
GuIn* in;
|
||||
uint8_t buf[];
|
||||
};
|
||||
|
||||
static const uint8_t*
|
||||
gu_buffered_in_begin_buffer(GuInStream* self, size_t* sz_out, GuExn* err)
|
||||
{
|
||||
GuBufferedInStream* bis =
|
||||
gu_container(self, GuBufferedInStream, stream);
|
||||
if (bis->curr == bis->have) {
|
||||
bis->curr = 0;
|
||||
bis->have = gu_in_some(bis->in, bis->buf, bis->alloc, err);
|
||||
if (!gu_ok(err)) return NULL;
|
||||
}
|
||||
*sz_out = bis->have - bis->curr;
|
||||
return &bis->buf[bis->curr];
|
||||
}
|
||||
|
||||
static void
|
||||
gu_buffered_in_end_buffer(GuInStream* self, size_t consumed, GuExn* err)
|
||||
{
|
||||
GuBufferedInStream* bis =
|
||||
gu_container(self, GuBufferedInStream, stream);
|
||||
gu_require(consumed < bis->have - bis->curr);
|
||||
bis->curr += consumed;
|
||||
}
|
||||
|
||||
static size_t
|
||||
gu_buffered_in_input(GuInStream* self, uint8_t* dst, size_t sz, GuExn* err)
|
||||
{
|
||||
GuBufferedInStream* bis =
|
||||
gu_container(self, GuBufferedInStream, stream);
|
||||
return gu_in_some(bis->in, dst, sz, err);
|
||||
}
|
||||
|
||||
GU_API GuIn*
|
||||
gu_buffered_in(GuIn* in, size_t buf_sz, GuPool* pool)
|
||||
{
|
||||
GuBufferedInStream* bis = gu_new_flex(pool, GuBufferedInStream,
|
||||
buf, buf_sz);
|
||||
bis->stream = (GuInStream) {
|
||||
.begin_buffer = gu_buffered_in_begin_buffer,
|
||||
.end_buffer = gu_buffered_in_end_buffer,
|
||||
.input = gu_buffered_in_input
|
||||
};
|
||||
bis->alloc = buf_sz;
|
||||
bis->have = bis->curr = 0;
|
||||
bis->in = in;
|
||||
return gu_new_in(&bis->stream, pool);
|
||||
}
|
||||
|
||||
typedef struct GuDataIn GuDataIn;
|
||||
|
||||
struct GuDataIn {
|
||||
GuInStream stream;
|
||||
const uint8_t* data;
|
||||
size_t sz;
|
||||
};
|
||||
|
||||
static const uint8_t*
|
||||
gu_data_in_begin_buffer(GuInStream* self, size_t* sz_out, GuExn* err)
|
||||
{
|
||||
(void) err;
|
||||
GuDataIn* di = gu_container(self, GuDataIn, stream);
|
||||
const uint8_t* buf = di->data;
|
||||
if (buf) {
|
||||
*sz_out = di->sz;
|
||||
di->data = NULL;
|
||||
di->sz = 0;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
GU_API GuIn*
|
||||
gu_data_in(const uint8_t* data, size_t sz, GuPool* pool)
|
||||
{
|
||||
GuDataIn* di = gu_new(GuDataIn, pool);
|
||||
di->stream.begin_buffer = gu_data_in_begin_buffer;
|
||||
di->stream.end_buffer = NULL;
|
||||
di->stream.input = NULL;
|
||||
di->data = data;
|
||||
di->sz = sz;
|
||||
return gu_new_in(&di->stream, pool);
|
||||
}
|
||||
|
||||
extern inline uint8_t
|
||||
gu_in_u8(GuIn* restrict in, GuExn* err);
|
||||
|
||||
extern inline void
|
||||
gu_in_bytes(GuIn* in, uint8_t* buf, size_t sz, GuExn* err);
|
||||
|
||||
extern inline int
|
||||
gu_in_peek_u8(GuIn* restrict in);
|
||||
|
||||
extern inline void
|
||||
gu_in_consume(GuIn* restrict in, size_t sz);
|
||||
@@ -1,134 +0,0 @@
|
||||
#ifndef GU_IN_H_
|
||||
#define GU_IN_H_
|
||||
|
||||
#include <gu/defs.h>
|
||||
#include <gu/exn.h>
|
||||
#include <gu/assert.h>
|
||||
|
||||
typedef struct GuInStream GuInStream;
|
||||
|
||||
struct GuInStream {
|
||||
const uint8_t* (*begin_buffer)(GuInStream* self, size_t* sz_out,
|
||||
GuExn* err);
|
||||
void (*end_buffer)(GuInStream* self, size_t consumed, GuExn* err);
|
||||
size_t (*input)(GuInStream* self, uint8_t* buf, size_t max_sz,
|
||||
GuExn* err);
|
||||
};
|
||||
|
||||
typedef struct GuIn GuIn;
|
||||
|
||||
struct GuIn {
|
||||
const uint8_t* restrict buf_end;
|
||||
ptrdiff_t buf_curr;
|
||||
size_t buf_size;
|
||||
GuInStream* stream;
|
||||
GuFinalizer fini;
|
||||
};
|
||||
|
||||
GU_API_DECL GuIn*
|
||||
gu_new_in(GuInStream* stream, GuPool* pool);
|
||||
|
||||
GU_API_DECL const uint8_t*
|
||||
gu_in_begin_span(GuIn* in, size_t *sz_out, GuExn* err);
|
||||
|
||||
GU_API_DECL void
|
||||
gu_in_end_span(GuIn* in, size_t consumed);
|
||||
|
||||
GU_API_DECL size_t
|
||||
gu_in_some(GuIn* in, uint8_t* buf, size_t max_len, GuExn* err);
|
||||
|
||||
inline void
|
||||
gu_in_bytes(GuIn* in, uint8_t* buf, size_t sz, GuExn* err)
|
||||
{
|
||||
gu_require(sz < PTRDIFF_MAX);
|
||||
ptrdiff_t curr = in->buf_curr;
|
||||
ptrdiff_t new_curr = curr + (ptrdiff_t) sz;
|
||||
if (GU_UNLIKELY(new_curr > 0)) {
|
||||
GU_API_DECL void gu_in_bytes_(GuIn* in, uint8_t* buf, size_t sz,
|
||||
GuExn* err);
|
||||
gu_in_bytes_(in, buf, sz, err);
|
||||
return;
|
||||
}
|
||||
memcpy(buf, &in->buf_end[curr], sz);
|
||||
in->buf_curr = new_curr;
|
||||
}
|
||||
|
||||
inline int
|
||||
gu_in_peek_u8(GuIn* restrict in)
|
||||
{
|
||||
if (GU_UNLIKELY(in->buf_curr == 0)) {
|
||||
return -1;
|
||||
}
|
||||
return in->buf_end[in->buf_curr];
|
||||
}
|
||||
|
||||
inline void
|
||||
gu_in_consume(GuIn* restrict in, size_t sz)
|
||||
{
|
||||
gu_require((ptrdiff_t) sz + in->buf_curr <= 0);
|
||||
in->buf_curr += sz;
|
||||
}
|
||||
|
||||
inline uint8_t
|
||||
gu_in_u8(GuIn* restrict in, GuExn* err)
|
||||
{
|
||||
if (GU_UNLIKELY(in->buf_curr == 0)) {
|
||||
GU_API_DECL uint8_t gu_in_u8_(GuIn* restrict in, GuExn* err);
|
||||
return gu_in_u8_(in, err);
|
||||
}
|
||||
return in->buf_end[in->buf_curr++];
|
||||
}
|
||||
|
||||
GU_API_DECL int8_t
|
||||
gu_in_s8(GuIn* in, GuExn* err);
|
||||
|
||||
GU_API_DECL uint16_t
|
||||
gu_in_u16le(GuIn* in, GuExn* err);
|
||||
|
||||
GU_API_DECL uint16_t
|
||||
gu_in_u16be(GuIn* in, GuExn* err);
|
||||
|
||||
GU_API_DECL int16_t
|
||||
gu_in_s16le(GuIn* in, GuExn* err);
|
||||
|
||||
GU_API_DECL int16_t
|
||||
gu_in_s16be(GuIn* in, GuExn* err);
|
||||
|
||||
GU_API_DECL uint32_t
|
||||
gu_in_u32le(GuIn* in, GuExn* err);
|
||||
|
||||
GU_API_DECL uint32_t
|
||||
gu_in_u32be(GuIn* in, GuExn* err);
|
||||
|
||||
GU_API_DECL int32_t
|
||||
gu_in_s32le(GuIn* in, GuExn* err);
|
||||
|
||||
GU_API_DECL int32_t
|
||||
gu_in_s32be(GuIn* in, GuExn* err);
|
||||
|
||||
GU_API_DECL uint64_t
|
||||
gu_in_u64le(GuIn* in, GuExn* err);
|
||||
|
||||
GU_API_DECL uint64_t
|
||||
gu_in_u64be(GuIn* in, GuExn* err);
|
||||
|
||||
GU_API_DECL int64_t
|
||||
gu_in_s64le(GuIn* in, GuExn* err);
|
||||
|
||||
GU_API_DECL int64_t
|
||||
gu_in_s64be(GuIn* in, GuExn* err);
|
||||
|
||||
GU_API_DECL double
|
||||
gu_in_f64le(GuIn* in, GuExn* err);
|
||||
|
||||
GU_API_DECL double
|
||||
gu_in_f64be(GuIn* in, GuExn* err);
|
||||
|
||||
GU_API_DECL GuIn*
|
||||
gu_buffered_in(GuIn* in, size_t sz, GuPool* pool);
|
||||
|
||||
GU_API_DECL GuIn*
|
||||
gu_data_in(const uint8_t* buf, size_t size, GuPool* pool);
|
||||
|
||||
|
||||
#endif // GU_IN_H_
|
||||
@@ -1,392 +0,0 @@
|
||||
#include <gu/defs.h>
|
||||
#include <gu/mem.h>
|
||||
#include <gu/map.h>
|
||||
#include <gu/assert.h>
|
||||
#include <gu/prime.h>
|
||||
#include <gu/string.h>
|
||||
|
||||
typedef struct GuMapData GuMapData;
|
||||
|
||||
#define SKIP_DELETED 1
|
||||
#define SKIP_NONE 2
|
||||
|
||||
struct GuMapData {
|
||||
uint8_t* keys;
|
||||
uint8_t* values;
|
||||
size_t n_occupied;
|
||||
size_t n_entries;
|
||||
size_t zero_idx;
|
||||
};
|
||||
|
||||
struct GuMap {
|
||||
GuHasher* hasher;
|
||||
size_t key_size;
|
||||
size_t value_size;
|
||||
size_t cell_size; // cell_size = GU_MAX(value_size,sizeof(uint8_t))
|
||||
const void* default_value;
|
||||
GuMapData data;
|
||||
|
||||
GuFinalizer fin;
|
||||
};
|
||||
|
||||
static void
|
||||
gu_map_finalize(GuFinalizer* fin)
|
||||
{
|
||||
GuMap* map = gu_container(fin, GuMap, fin);
|
||||
gu_mem_buf_free(map->data.keys);
|
||||
gu_mem_buf_free(map->data.values);
|
||||
}
|
||||
|
||||
static const GuWord gu_map_empty_key = 0;
|
||||
|
||||
static bool
|
||||
gu_map_buf_is_zero(const uint8_t* p, size_t sz) {
|
||||
while (sz >= sizeof(GuWord)) {
|
||||
sz -= sizeof(GuWord);
|
||||
if (memcmp(&p[sz], &gu_map_empty_key, sizeof(GuWord)) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return (memcmp(p, &gu_map_empty_key, sz) == 0);
|
||||
}
|
||||
|
||||
static bool
|
||||
gu_map_entry_is_free(GuMap* map, GuMapData* data, size_t idx)
|
||||
{
|
||||
if (idx == data->zero_idx) {
|
||||
return false;
|
||||
} else if (map->hasher == gu_addr_hasher) {
|
||||
const void* key = ((const void**)data->keys)[idx];
|
||||
return key == NULL;
|
||||
} else if (map->hasher == gu_word_hasher) {
|
||||
GuWord key = ((GuWord*)data->keys)[idx];
|
||||
return key == 0;
|
||||
} else if (map->hasher == gu_string_hasher) {
|
||||
GuString key = ((GuString*)data->keys)[idx];
|
||||
return key == NULL;
|
||||
}
|
||||
const void* key = &data->keys[idx * map->key_size];
|
||||
return gu_map_buf_is_zero(key, map->key_size);
|
||||
}
|
||||
|
||||
static bool
|
||||
gu_map_lookup(GuMap* map, const void* key, uint8_t del, size_t* idx_out)
|
||||
{
|
||||
size_t n = map->data.n_entries;
|
||||
if (map->hasher == gu_addr_hasher) {
|
||||
GuHash hash = (GuHash) key;
|
||||
size_t idx = hash % n;
|
||||
size_t offset = (hash % (n - 2)) + 1;
|
||||
while (true) {
|
||||
const void* entry_key =
|
||||
((const void**)map->data.keys)[idx];
|
||||
|
||||
if (entry_key == NULL && map->data.zero_idx != idx) {
|
||||
if (map->data.values[idx * map->cell_size] != del) { //skip deleted
|
||||
*idx_out = idx;
|
||||
return false;
|
||||
}
|
||||
} else if (entry_key == key) {
|
||||
*idx_out = idx;
|
||||
return true;
|
||||
}
|
||||
|
||||
idx = (idx + offset) % n;
|
||||
}
|
||||
} else if (map->hasher == gu_word_hasher) {
|
||||
GuWord w = *(const GuWord*)key;
|
||||
GuHash hash = (GuHash) w;
|
||||
size_t idx = hash % n;
|
||||
size_t offset = (hash % (n - 2)) + 1;
|
||||
while (true) {
|
||||
GuWord entry_key = ((GuWord*)map->data.keys)[idx];
|
||||
if (entry_key == 0 && map->data.zero_idx != idx) {
|
||||
*idx_out = idx;
|
||||
return false;
|
||||
} else if (entry_key == w) {
|
||||
*idx_out = idx;
|
||||
return true;
|
||||
}
|
||||
idx = (idx + offset) % n;
|
||||
}
|
||||
} else if (map->hasher == gu_string_hasher) {
|
||||
GuHasher* hasher = map->hasher;
|
||||
GuEquality* eq = (GuEquality*) hasher;
|
||||
GuHash hash = hasher->hash(hasher, key);
|
||||
size_t idx = hash % n;
|
||||
size_t offset = (hash % (n - 2)) + 1;
|
||||
while (true) {
|
||||
GuString entry_key =
|
||||
((GuString*)map->data.keys)[idx];
|
||||
if (entry_key == NULL && map->data.zero_idx != idx) {
|
||||
*idx_out = idx;
|
||||
return false;
|
||||
} else if (eq->is_equal(eq, key, entry_key)) {
|
||||
*idx_out = idx;
|
||||
return true;
|
||||
}
|
||||
idx = (idx + offset) % n;
|
||||
}
|
||||
} else {
|
||||
GuHasher* hasher = map->hasher;
|
||||
GuEquality* eq = (GuEquality*) hasher;
|
||||
GuHash hash = hasher->hash(hasher, key);
|
||||
size_t idx = hash % n;
|
||||
size_t offset = (hash % (n - 2)) + 1;
|
||||
size_t key_size = map->key_size;
|
||||
while (true) {
|
||||
void* entry_key = &map->data.keys[idx * key_size];
|
||||
if (gu_map_buf_is_zero(entry_key, key_size) &&
|
||||
map->data.zero_idx != idx) {
|
||||
*idx_out = idx;
|
||||
return false;
|
||||
} else if (eq->is_equal(eq, key, entry_key)) {
|
||||
*idx_out = idx;
|
||||
return true;
|
||||
}
|
||||
idx = (idx + offset) % n;
|
||||
}
|
||||
}
|
||||
|
||||
gu_impossible();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gu_map_resize(GuMap* map, size_t req_entries)
|
||||
{
|
||||
GuMapData* data = &map->data;
|
||||
GuMapData old_data = *data;
|
||||
|
||||
size_t key_size = map->key_size;
|
||||
size_t key_alloc = 0;
|
||||
data->keys = gu_mem_buf_alloc(req_entries * key_size, &key_alloc);
|
||||
memset(data->keys, 0, key_alloc);
|
||||
|
||||
size_t value_alloc = 0;
|
||||
size_t cell_size = map->cell_size;
|
||||
data->values = gu_mem_buf_alloc(req_entries * cell_size, &value_alloc);
|
||||
memset(data->values, 0, value_alloc);
|
||||
|
||||
data->n_entries = gu_twin_prime_inf(
|
||||
GU_MIN(key_alloc / key_size,
|
||||
value_alloc / cell_size));
|
||||
gu_assert(data->n_entries > data->n_occupied);
|
||||
|
||||
data->n_occupied = 0;
|
||||
data->zero_idx = SIZE_MAX;
|
||||
|
||||
for (size_t i = 0; i < old_data.n_entries; i++) {
|
||||
if (gu_map_entry_is_free(map, &old_data, i)) {
|
||||
continue;
|
||||
}
|
||||
void* old_key = &old_data.keys[i * key_size];
|
||||
if (map->hasher == gu_addr_hasher) {
|
||||
old_key = *(void**)old_key;
|
||||
} else if (map->hasher == gu_string_hasher) {
|
||||
old_key = (void*) *(GuString*)old_key;
|
||||
}
|
||||
void* old_value = &old_data.values[i * cell_size];
|
||||
|
||||
memcpy(gu_map_insert(map, old_key),
|
||||
old_value, map->value_size);
|
||||
}
|
||||
|
||||
gu_mem_buf_free(old_data.keys);
|
||||
gu_mem_buf_free(old_data.values);
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
gu_map_maybe_resize(GuMap* map)
|
||||
{
|
||||
if (map->data.n_entries <=
|
||||
map->data.n_occupied + (map->data.n_occupied / 4)) {
|
||||
size_t req_entries =
|
||||
gu_twin_prime_sup(GU_MAX(11, map->data.n_occupied * 4 / 3 + 1));
|
||||
gu_map_resize(map, req_entries);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
GU_API void*
|
||||
gu_map_find(GuMap* map, const void* key)
|
||||
{
|
||||
size_t idx;
|
||||
bool found = gu_map_lookup(map, key, SKIP_DELETED, &idx);
|
||||
if (found) {
|
||||
return &map->data.values[idx * map->cell_size];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GU_API const void*
|
||||
gu_map_find_default(GuMap* map, const void* key)
|
||||
{
|
||||
void* p = gu_map_find(map, key);
|
||||
return p ? p : map->default_value;
|
||||
}
|
||||
|
||||
GU_API const void*
|
||||
gu_map_find_key(GuMap* map, const void* key)
|
||||
{
|
||||
size_t idx;
|
||||
bool found = gu_map_lookup(map, key, SKIP_DELETED, &idx);
|
||||
if (found) {
|
||||
return &map->data.keys[idx * map->key_size];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GU_API bool
|
||||
gu_map_has(GuMap* ht, const void* key)
|
||||
{
|
||||
size_t idx;
|
||||
return gu_map_lookup(ht, key, SKIP_DELETED, &idx);
|
||||
}
|
||||
|
||||
GU_API void*
|
||||
gu_map_insert(GuMap* map, const void* key)
|
||||
{
|
||||
size_t idx;
|
||||
bool found = gu_map_lookup(map, key, SKIP_NONE, &idx);
|
||||
if (!found) {
|
||||
if (gu_map_maybe_resize(map)) {
|
||||
found = gu_map_lookup(map, key, SKIP_NONE, &idx);
|
||||
gu_assert(!found);
|
||||
}
|
||||
if (map->hasher == gu_addr_hasher) {
|
||||
((const void**)map->data.keys)[idx] = key;
|
||||
} else if (map->hasher == gu_string_hasher) {
|
||||
((GuString*)map->data.keys)[idx] = key;
|
||||
} else {
|
||||
memcpy(&map->data.keys[idx * map->key_size],
|
||||
key, map->key_size);
|
||||
}
|
||||
if (map->default_value) {
|
||||
memcpy(&map->data.values[idx * map->cell_size],
|
||||
map->default_value, map->value_size);
|
||||
}
|
||||
if (gu_map_entry_is_free(map, &map->data, idx)) {
|
||||
gu_assert(map->data.zero_idx == SIZE_MAX);
|
||||
map->data.zero_idx = idx;
|
||||
}
|
||||
map->data.n_occupied++;
|
||||
}
|
||||
return &map->data.values[idx * map->cell_size];
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_map_delete(GuMap* map, const void* key)
|
||||
{
|
||||
size_t idx;
|
||||
bool found = gu_map_lookup(map, key, SKIP_NONE, &idx);
|
||||
if (found) {
|
||||
if (map->hasher == gu_addr_hasher) {
|
||||
((const void**)map->data.keys)[idx] = NULL;
|
||||
} else if (map->hasher == gu_string_hasher) {
|
||||
((GuString*)map->data.keys)[idx] = NULL;
|
||||
} else {
|
||||
memset(&map->data.keys[idx * map->key_size],
|
||||
0, map->key_size);
|
||||
}
|
||||
map->data.values[idx * map->cell_size] = SKIP_DELETED;
|
||||
|
||||
if (gu_map_buf_is_zero(&map->data.keys[idx * map->key_size],
|
||||
map->key_size)) {
|
||||
map->data.zero_idx = SIZE_MAX;
|
||||
}
|
||||
|
||||
map->data.n_occupied--;
|
||||
}
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_map_iter(GuMap* map, GuMapItor* itor, GuExn* err)
|
||||
{
|
||||
for (size_t i = 0; i < map->data.n_entries && gu_ok(err); i++) {
|
||||
if (gu_map_entry_is_free(map, &map->data, i)) {
|
||||
continue;
|
||||
}
|
||||
const void* key = &map->data.keys[i * map->key_size];
|
||||
void* value = &map->data.values[i * map->cell_size];
|
||||
if (map->hasher == gu_addr_hasher) {
|
||||
key = *(const void* const*) key;
|
||||
} else if (map->hasher == gu_string_hasher) {
|
||||
key = *(GuString*) key;
|
||||
}
|
||||
itor->fn(itor, key, value, err);
|
||||
}
|
||||
}
|
||||
|
||||
GU_API bool
|
||||
gu_map_next(GuMap* map, size_t* pi, void* pkey, void* pvalue)
|
||||
{
|
||||
while (*pi < map->data.n_entries) {
|
||||
if (gu_map_entry_is_free(map, &map->data, *pi)) {
|
||||
(*pi)++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (map->hasher == gu_addr_hasher) {
|
||||
*((void**) pkey) = *((void**) &map->data.keys[*pi * sizeof(void*)]);
|
||||
} else if (map->hasher == gu_word_hasher) {
|
||||
*((GuWord*) pkey) = *((GuWord*) &map->data.keys[*pi * sizeof(GuWord)]);
|
||||
} else if (map->hasher == gu_string_hasher) {
|
||||
*((GuString*) pkey) = *((GuString*) &map->data.keys[*pi * sizeof(GuString)]);
|
||||
} else {
|
||||
memcpy(pkey, &map->data.keys[*pi * map->key_size], map->key_size);
|
||||
}
|
||||
|
||||
memcpy(pvalue, &map->data.values[*pi * map->cell_size],
|
||||
map->value_size);
|
||||
|
||||
(*pi)++;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
GU_API size_t
|
||||
gu_map_count(GuMap* map)
|
||||
{
|
||||
size_t count = 0;
|
||||
for (size_t i = 0; i < map->data.n_entries; i++) {
|
||||
if (gu_map_entry_is_free(map, &map->data, i)) {
|
||||
continue;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
GU_API GuMap*
|
||||
gu_make_map(size_t key_size, GuHasher* hasher,
|
||||
size_t value_size, const void* default_value,
|
||||
size_t init_size,
|
||||
GuPool* pool)
|
||||
{
|
||||
GuMapData data = {
|
||||
.n_occupied = 0,
|
||||
.n_entries = 0,
|
||||
.keys = NULL,
|
||||
.values = NULL,
|
||||
.zero_idx = SIZE_MAX
|
||||
};
|
||||
GuMap* map = gu_new(GuMap, pool);
|
||||
map->default_value = default_value;
|
||||
map->hasher = hasher;
|
||||
map->data = data;
|
||||
map->key_size = key_size;
|
||||
map->value_size = value_size;
|
||||
map->cell_size = GU_MAX(value_size,sizeof(uint8_t));
|
||||
map->fin.fn = gu_map_finalize;
|
||||
gu_pool_finally(pool, &map->fin);
|
||||
|
||||
init_size = gu_twin_prime_sup(init_size);
|
||||
gu_map_resize(map, init_size);
|
||||
return map;
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
#ifndef GU_MAP_H_
|
||||
#define GU_MAP_H_
|
||||
|
||||
#include <gu/hash.h>
|
||||
#include <gu/mem.h>
|
||||
#include <gu/exn.h>
|
||||
#include <gu/enum.h>
|
||||
|
||||
typedef struct GuMapItor GuMapItor;
|
||||
|
||||
struct GuMapItor {
|
||||
void (*fn)(GuMapItor* self, const void* key, void* value,
|
||||
GuExn *err);
|
||||
};
|
||||
|
||||
typedef struct GuMap GuMap;
|
||||
|
||||
GU_API_DECL GuMap*
|
||||
gu_make_map(size_t key_size, GuHasher* hasher,
|
||||
size_t value_size, const void* default_value,
|
||||
size_t init_size,
|
||||
GuPool* pool);
|
||||
|
||||
#define GU_MAP_DEFAULT_INIT_SIZE 11
|
||||
|
||||
#define gu_new_map(K, HASHER, V, DV, POOL) \
|
||||
(gu_make_map(sizeof(K), (HASHER), sizeof(V), (DV), GU_MAP_DEFAULT_INIT_SIZE, (POOL)))
|
||||
|
||||
#define gu_new_set(K, HASHER, POOL) \
|
||||
(gu_make_map(sizeof(K), (HASHER), 0, NULL, GU_MAP_DEFAULT_INIT_SIZE, (POOL)))
|
||||
|
||||
#define gu_new_addr_map(K, V, DV, POOL) \
|
||||
(gu_make_map(sizeof(K), gu_addr_hasher, sizeof(V), (DV), GU_MAP_DEFAULT_INIT_SIZE, (POOL)))
|
||||
|
||||
GU_API_DECL size_t
|
||||
gu_map_count(GuMap* map);
|
||||
|
||||
GU_API_DECL void*
|
||||
gu_map_find_full(GuMap* ht, void* key_inout);
|
||||
|
||||
GU_API_DECL const void*
|
||||
gu_map_find_default(GuMap* ht, const void* key);
|
||||
|
||||
#define gu_map_get(MAP, KEYP, V) \
|
||||
(*(V*)gu_map_find_default((MAP), (KEYP)))
|
||||
|
||||
GU_API_DECL void*
|
||||
gu_map_find(GuMap* ht, const void* key);
|
||||
|
||||
#define gu_map_set(MAP, KEYP, V, VAL) \
|
||||
GU_BEGIN \
|
||||
V* gu_map_set_p_ = gu_map_find((MAP), (KEYP)); \
|
||||
*gu_map_set_p_ = (VAL); \
|
||||
GU_END
|
||||
|
||||
GU_API_DECL const void*
|
||||
gu_map_find_key(GuMap* ht, const void* key);
|
||||
|
||||
GU_API_DECL bool
|
||||
gu_map_has(GuMap* ht, const void* key);
|
||||
|
||||
GU_API_DECL void*
|
||||
gu_map_insert(GuMap* ht, const void* key);
|
||||
|
||||
GU_API_DECL void
|
||||
gu_map_delete(GuMap* ht, const void* key);
|
||||
|
||||
#define gu_map_put(MAP, KEYP, V, VAL) \
|
||||
GU_BEGIN \
|
||||
V* gu_map_put_p_ = gu_map_insert((MAP), (KEYP)); \
|
||||
*gu_map_put_p_ = (VAL); \
|
||||
GU_END
|
||||
|
||||
GU_API_DECL void
|
||||
gu_map_iter(GuMap* ht, GuMapItor* itor, GuExn* err);
|
||||
|
||||
GU_API bool
|
||||
gu_map_next(GuMap* map, size_t* pi, void* pkey, void* pvalue);
|
||||
|
||||
typedef GuMap GuIntMap;
|
||||
|
||||
#define gu_new_int_map(VAL_T, DEFAULT, POOL) \
|
||||
gu_new_map(int, gu_int_hasher, VAL_T, DEFAULT, POOL)
|
||||
|
||||
#endif // GU_MAP_H_
|
||||
@@ -1,428 +0,0 @@
|
||||
#include <gu/mem.h>
|
||||
#include <gu/fun.h>
|
||||
#include <gu/bits.h>
|
||||
#include <gu/assert.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#if defined(__MINGW32__) || defined(_MSC_VER)
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#if !defined(_MSC_VER)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef USE_VALGRIND
|
||||
#include <valgrind/valgrind.h>
|
||||
#define VG(X) X
|
||||
#else
|
||||
#define VG(X) GU_NOP
|
||||
#endif
|
||||
|
||||
static const size_t
|
||||
// Maximum request size for a chunk. The actual maximum chunk size
|
||||
// may be somewhat larger.
|
||||
gu_mem_chunk_max_size = 1024 * sizeof(void*),
|
||||
|
||||
// number of bytes to allocate in the pool when it is created
|
||||
gu_mem_pool_initial_size = 24 * sizeof(void*),
|
||||
|
||||
// Pool allocations larger than this will get their own chunk if
|
||||
// there's no room in the current one. Allocations smaller than this may trigger
|
||||
// the creation of a new chunk, in which case the remaining space in
|
||||
// the current chunk is left unused (internal fragmentation).
|
||||
gu_mem_max_shared_alloc = 64 * sizeof(void*),
|
||||
|
||||
// Should not be smaller than the granularity for malloc
|
||||
gu_mem_unit_size = 2 * sizeof(void*),
|
||||
|
||||
/* Malloc tuning: the additional memory used by malloc next to the
|
||||
allocated object */
|
||||
gu_malloc_overhead = sizeof(size_t);
|
||||
|
||||
static void*
|
||||
gu_mem_realloc(void* p, size_t size)
|
||||
{
|
||||
void* buf = realloc(p, size);
|
||||
if (size != 0 && buf == NULL) {
|
||||
gu_fatal("Memory allocation failed");
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void*
|
||||
gu_mem_alloc(size_t size)
|
||||
{
|
||||
void* buf = malloc(size);
|
||||
if (buf == NULL) {
|
||||
gu_fatal("Memory allocation failed");
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void
|
||||
gu_mem_free(void* p)
|
||||
{
|
||||
free(p);
|
||||
}
|
||||
|
||||
static size_t
|
||||
gu_mem_padovan(size_t min)
|
||||
{
|
||||
// This could in principle be done faster with Q-matrices for
|
||||
// Padovan numbers, but not really worth it for our commonly
|
||||
// small numbers.
|
||||
if (min <= 5) {
|
||||
return min;
|
||||
}
|
||||
size_t a = 7, b = 9, c = 12;
|
||||
while (min > a) {
|
||||
if (b < a) {
|
||||
// overflow
|
||||
return SIZE_MAX;
|
||||
}
|
||||
size_t tmp = a + b;
|
||||
a = b;
|
||||
b = c;
|
||||
c = tmp;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
GU_API void*
|
||||
gu_mem_buf_realloc(void* old_buf, size_t min_size, size_t* real_size_out)
|
||||
{
|
||||
size_t min_blocks = ((min_size + gu_malloc_overhead - 1) /
|
||||
gu_mem_unit_size) + 1;
|
||||
size_t blocks = gu_mem_padovan(min_blocks);
|
||||
size_t size = blocks * gu_mem_unit_size - gu_malloc_overhead;
|
||||
void* buf = gu_mem_realloc(old_buf, size);
|
||||
*real_size_out = buf ? size : 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
GU_API void*
|
||||
gu_mem_buf_alloc(size_t min_size, size_t* real_size_out)
|
||||
{
|
||||
return gu_mem_buf_realloc(NULL, min_size, real_size_out);
|
||||
}
|
||||
|
||||
#if defined(__MINGW32__) || defined(_MSC_VER)
|
||||
#include <windows.h>
|
||||
|
||||
static int
|
||||
getpagesize()
|
||||
{
|
||||
SYSTEM_INFO system_info;
|
||||
GetSystemInfo(&system_info);
|
||||
return system_info.dwPageSize;
|
||||
}
|
||||
#endif
|
||||
|
||||
GU_API void*
|
||||
gu_mem_page_alloc(size_t min_size, size_t* real_size_out)
|
||||
{
|
||||
size_t page_size = getpagesize();
|
||||
size_t size = ((min_size + page_size - 1) / page_size) * page_size;
|
||||
void *page = NULL;
|
||||
|
||||
#if defined(ANDROID)
|
||||
if ((page = memalign(page_size, size)) == NULL) {
|
||||
#elif defined(__MINGW32__) || defined(_MSC_VER)
|
||||
if ((page = malloc(size)) == NULL) {
|
||||
#else
|
||||
if (posix_memalign(&page, page_size, size) != 0) {
|
||||
#endif
|
||||
gu_fatal("Memory allocation failed");
|
||||
}
|
||||
|
||||
*real_size_out = size;
|
||||
return page;
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_mem_buf_free(void* buf)
|
||||
{
|
||||
gu_mem_free(buf);
|
||||
}
|
||||
|
||||
|
||||
typedef struct GuMemChunk GuMemChunk;
|
||||
|
||||
struct GuMemChunk {
|
||||
GuMemChunk* next;
|
||||
uint8_t data[];
|
||||
};
|
||||
|
||||
typedef struct GuFinalizerNode GuFinalizerNode;
|
||||
|
||||
struct GuFinalizerNode {
|
||||
GuFinalizerNode* next;
|
||||
GuFinalizer* fin;
|
||||
};
|
||||
|
||||
enum GuPoolType {
|
||||
GU_POOL_HEAP,
|
||||
GU_POOL_LOCAL,
|
||||
GU_POOL_PAGE,
|
||||
GU_POOL_MMAP
|
||||
};
|
||||
|
||||
struct GuPool {
|
||||
uint8_t* curr_buf; // actually GuMemChunk*
|
||||
GuMemChunk* chunks;
|
||||
GuFinalizerNode* finalizers;
|
||||
uint16_t type;
|
||||
size_t left_edge;
|
||||
size_t right_edge;
|
||||
size_t curr_size;
|
||||
uint8_t init_buf[];
|
||||
};
|
||||
|
||||
static GuPool*
|
||||
gu_init_pool(uint8_t* buf, size_t sz)
|
||||
{
|
||||
gu_require(gu_aligned((uintptr_t) (void*) buf, gu_alignof(GuPool)));
|
||||
gu_require(sz >= sizeof(GuPool));
|
||||
GuPool* pool = (GuPool*) buf;
|
||||
pool->type = GU_POOL_HEAP;
|
||||
pool->curr_size = sz;
|
||||
pool->curr_buf = (uint8_t*) pool;
|
||||
pool->chunks = NULL;
|
||||
pool->finalizers = NULL;
|
||||
pool->left_edge = offsetof(GuPool, init_buf);
|
||||
pool->right_edge = sz;
|
||||
VG(VALGRIND_CREATE_MEMPOOL(pool, 0, false));
|
||||
return pool;
|
||||
}
|
||||
|
||||
GU_API GuPool*
|
||||
gu_local_pool_(uint8_t* buf, size_t sz)
|
||||
{
|
||||
GuPool* pool = gu_init_pool(buf, sz);
|
||||
pool->type = GU_POOL_LOCAL;
|
||||
return pool;
|
||||
}
|
||||
|
||||
GU_API GuPool*
|
||||
gu_new_pool(void)
|
||||
{
|
||||
size_t sz = GU_FLEX_SIZE(GuPool, init_buf, gu_mem_pool_initial_size);
|
||||
uint8_t* buf = gu_mem_buf_alloc(sz, &sz);
|
||||
GuPool* pool = gu_init_pool(buf, sz);
|
||||
return pool;
|
||||
}
|
||||
|
||||
GU_API GuPool*
|
||||
gu_new_page_pool(void)
|
||||
{
|
||||
size_t sz = GU_FLEX_SIZE(GuPool, init_buf, gu_mem_pool_initial_size);
|
||||
uint8_t* buf = gu_mem_page_alloc(sz, &sz);
|
||||
GuPool* pool = gu_init_pool(buf, sz);
|
||||
pool->type = GU_POOL_PAGE;
|
||||
return pool;
|
||||
}
|
||||
|
||||
GU_API GuPool*
|
||||
gu_mmap_pool(char* fpath, void* addr, size_t size, void**pptr)
|
||||
{
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
int prot = PROT_READ;
|
||||
int fd = open(fpath, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
if (errno == ENOENT) {
|
||||
fd = open(fpath, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
|
||||
if (fd < 0)
|
||||
return NULL;
|
||||
|
||||
if (ftruncate(fd, size) < 0) {
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
prot |= PROT_WRITE;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void *ptr = mmap(addr, size, prot, MAP_SHARED | MAP_FIXED, fd, 0);
|
||||
if (ptr == MAP_FAILED) {
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gu_require(ptr == addr);
|
||||
|
||||
*pptr = (prot & PROT_WRITE) ? NULL : ptr;
|
||||
|
||||
size_t sz = GU_FLEX_SIZE(GuPool, init_buf, sizeof(int));
|
||||
uint8_t* buf = gu_mem_buf_alloc(sz, &sz);
|
||||
GuPool* pool = gu_init_pool(buf, size);
|
||||
|
||||
uint8_t* pfd = pool->init_buf;
|
||||
*((int*) pfd) = fd;
|
||||
|
||||
pool->type = GU_POOL_MMAP;
|
||||
pool->curr_buf = ptr;
|
||||
pool->left_edge = 0;
|
||||
|
||||
return pool;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
gu_pool_expand(GuPool* pool, size_t req)
|
||||
{
|
||||
gu_require(pool->type != GU_POOL_MMAP);
|
||||
size_t real_req = GU_MAX(req, GU_MIN(((size_t)pool->curr_size) + 1,
|
||||
gu_mem_chunk_max_size));
|
||||
gu_assert(real_req >= sizeof(GuMemChunk));
|
||||
size_t size = 0;
|
||||
GuMemChunk* chunk =
|
||||
(pool->type == GU_POOL_PAGE)
|
||||
? gu_mem_page_alloc(real_req, &size)
|
||||
: gu_mem_buf_alloc(real_req, &size);
|
||||
chunk->next = pool->chunks;
|
||||
pool->chunks = chunk;
|
||||
pool->curr_buf = (uint8_t*) chunk;
|
||||
pool->left_edge = offsetof(GuMemChunk, data);
|
||||
pool->right_edge = pool->curr_size = size;
|
||||
gu_assert((size_t) pool->right_edge == size);
|
||||
}
|
||||
|
||||
static size_t
|
||||
gu_mem_advance(size_t old_pos, size_t pre_align, size_t pre_size,
|
||||
size_t align, size_t size)
|
||||
{
|
||||
size_t p = gu_align_forward(old_pos, pre_align);
|
||||
p += pre_size;
|
||||
p = gu_align_forward(p, align);
|
||||
p += size;
|
||||
return p;
|
||||
}
|
||||
|
||||
static void*
|
||||
gu_pool_malloc_aligned(GuPool* pool, size_t pre_align, size_t pre_size,
|
||||
size_t align, size_t size)
|
||||
{
|
||||
size_t pos = gu_mem_advance(pool->left_edge, pre_align, pre_size,
|
||||
align, size);
|
||||
if (pos > (size_t) pool->right_edge) {
|
||||
pos = gu_mem_advance(offsetof(GuMemChunk, data),
|
||||
pre_align, pre_size, align, size);
|
||||
gu_pool_expand(pool, pos);
|
||||
gu_assert(pos <= pool->right_edge);
|
||||
}
|
||||
pool->left_edge = pos;
|
||||
uint8_t* addr = &pool->curr_buf[pos - size];
|
||||
VG(VALGRIND_MEMPOOL_ALLOC(pool, addr - pre_size, size + pre_size ));
|
||||
return addr;
|
||||
}
|
||||
|
||||
static size_t
|
||||
gu_pool_avail(GuPool* pool)
|
||||
{
|
||||
return (size_t) pool->right_edge - (size_t) pool->left_edge;
|
||||
}
|
||||
|
||||
GU_API void*
|
||||
gu_pool_malloc_unaligned(GuPool* pool, size_t size)
|
||||
{
|
||||
if (size > gu_pool_avail(pool)) {
|
||||
gu_pool_expand(pool, offsetof(GuMemChunk, data) + size);
|
||||
gu_assert(size <= gu_pool_avail(pool));
|
||||
}
|
||||
pool->right_edge -= size;
|
||||
void* addr = &pool->curr_buf[pool->right_edge];
|
||||
VG(VALGRIND_MEMPOOL_ALLOC(pool, addr, size));
|
||||
return addr;
|
||||
}
|
||||
|
||||
GU_API void*
|
||||
gu_malloc_prefixed(GuPool* pool, size_t pre_align, size_t pre_size,
|
||||
size_t align, size_t size)
|
||||
{
|
||||
void* ret = NULL;
|
||||
if (pre_align == 0) {
|
||||
pre_align = gu_alignof(GuMaxAlign);
|
||||
}
|
||||
if (align == 0) {
|
||||
align = gu_alignof(GuMaxAlign);
|
||||
}
|
||||
size_t full_size = gu_mem_advance(offsetof(GuMemChunk, data),
|
||||
pre_align, pre_size, align, size);
|
||||
if (full_size > gu_mem_max_shared_alloc &&
|
||||
pool->type != GU_POOL_PAGE &&
|
||||
pool->type != GU_POOL_MMAP) {
|
||||
GuMemChunk* chunk = gu_mem_alloc(full_size);
|
||||
chunk->next = pool->chunks;
|
||||
pool->chunks = chunk;
|
||||
uint8_t* addr = &chunk->data[full_size - size
|
||||
- offsetof(GuMemChunk, data)];
|
||||
VG(VALGRIND_MEMPOOL_ALLOC(pool, addr - pre_size,
|
||||
pre_size + size));
|
||||
ret = addr;
|
||||
} else if (pre_align == 1 && align == 1) {
|
||||
uint8_t* buf = gu_pool_malloc_unaligned(pool, pre_size + size);
|
||||
ret = &buf[pre_size];
|
||||
} else {
|
||||
ret = gu_pool_malloc_aligned(pool, pre_align, pre_size,
|
||||
align, size);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
GU_API void*
|
||||
gu_malloc_aligned(GuPool* pool, size_t size, size_t align)
|
||||
{
|
||||
return gu_malloc_prefixed(pool, 1, 0, align, size);
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_pool_finally(GuPool* pool, GuFinalizer* finalizer)
|
||||
{
|
||||
gu_require(pool->type != GU_POOL_MMAP);
|
||||
GuFinalizerNode* node = gu_new(GuFinalizerNode, pool);
|
||||
node->next = pool->finalizers;
|
||||
node->fin = finalizer;
|
||||
pool->finalizers = node;
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_pool_free(GuPool* pool)
|
||||
{
|
||||
GuFinalizerNode* node = pool->finalizers;
|
||||
while (node) {
|
||||
node->fin->fn(node->fin);
|
||||
node = node->next;
|
||||
}
|
||||
GuMemChunk* chunk = pool->chunks;
|
||||
while (chunk) {
|
||||
GuMemChunk* next = chunk->next;
|
||||
gu_mem_buf_free(chunk);
|
||||
chunk = next;
|
||||
}
|
||||
VG(VALGRIND_DESTROY_MEMPOOL(pool));
|
||||
if (pool->type == GU_POOL_HEAP) {
|
||||
gu_mem_buf_free(pool);
|
||||
} else if (pool->type == GU_POOL_MMAP) {
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
uint8_t* pfd = pool->init_buf;
|
||||
int fd = *(pfd);
|
||||
|
||||
munmap(pool->curr_buf, pool->curr_size);
|
||||
close(fd);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern inline void* gu_malloc(GuPool* pool, size_t size);
|
||||
@@ -1,218 +0,0 @@
|
||||
/** @file
|
||||
*
|
||||
* Memory allocation tools.
|
||||
*/
|
||||
|
||||
#ifndef GU_MEM_H_
|
||||
#define GU_MEM_H_
|
||||
|
||||
#include <gu/defs.h>
|
||||
#include <gu/fun.h>
|
||||
|
||||
/** @defgroup GuPool Memory pools */
|
||||
//@{
|
||||
|
||||
|
||||
/// A memory pool.
|
||||
typedef struct GuPool GuPool;
|
||||
|
||||
/// @name Creating a pool
|
||||
//@{
|
||||
|
||||
|
||||
/// Create a new memory pool.
|
||||
GU_API_DECL GuPool*
|
||||
gu_new_pool(void);
|
||||
|
||||
/**<
|
||||
* @return A new memory pool.
|
||||
*/
|
||||
|
||||
|
||||
//@private
|
||||
GU_API_DECL GuPool*
|
||||
gu_local_pool_(uint8_t* init_buf, size_t sz);
|
||||
|
||||
//@private
|
||||
#define GU_LOCAL_POOL_INIT_SIZE (16 * sizeof(GuWord))
|
||||
|
||||
|
||||
/// Create a stack-allocated memory pool.
|
||||
#define gu_local_pool() \
|
||||
gu_local_pool_(gu_alloca(GU_LOCAL_POOL_INIT_SIZE), \
|
||||
GU_LOCAL_POOL_INIT_SIZE)
|
||||
/**<
|
||||
* @return A memory pool whose first chunk is allocated directly from
|
||||
* the stack. This makes its creation faster, and more suitable for
|
||||
* functions that usually allocate only a little memory from the pool
|
||||
* until it is freed.
|
||||
*
|
||||
* @note The pool created with #gu_local_pool \e must be freed with
|
||||
* #gu_pool_free before the end of the block where #gu_local_pool was
|
||||
* called.
|
||||
*
|
||||
* @note Because #gu_local_pool uses relatively much stack space, it
|
||||
* should not be used in the bodies of recursive functions.
|
||||
*/
|
||||
|
||||
/// Create a pool where each chunk is corresponds to one or
|
||||
/// more pages.
|
||||
GU_API_DECL GuPool*
|
||||
gu_new_page_pool(void);
|
||||
|
||||
/// Create a pool stored in a memory mapped file.
|
||||
GU_API_DECL GuPool*
|
||||
gu_mmap_pool(char* fpath, void* addr, size_t size, void**pptr);
|
||||
|
||||
//@}
|
||||
/// @name Destroying a pool
|
||||
//@{
|
||||
|
||||
|
||||
/// Free a memory pool and all objects allocated from it.
|
||||
GU_API_DECL void
|
||||
gu_pool_free(GU_ONLY GuPool* pool);
|
||||
/**<
|
||||
* When the pool is freed, all finalizers registered by
|
||||
* #gu_pool_finally on \p pool are invoked in reverse order of
|
||||
* registration.
|
||||
*
|
||||
* @note After the pool is freed, all objects allocated from it become
|
||||
* invalid and may no longer be used. */
|
||||
|
||||
//@}
|
||||
/// @name Allocating from a pool
|
||||
//@{
|
||||
|
||||
|
||||
/// Allocate memory with a specified alignment.
|
||||
GU_API_DECL void*
|
||||
gu_malloc_aligned(GuPool* pool, size_t size, size_t alignment);
|
||||
|
||||
GU_API_DECL void*
|
||||
gu_malloc_prefixed(GuPool* pool, size_t pre_align, size_t pre_size,
|
||||
size_t align, size_t size);
|
||||
|
||||
/// Allocate memory from a pool.
|
||||
inline void*
|
||||
gu_malloc(GuPool* pool, size_t size) {
|
||||
return gu_malloc_aligned(pool, size, 0);
|
||||
}
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/** Allocate memory to store an array of objects of a given type. */
|
||||
|
||||
#define gu_new_n(type, n, pool) \
|
||||
((type*)gu_malloc_aligned((pool), \
|
||||
sizeof(type) * (n), \
|
||||
gu_alignof(type)))
|
||||
/**<
|
||||
* @param type The C type of the objects to allocate.
|
||||
*
|
||||
* @param n The number of objects to allocate.
|
||||
*
|
||||
* @param pool The memory pool to allocate from.
|
||||
*
|
||||
* @return A pointer to a heap-allocated array of \p n uninitialized
|
||||
* objects of type \p type.
|
||||
*/
|
||||
|
||||
|
||||
/** Allocate memory to store an object of a given type. */
|
||||
|
||||
#define gu_new(type, pool) \
|
||||
gu_new_n(type, 1, pool)
|
||||
/**<
|
||||
* @param type The C type of the object to allocate.
|
||||
*
|
||||
* @param pool The memory pool to allocate from.
|
||||
*
|
||||
* @return A pointer to a heap-allocated uninitialized object of type
|
||||
* \p type.
|
||||
*/
|
||||
|
||||
|
||||
#define gu_new_prefixed(pre_type, type, pool) \
|
||||
((type*)(gu_malloc_prefixed((pool), \
|
||||
gu_alignof(pre_type), sizeof(pre_type), \
|
||||
gu_alignof(type), sizeof(type))))
|
||||
|
||||
// Alas, there's no portable way to get the alignment of flex structs.
|
||||
#define gu_new_flex(pool_, type_, flex_member_, n_elems_) \
|
||||
((type_ *)gu_malloc_aligned( \
|
||||
(pool_), \
|
||||
GU_FLEX_SIZE(type_, flex_member_, n_elems_), \
|
||||
gu_flex_alignof(type_)))
|
||||
|
||||
|
||||
//@}
|
||||
/// @name Finalizers
|
||||
//@{
|
||||
|
||||
|
||||
typedef struct GuFinalizer GuFinalizer;
|
||||
|
||||
struct GuFinalizer {
|
||||
void (*fn)(GuFinalizer* self);
|
||||
///< @param self A pointer to this finalizer.
|
||||
};
|
||||
|
||||
/// Register a finalizer.
|
||||
GU_API_DECL void gu_pool_finally(GuPool* pool, GuFinalizer* fini);
|
||||
|
||||
/**< Register \p fini to be called when \p pool is destroyed. The
|
||||
* finalizers are called in reverse order of registration.
|
||||
*/
|
||||
|
||||
|
||||
//@}
|
||||
//@}
|
||||
|
||||
/** @defgroup GuMemBuf Memory buffers
|
||||
*
|
||||
* Resizable blocks of heap-allocated memory. These operations differ
|
||||
* from standard \c malloc, \c realloc and \c free -functions in that
|
||||
* memory buffers are not allocated by exact size. Instead, a minimum
|
||||
* size is requested, and the returned buffer may be larger. This
|
||||
* gives the memory allocator more flexibility when the client code
|
||||
* can make use of larger buffers than requested.
|
||||
* */
|
||||
|
||||
//@{
|
||||
|
||||
|
||||
/// Allocate a new memory buffer.
|
||||
GU_API_DECL void*
|
||||
gu_mem_buf_alloc(size_t min_size, size_t* real_size);
|
||||
/**<
|
||||
* @param min_size The minimum acceptable size for a returned memory block.
|
||||
*
|
||||
* @param[out] real_size The actual size of the returned memory
|
||||
* block. This is never less than \p min_size.
|
||||
*
|
||||
* @return A pointer to the memory buffer.
|
||||
*/
|
||||
|
||||
|
||||
/// Allocate a new memory buffer to replace an old one.
|
||||
GU_API_DECL void*
|
||||
gu_mem_buf_realloc(
|
||||
GU_NULL GU_ONLY GU_RETURNED
|
||||
void* buf,
|
||||
size_t min_size,
|
||||
size_t* real_size_out);
|
||||
|
||||
/// Allocate enough memory pages to contain min_size bytes.
|
||||
GU_API_DECL void*
|
||||
gu_mem_page_alloc(size_t min_size, size_t* real_size_out);
|
||||
|
||||
/// Free a memory buffer.
|
||||
GU_API_DECL void
|
||||
gu_mem_buf_free(GU_ONLY void* buf);
|
||||
|
||||
|
||||
//@}
|
||||
|
||||
|
||||
#endif // GU_MEM_H_
|
||||
@@ -1,303 +0,0 @@
|
||||
#include <gu/seq.h>
|
||||
#include <gu/out.h>
|
||||
#include <gu/utf8.h>
|
||||
#include <gu/bits.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static bool
|
||||
gu_out_is_buffering(GuOut* out)
|
||||
{
|
||||
return !!out->buf_end;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gu_out_end_buf(GuOut* out, GuExn* err)
|
||||
{
|
||||
if (!gu_out_is_buffering(out)) {
|
||||
return;
|
||||
}
|
||||
GuOutStream* stream = out->stream;
|
||||
size_t curr_len = ((ptrdiff_t)out->buf_size) + out->buf_curr;
|
||||
stream->end_buf(stream, curr_len, err);
|
||||
out->buf_end = NULL;
|
||||
out->buf_size = out->buf_curr = 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
gu_out_begin_buf(GuOut* out, size_t req, GuExn* err)
|
||||
{
|
||||
GuOutStream* stream = out->stream;
|
||||
if (gu_out_is_buffering(out)) {
|
||||
if (out->buf_curr < 0) {
|
||||
return true;
|
||||
} else {
|
||||
gu_out_end_buf(out, err);
|
||||
if (!gu_ok(err)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (stream->begin_buf) {
|
||||
size_t sz = 0;
|
||||
uint8_t* buf = stream->begin_buf(stream, req, &sz, err);
|
||||
gu_assert(sz <= PTRDIFF_MAX);
|
||||
if (buf) {
|
||||
out->buf_end = &buf[sz];
|
||||
out->buf_curr = -(ptrdiff_t) sz;
|
||||
out->buf_size = sz;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
gu_out_fini(GuFinalizer* self)
|
||||
{
|
||||
GuOut* out = gu_container(self, GuOut, fini);
|
||||
if (gu_out_is_buffering(out)) {
|
||||
GuPool* pool = gu_local_pool();
|
||||
GuExn* err = gu_new_exn(pool);
|
||||
gu_out_end_buf(out, err);
|
||||
gu_pool_free(pool);
|
||||
}
|
||||
}
|
||||
|
||||
GU_API GuOut*
|
||||
gu_new_out(GuOutStream* stream, GuPool* pool)
|
||||
{
|
||||
gu_require(stream != NULL);
|
||||
|
||||
GuOut* out = gu_new(GuOut, pool);
|
||||
out->buf_end = NULL,
|
||||
out->buf_curr = 0,
|
||||
out->stream = stream,
|
||||
out->fini.fn = gu_out_fini;
|
||||
gu_pool_finally(pool, &out->fini);
|
||||
return out;
|
||||
}
|
||||
|
||||
extern inline bool
|
||||
gu_out_try_buf_(GuOut* out, const uint8_t* src, size_t len);
|
||||
|
||||
extern inline size_t
|
||||
gu_out_bytes(GuOut* out, const uint8_t* buf, size_t len, GuExn* err);
|
||||
|
||||
static size_t
|
||||
gu_out_output(GuOut* out, const uint8_t* src, size_t len, GuExn* err)
|
||||
{
|
||||
gu_out_end_buf(out, err);
|
||||
if (!gu_ok(err)) {
|
||||
return 0;
|
||||
}
|
||||
return out->stream->output(out->stream, src, len, err);
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_out_flush(GuOut* out, GuExn* err)
|
||||
{
|
||||
GuOutStream* stream = out->stream;
|
||||
if (out->buf_end) {
|
||||
gu_out_end_buf(out, err);
|
||||
if (!gu_ok(err)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (stream->flush) {
|
||||
stream->flush(stream, err);
|
||||
}
|
||||
}
|
||||
|
||||
GU_API uint8_t*
|
||||
gu_out_begin_span(GuOut* out, size_t req, size_t* sz_out, GuExn* err)
|
||||
{
|
||||
if (!out->buf_end && !gu_out_begin_buf(out, req, err)) {
|
||||
return NULL;
|
||||
}
|
||||
*sz_out = -out->buf_curr;
|
||||
return &out->buf_end[out->buf_curr];
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_out_end_span(GuOut* out, size_t sz)
|
||||
{
|
||||
ptrdiff_t new_curr = (ptrdiff_t) sz + out->buf_curr;
|
||||
gu_require(new_curr <= 0);
|
||||
out->buf_curr = new_curr;
|
||||
}
|
||||
|
||||
GU_API size_t
|
||||
gu_out_bytes_(GuOut* restrict out, const uint8_t* restrict src, size_t len,
|
||||
GuExn* err)
|
||||
{
|
||||
if (!gu_ok(err)) {
|
||||
return 0;
|
||||
} else if (gu_out_try_buf_(out, src, len)) {
|
||||
return len;
|
||||
}
|
||||
if (gu_out_begin_buf(out, len, err)) {
|
||||
if (gu_out_try_buf_(out, src, len)) {
|
||||
return len;
|
||||
}
|
||||
}
|
||||
return gu_out_output(out, src, len, err);
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_out_u8_(GuOut* restrict out, uint8_t u, GuExn* err)
|
||||
{
|
||||
if (gu_out_begin_buf(out, 1, err)) {
|
||||
if (gu_out_try_u8_(out, u)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
gu_out_output(out, &u, 1, err);
|
||||
}
|
||||
|
||||
extern inline void
|
||||
gu_out_u8(GuOut* restrict out, uint8_t u, GuExn* err);
|
||||
|
||||
extern inline void
|
||||
gu_out_s8(GuOut* restrict out, int8_t i, GuExn* err);
|
||||
|
||||
extern inline bool
|
||||
gu_out_is_buffered(GuOut* out);
|
||||
|
||||
extern inline bool
|
||||
gu_out_try_u8_(GuOut* restrict out, uint8_t u);
|
||||
|
||||
GU_API void
|
||||
gu_out_u16be(GuOut* out, uint16_t u, GuExn* err)
|
||||
{
|
||||
gu_out_u8(out, (u>>8) & 0xFF, err);
|
||||
gu_out_u8(out, u & 0xFF, err);
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_out_u64be(GuOut* out, uint64_t u, GuExn* err)
|
||||
{
|
||||
gu_out_u8(out, (u>>56) & 0xFF, err);
|
||||
gu_out_u8(out, (u>>48) & 0xFF, err);
|
||||
gu_out_u8(out, (u>>40) & 0xFF, err);
|
||||
gu_out_u8(out, (u>>32) & 0xFF, err);
|
||||
gu_out_u8(out, (u>>24) & 0xFF, err);
|
||||
gu_out_u8(out, (u>>16) & 0xFF, err);
|
||||
gu_out_u8(out, (u>>8) & 0xFF, err);
|
||||
gu_out_u8(out, u & 0xFF, err);
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_out_f64be(GuOut* out, double d, GuExn* err)
|
||||
{
|
||||
gu_out_u64be(out, gu_encode_double(d), err);
|
||||
}
|
||||
|
||||
typedef struct GuBufferedOutStream GuBufferedOutStream;
|
||||
|
||||
struct GuBufferedOutStream {
|
||||
GuOutStream stream;
|
||||
GuOut* real_out;
|
||||
size_t sz;
|
||||
uint8_t buf[];
|
||||
};
|
||||
|
||||
static uint8_t*
|
||||
gu_buffered_out_buf_begin(GuOutStream* self, size_t req, size_t* sz_out,
|
||||
GuExn* err)
|
||||
{
|
||||
(void) (req && err);
|
||||
GuBufferedOutStream* b =
|
||||
gu_container(self, GuBufferedOutStream, stream);
|
||||
*sz_out = b->sz;
|
||||
return b->buf;
|
||||
}
|
||||
|
||||
static void
|
||||
gu_buffered_out_buf_end(GuOutStream* self, size_t sz, GuExn* err)
|
||||
{
|
||||
GuBufferedOutStream* b =
|
||||
gu_container(self, GuBufferedOutStream, stream);
|
||||
gu_require(sz <= b->sz);
|
||||
gu_out_bytes(b->real_out, b->buf, sz, err);
|
||||
}
|
||||
|
||||
static size_t
|
||||
gu_buffered_out_output(GuOutStream* self, const uint8_t* src, size_t sz,
|
||||
GuExn* err)
|
||||
{
|
||||
GuBufferedOutStream* bos =
|
||||
gu_container(self, GuBufferedOutStream, stream);
|
||||
return gu_out_bytes(bos->real_out, src, sz, err);
|
||||
}
|
||||
|
||||
static void
|
||||
gu_buffered_out_flush(GuOutStream* self, GuExn* err)
|
||||
{
|
||||
GuBufferedOutStream* bos =
|
||||
gu_container(self, GuBufferedOutStream, stream);
|
||||
gu_out_flush(bos->real_out, err);
|
||||
}
|
||||
|
||||
GU_API GuOut*
|
||||
gu_new_buffered_out(GuOut* out, size_t sz, GuPool* pool)
|
||||
{
|
||||
GuBufferedOutStream* b =
|
||||
gu_new_flex(pool, GuBufferedOutStream, buf, sz);
|
||||
b->stream = (GuOutStream) {
|
||||
.begin_buf = gu_buffered_out_buf_begin,
|
||||
.end_buf = gu_buffered_out_buf_end,
|
||||
.output = gu_buffered_out_output,
|
||||
.flush = gu_buffered_out_flush
|
||||
};
|
||||
b->real_out = out;
|
||||
b->sz = sz;
|
||||
return gu_new_out(&b->stream, pool);
|
||||
}
|
||||
|
||||
GU_API GuOut*
|
||||
gu_out_buffered(GuOut* out, GuPool* pool)
|
||||
{
|
||||
if (gu_out_is_buffered(out)) {
|
||||
return out;
|
||||
}
|
||||
return gu_new_buffered_out(out, 4096, pool);
|
||||
}
|
||||
|
||||
|
||||
extern inline void
|
||||
gu_putc(char c, GuOut* out, GuExn* err);
|
||||
|
||||
GU_API void
|
||||
gu_puts(const char* str, GuOut* out, GuExn* err)
|
||||
{
|
||||
gu_out_bytes(out, (const uint8_t*) str, strlen(str), err);
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_vprintf(const char* fmt, va_list args, GuOut* out, GuExn* err)
|
||||
{
|
||||
GuPool* tmp_pool = gu_local_pool();
|
||||
|
||||
va_list args2;
|
||||
va_copy(args2, args);
|
||||
int len = vsnprintf(NULL, 0, fmt, args2);
|
||||
gu_assert_msg(len >= 0, "Invalid format string: \"%s\"", fmt);
|
||||
va_end(args2);
|
||||
char* str = gu_new_n(char, len + 1, tmp_pool);
|
||||
vsnprintf(str, len + 1, fmt, args);
|
||||
|
||||
gu_out_bytes(out, (const uint8_t*) str, strlen(str), err);
|
||||
gu_pool_free(tmp_pool);
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_printf(GuOut* out, GuExn* err, const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
gu_vprintf(fmt, args, out, err);
|
||||
va_end(args);
|
||||
}
|
||||
@@ -1,174 +0,0 @@
|
||||
#ifndef GU_OUT_H_
|
||||
#define GU_OUT_H_
|
||||
|
||||
#include <gu/defs.h>
|
||||
#include <gu/assert.h>
|
||||
#include <gu/exn.h>
|
||||
#include <gu/ucs.h>
|
||||
|
||||
typedef struct GuOut GuOut;
|
||||
|
||||
typedef struct GuOutStream GuOutStream;
|
||||
|
||||
struct GuOutStream {
|
||||
uint8_t* (*begin_buf)(GuOutStream* self, size_t req, size_t* sz_out,
|
||||
GuExn* err);
|
||||
void (*end_buf)(GuOutStream* self, size_t span, GuExn* err);
|
||||
size_t (*output)(GuOutStream* self, const uint8_t* buf, size_t size,
|
||||
GuExn* err);
|
||||
void (*flush)(GuOutStream* self, GuExn* err);
|
||||
};
|
||||
|
||||
|
||||
struct GuOut {
|
||||
uint8_t* restrict buf_end;
|
||||
ptrdiff_t buf_curr;
|
||||
size_t buf_size;
|
||||
GuOutStream* stream;
|
||||
GuFinalizer fini;
|
||||
};
|
||||
|
||||
GU_API_DECL GuOut*
|
||||
gu_new_out(GuOutStream* stream, GuPool* pool);
|
||||
|
||||
inline bool
|
||||
gu_out_is_buffered(GuOut* out)
|
||||
{
|
||||
return !!out->stream->begin_buf;
|
||||
}
|
||||
|
||||
GU_API_DECL GuOut*
|
||||
gu_new_buffered_out(GuOut* out, size_t buf_sz, GuPool* pool);
|
||||
|
||||
GU_API_DECL GuOut*
|
||||
gu_out_buffered(GuOut* out, GuPool* pool);
|
||||
|
||||
GU_API_DECL uint8_t*
|
||||
gu_out_begin_span(GuOut* out, size_t req, size_t* sz_out, GuExn* err);
|
||||
|
||||
GU_API_DECL uint8_t*
|
||||
gu_out_force_span(GuOut* out, size_t min, size_t max, size_t* sz_out,
|
||||
GuExn* err);
|
||||
|
||||
GU_API_DECL void
|
||||
gu_out_end_span(GuOut* out, size_t sz);
|
||||
|
||||
GU_API_DECL size_t
|
||||
gu_out_bytes_(GuOut* restrict out, const uint8_t* restrict src,
|
||||
size_t len, GuExn* err);
|
||||
|
||||
inline bool
|
||||
gu_out_try_buf_(GuOut* restrict out, const uint8_t* restrict src, size_t len)
|
||||
{
|
||||
gu_require(len <= PTRDIFF_MAX);
|
||||
ptrdiff_t curr = out->buf_curr;
|
||||
ptrdiff_t new_curr = curr + (ptrdiff_t) len;
|
||||
if (GU_UNLIKELY(new_curr > 0)) {
|
||||
return false;
|
||||
}
|
||||
memcpy(&out->buf_end[curr], src, len);
|
||||
out->buf_curr = new_curr;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline size_t
|
||||
gu_out_bytes(GuOut* restrict out, const uint8_t* restrict src, size_t len,
|
||||
GuExn* err)
|
||||
{
|
||||
if (GU_LIKELY(gu_out_try_buf_(out, src, len))) {
|
||||
return len;
|
||||
}
|
||||
return gu_out_bytes_(out, src, len, err);
|
||||
}
|
||||
|
||||
GU_API_DECL void
|
||||
gu_out_flush(GuOut* out, GuExn* err);
|
||||
|
||||
inline bool
|
||||
gu_out_try_u8_(GuOut* restrict out, uint8_t u)
|
||||
{
|
||||
ptrdiff_t curr = out->buf_curr;
|
||||
ptrdiff_t new_curr = curr + 1;
|
||||
if (GU_UNLIKELY(new_curr > 0)) {
|
||||
return false;
|
||||
}
|
||||
out->buf_end[curr] = u;
|
||||
out->buf_curr = new_curr;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void
|
||||
gu_out_u8(GuOut* restrict out, uint8_t u, GuExn* err)
|
||||
{
|
||||
if (GU_UNLIKELY(!gu_out_try_u8_(out, u))) {
|
||||
GU_API_DECL void gu_out_u8_(GuOut* restrict out, uint8_t u,
|
||||
GuExn* err);
|
||||
gu_out_u8_(out, u, err);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
gu_out_s8(GuOut* restrict out, int8_t i, GuExn* err)
|
||||
{
|
||||
gu_out_u8(out, (uint8_t) i, err);
|
||||
}
|
||||
|
||||
GU_API_DECL void
|
||||
gu_out_u16le(GuOut* out, uint16_t u, GuExn* err);
|
||||
|
||||
GU_API_DECL void
|
||||
gu_out_u16be(GuOut* out, uint16_t u, GuExn* err);
|
||||
|
||||
GU_API_DECL void
|
||||
gu_out_s16le(GuOut* out, int16_t u, GuExn* err);
|
||||
|
||||
GU_API_DECL void
|
||||
gu_out_s16be(GuOut* out, int16_t u, GuExn* err);
|
||||
|
||||
GU_API_DECL void
|
||||
gu_out_u32le(GuOut* out, uint32_t u, GuExn* err);
|
||||
|
||||
GU_API_DECL void
|
||||
gu_out_u32be(GuOut* out, uint32_t u, GuExn* err);
|
||||
|
||||
GU_API_DECL void
|
||||
gu_out_s32le(GuOut* out, int32_t u, GuExn* err);
|
||||
|
||||
GU_API_DECL void
|
||||
gu_out_s32be(GuOut* out, int32_t u, GuExn* err);
|
||||
|
||||
GU_API_DECL void
|
||||
gu_out_u64le(GuOut* out, uint64_t u, GuExn* err);
|
||||
|
||||
GU_API_DECL void
|
||||
gu_out_u64be(GuOut* out, uint64_t u, GuExn* err);
|
||||
|
||||
GU_API_DECL void
|
||||
gu_out_s64le(GuOut* out, int64_t u, GuExn* err);
|
||||
|
||||
GU_API_DECL void
|
||||
gu_out_s64be(GuOut* out, int64_t u, GuExn* err);
|
||||
|
||||
GU_API_DECL void
|
||||
gu_out_f64le(GuOut* out, double d, GuExn* err);
|
||||
|
||||
GU_API_DECL void
|
||||
gu_out_f64be(GuOut* out, double d, GuExn* err);
|
||||
|
||||
inline void
|
||||
gu_putc(char c, GuOut* out, GuExn* err)
|
||||
{
|
||||
GuUCS ucs = gu_char_ucs(c);
|
||||
gu_out_u8(out, (uint8_t) ucs, err);
|
||||
}
|
||||
|
||||
GU_API_DECL void
|
||||
gu_puts(const char* str, GuOut* out, GuExn* err);
|
||||
|
||||
GU_API_DECL void
|
||||
gu_vprintf(const char* fmt, va_list args, GuOut* out, GuExn* err);
|
||||
|
||||
GU_API_DECL void
|
||||
gu_printf(GuOut* out, GuExn* err, const char* fmt, ...);
|
||||
|
||||
#endif // GU_OUT_H_
|
||||
@@ -1,154 +0,0 @@
|
||||
#include <gu/defs.h>
|
||||
#include <gu/assert.h>
|
||||
|
||||
static const uint32_t gu_prime_wheel_mask = 0UL
|
||||
| 1 << 1
|
||||
| 1 << 7
|
||||
| 1 << 11
|
||||
| 1 << 13
|
||||
| 1 << 17
|
||||
| 1 << 19
|
||||
| 1 << 23
|
||||
| 1 << 29;
|
||||
|
||||
static bool
|
||||
gu_prime_wheel(int i)
|
||||
{
|
||||
gu_assert(i >= 0 && i < 30);
|
||||
return !!(gu_prime_wheel_mask & (1 << i));
|
||||
}
|
||||
|
||||
static const uint32_t gu_small_prime_mask = 0UL
|
||||
| 1 << 2
|
||||
| 1 << 3
|
||||
| 1 << 5
|
||||
| 1 << 7
|
||||
| 1 << 11
|
||||
| 1 << 13
|
||||
| 1 << 17
|
||||
| 1 << 19
|
||||
| 1 << 23
|
||||
| 1 << 29
|
||||
| 1U << 31;
|
||||
|
||||
static bool
|
||||
gu_is_wheel_prime(int u)
|
||||
{
|
||||
gu_assert(u > 30 && u % 2 != 0 && u % 3 != 0 && u % 5 != 0);
|
||||
int d = 0;
|
||||
int i = 7;
|
||||
goto start;
|
||||
while (d * d <= u) {
|
||||
for (i = 1; i <= 29; i+=2) {
|
||||
start:
|
||||
if (gu_prime_wheel(i) && u % (d + i) == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
d += 30;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
GU_INTERNAL int
|
||||
gu_prime_inf(int i)
|
||||
{
|
||||
if (i < 2) {
|
||||
return 0;
|
||||
} else if (i < 32) {
|
||||
while (!(gu_small_prime_mask & (1 << i))) {
|
||||
i--;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
int d = (i - 1) | 1;
|
||||
int r = d % 30;
|
||||
|
||||
while (!gu_prime_wheel(r) || !gu_is_wheel_prime(d)) {
|
||||
d -= 2;
|
||||
r -= 2;
|
||||
if (r < 0) {
|
||||
r += 30;
|
||||
}
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
GU_INTERNAL int
|
||||
gu_prime_sup(int i)
|
||||
{
|
||||
if (i <= 2) {
|
||||
return 2;
|
||||
} else if (i < 32) {
|
||||
while (!(gu_small_prime_mask & (1 << i))) {
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
int d = i | 1;
|
||||
int r = d % 30;
|
||||
|
||||
while (!gu_prime_wheel(r) || !gu_is_wheel_prime(d)) {
|
||||
d += 2;
|
||||
r += 2;
|
||||
if (r > 30) {
|
||||
r -= 30;
|
||||
}
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
GU_INTERNAL bool
|
||||
gu_is_prime(int i)
|
||||
{
|
||||
if (i < 2) {
|
||||
return false;
|
||||
} else if (i < 30) {
|
||||
return !!(gu_small_prime_mask & (1 << i));
|
||||
} else if (!gu_prime_wheel(i % 30)) {
|
||||
return false;
|
||||
} else {
|
||||
return gu_is_wheel_prime(i);
|
||||
}
|
||||
}
|
||||
|
||||
GU_INTERNAL bool
|
||||
gu_is_twin_prime(int i)
|
||||
{
|
||||
return gu_is_prime(i) && gu_is_prime(i - 2);
|
||||
}
|
||||
|
||||
GU_INTERNAL int
|
||||
gu_twin_prime_inf(int i)
|
||||
{
|
||||
while (true) {
|
||||
i = gu_prime_inf(i);
|
||||
if (i == 0) {
|
||||
return 0;
|
||||
} else if (gu_is_prime(i - 2)) {
|
||||
return i;
|
||||
}
|
||||
i = i - 4;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
GU_INTERNAL int
|
||||
gu_twin_prime_sup(int i)
|
||||
{
|
||||
if (i <= 5) {
|
||||
return 5;
|
||||
}
|
||||
i = i - 2;
|
||||
while (true) {
|
||||
i = gu_prime_sup(i);
|
||||
if (gu_is_prime(i + 2)) {
|
||||
return i + 2;
|
||||
}
|
||||
i = i + 4;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
#ifndef GU_PRIME_H_
|
||||
#define GU_PRIME_H_
|
||||
|
||||
#include <gu/defs.h>
|
||||
|
||||
GU_INTERNAL_DECL bool gu_is_prime(int i);
|
||||
|
||||
GU_INTERNAL_DECL bool gu_is_twin_prime(int i);
|
||||
|
||||
GU_INTERNAL_DECL int gu_prime_inf(int i);
|
||||
GU_INTERNAL_DECL int gu_twin_prime_inf(int i);
|
||||
|
||||
GU_INTERNAL_DECL int gu_prime_sup(int i);
|
||||
GU_INTERNAL_DECL int gu_twin_prime_sup(int i);
|
||||
|
||||
#endif // GU_PRIME_H_
|
||||
@@ -1,386 +0,0 @@
|
||||
#include <gu/out.h>
|
||||
#include <gu/seq.h>
|
||||
#include <gu/fun.h>
|
||||
#include <gu/assert.h>
|
||||
#include <stdlib.h>
|
||||
#if defined(__MINGW32__) || defined(_MSC_VER)
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
static void
|
||||
gu_buf_fini(GuFinalizer* fin)
|
||||
{
|
||||
GuBuf* buf = gu_container(fin, GuBuf, fin);
|
||||
if (buf->avail_len > 0)
|
||||
gu_mem_buf_free(buf->seq);
|
||||
}
|
||||
|
||||
GU_API GuBuf*
|
||||
gu_make_buf(size_t elem_size, GuPool* pool)
|
||||
{
|
||||
GuBuf* buf = gu_new(GuBuf, pool);
|
||||
buf->seq = gu_empty_seq();
|
||||
buf->elem_size = elem_size;
|
||||
buf->avail_len = 0;
|
||||
buf->fin.fn = gu_buf_fini;
|
||||
gu_pool_finally(pool, &buf->fin);
|
||||
return buf;
|
||||
}
|
||||
|
||||
extern size_t
|
||||
gu_buf_length(GuBuf* buf);
|
||||
|
||||
extern size_t
|
||||
gu_buf_avail(GuBuf* buf);
|
||||
|
||||
extern void*
|
||||
gu_buf_data(GuBuf* buf);
|
||||
|
||||
extern GuSeq*
|
||||
gu_buf_data_seq(GuBuf* buf);
|
||||
|
||||
extern void*
|
||||
gu_buf_extend(GuBuf* buf);
|
||||
|
||||
extern const void*
|
||||
gu_buf_trim(GuBuf* buf);
|
||||
|
||||
extern void
|
||||
gu_buf_flush(GuBuf* buf);
|
||||
|
||||
static GuSeq gu_empty_seq_ = {0};
|
||||
|
||||
GU_API GuSeq*
|
||||
gu_empty_seq() {
|
||||
return &gu_empty_seq_;
|
||||
}
|
||||
|
||||
GU_API GuSeq*
|
||||
gu_make_seq(size_t elem_size, size_t length, GuPool* pool)
|
||||
{
|
||||
GuSeq* seq = gu_malloc(pool, sizeof(GuSeq) + elem_size * length);
|
||||
seq->len = length;
|
||||
return seq;
|
||||
}
|
||||
|
||||
extern size_t
|
||||
gu_seq_length(GuSeq* seq);
|
||||
|
||||
extern void*
|
||||
gu_seq_data(GuSeq* seq);
|
||||
|
||||
GU_API GuSeq*
|
||||
gu_alloc_seq_(size_t elem_size, size_t length)
|
||||
{
|
||||
if (length == 0)
|
||||
return gu_empty_seq();
|
||||
|
||||
size_t real_size;
|
||||
GuSeq* seq = gu_mem_buf_alloc(sizeof(GuSeq) + elem_size * length, &real_size);
|
||||
seq->len = (real_size - sizeof(GuSeq)) / elem_size;
|
||||
return seq;
|
||||
}
|
||||
|
||||
GU_API GuSeq*
|
||||
gu_realloc_seq_(GuSeq* seq, size_t elem_size, size_t length)
|
||||
{
|
||||
size_t real_size;
|
||||
GuSeq* new_seq = (seq == NULL || seq == gu_empty_seq()) ?
|
||||
gu_mem_buf_alloc(sizeof(GuSeq) + elem_size * length, &real_size) :
|
||||
gu_mem_buf_realloc(seq, sizeof(GuSeq) + elem_size * length, &real_size);
|
||||
new_seq->len = (real_size - sizeof(GuSeq)) / elem_size;
|
||||
return new_seq;
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_seq_free(GuSeq* seq)
|
||||
{
|
||||
if (seq == NULL || seq == gu_empty_seq())
|
||||
return;
|
||||
gu_mem_buf_free(seq);
|
||||
}
|
||||
|
||||
static void
|
||||
gu_dummy_finalizer(GuFinalizer* self)
|
||||
{
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_buf_require(GuBuf* buf, size_t req_len)
|
||||
{
|
||||
if (req_len <= buf->avail_len) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t req_size = sizeof(GuSeq) + buf->elem_size * req_len;
|
||||
size_t real_size;
|
||||
|
||||
gu_require(buf->fin.fn != gu_dummy_finalizer);
|
||||
|
||||
if (buf->seq == NULL || buf->seq == gu_empty_seq()) {
|
||||
buf->seq = gu_mem_buf_alloc(req_size, &real_size);
|
||||
buf->seq->len = 0;
|
||||
} else {
|
||||
buf->seq = gu_mem_buf_realloc(buf->seq, req_size, &real_size);
|
||||
}
|
||||
|
||||
buf->avail_len = (real_size - sizeof(GuSeq)) / buf->elem_size;
|
||||
}
|
||||
|
||||
GU_API void*
|
||||
gu_buf_extend_n(GuBuf* buf, size_t n_elems)
|
||||
{
|
||||
size_t len = gu_buf_length(buf);
|
||||
size_t new_len = len + n_elems;
|
||||
gu_buf_require(buf, new_len);
|
||||
buf->seq->len = new_len;
|
||||
return &buf->seq->data[buf->elem_size * len];
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_buf_push_n(GuBuf* buf, const void* data, size_t n_elems)
|
||||
{
|
||||
void* p = gu_buf_extend_n(buf, n_elems);
|
||||
memcpy(p, data, buf->elem_size * n_elems);
|
||||
}
|
||||
|
||||
GU_API const void*
|
||||
gu_buf_trim_n(GuBuf* buf, size_t n_elems)
|
||||
{
|
||||
gu_require(n_elems <= gu_buf_length(buf));
|
||||
size_t new_len = gu_buf_length(buf) - n_elems;
|
||||
buf->seq->len = new_len;
|
||||
return &buf->seq->data[buf->elem_size * new_len];
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_buf_pop_n(GuBuf* buf, size_t n_elems, void* data_out)
|
||||
{
|
||||
const void* p = gu_buf_trim_n(buf, n_elems);
|
||||
memcpy(data_out, p, buf->elem_size * n_elems);
|
||||
}
|
||||
|
||||
GU_API GuSeq*
|
||||
gu_buf_freeze(GuBuf* buf, GuPool* pool)
|
||||
{
|
||||
size_t len = gu_buf_length(buf);
|
||||
GuSeq* seq = gu_make_seq(buf->elem_size, len, pool);
|
||||
void* bufdata = gu_buf_data(buf);
|
||||
void* seqdata = gu_seq_data(seq);
|
||||
memcpy(seqdata, bufdata, buf->elem_size * len);
|
||||
return seq;
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_buf_evacuate(GuBuf* buf, GuPool* pool)
|
||||
{
|
||||
if (buf->seq != gu_empty_seq()) {
|
||||
size_t len = gu_buf_length(buf);
|
||||
|
||||
GuSeq* seq = gu_make_seq(buf->elem_size, len, pool);
|
||||
void* bufdata = gu_buf_data(buf);
|
||||
void* seqdata = gu_seq_data(seq);
|
||||
memcpy(seqdata, bufdata, buf->elem_size * len);
|
||||
gu_mem_buf_free(buf->seq);
|
||||
|
||||
buf->seq = seq;
|
||||
buf->fin.fn = gu_dummy_finalizer;
|
||||
buf->avail_len = len;
|
||||
}
|
||||
}
|
||||
|
||||
GU_API void*
|
||||
gu_buf_insert(GuBuf* buf, size_t index)
|
||||
{
|
||||
size_t len = buf->seq->len;
|
||||
gu_buf_require(buf, len + 1);
|
||||
|
||||
uint8_t* target =
|
||||
buf->seq->data + buf->elem_size * index;
|
||||
memmove(target+buf->elem_size, target, (len-index)*buf->elem_size);
|
||||
|
||||
buf->seq->len++;
|
||||
return target;
|
||||
}
|
||||
|
||||
static void
|
||||
gu_quick_sort(GuBuf *buf, GuOrder *order, int left, int right)
|
||||
{
|
||||
int l_hold = left;
|
||||
int r_hold = right;
|
||||
|
||||
void* pivot = alloca(buf->elem_size);
|
||||
memcpy(pivot,
|
||||
&buf->seq->data[buf->elem_size * left],
|
||||
buf->elem_size);
|
||||
while (left < right) {
|
||||
|
||||
while ((order->compare(order, &buf->seq->data[buf->elem_size * right], pivot) >= 0) && (left < right))
|
||||
right--;
|
||||
|
||||
if (left != right) {
|
||||
memcpy(&buf->seq->data[buf->elem_size * left],
|
||||
&buf->seq->data[buf->elem_size * right],
|
||||
buf->elem_size);
|
||||
left++;
|
||||
}
|
||||
|
||||
while ((order->compare(order, &buf->seq->data[buf->elem_size * left], pivot) <= 0) && (left < right))
|
||||
left++;
|
||||
|
||||
if (left != right) {
|
||||
memcpy(&buf->seq->data[buf->elem_size * right],
|
||||
&buf->seq->data[buf->elem_size * left],
|
||||
buf->elem_size);
|
||||
right--;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(&buf->seq->data[buf->elem_size * left],
|
||||
pivot,
|
||||
buf->elem_size);
|
||||
int index = left;
|
||||
left = l_hold;
|
||||
right = r_hold;
|
||||
|
||||
if (left < index)
|
||||
gu_quick_sort(buf, order, left, index-1);
|
||||
|
||||
if (right > index)
|
||||
gu_quick_sort(buf, order, index+1, right);
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_buf_sort(GuBuf *buf, GuOrder *order)
|
||||
{
|
||||
gu_quick_sort(buf, order, 0, gu_buf_length(buf) - 1);
|
||||
}
|
||||
|
||||
GU_API void*
|
||||
gu_seq_binsearch_(GuSeq *seq, GuOrder *order, size_t elem_size, const void *key)
|
||||
{
|
||||
int i = 0;
|
||||
int j = seq->len-1;
|
||||
|
||||
while (i <= j) {
|
||||
int k = (i+j) / 2;
|
||||
uint8_t* elem_p = &seq->data[elem_size * k];
|
||||
int cmp = order->compare(order, key, elem_p);
|
||||
|
||||
if (cmp < 0) {
|
||||
j = k-1;
|
||||
} else if (cmp > 0) {
|
||||
i = k+1;
|
||||
} else {
|
||||
return elem_p;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GU_API bool
|
||||
gu_seq_binsearch_index_(GuSeq *seq, GuOrder *order, size_t elem_size,
|
||||
const void *key, size_t *pindex)
|
||||
{
|
||||
size_t i = 0;
|
||||
size_t j = seq->len-1;
|
||||
|
||||
while (i <= j) {
|
||||
size_t k = (i+j) / 2;
|
||||
uint8_t* elem_p = &seq->data[elem_size * k];
|
||||
int cmp = order->compare(order, key, elem_p);
|
||||
|
||||
if (cmp < 0) {
|
||||
j = k-1;
|
||||
} else if (cmp > 0) {
|
||||
i = k+1;
|
||||
} else {
|
||||
*pindex = k;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
*pindex = j;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
gu_heap_siftdown(GuBuf *buf, GuOrder *order,
|
||||
const void *value, int startpos, int pos)
|
||||
{
|
||||
while (pos > startpos) {
|
||||
int parentpos = (pos - 1) >> 1;
|
||||
void *parent = &buf->seq->data[buf->elem_size * parentpos];
|
||||
|
||||
if (order->compare(order, value, parent) >= 0)
|
||||
break;
|
||||
|
||||
memcpy(&buf->seq->data[buf->elem_size * pos], parent, buf->elem_size);
|
||||
pos = parentpos;
|
||||
}
|
||||
|
||||
memcpy(&buf->seq->data[buf->elem_size * pos], value, buf->elem_size);
|
||||
}
|
||||
|
||||
static void
|
||||
gu_heap_siftup(GuBuf *buf, GuOrder *order,
|
||||
const void *value, int pos)
|
||||
{
|
||||
int startpos = pos;
|
||||
int endpos = gu_buf_length(buf);
|
||||
|
||||
int childpos = 2*pos + 1;
|
||||
while (childpos < endpos) {
|
||||
int rightpos = childpos + 1;
|
||||
if (rightpos < endpos &&
|
||||
order->compare(order,
|
||||
&buf->seq->data[buf->elem_size * childpos],
|
||||
&buf->seq->data[buf->elem_size * rightpos]) >= 0) {
|
||||
childpos = rightpos;
|
||||
}
|
||||
|
||||
memcpy(&buf->seq->data[buf->elem_size * pos],
|
||||
&buf->seq->data[buf->elem_size * childpos], buf->elem_size);
|
||||
pos = childpos;
|
||||
childpos = 2*pos + 1;
|
||||
}
|
||||
|
||||
gu_heap_siftdown(buf, order, value, startpos, pos);
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_buf_heap_push(GuBuf *buf, GuOrder *order, void *value)
|
||||
{
|
||||
gu_buf_extend(buf);
|
||||
gu_heap_siftdown(buf, order, value, 0, gu_buf_length(buf)-1);
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_buf_heap_pop(GuBuf *buf, GuOrder *order, void* data_out)
|
||||
{
|
||||
const void* last = gu_buf_trim(buf); // raises an error if empty
|
||||
memcpy(data_out, buf->seq->data, buf->elem_size);
|
||||
gu_heap_siftup(buf, order, last, 0);
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_buf_heap_replace(GuBuf *buf, GuOrder *order, void *value, void *data_out)
|
||||
{
|
||||
gu_require(gu_buf_length(buf) > 0);
|
||||
|
||||
memcpy(data_out, buf->seq->data, buf->elem_size);
|
||||
gu_heap_siftup(buf, order, value, 0);
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_buf_heapify(GuBuf *buf, GuOrder *order)
|
||||
{
|
||||
size_t middle = gu_buf_length(buf) / 2;
|
||||
void *value = alloca(buf->elem_size);
|
||||
|
||||
for (size_t i = 0; i < middle; i++) {
|
||||
memcpy(value, &buf->seq->data[buf->elem_size * i], buf->elem_size);
|
||||
gu_heap_siftup(buf, order, value, i);
|
||||
}
|
||||
}
|
||||
@@ -1,193 +0,0 @@
|
||||
#ifndef GU_SEQ_H_
|
||||
#define GU_SEQ_H_
|
||||
|
||||
#include <gu/mem.h>
|
||||
|
||||
typedef struct {
|
||||
size_t len;
|
||||
uint8_t data[0];
|
||||
} GuSeq;
|
||||
|
||||
typedef struct {
|
||||
GuSeq* seq;
|
||||
size_t elem_size;
|
||||
size_t avail_len;
|
||||
GuFinalizer fin;
|
||||
} GuBuf;
|
||||
|
||||
GU_API_DECL GuSeq*
|
||||
gu_empty_seq();
|
||||
|
||||
GU_API_DECL GuSeq*
|
||||
gu_make_seq(size_t elem_size, size_t len, GuPool* pool);
|
||||
|
||||
#define gu_new_seq(T, N, POOL) \
|
||||
gu_make_seq(sizeof(T), (N), (POOL))
|
||||
|
||||
GU_API_DECL GuSeq*
|
||||
gu_alloc_seq_(size_t elem_size, size_t length);
|
||||
|
||||
#define gu_alloc_seq(T, N) \
|
||||
gu_alloc_seq_(sizeof(T), (N))
|
||||
|
||||
GU_API_DECL GuSeq*
|
||||
gu_realloc_seq_(GuSeq* seq, size_t elem_size, size_t length);
|
||||
|
||||
#define gu_realloc_seq(S, T, N) \
|
||||
gu_realloc_seq_(S, sizeof(T), (N))
|
||||
|
||||
GU_API_DECL void
|
||||
gu_seq_free(GuSeq* seq);
|
||||
|
||||
inline size_t
|
||||
gu_seq_length(GuSeq* seq)
|
||||
{
|
||||
return seq->len;
|
||||
}
|
||||
|
||||
inline void*
|
||||
gu_seq_data(GuSeq* seq)
|
||||
{
|
||||
return seq->data;
|
||||
}
|
||||
|
||||
#define gu_seq_index(SEQ, T, I) \
|
||||
(&((T*)gu_seq_data(SEQ))[I])
|
||||
|
||||
#define gu_seq_get(SEQ, T, I) \
|
||||
(*gu_seq_index(SEQ, T, I))
|
||||
|
||||
#define gu_seq_set(SEQ, T, I, V) \
|
||||
GU_BEGIN \
|
||||
(*gu_seq_index(SEQ, T, I) = (V)); \
|
||||
GU_END
|
||||
|
||||
|
||||
GU_API_DECL GuBuf*
|
||||
gu_make_buf(size_t elem_size, GuPool* pool);
|
||||
|
||||
#define gu_new_buf(T, POOL) \
|
||||
gu_make_buf(sizeof(T), (POOL))
|
||||
|
||||
inline size_t
|
||||
gu_buf_length(GuBuf* buf)
|
||||
{
|
||||
return buf->seq->len;
|
||||
}
|
||||
|
||||
inline size_t
|
||||
gu_buf_avail(GuBuf* buf)
|
||||
{
|
||||
return buf->avail_len;
|
||||
}
|
||||
|
||||
inline void*
|
||||
gu_buf_data(GuBuf* buf)
|
||||
{
|
||||
return &buf->seq->data;
|
||||
}
|
||||
|
||||
inline GuSeq*
|
||||
gu_buf_data_seq(GuBuf* buf)
|
||||
{
|
||||
return buf->seq;
|
||||
}
|
||||
|
||||
#define gu_buf_index(BUF, T, I) \
|
||||
(&((T*)gu_buf_data(BUF))[I])
|
||||
|
||||
#define gu_buf_get(BUF, T, I) \
|
||||
(*gu_buf_index(BUF, T, I))
|
||||
|
||||
#define gu_buf_set(BUF, T, I, V) \
|
||||
GU_BEGIN \
|
||||
(*gu_buf_index(BUF, T, I) = (V)); \
|
||||
GU_END
|
||||
|
||||
GU_API_DECL void
|
||||
gu_buf_push_n(GuBuf* buf, const void* elems, size_t n_elems);
|
||||
|
||||
GU_API_DECL void*
|
||||
gu_buf_extend_n(GuBuf* buf, size_t n_elems);
|
||||
|
||||
inline void*
|
||||
gu_buf_extend(GuBuf* buf)
|
||||
{
|
||||
return gu_buf_extend_n(buf, 1);
|
||||
}
|
||||
|
||||
#define gu_buf_push(BUF, T, VAL) \
|
||||
GU_BEGIN \
|
||||
((*(T*)gu_buf_extend(BUF)) = (VAL)); \
|
||||
GU_END
|
||||
|
||||
GU_API_DECL void
|
||||
gu_buf_pop_n(GuBuf* buf, size_t n_elems, void* data_out);
|
||||
|
||||
#define gu_buf_get_last(BUF, T) \
|
||||
(((T*)gu_buf_data(BUF))[(BUF)->seq->len-1])
|
||||
|
||||
#define gu_buf_index_last(BUF, T) \
|
||||
(&((T*)gu_buf_data(BUF))[(BUF)->seq->len-1])
|
||||
|
||||
GU_API_DECL const void*
|
||||
gu_buf_trim_n(GuBuf* buf, size_t n_elems);
|
||||
|
||||
inline const void*
|
||||
gu_buf_trim(GuBuf* buf)
|
||||
{
|
||||
return gu_buf_trim_n(buf, 1);
|
||||
}
|
||||
|
||||
GU_API_DECL void*
|
||||
gu_buf_insert(GuBuf* buf, size_t n_index);
|
||||
|
||||
inline void
|
||||
gu_buf_flush(GuBuf* buf)
|
||||
{
|
||||
buf->seq->len = 0;
|
||||
}
|
||||
|
||||
#define gu_buf_pop(BUF, T) \
|
||||
(*(T*)gu_buf_trim(BUF))
|
||||
|
||||
GU_API_DECL void
|
||||
gu_buf_sort(GuBuf *buf, GuOrder *order);
|
||||
|
||||
#define gu_seq_binsearch(S, O, T, V) \
|
||||
((T*) gu_seq_binsearch_(S, O, sizeof(T), V))
|
||||
|
||||
GU_API_DECL void*
|
||||
gu_seq_binsearch_(GuSeq *seq, GuOrder *order, size_t elem_size, const void *key);
|
||||
|
||||
#define gu_seq_binsearch_index(S, O, T, V, PI) \
|
||||
gu_seq_binsearch_index_(S, O, sizeof(T), V, PI)
|
||||
|
||||
GU_API_DECL bool
|
||||
gu_seq_binsearch_index_(GuSeq *seq, GuOrder *order, size_t elem_size,
|
||||
const void *key, size_t *pindex);
|
||||
|
||||
// Using a buffer as a heap
|
||||
GU_API_DECL void
|
||||
gu_buf_heap_push(GuBuf *buf, GuOrder *order, void *value);
|
||||
|
||||
GU_API_DECL void
|
||||
gu_buf_heap_pop(GuBuf *buf, GuOrder *order, void* data_out);
|
||||
|
||||
GU_API_DECL void
|
||||
gu_buf_heap_replace(GuBuf *buf, GuOrder *order, void *value, void *data_out);
|
||||
|
||||
GU_API_DECL void
|
||||
gu_buf_heapify(GuBuf *buf, GuOrder *order);
|
||||
|
||||
GU_API_DECL GuSeq*
|
||||
gu_buf_freeze(GuBuf* buf, GuPool* pool);
|
||||
|
||||
GU_API_DECL void
|
||||
gu_buf_evacuate(GuBuf* buf, GuPool* pool);
|
||||
#endif // GU_SEQ_H_
|
||||
|
||||
#ifdef GU_STRING_H_
|
||||
GU_INTERNAL_DECL void
|
||||
gu_buf_require(GuBuf* buf, size_t req_len);
|
||||
#endif // GU_STRING_H_
|
||||
@@ -1,313 +0,0 @@
|
||||
#include <gu/out.h>
|
||||
#include <gu/map.h>
|
||||
#include <gu/string.h>
|
||||
#include <gu/seq.h>
|
||||
#include <gu/utf8.h>
|
||||
#include <gu/assert.h>
|
||||
#include <stdlib.h>
|
||||
#if defined(__MINGW32__) || defined(_MSC_VER)
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
struct GuStringBuf {
|
||||
GuOutStream stream;
|
||||
GuBuf* buf;
|
||||
GuOut* out;
|
||||
};
|
||||
|
||||
static size_t
|
||||
gu_string_buf_output(GuOutStream* stream, const uint8_t* src, size_t sz,
|
||||
GuExn* err)
|
||||
{
|
||||
(void) err;
|
||||
GuStringBuf* sbuf = gu_container(stream, GuStringBuf, stream);
|
||||
gu_buf_push_n(sbuf->buf, src, sz);
|
||||
return sz;
|
||||
}
|
||||
|
||||
static uint8_t*
|
||||
gu_string_buf_begin(GuOutStream* stream, size_t req, size_t* sz_out, GuExn* err)
|
||||
{
|
||||
(void) req;
|
||||
(void) err;
|
||||
GuStringBuf* sbuf = gu_container(stream, GuStringBuf, stream);
|
||||
size_t len = gu_buf_length(sbuf->buf);
|
||||
gu_buf_require(sbuf->buf, len + req);
|
||||
size_t avail = sbuf->buf->avail_len;
|
||||
gu_assert(len < avail);
|
||||
*sz_out = (avail - len);
|
||||
return (uint8_t*) gu_buf_index(sbuf->buf, char, len);
|
||||
}
|
||||
|
||||
static void
|
||||
gu_string_buf_end(GuOutStream* stream, size_t sz, GuExn* err)
|
||||
{
|
||||
(void) err;
|
||||
GuStringBuf* sbuf = gu_container(stream, GuStringBuf, stream);
|
||||
size_t len = gu_buf_length(sbuf->buf);
|
||||
gu_require(sz < len - sbuf->buf->avail_len);
|
||||
sbuf->buf->seq->len = len + sz;
|
||||
}
|
||||
|
||||
GU_API GuStringBuf*
|
||||
gu_new_string_buf(GuPool* pool)
|
||||
{
|
||||
GuStringBuf* sbuf = gu_new(GuStringBuf, pool);
|
||||
sbuf->stream.output = gu_string_buf_output;
|
||||
sbuf->stream.begin_buf = gu_string_buf_begin;
|
||||
sbuf->stream.end_buf = gu_string_buf_end;
|
||||
sbuf->stream.flush = NULL;
|
||||
sbuf->buf = gu_new_buf(char, pool);
|
||||
sbuf->out = gu_new_out(&sbuf->stream, pool);
|
||||
return sbuf;
|
||||
}
|
||||
|
||||
GU_API GuOut*
|
||||
gu_string_buf_out(GuStringBuf* sb)
|
||||
{
|
||||
return sb->out;
|
||||
}
|
||||
|
||||
GU_API GuString
|
||||
gu_string_buf_freeze(GuStringBuf* sb, GuPool* pool)
|
||||
{
|
||||
gu_out_flush(sb->out, NULL);
|
||||
char* data = gu_buf_data(sb->buf);
|
||||
size_t len = gu_buf_length(sb->buf);
|
||||
|
||||
char* p = gu_malloc_aligned(pool, len+1, 2);
|
||||
memcpy(p, data, len);
|
||||
p[len] = 0;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
GU_API char*
|
||||
gu_string_buf_data(GuStringBuf* sb)
|
||||
{
|
||||
gu_out_flush(sb->out, NULL);
|
||||
return gu_buf_data(sb->buf);
|
||||
}
|
||||
|
||||
GU_API size_t
|
||||
gu_string_buf_length(GuStringBuf* sb)
|
||||
{
|
||||
gu_out_flush(sb->out, NULL);
|
||||
return gu_buf_length(sb->buf);
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_string_buf_flush(GuStringBuf* sb)
|
||||
{
|
||||
gu_buf_flush(sb->buf);
|
||||
}
|
||||
|
||||
GU_API GuIn*
|
||||
gu_string_in(GuString s, GuPool* pool)
|
||||
{
|
||||
return gu_data_in((uint8_t*) s, strlen(s), pool);
|
||||
}
|
||||
|
||||
GU_API GuString
|
||||
gu_string_copy(GuString string, GuPool* pool)
|
||||
{
|
||||
size_t len = strlen(string);
|
||||
char* p = gu_malloc_aligned(pool, len+1, 2);
|
||||
memcpy(p, string, len+1);
|
||||
return p;
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_string_write(GuString s, GuOut* out, GuExn* err)
|
||||
{
|
||||
gu_out_bytes(out, (uint8_t*) s, strlen(s), err);
|
||||
}
|
||||
|
||||
GU_API GuString
|
||||
gu_string_read(size_t len, GuPool* pool, GuIn* in, GuExn* err)
|
||||
{
|
||||
char* buf = alloca(len*6+1);
|
||||
char* p = buf;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
gu_in_utf8_buf((uint8_t**) &p, in, err);
|
||||
}
|
||||
*p++ = 0;
|
||||
|
||||
p = gu_malloc_aligned(pool, p-buf, 2);
|
||||
strcpy(p, buf);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
GU_API GuString
|
||||
gu_string_read_latin1(size_t len, GuPool* pool, GuIn* in, GuExn* err)
|
||||
{
|
||||
char* p = gu_malloc_aligned(pool, len+1, 2);
|
||||
gu_in_bytes(in, (uint8_t*)p, len, err);
|
||||
p[len] = 0;
|
||||
return p;
|
||||
}
|
||||
|
||||
GU_API GuString
|
||||
gu_format_string_v(const char* fmt, va_list args, GuPool* pool)
|
||||
{
|
||||
GuPool* tmp_pool = gu_local_pool();
|
||||
GuStringBuf* sb = gu_new_string_buf(tmp_pool);
|
||||
GuOut* out = gu_string_buf_out(sb);
|
||||
gu_vprintf(fmt, args, out, NULL);
|
||||
gu_out_flush(out, NULL);
|
||||
GuString s = gu_string_buf_freeze(sb, pool);
|
||||
gu_pool_free(tmp_pool);
|
||||
return s;
|
||||
}
|
||||
|
||||
GU_API GuString
|
||||
gu_format_string(GuPool* pool, const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
GuString s = gu_format_string_v(fmt, args, pool);
|
||||
va_end(args);
|
||||
return s;
|
||||
}
|
||||
|
||||
GU_API bool
|
||||
gu_string_to_int(GuString s, int *res)
|
||||
{
|
||||
bool neg = false;
|
||||
if (*s == '-') {
|
||||
neg = true;
|
||||
s++;
|
||||
}
|
||||
|
||||
if (*s == 0)
|
||||
return false;
|
||||
|
||||
int n = 0;
|
||||
for (; *s; s++) {
|
||||
if (*s < '0' || *s > '9')
|
||||
return false;
|
||||
|
||||
n = n * 10 + (*s - '0');
|
||||
}
|
||||
|
||||
*res = neg ? -n : n;
|
||||
return true;
|
||||
}
|
||||
|
||||
GU_API bool
|
||||
gu_string_to_double(GuString s, double *res)
|
||||
{
|
||||
bool neg = false;
|
||||
bool dec = false;
|
||||
double exp = 1;
|
||||
|
||||
if (*s == '-') {
|
||||
neg = true;
|
||||
s++;
|
||||
}
|
||||
|
||||
if (*s == 0)
|
||||
return false;
|
||||
|
||||
double d = 0;
|
||||
for (; *s; s++) {
|
||||
if (*s == '.') {
|
||||
if (dec) return false;
|
||||
|
||||
dec = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*s < '0' || *s > '9')
|
||||
return false;
|
||||
|
||||
if (dec) exp = exp * 10;
|
||||
|
||||
d = d * 10 + (*s - '0');
|
||||
}
|
||||
|
||||
*res = (neg ? -d : d) / exp;
|
||||
return true;
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_double_to_string(double val, GuOut* out, GuExn* err)
|
||||
{
|
||||
int ival = (int) val;
|
||||
gu_printf(out, err, "%d", ival);
|
||||
val -= ival;
|
||||
|
||||
if (val < 0)
|
||||
val = -val;
|
||||
|
||||
if (val != 0) {
|
||||
gu_putc('.', out, err);
|
||||
|
||||
while (val > 0.000001) // process remaining digits
|
||||
{
|
||||
val = val * 10;
|
||||
ival = (int) val;
|
||||
gu_printf(out, err, "%d", ival);
|
||||
val -= ival;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GU_API bool
|
||||
gu_string_is_prefix(GuString s1, GuString s2)
|
||||
{
|
||||
size_t len1 = strlen(s1);
|
||||
size_t len2 = strlen(s2);
|
||||
|
||||
if (len1 > len2)
|
||||
return false;
|
||||
|
||||
for (size_t len = len1; len > 0; len--) {
|
||||
if (*s1 != *s2)
|
||||
return false;
|
||||
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
GU_API GuHash
|
||||
gu_string_hash(GuHash h, GuString s)
|
||||
{
|
||||
return gu_hash_bytes(h, (uint8_t*)s, strlen(s));
|
||||
}
|
||||
|
||||
static bool
|
||||
gu_string_eq_fn(GuEquality* self, const void* p1, const void* p2)
|
||||
{
|
||||
(void) self;
|
||||
return strcmp((GuString) p1, (GuString) p2) == 0;
|
||||
}
|
||||
|
||||
GU_API GuEquality gu_string_equality[1] = { { gu_string_eq_fn } };
|
||||
|
||||
static int
|
||||
gu_string_cmp_fn(GuOrder* self, const void* p1, const void* p2)
|
||||
{
|
||||
(void) self;
|
||||
return strcmp((GuString) p1, (GuString) p2);
|
||||
}
|
||||
|
||||
GU_API GuOrder gu_string_order[1] = { { gu_string_cmp_fn } };
|
||||
|
||||
static GuHash
|
||||
gu_string_hasher_hash(GuHasher* self, const void* p)
|
||||
{
|
||||
(void) self;
|
||||
return gu_string_hash(0, (GuString) p);
|
||||
}
|
||||
|
||||
GU_API GuHasher gu_string_hasher[1] = {
|
||||
{
|
||||
.eq = { gu_string_eq_fn },
|
||||
.hash = gu_string_hasher_hash
|
||||
}
|
||||
};
|
||||
@@ -1,97 +0,0 @@
|
||||
#ifndef GU_STRING_H_
|
||||
#define GU_STRING_H_
|
||||
|
||||
#include <gu/bits.h>
|
||||
#include <gu/in.h>
|
||||
#include <gu/out.h>
|
||||
|
||||
typedef const char* GuString;
|
||||
|
||||
GU_API_DECL GuString
|
||||
gu_string_copy(GuString string, GuPool* pool);
|
||||
|
||||
GU_API_DECL void
|
||||
gu_string_write(GuString string, GuOut* out, GuExn* err);
|
||||
|
||||
GU_API_DECL GuString
|
||||
gu_string_read(size_t len, GuPool* pool, GuIn* in, GuExn* err);
|
||||
|
||||
GU_API_DECL GuString
|
||||
gu_string_read_latin1(size_t len, GuPool* pool, GuIn* in, GuExn* err);
|
||||
|
||||
GU_API_DECL GuIn*
|
||||
gu_string_in(GuString string, GuPool* pool);
|
||||
|
||||
typedef struct GuStringBuf GuStringBuf;
|
||||
|
||||
GU_API_DECL GuStringBuf*
|
||||
gu_new_string_buf(GuPool* pool);
|
||||
|
||||
GU_API_DECL GuOut*
|
||||
gu_string_buf_out(GuStringBuf* sb);
|
||||
|
||||
GU_API_DECL GuString
|
||||
gu_string_buf_freeze(GuStringBuf* sb, GuPool* pool);
|
||||
|
||||
GU_API_DECL char*
|
||||
gu_string_buf_data(GuStringBuf* sb);
|
||||
|
||||
GU_API_DECL size_t
|
||||
gu_string_buf_length(GuStringBuf* sb);
|
||||
|
||||
GU_API_DECL void
|
||||
gu_string_buf_flush(GuStringBuf* sb);
|
||||
|
||||
GU_API_DECL GuString
|
||||
gu_format_string_v(const char* fmt, va_list args, GuPool* pool);
|
||||
|
||||
GU_API_DECL GuString
|
||||
gu_format_string(GuPool* pool, const char* fmt, ...);
|
||||
|
||||
GU_API_DECL bool
|
||||
gu_string_to_int(GuString s, int *res);
|
||||
|
||||
GU_API_DECL bool
|
||||
gu_string_to_double(GuString s, double *res);
|
||||
|
||||
GU_API_DECL void
|
||||
gu_double_to_string(double val, GuOut* out, GuExn* err);
|
||||
|
||||
GU_API_DECL bool
|
||||
gu_string_is_prefix(GuString s1, GuString s2);
|
||||
|
||||
#endif // GU_STRING_H_
|
||||
|
||||
#if defined(GU_FUN_H_) && !defined(GU_STRING_H_FUN_)
|
||||
#define GU_STRING_H_FUN_
|
||||
GU_API_DECL extern GuEquality gu_string_equality[1];
|
||||
|
||||
GU_API_DECL extern GuOrder gu_string_order[1];
|
||||
#endif
|
||||
|
||||
#if defined(GU_HASH_H_) && !defined(GU_STRING_H_HASH_)
|
||||
#define GU_STRING_H_HASH_
|
||||
|
||||
GU_API_DECL GuHash
|
||||
gu_string_hash(GuHash h, GuString s);
|
||||
|
||||
GU_API_DECL extern GuHasher gu_string_hasher[1];
|
||||
#endif
|
||||
|
||||
#if defined(GU_SEQ_H_) && !defined(GU_STRING_H_SEQ_)
|
||||
#define GU_STRING_H_SEQ_
|
||||
|
||||
typedef GuSeq GuStrings;
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(GU_MAP_H_) && !defined(GU_STRING_H_MAP_)
|
||||
#define GU_STRING_H_MAP_
|
||||
|
||||
typedef GuMap GuStringMap;
|
||||
|
||||
#define gu_new_string_map(VAL_T, DEFAULT, POOL) \
|
||||
gu_new_map(GuString, gu_string_hasher, VAL_T, (DEFAULT), (POOL))
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
#ifndef GU_SYSDEPS_H_
|
||||
#define GU_SYSDEPS_H_
|
||||
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
# define GU_GNUC
|
||||
#endif
|
||||
|
||||
#ifdef GU_GNUC
|
||||
# define GU_ALIGNOF __alignof
|
||||
# define GU_GNUC_ATTR(x) __attribute__(( x ))
|
||||
# if defined(__OPTIMIZE_SIZE__)
|
||||
# define GU_OPTIMIZE_SIZE
|
||||
# elif defined(__OPTIMIZE__)
|
||||
# define GU_OPTIMIZE_SPEED
|
||||
# endif
|
||||
#else
|
||||
# define GU_GNUC_ATTR(x)
|
||||
#endif
|
||||
|
||||
#ifdef S_SPLINT_S
|
||||
# define GU_SPLINT(x) %{ x %}
|
||||
#else
|
||||
# define GU_SPLINT(x)
|
||||
#endif
|
||||
|
||||
|
||||
#endif // GU_SYSDEPS_H_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,55 +0,0 @@
|
||||
#ifndef GU_UCS_H_
|
||||
#define GU_UCS_H_
|
||||
|
||||
#include <gu/defs.h>
|
||||
#include <gu/exn.h>
|
||||
#include <gu/assert.h>
|
||||
|
||||
#if defined(__STDC_ISO_10646__) && WCHAR_MAX >= 0x10FFFF
|
||||
#include <wchar.h>
|
||||
#define GU_UCS_WCHAR
|
||||
typedef wchar_t GuUCS;
|
||||
#else
|
||||
typedef int32_t GuUCS;
|
||||
#endif
|
||||
|
||||
#define GU_UCS_MAX ((GuUCS)(0x10FFFF))
|
||||
|
||||
GU_API_DECL bool
|
||||
gu_char_is_valid(char c);
|
||||
|
||||
inline bool
|
||||
gu_ucs_valid(GuUCS ucs)
|
||||
{
|
||||
return ucs >= 0 && ucs <= GU_UCS_MAX;
|
||||
}
|
||||
|
||||
GU_API_DECL GuUCS
|
||||
gu_char_ucs(char c);
|
||||
|
||||
GU_API_DECL char
|
||||
gu_ucs_char(GuUCS uc, GuExn* err);
|
||||
|
||||
GU_API_DECL size_t
|
||||
gu_str_to_ucs(const char* cbuf, size_t len, GuUCS* ubuf, GuExn* err);
|
||||
|
||||
GU_API_DECL size_t
|
||||
gu_ucs_to_str(const GuUCS* ubuf, size_t len, char* cbuf, GuExn* err);
|
||||
|
||||
GU_API_DECL bool gu_ucs_is_upper(GuUCS c);
|
||||
GU_API_DECL bool gu_ucs_is_digit(GuUCS c);
|
||||
GU_API_DECL bool gu_ucs_is_alpha(GuUCS c);
|
||||
GU_API_DECL bool gu_ucs_is_cntrl(GuUCS c);
|
||||
GU_API_DECL bool gu_ucs_is_space(GuUCS c);
|
||||
GU_API_DECL bool gu_ucs_is_print(GuUCS c);
|
||||
GU_API_DECL bool gu_ucs_is_lower(GuUCS c);
|
||||
|
||||
GU_API_DECL bool gu_ucs_is_alnum(GuUCS c);
|
||||
|
||||
GU_API_DECL GuUCS gu_ucs_to_lower(GuUCS c);
|
||||
GU_API_DECL GuUCS gu_ucs_to_upper(GuUCS c);
|
||||
GU_API_DECL GuUCS gu_ucs_to_title(GuUCS c);
|
||||
|
||||
GU_API_DECL int gu_ucs_is_gencat(GuUCS wc);
|
||||
|
||||
#endif // GU_ISO10646_H_
|
||||
@@ -1,176 +0,0 @@
|
||||
#include <gu/assert.h>
|
||||
#include <gu/utf8.h>
|
||||
|
||||
GU_API GuUCS
|
||||
gu_utf8_decode(const uint8_t** src_inout)
|
||||
{
|
||||
const uint8_t* src = *src_inout;
|
||||
uint8_t c = src[0];
|
||||
if (c < 0x80) {
|
||||
*src_inout = src + 1;
|
||||
return (GuUCS) c;
|
||||
}
|
||||
size_t len = (c < 0xe0 ? 1 :
|
||||
c < 0xf0 ? 2 :
|
||||
c < 0xf8 ? 3 :
|
||||
c < 0xfc ? 4 :
|
||||
5
|
||||
);
|
||||
uint64_t mask = 0x0103070F1f7f;
|
||||
uint32_t u = c & (mask >> (len * 8));
|
||||
for (size_t i = 1; i <= len; i++) {
|
||||
c = src[i];
|
||||
u = u << 6 | (c & 0x3f);
|
||||
}
|
||||
*src_inout = &src[len + 1];
|
||||
return (GuUCS) u;
|
||||
}
|
||||
|
||||
GU_API GuUCS
|
||||
gu_in_utf8_(GuIn* in, GuExn* err)
|
||||
{
|
||||
uint8_t c = gu_in_u8(in, err);
|
||||
if (!gu_ok(err)) {
|
||||
return 0;
|
||||
}
|
||||
if (c < 0x80) {
|
||||
return c;
|
||||
}
|
||||
if (c < 0xc2) {
|
||||
goto fail;
|
||||
}
|
||||
int len = (c < 0xe0 ? 1 :
|
||||
c < 0xf0 ? 2 :
|
||||
c < 0xf8 ? 3 :
|
||||
c < 0xfc ? 4 :
|
||||
5
|
||||
);
|
||||
uint64_t mask = 0x0103070F1f7f;
|
||||
uint32_t u = c & (mask >> (len * 8));
|
||||
uint8_t buf[5];
|
||||
// If reading the extra bytes causes EOF, it is an encoding
|
||||
// error, not a legitimate end of character stream.
|
||||
gu_in_bytes(in, buf, len, err);
|
||||
if (gu_exn_caught(err, GuEOF)) {
|
||||
gu_exn_clear(err);
|
||||
goto fail;
|
||||
}
|
||||
if (!gu_ok(err)) {
|
||||
return 0;
|
||||
}
|
||||
for (int i = 0; i < len; i++) {
|
||||
c = buf[i];
|
||||
if ((c & 0xc0) != 0x80) {
|
||||
goto fail;
|
||||
}
|
||||
u = u << 6 | (c & 0x3f);
|
||||
}
|
||||
GuUCS ucs = (GuUCS) u;
|
||||
if (!gu_ucs_valid(ucs)) {
|
||||
goto fail;
|
||||
}
|
||||
return ucs;
|
||||
|
||||
fail:
|
||||
gu_raise(err, GuUCSExn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern inline GuUCS
|
||||
gu_in_utf8(GuIn* in, GuExn* err);
|
||||
|
||||
GU_API void
|
||||
gu_in_utf8_buf(uint8_t** buf, GuIn* in, GuExn* err)
|
||||
{
|
||||
uint8_t* p = *buf;
|
||||
|
||||
uint8_t c = gu_in_u8(in, err);
|
||||
if (!gu_ok(err)) {
|
||||
return;
|
||||
}
|
||||
*(p++) = c;
|
||||
|
||||
if (c < 0x80) {
|
||||
*buf = p;
|
||||
return;
|
||||
}
|
||||
if (c < 0xc2) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
int len = (c < 0xe0 ? 1 :
|
||||
c < 0xf0 ? 2 :
|
||||
c < 0xf8 ? 3 :
|
||||
c < 0xfc ? 4 :
|
||||
5
|
||||
);
|
||||
// If reading the extra bytes causes EOF, it is an encoding
|
||||
// error, not a legitimate end of character stream.
|
||||
gu_in_bytes(in, p, len, err);
|
||||
if (gu_exn_caught(err, GuEOF)) {
|
||||
gu_exn_clear(err);
|
||||
goto fail;
|
||||
}
|
||||
if (!gu_ok(err)) {
|
||||
return;
|
||||
}
|
||||
*buf = p+len;
|
||||
return;
|
||||
|
||||
fail:
|
||||
gu_raise(err, GuUCSExn);
|
||||
return;
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_utf8_encode(GuUCS ucs, uint8_t** buf)
|
||||
{
|
||||
gu_require(gu_ucs_valid(ucs));
|
||||
uint8_t* p = *buf;
|
||||
if (ucs < 0x80) {
|
||||
p[0] = (uint8_t) ucs;
|
||||
*buf = p+1;
|
||||
} else if (ucs < 0x800) {
|
||||
p[0] = 0xc0 | (ucs >> 6);
|
||||
p[1] = 0x80 | (ucs & 0x3f);
|
||||
*buf = p+2;
|
||||
} else if (ucs < 0x10000) {
|
||||
p[0] = 0xe0 | (ucs >> 12);
|
||||
p[1] = 0x80 | ((ucs >> 6) & 0x3f);
|
||||
p[2] = 0x80 | (ucs & 0x3f);
|
||||
*buf = p+3;
|
||||
} else if (ucs < 0x200000) {
|
||||
p[0] = 0xf0 | (ucs >> 18);
|
||||
p[1] = 0x80 | ((ucs >> 12) & 0x3f);
|
||||
p[2] = 0x80 | ((ucs >> 6) & 0x3f);
|
||||
p[3] = 0x80 | (ucs & 0x3f);
|
||||
*buf = p+4;
|
||||
} else if (ucs < 0x4000000) {
|
||||
p[0] = 0xf8 | (ucs >> 24);
|
||||
p[1] = 0x80 | ((ucs >> 18) & 0x3f);
|
||||
p[2] = 0x80 | ((ucs >> 12) & 0x3f);
|
||||
p[3] = 0x80 | ((ucs >> 6) & 0x3f);
|
||||
p[4] = 0x80 | (ucs & 0x3f);
|
||||
*buf = p+5;
|
||||
} else {
|
||||
p[0] = 0xfc | (ucs >> 30);
|
||||
p[1] = 0x80 | ((ucs >> 24) & 0x3f);
|
||||
p[2] = 0x80 | ((ucs >> 18) & 0x3f);
|
||||
p[3] = 0x80 | ((ucs >> 12) & 0x3f);
|
||||
p[4] = 0x80 | ((ucs >> 6) & 0x3f);
|
||||
p[5] = 0x80 | (ucs & 0x3f);
|
||||
*buf = p+6;
|
||||
}
|
||||
}
|
||||
|
||||
GU_API void
|
||||
gu_out_utf8_(GuUCS ucs, GuOut* out, GuExn* err)
|
||||
{
|
||||
uint8_t buf[6];
|
||||
uint8_t* p = buf;
|
||||
gu_utf8_encode(ucs, &p);
|
||||
gu_out_bytes(out, buf, p-buf, err);
|
||||
}
|
||||
|
||||
extern inline void
|
||||
gu_out_utf8(GuUCS ucs, GuOut* out, GuExn* err);
|
||||
@@ -1,43 +0,0 @@
|
||||
#ifndef GU_UTF8_H_
|
||||
#define GU_UTF8_H_
|
||||
|
||||
#include <gu/in.h>
|
||||
#include <gu/out.h>
|
||||
#include <gu/ucs.h>
|
||||
|
||||
inline GuUCS
|
||||
gu_in_utf8(GuIn* in, GuExn* err)
|
||||
{
|
||||
int i = gu_in_peek_u8(in);
|
||||
if (i >= 0 && i < 0x80) {
|
||||
gu_in_consume(in, 1);
|
||||
return (GuUCS) i;
|
||||
}
|
||||
GU_API_DECL GuUCS gu_in_utf8_(GuIn* in, GuExn* err);
|
||||
return gu_in_utf8_(in, err);
|
||||
}
|
||||
|
||||
inline void
|
||||
gu_out_utf8(GuUCS ucs, GuOut* out, GuExn* err)
|
||||
{
|
||||
gu_require(gu_ucs_valid(ucs));
|
||||
if (GU_LIKELY(ucs < 0x80)) {
|
||||
gu_out_u8(out, ucs, err);
|
||||
} else {
|
||||
GU_API_DECL void gu_out_utf8_(GuUCS ucs, GuOut* out, GuExn* err);
|
||||
gu_out_utf8_(ucs, out, err);
|
||||
}
|
||||
}
|
||||
|
||||
// Helper functions used in other modules
|
||||
|
||||
GU_API_DECL GuUCS
|
||||
gu_utf8_decode(const uint8_t** buf);
|
||||
|
||||
GU_API_DECL void
|
||||
gu_utf8_encode(GuUCS ucs, uint8_t** buf);
|
||||
|
||||
GU_API_DECL void
|
||||
gu_in_utf8_buf(uint8_t** buf, GuIn* in, GuExn* err);
|
||||
|
||||
#endif // GU_UTF8_H_
|
||||
@@ -1,94 +0,0 @@
|
||||
#include "variant.h"
|
||||
#include "bits.h"
|
||||
|
||||
enum {
|
||||
GU_VARIANT_ALIGNMENT = sizeof(uintptr_t)
|
||||
};
|
||||
|
||||
GU_API void*
|
||||
gu_alloc_variant(uint8_t tag, size_t size,
|
||||
size_t align, GuVariant* variant_out, GuPool* pool)
|
||||
{
|
||||
align = gu_max(align, GU_VARIANT_ALIGNMENT);
|
||||
if (((size_t)tag) > GU_VARIANT_ALIGNMENT - 2) {
|
||||
uint8_t* alloc = gu_malloc_aligned(pool, align + size, align);
|
||||
alloc[align - 1] = tag;
|
||||
void* p = &alloc[align];
|
||||
*variant_out = (uintptr_t)p;
|
||||
return p;
|
||||
}
|
||||
void* p = gu_malloc_aligned(pool, size, align);
|
||||
*variant_out = ((uintptr_t)p) | (tag + 1);
|
||||
return p;
|
||||
}
|
||||
|
||||
GU_API GuVariant
|
||||
gu_make_variant(uint8_t tag, size_t size, size_t align, const void* init,
|
||||
GuPool* pool)
|
||||
{
|
||||
GuVariant v;
|
||||
void* data = gu_alloc_variant(tag, size, align, &v, pool);
|
||||
memcpy(data, init, size);
|
||||
return v;
|
||||
}
|
||||
|
||||
GU_API int
|
||||
gu_variant_tag(GuVariant variant)
|
||||
{
|
||||
if (gu_variant_is_null(variant)) {
|
||||
return GU_VARIANT_NULL;
|
||||
}
|
||||
int u = variant % GU_VARIANT_ALIGNMENT;
|
||||
if (u == 0) {
|
||||
uint8_t* mem = (uint8_t*)variant;
|
||||
return mem[-1];
|
||||
}
|
||||
return u - 1;
|
||||
}
|
||||
|
||||
GU_API void*
|
||||
gu_variant_data(GuVariant variant)
|
||||
{
|
||||
if (gu_variant_is_null(variant)) {
|
||||
return NULL;
|
||||
}
|
||||
return (void*)gu_align_backward(variant, GU_VARIANT_ALIGNMENT);
|
||||
}
|
||||
|
||||
GU_API GuVariantInfo
|
||||
gu_variant_open(GuVariant variant)
|
||||
{
|
||||
GuVariantInfo info = {
|
||||
.tag = gu_variant_tag(variant),
|
||||
.data = gu_variant_data(variant)
|
||||
};
|
||||
return info;
|
||||
}
|
||||
|
||||
GU_API GuVariant
|
||||
gu_variant_close(GuVariantInfo info)
|
||||
{
|
||||
GuVariant variant;
|
||||
|
||||
if (((size_t)info.tag) > GU_VARIANT_ALIGNMENT - 2) {
|
||||
variant = (uintptr_t)info.data;
|
||||
assert(gu_variant_tag(variant) == info.tag);
|
||||
} else {
|
||||
variant = ((uintptr_t)info.data) | (info.tag + 1);
|
||||
}
|
||||
|
||||
return variant;
|
||||
}
|
||||
|
||||
GU_API int
|
||||
gu_variant_intval(GuVariant variant)
|
||||
{
|
||||
int u = variant % GU_VARIANT_ALIGNMENT;
|
||||
if (u == 0) {
|
||||
int* mem = (int*)variant;
|
||||
return *mem;
|
||||
}
|
||||
return (variant / GU_VARIANT_ALIGNMENT);
|
||||
}
|
||||
|
||||
GU_API const GuVariant gu_null_variant = { (GuWord) NULL };
|
||||
@@ -1,111 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010 University of Helsinki.
|
||||
*
|
||||
* This file is part of libgu.
|
||||
*
|
||||
* Libgu is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Libgu is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with libgu. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Lightweight tagged data.
|
||||
*/
|
||||
|
||||
#ifndef GU_VARIANT_H_
|
||||
#define GU_VARIANT_H_
|
||||
|
||||
#include <gu/defs.h>
|
||||
#include <gu/mem.h>
|
||||
|
||||
/** @name Variants
|
||||
* @{
|
||||
*/
|
||||
|
||||
typedef uintptr_t GuVariant;
|
||||
|
||||
|
||||
GU_API_DECL
|
||||
void* gu_alloc_variant(uint8_t tag,
|
||||
size_t size, size_t align,
|
||||
GuVariant* variant_out, GuPool* pool);
|
||||
|
||||
GU_API_DECL
|
||||
GuVariant gu_make_variant(uint8_t tag,
|
||||
size_t size, size_t align,
|
||||
const void* init, GuPool* pool);
|
||||
|
||||
#define gu_new_variant(tag, type, variant_out, pool) \
|
||||
((type*)gu_alloc_variant(tag, sizeof(type), \
|
||||
gu_alignof(type), variant_out, pool))
|
||||
|
||||
/**<
|
||||
* @hideinitializer */
|
||||
|
||||
#define gu_new_variant_i(POOL, TAG, T, ...) \
|
||||
gu_make_variant(TAG, sizeof(T), gu_alignof(T), \
|
||||
&(T){ __VA_ARGS__ }, POOL)
|
||||
|
||||
|
||||
|
||||
#define gu_new_flex_variant(tag, type, flex_mem, n_elems, variant_out, pool) \
|
||||
((type*)gu_alloc_variant(tag, \
|
||||
GU_FLEX_SIZE(type, flex_mem, n_elems), \
|
||||
gu_flex_alignof(type), \
|
||||
variant_out, pool))
|
||||
/**<
|
||||
* @hideinitializer */
|
||||
|
||||
enum {
|
||||
GU_VARIANT_NULL = -1
|
||||
};
|
||||
|
||||
GU_API_DECL
|
||||
int gu_variant_tag(GuVariant variant);
|
||||
|
||||
GU_API_DECL
|
||||
void* gu_variant_data(GuVariant variant);
|
||||
|
||||
|
||||
typedef struct GuVariantInfo GuVariantInfo;
|
||||
|
||||
struct GuVariantInfo {
|
||||
int tag;
|
||||
void* data;
|
||||
};
|
||||
|
||||
GU_API_DECL GuVariantInfo gu_variant_open(GuVariant variant);
|
||||
GU_API_DECL GuVariant gu_variant_close(GuVariantInfo info);
|
||||
|
||||
/** @} */
|
||||
|
||||
static inline void*
|
||||
gu_variant_to_ptr(GuVariant variant)
|
||||
{
|
||||
return (void*) variant;
|
||||
}
|
||||
|
||||
static inline GuVariant
|
||||
gu_variant_from_ptr(const void* p)
|
||||
{
|
||||
return (uintptr_t) p;
|
||||
}
|
||||
|
||||
GU_API_DECL extern const GuVariant gu_null_variant;
|
||||
|
||||
static inline bool
|
||||
gu_variant_is_null(GuVariant v) {
|
||||
return ((void*)v == NULL);
|
||||
}
|
||||
|
||||
#endif // GU_VARIANT_H_
|
||||
@@ -1,3 +0,0 @@
|
||||
bash setup.sh configure
|
||||
bash setup.sh build
|
||||
bash setup.sh install
|
||||
@@ -1,10 +0,0 @@
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: libgu
|
||||
Description: Gothenburg Utilities library
|
||||
Version: @VERSION@
|
||||
Libs: -L${libdir} -lgu
|
||||
Cflags: -I${includedir}
|
||||
@@ -5,7 +5,6 @@ includedir=@includedir@
|
||||
|
||||
Name: libpgf
|
||||
Description: Portable Grammar Format library
|
||||
Requires: libgu
|
||||
Version: @VERSION@
|
||||
Libs: -L${libdir} -lpgf
|
||||
Cflags: -I${includedir}
|
||||
|
||||
215
src/runtime/c/namespace.h
Normal file
215
src/runtime/c/namespace.h
Normal file
@@ -0,0 +1,215 @@
|
||||
#ifndef NAMESPACE_H
|
||||
#define NAMESPACE_H
|
||||
|
||||
#include "db.h"
|
||||
|
||||
template <class V>
|
||||
class Node;
|
||||
|
||||
template <class V>
|
||||
using Namespace = ref<Node<V>>;
|
||||
|
||||
template <class V>
|
||||
class Node {
|
||||
public:
|
||||
size_t sz;
|
||||
ref<V> value;
|
||||
ref<Node> left;
|
||||
ref<Node> right;
|
||||
|
||||
static
|
||||
ref<Node> new_node(ref<V> value) {
|
||||
ref<Node> node = current_db->malloc<Node>();
|
||||
node->sz = 1;
|
||||
node->value = value;
|
||||
node->left = 0;
|
||||
node->right = 0;
|
||||
return node;
|
||||
}
|
||||
|
||||
static
|
||||
ref<Node> new_node(ref<V> value, ref<Node> left, ref<Node> right) {
|
||||
ref<Node> node = current_db->malloc<Node>();
|
||||
node->sz = 1+namespace_size(left)+namespace_size(right);
|
||||
node->value = value;
|
||||
node->left = left;
|
||||
node->right = right;
|
||||
return node;
|
||||
}
|
||||
|
||||
static
|
||||
ref<Node> balanceL(ref<V> value, ref<Node> left, ref<Node> right) {
|
||||
if (right == 0) {
|
||||
if (left == 0) {
|
||||
return new_node(value);
|
||||
} else {
|
||||
if (left->left == 0) {
|
||||
if (left->right == 0) {
|
||||
return new_node(value,left,0);
|
||||
} else {
|
||||
return new_node(left->right->value,
|
||||
new_node(left->value),
|
||||
new_node(value));
|
||||
}
|
||||
} else {
|
||||
if (left->right == 0) {
|
||||
return new_node(left->value,
|
||||
left->left,
|
||||
new_node(value));
|
||||
} else {
|
||||
if (left->right->sz < 2 * left->left->sz) {
|
||||
return new_node(left->value,
|
||||
left->left,
|
||||
new_node(value,
|
||||
left->right,
|
||||
0));
|
||||
} else {
|
||||
return new_node(left->right->value,
|
||||
new_node(left->value,
|
||||
left->left,
|
||||
left->right->left),
|
||||
new_node(value,
|
||||
left->right->right,
|
||||
0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (left == 0) {
|
||||
return new_node(value,0,right);
|
||||
} else {
|
||||
if (left->sz > 3*right->sz) {
|
||||
if (left->right->sz < 2*left->left->sz)
|
||||
return new_node(left->value,
|
||||
left->left,
|
||||
new_node(value,
|
||||
left->right,
|
||||
right));
|
||||
else
|
||||
return new_node(left->right->value,
|
||||
new_node(left->value,
|
||||
left->left,
|
||||
left->right->left),
|
||||
new_node(value,
|
||||
left->right->right,
|
||||
right));
|
||||
} else {
|
||||
return new_node(value,left,right);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
ref<Node> balanceR(ref<V> value, ref<Node> left, ref<Node> right) {
|
||||
if (left == 0) {
|
||||
if (right == 0) {
|
||||
return new_node(value);
|
||||
} else {
|
||||
if (right->left == 0) {
|
||||
if (right->right == 0) {
|
||||
return new_node(value,0,right);
|
||||
} else {
|
||||
return new_node(right->value,
|
||||
new_node(value),
|
||||
right->right);
|
||||
}
|
||||
} else {
|
||||
if (right->right == 0) {
|
||||
return new_node(right->left->value,
|
||||
new_node(value),
|
||||
new_node(right->value));
|
||||
} else {
|
||||
if (right->left->sz < 2 * right->right->sz) {
|
||||
return new_node(right->value,
|
||||
new_node(value,
|
||||
0,
|
||||
right->left),
|
||||
right->right);
|
||||
} else {
|
||||
return new_node(right->left->value,
|
||||
new_node(value,
|
||||
0,
|
||||
right->left->left),
|
||||
new_node(right->value,
|
||||
right->left->right,
|
||||
right->right));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (right == 0) {
|
||||
return new_node(value,left,0);
|
||||
} else {
|
||||
if (right->sz > 3*left->sz) {
|
||||
if (right->left->sz < 2*right->right->sz)
|
||||
return new_node(right->value,
|
||||
new_node(value,
|
||||
left,
|
||||
right->left),
|
||||
right->right);
|
||||
else
|
||||
return new_node(right->left->value,
|
||||
new_node(value,
|
||||
left,
|
||||
right->left->left),
|
||||
new_node(right->value,
|
||||
right->left->right,
|
||||
right->right));
|
||||
} else {
|
||||
return new_node(value,left,right);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class V>
|
||||
Namespace<V> namespace_empty() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class V>
|
||||
Namespace<V> namespace_singleton(ref<V> value) {
|
||||
return Node<V>::new_node(value);
|
||||
}
|
||||
|
||||
template <class V>
|
||||
Namespace<V> namespace_insert(Namespace<V> map, ref<V> value) {
|
||||
if (map == 0)
|
||||
return Node<V>::new_node(value);
|
||||
|
||||
int cmp = strcmp(value->name,map->value->name);
|
||||
if (cmp < 0)
|
||||
return Node<V>::balanceL(map->value,
|
||||
namespace_insert(map->left, value),map->right);
|
||||
else if (cmp > 0)
|
||||
return Node<V>::balanceR(map->value,
|
||||
map->left, namespace_insert(map->right, value));
|
||||
else
|
||||
return Node<V>::new_node(value,map->left,map->right);
|
||||
}
|
||||
|
||||
template <class V>
|
||||
ref<V> namespace_lookup(Namespace<V> map, const char *name) {
|
||||
while (map != 0) {
|
||||
int cmp = strcmp(name,map->value->name);
|
||||
if (cmp < 0)
|
||||
map = map->left;
|
||||
else if (cmp > 0)
|
||||
map = map->right;
|
||||
else
|
||||
return map->value;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template <class V>
|
||||
size_t namespace_size(Namespace<V> map) {
|
||||
if (map == 0)
|
||||
return 0;
|
||||
return map->sz;
|
||||
}
|
||||
#endif
|
||||
51
src/runtime/c/pgf.cxx
Normal file
51
src/runtime/c/pgf.cxx
Normal file
@@ -0,0 +1,51 @@
|
||||
#include "data.h"
|
||||
#include "reader.h"
|
||||
|
||||
PGF_API
|
||||
PgfPGF *pgf_read(const char* fpath, PgfExn* err)
|
||||
{
|
||||
PgfPGF *pgf = NULL;
|
||||
|
||||
try {
|
||||
std::string fpath_n = fpath;
|
||||
size_t len = fpath_n.length();
|
||||
if (len > 4 && fpath_n.substr(len-4) == ".pgf")
|
||||
fpath_n[len-3] = 'n';
|
||||
else if (!(len > 4 && fpath_n.substr(len-4) == ".ngf"))
|
||||
fpath_n += ".ngf";
|
||||
|
||||
pgf = new PgfPGF(fpath_n.c_str());
|
||||
|
||||
if (pgf->db.get_root<PgfPGFRoot>() == 0) {
|
||||
std::ifstream in(fpath, std::ios::binary);
|
||||
if (in.fail()) {
|
||||
throw std::system_error(errno, std::generic_category());
|
||||
}
|
||||
|
||||
PgfReader rdr(&in);
|
||||
rdr.read_pgf(pgf);
|
||||
|
||||
pgf->set_root();
|
||||
}
|
||||
|
||||
return pgf;
|
||||
} catch (std::system_error& e) {
|
||||
err->type = "system_error";
|
||||
err->msg = NULL;
|
||||
} catch (pgf_error& e) {
|
||||
err->type = "pgf_error";
|
||||
err->msg = e.what();
|
||||
}
|
||||
|
||||
if (pgf != NULL)
|
||||
delete pgf;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void PgfPGF::set_root() {
|
||||
ref<PgfPGFRoot> root = db.malloc<PgfPGFRoot>();
|
||||
root->major_version = major_version;
|
||||
root->minor_version = minor_version;
|
||||
db.set_root(root);
|
||||
}
|
||||
50
src/runtime/c/pgf.h
Normal file
50
src/runtime/c/pgf.h
Normal file
@@ -0,0 +1,50 @@
|
||||
#ifndef PGF_H_
|
||||
#define PGF_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define EXTERN_C extern "C"
|
||||
#else
|
||||
#define EXTERN_C
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
#if defined(COMPILING_PGF)
|
||||
#define PGF_API_DECL __declspec(dllexport) EXTERN_C
|
||||
#define PGF_API __declspec(dllexport) EXTERN_C
|
||||
#else
|
||||
#define PGF_API_DECL __declspec(dllimport)
|
||||
#define PGF_API ERROR_NOT_COMPILING_LIBPGF
|
||||
#endif
|
||||
#define PGF_INTERNAL_DECL
|
||||
#define PGF_INTERNAL
|
||||
|
||||
#elif defined(__MINGW32__)
|
||||
|
||||
#define PGF_API_DECL EXTERN_C
|
||||
#define PGF_API EXTERN_C
|
||||
|
||||
#define PGF_INTERNAL_DECL
|
||||
#define PGF_INTERNAL
|
||||
|
||||
#else
|
||||
|
||||
#define PGF_API_DECL EXTERN_C
|
||||
#define PGF_API EXTERN_C
|
||||
|
||||
#define PGF_INTERNAL_DECL __attribute__ ((visibility ("hidden")))
|
||||
#define PGF_INTERNAL __attribute__ ((visibility ("hidden")))
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct PgfPGF PgfPGF;
|
||||
|
||||
typedef struct {
|
||||
const char *type;
|
||||
const char *msg;
|
||||
} PgfExn;
|
||||
|
||||
PGF_API_DECL
|
||||
PgfPGF *pgf_read(const char* fpath, PgfExn* err);
|
||||
|
||||
#endif // PGF_H_
|
||||
@@ -1,241 +0,0 @@
|
||||
#include "data.h"
|
||||
#include "linearizer.h"
|
||||
#include "pgf.h"
|
||||
#include <gu/utf8.h>
|
||||
|
||||
typedef struct {
|
||||
PgfLinFuncs* funcs;
|
||||
GuBuf* parent_stack;
|
||||
GuBuf* parent_current;
|
||||
GuBuf* phrases;
|
||||
PgfAlignmentPhrase* last_phrase;
|
||||
GuStringBuf* sbuf;
|
||||
size_t n_matches;
|
||||
GuExn* err;
|
||||
bool bind;
|
||||
PgfCapitState capit;
|
||||
GuPool* out_pool;
|
||||
GuPool* tmp_pool;
|
||||
} PgfAlignerLin;
|
||||
|
||||
static void
|
||||
pgf_aligner_flush_phrase(PgfAlignerLin* alin)
|
||||
{
|
||||
size_t n_fids = gu_buf_length(alin->parent_current);
|
||||
|
||||
if (alin->n_matches == n_fids &&
|
||||
alin->n_matches == alin->last_phrase->n_fids) {
|
||||
// if the current compound word has the same parents
|
||||
// as the last one then we just combine them with a space
|
||||
|
||||
alin->last_phrase->phrase =
|
||||
gu_format_string(alin->out_pool, "%s %s",
|
||||
alin->last_phrase->phrase,
|
||||
gu_string_buf_freeze(alin->sbuf, alin->tmp_pool));
|
||||
} else {
|
||||
// push the current word to the buffer of words
|
||||
|
||||
PgfAlignmentPhrase* phrase =
|
||||
gu_new_flex(alin->out_pool, PgfAlignmentPhrase, fids, n_fids);
|
||||
phrase->phrase = gu_string_buf_freeze(alin->sbuf, alin->out_pool);
|
||||
phrase->n_fids = n_fids;
|
||||
for (size_t i = 0; i < n_fids; i++) {
|
||||
phrase->fids[i] = gu_buf_get(alin->parent_current, int, i);
|
||||
}
|
||||
gu_buf_push(alin->phrases, PgfAlignmentPhrase*, phrase);
|
||||
|
||||
alin->last_phrase = phrase;
|
||||
}
|
||||
|
||||
alin->n_matches = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
pgf_aligner_push_parent(PgfAlignerLin* alin, int fid)
|
||||
{
|
||||
gu_buf_push(alin->parent_current, int, fid);
|
||||
|
||||
if (alin->last_phrase != NULL) {
|
||||
for (size_t i = 0; i < alin->last_phrase->n_fids; i++) {
|
||||
if (fid == alin->last_phrase->fids[i]) {
|
||||
alin->n_matches++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pgf_aligner_lzn_symbol_token(PgfLinFuncs** funcs, PgfToken tok)
|
||||
{
|
||||
PgfAlignerLin* alin = gu_container(funcs, PgfAlignerLin, funcs);
|
||||
if (!gu_ok(alin->err)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// get the tree node id that generates this token
|
||||
size_t n_parents = gu_buf_length(alin->parent_stack);
|
||||
int fid = gu_buf_get(alin->parent_stack, int, n_parents-1);
|
||||
|
||||
// how many nodes so far are involved in the current compound word
|
||||
size_t n_fids = gu_buf_length(alin->parent_current);
|
||||
|
||||
if (alin->bind) {
|
||||
// here we glue tokens
|
||||
|
||||
alin->bind = false;
|
||||
|
||||
bool found = false;
|
||||
for (size_t i = 0; i < n_fids; i++) {
|
||||
int current_fid = gu_buf_get(alin->parent_current, int, i);
|
||||
if (fid == current_fid) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// add the tree node id to the list of parents if it has not
|
||||
// been added already.
|
||||
if (!found) {
|
||||
pgf_aligner_push_parent(alin, fid);
|
||||
}
|
||||
} else {
|
||||
// here we start a new (compound) word
|
||||
|
||||
pgf_aligner_flush_phrase(alin);
|
||||
gu_string_buf_flush(alin->sbuf);
|
||||
gu_buf_flush(alin->parent_current);
|
||||
|
||||
pgf_aligner_push_parent(alin, fid);
|
||||
|
||||
if (alin->capit == PGF_CAPIT_NEXT)
|
||||
alin->capit = PGF_CAPIT_NONE;
|
||||
}
|
||||
|
||||
GuOut* out = gu_string_buf_out(alin->sbuf);
|
||||
|
||||
switch (alin->capit) {
|
||||
case PGF_CAPIT_NONE:
|
||||
gu_string_write(tok, out, alin->err);
|
||||
break;
|
||||
case PGF_CAPIT_FIRST: {
|
||||
GuUCS c = gu_utf8_decode((const uint8_t**) &tok);
|
||||
c = gu_ucs_to_upper(c);
|
||||
gu_out_utf8(c, out, alin->err);
|
||||
gu_string_write(tok, out, alin->err);
|
||||
alin->capit = PGF_CAPIT_NONE;
|
||||
break;
|
||||
}
|
||||
case PGF_CAPIT_ALL:
|
||||
alin->capit = PGF_CAPIT_NEXT;
|
||||
// continue
|
||||
case PGF_CAPIT_NEXT: {
|
||||
const uint8_t* p = (uint8_t*) tok;
|
||||
while (*p) {
|
||||
GuUCS c = gu_utf8_decode(&p);
|
||||
c = gu_ucs_to_upper(c);
|
||||
gu_out_utf8(c, out, alin->err);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pgf_aligner_lzn_begin_phrase(PgfLinFuncs** funcs, PgfCId cat, int fid, GuString ann, PgfCId fun)
|
||||
{
|
||||
PgfAlignerLin* alin = gu_container(funcs, PgfAlignerLin, funcs);
|
||||
gu_buf_push(alin->parent_stack, int, fid);
|
||||
}
|
||||
|
||||
static void
|
||||
pgf_aligner_lzn_end_phrase(PgfLinFuncs** funcs, PgfCId cat, int fid, GuString ann, PgfCId fun)
|
||||
{
|
||||
PgfAlignerLin* alin = gu_container(funcs, PgfAlignerLin, funcs);
|
||||
gu_buf_pop(alin->parent_stack, int);
|
||||
}
|
||||
|
||||
static void
|
||||
pgf_aligner_lzn_symbol_ne(PgfLinFuncs** funcs)
|
||||
{
|
||||
PgfAlignerLin* alin = gu_container(funcs, PgfAlignerLin, funcs);
|
||||
gu_raise(alin->err, PgalinNonExist);
|
||||
}
|
||||
|
||||
static void
|
||||
pgf_aligner_lzn_symbol_bind(PgfLinFuncs** funcs)
|
||||
{
|
||||
PgfAlignerLin* alin = gu_container(funcs, PgfAlignerLin, funcs);
|
||||
alin->bind = true;
|
||||
}
|
||||
|
||||
static void
|
||||
pgf_aligner_lzn_symbol_capit(PgfLinFuncs** funcs, PgfCapitState capit)
|
||||
{
|
||||
PgfAlignerLin* alin = gu_container(funcs, PgfAlignerLin, funcs);
|
||||
alin->capit = capit;
|
||||
}
|
||||
|
||||
static void
|
||||
pgf_aligner_lzn_symbol_meta(PgfLinFuncs** funcs, PgfMetaId id)
|
||||
{
|
||||
pgf_aligner_lzn_symbol_token(funcs, "?");
|
||||
}
|
||||
|
||||
static PgfLinFuncs pgf_file_lin_funcs = {
|
||||
.symbol_token = pgf_aligner_lzn_symbol_token,
|
||||
.begin_phrase = pgf_aligner_lzn_begin_phrase,
|
||||
.end_phrase = pgf_aligner_lzn_end_phrase,
|
||||
.symbol_ne = pgf_aligner_lzn_symbol_ne,
|
||||
.symbol_bind = pgf_aligner_lzn_symbol_bind,
|
||||
.symbol_capit = pgf_aligner_lzn_symbol_capit,
|
||||
.symbol_meta = pgf_aligner_lzn_symbol_meta
|
||||
};
|
||||
|
||||
GuSeq*
|
||||
pgf_align_words(PgfConcr* concr, PgfExpr expr,
|
||||
GuExn* err, GuPool* pool)
|
||||
{
|
||||
GuPool* tmp_pool = gu_local_pool();
|
||||
|
||||
GuEnum* cts =
|
||||
pgf_lzr_concretize(concr, expr, err, tmp_pool);
|
||||
if (!gu_ok(err)) {
|
||||
gu_pool_free(tmp_pool);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GuBuf* phrases = gu_new_buf(PgfAlignmentPhrase*, pool);
|
||||
|
||||
PgfCncTree ctree = gu_next(cts, PgfCncTree, tmp_pool);
|
||||
if (!gu_variant_is_null(ctree)) {
|
||||
ctree = pgf_lzr_wrap_linref(ctree, tmp_pool);
|
||||
|
||||
PgfAlignerLin alin = {
|
||||
.funcs = &pgf_file_lin_funcs,
|
||||
.parent_stack = gu_new_buf(int, tmp_pool),
|
||||
.parent_current = gu_new_buf(int, tmp_pool),
|
||||
.phrases = phrases,
|
||||
.last_phrase = NULL,
|
||||
.sbuf = gu_new_string_buf(tmp_pool),
|
||||
.n_matches = 0,
|
||||
.err = err,
|
||||
.bind = true,
|
||||
.capit = PGF_CAPIT_NONE,
|
||||
.out_pool = pool,
|
||||
.tmp_pool = tmp_pool
|
||||
};
|
||||
gu_buf_push(alin.parent_stack, int, -1);
|
||||
|
||||
pgf_lzr_linearize(concr, ctree, 0, &alin.funcs, tmp_pool);
|
||||
if (!gu_ok(err)) {
|
||||
gu_pool_free(tmp_pool);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pgf_aligner_flush_phrase(&alin);
|
||||
}
|
||||
|
||||
gu_pool_free(tmp_pool);
|
||||
return gu_buf_data_seq(phrases);
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
#include "data.h"
|
||||
#include <gu/variant.h>
|
||||
#include <gu/assert.h>
|
||||
#include <math.h>
|
||||
|
||||
PGF_INTERNAL bool
|
||||
pgf_tokens_equal(PgfTokens* t1, PgfTokens* t2)
|
||||
{
|
||||
size_t len1 = gu_seq_length(t1);
|
||||
size_t len2 = gu_seq_length(t2);
|
||||
if (len1 != len2) {
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < len1; i++) {
|
||||
GuString s1 = gu_seq_get(t1, PgfToken, i);
|
||||
GuString s2 = gu_seq_get(t2, PgfToken, i);
|
||||
if (strcmp(s1, s2) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
pgf_flag_cmp_fn(GuOrder* self, const void* p1, const void* p2)
|
||||
{
|
||||
(void) self;
|
||||
return strcmp((GuString) p1, ((PgfFlag*) p2)->name);
|
||||
}
|
||||
|
||||
PGF_INTERNAL GuOrder pgf_flag_order[1] = { { pgf_flag_cmp_fn } };
|
||||
|
||||
static int
|
||||
pgf_abscat_cmp_fn(GuOrder* self, const void* p1, const void* p2)
|
||||
{
|
||||
(void) self;
|
||||
return strcmp((GuString) p1, ((PgfAbsCat*) p2)->name);
|
||||
}
|
||||
|
||||
PGF_INTERNAL GuOrder pgf_abscat_order[1] = { { pgf_abscat_cmp_fn } };
|
||||
|
||||
static int
|
||||
pgf_absfun_cmp_fn(GuOrder* self, const void* p1, const void* p2)
|
||||
{
|
||||
(void) self;
|
||||
return strcmp((GuString) p1, ((PgfAbsFun*) p2)->name);
|
||||
}
|
||||
|
||||
PGF_INTERNAL GuOrder pgf_absfun_order[1] = { { pgf_absfun_cmp_fn } };
|
||||
|
||||
static int
|
||||
pgf_concr_cmp_fn(GuOrder* self, const void* p1, const void* p2)
|
||||
{
|
||||
(void) self;
|
||||
return strcmp((GuString) p1, ((PgfConcr*) p2)->name);
|
||||
}
|
||||
|
||||
PGF_INTERNAL GuOrder pgf_concr_order[1] = { { pgf_concr_cmp_fn } };
|
||||
@@ -1,372 +0,0 @@
|
||||
#ifndef PGF_DATA_H_
|
||||
#define PGF_DATA_H_
|
||||
|
||||
#include <gu/variant.h>
|
||||
#include <gu/map.h>
|
||||
#include <gu/string.h>
|
||||
#include <gu/seq.h>
|
||||
#include <pgf/pgf.h>
|
||||
|
||||
typedef struct PgfCCat PgfCCat;
|
||||
|
||||
typedef GuSeq PgfCCats;
|
||||
|
||||
#define PgfCIdMap GuStringMap
|
||||
|
||||
typedef struct {
|
||||
PgfCId name;
|
||||
PgfLiteral value;
|
||||
} PgfFlag;
|
||||
|
||||
typedef GuSeq PgfFlags;
|
||||
|
||||
PGF_INTERNAL_DECL extern GuOrder pgf_flag_order[1];
|
||||
|
||||
// PgfPatt
|
||||
|
||||
typedef GuVariant PgfPatt;
|
||||
|
||||
typedef enum {
|
||||
PGF_PATT_APP,
|
||||
PGF_PATT_VAR,
|
||||
PGF_PATT_AS,
|
||||
PGF_PATT_WILD,
|
||||
PGF_PATT_LIT,
|
||||
PGF_PATT_IMPL_ARG,
|
||||
PGF_PATT_TILDE,
|
||||
PGF_PATT_NUM_TAGS
|
||||
} PgfPattTag;
|
||||
|
||||
typedef struct {
|
||||
PgfCId ctor;
|
||||
size_t n_args;
|
||||
PgfPatt args[];
|
||||
} PgfPattApp;
|
||||
|
||||
typedef struct {
|
||||
PgfLiteral lit;
|
||||
} PgfPattLit;
|
||||
|
||||
typedef struct {
|
||||
PgfCId var;
|
||||
} PgfPattVar;
|
||||
|
||||
typedef struct {
|
||||
PgfCId var;
|
||||
PgfPatt patt;
|
||||
} PgfPattAs;
|
||||
|
||||
typedef char PgfPattWild;
|
||||
|
||||
typedef struct {
|
||||
PgfPatt patt;
|
||||
} PgfPattImplArg;
|
||||
|
||||
typedef struct {
|
||||
PgfExpr expr;
|
||||
} PgfPattTilde;
|
||||
|
||||
typedef struct {
|
||||
PgfExpr body;
|
||||
size_t n_patts;
|
||||
PgfPatt patts[];
|
||||
} PgfEquation;
|
||||
|
||||
typedef GuSeq PgfEquations;
|
||||
|
||||
typedef void *PgfFunction;
|
||||
|
||||
typedef struct {
|
||||
PgfCId name;
|
||||
PgfType* type;
|
||||
int arity;
|
||||
PgfEquations* defns; // maybe null
|
||||
PgfExprProb ep;
|
||||
PgfFunction predicate;
|
||||
struct {
|
||||
PgfFunction code;
|
||||
union {
|
||||
size_t caf_offset;
|
||||
PgfFunction* con;
|
||||
};
|
||||
} closure;
|
||||
} PgfAbsFun;
|
||||
|
||||
typedef GuSeq PgfAbsFuns;
|
||||
|
||||
PGF_INTERNAL_DECL extern GuOrder pgf_absfun_order[1];
|
||||
|
||||
typedef GuMap PgfMetaChildMap;
|
||||
|
||||
typedef struct {
|
||||
PgfCId name;
|
||||
PgfHypos* context;
|
||||
|
||||
prob_t prob;
|
||||
|
||||
void* predicate;
|
||||
} PgfAbsCat;
|
||||
|
||||
typedef GuSeq PgfAbsCats;
|
||||
|
||||
PGF_INTERNAL_DECL extern GuOrder pgf_abscat_order[1];
|
||||
|
||||
|
||||
typedef struct PgfEvalGates PgfEvalGates;
|
||||
|
||||
typedef struct {
|
||||
PgfCId name;
|
||||
PgfFlags* aflags;
|
||||
PgfAbsFuns* funs;
|
||||
PgfAbsCats* cats;
|
||||
PgfAbsFun* abs_lin_fun;
|
||||
PgfEvalGates* eval_gates;
|
||||
} PgfAbstr;
|
||||
|
||||
typedef enum {
|
||||
PGF_INSTR_CHECK_ARGS = 0,
|
||||
PGF_INSTR_CASE = 1,
|
||||
PGF_INSTR_CASE_LIT = 2,
|
||||
PGF_INSTR_SAVE = 3,
|
||||
PGF_INSTR_ALLOC = 4,
|
||||
PGF_INSTR_PUT_CONSTR = 5,
|
||||
PGF_INSTR_PUT_CLOSURE = 6,
|
||||
PGF_INSTR_PUT_LIT = 7,
|
||||
PGF_INSTR_SET = 8,
|
||||
PGF_INSTR_SET_PAD = 9,
|
||||
PGF_INSTR_PUSH_FRAME = 10,
|
||||
PGF_INSTR_PUSH = 11,
|
||||
PGF_INSTR_TUCK = 12,
|
||||
PGF_INSTR_EVAL = 13,
|
||||
PGF_INSTR_DROP = 16,
|
||||
PGF_INSTR_JUMP = 17,
|
||||
PGF_INSTR_FAIL = 18,
|
||||
PGF_INSTR_PUSH_ACCUM = 19,
|
||||
PGF_INSTR_POP_ACCUM = 20,
|
||||
PGF_INSTR_ADD = 21,
|
||||
} PgfInstruction;
|
||||
|
||||
typedef GuSeq PgfConcrs;
|
||||
|
||||
PGF_INTERNAL_DECL extern GuOrder pgf_concr_order[1];
|
||||
|
||||
struct PgfPGF {
|
||||
uint16_t major_version;
|
||||
uint16_t minor_version;
|
||||
PgfFlags* gflags;
|
||||
PgfAbstr abstract;
|
||||
PgfConcrs* concretes;
|
||||
GuPool* pool; // the pool in which the grammar is allocated
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
PgfAbsCat *abscat;
|
||||
PgfCCats* cats;
|
||||
|
||||
size_t n_lins;
|
||||
GuString labels[];
|
||||
/**< Labels for tuples. All nested tuples, records and tables
|
||||
* in the GF linearization types are flattened into a single
|
||||
* tuple in the corresponding PGF concrete category. This
|
||||
* field holds the labels that indicate which GF field or
|
||||
* parameter (or their combination) each tuple element
|
||||
* represents. */
|
||||
} PgfCncCat;
|
||||
|
||||
typedef GuSeq PgfTokens;
|
||||
|
||||
PGF_INTERNAL_DECL bool
|
||||
pgf_tokens_equal(PgfTokens* t1, PgfTokens* t2);
|
||||
|
||||
typedef GuSeq PgfSymbols;
|
||||
|
||||
typedef struct {
|
||||
PgfSymbols* form;
|
||||
/**< The form of this variant as a list of tokens. */
|
||||
|
||||
GuStrings* prefixes;
|
||||
/**< The prefixes of the following symbol that trigger this
|
||||
* form. */
|
||||
} PgfAlternative;
|
||||
|
||||
typedef struct PgfItemConts PgfItemConts;
|
||||
|
||||
typedef PgfCIdMap PgfPrintNames;
|
||||
|
||||
typedef GuStringMap PgfCncFunOverloadMap;
|
||||
|
||||
typedef GuMap PgfCncOverloadMap;
|
||||
|
||||
typedef struct PgfItem PgfItem;
|
||||
|
||||
typedef GuVariant PgfSymbol;
|
||||
|
||||
typedef enum {
|
||||
PGF_SYMBOL_CAT,
|
||||
PGF_SYMBOL_LIT,
|
||||
PGF_SYMBOL_VAR,
|
||||
PGF_SYMBOL_KS,
|
||||
PGF_SYMBOL_KP,
|
||||
PGF_SYMBOL_BIND,
|
||||
PGF_SYMBOL_SOFT_BIND,
|
||||
PGF_SYMBOL_NE,
|
||||
PGF_SYMBOL_SOFT_SPACE,
|
||||
PGF_SYMBOL_CAPIT,
|
||||
PGF_SYMBOL_ALL_CAPIT,
|
||||
} PgfSymbolTag;
|
||||
|
||||
typedef struct {
|
||||
int d;
|
||||
int r;
|
||||
} PgfSymbolIdx;
|
||||
|
||||
typedef PgfSymbolIdx PgfSymbolCat, PgfSymbolLit, PgfSymbolVar;
|
||||
|
||||
typedef struct {
|
||||
char token[0]; // a flexible array that contains the token
|
||||
} PgfSymbolKS;
|
||||
|
||||
typedef struct PgfSymbolKP
|
||||
/** A prefix-dependent symbol. The form that this symbol takes
|
||||
* depends on the form of a prefix of the following symbol. */
|
||||
{
|
||||
PgfSymbols* default_form;
|
||||
/**< Default form that this symbol takes if none of of the
|
||||
* variant forms is triggered. */
|
||||
|
||||
size_t n_forms;
|
||||
PgfAlternative forms[];
|
||||
/**< Variant forms whose choise depends on the following
|
||||
* symbol. */
|
||||
} PgfSymbolKP;
|
||||
|
||||
typedef struct {
|
||||
char nothing[0]; // Empty struct
|
||||
} PgfSymbolNE;
|
||||
|
||||
typedef struct {
|
||||
char nothing[0]; // Empty struct
|
||||
} PgfSymbolBIND;
|
||||
|
||||
typedef struct {
|
||||
char nothing[0]; // Empty struct
|
||||
} PgfSymbolCAPIT;
|
||||
|
||||
typedef GuBuf PgfProductionIdx;
|
||||
|
||||
typedef struct {
|
||||
PgfSymbols* syms; // -> PgfSymbol
|
||||
PgfProductionIdx* idx;
|
||||
} PgfSequence;
|
||||
|
||||
typedef GuSeq PgfSequences;
|
||||
|
||||
typedef struct {
|
||||
PgfAbsFun* absfun;
|
||||
PgfExprProb *ep;
|
||||
int funid;
|
||||
size_t n_lins;
|
||||
PgfSequence* lins[];
|
||||
} PgfCncFun;
|
||||
|
||||
typedef GuSeq PgfCncFuns;
|
||||
|
||||
struct PgfConcr {
|
||||
PgfCId name;
|
||||
PgfAbstr* abstr;
|
||||
PgfFlags* cflags;
|
||||
PgfPrintNames* printnames;
|
||||
GuMap* ccats;
|
||||
PgfCncFunOverloadMap* fun_indices;
|
||||
PgfCncOverloadMap* coerce_idx;
|
||||
PgfCncFuns* cncfuns;
|
||||
PgfSequences* sequences;
|
||||
PgfCIdMap* cnccats;
|
||||
int total_cats;
|
||||
|
||||
GuPool* pool; // if the language is loaded separately then this is the pool
|
||||
GuFinalizer fin; // and this is the finalizer in the pool of the whole grammar
|
||||
};
|
||||
|
||||
|
||||
|
||||
// PgfProduction
|
||||
|
||||
typedef GuVariant PgfProduction;
|
||||
|
||||
typedef enum {
|
||||
PGF_PRODUCTION_APPLY,
|
||||
PGF_PRODUCTION_COERCE,
|
||||
PGF_PRODUCTION_EXTERN
|
||||
} PgfProductionTag;
|
||||
|
||||
typedef struct {
|
||||
PgfCCat* ccat;
|
||||
PgfCCats* hypos;
|
||||
} PgfPArg;
|
||||
|
||||
typedef GuSeq PgfPArgs;
|
||||
|
||||
typedef struct {
|
||||
PgfCncFun* fun;
|
||||
PgfPArgs* args;
|
||||
} PgfProductionApply;
|
||||
|
||||
typedef struct PgfProductionCoerce
|
||||
/** A coercion. This production is a logical union of the coercions of
|
||||
* another FId. This allows common subsets of productions to be
|
||||
* shared. */
|
||||
{
|
||||
PgfCCat* coerce;
|
||||
} PgfProductionCoerce;
|
||||
|
||||
typedef struct {
|
||||
PgfExprProb *ep;
|
||||
size_t n_lins;
|
||||
PgfSymbols* lins[];
|
||||
} PgfProductionExtern;
|
||||
|
||||
typedef struct {
|
||||
PgfExprProb *ep;
|
||||
PgfPArgs* args;
|
||||
} PgfProductionMeta;
|
||||
|
||||
typedef GuSeq PgfProductionSeq;
|
||||
|
||||
typedef struct {
|
||||
PgfCCat* ccat;
|
||||
size_t lin_idx;
|
||||
PgfProductionApply* papp;
|
||||
} PgfProductionIdxEntry;
|
||||
|
||||
struct PgfCCat {
|
||||
PgfCncCat* cnccat;
|
||||
PgfCncFuns* lindefs;
|
||||
PgfCncFuns* linrefs;
|
||||
size_t n_synprods;
|
||||
PgfProductionSeq* prods;
|
||||
prob_t viterbi_prob;
|
||||
int fid;
|
||||
int chunk_count;
|
||||
PgfItemConts* conts;
|
||||
struct PgfAnswers* answers;
|
||||
GuFinalizer fin[0];
|
||||
};
|
||||
|
||||
PGF_API_DECL bool
|
||||
pgf_production_is_lexical(PgfProductionApply *papp,
|
||||
GuBuf* non_lexical_buf, GuPool* pool);
|
||||
|
||||
PGF_API_DECL void
|
||||
pgf_parser_index(PgfConcr* concr,
|
||||
PgfCCat* ccat, PgfProduction prod,
|
||||
bool is_lexical,
|
||||
GuPool *pool);
|
||||
|
||||
PGF_API_DECL void
|
||||
pgf_lzr_index(PgfConcr* concr,
|
||||
PgfCCat* ccat, PgfProduction prod,
|
||||
bool is_lexical,
|
||||
GuPool *pool);
|
||||
|
||||
#endif
|
||||
@@ -1,513 +0,0 @@
|
||||
#include "pgf/pgf.h"
|
||||
#include "pgf/data.h"
|
||||
#include "pgf/reasoner.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define PGF_ARGS_DELTA 5
|
||||
|
||||
static inline PgfClosure*
|
||||
pgf_mk_pap(PgfReasoner* rs, PgfClosure* fun,
|
||||
size_t n_args, PgfClosure** args)
|
||||
{
|
||||
if (n_args > 0) {
|
||||
PgfValuePAP* val = gu_new_flex(rs->pool, PgfValuePAP, args, n_args);
|
||||
val->header.code = rs->eval_gates->evaluate_value_pap;
|
||||
val->fun = fun;
|
||||
val->n_args = n_args*sizeof(PgfClosure*);
|
||||
for (size_t i = 0; i < n_args; i++) {
|
||||
val->args[i] = args[i];
|
||||
}
|
||||
return &val->header;
|
||||
}
|
||||
return fun;
|
||||
}
|
||||
|
||||
PGF_INTERNAL PgfClosure*
|
||||
pgf_evaluate_expr_thunk(PgfReasoner* rs, PgfExprThunk* thunk)
|
||||
{
|
||||
PgfEnv* env = thunk->env;
|
||||
PgfExpr expr = thunk->expr;
|
||||
|
||||
size_t n_args = 0;
|
||||
PgfClosure** args = NULL;
|
||||
PgfClosure* res = NULL;
|
||||
|
||||
repeat:;
|
||||
GuVariantInfo ei = gu_variant_open(expr);
|
||||
switch (ei.tag) {
|
||||
case PGF_EXPR_ABS: {
|
||||
PgfExprAbs* eabs = ei.data;
|
||||
|
||||
if (n_args > 0) {
|
||||
PgfEnv* new_env = gu_new(PgfEnv, rs->pool);
|
||||
new_env->next = env;
|
||||
new_env->closure = args[--n_args];
|
||||
|
||||
env = new_env;
|
||||
expr = eabs->body;
|
||||
goto repeat;
|
||||
} else {
|
||||
thunk->header.code = rs->eval_gates->evaluate_value_lambda;
|
||||
thunk->expr = eabs->body;
|
||||
res = &thunk->header;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PGF_EXPR_APP: {
|
||||
PgfExprApp* eapp = ei.data;
|
||||
PgfExprThunk* thunk =
|
||||
gu_new(PgfExprThunk, rs->pool);
|
||||
thunk->header.code = rs->eval_gates->evaluate_expr_thunk;
|
||||
thunk->env = env;
|
||||
thunk->expr = eapp->arg;
|
||||
|
||||
if (n_args % PGF_ARGS_DELTA == 0) {
|
||||
args = realloc(args, n_args + PGF_ARGS_DELTA);
|
||||
}
|
||||
args[n_args++] = &thunk->header;
|
||||
|
||||
expr = eapp->fun;
|
||||
goto repeat;
|
||||
}
|
||||
case PGF_EXPR_LIT: {
|
||||
PgfExprLit* elit = ei.data;
|
||||
PgfValueLit* val = (PgfValueLit*) thunk;
|
||||
val->header.code = rs->eval_gates->evaluate_value_lit;
|
||||
val->lit = elit->lit;
|
||||
res = &val->header;
|
||||
break;
|
||||
}
|
||||
case PGF_EXPR_META: {
|
||||
PgfExprMeta* emeta = ei.data;
|
||||
|
||||
PgfValueMeta* val =
|
||||
gu_new(PgfValueMeta, rs->pool);
|
||||
val->header.code = rs->eval_gates->evaluate_meta;
|
||||
val->env = env;
|
||||
val->id = emeta->id;
|
||||
res = pgf_mk_pap(rs, &val->header, n_args, args);
|
||||
break;
|
||||
}
|
||||
case PGF_EXPR_FUN: {
|
||||
PgfExprFun* efun = ei.data;
|
||||
|
||||
PgfAbsFun* absfun =
|
||||
gu_seq_binsearch(rs->abstract->funs, pgf_absfun_order, PgfAbsFun, efun->fun);
|
||||
gu_assert(absfun != NULL);
|
||||
|
||||
if (absfun->closure.code != NULL) {
|
||||
res = pgf_mk_pap(rs, (PgfClosure*) &absfun->closure, n_args, args);
|
||||
} else {
|
||||
size_t arity = absfun->arity;
|
||||
|
||||
if (n_args >= arity) {
|
||||
PgfValue* val = gu_new_flex(rs->pool, PgfValue, args, n_args);
|
||||
val->header.code = rs->eval_gates->evaluate_value;
|
||||
val->con = (PgfClosure*) &absfun->closure;
|
||||
|
||||
for (size_t i = 0; i < n_args; i++) {
|
||||
val->args[i] = args[--n_args];
|
||||
}
|
||||
res = &val->header;
|
||||
} else {
|
||||
PgfExprThunk* lambda = gu_new(PgfExprThunk, rs->pool);
|
||||
lambda->header.code = rs->eval_gates->evaluate_value_lambda;
|
||||
lambda->env = NULL;
|
||||
res = pgf_mk_pap(rs, &lambda->header, n_args, args);
|
||||
|
||||
for (size_t i = 0; i < arity; i++) {
|
||||
PgfExpr new_expr, arg;
|
||||
|
||||
PgfExprVar *evar =
|
||||
gu_new_variant(PGF_EXPR_VAR,
|
||||
PgfExprVar,
|
||||
&arg, rs->pool);
|
||||
evar->var = arity-i-1;
|
||||
|
||||
PgfExprApp *eapp =
|
||||
gu_new_variant(PGF_EXPR_APP,
|
||||
PgfExprApp,
|
||||
&new_expr, rs->pool);
|
||||
eapp->fun = expr;
|
||||
eapp->arg = arg;
|
||||
|
||||
expr = new_expr;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < arity-1; i++) {
|
||||
PgfExpr new_expr;
|
||||
|
||||
PgfExprAbs *eabs =
|
||||
gu_new_variant(PGF_EXPR_ABS,
|
||||
PgfExprAbs,
|
||||
&new_expr, rs->pool);
|
||||
eabs->bind_type = PGF_BIND_TYPE_EXPLICIT;
|
||||
eabs->id = "_";
|
||||
eabs->body = expr;
|
||||
|
||||
expr = new_expr;
|
||||
}
|
||||
|
||||
lambda->expr = expr;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PGF_EXPR_VAR: {
|
||||
PgfExprVar* evar = ei.data;
|
||||
PgfEnv* tmp_env = env;
|
||||
size_t i = evar->var;
|
||||
while (i > 0) {
|
||||
tmp_env = tmp_env->next;
|
||||
if (tmp_env == NULL) {
|
||||
GuExnData* err_data = gu_raise(rs->err, PgfExn);
|
||||
if (err_data) {
|
||||
err_data->data = "invalid de Bruijn index";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
i--;
|
||||
}
|
||||
|
||||
res = pgf_mk_pap(rs, tmp_env->closure, n_args, args);
|
||||
break;
|
||||
}
|
||||
case PGF_EXPR_TYPED: {
|
||||
PgfExprTyped* etyped = ei.data;
|
||||
expr = etyped->expr;
|
||||
goto repeat;
|
||||
}
|
||||
case PGF_EXPR_IMPL_ARG: {
|
||||
PgfExprImplArg* eimpl = ei.data;
|
||||
expr = eimpl->expr;
|
||||
goto repeat;
|
||||
}
|
||||
default:
|
||||
gu_impossible();
|
||||
}
|
||||
|
||||
free(args);
|
||||
return res;
|
||||
}
|
||||
|
||||
PGF_INTERNAL PgfClosure*
|
||||
pgf_evaluate_lambda_application(PgfReasoner* rs, PgfExprThunk* lambda,
|
||||
PgfClosure* arg)
|
||||
{
|
||||
PgfEnv* new_env = gu_new(PgfEnv, rs->pool);
|
||||
new_env->next = lambda->env;
|
||||
new_env->closure = arg;
|
||||
|
||||
PgfExprThunk* thunk = gu_new(PgfExprThunk, rs->pool);
|
||||
thunk->header.code = rs->eval_gates->evaluate_expr_thunk;
|
||||
thunk->env = new_env;
|
||||
thunk->expr = lambda->expr;
|
||||
return pgf_evaluate_expr_thunk(rs, thunk);
|
||||
}
|
||||
|
||||
static PgfExpr
|
||||
pgf_value2expr(PgfReasoner* rs, int level, PgfClosure* clos)
|
||||
{
|
||||
clos = rs->eval_gates->enter(rs, clos);
|
||||
if (clos == NULL)
|
||||
return gu_null_variant;
|
||||
|
||||
PgfExpr expr = gu_null_variant;
|
||||
size_t n_args = 0;
|
||||
PgfClosure** args;
|
||||
|
||||
if (clos->code == rs->eval_gates->evaluate_value) {
|
||||
PgfValue* val = (PgfValue*) clos;
|
||||
PgfAbsFun* absfun = gu_container(val->con, PgfAbsFun, closure);
|
||||
|
||||
expr = absfun->ep.expr;
|
||||
n_args = gu_seq_length(absfun->type->hypos);
|
||||
args = val->args;
|
||||
} else if (clos->code == rs->eval_gates->evaluate_value_lit) {
|
||||
PgfValueLit* val = (PgfValueLit*) clos;
|
||||
|
||||
PgfExprLit *elit =
|
||||
gu_new_variant(PGF_EXPR_LIT,
|
||||
PgfExprLit,
|
||||
&expr, rs->out_pool);
|
||||
|
||||
GuVariantInfo i = gu_variant_open(val->lit);
|
||||
switch (i.tag) {
|
||||
case PGF_LITERAL_STR: {
|
||||
PgfLiteralStr* lstr = i.data;
|
||||
|
||||
PgfLiteralStr* new_lstr =
|
||||
gu_new_flex_variant(PGF_LITERAL_STR,
|
||||
PgfLiteralStr,
|
||||
val, strlen(lstr->val)+1,
|
||||
&elit->lit, rs->out_pool);
|
||||
strcpy(new_lstr->val, lstr->val);
|
||||
break;
|
||||
}
|
||||
case PGF_LITERAL_INT: {
|
||||
PgfLiteralInt* lint = i.data;
|
||||
|
||||
PgfLiteralInt* new_lint =
|
||||
gu_new_variant(PGF_LITERAL_INT,
|
||||
PgfLiteralInt,
|
||||
&elit->lit, rs->out_pool);
|
||||
new_lint->val = lint->val;
|
||||
break;
|
||||
}
|
||||
case PGF_LITERAL_FLT: {
|
||||
PgfLiteralFlt* lflt = i.data;
|
||||
|
||||
PgfLiteralFlt* new_lflt =
|
||||
gu_new_variant(PGF_LITERAL_FLT,
|
||||
PgfLiteralFlt,
|
||||
&elit->lit, rs->out_pool);
|
||||
new_lflt->val = lflt->val;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
gu_impossible();
|
||||
}
|
||||
} else if (clos->code == rs->eval_gates->evaluate_value_pap) {
|
||||
PgfValuePAP *pap = (PgfValuePAP*) clos;
|
||||
|
||||
PgfValueGen* gen =
|
||||
gu_new(PgfValueGen, rs->pool);
|
||||
gen->header.code = rs->eval_gates->evaluate_gen;
|
||||
gen->level = level;
|
||||
|
||||
size_t n_args = pap->n_args/sizeof(PgfClosure*);
|
||||
PgfValuePAP* new_pap = gu_new_flex(rs->pool, PgfValuePAP, args, n_args+1);
|
||||
new_pap->header.code = rs->eval_gates->evaluate_value_pap;
|
||||
new_pap->fun = pap->fun;
|
||||
new_pap->n_args = pap->n_args+sizeof(PgfClosure*);
|
||||
new_pap->args[0] = &gen->header;
|
||||
for (size_t i = 0; i < n_args; i++) {
|
||||
new_pap->args[i+1] = pap->args[i];
|
||||
}
|
||||
|
||||
PgfExprAbs *eabs =
|
||||
gu_new_variant(PGF_EXPR_ABS,
|
||||
PgfExprAbs,
|
||||
&expr, rs->out_pool);
|
||||
eabs->bind_type = PGF_BIND_TYPE_EXPLICIT;
|
||||
eabs->id = gu_format_string(rs->out_pool, "v%d", level);
|
||||
eabs->body = pgf_value2expr(rs, level+1, &new_pap->header);
|
||||
} else if (clos->code == rs->eval_gates->evaluate_value_const) {
|
||||
PgfValuePAP* val = (PgfValuePAP*) clos;
|
||||
|
||||
if (val->fun->code == rs->eval_gates->evaluate_meta) {
|
||||
PgfValueMeta* fun = (PgfValueMeta*) val->fun;
|
||||
|
||||
PgfExprMeta *emeta =
|
||||
gu_new_variant(PGF_EXPR_META,
|
||||
PgfExprMeta,
|
||||
&expr, rs->out_pool);
|
||||
emeta->id = fun->id;
|
||||
} else if (val->fun->code == rs->eval_gates->evaluate_gen) {
|
||||
PgfValueGen* fun = (PgfValueGen*) val->fun;
|
||||
|
||||
PgfExprVar *evar =
|
||||
gu_new_variant(PGF_EXPR_VAR,
|
||||
PgfExprVar,
|
||||
&expr, rs->out_pool);
|
||||
evar->var = level - fun->level - 1;
|
||||
} else if (val->fun->code == rs->eval_gates->evaluate_sum) {
|
||||
PgfValueSum* sum = (PgfValueSum*) val->fun;
|
||||
|
||||
PgfExpr e1,e2;
|
||||
PgfExprFun *efun =
|
||||
gu_new_flex_variant(PGF_EXPR_FUN,
|
||||
PgfExprFun,
|
||||
fun, 2,
|
||||
&e1, rs->out_pool);
|
||||
strcpy(efun->fun, "+");
|
||||
|
||||
PgfExprLit *elit =
|
||||
gu_new_variant(PGF_EXPR_LIT,
|
||||
PgfExprLit,
|
||||
&e2, rs->out_pool);
|
||||
elit->lit = sum->lit;
|
||||
|
||||
PgfExprApp* eapp =
|
||||
gu_new_variant(PGF_EXPR_APP,
|
||||
PgfExprApp,
|
||||
&expr, rs->out_pool);
|
||||
eapp->fun = e1;
|
||||
eapp->arg = e2;
|
||||
|
||||
size_t n_consts = gu_buf_length(sum->consts);
|
||||
for (size_t i = 0; i < n_consts; i++) {
|
||||
PgfClosure* con =
|
||||
gu_buf_get(sum->consts, PgfClosure*, i);
|
||||
|
||||
PgfExpr fun = expr;
|
||||
PgfExpr arg =
|
||||
pgf_value2expr(rs, level, con);
|
||||
if (gu_variant_is_null(arg))
|
||||
return gu_null_variant;
|
||||
|
||||
PgfExprApp* e =
|
||||
gu_new_variant(PGF_EXPR_APP,
|
||||
PgfExprApp,
|
||||
&expr, rs->out_pool);
|
||||
e->fun = fun;
|
||||
e->arg = arg;
|
||||
}
|
||||
} else {
|
||||
PgfAbsFun* absfun = gu_container(val->fun, PgfAbsFun, closure);
|
||||
expr = absfun->ep.expr;
|
||||
}
|
||||
|
||||
n_args = val->n_args/sizeof(PgfClosure*);
|
||||
args = val->args;
|
||||
} else {
|
||||
gu_impossible();
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < n_args; i++) {
|
||||
PgfExpr fun = expr;
|
||||
PgfExpr arg =
|
||||
pgf_value2expr(rs, level, args[i]);
|
||||
if (gu_variant_is_null(arg))
|
||||
return gu_null_variant;
|
||||
|
||||
PgfExprApp* e =
|
||||
gu_new_variant(PGF_EXPR_APP,
|
||||
PgfExprApp,
|
||||
&expr, rs->out_pool);
|
||||
e->fun = fun;
|
||||
e->arg = arg;
|
||||
}
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
PGF_API PgfExpr
|
||||
pgf_compute(PgfPGF* pgf, PgfExpr expr, GuExn* err, GuPool* pool, GuPool* out_pool)
|
||||
{
|
||||
PgfReasoner* rs =
|
||||
pgf_new_reasoner(pgf, err, pool, out_pool);
|
||||
|
||||
PgfExprThunk* thunk =
|
||||
gu_new(PgfExprThunk, pool);
|
||||
thunk->header.code = rs->eval_gates->evaluate_expr_thunk;
|
||||
thunk->env = NULL;
|
||||
thunk->expr = expr;
|
||||
|
||||
return pgf_value2expr(rs, 0, &thunk->header);
|
||||
}
|
||||
|
||||
PGF_INTERNAL void
|
||||
pgf_evaluate_accum_init_int(PgfReasoner* rs,
|
||||
PgfEvalAccum* accum, int val)
|
||||
{
|
||||
PgfLiteralInt *lit_int =
|
||||
gu_new_variant(PGF_LITERAL_INT,
|
||||
PgfLiteralInt,
|
||||
&accum->lit,
|
||||
rs->pool);
|
||||
lit_int->val = val;
|
||||
accum->consts = NULL;
|
||||
}
|
||||
|
||||
PGF_INTERNAL void
|
||||
pgf_evaluate_accum_init_str(PgfReasoner* rs,
|
||||
PgfEvalAccum* accum, GuString val)
|
||||
{
|
||||
if (val == NULL)
|
||||
val = "";
|
||||
|
||||
PgfLiteralStr *lit_str =
|
||||
gu_new_flex_variant(PGF_LITERAL_STR,
|
||||
PgfLiteralStr,
|
||||
val, strlen(val)+1,
|
||||
&accum->lit, rs->pool);
|
||||
strcpy((char*) lit_str->val, (char*) val);
|
||||
accum->consts = NULL;
|
||||
}
|
||||
|
||||
PGF_INTERNAL void
|
||||
pgf_evaluate_accum_init_flt(PgfReasoner* rs,
|
||||
PgfEvalAccum* accum, float val)
|
||||
{
|
||||
PgfLiteralFlt *lit_flt =
|
||||
gu_new_variant(PGF_LITERAL_FLT,
|
||||
PgfLiteralFlt,
|
||||
&accum->lit,
|
||||
rs->pool);
|
||||
lit_flt->val = val;
|
||||
accum->enter_stack_ptr = rs->enter_stack_ptr;
|
||||
rs->enter_stack_ptr = ((char*)accum)-sizeof(char*)*2;
|
||||
accum->consts = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
pgf_evaluate_accum_add_helper(PgfEvalAccum* accum, PgfLiteral lit)
|
||||
{
|
||||
GuVariantInfo ei = gu_variant_open(lit);
|
||||
switch (ei.tag) {
|
||||
case PGF_LITERAL_INT: {
|
||||
PgfLiteralInt* lint = ei.data;
|
||||
((PgfLiteralInt*)gu_variant_data(accum->lit))->val += lint->val;
|
||||
break;
|
||||
}
|
||||
case PGF_LITERAL_STR: {
|
||||
PgfLiteralStr* lstr = ei.data;
|
||||
break;
|
||||
}
|
||||
case PGF_LITERAL_FLT: {
|
||||
PgfLiteralFlt* lflt = ei.data;
|
||||
((PgfLiteralFlt*)gu_variant_data(accum->lit))->val += lflt->val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PGF_INTERNAL void
|
||||
pgf_evaluate_accum_add(PgfReasoner* rs,
|
||||
PgfEvalAccum* accum, PgfClosure* closure)
|
||||
{
|
||||
if (closure->code == rs->eval_gates->evaluate_value_lit) {
|
||||
PgfValueLit* val = (PgfValueLit*) closure;
|
||||
pgf_evaluate_accum_add_helper(accum, val->lit);
|
||||
} else if (closure->code == rs->eval_gates->evaluate_value_const) {
|
||||
if (accum->consts == NULL)
|
||||
accum->consts = gu_new_buf(PgfClosure*, rs->pool);
|
||||
|
||||
PgfValuePAP* pap = (PgfValuePAP*) closure;
|
||||
|
||||
if (pap->fun->code == rs->eval_gates->evaluate_sum) {
|
||||
PgfValueSum* val = (PgfValueSum*) ((PgfValuePAP*) closure)->fun;
|
||||
pgf_evaluate_accum_add_helper(accum, val->lit);
|
||||
|
||||
size_t n_consts = gu_buf_length(val->consts);
|
||||
for (size_t i = 0; i < n_consts; i++) {
|
||||
PgfClosure* clos = gu_buf_get(val->consts, PgfClosure*, i);
|
||||
gu_buf_push(accum->consts, PgfClosure*, clos);
|
||||
}
|
||||
} else {
|
||||
gu_buf_push(accum->consts, PgfClosure*, closure);
|
||||
}
|
||||
} else {
|
||||
gu_impossible();
|
||||
}
|
||||
}
|
||||
|
||||
PGF_INTERNAL PgfClosure*
|
||||
pgf_evaluate_accum_done(PgfReasoner* rs, PgfEvalAccum* accum)
|
||||
{
|
||||
rs->enter_stack_ptr = accum->enter_stack_ptr;
|
||||
|
||||
if (accum->consts == NULL) {
|
||||
PgfValueLit* val = gu_new(PgfValueLit, rs->pool);
|
||||
val->header.code = rs->eval_gates->evaluate_value_lit;
|
||||
val->lit = accum->lit;
|
||||
return &val->header;
|
||||
} else {
|
||||
PgfValueSum* val = gu_new(PgfValueSum, rs->pool);
|
||||
val->header.code = rs->eval_gates->evaluate_sum;
|
||||
val->lit = accum->lit;
|
||||
val->consts = accum->consts;
|
||||
return &val->header;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,245 +0,0 @@
|
||||
#ifndef EXPR_H_
|
||||
#define EXPR_H_
|
||||
|
||||
#include <gu/in.h>
|
||||
#include <gu/out.h>
|
||||
#include <gu/variant.h>
|
||||
#include <gu/seq.h>
|
||||
|
||||
/// Abstract syntax trees
|
||||
/// @file
|
||||
|
||||
/// An abstract syntax tree
|
||||
typedef GuVariant PgfExpr;
|
||||
|
||||
typedef struct PgfHypo PgfHypo;
|
||||
typedef struct PgfType PgfType;
|
||||
|
||||
typedef int PgfMetaId;
|
||||
|
||||
typedef enum {
|
||||
PGF_BIND_TYPE_EXPLICIT,
|
||||
PGF_BIND_TYPE_IMPLICIT
|
||||
} PgfBindType;
|
||||
|
||||
// PgfLiteral
|
||||
|
||||
typedef GuVariant PgfLiteral;
|
||||
|
||||
|
||||
typedef enum {
|
||||
PGF_LITERAL_STR,
|
||||
PGF_LITERAL_INT,
|
||||
PGF_LITERAL_FLT,
|
||||
PGF_LITERAL_NUM_TAGS
|
||||
} PgfLiteralTag;
|
||||
|
||||
typedef struct {
|
||||
char val[0]; // a flexible array that contains the value
|
||||
} PgfLiteralStr;
|
||||
|
||||
typedef struct {
|
||||
int val;
|
||||
} PgfLiteralInt;
|
||||
|
||||
typedef struct {
|
||||
double val;
|
||||
} PgfLiteralFlt;
|
||||
|
||||
|
||||
|
||||
struct PgfHypo {
|
||||
PgfBindType bind_type;
|
||||
|
||||
PgfCId cid;
|
||||
/**< Locally scoped name for the parameter if dependent types
|
||||
* are used. "_" for normal parameters. */
|
||||
|
||||
PgfType* type;
|
||||
};
|
||||
|
||||
typedef GuSeq PgfHypos;
|
||||
|
||||
struct PgfType {
|
||||
PgfHypos* hypos;
|
||||
PgfCId cid; /// XXX: resolve to PgfCat*?
|
||||
size_t n_exprs;
|
||||
PgfExpr exprs[];
|
||||
};
|
||||
|
||||
|
||||
typedef enum {
|
||||
PGF_EXPR_ABS,
|
||||
PGF_EXPR_APP,
|
||||
PGF_EXPR_LIT,
|
||||
PGF_EXPR_META,
|
||||
PGF_EXPR_FUN,
|
||||
PGF_EXPR_VAR,
|
||||
PGF_EXPR_TYPED,
|
||||
PGF_EXPR_IMPL_ARG,
|
||||
PGF_EXPR_NUM_TAGS
|
||||
} PgfExprTag;
|
||||
|
||||
typedef struct {
|
||||
PgfBindType bind_type;
|
||||
PgfCId id;
|
||||
PgfExpr body;
|
||||
} PgfExprAbs;
|
||||
|
||||
typedef struct {
|
||||
PgfExpr fun;
|
||||
PgfExpr arg;
|
||||
} PgfExprApp;
|
||||
|
||||
typedef struct {
|
||||
PgfLiteral lit;
|
||||
} PgfExprLit;
|
||||
|
||||
typedef struct {
|
||||
PgfMetaId id;
|
||||
} PgfExprMeta;
|
||||
|
||||
typedef struct {
|
||||
char fun[0];
|
||||
} PgfExprFun;
|
||||
|
||||
typedef struct {
|
||||
int var;
|
||||
} PgfExprVar;
|
||||
|
||||
/**< A variable. The value is a de Bruijn index to the environment,
|
||||
* beginning from the innermost variable. */
|
||||
|
||||
typedef struct {
|
||||
PgfExpr expr;
|
||||
PgfType* type;
|
||||
} PgfExprTyped;
|
||||
|
||||
typedef struct {
|
||||
PgfExpr expr;
|
||||
} PgfExprImplArg;
|
||||
|
||||
typedef float prob_t;
|
||||
|
||||
typedef struct {
|
||||
prob_t prob;
|
||||
PgfExpr expr;
|
||||
} PgfExprProb;
|
||||
|
||||
typedef struct PgfApplication PgfApplication;
|
||||
|
||||
struct PgfApplication {
|
||||
PgfExpr efun;
|
||||
PgfCId fun;
|
||||
int n_args;
|
||||
PgfExpr args[];
|
||||
};
|
||||
|
||||
PGF_API_DECL PgfApplication*
|
||||
pgf_expr_unapply(PgfExpr expr, GuPool* pool);
|
||||
|
||||
PGF_API_DECL PgfApplication*
|
||||
pgf_expr_unapply_ex(PgfExpr expr, GuPool* pool);
|
||||
|
||||
PGF_API_DECL PgfExpr
|
||||
pgf_expr_apply(PgfApplication*, GuPool* pool);
|
||||
|
||||
PGF_API_DECL PgfExpr
|
||||
pgf_expr_abs(PgfBindType bind_type, PgfCId id, PgfExpr body, GuPool* pool);
|
||||
|
||||
PGF_API_DECL PgfExprAbs*
|
||||
pgf_expr_unabs(PgfExpr expr);
|
||||
|
||||
PGF_API_DECL PgfExpr
|
||||
pgf_expr_string(GuString, GuPool* pool);
|
||||
|
||||
PGF_API_DECL PgfExpr
|
||||
pgf_expr_int(int val, GuPool* pool);
|
||||
|
||||
PGF_API_DECL PgfExpr
|
||||
pgf_expr_float(double val, GuPool* pool);
|
||||
|
||||
PGF_API_DECL void*
|
||||
pgf_expr_unlit(PgfExpr expr, int lit_tag);
|
||||
|
||||
PGF_API_DECL PgfExpr
|
||||
pgf_expr_meta(int id, GuPool* pool);
|
||||
|
||||
PGF_API_DECL PgfExprMeta*
|
||||
pgf_expr_unmeta(PgfExpr expr);
|
||||
|
||||
PGF_API_DECL PgfExpr
|
||||
pgf_read_expr(GuIn* in, GuPool* pool, GuPool* tmp_pool, GuExn* err);
|
||||
|
||||
PGF_API_DECL PgfType*
|
||||
pgf_read_type(GuIn* in, GuPool* pool, GuPool* tmp_pool, GuExn* err);
|
||||
|
||||
PGF_API_DECL bool
|
||||
pgf_literal_eq(PgfLiteral lit1, PgfLiteral lit2);
|
||||
|
||||
PGF_API_DECL int
|
||||
pgf_expr_eq(PgfExpr e1, PgfExpr e2);
|
||||
|
||||
PGF_API_DECL bool
|
||||
pgf_type_eq(PgfType* t1, PgfType* t2);
|
||||
|
||||
PGF_API_DECL GuHash
|
||||
pgf_literal_hash(GuHash h, PgfLiteral lit);
|
||||
|
||||
PGF_API_DECL GuHash
|
||||
pgf_expr_hash(GuHash h, PgfExpr e);
|
||||
|
||||
PGF_API_DECL size_t
|
||||
pgf_expr_size(PgfExpr expr);
|
||||
|
||||
PGF_API_DECL GuSeq*
|
||||
pgf_expr_functions(PgfExpr expr, GuPool* pool);
|
||||
|
||||
PGF_API_DECL PgfExpr
|
||||
pgf_expr_substitute(PgfExpr expr, GuSeq* meta_values, GuPool* pool);
|
||||
|
||||
PGF_API_DECL PgfType*
|
||||
pgf_type_substitute(PgfType* type, GuSeq* meta_values, GuPool* pool);
|
||||
|
||||
typedef struct PgfPrintContext PgfPrintContext;
|
||||
|
||||
struct PgfPrintContext {
|
||||
PgfCId name;
|
||||
PgfPrintContext* next;
|
||||
};
|
||||
|
||||
PGF_API_DECL void
|
||||
pgf_print_cid(PgfCId id, GuOut* out, GuExn* err);
|
||||
|
||||
PGF_API_DECL void
|
||||
pgf_print_literal(PgfLiteral lit, GuOut* out, GuExn* err);
|
||||
|
||||
PGF_API_DECL void
|
||||
pgf_print_expr(PgfExpr expr, PgfPrintContext* ctxt, int prec,
|
||||
GuOut* out, GuExn* err);
|
||||
|
||||
PGF_API_DECL PgfPrintContext*
|
||||
pgf_print_hypo(PgfHypo *hypo, PgfPrintContext* ctxt, int prec,
|
||||
GuOut* out, GuExn *err);
|
||||
|
||||
PGF_API_DECL void
|
||||
pgf_print_type(PgfType *type, PgfPrintContext* ctxt, int prec,
|
||||
GuOut* out, GuExn *err);
|
||||
|
||||
PGF_API_DECL void
|
||||
pgf_print_context(PgfHypos *hypos, PgfPrintContext* ctxt,
|
||||
GuOut *out, GuExn *err);
|
||||
|
||||
PGF_API PgfLiteral
|
||||
pgf_clone_literal(PgfLiteral lit, GuPool* pool);
|
||||
|
||||
PGF_API PgfExpr
|
||||
pgf_clone_expr(PgfExpr expr, GuPool* pool);
|
||||
|
||||
PGF_API PgfType*
|
||||
pgf_clone_type(PgfType* type, GuPool* pool);
|
||||
|
||||
PGF_API_DECL prob_t
|
||||
pgf_compute_tree_probability(PgfPGF *gr, PgfExpr expr);
|
||||
|
||||
#endif /* EXPR_H_ */
|
||||
@@ -1,415 +0,0 @@
|
||||
#include "data.h"
|
||||
#include "graphviz.h"
|
||||
#include "linearizer.h"
|
||||
|
||||
PgfGraphvizOptions pgf_default_graphviz_options[1] =
|
||||
{ {0, 0, 0, 1, NULL, NULL, NULL, NULL, NULL, NULL} } ;
|
||||
|
||||
static int
|
||||
pgf_graphviz_abstract_tree_(PgfPGF* pgf, PgfExpr expr, int *pid,
|
||||
PgfGraphvizOptions* opts,
|
||||
GuOut* out, GuExn* err)
|
||||
{
|
||||
int id = -1;
|
||||
|
||||
GuVariantInfo ei = gu_variant_open(expr);
|
||||
switch (ei.tag) {
|
||||
case PGF_EXPR_ABS:
|
||||
gu_impossible();
|
||||
break;
|
||||
case PGF_EXPR_APP: {
|
||||
PgfExprApp* app = ei.data;
|
||||
id = pgf_graphviz_abstract_tree_(pgf, app->fun, pid, opts, out, err);
|
||||
int arg_id = pgf_graphviz_abstract_tree_(pgf, app->arg, pid, opts, out, err);
|
||||
gu_printf(out, err, "n%d -- n%d", id, arg_id);
|
||||
if (opts->nodeEdgeStyle != NULL && *opts->nodeEdgeStyle && opts->nodeColor != NULL && *opts->nodeColor)
|
||||
gu_printf(out, err, " [style = \"%s\", color = \"%s\"]", opts->nodeEdgeStyle, opts->nodeColor);
|
||||
else if (opts->nodeEdgeStyle != NULL && *opts->nodeEdgeStyle)
|
||||
gu_printf(out, err, " [style = \"%s\"]", opts->nodeEdgeStyle);
|
||||
else if (opts->nodeColor != NULL && *opts->nodeColor)
|
||||
gu_printf(out, err, " [color = \"%s\"]", opts->nodeColor);
|
||||
gu_printf(out, err, "\n", id, arg_id);
|
||||
break;
|
||||
}
|
||||
case PGF_EXPR_LIT: {
|
||||
PgfExprLit* lit = ei.data;
|
||||
id = (*pid)++;
|
||||
gu_printf(out, err, "n%d[label = \"", id);
|
||||
|
||||
GuVariantInfo ei = gu_variant_open(lit->lit);
|
||||
switch (ei.tag) {
|
||||
case PGF_LITERAL_STR: {
|
||||
PgfLiteralStr* lit = ei.data;
|
||||
gu_puts("\\\"", out, err);
|
||||
gu_string_write(lit->val, out, err);
|
||||
gu_puts("\\\"", out, err);
|
||||
break;
|
||||
}
|
||||
case PGF_LITERAL_INT: {
|
||||
PgfLiteralInt* lit = ei.data;
|
||||
gu_printf(out, err, "%d", lit->val);
|
||||
break;
|
||||
}
|
||||
case PGF_LITERAL_FLT: {
|
||||
PgfLiteralFlt* lit = ei.data;
|
||||
gu_printf(out, err, "%lf", lit->val);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
gu_impossible();
|
||||
}
|
||||
|
||||
gu_puts("\", style = \"solid\", shape = \"plaintext\"]\n", out, err);
|
||||
break;
|
||||
}
|
||||
case PGF_EXPR_META:
|
||||
id = (*pid)++;
|
||||
gu_printf(out, err, "n%d[label = \"?\", style = \"solid\", shape = \"plaintext\"]\n", id);
|
||||
break;
|
||||
case PGF_EXPR_FUN: {
|
||||
PgfExprFun* fun = ei.data;
|
||||
id = (*pid)++;
|
||||
if (opts->noFun && opts->noCat) {
|
||||
gu_printf(out, err, "n%d[shape = \"point\"]\n", id);
|
||||
} else {
|
||||
gu_printf(out, err, "n%d[label = \"", id);
|
||||
PgfType* ty = (opts->noCat) ? NULL : pgf_function_type(pgf, fun->fun);
|
||||
if (!opts->noFun)
|
||||
gu_string_write(fun->fun, out, err);
|
||||
if (!opts->noFun && ty != NULL)
|
||||
gu_puts(" : ", out,err);
|
||||
if (ty != NULL)
|
||||
gu_string_write(ty->cid, out, err);
|
||||
gu_puts("\", shape = \"plaintext\", style = \"solid\"", out, err);
|
||||
if (opts->nodeColor != NULL && *opts->nodeColor)
|
||||
gu_printf(out, err, ", fontcolor = \"%s\"", opts->nodeColor);
|
||||
if (opts->nodeFont != NULL && *opts->nodeFont)
|
||||
gu_printf(out, err, ", fontname = \"%s\"", opts->nodeFont);
|
||||
gu_puts("]\n", out, err);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PGF_EXPR_VAR:
|
||||
gu_impossible();
|
||||
break;
|
||||
case PGF_EXPR_TYPED: {
|
||||
PgfExprTyped* typed = ei.data;
|
||||
id = pgf_graphviz_abstract_tree_(pgf, typed->expr, pid, opts, out, err);
|
||||
break;
|
||||
}
|
||||
case PGF_EXPR_IMPL_ARG: {
|
||||
PgfExprImplArg* implarg = ei.data;
|
||||
id = pgf_graphviz_abstract_tree_(pgf, implarg->expr, pid, opts, out, err);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
gu_impossible();
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
PGF_API void
|
||||
pgf_graphviz_abstract_tree(PgfPGF* pgf, PgfExpr expr, PgfGraphvizOptions* opts, GuOut* out, GuExn* err)
|
||||
{
|
||||
int id = 0;
|
||||
|
||||
gu_puts("graph {\n", out, err);
|
||||
pgf_graphviz_abstract_tree_(pgf, expr, &id, opts, out, err);
|
||||
gu_puts("}", out, err);
|
||||
}
|
||||
|
||||
typedef struct PgfParseNode PgfParseNode;
|
||||
|
||||
struct PgfParseNode {
|
||||
int id;
|
||||
PgfParseNode* parent;
|
||||
GuString fun;
|
||||
GuString label;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
PgfLinFuncs* funcs;
|
||||
|
||||
GuPool* pool;
|
||||
GuOut* out;
|
||||
GuExn* err;
|
||||
|
||||
PgfParseNode* parent;
|
||||
size_t level;
|
||||
GuBuf* internals;
|
||||
GuBuf* leaves;
|
||||
} PgfBracketLznState;
|
||||
|
||||
static void
|
||||
pgf_bracket_lzn_symbol_token(PgfLinFuncs** funcs, PgfToken tok)
|
||||
{
|
||||
PgfBracketLznState* state = gu_container(funcs, PgfBracketLznState, funcs);
|
||||
|
||||
PgfParseNode* node = gu_new(PgfParseNode, state->pool);
|
||||
node->id = 100000 + gu_buf_length(state->leaves);
|
||||
node->parent = state->parent;
|
||||
node->fun = NULL;
|
||||
node->label = tok;
|
||||
gu_buf_push(state->leaves, PgfParseNode*, node);
|
||||
}
|
||||
|
||||
static void
|
||||
pgf_bracket_lzn_begin_phrase(PgfLinFuncs** funcs, PgfCId cat, int fid, GuString ann, PgfCId fun)
|
||||
{
|
||||
PgfBracketLznState* state = gu_container(funcs, PgfBracketLznState, funcs);
|
||||
|
||||
if (strcmp(cat, "_") == 0)
|
||||
return;
|
||||
|
||||
state->level++;
|
||||
|
||||
GuBuf* level;
|
||||
if (state->level < gu_buf_length(state->internals))
|
||||
level = gu_buf_get(state->internals, GuBuf*, state->level);
|
||||
else {
|
||||
level = gu_new_buf(PgfParseNode*, state->pool);
|
||||
gu_buf_push(state->internals, GuBuf*, level);
|
||||
}
|
||||
|
||||
size_t len = gu_buf_length(level);
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
PgfParseNode* node = gu_buf_get(level, PgfParseNode*, i);
|
||||
if (node->id == fid) {
|
||||
state->parent = node;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
PgfParseNode* node = gu_new(PgfParseNode, state->pool);
|
||||
node->id = fid;
|
||||
node->parent = state->parent;
|
||||
node->fun = fun;
|
||||
node->label = cat;
|
||||
gu_buf_push(level, PgfParseNode*, node);
|
||||
|
||||
state->parent = node;
|
||||
}
|
||||
|
||||
static void
|
||||
pgf_bracket_lzn_end_phrase(PgfLinFuncs** funcs, PgfCId cat, int fid, GuString ann, PgfCId fun)
|
||||
{
|
||||
PgfBracketLznState* state = gu_container(funcs, PgfBracketLznState, funcs);
|
||||
|
||||
if (strcmp(cat, "_") == 0)
|
||||
return;
|
||||
|
||||
state->level--;
|
||||
state->parent = state->parent->parent;
|
||||
}
|
||||
|
||||
static void
|
||||
pgf_bracket_lzn_symbol_meta(PgfLinFuncs** funcs, PgfMetaId meta_id)
|
||||
{
|
||||
PgfBracketLznState* state = gu_container(funcs, PgfBracketLznState, funcs);
|
||||
|
||||
PgfParseNode* node = gu_new(PgfParseNode, state->pool);
|
||||
node->id = 100000 + gu_buf_length(state->leaves);
|
||||
node->parent = state->parent;
|
||||
node->fun = NULL;
|
||||
node->label = "?";
|
||||
gu_buf_push(state->leaves, PgfParseNode*, node);
|
||||
}
|
||||
|
||||
static PgfLinFuncs pgf_bracket_lin_funcs = {
|
||||
.symbol_token = pgf_bracket_lzn_symbol_token,
|
||||
.begin_phrase = pgf_bracket_lzn_begin_phrase,
|
||||
.end_phrase = pgf_bracket_lzn_end_phrase,
|
||||
.symbol_ne = NULL,
|
||||
.symbol_bind = NULL,
|
||||
.symbol_capit = NULL,
|
||||
.symbol_meta = pgf_bracket_lzn_symbol_meta
|
||||
};
|
||||
|
||||
static void
|
||||
pgf_graphviz_parse_level(GuBuf* level, PgfGraphvizOptions* opts, GuOut* out, GuExn* err)
|
||||
{
|
||||
gu_puts("\n subgraph {rank=same;\n", out, err);
|
||||
|
||||
size_t len = gu_buf_length(level);
|
||||
|
||||
if (len > 1)
|
||||
gu_puts(" edge[style=invis]\n", out, err);
|
||||
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
PgfParseNode* node = gu_buf_get(level, PgfParseNode*, i);
|
||||
if (node->fun != NULL) {
|
||||
gu_printf(out, err, " n%d[label=\"", node->id);
|
||||
if (!opts->noFun)
|
||||
gu_string_write(node->fun, out, err);
|
||||
if (!opts->noFun && !opts->noCat)
|
||||
gu_puts(" : ", out, err);
|
||||
if (!opts->noCat)
|
||||
gu_string_write(node->label, out, err);
|
||||
gu_puts("\"", out, err);
|
||||
if (opts->nodeColor != NULL && *opts->nodeColor)
|
||||
gu_printf(out, err, ", fontcolor = \"%s\"", opts->nodeColor);
|
||||
if (opts->nodeFont != NULL && *opts->nodeFont)
|
||||
gu_printf(out, err, ", fontname = \"%s\"", opts->nodeFont);
|
||||
gu_puts("]\n", out, err);
|
||||
} else {
|
||||
if (opts->noLeaves)
|
||||
gu_printf(out, err, " n%d[label=\"\"]\n", node->id);
|
||||
else {
|
||||
gu_printf(out, err, " n%d[label=\"%s\"", node->id, node->label);
|
||||
if (opts->leafColor != NULL && *opts->leafColor)
|
||||
gu_printf(out, err, ", fontcolor = \"%s\"", opts->leafColor);
|
||||
if (opts->leafFont != NULL && *opts->leafFont)
|
||||
gu_printf(out, err, ", fontname = \"%s\"", opts->leafFont);
|
||||
gu_puts("]\n", out, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (len > 1) {
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
PgfParseNode* node = gu_buf_get(level, PgfParseNode*, i);
|
||||
|
||||
gu_puts((i == 0) ? " " : " -- ", out, err);
|
||||
gu_printf(out, err, "n%d", node->id);
|
||||
}
|
||||
gu_puts("\n", out, err);
|
||||
}
|
||||
|
||||
gu_puts(" }\n", out, err);
|
||||
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
PgfParseNode* node = gu_buf_get(level, PgfParseNode*, i);
|
||||
if (node->parent != NULL) {
|
||||
gu_printf(out, err, " n%d -- n%d", node->parent->id, node->id);
|
||||
|
||||
GuString edgeStyle, color;
|
||||
if (node->fun == NULL) {
|
||||
edgeStyle = opts->leafEdgeStyle;
|
||||
color = opts->leafColor;
|
||||
} else {
|
||||
edgeStyle = opts->nodeEdgeStyle;
|
||||
color = opts->nodeColor;
|
||||
}
|
||||
|
||||
if (edgeStyle != NULL && *edgeStyle && color != NULL && *color)
|
||||
gu_printf(out, err, " [style = \"%s\", color = \"%s\"]", edgeStyle, color);
|
||||
else if (edgeStyle != NULL && *edgeStyle)
|
||||
gu_printf(out, err, " [style = \"%s\"]", edgeStyle);
|
||||
else if (color != NULL && *color)
|
||||
gu_printf(out, err, " [color = \"%s\"]", color);
|
||||
|
||||
gu_putc('\n', out, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PGF_API void
|
||||
pgf_graphviz_parse_tree(PgfConcr* concr, PgfExpr expr, PgfGraphvizOptions* opts, GuOut* out, GuExn* err)
|
||||
{
|
||||
GuPool* tmp_pool = gu_local_pool();
|
||||
|
||||
GuEnum* cts =
|
||||
pgf_lzr_concretize(concr, expr, err, tmp_pool);
|
||||
if (!gu_ok(err)) {
|
||||
gu_pool_free(tmp_pool);
|
||||
return;
|
||||
}
|
||||
|
||||
PgfCncTree ctree = gu_next(cts, PgfCncTree, tmp_pool);
|
||||
if (gu_variant_is_null(ctree)) {
|
||||
gu_pool_free(tmp_pool);
|
||||
return;
|
||||
}
|
||||
|
||||
gu_puts("graph {\n", out, err);
|
||||
gu_puts(" node[shape=plaintext]\n", out, err);
|
||||
|
||||
PgfBracketLznState state;
|
||||
state.funcs = &pgf_bracket_lin_funcs;
|
||||
state.pool = tmp_pool;
|
||||
state.out = out;
|
||||
state.err = err;
|
||||
|
||||
state.parent = NULL;
|
||||
state.level = -1;
|
||||
state.internals = gu_new_buf(GuBuf*, tmp_pool);
|
||||
state.leaves = gu_new_buf(PgfParseNode*, tmp_pool);
|
||||
pgf_lzr_linearize(concr, ctree, 0, &state.funcs, tmp_pool);
|
||||
|
||||
size_t len = gu_buf_length(state.internals);
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
GuBuf* level = gu_buf_get(state.internals, GuBuf*, i);
|
||||
pgf_graphviz_parse_level(level, opts, out, err);
|
||||
}
|
||||
pgf_graphviz_parse_level(state.leaves, opts, out, err);
|
||||
|
||||
gu_puts("}", out, err);
|
||||
|
||||
gu_pool_free(tmp_pool);
|
||||
}
|
||||
|
||||
|
||||
PGF_API_DECL void
|
||||
pgf_graphviz_word_alignment(PgfConcr** concrs, size_t n_concrs, PgfExpr expr, PgfGraphvizOptions* opts, GuOut* out, GuExn* err)
|
||||
{
|
||||
GuPool* tmp_pool = gu_local_pool();
|
||||
|
||||
gu_puts("digraph {\n", out, err);
|
||||
gu_puts("rankdir=LR ;\n", out, err);
|
||||
gu_puts("node [shape = record", out, err);
|
||||
if (opts->leafFont != NULL && *opts->leafFont)
|
||||
gu_printf(out, err, ", fontname = \"%s\"", opts->leafFont);
|
||||
if (opts->leafColor != NULL && *opts->leafColor)
|
||||
gu_printf(out, err, ", fontcolor = \"%s\"", opts->leafColor);
|
||||
gu_puts("] ;\n\n", out, err);
|
||||
if (opts->leafEdgeStyle != NULL && *opts->leafEdgeStyle)
|
||||
gu_printf(out, err, "edge [style = %s];\n", opts->leafEdgeStyle);
|
||||
gu_puts("\n", out, err);
|
||||
|
||||
GuSeq* alignment = NULL;
|
||||
GuSeq* last_alignment = NULL;
|
||||
for (size_t i = 0; i < n_concrs; i++) {
|
||||
alignment = pgf_align_words(concrs[i], expr, err, tmp_pool);
|
||||
gu_printf(out, err, " struct%d[label=\"", i);
|
||||
|
||||
size_t n_tokens = gu_seq_length(alignment);
|
||||
for (size_t j = 0; j < n_tokens; j++) {
|
||||
PgfAlignmentPhrase* phrase = gu_seq_get(alignment, PgfAlignmentPhrase*, j);
|
||||
if (j > 0)
|
||||
gu_puts(" | ", out, err);
|
||||
gu_printf(out, err, "<n%d> %s", j, phrase->phrase);
|
||||
}
|
||||
|
||||
gu_puts("\"] ;\n", out, err);
|
||||
|
||||
if (last_alignment != NULL) {
|
||||
size_t n_last_tokens = gu_seq_length(last_alignment);
|
||||
|
||||
for (size_t j = 0; j < n_tokens; j++) {
|
||||
PgfAlignmentPhrase* phrase = gu_seq_get(alignment, PgfAlignmentPhrase*, j);
|
||||
|
||||
for (size_t k = 0; k < phrase->n_fids; k++) {
|
||||
int fid = phrase->fids[k];
|
||||
|
||||
for (size_t l = 0; l < n_last_tokens; l++) {
|
||||
PgfAlignmentPhrase* last_phrase = gu_seq_get(last_alignment, PgfAlignmentPhrase*, l);
|
||||
|
||||
for (size_t r = 0; r < last_phrase->n_fids; r++) {
|
||||
int last_fid = last_phrase->fids[r];
|
||||
if (fid == last_fid) {
|
||||
gu_printf(out, err, "struct%d:n%d:e -> struct%d:n%d:w ;\n",i,j,i-1,l);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
last_alignment = alignment;
|
||||
}
|
||||
|
||||
gu_puts("}", out, err);
|
||||
|
||||
gu_pool_free(tmp_pool);
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
#ifndef PGF_GRAPHVIZ_H_
|
||||
#define PGF_GRAPHVIZ_H_
|
||||
|
||||
typedef struct {
|
||||
int noLeaves;
|
||||
int noFun;
|
||||
int noCat;
|
||||
int noDep;
|
||||
GuString nodeFont;
|
||||
GuString leafFont;
|
||||
GuString nodeColor;
|
||||
GuString leafColor;
|
||||
GuString nodeEdgeStyle;
|
||||
GuString leafEdgeStyle;
|
||||
} PgfGraphvizOptions;
|
||||
|
||||
extern PgfGraphvizOptions pgf_default_graphviz_options[1];
|
||||
|
||||
PGF_API_DECL void
|
||||
pgf_graphviz_abstract_tree(PgfPGF* pgf, PgfExpr expr, PgfGraphvizOptions* opts, GuOut* out, GuExn* err);
|
||||
|
||||
PGF_API_DECL void
|
||||
pgf_graphviz_parse_tree(PgfConcr* concr, PgfExpr expr, PgfGraphvizOptions* opts, GuOut* out, GuExn* err);
|
||||
|
||||
PGF_API_DECL void
|
||||
pgf_graphviz_word_alignment(PgfConcr** concrs, size_t n_concrs, PgfExpr expr, PgfGraphvizOptions* opts, GuOut* out, GuExn* err);
|
||||
|
||||
#endif
|
||||
@@ -1,11 +0,0 @@
|
||||
#include "data.h"
|
||||
#include "reasoner.h"
|
||||
#include "hopu.h"
|
||||
|
||||
PGF_INTERNAL void
|
||||
pgf_pattern_unify(PgfReasoner* rs, PgfClosure* c1, PgfClosure* c2)
|
||||
{
|
||||
c1 = rs->eval_gates->enter(rs, c1);
|
||||
c2 = rs->eval_gates->enter(rs, c2);
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
#ifndef HOPU_H
|
||||
#define HOPU_H
|
||||
|
||||
PGF_INTERNAL_DECL void
|
||||
pgf_pattern_unify(PgfReasoner* rs, PgfClosure* c1, PgfClosure* c2);
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,62 +0,0 @@
|
||||
/******************************** -*- C -*- ****************************
|
||||
*
|
||||
* lightning main include file
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Copyright 2000 Free Software Foundation, Inc.
|
||||
* Written by Paolo Bonzini.
|
||||
*
|
||||
* This file is part of GNU lightning.
|
||||
*
|
||||
* GNU lightning is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2.1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU lightning is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with GNU lightning; see the file COPYING.LESSER; if not, write to the
|
||||
* Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef __lightning_h
|
||||
#define __lightning_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "lightning/asm-common.h"
|
||||
|
||||
#ifndef LIGHTNING_DEBUG
|
||||
#include "lightning/asm.h"
|
||||
#endif
|
||||
|
||||
#include "lightning/core.h"
|
||||
#include "lightning/core-common.h"
|
||||
#include "lightning/funcs.h"
|
||||
#include "lightning/funcs-common.h"
|
||||
#include "lightning/fp.h"
|
||||
#include "lightning/fp-common.h"
|
||||
|
||||
#ifndef JIT_R0
|
||||
#error GNU lightning does not support the current target
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __lightning_h */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,193 +0,0 @@
|
||||
/******************************** -*- C -*- ****************************
|
||||
*
|
||||
* Run-time assembler for the arm
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Copyright 2011 Free Software Foundation
|
||||
*
|
||||
* This file is part of GNU lightning.
|
||||
*
|
||||
* GNU lightning is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU lightning is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with GNU lightning; see the file COPYING.LESSER; if not, write to the
|
||||
* Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*
|
||||
* Authors:
|
||||
* Paulo Cesar Pereira de Andrade
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef __lightning_funcs_h
|
||||
#define __lightning_funcs_h
|
||||
|
||||
#if defined(__linux__)
|
||||
# include <stdio.h>
|
||||
# include <string.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#if defined(ios_HOST_OS) || defined (darwin_HOST_OS)
|
||||
extern void sys_icache_invalidate(void *start, size_t len);
|
||||
|
||||
static void
|
||||
jit_flush_code(void *start, void *end)
|
||||
{
|
||||
mprotect(start, (char *)end - (char *)start,
|
||||
PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||
sys_icache_invalidate(start, (char *)end-(char *)start);
|
||||
}
|
||||
#else
|
||||
extern void __clear_cache(void*, void*);
|
||||
|
||||
static void
|
||||
jit_flush_code(void *start, void *end)
|
||||
{
|
||||
mprotect(start, (char *)end - (char *)start,
|
||||
PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||
__clear_cache(start, end);
|
||||
}
|
||||
#endif
|
||||
|
||||
__attribute__((constructor)) static void
|
||||
jit_get_cpu(void)
|
||||
{
|
||||
#if defined(__linux__)
|
||||
FILE *fp;
|
||||
char *ptr;
|
||||
char buf[128];
|
||||
static int initialized;
|
||||
|
||||
if (initialized)
|
||||
return;
|
||||
initialized = 1;
|
||||
if ((fp = fopen("/proc/cpuinfo", "r")) == NULL)
|
||||
return;
|
||||
|
||||
while (fgets(buf, sizeof(buf), fp)) {
|
||||
if (strncmp(buf, "CPU architecture:", 17) == 0) {
|
||||
jit_cpu.version = strtol(buf + 17, &ptr, 10);
|
||||
while (*ptr) {
|
||||
if (*ptr == 'T' || *ptr == 't') {
|
||||
++ptr;
|
||||
jit_cpu.thumb = 1;
|
||||
}
|
||||
else if (*ptr == 'E' || *ptr == 'e') {
|
||||
jit_cpu.extend = 1;
|
||||
++ptr;
|
||||
}
|
||||
else
|
||||
++ptr;
|
||||
}
|
||||
}
|
||||
else if (strncmp(buf, "Features\t:", 10) == 0) {
|
||||
if ((ptr = strstr(buf + 10, "vfpv")))
|
||||
jit_cpu.vfp = strtol(ptr + 4, NULL, 0);
|
||||
if ((ptr = strstr(buf + 10, "neon")))
|
||||
jit_cpu.neon = 1;
|
||||
if ((ptr = strstr(buf + 10, "thumb")))
|
||||
jit_cpu.thumb = 1;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
#endif
|
||||
#if defined(__ARM_PCS_VFP)
|
||||
if (!jit_cpu.vfp)
|
||||
jit_cpu.vfp = 3;
|
||||
if (!jit_cpu.version)
|
||||
jit_cpu.version = 7;
|
||||
jit_cpu.abi = 1;
|
||||
#endif
|
||||
/* armv6t2 todo (software float and thumb2) */
|
||||
if (!jit_cpu.vfp && jit_cpu.thumb)
|
||||
jit_cpu.thumb = 0;
|
||||
}
|
||||
|
||||
extern int __aeabi_idivmod(int, int);
|
||||
extern unsigned __aeabi_uidivmod(unsigned, unsigned);
|
||||
|
||||
#pragma push_macro("_jit")
|
||||
#ifdef _jit
|
||||
#undef _jit
|
||||
#endif
|
||||
#define _jit (*jit)
|
||||
static void
|
||||
arm_divmod(jit_state* jit, int div, int sign,
|
||||
jit_gpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
|
||||
{
|
||||
int d;
|
||||
int l;
|
||||
void *p;
|
||||
l = 0xf;
|
||||
if ((int)r0 < 4)
|
||||
/* bogus extra push to align at 8 bytes */
|
||||
l = (l & ~(1 << r0)) | 0x10;
|
||||
#ifdef USE_THUMB_CODE
|
||||
T1_PUSH(l);
|
||||
#else
|
||||
_PUSH(l);
|
||||
#endif
|
||||
if (r1 == _R1 && r2 == _R0) {
|
||||
jit_movr_i(JIT_FTMP, _R0);
|
||||
jit_movr_i(_R0, _R1);
|
||||
jit_movr_i(_R1, JIT_FTMP);
|
||||
} else if (r2 == _R0) {
|
||||
jit_movr_i(_R1, r2);
|
||||
jit_movr_i(_R0, r1);
|
||||
} else {
|
||||
jit_movr_i(_R0, r1);
|
||||
jit_movr_i(_R1, r2);
|
||||
}
|
||||
p = (sign) ? (void*) __aeabi_idivmod : (void*) __aeabi_uidivmod;
|
||||
if (!jit_exchange_p()) {
|
||||
#ifdef USE_THUMB_CODE
|
||||
d = (((int)p - (int)_jit.x.pc) >> 1) - 2;
|
||||
#else
|
||||
d = (((int)p - (int)_jit.x.pc) >> 2) - 2;
|
||||
#endif
|
||||
if (_s24P(d)) {
|
||||
#ifdef USE_THUMB_CODE
|
||||
T2_BLI(encode_thumb_jump(d));
|
||||
#else
|
||||
_BLI(d & 0x00ffffff);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
goto fallback;
|
||||
} else {
|
||||
fallback:
|
||||
jit_movi_i(JIT_FTMP, (int)p);
|
||||
#ifdef USE_THUMB_CODE
|
||||
T1_BLX(JIT_FTMP);
|
||||
#else
|
||||
_BLX(JIT_FTMP);
|
||||
#endif
|
||||
}
|
||||
if (div) {
|
||||
jit_movr_i(r0, _R0);
|
||||
} else {
|
||||
jit_movr_i(r0, _R1);
|
||||
}
|
||||
#ifdef USE_THUMB_CODE
|
||||
T1_POP(l);
|
||||
#else
|
||||
_POP(l);
|
||||
#endif
|
||||
}
|
||||
#pragma pop_macro("_jit")
|
||||
|
||||
#endif /* __lightning_funcs_h */
|
||||
@@ -1,207 +0,0 @@
|
||||
/******************************** -*- C -*- ****************************
|
||||
*
|
||||
* Dynamic assembler support
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
* Written by Paolo Bonzini.
|
||||
*
|
||||
* This file is part of GNU lightning.
|
||||
*
|
||||
* GNU lightning is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU lightning is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with GNU lightning; see the file COPYING.LESSER; if not, write to the
|
||||
* Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
#ifndef __lightning_asm_common_h_
|
||||
#define __lightning_asm_common_h_
|
||||
|
||||
|
||||
#ifndef _ASM_SAFETY
|
||||
#define JITFAIL(MSG) 0
|
||||
#else
|
||||
#if (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) || (defined __GNUC__ && (__GNUC__ == 3 ? __GNUC_MINOR__ >= 2 : __GNUC__ > 3))
|
||||
#define JITFAIL(MSG) jit_fail(MSG, __FILE__, __LINE__, __func__)
|
||||
#elif defined __GNUC__
|
||||
#define JITFAIL(MSG) jit_fail(MSG, __FILE__, __LINE__, __FUNCTION__)
|
||||
#else
|
||||
#define JITFAIL(MSG) jit_fail(MSG, __FILE__, __LINE__, "(unknown)")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) || (defined __GNUC__ && (__GNUC__ == 3 ? __GNUC_MINOR__ >= 2 : __GNUC__ > 3))
|
||||
#define JITSORRY(MSG) jit_fail("sorry, unimplemented: " MSG, __FILE__, __LINE__, __func__)
|
||||
#elif defined __GNUC__
|
||||
#define JITSORRY(MSG) jit_fail("sorry, unimplemented: " MSG, __FILE__, __LINE__, __FUNCTION__)
|
||||
#else
|
||||
#define JITSORRY(MSG) jit_fail("sorry, unimplemented: " MSG, __FILE__, __LINE__, "(unknown)")
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define JIT_UNUSED __attribute__((__unused__))
|
||||
#else
|
||||
#define JIT_UNUSED
|
||||
#endif
|
||||
|
||||
|
||||
/* NextStep 2.0 cc is really gcc 1.93 but it defines __GNUC__ = 2 and
|
||||
does not implement __extension__. But that compiler doesn't define
|
||||
__GNUC_MINOR__. */
|
||||
#ifdef __GNUC__
|
||||
#if __GNUC__ < 2 || (defined(__NeXT__) && !__GNUC_MINOR__)
|
||||
#define __extension__
|
||||
#endif
|
||||
|
||||
#define _TEMPD(type, var)
|
||||
|
||||
#define _TEMP(type, var, val, body) __extension__ ({ \
|
||||
register struct { type var } _jitl; _jitl.var = val; \
|
||||
body; \
|
||||
})
|
||||
|
||||
#else
|
||||
|
||||
/* Between loading a global and calling a subroutine, we choose the lesser
|
||||
* evil. */
|
||||
#define _TEMPD(type, var) static type var;
|
||||
#define _TEMP(type, var, val, body) ((var = val), body)
|
||||
|
||||
#endif
|
||||
|
||||
typedef char _sc;
|
||||
typedef unsigned char _uc;
|
||||
typedef unsigned short _us;
|
||||
typedef unsigned int _ui;
|
||||
typedef long _sl;
|
||||
typedef unsigned long _ul;
|
||||
|
||||
#define _jit_UC(X) ((_uc )(X))
|
||||
#define _jit_US(X) ((_us )(X))
|
||||
#define _jit_UI(X) ((_ui )(X))
|
||||
#define _jit_SI(X) ((int )(X))
|
||||
#define _jit_SL(X) ((_sl )(X))
|
||||
#define _jit_UL(X) ((_ul )(X))
|
||||
# define _PUC(X) ((_uc *)(X))
|
||||
# define _PUS(X) ((_us *)(X))
|
||||
# define _PUI(X) ((_ui *)(X))
|
||||
# define _PSI(X) ((int *)(X))
|
||||
# define _PSL(X) ((_sl *)(X))
|
||||
# define _PUL(X) ((_ul *)(X))
|
||||
|
||||
#define _jit_B(B) _jit_UL(((*_jit.x.uc_pc++)= _jit_UC((B)& 0xff)))
|
||||
#define _jit_W(W) _jit_UL(((*_jit.x.us_pc++)= _jit_US((W)&0xffff)))
|
||||
#define _jit_I(I) _jit_UL(((*_jit.x.ui_pc++)= _jit_UI((I) )))
|
||||
#define _jit_L(L) _jit_UL(((*_jit.x.ul_pc++)= _jit_UL((L) )))
|
||||
#define _jit_I_noinc(I) _jit_UL(((*_jit.x.ui_pc)= _jit_UI((I) )))
|
||||
|
||||
#define _MASK(N) ((unsigned long)((1L<<(N)))-1L)
|
||||
#define _siP(N,I) (!((((unsigned long)(I))^(((unsigned long)(I))<<1))&~_MASK(N)))
|
||||
#define _uiP(N,I) (!(((unsigned long)(I))&~_MASK(N)))
|
||||
#define _suiP(N,I) (_siP(N,I) | _uiP(N,I))
|
||||
|
||||
#ifndef _ASM_SAFETY
|
||||
#define _ck_s(W,I) (_jit_UL(I) & _MASK(W))
|
||||
#define _ck_u(W,I) (_jit_UL(I) & _MASK(W))
|
||||
#define _ck_su(W,I) (_jit_UL(I) & _MASK(W))
|
||||
#define _ck_d(W,I) (_jit_UL(I) & _MASK(W))
|
||||
#else
|
||||
#define _ck_s(W,I) (_siP(W,I) ? (_jit_UL(I) & _MASK(W)) : JITFAIL( "signed integer `"#I"' too large for "#W"-bit field"))
|
||||
#define _ck_u(W,I) (_uiP(W,I) ? (_jit_UL(I) & _MASK(W)) : JITFAIL("unsigned integer `"#I"' too large for "#W"-bit field"))
|
||||
#define _ck_su(W,I) (_suiP(W,I) ? (_jit_UL(I) & _MASK(W)) : JITFAIL( "integer `"#I"' too large for "#W"-bit field"))
|
||||
#define _ck_d(W,I) (_siP(W,I) ? (_jit_UL(I) & _MASK(W)) : JITFAIL( "displacement `"#I"' too large for "#W"-bit field"))
|
||||
#endif
|
||||
|
||||
#define _s0P(I) ((I)==0)
|
||||
#define _s8P(I) _siP(8,I)
|
||||
#define _s16P(I) _siP(16,I)
|
||||
#define _s20P(I) _siP(20,I)
|
||||
#define _s24P(I) _siP(24,I)
|
||||
#define _s32P(I) _siP(32,I)
|
||||
#define _u8P(I) _uiP(8,I)
|
||||
#define _u16P(I) _uiP(16,I)
|
||||
#define _u32P(I) _uiP(32,I)
|
||||
|
||||
#define _su8(I) _ck_su(8,I)
|
||||
#define _su16(I) _ck_su(16,I)
|
||||
|
||||
#define _s1(I) _ck_s( 1,I)
|
||||
#define _s2(I) _ck_s( 2,I)
|
||||
#define _s3(I) _ck_s( 3,I)
|
||||
#define _s4(I) _ck_s( 4,I)
|
||||
#define _s5(I) _ck_s( 5,I)
|
||||
#define _s6(I) _ck_s( 6,I)
|
||||
#define _s7(I) _ck_s( 7,I)
|
||||
#define _s8(I) _ck_s( 8,I)
|
||||
#define _s9(I) _ck_s( 9,I)
|
||||
#define _s10(I) _ck_s(10,I)
|
||||
#define _s11(I) _ck_s(11,I)
|
||||
#define _s12(I) _ck_s(12,I)
|
||||
#define _s13(I) _ck_s(13,I)
|
||||
#define _s14(I) _ck_s(14,I)
|
||||
#define _s15(I) _ck_s(15,I)
|
||||
#define _s16(I) _ck_s(16,I)
|
||||
#define _s17(I) _ck_s(17,I)
|
||||
#define _s18(I) _ck_s(18,I)
|
||||
#define _s19(I) _ck_s(19,I)
|
||||
#define _s20(I) _ck_s(20,I)
|
||||
#define _s21(I) _ck_s(21,I)
|
||||
#define _s22(I) _ck_s(22,I)
|
||||
#define _s23(I) _ck_s(23,I)
|
||||
#define _s24(I) _ck_s(24,I)
|
||||
#define _s25(I) _ck_s(25,I)
|
||||
#define _s26(I) _ck_s(26,I)
|
||||
#define _s27(I) _ck_s(27,I)
|
||||
#define _s28(I) _ck_s(28,I)
|
||||
#define _s29(I) _ck_s(29,I)
|
||||
#define _s30(I) _ck_s(30,I)
|
||||
#define _s31(I) _ck_s(31,I)
|
||||
#define _u1(I) _ck_u( 1,I)
|
||||
#define _u2(I) _ck_u( 2,I)
|
||||
#define _u3(I) _ck_u( 3,I)
|
||||
#define _u4(I) _ck_u( 4,I)
|
||||
#define _u5(I) _ck_u( 5,I)
|
||||
#define _u6(I) _ck_u( 6,I)
|
||||
#define _u7(I) _ck_u( 7,I)
|
||||
#define _u8(I) _ck_u( 8,I)
|
||||
#define _u9(I) _ck_u( 9,I)
|
||||
#define _u10(I) _ck_u(10,I)
|
||||
#define _u11(I) _ck_u(11,I)
|
||||
#define _u12(I) _ck_u(12,I)
|
||||
#define _u13(I) _ck_u(13,I)
|
||||
#define _u14(I) _ck_u(14,I)
|
||||
#define _u15(I) _ck_u(15,I)
|
||||
#define _u16(I) _ck_u(16,I)
|
||||
#define _u17(I) _ck_u(17,I)
|
||||
#define _u18(I) _ck_u(18,I)
|
||||
#define _u19(I) _ck_u(19,I)
|
||||
#define _u20(I) _ck_u(20,I)
|
||||
#define _u21(I) _ck_u(21,I)
|
||||
#define _u22(I) _ck_u(22,I)
|
||||
#define _u23(I) _ck_u(23,I)
|
||||
#define _u24(I) _ck_u(24,I)
|
||||
#define _u25(I) _ck_u(25,I)
|
||||
#define _u26(I) _ck_u(26,I)
|
||||
#define _u27(I) _ck_u(27,I)
|
||||
#define _u28(I) _ck_u(28,I)
|
||||
#define _u29(I) _ck_u(29,I)
|
||||
#define _u30(I) _ck_u(30,I)
|
||||
#define _u31(I) _ck_u(31,I)
|
||||
|
||||
#endif /* __lightning_asm_common_h */
|
||||
@@ -1,638 +0,0 @@
|
||||
/******************************** -*- C -*- ****************************
|
||||
*
|
||||
* Platform-independent layer support
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Copyright 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
|
||||
* Written by Paolo Bonzini.
|
||||
*
|
||||
* This file is part of GNU lightning.
|
||||
*
|
||||
* GNU lightning is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2.1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU lightning is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with GNU lightning; see the file COPYING.LESSER; if not, write to the
|
||||
* Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
#ifndef __lightning_core_common_h_
|
||||
#define __lightning_core_common_h_
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
jit_insn *pc;
|
||||
_uc *uc_pc;
|
||||
_us *us_pc;
|
||||
_ui *ui_pc;
|
||||
_ul *ul_pc;
|
||||
} x;
|
||||
struct jit_fp *fp;
|
||||
struct jit_local_state jitl;
|
||||
} jit_state;
|
||||
|
||||
#define JIT_NOREG (-1)
|
||||
#define JIT_R0 JIT_R(0)
|
||||
#define JIT_R1 JIT_R(1)
|
||||
#define JIT_R2 JIT_R(2)
|
||||
#define JIT_V0 JIT_V(0)
|
||||
#define JIT_V1 JIT_V(1)
|
||||
#define JIT_V2 JIT_V(2)
|
||||
#define JIT_FPR0 JIT_FPR(0)
|
||||
#define JIT_FPR1 JIT_FPR(1)
|
||||
#define JIT_FPR2 JIT_FPR(2)
|
||||
#define JIT_FPR3 JIT_FPR(3)
|
||||
#define JIT_FPR4 JIT_FPR(4)
|
||||
#define JIT_FPR5 JIT_FPR(5)
|
||||
|
||||
#define _jitl _jit.jitl
|
||||
|
||||
#define jit_get_ip() (*(jit_code *) &_jit.x.pc)
|
||||
#define jit_set_ip(ptr) (_jit.x.pc = (ptr), jit_get_ip ())
|
||||
#define jit_get_label() (_jit.x.pc)
|
||||
#define jit_forward() (_jit.x.pc)
|
||||
|
||||
#define jit_field(struc, f) ( ((long) (&((struc *) 8)->f) ) - 8)
|
||||
#define jit_ptr_field(struc_p, f) ( ((long) (&((struc_p) 8)->f) ) - 8)
|
||||
|
||||
/* realignment via N-byte no-ops */
|
||||
|
||||
#ifndef jit_align
|
||||
#define jit_align(n)
|
||||
#endif
|
||||
|
||||
/* jit_code: union of many possible function pointer types. Returned
|
||||
* by jit_get_ip().
|
||||
*/
|
||||
typedef union jit_code {
|
||||
char *ptr;
|
||||
void (*vptr)(void);
|
||||
char (*cptr)(void);
|
||||
unsigned char (*ucptr)(void);
|
||||
short (*sptr)(void);
|
||||
unsigned short (*usptr)(void);
|
||||
int (*iptr)(void);
|
||||
unsigned int (*uiptr)(void);
|
||||
long (*lptr)(void);
|
||||
unsigned long (*ulptr)(void);
|
||||
void * (*pptr)(void);
|
||||
float (*fptr)(void);
|
||||
double (*dptr)(void);
|
||||
} jit_code;
|
||||
|
||||
#ifndef jit_fill_delay_after
|
||||
#define jit_fill_delay_after(branch) (branch)
|
||||
#endif
|
||||
|
||||
#define jit_delay(insn, branch) ((insn), jit_fill_delay_after(branch))
|
||||
|
||||
|
||||
/* ALU synonyms */
|
||||
#define jit_addi_ui(d, rs, is) jit_addi_i((d), (rs), (is))
|
||||
#define jit_addr_ui(d, s1, s2) jit_addr_i((d), (s1), (s2))
|
||||
#define jit_addci_ui(d, rs, is) jit_addci_i((d), (rs), (is))
|
||||
#define jit_addcr_ui(d, s1, s2) jit_addcr_i((d), (s1), (s2))
|
||||
#define jit_addxi_ui(d, rs, is) jit_addxi_i((d), (rs), (is))
|
||||
#define jit_addxr_ui(d, s1, s2) jit_addxr_i((d), (s1), (s2))
|
||||
#define jit_andi_ui(d, rs, is) jit_andi_i((d), (rs), (is))
|
||||
#define jit_andr_ui(d, s1, s2) jit_andr_i((d), (s1), (s2))
|
||||
#define jit_lshi_ui(d, rs, is) jit_lshi_i((d), (rs), (is))
|
||||
#define jit_lshr_ui(d, s1, s2) jit_lshr_i((d), (s1), (s2))
|
||||
#define jit_movi_ui(d, rs) jit_movi_i((d), (rs))
|
||||
#define jit_movr_ui(d, rs) jit_movr_i((d), (rs))
|
||||
#define jit_ori_ui(d, rs, is) jit_ori_i((d), (rs), (is))
|
||||
#define jit_orr_ui(d, s1, s2) jit_orr_i((d), (s1), (s2))
|
||||
#define jit_rsbi_ui(d, rs, is) jit_rsbi_i((d), (rs), (is))
|
||||
#define jit_rsbr_ui(d, s1, s2) jit_rsbr_i((d), (s1), (s2))
|
||||
#define jit_subi_ui(d, rs, is) jit_subi_i((d), (rs), (is))
|
||||
#define jit_subr_ui(d, s1, s2) jit_subr_i((d), (s1), (s2))
|
||||
#define jit_subci_ui(d, rs, is) jit_subci_i((d), (rs), (is))
|
||||
#define jit_subcr_ui(d, s1, s2) jit_subcr_i((d), (s1), (s2))
|
||||
#define jit_subxi_ui(d, rs, is) jit_subxi_i((d), (rs), (is))
|
||||
#define jit_subxr_ui(d, s1, s2) jit_subxr_i((d), (s1), (s2))
|
||||
#define jit_xori_ui(d, rs, is) jit_xori_i((d), (rs), (is))
|
||||
#define jit_xorr_ui(d, s1, s2) jit_xorr_i((d), (s1), (s2))
|
||||
|
||||
#define jit_addi_ul(d, rs, is) jit_addi_l((d), (rs), (is))
|
||||
#define jit_addr_ul(d, s1, s2) jit_addr_l((d), (s1), (s2))
|
||||
#define jit_addci_ul(d, rs, is) jit_addci_l((d), (rs), (is))
|
||||
#define jit_addcr_ul(d, s1, s2) jit_addcr_l((d), (s1), (s2))
|
||||
#define jit_addxi_ul(d, rs, is) jit_addxi_l((d), (rs), (is))
|
||||
#define jit_addxr_ul(d, s1, s2) jit_addxr_l((d), (s1), (s2))
|
||||
#define jit_andi_ul(d, rs, is) jit_andi_l((d), (rs), (is))
|
||||
#define jit_andr_ul(d, s1, s2) jit_andr_l((d), (s1), (s2))
|
||||
#define jit_lshi_ul(d, rs, is) jit_lshi_l((d), (rs), (is))
|
||||
#define jit_lshr_ul(d, s1, s2) jit_lshr_l((d), (s1), (s2))
|
||||
#define jit_movi_ul(d, rs) jit_movi_l((d), (rs))
|
||||
#define jit_movr_ul(d, rs) jit_movr_l((d), (rs))
|
||||
#define jit_ori_ul(d, rs, is) jit_ori_l((d), (rs), (is))
|
||||
#define jit_orr_ul(d, s1, s2) jit_orr_l((d), (s1), (s2))
|
||||
#define jit_rsbi_ul(d, rs, is) jit_rsbi_l((d), (rs), (is))
|
||||
#define jit_rsbr_ul(d, s1, s2) jit_rsbr_l((d), (s1), (s2))
|
||||
#define jit_subi_ul(d, rs, is) jit_subi_l((d), (rs), (is))
|
||||
#define jit_subr_ul(d, s1, s2) jit_subr_l((d), (s1), (s2))
|
||||
#define jit_subci_ul(d, rs, is) jit_subci_l((d), (rs), (is))
|
||||
#define jit_subcr_ul(d, s1, s2) jit_subcr_l((d), (s1), (s2))
|
||||
#define jit_subxi_ui(d, rs, is) jit_subxi_i((d), (rs), (is))
|
||||
#define jit_subxi_ul(d, rs, is) jit_subxi_l((d), (rs), (is))
|
||||
#define jit_subxr_ui(d, s1, s2) jit_subxr_i((d), (s1), (s2))
|
||||
#define jit_subxr_ul(d, s1, s2) jit_subxr_i((d), (s1), (s2))
|
||||
#define jit_xori_ul(d, rs, is) jit_xori_l((d), (rs), (is))
|
||||
#define jit_xorr_ul(d, s1, s2) jit_xorr_l((d), (s1), (s2))
|
||||
|
||||
#define jit_addr_p(d, s1, s2) jit_addr_ul((d), (s1), (s2))
|
||||
#define jit_addi_p(d, rs, is) (jit_addi_ul((d), (rs), (long) (is)), _jit.x.pc)
|
||||
#define jit_movr_p(d, rs) jit_movr_ul((d), (rs))
|
||||
#define jit_subr_p(d, s1, s2) jit_subr_ul((d), (s1), (s2))
|
||||
#define jit_subi_p(d, rs, is) jit_subi_ul((d), (rs), (long) (is))
|
||||
#define jit_rsbi_p(d, rs, is) jit_rsbi_ul((d), (rs), (long) (is))
|
||||
|
||||
#ifndef jit_movi_p
|
||||
#define jit_movi_p(d, is) (jit_movi_ul((d), (long) (is)), _jit.x.pc)
|
||||
#endif
|
||||
|
||||
#define jit_patch(pv) jit_patch_at ((pv), (_jit.x.pc))
|
||||
|
||||
#ifndef jit_addci_i
|
||||
#define jit_addci_i(d, rs, is) jit_addi_i((d), (rs), (is))
|
||||
#define jit_addcr_i(d, s1, s2) jit_addr_i((d), (s1), (s2))
|
||||
#define jit_addci_l(d, rs, is) jit_addi_l((d), (rs), (is))
|
||||
#define jit_addcr_l(d, s1, s2) jit_addr_l((d), (s1), (s2))
|
||||
#endif
|
||||
|
||||
#ifndef jit_subcr_i
|
||||
#define jit_subcr_i(d, s1, s2) jit_subr_i((d), (s1), (s2))
|
||||
#endif
|
||||
|
||||
/* NEG is not mandatory -- pick an appropriate implementation */
|
||||
#ifndef jit_negr_i
|
||||
# ifdef JIT_RZERO
|
||||
# define jit_negr_i(d, rs) jit_subr_i((d), JIT_RZERO, (rs))
|
||||
# define jit_negr_l(d, rs) jit_subr_l((d), JIT_RZERO, (rs))
|
||||
# else /* !JIT_RZERO */
|
||||
# ifndef jit_rsbi_i
|
||||
# define jit_negr_i(d, rs) (jit_xori_i((d), (rs), -1), jit_addi_l((d), (d), 1))
|
||||
# define jit_negr_l(d, rs) (jit_xori_l((d), (rs), -1), jit_addi_l((d), (d), 1))
|
||||
# else /* jit_rsbi_i */
|
||||
# define jit_negr_i(d, rs) jit_rsbi_i((d), (rs), 0)
|
||||
# define jit_negr_l(d, rs) jit_rsbi_l((d), (rs), 0)
|
||||
# endif /* jit_rsbi_i */
|
||||
# endif /* !JIT_RZERO */
|
||||
#endif /* !jit_negr_i */
|
||||
|
||||
/* RSB is not mandatory */
|
||||
#ifndef jit_rsbi_i
|
||||
# define jit_rsbi_i(d, rs, is) (jit_subi_i((d), (rs), (is)), jit_negr_i((d), (d)))
|
||||
|
||||
# ifndef jit_rsbi_l
|
||||
# define jit_rsbi_l(d, rs, is) (jit_subi_l((d), (rs), (is)), jit_negr_l((d), (d)))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Common 'shortcut' implementations */
|
||||
#ifndef jit_subi_i
|
||||
#define jit_subi_i(d, rs, is) jit_addi_i((d), (rs), -(is))
|
||||
#endif
|
||||
#define jit_subi_l(d, rs, is) jit_addi_l((d), (rs), -(is))
|
||||
#ifndef jit_subci_i
|
||||
#define jit_subci_i(d, rs, is) jit_addci_i((d), (rs), -(is))
|
||||
#endif
|
||||
#define jit_subci_l(d, rs, is) jit_addci_l((d), (rs), -(is))
|
||||
#define jit_rsbr_f(d, s1, s2) jit_subr_f((d), (s2), (s1))
|
||||
#define jit_rsbr_d(d, s1, s2) jit_subr_d((d), (s2), (s1))
|
||||
#ifndef jit_rsbr_i
|
||||
#define jit_rsbr_i(d, s1, s2) jit_subr_i((d), (s2), (s1))
|
||||
#endif
|
||||
#define jit_rsbr_l(d, s1, s2) jit_subr_l((d), (s2), (s1))
|
||||
#define jit_rsbr_p(d, s1, s2) jit_subr_p((d), (s2), (s1))
|
||||
|
||||
/* Unary */
|
||||
#define jit_notr_c(d, rs) jit_xori_c((d), (rs), 255)
|
||||
#define jit_notr_uc(d, rs) jit_xori_c((d), (rs), 255)
|
||||
#define jit_notr_s(d, rs) jit_xori_s((d), (rs), 65535)
|
||||
#define jit_notr_us(d, rs) jit_xori_s((d), (rs), 65535)
|
||||
#ifndef jit_notr_i
|
||||
#define jit_notr_i(d, rs) jit_xori_i((d), (rs), ~0)
|
||||
#endif
|
||||
#define jit_notr_ui(d, rs) jit_xori_i((d), (rs), ~0)
|
||||
#define jit_notr_l(d, rs) jit_xori_l((d), (rs), ~0L)
|
||||
#define jit_notr_ul(d, rs) jit_xori_l((d), (rs), ~0L)
|
||||
|
||||
#ifndef jit_extr_c_ui
|
||||
#define jit_extr_c_ui(d, rs) jit_andi_ui((d), (rs), 0xFF)
|
||||
#endif
|
||||
#ifndef jit_extr_s_ui
|
||||
#define jit_extr_s_ui(d, rs) jit_andi_ui((d), (rs), 0xFFFF)
|
||||
#endif
|
||||
#ifndef jit_extr_c_i
|
||||
#define jit_extr_c_i(d, rs) (jit_lshi_i((d), (rs), 24), jit_rshi_i((d), (d), 24))
|
||||
#endif
|
||||
#ifndef jit_extr_s_i
|
||||
#define jit_extr_s_i(d, rs) (jit_lshi_i((d), (rs), 16), jit_rshi_i((d), (d), 16))
|
||||
#endif
|
||||
|
||||
#ifdef jit_addi_l /* sizeof(long) != sizeof(int) */
|
||||
#ifndef jit_extr_c_l
|
||||
#define jit_extr_c_l(d, rs) (jit_lshi_l((d), (rs), 56), jit_rshi_l((d), (d), 56))
|
||||
#endif
|
||||
#ifndef jit_extr_s_l
|
||||
#define jit_extr_s_l(d, rs) (jit_lshi_l((d), (rs), 48), jit_rshi_l((d), (d), 48))
|
||||
#endif
|
||||
#ifndef jit_extr_i_l
|
||||
#define jit_extr_i_l(d, rs) (jit_lshi_l((d), (rs), 32), jit_rshi_l((d), (d), 32))
|
||||
#endif
|
||||
#ifndef jit_extr_c_ul
|
||||
#define jit_extr_c_ul(d, rs) jit_andi_l((d), (rs), 0xFF)
|
||||
#endif
|
||||
#ifndef jit_extr_s_ul
|
||||
#define jit_extr_s_ul(d, rs) jit_andi_l((d), (rs), 0xFFFF)
|
||||
#endif
|
||||
#ifndef jit_extr_i_ul
|
||||
#define jit_extr_i_ul(d, rs) jit_andi_l((d), (rs), 0xFFFFFFFFUL)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define jit_extr_c_s(d, rs) jit_extr_c_i((d), (rs))
|
||||
#define jit_extr_c_us(d, rs) jit_extr_c_ui((d), (rs))
|
||||
#define jit_extr_uc_s(d, rs) jit_extr_uc_i((d), (rs))
|
||||
#define jit_extr_uc_us(d, rs) jit_extr_uc_ui((d), (rs))
|
||||
#define jit_extr_uc_i(d, rs) jit_extr_c_ui((d), (rs))
|
||||
#define jit_extr_uc_ui(d, rs) jit_extr_c_ui((d), (rs))
|
||||
#define jit_extr_us_i(d, rs) jit_extr_s_ui((d), (rs))
|
||||
#define jit_extr_us_ui(d, rs) jit_extr_s_ui((d), (rs))
|
||||
#define jit_extr_uc_l(d, rs) jit_extr_c_ul((d), (rs))
|
||||
#define jit_extr_uc_ul(d, rs) jit_extr_c_ul((d), (rs))
|
||||
#define jit_extr_us_l(d, rs) jit_extr_s_ul((d), (rs))
|
||||
#define jit_extr_us_ul(d, rs) jit_extr_s_ul((d), (rs))
|
||||
#define jit_extr_ui_l(d, rs) jit_extr_i_ul((d), (rs))
|
||||
#define jit_extr_ui_ul(d, rs) jit_extr_i_ul((d), (rs))
|
||||
|
||||
|
||||
/* NTOH/HTON is not mandatory for big endian architectures */
|
||||
#ifndef jit_ntoh_ui /* big endian */
|
||||
#define jit_ntoh_ui(d, rs) ((d) == (rs) ? (void)0 : jit_movr_i((d), (rs)))
|
||||
#define jit_ntoh_us(d, rs) ((d) == (rs) ? (void)0 : jit_movr_i((d), (rs)))
|
||||
#endif /* big endian */
|
||||
|
||||
/* hton is a synonym for ntoh */
|
||||
#define jit_hton_ui(d, rs) jit_ntoh_ui((d), (rs))
|
||||
#define jit_hton_us(d, rs) jit_ntoh_us((d), (rs))
|
||||
|
||||
/* Stack synonyms */
|
||||
#define jit_pushr_ui(rs) jit_pushr_i(rs)
|
||||
#define jit_popr_ui(rs) jit_popr_i(rs)
|
||||
#define jit_pushr_ul(rs) jit_pushr_l(rs)
|
||||
#define jit_popr_ul(rs) jit_popr_l(rs)
|
||||
#define jit_pushr_p(rs) jit_pushr_ul(rs)
|
||||
#define jit_popr_p(rs) jit_popr_ul(rs)
|
||||
|
||||
#define jit_prepare(nint) jit_prepare_i((nint))
|
||||
#define jit_pusharg_c(rs) jit_pusharg_i(rs)
|
||||
#define jit_pusharg_s(rs) jit_pusharg_i(rs)
|
||||
#define jit_pusharg_uc(rs) jit_pusharg_i(rs)
|
||||
#define jit_pusharg_us(rs) jit_pusharg_i(rs)
|
||||
#define jit_pusharg_ui(rs) jit_pusharg_i(rs)
|
||||
#define jit_pusharg_ul(rs) jit_pusharg_l(rs)
|
||||
#define jit_pusharg_p(rs) jit_pusharg_ul(rs)
|
||||
|
||||
/* Memory synonyms */
|
||||
|
||||
#ifdef JIT_RZERO
|
||||
#ifndef jit_ldi_c
|
||||
#define jit_ldi_c(rd, is) jit_ldxi_c((rd), JIT_RZERO, (is))
|
||||
#define jit_sti_c(id, rs) jit_stxi_c((id), JIT_RZERO, (rs))
|
||||
#define jit_ldi_s(rd, is) jit_ldxi_s((rd), JIT_RZERO, (is))
|
||||
#define jit_sti_s(id, rs) jit_stxi_s((id), JIT_RZERO, (rs))
|
||||
#define jit_ldi_i(rd, is) jit_ldxi_i((rd), JIT_RZERO, (is))
|
||||
#define jit_sti_i(id, rs) jit_stxi_i((id), JIT_RZERO, (rs))
|
||||
#define jit_ldi_l(rd, is) jit_ldxi_l((rd), JIT_RZERO, (is))
|
||||
#define jit_sti_l(id, rs) jit_stxi_l((id), JIT_RZERO, (rs))
|
||||
#define jit_ldi_uc(rd, is) jit_ldxi_uc((rd), JIT_RZERO, (is))
|
||||
#define jit_ldi_us(rd, is) jit_ldxi_us((rd), JIT_RZERO, (is))
|
||||
#define jit_ldi_ui(rd, is) jit_ldxi_ui((rd), JIT_RZERO, (is))
|
||||
#define jit_ldi_ul(rd, is) jit_ldxi_ul((rd), JIT_RZERO, (is))
|
||||
#endif
|
||||
|
||||
#ifndef jit_ldr_c
|
||||
#define jit_ldr_c(rd, rs) jit_ldxr_c((rd), JIT_RZERO, (rs))
|
||||
#define jit_str_c(rd, rs) jit_stxr_c(JIT_RZERO, (rd), (rs))
|
||||
#define jit_ldr_s(rd, rs) jit_ldxr_s((rd), JIT_RZERO, (rs))
|
||||
#define jit_str_s(rd, rs) jit_stxr_s(JIT_RZERO, (rd), (rs))
|
||||
#define jit_ldr_i(rd, rs) jit_ldxr_i((rd), JIT_RZERO, (rs))
|
||||
#define jit_str_i(rd, rs) jit_stxr_i(JIT_RZERO, (rd), (rs))
|
||||
#define jit_ldr_l(rd, rs) jit_ldxr_l((rd), JIT_RZERO, (rs))
|
||||
#define jit_str_l(rd, rs) jit_stxr_l(JIT_RZERO, (rd), (rs))
|
||||
#define jit_ldr_uc(rd, rs) jit_ldxr_uc((rd), JIT_RZERO, (rs))
|
||||
#define jit_ldr_us(rd, rs) jit_ldxr_us((rd), JIT_RZERO, (rs))
|
||||
#define jit_ldr_ui(rd, rs) jit_ldxr_ui((rd), JIT_RZERO, (rs))
|
||||
#define jit_ldr_ul(rd, rs) jit_ldxr_ul((rd), JIT_RZERO, (rs))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define jit_str_uc(rd, rs) jit_str_c((rd), (rs))
|
||||
#define jit_sti_uc(id, rs) jit_sti_c((id), (rs))
|
||||
#define jit_stxr_uc(d1, d2, rs) jit_stxr_c((d1), (d2), (rs))
|
||||
#define jit_stxi_uc(id, rd, is) jit_stxi_c((id), (rd), (is))
|
||||
|
||||
#define jit_str_us(rd, rs) jit_str_s((rd), (rs))
|
||||
#define jit_sti_us(id, rs) jit_sti_s((id), (rs))
|
||||
#define jit_stxr_us(d1, d2, rs) jit_stxr_s((d1), (d2), (rs))
|
||||
#define jit_stxi_us(id, rd, is) jit_stxi_s((id), (rd), (is))
|
||||
|
||||
#define jit_str_ui(rd, rs) jit_str_i((rd), (rs))
|
||||
#define jit_sti_ui(id, rs) jit_sti_i((id), (rs))
|
||||
#define jit_stxr_ui(d1, d2, rs) jit_stxr_i((d1), (d2), (rs))
|
||||
#define jit_stxi_ui(id, rd, is) jit_stxi_i((id), (rd), (is))
|
||||
|
||||
#define jit_str_ul(rd, rs) jit_str_l((rd), (rs))
|
||||
#define jit_sti_ul(id, rs) jit_sti_l((id), (rs))
|
||||
#define jit_stxr_ul(d1, d2, rs) jit_stxr_l((d1), (d2), (rs))
|
||||
#define jit_stxi_ul(id, rd, is) jit_stxi_l((id), (rd), (is))
|
||||
|
||||
#define jit_str_p(rd, rs) jit_str_l((rd), (rs))
|
||||
#define jit_sti_p(id, rs) jit_sti_l((id), (rs))
|
||||
#define jit_stxr_p(d1, d2, rs) jit_stxr_l((d1), (d2), (rs))
|
||||
#define jit_stxi_p(id, rd, is) jit_stxi_l((id), (rd), (is))
|
||||
|
||||
#define jit_ldr_p(rd, rs) jit_ldr_l((rd), (rs))
|
||||
#define jit_ldi_p(rd, is) jit_ldi_l((rd), (is))
|
||||
#define jit_ldxr_p(rd, s1, s2) jit_ldxr_l((rd), (s1), (s2))
|
||||
#define jit_ldxi_p(rd, rs, is) jit_ldxi_l((rd), (rs), (is))
|
||||
|
||||
|
||||
/* Boolean & branch synonyms */
|
||||
#define jit_eqr_ui(d, s1, s2) jit_eqr_i((d), (s1), (s2))
|
||||
#define jit_eqi_ui(d, rs, is) jit_eqi_i((d), (rs), (is))
|
||||
#define jit_ner_ui(d, s1, s2) jit_ner_i((d), (s1), (s2))
|
||||
#define jit_nei_ui(d, rs, is) jit_nei_i((d), (rs), (is))
|
||||
|
||||
#define jit_eqr_ul(d, s1, s2) jit_eqr_l((d), (s1), (s2))
|
||||
#define jit_eqi_ul(d, rs, is) jit_eqi_l((d), (rs), (is))
|
||||
#define jit_ner_ul(d, s1, s2) jit_ner_l((d), (s1), (s2))
|
||||
#define jit_nei_ul(d, rs, is) jit_nei_l((d), (rs), (is))
|
||||
|
||||
#define jit_beqr_ui(label, s1, s2) jit_beqr_i((label), (s1), (s2))
|
||||
#define jit_beqi_ui(label, rs, is) jit_beqi_i((label), (rs), (is))
|
||||
#define jit_bner_ui(label, s1, s2) jit_bner_i((label), (s1), (s2))
|
||||
#define jit_bnei_ui(label, rs, is) jit_bnei_i((label), (rs), (is))
|
||||
#define jit_bmcr_ui(label, s1, s2) jit_bmcr_i((label), (s1), (s2))
|
||||
#define jit_bmci_ui(label, rs, is) jit_bmci_i((label), (rs), (is))
|
||||
#define jit_bmsr_ui(label, s1, s2) jit_bmsr_i((label), (s1), (s2))
|
||||
#define jit_bmsi_ui(label, rs, is) jit_bmsi_i((label), (rs), (is))
|
||||
|
||||
#define jit_beqr_ul(label, s1, s2) jit_beqr_l((label), (s1), (s2))
|
||||
#define jit_beqi_ul(label, rs, is) jit_beqi_l((label), (rs), (is))
|
||||
#define jit_bner_ul(label, s1, s2) jit_bner_l((label), (s1), (s2))
|
||||
#define jit_bnei_ul(label, rs, is) jit_bnei_l((label), (rs), (is))
|
||||
#define jit_bmcr_ul(label, s1, s2) jit_bmcr_l((label), (s1), (s2))
|
||||
#define jit_bmci_ul(label, rs, is) jit_bmci_l((label), (rs), (is))
|
||||
#define jit_bmsr_ul(label, s1, s2) jit_bmsr_l((label), (s1), (s2))
|
||||
#define jit_bmsi_ul(label, rs, is) jit_bmsi_l((label), (rs), (is))
|
||||
|
||||
#define jit_ltr_p(d, s1, s2) jit_ltr_ul((d), (s1), (s2))
|
||||
#define jit_lti_p(d, rs, is) jit_lti_ul((d), (rs), (is))
|
||||
#define jit_ler_p(d, s1, s2) jit_ler_ul((d), (s1), (s2))
|
||||
#define jit_lei_p(d, rs, is) jit_lei_ul((d), (rs), (is))
|
||||
#define jit_gtr_p(d, s1, s2) jit_gtr_ul((d), (s1), (s2))
|
||||
#define jit_gti_p(d, rs, is) jit_gti_ul((d), (rs), (is))
|
||||
#define jit_ger_p(d, s1, s2) jit_ger_ul((d), (s1), (s2))
|
||||
#define jit_gei_p(d, rs, is) jit_gei_ul((d), (rs), (is))
|
||||
#define jit_eqr_p(d, s1, s2) jit_eqr_ul((d), (s1), (s2))
|
||||
#define jit_eqi_p(d, rs, is) jit_eqi_ul((d), (rs), (is))
|
||||
#define jit_ner_p(d, s1, s2) jit_ner_ul((d), (s1), (s2))
|
||||
#define jit_nei_p(d, rs, is) jit_nei_ul((d), (rs), (is))
|
||||
|
||||
#define jit_bltr_p(label, s1, s2) jit_bltr_ul((label), (s1), (s2))
|
||||
#define jit_blti_p(label, rs, is) jit_blti_ul((label), (rs), (is))
|
||||
#define jit_bler_p(label, s1, s2) jit_bler_ul((label), (s1), (s2))
|
||||
#define jit_blei_p(label, rs, is) jit_blei_ul((label), (rs), (is))
|
||||
#define jit_bgtr_p(label, s1, s2) jit_bgtr_ul((label), (s1), (s2))
|
||||
#define jit_bgti_p(label, rs, is) jit_bgti_ul((label), (rs), (is))
|
||||
#define jit_bger_p(label, s1, s2) jit_bger_ul((label), (s1), (s2))
|
||||
#define jit_bgei_p(label, rs, is) jit_bgei_ul((label), (rs), (is))
|
||||
#define jit_beqr_p(label, s1, s2) jit_beqr_ul((label), (s1), (s2))
|
||||
#define jit_beqi_p(label, rs, is) jit_beqi_ul((label), (rs), (is))
|
||||
#define jit_bner_p(label, s1, s2) jit_bner_ul((label), (s1), (s2))
|
||||
#define jit_bnei_p(label, rs, is) jit_bnei_ul((label), (rs), _jit_UL(is))
|
||||
|
||||
#define jit_retval_ui(rd) jit_retval_i((rd))
|
||||
#define jit_retval_uc(rd) jit_retval_i((rd))
|
||||
#define jit_retval_us(rd) jit_retval_i((rd))
|
||||
#define jit_retval_ul(rd) jit_retval_l((rd))
|
||||
#define jit_retval_p(rd) jit_retval_ul((rd))
|
||||
#define jit_retval_c(rd) jit_retval_i((rd))
|
||||
#define jit_retval_s(rd) jit_retval_i((rd))
|
||||
|
||||
/* This was a bug, but we keep it. */
|
||||
#define jit_retval(rd) jit_retval_i ((rd))
|
||||
|
||||
#ifndef jit_finish
|
||||
#define jit_finish(sub) jit_calli(sub)
|
||||
#endif
|
||||
|
||||
#ifndef jit_finishr
|
||||
#define jit_finishr(reg) jit_callr(reg)
|
||||
#endif
|
||||
|
||||
#ifndef jit_prolog
|
||||
#define jit_prolog(numargs)
|
||||
#endif
|
||||
|
||||
#ifndef jit_leaf
|
||||
#define jit_leaf(numargs) jit_prolog(numargs)
|
||||
#endif
|
||||
|
||||
#ifndef jit_getarg_c
|
||||
#ifndef JIT_FP
|
||||
#define jit_getarg_c(reg, ofs) jit_extr_c_i ((reg), (ofs))
|
||||
#define jit_getarg_i(reg, ofs) jit_movr_i ((reg), (ofs))
|
||||
#define jit_getarg_l(reg, ofs) jit_movr_l ((reg), (ofs))
|
||||
#define jit_getarg_p(reg, ofs) jit_movr_p ((reg), (ofs))
|
||||
#define jit_getarg_s(reg, ofs) jit_extr_s_i ((reg), (ofs))
|
||||
#define jit_getarg_uc(reg, ofs) jit_extr_uc_ui((reg), (ofs))
|
||||
#define jit_getarg_ui(reg, ofs) jit_movr_ui ((reg), (ofs))
|
||||
#define jit_getarg_ul(reg, ofs) jit_extr_uc_ul((reg), (ofs))
|
||||
#define jit_getarg_us(reg, ofs) jit_extr_us_ul((reg), (ofs))
|
||||
#else
|
||||
#define jit_getarg_c(reg, ofs) jit_ldxi_c((reg), JIT_FP, (ofs));
|
||||
#define jit_getarg_uc(reg, ofs) jit_ldxi_uc((reg), JIT_FP, (ofs));
|
||||
#define jit_getarg_s(reg, ofs) jit_ldxi_s((reg), JIT_FP, (ofs));
|
||||
#define jit_getarg_us(reg, ofs) jit_ldxi_us((reg), JIT_FP, (ofs));
|
||||
#define jit_getarg_i(reg, ofs) jit_ldxi_i((reg), JIT_FP, (ofs));
|
||||
#define jit_getarg_ui(reg, ofs) jit_ldxi_ui((reg), JIT_FP, (ofs));
|
||||
#define jit_getarg_l(reg, ofs) jit_ldxi_l((reg), JIT_FP, (ofs));
|
||||
#define jit_getarg_ul(reg, ofs) jit_ldxi_ul((reg), JIT_FP, (ofs));
|
||||
#define jit_getarg_p(reg, ofs) jit_ldxi_p((reg), JIT_FP, (ofs));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef jit_setarg_p
|
||||
#ifdef JIT_FP
|
||||
#define jit_setarg_p(reg, ofs) jit_stxi_p((ofs), JIT_FP, (reg));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* Common definitions when sizeof(long) = sizeof(int) */
|
||||
#ifndef jit_addi_l
|
||||
#define JIT_LONG_IS_INT
|
||||
|
||||
/* ALU */
|
||||
#define jit_addi_l(d, rs, is) jit_addi_i((d), (rs), (is))
|
||||
#define jit_addr_l(d, s1, s2) jit_addr_i((d), (s1), (s2))
|
||||
#define jit_addci_l(d, rs, is) jit_addci_i((d), (rs), (is))
|
||||
#define jit_addcr_l(d, s1, s2) jit_addcr_i((d), (s1), (s2))
|
||||
#define jit_addxi_l(d, rs, is) jit_addxi_i((d), (rs), (is))
|
||||
#define jit_addxr_l(d, s1, s2) jit_addxr_i((d), (s1), (s2))
|
||||
#define jit_andi_l(d, rs, is) jit_andi_i((d), (rs), (is))
|
||||
#define jit_andr_l(d, s1, s2) jit_andr_i((d), (s1), (s2))
|
||||
#define jit_divi_l(d, rs, is) jit_divi_i((d), (rs), (is))
|
||||
#define jit_divr_l(d, s1, s2) jit_divr_i((d), (s1), (s2))
|
||||
#define jit_hmuli_l(d, rs, is) jit_hmuli_i((d), (rs), (is))
|
||||
#define jit_hmulr_l(d, s1, s2) jit_hmulr_i((d), (s1), (s2))
|
||||
#define jit_lshi_l(d, rs, is) jit_lshi_i((d), (rs), (is))
|
||||
#define jit_lshr_l(d, s1, s2) jit_lshr_i((d), (s1), (s2))
|
||||
#define jit_modi_l(d, rs, is) jit_modi_i((d), (rs), (is))
|
||||
#define jit_modr_l(d, s1, s2) jit_modr_i((d), (s1), (s2))
|
||||
#define jit_muli_l(d, rs, is) jit_muli_i((d), (rs), (is))
|
||||
#define jit_mulr_l(d, s1, s2) jit_mulr_i((d), (s1), (s2))
|
||||
#define jit_ori_l(d, rs, is) jit_ori_i((d), (rs), (is))
|
||||
#define jit_orr_l(d, s1, s2) jit_orr_i((d), (s1), (s2))
|
||||
#define jit_rshi_l(d, rs, is) jit_rshi_i((d), (rs), (is))
|
||||
#define jit_rshr_l(d, s1, s2) jit_rshr_i((d), (s1), (s2))
|
||||
#define jit_subr_l(d, s1, s2) jit_subr_i((d), (s1), (s2))
|
||||
#define jit_subcr_l(d, s1, s2) jit_subcr_i((d), (s1), (s2))
|
||||
#define jit_subxi_l(d, rs, is) jit_subxi_i((d), (rs), (is))
|
||||
#define jit_subxr_l(d, s1, s2) jit_subxr_i((d), (s1), (s2))
|
||||
#define jit_xori_l(d, rs, is) jit_xori_i((d), (rs), (is))
|
||||
#define jit_xorr_l(d, s1, s2) jit_xorr_i((d), (s1), (s2))
|
||||
|
||||
#ifndef jit_rsbi_l
|
||||
#define jit_rsbi_l(d, rs, is) jit_rsbi_i((d), (rs), (is))
|
||||
#endif
|
||||
|
||||
#define jit_divi_ul(d, rs, is) jit_divi_ui((d), (rs), (is))
|
||||
#define jit_divr_ul(d, s1, s2) jit_divr_ui((d), (s1), (s2))
|
||||
#define jit_hmuli_ul(d, rs, is) jit_hmuli_ui((d), (rs), (is))
|
||||
#define jit_hmulr_ul(d, s1, s2) jit_hmulr_ui((d), (s1), (s2))
|
||||
#define jit_modi_ul(d, rs, is) jit_modi_ui((d), (rs), (is))
|
||||
#define jit_modr_ul(d, s1, s2) jit_modr_ui((d), (s1), (s2))
|
||||
#define jit_muli_ul(d, rs, is) jit_muli_ui((d), (rs), (is))
|
||||
#define jit_mulr_ul(d, s1, s2) jit_mulr_ui((d), (s1), (s2))
|
||||
#define jit_rshi_ul(d, rs, is) jit_rshi_ui((d), (rs), (is))
|
||||
#define jit_rshr_ul(d, s1, s2) jit_rshr_ui((d), (s1), (s2))
|
||||
|
||||
/* Sign/Zero extension */
|
||||
#define jit_extr_c_l(d, rs) jit_extr_c_i(d, rs)
|
||||
#define jit_extr_c_ul(d, rs) jit_extr_c_ui(d, rs)
|
||||
#define jit_extr_s_l(d, rs) jit_extr_s_i(d, rs)
|
||||
#define jit_extr_s_ul(d, rs) jit_extr_s_ui(d, rs)
|
||||
#define jit_extr_i_l(d, rs) jit_movr_i(d, rs)
|
||||
#define jit_extr_i_ul(d, rs) jit_movr_i(d, rs)
|
||||
|
||||
/* Unary */
|
||||
#define jit_movi_l(d, rs) jit_movi_i((d), (rs))
|
||||
#define jit_movr_l(d, rs) jit_movr_i((d), (rs))
|
||||
|
||||
/* Stack */
|
||||
#define jit_pushr_l(rs) jit_pushr_i(rs)
|
||||
#define jit_popr_l(rs) jit_popr_i(rs)
|
||||
#define jit_pusharg_l(rs) jit_pusharg_i(rs)
|
||||
|
||||
/* Memory */
|
||||
#ifndef JIT_RZERO
|
||||
#define jit_ldr_l(d, rs) jit_ldr_i((d), (rs))
|
||||
#define jit_ldi_l(d, is) jit_ldi_i((d), (is))
|
||||
#define jit_str_l(d, rs) jit_str_i((d), (rs))
|
||||
#define jit_sti_l(d, is) jit_sti_i((d), (is))
|
||||
#define jit_ldr_ui(d, rs) jit_ldr_i((d), (rs))
|
||||
#define jit_ldi_ui(d, is) jit_ldi_i((d), (is))
|
||||
#define jit_ldr_ul(d, rs) jit_ldr_ui((d), (rs))
|
||||
#define jit_ldi_ul(d, is) jit_ldi_ui((d), (is))
|
||||
#endif
|
||||
|
||||
#define jit_ldxr_l(d, s1, s2) jit_ldxr_i((d), (s1), (s2))
|
||||
#define jit_ldxi_l(d, rs, is) jit_ldxi_i((d), (rs), (is))
|
||||
#define jit_stxr_l(d, s1, s2) jit_stxr_i((d), (s1), (s2))
|
||||
#define jit_stxi_l(d, rs, is) jit_stxi_i((d), (rs), (is))
|
||||
#define jit_ldxr_ui(d, s1, s2) jit_ldxr_i((d), (s1), (s2))
|
||||
#define jit_ldxi_ui(d, rs, is) jit_ldxi_i((d), (rs), (is))
|
||||
#define jit_ldxr_ul(d, s1, s2) jit_ldxr_ui((d), (s1), (s2))
|
||||
#define jit_ldxi_ul(d, rs, is) jit_ldxi_ui((d), (rs), (is))
|
||||
|
||||
|
||||
/* Boolean */
|
||||
#define jit_ltr_l(d, s1, s2) jit_ltr_i((d), (s1), (s2))
|
||||
#define jit_lti_l(d, rs, is) jit_lti_i((d), (rs), (is))
|
||||
#define jit_ler_l(d, s1, s2) jit_ler_i((d), (s1), (s2))
|
||||
#define jit_lei_l(d, rs, is) jit_lei_i((d), (rs), (is))
|
||||
#define jit_gtr_l(d, s1, s2) jit_gtr_i((d), (s1), (s2))
|
||||
#define jit_gti_l(d, rs, is) jit_gti_i((d), (rs), (is))
|
||||
#define jit_ger_l(d, s1, s2) jit_ger_i((d), (s1), (s2))
|
||||
#define jit_gei_l(d, rs, is) jit_gei_i((d), (rs), (is))
|
||||
#define jit_eqr_l(d, s1, s2) jit_eqr_i((d), (s1), (s2))
|
||||
#define jit_eqi_l(d, rs, is) jit_eqi_i((d), (rs), (is))
|
||||
#define jit_ner_l(d, s1, s2) jit_ner_i((d), (s1), (s2))
|
||||
#define jit_nei_l(d, rs, is) jit_nei_i((d), (rs), (is))
|
||||
#define jit_ltr_ul(d, s1, s2) jit_ltr_ui((d), (s1), (s2))
|
||||
#define jit_lti_ul(d, rs, is) jit_lti_ui((d), (rs), (is))
|
||||
#define jit_ler_ul(d, s1, s2) jit_ler_ui((d), (s1), (s2))
|
||||
#define jit_lei_ul(d, rs, is) jit_lei_ui((d), (rs), (is))
|
||||
#define jit_gtr_ul(d, s1, s2) jit_gtr_ui((d), (s1), (s2))
|
||||
#define jit_gti_ul(d, rs, is) jit_gti_ui((d), (rs), (is))
|
||||
#define jit_ger_ul(d, s1, s2) jit_ger_ui((d), (s1), (s2))
|
||||
#define jit_gei_ul(d, rs, is) jit_gei_ui((d), (rs), (is))
|
||||
|
||||
/* Branches */
|
||||
#define jit_bltr_l(label, s1, s2) jit_bltr_i((label), (s1), (s2))
|
||||
#define jit_blti_l(label, rs, is) jit_blti_i((label), (rs), (is))
|
||||
#define jit_bler_l(label, s1, s2) jit_bler_i((label), (s1), (s2))
|
||||
#define jit_blei_l(label, rs, is) jit_blei_i((label), (rs), (is))
|
||||
#define jit_bgtr_l(label, s1, s2) jit_bgtr_i((label), (s1), (s2))
|
||||
#define jit_bgti_l(label, rs, is) jit_bgti_i((label), (rs), (is))
|
||||
#define jit_bger_l(label, s1, s2) jit_bger_i((label), (s1), (s2))
|
||||
#define jit_bgei_l(label, rs, is) jit_bgei_i((label), (rs), (is))
|
||||
#define jit_beqr_l(label, s1, s2) jit_beqr_i((label), (s1), (s2))
|
||||
#define jit_beqi_l(label, rs, is) jit_beqi_i((label), (rs), (is))
|
||||
#define jit_bner_l(label, s1, s2) jit_bner_i((label), (s1), (s2))
|
||||
#define jit_bnei_l(label, rs, is) jit_bnei_i((label), (rs), (is))
|
||||
#define jit_bmcr_l(label, s1, s2) jit_bmcr_i((label), (s1), (s2))
|
||||
#define jit_bmci_l(label, rs, is) jit_bmci_i((label), (rs), (is))
|
||||
#define jit_bmsr_l(label, s1, s2) jit_bmsr_i((label), (s1), (s2))
|
||||
#define jit_bmsi_l(label, rs, is) jit_bmsi_i((label), (rs), (is))
|
||||
#define jit_boaddr_l(label, s1, s2) jit_boaddr_i((label), (s1), (s2))
|
||||
#define jit_boaddi_l(label, rs, is) jit_boaddi_i((label), (rs), (is))
|
||||
#define jit_bosubr_l(label, s1, s2) jit_bosubr_i((label), (s1), (s2))
|
||||
#define jit_bosubi_l(label, rs, is) jit_bosubi_i((label), (rs), (is))
|
||||
#define jit_bltr_ul(label, s1, s2) jit_bltr_ui((label), (s1), (s2))
|
||||
#define jit_blti_ul(label, rs, is) jit_blti_ui((label), (rs), (is))
|
||||
#define jit_bler_ul(label, s1, s2) jit_bler_ui((label), (s1), (s2))
|
||||
#define jit_blei_ul(label, rs, is) jit_blei_ui((label), (rs), (is))
|
||||
#define jit_bgtr_ul(label, s1, s2) jit_bgtr_ui((label), (s1), (s2))
|
||||
#define jit_bgti_ul(label, rs, is) jit_bgti_ui((label), (rs), (is))
|
||||
#define jit_bger_ul(label, s1, s2) jit_bger_ui((label), (s1), (s2))
|
||||
#define jit_bgei_ul(label, rs, is) jit_bgei_ui((label), (rs), (is))
|
||||
#define jit_boaddr_ul(label, s1, s2) jit_boaddr_ui((label), (s1), (s2))
|
||||
#define jit_boaddi_ul(label, rs, is) jit_boaddi_ui((label), (rs), (is))
|
||||
#define jit_bosubr_ul(label, s1, s2) jit_bosubr_ui((label), (s1), (s2))
|
||||
#define jit_bosubi_ul(label, rs, is) jit_bosubi_ui((label), (rs), (is))
|
||||
|
||||
#define jit_retval_l(rd) jit_retval_i((rd))
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __lightning_core_common_h_ */
|
||||
@@ -1,86 +0,0 @@
|
||||
/******************************** -*- C -*- ****************************
|
||||
*
|
||||
* Platform-independent layer floating-point interface
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
* Written by Paolo Bonzini.
|
||||
*
|
||||
* This file is part of GNU lightning.
|
||||
*
|
||||
* GNU lightning is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2.1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU lightning is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with GNU lightning; see the file COPYING.LESSER; if not, write to the
|
||||
* Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
#define JIT_FPR0 JIT_FPR(0)
|
||||
#define JIT_FPR1 JIT_FPR(1)
|
||||
#define JIT_FPR2 JIT_FPR(2)
|
||||
#define JIT_FPR3 JIT_FPR(3)
|
||||
#define JIT_FPR4 JIT_FPR(4)
|
||||
#define JIT_FPR5 JIT_FPR(5)
|
||||
|
||||
#ifdef JIT_RZERO
|
||||
#ifndef jit_ldi_f
|
||||
#define jit_ldi_f(rd, is) jit_ldxi_f((rd), JIT_RZERO, (is))
|
||||
#define jit_sti_f(id, rs) jit_stxi_f((id), JIT_RZERO, (rs))
|
||||
#define jit_ldi_d(rd, is) jit_ldxi_d((rd), JIT_RZERO, (is))
|
||||
#define jit_sti_d(id, rs) jit_stxi_d((id), JIT_RZERO, (rs))
|
||||
#endif
|
||||
|
||||
#ifndef jit_ldr_f
|
||||
#define jit_ldr_f(rd, rs) jit_ldxr_f((rd), JIT_RZERO, (rs))
|
||||
#define jit_str_f(rd, rs) jit_stxr_f((rd), JIT_RZERO, (rs))
|
||||
#define jit_ldr_d(rd, rs) jit_ldxr_d((rd), JIT_RZERO, (rs))
|
||||
#define jit_str_d(rd, rs) jit_stxr_d((rd), JIT_RZERO, (rs))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef jit_addr_f
|
||||
#define jit_addr_f(rd,s1,s2) jit_addr_d(rd,s1,s2)
|
||||
#define jit_subr_f(rd,s1,s2) jit_subr_d(rd,s1,s2)
|
||||
#define jit_mulr_f(rd,s1,s2) jit_mulr_d(rd,s1,s2)
|
||||
#define jit_divr_f(rd,s1,s2) jit_divr_d(rd,s1,s2)
|
||||
#define jit_movr_f(rd,rs) jit_movr_d(rd,rs)
|
||||
#define jit_abs_f(rd,rs) jit_abs_d(rd,rs)
|
||||
#define jit_negr_f(rd,rs) jit_negr_d(rd,rs)
|
||||
#define jit_sqrt_f(rd,rs) jit_sqrt_d(rd,rs)
|
||||
#define jit_extr_f_d(rs, rd)
|
||||
#define jit_extr_d_f(rs, rd)
|
||||
#define jit_extr_i_f(rd, rs) jit_extr_i_d(rd, rs)
|
||||
#define jit_roundr_f_i(rd, rs) jit_roundr_d_i(rd, rs)
|
||||
#define jit_floorr_f_i(rd, rs) jit_floorr_d_i(rd, rs)
|
||||
#define jit_ceilr_f_i(rd, rs) jit_ceilr_d_i(rd, rs)
|
||||
#define jit_truncr_f_i(rd, rs) jit_truncr_d_i(rd, rs)
|
||||
#define jit_ltr_f(d, s1, s2) jit_ltr_d(d, s1, s2)
|
||||
#define jit_ler_f(d, s1, s2) jit_ler_d(d, s1, s2)
|
||||
#define jit_eqr_f(d, s1, s2) jit_eqr_d(d, s1, s2)
|
||||
#define jit_ner_f(d, s1, s2) jit_ner_d(d, s1, s2)
|
||||
#define jit_ger_f(d, s1, s2) jit_ger_d(d, s1, s2)
|
||||
#define jit_gtr_f(d, s1, s2) jit_gtr_d(d, s1, s2)
|
||||
#define jit_unltr_f(d, s1, s2) jit_unltr_d(d, s1, s2)
|
||||
#define jit_unler_f(d, s1, s2) jit_unler_d(d, s1, s2)
|
||||
#define jit_uneqr_f(d, s1, s2) jit_uneqr_d(d, s1, s2)
|
||||
#define jit_ltgtr_f(d, s1, s2) jit_ltgtr_d(d, s1, s2)
|
||||
#define jit_unger_f(d, s1, s2) jit_unger_d(d, s1, s2)
|
||||
#define jit_ungtr_f(d, s1, s2) jit_ungtr_d(d, s1, s2)
|
||||
#define jit_ordr_f(d, s1, s2) jit_ordr_d(d, s1, s2)
|
||||
#define jit_unordr_f(d, s1, s2) jit_unordr_d(d, s1, s2)
|
||||
#define jit_retval_f(rs) jit_retval_d(rs)
|
||||
#endif
|
||||
@@ -1,54 +0,0 @@
|
||||
/******************************** -*- C -*- ****************************
|
||||
*
|
||||
* Platform-independent layer inline functions (common part)
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
* Written by Paolo Bonzini.
|
||||
*
|
||||
* This file is part of GNU lightning.
|
||||
*
|
||||
* GNU lightning is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2.1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU lightning is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with GNU lightning; see the file COPYING.LESSER; if not, write to the
|
||||
* Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef __lightning_funcs_common_h
|
||||
#define __lightning_funcs_common_h
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static int jit_fail(const char *, const char*, int, const char *) JIT_UNUSED;
|
||||
|
||||
int
|
||||
jit_fail(const char *msg, const char *file, int line, const char *function)
|
||||
{
|
||||
fprintf(stderr, "%s: In function `%s':\n", file, function);
|
||||
fprintf(stderr, "%s:%d: %s\n", file, line, msg);
|
||||
abort();
|
||||
}
|
||||
|
||||
|
||||
#ifndef jit_start_pfx
|
||||
#define jit_start_pfx() ( (jit_insn*)0x4)
|
||||
#define jit_end_pfx() ( (jit_insn*)0x0)
|
||||
#endif
|
||||
|
||||
#endif /* __lightning_funcs_common_h */
|
||||
@@ -1,125 +0,0 @@
|
||||
/******************************** -*- C -*- ****************************
|
||||
*
|
||||
* Run-time assembler for the i386
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Copyright 2003 Gwenole Beauchesne
|
||||
* Copyright 2006 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU lightning.
|
||||
*
|
||||
* GNU lightning is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU lightning is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with GNU lightning; see the file COPYING.LESSER; if not, write to the
|
||||
* Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef __lightning_asm_h
|
||||
#define __lightning_asm_h
|
||||
|
||||
#ifndef LIGHTNING_DEBUG
|
||||
|
||||
/* OPCODE + i = immediate operand
|
||||
* + r = register operand
|
||||
* + m = memory operand (disp,base,index,scale)
|
||||
* + sr/sm = a star preceding a register or memory
|
||||
*/
|
||||
|
||||
#if !_ASM_SAFETY
|
||||
# define _r1(R) _rN(R)
|
||||
# define _r2(R) _rN(R)
|
||||
# define _r4(R) _rN(R)
|
||||
# define _r8(R) _rN(R)
|
||||
# define _rM(R) _rN(R)
|
||||
# define _rX(R) _rN(R)
|
||||
#else
|
||||
/* _r1() used to check only for _AL and _AH but there is
|
||||
* usage of _CL and _DL when _*AX is already an operand */
|
||||
# define _r1(R) \
|
||||
/* Valid 32 bit register? */ \
|
||||
((!((R) & ~0x77) \
|
||||
/* 32, 16 or 8 bit register? */ \
|
||||
&& (((_rC(R) == 0x40 || _rC(R) == 0x30 || _rC(R) == 0x10) \
|
||||
/* Yes. Register is _AL, _CL or _DL? */ \
|
||||
&& ( (_rN(R) | 0x10) == _AL \
|
||||
|| (_rN(R) | 0x10) == _CL \
|
||||
|| (_rN(R) | 0x10) == _DL)) \
|
||||
/* No. Register is _AH? */ \
|
||||
|| ((_rC(R) == 0x20 && (_rN(R) | 0x20) == _AH)))) \
|
||||
? _rN(R) : JITFAIL("bad 8-bit register " #R))
|
||||
# define _r2(R) \
|
||||
/* Valid 32 bit register? */ \
|
||||
((!((R) & ~0x77) \
|
||||
/* 32, 16 or 8 bit register? */ \
|
||||
&& (_rC(R) == 0x40 || _rC(R) == 0x30 || _rC(R) == 0x10)) \
|
||||
? _rN(R) : JITFAIL("bad 16-bit register " #R))
|
||||
# define _r4(R) \
|
||||
/* Valid 32 bit register? */ \
|
||||
((!((R) & ~0x77) \
|
||||
/* 32, 16 or 8 bit register? */ \
|
||||
&& (_rC(R) == 0x40 || _rC(R) == 0x30 || _rC(R) == 0x10)) \
|
||||
? _rN(R) : JITFAIL("bad 32-bit register " #R))
|
||||
# define _r8(R) \
|
||||
JITFAIL("bad 64-bit register " #R)
|
||||
# define _rM(R) \
|
||||
/* Valid MMX register? */ \
|
||||
((!((R) & ~0x67) && _rC(R) == 0x60) \
|
||||
? _rN(R) : JITFAIL("bad MMX register " #R))
|
||||
# define _rX(R) \
|
||||
/* Valid SSE register? */ \
|
||||
((!((R) & ~0x77) && _rC(R) == 0x70) \
|
||||
? _rN(R) : JITFAIL("bad SSE register " #R))
|
||||
#endif
|
||||
|
||||
#define _rA(R) _r4(R)
|
||||
|
||||
#define jit_check8(rs) ((_rN(rs) | _AL) == _AL)
|
||||
#define jit_reg8(rs) \
|
||||
((jit_reg16(rs) == _SI || jit_reg16(rs) == _DI) \
|
||||
? _AL : (_rN(rs) | _AL))
|
||||
#define jit_reg16(rs) (_rN(rs) | _AX)
|
||||
|
||||
/* Use RIP-addressing in 64-bit mode, if possible */
|
||||
#define _r_X( R, D,B,I,S,O) (_r0P(I) ? (_r0P(B) ? _r_D (R,D ) : \
|
||||
(_rsp12P(B) ? _r_DBIS(R,D,_ESP,_ESP,1) : \
|
||||
_r_DB (R,D, B ))) : \
|
||||
(_r0P(B) ? _r_4IS (R,D, I,S) : \
|
||||
(!_rspP(I) ? _r_DBIS(R,D, B, I,S) : \
|
||||
JITFAIL("illegal index register: %esp"))))
|
||||
#define _m32only(X) (X)
|
||||
#define _m64only(X) JITFAIL("invalid instruction in 32-bit mode")
|
||||
#define _m64(X) ((void)0)
|
||||
|
||||
#define _AH 0x24
|
||||
#define _CH 0x25
|
||||
#define _DH 0x26
|
||||
#define _BH 0x27
|
||||
|
||||
#define CALLsr(R) CALLLsr(R)
|
||||
#define JMPsr(R) JMPLsr(R)
|
||||
|
||||
#define DECWr(RD) (_d16(), _Or (0x48,_r2(RD) ))
|
||||
#define DECLr(RD) _Or (0x48,_r4(RD) )
|
||||
#define INCWr(RD) (_d16(), _Or (0x40,_r2(RD) ))
|
||||
#define INCLr(RD) _Or (0x40,_r4(RD) )
|
||||
|
||||
#endif
|
||||
#endif /* __lightning_asm_h */
|
||||
@@ -1,430 +0,0 @@
|
||||
/******************************** -*- C -*- ****************************
|
||||
*
|
||||
* Run-time assembler for the x86-64
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Copyright 2003 Gwenole Beauchesne
|
||||
* Copyright 2006 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU lightning.
|
||||
*
|
||||
* GNU lightning is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU lightning is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with GNU lightning; see the file COPYING.LESSER; if not, write to the
|
||||
* Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef __lightning_asm_h
|
||||
#define __lightning_asm_h
|
||||
|
||||
#ifndef LIGHTNING_DEBUG
|
||||
|
||||
/* OPCODE + i = immediate operand
|
||||
* + r = register operand
|
||||
* + m = memory operand (disp,base,index,scale)
|
||||
* + sr/sm = a star preceding a register or memory
|
||||
*/
|
||||
|
||||
#if !_ASM_SAFETY
|
||||
# define _r1(R) _rN(R)
|
||||
# define _r2(R) _rN(R)
|
||||
# define _r4(R) _rN(R)
|
||||
# define _r8(R) _rN(R)
|
||||
# define _rM(R) _rN(R)
|
||||
# define _rX(R) _rN(R)
|
||||
#else
|
||||
# define _r1(R) \
|
||||
/* Valid 64 bit register? */ \
|
||||
((!((R) & ~0xff) \
|
||||
/* 64, 32, 16 or 8 bit register? */ \
|
||||
&& (_rC(R) == 0x50 || _rC(R) == 0x40 \
|
||||
|| _rC(R) == 0x30 || _rC(R) == 0x10)) \
|
||||
? _rN(R) : JITFAIL("bad 8-bit register " #R))
|
||||
# define _r2(R) \
|
||||
/* Valid 64 bit register? */ \
|
||||
((!((R) & ~0xff) \
|
||||
/* 64, 32, 16 or 8 bit register? */ \
|
||||
&& (_rC(R) == 0x50 || _rC(R) == 0x40 \
|
||||
|| _rC(R) == 0x30 || _rC(R) == 0x10)) \
|
||||
? _rN(R) : JITFAIL("bad 16-bit register " #R))
|
||||
# define _r4(R) \
|
||||
/* Valid 64 bit register? */ \
|
||||
((!((R) & ~0xff) \
|
||||
/* 64, 32, 16 or 8 bit register? */ \
|
||||
&& (_rC(R) == 0x50 || _rC(R) == 0x40 \
|
||||
|| _rC(R) == 0x30 || _rC(R) == 0x10)) \
|
||||
? _rN(R) : JITFAIL("bad 32-bit register " #R))
|
||||
# define _r8(R) \
|
||||
/* Valid 64 bit register? */ \
|
||||
((!((R) & ~0xff) \
|
||||
/* 64, 32, 16 or 8 bit register? */ \
|
||||
&& (_rC(R) == 0x50 || _rC(R) == 0x40 \
|
||||
|| _rC(R) == 0x30 || _rC(R) == 0x10)) \
|
||||
? _rN(R) : JITFAIL("bad 64-bit register " #R))
|
||||
# define _rM(R) \
|
||||
/* Valid MMX* register? */ \
|
||||
((!((R) & ~0x6f) && _rC(R) == 0x60) \
|
||||
? _rN(R) : JITFAIL("bad MMX register " #R))
|
||||
# define _rX(R) \
|
||||
/* Valid SSE2 register? */ \
|
||||
((!((R) & ~0x7f) && _rC(R) == 0x70) \
|
||||
? _rN(R) : JITFAIL("bad SSE2 register " #R))
|
||||
#endif
|
||||
|
||||
#define _rA(R) _r8(R)
|
||||
|
||||
#define jit_check8(rs) 1
|
||||
#define jit_reg8(rs) (_rR(rs) | _AL)
|
||||
#define jit_reg16(rs) (_rR(rs) | _AX)
|
||||
|
||||
/* Use RIP-addressing in 64-bit mode, if possible */
|
||||
#if 0
|
||||
#define _x86_RIP_addressing_possible(D,O) (X86_RIP_RELATIVE_ADDR && \
|
||||
((unsigned long)x86_get_target() + 4 + (O) - (D) <= 0xffffffff))
|
||||
|
||||
#define _r_X( R, D,B,I,S,O) (_r0P(I) ? (_r0P(B) ? (!X86_TARGET_64BIT ? _r_D(R,D) : \
|
||||
(_x86_RIP_addressing_possible(D, O) ? \
|
||||
_r_D(R, (D) - ((unsigned long)x86_get_target() + 4 + (O))) : \
|
||||
_r_DSIB(R,D))) : \
|
||||
_r_DSIB(R,D )) : \
|
||||
(_rIP(B) ? _r_D (R,D ) : \
|
||||
(_rsp12P(B) ? _r_DBIS(R,D,_RSP,_RSP,1) : \
|
||||
_r_DB (R,D, B )))) : \
|
||||
(_r0P(B) ? _r_4IS (R,D, I,S) : \
|
||||
(!_rspP(I) ? _r_DBIS(R,D, B, I,S) : \
|
||||
JITFAIL("illegal index register: %esp"))))
|
||||
#else
|
||||
#define _r_X( R, D,B,I,S,O) (_r0P(I) ? (_r0P(B) ? _r_DSIB(R,D ) : \
|
||||
(_rIP(B) ? _r_D (R,D ) : \
|
||||
(_rsp12P(B) ? _r_DBIS(R,D,_RSP,_RSP,1) : \
|
||||
_r_DB (R,D, B )))) : \
|
||||
(_r0P(B) ? _r_4IS (R,D, I,S) : \
|
||||
(!_rspP(I) ? _r_DBIS(R,D, B, I,S) : \
|
||||
JITFAIL("illegal index register: %esp"))))
|
||||
#endif
|
||||
|
||||
|
||||
#define _m32only(X) (JITFAIL("invalid instruction in 64-bit mode"))
|
||||
#define _m64only(X) (X)
|
||||
#define _m64(X) (X)
|
||||
|
||||
#define _SPL 0x14
|
||||
#define _BPL 0x15
|
||||
#define _SIL 0x16
|
||||
#define _DIL 0x17
|
||||
#define _R8B 0x18
|
||||
#define _R9B 0x19
|
||||
#define _R10B 0x1A
|
||||
#define _R11B 0x1B
|
||||
#define _R12B 0x1C
|
||||
#define _R13B 0x1D
|
||||
#define _R14B 0x1E
|
||||
#define _R15B 0x1F
|
||||
|
||||
#define _R8W 0x38
|
||||
#define _R9W 0x39
|
||||
#define _R10W 0x3A
|
||||
#define _R11W 0x3B
|
||||
#define _R12W 0x3C
|
||||
#define _R13W 0x3D
|
||||
#define _R14W 0x3E
|
||||
#define _R15W 0x3F
|
||||
#define _R8D 0x48
|
||||
#define _R9D 0x49
|
||||
#define _R10D 0x4A
|
||||
#define _R11D 0x4B
|
||||
#define _R12D 0x4C
|
||||
#define _R13D 0x4D
|
||||
#define _R14D 0x4E
|
||||
#define _R15D 0x4F
|
||||
|
||||
#define _RAX 0x50
|
||||
#define _RCX 0x51
|
||||
#define _RDX 0x52
|
||||
#define _RBX 0x53
|
||||
#define _RSP 0x54
|
||||
#define _RBP 0x55
|
||||
#define _RSI 0x56
|
||||
#define _RDI 0x57
|
||||
#define _R8 0x58
|
||||
#define _R9 0x59
|
||||
#define _R10 0x5A
|
||||
#define _R11 0x5B
|
||||
#define _R12 0x5C
|
||||
#define _R13 0x5D
|
||||
#define _R14 0x5E
|
||||
#define _R15 0x5F
|
||||
#define _RIP -2
|
||||
|
||||
#define _r1e8lP(R) ((int)(R) >= _SPL && (int)(R) <= _DIL)
|
||||
|
||||
#define DECWr(RD) (_d16(), _REXLrr(0, RD), _O_Mrm (0xff ,_b11,_b001 ,_r2(RD) ))
|
||||
#define DECLr(RD) (_REXLrr(0, RD), _O_Mrm (0xff ,_b11,_b001 ,_r4(RD) ))
|
||||
#define INCWr(RD) (_d16(), _REXLrr(0, RD), _O_Mrm (0xff ,_b11,_b000 ,_r2(RD) ))
|
||||
#define INCLr(RD) (_REXLrr(0, RD), _O_Mrm (0xff ,_b11,_b000 ,_r4(RD) ))
|
||||
|
||||
#define ADCQrr(RS, RD) _ALUQrr(X86_ADC, RS, RD)
|
||||
#define ADCQmr(MD, MB, MI, MS, RD) _ALUQmr(X86_ADC, MD, MB, MI, MS, RD)
|
||||
#define ADCQrm(RS, MD, MB, MI, MS) _ALUQrm(X86_ADC, RS, MD, MB, MI, MS)
|
||||
#define ADCQir(IM, RD) _ALUQir(X86_ADC, IM, RD)
|
||||
#define ADCQim(IM, MD, MB, MI, MS) _ALUQim(X86_ADC, IM, MD, MB, MI, MS)
|
||||
|
||||
#define ADDQrr(RS, RD) _ALUQrr(X86_ADD, RS, RD)
|
||||
#define ADDQmr(MD, MB, MI, MS, RD) _ALUQmr(X86_ADD, MD, MB, MI, MS, RD)
|
||||
#define ADDQrm(RS, MD, MB, MI, MS) _ALUQrm(X86_ADD, RS, MD, MB, MI, MS)
|
||||
#define ADDQir(IM, RD) _ALUQir(X86_ADD, IM, RD)
|
||||
#define ADDQim(IM, MD, MB, MI, MS) _ALUQim(X86_ADD, IM, MD, MB, MI, MS)
|
||||
|
||||
#define ANDQrr(RS, RD) _ALUQrr(X86_AND, RS, RD)
|
||||
#define ANDQmr(MD, MB, MI, MS, RD) _ALUQmr(X86_AND, MD, MB, MI, MS, RD)
|
||||
#define ANDQrm(RS, MD, MB, MI, MS) _ALUQrm(X86_AND, RS, MD, MB, MI, MS)
|
||||
#define ANDQir(IM, RD) _ALUQir(X86_AND, IM, RD)
|
||||
#define ANDQim(IM, MD, MB, MI, MS) _ALUQim(X86_AND, IM, MD, MB, MI, MS)
|
||||
|
||||
#define CMPQrr(RS, RD) _ALUQrr(X86_CMP, RS, RD)
|
||||
#define CMPQmr(MD, MB, MI, MS, RD) _ALUQmr(X86_CMP, MD, MB, MI, MS, RD)
|
||||
#define CMPQrm(RS, MD, MB, MI, MS) _ALUQrm(X86_CMP, RS, MD, MB, MI, MS)
|
||||
#define CMPQir(IM, RD) _ALUQir(X86_CMP, IM, RD)
|
||||
#define CMPQim(IM, MD, MB, MI, MS) _ALUQim(X86_CMP, IM, MD, MB, MI, MS)
|
||||
|
||||
#define ORQrr(RS, RD) _ALUQrr(X86_OR, RS, RD)
|
||||
#define ORQmr(MD, MB, MI, MS, RD) _ALUQmr(X86_OR, MD, MB, MI, MS, RD)
|
||||
#define ORQrm(RS, MD, MB, MI, MS) _ALUQrm(X86_OR, RS, MD, MB, MI, MS)
|
||||
#define ORQir(IM, RD) _ALUQir(X86_OR, IM, RD)
|
||||
#define ORQim(IM, MD, MB, MI, MS) _ALUQim(X86_OR, IM, MD, MB, MI, MS)
|
||||
|
||||
#define SBBQrr(RS, RD) _ALUQrr(X86_SBB, RS, RD)
|
||||
#define SBBQmr(MD, MB, MI, MS, RD) _ALUQmr(X86_SBB, MD, MB, MI, MS, RD)
|
||||
#define SBBQrm(RS, MD, MB, MI, MS) _ALUQrm(X86_SBB, RS, MD, MB, MI, MS)
|
||||
#define SBBQir(IM, RD) _ALUQir(X86_SBB, IM, RD)
|
||||
#define SBBQim(IM, MD, MB, MI, MS) _ALUQim(X86_SBB, IM, MD, MB, MI, MS)
|
||||
|
||||
#define SUBQrr(RS, RD) _ALUQrr(X86_SUB, RS, RD)
|
||||
#define SUBQmr(MD, MB, MI, MS, RD) _ALUQmr(X86_SUB, MD, MB, MI, MS, RD)
|
||||
#define SUBQrm(RS, MD, MB, MI, MS) _ALUQrm(X86_SUB, RS, MD, MB, MI, MS)
|
||||
#define SUBQir(IM, RD) _ALUQir(X86_SUB, IM, RD)
|
||||
#define SUBQim(IM, MD, MB, MI, MS) _ALUQim(X86_SUB, IM, MD, MB, MI, MS)
|
||||
|
||||
#define XORQrr(RS, RD) _ALUQrr(X86_XOR, RS, RD)
|
||||
#define XORQmr(MD, MB, MI, MS, RD) _ALUQmr(X86_XOR, MD, MB, MI, MS, RD)
|
||||
#define XORQrm(RS, MD, MB, MI, MS) _ALUQrm(X86_XOR, RS, MD, MB, MI, MS)
|
||||
#define XORQir(IM, RD) _ALUQir(X86_XOR, IM, RD)
|
||||
#define XORQim(IM, MD, MB, MI, MS) _ALUQim(X86_XOR, IM, MD, MB, MI, MS)
|
||||
|
||||
#define ROLQir(IM, RD) _ROTSHIQir(X86_ROL, IM, RD)
|
||||
#define ROLQim(IM, MD, MB, MI, MS) _ROTSHIQim(X86_ROL, IM, MD, MB, MI, MS)
|
||||
#define ROLQrr(RS, RD) _ROTSHIQrr(X86_ROL, RS, RD)
|
||||
#define ROLQrm(RS, MD, MB, MI, MS) _ROTSHIQrm(X86_ROL, RS, MD, MB, MI, MS)
|
||||
|
||||
#define RORQir(IM, RD) _ROTSHIQir(X86_ROR, IM, RD)
|
||||
#define RORQim(IM, MD, MB, MI, MS) _ROTSHIQim(X86_ROR, IM, MD, MB, MI, MS)
|
||||
#define RORQrr(RS, RD) _ROTSHIQrr(X86_ROR, RS, RD)
|
||||
#define RORQrm(RS, MD, MB, MI, MS) _ROTSHIQrm(X86_ROR, RS, MD, MB, MI, MS)
|
||||
|
||||
#define RCLQir(IM, RD) _ROTSHIQir(X86_RCL, IM, RD)
|
||||
#define RCLQim(IM, MD, MB, MI, MS) _ROTSHIQim(X86_RCL, IM, MD, MB, MI, MS)
|
||||
#define RCLQrr(RS, RD) _ROTSHIQrr(X86_RCL, RS, RD)
|
||||
#define RCLQrm(RS, MD, MB, MI, MS) _ROTSHIQrm(X86_RCL, RS, MD, MB, MI, MS)
|
||||
|
||||
#define RCRQir(IM, RD) _ROTSHIQir(X86_RCR, IM, RD)
|
||||
#define RCRQim(IM, MD, MB, MI, MS) _ROTSHIQim(X86_RCR, IM, MD, MB, MI, MS)
|
||||
#define RCRQrr(RS, RD) _ROTSHIQrr(X86_RCR, RS, RD)
|
||||
#define RCRQrm(RS, MD, MB, MI, MS) _ROTSHIQrm(X86_RCR, RS, MD, MB, MI, MS)
|
||||
|
||||
#define SHLQir(IM, RD) _ROTSHIQir(X86_SHL, IM, RD)
|
||||
#define SHLQim(IM, MD, MB, MI, MS) _ROTSHIQim(X86_SHL, IM, MD, MB, MI, MS)
|
||||
#define SHLQrr(RS, RD) _ROTSHIQrr(X86_SHL, RS, RD)
|
||||
#define SHLQrm(RS, MD, MB, MI, MS) _ROTSHIQrm(X86_SHL, RS, MD, MB, MI, MS)
|
||||
|
||||
#define SHRQir(IM, RD) _ROTSHIQir(X86_SHR, IM, RD)
|
||||
#define SHRQim(IM, MD, MB, MI, MS) _ROTSHIQim(X86_SHR, IM, MD, MB, MI, MS)
|
||||
#define SHRQrr(RS, RD) _ROTSHIQrr(X86_SHR, RS, RD)
|
||||
#define SHRQrm(RS, MD, MB, MI, MS) _ROTSHIQrm(X86_SHR, RS, MD, MB, MI, MS)
|
||||
|
||||
#define SALQir SHLQir
|
||||
#define SALQim SHLQim
|
||||
#define SALQrr SHLQrr
|
||||
#define SALQrm SHLQrm
|
||||
|
||||
#define SARQir(IM, RD) _ROTSHIQir(X86_SAR, IM, RD)
|
||||
#define SARQim(IM, MD, MB, MI, MS) _ROTSHIQim(X86_SAR, IM, MD, MB, MI, MS)
|
||||
#define SARQrr(RS, RD) _ROTSHIQrr(X86_SAR, RS, RD)
|
||||
#define SARQrm(RS, MD, MB, MI, MS) _ROTSHIQrm(X86_SAR, RS, MD, MB, MI, MS)
|
||||
|
||||
#define BTQir(IM, RD) _BTQir(X86_BT, IM, RD)
|
||||
#define BTQim(IM, MD, MB, MI, MS) _BTQim(X86_BT, IM, MD, MB, MI, MS)
|
||||
#define BTQrr(RS, RD) _BTQrr(X86_BT, RS, RD)
|
||||
#define BTQrm(RS, MD, MB, MI, MS) _BTQrm(X86_BT, RS, MD, MB, MI, MS)
|
||||
|
||||
#define BTCQir(IM, RD) _BTQir(X86_BTC, IM, RD)
|
||||
#define BTCQim(IM, MD, MB, MI, MS) _BTQim(X86_BTC, IM, MD, MB, MI, MS)
|
||||
#define BTCQrr(RS, RD) _BTQrr(X86_BTC, RS, RD)
|
||||
#define BTCQrm(RS, MD, MB, MI, MS) _BTQrm(X86_BTC, RS, MD, MB, MI, MS)
|
||||
|
||||
#define BTRQir(IM, RD) _BTQir(X86_BTR, IM, RD)
|
||||
#define BTRQim(IM, MD, MB, MI, MS) _BTQim(X86_BTR, IM, MD, MB, MI, MS)
|
||||
#define BTRQrr(RS, RD) _BTQrr(X86_BTR, RS, RD)
|
||||
#define BTRQrm(RS, MD, MB, MI, MS) _BTQrm(X86_BTR, RS, MD, MB, MI, MS)
|
||||
|
||||
#define BTSQir(IM, RD) _BTQir(X86_BTS, IM, RD)
|
||||
#define BTSQim(IM, MD, MB, MI, MS) _BTQim(X86_BTS, IM, MD, MB, MI, MS)
|
||||
#define BTSQrr(RS, RD) _BTQrr(X86_BTS, RS, RD)
|
||||
#define BTSQrm(RS, MD, MB, MI, MS) _BTQrm(X86_BTS, RS, MD, MB, MI, MS)
|
||||
|
||||
#define LEAQmr(MD, MB, MI, MS, RD) (_REXQmr(MB, MI, RD), _O_r_X (0x8d ,_r8(RD) ,MD,MB,MI,MS ))
|
||||
|
||||
#define MOVQrr(RS, RD) (_REXQrr(RS, RD), _O_Mrm (0x89 ,_b11,_r8(RS),_r8(RD) ))
|
||||
#define MOVQmr(MD, MB, MI, MS, RD) (_REXQmr(MB, MI, RD), _O_r_X (0x8b ,_r8(RD) ,MD,MB,MI,MS ))
|
||||
#define MOVQrm(RS, MD, MB, MI, MS) (_REXQrm(RS, MB, MI), _O_r_X (0x89 ,_r8(RS) ,MD,MB,MI,MS ))
|
||||
#define MOVQir(IM, R) (_REXQrr(0, R), _Or_Q (0xb8,_r8(R) ,IM ))
|
||||
#define MOVQim(IM, MD, MB, MI, MS) (_REXQrm(0, MB, MI), _O_X_L (0xc7 ,MD,MB,MI,MS ,IM ))
|
||||
|
||||
#define NOTQr(RS) _UNARYQr(X86_NOT, RS)
|
||||
#define NOTQm(MD, MB, MI, MS) _UNARYQm(X86_NOT, MD, MB, MI, MS)
|
||||
|
||||
#define NEGQr(RS) _UNARYQr(X86_NEG, RS)
|
||||
#define NEGQm(MD, MB, MI, MS) _UNARYQm(X86_NEG, MD, MB, MI, MS)
|
||||
|
||||
#define MULQr(RS) _UNARYQr(X86_MUL, RS)
|
||||
#define MULQm(MD, MB, MI, MS) _UNARYQm(X86_MUL, MD, MB, MI, MS)
|
||||
|
||||
#define IMULQr(RS) _UNARYQr(X86_IMUL, RS)
|
||||
#define IMULQm(MD, MB, MI, MS) _UNARYQm(X86_IMUL, MD, MB, MI, MS)
|
||||
|
||||
#define DIVQr(RS) _UNARYQr(X86_DIV, RS)
|
||||
#define DIVQm(MD, MB, MI, MS) _UNARYQm(X86_DIV, MD, MB, MI, MS)
|
||||
|
||||
#define IDIVQr(RS) _UNARYQr(X86_IDIV, RS)
|
||||
#define IDIVQm(MD, MB, MI, MS) _UNARYQm(X86_IDIV, MD, MB, MI, MS)
|
||||
|
||||
#define IMULQir(IM, RD) IMULQirr(IM, RD, RD)
|
||||
#define IMULQrr(RS, RD) (_REXQrr(RD, RS), _OO_Mrm (0x0faf ,_b11,_r8(RD),_r8(RS) ))
|
||||
#define IMULQmr(MD, MB, MI, MS, RD) (_REXQmr(MB, MI, RD), _OO_r_X (0x0faf ,_r8(RD) ,MD,MB,MI,MS ))
|
||||
#define IMULQirr(IM,RS,RD) (_REXQrr(RD, RS), _Os_Mrm_sL (0x69 ,_b11,_r8(RS),_r8(RD) ,IM ))
|
||||
#define IMULQimr(IM,MD,MB,MI,MS,RD) (_REXQmr(MB, MI, RD), _Os_r_X_sL (0x69 ,_r8(RD) ,MD,MB,MI,MS ,IM ))
|
||||
|
||||
#define CALLQsr(R) (_REXQrr(0, R), _O_Mrm (0xff ,_b11,_b010,_r8(R) ))
|
||||
#define JMPQsr(R) (_REXQrr(0, R), _O_Mrm (0xff ,_b11,_b100,_r8(R) ))
|
||||
|
||||
#define CMOVQrr(CC,RS,RD) (_REXQrr(RD, RS), _OO_Mrm (0x0f40|(CC) ,_b11,_r8(RD),_r8(RS) ))
|
||||
#define CMOVQmr(CC,MD,MB,MI,MS,RD) (_REXQmr(MB, MI, RD), _OO_r_X (0x0f40|(CC) ,_r8(RD) ,MD,MB,MI,MS ))
|
||||
|
||||
#define POPQr(RD) _m64only((_REXQr(RD), _Or (0x58,_r8(RD) )))
|
||||
#define POPQm(MD, MB, MI, MS) _m64only((_REXQm(MB, MI), _O_r_X (0x8f ,_b000 ,MD,MB,MI,MS )))
|
||||
|
||||
#define PUSHQr(RS) _m64only((_REXQr(RS), _Or (0x50,_r8(RS) )))
|
||||
#define PUSHQm(MD, MB, MI, MS) _m64only((_REXQm(MB, MI), _O_r_X (0xff ,_b110 ,MD,MB,MI,MS )))
|
||||
#define PUSHQi(IM) _m64only( _Os_sL (0x68 ,IM ))
|
||||
|
||||
#define TESTQrr(RS, RD) (_REXQrr(RS, RD), _O_Mrm (0x85 ,_b11,_r8(RS),_r8(RD) ))
|
||||
#define TESTQrm(RS, MD, MB, MI, MS) (_REXQrm(RS, MB, MI), _O_r_X (0x85 ,_r8(RS) ,MD,MB,MI,MS ))
|
||||
#define TESTQir(IM, RD) \
|
||||
/* Immediate fits in 32 bits? */ \
|
||||
(_s32P((long)(IM)) \
|
||||
/* Yes. Immediate does not fit in 8 bits and reg is %rax? */ \
|
||||
? (!_s8P(IM) && (RD) == _RAX \
|
||||
? (_REXQrr(0, RD), _O_L(0xa9, IM)) \
|
||||
: (_REXQrr(0, RD), _O_Mrm_L(0xf7, _b11, _b000, _r8(RD), IM))) \
|
||||
/* No. Need immediate in a register */ \
|
||||
: (MOVQir(IM, JIT_REXTMP), TESTQrr(JIT_REXTMP, RD)))
|
||||
#define TESTQim(IM, MD, MB, MI, MS) (_REXQrm(0, MB, MI), _O_r_X_L (0xf7 ,_b000 ,MD,MB,MI,MS ,IM ))
|
||||
|
||||
#define CMPXCHGQrr(RS, RD) (_REXQrr(RS, RD), _OO_Mrm (0x0fb1 ,_b11,_r8(RS),_r8(RD) ))
|
||||
#define CMPXCHGQrm(RS, MD, MB, MI, MS) (_REXQrm(RS, MB, MI), _OO_r_X (0x0fb1 ,_r8(RS) ,MD,MB,MI,MS ))
|
||||
|
||||
#define XADDQrr(RS, RD) (_REXQrr(RS, RD), _OO_Mrm (0x0fc1 ,_b11,_r8(RS),_r8(RD) ))
|
||||
#define XADDQrm(RS, MD, MB, MI, MS) (_REXQrm(RS, MB, MI), _OO_r_X (0x0fc1 ,_r8(RS) ,MD,MB,MI,MS ))
|
||||
|
||||
#define XCHGQrr(RS, RD) (_REXQrr(RS, RD), _O_Mrm (0x87 ,_b11,_r8(RS),_r8(RD) ))
|
||||
#define XCHGQrm(RS, MD, MB, MI, MS) (_REXQrm(RS, MB, MI), _O_r_X (0x87 ,_r8(RS) ,MD,MB,MI,MS ))
|
||||
|
||||
#define DECQm(MD, MB, MI, MS) (_REXQrm(0, MB, MI), _O_r_X (0xff ,_b001 ,MD,MB,MI,MS ))
|
||||
#define DECQr(RD) (_REXQrr(0, RD), _O_Mrm (0xff ,_b11,_b001 ,_r8(RD) ))
|
||||
#define INCQm(MD, MB, MI, MS) (_REXQrm(0, MB, MI), _O_r_X (0xff ,_b000 ,MD,MB,MI,MS ))
|
||||
#define INCQr(RD) (_REXQrr(0, RD), _O_Mrm (0xff ,_b11,_b000 ,_r8(RD) ))
|
||||
|
||||
#define BSFQrr(RS, RD) (_REXQrr(RD, RS), _OO_Mrm (0x0fbc ,_b11,_r8(RD),_r8(RS) ))
|
||||
#define BSFQmr(MD, MB, MI, MS, RD) (_REXQmr(MB, MI, RD), _OO_r_X (0x0fbc ,_r8(RD) ,MD,MB,MI,MS ))
|
||||
|
||||
#define BSRQrr(RS, RD) (_REXQrr(RD, RS), _OO_Mrm (0x0fbd ,_b11,_r8(RD),_r8(RS) ))
|
||||
#define BSRQmr(MD, MB, MI, MS, RD) (_REXQmr(MB, MI, RD), _OO_r_X (0x0fbd ,_r8(RD) ,MD,MB,MI,MS ))
|
||||
|
||||
#define MOVSBQrr(RS, RD) (_REXQrr(RD, RS), _OO_Mrm (0x0fbe ,_b11,_r8(RD),_r1(RS) ))
|
||||
#define MOVSBQmr(MD, MB, MI, MS, RD) (_REXQmr(MB, MI, RD), _OO_r_X (0x0fbe ,_r8(RD) ,MD,MB,MI,MS ))
|
||||
|
||||
#define MOVZBQrr(RS, RD) (_REXQrr(RD, RS), _OO_Mrm (0x0fb6 ,_b11,_r8(RD),_r1(RS) ))
|
||||
#define MOVZBQmr(MD, MB, MI, MS, RD) (_REXQmr(MB, MI, RD), _OO_r_X (0x0fb6 ,_r8(RD) ,MD,MB,MI,MS ))
|
||||
|
||||
#define MOVSWQrr(RS, RD) (_REXQrr(RD, RS), _OO_Mrm (0x0fbf ,_b11,_r8(RD),_r2(RS) ))
|
||||
#define MOVSWQmr(MD, MB, MI, MS, RD) (_REXQmr(MB, MI, RD), _OO_r_X (0x0fbf ,_r8(RD) ,MD,MB,MI,MS ))
|
||||
|
||||
#define MOVZWQrr(RS, RD) (_REXQrr(RD, RS), _OO_Mrm (0x0fb7 ,_b11,_r8(RD),_r2(RS) ))
|
||||
#define MOVZWQmr(MD, MB, MI, MS, RD) (_REXQmr(MB, MI, RD), _OO_r_X (0x0fb7 ,_r8(RD) ,MD,MB,MI,MS ))
|
||||
|
||||
#define MOVSLQrr(RS, RD) _m64only((_REXQrr(RD, RS), _O_Mrm (0x63 ,_b11,_r8(RD),_r4(RS) )))
|
||||
#define MOVSLQmr(MD, MB, MI, MS, RD) _m64only((_REXQmr(MB, MI, RD), _O_r_X (0x63 ,_r8(RD) ,MD,MB,MI,MS )))
|
||||
|
||||
#define BSWAPQr(R) (_REXQrr(0, R), _OOr (0x0fc8,_r8(R) ))
|
||||
|
||||
|
||||
|
||||
#define __SSEQrr(OP,RS,RSA,RD,RDA) (_REXQrr(RD, RS), _OO_Mrm (0x0f00|(OP) ,_b11,RDA(RD),RSA(RS) ))
|
||||
#define __SSEQmr(OP,MD,MB,MI,MS,RD,RDA) (_REXQmr(MB, MI, RD), _OO_r_X (0x0f00|(OP) ,RDA(RD) ,MD,MB,MI,MS ))
|
||||
#define __SSEQrm(OP,RS,RSA,MD,MB,MI,MS) (_REXQrm(RS, MB, MI), _OO_r_X (0x0f00|(OP) ,RSA(RS) ,MD,MB,MI,MS ))
|
||||
#define __SSEQ1rm(OP,RS,RSA,MD,MB,MI,MS) (_REXQrm(RS, MB, MI), _OO_r_X (0x0f01|(OP) ,RSA(RS) ,MD,MB,MI,MS ))
|
||||
|
||||
#define _SSEQrr(PX,OP,RS,RSA,RD,RDA) (_jit_B(PX), __SSEQrr(OP, RS, RSA, RD, RDA))
|
||||
#define _SSEQmr(PX,OP,MD,MB,MI,MS,RD,RDA) (_jit_B(PX), __SSEQmr(OP, MD, MB, MI, MS, RD, RDA))
|
||||
#define _SSEQrm(PX,OP,RS,RSA,MD,MB,MI,MS) (_jit_B(PX), __SSEQrm(OP, RS, RSA, MD, MB, MI, MS))
|
||||
#define _SSEQ1rm(PX,OP,RS,RSA,MD,MB,MI,MS) (_jit_B(PX), __SSEQ1rm(OP, RS, RSA, MD, MB, MI, MS))
|
||||
|
||||
#define CVTTSS2SIQrr(RS, RD) _SSEQrr(0xf3, X86_SSE_CVTTSI, RS,_rX, RD,_r8)
|
||||
#define CVTTSS2SIQmr(MD, MB, MI, MS, RD) _SSEQmr(0xf3, X86_SSE_CVTTSI, MD, MB, MI, MS, RD,_r8)
|
||||
#define CVTTSD2SIQrr(RS, RD) _SSEQrr(0xf2, X86_SSE_CVTTSI, RS,_rX, RD,_r8)
|
||||
#define CVTTSD2SIQmr(MD, MB, MI, MS, RD) _SSEQmr(0xf2, X86_SSE_CVTTSI, MD, MB, MI, MS, RD,_r8)
|
||||
|
||||
#define CVTSS2SIQrr(RS, RD) _SSEQrr(0xf3, X86_SSE_CVTSI, RS,_rX, RD,_r8)
|
||||
#define CVTSS2SIQmr(MD, MB, MI, MS, RD) _SSEQmr(0xf3, X86_SSE_CVTSI, MD, MB, MI, MS, RD,_r8)
|
||||
#define CVTSD2SIQrr(RS, RD) _SSEQrr(0xf2, X86_SSE_CVTSI, RS,_rX, RD,_r8)
|
||||
#define CVTSD2SIQmr(MD, MB, MI, MS, RD) _SSEQmr(0xf2, X86_SSE_CVTSI, MD, MB, MI, MS, RD,_r8)
|
||||
|
||||
#define CVTSI2SSQrr(RS, RD) _SSEQrr(0xf3, X86_SSE_CVTIS, RS,_r8, RD,_rX)
|
||||
#define CVTSI2SSQmr(MD, MB, MI, MS, RD) _SSEQmr(0xf3, X86_SSE_CVTIS, MD, MB, MI, MS, RD,_rX)
|
||||
#define CVTSI2SDQrr(RS, RD) _SSEQrr(0xf2, X86_SSE_CVTIS, RS,_r8, RD,_rX)
|
||||
#define CVTSI2SDQmr(MD, MB, MI, MS, RD) _SSEQmr(0xf2, X86_SSE_CVTIS, MD, MB, MI, MS, RD,_rX)
|
||||
|
||||
#define MOVDQXrr(RS, RD) _SSEQrr(0x66, 0x6e, RS,_r8, RD,_rX)
|
||||
#define MOVDQXmr(MD, MB, MI, MS, RD) _SSEQmr(0x66, 0x6e, MD, MB, MI, MS, RD,_rX)
|
||||
|
||||
#define MOVDXQrr(RS, RD) _SSEQrr(0x66, 0x7e, RS,_rX, RD,_r8)
|
||||
#define MOVDXQrm(RS, MD, MB, MI, MS) _SSEQrm(0x66, 0x7e, RS,_rX, MD, MB, MI, MS)
|
||||
#define MOVDQMrr(RS, RD) __SSEQrr( 0x6e, RS,_r8, RD,_rM)
|
||||
#define MOVDQMmr(MD, MB, MI, MS, RD) __SSEQmr( 0x6e, MD, MB, MI, MS, RD,_rM)
|
||||
#define MOVDMQrr(RS, RD) __SSEQrr( 0x7e, RS,_rM, RD,_r8)
|
||||
#define MOVDMQrm(RS, MD, MB, MI, MS) __SSEQrm( 0x7e, RS,_rM, MD, MB, MI, MS)
|
||||
|
||||
|
||||
|
||||
#define CALLsr(R) CALLQsr(R)
|
||||
#define JMPsr(R) JMPQsr(R)
|
||||
|
||||
#endif
|
||||
#endif /* __lightning_asm_h */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,177 +0,0 @@
|
||||
/******************************** -*- C -*- ****************************
|
||||
*
|
||||
* Platform-independent layer (i386 version)
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Copyright 2000, 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
|
||||
* Written by Paolo Bonzini and Matthew Flatt.
|
||||
*
|
||||
* This file is part of GNU lightning.
|
||||
*
|
||||
* GNU lightning is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU lightning is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with GNU lightning; see the file COPYING.LESSER; if not, write to the
|
||||
* Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef __lightning_core_h
|
||||
#define __lightning_core_h
|
||||
|
||||
#define JIT_CAN_16 1
|
||||
#define JIT_AP _EBP
|
||||
|
||||
#define JIT_R_NUM 3
|
||||
#define JIT_R(i) (_EAX + (i))
|
||||
#define JIT_V_NUM 3
|
||||
#define JIT_V(i) ((i) == 0 ? _EBX : _ESI + (i) - 1)
|
||||
|
||||
struct jit_local_state {
|
||||
int framesize;
|
||||
int argssize;
|
||||
int alloca_offset;
|
||||
int alloca_slack;
|
||||
jit_insn *finish_ref;
|
||||
};
|
||||
|
||||
/* Whether a register is used for the user-accessible registers. */
|
||||
#define jit_save(reg) 1
|
||||
|
||||
#define jit_base_prolog() (_jitl.framesize = 20, _jitl.alloca_offset = _jitl.alloca_slack = 0, _jitl.argssize = 0, \
|
||||
PUSHLr(_EBX), PUSHLr(_ESI), PUSHLr(_EDI), PUSHLr(_EBP), MOVLrr(_ESP, _EBP))
|
||||
#define jit_base_ret(ofs) \
|
||||
(((ofs) < 0 ? LEAVE_() : POPLr(_EBP)), \
|
||||
POPLr(_EDI), POPLr(_ESI), POPLr(_EBX), RET_())
|
||||
|
||||
/* Used internally. SLACK is used by the Darwin ABI which keeps the stack
|
||||
aligned to 16-bytes. */
|
||||
|
||||
#define jit_allocai_internal(amount, slack) \
|
||||
(((amount) < _jitl.alloca_slack \
|
||||
? (void)0 \
|
||||
: (void)(_jitl.alloca_slack += (amount) + (slack), \
|
||||
((amount) + (slack) == sizeof (int) \
|
||||
? PUSHLr(_EAX) \
|
||||
: SUBLir((amount) + (slack), _ESP)))), \
|
||||
_jitl.alloca_slack -= (amount), \
|
||||
_jitl.alloca_offset -= (amount))
|
||||
|
||||
/* Stack */
|
||||
#define jit_pushr_i(rs) PUSHLr(rs)
|
||||
#define jit_popr_i(rs) POPLr(rs)
|
||||
|
||||
/* The += in argssize allows for stack pollution */
|
||||
|
||||
#ifdef __APPLE__
|
||||
/* Stack must stay 16-byte aligned: */
|
||||
# define jit_prepare_i(ni) (((ni & 0x3) \
|
||||
? (void)SUBLir(4 * ((((ni) + 3) & ~(0x3)) - (ni)), JIT_SP) \
|
||||
: (void)0), \
|
||||
_jitl.argssize += (((ni) + 3) & ~(0x3)))
|
||||
|
||||
#define jit_allocai(n) \
|
||||
jit_allocai_internal ((n), (_jitl.alloca_slack - (n)) & 15)
|
||||
|
||||
#define jit_prolog(n) (jit_base_prolog(), jit_subi_i (JIT_SP, JIT_SP, 12))
|
||||
#define jit_ret() jit_base_ret (-12)
|
||||
|
||||
#else
|
||||
# define jit_prepare_i(ni) (_jitl.argssize += (ni))
|
||||
|
||||
#define jit_allocai(n) \
|
||||
jit_allocai_internal ((n), 0)
|
||||
|
||||
#define jit_prolog(n) jit_base_prolog()
|
||||
#define jit_ret() jit_base_ret (_jitl.alloca_offset)
|
||||
#endif
|
||||
|
||||
#define jit_bare_ret() RET_()
|
||||
|
||||
#define jit_calli(label) (CALLm( ((unsigned long) (label))), _jit.x.pc)
|
||||
#define jit_callr(reg) CALLsr(reg)
|
||||
|
||||
#define jit_pusharg_i(rs) PUSHLr(rs)
|
||||
#define jit_finish(sub) (_jitl.finish_ref = jit_calli((sub)), ADDLir(sizeof(long) * _jitl.argssize, JIT_SP), _jitl.argssize = 0, _jitl.finish_ref)
|
||||
#define jit_finishr(reg) (jit_callr((reg)), ADDLir(sizeof(long) * _jitl.argssize, JIT_SP), _jitl.argssize = 0)
|
||||
|
||||
#define jit_arg_c() ((_jitl.framesize += sizeof(int)) - sizeof(int))
|
||||
#define jit_arg_uc() ((_jitl.framesize += sizeof(int)) - sizeof(int))
|
||||
#define jit_arg_s() ((_jitl.framesize += sizeof(int)) - sizeof(int))
|
||||
#define jit_arg_us() ((_jitl.framesize += sizeof(int)) - sizeof(int))
|
||||
#define jit_arg_i() ((_jitl.framesize += sizeof(int)) - sizeof(int))
|
||||
#define jit_arg_ui() ((_jitl.framesize += sizeof(int)) - sizeof(int))
|
||||
#define jit_arg_l() ((_jitl.framesize += sizeof(long)) - sizeof(long))
|
||||
#define jit_arg_ul() ((_jitl.framesize += sizeof(long)) - sizeof(long))
|
||||
#define jit_arg_p() ((_jitl.framesize += sizeof(long)) - sizeof(long))
|
||||
|
||||
#define jit_movi_p(d, is) (MOVLir (((long)(is)), (d)), _jit.x.pc)
|
||||
#define jit_patch_long_at(jump_pc,v) (*_PSL((jump_pc) - sizeof(long)) = _jit_SL((jit_insn *)(v) - (jump_pc)))
|
||||
#define jit_patch_at(jump_pc,v) jit_patch_long_at(jump_pc, v)
|
||||
#define jit_patch_calli(jump_pc,v) jit_patch_long_at(jump_pc, v)
|
||||
|
||||
/* Memory */
|
||||
#define jit_replace(s, rep, op) \
|
||||
(jit_pushr_i(rep), \
|
||||
MOVLrr((s), (rep)), \
|
||||
op, jit_popr_i(rep))
|
||||
|
||||
#define jit_movbrm(rs, dd, db, di, ds) \
|
||||
(jit_check8(rs) \
|
||||
? MOVBrm(jit_reg8(rs), dd, db, di, ds) \
|
||||
: jit_replace(rs, \
|
||||
((dd != _EAX && db != _EAX && di != _EAX) ? _EAX : \
|
||||
((dd != _ECX && db != _ECX && di != _ECX) ? _ECX : _EDX)), \
|
||||
MOVBrm(((dd != _EAX && db != _EAX && di != _EAX) ? _AL : \
|
||||
((dd != _ECX && db != _ECX && di != _ECX) ? _CL : _DL)), \
|
||||
dd, db, di, ds)))
|
||||
|
||||
#define jit_ldr_c(d, rs) MOVSBLmr(0, (rs), 0, 0, (d))
|
||||
#define jit_ldxr_c(d, s1, s2) MOVSBLmr(0, (s1), (s2), 1, (d))
|
||||
|
||||
#define jit_ldr_s(d, rs) MOVSWLmr(0, (rs), 0, 0, (d))
|
||||
#define jit_ldxr_s(d, s1, s2) MOVSWLmr(0, (s1), (s2), 1, (d))
|
||||
|
||||
#define jit_ldi_c(d, is) MOVSBLmr((is), 0, 0, 0, (d))
|
||||
#define jit_ldxi_c(d, rs, is) MOVSBLmr((is), (rs), 0, 0, (d))
|
||||
|
||||
#define jit_ldi_uc(d, is) MOVZBLmr((is), 0, 0, 0, (d))
|
||||
#define jit_ldxi_uc(d, rs, is) MOVZBLmr((is), (rs), 0, 0, (d))
|
||||
|
||||
#define jit_sti_c(id, rs) jit_movbrm((rs), (id), 0, 0, 0)
|
||||
#define jit_stxi_c(id, rd, rs) jit_movbrm((rs), (id), (rd), 0, 0)
|
||||
|
||||
#define jit_ldi_s(d, is) MOVSWLmr((is), 0, 0, 0, (d))
|
||||
#define jit_ldxi_s(d, rs, is) MOVSWLmr((is), (rs), 0, 0, (d))
|
||||
|
||||
#define jit_ldi_us(d, is) MOVZWLmr((is), 0, 0, 0, (d))
|
||||
#define jit_ldxi_us(d, rs, is) MOVZWLmr((is), (rs), 0, 0, (d))
|
||||
|
||||
#define jit_sti_s(id, rs) MOVWrm(jit_reg16(rs), (id), 0, 0, 0)
|
||||
#define jit_stxi_s(id, rd, rs) MOVWrm(jit_reg16(rs), (id), (rd), 0, 0)
|
||||
|
||||
#define jit_ldi_i(d, is) MOVLmr((is), 0, 0, 0, (d))
|
||||
#define jit_ldxi_i(d, rs, is) MOVLmr((is), (rs), 0, 0, (d))
|
||||
|
||||
#define jit_ldr_i(d, rs) MOVLmr(0, (rs), 0, 0, (d))
|
||||
#define jit_ldxr_i(d, s1, s2) MOVLmr(0, (s1), (s2), 1, (d))
|
||||
|
||||
#define jit_sti_i(id, rs) MOVLrm((rs), (id), 0, 0, 0)
|
||||
#define jit_stxi_i(id, rd, rs) MOVLrm((rs), (id), (rd), 0, 0)
|
||||
|
||||
#endif /* __lightning_core_h */
|
||||
@@ -1,499 +0,0 @@
|
||||
/******************************** -*- C -*- ****************************
|
||||
*
|
||||
* Platform-independent layer (i386 version)
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Copyright 2000, 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
|
||||
* Written by Paolo Bonzini and Matthew Flatt.
|
||||
*
|
||||
* This file is part of GNU lightning.
|
||||
*
|
||||
* GNU lightning is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU lightning is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with GNU lightning; see the file COPYING.LESSER; if not, write to the
|
||||
* Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef __lightning_core_h
|
||||
#define __lightning_core_h
|
||||
|
||||
/* Used to implement ldc, stc, ... */
|
||||
#define JIT_CAN_16 0
|
||||
#define JIT_REXTMP _R12
|
||||
|
||||
/* Number or integer argument registers */
|
||||
#define JIT_ARG_MAX 6
|
||||
|
||||
/* Number of float argument registers */
|
||||
#define JIT_FP_ARG_MAX 8
|
||||
|
||||
#define JIT_R_NUM 3
|
||||
#define JIT_R(i) ((i) == 0 ? _EAX : _R9 + (i))
|
||||
#define JIT_V_NUM 3
|
||||
#define JIT_V(i) ((i) == 0 ? _EBX : _R12 + (i))
|
||||
|
||||
struct jit_local_state {
|
||||
int long_jumps;
|
||||
int nextarg_getfp;
|
||||
int nextarg_putfp;
|
||||
int nextarg_geti;
|
||||
int nextarg_puti;
|
||||
int framesize;
|
||||
int argssize;
|
||||
int fprssize;
|
||||
int alloca_offset;
|
||||
int alloca_slack;
|
||||
jit_insn *finish_ref;
|
||||
};
|
||||
|
||||
/* Whether a register in the "low" bank is used for the user-accessible
|
||||
registers. */
|
||||
#define jit_save(reg) ((reg) == _EAX || (reg) == _EBX)
|
||||
|
||||
/* Keep the stack 16-byte aligned, the SSE hardware prefers it this way. */
|
||||
#define jit_allocai_internal(amount, slack) \
|
||||
(((amount) < _jitl.alloca_slack \
|
||||
? 0 \
|
||||
: (_jitl.alloca_slack += (amount) + (slack), \
|
||||
SUBQir((amount) + (slack), _ESP))), \
|
||||
_jitl.alloca_slack -= (amount), \
|
||||
_jitl.alloca_offset -= (amount))
|
||||
|
||||
#define jit_allocai(n) \
|
||||
jit_allocai_internal ((n), (_jitl.alloca_slack - (n)) & 15)
|
||||
|
||||
/* 3-parameter operation */
|
||||
#define jit_qopr_(d, s1, s2, op1d, op2d) \
|
||||
( ((s2) == (d)) ? op1d : \
|
||||
( (((s1) == (d)) ? (void)0 : (void)MOVQrr((s1), (d))), op2d ) \
|
||||
)
|
||||
|
||||
/* 3-parameter operation, with immediate. TODO: fix the case where mmediate
|
||||
does not fit! */
|
||||
#define jit_qop_small(d, s1, op2d) \
|
||||
(((s1) == (d)) ? op2d : (MOVQrr((s1), (d)), op2d))
|
||||
#define jit_qop_(d, s1, is, op2d, op2i) \
|
||||
(_s32P((long)(is)) \
|
||||
? jit_qop_small ((d), (s1), (op2d)) \
|
||||
: (MOVQir ((is), JIT_REXTMP), jit_qop_small ((d), (s1), (op2i))))
|
||||
|
||||
#define jit_bra_qr(s1, s2, op) (CMPQrr(s2, s1), op, _jit.x.pc)
|
||||
#define _jit_bra_l(rs, is, op) (CMPQir(is, rs), op, _jit.x.pc)
|
||||
|
||||
#define jit_bra_l(rs, is, op) (_s32P((long)(is)) \
|
||||
? _jit_bra_l(rs, is, op) \
|
||||
: (MOVQir(is, JIT_REXTMP), jit_bra_qr(rs, JIT_REXTMP, op)))
|
||||
|
||||
/* When CMP with 0 can be replaced with TEST */
|
||||
#define jit_bra_l0(rs, is, op, op0) \
|
||||
( (is) == 0 ? (TESTQrr(rs, rs), op0, _jit.x.pc) : jit_bra_l(rs, is, op))
|
||||
|
||||
#define jit_reduceQ(op, is, rs) \
|
||||
(_u8P(is) ? jit_reduce_(op##Bir(is, jit_reg8(rs))) : \
|
||||
jit_reduce_(op##Qir(is, rs)) )
|
||||
|
||||
#define jit_addi_l(d, rs, is) \
|
||||
/* Value is not zero? */ \
|
||||
((is) \
|
||||
/* Yes. Value is unsigned and fits in signed 32 bits? */ \
|
||||
? (_uiP(31, is) \
|
||||
/* Yes. d == rs? */ \
|
||||
? jit_opi_((d), (rs), \
|
||||
/* Yes. Use add opcode */ \
|
||||
ADDQir((is), (d)), \
|
||||
/* No. Use lea opcode */ \
|
||||
LEAQmr((is), (rs), 0, 0, (d))) \
|
||||
/* No. Need value in a register */ \
|
||||
: (jit_movi_l(JIT_REXTMP, is), \
|
||||
jit_addr_l(d, rs, JIT_REXTMP))) \
|
||||
: jit_opi_((d),(rs),0,jit_movr_l(d, rs)))
|
||||
#define jit_addr_l(d, s1, s2) jit_opo_((d), (s1), (s2), ADDQrr((s2), (d)), ADDQrr((s1), (d)), LEAQmr(0, (s1), (s2), 1, (d)) )
|
||||
#define jit_addci_l(d, rs, is) jit_qop_ ((d), (rs), (is), ADCQir((is), (d)), ADCQrr(JIT_REXTMP, (d)))
|
||||
#define jit_addcr_l(d, s1, s2) jit_qopr_((d), (s1), (s2), ADCQrr((s1), (d)), ADCQrr((s2), (d)) )
|
||||
#define jit_addxi_l(d, rs, is) jit_qop_ ((d), (rs), (is), ADDQir((is), (d)), ADDQrr(JIT_REXTMP, (d)))
|
||||
#define jit_addxr_l(d, s1, s2) jit_qopr_((d), (s1), (s2), ADDQrr((s1), (d)), ADDQrr((s2), (d)) )
|
||||
#define jit_andi_l(d, rs, is) jit_qop_ ((d), (rs), (is), ANDQir((is), (d)), ANDQrr(JIT_REXTMP, (d)))
|
||||
#define jit_andr_l(d, s1, s2) jit_qopr_((d), (s1), (s2), ANDQrr((s1), (d)), ANDQrr((s2), (d)) )
|
||||
#define jit_orr_l(d, s1, s2) jit_qopr_((d), (s1), (s2), ORQrr((s1), (d)), ORQrr((s2), (d)) )
|
||||
#define jit_subr_l(d, s1, s2) jit_qopr_((d), (s1), (s2), (SUBQrr((s1), (d)), NEGQr(d)), SUBQrr((s2), (d)) )
|
||||
#define jit_xorr_l(d, s1, s2) jit_qopr_((d), (s1), (s2), XORQrr((s1), (d)), XORQrr((s2), (d)) )
|
||||
|
||||
/* These can sometimes use byte or word versions! */
|
||||
#define jit_ori_l(d, rs, is) jit_qop_ ((d), (rs), (is), jit_reduceQ(OR, (is), (d)), ORQrr(JIT_REXTMP, (d)) )
|
||||
#define jit_xori_l(d, rs, is) jit_qop_ ((d), (rs), (is), jit_reduceQ(XOR, (is), (d)), XORQrr(JIT_REXTMP, (d)) )
|
||||
|
||||
#define jit_lshi_l(d, rs, is) ((is) <= 3 ? LEAQmr(0, 0, (rs), 1 << (is), (d)) : jit_qop_small ((d), (rs), SHLQir((is), (d)) ))
|
||||
#define jit_rshi_l(d, rs, is) jit_qop_small ((d), (rs), SARQir((is), (d)) )
|
||||
#define jit_rshi_ul(d, rs, is) jit_qop_small ((d), (rs), SHRQir((is), (d)) )
|
||||
#define jit_lshr_l(d, r1, r2) jit_shift((d), (r1), (r2), SHLQrr)
|
||||
#define jit_rshr_l(d, r1, r2) jit_shift((d), (r1), (r2), SARQrr)
|
||||
#define jit_rshr_ul(d, r1, r2) jit_shift((d), (r1), (r2), SHRQrr)
|
||||
|
||||
|
||||
/* Stack */
|
||||
#define jit_pushr_i(rs) PUSHQr(rs)
|
||||
#define jit_popr_i(rs) POPQr(rs)
|
||||
|
||||
/* A return address is 8 bytes, plus 5 registers = 40 bytes, total = 48 bytes. */
|
||||
#define jit_prolog(n) (_jitl.framesize = ((n) & 1) ? 56 : 48, _jitl.nextarg_getfp = _jitl.nextarg_geti = 0, _jitl.alloca_offset = 0, \
|
||||
PUSHQr(_EBX), PUSHQr(_R12), PUSHQr(_R13), PUSHQr(_R14), PUSHQr(_EBP), MOVQrr(_ESP, _EBP))
|
||||
|
||||
#define jit_calli(sub) (MOVQir((long) (sub), JIT_REXTMP), _jitl.finish_ref = _jit.x.pc, CALLsr(JIT_REXTMP), _jitl.finish_ref)
|
||||
#define jit_callr(reg) CALLsr((reg))
|
||||
|
||||
#define jit_prepare_i(ni) (_jitl.nextarg_puti = (ni), \
|
||||
_jitl.argssize = _jitl.nextarg_puti > JIT_ARG_MAX \
|
||||
? _jitl.nextarg_puti - JIT_ARG_MAX : 0)
|
||||
#define jit_pusharg_i(rs) (--_jitl.nextarg_puti >= JIT_ARG_MAX \
|
||||
? PUSHQr(rs) : MOVQrr(rs, jit_arg_reg_order[_jitl.nextarg_puti]))
|
||||
|
||||
#define jit_finish(sub) (_jitl.fprssize \
|
||||
? (MOVBir(_jitl.fprssize, _AL), _jitl.fprssize = 0) \
|
||||
: MOVBir(0, _AL), \
|
||||
((_jitl.argssize & 1) \
|
||||
? (PUSHQr(_EAX), ++_jitl.argssize) : 0), \
|
||||
jit_calli(sub), \
|
||||
(_jitl.argssize \
|
||||
? (ADDQir(sizeof(long) * _jitl.argssize, JIT_SP), _jitl.argssize = 0) \
|
||||
: 0), \
|
||||
_jitl.finish_ref)
|
||||
#define jit_reg_is_arg(reg) ((reg) == _ECX || (reg) == _EDX)
|
||||
|
||||
#define jit_finishr(reg) (_jitl.fprssize \
|
||||
? (MOVBir(_jitl.fprssize, _AL), _jitl.fprssize = 0) \
|
||||
: MOVBir(0, _AL), \
|
||||
((_jitl.argssize & 1) \
|
||||
? (PUSHQr(_EAX), ++_jitl.argssize) : 0), \
|
||||
(jit_reg_is_arg((reg)) \
|
||||
? (MOVQrr(reg, JIT_REXTMP), \
|
||||
jit_callr(JIT_REXTMP)) \
|
||||
: jit_callr(reg)), \
|
||||
(_jitl.argssize \
|
||||
? (ADDQir(sizeof(long) * _jitl.argssize, JIT_SP), _jitl.argssize = 0) \
|
||||
: 0))
|
||||
|
||||
#define jit_retval_l(rd) ((void)jit_movr_l ((rd), _EAX))
|
||||
#define jit_arg_i() (_jitl.nextarg_geti < JIT_ARG_MAX \
|
||||
? _jitl.nextarg_geti++ \
|
||||
: (int) ((_jitl.framesize += sizeof(long)) - sizeof(long)))
|
||||
#define jit_arg_c() jit_arg_i()
|
||||
#define jit_arg_uc() jit_arg_i()
|
||||
#define jit_arg_s() jit_arg_i()
|
||||
#define jit_arg_us() jit_arg_i()
|
||||
#define jit_arg_ui() jit_arg_i()
|
||||
#define jit_arg_l() jit_arg_i()
|
||||
#define jit_arg_ul() jit_arg_i()
|
||||
#define jit_arg_p() jit_arg_i()
|
||||
|
||||
#define jit_getarg_c(reg, ofs) ((ofs) < JIT_ARG_MAX \
|
||||
? jit_extr_c_l((reg), jit_arg_reg_order[(ofs)]) \
|
||||
: jit_ldxi_c((reg), JIT_FP, (ofs)))
|
||||
#define jit_getarg_uc(reg, ofs) ((ofs) < JIT_ARG_MAX \
|
||||
? jit_extr_uc_ul((reg), jit_arg_reg_order[(ofs)]) \
|
||||
: jit_ldxi_uc((reg), JIT_FP, (ofs)))
|
||||
#define jit_getarg_s(reg, ofs) ((ofs) < JIT_ARG_MAX \
|
||||
? jit_extr_s_l((reg), jit_arg_reg_order[(ofs)]) \
|
||||
: jit_ldxi_s((reg), JIT_FP, (ofs)))
|
||||
#define jit_getarg_us(reg, ofs) ((ofs) < JIT_ARG_MAX \
|
||||
? jit_extr_us_ul((reg), jit_arg_reg_order[(ofs)]) \
|
||||
: jit_ldxi_us((reg), JIT_FP, (ofs)))
|
||||
#define jit_getarg_i(reg, ofs) ((ofs) < JIT_ARG_MAX \
|
||||
? jit_movr_l((reg), jit_arg_reg_order[(ofs)]) \
|
||||
: jit_ldxi_i((reg), JIT_FP, (ofs)))
|
||||
#define jit_getarg_ui(reg, ofs) ((ofs) < JIT_ARG_MAX \
|
||||
? jit_movr_ul((reg), jit_arg_reg_order[(ofs)]) \
|
||||
: jit_ldxi_ui((reg), JIT_FP, (ofs)))
|
||||
#define jit_getarg_l(reg, ofs) ((ofs) < JIT_ARG_MAX \
|
||||
? jit_movr_l((reg), jit_arg_reg_order[(ofs)]) \
|
||||
: jit_ldxi_l((reg), JIT_FP, (ofs)))
|
||||
#define jit_getarg_ul(reg, ofs) ((ofs) < JIT_ARG_MAX \
|
||||
? jit_movr_ul((reg), jit_arg_reg_order[(ofs)]) \
|
||||
: jit_ldxi_ul((reg), JIT_FP, ofs))
|
||||
#define jit_getarg_p(reg, ofs) ((ofs) < JIT_ARG_MAX \
|
||||
? jit_movr_p((reg), jit_arg_reg_order[(ofs)]) \
|
||||
: jit_ldxi_p((reg), JIT_FP, (ofs)))
|
||||
|
||||
static int jit_arg_reg_order[] = { _EDI, _ESI, _EDX, _ECX, _R8D, _R9D };
|
||||
|
||||
#define jit_negr_l(d, rs) jit_opi_((d), (rs), NEGQr(d), (XORQrr((d), (d)), SUBQrr((rs), (d))) )
|
||||
#define jit_movr_l(d, rs) ((void)((rs) == (d) ? 0 : MOVQrr((rs), (d))))
|
||||
#define jit_movi_p(d, is) (MOVQir(((long)(is)), (d)), _jit.x.pc)
|
||||
#define jit_movi_l(d, is) \
|
||||
/* Value is not zero? */ \
|
||||
((is) \
|
||||
/* Yes. Value is unsigned and fits in signed 32 bits? */ \
|
||||
? (_uiP(31, is) \
|
||||
/* Yes. Use 32 bits opcode */ \
|
||||
? MOVLir(is, (d)) \
|
||||
/* No. Use 64 bits opcode */ \
|
||||
: MOVQir(is, (d))) \
|
||||
/* No. Set register to zero. */ \
|
||||
: XORQrr ((d), (d)))
|
||||
|
||||
#define jit_bmsr_l(label, s1, s2) (TESTQrr((s1), (s2)), JNZm(label), _jit.x.pc)
|
||||
#define jit_bmcr_l(label, s1, s2) (TESTQrr((s1), (s2)), JZm(label), _jit.x.pc)
|
||||
#define jit_boaddr_l(label, s1, s2) (ADDQrr((s2), (s1)), JOm(label), _jit.x.pc)
|
||||
#define jit_bosubr_l(label, s1, s2) (SUBQrr((s2), (s1)), JOm(label), _jit.x.pc)
|
||||
#define jit_boaddr_ul(label, s1, s2) (ADDQrr((s2), (s1)), JCm(label), _jit.x.pc)
|
||||
#define jit_bosubr_ul(label, s1, s2) (SUBQrr((s2), (s1)), JCm(label), _jit.x.pc)
|
||||
|
||||
#define jit_boaddi_l(label, rs, is) (ADDQir((is), (rs)), JOm(label), _jit.x.pc)
|
||||
#define jit_bosubi_l(label, rs, is) (SUBQir((is), (rs)), JOm(label), _jit.x.pc)
|
||||
#define jit_boaddi_ul(label, rs, is) (ADDQir((is), (rs)), JCm(label), _jit.x.pc)
|
||||
#define jit_bosubi_ul(label, rs, is) (SUBQir((is), (rs)), JCm(label), _jit.x.pc)
|
||||
|
||||
#define jit_patch_long_at(jump_pc,v) (*_PSL((jump_pc) - sizeof(long)) = _jit_SL((jit_insn *)(v)))
|
||||
#define jit_patch_short_at(jump_pc,v) (*_PSI((jump_pc) - sizeof(int)) = _jit_SI((jit_insn *)(v) - (jump_pc)))
|
||||
#define jit_patch_at(jump_pc,v) (_jitl.long_jumps ? jit_patch_long_at((jump_pc)-3, v) : jit_patch_short_at(jump_pc, v))
|
||||
#define jit_patch_calli(pa,pv) (*_PSL((pa) - sizeof(long)) = _jit_SL((pv)))
|
||||
#define jit_ret() (LEAVE_(), POPQr(_R14), POPQr(_R13), POPQr(_R12), POPQr(_EBX), RET_())
|
||||
#define jit_bare_ret() RET_()
|
||||
|
||||
/* Memory */
|
||||
|
||||
/* Used to implement ldc, stc, ... We have SIL and friends which simplify it all. */
|
||||
#define jit_movbrm(rs, dd, db, di, ds) MOVBrm(jit_reg8(rs), dd, db, di, ds)
|
||||
|
||||
#define jit_ldr_c(d, rs) MOVSBQmr(0, (rs), 0, 0, (d))
|
||||
#define jit_ldxr_c(d, s1, s2) MOVSBQmr(0, (s1), (s2), 1, (d))
|
||||
|
||||
#define jit_ldr_s(d, rs) MOVSWQmr(0, (rs), 0, 0, (d))
|
||||
#define jit_ldxr_s(d, s1, s2) MOVSWQmr(0, (s1), (s2), 1, (d))
|
||||
|
||||
#define jit_ldi_c(d, is) (_u32P((long)(is)) ? MOVSBQmr((is), 0, 0, 0, (d)) : (jit_movi_l(JIT_REXTMP, is), jit_ldr_c(d, JIT_REXTMP)))
|
||||
#define jit_ldxi_c(d, rs, is) (_u32P((long)(is)) ? MOVSBQmr((is), (rs), 0, 0, (d)) : (jit_movi_l(JIT_REXTMP, is), jit_ldxr_c(d, rs, JIT_REXTMP)))
|
||||
|
||||
#define jit_ldi_uc(d, is) (_u32P((long)(is)) ? MOVZBLmr((is), 0, 0, 0, (d)) : (jit_movi_l(JIT_REXTMP, is), jit_ldr_uc(d, JIT_REXTMP)))
|
||||
#define jit_ldxi_uc(d, rs, is) (_u32P((long)(is)) ? MOVZBLmr((is), (rs), 0, 0, (d)) : (jit_movi_l(JIT_REXTMP, is), jit_ldxr_uc(d, rs, JIT_REXTMP)))
|
||||
|
||||
#define jit_sti_c(id, rs) (_u32P((long)(id)) ? MOVBrm(jit_reg8(rs), (id), 0, 0, 0) : (jit_movi_l(JIT_REXTMP, id), jit_str_c(JIT_REXTMP, rs)))
|
||||
#define jit_stxi_c(id, rd, rs) (_u32P((long)(id)) ? MOVBrm(jit_reg8(rs), (id), (rd), 0, 0) : (jit_movi_l(JIT_REXTMP, id), jit_stxr_c(JIT_REXTMP, rd, rs)))
|
||||
|
||||
#define jit_ldi_s(d, is) (_u32P((long)(is)) ? MOVSWQmr((is), 0, 0, 0, (d)) : (jit_movi_l(JIT_REXTMP, is), jit_ldr_s(d, JIT_REXTMP)))
|
||||
#define jit_ldxi_s(d, rs, is) (_u32P((long)(is)) ? MOVSWQmr((is), (rs), 0, 0, (d)) : (jit_movi_l(JIT_REXTMP, is), jit_ldxr_s(d, rs, JIT_REXTMP)))
|
||||
|
||||
#define jit_ldi_us(d, is) (_u32P((long)(is)) ? MOVZWLmr((is), 0, 0, 0, (d)) : (jit_movi_l(JIT_REXTMP, is), jit_ldr_us(d, JIT_REXTMP)))
|
||||
#define jit_ldxi_us(d, rs, is) (_u32P((long)(is)) ? MOVZWLmr((is), (rs), 0, 0, (d)) : (jit_movi_l(JIT_REXTMP, is), jit_ldxr_us(d, rs, JIT_REXTMP)))
|
||||
|
||||
#define jit_sti_s(id, rs) (_u32P((long)(id)) ? MOVWrm(jit_reg16(rs), (id), 0, 0, 0) : (jit_movi_l(JIT_REXTMP, id), jit_str_s(JIT_REXTMP, rs)))
|
||||
#define jit_stxi_s(id, rd, rs) (_u32P((long)(id)) ? MOVWrm(jit_reg16(rs), (id), (rd), 0, 0) : (jit_movi_l(JIT_REXTMP, id), jit_stxr_s(JIT_REXTMP, rd, rs)))
|
||||
|
||||
#define jit_ldi_ui(d, is) (_u32P((long)(is)) ? MOVLmr((is), 0, 0, 0, (d)) : (jit_movi_l(JIT_REXTMP, is), jit_ldr_ui(d, JIT_REXTMP)))
|
||||
#define jit_ldxi_ui(d, rs, is) (_u32P((long)(is)) ? MOVLmr((is), (rs), 0, 0, (d)) : (jit_movi_l(JIT_REXTMP, is), jit_ldxr_ui(d, rs, JIT_REXTMP)))
|
||||
|
||||
#define jit_ldi_i(d, is) (_u32P((long)(is)) ? MOVSLQmr((is), 0, 0, 0, (d)) : (jit_movi_l(JIT_REXTMP, is), jit_ldr_i(d, JIT_REXTMP)))
|
||||
#define jit_ldxi_i(d, rs, is) (_u32P((long)(is)) ? MOVSLQmr((is), (rs), 0, 0, (d)) : (jit_movi_l(JIT_REXTMP, is), jit_ldxr_i(d, rs, JIT_REXTMP)))
|
||||
|
||||
#define jit_sti_i(id, rs) (_u32P((long)(id)) ? MOVLrm((rs), (id), 0, 0, 0) : (jit_movi_l(JIT_REXTMP, id), jit_str_i(JIT_REXTMP, rs)))
|
||||
#define jit_stxi_i(id, rd, rs) (_u32P((long)(id)) ? MOVLrm((rs), (id), (rd), 0, 0) : (jit_movi_l(JIT_REXTMP, id), jit_stxr_i(JIT_REXTMP, rd, rs)))
|
||||
|
||||
#define jit_ldi_l(d, is) (_u32P((long)(is)) ? MOVQmr((is), 0, 0, 0, (d)) : (jit_movi_l(JIT_REXTMP, is), jit_ldr_l(d, JIT_REXTMP)))
|
||||
#define jit_ldxi_l(d, rs, is) (_u32P((long)(is)) ? MOVQmr((is), (rs), 0, 0, (d)) : (jit_movi_l(JIT_REXTMP, is), jit_ldxr_l(d, rs, JIT_REXTMP)))
|
||||
|
||||
#define jit_sti_l(id, rs) (_u32P((long)(id)) ? MOVQrm((rs), (id), 0, 0, 0) : (jit_movi_l(JIT_REXTMP, id), jit_str_l(JIT_REXTMP, rs)))
|
||||
#define jit_stxi_l(id, rd, rs) (_u32P((long)(id)) ? MOVQrm((rs), (id), (rd), 0, 0) : (jit_movi_l(JIT_REXTMP, id), jit_stxr_l(JIT_REXTMP, rd, rs)))
|
||||
|
||||
#define jit_ldr_ui(d, rs) MOVLmr(0, (rs), 0, 0, (d))
|
||||
#define jit_ldxr_ui(d, s1, s2) MOVLmr(0, (s1), (s2), 1, (d))
|
||||
|
||||
#define jit_ldr_i(d, rs) MOVSLQmr(0, (rs), 0, 0, (d))
|
||||
#define jit_ldxr_i(d, s1, s2) MOVSLQmr(0, (s1), (s2), 1, (d))
|
||||
|
||||
#define jit_ldr_l(d, rs) MOVQmr(0, (rs), 0, 0, (d))
|
||||
#define jit_ldxr_l(d, s1, s2) MOVQmr(0, (s1), (s2), 1, (d))
|
||||
|
||||
#define jit_str_l(rd, rs) MOVQrm((rs), 0, (rd), 0, 0)
|
||||
#define jit_stxr_l(d1, d2, rs) MOVQrm((rs), 0, (d1), (d2), 1)
|
||||
|
||||
#define jit_blti_l(label, rs, is) jit_bra_l0((rs), (is), JLm(label), JSm(label) )
|
||||
#define jit_blei_l(label, rs, is) jit_bra_l ((rs), (is), JLEm(label) )
|
||||
#define jit_bgti_l(label, rs, is) jit_bra_l ((rs), (is), JGm(label) )
|
||||
#define jit_bgei_l(label, rs, is) jit_bra_l0((rs), (is), JGEm(label), JNSm(label) )
|
||||
#define jit_beqi_l(label, rs, is) jit_bra_l0((rs), (is), JEm(label), JEm(label) )
|
||||
#define jit_bnei_l(label, rs, is) jit_bra_l0((rs), (is), JNEm(label), JNEm(label) )
|
||||
#define jit_blti_ul(label, rs, is) jit_bra_l ((rs), (is), JBm(label) )
|
||||
#define jit_blei_ul(label, rs, is) jit_bra_l0((rs), (is), JBEm(label), JEm(label) )
|
||||
#define jit_bgti_ul(label, rs, is) jit_bra_l0((rs), (is), JAm(label), JNEm(label) )
|
||||
#define jit_bgei_ul(label, rs, is) jit_bra_l ((rs), (is), JAEm(label) )
|
||||
#define jit_bmsi_l(label, rs, is) (jit_reduceQ(TEST, (is), (rs)), JNZm(label), _jit.x.pc)
|
||||
#define jit_bmci_l(label, rs, is) (jit_reduceQ(TEST, (is), (rs)), JZm(label), _jit.x.pc)
|
||||
|
||||
#define jit_pushr_l(rs) jit_pushr_i(rs)
|
||||
#define jit_popr_l(rs) jit_popr_i(rs)
|
||||
|
||||
#define jit_pusharg_l(rs) jit_pusharg_i(rs)
|
||||
#define jit_retval_l(rd) ((void)jit_movr_l ((rd), _EAX))
|
||||
#define jit_bltr_l(label, s1, s2) jit_bra_qr((s1), (s2), JLm(label) )
|
||||
#define jit_bler_l(label, s1, s2) jit_bra_qr((s1), (s2), JLEm(label) )
|
||||
#define jit_bgtr_l(label, s1, s2) jit_bra_qr((s1), (s2), JGm(label) )
|
||||
#define jit_bger_l(label, s1, s2) jit_bra_qr((s1), (s2), JGEm(label) )
|
||||
#define jit_beqr_l(label, s1, s2) jit_bra_qr((s1), (s2), JEm(label) )
|
||||
#define jit_bner_l(label, s1, s2) jit_bra_qr((s1), (s2), JNEm(label) )
|
||||
#define jit_bltr_ul(label, s1, s2) jit_bra_qr((s1), (s2), JBm(label) )
|
||||
#define jit_bler_ul(label, s1, s2) jit_bra_qr((s1), (s2), JBEm(label) )
|
||||
#define jit_bgtr_ul(label, s1, s2) jit_bra_qr((s1), (s2), JAm(label) )
|
||||
#define jit_bger_ul(label, s1, s2) jit_bra_qr((s1), (s2), JAEm(label) )
|
||||
|
||||
/* Bool operations. */
|
||||
#define jit_bool_qr(d, s1, s2, op) \
|
||||
(jit_replace8(d, CMPQrr(s2, s1), op))
|
||||
|
||||
#define jit_bool_qi(d, rs, is, op) \
|
||||
(jit_replace8(d, CMPQir(is, rs), op))
|
||||
|
||||
/* When CMP with 0 can be replaced with TEST */
|
||||
#define jit_bool_qi0(d, rs, is, op, op0) \
|
||||
((is) != 0 \
|
||||
? (jit_replace8(d, CMPQir(is, rs), op)) \
|
||||
: (jit_replace8(d, TESTQrr(rs, rs), op0)))
|
||||
|
||||
#define jit_ltr_l(d, s1, s2) jit_bool_qr((d), (s1), (s2), SETLr )
|
||||
#define jit_ler_l(d, s1, s2) jit_bool_qr((d), (s1), (s2), SETLEr )
|
||||
#define jit_gtr_l(d, s1, s2) jit_bool_qr((d), (s1), (s2), SETGr )
|
||||
#define jit_ger_l(d, s1, s2) jit_bool_qr((d), (s1), (s2), SETGEr )
|
||||
#define jit_eqr_l(d, s1, s2) jit_bool_qr((d), (s1), (s2), SETEr )
|
||||
#define jit_ner_l(d, s1, s2) jit_bool_qr((d), (s1), (s2), SETNEr )
|
||||
#define jit_ltr_ul(d, s1, s2) jit_bool_qr((d), (s1), (s2), SETBr )
|
||||
#define jit_ler_ul(d, s1, s2) jit_bool_qr((d), (s1), (s2), SETBEr )
|
||||
#define jit_gtr_ul(d, s1, s2) jit_bool_qr((d), (s1), (s2), SETAr )
|
||||
#define jit_ger_ul(d, s1, s2) jit_bool_qr((d), (s1), (s2), SETAEr )
|
||||
|
||||
#define jit_lti_l(d, rs, is) jit_bool_qi0((d), (rs), (is), SETLr, SETSr )
|
||||
#define jit_lei_l(d, rs, is) jit_bool_qi ((d), (rs), (is), SETLEr )
|
||||
#define jit_gti_l(d, rs, is) jit_bool_qi ((d), (rs), (is), SETGr )
|
||||
#define jit_gei_l(d, rs, is) jit_bool_qi0((d), (rs), (is), SETGEr, SETNSr )
|
||||
#define jit_eqi_l(d, rs, is) jit_bool_qi0((d), (rs), (is), SETEr, SETEr )
|
||||
#define jit_nei_l(d, rs, is) jit_bool_qi0((d), (rs), (is), SETNEr, SETNEr )
|
||||
#define jit_lti_ul(d, rs, is) jit_bool_qi ((d), (rs), (is), SETBr )
|
||||
#define jit_lei_ul(d, rs, is) jit_bool_qi0((d), (rs), (is), SETBEr, SETEr )
|
||||
#define jit_gti_ul(d, rs, is) jit_bool_qi0((d), (rs), (is), SETAr, SETNEr )
|
||||
#define jit_gei_ul(d, rs, is) jit_bool_qi0((d), (rs), (is), SETAEr, INCLr )
|
||||
|
||||
/* Multiplication/division. */
|
||||
#define jit_mulr_ul_(s1, s2) \
|
||||
jit_qopr_(_RAX, s1, s2, MULQr(s1), MULQr(s2))
|
||||
|
||||
#define jit_mulr_l_(s1, s2) \
|
||||
jit_qopr_(_RAX, s1, s2, IMULQr(s1), IMULQr(s2))
|
||||
|
||||
#define jit_muli_l_(is, rs) \
|
||||
(MOVQir(is, rs == _RAX ? _RDX : _RAX), \
|
||||
IMULQr(rs == _RAX ? _RDX : rs))
|
||||
|
||||
#define jit_muli_ul_(is, rs) \
|
||||
(MOVQir(is, rs == _RAX ? _RDX : _RAX), \
|
||||
IMULQr(rs == _RAX ? _RDX : rs))
|
||||
|
||||
#define jit_divi_l_(result, d, rs, is) \
|
||||
(jit_might (d, _RAX, jit_pushr_l(_RAX)), \
|
||||
jit_might (d, _RCX, jit_pushr_l(_RCX)), \
|
||||
jit_might (d, _RDX, jit_pushr_l(_RDX)), \
|
||||
jit_might (rs, _RAX, MOVQrr(rs, _RAX)), \
|
||||
jit_might (rs, _RDX, MOVQrr(rs, _RDX)), \
|
||||
MOVQir(is, _RCX), \
|
||||
SARQir(63, _RDX), \
|
||||
IDIVQr(_RCX), \
|
||||
jit_might(d, result, MOVQrr(result, d)), \
|
||||
jit_might(d, _RDX, jit_popr_l(_RDX)), \
|
||||
jit_might(d, _RCX, jit_popr_l(_RCX)), \
|
||||
jit_might(d, _RAX, jit_popr_l(_RAX)))
|
||||
|
||||
#define jit_divr_l_(result, d, s1, s2) \
|
||||
(jit_might (d, _RAX, jit_pushr_l(_RAX)), \
|
||||
jit_might (d, _RCX, jit_pushr_l(_RCX)), \
|
||||
jit_might (d, _RDX, jit_pushr_l(_RDX)), \
|
||||
((s1 == _RCX) ? jit_pushr_l(_RCX) : 0), \
|
||||
jit_might (s2, _RCX, MOVQrr(s2, _RCX)), \
|
||||
((s1 == _RCX) ? jit_popr_l(_RDX) : \
|
||||
jit_might (s1, _RDX, MOVQrr(s1, _RDX))), \
|
||||
MOVQrr(_RDX, _RAX), \
|
||||
SARQir(63, _RDX), \
|
||||
IDIVQr(_RCX), \
|
||||
jit_might(d, result, MOVQrr(result, d)), \
|
||||
jit_might(d, _RDX, jit_popr_l(_RDX)), \
|
||||
jit_might(d, _RCX, jit_popr_l(_RCX)), \
|
||||
jit_might(d, _RAX, jit_popr_l(_RAX)))
|
||||
|
||||
#define jit_divi_ul_(result, d, rs, is) \
|
||||
(jit_might (d, _RAX, jit_pushr_l(_RAX)), \
|
||||
jit_might (d, _RCX, jit_pushr_l(_RCX)), \
|
||||
jit_might (d, _RDX, jit_pushr_l(_RDX)), \
|
||||
jit_might (rs, _RAX, MOVQrr(rs, _RAX)), \
|
||||
MOVQir(is, _RCX), \
|
||||
XORQrr(_RDX, _RDX), \
|
||||
DIVQr(_RCX), \
|
||||
jit_might(d, result, MOVQrr(result, d)), \
|
||||
jit_might(d, _RDX, jit_popr_l(_RDX)), \
|
||||
jit_might(d, _RCX, jit_popr_l(_RCX)), \
|
||||
jit_might(d, _RAX, jit_popr_l(_RAX)))
|
||||
|
||||
#define jit_divr_ul_(result, d, s1, s2) \
|
||||
(jit_might (d, _RAX, jit_pushr_l(_RAX)), \
|
||||
jit_might (d, _RCX, jit_pushr_l(_RCX)), \
|
||||
jit_might (d, _RDX, jit_pushr_l(_RDX)), \
|
||||
((s1 == _RCX) ? jit_pushr_l(_RCX) : 0), \
|
||||
jit_might (s2, _RCX, MOVQrr(s2, _RCX)), \
|
||||
((s1 == _RCX) ? jit_popr_l(_RAX) : \
|
||||
jit_might (s1, _RAX, MOVQrr(s1, _RAX))), \
|
||||
XORQrr(_RDX, _RDX), \
|
||||
DIVQr(_RCX), \
|
||||
jit_might(d, result, MOVQrr(result, d)), \
|
||||
jit_might(d, _RDX, jit_popr_l(_RDX)), \
|
||||
jit_might(d, _RCX, jit_popr_l(_RCX)), \
|
||||
jit_might(d, _RAX, jit_popr_l(_RAX)))
|
||||
|
||||
#define jit_muli_l(d, rs, is) jit_qop_ ((d), (rs), (is), IMULQir((is), (d)), IMULQrr(JIT_REXTMP, (d)) )
|
||||
#define jit_mulr_l(d, s1, s2) jit_qopr_((d), (s1), (s2), IMULQrr((s1), (d)), IMULQrr((s2), (d)) )
|
||||
|
||||
/* As far as low bits are concerned, signed and unsigned multiplies are
|
||||
exactly the same. */
|
||||
#define jit_muli_ul(d, rs, is) jit_qop_ ((d), (rs), (is), IMULQir((is), (d)), IMULQrr(JIT_REXTMP, (d)) )
|
||||
#define jit_mulr_ul(d, s1, s2) jit_qopr_((d), (s1), (s2), IMULQrr((s1), (d)), IMULQrr((s2), (d)) )
|
||||
|
||||
#define jit_hmuli_l(d, rs, is) \
|
||||
((d) == _RDX ? ( jit_pushr_l(_RAX), jit_muli_l_((is), (rs)), jit_popr_l(_RAX) ) : \
|
||||
((d) == _RAX ? (jit_pushr_l(_RDX), jit_muli_l_((is), (rs)), MOVQrr(_RDX, _RAX), jit_popr_l(_RDX) ) : \
|
||||
(jit_pushr_l(_RDX), jit_pushr_l(_RAX), jit_muli_l_((is), (rs)), MOVQrr(_RDX, (d)), jit_popr_l(_RAX), jit_popr_l(_RDX) )))
|
||||
|
||||
#define jit_hmulr_l(d, s1, s2) \
|
||||
((d) == _RDX ? ( jit_pushr_l(_RAX), jit_mulr_l_((s1), (s2)), jit_popr_l(_RAX) ) : \
|
||||
((d) == _RAX ? (jit_pushr_l(_RDX), jit_mulr_l_((s1), (s2)), MOVQrr(_RDX, _RAX), jit_popr_l(_RDX) ) : \
|
||||
(jit_pushr_l(_RDX), jit_pushr_l(_RAX), jit_mulr_l_((s1), (s2)), MOVQrr(_RDX, (d)), jit_popr_l(_RAX), jit_popr_l(_RDX) )))
|
||||
|
||||
#define jit_hmuli_ul(d, rs, is) \
|
||||
((d) == _RDX ? ( jit_pushr_l(_RAX), jit_muli_ul_((is), (rs)), jit_popr_l(_RAX) ) : \
|
||||
((d) == _RAX ? (jit_pushr_l(_RDX), jit_muli_ul_((is), (rs)), MOVQrr(_RDX, _RAX), jit_popr_l(_RDX) ) : \
|
||||
(jit_pushr_l(_RDX), jit_pushr_l(_RAX), jit_muli_ul_((is), (rs)), MOVQrr(_RDX, (d)), jit_popr_l(_RAX), jit_popr_l(_RDX) )))
|
||||
|
||||
#define jit_hmulr_ul(d, s1, s2) \
|
||||
((d) == _RDX ? ( jit_pushr_l(_RAX), jit_mulr_ul_((s1), (s2)), jit_popr_l(_RAX) ) : \
|
||||
((d) == _RAX ? (jit_pushr_l(_RDX), jit_mulr_ul_((s1), (s2)), MOVQrr(_RDX, _RAX), jit_popr_l(_RDX) ) : \
|
||||
(jit_pushr_l(_RDX), jit_pushr_l(_RAX), jit_mulr_ul_((s1), (s2)), MOVQrr(_RDX, (d)), jit_popr_l(_RAX), jit_popr_l(_RDX) )))
|
||||
|
||||
#define jit_divi_l(d, rs, is) jit_divi_l_(_RAX, (d), (rs), (is))
|
||||
#define jit_divi_ul(d, rs, is) jit_divi_ul_(_RAX, (d), (rs), (is))
|
||||
#define jit_modi_l(d, rs, is) jit_divi_l_(_RDX, (d), (rs), (is))
|
||||
#define jit_modi_ul(d, rs, is) jit_divi_ul_(_RDX, (d), (rs), (is))
|
||||
#define jit_divr_l(d, s1, s2) jit_divr_l_(_RAX, (d), (s1), (s2))
|
||||
#define jit_divr_ul(d, s1, s2) jit_divr_ul_(_RAX, (d), (s1), (s2))
|
||||
#define jit_modr_l(d, s1, s2) jit_divr_l_(_RDX, (d), (s1), (s2))
|
||||
#define jit_modr_ul(d, s1, s2) jit_divr_ul_(_RDX, (d), (s1), (s2))
|
||||
|
||||
#endif /* __lightning_core_h */
|
||||
@@ -1,366 +0,0 @@
|
||||
/******************************** -*- C -*- ****************************
|
||||
*
|
||||
* Platform-independent layer (i386 version)
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Copyright 2000, 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
|
||||
* Written by Paolo Bonzini and Matthew Flatt.
|
||||
*
|
||||
* This file is part of GNU lightning.
|
||||
*
|
||||
* GNU lightning is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU lightning is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with GNU lightning; see the file COPYING.LESSER; if not, write to the
|
||||
* Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef __lightning_core_i386_h
|
||||
#define __lightning_core_i386_h
|
||||
|
||||
#define JIT_FP _EBP
|
||||
#define JIT_SP _ESP
|
||||
#define JIT_RET _EAX
|
||||
|
||||
|
||||
/* 3-parameter operation */
|
||||
#define jit_opr_(d, s1, s2, op1d, op2d) \
|
||||
( (s2 == d) ? op1d : \
|
||||
( ((s1 == d) ? (void)0 : (void)MOVLrr(s1, d)), op2d ) \
|
||||
)
|
||||
|
||||
/* 3-parameter operation, with immediate */
|
||||
#define jit_op_(d, s1, op2d) \
|
||||
((s1 == d) ? op2d : (MOVLrr(s1, d), op2d))
|
||||
|
||||
/* 3-parameter operation, optimizable */
|
||||
#define jit_opo_(d, s1, s2, op1d, op2d, op12d) \
|
||||
((s2 == d) ? op2d : \
|
||||
((s1 == d) ? op1d : op12d))
|
||||
|
||||
/* 3-parameter operation, optimizable, with immediate */
|
||||
#define jit_opi_(d, rs, opdi, opdri) \
|
||||
((rs == d) ? opdi : opdri)
|
||||
|
||||
/* For LT, LE, ... */
|
||||
#define jit_replace8(d, cmp, op) \
|
||||
(jit_check8(d) \
|
||||
? ((cmp), \
|
||||
MOVLir(0, (d)), \
|
||||
op(_rR(d) | _AL)) \
|
||||
: (jit_pushr_i(_EAX), (cmp), \
|
||||
MOVLir(0, _EAX), \
|
||||
op(_AL), MOVLrr(_EAX, (d)), jit_popr_i(_EAX)))
|
||||
|
||||
#define jit_bool_r(d, s1, s2, op) \
|
||||
(jit_replace8(d, CMPLrr(s2, s1), op))
|
||||
|
||||
#define jit_bool_i(d, rs, is, op) \
|
||||
(jit_replace8(d, CMPLir(is, rs), op))
|
||||
|
||||
/* When CMP with 0 can be replaced with TEST */
|
||||
#define jit_bool_i0(d, rs, is, op, op0) \
|
||||
((is) != 0 \
|
||||
? (jit_replace8(d, CMPLir(is, rs), op)) \
|
||||
: (jit_replace8(d, TESTLrr(rs, rs), op0)))
|
||||
|
||||
/* For BLT, BLE, ... */
|
||||
#define jit_bra_r(s1, s2, op) (CMPLrr(s2, s1), op, _jit.x.pc)
|
||||
#define jit_bra_i(rs, is, op) (CMPLir(is, rs), op, _jit.x.pc)
|
||||
|
||||
/* When CMP with 0 can be replaced with TEST */
|
||||
#define jit_bra_i0(rs, is, op, op0) \
|
||||
( (is) == 0 ? (TESTLrr(rs, rs), op0, _jit.x.pc) : (CMPLir(is, rs), op, _jit.x.pc))
|
||||
|
||||
/* Reduce arguments of XOR/OR/TEST */
|
||||
#define jit_reduce_(op) op
|
||||
#define jit_reduce(op, is, rs) \
|
||||
(_u8P(is) && jit_check8(rs) ? jit_reduce_(op##Bir(is, jit_reg8(rs))) : \
|
||||
(_u16P(is) && JIT_CAN_16 ? jit_reduce_(op##Wir(is, jit_reg16(rs))) : \
|
||||
jit_reduce_(op##Lir(is, rs)) ))
|
||||
|
||||
/* Helper macros for MUL/DIV/IDIV */
|
||||
#define jit_might(d, s1, op) \
|
||||
((s1 == d) ? 0 : op)
|
||||
|
||||
#define jit_mulr_ui_(s1, s2) jit_opr_(_EAX, s1, s2, MULLr(s1), MULLr(s2))
|
||||
#define jit_mulr_i_(s1, s2) jit_opr_(_EAX, s1, s2, IMULLr(s1), IMULLr(s2))
|
||||
|
||||
|
||||
#define jit_muli_i_(is, rs) \
|
||||
(MOVLir(is, rs == _EAX ? _EDX : _EAX), \
|
||||
IMULLr(rs == _EAX ? _EDX : rs))
|
||||
|
||||
#define jit_muli_ui_(is, rs) \
|
||||
(MOVLir(is, rs == _EAX ? _EDX : _EAX), \
|
||||
IMULLr(rs == _EAX ? _EDX : rs))
|
||||
|
||||
#define jit_divi_i_(result, d, rs, is) \
|
||||
(jit_might (d, _EAX, jit_pushr_i(_EAX)), \
|
||||
jit_might (d, _ECX, jit_pushr_i(_ECX)), \
|
||||
jit_might (d, _EDX, jit_pushr_i(_EDX)), \
|
||||
jit_might (rs, _EAX, MOVLrr(rs, _EAX)), \
|
||||
jit_might (rs, _EDX, MOVLrr(rs, _EDX)), \
|
||||
MOVLir(is, _ECX), \
|
||||
SARLir(31, _EDX), \
|
||||
IDIVLr(_ECX), \
|
||||
jit_might(d, result, MOVLrr(result, d)), \
|
||||
jit_might(d, _EDX, jit_popr_i(_EDX)), \
|
||||
jit_might(d, _ECX, jit_popr_i(_ECX)), \
|
||||
jit_might(d, _EAX, jit_popr_i(_EAX)))
|
||||
|
||||
#define jit_divr_i_(result, d, s1, s2) \
|
||||
(jit_might (d, _EAX, jit_pushr_i(_EAX)), \
|
||||
jit_might (d, _ECX, jit_pushr_i(_ECX)), \
|
||||
jit_might (d, _EDX, jit_pushr_i(_EDX)), \
|
||||
((s1 == _ECX) ? jit_pushr_i(_ECX) : 0), \
|
||||
jit_might (s2, _ECX, MOVLrr(s2, _ECX)), \
|
||||
((s1 == _ECX) ? jit_popr_i(_EDX) : \
|
||||
jit_might (s1, _EDX, MOVLrr(s1, _EDX))), \
|
||||
MOVLrr(_EDX, _EAX), \
|
||||
SARLir(31, _EDX), \
|
||||
IDIVLr(_ECX), \
|
||||
jit_might(d, result, MOVLrr(result, d)), \
|
||||
jit_might(d, _EDX, jit_popr_i(_EDX)), \
|
||||
jit_might(d, _ECX, jit_popr_i(_ECX)), \
|
||||
jit_might(d, _EAX, jit_popr_i(_EAX)))
|
||||
|
||||
#define jit_divi_ui_(result, d, rs, is) \
|
||||
(jit_might (d, _EAX, jit_pushr_i(_EAX)), \
|
||||
jit_might (d, _ECX, jit_pushr_i(_ECX)), \
|
||||
jit_might (d, _EDX, jit_pushr_i(_EDX)), \
|
||||
jit_might (rs, _EAX, MOVLrr(rs, _EAX)), \
|
||||
MOVLir(is, _ECX), \
|
||||
XORLrr(_EDX, _EDX), \
|
||||
DIVLr(_ECX), \
|
||||
jit_might(d, result, MOVLrr(result, d)), \
|
||||
jit_might(d, _EDX, jit_popr_i(_EDX)), \
|
||||
jit_might(d, _ECX, jit_popr_i(_ECX)), \
|
||||
jit_might(d, _EAX, jit_popr_i(_EAX)))
|
||||
|
||||
#define jit_divr_ui_(result, d, s1, s2) \
|
||||
(jit_might (d, _EAX, jit_pushr_i(_EAX)), \
|
||||
jit_might (d, _ECX, jit_pushr_i(_ECX)), \
|
||||
jit_might (d, _EDX, jit_pushr_i(_EDX)), \
|
||||
((s1 == _ECX) ? jit_pushr_i(_ECX) : 0), \
|
||||
jit_might (s2, _ECX, MOVLrr(s2, _ECX)), \
|
||||
((s1 == _ECX) ? jit_popr_i(_EAX) : \
|
||||
jit_might (s1, _EAX, MOVLrr(s1, _EAX))), \
|
||||
XORLrr(_EDX, _EDX), \
|
||||
DIVLr(_ECX), \
|
||||
jit_might(d, result, MOVLrr(result, d)), \
|
||||
jit_might(d, _EDX, jit_popr_i(_EDX)), \
|
||||
jit_might(d, _ECX, jit_popr_i(_ECX)), \
|
||||
jit_might(d, _EAX, jit_popr_i(_EAX)))
|
||||
|
||||
|
||||
/* ALU */
|
||||
#define jit_addi_i(d, rs, is) jit_opi_((d), (rs), ADDLir((is), (d)), LEALmr((is), (rs), 0, 0, (d)) )
|
||||
#define jit_addr_i(d, s1, s2) jit_opo_((d), (s1), (s2), ADDLrr((s2), (d)), ADDLrr((s1), (d)), LEALmr(0, (s1), (s2), 1, (d)) )
|
||||
#define jit_addci_i(d, rs, is) jit_op_ ((d), (rs), ADDLir((is), (d)) )
|
||||
#define jit_addcr_i(d, s1, s2) jit_opr_((d), (s1), (s2), ADDLrr((s1), (d)), ADDLrr((s2), (d)) )
|
||||
#define jit_addxi_i(d, rs, is) jit_op_ ((d), (rs), ADCLir((is), (d)) )
|
||||
#define jit_addxr_i(d, s1, s2) jit_opr_((d), (s1), (s2), ADCLrr((s1), (d)), ADCLrr((s2), (d)) )
|
||||
#define jit_andi_i(d, rs, is) jit_op_ ((d), (rs), ANDLir((is), (d)) )
|
||||
#define jit_andr_i(d, s1, s2) jit_opr_((d), (s1), (s2), ANDLrr((s1), (d)), ANDLrr((s2), (d)) )
|
||||
#define jit_orr_i(d, s1, s2) jit_opr_((d), (s1), (s2), ORLrr((s1), (d)), ORLrr((s2), (d)) )
|
||||
#define jit_subr_i(d, s1, s2) jit_opr_((d), (s1), (s2), (SUBLrr((s1), (d)), NEGLr(d)), SUBLrr((s2), (d)) )
|
||||
#define jit_subcr_i(d, s1, s2) jit_subr_i((d), (s1), (s2))
|
||||
#define jit_subxr_i(d, s1, s2) jit_opr_((d), (s1), (s2), SBBLrr((s1), (d)), SBBLrr((s2), (d)) )
|
||||
#define jit_subxi_i(d, rs, is) jit_op_ ((d), (rs), SBBLir((is), (d)) )
|
||||
#define jit_xorr_i(d, s1, s2) jit_opr_((d), (s1), (s2), XORLrr((s1), (d)), XORLrr((s2), (d)) )
|
||||
|
||||
|
||||
/* These can sometimes use byte or word versions! */
|
||||
#define jit_ori_i(d, rs, is) jit_op_ ((d), (rs), jit_reduce(OR, (is), (d)) )
|
||||
#define jit_xori_i(d, rs, is) jit_op_ ((d), (rs), jit_reduce(XOR, (is), (d)) )
|
||||
|
||||
#define jit_muli_i(d, rs, is) jit_op_ ((d), (rs), IMULLir((is), (d)) )
|
||||
#define jit_mulr_i(d, s1, s2) jit_opr_((d), (s1), (s2), IMULLrr((s1), (d)), IMULLrr((s2), (d)) )
|
||||
|
||||
/* As far as low bits are concerned, signed and unsigned multiplies are
|
||||
exactly the same. */
|
||||
#define jit_muli_ui(d, rs, is) jit_op_ ((d), (rs), IMULLir((is), (d)) )
|
||||
#define jit_mulr_ui(d, s1, s2) jit_opr_((d), (s1), (s2), IMULLrr((s1), (d)), IMULLrr((s2), (d)) )
|
||||
|
||||
#define jit_hmuli_i(d, rs, is) \
|
||||
((d) == _EDX ? ( jit_pushr_i(_EAX), jit_muli_i_((is), (rs)), jit_popr_i(_EAX) ) : \
|
||||
((d) == _EAX ? (jit_pushr_i(_EDX), jit_muli_i_((is), (rs)), MOVLrr(_EDX, _EAX), jit_popr_i(_EDX) ) : \
|
||||
(jit_pushr_i(_EDX), jit_pushr_i(_EAX), jit_muli_i_((is), (rs)), MOVLrr(_EDX, (d)), jit_popr_i(_EAX), jit_popr_i(_EDX) )))
|
||||
|
||||
#define jit_hmulr_i(d, s1, s2) \
|
||||
((d) == _EDX ? ( jit_pushr_i(_EAX), jit_mulr_i_((s1), (s2)), jit_popr_i(_EAX) ) : \
|
||||
((d) == _EAX ? (jit_pushr_i(_EDX), jit_mulr_i_((s1), (s2)), MOVLrr(_EDX, _EAX), jit_popr_i(_EDX) ) : \
|
||||
(jit_pushr_i(_EDX), jit_pushr_i(_EAX), jit_mulr_i_((s1), (s2)), MOVLrr(_EDX, (d)), jit_popr_i(_EAX), jit_popr_i(_EDX) )))
|
||||
|
||||
#define jit_hmuli_ui(d, rs, is) \
|
||||
((d) == _EDX ? ( jit_pushr_i(_EAX), jit_muli_ui_((is), (rs)), jit_popr_i(_EAX) ) : \
|
||||
((d) == _EAX ? (jit_pushr_i(_EDX), jit_muli_ui_((is), (rs)), MOVLrr(_EDX, _EAX), jit_popr_i(_EDX) ) : \
|
||||
(jit_pushr_i(_EDX), jit_pushr_i(_EAX), jit_muli_ui_((is), (rs)), MOVLrr(_EDX, (d)), jit_popr_i(_EAX), jit_popr_i(_EDX) )))
|
||||
|
||||
#define jit_hmulr_ui(d, s1, s2) \
|
||||
((d) == _EDX ? ( jit_pushr_i(_EAX), jit_mulr_ui_((s1), (s2)), jit_popr_i(_EAX) ) : \
|
||||
((d) == _EAX ? (jit_pushr_i(_EDX), jit_mulr_ui_((s1), (s2)), MOVLrr(_EDX, _EAX), jit_popr_i(_EDX) ) : \
|
||||
(jit_pushr_i(_EDX), jit_pushr_i(_EAX), jit_mulr_ui_((s1), (s2)), MOVLrr(_EDX, (d)), jit_popr_i(_EAX), jit_popr_i(_EDX) )))
|
||||
|
||||
#define jit_divi_i(d, rs, is) jit_divi_i_(_EAX, (d), (rs), (is))
|
||||
#define jit_divi_ui(d, rs, is) jit_divi_ui_(_EAX, (d), (rs), (is))
|
||||
#define jit_modi_i(d, rs, is) jit_divi_i_(_EDX, (d), (rs), (is))
|
||||
#define jit_modi_ui(d, rs, is) jit_divi_ui_(_EDX, (d), (rs), (is))
|
||||
#define jit_divr_i(d, s1, s2) jit_divr_i_(_EAX, (d), (s1), (s2))
|
||||
#define jit_divr_ui(d, s1, s2) jit_divr_ui_(_EAX, (d), (s1), (s2))
|
||||
#define jit_modr_i(d, s1, s2) jit_divr_i_(_EDX, (d), (s1), (s2))
|
||||
#define jit_modr_ui(d, s1, s2) jit_divr_ui_(_EDX, (d), (s1), (s2))
|
||||
|
||||
|
||||
/* Shifts */
|
||||
#define jit_shift(d, s1, s2, m) \
|
||||
((d) == _ECX || (d) == (s2) \
|
||||
? ((s2) == _EAX \
|
||||
? jit_fixd(d, _EDX, jit_shift2(_EDX, s1, s2, m)) \
|
||||
: jit_fixd(d, _EAX, jit_shift2(_EAX, s1, s2, m))) \
|
||||
: jit_shift2(d, s1, s2, m))
|
||||
|
||||
/* Shift operation, assuming d != s2 or ECX */
|
||||
#define jit_shift2(d, s1, s2, m) \
|
||||
jit_op_(d, s1, jit_cfixs(s2, _ECX, m(_CL, d)))
|
||||
|
||||
/* Substitute x for destination register d */
|
||||
#define jit_fixd(d, x, op) \
|
||||
(jit_pushr_i(x), op, jit_movr_i(d, x), jit_popr_i(x))
|
||||
|
||||
/* Conditionally substitute y for source register s */
|
||||
#define jit_cfixs(s, y, op) \
|
||||
((s) == (y) ? op : \
|
||||
(jit_pushr_i(y), jit_movr_i(y, s), op, jit_popr_i(y)))
|
||||
|
||||
#define jit_lshi_i(d, rs, is) ((is) <= 3 ? LEALmr(0, 0, (rs), 1 << (is), (d)) : jit_op_ ((d), (rs), SHLLir((is), (d)) ))
|
||||
#define jit_rshi_i(d, rs, is) jit_op_ ((d), (rs), SARLir((is), (d)) )
|
||||
#define jit_rshi_ui(d, rs, is) jit_op_ ((d), (rs), SHRLir((is), (d)) )
|
||||
#define jit_lshr_i(d, r1, r2) jit_shift((d), (r1), (r2), SHLLrr)
|
||||
#define jit_rshr_i(d, r1, r2) jit_shift((d), (r1), (r2), SARLrr)
|
||||
#define jit_rshr_ui(d, r1, r2) jit_shift((d), (r1), (r2), SHRLrr)
|
||||
|
||||
/* Stack */
|
||||
#define jit_retval_i(rd) ((void)jit_movr_i ((rd), _EAX))
|
||||
|
||||
/* Unary */
|
||||
#define jit_negr_i(d, rs) jit_opi_((d), (rs), NEGLr(d), (XORLrr((d), (d)), SUBLrr((rs), (d))) )
|
||||
|
||||
#define jit_movr_i(d, rs) ((void)((rs) == (d) ? 0 : MOVLrr((rs), (d))))
|
||||
#define jit_movi_i(d, is) ((is) ? MOVLir((is), (d)) : XORLrr ((d), (d)) )
|
||||
#define jit_patch_movi(pa,pv) (*_PSL((pa) - sizeof(long)) = _jit_SL((pv)))
|
||||
|
||||
#define jit_ntoh_ui(d, rs) jit_op_((d), (rs), BSWAPLr(d))
|
||||
#define jit_ntoh_us(d, rs) jit_op_((d), (rs), RORWir(8, d))
|
||||
|
||||
/* Boolean */
|
||||
#define jit_ltr_i(d, s1, s2) jit_bool_r((d), (s1), (s2), SETLr )
|
||||
#define jit_ler_i(d, s1, s2) jit_bool_r((d), (s1), (s2), SETLEr )
|
||||
#define jit_gtr_i(d, s1, s2) jit_bool_r((d), (s1), (s2), SETGr )
|
||||
#define jit_ger_i(d, s1, s2) jit_bool_r((d), (s1), (s2), SETGEr )
|
||||
#define jit_eqr_i(d, s1, s2) jit_bool_r((d), (s1), (s2), SETEr )
|
||||
#define jit_ner_i(d, s1, s2) jit_bool_r((d), (s1), (s2), SETNEr )
|
||||
#define jit_ltr_ui(d, s1, s2) jit_bool_r((d), (s1), (s2), SETBr )
|
||||
#define jit_ler_ui(d, s1, s2) jit_bool_r((d), (s1), (s2), SETBEr )
|
||||
#define jit_gtr_ui(d, s1, s2) jit_bool_r((d), (s1), (s2), SETAr )
|
||||
#define jit_ger_ui(d, s1, s2) jit_bool_r((d), (s1), (s2), SETAEr )
|
||||
|
||||
#define jit_lti_i(d, rs, is) jit_bool_i0((d), (rs), (is), SETLr, SETSr )
|
||||
#define jit_lei_i(d, rs, is) jit_bool_i ((d), (rs), (is), SETLEr )
|
||||
#define jit_gti_i(d, rs, is) jit_bool_i ((d), (rs), (is), SETGr )
|
||||
#define jit_gei_i(d, rs, is) jit_bool_i0((d), (rs), (is), SETGEr, SETNSr )
|
||||
#define jit_eqi_i(d, rs, is) jit_bool_i0((d), (rs), (is), SETEr, SETEr )
|
||||
#define jit_nei_i(d, rs, is) jit_bool_i0((d), (rs), (is), SETNEr, SETNEr )
|
||||
#define jit_lti_ui(d, rs, is) jit_bool_i ((d), (rs), (is), SETBr )
|
||||
#define jit_lei_ui(d, rs, is) jit_bool_i0((d), (rs), (is), SETBEr, SETEr )
|
||||
#define jit_gti_ui(d, rs, is) jit_bool_i0((d), (rs), (is), SETAr, SETNEr )
|
||||
#define jit_gei_ui(d, rs, is) jit_bool_i0((d), (rs), (is), SETAEr, INCLr )
|
||||
|
||||
/* Jump */
|
||||
#define jit_bltr_i(label, s1, s2) jit_bra_r((s1), (s2), JLm(label) )
|
||||
#define jit_bler_i(label, s1, s2) jit_bra_r((s1), (s2), JLEm(label) )
|
||||
#define jit_bgtr_i(label, s1, s2) jit_bra_r((s1), (s2), JGm(label) )
|
||||
#define jit_bger_i(label, s1, s2) jit_bra_r((s1), (s2), JGEm(label) )
|
||||
#define jit_beqr_i(label, s1, s2) jit_bra_r((s1), (s2), JEm(label) )
|
||||
#define jit_bner_i(label, s1, s2) jit_bra_r((s1), (s2), JNEm(label) )
|
||||
#define jit_bltr_ui(label, s1, s2) jit_bra_r((s1), (s2), JBm(label) )
|
||||
#define jit_bler_ui(label, s1, s2) jit_bra_r((s1), (s2), JBEm(label) )
|
||||
#define jit_bgtr_ui(label, s1, s2) jit_bra_r((s1), (s2), JAm(label) )
|
||||
#define jit_bger_ui(label, s1, s2) jit_bra_r((s1), (s2), JAEm(label) )
|
||||
#define jit_bmsr_i(label, s1, s2) (TESTLrr((s1), (s2)), JNZm(label), _jit.x.pc)
|
||||
#define jit_bmcr_i(label, s1, s2) (TESTLrr((s1), (s2)), JZm(label), _jit.x.pc)
|
||||
#define jit_boaddr_i(label, s1, s2) (ADDLrr((s2), (s1)), JOm(label), _jit.x.pc)
|
||||
#define jit_bosubr_i(label, s1, s2) (SUBLrr((s2), (s1)), JOm(label), _jit.x.pc)
|
||||
#define jit_boaddr_ui(label, s1, s2) (ADDLrr((s2), (s1)), JCm(label), _jit.x.pc)
|
||||
#define jit_bosubr_ui(label, s1, s2) (SUBLrr((s2), (s1)), JCm(label), _jit.x.pc)
|
||||
|
||||
#define jit_blti_i(label, rs, is) jit_bra_i0((rs), (is), JLm(label), JSm(label) )
|
||||
#define jit_blei_i(label, rs, is) jit_bra_i ((rs), (is), JLEm(label) )
|
||||
#define jit_bgti_i(label, rs, is) jit_bra_i ((rs), (is), JGm(label) )
|
||||
#define jit_bgei_i(label, rs, is) jit_bra_i0((rs), (is), JGEm(label), JNSm(label) )
|
||||
#define jit_beqi_i(label, rs, is) jit_bra_i0((rs), (is), JEm(label), JEm(label) )
|
||||
#define jit_bnei_i(label, rs, is) jit_bra_i0((rs), (is), JNEm(label), JNEm(label) )
|
||||
#define jit_blti_ui(label, rs, is) jit_bra_i ((rs), (is), JBm(label) )
|
||||
#define jit_blei_ui(label, rs, is) jit_bra_i0((rs), (is), JBEm(label), JEm(label) )
|
||||
#define jit_bgti_ui(label, rs, is) jit_bra_i0((rs), (is), JAm(label), JNEm(label) )
|
||||
#define jit_bgei_ui(label, rs, is) jit_bra_i ((rs), (is), JAEm(label) )
|
||||
#define jit_boaddi_i(label, rs, is) (ADDLir((is), (rs)), JOm(label), _jit.x.pc)
|
||||
#define jit_bosubi_i(label, rs, is) (SUBLir((is), (rs)), JOm(label), _jit.x.pc)
|
||||
#define jit_boaddi_ui(label, rs, is) (ADDLir((is), (rs)), JCm(label), _jit.x.pc)
|
||||
#define jit_bosubi_ui(label, rs, is) (SUBLir((is), (rs)), JCm(label), _jit.x.pc)
|
||||
|
||||
#define jit_bmsi_i(label, rs, is) (jit_reduce(TEST, (is), (rs)), JNZm(label), _jit.x.pc)
|
||||
#define jit_bmci_i(label, rs, is) (jit_reduce(TEST, (is), (rs)), JZm(label), _jit.x.pc)
|
||||
|
||||
#define jit_jmpi(label) (JMPm( ((unsigned long) (label))), _jit.x.pc)
|
||||
#define jit_jmpr(reg) JMPsr(reg)
|
||||
|
||||
/* Memory */
|
||||
#define jit_ldr_uc(d, rs) MOVZBLmr(0, (rs), 0, 0, (d))
|
||||
#define jit_ldxr_uc(d, s1, s2) MOVZBLmr(0, (s1), (s2), 1, (d))
|
||||
|
||||
#define jit_str_c(rd, rs) jit_movbrm((rs), 0, (rd), 0, 0)
|
||||
#define jit_stxr_c(d1, d2, rs) jit_movbrm((rs), 0, (d1), (d2), 1)
|
||||
|
||||
#define jit_ldr_us(d, rs) MOVZWLmr(0, (rs), 0, 0, (d))
|
||||
#define jit_ldxr_us(d, s1, s2) MOVZWLmr(0, (s1), (s2), 1, (d))
|
||||
|
||||
#define jit_str_s(rd, rs) MOVWrm(jit_reg16(rs), 0, (rd), 0, 0)
|
||||
#define jit_stxr_s(d1, d2, rs) MOVWrm(jit_reg16(rs), 0, (d1), (d2), 1)
|
||||
|
||||
#define jit_str_i(rd, rs) MOVLrm((rs), 0, (rd), 0, 0)
|
||||
#define jit_stxr_i(d1, d2, rs) MOVLrm((rs), 0, (d1), (d2), 1)
|
||||
|
||||
/* Extra */
|
||||
#define jit_nop() NOP_()
|
||||
|
||||
#define _jit_alignment(pc, n) (((pc ^ _MASK(4)) + 1) & _MASK(n))
|
||||
#define jit_align(n) NOPi(_jit_alignment(_jit_UL(_jit.x.pc), (n)))
|
||||
|
||||
|
||||
#if LIGHTNING_CROSS \
|
||||
? LIGHTNING_TARGET == LIGHTNING_X86_64 \
|
||||
: defined (__x86_64__)
|
||||
#include "i386/core-64.h"
|
||||
#else
|
||||
#include "i386/core-32.h"
|
||||
#endif
|
||||
|
||||
#endif /* __lightning_core_i386_h */
|
||||
@@ -1,356 +0,0 @@
|
||||
/******************************** -*- C -*- ****************************
|
||||
*
|
||||
* Support macros for the i386 math coprocessor
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Copyright 2000, 2001, 2002, 2004, 2008 Free Software Foundation, Inc.
|
||||
* Written by Paolo Bonzini.
|
||||
*
|
||||
* This file is part of GNU lightning.
|
||||
*
|
||||
* GNU lightning is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU lightning is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with GNU lightning; see the file COPYING.LESSER; if not, write to the
|
||||
* Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
#ifndef __lightning_fp_h
|
||||
#define __lightning_fp_h
|
||||
|
||||
/* We really must map the x87 stack onto a flat register file. In practice,
|
||||
we can provide something sensible and make it work on the x86 using the
|
||||
stack like a file of eight registers.
|
||||
|
||||
We use six or seven registers so as to have some freedom
|
||||
for floor, ceil, round, (and log, tan, atn and exp).
|
||||
|
||||
Not hard at all, basically play with FXCH. FXCH is mostly free,
|
||||
so the generated code is not bad. Of course we special case when one
|
||||
of the operands turns out to be ST0.
|
||||
|
||||
Here are the macros that actually do the trick. */
|
||||
|
||||
#define JIT_FPR_NUM 6
|
||||
#define JIT_FPRET 0
|
||||
#define JIT_FPR(i) (i)
|
||||
|
||||
#define jit_fxch(rs, op) (((rs) != 0 ? FXCHr(rs) : 0), \
|
||||
op, ((rs) != 0 ? FXCHr(rs) : 0))
|
||||
|
||||
#define jit_fp_unary(rd, s1, op) \
|
||||
((rd) == (s1) ? jit_fxch ((rd), op) \
|
||||
: (rd) == 0 ? (FSTPr (0), FLDr ((s1)-1), op) \
|
||||
: (FLDr ((s1)), op, FSTPr ((rd) + 1)))
|
||||
|
||||
#define jit_fp_binary(rd, s1, s2, op, opr) \
|
||||
((rd) == (s1) ? \
|
||||
((s2) == 0 ? opr(0, (rd)) \
|
||||
: (s2) == (s1) ? jit_fxch((rd), op(0, 0)) \
|
||||
: jit_fxch((rd), op((s2), 0))) \
|
||||
: (rd) == (s2) ? \
|
||||
((s1) == 0 ? op(0, (rd)) \
|
||||
: jit_fxch((rd), opr((s1), 0))) \
|
||||
: (FLDr (s1), op((s2)+1, 0), FSTPr((rd)+1)))
|
||||
|
||||
#define jit_addr_d(rd,s1,s2) jit_fp_binary((rd),(s1),(s2),FADDrr,FADDrr)
|
||||
#define jit_subr_d(rd,s1,s2) jit_fp_binary((rd),(s1),(s2),FSUBrr,FSUBRrr)
|
||||
#define jit_mulr_d(rd,s1,s2) jit_fp_binary((rd),(s1),(s2),FMULrr,FMULrr)
|
||||
#define jit_divr_d(rd,s1,s2) jit_fp_binary((rd),(s1),(s2),FDIVrr,FDIVRrr)
|
||||
|
||||
#define jit_abs_d(rd,rs) jit_fp_unary ((rd), (rs), _OO (0xd9e1))
|
||||
#define jit_negr_d(rd,rs) jit_fp_unary ((rd), (rs), _OO (0xd9e0))
|
||||
#define jit_sqrt_d(rd,rs) jit_fp_unary ((rd), (rs), _OO (0xd9fa))
|
||||
|
||||
/* - moves:
|
||||
|
||||
move FPR0 to FPR3
|
||||
FST ST3
|
||||
|
||||
move FPR3 to FPR0
|
||||
FXCH ST3
|
||||
FST ST3
|
||||
|
||||
move FPR3 to FPR1
|
||||
FLD ST3
|
||||
FSTP ST2 Stack is rotated, so FPRn becomes STn+1 */
|
||||
|
||||
#define jit_movr_d(rd,s1) \
|
||||
((s1) == (rd) ? 0 \
|
||||
: (s1) == 0 ? FSTr ((rd)) \
|
||||
: (rd) == 0 ? (FXCHr ((s1)), FSTr ((s1))) \
|
||||
: (FLDr ((s1)), FSTPr ((rd)+1)))
|
||||
|
||||
/* - loads:
|
||||
|
||||
load into FPR0
|
||||
FSTP ST0
|
||||
FLD [FUBAR]
|
||||
|
||||
load into FPR3
|
||||
FSTP ST3 Save old st0 into destination register
|
||||
FLD [FUBAR]
|
||||
FXCH ST3 Get back old st0
|
||||
|
||||
(and similarly for immediates, using the stack) */
|
||||
|
||||
#define jit_movi_f(rd,immf) \
|
||||
(_O (0x68), \
|
||||
*((float *) _jit.x.pc) = (float) immf, \
|
||||
_jit.x.uc_pc += sizeof (float), \
|
||||
jit_ldr_f((rd), _ESP), \
|
||||
ADDLir(4, _ESP))
|
||||
|
||||
union jit_double_imm {
|
||||
double d;
|
||||
int i[2];
|
||||
};
|
||||
|
||||
#define jit_movi_d(rd,immd) \
|
||||
(_O (0x68), \
|
||||
_jit.x.uc_pc[4] = 0x68, \
|
||||
((union jit_double_imm *) (_jit.x.uc_pc + 5))->d = (double) immd, \
|
||||
*((int *) _jit.x.uc_pc) = ((union jit_double_imm *) (_jit.x.uc_pc + 5))->i[1], \
|
||||
_jit.x.uc_pc += 9, \
|
||||
jit_ldr_d((rd), _ESP), \
|
||||
ADDLir(8, _ESP))
|
||||
|
||||
#define jit_ldi_f(rd, is) \
|
||||
((rd) == 0 ? (FSTPr (0), FLDSm((is), 0, 0, 0)) \
|
||||
: (FLDSm((is), 0, 0, 0), FSTPr ((rd) + 1)))
|
||||
|
||||
#define jit_ldi_d(rd, is) \
|
||||
((rd) == 0 ? (FSTPr (0), FLDLm((is), 0, 0, 0)) \
|
||||
: (FLDLm((is), 0, 0, 0), FSTPr ((rd) + 1)))
|
||||
|
||||
#define jit_ldr_f(rd, rs) \
|
||||
((rd) == 0 ? (FSTPr (0), FLDSm(0, (rs), 0, 0)) \
|
||||
: (FLDSm(0, (rs), 0, 0), FSTPr ((rd) + 1)))
|
||||
|
||||
#define jit_ldr_d(rd, rs) \
|
||||
((rd) == 0 ? (FSTPr (0), FLDLm(0, (rs), 0, 0)) \
|
||||
: (FLDLm(0, (rs), 0, 0), FSTPr ((rd) + 1)))
|
||||
|
||||
#define jit_ldxi_f(rd, rs, is) \
|
||||
((rd) == 0 ? (FSTPr (0), FLDSm((is), (rs), 0, 0)) \
|
||||
: (FLDSm((is), (rs), 0, 0), FSTPr ((rd) + 1)))
|
||||
|
||||
#define jit_ldxi_d(rd, rs, is) \
|
||||
((rd) == 0 ? (FSTPr (0), FLDLm((is), (rs), 0, 0)) \
|
||||
: (FLDLm((is), (rs), 0, 0), FSTPr ((rd) + 1)))
|
||||
|
||||
#define jit_ldxr_f(rd, s1, s2) \
|
||||
((rd) == 0 ? (FSTPr (0), FLDSm(0, (s1), (s2), 1)) \
|
||||
: (FLDSm(0, (s1), (s2), 1), FSTPr ((rd) + 1)))
|
||||
|
||||
#define jit_ldxr_d(rd, s1, s2) \
|
||||
((rd) == 0 ? (FSTPr (0), FLDLm(0, (s1), (s2), 1)) \
|
||||
: (FLDLm(0, (s1), (s2), 1), FSTPr ((rd) + 1)))
|
||||
|
||||
#define jit_extr_i_d(rd, rs) (PUSHLr((rs)), \
|
||||
((rd) == 0 ? (FSTPr (0), FILDLm(0, _ESP, 0, 0)) \
|
||||
: (FILDLm(0, _ESP, 0, 0), FSTPr ((rd) + 1))), \
|
||||
POPLr((rs)))
|
||||
|
||||
#define jit_stxi_f(id, rd, rs) jit_fxch ((rs), FSTSm((id), (rd), 0, 0))
|
||||
#define jit_stxr_f(d1, d2, rs) jit_fxch ((rs), FSTSm(0, (d1), (d2), 1))
|
||||
#define jit_stxi_d(id, rd, rs) jit_fxch ((rs), FSTLm((id), (rd), 0, 0))
|
||||
#define jit_stxr_d(d1, d2, rs) jit_fxch ((rs), FSTLm(0, (d1), (d2), 1))
|
||||
#define jit_sti_f(id, rs) jit_fxch ((rs), FSTSm((id), 0, 0, 0))
|
||||
#define jit_str_f(rd, rs) jit_fxch ((rs), FSTSm(0, (rd), 0, 0))
|
||||
#define jit_sti_d(id, rs) jit_fxch ((rs), FSTLm((id), 0, 0, 0))
|
||||
#define jit_str_d(rd, rs) jit_fxch ((rs), FSTLm(0, (rd), 0, 0))
|
||||
|
||||
/* ABI */
|
||||
#define jit_retval_d(rd) FSTPr((rd) + 1)
|
||||
|
||||
/* Assume round to near mode */
|
||||
#define jit_floorr_d_i(rd, rs) \
|
||||
(FLDr (rs), jit_floor2((rd), ((rd) == _EDX ? _EAX : _EDX)))
|
||||
|
||||
#define jit_ceilr_d_i(rd, rs) \
|
||||
(FLDr (rs), jit_ceil2((rd), ((rd) == _EDX ? _EAX : _EDX)))
|
||||
|
||||
#define jit_truncr_d_i(rd, rs) \
|
||||
(FLDr (rs), jit_trunc2((rd), ((rd) == _EDX ? _EAX : _EDX)))
|
||||
|
||||
#define jit_calc_diff(ofs) \
|
||||
FISTLm(ofs, _ESP, 0, 0), \
|
||||
FILDLm(ofs, _ESP, 0, 0), \
|
||||
FSUBRPr(1), \
|
||||
FSTPSm(4+ofs, _ESP, 0, 0) \
|
||||
|
||||
/* The real meat */
|
||||
#define jit_floor2(rd, aux) \
|
||||
(PUSHLr(aux), \
|
||||
SUBLir(8, _ESP), \
|
||||
jit_calc_diff(0), \
|
||||
POPLr(rd), /* floor in rd */ \
|
||||
POPLr(aux), /* x-round(x) in aux */ \
|
||||
ADDLir(0x7FFFFFFF, aux), /* carry if x-round(x) < -0 */ \
|
||||
SBBLir(0, rd), /* subtract 1 if carry */ \
|
||||
POPLr(aux))
|
||||
|
||||
#define jit_ceil2(rd, aux) \
|
||||
(PUSHLr(aux), \
|
||||
SUBLir(8, _ESP), \
|
||||
jit_calc_diff(0), \
|
||||
POPLr(rd), /* floor in rd */ \
|
||||
POPLr(aux), /* x-round(x) in aux */ \
|
||||
TESTLrr(aux, aux), \
|
||||
SETGr(jit_reg8(aux)), \
|
||||
SHRLir(1, aux), \
|
||||
ADCLir(0, rd), \
|
||||
POPLr(aux))
|
||||
|
||||
/* a mingling of the two above */
|
||||
#define jit_trunc2(rd, aux) \
|
||||
(PUSHLr(aux), \
|
||||
SUBLir(12, _ESP), \
|
||||
FSTSm(0, _ESP, 0, 0), \
|
||||
jit_calc_diff(4), \
|
||||
POPLr(aux), \
|
||||
POPLr(rd), \
|
||||
TESTLrr(aux, aux), \
|
||||
POPLr(aux), \
|
||||
JSSm(_jit.x.pc + 11), \
|
||||
ADDLir(0x7FFFFFFF, aux), /* 6 */ \
|
||||
SBBLir(0, rd), /* 3 */ \
|
||||
JMPSm(_jit.x.pc + 10), /* 2 */ \
|
||||
TESTLrr(aux, aux), /* 2 */ \
|
||||
SETGr(jit_reg8(aux)), /* 3 */ \
|
||||
SHRLir(1, aux), /* 2 */ \
|
||||
ADCLir(0, rd), /* 3 */ \
|
||||
POPLr(aux))
|
||||
|
||||
/* the easy one */
|
||||
#define jit_roundr_d_i(rd, rs) \
|
||||
(PUSHLr(_EAX), \
|
||||
jit_fxch ((rs), FISTLm(0, _ESP, 0, 0)), \
|
||||
POPLr((rd)))
|
||||
|
||||
#define jit_fp_test(d, s1, s2, n, _and, res) \
|
||||
(((s1) == 0 ? FUCOMr((s2)) : (FLDr((s1)), FUCOMPr((s2) + 1))), \
|
||||
((d) != _EAX ? MOVLrr(_EAX, (d)) : 0), \
|
||||
FNSTSWr(_EAX), \
|
||||
SHRLir(n, _EAX), \
|
||||
((_and) ? ANDLir((_and), _EAX) : MOVLir(0, _EAX)), \
|
||||
res, \
|
||||
((d) != _EAX ? _O (0x90 + ((d) & 7)) : 0)) /* xchg */
|
||||
|
||||
#define jit_fp_btest(d, s1, s2, n, _and, cmp, res) \
|
||||
(((s1) == 0 ? FUCOMr((s2)) : (FLDr((s1)), FUCOMPr((s2) + 1))), \
|
||||
PUSHLr(_EAX), \
|
||||
FNSTSWr(_EAX), \
|
||||
SHRLir(n, _EAX), \
|
||||
((_and) ? ANDLir ((_and), _EAX) : 0), \
|
||||
((cmp) ? CMPLir ((cmp), _EAX) : 0), \
|
||||
POPLr(_EAX), \
|
||||
res ((d)), \
|
||||
_jit.x.pc)
|
||||
|
||||
#define jit_nothing_needed(x)
|
||||
|
||||
/* After FNSTSW we have 1 if <, 40 if =, 0 if >, 45 if unordered. Here
|
||||
is how to map the values of the status word's high byte to the
|
||||
conditions.
|
||||
|
||||
< = > unord valid values condition
|
||||
gt no no yes no 0 STSW & 45 == 0
|
||||
lt yes no no no 1 STSW & 45 == 1
|
||||
eq no yes no no 40 STSW & 45 == 40
|
||||
unord no no no yes 45 bit 2 == 1
|
||||
|
||||
ge no yes no no 0, 40 bit 0 == 0
|
||||
unlt yes no no yes 1, 45 bit 0 == 1
|
||||
ltgt yes no yes no 0, 1 bit 6 == 0
|
||||
uneq no yes no yes 40, 45 bit 6 == 1
|
||||
le yes yes no no 1, 40 odd parity for STSW & 41
|
||||
ungt no no yes yes 0, 45 even parity for STSW & 41
|
||||
|
||||
unle yes yes no yes 1, 40, 45 STSW & 45 != 0
|
||||
unge no yes yes yes 0, 40, 45 STSW & 45 != 1
|
||||
ne yes no yes yes 0, 1, 45 STSW & 45 != 40
|
||||
ord yes yes yes no 0, 1, 40 bit 2 == 0
|
||||
|
||||
lt, le, ungt, unge are actually computed as gt, ge, unlt, unle with
|
||||
the operands swapped; it is more efficient this way. */
|
||||
|
||||
#define jit_gtr_d(d, s1, s2) jit_fp_test((d), (s1), (s2), 8, 0x45, SETZr (_AL))
|
||||
#define jit_ger_d(d, s1, s2) jit_fp_test((d), (s1), (s2), 9, 0, SBBBir (-1, _AL))
|
||||
#define jit_unler_d(d, s1, s2) jit_fp_test((d), (s1), (s2), 8, 0x45, SETNZr (_AL))
|
||||
#define jit_unltr_d(d, s1, s2) jit_fp_test((d), (s1), (s2), 9, 0, ADCBir (0, _AL))
|
||||
#define jit_ltr_d(d, s1, s2) jit_fp_test((d), (s2), (s1), 8, 0x45, SETZr (_AL))
|
||||
#define jit_ler_d(d, s1, s2) jit_fp_test((d), (s2), (s1), 9, 0, SBBBir (-1, _AL))
|
||||
#define jit_unger_d(d, s1, s2) jit_fp_test((d), (s2), (s1), 8, 0x45, SETNZr (_AL))
|
||||
#define jit_ungtr_d(d, s1, s2) jit_fp_test((d), (s2), (s1), 9, 0, ADCBir (0, _AL))
|
||||
#define jit_eqr_d(d, s1, s2) jit_fp_test((d), (s1), (s2), 8, 0x45, (CMPBir (0x40, _AL), SETEr (_AL)))
|
||||
#define jit_ner_d(d, s1, s2) jit_fp_test((d), (s1), (s2), 8, 0x45, (CMPBir (0x40, _AL), SETNEr (_AL)))
|
||||
#define jit_ltgtr_d(d, s1, s2) jit_fp_test((d), (s1), (s2), 15, 0, SBBBir (-1, _AL))
|
||||
#define jit_uneqr_d(d, s1, s2) jit_fp_test((d), (s1), (s2), 15, 0, ADCBir (0, _AL))
|
||||
#define jit_ordr_d(d, s1, s2) jit_fp_test((d), (s1), (s2), 11, 0, SBBBir (-1, _AL))
|
||||
#define jit_unordr_d(d, s1, s2) jit_fp_test((d), (s1), (s2), 11, 0, ADCBir (0, _AL))
|
||||
|
||||
#define jit_bgtr_d(d, s1, s2) jit_fp_btest((d), (s1), (s2), 8, 0x45, 0, JZm)
|
||||
#define jit_bger_d(d, s1, s2) jit_fp_btest((d), (s1), (s2), 9, 0, 0, JNCm)
|
||||
#define jit_bunler_d(d, s1, s2) jit_fp_btest((d), (s1), (s2), 8, 0x45, 0, JNZm)
|
||||
#define jit_bunltr_d(d, s1, s2) jit_fp_btest((d), (s1), (s2), 9, 0, 0, JCm)
|
||||
#define jit_bltr_d(d, s1, s2) jit_fp_btest((d), (s2), (s1), 8, 0x45, 0, JZm)
|
||||
#define jit_bler_d(d, s1, s2) jit_fp_btest((d), (s2), (s1), 9, 0, 0, JNCm)
|
||||
#define jit_bunger_d(d, s1, s2) jit_fp_btest((d), (s2), (s1), 8, 0x45, 0, JNZm)
|
||||
#define jit_bungtr_d(d, s1, s2) jit_fp_btest((d), (s2), (s1), 9, 0, 0, JCm)
|
||||
#define jit_beqr_d(d, s1, s2) jit_fp_btest((d), (s1), (s2), 8, 0x45, 0x40, JZm)
|
||||
#define jit_bner_d(d, s1, s2) jit_fp_btest((d), (s1), (s2), 8, 0x45, 0x40, JNZm)
|
||||
#define jit_bltgtr_d(d, s1, s2) jit_fp_btest((d), (s1), (s2), 15, 0, 0, JNCm)
|
||||
#define jit_buneqr_d(d, s1, s2) jit_fp_btest((d), (s1), (s2), 15, 0, 0, JCm)
|
||||
#define jit_bordr_d(d, s1, s2) jit_fp_btest((d), (s1), (s2), 11, 0, 0, JNCm)
|
||||
#define jit_bunordr_d(d, s1, s2) jit_fp_btest((d), (s1), (s2), 11, 0, 0, JCm)
|
||||
|
||||
#define jit_pusharg_d(rs) (jit_subi_i(JIT_SP,JIT_SP,sizeof(double)), jit_str_d(JIT_SP,(rs)))
|
||||
#define jit_pusharg_f(rs) (jit_subi_i(JIT_SP,JIT_SP,sizeof(float)), jit_str_f(JIT_SP,(rs)))
|
||||
|
||||
|
||||
#if 0
|
||||
#define jit_sin() _OO(0xd9fe) /* fsin */
|
||||
#define jit_cos() _OO(0xd9ff) /* fcos */
|
||||
#define jit_tan() (_OO(0xd9f2), /* fptan */ \
|
||||
FSTPr(0)) /* fstp st */
|
||||
#define jit_atn() (_OO(0xd9e8), /* fld1 */ \
|
||||
_OO(0xd9f3)) /* fpatan */
|
||||
#define jit_exp() (_OO(0xd9ea), /* fldl2e */ \
|
||||
FMULPr(1), /* fmulp */ \
|
||||
_OO(0xd9c0), /* fld st */ \
|
||||
_OO(0xd9fc), /* frndint */ \
|
||||
_OO(0xdce9), /* fsubr */ \
|
||||
FXCHr(1), /* fxch st(1) */ \
|
||||
_OO(0xd9f0), /* f2xm1 */ \
|
||||
_OO(0xd9e8), /* fld1 */ \
|
||||
_OO(0xdec1), /* faddp */ \
|
||||
_OO(0xd9fd), /* fscale */ \
|
||||
FSTPr(1)) /* fstp st(1) */
|
||||
#define jit_log() (_OO(0xd9ed), /* fldln2 */ \
|
||||
FXCHr(1), /* fxch st(1) */ \
|
||||
_OO(0xd9f1)) /* fyl2x */
|
||||
#endif
|
||||
|
||||
#define jit_prepare_f(nf) (_jitl.argssize += (nf))
|
||||
#define jit_prepare_d(nd) (_jitl.argssize += 2 * (nd))
|
||||
#define jit_arg_f() ((_jitl.framesize += sizeof(float)) - sizeof(float))
|
||||
#define jit_arg_d() ((_jitl.framesize += sizeof(double)) - sizeof(double))
|
||||
|
||||
#endif /* __lightning_fp_h */
|
||||
@@ -1,325 +0,0 @@
|
||||
/******************************** -*- C -*- ****************************
|
||||
*
|
||||
* Support macros for SSE floating-point math
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Copyright 2006 Free Software Foundation, Inc.
|
||||
* Written by Paolo Bonzini.
|
||||
*
|
||||
* This file is part of GNU lightning.
|
||||
*
|
||||
* GNU lightning is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU lightning is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with GNU lightning; see the file COPYING.LESSER; if not, write to the
|
||||
* Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
#ifndef __lightning_fp_h
|
||||
#define __lightning_fp_h
|
||||
|
||||
#include <float.h>
|
||||
|
||||
#define JIT_FPR_NUM 7
|
||||
#define JIT_FPRET _XMM0
|
||||
#define JIT_FPR(i) (_XMM8 + (i))
|
||||
#define JIT_FPTMP _XMM15
|
||||
|
||||
/* Either use a temporary register that is finally AND/OR/XORed with RS = RD,
|
||||
or use RD as the temporary register and to the AND/OR/XOR with RS. */
|
||||
#define jit_unop_tmp(rd, rs, op) \
|
||||
( (rs) == (rd) \
|
||||
? op((rd), JIT_FPTMP, JIT_FPTMP)) \
|
||||
: op((rd), (rd), (rs)))
|
||||
|
||||
#define jit_unop_f(rd, rs, op) \
|
||||
((rs) == (rd) ? op((rd)) : (MOVSSrr ((rs), (rd)), op((rd))))
|
||||
|
||||
#define jit_unop_d(rd, rs, op) \
|
||||
((rs) == (rd) ? op((rd)) : (MOVSDrr ((rs), (rd)), op((rd))))
|
||||
|
||||
#define jit_3opc_f(rd, s1, s2, op) \
|
||||
( (s1) == (rd) ? op((s2), (rd)) \
|
||||
: ((s2) == (rd) ? op((s1), (rd)) \
|
||||
: (MOVSSrr ((s1), (rd)), op((s2), (rd)))))
|
||||
|
||||
#define jit_3opc_d(rd, s1, s2, op) \
|
||||
( (s1) == (rd) ? op((s2), (rd)) \
|
||||
: ((s2) == (rd) ? op((s1), (rd)) \
|
||||
: (MOVSDrr ((s1), (rd)), op((s2), (rd)))))
|
||||
|
||||
#define jit_3op_f(rd, s1, s2, op) \
|
||||
( (s1) == (rd) ? op((s2), (rd)) \
|
||||
: ((s2) == (rd) \
|
||||
? (MOVSSrr ((rd), JIT_FPTMP), MOVSSrr ((s1), (rd)), op(JIT_FPTMP, (rd))) \
|
||||
: (MOVSSrr ((s1), (rd)), op((s2), (rd)))))
|
||||
|
||||
#define jit_3op_d(rd, s1, s2, op) \
|
||||
( (s1) == (rd) ? op((s2), (rd)) \
|
||||
: ((s2) == (rd) \
|
||||
? (MOVSDrr ((rd), JIT_FPTMP), MOVSDrr ((s1), (rd)), op(JIT_FPTMP, (rd))) \
|
||||
: (MOVSDrr ((s1), (rd)), op((s2), (rd)))))
|
||||
|
||||
#define jit_addr_f(rd,s1,s2) jit_3opc_f((rd), (s1), (s2), ADDSSrr)
|
||||
#define jit_subr_f(rd,s1,s2) jit_3op_f((rd), (s1), (s2), SUBSSrr)
|
||||
#define jit_mulr_f(rd,s1,s2) jit_3opc_f((rd), (s1), (s2), MULSSrr)
|
||||
#define jit_divr_f(rd,s1,s2) jit_3op_f((rd), (s1), (s2), DIVSSrr)
|
||||
|
||||
#define jit_addr_d(rd,s1,s2) jit_3opc_d((rd), (s1), (s2), ADDSDrr)
|
||||
#define jit_subr_d(rd,s1,s2) jit_3op_d((rd), (s1), (s2), SUBSDrr)
|
||||
#define jit_mulr_d(rd,s1,s2) jit_3opc_d((rd), (s1), (s2), MULSDrr)
|
||||
#define jit_divr_d(rd,s1,s2) jit_3op_d((rd), (s1), (s2), DIVSDrr)
|
||||
|
||||
#define jit_movr_f(rd,rs) MOVSSrr((rs), (rd))
|
||||
#define jit_movr_d(rd,rs) MOVSDrr((rs), (rd))
|
||||
|
||||
/* either pcmpeqd %xmm7, %xmm7 / psrld $1, %xmm7 / andps %xmm7, %RD (if RS = RD)
|
||||
or pcmpeqd %RD, %RD / psrld $1, %RD / andps %RS, %RD (if RS != RD) */
|
||||
#define _jit_abs_f(rd,cnst,rs) \
|
||||
(PCMPEQDrr((cnst), (cnst)), PSRLDir (1, (cnst)), ANDPSrr ((rs), (rd)))
|
||||
#define _jit_neg_f(rd,cnst,rs) \
|
||||
(PCMPEQDrr((cnst), (cnst)), PSLLDir (31, (cnst)), XORPSrr ((rs), (rd)))
|
||||
#define jit_abs_f(rd,rs) jit_unop_tmp ((rd), (rs), _jit_abs_f)
|
||||
#define jit_neg_f(rd,rs) jit_unop_tmp ((rd), (rs), _jit_neg_f)
|
||||
|
||||
#define _jit_abs_d(rd,cnst,rs) \
|
||||
(PCMPEQDrr((cnst), (cnst)), PSRLQir (1, (cnst)), ANDPDrr ((rs), (rd)))
|
||||
#define _jit_neg_d(rd,cnst,rs) \
|
||||
(PCMPEQDrr((cnst), (cnst)), PSLLQir (63, (cnst)), XORPDrr ((rs), (rd)))
|
||||
#define jit_abs_d(rd,rs) jit_unop_tmp ((rd), (rs), _jit_abs_d)
|
||||
#define jit_neg_d(rd,rs) jit_unop_tmp ((rd), (rs), _jit_neg_d)
|
||||
|
||||
#define jit_sqrt_d(rd,rs) SQRTSSrr((rs), (rd))
|
||||
#define jit_sqrt_f(rd,rs) SQRTSDrr((rs), (rd))
|
||||
|
||||
#define _jit_ldi_f(d, is) MOVSSmr((is), 0, 0, 0, (d))
|
||||
#define _jit_ldxi_f(d, rs, is) MOVSSmr((is), (rs), 0, 0, (d))
|
||||
#define jit_ldr_f(d, rs) MOVSSmr(0, (rs), 0, 0, (d))
|
||||
#define jit_ldxr_f(d, s1, s2) MOVSSmr(0, (s1), (s2), 1, (d))
|
||||
|
||||
#define _jit_sti_f(id, rs) MOVSSrm((rs), (id), 0, 0, 0)
|
||||
#define _jit_stxi_f(id, rd, rs) MOVSSrm((rs), (id), (rd), 0, 0)
|
||||
#define jit_str_f(rd, rs) MOVSSrm((rs), 0, (rd), 0, 0)
|
||||
#define jit_stxr_f(d1, d2, rs) MOVSSrm((rs), 0, (d1), (d2), 1)
|
||||
|
||||
#define jit_ldi_f(d, is) (_u32P((long)(is)) ? _jit_ldi_f((d), (is)) : (jit_movi_l(JIT_REXTMP, (is)), jit_ldr_f((d), JIT_REXTMP)))
|
||||
#define jit_sti_f(id, rs) (_u32P((long)(id)) ? _jit_sti_f((id), (rs)) : (jit_movi_l(JIT_REXTMP, (id)), jit_str_f (JIT_REXTMP, (rs))))
|
||||
#define jit_ldxi_f(d, rs, is) (_u32P((long)(is)) ? _jit_ldxi_f((d), (rs), (is)) : (jit_movi_l(JIT_REXTMP, (is)), jit_ldxr_f((d), (rs), JIT_REXTMP)))
|
||||
#define jit_stxi_f(id, rd, rs) (_u32P((long)(id)) ? _jit_stxi_f((id), (rd), (rs)) : (jit_movi_l(JIT_REXTMP, (id)), jit_stxr_f (JIT_REXTMP, (rd), (rs))))
|
||||
|
||||
#define _jit_ldi_d(d, is) MOVSDmr((is), 0, 0, 0, (d))
|
||||
#define _jit_ldxi_d(d, rs, is) MOVSDmr((is), (rs), 0, 0, (d))
|
||||
#define jit_ldr_d(d, rs) MOVSDmr(0, (rs), 0, 0, (d))
|
||||
#define jit_ldxr_d(d, s1, s2) MOVSDmr(0, (s1), (s2), 1, (d))
|
||||
|
||||
#define _jit_sti_d(id, rs) MOVSDrm((rs), (id), 0, 0, 0)
|
||||
#define _jit_stxi_d(id, rd, rs) MOVSDrm((rs), (id), (rd), 0, 0)
|
||||
#define jit_str_d(rd, rs) MOVSDrm((rs), 0, (rd), 0, 0)
|
||||
#define jit_stxr_d(d1, d2, rs) MOVSDrm((rs), 0, (d1), (d2), 1)
|
||||
|
||||
#define jit_ldi_d(d, is) (_u32P((long)(is)) ? _jit_ldi_d((d), (is)) : (jit_movi_l(JIT_REXTMP, (is)), jit_ldr_d((d), JIT_REXTMP)))
|
||||
#define jit_sti_d(id, rs) (_u32P((long)(id)) ? _jit_sti_d((id), (rs)) : (jit_movi_l(JIT_REXTMP, (id)), jit_str_d (JIT_REXTMP, (rs))))
|
||||
#define jit_ldxi_d(d, rs, is) (_u32P((long)(is)) ? _jit_ldxi_d((d), (rs), (is)) : (jit_movi_l(JIT_REXTMP, (is)), jit_ldxr_d((d), (rs), JIT_REXTMP)))
|
||||
#define jit_stxi_d(id, rd, rs) (_u32P((long)(id)) ? _jit_stxi_d((id), (rd), (rs)) : (jit_movi_l(JIT_REXTMP, (id)), jit_stxr_d (JIT_REXTMP, (rd), (rs))))
|
||||
|
||||
|
||||
#define jit_movi_f(rd,immf) \
|
||||
((immf) == 0.0 ? XORSSrr ((rd), (rd)) : \
|
||||
(PUSHQi (0x12345678L), \
|
||||
*((float *) (_jit.x.uc_pc - 4)) = (float) immf, \
|
||||
jit_ldr_f((rd), _ESP), \
|
||||
ADDQir(8, _ESP)))
|
||||
|
||||
union jit_double_imm {
|
||||
double d;
|
||||
long l;
|
||||
};
|
||||
|
||||
#define jit_movi_d(rd,immd) \
|
||||
((immd) == 0.0 ? XORSDrr ((rd), (rd)) : \
|
||||
(_O (0x50), \
|
||||
MOVQir (0x123456789abcdef0L, _EAX), \
|
||||
((union jit_double_imm *) (_jit.x.uc_pc - 8))->d = (double) immd, \
|
||||
_O (0x50), jit_ldr_d((rd), _ESP), \
|
||||
_O (0x58), _O (0x58)))
|
||||
|
||||
#define jit_extr_i_d(rd, rs) CVTSI2SDLrr((rs), (rd))
|
||||
#define jit_extr_i_f(rd, rs) CVTSI2SSLrr((rs), (rd))
|
||||
#define jit_extr_l_d(rd, rs) CVTSI2SDQrr((rs), (rd))
|
||||
#define jit_extr_l_f(rd, rs) CVTSI2SSQrr((rs), (rd))
|
||||
#define jit_extr_f_d(rd, rs) CVTSS2SDrr((rs), (rd))
|
||||
#define jit_extr_d_f(rd, rs) CVTSD2SSrr((rs), (rd))
|
||||
#define jit_roundr_d_i(rd, rs) CVTSD2SILrr((rs), (rd))
|
||||
#define jit_roundr_f_i(rd, rs) CVTSS2SILrr((rs), (rd))
|
||||
#define jit_roundr_d_l(rd, rs) CVTSD2SIQrr((rs), (rd))
|
||||
#define jit_roundr_f_l(rd, rs) CVTSS2SIQrr((rs), (rd))
|
||||
#define jit_truncr_d_i(rd, rs) CVTTSD2SILrr((rs), (rd))
|
||||
#define jit_truncr_f_i(rd, rs) CVTTSS2SILrr((rs), (rd))
|
||||
#define jit_truncr_d_l(rd, rs) CVTTSD2SIQrr((rs), (rd))
|
||||
#define jit_truncr_f_l(rd, rs) CVTTSS2SIQrr((rs), (rd))
|
||||
|
||||
|
||||
#define jit_ceilr_f_i(rd, rs) do { \
|
||||
jit_roundr_f_i ((rd), (rs)); \
|
||||
jit_extr_i_f (JIT_FPTMP, (rd)); \
|
||||
UCOMISSrr ((rs), JIT_FPTMP); \
|
||||
ADCLir (0, (rd)); \
|
||||
} while (0)
|
||||
|
||||
#define jit_ceilr_d_i(rd, rs) do { \
|
||||
jit_roundr_d_i ((rd), (rs)); \
|
||||
jit_extr_i_d (JIT_FPTMP, (rd)); \
|
||||
UCOMISDrr ((rs), JIT_FPTMP); \
|
||||
ADCLir (0, (rd)); \
|
||||
} while (0)
|
||||
|
||||
#define jit_ceilr_f_l(rd, rs) do { \
|
||||
jit_roundr_f_l ((rd), (rs)); \
|
||||
jit_extr_l_f (JIT_FPTMP, (rd)); \
|
||||
UCOMISSrr ((rs), JIT_FPTMP); \
|
||||
ADCLir (0, (rd)); \
|
||||
} while (0)
|
||||
|
||||
#define jit_ceilr_d_l(rd, rs) do { \
|
||||
jit_roundr_d_l ((rd), (rs)); \
|
||||
jit_extr_l_d (JIT_FPTMP, (rd)); \
|
||||
UCOMISDrr ((rs), JIT_FPTMP); \
|
||||
ADCLir (0, (rd)); \
|
||||
} while (0)
|
||||
|
||||
#define jit_floorr_f_i(rd, rs) do { \
|
||||
jit_roundr_f_i ((rd), (rs)); \
|
||||
jit_extr_i_f (JIT_FPTMP, (rd)); \
|
||||
UCOMISSrr (JIT_FPTMP, (rs)); \
|
||||
SBBLir (0, (rd)); \
|
||||
} while (0)
|
||||
|
||||
#define jit_floorr_d_i(rd, rs) do { \
|
||||
jit_roundr_d_i ((rd), (rs)); \
|
||||
jit_extr_i_d (JIT_FPTMP, (rd)); \
|
||||
UCOMISDrr (JIT_FPTMP, (rs)); \
|
||||
SBBLir (0, (rd)); \
|
||||
} while (0)
|
||||
|
||||
#define jit_floorr_f_l(rd, rs) do { \
|
||||
jit_roundr_f_l ((rd), (rs)); \
|
||||
jit_extr_l_f (JIT_FPTMP, (rd)); \
|
||||
UCOMISSrr (JIT_FPTMP, (rs)); \
|
||||
SBBLir (0, (rd)); \
|
||||
} while (0)
|
||||
|
||||
#define jit_floorr_d_l(rd, rs) do { \
|
||||
jit_roundr_d_l ((rd), (rs)); \
|
||||
jit_extr_l_d (JIT_FPTMP, (rd)); \
|
||||
UCOMISDrr (JIT_FPTMP, (rs)); \
|
||||
SBBLir (0, (rd)); \
|
||||
} while (0)
|
||||
|
||||
#define jit_bltr_f(d, s1, s2) (UCOMISSrr ((s1), (s2)), JAm ((d)), _jit.x.pc)
|
||||
#define jit_bler_f(d, s1, s2) (UCOMISSrr ((s1), (s2)), JAEm ((d)), _jit.x.pc)
|
||||
#define jit_beqr_f(d, s1, s2) (UCOMISSrr ((s1), (s2)), _OO (0x7a06), JEm ((d)), _jit.x.pc)
|
||||
#define jit_bner_f(d, s1, s2) (UCOMISSrr ((s1), (s2)), _OO (0x7a02), _OO (0x7405), JMPm (((d))), _jit.x.pc) /* JP to JMP, JZ past JMP */
|
||||
#define jit_bger_f(d, s1, s2) (UCOMISSrr ((s2), (s1)), JAEm ((d)), _jit.x.pc)
|
||||
#define jit_bgtr_f(d, s1, s2) (UCOMISSrr ((s2), (s1)), JAm ((d)), _jit.x.pc)
|
||||
#define jit_bunltr_f(d, s1, s2) (UCOMISSrr ((s2), (s1)), JNAEm ((d)), _jit.x.pc)
|
||||
#define jit_bunler_f(d, s1, s2) (UCOMISSrr ((s2), (s1)), JNAm ((d)), _jit.x.pc)
|
||||
#define jit_buneqr_f(d, s1, s2) (UCOMISSrr ((s1), (s2)), JEm ((d)), _jit.x.pc)
|
||||
#define jit_bltgtr_f(d, s1, s2) (UCOMISSrr ((s1), (s2)), JNEm ((d)), _jit.x.pc)
|
||||
#define jit_bunger_f(d, s1, s2) (UCOMISSrr ((s1), (s2)), JNAm ((d)), _jit.x.pc)
|
||||
#define jit_bungtr_f(d, s1, s2) (UCOMISSrr ((s1), (s2)), JNAEm ((d)), _jit.x.pc)
|
||||
#define jit_bordr_f(d, s1, s2) (UCOMISSrr ((s1), (s2)), JNPm ((d)), _jit.x.pc)
|
||||
#define jit_bunordr_f(d, s1, s2) (UCOMISSrr ((s1), (s2)), JPm ((d)), _jit.x.pc)
|
||||
|
||||
#define jit_bltr_d(d, s1, s2) (UCOMISDrr ((s1), (s2)), JAm ((d)), _jit.x.pc)
|
||||
#define jit_bler_d(d, s1, s2) (UCOMISDrr ((s1), (s2)), JAEm ((d)), _jit.x.pc)
|
||||
#define jit_beqr_d(d, s1, s2) (UCOMISDrr ((s1), (s2)), _OO (0x7a06), JEm ((d)), _jit.x.pc)
|
||||
#define jit_bner_d(d, s1, s2) (UCOMISDrr ((s1), (s2)), _OO (0x7a02), _OO (0x7405), JMPm (((d))), _jit.x.pc) /* JP to JMP, JZ past JMP */
|
||||
#define jit_bger_d(d, s1, s2) (UCOMISDrr ((s2), (s1)), JAEm ((d)), _jit.x.pc)
|
||||
#define jit_bgtr_d(d, s1, s2) (UCOMISDrr ((s2), (s1)), JAm ((d)), _jit.x.pc)
|
||||
#define jit_bunltr_d(d, s1, s2) (UCOMISDrr ((s2), (s1)), JNAEm ((d)), _jit.x.pc, _jit.x.pc)
|
||||
#define jit_bunler_d(d, s1, s2) (UCOMISDrr ((s2), (s1)), JNAm ((d)), _jit.x.pc)
|
||||
#define jit_buneqr_d(d, s1, s2) (UCOMISDrr ((s1), (s2)), JEm ((d)), _jit.x.pc)
|
||||
#define jit_bltgtr_d(d, s1, s2) (UCOMISDrr ((s1), (s2)), JNEm ((d)), _jit.x.pc)
|
||||
#define jit_bunger_d(d, s1, s2) (UCOMISDrr ((s1), (s2)), JNAm ((d)), _jit.x.pc)
|
||||
#define jit_bungtr_d(d, s1, s2) (UCOMISDrr ((s1), (s2)), JNAEm ((d)), _jit.x.pc)
|
||||
#define jit_bordr_d(d, s1, s2) (UCOMISDrr ((s1), (s2)), JNPm ((d)), _jit.x.pc)
|
||||
#define jit_bunordr_d(d, s1, s2) (UCOMISDrr ((s1), (s2)), JPm ((d)), _jit.x.pc)
|
||||
|
||||
#define jit_ltr_f(d, s1, s2) (XORLrr ((d), (d)), UCOMISSrr ((s1), (s2)), SETAr (jit_reg8((d))))
|
||||
#define jit_ler_f(d, s1, s2) (XORLrr ((d), (d)), UCOMISSrr ((s1), (s2)), SETAEr (jit_reg8((d))))
|
||||
#define jit_eqr_f(d, s1, s2) (XORLrr ((d), (d)), UCOMISSrr ((s1), (s2)), _OO(0x7a03), SETEr (jit_reg8((d))))
|
||||
#define jit_ner_f(d, s1, s2) (UCOMISSrr ((s1), (s2)), MOVLir (1, (d)), _OO(0x7a03), SETNEr (jit_reg8((d))))
|
||||
#define jit_ger_f(d, s1, s2) (XORLrr ((d), (d)), UCOMISSrr ((s2), (s1)), SETAEr (jit_reg8((d))))
|
||||
#define jit_gtr_f(d, s1, s2) (XORLrr ((d), (d)), UCOMISSrr ((s2), (s1)), SETAr (jit_reg8((d))))
|
||||
#define jit_unltr_f(d, s1, s2) (XORLrr ((d), (d)), UCOMISSrr ((s2), (s1)), SETNAEr (jit_reg8((d))))
|
||||
#define jit_unler_f(d, s1, s2) (XORLrr ((d), (d)), UCOMISSrr ((s2), (s1)), SETNAr (jit_reg8((d))))
|
||||
#define jit_uneqr_f(d, s1, s2) (XORLrr ((d), (d)), UCOMISSrr ((s1), (s2)), SETEr (jit_reg8((d))))
|
||||
#define jit_ltgtr_f(d, s1, s2) (XORLrr ((d), (d)), UCOMISSrr ((s1), (s2)), SETNEr (jit_reg8((d))))
|
||||
#define jit_unger_f(d, s1, s2) (XORLrr ((d), (d)), UCOMISSrr ((s1), (s2)), SETNAr (jit_reg8((d))))
|
||||
#define jit_ungtr_f(d, s1, s2) (XORLrr ((d), (d)), UCOMISSrr ((s1), (s2)), SETNAEr (jit_reg8((d))))
|
||||
#define jit_ordr_f(d, s1, s2) (XORLrr ((d), (d)), UCOMISSrr ((s1), (s2)), SETNPr (jit_reg8((d))))
|
||||
#define jit_unordr_f(d, s1, s2) (XORLrr ((d), (d)), UCOMISSrr ((s1), (s2)), SETPr (jit_reg8((d))))
|
||||
|
||||
#define jit_ltr_d(d, s1, s2) (XORLrr ((d), (d)), UCOMISDrr ((s1), (s2)), SETAr (jit_reg8((d))))
|
||||
#define jit_ler_d(d, s1, s2) (XORLrr ((d), (d)), UCOMISDrr ((s1), (s2)), SETAEr (jit_reg8((d))))
|
||||
#define jit_eqr_d(d, s1, s2) (XORLrr ((d), (d)), UCOMISDrr ((s1), (s2)), _OO(0x7a03), SETEr (jit_reg8((d))))
|
||||
#define jit_ner_d(d, s1, s2) (UCOMISDrr ((s1), (s2)), MOVLir (1, (d)), _OO(0x7a03), SETNEr (jit_reg8((d))))
|
||||
#define jit_ger_d(d, s1, s2) (XORLrr ((d), (d)), UCOMISDrr ((s2), (s1)), SETAEr (jit_reg8((d))))
|
||||
#define jit_gtr_d(d, s1, s2) (XORLrr ((d), (d)), UCOMISDrr ((s2), (s1)), SETAr (jit_reg8((d))))
|
||||
#define jit_unltr_d(d, s1, s2) (XORLrr ((d), (d)), UCOMISDrr ((s2), (s1)), SETNAEr (jit_reg8((d))))
|
||||
#define jit_unler_d(d, s1, s2) (XORLrr ((d), (d)), UCOMISDrr ((s2), (s1)), SETNAr (jit_reg8((d))))
|
||||
#define jit_uneqr_d(d, s1, s2) (XORLrr ((d), (d)), UCOMISDrr ((s1), (s2)), SETEr (jit_reg8((d))))
|
||||
#define jit_ltgtr_d(d, s1, s2) (XORLrr ((d), (d)), UCOMISDrr ((s1), (s2)), SETNEr (jit_reg8((d))))
|
||||
#define jit_unger_d(d, s1, s2) (XORLrr ((d), (d)), UCOMISDrr ((s1), (s2)), SETNAr (jit_reg8((d))))
|
||||
#define jit_ungtr_d(d, s1, s2) (XORLrr ((d), (d)), UCOMISDrr ((s1), (s2)), SETNAEr (jit_reg8((d))))
|
||||
#define jit_ordr_d(d, s1, s2) (XORLrr ((d), (d)), UCOMISDrr ((s1), (s2)), SETNPr (jit_reg8((d))))
|
||||
#define jit_unordr_d(d, s1, s2) (XORLrr ((d), (d)), UCOMISDrr ((s1), (s2)), SETPr (jit_reg8((d))))
|
||||
|
||||
#define jit_prepare_f(num) ((_jitl.nextarg_putfp + (num) > JIT_FP_ARG_MAX \
|
||||
? (_jitl.argssize += _jitl.nextarg_putfp + (num) - JIT_FP_ARG_MAX, \
|
||||
_jitl.fprssize = JIT_FP_ARG_MAX) \
|
||||
: (_jitl.fprssize += (num))), \
|
||||
_jitl.nextarg_putfp += (num))
|
||||
#define jit_prepare_d(num) ((_jitl.nextarg_putfp + (num) > JIT_FP_ARG_MAX \
|
||||
? (_jitl.argssize += _jitl.nextarg_putfp + (num) - JIT_FP_ARG_MAX, \
|
||||
_jitl.fprssize = JIT_FP_ARG_MAX) \
|
||||
: (_jitl.fprssize += (num))), \
|
||||
_jitl.nextarg_putfp += (num))
|
||||
|
||||
#define jit_arg_f() (_jitl.nextarg_getfp < JIT_FP_ARG_MAX \
|
||||
? _jitl.nextarg_getfp++ \
|
||||
: ((_jitl.framesize += sizeof(double)) - sizeof(double)))
|
||||
#define jit_arg_d() (_jitl.nextarg_getfp < JIT_FP_ARG_MAX \
|
||||
? _jitl.nextarg_getfp++ \
|
||||
: ((_jitl.framesize += sizeof(double)) - sizeof(double)))
|
||||
|
||||
#define jit_getarg_f(reg, ofs) ((ofs) < JIT_FP_ARG_MAX \
|
||||
? jit_movr_f((reg), _XMM0 + (ofs)) \
|
||||
: jit_ldxi_f((reg), JIT_FP, (ofs)))
|
||||
#define jit_getarg_d(reg, ofs) ((ofs) < JIT_FP_ARG_MAX \
|
||||
? jit_movr_d((reg), _XMM0 + (ofs)) \
|
||||
: jit_ldxi_d((reg), JIT_FP, (ofs)))
|
||||
|
||||
#define jit_pusharg_f(rs) (--_jitl.nextarg_putfp >= JIT_FP_ARG_MAX \
|
||||
? (SUBQir(sizeof(double), JIT_SP), jit_str_f(JIT_SP,(rs))) \
|
||||
: jit_movr_f(_XMM0 + _jitl.nextarg_putfp, (rs)))
|
||||
#define jit_pusharg_d(rs) (--_jitl.nextarg_putfp >= JIT_FP_ARG_MAX \
|
||||
? (SUBQir(sizeof(double), JIT_SP), jit_str_d(JIT_SP,(rs))) \
|
||||
: jit_movr_d(_XMM0 + _jitl.nextarg_putfp, (rs)))
|
||||
|
||||
#endif /* __lightning_fp_h */
|
||||
@@ -1,45 +0,0 @@
|
||||
/******************************** -*- C -*- ****************************
|
||||
*
|
||||
* Floating-point support (i386)
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Copyright 2008 Free Software Foundation, Inc.
|
||||
* Written by Paolo Bonzini.
|
||||
*
|
||||
* This file is part of GNU lightning.
|
||||
*
|
||||
* GNU lightning is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU lightning is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with GNU lightning; see the file COPYING.LESSER; if not, write to the
|
||||
* Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef __lightning_fp_i386_h
|
||||
#define __lightning_fp_i386_h
|
||||
|
||||
#if LIGHTNING_CROSS \
|
||||
? LIGHTNING_TARGET == LIGHTNING_X86_64 \
|
||||
: defined (__x86_64__)
|
||||
#include "i386/fp-64.h"
|
||||
#else
|
||||
#include "i386/fp-32.h"
|
||||
#endif
|
||||
|
||||
#endif /* __lightning_fp_i386_h */
|
||||
@@ -1,92 +0,0 @@
|
||||
/******************************** -*- C -*- ****************************
|
||||
*
|
||||
* Platform-independent layer inline functions (i386)
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Copyright 2000, 2001, 2002, 2006 Free Software Foundation, Inc.
|
||||
* Written by Paolo Bonzini.
|
||||
*
|
||||
* This file is part of GNU lightning.
|
||||
*
|
||||
* GNU lightning is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU lightning is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with GNU lightning; see the file COPYING.LESSER; if not, write to the
|
||||
* Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef __lightning_funcs_h
|
||||
#define __lightning_funcs_h
|
||||
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
static void
|
||||
jit_flush_code(void *dest, void *end)
|
||||
{
|
||||
/* On the x86, the PROT_EXEC bits are not handled by the MMU.
|
||||
However, the kernel can emulate this by setting the code
|
||||
segment's limit to the end address of the highest page
|
||||
whose PROT_EXEC bit is set.
|
||||
|
||||
Linux kernels that do so and that disable by default the
|
||||
execution of the data and stack segment are becoming more
|
||||
and more common (Fedora, for example), so we implement our
|
||||
jit_flush_code as an mprotect. */
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
static unsigned long prev_page = 0, prev_length = 0;
|
||||
unsigned long page, length;
|
||||
#ifdef PAGESIZE
|
||||
const int page_size = PAGESIZE;
|
||||
#else
|
||||
static int page_size = -1;
|
||||
if (page_size == -1)
|
||||
page_size = getpagesize();
|
||||
#endif
|
||||
|
||||
page = (long) dest & ~(page_size - 1);
|
||||
length = ((char *) end - (char *) page + page_size - 1) & ~(page_size - 1);
|
||||
|
||||
/* Simple-minded attempt at optimizing the common case where a single
|
||||
chunk of memory is used to compile multiple functions. */
|
||||
if (page >= prev_page && page + length <= prev_page + prev_length)
|
||||
return;
|
||||
|
||||
mprotect ((void *) page, length, PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||
|
||||
/* See if we can extend the previously mprotect'ed memory area towards
|
||||
higher addresses: the starting address remains the same as before. */
|
||||
if (page >= prev_page && page <= prev_page + prev_length)
|
||||
prev_length = page + length - prev_page;
|
||||
|
||||
/* See if we can extend the previously mprotect'ed memory area towards
|
||||
lower addresses: the highest address remains the same as before. */
|
||||
else if (page < prev_page && page + length >= prev_page
|
||||
&& page + length <= prev_page + prev_length)
|
||||
prev_length += prev_page - page, prev_page = page;
|
||||
|
||||
/* Nothing to do, replace the area. */
|
||||
else
|
||||
prev_page = page, prev_length = length;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* __lightning_funcs_h */
|
||||
@@ -1,647 +0,0 @@
|
||||
/******************************** -*- C -*- ****************************
|
||||
*
|
||||
* Run-time assembler for the PowerPC
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Copyright 1999, 2000, 2001, 2002 Ian Piumarta
|
||||
*
|
||||
* This file is part of GNU lightning.
|
||||
*
|
||||
* GNU lightning is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2.1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU lightning is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with GNU lightning; see the file COPYING.LESSER; if not, write to the
|
||||
* Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef __lightning_asm_h
|
||||
#define __lightning_asm_h
|
||||
|
||||
/* <imm> = [0-9]+ | (.+) -> add i, one parameter (imm)
|
||||
* <reg> = r<imm> -> add r, one parameter (imm)
|
||||
* <mem> = <imm>(<reg>) -> add m, two parameters (imm,reg)
|
||||
* <idx> = <reg>(<reg>) -> add x, two parameters (reg,reg)
|
||||
*
|
||||
* `x' operands have two forms. For example `stwu source, rega(regb)'
|
||||
* could be written as either
|
||||
* STWUrx(source, rega, regb)
|
||||
* or
|
||||
* STWUXrrr(source, rega, regb)
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*** a brief NOTE about halfwords and "shifted" operands
|
||||
*
|
||||
* LOGICAL insns require UNSIGNED args in 0..65535, whether or not shifted
|
||||
*
|
||||
* ARITHMETIC insns require SIGNED args in -32768..32767, even when shifted
|
||||
*
|
||||
* as a special case: "lis/addis" also accepts UNSIGNED arguments in
|
||||
* 0..65535 since it is often used immediately before "ori" to load a 32-bit
|
||||
* constant (this is consistent with the GNU rs/6000 and PowerPC assemblers)
|
||||
*
|
||||
* thus: lis rD, expression@hi
|
||||
* ori rD, rD, expression@lo ; load 32-bit constant
|
||||
*/
|
||||
|
||||
typedef unsigned int jit_insn;
|
||||
|
||||
#ifndef LIGHTNING_DEBUG
|
||||
#define _cr0 0
|
||||
#define _cr1 1
|
||||
#define _cr2 2
|
||||
#define _cr3 3
|
||||
#define _cr4 4
|
||||
#define _cr5 5
|
||||
#define _cr6 6
|
||||
#define _cr7 7
|
||||
|
||||
#define _lt 0
|
||||
#define _gt 1
|
||||
#define _eq 2
|
||||
#define _so 3
|
||||
#define _un 3
|
||||
|
||||
#define _d16(D) (_ck_d(16,(_jit_UL(D)-_jit_UL(_jit.x.pc))) & ~3)
|
||||
#define _d26(D) (_ck_d(26,(_jit_UL(D)-_jit_UL(_jit.x.pc))) & ~3)
|
||||
|
||||
/* primitive instruction forms [1, Section A.4] */
|
||||
|
||||
#define _FB( OP, BD,AA,LK ) (_jit_I_noinc((_u6(OP)<<26)| _d26(BD)| (_u1(AA)<<1)|_u1(LK)), _jit.x.pc++, 0)
|
||||
#define _FBA( OP, BD,AA,LK ) _jit_I((_u6(OP)<<26)| (_u26(BD)&~3)| (_u1(AA)<<1)|_u1(LK))
|
||||
#define _BB( OP,BO,BI, BD,AA,LK ) (_jit_I_noinc((_u6(OP)<<26)|(_u5(BO)<<21)|(_u5(BI)<<16)| _d16(BD)| (_u1(AA)<<1)|_u1(LK)), _jit.x.pc++, 0)
|
||||
#define _D( OP,RD,RA, DD ) _jit_I((_u6(OP)<<26)|(_u5(RD)<<21)|(_u5(RA)<<16)| _s16(DD) )
|
||||
#define _Du( OP,RD,RA, DD ) _jit_I((_u6(OP)<<26)|(_u5(RD)<<21)|(_u5(RA)<<16)| _u16(DD) )
|
||||
#define _Ds( OP,RD,RA, DD ) _jit_I((_u6(OP)<<26)|(_u5(RD)<<21)|(_u5(RA)<<16)| _su16(DD) )
|
||||
#define _X( OP,RD,RA,RB, XO,RC ) _jit_I((_u6(OP)<<26)|(_u5(RD)<<21)|(_u5(RA)<<16)|( _u5(RB)<<11)| (_u10(XO)<<1)|_u1(RC))
|
||||
#define _XL( OP,BO,BI, XO,LK ) _jit_I((_u6(OP)<<26)|(_u5(BO)<<21)|(_u5(BI)<<16)|( _u5(00)<<11)| (_u10(XO)<<1)|_u1(LK))
|
||||
#define _XFX( OP,RD, SR,XO ) _jit_I((_u6(OP)<<26)|(_u5(RD)<<21)| (_u10(SR)<<11)| (_u10(XO)<<1)|_u1(00))
|
||||
#define _XO( OP,RD,RA,RB,OE,XO,RC ) _jit_I((_u6(OP)<<26)|(_u5(RD)<<21)|(_u5(RA)<<16)|( _u5(RB)<<11)|(_u1(OE)<<10)|( _u9(XO)<<1)|_u1(RC))
|
||||
#define _M( OP,RS,RA,SH,MB,ME,RC ) _jit_I((_u6(OP)<<26)|(_u5(RS)<<21)|(_u5(RA)<<16)|( _u5(SH)<<11)|(_u5(MB)<< 6)|( _u5(ME)<<1)|_u1(RC))
|
||||
|
||||
|
||||
/* special purpose registers (form XFX) [1, Section 8.2, page 8-138] */
|
||||
|
||||
#define SPR_LR ((8<<5)|(0))
|
||||
|
||||
/* +++ intrinsic instructions */
|
||||
|
||||
#define ADDrrr(RD, RA, RB) _XO (31, RD, RA, RB, 0, 266, 0)
|
||||
#define ADD_rrr(RD, RA, RB) _XO (31, RD, RA, RB, 0, 266, 1)
|
||||
#define ADDCrrr(RD, RA, RB) _XO (31, RD, RA, RB, 0, 10, 0)
|
||||
#define ADDC_rrr(RD, RA, RB) _XO (31, RD, RA, RB, 0, 10, 1)
|
||||
#define ADDErrr(RD, RA, RB) _XO (31, RD, RA, RB, 0, 138, 0)
|
||||
#define ADDE_rrr(RD, RA, RB) _XO (31, RD, RA, RB, 0, 138, 1)
|
||||
#define ADDOrrr(RD, RA, RB) _XO (31, RD, RA, RB, 1, 266, 0)
|
||||
#define ADDO_rrr(RD, RA, RB) _XO (31, RD, RA, RB, 1, 266, 1)
|
||||
#define ADDIrri(RD, RA, IMM) _D (14, RD, RA, IMM)
|
||||
#define ADDICrri(RD, RA, IMM) _D (12, RD, RA, IMM)
|
||||
#define ADDIC_rri(RD, RA, IMM) _D (13, RD, RA, IMM)
|
||||
#define ADDISrri(RD, RA, IMM) _Ds (15, RD, RA, IMM)
|
||||
|
||||
#define ANDrrr(RA, RS, RB) _X (31, RS, RA, RB, 28, 0)
|
||||
#define AND_rrr(RA, RS, RB) _X (31, RS, RA, RB, 28, 1)
|
||||
#define ANDCrrr(RA, RS, RB) _X (31, RS, RA, RB, 60, 0)
|
||||
#define ANDC_rrr(RA, RS, RB) _X (31, RS, RA, RB, 60, 1)
|
||||
#define ANDI_rri(RA, RS, IMM) _Du (28, RS, RA, IMM)
|
||||
#define ANDIS_rri(RA, RS, IMM) _Du (29, RS, RA, IMM)
|
||||
|
||||
#define Bi(BD) _FB (18, BD, 0, 0)
|
||||
#define BAi(BD) _FBA (18, BD, 1, 0)
|
||||
#define BLi(BD) _FB (18, BD, 0, 1)
|
||||
#define BLAi(BD) _FBA (18, BD, 1, 1)
|
||||
|
||||
#define BCiii(BO,BI,BD) _BB (16, BO, BI, BD, 0, 0)
|
||||
#define BCAiii(BO,BI,BD) _BB (16, BO, BI, BD, 1, 0)
|
||||
#define BCLiii(BO,BI,BD) _BB (16, BO, BI, BD, 0, 1)
|
||||
#define BCLAiii(BO,BI,BD) _BB (16, BO, BI, BD, 1, 1)
|
||||
|
||||
#define BCCTRii(BO,BI) _XL (19, BO, BI, 528, 0)
|
||||
#define BCCTRLii(BO,BI) _XL (19, BO, BI, 528, 1)
|
||||
|
||||
#define BCLRii(BO,BI) _XL (19, BO, BI, 16, 0)
|
||||
#define BCLRLii(BO,BI) _XL (19, BO, BI, 16, 1)
|
||||
|
||||
#define CMPiirr(CR, LL, RA, RB) _X (31, ((CR)<<2)|(LL), RA, RB, 0, 0)
|
||||
#define CMPIiiri(CR, LL, RA, IMM) _D (11, ((CR)<<2)|(LL), RA, IMM)
|
||||
|
||||
#define CMPLiirr(CR, LL, RA, RB) _X (31, ((CR)<<2)|(LL), RA, RB, 32, 0)
|
||||
#define CMPLIiiri(CR, LL, RA, IMM) _D (10, ((CR)<<2)|(LL), RA, IMM)
|
||||
|
||||
#define CRANDiii(CRD,CRA,CRB) _X (19, CRD, CRA, CRB, 257, 0)
|
||||
#define CRANDCiii(CRD,CRA,CRB) _X (19, CRD, CRA, CRB, 129, 0)
|
||||
#define CREQViii(CRD,CRA,CRB) _X (19, CRD, CRA, CRB, 289, 0)
|
||||
#define CRNANDiii(CRD,CRA,CRB) _X (19, CRD, CRA, CRB, 225, 0)
|
||||
#define CRNORiii(CRD,CRA,CRB) _X (19, CRD, CRA, CRB, 33, 0)
|
||||
#define CRORiii(CRD,CRA,CRB) _X (19, CRD, CRA, CRB, 449, 0)
|
||||
#define CRORCiii(CRD,CRA,CRB) _X (19, CRD, CRA, CRB, 417, 0)
|
||||
#define CRXORiii(CRD,CRA,CRB) _X (19, CRD, CRA, CRB, 193, 0)
|
||||
|
||||
#define DCBSTrr(RA,RB) _X (31, 00, RA, RB, 54, 0)
|
||||
|
||||
#define DIVWrrr(RD, RA, RB) _XO (31, RD, RA, RB, 0, 491, 0)
|
||||
#define DIVW_rrr(RD, RA, RB) _XO (31, RD, RA, RB, 0, 491, 1)
|
||||
#define DIVWOrrr(RD, RA, RB) _XO (31, RD, RA, RB, 1, 491, 0)
|
||||
#define DIVWO_rrr(RD, RA, RB) _XO (31, RD, RA, RB, 1, 491, 1)
|
||||
|
||||
#define DIVWUrrr(RD, RA, RB) _XO (31, RD, RA, RB, 0, 459, 0)
|
||||
#define DIVWU_rrr(RD, RA, RB) _XO (31, RD, RA, RB, 0, 459, 1)
|
||||
#define DIVWUOrrr(RD, RA, RB) _XO (31, RD, RA, RB, 1, 459, 0)
|
||||
#define DIVWUO_rrr(RD, RA, RB) _XO (31, RD, RA, RB, 1, 459, 1)
|
||||
|
||||
#define EQVrrr(Ra,RS,RB) _X (31, RS, RA, RB, 284, 0)
|
||||
#define EQV_rrr(Ra,RS,RB) _X (31, RS, RA, RB, 284, 1)
|
||||
|
||||
#define EXTSBrr(RA,RS) _X (31, RS, RA, 0, 954, 0)
|
||||
#define EXTSB_rr(RA,RS) _X (31, RS, RA, 0, 954, 1)
|
||||
|
||||
#define EXTSHrr(RA,RS) _X (31, RS, RA, 0, 922, 0)
|
||||
#define EXTSH_rr(RA,RS) _X (31, RS, RA, 0, 922, 1)
|
||||
|
||||
#define ICBIrr(RA,RB) _X (31, 00, RA, RB, 982, 0)
|
||||
|
||||
#define ISYNC() _X (19, 00, 00, 00, 150, 0)
|
||||
|
||||
#define LBZrm(RD,ID,RA) _D (34, RD, RA, ID)
|
||||
#define LBZUrm(RD,ID,RA) _D (35, RD, RA, ID)
|
||||
#define LBZUXrrr(RD,RA,RB) _X (31, RD, RA, RB, 119, 0)
|
||||
#define LBZXrrr(RD,RA,RB) _X (31, RD, RA, RB, 87, 0)
|
||||
|
||||
#define LHArm(RD,ID,RA) _D (42, RD, RA, ID)
|
||||
#define LHAUrm(RD,ID,RA) _D (43, RD, RA, ID)
|
||||
#define LHAUXrrr(RD,RA,RB) _X (31, RD, RA, RB, 375, 0)
|
||||
#define LHAXrrr(RD,RA,RB) _X (31, RD, RA, RB, 343, 0)
|
||||
#define LHBRXrrr(RD,RA,RB) _X (31, RD, RA, RB, 790, 0)
|
||||
|
||||
#define LHZrm(RD,ID,RA) _D (40, RD, RA, ID)
|
||||
#define LHZUrm(RD,ID,RA) _D (41, RD, RA, ID)
|
||||
#define LHZUXrrr(RD,RA,RB) _X (31, RD, RA, RB, 311, 0)
|
||||
#define LHZXrrr(RD,RA,RB) _X (31, RD, RA, RB, 279, 0)
|
||||
|
||||
#define LMWrm(RD,ID,RA) _D (46, RD, RA, ID)
|
||||
|
||||
#define LWBRXrrr(RD,RA,RB) _X (31, RD, RA, RB, 534, 0)
|
||||
|
||||
#define LWZrm(RD, DISP, RA) _D (32, RD, RA, DISP)
|
||||
#define LWZUrm(RD, DISP, RA) _D (33, RD, RA, DISP)
|
||||
#define LWZUXrrr(RD, RA, RB) _X (31, RD, RA, RB, 56, 0)
|
||||
#define LWZXrrr(RD, RA, RB) _X (31, RD, RA, RB, 23, 0)
|
||||
|
||||
#define MCRFii(CD,CS) _X (19, ((CD)<<2), ((CS)<<2), 0, 0, 0)
|
||||
|
||||
#define MFCRr(RD) _X (31, RD, 0, 0, 19, 0)
|
||||
#define MCRXRi(RD) _XFX (31, (RD)<<2, 0, 512)
|
||||
|
||||
#define MFSPRri(RD, SPR) _XFX (31, RD, (SPR)<<5, 339)
|
||||
#define MTSPRir(SPR, RS) _XFX (31, RS, (SPR)<<5, 467)
|
||||
|
||||
#define MULHWrrr(RD,RA,RB) _XO (31, RD, RA, RB, 0, 75, 0)
|
||||
#define MULHW_rrr(RD,RA,RB) _XO (31, RD, RA, RB, 0, 75, 1)
|
||||
#define MULHWUrrr(RD,RA,RB) _XO (31, RD, RA, RB, 0, 11, 0)
|
||||
#define MULHWU_rrr(RD,RA,RB) _XO (31, RD, RA, RB, 0, 11, 1)
|
||||
|
||||
#define MULLIrri(RD,RA,IM) _D (07, RD, RA, IM)
|
||||
|
||||
#define MULLWrrr(RD,RA,RB) _XO (31, RD, RA, RB, 0, 235, 0)
|
||||
#define MULLW_rrr(RD,RA,RB) _XO (31, RD, RA, RB, 0, 235, 1)
|
||||
#define MULLWOrrr(RD,RA,RB) _XO (31, RD, RA, RB, 1, 235, 0)
|
||||
#define MULLWO_rrr(RD,RA,RB) _XO (31, RD, RA, RB, 1, 235, 1)
|
||||
|
||||
#define NANDrrr(RA,RS,RB) _X (31, RS, RA, RB, 476, 0)
|
||||
#define NAND_rrr(RA,RS,RB) _X (31, RS, RA, RB, 476, 1)
|
||||
|
||||
#define NEGrr(RD,RA) _XO (31, RD, RA, 0, 0, 104, 0)
|
||||
#define NEG_rr(RD,RA) _XO (31, RD, RA, 0, 0, 104, 1)
|
||||
#define NEGOrr(RD,RA) _XO (31, RD, RA, 0, 1, 104, 0)
|
||||
#define NEGO_rr(RD,RA) _XO (31, RD, RA, 0, 1, 104, 1)
|
||||
|
||||
#define NORrrr(RA,RS,RB) _X (31, RS, RA, RB, 124, 0)
|
||||
#define NOR_rrr(RA,RS,RB) _X (31, RS, RA, RB, 124, 1)
|
||||
|
||||
#define ORrrr(RA,RS,RB) _X (31, RS, RA, RB, 444, 0)
|
||||
#define OR_rrr(RA,RS,RB) _X (31, RS, RA, RB, 444, 1)
|
||||
#define ORCrrr(RA,RS,RB) _X (31, RS, RA, RB, 412, 0)
|
||||
#define ORC_rrr(RA,RS,RB) _X (31, RS, RA, RB, 412, 1)
|
||||
#define ORIrri(RA,RS,IM) _Du (24, RS, RA, IM)
|
||||
#define ORISrri(RA,RS,IM) _Du (25, RS, RA, IM)
|
||||
|
||||
#define RLWIMIrriii(RA,RS,SH,MB,ME) _M (20, RS, RA, SH, MB, ME, 0)
|
||||
#define RLWIMI_rriii(RA,RS,SH,MB,ME) _M (20, RS, RA, SH, MB, ME, 1)
|
||||
|
||||
#define RLWINMrriii(RA,RS,SH,MB,ME) _M (21, RS, RA, SH, MB, ME, 0)
|
||||
#define RLWINM_rriii(RA,RS,SH,MB,ME) _M (21, RS, RA, SH, MB, ME, 1)
|
||||
|
||||
#define RLWNMrrrii(RA,RS,RB,MB,ME) _M (23, RS, RA, RB, MB, ME, 0)
|
||||
#define RLWNM_rrrii(RA,RS,RB,MB,ME) _M (23, RS, RA, RB, MB, ME, 1)
|
||||
|
||||
#define SLWrrr(RA,RS,RB) _X (31, RS, RA, RB, 24, 0)
|
||||
#define SLW_rrr(RA,RS,RB) _X (31, RS, RA, RB, 24, 1)
|
||||
|
||||
#define SRAWrrr(RA,RS,RB) _X (31, RS, RA, RB, 792, 0)
|
||||
#define SRAW_rrr(RA,RS,RB) _X (31, RS, RA, RB, 792, 1)
|
||||
|
||||
#define SRAWIrri(RD, RS, SH) _X (31, RS, RD, SH, 824, 0)
|
||||
#define SRAWI_rri(RD, RS, SH) _X (31, RS, RD, SH, 824, 1)
|
||||
|
||||
#define SRWrrr(RA,RS,RB) _X (31, RS, RA, RB, 536, 0)
|
||||
#define SRW_rrr(RA,RS,RB) _X (31, RS, RA, RB, 536, 1)
|
||||
|
||||
#define STBrm(RS,ID,RA) _D (38, RS, RA, ID)
|
||||
#define STBUrm(RS,ID,RA) _D (39, RS, RA, ID)
|
||||
#define STBUXrrr(RS,RA,RB) _X (31, RS, RA, RB, 247, 0)
|
||||
#define STBXrrr(RS,RA,RB) _X (31, RS, RA, RB, 215, 0)
|
||||
|
||||
#define STHrm(RS,ID,RA) _D (44, RS, RA, ID)
|
||||
#define STHUrm(RS,ID,RA) _D (45, RS, RA, ID)
|
||||
#define STHBRXrrr(RS,RA,RB) _X (31, RS, RA, RB, 918, 0)
|
||||
#define STHUXrrr(RS,RA,RB) _X (31, RS, RA, RB, 439, 0)
|
||||
#define STHXrrr(RS,RA,RB) _X (31, RS, RA, RB, 407, 0)
|
||||
|
||||
#define STMWrm(RS,ID,RA) _D (47, RS, RA, ID)
|
||||
|
||||
#define STWrm(RS,ID,RA) _D (36, RS, RA, ID)
|
||||
#define STWBRXrrr(RS,RA,RB) _X (31, RS, RA, RB, 662, 0)
|
||||
#define STWCXrrr(RS,RA,RB) _X (31, RS, RA, RB, 150, 0)
|
||||
#define STWCX_rrr(RS,RA,RB) _X (31, RS, RA, RB, 150, 1)
|
||||
#define STWUrm(RS,ID,RA) _D (37, RS, RA, ID)
|
||||
#define STWUXrrr(RS,RA,RB) _X (31, RS, RA, RB, 183, 0)
|
||||
#define STWXrrr(RS,RA,RB) _X (31, RS, RA, RB, 151, 0)
|
||||
|
||||
#define SUBFrrr(RD, RA, RB) _XO (31, RD, RA, RB, 0, 40, 0)
|
||||
#define SUBF_rrr(RD, RA, RB) _XO (31, RD, RA, RB, 0, 40, 1)
|
||||
#define SUBFrrr(RD, RA, RB) _XO (31, RD, RA, RB, 0, 40, 0)
|
||||
#define SUBF_rrr(RD, RA, RB) _XO (31, RD, RA, RB, 0, 40, 1)
|
||||
#define SUBFErrr(RD, RA, RB) _XO (31, RD, RA, RB, 1, 136, 0)
|
||||
#define SUBFE_rrr(RD, RA, RB) _XO (31, RD, RA, RB, 1, 136, 1)
|
||||
#define SUBFCrrr(RD, RA, RB) _XO (31, RD, RA, RB, 0, 8, 0)
|
||||
#define SUBFC_rrr(RD, RA, RB) _XO (31, RD, RA, RB, 0, 8, 1)
|
||||
#define SUBFCOrrr(RD, RA, RB) _XO (31, RD, RA, RB, 1, 8, 0)
|
||||
#define SUBFCO_rrr(RD, RA, RB) _XO (31, RD, RA, RB, 1, 8, 1)
|
||||
#define SUBFICrri(RD, RA, IMM) _D (8, RD, RA, IMM)
|
||||
|
||||
#define ADDrrr(RD, RA, RB) _XO (31, RD, RA, RB, 0, 266, 0)
|
||||
#define ADDOrrr(RD, RA, RB) _XO (31, RD, RA, RB, 1, 266, 0)
|
||||
#define ADDIrri(RD, RA, IMM) _D (14, RD, RA, IMM)
|
||||
#define ADDISrri(RD, RA, IMM) _Ds (15, RD, RA, IMM)
|
||||
|
||||
#define SYNC() _X (31, 00, 00, 00, 598, 0)
|
||||
|
||||
#define TWirr(TO,RA,RB) _X (31, TO, RA, RB, 4, 0)
|
||||
#define TWIiri(TO,RA,IM) _D (03, TO, RA, IM)
|
||||
|
||||
#define XORrrr(RA,RS,RB) _X (31, RS, RA, RB, 316, 0)
|
||||
#define XOR_rrr(RA,RS,RB) _X (31, RS, RA, RB, 316, 1)
|
||||
#define XORIrri(RA,RS,IM) _Du (26, RS, RA, IM)
|
||||
#define XORISrri(RA,RS,IM) _Du (27, RS, RA, IM)
|
||||
|
||||
/* simplified mnemonics [1, Appendix F] */
|
||||
|
||||
#define MOVEIri2(R,H,L) (LISri(R,H), (L ? ORIrri(R,R,L) : 0))
|
||||
#define MOVEIri(R,I) (_siP(16,I) ? LIri(R,I) : \
|
||||
MOVEIri2(R, _HI(I), _LO(I)) )
|
||||
|
||||
#define SUBIrri(RD,RA,IM) ADDIrri(RD,RA,-_LO((IM))) /* [1, Section F.2.1] */
|
||||
#define SUBISrri(RD,RA,IM) ADDISrri(RD,RA,-_LO((IM)))
|
||||
#define SUBICrri(RD,RA,IM) ADDICrri(RD,RA,-_LO((IM)))
|
||||
#define SUBIC_rri(RD,RA,IM) ADDIC_rri(RD,RA,-_LO((IM)))
|
||||
|
||||
#define SUBrrr(RD,RA,RB) SUBFrrr(RD,RB,RA) /* [1, Section F.2.2] */
|
||||
#define SUBOrrr(RD,RA,RB) SUBFOrrr(RD,RB,RA)
|
||||
#define SUB_rrr(RD,RA,RB) SUBF_rrr(RD,RB,RA)
|
||||
#define SUBCrrr(RD,RA,RB) SUBFCrrr(RD,RB,RA)
|
||||
#define SUBCOrrr(RD,RA,RB) SUBFCOrrr(RD,RB,RA)
|
||||
#define SUBC_rrr(RD,RA,RB) SUBFC_rrr(RD,RB,RA)
|
||||
#define SUBErrr(RD,RA,RB) SUBFErrr(RD,RB,RA)
|
||||
#define SUBE_rrr(RD,RA,RB) SUBFE_rrr(RD,RB,RA)
|
||||
|
||||
#define CMPWIiri(C,RA,IM) CMPIiiri(C,0,RA,IM) /* [1, Table F-2] */
|
||||
#define CMPWirr(C,RA,RB) CMPiirr(C,0,RA,RB)
|
||||
#define CMPLWIiri(C,RA,IM) CMPLIiiri(C,0,RA,IM)
|
||||
#define CMPLWirr(C,RA,RB) CMPLiirr(C,0,RA,RB)
|
||||
|
||||
#define CMPWIri(RA,IM) CMPWIiri(0,RA,IM) /* with implicit _cr0 */
|
||||
#define CMPWrr(RA,RB) CMPWirr(0,RA,RB)
|
||||
#define CMPLWIri(RA,IM) CMPLWIiri(0,RA,IM)
|
||||
#define CMPLWrr(RA,RB) CMPLWirr(0,RA,RB)
|
||||
|
||||
#define EXTLWIrrii(RA,RS,N,B) RLWINMrriii(RA, RS, B, 0, (N)-1) /* [1, Table F-3] */
|
||||
#define EXTRWIrrii(RA,RS,N,B) RLWINMrriii(RA, RS, (B)+(N), 32-(N), 31)
|
||||
#define INSLWIrrii(RA,RS,N,B) RLWIMIrriii(RA, RS, 32-(B), B, (B)+(N)-1)
|
||||
#define INSRWIrrii(RA,RS,N,B) RLWIMIrriii(RA, RS, 32-((B)+(N)), B, (B)+(N)-1)
|
||||
#define ROTLWIrri(RA,RS,N) RLWINMrriii(RA, RS, N, 0, 31)
|
||||
#define ROTRWIrri(RA,RS,N) RLWINMrriii(RA, RS, 32-(N), 0, 31)
|
||||
#define ROTLWrrr(RA,RS,RB) RLWNMrrrii( RA, RS, RB, 0, 31)
|
||||
#define SLWIrri(RA,RS,N) RLWINMrriii(RA, RS, N, 0, 31-(N))
|
||||
#define SRWIrri(RA,RS,N) RLWINMrriii(RA, RS, 32-(N), N, 31)
|
||||
#define CLRLWIrri(RA,RS,N) RLWINMrriii(RA, RS, 0, N, 31)
|
||||
#define CLRRWIrri(RA,RS,N) RLWINMrriii(RA, RS, 0, 0, 31-(N))
|
||||
#define CLRLSLWIrrii(RA,RS,B,N) RLWINMrriii(RA, RS, N, (B)-(N), 31-(N))
|
||||
|
||||
|
||||
/* 9 below inverts the branch condition and the branch prediction.
|
||||
* This has an incestuous knowledge of JIT_AUX */
|
||||
#define BC_EXT(A, C, D) (_siP(16, _jit_UL(D)-_jit_UL(_jit.x.pc)) \
|
||||
? BCiii((A), (C), (D)) \
|
||||
: (BCiii((A)^9, (C), _jit.x.pc+5), \
|
||||
LISri(JIT_AUX,_HI(D)), \
|
||||
ORIrri(JIT_AUX,JIT_AUX,_LO(D)), \
|
||||
MTLRr(JIT_AUX), BLR() ))
|
||||
|
||||
#define B_EXT(D) (_siP(16, _jit_UL(D)-_jit_UL(_jit.x.pc)) \
|
||||
? Bi((D)) \
|
||||
: (LISri(JIT_AUX,_HI(D)), \
|
||||
ORIrri(JIT_AUX,JIT_AUX,_LO(D)), \
|
||||
MTLRr(JIT_AUX), BLR()) )
|
||||
|
||||
#define BTii(C,D) BC_EXT(12, C, D) /* [1, Table F-5] */
|
||||
#define BFii(C,D) BC_EXT( 4, C, D)
|
||||
#define BDNZi(D) BCiii(16, 0, D)
|
||||
#define BDNZTii(C,D) BC_EXT( 8, C, D)
|
||||
#define BDNZFii(C,D) BC_EXT( 0, C, D)
|
||||
#define BDZi(D) BCiii(18, 0, D)
|
||||
#define BDZTii(C,D) BC_EXT(10, C, D)
|
||||
#define BDZFii(C,D) BC_EXT( 2, C, D)
|
||||
|
||||
#define BCTR() BCCTRii(20, 0) /* [1, Table F-6] */
|
||||
#define BCTRL() BCCTRLii(20, 0)
|
||||
|
||||
#define BLR() BCLRii(20, 0) /* [1, Table F-6] */
|
||||
#define BLRL() BCLRLii(20, 0)
|
||||
|
||||
|
||||
#define BLTLRi(CR) BCLRii(12, ((CR)<<2)+0) /* [1, Table F-10] */
|
||||
#define BLELRi(CR) BCLRii( 4, ((CR)<<2)+1)
|
||||
#define BEQLRi(CR) BCLRii(12, ((CR)<<2)+2)
|
||||
#define BGELRi(CR) BCLRii( 4, ((CR)<<2)+0)
|
||||
#define BGTLRi(CR) BCLRii(12, ((CR)<<2)+1)
|
||||
#define BNLLRi(CR) BCLRii( 4, ((CR)<<2)+0)
|
||||
#define BNELRi(CR) BCLRii( 4, ((CR)<<2)+2)
|
||||
#define BNGLRi(CR) BCLRii( 4, ((CR)<<2)+1)
|
||||
#define BSOLRi(CR) BCLRii(12, ((CR)<<2)+3)
|
||||
#define BNSLRi(CR) BCLRii( 4, ((CR)<<2)+3)
|
||||
#define BUNLRi(CR) BCLRii(12, ((CR)<<2)+3)
|
||||
#define BNULRi(CR) BCLRii( 4, ((CR)<<2)+3)
|
||||
|
||||
#define BLTLRLi(CR) BCLRLii(12, ((CR)<<2)+0) /* [1, Table F-10] */
|
||||
#define BLELRLi(CR) BCLRLii( 4, ((CR)<<2)+1)
|
||||
#define BEQLRLi(CR) BCLRLii(12, ((CR)<<2)+2)
|
||||
#define BGELRLi(CR) BCLRLii( 4, ((CR)<<2)+0)
|
||||
#define BGTLRLi(CR) BCLRLii(12, ((CR)<<2)+1)
|
||||
#define BNLLRLi(CR) BCLRLii( 4, ((CR)<<2)+0)
|
||||
#define BNELRLi(CR) BCLRLii( 4, ((CR)<<2)+2)
|
||||
#define BNGLRLi(CR) BCLRLii( 4, ((CR)<<2)+1)
|
||||
#define BSOLRLi(CR) BCLRLii(12, ((CR)<<2)+3)
|
||||
#define BNSLRLi(CR) BCLRLii( 4, ((CR)<<2)+3)
|
||||
#define BUNLRLi(CR) BCLRLii(12, ((CR)<<2)+3)
|
||||
#define BNULRLi(CR) BCLRLii( 4, ((CR)<<2)+3)
|
||||
|
||||
#define BLTCTRi(CR) BCCTRii(12, ((CR)<<2)+0) /* [1, Table F-10] */
|
||||
#define BLECTRi(CR) BCCTRii( 4, ((CR)<<2)+1)
|
||||
#define BEQCTRi(CR) BCCTRii(12, ((CR)<<2)+2)
|
||||
#define BGECTRi(CR) BCCTRii( 4, ((CR)<<2)+0)
|
||||
#define BGTCTRi(CR) BCCTRii(12, ((CR)<<2)+1)
|
||||
#define BNLCTRi(CR) BCCTRii( 4, ((CR)<<2)+0)
|
||||
#define BNECTRi(CR) BCCTRii( 4, ((CR)<<2)+2)
|
||||
#define BNGCTRi(CR) BCCTRii( 4, ((CR)<<2)+1)
|
||||
#define BSOCTRi(CR) BCCTRii(12, ((CR)<<2)+3)
|
||||
#define BNSCTRi(CR) BCCTRii( 4, ((CR)<<2)+3)
|
||||
#define BUNCTRi(CR) BCCTRii(12, ((CR)<<2)+3)
|
||||
#define BNUCTRi(CR) BCCTRii( 4, ((CR)<<2)+3)
|
||||
|
||||
#define BLTCTRLi(CR) BCCTRLii(12, ((CR)<<2)+0) /* [1, Table F-10] */
|
||||
#define BLECTRLi(CR) BCCTRLii( 4, ((CR)<<2)+1)
|
||||
#define BEQCTRLi(CR) BCCTRLii(12, ((CR)<<2)+2)
|
||||
#define BGECTRLi(CR) BCCTRLii( 4, ((CR)<<2)+0)
|
||||
#define BGTCTRLi(CR) BCCTRLii(12, ((CR)<<2)+1)
|
||||
#define BNLCTRLi(CR) BCCTRLii( 4, ((CR)<<2)+0)
|
||||
#define BNECTRLi(CR) BCCTRLii( 4, ((CR)<<2)+2)
|
||||
#define BNGCTRLi(CR) BCCTRLii( 4, ((CR)<<2)+1)
|
||||
#define BSOCTRLi(CR) BCCTRLii(12, ((CR)<<2)+3)
|
||||
#define BNSCTRLi(CR) BCCTRLii( 4, ((CR)<<2)+3)
|
||||
#define BUNCTRLi(CR) BCCTRLii(12, ((CR)<<2)+3)
|
||||
#define BNUCTRLi(CR) BCCTRLii( 4, ((CR)<<2)+3)
|
||||
|
||||
|
||||
#define BLTLR() BLTLRi(0) /* with implicit _cr0 */
|
||||
#define BLELR() BLELRi(0)
|
||||
#define BEQLR() BEQLRi(0)
|
||||
#define BGELR() BGELRi(0)
|
||||
#define BGTLR() BGTLRi(0)
|
||||
#define BNLLR() BNLLRi(0)
|
||||
#define BNELR() BNELRi(0)
|
||||
#define BNGLR() BNGLRi(0)
|
||||
#define BSOLR() BSOLRi(0)
|
||||
#define BNSLR() BNSLRi(0)
|
||||
#define BUNLR() BUNLRi(0)
|
||||
#define BNULR() BNULRi(0)
|
||||
|
||||
#define BLTLRL() BLTLRLi(0)
|
||||
#define BLELRL() BLELRLi(0)
|
||||
#define BEQLRL() BEQLRLi(0)
|
||||
#define BGELRL() BGELRLi(0)
|
||||
#define BGTLRL() BGTLRLi(0)
|
||||
#define BNLLRL() BNLLRLi(0)
|
||||
#define BNELRL() BNELRLi(0)
|
||||
#define BNGLRL() BNGLRLi(0)
|
||||
#define BSOLRL() BSOLRLi(0)
|
||||
#define BNSLRL() BNSLRLi(0)
|
||||
#define BUNLRL() BUNLRLi(0)
|
||||
#define BNULRL() BNULRLi(0)
|
||||
|
||||
#define BLTCTR() BLTCTRi(0)
|
||||
#define BLECTR() BLECTRi(0)
|
||||
#define BEQCTR() BEQCTRi(0)
|
||||
#define BGECTR() BGECTRi(0)
|
||||
#define BGTCTR() BGTCTRi(0)
|
||||
#define BNLCTR() BNLCTRi(0)
|
||||
#define BNECTR() BNECTRi(0)
|
||||
#define BNGCTR() BNGCTRi(0)
|
||||
#define BSOCTR() BSOCTRi(0)
|
||||
#define BNSCTR() BNSCTRi(0)
|
||||
#define BUNCTR() BUNCTRi(0)
|
||||
#define BNUCTR() BNUCTRi(0)
|
||||
|
||||
#define BLTCTRL() BLTCTRLi(0)
|
||||
#define BLECTRL() BLECTRLi(0)
|
||||
#define BEQCTRL() BEQCTRLi(0)
|
||||
#define BGECTRL() BGECTRLi(0)
|
||||
#define BGTCTRL() BGTCTRLi(0)
|
||||
#define BNLCTRL() BNLCTRLi(0)
|
||||
#define BNECTRL() BNECTRLi(0)
|
||||
#define BNGCTRL() BNGCTRLi(0)
|
||||
#define BSOCTRL() BSOCTRLi(0)
|
||||
#define BNSCTRL() BNSCTRLi(0)
|
||||
#define BUNCTRL() BUNCTRLi(0)
|
||||
#define BNUCTRL() BNUCTRLi(0)
|
||||
|
||||
|
||||
#define BLTii(C,D) BC_EXT(12, ((C)<<2)+0, D) /* [1, Table F-11] */
|
||||
#define BNLii(C,D) BC_EXT( 4, ((C)<<2)+0, D)
|
||||
#define BGEii(C,D) BC_EXT( 4, ((C)<<2)+0, D)
|
||||
#define BGTii(C,D) BC_EXT(12, ((C)<<2)+1, D)
|
||||
#define BNGii(C,D) BC_EXT( 4, ((C)<<2)+1, D)
|
||||
#define BLEii(C,D) BC_EXT( 4, ((C)<<2)+1, D)
|
||||
#define BEQii(C,D) BC_EXT(12, ((C)<<2)+2, D)
|
||||
#define BNEii(C,D) BC_EXT( 4, ((C)<<2)+2, D)
|
||||
#define BSOii(C,D) BC_EXT(12, ((C)<<2)+3, D)
|
||||
#define BNSii(C,D) BC_EXT( 4, ((C)<<2)+3, D)
|
||||
#define BUNii(C,D) BC_EXT(12, ((C)<<2)+3, D)
|
||||
#define BNUii(C,D) BC_EXT( 4, ((C)<<2)+3, D)
|
||||
|
||||
#define BLTi(D) BLTii(0,D) /* with implicit _cr0 */
|
||||
#define BLEi(D) BLEii(0,D)
|
||||
#define BEQi(D) BEQii(0,D)
|
||||
#define BGEi(D) BGEii(0,D)
|
||||
#define BGTi(D) BGTii(0,D)
|
||||
#define BNLi(D) BNLii(0,D)
|
||||
#define BNEi(D) BNEii(0,D)
|
||||
#define BNGi(D) BNGii(0,D)
|
||||
#define BSOi(D) BSOii(0,D)
|
||||
#define BNSi(D) BNSii(0,D)
|
||||
#define BUNi(D) BUNii(0,D)
|
||||
#define BNUi(D) BNUii(0,D)
|
||||
|
||||
#define BLTLii(C,D) BCLiii(12, ((C)<<2)+0, D) /* [1, Table F-??] */
|
||||
#define BLELii(C,D) BCLiii( 4, ((C)<<2)+1, D)
|
||||
#define BEQLii(C,D) BCLiii(12, ((C)<<2)+2, D)
|
||||
#define BGELii(C,D) BCLiii( 4, ((C)<<2)+0, D)
|
||||
#define BGTLii(C,D) BCLiii(12, ((C)<<2)+1, D)
|
||||
#define BNLLii(C,D) BCLiii( 4, ((C)<<2)+0, D)
|
||||
#define BNELii(C,D) BCLiii( 4, ((C)<<2)+2, D)
|
||||
#define BNGLii(C,D) BCLiii( 4, ((C)<<2)+1, D)
|
||||
#define BSOLii(C,D) BCLiii(12, ((C)<<2)+3, D)
|
||||
#define BNSLii(C,D) BCLiii( 4, ((C)<<2)+3, D)
|
||||
#define BUNLii(C,D) BCLiii(12, ((C)<<2)+3, D)
|
||||
#define BNULii(C,D) BCLiii( 4, ((C)<<2)+3, D)
|
||||
|
||||
#define BLTLi(D) BLTLii(0,D) /* with implicit _cr0 */
|
||||
#define BLELi(D) BLELii(0,D)
|
||||
#define BEQLi(D) BEQLii(0,D)
|
||||
#define BGELi(D) BGELii(0,D)
|
||||
#define BGTLi(D) BGTLii(0,D)
|
||||
#define BNLLi(D) BNLLii(0,D)
|
||||
#define BNELi(D) BNELii(0,D)
|
||||
#define BNGLi(D) BNGLii(0,D)
|
||||
#define BSOLi(D) BSOLii(0,D)
|
||||
#define BNSLi(D) BNSLii(0,D)
|
||||
#define BUNLi(D) BUNLii(0,D)
|
||||
#define BNULi(D) BNULii(0,D)
|
||||
|
||||
/* Note: there are many tens of other simplified branches that are not (yet?) defined here */
|
||||
|
||||
#define CRSETi(BX) CREQViii(BX, BX, BX) /* [1, Table F-15] */
|
||||
#define CRCLRi(BX) CRXORiii(BX, BX, BX)
|
||||
#define CRMOVEii(BX,BY) CRORiii(BX, BY, BY)
|
||||
#define CRNOTii(BX,BY) CRNORiii(BX, BY, BY)
|
||||
|
||||
#define MTLRr(RS) MTSPRir(8, RS) /* [1, Table F-20] */
|
||||
#define MFLRr(RD) MFSPRri(RD, 8)
|
||||
#define MTCTRr(RS) MTSPRir(9, RS)
|
||||
#define MFCTRr(RD) MFSPRri(RD, 9)
|
||||
#define MTXERr(RS) MTSPRir(1, RS)
|
||||
#define MFXERr(RD) MFSPRri(RD, 1)
|
||||
|
||||
#define NOP() ORIrri(0, 0, 0) /* [1, Section F.9] */
|
||||
#define LIri(RD,IM) ADDIrri(RD, 0, IM)
|
||||
#define LISri(RD,IM) ADDISrri(RD, 0, IM)
|
||||
#define LArm(RD,D,RA) ADDIrri(RD, RA, D)
|
||||
#define LArrr(RD,RB,RA) ADDIrrr(RD, RA, RB)
|
||||
#define MRrr(RA,RS) ORrrr(RA, RS, RS)
|
||||
#define NOTrr(RA,RS) NORrrr(RA, RS, RS)
|
||||
|
||||
/* alternative parenthesised forms of extended indexed load/store insns */
|
||||
|
||||
#define LBZUrx(RD,RA,RB) LBZUXrrr(RD,RA,RB)
|
||||
#define LBZrx(RD,RA,RB) LBZXrrr(RD,RA,RB)
|
||||
#define LHAUrx(RD,RA,RB) LHAUXrrr(RD,RA,RB)
|
||||
#define LHArx(RD,RA,RB) LHAXrrr(RD,RA,RB)
|
||||
#define LHBRrx(RD,RA,RB) LHBRXrrr(RD,RA,RB)
|
||||
#define LHZUrx(RD,RA,RB) LHZUXrrr(RD,RA,RB)
|
||||
#define LHZrx(RD,RA,RB) LHZXrrr(RD,RA,RB)
|
||||
#define LWBRrx(RD,RA,RB) LWBRXrrr(RD,RA,RB)
|
||||
#define LWZUrx(RD, RA, RB) LWZUXrrr(RD, RA, RB)
|
||||
#define LWZrx(RD, RA, RB) LWZXrrr(RD, RA, RB)
|
||||
#define STBUrx(RD,RA,RB) STBUXrrr(RD,RA,RB)
|
||||
#define STBrx(RD,RA,RB) STBXrrr(RD,RA,RB)
|
||||
#define STHBRrx(RS,RA,RB) STHBRXrrr(RS,RA,RB)
|
||||
#define STHUrx(RS,RA,RB) STHUXrrr(RS,RA,RB)
|
||||
#define STHrx(RS,RA,RB) STHXrrr(RS,RA,RB)
|
||||
#define STWBRrx(RS,RA,RB) STWBRXrrr(RS,RA,RB)
|
||||
#define STWCrx(RS,RA,RB) STWCXrrr(RS,RA,RB)
|
||||
#define STWCX_rx(RS,RA,RB) STWCX_rrr(RS,RA,RB)
|
||||
#define STWUrx(RS,RA,RB) STWUXrrr(RS,RA,RB)
|
||||
#define STWrx(RS,RA,RB) STWXrrr(RS,RA,RB)
|
||||
#define LArx(RD,RB,RA) LArrr(RD,RB,RA)
|
||||
|
||||
|
||||
#define _LO(I) (_jit_UL(I) & _MASK(16))
|
||||
#define _HI(I) (_jit_UL(I) >> (16))
|
||||
|
||||
#define _A(OP,RD,RA,RB,RC,XO,RCx) _jit_I((_u6(OP)<<26)|(_u5(RD)<<21)|(_u5(RA)<<16)|( _u5(RB)<<11)|_u5(RC)<<6|(_u5(XO)<<1)|_u1(RCx))
|
||||
|
||||
#define LFDrri(RD,RA,imm) _D(50,RD,RA,imm)
|
||||
#define LFDUrri(RD,RA,imm) _D(51,RD,RA,imm)
|
||||
#define LFDUxrrr(RD,RA,RB) _X(31,RD,RA,RB,631,0)
|
||||
#define LFDxrrr(RD,RA,RB) _X(31,RD,RA,RB,599,0)
|
||||
|
||||
#define LFSrri(RD,RA,imm) _D(48,RD,RA,imm)
|
||||
#define LFSUrri(RD,RA,imm) _D(49,RD,RA,imm)
|
||||
#define LFSUxrrr(RD,RA,RB) _X(31,RD,RA,RB,567,0)
|
||||
#define LFSxrrr(RD,RA,RB) _X(31,RD,RA,RB,535,0)
|
||||
|
||||
#define STFDrri(RS,RA,imm) _D(54,RS,RA,imm)
|
||||
#define STFDUrri(RS,RA,imm) _D(55,RS,RA,imm)
|
||||
#define STFDUxrrr(RS,RA,RB) _X(31,RS,RA,RB,759,0)
|
||||
#define STFDxrrr(RS,RA,RB) _X(31,RS,RA,RB,727,0)
|
||||
|
||||
#define STFSrri(RS,RA,imm) _D(52,RS,RA,imm)
|
||||
#define STFSUrri(RS,RA,imm) _D(53,RS,RA,imm)
|
||||
#define STFSUxrrr(RS,RA,RB) _X(31,RS,RA,RB,695,0)
|
||||
#define STFSxrrr(RS,RA,RB) _X(31,RS,RA,RB,663,0)
|
||||
#define STFIWXrrr(RS,RA,RB) _X(31,RS,RA,RB,983,0)
|
||||
|
||||
#define FADDDrrr(RD,RA,RB) _A(63,RD,RA,RB,0,21,0)
|
||||
#define FADDSrrr(RD,RA,RB) _A(59,RD,RA,RB,0,21,0)
|
||||
#define FSUBDrrr(RD,RA,RB) _A(63,RD,RA,RB,0,20,0)
|
||||
#define FSUBSrrr(RD,RA,RB) _A(59,RD,RA,RB,0,20,0)
|
||||
#define FMULDrrr(RD,RA,RC) _A(63,RD,RA,0,RC,25,0)
|
||||
#define FMULSrrr(RD,RA,RC) _A(59,RD,RA,0,RC,25,0)
|
||||
#define FDIVDrrr(RD,RA,RB) _A(63,RD,RA,RB,0,18,0)
|
||||
#define FDIVSrrr(RD,RA,RB) _A(59,RD,RA,RB,0,25,0)
|
||||
#define FSQRTDrr(RD,RB) _A(63,RD,0,RB,0,22,0)
|
||||
#define FSQRTSrr(RD,RB) _A(59,RD,0,RB,0,22,0)
|
||||
#define FSELrrrr(RD,RA,RB,RC) _A(63,RD,RA,RB,RC,23,0)
|
||||
#define FCTIWrr(RD,RB) _X(63,RD,0,RB,14,0)
|
||||
#define FCTIWZrr(RD,RB) _X(63,RD,0,RB,15,0)
|
||||
#define FRSPrr(RD,RB) _X(63,RD,0,RB,12,0)
|
||||
#define FABSrr(RD,RB) _X(63,RD,0,RB,264,0)
|
||||
#define FNABSrr(RD,RB) _X(63,RD,0,RB,136,0)
|
||||
#define FNEGrr(RD,RB) _X(63,RD,0,RB,40,0)
|
||||
#define FMOVErr(RD,RB) _X(63,RD,0,RB,72,0)
|
||||
#define FCMPOrrr(CR,RA,RB) _X(63,_u3((CR)<<2),RA,RB,32,0)
|
||||
#define FCMPUrrr(CR,RA,RB) _X(63,_u3((CR)<<2),RA,RB,0,0)
|
||||
#define MTFSFIri(CR,IMM) _X(63,_u5((CR)<<2),0,_u5((IMM)<<1),134,0)
|
||||
|
||||
/*** References:
|
||||
*
|
||||
* [1] "PowerPC Microprocessor Family: The Programming Environments For 32-Bit Microprocessors", Motorola, 1997.
|
||||
*/
|
||||
|
||||
|
||||
#endif
|
||||
#endif /* __ccg_asm_ppc_h */
|
||||
@@ -1,298 +0,0 @@
|
||||
/******************************** -*- C -*- ****************************
|
||||
*
|
||||
* Platform-independent layer (PowerPC version)
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
* Written by Paolo Bonzini.
|
||||
*
|
||||
* This file is part of GNU lightning.
|
||||
*
|
||||
* GNU lightning is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2.1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU lightning is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with GNU lightning; see the file COPYING.LESSER; if not, write to the
|
||||
* Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef __lightning_core_h
|
||||
#define __lightning_core_h
|
||||
|
||||
struct jit_local_state {
|
||||
int nextarg_puti; /* number of integer args */
|
||||
int nextarg_putf; /* number of float args */
|
||||
int nextarg_putd; /* number of double args */
|
||||
int nextarg_geti; /* Next r20-r25 reg. to be read */
|
||||
int nextarg_getd; /* The FP args are picked up from FPR1 -> FPR10 */
|
||||
int nbArgs; /* Number of arguments for the prolog */
|
||||
};
|
||||
|
||||
#define JIT_SP 1
|
||||
#define JIT_RET 3
|
||||
#define JIT_R_NUM 3
|
||||
#define JIT_V_NUM 7
|
||||
#define JIT_R(i) (9+(i))
|
||||
#define JIT_V(i) (31-(i))
|
||||
#define JIT_AUX JIT_V(JIT_V_NUM) /* for 32-bit operands & shift counts */
|
||||
|
||||
#define jit_pfx_start() (_jit.jitl.trampolines)
|
||||
#define jit_pfx_end() (_jit.jitl.free)
|
||||
|
||||
/* If possible, use the `small' instruction (rd, rs, imm)
|
||||
* else load imm into r26 and use the `big' instruction (rd, rs, r26)
|
||||
*/
|
||||
#define jit_chk_ims(imm, small, big) (_siP(16,(imm)) ? (small) : (MOVEIri(JIT_AUX, imm), (big)) )
|
||||
#define jit_chk_imu(imm, small, big) (_uiP(16,(imm)) ? (small) : (MOVEIri(JIT_AUX, imm), (big)) )
|
||||
#define jit_chk_imu15(imm, small, big) (_uiP(15,(imm)) ? (small) : (MOVEIri(JIT_AUX, imm), (big)) )
|
||||
|
||||
#define jit_big_ims(imm, big) (MOVEIri(JIT_AUX, imm), (big))
|
||||
#define jit_big_imu(imm, big) (MOVEIri(JIT_AUX, imm), (big))
|
||||
|
||||
/* Helper macros for branches */
|
||||
#define jit_s_brai(rs, is, jmp) (jit_chk_ims (is, CMPWIri(rs, is), CMPWrr(rs, JIT_AUX)), jmp, _jit.x.pc)
|
||||
#define jit_s_brar(s1, s2, jmp) ( CMPWrr(s1, s2), jmp, _jit.x.pc)
|
||||
#define jit_u_brai(rs, is, jmp) (jit_chk_imu (is, CMPLWIri(rs, is), CMPLWrr(rs, JIT_AUX)), jmp, _jit.x.pc)
|
||||
#define jit_u_brar(s1, s2, jmp) ( CMPLWrr(s1, s2), jmp, _jit.x.pc)
|
||||
|
||||
/* Helper macros for boolean tests. */
|
||||
#define jit_sbooli(d, rs, is, jmp) (jit_chk_ims (is, CMPWIri (rs, is), CMPWrr(rs, JIT_AUX)), MFCRr((d)), EXTRWIrrii((d), (d), 1, (jmp)))
|
||||
#define jit_sboolr(d, s1, s2, jmp) ( CMPWrr (s1, s2), MFCRr((d)), EXTRWIrrii((d), (d), 1, (jmp)))
|
||||
#define jit_sbooli2(d, rs, is, jmp) (jit_chk_ims (is, CMPWIri (rs, is), CMPWrr(rs, JIT_AUX)), MFCRr((d)), EXTRWIrrii((d), (d), 1, (jmp)), XORIrri((d), (d), 1))
|
||||
#define jit_sboolr2(d, s1, s2, jmp) ( CMPWrr (s1, s2), MFCRr((d)), EXTRWIrrii((d), (d), 1, (jmp)), XORIrri((d), (d), 1))
|
||||
#define jit_ubooli(d, rs, is, jmp) (jit_chk_imu (is, CMPLWIri(rs, is), CMPLWrr(rs, JIT_AUX)), MFCRr((d)), EXTRWIrrii((d), (d), 1, (jmp)))
|
||||
#define jit_uboolr(d, s1, s2, jmp) ( CMPLWrr (s1, s2), MFCRr((d)), EXTRWIrrii((d), (d), 1, (jmp)))
|
||||
#define jit_ubooli2(d, rs, is, jmp) (jit_chk_imu (is, CMPLWIri(rs, is), CMPLWrr(rs, JIT_AUX)), MFCRr((d)), EXTRWIrrii((d), (d), 1, (jmp)), XORIrri((d), (d), 1))
|
||||
#define jit_uboolr2(d, s1, s2, jmp) ( CMPLWrr (s1, s2), MFCRr((d)), EXTRWIrrii((d), (d), 1, (jmp)), XORIrri((d), (d), 1))
|
||||
|
||||
/* modulus with immediate
|
||||
* movei r26, imm
|
||||
* mtlr r31
|
||||
* divw r31, rs, r26 (or divwu)
|
||||
* mullw r31, r31, r26
|
||||
* sub rs, rs, r26
|
||||
* mflr r31
|
||||
*/
|
||||
|
||||
#define _jit_mod(div, rs, imm) (MOVEIri(JIT_AUX, (imm)), MTLRr(31), (div), \
|
||||
MULLWrrr(31, 31, JIT_AUX), SUBrrr((rs), (rs), JIT_AUX), \
|
||||
MFLRr(31))
|
||||
|
||||
/* Patch a movei instruction made of a LIS at lis_pc and an ORI at ori_pc. */
|
||||
#define jit_patch_movei(lis_pc, ori_pc, dest) \
|
||||
(*(lis_pc) &= ~_MASK(16), *(lis_pc) |= _HI(dest), \
|
||||
*(ori_pc) &= ~_MASK(16), *(ori_pc) |= _LO(dest)) \
|
||||
|
||||
/* Patch a branch instruction */
|
||||
#define jit_patch_branch(jump_pc,pv) \
|
||||
(*(jump_pc) &= ~_MASK(16) | 3, \
|
||||
*(jump_pc) |= (_jit_UL(pv) - _jit_UL(jump_pc)) & _MASK(16))
|
||||
|
||||
#define jit_patch_ucbranch(jump_pc,pv) \
|
||||
(*(jump_pc) &= ~_MASK(26) | 3, \
|
||||
(*(jump_pc) |= (_jit_UL((pv)) - _jit_UL(jump_pc)) & _MASK(26)))
|
||||
|
||||
#define _jit_b_encoding (18 << 26)
|
||||
#define _jit_blr_encoding ((19 << 26) | (20 << 21) | (00 << 16) | (00 << 11) | (16 << 1))
|
||||
#define _jit_is_ucbranch(a) (((*(a) & (63<<26)) == _jit_b_encoding))
|
||||
|
||||
#define jit_patch_at(jump_pc, value) ( \
|
||||
((*(jump_pc - 1) & ~1) == _jit_blr_encoding) \
|
||||
? jit_patch_movei(((jump_pc) - 4), ((jump_pc) - 3), (value)) \
|
||||
: ( _jit_is_ucbranch((jump_pc) - 1) \
|
||||
? jit_patch_ucbranch((jump_pc) - 1, (value)) \
|
||||
: jit_patch_branch((jump_pc) - 1, (value))))
|
||||
|
||||
#define jit_patch_movi(movi_pc, val) \
|
||||
jit_patch_movei((movi_pc) - 2, (movi_pc) - 1, (val))
|
||||
|
||||
#define jit_arg_c() (_jitl.nextarg_geti--)
|
||||
#define jit_arg_i() (_jitl.nextarg_geti--)
|
||||
#define jit_arg_l() (_jitl.nextarg_geti--)
|
||||
#define jit_arg_p() (_jitl.nextarg_geti--)
|
||||
#define jit_arg_s() (_jitl.nextarg_geti--)
|
||||
#define jit_arg_uc() (_jitl.nextarg_geti--)
|
||||
#define jit_arg_ui() (_jitl.nextarg_geti--)
|
||||
#define jit_arg_ul() (_jitl.nextarg_geti--)
|
||||
#define jit_arg_us() (_jitl.nextarg_geti--)
|
||||
|
||||
/* Check Mach-O-Runtime documentation: Must skip GPR(s) whenever "corresponding" FPR is used */
|
||||
#define jit_arg_f() (_jitl.nextarg_geti-- ,_jitl.nextarg_getd++)
|
||||
#define jit_arg_d() (_jitl.nextarg_geti-=2,_jitl.nextarg_getd++)
|
||||
|
||||
#define jit_addi_i(d, rs, is) jit_chk_ims((is), ADDICrri((d), (rs), (is)), ADDrrr((d), (rs), JIT_AUX))
|
||||
#define jit_addr_i(d, s1, s2) ADDrrr((d), (s1), (s2))
|
||||
#define jit_addci_i(d, rs, is) jit_chk_ims((is), ADDICrri((d), (rs), (is)), ADDCrrr((d), (rs), JIT_AUX))
|
||||
#define jit_addcr_i(d, s1, s2) ADDCrrr((d), (s1), (s2))
|
||||
#define jit_addxi_i(d, rs, is) (MOVEIri(JIT_AUX, (is)), ADDErrr((d), (rs), JIT_AUX))
|
||||
#define jit_addxr_i(d, s1, s2) ADDErrr((d), (s1), (s2))
|
||||
#define jit_andi_i(d, rs, is) jit_chk_imu((is), ANDI_rri((d), (rs), (is)), ANDrrr((d), (rs), JIT_AUX))
|
||||
#define jit_andr_i(d, s1, s2) ANDrrr((d), (s1), (s2))
|
||||
#define jit_bmsi_i(label, rs, is) (jit_chk_imu((is), ANDI_rri(JIT_AUX, (rs), (is)), AND_rrr(JIT_AUX, (rs), JIT_AUX)), BGTi((label)), _jit.x.pc)
|
||||
#define jit_bmci_i(label, rs, is) (jit_chk_imu((is), ANDI_rri(JIT_AUX, (rs), (is)), AND_rrr(JIT_AUX, (rs), JIT_AUX)), BEQi((label)), _jit.x.pc)
|
||||
#define jit_bmsr_i(label, s1, s2) ( AND_rrr(JIT_AUX, (s1), (s2)), BGTi((label)), _jit.x.pc)
|
||||
#define jit_bmcr_i(label, s1, s2) ( AND_rrr(JIT_AUX, (s1), (s2)), BEQi((label)), _jit.x.pc)
|
||||
#define jit_beqi_i(label, rs, is) jit_s_brai((rs), (is), BEQi((label)) )
|
||||
#define jit_beqr_i(label, s1, s2) jit_s_brar((s1), (s2), BEQi((label)) )
|
||||
#define jit_bgei_i(label, rs, is) jit_s_brai((rs), (is), BGEi((label)) )
|
||||
#define jit_bgei_ui(label, rs, is) jit_u_brai((rs), (is), BGEi((label)) )
|
||||
#define jit_bger_i(label, s1, s2) jit_s_brar((s1), (s2), BGEi((label)) )
|
||||
#define jit_bger_ui(label, s1, s2) jit_u_brar((s1), (s2), BGEi((label)) )
|
||||
#define jit_bgti_i(label, rs, is) jit_s_brai((rs), (is), BGTi((label)) )
|
||||
#define jit_bgti_ui(label, rs, is) jit_u_brai((rs), (is), BGTi((label)) )
|
||||
#define jit_bgtr_i(label, s1, s2) jit_s_brar((s1), (s2), BGTi((label)) )
|
||||
#define jit_bgtr_ui(label, s1, s2) jit_u_brar((s1), (s2), BGTi((label)) )
|
||||
#define jit_blei_i(label, rs, is) jit_s_brai((rs), (is), BLEi((label)) )
|
||||
#define jit_blei_ui(label, rs, is) jit_u_brai((rs), (is), BLEi((label)) )
|
||||
#define jit_bler_i(label, s1, s2) jit_s_brar((s1), (s2), BLEi((label)) )
|
||||
#define jit_bler_ui(label, s1, s2) jit_u_brar((s1), (s2), BLEi((label)) )
|
||||
#define jit_blti_i(label, rs, is) jit_s_brai((rs), (is), BLTi((label)) )
|
||||
#define jit_blti_ui(label, rs, is) jit_u_brai((rs), (is), BLTi((label)) )
|
||||
#define jit_bltr_i(label, s1, s2) jit_s_brar((s1), (s2), BLTi((label)) )
|
||||
#define jit_bltr_ui(label, s1, s2) jit_u_brar((s1), (s2), BLTi((label)) )
|
||||
#define jit_bnei_i(label, rs, is) jit_s_brai((rs), (is), BNEi((label)) )
|
||||
#define jit_bner_i(label, s1, s2) jit_s_brar((s1), (s2), BNEi((label)) )
|
||||
#define jit_boaddi_i(label, rs, is) (MOVEIri(JIT_AUX, (is)), ADDOrrr((rs), (rs), JIT_AUX), MCRXRi(0), BGTi((label)), _jit.x.pc) /* GT = bit 1 of XER = OV */
|
||||
#define jit_bosubi_i(label, rs, is) (MOVEIri(JIT_AUX, (is)), SUBCOrrr((rs), (rs), JIT_AUX), MCRXRi(0), BGTi((label)), _jit.x.pc)
|
||||
#define jit_boaddr_i(label, s1, s2) ( ADDOrrr((s1), (s1), (s2)), MCRXRi(0), BGTi((label)), _jit.x.pc)
|
||||
#define jit_bosubr_i(label, s1, s2) ( SUBCOrrr((s1), (s1), (s2)), MCRXRi(0), BGTi((label)), _jit.x.pc)
|
||||
#define jit_boaddi_ui(label, rs, is) (jit_chk_ims ((is), ADDICri((rs), (rs), is), ADDCrr((rs), JIT_AUX)), MCRXRi(0), BEQi((label)), _jit.x.pc) /* EQ = bit 2 of XER = CA */
|
||||
#define jit_bosubi_ui(label, rs, is) (jit_chk_ims ((is), SUBICri((rs), (rs), is), SUBCrr((rs), JIT_AUX)), MCRXRi(0), BEQi((label)), _jit.x.pc)
|
||||
#define jit_boaddr_ui(label, s1, s2) ( ADDCrr((s1), (s1), (s2)), MCRXRi(0), BEQi((label)), _jit.x.pc)
|
||||
#define jit_bosubr_ui(label, s1, s2) ( SUBCrr((s1), (s1), (s2)), MCRXRi(0), BEQi((label)), _jit.x.pc)
|
||||
#define jit_calli(label) (jit_movi_p(JIT_AUX, (label)), MTCTRr(JIT_AUX), BCTRL(), _jitl.nextarg_puti = _jitl.nextarg_putf = _jitl.nextarg_putd = 0, _jit.x.pc)
|
||||
#define jit_callr(reg) (MTCTRr(reg), BCTRL())
|
||||
#define jit_divi_i(d, rs, is) jit_big_ims((is), DIVWrrr ((d), (rs), JIT_AUX))
|
||||
#define jit_divi_ui(d, rs, is) jit_big_imu((is), DIVWUrrr((d), (rs), JIT_AUX))
|
||||
#define jit_divr_i(d, s1, s2) DIVWrrr ((d), (s1), (s2))
|
||||
#define jit_divr_ui(d, s1, s2) DIVWUrrr((d), (s1), (s2))
|
||||
#define jit_eqi_i(d, rs, is) (jit_chk_ims((is), SUBIrri(JIT_AUX, (rs), (is)), SUBrrr(JIT_AUX, (rs), JIT_AUX)), SUBFICrri((d), JIT_AUX, 0), ADDErrr((d), (d), JIT_AUX))
|
||||
#define jit_eqr_i(d, s1, s2) (SUBrrr(JIT_AUX, (s1), (s2)), SUBFICrri((d), JIT_AUX, 0), ADDErrr((d), (d), JIT_AUX))
|
||||
#define jit_extr_c_i(d, rs) EXTSBrr((d), (rs))
|
||||
#define jit_extr_s_i(d, rs) EXTSHrr((d), (rs))
|
||||
#define jit_gei_i(d, rs, is) jit_sbooli2((d), (rs), (is), _lt)
|
||||
#define jit_gei_ui(d, rs, is) jit_ubooli2((d), (rs), (is), _lt)
|
||||
#define jit_ger_i(d, s1, s2) jit_sboolr2((d), (s1), (s2), _lt)
|
||||
#define jit_ger_ui(d, s1, s2) jit_uboolr2((d), (s1), (s2), _lt)
|
||||
#define jit_gti_i(d, rs, is) jit_sbooli ((d), (rs), (is), _gt)
|
||||
#define jit_gti_ui(d, rs, is) jit_ubooli ((d), (rs), (is), _gt)
|
||||
#define jit_gtr_i(d, s1, s2) jit_sboolr ((d), (s1), (s2), _gt)
|
||||
#define jit_gtr_ui(d, s1, s2) jit_uboolr ((d), (s1), (s2), _gt)
|
||||
#define jit_hmuli_i(d, rs, is) jit_big_ims((is), MULHWrrr ((d), (rs), JIT_AUX))
|
||||
#define jit_hmuli_ui(d, rs, is) jit_big_imu((is), MULHWUrrr((d), (rs), JIT_AUX))
|
||||
#define jit_hmulr_i(d, s1, s2) MULHWrrr ((d), (s1), (s2))
|
||||
#define jit_hmulr_ui(d, s1, s2) MULHWUrrr((d), (s1), (s2))
|
||||
#define jit_jmpi(label) (B_EXT((label)), _jit.x.pc)
|
||||
#define jit_jmpr(reg) (MTLRr(reg), BLR())
|
||||
#define jit_ldxi_c(d, rs, is) (jit_ldxi_uc((d), (rs), (is)), jit_extr_c_i((d), (d)))
|
||||
#define jit_ldxr_c(d, s1, s2) (jit_ldxr_uc((d), (s1), (s2)), jit_extr_c_i((d), (d)))
|
||||
#define jit_ldxi_i(d, rs, is) jit_chk_ims((d), LWZrm((d), (is), (rs)), LWZrx((d), JIT_AUX, (rs)))
|
||||
#define jit_ldxi_s(d, rs, is) jit_chk_ims((d), LHArm((d), (is), (rs)), LHArx((d), JIT_AUX, (rs)))
|
||||
#define jit_ldxi_uc(d, rs, is) jit_chk_ims((d), LBZrm((d), (is), (rs)), LBZrx((d), JIT_AUX, (rs)))
|
||||
#define jit_ldxi_us(d, rs, is) jit_chk_ims((d), LHZrm((d), (is), (rs)), LHZrx((d), JIT_AUX, (rs)))
|
||||
#define jit_ldxr_i(d, s1, s2) LWZrx((d), (s1), (s2))
|
||||
#define jit_ldxr_s(d, s1, s2) LHArx((d), (s1), (s2))
|
||||
#define jit_ldxr_uc(d, s1, s2) LBZrx((d), (s1), (s2))
|
||||
#define jit_ldxr_us(d, s1, s2) LHZrx((d), (s1), (s2))
|
||||
#define jit_lei_i(d, rs, is) jit_sbooli2((d), (rs), (is), _gt )
|
||||
#define jit_lei_ui(d, rs, is) jit_ubooli2((d), (rs), (is), _gt )
|
||||
#define jit_ler_i(d, s1, s2) jit_sboolr2((d), (s1), (s2), _gt )
|
||||
#define jit_ler_ui(d, s1, s2) jit_uboolr2((d), (s1), (s2), _gt )
|
||||
#define jit_lshi_i(d, rs, is) SLWIrri((d), (rs), (is))
|
||||
#define jit_lshr_i(d, s1, s2) (ANDI_rri(JIT_AUX, (s2), 31), SLWrrr ((d), (s1), JIT_AUX))
|
||||
#define jit_lti_i(d, rs, is) jit_sbooli ((d), (rs), (is), _lt )
|
||||
#define jit_lti_ui(d, rs, is) jit_ubooli ((d), (rs), (is), _lt )
|
||||
#define jit_ltr_i(d, s1, s2) jit_sboolr ((d), (s1), (s2), _lt )
|
||||
#define jit_ltr_ui(d, s1, s2) jit_uboolr ((d), (s1), (s2), _lt )
|
||||
#define jit_modi_i(d, rs, is) _jit_mod(jit_divi_i (31, (rs), JIT_AUX), (rs), (is))
|
||||
#define jit_modi_ui(d, rs, is) _jit_mod(jit_divi_ui(31, (rs), JIT_AUX), (rs), (is))
|
||||
#define jit_modr_i(d, s1, s2) (DIVWrrr(JIT_AUX, (s1), (s2)), MULLWrrr(JIT_AUX, JIT_AUX, (s2)), SUBrrr((d), (s1), JIT_AUX))
|
||||
#define jit_modr_ui(d, s1, s2) (DIVWUrrr(JIT_AUX, (s1), (s2)), MULLWrrr(JIT_AUX, JIT_AUX, (s2)), SUBrrr((d), (s1), JIT_AUX))
|
||||
#define jit_movi_i(d, is) MOVEIri((d), (is))
|
||||
#define jit_movi_p(d, is) (LISri((d), _HI((is))),ORIrri((d),(d),_LO((is))),_jit.x.pc)
|
||||
|
||||
#define jit_movr_i(d, rs) MRrr((d), (rs))
|
||||
#define jit_muli_i(d, rs, is) jit_chk_ims ((is), MULLIrri((d), (rs), (is)), MULLWrrr((d), (rs), JIT_AUX))
|
||||
#define jit_muli_ui(d, rs, is) jit_chk_imu15((is), MULLIrri((d), (rs), (is)), MULLWrrr((d), (rs), JIT_AUX))
|
||||
#define jit_mulr_i(d, s1, s2) MULLWrrr((d), (s1), (s2))
|
||||
#define jit_mulr_ui(d, s1, s2) MULLWrrr((d), (s1), (s2))
|
||||
#define jit_nei_i(d, rs, is) (jit_chk_ims((is), SUBIrri(JIT_AUX, (rs), (is)), SUBrrr(JIT_AUX, (rs), JIT_AUX)), ADDICrri((d), JIT_AUX, -1), SUBFErrr((d), (d), JIT_AUX))
|
||||
#define jit_ner_i(d, s1, s2) (SUBrrr(JIT_AUX, (s1), (s2)), ADDICrri((d), JIT_AUX, -1), SUBFErrr((d), (d), JIT_AUX))
|
||||
#define jit_nop() NOP()
|
||||
#define jit_ori_i(d, rs, is) jit_chk_imu((is), ORIrri((d), (rs), (is)), ORrrr((d), (rs), JIT_AUX))
|
||||
#define jit_orr_i(d, s1, s2) ORrrr((d), (s1), (s2))
|
||||
#define jit_popr_i(rs) (LWZrm((rs), 0, 1), ADDIrri(1, 1, 4))
|
||||
#define jit_prepare_i(numi) (_jitl.nextarg_puti = numi)
|
||||
#define jit_prepare_f(numf) (_jitl.nextarg_putf = numf)
|
||||
#define jit_prepare_d(numd) (_jitl.nextarg_putd = numd)
|
||||
#define jit_prolog(n) _jit_prolog(&_jit, (n))
|
||||
#define jit_pushr_i(rs) STWUrm((rs), -4, 1)
|
||||
#define jit_pusharg_i(rs) (--_jitl.nextarg_puti, MRrr((3 + _jitl.nextarg_putd * 2 + _jitl.nextarg_putf + _jitl.nextarg_puti), (rs)))
|
||||
#define jit_ret() _jit_epilog(&_jit)
|
||||
#define jit_retval_i(rd) MRrr((rd), 3)
|
||||
#define jit_rsbi_i(d, rs, is) jit_chk_ims((is), SUBFICrri((d), (rs), (is)), SUBFCrrr((d), (rs), JIT_AUX))
|
||||
#define jit_rshi_i(d, rs, is) SRAWIrri((d), (rs), (is))
|
||||
#define jit_rshi_ui(d, rs, is) SRWIrri ((d), (rs), (is))
|
||||
#define jit_rshr_i(d, s1, s2) (ANDI_rri(JIT_AUX, (s2), 31), SRAWrrr ((d), (s1), JIT_AUX))
|
||||
#define jit_rshr_ui(d, s1, s2) (ANDI_rri(JIT_AUX, (s2), 31), SRWrrr ((d), (s1), JIT_AUX))
|
||||
#define jit_stxi_c(id, rd, rs) jit_chk_ims((id), STBrm((rs), (id), (rd)), STBrx((rs), (rd), JIT_AUX))
|
||||
#define jit_stxi_i(id, rd, rs) jit_chk_ims((id), STWrm((rs), (id), (rd)), STWrx((rs), (rd), JIT_AUX))
|
||||
#define jit_stxi_s(id, rd, rs) jit_chk_ims((id), STHrm((rs), (id), (rd)), STHrx((rs), (rd), JIT_AUX))
|
||||
#define jit_stxr_c(d1, d2, rs) STBrx((rs), (d1), (d2))
|
||||
#define jit_stxr_i(d1, d2, rs) STWrx((rs), (d1), (d2))
|
||||
#define jit_stxr_s(d1, d2, rs) STHrx((rs), (d1), (d2))
|
||||
#define jit_subr_i(d, s1, s2) SUBrrr((d), (s1), (s2))
|
||||
#define jit_subcr_i(d, s1, s2) SUBCrrr((d), (s1), (s2))
|
||||
#define jit_subxi_i(d, rs, is) jit_big_ims((is), SUBErrr((d), (rs), JIT_AUX))
|
||||
#define jit_subxr_i(d, s1, s2) SUBErrr((d), (s1), (s2))
|
||||
#define jit_xori_i(d, rs, is) jit_chk_imu((is), XORIrri((d), (rs), (is)), XORrrr((d), (rs), JIT_AUX))
|
||||
#define jit_xorr_i(d, s1, s2) XORrrr((d), (s1), (s2))
|
||||
|
||||
/* Cannot use JIT_RZERO because having 0 in a register field on the PowerPC
|
||||
* does not mean `a register whose value is 0', but rather `no register at
|
||||
* all' */
|
||||
|
||||
#define jit_negr_i(d, rs) jit_rsbi_i((d), (rs), 0)
|
||||
#define jit_negr_l(d, rs) jit_rsbi_l((d), (rs), 0)
|
||||
#define jit_ldr_c(rd, rs) jit_ldxr_c((rd), 0, (rs))
|
||||
#define jit_str_c(rd, rs) jit_stxr_c(0, (rd), (rs))
|
||||
#define jit_ldr_s(rd, rs) jit_ldxr_s((rd), 0, (rs))
|
||||
#define jit_str_s(rd, rs) jit_stxr_s(0, (rd), (rs))
|
||||
#define jit_ldr_i(rd, rs) jit_ldxr_i((rd), 0, (rs))
|
||||
#define jit_str_i(rd, rs) jit_stxr_i(0, (rd), (rs))
|
||||
#define jit_ldr_uc(rd, rs) jit_ldxr_uc((rd), 0, (rs))
|
||||
#define jit_ldr_us(rd, rs) jit_ldxr_us((rd), 0, (rs))
|
||||
|
||||
/* e.g.
|
||||
* 0x01234567 _HA << 16 = 0x01230000 _LA = 0x00004567 _HA << 16 + LA = 0x01234567
|
||||
* 0x89abcdef _HA << 16 = 0x89ac0000 _LA = 0xffffcdef _HA << 16 + LA = 0x89abcdef
|
||||
*/
|
||||
#define _HA(addr) ((_jit_UL(addr) >> 16) + (_jit_US(_jit_UL(addr)) >> 15))
|
||||
#define _LA(addr) (_jit_UL(addr) - (_HA(addr) << 16))
|
||||
|
||||
#define jit_ldi_c(rd, is) (LISri(JIT_AUX, _HA(is)), jit_ldxi_c((rd), JIT_AUX, _LA(is)))
|
||||
#define jit_sti_c(id, rs) (LISri(JIT_AUX, _HA(id)), jit_stxi_c(_LA(id), JIT_AUX, (rs)))
|
||||
#define jit_ldi_s(rd, is) (LISri(JIT_AUX, _HA(is)), jit_ldxi_s((rd), JIT_AUX, _LA(is)))
|
||||
#define jit_sti_s(id, rs) (LISri(JIT_AUX, _HA(id)), jit_stxi_s(_LA(id), JIT_AUX, (rs)))
|
||||
#define jit_ldi_i(rd, is) (LISri(JIT_AUX, _HA(is)), jit_ldxi_i((rd), JIT_AUX, _LA(is)))
|
||||
#define jit_sti_i(id, rs) (LISri(JIT_AUX, _HA(id)), jit_stxi_i(_LA(id), JIT_AUX, (rs)))
|
||||
#define jit_ldi_uc(rd, is) (LISri(JIT_AUX, _HA(is)), jit_ldxi_uc((rd), JIT_AUX, _LA(is)))
|
||||
#define jit_ldi_us(rd, is) (LISri(JIT_AUX, _HA(is)), jit_ldxi_us((rd), JIT_AUX, _LA(is)))
|
||||
|
||||
#endif /* __lightning_core_h */
|
||||
@@ -1,211 +0,0 @@
|
||||
/******************************** -*- C -*- ****************************
|
||||
*
|
||||
* Run-time assembler & support macros for the Sparc math unit
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
* Written by Paolo Bonzini.
|
||||
*
|
||||
* This file is part of GNU lightning.
|
||||
*
|
||||
* GNU lightning is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2.1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU lightning is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with GNU lightning; see the file COPYING.LESSER; if not, write to the
|
||||
* Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef __lightning_asm_fp_h
|
||||
#define __lightning_asm_fp_h
|
||||
|
||||
|
||||
#define JIT_FPR_NUM 6
|
||||
#define JIT_FPR(i) (8+(i))
|
||||
|
||||
#define JIT_FPFR 0
|
||||
|
||||
/* Make space for 1 or 2 words, store address in REG */
|
||||
#define jit_data(REG, D1) (_FBA (18, 8, 0, 1), _jit_L(D1), MFLRr(REG))
|
||||
|
||||
#define jit_addr_d(rd,s1,s2) FADDDrrr((rd),(s1),(s2))
|
||||
#define jit_subr_d(rd,s1,s2) FSUBDrrr((rd),(s1),(s2))
|
||||
#define jit_mulr_d(rd,s1,s2) FMULDrrr((rd),(s1),(s2))
|
||||
#define jit_divr_d(rd,s1,s2) FDIVDrrr((rd),(s1),(s2))
|
||||
|
||||
#define jit_addr_f(rd,s1,s2) FADDSrrr((rd),(s1),(s2))
|
||||
#define jit_subr_f(rd,s1,s2) FSUBSrrr((rd),(s1),(s2))
|
||||
#define jit_mulr_f(rd,s1,s2) FMULSrrr((rd),(s1),(s2))
|
||||
#define jit_divr_f(rd,s1,s2) FDIVSrrr((rd),(s1),(s2))
|
||||
|
||||
#define jit_movr_d(rd,rs) ( (rd) == (rs) ? 0 : FMOVErr((rd),(rs)))
|
||||
#define jit_movi_d(reg0,d) do { \
|
||||
double _v = (d); \
|
||||
_FBA (18, 12, 0, 1); \
|
||||
memcpy(_jit.x.uc_pc, &_v, sizeof (double)); \
|
||||
_jit.x.uc_pc += sizeof (double); \
|
||||
MFLRr (JIT_AUX); \
|
||||
jit_ldxi_d((reg0), JIT_AUX, 0); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define jit_movr_f(rd,rs) ( (rd) == (rs) ? 0 : FMOVErr((rd),(rs)))
|
||||
#define jit_movi_f(reg0,f) do { \
|
||||
float _v = (f); \
|
||||
_FBA (18, 8, 0, 1); \
|
||||
memcpy(_jit.x.uc_pc, &_v, sizeof (float)); \
|
||||
_jit.x.uc_pc += sizeof (float); \
|
||||
MFLRr (JIT_AUX); \
|
||||
jit_ldxi_f((reg0), JIT_AUX, 0); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define jit_abs_d(rd,rs) FABSrr((rd),(rs))
|
||||
#define jit_negr_d(rd,rs) FNEGrr((rd),(rs))
|
||||
#define jit_sqrt_d(rd,rs) FSQRTDrr((rd),(rs))
|
||||
|
||||
|
||||
#define jit_ldxi_f(reg0, rs, is) (_siP(16,(is)) ? LFSrri((reg0),(rs),(is)) : (MOVEIri(JIT_AUX,(is)),LFSxrrr((reg0),(rs),JIT_AUX)))
|
||||
#define jit_ldxi_d(reg0, rs, is) (_siP(16,(is)) ? LFDrri((reg0),(rs),(is)) : (MOVEIri(JIT_AUX,(is)),LFDxrrr((reg0),(rs),JIT_AUX)))
|
||||
#define jit_ldxr_f(reg0, s1, s2) LFSxrrr((reg0),(s1),(s2))
|
||||
#define jit_ldxr_d(reg0, s1, s2) LFDxrrr((reg0),(s1),(s2))
|
||||
#define jit_ldi_f(reg0, is) (_siP(16,(is)) ? LFSrri((reg0),0,(is)) : (MOVEIri(JIT_AUX,(is)),LFSrri((reg0),JIT_AUX,0)))
|
||||
#define jit_ldi_d(reg0, is) (_siP(16,(is)) ? LFDrri((reg0),0,(is)) : (MOVEIri(JIT_AUX,(is)),LFDrri((reg0),JIT_AUX,0)))
|
||||
#define jit_ldr_f(reg0, rs) LFSrri((reg0),(rs),0)
|
||||
#define jit_ldr_d(reg0, rs) LFDrri((reg0),(rs),0)
|
||||
#define jit_stxi_f(id, rd, reg0) (_siP(16,(id)) ? STFSrri((reg0),(rd),(id)) : (MOVEIri(JIT_AUX,(id)),STFSrri((reg0),(rd),JIT_AUX)))
|
||||
#define jit_stxi_d(id, rd, reg0) (_siP(16,(id)) ? STFDrri((reg0),(rd),(id)) : (MOVEIri(JIT_AUX,(id)),STFDrri((reg0),(rd),JIT_AUX)))
|
||||
#define jit_stxr_f(d1, d2, reg0) STFSxrrr((reg0),(d1),(d2))
|
||||
#define jit_stxr_d(d1, d2, reg0) STFDxrrr((reg0),(d1),(d2))
|
||||
#define jit_sti_f(id, reg0) (_siP(16,(id)) ? STFSrri((reg0),0,(id)) : (MOVEIri(JIT_AUX,(id)),STFSrri((reg0),JIT_AUX,0)))
|
||||
#define jit_sti_d(id, reg0) (_siP(16,(id)) ? STFDrri((reg0),0,(id)) : (MOVEIri(JIT_AUX,(id)),STFDrri((reg0),JIT_AUX,0)))
|
||||
#define jit_str_f(rd, reg0) STFSrri((reg0),(rd),0)
|
||||
#define jit_str_d(rd, reg0) STFDrri((reg0),(rd),0)
|
||||
|
||||
#define jit_fpboolr(d, s1, s2, rcbit) ( \
|
||||
FCMPOrrr(_cr0,(s1),(s2)), \
|
||||
MFCRr((d)), \
|
||||
EXTRWIrrii((d), (d), 1, (rcbit)))
|
||||
|
||||
#define jit_fpboolr_neg(d, s1, s2,rcbit) ( \
|
||||
FCMPOrrr(_cr0,(s1),(s2)), \
|
||||
MFCRr((d)), \
|
||||
EXTRWIrrii((d), (d), 1, (rcbit)), \
|
||||
XORIrri((d), (d), 1))
|
||||
|
||||
#define jit_fpboolur(d, s1, s2, rcbit) ( \
|
||||
FCMPUrrr(_cr0,(s1),(s2)), \
|
||||
MFCRr((d)), \
|
||||
EXTRWIrrii((d), (d), 1, (rcbit)))
|
||||
|
||||
#define jit_fpboolur_neg(d, s1, s2,rcbit) ( \
|
||||
FCMPUrrr(_cr0,(s1),(s2)), \
|
||||
MFCRr((d)), \
|
||||
EXTRWIrrii((d), (d), 1, (rcbit)), \
|
||||
XORIrri((d), (d), 1))
|
||||
|
||||
#define jit_fpboolur_or(d, s1, s2, bit1, bit2) (\
|
||||
FCMPUrrr(_cr0,(s1),(s2)), \
|
||||
CRORiii((bit1), (bit1), (bit2)), \
|
||||
MFCRr((d)), \
|
||||
EXTRWIrrii((d), (d), 1, (bit1)))
|
||||
|
||||
#define jit_gtr_d(d, s1, s2) jit_fpboolr ((d),(s1),(s2),_gt)
|
||||
#define jit_ger_d(d, s1, s2) jit_fpboolr_neg((d),(s1),(s2),_lt)
|
||||
#define jit_ltr_d(d, s1, s2) jit_fpboolr ((d),(s1),(s2),_lt)
|
||||
#define jit_ler_d(d, s1, s2) jit_fpboolr_neg((d),(s1),(s2),_gt)
|
||||
#define jit_eqr_d(d, s1, s2) jit_fpboolr ((d),(s1),(s2),_eq)
|
||||
#define jit_ner_d(d, s1, s2) jit_fpboolr_neg((d),(s1),(s2),_eq)
|
||||
#define jit_unordr_d(d, s1, s2) jit_fpboolur ((d),(s1),(s2),_un)
|
||||
#define jit_ordr_d(d, s1, s2) jit_fpboolur_neg((d),(s1),(s2),_un)
|
||||
#define jit_unler_d(d, s1, s2) jit_fpboolur_neg ((d), (s1), (s2), _gt)
|
||||
#define jit_unltr_d(d, s1, s2) jit_fpboolur_or ((d), (s1), (s2), _un, _lt)
|
||||
#define jit_unger_d(d, s1, s2) jit_fpboolur_neg ((d), (s1), (s2), _lt)
|
||||
#define jit_ungtr_d(d, s1, s2) jit_fpboolur_or ((d), (s1), (s2), _un, _gt)
|
||||
#define jit_ltgtr_d(d, s1, s2) jit_fpboolur_or ((d), (s1), (s2), _gt, _lt)
|
||||
#define jit_uneqr_d(d, s1, s2) jit_fpboolur_or ((d), (s1), (s2), _un, _eq)
|
||||
|
||||
#define jit_fpbr(d, s1, s2, rcbit) ( \
|
||||
FCMPOrrr(_cr0,(s1),(s2)), \
|
||||
BTii ((rcbit), (d)))
|
||||
|
||||
#define jit_fpbr_neg(d, s1, s2,rcbit) ( \
|
||||
FCMPOrrr(_cr0,(s1),(s2)), \
|
||||
BFii ((rcbit), (d)))
|
||||
|
||||
#define jit_fpbur(d, s1, s2, rcbit) ( \
|
||||
FCMPUrrr(_cr0,(s1),(s2)), \
|
||||
BTii ((rcbit), (d)))
|
||||
|
||||
#define jit_fpbur_neg(d, s1, s2,rcbit) ( \
|
||||
FCMPUrrr(_cr0,(s1),(s2)), \
|
||||
BFii ((rcbit), (d)))
|
||||
|
||||
#define jit_fpbur_or(d, s1, s2, bit1, bit2) ( \
|
||||
FCMPUrrr(_cr0,(s1),(s2)), \
|
||||
CRORiii((bit1), (bit1), (bit2)), \
|
||||
BTii ((bit1), (d)))
|
||||
|
||||
#define jit_bgtr_d(d, s1, s2) jit_fpbr ((d),(s1),(s2),_gt)
|
||||
#define jit_bger_d(d, s1, s2) jit_fpbr_neg((d),(s1),(s2),_lt)
|
||||
#define jit_bltr_d(d, s1, s2) jit_fpbr ((d),(s1),(s2),_lt)
|
||||
#define jit_bler_d(d, s1, s2) jit_fpbr_neg((d),(s1),(s2),_gt)
|
||||
#define jit_beqr_d(d, s1, s2) jit_fpbr ((d),(s1),(s2),_eq)
|
||||
#define jit_bner_d(d, s1, s2) jit_fpbr_neg((d),(s1),(s2),_eq)
|
||||
#define jit_bunordr_d(d, s1, s2) jit_fpbur ((d),(s1),(s2),_un)
|
||||
#define jit_bordr_d(d, s1, s2) jit_fpbur_neg((d),(s1),(s2),_un)
|
||||
#define jit_bunler_d(d, s1, s2) jit_fpbur_neg ((d), (s1), (s2), _gt)
|
||||
#define jit_bunltr_d(d, s1, s2) jit_fpbur_or ((d), (s1), (s2), _un, _lt)
|
||||
#define jit_bunger_d(d, s1, s2) jit_fpbur_neg ((d), (s1), (s2), _lt)
|
||||
#define jit_bungtr_d(d, s1, s2) jit_fpbur_or ((d), (s1), (s2), _un, _gt)
|
||||
#define jit_bltgtr_d(d, s1, s2) jit_fpbur_or ((d), (s1), (s2), _gt, _lt)
|
||||
#define jit_buneqr_d(d, s1, s2) jit_fpbur_or ((d), (s1), (s2), _un, _eq)
|
||||
|
||||
#define jit_getarg_f(rd, ofs) jit_movr_f((rd),(ofs))
|
||||
#define jit_getarg_d(rd, ofs) jit_movr_d((rd),(ofs))
|
||||
#define jit_pusharg_d(rs) (_jitl.nextarg_putd--,jit_movr_d((_jitl.nextarg_putf+_jitl.nextarg_putd+1), (rs)))
|
||||
#define jit_pusharg_f(rs) (_jitl.nextarg_putf--,jit_movr_f((_jitl.nextarg_putf+_jitl.nextarg_putd+1), (rs)))
|
||||
#define jit_retval_d(op1) jit_movr_d(1, (op1))
|
||||
#define jit_retval_f(op1) jit_movr_f(1, (op1))
|
||||
|
||||
|
||||
#define jit_floorr_d_i(rd,rs) (MTFSFIri(7,3), \
|
||||
FCTIWrr(7,(rs)), \
|
||||
MOVEIri(JIT_AUX,-4), \
|
||||
STFIWXrrr(7,JIT_SP,JIT_AUX), \
|
||||
LWZrm((rd),-4,JIT_SP))
|
||||
|
||||
#define jit_ceilr_d_i(rd,rs) (MTFSFIri(7,2), \
|
||||
FCTIWrr(7,(rs)), \
|
||||
MOVEIri(JIT_AUX,-4), \
|
||||
STFIWXrrr(7,JIT_SP,JIT_AUX), \
|
||||
LWZrm((rd),-4,JIT_SP))
|
||||
|
||||
#define jit_roundr_d_i(rd,rs) (MTFSFIri(7,0), \
|
||||
FCTIWrr(7,(rs)), \
|
||||
MOVEIri(JIT_AUX,-4), \
|
||||
STFIWXrrr(7,JIT_SP,JIT_AUX), \
|
||||
LWZrm((rd),-4,JIT_SP))
|
||||
|
||||
#define jit_truncr_d_i(rd,rs) (FCTIWZrr(7,(rs)), \
|
||||
MOVEIri(JIT_AUX,-4), \
|
||||
STFIWXrrr(7,JIT_SP,JIT_AUX), \
|
||||
LWZrm((rd),-4,JIT_SP))
|
||||
|
||||
#endif /* __lightning_asm_h */
|
||||
@@ -1,164 +0,0 @@
|
||||
/******************************** -*- C -*- ****************************
|
||||
*
|
||||
* Platform-independent layer inline functions (PowerPC)
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Copyright 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
* Written by Paolo Bonzini.
|
||||
*
|
||||
* This file is part of GNU lightning.
|
||||
*
|
||||
* GNU lightning is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2.1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU lightning is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with GNU lightning; see the file COPYING.LESSER; if not, write to the
|
||||
* Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef __lightning_funcs_h
|
||||
#define __lightning_funcs_h
|
||||
|
||||
#if !defined(__GNUC__) && !defined(__GNUG__)
|
||||
#error Go get GNU C, I do not know how to flush the cache
|
||||
#error with this compiler.
|
||||
#else
|
||||
static void
|
||||
jit_flush_code(void *start, void *end)
|
||||
{
|
||||
#ifndef LIGHTNING_CROSS
|
||||
register char *ddest, *idest;
|
||||
|
||||
static int cache_line_size;
|
||||
if (cache_line_size == 0) {
|
||||
char buffer[8192];
|
||||
int i, probe;
|
||||
|
||||
/* Find out the size of a cache line by zeroing one */
|
||||
memset(buffer, 0xFF, 8192);
|
||||
__asm__ __volatile__ ("dcbz 0,%0" : : "r"(buffer + 4096));
|
||||
|
||||
/* Probe for the beginning of the cache line. */
|
||||
for(i = 0, probe = 4096; probe; probe >>= 1)
|
||||
if (buffer[i | probe] != 0x00)
|
||||
i |= probe;
|
||||
|
||||
/* i is now just before the start of the cache line */
|
||||
i++;
|
||||
for(cache_line_size = 1; i + cache_line_size < 8192; cache_line_size <<= 1)
|
||||
if (buffer[i + cache_line_size] != 0x00)
|
||||
break;
|
||||
}
|
||||
|
||||
start -= ((long) start) & (cache_line_size - 1);
|
||||
end -= ((long) end) & (cache_line_size - 1);
|
||||
|
||||
/* Force data cache write-backs */
|
||||
for (ddest = (char *) start; ddest <= (char *) end; ddest += cache_line_size) {
|
||||
__asm__ __volatile__ ("dcbst 0,%0" : : "r"(ddest));
|
||||
}
|
||||
__asm__ __volatile__ ("sync" : : );
|
||||
|
||||
/* Now invalidate the instruction cache */
|
||||
for (idest = (char *) start; idest <= (char *) end; idest += cache_line_size) {
|
||||
__asm__ __volatile__ ("icbi 0,%0" : : "r"(idest));
|
||||
}
|
||||
__asm__ __volatile__ ("isync" : : );
|
||||
#endif /* !LIGHTNING_CROSS */
|
||||
}
|
||||
#endif /* __GNUC__ || __GNUG__ */
|
||||
|
||||
#define _jit (*jit)
|
||||
|
||||
static void
|
||||
_jit_epilog(jit_state *jit)
|
||||
{
|
||||
int n = _jitl.nbArgs;
|
||||
int frame_size, ofs;
|
||||
int first_saved_reg = JIT_AUX - n;
|
||||
int num_saved_regs = 32 - first_saved_reg;
|
||||
|
||||
frame_size = 24 + 32 + num_saved_regs * 4; /* r24..r31 + args */
|
||||
frame_size += 15; /* the stack must be quad-word */
|
||||
frame_size &= ~15; /* aligned */
|
||||
|
||||
#ifdef _CALL_DARWIN
|
||||
LWZrm(0, frame_size + 8, 1); /* lwz r0, x+8(r1) (ret.addr.) */
|
||||
#else
|
||||
LWZrm(0, frame_size + 4, 1); /* lwz r0, x+4(r1) (ret.addr.) */
|
||||
#endif
|
||||
MTLRr(0); /* mtspr LR, r0 */
|
||||
|
||||
ofs = frame_size - num_saved_regs * 4;
|
||||
LMWrm(first_saved_reg, ofs, 1); /* lmw rI, ofs(r1) */
|
||||
ADDIrri(1, 1, frame_size); /* addi r1, r1, x */
|
||||
BLR(); /* blr */
|
||||
}
|
||||
|
||||
/* Emit a prolog for a function.
|
||||
Upon entrance to the trampoline:
|
||||
- LR = address where the real code for the function lies
|
||||
- R3-R8 = parameters
|
||||
Upon finishing the trampoline:
|
||||
- R0 = return address for the function
|
||||
- R25-R20 = parameters (order is reversed, 1st argument is R25)
|
||||
|
||||
The +32 in frame_size computation is to accound for the parameter area of
|
||||
a function frame.
|
||||
|
||||
On PPC the frame must have space to host the arguments of any callee.
|
||||
However, as it currently stands, the argument to jit_trampoline (n) is
|
||||
the number of arguments of the caller we generate. Therefore, the
|
||||
callee can overwrite a part of the stack (saved register area when it
|
||||
flushes its own parameter on the stack. The addition of a constant
|
||||
offset = 32 is enough to hold eight 4 bytes arguments. This is less
|
||||
than perfect but is a reasonable work around for now.
|
||||
Better solution must be investigated. */
|
||||
static void
|
||||
_jit_prolog(jit_state *jit, int n)
|
||||
{
|
||||
int frame_size;
|
||||
int ofs, i;
|
||||
int first_saved_reg = JIT_AUX - n;
|
||||
int num_saved_regs = 32 - first_saved_reg;
|
||||
|
||||
_jitl.nextarg_geti = JIT_AUX - 1;
|
||||
_jitl.nextarg_getd = 1;
|
||||
_jitl.nbArgs = n;
|
||||
|
||||
frame_size = 24 + 32 + num_saved_regs * 4; /* r27..r31 + args */
|
||||
frame_size += 15; /* the stack must be quad-word */
|
||||
frame_size &= ~15; /* aligned */
|
||||
|
||||
MFLRr(0);
|
||||
STWUrm(1, -frame_size, 1); /* stwu r1, -x(r1) */
|
||||
|
||||
ofs = frame_size - num_saved_regs * 4;
|
||||
STMWrm(first_saved_reg, ofs, 1); /* stmw rI, ofs(r1) */
|
||||
#ifdef _CALL_DARWIN
|
||||
STWrm(0, frame_size + 8, 1); /* stw r0, x+8(r1) */
|
||||
#else
|
||||
STWrm(0, frame_size + 4, 1); /* stw r0, x+4(r1) */
|
||||
#endif
|
||||
for (i = 0; i < n; i++)
|
||||
MRrr(JIT_AUX-1-i, 3+i); /* save parameters below r24 */
|
||||
}
|
||||
|
||||
#undef _jit
|
||||
|
||||
#endif /* __lightning_funcs_h */
|
||||
@@ -1,383 +0,0 @@
|
||||
/******************************** -*- C -*- ****************************
|
||||
*
|
||||
* Run-time assembler for the SPARC
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Copyright 1999, 2000, 2001, 2002 Ian Piumarta
|
||||
*
|
||||
* This file is part of GNU lightning.
|
||||
*
|
||||
* GNU lightning is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2.1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU lightning is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with GNU lightning; see the file COPYING.LESSER; if not, write to the
|
||||
* Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef __lightning_asm_h
|
||||
#define __lightning_asm_h
|
||||
|
||||
|
||||
/* <imm> = [0-9]+ -> add i, one parameter (imm)
|
||||
* <reg> = %<imm> -> add r, one parameter (imm or _Rr(imm) )
|
||||
* %g<imm> -> add r, one parameter (imm or _Rg(imm) )
|
||||
* %o<imm> -> add r, one parameter (imm+8 or _Ro(imm) )
|
||||
* %l<imm> -> add r, one parameter (imm+16 or _Rl(imm) )
|
||||
* %i<imm> -> add r, one parameter (imm+24 or _Ri(imm) )
|
||||
* <mem> = <imm>(<reg>) -> add m, two parameters (reg,imm)
|
||||
* <idx> = <reg>(<reg>) -> add x, two parameters (reg,reg)
|
||||
*/
|
||||
|
||||
|
||||
typedef unsigned int jit_insn;
|
||||
|
||||
#ifndef LIGHTNING_DEBUG
|
||||
#define _d30(BD) ((_jit_UL(BD) - _jit_UL(_jit.x.pc))>>2)
|
||||
#define _d22(BD) _ck_d(22, _d30(BD))
|
||||
|
||||
#define _HI(I) (_jit_UL(I) >> (10))
|
||||
#define _LO(I) (_jit_UL(I) & _MASK(10))
|
||||
|
||||
/* register names */
|
||||
|
||||
#define _y 0
|
||||
#define _psr 1
|
||||
|
||||
#define _Rr(N) ( 0+(N))
|
||||
#define _Rg(N) ( 0+(N))
|
||||
#define _Ro(N) ( 8+(N))
|
||||
#define _Rl(N) (16+(N))
|
||||
#define _Ri(N) (24+(N))
|
||||
|
||||
/* instruction formats -- Figure 5-1, page 44 in */
|
||||
/* SPARC International, "The SPARC Architecture Manual, Version 8", Prentice-Hall, 1992. */
|
||||
|
||||
#define _0i(RD, OP2, IMM) _jit_I((0<<30)| (_u5(RD)<<25)|(_u3(OP2)<<22)| _u22(IMM))
|
||||
#define _0( A, CC, OP2, DSP) _jit_I((0<<30)|(_u1(A)<<29)|(_u4(CC)<<25)|(_u3(OP2)<<22)| _d22(DSP))
|
||||
#define _0d( A, CC, OP2, DSP) _jit_I((0<<30)|(_u1(A)<<29)|(_u4(CC)<<25)|(_u3(OP2)<<22)| _u22(DSP))
|
||||
|
||||
#define _1( DSP) _jit_I((1<<30)| _d30(DSP))
|
||||
|
||||
#define _2( RD, OP3, RS1, I, ASI, RS2) _jit_I((2<<30)| (_u5(RD)<<25)|(_u6(OP3)<<19)|(_u5(RS1)<<14)|(_u1(I)<<13)|(_u8(ASI)<<5)|_u5 (RS2))
|
||||
#define _2i(RD, OP3, RS1, I, IMM) _jit_I((2<<30)| (_u5(RD)<<25)|(_u6(OP3)<<19)|(_u5(RS1)<<14)|(_u1(I)<<13)| _s13(IMM))
|
||||
#define _2f(RD, OP3, RS1, OPF, RS2) _jit_I((2<<30)| (_u5(RD)<<25)|(_u6(OP3)<<19)|(_u5(RS1)<<14)| (_u9(OPF)<<5)|_u5 (RS2))
|
||||
|
||||
#define _3( RD, OP3, RS1, I, ASI, RS2) _jit_I((3<<30)| (_u5(RD)<<25)|(_u6(OP3)<<19)|(_u5(RS1)<<14)|(_u1(I)<<13)|(_u8(ASI)<<5)|_u5 (RS2))
|
||||
#define _3i(RD, OP3, RS1, I, IMM) _jit_I((3<<30)| (_u5(RD)<<25)|(_u6(OP3)<<19)|(_u5(RS1)<<14)|(_u1(I)<<13)| _s13(IMM))
|
||||
|
||||
#define _FP1(RD, RS1, OPF, RS2) _2f((RD), 52, (RS1), (OPF), (RS2))
|
||||
#define _FP2(RD, RS1, OPF, RS2) _2f((RD), 53, (RS1), (OPF), (RS2))
|
||||
|
||||
/* basic instructions [Section B, page 87] */
|
||||
|
||||
#define ADDrrr(RS1, RS2, RD) _2 ((RD), 0, (RS1), 0, 0, (RS2))
|
||||
#define ADDrir(RS1, IMM, RD) _2i ((RD), 0, (RS1), 1, (IMM))
|
||||
#define ADDCCrrr(RS1, RS2, RD) _2 ((RD), 16, (RS1), 0, 0, (RS2))
|
||||
#define ADDCCrir(RS1, IMM, RD) _2i ((RD), 16, (RS1), 1, (IMM))
|
||||
#define ADDXrrr(RS1, RS2, RD) _2 ((RD), 8, (RS1), 0, 0, (RS2))
|
||||
#define ADDXrir(RS1, IMM, RD) _2i ((RD), 8, (RS1), 1, (IMM))
|
||||
#define ADDXCCrrr(RS1, RS2, RD) _2 ((RD), 24, (RS1), 0, 0, (RS2))
|
||||
#define ADDXCCrir(RS1, IMM, RD) _2i ((RD), 24, (RS1), 1, (IMM))
|
||||
#define ANDrrr(RS1, RS2, RD) _2 ((RD), 1, (RS1), 0, 0, (RS2))
|
||||
#define ANDrir(RS1, IMM, RD) _2i ((RD), 1, (RS1), 1, (IMM))
|
||||
#define ANDCCrrr(RS1, RS2, RD) _2 ((RD), 17, (RS1), 0, 0, (RS2))
|
||||
#define ANDCCrir(RS1, IMM, RD) _2i ((RD), 17, (RS1), 1, (IMM))
|
||||
|
||||
#define BNi(DISP) _0 (0, 0, 2, (DISP))
|
||||
#define BN_Ai(DISP) _0 (1, 0, 2, (DISP))
|
||||
#define BEi(DISP) _0 (0, 1, 2, (DISP))
|
||||
#define BE_Ai(DISP) _0 (1, 1, 2, (DISP))
|
||||
#define BLEi(DISP) _0 (0, 2, 2, (DISP))
|
||||
#define BLE_Ai(DISP) _0 (1, 2, 2, (DISP))
|
||||
#define BLi(DISP) _0 (0, 3, 2, (DISP))
|
||||
#define BL_Ai(DISP) _0 (1, 3, 2, (DISP))
|
||||
#define BLEUi(DISP) _0 (0, 4, 2, (DISP))
|
||||
#define BLEU_Ai(DISP) _0 (1, 4, 2, (DISP))
|
||||
#define BCSi(DISP) _0 (0, 5, 2, (DISP))
|
||||
#define BCS_Ai(DISP) _0 (1, 5, 2, (DISP))
|
||||
#define BNEGi(DISP) _0 (0, 6, 2, (DISP))
|
||||
#define BNEG_Ai(DISP) _0 (1, 6, 2, (DISP))
|
||||
#define BVSi(DISP) _0 (0, 7, 2, (DISP))
|
||||
#define BVS_Ai(DISP) _0 (1, 7, 2, (DISP))
|
||||
#define BAi(DISP) _0 (0, 8, 2, (DISP))
|
||||
#define BA_Ai(DISP) _0 (1, 8, 2, (DISP))
|
||||
#define BNEi(DISP) _0 (0, 9, 2, (DISP))
|
||||
#define BNE_Ai(DISP) _0 (1, 9, 2, (DISP))
|
||||
#define BGi(DISP) _0 (0, 10, 2, (DISP))
|
||||
#define BG_Ai(DISP) _0 (1, 10, 2, (DISP))
|
||||
#define BGEi(DISP) _0 (0, 11, 2, (DISP))
|
||||
#define BGE_Ai(DISP) _0 (1, 11, 2, (DISP))
|
||||
#define BGUi(DISP) _0 (0, 12, 2, (DISP))
|
||||
#define BGU_Ai(DISP) _0 (1, 12, 2, (DISP))
|
||||
#define BCCi(DISP) _0 (0, 13, 2, (DISP))
|
||||
#define BCC_Ai(DISP) _0 (1, 13, 2, (DISP))
|
||||
#define BPOSi(DISP) _0 (0, 14, 2, (DISP))
|
||||
#define BPOS_Ai(DISP) _0 (1, 14, 2, (DISP))
|
||||
#define BVCi(DISP) _0 (0, 15, 2, (DISP))
|
||||
#define BVC_Ai(DISP) _0 (1, 15, 2, (DISP))
|
||||
|
||||
#define CALLi(DISP) _1 ((DISP))
|
||||
|
||||
#define FLUSHrr(RS1, RS2) _2 (0, 0x3b, (RS1), 0, 0, (RS2))
|
||||
#define FLUSHir(IMM, RS1) _2i (0, 0x3b, (RS1), 1, (IMM))
|
||||
|
||||
#define JMPLxr(RS1, RS2, RD) _2 ((RD), 56, (RS1), 0, 0, (RS2))
|
||||
#define JMPLmr(RS1, IMM, RD) _2i ((RD), 56, (RS1), 1, (IMM))
|
||||
|
||||
#define LDxr(RS1, RS2, RD) _3 ((RD), 0, (RS1), 0, 0, (RS2))
|
||||
#define LDmr(RS1, IMM, RD) _3i ((RD), 0, (RS1), 1, (IMM))
|
||||
#define LDUBxr(RS1, RS2, RD) _3 ((RD), 1, (RS1), 0, 0, (RS2))
|
||||
#define LDUBmr(RS1, IMM, RD) _3i ((RD), 1, (RS1), 1, (IMM))
|
||||
#define LDUHxr(RS1, RS2, RD) _3 ((RD), 2, (RS1), 0, 0, (RS2))
|
||||
#define LDUHmr(RS1, IMM, RD) _3i ((RD), 2, (RS1), 1, (IMM))
|
||||
#define LDDxr(RS1, RS2, RD) _3 ((RD), 3, (RS1), 0, 0, (RS2))
|
||||
#define LDDmr(RS1, IMM, RD) _3i ((RD), 3, (RS1), 1, (IMM))
|
||||
#define LDSBxr(RS1, RS2, RD) _3 ((RD), 9, (RS1), 0, 0, (RS2))
|
||||
#define LDSBmr(RS1, IMM, RD) _3i ((RD), 9, (RS1), 1, (IMM))
|
||||
#define LDSHxr(RS1, RS2, RD) _3 ((RD), 10, (RS1), 0, 0, (RS2))
|
||||
#define LDSHmr(RS1, IMM, RD) _3i ((RD), 10, (RS1), 1, (IMM))
|
||||
|
||||
#define ORrrr(RS1, RS2, RD) _2 ((RD), 2, (RS1), 0, 0, (RS2))
|
||||
#define ORrir(RS1, IMM, RD) _2i ((RD), 2, (RS1), 1, (IMM))
|
||||
#define ORCCrrr(RS1, RS2, RD) _2 ((RD), 18, (RS1), 0, 0, (RS2))
|
||||
#define ORCCrir(RS1, IMM, RD) _2i ((RD), 18, (RS1), 1, (IMM))
|
||||
|
||||
#define RDir(RS, RD) _2 ((RD), (RS)|0x28, 0, 0, 0,0)
|
||||
#define RESTORErrr(RS1, RS2, RD) _2 ((RD), 61, (RS1), 0, 0, (RS2))
|
||||
#define RESTORErir(RS1, IMM, RD) _2i ((RD), 61, (RS1), 1, (IMM))
|
||||
|
||||
#define SAVErrr(RS1, RS2, RD) _2 ((RD), 60, (RS1), 0, 0, (RS2))
|
||||
#define SAVErir(RS1, IMM, RD) _2i ((RD), 60, (RS1), 1, (IMM))
|
||||
#define SDIVrrr(RS1, RS2, RD) _2 ((RD), 15, (RS1), 0, 0, (RS2))
|
||||
#define SDIVrir(RS1, IMM, RD) _2i ((RD), 15, (RS1), 1, (IMM))
|
||||
#define SDIVCCrrr(RS1, RS2, RD) _2 ((RD), 31, (RS1), 0, 0, (RS2))
|
||||
#define SDIVCCrir(RS1, IMM, RD) _2i ((RD), 31, (RS1), 1, (IMM))
|
||||
#define SETHIir(IMM, RD) _0i ((RD), 4, (IMM))
|
||||
#define SLLrrr(RS1, RS2, RD) _2 ((RD), 37, (RS1), 0, 0, (RS2))
|
||||
#define SLLrir(RS1, IMM, RD) _2i ((RD), 37, (RS1), 1, (IMM))
|
||||
#define SMULrrr(RS1, RS2, RD) _2 ((RD), 11, (RS1), 0, 0, (RS2))
|
||||
#define SMULrir(RS1, IMM, RD) _2i ((RD), 11, (RS1), 1, (IMM))
|
||||
#define SMULCCrrr(RS1, RS2, RD) _2 ((RD), 27, (RS1), 0, 0, (RS2))
|
||||
#define SMULCCrir(RS1, IMM, RD) _2i ((RD), 27, (RS1), 1, (IMM))
|
||||
#define SRArrr(RS1, RS2, RD) _2 ((RD), 39, (RS1), 0, 0, (RS2))
|
||||
#define SRArir(RS1, IMM, RD) _2i ((RD), 39, (RS1), 1, (IMM))
|
||||
#define SRLrrr(RS1, RS2, RD) _2 ((RD), 38, (RS1), 0, 0, (RS2))
|
||||
#define SRLrir(RS1, IMM, RD) _2i ((RD), 38, (RS1), 1, (IMM))
|
||||
#define STrx(RS, RD1, RD2) _3 ((RS), 4, (RD1), 0, 0, (RD2))
|
||||
#define STrm(RS, RD, IMM) _3i ((RS), 4, (RD), 1, (IMM))
|
||||
#define STBrx(RS, RD1, RD2) _3 ((RS), 5, (RD1), 0, 0, (RD2))
|
||||
#define STBrm(RS, RD, IMM) _3i ((RS), 5, (RD), 1, (IMM))
|
||||
#define STBAR() _0i (0, 0x28, 15, 0, 0)
|
||||
#define STHrx(RS, RD1, RD2) _3 ((RS), 6, (RD1), 0, 0, (RD2))
|
||||
#define STHrm(RS, RD, IMM) _3i ((RS), 6, (RD), 1, (IMM))
|
||||
#define STDrx(RS, RD1, RD2) _3 ((RS), 7, (RD1), 0, 0, (RD2))
|
||||
#define STDrm(RS, RD, IMM) _3i ((RS), 7, (RD), 1, (IMM))
|
||||
#define SUBrrr(RS1, RS2, RD) _2 ((RD), 4, (RS1), 0, 0, (RS2))
|
||||
#define SUBrir(RS1, IMM, RD) _2i ((RD), 4, (RS1), 1, (IMM))
|
||||
#define SUBCCrrr(RS1, RS2, RD) _2 ((RD), 20, (RS1), 0, 0, (RS2))
|
||||
#define SUBCCrir(RS1, IMM, RD) _2i ((RD), 20, (RS1), 1, (IMM))
|
||||
#define SUBXrrr(RS1, RS2, RD) _2 ((RD), 12, (RS1), 0, 0, (RS2))
|
||||
#define SUBXrir(RS1, IMM, RD) _2i ((RD), 12, (RS1), 1, (IMM))
|
||||
#define SUBXCCrrr(RS1, RS2, RD) _2 ((RD), 28, (RS1), 0, 0, (RS2))
|
||||
#define SUBXCCrir(RS1, IMM, RD) _2i ((RD), 28, (RS1), 1, (IMM))
|
||||
|
||||
#define UDIVrrr(RS1, RS2, RD) _2 ((RD), 14, (RS1), 0, 0, (RS2))
|
||||
#define UDIVrir(RS1, IMM, RD) _2i ((RD), 14, (RS1), 1, (IMM))
|
||||
#define UDIVCCrrr(RS1, RS2, RD) _2 ((RD), 30, (RS1), 0, 0, (RS2))
|
||||
#define UDIVCCrir(RS1, IMM, RD) _2i ((RD), 30, (RS1), 1, (IMM))
|
||||
#define UMULrrr(RS1, RS2, RD) _2 ((RD), 10, (RS1), 0, 0, (RS2))
|
||||
#define UMULrir(RS1, IMM, RD) _2i ((RD), 10, (RS1), 1, (IMM))
|
||||
#define UMULCCrrr(RS1, RS2, RD) _2 ((RD), 26, (RS1), 0, 0, (RS2))
|
||||
#define UMULCCrir(RS1, IMM, RD) _2i ((RD), 26, (RS1), 1, (IMM))
|
||||
|
||||
#define WRrri(RS1, RS2, RD) _2 (0, (RD)|0x30, RS1, 0, 0, (RS2))
|
||||
#define WRrii(RS1, IMM, RD) _2i (0, (RD)|0x30, RS1, 1, (IMM))
|
||||
|
||||
#define XORrrr(RS1, RS2, RD) _2 ((RD), 3, (RS1), 0, 0, (RS2))
|
||||
#define XORrir(RS1, IMM, RD) _2i ((RD), 3, (RS1), 1, (IMM))
|
||||
#define XORCCrrr(RS1, RS2, RD) _2 ((RD), 19, (RS1), 0, 0, (RS2))
|
||||
#define XORCCrir(RS1, IMM, RD) _2i ((RD), 19, (RS1), 1, (IMM))
|
||||
|
||||
/* synonyms */
|
||||
|
||||
#define Bi(DISP) BAi((DISP))
|
||||
#define B_Ai(DISP) BA_Ai((DISP))
|
||||
#define BNZi(DISP) BNEi((DISP))
|
||||
#define BNZ_Ai(DISP) BNE_Ai((DISP))
|
||||
#define BZi(DISP) BEi((DISP))
|
||||
#define BZ_Ai(DISP) BE_Ai((DISP))
|
||||
#define BGEUi(DISP) BCCi((DISP))
|
||||
#define BGEU_Ai(DISP) BCC_Ai((DISP))
|
||||
#define BLUi(DISP) BCSi((DISP))
|
||||
#define BLU_Ai(DISP) BCS_Ai((DISP))
|
||||
|
||||
#define LDUWxr(RS1, RS2, RD) LDxr((RS1), (RS2), (RD))
|
||||
#define LDUWmr(RS1, IMM, RD) LDmr((RS1), (IMM), (RD))
|
||||
#define LDSWxr(RS1, RS2, RD) LDxr((RS1), (RS2), (RD))
|
||||
#define LDSWmr(RS1, IMM, RD) LDmr((RS1), (IMM), (RD))
|
||||
|
||||
#define STWrx(RS, RD1, RD2) STrx((RS), (RD1), (RD2))
|
||||
#define STWrm(RS, RD, IMM) STrm((RS), (RD), (IMM))
|
||||
|
||||
/* synthetic instructions [Table A-1, page 85] */
|
||||
|
||||
#define BCLRrr(R,S) ANDNrrr((R), (S), (S))
|
||||
#define BCLRir(I,R) ANDNrir((R), (I), (R))
|
||||
#define BSETrr(R,S) ORrrr((R), (S), (S))
|
||||
#define BSETir(I,R) ORrir((R), (I), (R))
|
||||
#define BTOGrr(R,S) XORrrr((R), (S), (S))
|
||||
#define BTOGir(I,R) XORrir((R), (I), (R))
|
||||
#define BTSTrr(R,S) ANDCCrrr((R), (S), 0)
|
||||
#define BTSTir(I,R) ANDCCrir((R), (I), 0)
|
||||
|
||||
#define CALLm(R,I) JMPLmr((R), (I), _Ro(7))
|
||||
#define CALLx(R,S) JMPLxr((R), (S), _Ro(7))
|
||||
|
||||
#define CLRr(R) ORrrr(0, 0, (R))
|
||||
#define CLRBm(R,I) STBrm(0, (R), (I))
|
||||
#define CLRBx(R,S) STBrm(0, (R), (S))
|
||||
#define CLRHm(R,I) STHrm(0, (R), (I))
|
||||
#define CLRHx(R,S) STHrm(0, (R), (S))
|
||||
#define CLRm(R,I) STrm(0, (R), (I))
|
||||
#define CLRx(R,S) STrm(0, (R), (S))
|
||||
|
||||
#define CMPrr(RS1, RS2) SUBCCrrr((RS1), (RS2), 0)
|
||||
#define CMPri(RS1, IMM) SUBCCrir((RS1), (IMM), 0)
|
||||
|
||||
#define DECr(R) SUBrir((R), 1, (R))
|
||||
#define DECir(I,R) SUBrir((R), (I), (R))
|
||||
#define DECCCr(R) SUBCCrir((R), 1, (R))
|
||||
#define DECCCir(I,R) SUBCCrir((R), (I), (R))
|
||||
|
||||
#define INCr(R) ADDrir((R), 1, (R))
|
||||
#define INCir(I,R) ADDrir((R), (I), (R))
|
||||
#define INCCCr(R) ADDCCrir((R), 1, (R))
|
||||
#define INCCCir(I,R) ADDCCrir((R), (I), (R))
|
||||
|
||||
#define JMPm(R,I) JMPLmr((R), (I), 0)
|
||||
#define JMPx(R,S) JMPLxr((R), (S), 0)
|
||||
|
||||
#define MOVrr(R,S) ORrrr(0, (R), (S))
|
||||
#define MOVir(I, R) ORrir(0, (I), (R))
|
||||
|
||||
#define NEGrr(R,S) SUBrrr(0, (R), (S))
|
||||
#define NEGr(R) SUBrrr(0, (R), (R))
|
||||
#define NOP() SETHIir(0, 0)
|
||||
|
||||
#define NOTrr(R,S) XNORrrr((R), 0, (S))
|
||||
#define NOTr(R) XNORrrr((R), 0, (R))
|
||||
|
||||
#define RESTORE() RESTORErrr(0, 0, 0)
|
||||
#define RET() JMPLmr(_Ri(7),8 ,0)
|
||||
#define RETL() JMPLmr(_Ro(7),8 ,0)
|
||||
|
||||
#define SAVE() SAVErrr(0, 0, 0)
|
||||
#define SETir(I,R) (_siP(13,(I)) ? MOVir((I),(R)) : SETir2(_HI(I), _LO(I), (R)))
|
||||
#define SETir2(H,L,R) (SETHIir(H,R), (L ? ORrir(R,L,R) : 0))
|
||||
|
||||
/* BNZ,a executes the delay instruction if NZ (so skips if Z)
|
||||
* BZ,a executes the delay instruction if Z (so skips if NZ). */
|
||||
#define SKIPZ() _0d (1, 9, 2, 2) /* BNZ,a .+8 */
|
||||
#define SKIPNZ() _0d (1, 1, 2, 2) /* BZ,a .+8 */
|
||||
#define SKIP() _0d (1, 0, 2, 0) /* BN,a . */
|
||||
|
||||
#define TSTr(R) ORCCrrr(0, (R), 0)
|
||||
|
||||
#define WRii(IMM, RD) WRrii(0, (IMM), (RD))
|
||||
#define WRri(RS2, RD) WRrri(0, (RS2), (RD))
|
||||
|
||||
#define LDFSRx(RS1, RS2) _3 (0, 33, (RS1), 0, 0, (RS2))
|
||||
#define LDFSRm(RS1, IMM) _3i (0, 33, (RS1), 1, (IMM))
|
||||
#define STFSRx(RD1, RD2) _3 (0, 37, (RD1), 0, 0, (RD2))
|
||||
#define STFSRm(RD, IMM) _3i (0, 37, (RD), 1, (IMM))
|
||||
|
||||
#define FITODrr(FRS, FRD) _FP1((FRD), 0, 200, (FRS))
|
||||
#define FITOSrr(FRS, FRD) _FP1((FRD), 0, 196, (FRS))
|
||||
#define FDTOIrr(FRS, FRD) _FP1((FRD), 0, 210, (FRS))
|
||||
#define FSTOIrr(FRS, FRD) _FP1((FRD), 0, 209, (FRS))
|
||||
#define FSTODrr(FRS, FRD) _FP1((FRD), 0, 201, (FRS))
|
||||
#define FDTOSrr(FRS, FRD) _FP1((FRD), 0, 198, (FRS))
|
||||
#define FMOVSrr(FRS, FRD) _FP1((FRD), 0, 1, (FRS))
|
||||
#define FNEGSrr(FRS, FRD) _FP1((FRD), 0, 5, (FRS))
|
||||
#define FABSSrr(FRS, FRD) _FP1((FRD), 0, 9, (FRS))
|
||||
#define FMOVDrr(FRS, FRD) _FP1((FRD), 0, 2, (FRS))
|
||||
#define FNEGDrr(FRS, FRD) _FP1((FRD), 0, 6, (FRS))
|
||||
#define FABSDrr(FRS, FRD) _FP1((FRD), 0, 10, (FRS))
|
||||
#define FSQRTDrr(FRS, FRD) _FP1((FRD), 0, 42, (FRS))
|
||||
#define FSQRTSrr(FRS, FRD) _FP1((FRD), 0, 41, (FRS))
|
||||
|
||||
#define FADDSrrr(FRS1, FRS2, FRD) _FP1((FRD), (FRS1), 65, (FRS2))
|
||||
#define FSUBSrrr(FRS1, FRS2, FRD) _FP1((FRD), (FRS1), 69, (FRS2))
|
||||
#define FMULSrrr(FRS1, FRS2, FRD) _FP1((FRD), (FRS1), 73, (FRS2))
|
||||
#define FDIVSrrr(FRS1, FRS2, FRD) _FP1((FRD), (FRS1), 77, (FRS2))
|
||||
|
||||
#define FADDDrrr(FRS1, FRS2, FRD) _FP1((FRD), (FRS1), 66, (FRS2))
|
||||
#define FSUBDrrr(FRS1, FRS2, FRD) _FP1((FRD), (FRS1), 70, (FRS2))
|
||||
#define FMULDrrr(FRS1, FRS2, FRD) _FP1((FRD), (FRS1), 74, (FRS2))
|
||||
#define FDIVDrrr(FRS1, FRS2, FRD) _FP1((FRD), (FRS1), 78, (FRS2))
|
||||
|
||||
#define FCMPSrr(FRS1, FRS2) _FP2(0, (FRS1), 81, (FRS2))
|
||||
#define FCMPDrr(FRS1, FRS2) _FP2(0, (FRS1), 82, (FRS2))
|
||||
|
||||
#define LDFxr(RS1, RS2, RD) _3 ((RD), 32, (RS1), 0, 0, (RS2))
|
||||
#define LDFmr(RS1, IMM, RD) _3i ((RD), 32, (RS1), 1, (IMM))
|
||||
#define LDDFxr(RS1, RS2, RD) _3 ((RD), 35, (RS1), 0, 0, (RS2))
|
||||
#define LDDFmr(RS1, IMM, RD) _3i ((RD), 35, (RS1), 1, (IMM))
|
||||
#define STFrx(RS, RD1, RD2) _3 ((RS), 36, (RD1), 0, 0, (RD2))
|
||||
#define STFrm(RS, RD1, IMM) _3i ((RS), 36, (RD1), 1, (IMM))
|
||||
#define STDFrx(RS, RD1, RD2) _3 ((RS), 39, (RD1), 0, 0, (RD2))
|
||||
#define STDFrm(RS, RD1, IMM) _3i ((RS), 39, (RD1), 1, (IMM))
|
||||
|
||||
#define FBNi(DISP) _0 (0, 0, 6, (DISP))
|
||||
#define FBN_Ai(DISP) _0 (1, 0, 6, (DISP))
|
||||
#define FBNEi(DISP) _0 (0, 1, 6, (DISP))
|
||||
#define FBNE_Ai(DISP) _0 (1, 1, 6, (DISP))
|
||||
#define FBLGi(DISP) _0 (0, 2, 6, (DISP))
|
||||
#define FBLG_Ai(DISP) _0 (1, 2, 6, (DISP))
|
||||
#define FBULi(DISP) _0 (0, 3, 6, (DISP))
|
||||
#define FBUL_Ai(DISP) _0 (1, 3, 6, (DISP))
|
||||
#define FBLi(DISP) _0 (0, 4, 6, (DISP))
|
||||
#define FBL_Ai(DISP) _0 (1, 4, 6, (DISP))
|
||||
#define FBUGi(DISP) _0 (0, 5, 6, (DISP))
|
||||
#define FBUG_Ai(DISP) _0 (1, 5, 6, (DISP))
|
||||
#define FBGi(DISP) _0 (0, 6, 6, (DISP))
|
||||
#define FBG_Ai(DISP) _0 (1, 6, 6, (DISP))
|
||||
#define FBUi(DISP) _0 (0, 7, 6, (DISP))
|
||||
#define FBU_Ai(DISP) _0 (1, 7, 6, (DISP))
|
||||
#define FBAi(DISP) _0 (0, 8, 6, (DISP))
|
||||
#define FBA_Ai(DISP) _0 (1, 8, 6, (DISP))
|
||||
#define FBEi(DISP) _0 (0, 9, 6, (DISP))
|
||||
#define FBE_Ai(DISP) _0 (1, 9, 6, (DISP))
|
||||
#define FBUEi(DISP) _0 (0, 10, 6, (DISP))
|
||||
#define FBUE_Ai(DISP) _0 (1, 10, 6, (DISP))
|
||||
#define FBGEi(DISP) _0 (0, 11, 6, (DISP))
|
||||
#define FBGE_Ai(DISP) _0 (1, 11, 6, (DISP))
|
||||
#define FBUGEi(DISP) _0 (0, 12, 6, (DISP))
|
||||
#define FBUGE_Ai(DISP) _0 (1, 12, 6, (DISP))
|
||||
#define FBLEi(DISP) _0 (0, 13, 6, (DISP))
|
||||
#define FBLE_Ai(DISP) _0 (1, 13, 6, (DISP))
|
||||
#define FBULEi(DISP) _0 (0, 14, 6, (DISP))
|
||||
#define FBULE_Ai(DISP) _0 (1, 14, 6, (DISP))
|
||||
#define FBOi(DISP) _0 (0, 15, 6, (DISP))
|
||||
#define FBO_Ai(DISP) _0 (1, 15, 6, (DISP))
|
||||
|
||||
#endif
|
||||
#endif /* __ccg_asm_sparc_h */
|
||||
@@ -1,265 +0,0 @@
|
||||
/******************************** -*- C -*- ****************************
|
||||
*
|
||||
* Platform-independent layer (Sparc version)
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
* Written by Paolo Bonzini.
|
||||
*
|
||||
* This file is part of GNU lightning.
|
||||
*
|
||||
* GNU lightning is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2.1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU lightning is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with GNU lightning; see the file COPYING.LESSER; if not, write to the
|
||||
* Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
#ifndef __lightning_core_h
|
||||
#define __lightning_core_h
|
||||
|
||||
#define JIT_R_NUM 3
|
||||
#define JIT_V_NUM 6
|
||||
#define JIT_R(i) ((i) ? _Rl((i) - 1) : _Rg(2))
|
||||
#define JIT_V(i) _Rl((i)+2)
|
||||
|
||||
#define JIT_BIG _Rg(1) /* %g1 used to make 32-bit operands */
|
||||
#define JIT_BIG2 _Ro(7) /* %o7 used to make 32-bit compare operands */
|
||||
#define JIT_SP _Ro(6)
|
||||
#define JIT_RZERO _Rg(0)
|
||||
#define JIT_RET _Ri(0)
|
||||
|
||||
/* Delay slot scheduling: jmp generates branches with annulled delay
|
||||
* slots; we toggle the annul bit if we can fill the slot. CALLs and
|
||||
* cond. branches have a different meaning for the annul bit, so we
|
||||
* automatically generate a NOP and eventually copy the delay insn onto
|
||||
* it. Delay slots in RET are already used for RESTORE, so we don't
|
||||
* schedule them.
|
||||
*
|
||||
* ,--- _jit.x.pc
|
||||
* insn X X before
|
||||
* cmp branch insn X X after (branch)
|
||||
* `--- _jit.x.pc
|
||||
* call insn insn X after (call)
|
||||
* `--- _jit.x.pc
|
||||
*/
|
||||
|
||||
struct jit_local_state {
|
||||
int nextarg_put; /* Next %o reg. to be written */
|
||||
int nextarg_get; /* Next %i reg. to be read */
|
||||
jit_insn delay;
|
||||
};
|
||||
|
||||
#define jit_fill_delay_after(branch) (_jitl.delay = *--_jit.x.pc, \
|
||||
((branch) == _jit.x.pc /* check if NOP was inserted */ \
|
||||
? (_jit.x.pc[-1] ^= 1<<29) /* no if branch, toggle annul bit */ \
|
||||
: (_jit.x.pc[-1] = _jitl.delay)), /* yes if call, replace NOP with delay insn */ \
|
||||
*_jit.x.pc = _jitl.delay, _jit.x.pc - 1) /* return addr of delay insn */
|
||||
|
||||
/* If possible, use the `small' instruction (rs, imm, rd)
|
||||
* else load imm into %l6 and use the `big' instruction (rs, %l6, rd)
|
||||
* jit_chk_imm2 uses %l7 instead of %l6 to avoid conflicts when using delay slots
|
||||
*/
|
||||
#define jit_chk_imm(imm, small, big) (_siP(13,(imm)) ? (small) : (SETir((imm), JIT_BIG), (big)) )
|
||||
#define jit_chk_imm2(imm, small, big) (_siP(13,(imm)) ? (small) : (SETir((imm), JIT_BIG2), (big)) )
|
||||
|
||||
/* Helper macros for branches */
|
||||
#define jit_branchi(rs, is, jmp, nop) (jit_chk_imm2(is, CMPri(rs, is), CMPrr(rs, JIT_BIG2)), jmp, nop, _jit.x.pc - 1)
|
||||
#define jit_branchr(s1, s2, jmp, nop) ( CMPrr(s1, s2), jmp, nop, _jit.x.pc - 1)
|
||||
|
||||
/* Helper macros for boolean tests -- delay slot sets d to 1;
|
||||
* taken branch leaves it to 1, not-taken branch resets it to 0 */
|
||||
#define jit_booli(d, rs, is, jmp) (jit_chk_imm (is, CMPri(rs, is), CMPrr(rs, JIT_BIG)), jmp, MOVir(1, (d)), MOVir(0, (d)))
|
||||
#define jit_boolr(d, s1, s2, jmp) ( CMPrr(s1, s2), jmp, MOVir(1, (d)), MOVir(0, (d)))
|
||||
|
||||
/* Helper macros for division
|
||||
* The architecture specifies that there must be 3 instructions between *
|
||||
* a y register write and a use of it for correct results. */
|
||||
#define jit_prepare_y(rs, is) (SRArir(rs, 31, JIT_BIG), WRri(JIT_BIG, _y), NOP(), NOP(), NOP(), _jit.x.pc -= jit_immsize(is))
|
||||
#define jit_clr_y(rs, is) ( WRri(0, _y), NOP(), NOP(), NOP(), _jit.x.pc -= jit_immsize(is))
|
||||
|
||||
#define jit_modr(jit_div, jit_mul, d, s1, s2) \
|
||||
(jit_div (JIT_BIG, s1, s2), \
|
||||
jit_mul (JIT_BIG, JIT_BIG, s2), \
|
||||
jit_subr_i (d, s1, JIT_BIG))
|
||||
|
||||
#define jit_modi(jit_divi, jit_muli, jit_divr, jit_mulr, d, rs, is) \
|
||||
(_siP(13,(imm)) \
|
||||
? (jit_divi (JIT_BIG, rs, is), \
|
||||
jit_muli (JIT_BIG, JIT_BIG, is), \
|
||||
jit_subr_i (d, rs, JIT_BIG)) \
|
||||
: (SETir ((is), JIT_BIG2), \
|
||||
jit_modr (jit_divr, jit_mulr, d, rs, JIT_BIG2)))
|
||||
|
||||
/* How many instruction are needed to put imm in a register. */
|
||||
#define jit_immsize(imm) (!(imm) ? 0 : \
|
||||
(!_siP((imm), 13) && ((imm) & 0x3ff) ? 2 : 1))
|
||||
|
||||
|
||||
/* branch instructions return the address of the *delay* instruction -- this
|
||||
* is just a helper macro that makes jit_patch more readable.
|
||||
*/
|
||||
#define jit_patch_(jump_pc,pv) \
|
||||
(*jump_pc &= ~_MASK(22), \
|
||||
*jump_pc |= ((_jit_UL((pv)) - _jit_UL(jump_pc)) >> 2) & _MASK(22))
|
||||
|
||||
#define jit_patch_set(sethi_pc, or_pc, dest) \
|
||||
(*(sethi_pc) &= ~_MASK(22), *(sethi_pc) |= _HI(dest), \
|
||||
*(or_pc) &= ~_MASK(13), *(or_pc) |= _LO(dest)) \
|
||||
|
||||
#define jit_patch_movi(movi_pc, val) \
|
||||
jit_patch_set((movi_pc) - 2, (movi_pc) - 1, (val))
|
||||
|
||||
#define jit_arg_c() (_jitl.nextarg_get++)
|
||||
#define jit_arg_i() (_jitl.nextarg_get++)
|
||||
#define jit_arg_l() (_jitl.nextarg_get++)
|
||||
#define jit_arg_p() (_jitl.nextarg_get++)
|
||||
#define jit_arg_s() (_jitl.nextarg_get++)
|
||||
#define jit_arg_uc() (_jitl.nextarg_get++)
|
||||
#define jit_arg_ui() (_jitl.nextarg_get++)
|
||||
#define jit_arg_ul() (_jitl.nextarg_get++)
|
||||
#define jit_arg_us() (_jitl.nextarg_get++)
|
||||
#define jit_addi_i(d, rs, is) jit_chk_imm((is), ADDrir((rs), (is), (d)), ADDrrr((rs), JIT_BIG, (d)))
|
||||
#define jit_addr_i(d, s1, s2) ADDrrr((s1), (s2), (d))
|
||||
#define jit_addci_i(d, rs, is) jit_chk_imm((is), ADDCCrir((rs), (is), (d)), ADDCCrrr((rs), JIT_BIG, (d)))
|
||||
#define jit_addcr_i(d, s1, s2) ADDCCrrr((s1), (s2), (d))
|
||||
#define jit_addxi_i(d, rs, is) jit_chk_imm((is), ADDXCCrir((rs), (is), (d)), ADDXCCrrr((rs), JIT_BIG, (d)))
|
||||
#define jit_addxr_i(d, s1, s2) ADDXCCrrr((s1), (s2), (d))
|
||||
#define jit_andi_i(d, rs, is) jit_chk_imm((is), ANDrir((rs), (is), (d)), ANDrrr((rs), JIT_BIG, (d)))
|
||||
#define jit_andr_i(d, s1, s2) ANDrrr((s1), (s2), (d))
|
||||
#define jit_beqi_i(label, rs, is) jit_branchi((rs), (is), BEi((label)), NOP() )
|
||||
#define jit_beqr_i(label, s1, s2) jit_branchr((s1), (s2), BEi((label)), NOP() )
|
||||
#define jit_bgei_i(label, rs, is) jit_branchi((rs), (is), BGEi((label)), NOP() )
|
||||
#define jit_bgei_ui(label, rs, is) jit_branchi((rs), (is), BGEUi((label)), NOP() )
|
||||
#define jit_bger_i(label, s1, s2) jit_branchr((s1), (s2), BGEi((label)), NOP() )
|
||||
#define jit_bger_ui(label, s1, s2) jit_branchr((s1), (s2), BGEUi((label)), NOP() )
|
||||
#define jit_bgti_i(label, rs, is) jit_branchi((rs), (is), BGi((label)), NOP() )
|
||||
#define jit_bgti_ui(label, rs, is) jit_branchi((rs), (is), BGUi((label)), NOP() )
|
||||
#define jit_bgtr_i(label, s1, s2) jit_branchr((s1), (s2), BGi((label)), NOP() )
|
||||
#define jit_bgtr_ui(label, s1, s2) jit_branchr((s1), (s2), BGUi((label)), NOP() )
|
||||
#define jit_blei_i(label, rs, is) jit_branchi((rs), (is), BLEi((label)), NOP() )
|
||||
#define jit_blei_ui(label, rs, is) jit_branchi((rs), (is), BLEUi((label)), NOP() )
|
||||
#define jit_bler_i(label, s1, s2) jit_branchr((s1), (s2), BLEi((label)), NOP() )
|
||||
#define jit_bler_ui(label, s1, s2) jit_branchr((s1), (s2), BLEUi((label)), NOP() )
|
||||
#define jit_blti_i(label, rs, is) jit_branchi((rs), (is), BLi((label)), NOP() )
|
||||
#define jit_blti_ui(label, rs, is) jit_branchi((rs), (is), BLUi((label)), NOP() )
|
||||
#define jit_bltr_i(label, s1, s2) jit_branchr((s1), (s2), BLi((label)), NOP() )
|
||||
#define jit_bltr_ui(label, s1, s2) jit_branchr((s1), (s2), BLUi((label)), NOP() )
|
||||
#define jit_bnei_i(label, rs, is) jit_branchi((rs), (is), BNEi((label)), NOP() )
|
||||
#define jit_bner_i(label, s1, s2) jit_branchr((s1), (s2), BNEi((label)), NOP() )
|
||||
#define jit_bmsi_i(label, rs, is) (jit_chk_imm((is), BTSTir((is), (rs)), BTSTrr((rs), JIT_BIG)), BNEi((label)), NOP(), _jit.x.pc - 1)
|
||||
#define jit_bmci_i(label, rs, is) (jit_chk_imm((is), BTSTir((is), (rs)), BTSTrr((rs), JIT_BIG)), BEi((label)), NOP(), _jit.x.pc - 1)
|
||||
#define jit_bmsr_i(label, s1, s2) ( BTSTrr((s1), (s2)), BNEi((label)), NOP(), _jit.x.pc - 1)
|
||||
#define jit_bmcr_i(label, s1, s2) ( BTSTrr((s1), (s2)), BEi((label)), NOP(), _jit.x.pc - 1)
|
||||
#define jit_boaddi_i(label, rs, is) (jit_chk_imm((is), ADDCCrir((rs), (is), (rs)), ADDCCrrr((rs), JIT_BIG, (rs))), BVSi((label)), NOP(), _jit.x.pc - 1)
|
||||
#define jit_bosubi_i(label, rs, is) (jit_chk_imm((is), SUBCCrir((rs), (is), (rs)), SUBCCrrr((rs), JIT_BIG, (rs))), BVSi((label)), NOP(), _jit.x.pc - 1)
|
||||
#define jit_boaddr_i(label, s1, s2) ( ADDCCrrr((s1), (s2), (s1)), BVSi((label)), NOP(), _jit.x.pc - 1)
|
||||
#define jit_bosubr_i(label, s1, s2) ( SUBCCrrr((s1), (s2), (s1)), BVSi((label)), NOP(), _jit.x.pc - 1)
|
||||
#define jit_boaddi_ui(label, rs, is) (jit_chk_imm((is), ADDCCrir((rs), (is), (rs)), ADDCCrrr((rs), JIT_BIG, (rs))), BCSi((label)), NOP(), _jit.x.pc - 1)
|
||||
#define jit_bosubi_ui(label, rs, is) (jit_chk_imm((is), SUBCCrir((rs), (is), (rs)), SUBCCrrr((rs), JIT_BIG, (rs))), BCSi((label)), NOP(), _jit.x.pc - 1)
|
||||
#define jit_boaddr_ui(label, s1, s2) ( ADDCCrrr((s1), (s2), (s1)), BCSi((label)), NOP(), _jit.x.pc - 1)
|
||||
#define jit_bosubr_ui(label, s1, s2) ( SUBCCrrr((s1), (s2), (s1)), BCSi((label)), NOP(), _jit.x.pc - 1)
|
||||
#define jit_calli(label) (CALLi(label), NOP(), _jit.x.pc - 1)
|
||||
#define jit_callr(reg) (CALLx((reg), 0), NOP())
|
||||
|
||||
#define jit_divi_i(d, rs, is) (jit_prepare_y((rs), 0x12345678), SETir((is), JIT_BIG), SDIVrrr((rs), JIT_BIG, (d)) )
|
||||
#define jit_divi_ui(d, rs, is) (jit_clr_y((rs), 0x12345678), SETir((is), JIT_BIG), UDIVrrr((rs), JIT_BIG, (d)) )
|
||||
#define jit_divr_i(d, s1, s2) (jit_prepare_y((s1), 0), SDIVrrr((s1), (s2), (d)))
|
||||
#define jit_divr_ui(d, s1, s2) (jit_clr_y((s1), 0), UDIVrrr((s1), (s2), (d)))
|
||||
#define jit_eqi_i(d, rs, is) jit_chk_imm((is), \
|
||||
(SUBCCrir((rs), (is), (d)), ADDXCCrir((d), -1, JIT_BIG), SUBXrir(0,-1,(d))),\
|
||||
jit_eqr_i(d, rs, JIT_BIG))
|
||||
#define jit_eqr_i(d, s1, s2) (SUBCCrrr((s1), (s2), (d)), ADDXCCrir((d), -1, JIT_BIG), SUBXrir(0,-1,(d)))
|
||||
#define jit_nei_i(d, rs, is) jit_chk_imm((is), \
|
||||
(SUBCCrir((rs), (is), (d)), ADDXCCrir((d), -1, JIT_BIG), ADDXrrr(0,0,(d))),\
|
||||
jit_ner_i(d, rs, JIT_BIG))
|
||||
#define jit_ner_i(d, s1, s2) (SUBCCrrr((s1), (s2), (d)), ADDXCCrir((d), -1, JIT_BIG), ADDXrrr(0,0,(d)))
|
||||
#define jit_gei_i(d, rs, is) jit_booli ((d), (rs), (is), BGEi(_jit.x.pc + 3) )
|
||||
#define jit_gei_ui(d, rs, is) jit_booli ((d), (rs), (is), BGEUi(_jit.x.pc + 3))
|
||||
#define jit_ger_i(d, s1, s2) jit_boolr ((d), (s1), (s2), BGEi(_jit.x.pc + 3) )
|
||||
#define jit_ger_ui(d, s1, s2) jit_boolr ((d), (s1), (s2), BGEUi(_jit.x.pc + 3))
|
||||
#define jit_gti_i(d, rs, is) jit_booli ((d), (rs), (is), BGi(_jit.x.pc + 3) )
|
||||
#define jit_gti_ui(d, rs, is) jit_booli ((d), (rs), (is), BGUi(_jit.x.pc + 3) )
|
||||
#define jit_gtr_i(d, s1, s2) jit_boolr ((d), (s1), (s2), BGi(_jit.x.pc + 3) )
|
||||
#define jit_gtr_ui(d, s1, s2) jit_boolr ((d), (s1), (s2), BGUi(_jit.x.pc + 3) )
|
||||
#define jit_hmuli_i(d, rs, is) (jit_muli_i (JIT_BIG, (rs), (is)), RDir (_y, (d)))
|
||||
#define jit_hmuli_ui(d, rs, is) (jit_muli_ui(JIT_BIG, (rs), (is)), RDir (_y, (d)))
|
||||
#define jit_hmulr_i(d, s1, s2) (jit_mulr_i (JIT_BIG, (s1), (s2)), RDir (_y, (d)))
|
||||
#define jit_hmulr_ui(d, s1, s2) (jit_mulr_ui(JIT_BIG, (s1), (s2)), RDir (_y, (d)))
|
||||
#define jit_jmpi(label) (BA_Ai((label)), _jit.x.pc)
|
||||
#define jit_jmpr(reg) (JMPx(JIT_RZERO, (reg)), NOP(), _jit.x.pc - 1)
|
||||
#define jit_ldxi_c(d, rs, is) jit_chk_imm((is), LDSBmr((rs), (is), (d)), LDSBxr((rs), JIT_BIG, (d)))
|
||||
#define jit_ldxi_i(d, rs, is) jit_chk_imm((is), LDSWmr((rs), (is), (d)), LDSWxr((rs), JIT_BIG, (d)))
|
||||
#define jit_ldxi_s(d, rs, is) jit_chk_imm((is), LDSHmr((rs), (is), (d)), LDSHxr((rs), JIT_BIG, (d)))
|
||||
#define jit_ldxi_uc(d, rs, is) jit_chk_imm((is), LDUBmr((rs), (is), (d)), LDUBxr((rs), JIT_BIG, (d)))
|
||||
#define jit_ldxi_us(d, rs, is) jit_chk_imm((is), LDUHmr((rs), (is), (d)), LDUHxr((rs), JIT_BIG, (d)))
|
||||
#define jit_ldxr_c(d, s1, s2) LDSBxr((s1), (s2), (d))
|
||||
#define jit_ldxr_i(d, s1, s2) LDSWxr((s1), (s2), (d))
|
||||
#define jit_ldxr_s(d, s1, s2) LDSHxr((s1), (s2), (d))
|
||||
#define jit_ldxr_uc(d, s1, s2) LDUBxr((s1), (s2), (d))
|
||||
#define jit_ldxr_us(d, s1, s2) LDUHxr((s1), (s2), (d))
|
||||
#define jit_lei_i(d, rs, is) jit_booli ((d), (rs), (is), BLEi(_jit.x.pc + 3) )
|
||||
#define jit_lei_ui(d, rs, is) jit_booli ((d), (rs), (is), BLEUi(_jit.x.pc + 3))
|
||||
#define jit_ler_i(d, s1, s2) jit_boolr ((d), (s1), (s2), BLEi(_jit.x.pc + 3) )
|
||||
#define jit_ler_ui(d, s1, s2) jit_boolr ((d), (s1), (s2), BLEUi(_jit.x.pc + 3))
|
||||
#define jit_lshi_i(d, rs, is) SLLrir((rs), (is), (d))
|
||||
#define jit_lshr_i(d, r1, r2) SLLrrr((r1), (r2), (d))
|
||||
#define jit_lti_i(d, rs, is) jit_booli ((d), (rs), (is), BLi(_jit.x.pc + 3) )
|
||||
#define jit_lti_ui(d, rs, is) jit_booli ((d), (rs), (is), BLUi(_jit.x.pc + 3) )
|
||||
#define jit_ltr_i(d, s1, s2) jit_boolr ((d), (s1), (s2), BLi(_jit.x.pc + 3) )
|
||||
#define jit_ltr_ui(d, s1, s2) jit_boolr ((d), (s1), (s2), BLUi(_jit.x.pc + 3) )
|
||||
#define jit_modi_i(d, rs, is) jit_modi(jit_divi_i, jit_muli_i, jit_divr_i, jit_mulr_i, (d), (rs), (is))
|
||||
#define jit_modi_ui(d, rs, is) jit_modi(jit_divi_ui, jit_muli_ui, jit_divr_ui, jit_mulr_ui, (d), (rs), (is))
|
||||
#define jit_modr_i(d, s1, s2) jit_modr(jit_divr_i, jit_mulr_i, (d), (s1), (s2))
|
||||
#define jit_modr_ui(d, s1, s2) jit_modr(jit_divr_ui, jit_mulr_ui, (d), (s1), (s2))
|
||||
#define jit_movi_i(d, is) SETir((is), (d))
|
||||
#define jit_movi_p(d, is) (SETir2(_HI((is)), _LO((is)), (d)), _jit.x.pc)
|
||||
#define jit_movr_i(d, rs) MOVrr((rs), (d))
|
||||
#define jit_muli_i(d, rs, is) jit_chk_imm((is), SMULrir((rs), (is), (d)), SMULrrr((rs), JIT_BIG, (d)))
|
||||
#define jit_muli_ui(d, rs, is) jit_chk_imm((is), UMULrir((rs), (is), (d)), UMULrrr((rs), JIT_BIG, (d)))
|
||||
#define jit_mulr_i(d, s1, s2) SMULrrr((s1), (s2), (d))
|
||||
#define jit_mulr_ui(d, s1, s2) UMULrrr((s1), (s2), (d))
|
||||
#define jit_nop() NOP()
|
||||
#define jit_ori_i(d, rs, is) jit_chk_imm((is), ORrir((rs), (is), (d)), ORrrr((rs), JIT_BIG, (d)))
|
||||
#define jit_orr_i(d, s1, s2) ORrrr((s1), (s2), (d))
|
||||
#define jit_patch_at(delay_pc, pv) jit_patch_ (((delay_pc) - 1) , (pv))
|
||||
#define jit_popr_i(rs) (LDmr(JIT_SP, 0, (rs)), ADDrir(JIT_SP, 8, JIT_SP))
|
||||
#define jit_prepare_i(num) (_jitl.nextarg_put += (num))
|
||||
#define jit_prolog(numargs) (SAVErir(JIT_SP, -120, JIT_SP), _jitl.nextarg_get = _Ri(0))
|
||||
#define jit_pushr_i(rs) (STrm((rs), JIT_SP, -8), SUBrir(JIT_SP, 8, JIT_SP))
|
||||
#define jit_pusharg_i(rs) (--_jitl.nextarg_put, MOVrr((rs), _Ro(_jitl.nextarg_put)))
|
||||
#define jit_ret() (RET(), RESTORE())
|
||||
#define jit_retval_i(rd) MOVrr(_Ro(0), (rd))
|
||||
#define jit_rshi_i(d, rs, is) SRArir((rs), (is), (d))
|
||||
#define jit_rshi_ui(d, rs, is) SRLrir((rs), (is), (d))
|
||||
#define jit_rshr_i(d, r1, r2) SRArrr((r1), (r2), (d))
|
||||
#define jit_rshr_ui(d, r1, r2) SRLrrr((r1), (r2), (d))
|
||||
#define jit_stxi_c(id, rd, rs) jit_chk_imm((id), STBrm((rs), (rd), (id)), STBrx((rs), (rd), JIT_BIG))
|
||||
#define jit_stxi_i(id, rd, rs) jit_chk_imm((id), STWrm((rs), (rd), (id)), STWrx((rs), (rd), JIT_BIG))
|
||||
#define jit_stxi_s(id, rd, rs) jit_chk_imm((id), STHrm((rs), (rd), (id)), STHrx((rs), (rd), JIT_BIG))
|
||||
#define jit_stxr_c(d1, d2, rs) STBrx((rs), (d1), (d2))
|
||||
#define jit_stxr_i(d1, d2, rs) STWrx((rs), (d1), (d2))
|
||||
#define jit_stxr_s(d1, d2, rs) STHrx((rs), (d1), (d2))
|
||||
#define jit_subr_i(d, s1, s2) SUBrrr((s1), (s2), (d))
|
||||
#define jit_subcr_i(d, s1, s2) SUBCCrrr((s1), (s2), (d))
|
||||
#define jit_subxi_i(d, rs, is) jit_chk_imm((is), SUBXCCrir((rs), (is), (d)), SUBXCCrrr((rs), JIT_BIG, (d)))
|
||||
#define jit_subxr_i(d, s1, s2) SUBXCCrrr((s1), (s2), (d))
|
||||
#define jit_xori_i(d, rs, is) jit_chk_imm((is), XORrir((rs), (is), (d)), XORrrr((rs), JIT_BIG, (d)))
|
||||
#define jit_xorr_i(d, s1, s2) XORrrr((s1), (s2), (d))
|
||||
|
||||
#endif /* __lightning_core_h */
|
||||
@@ -1,222 +0,0 @@
|
||||
/******************************** -*- C -*- ****************************
|
||||
*
|
||||
* Run-time assembler & support macros for the PowerPC math unit
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Copyright 2000, 2001, 2002, 2004 Free Software Foundation, Inc.
|
||||
* Written by Paolo Bonzini.
|
||||
*
|
||||
* This file is part of GNU lightning.
|
||||
*
|
||||
* GNU lightning is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2.1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU lightning is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with GNU lightning; see the file COPYING.LESSER; if not, write to the
|
||||
* Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef __lightning_asm_fp_h
|
||||
#define __lightning_asm_fp_h
|
||||
|
||||
#include <float.h>
|
||||
|
||||
#define JIT_FPR_NUM 6
|
||||
#define JIT_FPR(i) (30-(i)*2)
|
||||
#define JIT_FPTMP 18
|
||||
|
||||
#define jit_addr_f(rd,s1,s2) FADDSrrr((s1), (s2), (rd))
|
||||
#define jit_subr_f(rd,s1,s2) FSUBSrrr((s1), (s2), (rd))
|
||||
#define jit_mulr_f(rd,s1,s2) FMULSrrr((s1), (s2), (rd))
|
||||
#define jit_divr_f(rd,s1,s2) FDIVSrrr((s1), (s2), (rd))
|
||||
|
||||
#define jit_addr_d(rd,s1,s2) FADDDrrr((s1), (s2), (rd))
|
||||
#define jit_subr_d(rd,s1,s2) FSUBDrrr((s1), (s2), (rd))
|
||||
#define jit_mulr_d(rd,s1,s2) FMULDrrr((s1), (s2), (rd))
|
||||
#define jit_divr_d(rd,s1,s2) FDIVDrrr((s1), (s2), (rd))
|
||||
|
||||
#define jit_movr_f(rd,rs) FMOVSrr((rs), (rd))
|
||||
#define jit_abs_d(rd,rs) FABSSrr((rs), (rd))
|
||||
#define jit_negr_d(rd,rs) FNEGSrr((rs), (rd))
|
||||
#define jit_sqrt_d(rd,rs) FSQRTSrr((rs), (rd))
|
||||
#define jit_movr_d(rd,rs) FMOVDrr((rs), (rd))
|
||||
#define jit_abs_f(rd,rs) FABSDrr((rs), (rd))
|
||||
#define jit_negr_f(rd,rs) FNEGDrr((rs), (rd))
|
||||
#define jit_sqrt_f(rd,rs) FSQRTDrr((rs), (rd))
|
||||
#define jit_extr_f_d(rs, rd) FSTODrr((rs), (rd))
|
||||
#define jit_extr_d_f(rs, rd) FDTOSrr((rs), (rd))
|
||||
|
||||
#define jit_movi_f(rd,immf) \
|
||||
do { \
|
||||
float _v = (immf); \
|
||||
_1(_jit.x.pc + 3), LDFmr(_Ro(7), 8, (rd)); \
|
||||
memcpy(_jit.x.uc_pc, &_v, sizeof (float)); \
|
||||
_jit.x.uc_pc += sizeof (float); \
|
||||
} while(0)
|
||||
|
||||
#define jit_movi_d(rd,immd) \
|
||||
do { \
|
||||
double _v = (immd); \
|
||||
if ((long)_jit.x.pc & 4) NOP(); \
|
||||
_1(_jit.x.pc + 4); \
|
||||
LDDFmr(_Ro(7), 8, (rd)); \
|
||||
memcpy(_jit.x.uc_pc, &_v, sizeof (double)); \
|
||||
_jit.x.uc_pc += sizeof (double); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define jit_ldxi_f(rd, rs, is) jit_chk_imm((is), LDFmr((rs), (is), (rd)), LDFxr((rs), JIT_BIG, (rd)))
|
||||
#define jit_ldxi_d(rd, rs, is) jit_chk_imm((is), LDDFmr((rs), (is), (rd)), LDDFxr((rs), JIT_BIG, (rd)))
|
||||
#define jit_ldxr_f(rd, s1, s2) LDFxr((s1), (s2), (rd))
|
||||
#define jit_ldxr_d(rd, s1, s2) LDDFxr((s1), (s2), (rd))
|
||||
#define jit_stxi_f(id, rd, rs) jit_chk_imm((id), STFrm((rs), (rd), (id)), STFrx((rs), (rd), JIT_BIG))
|
||||
#define jit_stxi_d(id, rd, rs) jit_chk_imm((id), STDFrm((rs), (rd), (id)), STDFrx((rs), (rd), JIT_BIG))
|
||||
#define jit_stxr_f(d1, d2, rs) STFrx((rs), (d1), (d2))
|
||||
#define jit_stxr_d(d1, d2, rs) STDFrx((rs), (d1), (d2))
|
||||
|
||||
#define jit_truncr_f_i(rd, rs) ( \
|
||||
_1(_jit.x.pc + 3), \
|
||||
FSTOIrr((rs), JIT_FPTMP), \
|
||||
NOP(), \
|
||||
STFrm(JIT_FPTMP, _Ro(7), 8), \
|
||||
LDmr(_Ro(7), 8, (rd)))
|
||||
|
||||
#define jit_truncr_d_i(rd, rs) ( \
|
||||
_1(_jit.x.pc + 3), \
|
||||
FDTOIrr((rs), JIT_FPTMP), \
|
||||
NOP(), \
|
||||
STFrm(JIT_FPTMP, _Ro(7), 8), \
|
||||
LDmr(_Ro(7), 8, (rd)))
|
||||
|
||||
#define jit_extr_i_d(rd, rs) (_1 (_jit.x.pc + 3), NOP(), NOP(), STrm((rs), _Ro(7), 8), LDFmr(_Ro(7), 8, (rd)), FITODrr((rd), (rd)))
|
||||
#define jit_extr_i_f(rd, rs) (_1 (_jit.x.pc + 3), NOP(), NOP(), STrm((rs), _Ro(7), 8), LDFmr(_Ro(7), 8, (rd)), FITOSrr((rd), (rd)))
|
||||
|
||||
#define jit_do_round_f(rd, rs, fixup, mode) do { \
|
||||
jit_movi_f (JIT_FPTMP, fixup); \
|
||||
_1(_jit.x.pc + 4); \
|
||||
SETHIir(_HI(mode << 29), JIT_BIG); \
|
||||
NOP(); \
|
||||
NOP(); \
|
||||
STFSRm(_Ro(7), 8); /* store fsr */ \
|
||||
LDmr(_Ro(7), 8, rd); \
|
||||
XORrrr(rd, JIT_BIG, JIT_BIG); /* adjust mode */ \
|
||||
STrm(JIT_BIG, _Ro(7), 12); \
|
||||
LDFSRm(_Ro(7), 12); /* load fsr */ \
|
||||
FADDSrrr ((rs), JIT_FPTMP, JIT_FPTMP); \
|
||||
LDFSRm(_Ro(7), 8); \
|
||||
FSTOIrr(JIT_FPTMP, JIT_FPTMP); \
|
||||
STFrm(JIT_FPTMP, _Ro(7), 8); \
|
||||
LDmr(_Ro(7), 8, (rd)); \
|
||||
ADDCCrrr ((rd), (rd), 0); \
|
||||
SUBXrrr ((rd), 0, (rd)); \
|
||||
} while (0);
|
||||
|
||||
#define jit_do_round_d(rd, rs, fixup, mode) do { \
|
||||
jit_movi_d (JIT_FPTMP, fixup); \
|
||||
_1(_jit.x.pc + 4); \
|
||||
SETHIir(_HI(mode << 29), JIT_BIG); \
|
||||
NOP(); \
|
||||
NOP(); \
|
||||
STFSRm(_Ro(7), 8); /* store fsr */ \
|
||||
LDmr(_Ro(7), 8, rd); \
|
||||
XORrrr(rd, JIT_BIG, JIT_BIG); /* adjust mode */ \
|
||||
STrm(JIT_BIG, _Ro(7), 12); \
|
||||
LDFSRm(_Ro(7), 12); /* load fsr */ \
|
||||
FADDDrrr ((rs), JIT_FPTMP, JIT_FPTMP); \
|
||||
LDFSRm(_Ro(7), 8); \
|
||||
FDTOIrr(JIT_FPTMP, JIT_FPTMP); \
|
||||
STFrm(JIT_FPTMP, _Ro(7), 8); \
|
||||
LDmr(_Ro(7), 8, (rd)); \
|
||||
ADDCCrrr ((rd), (rd), 0); \
|
||||
SUBXrrr ((rd), 0, (rd)); \
|
||||
} while (0);
|
||||
|
||||
#define jit_roundr_f_i(rd, rs) do { \
|
||||
jit_movi_f (JIT_FPTMP, 0.5); \
|
||||
FADDSrrr ((rs), JIT_FPTMP, JIT_FPTMP); \
|
||||
jit_truncr_f_i ((rd), JIT_FPTMP); \
|
||||
ADDCCrrr ((rd), (rd), 0); \
|
||||
SUBXrrr ((rd), 0, (rd)); \
|
||||
} while (0)
|
||||
|
||||
#define jit_roundr_d_i(rd, rs) do { \
|
||||
jit_movi_d (JIT_FPTMP, 0.5); \
|
||||
FADDDrrr ((rs), JIT_FPTMP, JIT_FPTMP); \
|
||||
jit_truncr_d_i ((rd), JIT_FPTMP); \
|
||||
ADDCCrrr ((rd), (rd), 0); \
|
||||
SUBXrrr ((rd), 0, (rd)); \
|
||||
} while (0)
|
||||
|
||||
#define jit_ceilr_f_i(rd, rs) \
|
||||
jit_do_round_f ((rd), (rs), 1.0f - FLT_EPSILON, 3)
|
||||
|
||||
#define jit_ceilr_d_i(rd, rs) \
|
||||
jit_do_round_d ((rd), (rs), 1.0 - DBL_EPSILON, 3)
|
||||
|
||||
#define jit_floorr_f_i(rd, rs) \
|
||||
jit_do_round_f ((rd), (rs), FLT_EPSILON, 2)
|
||||
|
||||
#define jit_floorr_d_i(rd, rs) \
|
||||
jit_do_round_d ((rd), (rs), DBL_EPSILON, 2)
|
||||
|
||||
#define jit_ltr_d(d, s1, s2) (FCMPDrr ((s1), (s2)), FBLi(_jit.x.pc + 3), MOVir (1, (d)), MOVir (0, (d)))
|
||||
#define jit_ltr_f(d, s1, s2) (FCMPSrr ((s1), (s2)), FBLi(_jit.x.pc + 3), MOVir (1, (d)), MOVir (0, (d)))
|
||||
#define jit_ler_d(d, s1, s2) (FCMPDrr ((s1), (s2)), FBLEi(_jit.x.pc + 3), MOVir (1, (d)), MOVir (0, (d)))
|
||||
#define jit_ler_f(d, s1, s2) (FCMPSrr ((s1), (s2)), FBLEi(_jit.x.pc + 3), MOVir (1, (d)), MOVir (0, (d)))
|
||||
#define jit_eqr_d(d, s1, s2) (FCMPDrr ((s1), (s2)), FBEi(_jit.x.pc + 3), MOVir (1, (d)), MOVir (0, (d)))
|
||||
#define jit_eqr_f(d, s1, s2) (FCMPSrr ((s1), (s2)), FBEi(_jit.x.pc + 3), MOVir (1, (d)), MOVir (0, (d)))
|
||||
#define jit_ner_d(d, s1, s2) (FCMPDrr ((s1), (s2)), FBNEi(_jit.x.pc + 3), MOVir (1, (d)), MOVir (0, (d)))
|
||||
#define jit_ner_f(d, s1, s2) (FCMPSrr ((s1), (s2)), FBNEi(_jit.x.pc + 3), MOVir (1, (d)), MOVir (0, (d)))
|
||||
#define jit_ger_d(d, s1, s2) (FCMPDrr ((s1), (s2)), FBGEi(_jit.x.pc + 3), MOVir (1, (d)), MOVir (0, (d)))
|
||||
#define jit_ger_f(d, s1, s2) (FCMPSrr ((s1), (s2)), FBGEi(_jit.x.pc + 3), MOVir (1, (d)), MOVir (0, (d)))
|
||||
#define jit_gtr_d(d, s1, s2) (FCMPDrr ((s1), (s2)), FBGi(_jit.x.pc + 3), MOVir (1, (d)), MOVir (0, (d)))
|
||||
#define jit_gtr_f(d, s1, s2) (FCMPSrr ((s1), (s2)), FBGi(_jit.x.pc + 3), MOVir (1, (d)), MOVir (0, (d)))
|
||||
#define jit_unltr_d(d, s1, s2) (FCMPDrr ((s1), (s2)), FBULi(_jit.x.pc + 3), MOVir (1, (d)), MOVir (0, (d)))
|
||||
#define jit_unltr_f(d, s1, s2) (FCMPSrr ((s1), (s2)), FBULi(_jit.x.pc + 3), MOVir (1, (d), MOVir (0, (d)))
|
||||
#define jit_unler_d(d, s1, s2) (FCMPDrr ((s1), (s2)), FBULEi(_jit.x.pc + 3), MOVir (1, (d)), MOVir (0, (d)))
|
||||
#define jit_unler_f(d, s1, s2) (FCMPSrr ((s1), (s2)), FBULEi(_jit.x.pc + 3), MOVir (1, (d)), MOVir (0, (d)))
|
||||
#define jit_uneqr_d(d, s1, s2) (FCMPDrr ((s1), (s2)), FBUEi(_jit.x.pc + 3), MOVir (1, (d)), MOVir (0, (d)))
|
||||
#define jit_uneqr_f(d, s1, s2) (FCMPSrr ((s1), (s2)), FBUEi(_jit.x.pc + 3), MOVir (1, (d)), MOVir (0, (d)))
|
||||
#define jit_ltgtr_d(d, s1, s2) (FCMPDrr ((s1), (s2)), FBLGi(_jit.x.pc + 3), MOVir (1, (d)), MOVir (0, (d)))
|
||||
#define jit_ltgtr_f(d, s1, s2) (FCMPSrr ((s1), (s2)), FBLGi(_jit.x.pc + 3), MOVir (1, (d)), MOVir (0, (d)))
|
||||
#define jit_unger_d(d, s1, s2) (FCMPDrr ((s1), (s2)), FBUGEi(_jit.x.pc + 3), MOVir (1, (d)), MOVir (0, (d)))
|
||||
#define jit_unger_f(d, s1, s2) (FCMPSrr ((s1), (s2)), FBUGEi(_jit.x.pc + 3), MOVir (1, (d)), MOVir (0, (d)))
|
||||
#define jit_ungtr_d(d, s1, s2) (FCMPDrr ((s1), (s2)), FBUGi(_jit.x.pc + 3), MOVir (1, (d)), MOVir (0, (d)))
|
||||
#define jit_ungtr_f(d, s1, s2) (FCMPSrr ((s1), (s2)), FBUGi(_jit.x.pc + 3), MOVir (1, (d)), MOVir (0, (d)))
|
||||
#define jit_ordr_d(d, s1, s2) (FCMPDrr ((s1), (s2)), FBOi(_jit.x.pc + 3), MOVir (1, (d)), MOVir (0, (d)))
|
||||
#define jit_ordr_f(d, s1, s2) (FCMPSrr ((s1), (s2)), FBOi(_jit.x.pc + 3), MOVir (1, (d)), MOVir (0, (d)))
|
||||
#define jit_unordr_d(d, s1, s2) (FCMPDrr ((s1), (s2)), FBUi(_jit.x.pc + 3), MOVir (1, (d)), MOVir (0, (d)))
|
||||
#define jit_unordr_f(d, s1, s2) (FCMPSrr ((s1), (s2)), FBUi(_jit.x.pc + 3), MOVir (1, (d)), MOVir (0, (d)))
|
||||
|
||||
#define jit_prepare_f(num) (_jitl.nextarg_put += (num))
|
||||
#define jit_prepare_d(num) (_jitl.nextarg_put += 2 * (num))
|
||||
|
||||
#define jit_arg_f() (_jitl.nextarg_get++)
|
||||
#define jit_arg_d() (_jitl.nextarg_get += _jitl.nextarg_get & 1, _jitl.nextarg_get += 2, _jitl.nextarg_get - 2)
|
||||
|
||||
#define jit_getarg_f(rd, ofs) (STrm(ofs, _Ri(6), -24), LDFmr (_Ri(6), -24, (rd)))
|
||||
#define jit_getarg_d(rd, ofs) (STDrm(ofs, _Ri(6), -24), LDDFmr (_Ri(6), -24, (rd)))
|
||||
|
||||
#define jit_pusharg_f(rs) (STFrm((rs), _Ri(6), -24), --_jitl.nextarg_put, LDmr (_Ri(6), -24, _Ro(_jitl.nextarg_put)))
|
||||
#define jit_pusharg_d(rs) (STDFrm((rs), _Ri(6), -24), _jitl.nextarg_put -= 2, LDmr (_Ri(6), -24, _Ro(_jitl.nextarg_put)))
|
||||
|
||||
#define jit_retval_f(rs) jit_movr_f(0, rs)
|
||||
#define jit_retval_d(rs) jit_movr_d(0, rs)
|
||||
|
||||
#endif /* __lightning_asm_fp_h */
|
||||
@@ -1,65 +0,0 @@
|
||||
/******************************** -*- C -*- ****************************
|
||||
*
|
||||
* Platform-independent layer inline functions (Sparc)
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
* Written by Paolo Bonzini.
|
||||
*
|
||||
* This file is part of GNU lightning.
|
||||
*
|
||||
* GNU lightning is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2.1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU lightning is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with GNU lightning; see the file COPYING.LESSER; if not, write to the
|
||||
* Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef __lightning_funcs_h
|
||||
#define __lightning_funcs_h
|
||||
|
||||
#if !defined(__GNUC__) && !defined(__GNUG__)
|
||||
#error Go get GNU C, I do not know how to flush the cache
|
||||
#error with this compiler.
|
||||
#else
|
||||
/* Why doesn't this compile?!?
|
||||
* static void
|
||||
* jit_flush_code(start, end)
|
||||
* void *start;
|
||||
* void *end;
|
||||
*/
|
||||
|
||||
static void
|
||||
jit_flush_code(void* start, void* end)
|
||||
{
|
||||
#ifndef LIGHTNING_CROSS
|
||||
register char *dest;
|
||||
|
||||
__asm__ __volatile__ ("stbar");
|
||||
for (dest = (char *)start; dest <= (char *)end; dest += 4) {
|
||||
__asm__ __volatile__ ("flush %0"::"r"(dest));
|
||||
}
|
||||
|
||||
/* [SPARC Architecture Manual v8, page 139, implementation note #5] */
|
||||
__asm__ __volatile__ ("nop; nop; nop; nop; nop");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __lightning_core_h */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,126 +0,0 @@
|
||||
#ifndef PGF_LINEARIZER_H_
|
||||
#define PGF_LINEARIZER_H_
|
||||
|
||||
#include <gu/enum.h>
|
||||
|
||||
/// Linearization of abstract syntax trees.
|
||||
|
||||
//
|
||||
// PgfCncTree
|
||||
//
|
||||
|
||||
/// A concrete syntax tree
|
||||
typedef GuVariant PgfCncTree;
|
||||
|
||||
#ifdef PGF_DATA_H_
|
||||
|
||||
typedef enum {
|
||||
PGF_CNC_TREE_APP,
|
||||
PGF_CNC_TREE_CHUNKS,
|
||||
PGF_CNC_TREE_LIT,
|
||||
} PgfCncTreeTag;
|
||||
|
||||
typedef struct {
|
||||
PgfCCat* ccat;
|
||||
PgfCncFun* fun;
|
||||
int fid;
|
||||
|
||||
size_t n_vars;
|
||||
PgfPrintContext* context;
|
||||
|
||||
size_t n_args;
|
||||
PgfCncTree args[];
|
||||
} PgfCncTreeApp;
|
||||
|
||||
typedef struct {
|
||||
PgfMetaId id;
|
||||
|
||||
size_t n_vars;
|
||||
PgfPrintContext* context;
|
||||
|
||||
size_t n_args;
|
||||
PgfCncTree args[];
|
||||
} PgfCncTreeChunks;
|
||||
|
||||
typedef struct {
|
||||
size_t n_vars;
|
||||
PgfPrintContext* context;
|
||||
|
||||
int fid;
|
||||
PgfLiteral lit;
|
||||
} PgfCncTreeLit;
|
||||
|
||||
#endif
|
||||
|
||||
/// An enumeration of #PgfCncTree trees.
|
||||
typedef GuEnum PgfCncTreeEnum;
|
||||
|
||||
/// Begin enumerating concrete syntax variants.
|
||||
PGF_API_DECL PgfCncTreeEnum*
|
||||
pgf_lzr_concretize(PgfConcr* concr, PgfExpr expr, GuExn* err, GuPool* pool);
|
||||
|
||||
typedef struct {
|
||||
char nothing[0]; // Empty struct
|
||||
} PgfLinNonExist;
|
||||
|
||||
PGF_API_DECL PgfCncTree
|
||||
pgf_lzr_wrap_linref(PgfCncTree ctree, GuPool* pool);
|
||||
|
||||
|
||||
|
||||
typedef struct PgfLinFuncs PgfLinFuncs;
|
||||
|
||||
typedef enum {
|
||||
PGF_CAPIT_NONE,
|
||||
PGF_CAPIT_FIRST,
|
||||
PGF_CAPIT_ALL,
|
||||
PGF_CAPIT_NEXT
|
||||
} PgfCapitState;
|
||||
|
||||
struct PgfLinFuncs
|
||||
{
|
||||
/// Output tokens
|
||||
void (*symbol_token)(PgfLinFuncs** self, PgfToken tok);
|
||||
|
||||
/// Begin phrase
|
||||
void (*begin_phrase)(PgfLinFuncs** self, PgfCId cat, int fid, GuString ann, PgfCId fun);
|
||||
|
||||
/// End phrase
|
||||
void (*end_phrase)(PgfLinFuncs** self, PgfCId cat, int fid, GuString ann, PgfCId fun);
|
||||
|
||||
/// handling nonExist
|
||||
void (*symbol_ne)(PgfLinFuncs** self);
|
||||
|
||||
/// token binding
|
||||
void (*symbol_bind)(PgfLinFuncs** self);
|
||||
|
||||
/// capitalization
|
||||
void (*symbol_capit)(PgfLinFuncs** self, PgfCapitState capit);
|
||||
|
||||
/// meta variable
|
||||
void (*symbol_meta)(PgfLinFuncs** self, PgfMetaId id);
|
||||
};
|
||||
|
||||
/// Linearize a concrete syntax tree.
|
||||
PGF_API_DECL void
|
||||
pgf_lzr_linearize(PgfConcr* concr, PgfCncTree ctree, size_t lin_idx,
|
||||
PgfLinFuncs** funcs, GuPool* tmp_pool);
|
||||
|
||||
/// Linearize a concrete syntax tree as space-separated tokens.
|
||||
PGF_API_DECL void
|
||||
pgf_lzr_linearize_simple(PgfConcr* concr, PgfCncTree ctree, size_t lin_idx,
|
||||
GuOut* out, GuExn* err,
|
||||
GuPool* tmp_pool);
|
||||
|
||||
|
||||
PGF_API_DECL void
|
||||
pgf_lzr_get_table(PgfConcr* concr, PgfCncTree ctree,
|
||||
size_t* n_lins, GuString** labels);
|
||||
|
||||
#ifdef PGF_DATA_H_
|
||||
// Used internally in the parser
|
||||
PGF_INTERNAL_DECL GuString
|
||||
pgf_get_tokens(PgfSymbols* sym, uint16_t sym_idx, GuPool* pool);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,492 +0,0 @@
|
||||
#include <gu/in.h>
|
||||
#include <gu/utf8.h>
|
||||
#include <pgf/literals.h>
|
||||
#include <wctype.h>
|
||||
|
||||
|
||||
static PgfExprProb*
|
||||
pgf_match_string_lit(PgfLiteralCallback* self, PgfConcr* concr,
|
||||
GuString ann,
|
||||
GuString sentence, size_t* poffset,
|
||||
GuPool *out_pool)
|
||||
{
|
||||
if (strcmp(ann,"s") != 0)
|
||||
return NULL;
|
||||
|
||||
const uint8_t* buf = (uint8_t*) (sentence + *poffset);
|
||||
const uint8_t* p = buf;
|
||||
size_t len = 0;
|
||||
while (*p && !gu_ucs_is_space(gu_utf8_decode(&p))) {
|
||||
len = p - buf;
|
||||
}
|
||||
|
||||
if (len > 0) {
|
||||
PgfExprProb* ep = gu_new(PgfExprProb, out_pool);
|
||||
ep->prob = 0;
|
||||
|
||||
PgfExprLit *expr_lit =
|
||||
gu_new_variant(PGF_EXPR_LIT,
|
||||
PgfExprLit,
|
||||
&ep->expr, out_pool);
|
||||
|
||||
PgfLiteralStr *lit_str =
|
||||
gu_new_flex_variant(PGF_LITERAL_STR,
|
||||
PgfLiteralStr,
|
||||
val, len+1,
|
||||
&expr_lit->lit, out_pool);
|
||||
memcpy(lit_str->val, buf, len);
|
||||
lit_str->val[len] = 0;
|
||||
|
||||
*poffset += len;
|
||||
return ep;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pgf_predict_empty_next(GuEnum* self, void* to, GuPool* pool)
|
||||
{
|
||||
*((PgfTokenProb**) to) = NULL;
|
||||
}
|
||||
|
||||
static GuEnum*
|
||||
pgf_predict_empty(PgfLiteralCallback* self, PgfConcr* concr,
|
||||
GuString ann,
|
||||
GuString prefix,
|
||||
GuPool *out_pool)
|
||||
{
|
||||
GuEnum* en = gu_new(GuEnum, out_pool);
|
||||
en->next = pgf_predict_empty_next;
|
||||
return en;
|
||||
}
|
||||
|
||||
static PgfLiteralCallback pgf_string_literal_callback =
|
||||
{ pgf_match_string_lit, pgf_predict_empty } ;
|
||||
|
||||
|
||||
|
||||
static PgfExprProb*
|
||||
pgf_match_int_lit(PgfLiteralCallback* self, PgfConcr* concr,
|
||||
GuString ann,
|
||||
GuString sentence, size_t* poffset,
|
||||
GuPool *out_pool)
|
||||
{
|
||||
if (strcmp(ann,"s") != 0)
|
||||
return NULL;
|
||||
|
||||
const uint8_t* buf = (uint8_t*) (sentence + *poffset);
|
||||
const uint8_t* p = buf;
|
||||
size_t len = 0;
|
||||
while (*p && !gu_ucs_is_space(gu_utf8_decode(&p))) {
|
||||
len = p - buf;
|
||||
}
|
||||
|
||||
if (len > 0) {
|
||||
GuPool* tmp_pool = gu_local_pool();
|
||||
PgfToken tok = gu_malloc(tmp_pool, len+1);
|
||||
memcpy((char*) tok, buf, len);
|
||||
((char*) tok)[len] = 0;
|
||||
|
||||
int val;
|
||||
if (!gu_string_to_int(tok, &val)) {
|
||||
gu_pool_free(tmp_pool);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gu_pool_free(tmp_pool);
|
||||
|
||||
PgfExprProb* ep = gu_new(PgfExprProb, out_pool);
|
||||
ep->prob = 0;
|
||||
|
||||
PgfExprLit *expr_lit =
|
||||
gu_new_variant(PGF_EXPR_LIT,
|
||||
PgfExprLit,
|
||||
&ep->expr, out_pool);
|
||||
PgfLiteralInt *lit_int =
|
||||
gu_new_variant(PGF_LITERAL_INT,
|
||||
PgfLiteralInt,
|
||||
&expr_lit->lit, out_pool);
|
||||
lit_int->val = val;
|
||||
|
||||
*poffset += len;
|
||||
return ep;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static PgfLiteralCallback pgf_int_literal_callback =
|
||||
{ pgf_match_int_lit, pgf_predict_empty } ;
|
||||
|
||||
|
||||
|
||||
static PgfExprProb*
|
||||
pgf_match_float_lit(PgfLiteralCallback* self, PgfConcr* concr,
|
||||
GuString ann,
|
||||
GuString sentence, size_t* poffset,
|
||||
GuPool *out_pool)
|
||||
{
|
||||
if (strcmp(ann,"s") != 0)
|
||||
return NULL;
|
||||
|
||||
const uint8_t* buf = (uint8_t*) (sentence + *poffset);
|
||||
const uint8_t* p = buf;
|
||||
size_t len = 0;
|
||||
while (*p && !gu_ucs_is_space(gu_utf8_decode(&p))) {
|
||||
len = p - buf;
|
||||
}
|
||||
|
||||
if (len > 0) {
|
||||
GuPool* tmp_pool = gu_local_pool();
|
||||
PgfToken tok = gu_malloc(tmp_pool, len+1);
|
||||
memcpy((char*) tok, buf, len);
|
||||
((char*) tok)[len] = 0;
|
||||
|
||||
double val;
|
||||
if (!gu_string_to_double(tok, &val)) {
|
||||
gu_pool_free(tmp_pool);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gu_pool_free(tmp_pool);
|
||||
|
||||
PgfExprProb* ep = gu_new(PgfExprProb, out_pool);
|
||||
ep->prob = 0;
|
||||
|
||||
PgfExprLit *expr_lit =
|
||||
gu_new_variant(PGF_EXPR_LIT,
|
||||
PgfExprLit,
|
||||
&ep->expr, out_pool);
|
||||
PgfLiteralFlt *lit_flt =
|
||||
gu_new_variant(PGF_LITERAL_FLT,
|
||||
PgfLiteralFlt,
|
||||
&expr_lit->lit, out_pool);
|
||||
lit_flt->val = val;
|
||||
|
||||
*poffset += len;
|
||||
return ep;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static PgfLiteralCallback pgf_float_literal_callback =
|
||||
{ pgf_match_float_lit, pgf_predict_empty } ;
|
||||
|
||||
typedef struct {
|
||||
PgfMorphoCallback callback;
|
||||
PgfAbstr* abstract;
|
||||
PgfExpr expr;
|
||||
bool is_known;
|
||||
GuPool* out_pool;
|
||||
} PgfMatchMorphoCallback;
|
||||
|
||||
static void
|
||||
pgf_match_name_morpho_callback(PgfMorphoCallback* self_,
|
||||
PgfCId lemma, GuString analysis, prob_t prob,
|
||||
GuExn* err)
|
||||
{
|
||||
PgfMatchMorphoCallback* self =
|
||||
gu_container(self_, PgfMatchMorphoCallback, callback);
|
||||
|
||||
PgfAbsFun* absfun =
|
||||
gu_seq_binsearch(self->abstract->funs, pgf_absfun_order, PgfAbsFun, lemma);
|
||||
if (absfun != NULL) {
|
||||
if (strcmp(absfun->type->cid, "PN") == 0) {
|
||||
self->expr = absfun->ep.expr;
|
||||
} else if (strcmp(absfun->type->cid, "Weekday") == 0) {
|
||||
PgfExprApp *expr_app =
|
||||
gu_new_variant(PGF_EXPR_APP,
|
||||
PgfExprApp,
|
||||
&self->expr, self->out_pool);
|
||||
GuString con = "weekdayPN";
|
||||
PgfExprFun *expr_fun =
|
||||
gu_new_flex_variant(PGF_EXPR_FUN,
|
||||
PgfExprFun,
|
||||
fun, strlen(con)+1,
|
||||
&expr_app->fun, self->out_pool);
|
||||
strcpy(expr_fun->fun, con);
|
||||
expr_app->arg = absfun->ep.expr;
|
||||
} else if (strcmp(absfun->type->cid, "Month") == 0) {
|
||||
PgfExprApp *expr_app =
|
||||
gu_new_variant(PGF_EXPR_APP,
|
||||
PgfExprApp,
|
||||
&self->expr, self->out_pool);
|
||||
GuString con = "monthPN";
|
||||
PgfExprFun *expr_fun =
|
||||
gu_new_flex_variant(PGF_EXPR_FUN,
|
||||
PgfExprFun,
|
||||
fun, strlen(con)+1,
|
||||
&expr_app->fun, self->out_pool);
|
||||
strcpy(expr_fun->fun, con);
|
||||
expr_app->arg = absfun->ep.expr;
|
||||
} else {
|
||||
self->is_known = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static PgfExprProb*
|
||||
pgf_match_name_lit(PgfLiteralCallback* self, PgfConcr* concr,
|
||||
GuString ann,
|
||||
GuString sentence, size_t* poffset,
|
||||
GuPool *out_pool)
|
||||
{
|
||||
if (strcmp(ann,"s") != 0)
|
||||
return NULL;
|
||||
|
||||
GuPool* tmp_pool = gu_local_pool();
|
||||
GuStringBuf *sbuf = gu_new_string_buf(tmp_pool);
|
||||
GuOut* out = gu_string_buf_out(sbuf);
|
||||
GuExn* err = gu_new_exn(tmp_pool);
|
||||
|
||||
const uint8_t* buf = (uint8_t*) (sentence + *poffset);
|
||||
const uint8_t* p = buf;
|
||||
|
||||
int i = 0;
|
||||
GuUCS ucs = gu_utf8_decode(&p);
|
||||
while (gu_ucs_is_upper(ucs)) {
|
||||
if (i > 0)
|
||||
gu_putc(' ', out, err);
|
||||
gu_out_utf8(ucs, out, err);
|
||||
*poffset = p - ((uint8_t*) sentence);
|
||||
|
||||
ucs = gu_utf8_decode(&p);
|
||||
while (ucs != 0 && !gu_ucs_is_space(ucs)) {
|
||||
gu_out_utf8(ucs, out, err);
|
||||
*poffset = p - ((uint8_t*) sentence);
|
||||
|
||||
ucs = gu_utf8_decode(&p);
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
while (gu_ucs_is_space(ucs))
|
||||
ucs = gu_utf8_decode(&p);
|
||||
}
|
||||
|
||||
PgfExprProb* ep = NULL;
|
||||
if (i > 0) {
|
||||
GuString name = gu_string_buf_freeze(sbuf, tmp_pool);
|
||||
|
||||
// Detect I and I'm in English
|
||||
GuString concr_name = pgf_concrete_name(concr);
|
||||
size_t concr_name_len = strlen(concr_name);
|
||||
if (concr_name_len >= 3 && strcmp(concr_name+concr_name_len-3,"Eng") == 0) {
|
||||
if (strcmp(name, "I") == 0 || strcmp(name, "I'm") == 0) {
|
||||
gu_pool_free(tmp_pool);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
PgfMatchMorphoCallback clo = { { pgf_match_name_morpho_callback },
|
||||
concr->abstr,
|
||||
gu_null_variant,
|
||||
false,
|
||||
out_pool
|
||||
};
|
||||
pgf_lookup_morpho(concr, name, &clo.callback, NULL);
|
||||
|
||||
if (clo.is_known) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (gu_variant_is_null(clo.expr)) {
|
||||
PgfExprApp *expr_app1 =
|
||||
gu_new_variant(PGF_EXPR_APP,
|
||||
PgfExprApp,
|
||||
&clo.expr, out_pool);
|
||||
GuString con1 = "SymbPN";
|
||||
PgfExprFun *expr_fun1 =
|
||||
gu_new_flex_variant(PGF_EXPR_FUN,
|
||||
PgfExprFun,
|
||||
fun, strlen(con1)+1,
|
||||
&expr_app1->fun, out_pool);
|
||||
strcpy(expr_fun1->fun, con1);
|
||||
PgfExprApp *expr_app2 =
|
||||
gu_new_variant(PGF_EXPR_APP,
|
||||
PgfExprApp,
|
||||
&expr_app1->arg, out_pool);
|
||||
GuString con2 = "MkSymb";
|
||||
PgfExprFun *expr_fun2 =
|
||||
gu_new_flex_variant(PGF_EXPR_FUN,
|
||||
PgfExprFun,
|
||||
fun, strlen(con2)+1,
|
||||
&expr_app2->fun, out_pool);
|
||||
strcpy(expr_fun2->fun, con2);
|
||||
PgfExprLit *expr_lit =
|
||||
gu_new_variant(PGF_EXPR_LIT,
|
||||
PgfExprLit,
|
||||
&expr_app2->arg, out_pool);
|
||||
PgfLiteralStr *lit_str =
|
||||
gu_new_flex_variant(PGF_LITERAL_STR,
|
||||
PgfLiteralStr,
|
||||
val, strlen(name)+1,
|
||||
&expr_lit->lit, out_pool);
|
||||
strcpy(lit_str->val, name);
|
||||
}
|
||||
|
||||
ep = gu_new(PgfExprProb, out_pool);
|
||||
ep->prob = 0;
|
||||
ep->expr = clo.expr;
|
||||
}
|
||||
|
||||
gu_pool_free(tmp_pool);
|
||||
|
||||
return ep;
|
||||
}
|
||||
|
||||
PGF_API PgfLiteralCallback pgf_nerc_literal_callback =
|
||||
{ pgf_match_name_lit, pgf_predict_empty } ;
|
||||
|
||||
static void
|
||||
pgf_match_unknown_morpho_callback(PgfMorphoCallback* self_,
|
||||
PgfCId lemma, GuString analysis, prob_t prob,
|
||||
GuExn* err)
|
||||
{
|
||||
PgfMatchMorphoCallback* self =
|
||||
gu_container(self_, PgfMatchMorphoCallback, callback);
|
||||
self->is_known = true;
|
||||
}
|
||||
|
||||
static PgfExprProb*
|
||||
pgf_match_unknown_lit(PgfLiteralCallback* self, PgfConcr* concr,
|
||||
GuString ann,
|
||||
GuString sentence, size_t* poffset,
|
||||
GuPool *out_pool)
|
||||
{
|
||||
const uint8_t* buf = (uint8_t*) (sentence + *poffset);
|
||||
const uint8_t* p = buf;
|
||||
|
||||
PgfExprProb* ep = NULL;
|
||||
|
||||
GuUCS ucs = gu_utf8_decode(&p);
|
||||
if (!gu_ucs_is_upper(ucs)) {
|
||||
GuPool* tmp_pool = gu_local_pool();
|
||||
GuStringBuf *sbuf = gu_new_string_buf(tmp_pool);
|
||||
GuOut* out = gu_string_buf_out(sbuf);
|
||||
GuExn* err = gu_new_exn(tmp_pool);
|
||||
|
||||
gu_out_utf8(ucs, out, err);
|
||||
*poffset = p - ((uint8_t*) sentence);
|
||||
|
||||
ucs = gu_utf8_decode(&p);
|
||||
while (ucs != 0 && !gu_ucs_is_space(ucs)) {
|
||||
gu_out_utf8(ucs, out, err);
|
||||
*poffset = p - ((uint8_t*) sentence);
|
||||
|
||||
ucs = gu_utf8_decode(&p);
|
||||
}
|
||||
|
||||
GuString word = gu_string_buf_freeze(sbuf, tmp_pool);
|
||||
|
||||
PgfMatchMorphoCallback clo = { { pgf_match_unknown_morpho_callback },
|
||||
concr->abstr,
|
||||
gu_null_variant,
|
||||
false,
|
||||
out_pool
|
||||
};
|
||||
pgf_lookup_morpho(concr, word, &clo.callback, NULL);
|
||||
|
||||
if (!clo.is_known) {
|
||||
ep = gu_new(PgfExprProb, out_pool);
|
||||
ep->prob = 0;
|
||||
|
||||
PgfExprApp *expr_app =
|
||||
gu_new_variant(PGF_EXPR_APP,
|
||||
PgfExprApp,
|
||||
&ep->expr, out_pool);
|
||||
GuString con = "MkSymb";
|
||||
PgfExprFun *expr_fun =
|
||||
gu_new_flex_variant(PGF_EXPR_FUN,
|
||||
PgfExprFun,
|
||||
fun, strlen(con)+1,
|
||||
&expr_app->fun, out_pool);
|
||||
strcpy(expr_fun->fun, con);
|
||||
PgfExprLit *expr_lit =
|
||||
gu_new_variant(PGF_EXPR_LIT,
|
||||
PgfExprLit,
|
||||
&expr_app->arg, out_pool);
|
||||
PgfLiteralStr *lit_str =
|
||||
gu_new_flex_variant(PGF_LITERAL_STR,
|
||||
PgfLiteralStr,
|
||||
val, strlen(word)+1,
|
||||
&expr_lit->lit, out_pool);
|
||||
strcpy(lit_str->val, word);
|
||||
}
|
||||
|
||||
gu_pool_free(tmp_pool);
|
||||
}
|
||||
|
||||
return ep;
|
||||
}
|
||||
|
||||
PGF_API PgfLiteralCallback pgf_unknown_literal_callback =
|
||||
{ pgf_match_unknown_lit, pgf_predict_empty } ;
|
||||
|
||||
PgfCallbacksMap*
|
||||
pgf_new_callbacks_map(PgfConcr* concr, GuPool *pool)
|
||||
{
|
||||
int fid;
|
||||
PgfCCat* ccat;
|
||||
|
||||
PgfCallbacksMap* callbacks =
|
||||
gu_new_addr_map(PgfCncCat*, PgfLiteralCallback*, &gu_null_struct, pool);
|
||||
|
||||
fid = -1;
|
||||
ccat = gu_map_get(concr->ccats, &fid, PgfCCat*);
|
||||
if (ccat != NULL)
|
||||
gu_map_put(callbacks, ccat->cnccat,
|
||||
PgfLiteralCallback*, &pgf_string_literal_callback);
|
||||
|
||||
fid = -2;
|
||||
ccat = gu_map_get(concr->ccats, &fid, PgfCCat*);
|
||||
if (ccat != NULL)
|
||||
gu_map_put(callbacks, ccat->cnccat,
|
||||
PgfLiteralCallback*, &pgf_int_literal_callback);
|
||||
|
||||
fid = -3;
|
||||
ccat = gu_map_get(concr->ccats, &fid, PgfCCat*);
|
||||
if (ccat != NULL)
|
||||
gu_map_put(callbacks, ccat->cnccat,
|
||||
PgfLiteralCallback*, &pgf_float_literal_callback);
|
||||
|
||||
return callbacks;
|
||||
}
|
||||
|
||||
void
|
||||
pgf_callbacks_map_add_literal(PgfConcr* concr, PgfCallbacksMap* callbacks,
|
||||
PgfCId cat, PgfLiteralCallback* callback)
|
||||
{
|
||||
PgfCncCat* cnccat =
|
||||
gu_map_get(concr->cnccats, cat, PgfCncCat*);
|
||||
if (cnccat == NULL)
|
||||
return;
|
||||
|
||||
gu_map_put(callbacks, cnccat,
|
||||
PgfLiteralCallback*, callback);
|
||||
}
|
||||
|
||||
PGF_INTERNAL PgfCCat*
|
||||
pgf_literal_cat(PgfConcr* concr, PgfLiteral lit)
|
||||
{
|
||||
int fid;
|
||||
|
||||
switch (gu_variant_tag(lit)) {
|
||||
case PGF_LITERAL_STR:
|
||||
fid = -1;
|
||||
break;
|
||||
case PGF_LITERAL_INT:
|
||||
fid = -2;
|
||||
break;
|
||||
case PGF_LITERAL_FLT:
|
||||
fid = -3;
|
||||
break;
|
||||
default:
|
||||
gu_impossible();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return gu_map_get(concr->ccats, &fid, PgfCCat*);
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
#ifndef PGF_LITERALS_H_
|
||||
#define PGF_LITERALS_H_
|
||||
|
||||
#include <pgf/data.h>
|
||||
|
||||
// literal for named entities recognition
|
||||
PGF_API_DECL extern PgfLiteralCallback pgf_nerc_literal_callback;
|
||||
|
||||
// literal for finding unknown words
|
||||
PGF_API_DECL extern PgfLiteralCallback pgf_unknown_literal_callback;
|
||||
|
||||
PGF_INTERNAL_DECL PgfCCat*
|
||||
pgf_literal_cat(PgfConcr* concr, PgfLiteral lit);
|
||||
|
||||
#endif // PGF_LITERALS_H_
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user