[svn:parrot] r41837 - in branches/auto_libjit: . config/auto config/auto/libjit config/gen config/gen/libjit config/gen/makefiles lib/Parrot/Configure/Options lib/Parrot/Configure/Options/Conf lib/Parrot/Configure/Step src t/pmc t/steps/auto t/steps/gen tools/build
jkeenan at svn.parrot.org
jkeenan at svn.parrot.org
Tue Oct 13 02:20:16 UTC 2009
Author: jkeenan
Date: Tue Oct 13 02:20:14 2009
New Revision: 41837
URL: https://trac.parrot.org/parrot/changeset/41837
Log:
Apply in branch plobsing's patch submitted in
https://trac.parrot.org/parrot/ticket/1105, with these modifications:
1. Move config step gen::libjit up to 4th last step.
2. Add SVN properties and rebuild MANIFEST.
Added:
branches/auto_libjit/config/auto/libjit/
branches/auto_libjit/config/auto/libjit.pm (contents, props changed)
branches/auto_libjit/config/auto/libjit/libjit_c.in
branches/auto_libjit/config/gen/libjit/
branches/auto_libjit/config/gen/libjit.pm (contents, props changed)
branches/auto_libjit/config/gen/libjit/frame_builder_libjit_c.in
branches/auto_libjit/config/gen/libjit/frame_builder_libjit_h.in
branches/auto_libjit/t/steps/auto/libjit-01.t (contents, props changed)
branches/auto_libjit/t/steps/gen/libjit-01.t (contents, props changed)
Modified:
branches/auto_libjit/MANIFEST
branches/auto_libjit/config/gen/makefiles/root.in
branches/auto_libjit/lib/Parrot/Configure/Options/Conf.pm
branches/auto_libjit/lib/Parrot/Configure/Options/Conf/Shared.pm
branches/auto_libjit/lib/Parrot/Configure/Step/List.pm
branches/auto_libjit/src/frame_builder.c
branches/auto_libjit/src/frame_builder.h
branches/auto_libjit/src/nci_test.c
branches/auto_libjit/t/pmc/nci.t
branches/auto_libjit/tools/build/nativecall.pl
Modified: branches/auto_libjit/MANIFEST
==============================================================================
--- branches/auto_libjit/MANIFEST Tue Oct 13 01:44:21 2009 (r41836)
+++ branches/auto_libjit/MANIFEST Tue Oct 13 02:20:14 2009 (r41837)
@@ -1,7 +1,7 @@
# ex: set ro:
# $Id$
#
-# generated by tools/dev/mk_manifest_and_skip.pl Wed Sep 30 22:16:16 2009 UT
+# generated by tools/dev/mk_manifest_and_skip.pl Tue Oct 13 02:18:39 2009 UT
#
# See below for documentation on the format of this file.
#
@@ -257,6 +257,8 @@
config/auto/isreg.pm []
config/auto/isreg/test_c.in []
config/auto/jit.pm []
+config/auto/libjit.pm []
+config/auto/libjit/libjit_c.in []
config/auto/memalign.pm []
config/auto/memalign/test2_c.in []
config/auto/memalign/test_c.in []
@@ -309,6 +311,9 @@
config/gen/crypto.pm []
config/gen/crypto/digest_pmc.in []
config/gen/crypto/digest_t.in []
+config/gen/libjit.pm []
+config/gen/libjit/frame_builder_libjit_c.in []
+config/gen/libjit/frame_builder_libjit_h.in []
config/gen/makefiles.pm []
config/gen/makefiles/CFLAGS.in []
config/gen/makefiles/data_json.in []
@@ -1931,6 +1936,7 @@
t/steps/auto/inline-01.t [test]
t/steps/auto/isreg-01.t [test]
t/steps/auto/jit-01.t [test]
+t/steps/auto/libjit-01.t [test]
t/steps/auto/memalign-01.t [test]
t/steps/auto/msvc-01.t [test]
t/steps/auto/neg_0-01.t [test]
@@ -1955,6 +1961,7 @@
t/steps/gen/config_pm-01.t [test]
t/steps/gen/core_pmcs-01.t [test]
t/steps/gen/crypto-01.t [test]
+t/steps/gen/libjit-01.t [test]
t/steps/gen/makefiles-01.t [test]
t/steps/gen/opengl-01.t [test]
t/steps/gen/parrot_include-01.t [test]
Added: branches/auto_libjit/config/auto/libjit.pm
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/auto_libjit/config/auto/libjit.pm Tue Oct 13 02:20:14 2009 (r41837)
@@ -0,0 +1,97 @@
+# Copyright (C) 2009, Parrot Foundation.
+# $Id$
+
+=head1 NAME
+
+config/auto/libjit - Check whether LibJIT is installed
+
+=head1 DESCRIPTION
+
+Determines whether LibJIT is present is installed and
+functional on the system. It is OK when it doesn't exist.
+
+=cut
+
+package auto::libjit;
+
+use strict;
+use warnings;
+
+use base 'Parrot::Configure::Step';
+
+use Parrot::Configure::Utils ':auto';
+
+sub _init {
+ my $self = shift;
+ my %data = (
+ description => 'Is LibJIT installed',
+ result => '',
+ );
+ return \%data;
+}
+
+sub runstep {
+ my ($self, $conf) = @_;
+
+ my ($verbose, $without) = $conf->options->get( qw{
+ verbose
+ without-libjit
+ });
+
+ if ($without) {
+ $conf->data->set( HAS_LIBJIT => 0 );
+ $self->set_result('no');
+ return 1;
+ }
+
+ my $extra_libs = $self->_select_lib({
+ conf => $conf,
+ osname => $conf->data->get_p5('OSNAME'),
+ cc => $conf->data->get('cc'),
+ win32_nongcc => 'libjit.lib',
+ default => '-ljit',
+ });
+
+ $conf->cc_gen('config/auto/libjit/libjit_c.in');
+ eval {$conf->cc_build('', $extra_libs)};
+ my $has_libjit = 0;
+ if (!$@) {
+ my $test = $conf->cc_run();
+ $has_libjit = $self->_evaluate_cc_run($conf, $test, $has_libjit, $verbose);
+ } else {
+ die $@;
+ }
+
+ $conf->data->set( HAS_LIBJIT => $has_libjit );
+ $self->set_result( $has_libjit ? 'yes' : 'no' );
+
+ if ($has_libjit) {
+ $conf->data->set(
+ cc_build_call_frames => '-DCAN_BUILD_CALL_FRAMES',
+ has_exec_protect => 1,
+ );
+ $conf->data->add( ' ', libs => $extra_libs );
+ }
+
+ return 1;
+}
+
+sub _evaluate_cc_run {
+ my $self = shift;
+ my ($conf, $test, $has_libjit, $verbose) = @_;
+ if ($test =~ m/^USES INTERPRETER: \d+/ ) {
+ $has_libjit = 1;
+ print " (yes) " if $verbose;
+ $self->set_result("yes");
+ }
+ return $has_libjit;
+}
+
+1;
+
+# Local Variables:
+# mode: cperl
+# cperl-indent-level: 4
+# fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4:
Added: branches/auto_libjit/config/auto/libjit/libjit_c.in
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/auto_libjit/config/auto/libjit/libjit_c.in Tue Oct 13 02:20:14 2009 (r41837)
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2009, Parrot Foundation.
+ * $Id$
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <jit/jit.h>
+
+int
+main(int argc, char *argv[]) {
+ jit_init();
+ printf("USES INTERPRETER: %i\n", jit_uses_interpreter());
+ return EXIT_SUCCESS;
+}
+
+/*
+ * Local variables:
+ * c-file-style: "parrot"
+ * End:
+ * vim: expandtab shiftwidth=4:
+ */
Added: branches/auto_libjit/config/gen/libjit.pm
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/auto_libjit/config/gen/libjit.pm Tue Oct 13 02:20:14 2009 (r41837)
@@ -0,0 +1,199 @@
+# Copyright (C) 2009, Parrot Foundation.
+# $Id$
+
+=head1 NAME
+
+config/gen/libjit.pm - LibJIT Code Generation
+
+=head1 DESCRIPTION
+
+Populate F<config/gen/frame_builder_libjit_h.in> and
+F<configu/gen/frame_builder_libjit_c.in> with system appropriate
+type information and automatically generated parrot function and
+vtable jit wrappers.
+
+=cut
+
+package gen::libjit;
+
+use strict;
+use warnings;
+
+use base 'Parrot::Configure::Step';
+
+use Parrot::Configure::Utils ':gen';
+
+
+sub _init {
+ my $self = shift;
+ my %data = (
+ description => 'Generate LibJIT specific code',
+ result => '',
+ targets => {
+ frame_builder_h => 'src/frame_builder_libjit.h',
+ frame_builder_c => 'src/frame_builder_libjit.c',
+ },
+ templates => {
+ frame_builder_h => 'config/gen/libjit/frame_builder_libjit_h.in',
+ frame_builder_c => 'config/gen/libjit/frame_builder_libjit_c.in',
+ },
+ wrapped_vtables => {
+ get_integer => [ () => 'INTVAL' ],
+ set_integer_native => [ ('INTVAL') => 'void' ],
+ get_pointer => [ () => 'void_ptr' ],
+ set_pointer => [ ('void_ptr') => 'void' ],
+ },
+ wrapped_funcs => {
+ get_nci_I => [ qw(void_ptr void_ptr sys_int) => 'INTVAL' ],
+ get_nci_N => [ qw(void_ptr void_ptr sys_int) => 'FLOATVAL' ],
+ get_nci_S => [ qw(void_ptr void_ptr sys_int) => 'void_ptr' ],
+ get_nci_P => [ qw(void_ptr void_ptr sys_int) => 'void_ptr' ],
+ get_nci_p => [ qw(void_ptr void_ptr sys_int) => 'void_ptr' ],
+
+ set_nci_I => [ qw(void_ptr void_ptr INTVAL) => 'void' ],
+ set_nci_N => [ qw(void_ptr void_ptr FLOATVAL) => 'void' ],
+ set_nci_S => [ qw(void_ptr void_ptr void_ptr) => 'void' ],
+ set_nci_P => [ qw(void_ptr void_ptr void_ptr) => 'void' ],
+
+ Parrot_str_new => [ qw(void_ptr void_ptr UINTVAL) => 'void_ptr' ],
+ Parrot_str_to_cstring => [ qw(void_ptr void_ptr) => 'void_ptr' ],
+ Parrot_str_free_cstring => [ ('void_ptr') => 'void' ],
+
+ Parrot_init_arg_nci => [ qw(void_ptr void_ptr void_ptr) => 'void_ptr' ],
+ pmc_new_noinit => [ qw(void_ptr INTVAL) => 'void_ptr' ],
+ },
+ );
+ return \%data;
+}
+
+sub runstep {
+ my ($self, $conf) = @_;
+
+ my ($libjit_iv, $libjit_uv) = @{
+ my $iv = $conf->data->get('iv') || '';
+ {
+ short => [ 'jit_type_sys_short' , 'jit_type_sys_ushort' ],
+ int => [ 'jit_type_sys_int' , 'jit_type_sys_uint' ],
+ long => [ 'jit_type_sys_long' , 'jit_type_sys_ulong' ],
+ 'long long' => [ 'jit_type_sys_longlong', 'jit_type_sys_ulonglong' ],
+ }->{$iv}
+ or die "Couldn't determine libjity type for intval of type '$iv'";
+ };
+
+ my $libjit_nv = do {
+ my $nv = $conf->data->get('nv') || '';
+ {
+ float => 'jit_type_sys_float',
+ double => 'jit_type_sys_double',
+ 'long double' => 'jit_type_sys_long_double',
+ }->{$nv}
+ or die "Couldn't determine libjity type for floatval of type '$nv'";
+ };
+
+ $conf->data->set( libjit_iv => $libjit_iv,
+ libjit_uv => $libjit_uv,
+ libjit_nv => $libjit_nv, );
+
+ my @vtable_wrappers = map {gen_vtable_wrapper($self, $_)} keys %{$self->{wrapped_vtables}};
+ my @function_wrappers = map {gen_function_wrapper($self, $_)} keys %{$self->{wrapped_funcs}};
+
+ $conf->data->set( TEMP_vtable_wrap_decls => (join "\n", map {$_->{decl}} @vtable_wrappers),
+ TEMP_vtable_wrap_defns => (join "\n", map {$_->{defn}} @vtable_wrappers),
+ TEMP_func_wrap_decls => (join "\n", map {$_->{decl}} @function_wrappers),
+ TEMP_func_wrap_defns => (join "\n", map {$_->{defn}} @function_wrappers) );
+
+ foreach (keys %{$self->{targets}}) {
+ $conf->genfile($self->{templates}{$_}, $self->{targets}{$_});
+ }
+
+ return 1;
+}
+
+sub gen_vtable_wrapper {
+ my ($self, $entry_name) = @_;
+
+ my $entry_sig = $self->{wrapped_vtables}{$entry_name};
+ $_ = jit_prefix_type($_) for @$entry_sig;
+
+ my $ret_t = pop @$entry_sig;
+ my $arg_t = join ", ", @$entry_sig;
+
+ my $n_args = scalar @$entry_sig;
+ my $arg_decls_t = join ", ", map {'jit_value_t'} 1..$n_args;
+ my $arg_decls_v = join ", ", map {"jit_value_t v$_"} 1..$n_args;
+ my $arg_v = join ", ", map {"v$_"} 1..$n_args;
+
+ my $_arg_decls_t = $n_args ? ", $arg_decls_t" : "";
+ my $_arg_decls_v = $n_args ? ", $arg_decls_v" : "";
+ my $_arg_t = $n_args ? ", $arg_t" : "";
+ my $_arg_v = $n_args ? ", $arg_v" : "";
+
+ return { decl => <<DECL, defn => <<DEFN };
+jit_value_t
+jit__vtable_$entry_name(jit_function_t, jit_value_t, jit_value_t $_arg_decls_t);
+DECL
+jit_value_t
+jit__vtable_$entry_name(jit_function_t f, jit_value_t interp, jit_value_t self $_arg_decls_v) {
+ jit_type_t sig;
+ jit_value_t vtable, method;
+ jit_type_t arg_t[] = { jit_type_void_ptr, jit_type_void_ptr $_arg_t };
+ jit_value_t arg_v[] = { interp, self $_arg_v };
+
+ sig = jit_type_create_signature(jit_abi_cdecl, $ret_t, arg_t, $n_args + 2, 1);
+
+ vtable = jit_insn_load_relative(f, self, offsetof(PMC, vtable), jit_type_void_ptr);
+ method = jit_insn_load_relative(f, vtable, offsetof(VTABLE, $entry_name), jit_type_void_ptr);
+
+ return jit_insn_call_indirect(f, method, sig, arg_v, $n_args + 2, 0);
+}
+DEFN
+}
+
+sub gen_function_wrapper {
+ my ($self, $func_name) = @_;
+
+ my $func_sig = $self->{wrapped_funcs}{$func_name};
+ $_ = jit_prefix_type($_) for @$func_sig;
+
+ my $ret_t = pop @$func_sig;
+ my $arg_t = join ", ", @$func_sig;
+
+ my $n_args = scalar @$func_sig;
+ my $arg_decls_t = join ", ", map {'jit_value_t'} 1..$n_args;
+ my $arg_decls_v = join ", ", map {"jit_value_t v$_"} 1..$n_args;
+ my $arg_v = join ", ", map {"v$_"} 1..$n_args;
+
+ return { decl => <<DECL, defn => <<DEFN };
+jit_value_t
+jit__$func_name(jit_function_t, $arg_decls_t);
+DECL
+jit_value_t
+jit__$func_name(jit_function_t f, $arg_decls_v) {
+ jit_type_t sig;
+ jit_type_t arg_t[] = { $arg_t };
+ jit_value_t arg_v[] = { $arg_v };
+
+ sig = jit_type_create_signature(jit_abi_cdecl, $ret_t, arg_t, $n_args, 1);
+
+ return jit_insn_call_native(f, "$func_name", (void *)&$func_name, sig, arg_v, $n_args, 0);
+}
+DEFN
+}
+
+sub jit_prefix_type {
+ my $type = shift;
+ if ($type !~ /[A-Z]/) {
+ return "jit_type_$_";
+ } else {
+ return "JIT_TYPE_$_";
+ }
+}
+
+1;
+
+# Local Variables:
+# mode: cperl
+# cperl-indent-level: 4
+# fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4:
Added: branches/auto_libjit/config/gen/libjit/frame_builder_libjit_c.in
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/auto_libjit/config/gen/libjit/frame_builder_libjit_c.in Tue Oct 13 02:20:14 2009 (r41837)
@@ -0,0 +1,637 @@
+/*
+Copyright (C) 2008-2009, Parrot Foundation.
+$Id$
+*/
+
+/* HEADERIZER HFILE: none */
+/* HEADERIZER STOP */
+
+#include "parrot/parrot.h"
+#include "pmc/pmc_integer.h"
+#include "pmc/pmc_unmanagedstruct.h"
+#include "pmc/pmc_managedstruct.h"
+#include "frame_builder.h"
+#include "frame_builder_libjit.h"
+
+#if PARROT_HAS_LIBJIT
+
+/*
+
+=over 4
+
+=item C<void *Parrot_jit_build_call_func(PARROT_INTERP, PMC *nci, STRING *sig, void **priv)>
+
+Public interface to NCI function interface builder.
+
+=cut
+
+*/
+
+void *
+Parrot_jit_build_call_func(PARROT_INTERP, PMC *pmc, STRING *sig, void **priv) {
+ void *thunk;
+ char *sig_cstr;
+
+ sig_cstr = Parrot_str_to_cstring(interp, sig);
+ *priv = mem_sys_allocate(sizeof (struct jit_buffer_private_data));
+
+ thunk = Parrot_jit_create_thunk(interp, sig_cstr, *priv);
+
+ Parrot_str_free_cstring(sig_cstr);
+
+ return thunk;
+}
+
+/*
+
+=item C<void Parrot_jit_free_buffer(PARROT_INTERP, void *ptr, void *priv)>
+
+This is a callback to implement the proper freeing semantics. It is called by
+the ManagedStruct PMC as it is garbage collected.
+
+=cut
+
+*/
+
+void
+Parrot_jit_free_buffer(PARROT_INTERP, void *ptr, void *priv)
+{
+ struct jit_buffer_private_data *jit = (struct jit_buffer_private_data*)priv;
+ jit_context_destroy(jit->ctx);
+ mem_sys_free(jit->sig);
+ mem_sys_free(priv);
+}
+
+/*
+
+=item C<PMC *Parrot_jit_clone_buffer(PARROT_INTERP, PMC *pmc, void *priv)>
+
+This is a callback to implement the proper cloning semantics for jit buffers.
+It is called by the ManagedStruct PMC's clone() function.
+
+=back
+
+=cut
+
+*/
+
+PMC *
+Parrot_jit_clone_buffer(PARROT_INTERP, PMC *pmc, void *priv)
+{
+ PMC * const rv = pmc_new(interp, pmc->vtable->base_type);
+
+ VTABLE_init(interp, rv);
+ /* copy the attributes */
+ {
+ void (*tmpfreefunc)(PARROT_INTERP, void*, void*);
+ GETATTR_ManagedStruct_custom_free_func(interp, pmc, tmpfreefunc);
+ SETATTR_ManagedStruct_custom_free_func(interp, rv , tmpfreefunc);
+ }
+ {
+ PMC* (*tmpclonefunc)(PARROT_INTERP, PMC*, void*);
+ GETATTR_ManagedStruct_custom_clone_func(interp, pmc, tmpclonefunc);
+ SETATTR_ManagedStruct_custom_clone_func(interp, rv , tmpclonefunc);
+ }
+
+ /* compile a clone of the function */
+ if (PARROT_MANAGEDSTRUCT(pmc)->ptr) {
+ void *rv_priv;
+ struct jit_buffer_private_data *jit = (struct jit_buffer_private_data*)priv;
+ STRING *sig = Parrot_str_new(interp, jit->sig, 0);
+ PARROT_MANAGEDSTRUCT(rv)->ptr = Parrot_jit_build_call_func(interp, rv, sig, &rv_priv);
+ }
+
+ return rv;
+}
+
+/*
+ * JIT functions
+ */
+
+void *
+Parrot_jit_create_thunk(PARROT_INTERP, char *sig, void *priv) {
+ struct jit_buffer_private_data *p;
+ jit_function_t f;
+ jit_value_t jit_interp, jit_func;
+ jit_type_t *jit_args_t;
+ jit_value_t *jit_args_v, *jit_regs;
+
+ /* populate private data */
+ p = (struct jit_buffer_private_data*)priv;
+ p->ctx = jit_context_create();
+ p->sig = mem_sys_strdup(sig);
+
+ /* start compiling */
+ jit_context_build_start(p->ctx);
+
+ /* start JIT function */
+ {
+ jit_type_t arg_types[] = {
+ jit_type_void_ptr, /* interp */
+ jit_type_void_ptr /* nci_info */
+ };
+ jit_type_t f_sig = jit_type_create_signature(jit_abi_cdecl, jit_type_void, arg_types, 2, 1);
+ f = jit_function_create(p->ctx, f_sig);
+ }
+
+ /* get the incomming args */
+ jit_interp = jit_value_get_param(f, 0);
+ jit_func = jit__vtable_get_pointer(f, jit_interp, jit_value_get_param(f, 1));
+
+ /* get the outgoing args */
+ {
+ jit_value_t st;
+ int nargs;
+
+ {
+ jit_value_t sizeof_call_state
+ = jit_value_create_nint_constant(f, jit_type_sys_int, sizeof (call_state));
+ st = jit_insn_alloca(f, sizeof_call_state);
+ }
+
+ nargs = Parrot_jit_parse_sig_args_pre(interp, sig, f, jit_interp, st,
+ &jit_args_t, &jit_args_v, &jit_regs);
+
+ /* get the return type */
+ {
+ jit_type_t ret_t;
+ jit_value_t ret_v;
+
+ ret_t = Parrot_jit_parse_sig_ret_pre(interp, sig);
+
+ /* make the call */
+ {
+ jit_type_t jit_sig
+ = jit_type_create_signature(jit_abi_cdecl, ret_t, jit_args_t, nargs, 1);
+ ret_v = jit_insn_call_indirect(f, jit_func, jit_sig, jit_args_v, nargs, 0);
+ }
+
+ /* get the incomming return */
+ Parrot_jit_parse_sig_ret_post(interp, sig, f, jit_interp, st, ret_v);
+ }
+
+ /* clean up args */
+ Parrot_jit_parse_sig_args_post(interp, sig, nargs, f, jit_interp, jit_args_v, jit_regs);
+ }
+
+ /* end JIT function */
+ jit_insn_return(f, NULL);
+
+ /* compile to native callable func poitner */
+ jit_function_compile(f);
+ jit_context_build_end(p->ctx);
+
+ mem_sys_free(jit_args_t);
+ mem_sys_free(jit_args_v);
+ mem_sys_free(jit_regs);
+
+ return jit_function_to_closure(f);
+}
+
+int
+Parrot_jit_parse_sig_args_pre(PARROT_INTERP, char *sig, jit_function_t f,
+ jit_value_t jinterp, jit_value_t st,
+ jit_type_t **arg_types,
+ jit_value_t **arg_vals, jit_value_t **arg_regs) {
+ int nargs, nregs, i, j;
+
+ sig += 1; /* ignore return character */
+
+ nargs = strlen(sig);
+ nregs = Parrot_jit_init_pcc(sig, nargs, f, jinterp, st);
+
+ *arg_types = (jit_type_t *)mem_sys_allocate(nargs * sizeof (jit_type_t));
+ *arg_vals = (jit_value_t *)mem_sys_allocate(nargs * sizeof (jit_value_t));
+ *arg_regs = (jit_value_t *)mem_sys_allocate(nregs * sizeof (jit_value_t));
+
+ for (i = 0, j = 0; i < nargs; i++) {
+ char c;
+ jit_type_t t1;
+ jit_value_t v1, v2, v3, v4;
+ switch (c = sig[i]) {
+ case 'I':
+ t1 = JIT_TYPE_INTVAL;
+ read_int_reg:
+ (*arg_types)[i] = t1;
+ v1 = jit_value_create_nint_constant(f, jit_type_sys_int, j);
+ v2 = jit__get_nci_I(f, jinterp, st, v1);
+ (*arg_regs)[j++] = (*arg_vals)[i] = v2;
+ break;
+ case 'c':
+ t1 = jit_type_sys_char;
+ goto read_int_reg;
+ case 's':
+ t1 = jit_type_sys_short;
+ goto read_int_reg;
+ case 'i':
+ t1 = jit_type_sys_int;
+ goto read_int_reg;
+ case 'l':
+ t1 = jit_type_sys_long;
+ goto read_int_reg;
+
+ case 'N':
+ t1 = JIT_TYPE_FLOATVAL;
+ read_float_reg:
+ (*arg_types)[i] = t1;
+ v1 = jit_value_create_nint_constant(f, jit_type_sys_int, j);
+ v2 = jit__get_nci_N(f, jinterp, st, v1);
+ (*arg_regs)[j++] = (*arg_vals)[i] = v2;
+ break;
+ case 'f':
+ t1 = jit_type_sys_float;
+ goto read_float_reg;
+ case 'd':
+ t1 = jit_type_sys_double;
+ goto read_float_reg;
+
+ case 'S':
+ (*arg_types)[i] = jit_type_void_ptr;
+ v1 = jit_value_create_nint_constant(f, jit_type_sys_int, j);
+ v2 = jit__get_nci_S(f, jinterp, st, v1);
+ (*arg_regs)[j++] = (*arg_vals)[i] = v2;
+ break;
+
+ case 't':
+ (*arg_types)[i] = jit_type_void_ptr;
+ v1 = jit_value_create_nint_constant(f, jit_type_sys_int, j);
+ v2 = jit__get_nci_S(f, jinterp, st, v1);
+ (*arg_regs)[j++] = v2;
+ (*arg_vals)[i] = jit__Parrot_str_to_cstring(f, jinterp, v2);
+ break;
+
+ case 'b':
+ (*arg_types)[i] = jit_type_void_ptr;
+ v1 = jit_value_create_nint_constant(f, jit_type_sys_int, j);
+ v2 = jit__get_nci_S(f, jinterp, st, v1);
+ (*arg_regs)[j++] = v2;
+ (*arg_vals)[i] = jit__Buffer_bufstart(f, v2);
+ break;
+ case 'B':
+ (*arg_types)[i] = jit_type_void_ptr;
+ v1 = jit_value_create_nint_constant(f, jit_type_sys_int, j);
+ v2 = jit__get_nci_S(f, jinterp, st, v1);
+ (*arg_regs)[j++] = v2;
+ v3 = jit__Parrot_str_to_cstring(f, jinterp, v2);
+ jit_value_set_addressable(v3);
+ (*arg_vals)[i] = jit_insn_address_of(f, v3);
+ break;
+
+ case 'p':
+ (*arg_types)[i] = jit_type_void_ptr;
+ v1 = jit_value_create_nint_constant(f, jit_type_sys_int, j);
+ v2 = jit__get_nci_p(f, jinterp, st, v1);
+ (*arg_regs)[j++] = (*arg_vals)[i] = v2;
+ break;
+ case 'P':
+ case 'O':
+ case '@':
+ (*arg_types)[i] = jit_type_void_ptr;
+ v1 = jit_value_create_nint_constant(f, jit_type_sys_int, j);
+ v2 = jit__get_nci_P(f, jinterp, st, v1);
+ (*arg_regs)[j++] = (*arg_vals)[i] = v2;
+ break;
+ case '2':
+ t1 = jit_type_sys_short;
+ goto call_get_integer;
+ case '3':
+ t1 = jit_type_sys_int;
+ goto call_get_integer;
+ case '4':
+ t1 = jit_type_sys_long;
+ call_get_integer:
+ (*arg_types)[i] = jit_type_void_ptr;
+ v1 = jit_value_create_nint_constant(f, jit_type_sys_int, j);
+ v2 = jit__get_nci_P(f, jinterp, st, v1);
+ (*arg_regs)[j++] = v2;
+ v3 = jit__vtable_get_integer(f, jinterp, v2);
+ v4 = jit_value_create(f, t1);
+ jit_value_set_addressable(v4);
+ jit_insn_store(f, v4, v3);
+ (*arg_vals)[i] = jit_insn_address_of(f, v4);
+ break;
+
+ case 'V':
+ (*arg_types)[i] = jit_type_void_ptr;
+ v1 = jit_value_create_nint_constant(f, jit_type_sys_int, j);
+ v2 = jit__get_nci_P(f, jinterp, st, v1);
+ (*arg_regs)[j++] = v2;
+ v3 = jit__vtable_get_pointer(f, jinterp, v2);
+ v4 = jit_value_create(f, jit_type_void_ptr);
+ jit_value_set_addressable(v4);
+ jit_insn_store(f, v4, v3);
+ (*arg_vals)[i] = jit_insn_address_of(f, v4);
+ break;
+
+ case '0':
+ (*arg_types)[i] = jit_type_void_ptr;
+ (*arg_vals)[i] = jit_value_create_nint_constant(f, jit_type_void_ptr, (jit_nint)NULL);
+ break;
+
+ case 'J':
+ (*arg_types)[i] = jit_type_void_ptr;
+ (*arg_vals)[i] = jinterp;
+ break;
+
+ case 'U':
+ /* TODO */
+ Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,
+ "arg type 'U' not yet implemented");
+ return -1;
+
+ default:
+ Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,
+ "unkown arg type '%c'", c);
+ return -1;
+ }
+ }
+
+ return nargs;
+}
+
+int
+Parrot_jit_init_pcc(char *sig, int nargs, jit_function_t f, jit_value_t interp, jit_value_t st) {
+ int i, j;
+ char pcc_sig[nargs];
+
+ for (i = 0, j = 0; i < nargs; i++) {
+ switch (sig[i]) {
+ case 'I':
+ case 'c':
+ case 's':
+ case 'i':
+ case 'l':
+ pcc_sig[j++] = 'I';
+ break;
+
+ case 'N':
+ case 'f':
+ case 'd':
+ pcc_sig[j++] = 'N';
+ break;
+
+ case 'S':
+ case 't':
+ case 'b':
+ case 'B':
+ pcc_sig[j++] = 'S';
+ break;
+
+ case 'p':
+ case 'P':
+ case 'O':
+ case 'V':
+ case '2':
+ case '3':
+ case '4':
+ pcc_sig[j++] = 'P';
+ break;
+
+ case '@':
+ pcc_sig[j++] = '@';
+ break;
+
+ default:
+ break;
+ }
+ }
+ pcc_sig[j] = '\0';
+
+ jit__Parrot_init_arg_nci(f, interp, st,
+ jit_value_create_string_constant(f, pcc_sig, j+1));
+
+ return j;
+}
+
+jit_type_t
+Parrot_jit_parse_sig_ret_pre(PARROT_INTERP, char *sig) {
+ char c;
+ switch (c = sig[0]) {
+ case 'v':
+ return jit_type_void;
+
+ case 'I':
+ return JIT_TYPE_INTVAL;
+ case 'c':
+ return jit_type_sys_char;
+ case 's':
+ return jit_type_sys_short;
+ case 'i':
+ return jit_type_sys_int;
+ case 'l':
+ return jit_type_sys_long;
+
+ case 'N':
+ return JIT_TYPE_FLOATVAL;
+ case 'f':
+ return jit_type_sys_float;
+ case 'd':
+ return jit_type_sys_double;
+
+ case 'S':
+ case 't':
+ return jit_type_void_ptr;
+
+ case 'p':
+ case 'P':
+ return jit_type_void_ptr;
+
+ case 'U':
+ /* TODO */
+ Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,
+ "return type 'U' not yet implemented");
+ return NULL;
+ default:
+ /* FAIL */
+ Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,
+ "unknown return type '%c'", c);
+ return NULL;
+ }
+}
+
+void
+Parrot_jit_parse_sig_ret_post(PARROT_INTERP, char *sig,
+ jit_function_t f, jit_value_t jinterp, jit_value_t st,
+ jit_value_t retval) {
+ jit_type_t t1;
+ jit_value_t v1, v2, v3;
+ switch (sig[0]) {
+ case 'v':
+ break;
+
+ case 'I':
+ case 'c':
+ case 's':
+ case 'i':
+ case 'l':
+ jit__set_nci_I(f, jinterp, st, retval);
+ break;
+
+ case 'N':
+ case 'f':
+ case 'd':
+ jit__set_nci_N(f, jinterp, st, retval);
+ break;
+
+ case 'S':
+ jit__set_nci_S(f, jinterp, st, retval);
+ break;
+ case 't':
+ v1 = jit_value_create_nint_constant(f, jit_type_sys_int, 0);
+ v2 = jit__Parrot_str_new(f, jinterp, retval, v1);
+ jit__set_nci_S(f, jinterp, st, v2);
+ break;
+
+ case 'P':
+ jit__set_nci_P(f, jinterp, st, retval);
+ break;
+ case 'p':
+ v1 = jit_value_create_intval_constant(f, enum_class_UnManagedStruct);
+ v2 = jit__pmc_new_noinit(f, jinterp, v1);
+ jit__vtable_set_pointer(f, jinterp, v2, retval);
+ jit__set_nci_P(f, jinterp, st, v2);
+ break;
+ case '2':
+ t1 = jit_type_sys_short;
+ goto create_int_pmc;
+ case '3':
+ t1 = jit_type_sys_int;
+ goto create_int_pmc;
+ case '4':
+ t1 = jit_type_sys_long;
+ create_int_pmc:
+ v1 = jit_insn_load_relative(f, retval, 0, t1);
+ v2 = jit_value_create_intval_constant(f, enum_class_Integer);
+ v3 = jit__pmc_new_noinit(f, jinterp, v2);
+ jit__vtable_set_integer_native(f, jinterp, v3, v1);
+ jit__set_nci_P(f, jinterp, st, v3);
+ break;
+
+ case 'U':
+ /* ignore (failed elsewhere) */
+ break;
+
+ default:
+ /* ignore (failed elsewhere) */
+ break;
+ }
+}
+
+void
+Parrot_jit_parse_sig_args_post(PARROT_INTERP, char *sig, int nargs,
+ jit_function_t f, jit_value_t jinterp,
+ jit_value_t *args, jit_value_t *regs) {
+ int i, j;
+
+ sig += 1;
+
+ for (i = 0, j = 0; i < nargs; i++) {
+ jit_type_t t1;
+ jit_value_t v1;
+ switch (sig[i]) {
+ case 't':
+ jit__Parrot_str_free_cstring(f, args[i]);
+ j++;
+ break;
+
+ case 'B':
+ v1 = jit_insn_load_relative(f, args[i], 0, jit_type_void_ptr);
+ jit__Parrot_str_free_cstring(f, v1);
+ j++;
+ break;
+
+ case '2':
+ t1 = jit_type_sys_short;
+ goto set_integer;
+ case '3':
+ t1 = jit_type_sys_int;
+ goto set_integer;
+ case '4':
+ t1 = jit_type_sys_long;
+ set_integer:
+ v1 = jit_insn_load_relative(f, args[i], 0, t1);
+ jit__vtable_set_integer_native(f, jinterp, regs[j], v1);
+ j++;
+ break;
+
+ case 'V':
+ v1 = jit_insn_load_relative(f, args[i], 0, jit_type_void_ptr);
+ jit__vtable_set_pointer(f, jinterp, regs[j], v1);
+ j++;
+ break;
+
+ case 'I':
+ case 'c':
+ case 'i':
+ case 'l':
+ case 'N':
+ case 'f':
+ case 'd':
+ case 'S':
+ case 'b':
+ case 'p':
+ case 'P':
+ case 'O':
+ case '@':
+ j++;
+ break;
+
+ case 'U':
+ /* TODO */
+ break;
+ default:
+ /* ignore */
+ break;
+ }
+ }
+}
+
+jit_value_t
+jit_value_create_intval_constant(jit_function_t f, INTVAL i) {
+ return jit_value_create_nint_constant(f, JIT_TYPE_INTVAL, i);
+}
+
+jit_value_t
+jit_value_create_string_constant(jit_function_t f, char *str, int len) {
+ jit_value_t jit_len, jit_str;
+ int i;
+
+ if (len < 1) {
+ len = strlen(str);
+ }
+
+ jit_len = jit_value_create_nint_constant(f, jit_type_sys_int, len);
+ jit_str = jit_insn_alloca(f, jit_len);
+
+ for (i = 0; i < len; i++) {
+ jit_value_t c = jit_value_create_nint_constant(f, jit_type_sys_char, str[i]);
+ jit_insn_store_relative(f, jit_str, i, c);
+ }
+
+ return jit_str;
+}
+
+/*
+ * JIT wrappers
+ */
+
+/* custom wrappers */
+jit_value_t
+jit__Buffer_bufstart(jit_function_t f, jit_value_t buf) {
+ return jit_insn_load_relative(f, buf, offsetof(Buffer, _bufstart), jit_type_void_ptr);
+}
+
+/* vtable wrappers */
+ at TEMP_vtable_wrap_defns@
+
+/* function wrappers */
+ at TEMP_func_wrap_defns@
+
+#endif /* PARROT_HAS_LIBJIT */
+
+/*
+ * Local variables:
+ * c-file-style: "parrot"
+ * End:
+ * vim: expandtab shiftwidth=4:
+ */
Added: branches/auto_libjit/config/gen/libjit/frame_builder_libjit_h.in
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/auto_libjit/config/gen/libjit/frame_builder_libjit_h.in Tue Oct 13 02:20:14 2009 (r41837)
@@ -0,0 +1,91 @@
+/* frame_builder_libjit.h
+ * $Id$
+ * Copyright (C) 2009, Parrot Foundation.
+ */
+
+#ifndef PARROT_FRAME_BUILDER_LIBJIT_H_GUARD
+#define PARROT_FRAME_BUILDER_LIBJIT_H_GUARD
+
+
+#if defined(__cplusplus)
+# define EXTERN extern "C"
+#else
+# define EXTERN
+#endif
+
+#include <assert.h>
+#include "parrot/parrot.h"
+#include "frame_builder.h"
+
+#if PARROT_HAS_LIBJIT
+
+#include <jit/jit.h>
+
+/*
+ * JITted function state data
+ */
+struct jit_buffer_private_data {
+ jit_context_t ctx;
+ char *sig;
+};
+
+/*
+ * JIT types
+ */
+
+#define JIT_TYPE_UINTVAL @libjit_uv@ // jit_type_sys_ulong
+#define JIT_TYPE_INTVAL @libjit_iv@ // jit_type_sys_long
+#define JIT_TYPE_FLOATVAL @libjit_nv@ // jit_type_sys_double
+
+/*
+ * JIT functions
+ */
+
+void *
+Parrot_jit_create_thunk(Interp *, char *, void *);
+
+int
+Parrot_jit_parse_sig_args_pre(Interp *, char *, jit_function_t, jit_value_t, jit_value_t,
+ jit_type_t **, jit_value_t **, jit_value_t **);
+
+int
+Parrot_jit_init_pcc(char *, int, jit_function_t, jit_value_t, jit_value_t);
+
+jit_type_t
+Parrot_jit_parse_sig_ret_pre(Interp *, char *);
+
+void
+Parrot_jit_parse_sig_ret_post(Interp *, char *, jit_function_t, jit_value_t, jit_value_t, jit_value_t);
+
+void
+Parrot_jit_parse_sig_args_post(Interp *, char *, int, jit_function_t, jit_value_t, jit_value_t *, jit_value_t *);
+
+jit_value_t
+jit_value_create_intval_constant(jit_function_t, INTVAL);
+
+jit_value_t
+jit_value_create_string_constant(jit_function_t, char *, int);
+
+/*
+ * JIT wrappers
+ */
+
+/* custom wrappers */
+jit_value_t
+jit__Buffer_bufstart(jit_function_t, jit_value_t);
+
+/* vtable wrappers */
+ at TEMP_vtable_wrap_decls@
+
+/* function wrappers */
+ at TEMP_func_wrap_decls@
+
+#endif /* PARROT_HAS_LIBJIT */
+#endif /* PARROT_FRAME_BUILDER_LIBJIT_H_GUARD */
+
+/*
+ * Local variables:
+ * c-file-style: "parrot"
+ * End:
+ * vim: expandtab shiftwidth=4:
+ */
Modified: branches/auto_libjit/config/gen/makefiles/root.in
==============================================================================
--- branches/auto_libjit/config/gen/makefiles/root.in Tue Oct 13 01:44:21 2009 (r41836)
+++ branches/auto_libjit/config/gen/makefiles/root.in Tue Oct 13 02:20:14 2009 (r41837)
@@ -217,6 +217,8 @@
myconfig \
$(GEN_PASM_INCLUDES) \
$(SRC_DIR)/call_list.txt \
+ $(SRC_DIR)/frame_builder_libjit.h \
+ $(SRC_DIR)/frame_builder_libjit.c \
MANIFEST.configure.generated \
.configure_trace.sto \
.parrot_current_rev
@@ -440,6 +442,7 @@
$(SRC_DIR)/misc$(O) \
$(SRC_DIR)/multidispatch$(O) \
$(SRC_DIR)/frame_builder$(O) \
+ $(SRC_DIR)/frame_builder_libjit$(O) \
$(SRC_DIR)/nci$(O) \
$(SRC_DIR)/oo$(O) \
$(SRC_DIR)/packfile$(O) \
@@ -622,6 +625,7 @@
$(SRC_DIR)/library.str \
$(SRC_DIR)/multidispatch.str \
$(SRC_DIR)/frame_builder.str \
+ $(SRC_DIR)/frame_builder_libjit.str \
$(SRC_DIR)/nci.str \
$(SRC_DIR)/packfile.str \
$(SRC_DIR)/pmc.str \
@@ -1191,11 +1195,26 @@
$(SRC_DIR)/nci$(O) : $(GENERAL_H_FILES) $(SRC_DIR)/nci.c $(SRC_DIR)/nci.str \
$(SRC_DIR)/frame_builder$(O) \
+ $(SRC_DIR)/frame_builder_libjit$(O) \
$(SRC_DIR)/pmc/pmc_managedstruct.h \
$(SRC_DIR)/pmc/pmc_nci.h \
$(SRC_DIR)/pmc/pmc_pointer.h
-$(SRC_DIR)/frame_builder$(O) : $(SRC_DIR)/frame_builder.h $(GENERAL_H_FILES) $(SRC_DIR)/frame_builder.c $(SRC_DIR)/frame_builder.str
+$(SRC_DIR)/frame_builder$(O) : \
+ $(SRC_DIR)/frame_builder.h \
+ $(SRC_DIR)/frame_builder.c \
+ $(SRC_DIR)/frame_builder.str \
+ $(INC_DIR)/parrot.h
+
+$(SRC_DIR)/frame_builder_libjit$(O) : \
+ $(SRC_DIR)/frame_builder_libjit.h \
+ $(SRC_DIR)/frame_builder_libjit.c \
+ $(SRC_DIR)/frame_builder_libjit.str \
+ $(SRC_DIR)/frame_builder.h \
+ $(SRC_DIR)/pmc/pmc_integer.h \
+ $(SRC_DIR)/pmc/pmc_unmanagedstruct.h \
+ $(SRC_DIR)/pmc/pmc_managedstruct.h \
+ $(INC_DIR)/parrot.h
$(SRC_DIR)/vtables$(O) : $(GENERAL_H_FILES) $(SRC_DIR)/vtables.c
Modified: branches/auto_libjit/lib/Parrot/Configure/Options/Conf.pm
==============================================================================
--- branches/auto_libjit/lib/Parrot/Configure/Options/Conf.pm Tue Oct 13 01:44:21 2009 (r41836)
+++ branches/auto_libjit/lib/Parrot/Configure/Options/Conf.pm Tue Oct 13 02:20:14 2009 (r41837)
@@ -105,6 +105,7 @@
--without-gmp Build parrot without GMP support
--without-opengl Build parrot without OpenGL support (GL/GLU/GLUT)
--without-pcre Build parrot without pcre support
+ --without-libjit Build parrot without LibJIT support
ICU Options:
Modified: branches/auto_libjit/lib/Parrot/Configure/Options/Conf/Shared.pm
==============================================================================
--- branches/auto_libjit/lib/Parrot/Configure/Options/Conf/Shared.pm Tue Oct 13 01:44:21 2009 (r41836)
+++ branches/auto_libjit/lib/Parrot/Configure/Options/Conf/Shared.pm Tue Oct 13 02:20:14 2009 (r41837)
@@ -75,6 +75,7 @@
without-gettext
without-gmp
without-icu
+ without-libjit
without-opengl
without-pcre
without-threads
Modified: branches/auto_libjit/lib/Parrot/Configure/Step/List.pm
==============================================================================
--- branches/auto_libjit/lib/Parrot/Configure/Step/List.pm Tue Oct 13 01:44:21 2009 (r41836)
+++ branches/auto_libjit/lib/Parrot/Configure/Step/List.pm Tue Oct 13 02:20:14 2009 (r41837)
@@ -64,17 +64,23 @@
auto::ctags
auto::revision
auto::icu
+ auto::libjit
gen::config_h
gen::core_pmcs
gen::crypto
gen::parrot_include
gen::opengl
gen::call_list
+ gen::libjit
gen::makefiles
gen::platform
gen::config_pm
);
+=pod
+
+=cut
+
sub get_steps_list { return @steps; }
1;
Modified: branches/auto_libjit/src/frame_builder.c
==============================================================================
--- branches/auto_libjit/src/frame_builder.c Tue Oct 13 01:44:21 2009 (r41836)
+++ branches/auto_libjit/src/frame_builder.c Tue Oct 13 02:20:14 2009 (r41837)
@@ -7,99 +7,8 @@
/* HEADERIZER STOP */
#include "parrot/parrot.h"
-#include "pmc/pmc_fixedintegerarray.h"
-#include "pmc/pmc_unmanagedstruct.h"
-#include "pmc/pmc_managedstruct.h"
#include "frame_builder.h"
-/*
-
-=over 4
-
-=item C<void Parrot_jit_free_buffer(PARROT_INTERP, void *ptr, void *priv)>
-
-This is a callback to implement the proper freeing semantics. It is called by
-the ManagedStruct PMC as it is garbage collected.
-
-=cut
-
-*/
-
-void
-Parrot_jit_free_buffer(PARROT_INTERP, void *ptr, void *priv)
-{
- const struct jit_buffer_private_data * const jit = (struct jit_buffer_private_data*)priv;
- mem_free_executable(ptr, jit->size);
- free(priv);
-}
-
-/*
-
-=item C<PMC *Parrot_jit_clone_buffer(PARROT_INTERP, PMC *pmc, void *priv)>
-
-This is a callback to implement the proper cloning semantics for jit buffers.
-It is called by the ManagedStruct PMC's clone() function.
-
-=back
-
-=cut
-
-*/
-
-PMC *
-Parrot_jit_clone_buffer(PARROT_INTERP, PMC *pmc, void *priv)
-{
- PMC * const rv = pmc_new(interp, pmc->vtable->base_type);
-
- VTABLE_init(interp, rv);
- /* copy the attributes */
- {
- void (*tmpfreefunc)(PARROT_INTERP, void*, void*);
- GETATTR_ManagedStruct_custom_free_func(interp, pmc, tmpfreefunc);
- SETATTR_ManagedStruct_custom_free_func(interp, rv , tmpfreefunc);
- }
- {
- PMC* (*tmpclonefunc)(PARROT_INTERP, PMC*, void*);
- GETATTR_ManagedStruct_custom_clone_func(interp, pmc, tmpclonefunc);
- SETATTR_ManagedStruct_custom_clone_func(interp, rv , tmpclonefunc);
- }
-
- {
- void *freepriv, *clonepriv;
- GETATTR_ManagedStruct_custom_free_priv(interp , pmc, freepriv);
- GETATTR_ManagedStruct_custom_clone_priv(interp, pmc, clonepriv);
- if (freepriv) {
- void *tmp = mem_sys_allocate(sizeof (struct jit_buffer_private_data));
- memcpy(tmp, freepriv, sizeof (struct jit_buffer_private_data));
- SETATTR_ManagedStruct_custom_free_priv(interp, rv , tmp);
- if (clonepriv == freepriv) {
- /* clonepriv is a copy of freepriv, make it a copy in the clone too. */
- SETATTR_ManagedStruct_custom_clone_priv(interp, rv , tmp);
- clonepriv = NULL; /* disable the clonepriv copying below */
- }
- }
- if (clonepriv) {
- void *tmp = mem_sys_allocate(sizeof (struct jit_buffer_private_data));
- memcpy(tmp, clonepriv, sizeof (struct jit_buffer_private_data));
- SETATTR_ManagedStruct_custom_clone_priv(interp, rv , tmp);
- }
- }
-
- /* copy the execmem buffer */
- if (PARROT_MANAGEDSTRUCT(pmc)->ptr) {
- struct jit_buffer_private_data *jit = (struct jit_buffer_private_data*)priv;
- void *ptr = PARROT_MANAGEDSTRUCT(pmc)->ptr;
- void *newptr = mem_alloc_executable(jit->size);
- if (!newptr)
- Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,
- "Cannot allocate executable memory");
- memcpy(newptr, ptr, jit->size);
- PARROT_MANAGEDSTRUCT(rv)->ptr = newptr;
- }
-
- return rv;
-}
-
INTVAL
get_nci_I(PARROT_INTERP, ARGMOD(call_state *st), int n)
{
@@ -224,514 +133,6 @@
}
}
-int
-emit_is8bit(long disp)
-{
- return disp >= -128 && disp <= 127;
-}
-
-char *
-emit_disp8_32(char *pc, int disp)
-{
- if (emit_is8bit(disp)) {
- *(pc++) = (char)disp;
- return pc;
- }
- else {
- *(long *)pc = disp;
- return pc + 4;
- }
-}
-
-void
-emit_sib(PARROT_INTERP, char *pc, int scale, int i, int base)
-{
- int scale_byte;
-
- switch (scale) {
- case 1:
- scale_byte = emit_Scale_1;
- break;
- case 2:
- scale_byte = emit_Scale_2;
- break;
- case 4:
- scale_byte = emit_Scale_4;
- break;
- case 8:
- scale_byte = emit_Scale_8;
- break;
- default:
- Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,
- "Invalid scale factor %d\n", scale);
- return;
- }
-
- *pc = (char)(scale_byte | (i == emit_None ? emit_Index_None : emit_reg_Index(i)) |
- emit_reg_Base(base));
-}
-
-char *
-emit_r_X(PARROT_INTERP, char *pc, int reg_opcode, int base, int i, int scale, long disp)
-{
- if (i && !scale)
- Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,
- "emit_r_X passed invalid scale+index combo\n");
-
- if (base == emit_EBP) {
- /* modrm disp */
- if (i == emit_None) {
- *(pc++) = (char)((emit_is8bit(disp) ? emit_Mod_b01 : emit_Mod_b10)
- | reg_opcode | emit_reg_rm(emit_EBP));
- return emit_disp8_32(pc, disp);
- }
- /* modrm sib disp */
- else {
- *(pc++) = (char)((emit_is8bit(disp) ? emit_Mod_b01 : emit_Mod_b10)
- | reg_opcode | emit_b100);
- emit_sib(interp, pc++, scale, i, base);
- return emit_disp8_32(pc, disp);
- }
- }
-
- /* modrm sib disp */
- if (base == emit_ESP) {
- *(pc++) = (char)((emit_is8bit(disp) ? emit_Mod_b01 : emit_Mod_b10)
- | reg_opcode | emit_rm_b100);
- emit_sib(interp, pc++, scale, i, emit_ESP);
- return emit_disp8_32(pc, disp);
- }
-
- /* modrm disp32 */
- if (!base && !(i && scale)) {
- *(pc++) = (char)(emit_Mod_b00 | reg_opcode | emit_rm_b101);
- *(long *)pc = disp;
- return pc + 4;
- }
-
- /* Ok, everything should be more regular here */
- *(pc++) = (char)((disp == 0 ? emit_Mod_b00 :
- (emit_is8bit(disp) ?
- emit_Mod_b01 : emit_Mod_b10)) |
- reg_opcode |
- (!base || (scale && i) ? emit_rm_b100 : emit_reg_rm(base)));
-
- if (!base || (scale && i)) {
- emit_sib(interp, pc++, scale, i, base);
- }
- if (disp)
- pc = emit_disp8_32(pc, disp);
-
- return pc;
-}
-
-char *
-emit_shift_i_r(PARROT_INTERP, char *pc, int opcode, int imm, int reg)
-{
- if (opcode == emit_b000 && imm < 0) {
- opcode = emit_b001; /* -rol => 32 + ror */
- imm = -imm;
- }
-
- if (imm == 0) {
- /* noop */
- }
- else if (imm == 1) {
- *(pc++) = (char) 0xd1;
- *(pc++) = (char) emit_alu_X_r(opcode, reg);
- }
- else if (imm > 1 && imm < 33) {
- *(pc++) = (char) 0xc1;
- *(pc++) = (char) emit_alu_X_r(opcode, reg);
- *(pc++) = (char)imm;
- }
- else {
- Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,
- "emit_shift_i_r passed invalid shift\n");
- }
-
- return pc;
-}
-
-char *
-emit_popl_r(char *pc, int reg)
-{
- *(pc++) = (char)(0x58 | (reg - 1));
- return pc;
-}
-
-unsigned char *lastpc;
-
-size_t
-calc_signature_needs(const char *sig, int *strings)
-{
- size_t stack_size = 0;
- while (*sig) {
- switch (*sig) {
- case 't':
- (*strings)++;
- stack_size +=4;
- break;
- case 'd':
- stack_size +=8;
- break;
- default:
- stack_size +=4;
- break;
- }
- sig++;
- }
- return stack_size;
-
-}
-
-/*
- * The function generated here is called as func(interp, nci_info)
- * interp ... 8(%ebp)
- * nci_info ... 12(%ebp)
- *
- * The generate function for a specific signature looks quite similar to
- * an optimized compile of src/nci.c:pcf_x_yy(). In case of any troubles
- * just compare the disassembly.
- *
- * If a non-NULL sizeptr is passed, the integer it points to will be written
- * with the size of the allocated execmem buffer.
- */
-
-void *
-Parrot_jit_build_call_func(PARROT_INTERP, PMC *pmc_nci, STRING *signature, int *sizeptr)
-{
- char *pc;
- char *execmem;
- int i = 0;
- int arg_count = 0;
- int string_buffer_count = 0;
- const int ST_SIZE_OF = 124;
- const int JIT_ALLOC_SIZE = 1024;
-
- char *signature_str = Parrot_str_to_cstring(interp, signature);
- /* skip over the result */
- char *sig = signature_str + 1;
- size_t stack_space_needed = calc_signature_needs(sig,
- &string_buffer_count);
-
- int base_offset = 0;
- int strings_offset = base_offset - (sizeof (char *) * string_buffer_count);
- int st_offset = strings_offset - ST_SIZE_OF;
- int args_offset = st_offset - stack_space_needed;
- int temp_calls_offset = args_offset - 16;
- int total_stack_needed = -temp_calls_offset;
-
- /*
- * ESP
- * 0-15, 16 bytes for utility calls
- * stack_space_needed for actual NCI call
- * st
- * STRINGS -> char * holding space
- * EBP
- */
-
- /* this ought to be enough - the caller of this function
- * should free the function pointer returned here
- */
- pc = execmem = (char *)mem_alloc_executable(JIT_ALLOC_SIZE);
- if (! pc)
- Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,
- "Cannot allocate executable memory");
-
-
- /* this generated jit function will be called as (INTERP (EBP 8), func_ptr
- * (ESP 12), args signature (ESP 16)) */
-
- /* make stack frame, preserve %ebx */
- jit_emit_stack_frame_enter(pc);
-
- emitm_subl_i_r(pc, total_stack_needed, emit_ESP);
-
- /* Parrot_init_arg_nci(interp, &st, "S"); */
- /* args signature "S" */
- emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 16);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
-
- /*&st*/
- emitm_lea_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, st_offset);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);
-
- /*interpreter*/
- emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 8);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 0);
-
- if (sig && *sig)
- emitm_call_cfunc(pc, Parrot_init_arg_nci);
-
- while (*sig) {
- emitm_movl_i_m(pc, arg_count, emit_EBP, 0, 1, temp_calls_offset + 8);
-
- switch (*sig) {
- case '0': /* null ptr or such - doesn't consume a reg */
- jit_emit_bxor_rr_i(interp, pc, emit_EAX, emit_EAX);
- emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
- break;
- case 'f':
- emitm_call_cfunc(pc, get_nci_N);
- emitm_fstps(interp, pc, emit_EBP, 0, 1, args_offset);
- break;
- case 'N':
- case 'd':
- emitm_call_cfunc(pc, get_nci_N);
- emitm_fstpl(interp, pc, emit_EBP, 0, 1, args_offset);
- args_offset += 4;
- break;
- case 'I': /* INTVAL */
- case 'l': /* long */
- case 'i': /* int */
- emitm_call_cfunc(pc, get_nci_I);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
- break;
- case 't': /* string, pass a cstring */
- emitm_call_cfunc(pc, get_nci_S);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);
- emitm_call_cfunc(pc, string_to_cstring_nullable);
-
- emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
- /* save off temporary allocation address */
- emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, strings_offset);
- strings_offset += 4;
-
- /* reset ESP(4) */
- emitm_lea_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, st_offset);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);
- break;
- case 's': /* short: movswl intreg_o(base), %eax */
- emitm_call_cfunc(pc, get_nci_I);
- emitm_movswl_r_r(pc, emit_EAX, emit_EAX);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
- break;
- case 'c': /* char: movsbl intreg_o(base), %eax */
- emitm_call_cfunc(pc, get_nci_I);
- emitm_movsbl_r_r(pc, emit_EAX, emit_EAX);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
- break;
- case 'J': /* interpreter */
- emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 8);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
- arg_count--;
- break;
- case 'p': /* push pmc->data */
- emitm_call_cfunc(pc, get_nci_p);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
- break;
- case 'O': /* push PMC * object in P2 */
- case 'P': /* push PMC * */
- case '@':
- emitm_call_cfunc(pc, get_nci_P);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
- break;
- case 'v':
- break;
- case 'b': /* buffer (void*) pass Buffer_bufstart(SReg) */
- emitm_call_cfunc(pc, get_nci_S);
- emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1,
- (size_t) &Buffer_bufstart((STRING *) NULL));
- emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
- break;
- case 'B': /* buffer (void**) pass &Buffer_bufstart(SReg) */
- emitm_call_cfunc(pc, get_nci_S);
- emitm_lea_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1,
- (size_t) &Buffer_bufstart((STRING *) NULL));
- emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
- break;
- case 'S':
- emitm_call_cfunc(pc, get_nci_S);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
- break;
-
-
- /* I have no idea how to handle these */
- case '2':
- case '3':
- case '4':
- case 'V':
- mem_free_executable(execmem, JIT_ALLOC_SIZE);
- Parrot_str_free_cstring(signature_str);
- return NULL;
- break;
- default:
- Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,
- "Unknown arg Signature %c\n", *sig);
- /*
- * oops unknown signature:
- * cleanup and try nci.c
- */
- mem_free_executable(execmem, JIT_ALLOC_SIZE);
- Parrot_str_free_cstring(signature_str);
- return NULL;
- }
- args_offset +=4;
- arg_count++;
- sig++;
- }
-
- /* prepare to call VTABLE_get_pointer, set up args */
- /* interpreter - movl 8(%ebp), %eax */
- emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 8);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 0);
-
- /* pmc - movl 12(%ebp), %eax */
- emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 12);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);
-
- /* get the get_pointer() pointer from the pmc's vtable */
- emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(PMC, vtable));
- emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(VTABLE, get_pointer));
-
- /* call get_pointer(), result goes into eax */
- emitm_callr(pc, emit_EAX);
- emitm_addl_i_r(pc, 16, emit_ESP);
-
- /* call the resulting function pointer */
- emitm_callr(pc, emit_EAX);
- emitm_subl_i_r(pc, 16, emit_ESP);
-
- /* SAVE OFF EAX */
- emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
-
- /*&st*/
- emitm_lea_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, st_offset);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);
-
- /*interpreter*/
- emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 8);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 0);
-
- /* RESTORE BACK EAX */
- emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
-
- /* now place return value in registers */
- /* first in signature is the return value */
- sig = signature_str; /* the result */
- switch (*sig) {
- /* I have no idea how to handle these */
- case '2':
- case '3':
- case '4':
- /* get integer from pointer - untested */
- emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, 0);
- if (*sig == 2) /* short */
- emitm_movswl_r_r(pc, emit_EAX, emit_EAX);
- emitm_call_cfunc(pc, set_nci_I);
- break;
- case 'f':
- case 'd':
- jit_emit_fstore_mb_n(interp, pc, emit_EBP, temp_calls_offset + 8);
- emitm_call_cfunc(pc, set_nci_N);
- /* pop num from st(0) and mov to reg */
- break;
- case 's':
- /* movswl %ax, %eax */
- emitm_movswl_r_r(pc, emit_EAX, emit_EAX);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
- emitm_call_cfunc(pc, set_nci_I);
- break;
- case 'c':
- /* movsbl %al, %eax */
- emitm_movsbl_r_r(pc, emit_EAX, emit_EAX);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
- emitm_call_cfunc(pc, set_nci_I);
- break;
- case 'I': /* INTVAL */
- case 'l':
- case 'i':
- emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
- emitm_call_cfunc(pc, set_nci_I);
- break;
- case 'v': /* void - do nothing */
- break;
- case 'P':
- emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
- emitm_call_cfunc(pc, set_nci_P);
- break;
- case 'p': /* make a new unmanaged struct */
- /* save return value on stack */
-
- /* save pointer p */
- emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 12);
-
- /* make new pmc */
- emitm_movl_i_m(pc, enum_class_UnManagedStruct, emit_EBP, 0, 1, temp_calls_offset + 4);
- emitm_call_cfunc(pc, pmc_new);
-
- /* restore pointer p to EDX */
- emitm_movl_m_r(interp, pc, emit_EDX, emit_EBP, 0, 1, temp_calls_offset + 12);
-
- /* copy UnManagedStruct to stack for set_nci_P call */
- emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
-
- /* eax = PMC, get return value into edx */
- /* mov data(%eax), %eax
- mov %edx, ptr(%eax) */
- emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(struct PMC, data));
- emitm_movl_r_m(interp, pc, emit_EDX, emit_EAX, 0, 1,
- offsetof(struct Parrot_UnManagedStruct_attributes, ptr));
-
- /* reset EBP(4) */
- emitm_lea_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, st_offset);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);
-
- emitm_call_cfunc(pc, set_nci_P);
- break;
- case 'S':
- emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
- emitm_call_cfunc(pc, set_nci_S);
- break;
- case 't': /* string */
- /* EAX is char* */
- emitm_movl_i_m(pc, 0, emit_EBP, 0, 1, temp_calls_offset + 8); /* len */
-
- /* overwrites address of st in EBP(4) */
- emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);
-
- emitm_call_cfunc(pc, Parrot_str_new);
-
- emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
-
- /* reset EBP(4) */
- emitm_lea_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, st_offset);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);
-
- emitm_call_cfunc(pc, set_nci_S);
- break;
- default:
- Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,
- "Unknown return Signature %c\n", *sig);
- /*
- * oops unknown signature:
- * cleanup and try nci.c
- */
- Parrot_str_free_cstring(signature_str);
- mem_free_executable(execmem, JIT_ALLOC_SIZE);
- return NULL;
- }
-
- /* free temporary strings */
- strings_offset = st_offset + ST_SIZE_OF;
- for (i=0; i<string_buffer_count; i++) {
- emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, strings_offset);
- emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 0);
- emitm_call_cfunc(pc, Parrot_str_free_cstring);
- strings_offset += 4;
- }
-
- jit_emit_stack_frame_leave(pc);
- emitm_ret(pc);
- PARROT_ASSERT(pc - execmem <= JIT_ALLOC_SIZE);
-
- if (sizeptr)
- *sizeptr = JIT_ALLOC_SIZE;
- Parrot_str_free_cstring(signature_str);
- return (void *)D2FPTR(execmem);
-}
-
/*
* Local variables:
* c-file-style: "parrot"
Modified: branches/auto_libjit/src/frame_builder.h
==============================================================================
--- branches/auto_libjit/src/frame_builder.h Tue Oct 13 01:44:21 2009 (r41836)
+++ branches/auto_libjit/src/frame_builder.h Tue Oct 13 02:20:14 2009 (r41837)
@@ -1,17 +1,13 @@
/*
* Copyright (C) 2002-2009, Parrot Foundation.
- */
-
-/*
- * frame_builder.h
*
- * i386
+ * frame_builder.h
*
* $Id$
*/
-#ifndef PARROT_I386_JIT_EMIT_H_GUARD
-#define PARROT_I386_JIT_EMIT_H_GUARD
+#ifndef PARROT_FRAME_BUILDER_H_GUARD
+#define PARROT_FRAME_BUILDER_H_GUARD
#if defined(__cplusplus)
# define EXTERN extern "C"
@@ -21,14 +17,13 @@
#include <assert.h>
#include "parrot/parrot.h"
-#include "parrot/hash.h"
-#include "parrot/oplib/ops.h"
/*
* NCI interface
*/
+
void *
-Parrot_jit_build_call_func(Interp *, PMC *, STRING *, int *);
+Parrot_jit_build_call_func(Interp *, PMC *, STRING *, void **);
/* custom pmc callback functions */
void
@@ -37,22 +32,6 @@
PMC*
Parrot_jit_clone_buffer(PARROT_INTERP, PMC *pmc, void *priv);
-struct jit_buffer_private_data {
- int size;
-};
-
-/* Scale factor values */
-#define emit_Scale(scale) ((scale) << 6)
-#define emit_Scale_1 emit_Scale(0)
-#define emit_Scale_2 emit_Scale(1)
-#define emit_Scale_4 emit_Scale(2)
-#define emit_Scale_8 emit_Scale(3)
-
-/* ESIB byte */
-#define emit_reg_Index(x) (((x)-1) << 3)
-#define emit_reg_Base(x) ((x)-1)
-#define emit_Index_None ((emit_b100) << 3)
-
/*
* helper funcs - get argument n
*/
@@ -92,1308 +71,7 @@
void set_nci_P(PARROT_INTERP, ARGOUT(call_state *st), PMC* val);
-/*
- * if we have a delegated method like typeof_i_p, that returns an INTVAL
- * and that is all in a sequence of JITted opcodes, and when these INTVAL
- * is MAPped, we got a problem. So the EXT_CALL flag is disabled - mapped
- * registers are saved/restored around vtable calls.
- */
-#define JIT_VTABLE_OPS 1
-
-/* EXEC_SHARED generates code to be used with libparrot.so
- * It grabs the real address of cgp_core from the gcc generated code
- * x/1i cgp_code
- * jmp *0xXXXX
- * x/1wx 0xXXXX
- * real address of cpg_core
- * s. exec_emit_end
- * XXX This should be a command line option.
- */
-#undef EXEC_SHARED
-
-extern UINTVAL ld(UINTVAL);
-
-#define NEG_MINUS_ZERO
-/* #define NEG_ZERO_SUB */
-
-/* Register codes */
-#define emit_None 0
-
-/* These are + 1 the real values */
-#define emit_EAX 1
-#define emit_ECX 2
-#define emit_EDX 3
-#define emit_EBX 4
-#define emit_ESP 5
-#define emit_EBP 6
-#define emit_ESI 7
-#define emit_EDI 8
-
-/* Scratch register. */
-
-#define ISR1 emit_EAX
-#define FSR1 0
-
-#define emit_b00 0
-#define emit_b01 1
-#define emit_b10 2
-#define emit_b11 3
-
-#define emit_b000 0
-#define emit_b001 1
-#define emit_b010 2
-#define emit_b011 3
-#define emit_b100 4
-#define emit_b101 5
-#define emit_b110 6
-#define emit_b111 7
-
-/* Mod R/M byte */
-#define emit_reg(x) ((x) << 3)
-#define emit_Mod(Mod) ((Mod) << 6)
-#define emit_reg_rm(x) ((x)-1)
-
-/* Mod values for Mod R/M Byte */
-#define emit_Mod_b00 emit_Mod(emit_b00)
-#define emit_Mod_b01 emit_Mod(emit_b01)
-#define emit_Mod_b10 emit_Mod(emit_b10)
-
-/* special R/M values */
-#define emit_rm_b101 emit_b101
-#define emit_rm_b100 emit_b100
-
-#define emit_r_m(interp, pc, reg1, b, i, s, d) \
- emit_r_X((interp), (pc), emit_reg((reg1)-1), (b), (i), (s), (d))
-
-#define emit_alu_X_r(X, reg) ((emit_b11 << 6) | ((X) << 3) | ((reg) - 1))
-
-#define emit_alu_r_r(reg1, reg2) emit_alu_X_r(((reg1) - 1), (reg2))
-
-int emit_is8bit(long disp);
-
-char * emit_disp8_32(char *pc, int disp);
-
-void emit_sib(PARROT_INTERP, char *pc, int scale, int i, int base);
-
-char * emit_r_X(PARROT_INTERP, char *pc, int reg_opcode, int base, int i,
- int scale, long disp);
-
-char * emit_shift_i_r(PARROT_INTERP, char *pc, int opcode, int imm, int reg);
-
-char * emit_shift_i_m(PARROT_INTERP, char *pc, int opcode, int imm,
- int base, int i, int scale, long disp);
-
-char * emit_shift_r_r(PARROT_INTERP, char *pc, int opcode, int reg1, int reg2);
-
-char * emit_shift_r_m(PARROT_INTERP, char *pc, int opcode, int reg,
- int base, int i, int scale, long disp);
-
-/* CDQ - need this to do multiply */
-#define emitm_cdq(pc) *((pc)++) = (char) 0x99
-
-/* RET */
-#define emitm_ret(pc) *((pc)++) = (char) 0xc3
-
-/* NOP */
-#define emit_nop(pc) *((pc)++) = (char) 0x90
-
-/* PUSHes */
-
-#define emitm_pushl_r(pc, reg) \
- *((pc)++) = (char) 0x50 | ((reg) - 1)
-
-#define emitm_pushl_i(pc, imm) { \
- *((pc)++) = (char) 0x68; \
- *(long *)(pc) = (long)(imm); \
- (pc) += 4; }
-
-#define emitm_pushl_m(pc, mem) { \
- *((pc)++) = (char) 0xff; \
- *((pc)++) = (char) 0x35; \
- *(long *)(pc) = (long)(mem); \
- (pc) += 4; }
-
-char * emit_pushl_m(PARROT_INTERP, char *pc, int base, int i, int scale,
- long disp);
-
-/* POPs */
-
-char * emit_popl_r(char *pc, int reg);
-
-# define emitm_popl_r(pc, reg) \
- (pc) = emit_popl_r((pc), (reg))
-
-char * emit_popl_m(PARROT_INTERP, char *pc, int base, int i, int scale,
- long disp);
-
-/* MOVes */
-
-char * emit_movb_r_r(char *pc, int reg1, int reg2);
-
-# define jit_emit_mov_rr_i(pc, reg2, reg1) if ((reg1) != (reg2)) { \
- *((pc)++) = (char) 0x89; \
- *((pc)++) = (char) emit_alu_r_r((reg1), (reg2)); }
-
-# define jit_emit_mov_ri_i(interp, pc, reg, imm) { \
- *((pc)++) = (char)(0xb8 | ((reg) - 1)); \
- *(long *)(pc) = (long)(imm); (pc) += 4; }
-
-# define emitm_movX_Y_Z(interp, op, pc, reg1, b, i, s, d) { \
- *((pc)++) = (char) (op); \
- (pc) = emit_r_m((interp), (pc), (reg1), (b), (i), (s), (long)(d)); }
-
-# define emitm_movb_r_m(interp, pc, reg1, b, i, s, d) \
- emitm_movX_Y_Z((interp), 0x88, (pc), (reg1), (b), (i), (s), (d))
-
-# define emitm_movl_r_m(interp, pc, reg1, b, i, s, d) \
- emitm_movX_Y_Z((interp), 0x89, (pc), (reg1), (b), (i), (s), (d))
-
-/* move byte/word with sign extension */
-# define emitm_movsbl_r_m(interp, pc, reg1, b, i, s, d) { \
- *((pc)++) = (char) 0x0f; \
- emitm_movX_Y_Z((interp), 0xBE, (pc), (reg1), (b), (i), (s), (d)); \
-}
-
-# define emitm_movswl_r_m(interp, pc, reg1, b, i, s, d) { \
- *((pc)++) = (char) 0x0f; \
- emitm_movX_Y_Z((interp), 0xBF, (pc), (reg1), (b), (i), (s), (d)); \
-}
-
-# define emitm_movsbl_r_r(pc, reg1, reg2) { \
- *((pc)++) = (char) 0x0f; \
- *((pc)++) = (char) 0xbe; \
- *((pc)++) = (char) emit_alu_r_r((reg1), (reg2)); \
-}
-
-# define emitm_movswl_r_r(pc, reg1, reg2) { \
- *((pc)++) = (char) 0x0f; \
- *((pc)++) = (char) 0xbf; \
- *((pc)++) = (char) emit_alu_r_r((reg1), (reg2)); \
-}
-
-# define emitm_movb_m_r(interp, pc, reg1, b, i, s, d) \
- emitm_movX_Y_Z((interp), 0x8a, (pc), (reg1), (b), (i), (s), (d))
-
-# define emitm_movl_m_r(interp, pc, reg1, b, i, s, d) \
- emitm_movX_Y_Z((interp), 0x8b, (pc), (reg1), (b), (i), (s), (d))
-
-# define emitm_lea_m_r(interp, pc, reg1, b, i, s, d) \
- emitm_movX_Y_Z((interp), 0x8d, (pc), (reg1), (b), (i), (s), (d))
-
-char * emit_movb_i_m(PARROT_INTERP, char *pc, char imm, int base, int i,
- int scale, long disp);
-
-# define emitm_movl_i_m(pc, imm, b, i, s, d) { \
- *((pc)++) = (char) 0xc7; \
- (pc) = emit_r_X((interp), (pc), emit_reg(emit_b000), (b), (i), (s), (long)(d)); \
- *(long *)(pc) = (long)(imm); (pc) += 4; }
-
-/* Various ALU formats */
-
-# define emitm_alul_r_r(pc, op, reg1, reg2) { \
- *((pc)++) = (char) (op); *((pc)++) = (char) emit_alu_r_r((reg1), (reg2)); }
-
-# define emitm_alub_i_r(pc, op1, op2, imm, reg) { \
- *((pc)++) = (char) (op1); *((pc)++) = (char) emit_alu_X_r((op2), (reg)); *((pc)++) = (char)(imm); }
-
-# define emitm_alul_i_r(pc, op1, op2, imm, reg) { \
- *((pc)++) = (char) (op1); \
- *((pc)++) = (char) emit_alu_X_r((op2), (reg)); \
- *(long *)((pc)) = (long)(imm); (pc) += 4; }
-
-# define emitm_alul_i_m(pc, op1, op2, imm, b, i, s, d) { \
- *((pc)++) = (char) (op1); \
- (pc) = emit_r_X((interp), (pc), emit_reg(op2), (b), (i), (s), (d)); \
- *(long *)(pc) = (long)(imm); (pc) += 4; }
-
-# define emitm_alul_r_m(pc, op, reg, b, i, s, d) { \
- *((pc)++) = (char) (op); \
- (pc) = emit_r_X((interp), (pc), emit_reg((reg)-1), (b), (i), (s), (long)(d)); }
-
-/* ADDs */
-
-# define emitm_addb_r_r(pc, reg1, reg2) \
- emitm_alul_r_r((pc), 0x00, (reg1), (reg2))
-
-# define emitm_addb_i_r(pc, imm, reg) \
- emitm_alub_i_r((pc), 0x83, emit_b000, (imm), (reg))
-
-# define jit_emit_add_rr_i(interp, pc, reg1, reg2) \
- emitm_alul_r_r((pc), 0x01, (reg2), (reg1))
-
-# define jit_emit_add_ri_i(interp, pc, reg, imm) \
- emitm_alul_i_r((pc), 0x81, emit_b000, (imm), (reg))
-
-# define emitm_addl_i_r(pc, imm, reg) \
- emitm_alul_i_r((pc), 0x81, emit_b000, (imm), (reg))
-
-# define emitm_addl_i_m(pc, imm, b, i, s, d) \
- emitm_alul_i_m((pc), 0x81, emit_b000, (imm), (b), (i), (s), (d))
-
-# define emitm_addl_r_m(pc, reg, b, i, s, d) \
- emitm_alul_r_m((pc), 0x01, (reg), (b), (i), (s), (d))
-
-# define emitm_addl_m_r(pc, reg, b, i, s, d) \
- emitm_alul_r_m((pc), 0x03, (reg), (b), (i), (s), (d))
-
-/* SUBs */
-
-# define jit_emit_sub_rr_i(interp, pc, reg1, reg2) \
- emitm_alul_r_r((pc), 0x29, (reg2), (reg1))
-
-# define emitm_subl_i_r(pc, imm, reg) \
- emitm_alul_i_r((pc), 0x81, emit_b101, (imm), (reg))
-
-# define jit_emit_sub_ri_i(interp, pc, r, i) emitm_subl_i_r((pc), (i), (r))
-
-# define emitm_subl_r_m(pc, reg, b, i, s, d) \
- emitm_alul_r_m((pc), 0x29, (reg), (b), (i), (s), (d))
-
-# define emitm_subl_m_r(pc, reg, b, i, s, d) \
- emitm_alul_r_m((pc), 0x2b, (reg), (b), (i), (s), (d))
-
-# define emitm_subl_i_m(pc, imm, b, i, s, d) \
- emitm_alul_i_m((pc), 0x81, emit_b101, (imm), (b), (i), (s), (d))
-
-/* These are used by both signed and unsigned EDIV, but only unsigned MUL */
-# define emitm_alu_imp_r(pc, op, reg) { \
- *((pc)++) = (char) 0xf7; \
- *((pc)++) = (char) emit_alu_X_r((op), (reg)); }
-
-# define emitm_alu_imp_m(pc, op, b, i, s, d) { \
- *((pc)++) = (char) 0xf7; \
- (pc) = emit_r_X((interp), (pc), emit_reg(op), (b), (i), (s), (d)); }
-
-/* Unsigned MUL and EDIV */
-/* EAX implicit destination in multiply and divide */
-
-# define emitm_umull_r(pc, reg2) emitm_alu_imp_r((pc), emit_b100, (reg2))
-
-# define emitm_udivl_r(pc, reg2) emitm_alu_imp_r((pc), emit_b110, (reg2))
-
-# define emitm_umull_m(pc, b, i, s, d) \
- emitm_alu_imp_m((pc), emit_b100, (b), (i), (s), (d))
-
-# define emitm_udivl_m(pc, b, i, s, d) \
- emitm_alu_imp_m((pc), emit_b110, (b), (i), (s), (d))
-
-/* Signed MUL and EDIV */
-
-# define emitm_sdivl_r(pc, reg2) emitm_alu_imp_r((pc), emit_b111, (reg2))
-
-# define emitm_sdivl_m(pc, b, i, s, d) \
- emitm_alu_imp_m((pc), emit_b111, (b), (i), (s), (d))
-
-# define jit_emit_cdq(pc) *(pc)++ = 0x99
-
-/* TEST for zero */
-# define jit_emit_test_r_i(pc, reg1) emitm_alul_r_r((pc), 0x85, (reg1), (reg1))
-
-# define emitm_smull_r(pc, reg2) emitm_alu_imp_r((pc), emit_b101, (reg2))
-
-# define jit_emit_mul_rr_i(interp, pc, reg1, reg2) { \
- *(pc)++ = 0xf; \
- emitm_alul_r_r((pc), 0xaf, (reg1), (reg2)); }
-
-# define emitm_smull_r_m(pc, reg1, b, i, s, d) { \
- *(pc)++ = 0xf; \
- emitm_alul_r_m((pc), 0xaf, (reg1), (b), (i), (s), (d)); }
-
-char * opt_mul(PARROT_INTERP, char *pc, int dest, INTVAL imm, int src);
-
-# define jit_emit_mul_rir_i(pc, dest, imm, src) \
- (pc) = opt_mul(interp, (pc), (dest), (imm), (src))
-
-
-# define jit_emit_mul_ri_i(pc, r, imm) jit_emit_mul_rir_i((pc), (r), (imm), (r))
-
-# define jit_emit_mul_RIM_ii(pc, reg, imm, ofs) \
- emitm_alul_r_m((pc), 0x69, (reg), emit_EBX, emit_None, 1, (ofs)); \
- *(long *)(pc) = (long)(imm); \
- (pc) += 4;
-
-/* NEG */
-
-# define jit_emit_neg_r_i(pc, reg) emitm_alu_imp_r((pc), emit_b011, (reg))
-
-# define emitm_negl_m(pc, b, i, s, d) \
- emitm_alu_imp_m((pc), emit_b011, (b), (i), (s), (d))
-
-/* AND */
-
-# define emit_andl_r_r(pc, reg1, reg2) emitm_alul_r_r((pc), 0x21, (reg1), (reg2))
-# define jit_emit_band_rr_i(interp, pc, r1, r2) emit_andl_r_r((pc), (r2), (r1))
-
-# define jit_emit_band_ri_i(interp, pc, reg, imm) \
- emitm_alul_i_r((pc), 0x81, emit_b100, (imm), (reg))
-
-# define emitm_andl_r_m(pc, reg, b, i, s, d) \
- emitm_alul_r_m((pc), 0x21, (reg), (b), (i), (s), (d))
-
-# define emitm_andl_m_r(pc, reg, b, i, s, d) \
- emitm_alul_r_m((pc), 0x23, (reg), (b), (i), (s), (d))
-
-# define emitm_andl_i_m(pc, imm, b, i, s, d) \
- emitm_alul_i_m((pc), 0x81, emit_b100, (imm), (b), (i), (s), (d))
-
-/* TEST op */
-# define jit_emit_test_rr_i(pc, r1, r2) emitm_alul_r_r((pc), 0x85, (r1), (r2))
-
-# define jit_emit_test_ri_i(pc, r, im) \
- emitm_alul_i_r((pc), 0xF7, emit_b000, (im), (r))
-
-# define jit_emit_test_RM_i(pc, r, offs) \
- emitm_alul_r_m((pc), 0x85, (r), emit_EBX, 0, 1, (offs))
-
-/* OR */
-
-# define jit_emit_bor_rr_i(interp, pc, reg1, reg2) emitm_alul_r_r((pc), 0x9, (reg2), (reg1))
-
-# define jit_emit_bor_ri_i(interp, pc, reg, imm) \
- emitm_alul_i_r((pc), 0x81, emit_b001, (imm), (reg))
-
-# define emitm_orl_r_m(pc, reg, b, i, s, d) \
- emitm_alul_r_m((pc), 0x09, (reg), (b), (i), (s), (d))
-
-# define emitm_orl_m_r(pc, reg, b, i, s, d) \
- emitm_alul_r_m((pc), 0x0b, (reg), (b), (i), (s), (d))
-
-# define emitm_orl_i_m(pc, imm, b, i, s, d) \
- emitm_alul_i_m((pc), 0x81, emit_b001, (imm), (b), (i), (s), (d))
-
-/* XOR */
-
-# define jit_emit_bxor_rr_i(interp, pc, reg1, reg2) \
- emitm_alul_r_r((pc), 0x31, (reg2), (reg1))
-
-# define jit_emit_bxor_ri_i(intepr, pc, reg, imm) \
- emitm_alul_i_r((pc), 0x81, emit_b110, (imm), (reg))
-
-# define emitm_xorl_r_m(pc, reg, b, i, s, d) \
- emitm_alul_r_m((pc), 0x31, (reg), (b), (i), (s), (d))
-
-# define emitm_xorl_m_r(pc, reg, b, i, s, d) \
- emitm_alul_r_m((pc), 0x33, (reg), (b), (i), (s), (d))
-
-# define emitm_xorl_i_m(pc, imm, b, i, s, d) \
- emitm_alul_i_m((pc), 0x81, emit_b110, (imm), (b), (i), (s), (d))
-
-/* NOT */
-
-# define jit_emit_not_r_i(pc, reg) emitm_alu_imp_r((pc), emit_b010, (reg))
-# define emitm_notl_m(pc, b, i, s, d) \
- emitm_alu_imp_m((pc), emit_b010, (b), (i), (s), (d))
-
-# define jit_emit_not_M_i(interp, pc, offs) emitm_notl_m((pc), emit_EBX, 0, 1, (offs))
-
-/* XCHG */
-# define jit_emit_xchg_rr_i(interp, pc, r1, r2) { \
- if ((r1) != (r2)) { \
- *((pc)++) = (char) 0x87; \
- *((pc)++) = (char) emit_alu_r_r((r1), (r2)); \
- } \
-}
-
-# define jit_emit_xchg_rm_i(pc, r, m) { \
- emitm_alul_r_m((pc), 0x87, (r), emit_None, emit_None, emit_None, (m)) \
-}
-# define jit_emit_xchg_RM_i(interp, pc, r, offs) { \
- emitm_alul_r_m((pc), 0x87, (r), emit_EBX, emit_None, 1, (offs)) \
-}
-# define jit_emit_xchg_MR_i(interp, pc, offs, r) jit_emit_xchg_RM_i((interp), (pc), (r), (offs))
-
-/* SHL */
-
-# define jit_emit_shl_ri_i(interp, pc, reg, imm) \
- { (pc) = emit_shift_i_r((interp), (pc), emit_b100, (imm), (reg)); }
-
-# define emitm_shll_i_m(pc, imm, b, i, s, d) \
- { (pc) = emit_shift_i_m((pc), emit_b100, (imm), (b), (i), (s), (d)); }
-
-# define emitm_shll_r_r(interp, pc, reg1, reg2) \
- { (pc) = emit_shift_r_r((interp), (pc), emit_b100, (reg1), (reg2)); }
-
-# define emitm_shll_r_m(pc, reg, b, i, s, d) \
- { (pc) = emit_shift_r_m((pc), emit_b100, (reg), (b), (i), (s), (d)); }
-
-/* SHR */
-
-# define jit_emit_lsr_ri_i(interp, pc, reg, imm) \
- { (pc) = emit_shift_i_r((interp), (pc), emit_b101, (imm), (reg)); }
-
-# define emitm_shrl_i_m(pc, imm, b, i, s, d) \
- { (pc) = emit_shift_i_m((pc), emit_b101, (imm), (b), (i), (s), (d)); }
-
-# define emitm_shrl_r_r(interp, pc, reg1, reg2) \
- { (pc) = emit_shift_r_r((interp), (pc), emit_b101, (reg1), (reg2)); }
-
-# define emitm_shrl_r_m(pc, reg, b, i, s, d) \
- { (pc) = emit_shift_r_m((pc), emit_b101, (reg), (b), (i), (s), (d)); }
-
-/* SAL */
-
-# define emitm_sall_i_r(interp, pc, imm, reg) \
- { (pc) = emit_shift_i_r((interp), (pc), emit_b100, (imm), (reg)); }
-
-# define emitm_sall_i_m(pc, imm, b, i, s, d) \
- { (pc) = emit_shift_i_m((pc), emit_b100, (imm), (b), (i), (s), (d)); }
-
-# define emitm_sall_r_r(interp, pc, reg1, reg2) \
- { (pc) = emit_shift_r_r((interp), (pc), emit_b100, (reg1), (reg2)); }
-
-# define emitm_sall_r_m(pc, reg, b, i, s, d) \
- { (pc) = emit_shift_r_m((pc), emit_b100, (reg), (b), (i), (s), (d)); }
-
-/* SAR */
-
-# define jit_emit_shr_ri_i(interp, pc, reg, imm) \
- { (pc) = emit_shift_i_r((interp), (pc), emit_b111, (imm), (reg)); }
-
-
-# define emitm_sarl_i_m(pc, imm, b, i, s, d) \
- { (pc) = emit_shift_i_m((pc), emit_b111, (imm), (b), (i), (s), (d)); }
-
-# define emitm_sarl_r_r(interp, pc, reg1, reg2) \
- { (pc) = emit_shift_r_r((interp), (pc), emit_b111, (reg1), (reg2)); }
-
-# define emitm_sarl_r_m(pc, reg, b, i, s, d) \
- { (pc) = emit_shift_r_m((pc), emit_b111, (reg), (b), (i), (s), (d)); }
-
-/* rotate */
-
-# define jit_emit_rol_ri_i(interp, pc, reg, imm) \
- { (pc) = emit_shift_i_r((interp), (pc), emit_b000, (imm), (reg)); }
-
-# define jit_emit_ror_ri_i(interp, pc, reg, imm) \
- { (pc) = emit_shift_i_r((interp), (pc), emit_b001, (imm), (reg)); }
-
-/* interface, shift r1 by r2 bits */
-
-# define jit_emit_shl_rr_i(interp, pc, r1, r2) \
- (pc) = opt_shift_rr((interp), jit_info, (r1), (r2), emit_b100)
-
-# define jit_emit_shl_RM_i(interp, pc, r1, offs) \
- (pc) = opt_shift_rm((interp), jit_info, (r1), (offs), emit_b100)
-
-/* shr seems to be the arithmetic shift */
-# define jit_emit_shr_rr_i(interp, pc, r1, r2) \
- (pc) = opt_shift_rr((interp), jit_info, (r1), (r2), emit_b111)
-
-# define jit_emit_shr_RM_i(interp, pc, r1, offs) \
- (pc) = opt_shift_rm((interp), jit_info, (r1), (offs), emit_b111)
-
-# define jit_emit_lsr_rr_i(interp, pc, r1, r2) \
- (pc) = opt_shift_rr((interp), jit_info, (r1), (r2), emit_b101)
-
-# define jit_emit_lsr_RM_i(interp, pc, r1, offs) \
- (pc) = opt_shift_rm((interp), jit_info, (r1), (offs), emit_b101)
-
-/* MOV (reg), reg */
-# define emit_movm_r_r(pc, src, dest) \
- *((pc)++) = (char) 0x8b; \
- *((pc)++) = (char) (src) | (dest) << 3
-
-/* MOV X(reg), reg */
-# define emit_movb_i_r_r(pc, imm, src, dest) \
- *((pc)++) = (char)(0x8b); \
- *((p)c++) = (char)(0x40 | ((src) - 1) | ((dest) - 1) << 3); \
- *((pc)++) = (imm)
-
-/* INC / DEC */
-# define jit_emit_inc_r_i(pc, reg) *((pc)++) = (char)(0x40 | ((reg) - 1))
-# define jit_emit_dec_r_i(pc, reg) *((pc)++) = (char)(0x48 | ((reg) - 1))
-
-/* Floating point ops */
-
-# define emitm_floatop 0xd8 /* 11011000 */
-# define jit_emit_dec_fsp(pc) { *((pc)++) = (char) 0xD9; *((pc)++) = (char) 0xF6; }
-# define jit_emit_inc_fsp(pc) { *((pc)++) = (char) 0xD9; *((pc)++) = (char) 0xF7; }
-
-# define emitm_fl_2(interp, pc, mf, opa, opb, b, i, s, d) { \
- *((pc)++) = (char)(emitm_floatop | ((mf) << 1) | (opa)); \
- (pc) = emit_r_X((interp), (pc), emit_reg(opb), (b), (i), (s), (long)(d)); }
-
-# define emitm_fl_3(pc, d_p_opa, opb_r, sti) { \
- *((pc)++) = (char)(emitm_floatop | (d_p_opa)); \
- *((pc)++) = (char)(0xc0 | ((opb_r) << 3) | (sti)); }
-
-# define emitm_fl_4(pc, op) { \
- *((pc)++) = (char)(emitm_floatop | emit_b001); \
- *((pc)++) = (char)(0xe0 | (op)); }
-
-/* Integer loads and stores */
-# define emitm_fildl(interp, pc, b, i, s, d) \
- emitm_fl_2((interp), (pc), emit_b01, 1, emit_b000, (b), (i), (s), (d))
-
-# define emitm_fistpl(interp, pc, b, i, s, d) \
- emitm_fl_2((interp), (pc), emit_b01, 1, emit_b011, (b), (i), (s), (d))
-
-# define emitm_fistl(interp, pc, b, i, s, d) \
- emitm_fl_2((interp), (pc), emit_b01, 1, emit_b010, (b), (i), (s), (d))
-
-/* long long integer load/store */
-# define emitm_fildll(interp, pc, b, i, s, d) \
- emitm_fl_2((interp), (pc), emit_b11, 1, emit_b101, (b), (i), (s), (d))
-
-# define emitm_fistpll(interp, pc, b, i, s, d) \
- emitm_fl_2((interp), (pc), emit_b11, 1, emit_b111, (b), (i), (s), (d))
-
-/* Double loads and stores */
-# define emitm_fldl(interp, pc, b, i, s, d) \
- emitm_fl_2((interp), (pc), emit_b10, 1, emit_b000, (b), (i), (s), (d))
-
-# define emitm_fstpl(interp, pc, b, i, s, d) \
- emitm_fl_2((interp), (pc), emit_b10, 1, emit_b011, (b), (i), (s), (d))
-
-# define emitm_fstl(interp, pc, b, i, s, d) \
- emitm_fl_2((interp), (pc), emit_b10, 1, emit_b010, (b), (i), (s), (d))
-
-/* long double load / store */
-# define emitm_fldt(interp, pc, b, i, s, d) \
- emitm_fl_2((interp), (pc), emit_b01, 1, emit_b101, (b), (i), (s), (d))
-
-# define emitm_fstpt(interp, pc, b, i, s, d) \
- emitm_fl_2((interp), (pc), emit_b01, 1, emit_b111, (b), (i), (s), (d))
-
-/* short float load / store */
-# define emitm_flds(interp, pc, b, i, s, d) \
- emitm_fl_2((interp), (pc), emit_b00, 1, emit_b000, (b), (i), (s), (d))
-
-# define emitm_fstps(interp, pc, b, i, s, d) \
- emitm_fl_2((interp), (pc), emit_b00, 1, emit_b010, (b), (i), (s), (d))
-
-#if NUMVAL_SIZE == 8
-
-# define jit_emit_fload_m_n(interp, pc, address) \
- emitm_fldl((interp), (pc), emit_None, emit_None, emit_None, (address))
-
-# define jit_emit_fload_mb_n(interp, pc, base, offs) \
- emitm_fldl((interp), (pc), (base), emit_None, 1, (offs))
-
-# define jit_emit_fstore_m_n(interp, pc, address) \
- emitm_fstpl((interp), (pc), emit_None, emit_None, emit_None, (address))
-
-# define jit_emit_fstore_mb_n(interp, pc, base, offs) \
- emitm_fstpl((interp), (pc), (base), emit_None, 1, (offs))
-
-# define jit_emit_fst_mb_n(interp, pc, base, offs) \
- emitm_fstl((interp), (pc), (base), emit_None, 1, (offs))
-
-#else /* NUMVAL_SIZE */
-
-# define jit_emit_fload_m_n(interp, pc, address) \
- emitm_fldt((pc), emit_None, emit_None, emit_None, (address))
-
-# define jit_emit_fload_mb_n(interp, pc, base, offs) \
- emitm_fldt((pc), (base), emit_None, 1, (offs))
-
-# define jit_emit_fstore_m_n(pc, address) \
- emitm_fstpt((pc), emit_None, emit_None, emit_None, (address))
-
-# define jit_emit_fstore_mb_n(interp, pc, base, offs) \
- emitm_fstpt((pc), (base), emit_None, 1, (offs))
-
-# define jit_emit_fst_mb_n(interp, pc, base, offs) \
- emitm_fstt((pc), (base), emit_None, 1, (offs))
-
-#endif /* NUMVAL_SIZE */
-
-#if INTVAL_SIZE == 4
-
-# define jit_emit_fload_m_i(interp, pc, address) \
- emitm_fildl((interp), (pc), emit_None, emit_None, emit_None, (address))
-# define jit_emit_fload_mb_i(interp, pc, offs) \
- emitm_fildl((interp), (pc), emit_EBX, emit_None, 1, (offs))
-# define jit_emit_fstore_m_i(pc, m) \
- emitm_fistpl((pc), emit_None, emit_None, emit_None, (m))
-
-#else /* INTVAL_SIZE */
-
-# define jit_emit_fload_m_i(interp, pc, address) \
- emitm_fildll((interp), (pc), emit_None, emit_None, emit_None, (address))
-# define jit_emit_fload_mb_i(interp, pc, offs) \
- emitm_fildll((interp), (pc), emit_EBX, emit_None, 1, (offs))
-# define jit_emit_fstore_m_i(pc, m) \
- emitm_fistpll((pc), emit_None, emit_None, emit_None, (m))
-
-#endif /* INTVAL_SIZE */
-
-/* 0xD8 ops */
-# define emitm_fadd(pc, sti) emitm_fl_3((pc), emit_b000, emit_b000, (sti))
-# define emitm_fmul(pc, sti) emitm_fl_3((pc), emit_b000, emit_b001, (sti))
-# define emitm_fsub(pc, sti) emitm_fl_3((pc), emit_b000, emit_b100, (sti))
-# define emitm_fdiv(pc, sti) emitm_fl_3((pc), emit_b000, emit_b110, (sti))
-
-/* 0xD9 ops */
-# define emitm_fldz(pc) { *((pc)++) = (char) 0xd9; *((pc)++) = (char) 0xee; }
-# define emitm_fld1(pc) { *((pc)++) = (char) 0xd9; *((pc)++) = (char) 0xe8; }
-# define emitm_fsqrt(pc) { *((pc)++) = (char) 0xd9; *((pc)++) = (char) 0xfa; }
-# define emitm_fsin(pc) { *((pc)++) = (char) 0xd9; *((pc)++) = (char) 0xfe; }
-# define emitm_fcos(pc) { *((pc)++) = (char) 0xd9; *((pc)++) = (char) 0xff; }
-# define emitm_fxam(pc) { *((pc)++) = (char) 0xd9; *((pc)++) = (char) 0xe5; }
-
-/* FXCH ST, ST(i) , optimize 2 consecutive fxch with same reg */
-# define emitm_fxch(pc, sti) { \
- emitm_fl_3((pc), emit_b001, emit_b001, (sti)); \
-}
-
-/* FLD ST, ST(i), optimized FSTP(N+1);FLD(N) => FST(N+1) */
-extern unsigned char *lastpc;
-# define emitm_fld(pc, sti) do { \
- if ((unsigned char *)(pc) == (lastpc + 2) && \
- (int)(*lastpc) == (int)0xDD && \
- (int)lastpc[1] == (int)(0xD8+(sti)+1)) \
- lastpc[1] = 0xD0+(sti)+1; \
- else \
- emitm_fl_3((pc), emit_b001, emit_b000, (sti)); \
- } while (0)
-
-/* 0xDA, 0xDB ops */
-/* FCMOV*, FCOMI PPRO */
-
-/* 0xDC like 0xD8 with reversed operands */
-# define emitm_faddr(pc, sti) emitm_fl_3((pc), emit_b100, emit_b000, (sti))
-# define emitm_fmulr(pc, sti) emitm_fl_3((pc), emit_b100, emit_b001, (sti))
-# define emitm_fsubr(pc, sti) emitm_fl_3((pc), emit_b100, emit_b100, (sti))
-
-/* 0xDD ops */
-/* FFree ST(i) */
-# define emitm_ffree(pc, sti) emitm_fl_3((pc), emit_b101, emit_b000, (sti))
-
-/* FST ST(i) = ST */
-# define emitm_fst(pc, sti) emitm_fl_3((pc), emit_b101, emit_b010, (sti))
-
-/* FSTP ST(i) = ST, POP */
-# define emitm_fstp(pc, sti) { \
- lastpc = (unsigned char*) (pc); \
- emitm_fl_3((pc), emit_b101, emit_b011, (sti)); \
-}
-
-/* FUCOM ST(i) <=> ST unordered compares */
-# define emitm_fucom(pc, sti) emitm_fl_3((pc), emit_b101, emit_b100, (sti))
-
-/* FUCOMP ST(i) <=> ST, POP */
-# define emitm_fucomp(pc, sti) emitm_fl_3((pc), emit_b101, emit_b101, (sti))
-
-/* 0xDE ops */
-/* FADDP Add ST(i) = ST + ST(i); POP */
-# define emitm_faddp(pc, sti) emitm_fl_3((pc), emit_b110, emit_b000, (sti))
-
-/* FMULP Mul ST(i) = ST * ST(i); POP */
-# define emitm_fmulp(pc, sti) emitm_fl_3((pc), emit_b110, emit_b001, (sti))
-
-/* FSUB ST = ST - ST(i) */
-
-/* FSUBRP SubR ST(i) = ST - ST(i); POP */
-# define emitm_fsubrp(pc, sti) emitm_fl_3((pc), emit_b110, emit_b100, (sti))
-
-/* FSUBP Sub ST(i) = ST(i) - ST; POP */
-# define emitm_fsubp(pc, sti) emitm_fl_3((pc), emit_b110, emit_b101, (sti))
-
-/* FDIVRP DivR ST(i) = ST(i) / ST(0); POP */
-# define emitm_fdivrp(pc, sti) emitm_fl_3((pc), emit_b110, emit_b110, (sti))
-
-/* FDIVP Div ST(i) = ST(0) / ST(i); POP ST(0) */
-# define emitm_fdivp(pc, sti) emitm_fl_3((pc), emit_b110, emit_b111, (sti))
-
-/* 0xDF OPS: FCOMIP, FUCOMIP PPRO */
-
-/* Negate - called change sign */
-# define emitm_fchs(pc) emitm_fl_4((pc), 0)
-
-/* ABS - ST(0) = ABS(ST(0)) */
-# define emitm_fabs(pc) emitm_fl_4((pc), 1)
-
-/* Comparisons */
-
-# define emitm_fcom(pc, sti) emitm_fl_3((pc), emit_b000, emit_b010, (sti))
-
-# define emitm_fcomp(pc, sti) emitm_fl_3((pc), emit_b000, emit_b011, (sti))
-
-#ifdef PARROT_HAS_JIT_FCOMIP
-# define emitm_fcomip(pc, sti) emitm_fl_3((pc), emit_b111, emit_b110, (sti))
-# define emitm_fcomi(pc, sti) emitm_fl_3((pc), emit_b011, emit_b110, (sti))
-#else
-# define emitm_fcomip(pc, sti) do { \
- emitm_fcomp((pc), (sti)); \
- emitm_fstw(pc); \
- emitm_sahf(pc); \
- } while (0)
-# define emitm_fcomi(pc, sti) do { \
- emitm_fcom((pc), (sti)); \
- emitm_fstw(pc); \
- emitm_sahf(pc); \
- } while (0)
-#endif
-
-# define emitm_fcompp(pc) { *((pc)++) = (char) 0xde; *((pc)++) = (char) 0xd9; }
-
-# define emitm_fcom_m(interp, pc, b, i, s, d) \
- emitm_fl_2((interp), (pc), emit_b10, 0, emit_b010, (b), (i), (s), (d))
-
-# define emitm_fcomp_m(interp, pc, b, i, s, d) \
- emitm_fl_2((interp), (pc), emit_b10, 0, emit_b011, (b), (i), (s), (d))
-
-/* ST -= real64 */
-# define emitm_fsub_m(interp, pc, b, i, s, d) \
- emitm_fl_2((interp), (pc), emit_b10, 0, emit_b100, (b), (i), (s), (d))
-
-/* ST -= int32_mem */
-# define emitm_fisub_m(interp, pc, b, i, s, d) \
- emitm_fl_2((interp), (pc), emit_b01, 0, emit_b100, (b), (i), (s), (d))
-
-# define emitm_fadd_m(interp, pc, b, i, s, d) \
- emitm_fl_2((interp), (pc), emit_b10, 0, emit_b000, (b), (i), (s), (d))
-
-/* ST += int32_mem */
-# define emitm_fiadd_m(interp, pc, b, i, s, d) \
- emitm_fl_2((interp), (pc), emit_b01, 0, emit_b000, (b), (i), (s), (d))
-
-/* ST *= real64 */
-# define emitm_fmul_m(interp, pc, b, i, s, d) \
- emitm_fl_2((interp), (pc), emit_b10, 0, emit_b001, (b), (i), (s), (d))
-
-/* ST *= int32_mem */
-# define emitm_fimul_m(interp, pc, b, i, s, d) \
- emitm_fl_2((interp), (pc), emit_b01, 0, emit_b001, (b), (i), (s), (d))
-
-/* ST /= real64 */
-# define emitm_fdiv_m(interp, pc, b, i, s, d) \
- emitm_fl_2((interp), (pc), emit_b10, 0, emit_b110, (b), (i), (s), (d))
-
-/* ST /= int32_mem */
-# define emitm_fidiv_m(interp, pc, b, i, s, d) \
- emitm_fl_2((interp), (pc), emit_b01, 0, emit_b110, (b), (i), (s), (d))
-
-/* Ops Needed to support loading EFLAGs for conditional branches */
-# define emitm_fstw(pc) emitm_fl_3((pc), emit_b111, emit_b100, emit_b000)
-
-# define emitm_sahf(pc) *((pc)++) = (char) 0x9e
-
-/* misc float */
-# define emitm_ftst(pc) { *(pc)++ = 0xd9; *(pc)++ = 0xE4; }
-# define emitm_fprem(pc) { *(pc)++ = 0xd9; *(pc)++ = 0xF8; }
-# define emitm_fprem1(pc) { *(pc)++ = 0xd9; *(pc)++ = 0xF5; }
-
-# define emitm_fldcw(interp, pc, mem) \
- emitm_fl_2((interp), (pc), emit_b00, 1, emit_b101, 0, 0, 0, (mem))
-
-#if defined(NEG_MINUS_ZERO)
-# define jit_emit_neg_r_n(pc, r) { \
- if (r) { \
- emitm_fld((pc), (r)); \
- } \
- emitm_fchs(pc); \
- if (r) { \
- emitm_fstp((pc), ((r)+1)); \
- } \
- }
-
-# define jit_emit_neg_M_n(interp, pc, mem) { \
- jit_emit_fload_mb_n((interp), (pc), emit_EBX, (mem)); \
- emitm_fchs(pc); \
- jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (mem)); \
- }
-
-#elif defined(NEG_ZERO_SUB)
-
-# define jit_emit_neg_r_n(pc, r) { \
- emitm_fldz(pc); \
- emitm_fsubrp((pc), ((r)+1)); \
- }
-
-# define jit_emit_neg_M_n(interp, pc, mem) { \
- jit_emit_fload_mb_n((interp), (pc), emit_EBX, (mem)); \
- emitm_fldz(pc); \
- emitm_fsubrp((pc), 1); \
- jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (mem)); \
- }
-#else
-
-# define jit_emit_neg_r_n(pc, r) { \
- if (r) { \
- emitm_fld((pc), (r)); \
- } \
- emitm_ftst(pc); \
- emitm_fstw(pc); \
- emitm_sahf(pc); \
- emitm_jxs((pc), emitm_jz, 2); \
- emitm_fchs(pc); \
- if (r) { \
- emitm_fstp((pc), ((r)+1)); \
- } \
- }
-
-# define jit_emit_neg_M_n(interp, pc, mem) { \
- jit_emit_fload_mb_n((interp), (pc), emit_EBX, (mem)); \
- emitm_ftst(pc); \
- emitm_fstw(pc); \
- emitm_sahf(pc); \
- emitm_jxs((pc), emitm_jz, 2); \
- emitm_fchs(pc); \
- jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (mem)); \
- }
-#endif
-
-# define jit_emit_sin_r_n(pc, r) \
- if (r) { \
- emitm_fld((pc), (r)); \
- } \
- emitm_fsin(pc); \
- if (r) { \
- emitm_fstp((pc), ((r)+1)); \
- }
-
-# define jit_emit_cos_r_n(pc, r) \
- if (r) { \
- emitm_fld((pc), (r)); \
- } \
- emitm_fcos(pc); \
- if (r) { \
- emitm_fstp((pc), ((r)+1)); \
- }
-
-# define jit_emit_sqrt_r_n(pc, r) \
- if (r) { \
- emitm_fld((pc), (r)); \
- } \
- emitm_fsqrt(pc); \
- if (r) { \
- emitm_fstp((pc), ((r)+1)); \
- }
-
-# define jit_emit_abs_r_n(pc, r) { \
- if (r) { \
- emitm_fld((pc), (r)); \
- } \
- emitm_fabs(pc); \
- if (r) { \
- emitm_fstp((pc), ((r)+1)); \
- } \
- }
-
-# define jit_emit_abs_r_i(pc, r) { \
- jit_emit_test_r_i((pc), (r)); \
- emitm_jxs((pc), emitm_jns, 3); \
- jit_emit_not_r_i((pc), (r)); \
- jit_emit_inc_r_i((pc), (r)); \
- }
-
-# define jit_emit_abs_m_n(interp, pc, mem) { \
- jit_emit_fload_m_n((interp), (pc), (mem)); \
- emitm_fabs(pc); \
- jit_emit_fstore_m_n((pc), (mem)); \
- }
-
-/* Integer comparisons */
-# define jit_emit_cmp_rr(pc, reg1, reg2) \
- emitm_alul_r_r((pc), 0x39, (reg2), (reg1))
-# define jit_emit_cmp_rr_i(pc, r1, r2) jit_emit_cmp_rr((pc), (r1), (r2))
-
-# define emitm_cmpl_r_m(pc, reg, b, i, s, d) \
- emitm_alul_r_m((pc), 0x3b, (reg), (b), (i), (s), (d))
-
-# define emitm_cmpl_m_r(pc, reg, b, i, s, d) \
- emitm_alul_r_m((pc), 0x39, (reg), (b), (i), (s), (d))
-
-# define jit_emit_cmp_ri_i(interp, pc, reg, imm) \
- emitm_alul_i_r((pc), 0x81, emit_b111, (imm), (reg))
-
-/* Unconditional Jump/Call */
-
-# define emitm_call_cfunc(pc, func) emitm_calll((pc), (char *)(func) - (pc) - 4)
-
-# define emitm_calll(pc, disp) { \
- *((pc)++) = (char) 0xe8; \
- *(long *)(pc) = (disp); (pc) += 4; }
-
-# define emitm_callr(pc, reg) { \
- *((pc)++) = (char) 0xff; \
- *((pc)++) = (char) 0xd0 | ((reg) - 1); }
-
-# define emitm_callm(pc, b, i, s, d) { \
- *((pc)++) = (char) 0xff; \
- (pc) = emit_r_X((interp), (pc), emit_reg(emit_b010), (b), (i), (s), (d)); }
-
-# define emitm_jumps(pc, disp) { \
- *((pc)++) = (char) 0xeb; \
- *((pc)++) = (disp); }
-
-# define emitm_jumpl(pc, disp) { \
- *((pc)++) = (char) 0xe9; \
- *(long *)(pc) = (disp); (pc) += 4; }
-
-# define emitm_jumpr(pc, reg) { \
- *((pc)++) = (char) 0xff; \
- *((pc)++) = (char)(0xe0 | ((reg) - 1)); }
-
-# define emitm_jumpm(pc, b, i, s, d) { \
- *((pc)++) = (char) 0xff; \
- (pc) = emit_r_X((interp), (pc), emit_reg(emit_b100), (b), (i), (s), (d)); }
-
-/* Conditional jumps */
-
-/* Short jump - 8 bit disp */
-# define emitm_jxs(pc, code, disp) { \
- *((pc)++) = (char)(0x70 | (code)); \
- *((pc)++) = (char)(disp); }
-
-/* Long jump - 32 bit disp */
-# define emitm_jxl(pc, code, disp) { \
- *((pc)++) = (char) 0x0f; \
- *((pc)++) = (char)(0x80 | (code)); \
- *(long *)(pc) = (disp); (pc) += 4; }
-
-# define emitm_jo 0
-# define emitm_jno 1
-# define emitm_jb 2
-# define emitm_jnb 3
-# define emitm_jz 4
-# define emitm_je emitm_jz
-# define emitm_jnz 5
-# define emitm_jne emitm_jnz
-# define emitm_jbe 6
-# define emitm_ja 7
-# define emitm_js 8
-# define emitm_jns 9
-# define emitm_jp 10
-# define emitm_jnp 11
-# define emitm_jl 12
-# define emitm_jnl 13
-# define emitm_jle 14
-# define emitm_jg 15
-
-/* set byte conditional */
-# define jit_emit_setcc_r(pc, cc, r) \
- *(pc)++ = 0x0f; \
- *(pc)++ = 0x90 + (cc); \
- *(pc)++ = (char) emit_alu_X_r(0, (r))
-
-/*
- * core.jit interface
- *
- * The new offset based versions have uppercase RM or MR inside
- * That's probably only during transition time
- */
-
-# define jit_emit_mov_mi_i(pc, dest, immediate) \
- emitm_movl_i_m((pc), (immediate), emit_None, emit_None, emit_None, (dest))
-
-# define jit_emit_mov_MI_i(interp, pc, offs, immediate) \
- emitm_movl_i_m((pc), (immediate), emit_EBX, emit_None, 1, (offs))
-
-# define jit_emit_mov_rm_i(interp, pc, reg, address) \
- emitm_movl_m_r((interp), (pc), (reg), emit_None, emit_None, emit_None, (address))
-
-# define jit_emit_mov_RM_i(interp, pc, reg, offs) \
- emitm_movl_m_r((interp), (pc), (reg), emit_EBX, emit_None, 1, (offs))
-
-# define jit_emit_mov_mr_i(interp, pc, address, reg) \
- emitm_movl_r_m((interp), (pc), (reg), emit_None, emit_None, emit_None, (address))
-
-# define jit_emit_mov_MR_i(interp, pc, offs, reg) \
- emitm_movl_r_m((interp), (pc), (reg), emit_EBX, emit_None, 1, (offs))
-
-# define jit_emit_mul_RM_i(interp, pc, reg, offs) \
- emitm_smull_r_m((pc), (reg), emit_EBX, emit_None, 1, (offs))
-
-# define jit_emit_sub_RM_i(interp, pc, reg, offs) \
- emitm_subl_m_r((pc), (reg), emit_EBX, emit_None, 1, (offs))
-
-# define jit_emit_sub_MR_i(interp, pc, offs, reg) \
- emitm_subl_r_m((pc), (reg), emit_EBX, emit_None, 1, (offs))
-
-# define jit_emit_sub_MI_i(pc, offs, imm) \
- emitm_subl_i_m((pc), (imm), emit_EBX, emit_None, 1, (offs))
-
-# define jit_emit_add_RM_i(interp, pc, reg, offs) \
- emitm_addl_m_r((pc), (reg), emit_EBX, emit_None, 1, (offs))
-
-# define jit_emit_add_MR_i(interp, pc, offs, reg) \
- emitm_addl_r_m((pc), (reg), emit_EBX, emit_None, 1, (offs))
-
-# define jit_emit_add_MI_i(pc, offs, imm) \
- emitm_addl_i_m((pc), (imm), emit_EBX, emit_None, 1, (offs))
-
-# define jit_emit_cmp_rm_i(pc, reg, address) \
- emitm_cmpl_r_m((pc), (reg), emit_None, emit_None, emit_None, (address))
-
-# define jit_emit_cmp_RM_i(interp, pc, reg, offs) \
- emitm_cmpl_r_m((pc), (reg), emit_EBX, emit_None, 1, (offs))
-
-# define jit_emit_cmp_MR_i(interp, pc, offs, reg) \
- emitm_cmpl_m_r((pc), (reg), emit_EBX, emit_None, 1, (offs))
-
-/* high level routines, behave like real 2 register FP */
-
-/* mapped float registers numbers are ST(1)-ST(4).
- * scratch register is ST(0)
- */
-
-/* ST(i) <- numvar */
-# define jit_emit_mov_RM_n(interp, pc, r, d) { \
- jit_emit_fload_mb_n((interp), (pc), emit_EBX, (d)); \
- emitm_fstp((pc), ((r)+1)); \
-}
-
-/* ST(i) <= NUM_CONST */
-# define jit_emit_mov_ri_n(interp, pc, r, i) { \
- jit_emit_fload_m_n((interp), (pc), (i)); \
- emitm_fstp((pc), ((r)+1)); \
-}
-
-/* ST(i) <= &INT_CONST */
-# define jit_emit_mov_ri_ni(interp, pc, r, i) { \
- jit_emit_fload_m_i((interp), (pc), (i)); \
- emitm_fstp((pc), ((r)+1)); \
-}
-
-/* ST(i) <= INT_REG */
-# define jit_emit_mov_RM_ni(interp, pc, r, i) { \
- jit_emit_fload_mb_i((interp), (pc), (i)); \
- emitm_fstp((pc), ((r)+1)); \
-}
-
-/* NUM_REG(i) <= &INT_CONST
- * the int const i is loaded from the code memory
- */
-# define jit_emit_mov_MI_ni(interp, pc, offs, i) { \
- jit_emit_fload_m_i((interp), (pc), (i)); \
- jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (offs)); \
-}
-
-/* INT_REG <= ST(i) */
-# define jit_emit_mov_mr_in(pc, mem, r) { \
- emitm_fld((pc), (r)); \
- jit_emit_fstore_m_i((pc), (mem)); \
-}
-
-/* numvar <- ST(i) */
-# define jit_emit_mov_mr_n(pc, d, r) { \
- emitm_fld((pc), (r)); \
- jit_emit_fstore_m_n((pc), (d)); \
-}
-
-# define jit_emit_mov_MR_n(interp, pc, d, r) { \
- if (r) { \
- emitm_fld((pc), (r)); \
- jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (d)); \
- } \
- else { \
- jit_emit_fst_mb_n((interp), (pc), emit_EBX, (d)); \
- } \
-}
-
-/* ST(r1) <= ST(r2) */
-# define jit_emit_mov_rr_n(pc, r1, r2) { \
- if ((r1) != (r2)) { \
- if (r2) { \
- emitm_fld((pc), (r2)); \
- emitm_fstp((pc), ((r1)+1)); \
- } \
- else { \
- emitm_fst((pc), (r1)); \
- } \
- } \
-}
-
-/* ST(r1) xchg ST(r2) */
-# define jit_emit_xchg_rr_n(interp, pc, r1, r2) { \
- if ((r1) != (r2)) { \
- emitm_fld((pc), (r1)); \
- emitm_fld((pc), ((r2)+1)); \
- emitm_fstp((pc), ((r1)+2)); \
- emitm_fstp((pc), ((r2)+1)); \
- } \
-}
-
-# define jit_emit_xchg_RM_n(interp, pc, r, offs) { \
- emitm_fld((pc), (r)); \
- jit_emit_fload_mb_n((interp), (pc), emit_EBX, (offs)); \
- emitm_fstp((pc), ((r)+2)); \
- jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (offs)); \
-}
-
-# define jit_emit_xchg_MR_n(interp, pc, offs, r) { \
- emitm_fld((pc), (r)); \
- jit_emit_fload_mb_n((interp), (pc), emit_EBX, (offs)); \
- emitm_fstp((pc), ((r)+2)); \
- jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (offs)); \
-}
-
-# define jit_emit_finit(pc) { *((pc)++) = (char) 0xdb; *((pc)++) = (char) 0xe3; }
-
-/* ST(i) op= MEM */
-
-# define jit_emit_xxx_rm_n(interp, op, pc, r, m) { \
- jit_emit_fload_m_n((interp), (pc), (m)); \
- emitm_f ## op ## p((pc), ((r)+1)); \
-}
-
-# define jit_emit_xxx_RM_n(interp, op, pc, r, offs) { \
- jit_emit_fload_mb_n((interp), (pc), emit_EBX, (offs)); \
- emitm_f ## op ## p((pc), ((r)+1)); \
-}
-
-/*
- * float ops in two flavors: abs memory for constants, offsets for regs
- */
-
-# define jit_emit_add_ri_n(interp, pc, r, m) jit_emit_xxx_rm_n((interp), add, (pc), (r), (m))
-# define jit_emit_sub_ri_n(interp, pc, r, m) jit_emit_xxx_rm_n((interp), sub, (pc), (r), (m))
-# define jit_emit_mul_ri_n(interp, pc, r, m) jit_emit_xxx_rm_n((interp), mul, (pc), (r), (m))
-
-# define jit_emit_add_RM_n(interp, pc, r, o) jit_emit_xxx_RM_n((interp), add, (pc), (r), (o))
-# define jit_emit_sub_RM_n(interp, pc, r, o) jit_emit_xxx_RM_n((interp), sub, (pc), (r), (o))
-# define jit_emit_mul_RM_n(interp, pc, r, o) jit_emit_xxx_RM_n((interp), mul, (pc), (r), (o))
-
-/* ST(r1) += ST(r2) */
-/* r1 == 0: ST(0) <- ST(0) + ST(i)
- * r2 == 0: ST(i) <- ST(0) + ST(i)
- */
-# define jit_emit_add_rr_n(interp, pc, r1, r2) do { \
- if (!(r1)) { \
- emitm_fadd((pc), (r2)); \
- } \
- else if (!(r2)) { \
- emitm_faddr((pc), (r1)); \
- } \
- else { \
- emitm_fld((pc), (r2)); \
- emitm_faddp((pc), ((r1)+1)); \
- } \
- } \
- while (0)
-/*
- * ST(r) += INT_REG
- */
-# define jit_emit_add_RM_ni(pc, r, offs) { \
- emitm_fld((pc), (r)); \
- emitm_fiadd_m((pc), emit_EBX, 0, 1, (offs)); \
- emitm_fstp((pc), ((r)+1)); \
-}
-
-/* ST(r1) -= ST(r2) */
-/* r1 == 0: ST(0) <- ST(0) - ST(i)
- * r2 == 0: ST(i) <- ST(i) - ST(0)
- */
-# define jit_emit_sub_rr_n(interp, pc, r1, r2) do { \
- if (!(r1)) { \
- emitm_fsub((pc), (r2)); \
- } \
- else if (!(r2)) { \
- emitm_fsubr((pc), (r1)); \
- } \
- else { \
- emitm_fld((pc), (r2)); \
- emitm_fsubp((pc), ((r1)+1)); \
- } \
- } \
- while (0)
-
-/*
- * ST(r) -= INT_REG
- */
-# define jit_emit_sub_RM_ni(pc, r, offs) { \
- emitm_fld((pc), (r)); \
- emitm_fisub_m((pc), emit_EBX, 0, 1, (offs)); \
- emitm_fstp((pc), ((r)+1)); \
-}
-
-# define jit_emit_inc_r_n(pc, r) { \
- emitm_fld1(pc); \
- emitm_faddp((pc), ((r)+1)); \
-}
-
-# define jit_emit_dec_r_n(pc, r) { \
- emitm_fld1(pc); \
- emitm_fsubp((pc), ((r)+1)); \
-}
-
-/* ST(r1) *= ST(r2) */
-/* r1 == 0: ST(0) <- ST(0) * ST(i)
- * r2 == 0: ST(i) <- ST(0) * ST(i)
- */
-# define jit_emit_mul_rr_n(interp, pc, r1, r2) do { \
- if (!(r1)) { \
- emitm_fmul((pc), (r2)); \
- } \
- else if (!(r2)) { \
- emitm_fmulr((pc), (r1)); \
- } \
- else { \
- emitm_fld((pc), (r2)); \
- emitm_fmulp((pc), ((r1)+1)); \
- } \
- } \
- while (0)
-
-/*
- * ST(r) *= INT_REG
- */
-# define jit_emit_mul_RM_ni(pc, r, offs) { \
- emitm_fld((pc), (r)); \
- emitm_fimul_m((pc), emit_EBX, 0, 1, (offs)); \
- emitm_fstp((pc), ((r)+1)); \
-}
-
-/*
- * ST(r) /= INT_REG
- */
-# define jit_emit_div_RM_ni(pc, r, offs) { \
- emitm_fld((pc), (r)); \
- emitm_fidiv_m((pc), emit_EBX, 0, 1, (offs)); \
- emitm_fstp((pc), ((r)+1)); \
-}
-
-/* test r for zero */
-# define jit_emit_test_r_n(pc, r) { \
- if (r) { \
- emitm_fxch((pc), (r)); \
- } \
- emitm_fxam(pc); \
- emitm_fstw(pc); \
- emitm_sahf(pc); \
- if (r) { \
- emitm_fxch((pc), (r)); \
- } \
-}
-
-enum { JIT_X86BRANCH, JIT_X86JUMP, JIT_X86CALL };
-
-# define jit_emit_stack_frame_enter(pc) do { \
- emitm_pushl_r((pc), emit_EBP); \
- jit_emit_mov_rr_i((pc), emit_EBP, emit_ESP); \
-} while (0)
-
-# define jit_emit_stack_frame_leave(pc) do { \
- jit_emit_mov_rr_i((pc), emit_ESP, emit_EBP); \
- emitm_popl_r((pc), emit_EBP); \
-} while (0)
-
-# define jit_emit_end(pc) { \
- jit_emit_add_ri_i((interp), (pc), emit_ESP, 4); \
- emitm_popl_r((pc), emit_EDI); \
- emitm_popl_r((pc), emit_ESI); \
- emitm_popl_r((pc), emit_EBX); \
- emitm_popl_r((pc), emit_EBP); \
- emitm_ret(pc); \
- }
-
-size_t calc_signature_needs(const char *sig, int *strings);
-
-void * Parrot_jit_build_call_func(PARROT_INTERP, PMC *pmc_nci,
- STRING *signature, int *sizeptr);
-
-/*
- * register usage
- * %edi, %esi ... mapped, preserved
- * %edx, %ecx ... mapped, not preserved
- * %ebx ... base pointer for register access, preserved
- * %eax ... scratch, return value register
- */
-
-#endif /* PARROT_I386_JIT_EMIT_H_GUARD */
+#endif /* PARROT_FRAME_BUILDER_H_GUARD */
/*
* Local variables:
Modified: branches/auto_libjit/src/nci_test.c
==============================================================================
--- branches/auto_libjit/src/nci_test.c Tue Oct 13 01:44:21 2009 (r41836)
+++ branches/auto_libjit/src/nci_test.c Tue Oct 13 02:20:14 2009 (r41837)
@@ -109,6 +109,8 @@
PARROT_EXPORT void nci_vfff(float, float, float);
PARROT_EXPORT void nci_vV(const char **);
PARROT_EXPORT void nci_vVVV(const char **, const char **, const char **);
+PARROT_EXPORT int nci_i20(int, int, int, int, int, int, int, int, int, int, int, int, int, int,
+ int, int, int, int, int);
/* Declarations for callback tests */
@@ -1190,6 +1192,50 @@
*ptr3 = "Go suck a lemon.\n";
}
+/*
+
+=item C<int
+nci_i20(int sel, int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8, int v9, int v10,
+ int v11, int v12, int v13, int v14, int v15, int v16, int v17, int v18)>
+
+Prints and returns the nth value in a list of integers. First argument is the selector; subsequents,
+the list.
+
+This function is designed to be outside of the range of the static frame builder as an excercise for
+the dynamic frame builder.
+
+=cut
+
+*/
+PARROT_EXPORT int
+nci_i20(int sel, int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8, int v9, int v10,
+ int v11, int v12, int v13, int v14, int v15, int v16, int v17, int v18) {
+ int *selected;
+ switch ((sel < 0 ? -sel : sel) % 18) {
+ case 0: selected = &v1; break;
+ case 1: selected = &v2; break;
+ case 2: selected = &v3; break;
+ case 3: selected = &v4; break;
+ case 4: selected = &v5; break;
+ case 5: selected = &v6; break;
+ case 6: selected = &v7; break;
+ case 7: selected = &v8; break;
+ case 8: selected = &v9; break;
+ case 9: selected = &v10; break;
+ case 10: selected = &v11; break;
+ case 11: selected = &v12; break;
+ case 12: selected = &v13; break;
+ case 13: selected = &v14; break;
+ case 14: selected = &v15; break;
+ case 15: selected = &v16; break;
+ case 16: selected = &v17; break;
+ case 17: selected = &v18; break;
+ default: printf("default case reached (should never happen)"); return -1;
+ }
+ printf("%d\n", *selected);
+ return *selected;
+}
+
#ifdef TEST
char l2 = 4;
Modified: branches/auto_libjit/t/pmc/nci.t
==============================================================================
--- branches/auto_libjit/t/pmc/nci.t Tue Oct 13 01:44:21 2009 (r41836)
+++ branches/auto_libjit/t/pmc/nci.t Tue Oct 13 02:20:14 2009 (r41837)
@@ -6,7 +6,7 @@
use warnings;
use lib qw( . lib ../lib ../../lib );
use Test::More;
-use Parrot::Test tests => 70;
+use Parrot::Test tests => 71;
use Parrot::Config qw(%PConfig);
=head1 NAME
@@ -2753,6 +2753,76 @@
Go suck a lemon.
OUTPUT
+my $test_code = <<'CODE';
+.sub test :main
+ .local pmc libnci_test
+ $S0 = 'libnci_test'
+ libnci_test = loadlib $S0
+
+ .local pmc nci_i20
+ nci_i20 = dlfunc libnci_test, "nci_i20", "iiiiiiiiiiiiiiiiiiii"
+
+ .local pmc args
+ args = new ['FixedIntegerArray']
+ args = 18
+
+ $I0 = 2
+ args[0] = 1
+ args[1] = 1
+
+LOOP1:
+ $I1 = $I0 - 1
+ $I1 = args[$I1]
+
+ $I2 = $I0 - 2
+ $I2 = args[$I2]
+
+ $I3 = $I1 + $I2
+ args[$I0] = $I3
+ inc $I0
+ if $I0 < 18 goto LOOP1
+
+ $I0 = args
+ dec $I0
+
+ $I1 = args[0]
+ $I2 = args[1]
+ $I3 = args[2]
+ $I4 = args[3]
+ $I5 = args[4]
+ $I6 = args[5]
+ $I7 = args[6]
+ $I8 = args[7]
+ $I9 = args[8]
+ $I10 = args[9]
+ $I11 = args[10]
+ $I12 = args[11]
+ $I13 = args[12]
+ $I14 = args[13]
+ $I15 = args[14]
+ $I16 = args[15]
+ $I17 = args[16]
+ $I18 = args[17]
+
+LOOP2:
+ nci_i20($I0, $I1, $I2, $I3, $I4, $I5, $I6, $I7, $I8, $I9, $I10, $I11, $I12, $I13, $I14, $I15, $I16, $I17, $I18)
+ $I0 = $I0 / 2
+ if $I0 > 0 goto LOOP2
+.end
+CODE
+if ($PConfig{cc_build_call_frames}) {
+ pir_output_is($test_code, <<DYNAMIC_FRAMEBUILDER_OUTPUT, 'dynamic frame builder builds ridiculous call frames');
+2584
+34
+5
+2
+1
+DYNAMIC_FRAMEBUILDER_OUTPUT
+} else {
+ my $output_re = qr/^Parrot VM: PANIC: iiiiiiiiiiiiiiiiiiii is an unknown signature type./;
+ pir_error_output_like($test_code, $output_re, "static frame builder can't build ridiculous signatures");
+}
+
# Local Variables:
# mode: cperl
# cperl-indent-level: 4
Added: branches/auto_libjit/t/steps/auto/libjit-01.t
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/auto_libjit/t/steps/auto/libjit-01.t Tue Oct 13 02:20:14 2009 (r41837)
@@ -0,0 +1,69 @@
+#! perl
+# Copyright (C) 2009, Parrot Foundation.
+# $Id$
+# auto/libjit-01.t
+
+use strict;
+use warnings;
+
+use Test::More tests => 9;
+
+use lib 'lib';
+
+use Parrot::Configure;
+use Parrot::Configure::Options 'process_options';
+use Parrot::Configure::Test qw(
+ test_step_thru_runstep
+ test_step_constructor_and_description
+);
+
+use_ok('config::init::defaults');
+use_ok('config::auto::libjit');
+
+########## _select_lib() ##########
+
+my ($args, $step_list_ref) = process_options(
+ {
+ argv => [],
+ mode => 'configure',
+ }
+);
+
+my $conf = Parrot::Configure->new;
+
+test_step_thru_runstep( $conf, 'init::defaults', $args );
+
+my $pkg = 'auto::libjit';
+
+$conf->add_steps($pkg);
+$conf->options->set(%$args);
+my $stp = test_step_constructor_and_description($conf);
+
+################### DOCUMENTATION ###################
+
+=head1 NAME
+
+auto/libjit-01.t - test auto::libjit
+
+=head1 SYNOPSIS
+
+ % prove t/steps/auto/libjit-01.t
+
+=head1 DESCRIPTION
+
+The files in this directory test functionality used by F<Configure.pl>.
+
+The tests in this file test auto::libjit.
+
+=head1 SEE ALSO
+
+config::auto::libjit, F<Configure.pl>.
+
+=cut
+
+# Local Variables:
+# mode: cperl
+# cperl-indent-level: 4
+# fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4:
Added: branches/auto_libjit/t/steps/gen/libjit-01.t
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/auto_libjit/t/steps/gen/libjit-01.t Tue Oct 13 02:20:14 2009 (r41837)
@@ -0,0 +1,107 @@
+#! perl
+# Copyright (C) 2009, Parrot Foundation.
+# $Id$
+# gen/libjit-01.t
+
+use strict;
+use warnings;
+
+use constant num_generated_files => 2;
+use Test::More tests => 8 + 2*num_generated_files;
+
+use File::Copy 'move';
+use File::Temp 'tempfile';
+
+use lib 'lib';
+use Parrot::Configure;
+use Parrot::Configure::Options 'process_options';
+use Parrot::Configure::Test qw(
+ test_step_thru_runstep
+ rerun_defaults_for_testing
+ test_step_constructor_and_description
+);
+
+use_ok('config::gen::libjit');
+
+my ($args, $step_list_ref) = process_options(
+ {
+ argv => [],
+ mode => 'configure',
+ }
+);
+
+my $conf = Parrot::Configure->new;
+
+my $serialized = $conf->pcfreeze();
+
+my $pkg = 'gen::libjit';
+$conf->add_steps($pkg);
+$conf->options->set( %$args );
+my $step = test_step_constructor_and_description($conf);
+
+is( scalar keys %{$step->{targets}}, num_generated_files, "Expected number of generated files");
+is_deeply([keys %{$step->{targets}}], [keys %{$step->{templates}}], "Templates match targets");
+
+foreach (keys %{$step->{templates}}) {
+ ok(-f $step->{templates}{$_}, "Able to locate $_ template")
+}
+
+my %orig_files;
+foreach (keys %{$step->{targets}}) {
+ if (-f (my $targ_name = $step->{targets}{$_})) {
+ $orig_files{$_} = tempfile();
+ move($targ_name, $orig_files{$_});
+ }
+}
+
+my %orig_conf = map { $_ => $conf->data->get($_) } qw[ iv nv ];
+$conf->data->set( iv => 'int', nv => 'float' );
+my $ret = $step->runstep($conf);
+ok( $ret, "runstep() returned true value" );
+foreach (keys %{$step->{targets}}) {
+ ok(-f $step->{targets}{$_}, "$_ target generated");
+}
+
+# re-set for next test
+$conf->data->set(%orig_conf);
+$step->set_result( '' );
+foreach (keys %{$step->{targets}}) {
+ if (exists $orig_files{$_}) {
+ move( $orig_files{$_}, $step->{targets}{$_} );
+ } else {
+ unlink $_;
+ }
+}
+
+$conf->replenish($serialized);
+
+pass("Completed all tests in $0");
+
+################### DOCUMENTATION ###################
+
+=head1 NAME
+
+ gen/libjit-01.t - test gen::libjit
+
+=head1 SYNOPSIS
+
+ % prove t/steps/gen/libjit-01.t
+
+=head1 DESCRIPTION
+
+The files in this directory test functionality used by F<Configure.pl>.
+
+The tests in this file test gen::libjit.
+
+=head1 SEE ALSO
+
+config::gen::libjit, F<Configure.pl>.
+
+=cut
+
+# Local Variables:
+# mode: cperl
+# cperl-indent-level: 4
+# fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4:
Modified: branches/auto_libjit/tools/build/nativecall.pl
==============================================================================
--- branches/auto_libjit/tools/build/nativecall.pl Tue Oct 13 01:44:21 2009 (r41836)
+++ branches/auto_libjit/tools/build/nativecall.pl Tue Oct 13 02:20:14 2009 (r41837)
@@ -467,17 +467,13 @@
return F2DPTR(VTABLE_get_pointer(interp, b));
}
else {
- int jit_size;
- void * const result = Parrot_jit_build_call_func(interp, pmc_nci, signature, &jit_size);
+ void *priv;
+ void * const result = Parrot_jit_build_call_func(interp, pmc_nci, signature, &priv);
if (result) {
- struct jit_buffer_private_data *priv;
*jitted = 1;
temp_pmc = pmc_new(interp, enum_class_ManagedStruct);
VTABLE_set_pointer(interp, temp_pmc, (void *)result);
#ifdef PARROT_HAS_EXEC_PROTECT
- priv = (struct jit_buffer_private_data *)
- mem_sys_allocate(sizeof(struct jit_buffer_private_data));
- priv->size = jit_size;
SETATTR_ManagedStruct_custom_free_func(interp, temp_pmc, Parrot_jit_free_buffer);
SETATTR_ManagedStruct_custom_free_priv(interp, temp_pmc, priv);
SETATTR_ManagedStruct_custom_clone_func(interp, temp_pmc, Parrot_jit_clone_buffer);
More information about the parrot-commits
mailing list