started a new database-backed runtime from scratch

This commit is contained in:
krangelov
2021-07-30 12:08:28 +02:00
parent 155657709a
commit 8f0a1b8fee
117 changed files with 1637 additions and 41288 deletions

View File

@@ -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>

View File

@@ -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)

View File

@@ -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.

View File

@@ -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.

View File

@@ -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

View File

@@ -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
View 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
View 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
View 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
View 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_ */

View File

@@ -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();
}

View File

@@ -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_ */

View File

@@ -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;
}

View File

@@ -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_

View File

@@ -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;
}

View File

@@ -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_

View File

@@ -1,4 +0,0 @@
#include <gu/defs.h>
void* const gu_null = NULL;
GU_API GuStruct* const gu_null_struct = NULL;

View File

@@ -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_

View File

@@ -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);
}

View File

@@ -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_ */

View File

@@ -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;
}
}

View File

@@ -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_

View File

@@ -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);
}

View File

@@ -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_

View File

@@ -1 +0,0 @@
#include <gu/fun.h>

View File

@@ -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_

View File

@@ -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
}
};

View File

@@ -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_

View File

@@ -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);

View File

@@ -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_

View File

@@ -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;
}

View File

@@ -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_

View File

@@ -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);

View File

@@ -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_

View File

@@ -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);
}

View File

@@ -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_

View File

@@ -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;
}

View File

@@ -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_

View File

@@ -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);
}
}

View File

@@ -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_

View File

@@ -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
}
};

View File

@@ -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

View File

@@ -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

View File

@@ -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_

View File

@@ -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);

View File

@@ -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_

View File

@@ -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 };

View File

@@ -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_

View File

@@ -1,3 +0,0 @@
bash setup.sh configure
bash setup.sh build
bash setup.sh install

View File

@@ -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}

View File

@@ -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
View 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
View 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
View 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_

View File

@@ -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);
}

View File

@@ -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 } };

View File

@@ -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

View File

@@ -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

View File

@@ -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_ */

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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_ */

View File

@@ -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

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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

View File

@@ -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

View File

@@ -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*);
}

View File

@@ -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