2013-05-23 14:52:29 +02:00
|
|
|
/* Copyright (C) 2001, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
|
2001-04-01 05:03:41 +00:00
|
|
|
*
|
2009-05-26 22:23:44 +02:00
|
|
|
* This library is free software; you can redistribute it and/or
|
2009-06-17 00:22:09 +01:00
|
|
|
* modify it under the terms of the GNU Lesser General Public License
|
|
|
|
|
* as published by the Free Software Foundation; either version 3 of
|
|
|
|
|
* the License, or (at your option) any later version.
|
2001-04-01 05:03:41 +00:00
|
|
|
*
|
2009-06-17 00:22:09 +01:00
|
|
|
* This library is distributed in the hope that it will be useful, but
|
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
2009-05-26 22:23:44 +02:00
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
* Lesser General Public License for more details.
|
2001-04-01 05:03:41 +00:00
|
|
|
*
|
2009-05-26 22:23:44 +02:00
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
|
* License along with this library; if not, write to the Free Software
|
2009-06-17 00:22:09 +01:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
|
|
|
* 02110-1301 USA
|
2009-05-26 22:23:44 +02:00
|
|
|
*/
|
2001-04-01 05:03:41 +00:00
|
|
|
|
2008-05-20 11:46:52 +02:00
|
|
|
#if HAVE_CONFIG_H
|
|
|
|
|
# include <config.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2001-04-01 05:03:41 +00:00
|
|
|
#include <string.h>
|
2009-05-26 22:23:44 +02:00
|
|
|
|
|
|
|
|
#include "_scm.h"
|
2011-02-10 21:11:47 +01:00
|
|
|
#include "threads.h"
|
2001-04-01 05:03:41 +00:00
|
|
|
#include "instructions.h"
|
|
|
|
|
|
2011-02-10 21:11:47 +01:00
|
|
|
|
2013-07-19 09:55:20 +02:00
|
|
|
SCM_SYMBOL (sym_left_arrow, "<-");
|
|
|
|
|
SCM_SYMBOL (sym_bang, "!");
|
|
|
|
|
|
|
|
|
|
|
2013-05-23 14:52:29 +02:00
|
|
|
#define OP_HAS_ARITY (1U << 0)
|
|
|
|
|
|
|
|
|
|
#define FOR_EACH_INSTRUCTION_WORD_TYPE(M) \
|
|
|
|
|
M(X32) \
|
|
|
|
|
M(U8_X24) \
|
|
|
|
|
M(U8_U24) \
|
|
|
|
|
M(U8_L24) \
|
|
|
|
|
M(U8_U8_I16) \
|
|
|
|
|
M(U8_U8_U8_U8) \
|
|
|
|
|
M(U8_U12_U12) \
|
|
|
|
|
M(U32) /* Unsigned. */ \
|
|
|
|
|
M(I32) /* Immediate. */ \
|
|
|
|
|
M(A32) /* Immediate, high bits. */ \
|
|
|
|
|
M(B32) /* Immediate, low bits. */ \
|
|
|
|
|
M(N32) /* Non-immediate. */ \
|
|
|
|
|
M(S32) /* Scheme value (indirected). */ \
|
|
|
|
|
M(L32) /* Label. */ \
|
|
|
|
|
M(LO32) /* Label with offset. */ \
|
|
|
|
|
M(X8_U24) \
|
|
|
|
|
M(X8_U12_U12) \
|
|
|
|
|
M(X8_L24) \
|
|
|
|
|
M(B1_X7_L24) \
|
Various RTL VM and calling convention tweaks
* libguile/instructions.c (FOR_EACH_INSTRUCTION_WORD_TYPE): Allow for
five-word instructions, and for new instruction word types.
* libguile/vm-engine.c (RETURN_ONE_VALUE): Instead of returning the
value in the fixed part of the call frame, return it in the same place
multiple-value returns go: from slot 1.
(BR_ARITHMETIC): Allow arithmetic tests to be negated.
(rtl_vm_engine): Change calling convention to use the same location
for single and multiple-value returns. Renumber all instructions.
(halt, halt/values): Fold into a single instruction (halt).
(call): Take the location of the procedure instead of the location of
the call frame. Also take the number of args, and reset the sp before
jumping to the procedure, so as to indicate the number of arguments.
(call/values): Remove, as the new calling convention has RA == MVRA.
(tail-call): Require the procedure to be shuffled down already, and
take "nlocals" as an arg instead of "nargs".
(receive, receive-values): New instructions, for receiving returned
values from calls.
(return-values): Rename from return/values. Remove "values".
(alloc-frame): Rename from reserve-locals.
(reset-frame): New instruction.
(drop-locals): Remove.
(br-if-=, br-if-<, br-if-<=): Allow these instructions to be
negatable.
(br-if->, br-if->=): Remove. Probably a bad idea, given NaN.
(box-ref): Don't bother trying to do a reverse lookup -- the
toplevel-box, module-box, and resolve instructions should handle
that.
(resolve): Add arg to check that the variable is bound.
(toplevel-box, module-box): New instructions, replacing toplevel-ref,
toplevel-set, module-ref, and module-set.
* libguile/vm.c (rtl_boot_continuation_code, rtl_values_code): Adapt to
instruction set changes.
* module/Makefile.am: Make the assembler and disassembler dependent on
vm-operations.h.
* module/system/vm/assembler.scm:
* module/system/vm/disassembler.scm: Adapt to instruction changes and
new instruction word kinds.
* test-suite/tests/rtl.test: Adapt to instruction set changes.
2013-08-11 16:42:06 +02:00
|
|
|
M(B1_U7_L24) \
|
|
|
|
|
M(B1_X7_U24) \
|
|
|
|
|
M(B1_X31)
|
2013-05-23 14:52:29 +02:00
|
|
|
|
|
|
|
|
#define TYPE_WIDTH 5
|
|
|
|
|
|
|
|
|
|
enum word_type
|
|
|
|
|
{
|
|
|
|
|
#define ENUM(type) type,
|
|
|
|
|
FOR_EACH_INSTRUCTION_WORD_TYPE (ENUM)
|
|
|
|
|
#undef ENUM
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static SCM word_type_symbols[] =
|
|
|
|
|
{
|
|
|
|
|
#define FALSE(type) SCM_BOOL_F,
|
|
|
|
|
FOR_EACH_INSTRUCTION_WORD_TYPE (FALSE)
|
|
|
|
|
#undef FALSE
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#define OP(n,type) ((type) << (n*TYPE_WIDTH))
|
|
|
|
|
|
|
|
|
|
/* The VM_DEFINE_OP macro uses a CPP-based DSL to describe what kinds of
|
2013-11-19 20:45:57 +01:00
|
|
|
arguments each instruction takes. This piece of code is the only
|
2013-05-23 14:52:29 +02:00
|
|
|
bit that actually interprets that language. These macro definitions
|
|
|
|
|
encode the operand types into bits in a 32-bit integer.
|
|
|
|
|
|
2013-11-19 20:45:57 +01:00
|
|
|
(instruction-list) parses those encoded values into lists of symbols,
|
|
|
|
|
one for each 32-bit word that the operator takes. This list is used
|
|
|
|
|
by Scheme to generate assemblers and disassemblers for the
|
|
|
|
|
instructions. */
|
2013-05-23 14:52:29 +02:00
|
|
|
|
2013-11-21 22:51:38 +01:00
|
|
|
#define NOP SCM_T_UINT32_MAX
|
2013-05-23 14:52:29 +02:00
|
|
|
#define OP1(type0) \
|
|
|
|
|
(OP (0, type0))
|
|
|
|
|
#define OP2(type0, type1) \
|
|
|
|
|
(OP (0, type0) | OP (1, type1))
|
|
|
|
|
#define OP3(type0, type1, type2) \
|
|
|
|
|
(OP (0, type0) | OP (1, type1) | OP (2, type2))
|
|
|
|
|
#define OP4(type0, type1, type2, type3) \
|
|
|
|
|
(OP (0, type0) | OP (1, type1) | OP (2, type2) | OP (3, type3))
|
Various RTL VM and calling convention tweaks
* libguile/instructions.c (FOR_EACH_INSTRUCTION_WORD_TYPE): Allow for
five-word instructions, and for new instruction word types.
* libguile/vm-engine.c (RETURN_ONE_VALUE): Instead of returning the
value in the fixed part of the call frame, return it in the same place
multiple-value returns go: from slot 1.
(BR_ARITHMETIC): Allow arithmetic tests to be negated.
(rtl_vm_engine): Change calling convention to use the same location
for single and multiple-value returns. Renumber all instructions.
(halt, halt/values): Fold into a single instruction (halt).
(call): Take the location of the procedure instead of the location of
the call frame. Also take the number of args, and reset the sp before
jumping to the procedure, so as to indicate the number of arguments.
(call/values): Remove, as the new calling convention has RA == MVRA.
(tail-call): Require the procedure to be shuffled down already, and
take "nlocals" as an arg instead of "nargs".
(receive, receive-values): New instructions, for receiving returned
values from calls.
(return-values): Rename from return/values. Remove "values".
(alloc-frame): Rename from reserve-locals.
(reset-frame): New instruction.
(drop-locals): Remove.
(br-if-=, br-if-<, br-if-<=): Allow these instructions to be
negatable.
(br-if->, br-if->=): Remove. Probably a bad idea, given NaN.
(box-ref): Don't bother trying to do a reverse lookup -- the
toplevel-box, module-box, and resolve instructions should handle
that.
(resolve): Add arg to check that the variable is bound.
(toplevel-box, module-box): New instructions, replacing toplevel-ref,
toplevel-set, module-ref, and module-set.
* libguile/vm.c (rtl_boot_continuation_code, rtl_values_code): Adapt to
instruction set changes.
* module/Makefile.am: Make the assembler and disassembler dependent on
vm-operations.h.
* module/system/vm/assembler.scm:
* module/system/vm/disassembler.scm: Adapt to instruction changes and
new instruction word kinds.
* test-suite/tests/rtl.test: Adapt to instruction set changes.
2013-08-11 16:42:06 +02:00
|
|
|
#define OP5(type0, type1, type2, type3, type4) \
|
|
|
|
|
(OP (0, type0) | OP (1, type1) | OP (2, type2) | OP (3, type3) | OP (4, type4))
|
2013-05-23 14:52:29 +02:00
|
|
|
|
|
|
|
|
#define OP_DST (1 << (TYPE_WIDTH * 5))
|
|
|
|
|
|
|
|
|
|
#define WORD_TYPE(n, word) \
|
|
|
|
|
(((word) >> ((n) * TYPE_WIDTH)) & ((1 << TYPE_WIDTH) - 1))
|
|
|
|
|
|
2013-11-21 22:51:38 +01:00
|
|
|
/* Scheme interface */
|
2011-02-10 21:11:47 +01:00
|
|
|
|
2013-11-21 22:51:38 +01:00
|
|
|
static SCM
|
|
|
|
|
parse_instruction (scm_t_uint8 opcode, const char *name, scm_t_uint32 meta)
|
2013-05-23 14:52:29 +02:00
|
|
|
{
|
2013-11-21 22:51:38 +01:00
|
|
|
SCM tail = SCM_EOL;
|
|
|
|
|
int len;
|
|
|
|
|
|
|
|
|
|
/* Format: (name opcode word0 word1 ...) */
|
|
|
|
|
|
|
|
|
|
if (WORD_TYPE (4, meta))
|
|
|
|
|
len = 5;
|
|
|
|
|
else if (WORD_TYPE (3, meta))
|
|
|
|
|
len = 4;
|
|
|
|
|
else if (WORD_TYPE (2, meta))
|
|
|
|
|
len = 3;
|
|
|
|
|
else if (WORD_TYPE (1, meta))
|
|
|
|
|
len = 2;
|
|
|
|
|
else if (WORD_TYPE (0, meta))
|
|
|
|
|
len = 1;
|
|
|
|
|
else
|
|
|
|
|
abort ();
|
|
|
|
|
|
|
|
|
|
switch (len)
|
2013-05-23 14:52:29 +02:00
|
|
|
{
|
2013-11-21 22:51:38 +01:00
|
|
|
case 5:
|
|
|
|
|
tail = scm_cons (word_type_symbols[WORD_TYPE (4, meta)], tail);
|
|
|
|
|
case 4:
|
|
|
|
|
tail = scm_cons (word_type_symbols[WORD_TYPE (3, meta)], tail);
|
|
|
|
|
case 3:
|
|
|
|
|
tail = scm_cons (word_type_symbols[WORD_TYPE (2, meta)], tail);
|
|
|
|
|
case 2:
|
|
|
|
|
tail = scm_cons (word_type_symbols[WORD_TYPE (1, meta)], tail);
|
|
|
|
|
case 1:
|
|
|
|
|
tail = scm_cons (word_type_symbols[WORD_TYPE (0, meta)], tail);
|
|
|
|
|
default:
|
|
|
|
|
tail = scm_cons ((meta & OP_DST) ? sym_left_arrow : sym_bang, tail);
|
|
|
|
|
tail = scm_cons (scm_from_int (opcode), tail);
|
|
|
|
|
tail = scm_cons (scm_from_utf8_symbol (name), tail);
|
|
|
|
|
return tail;
|
2013-05-23 14:52:29 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-19 20:45:57 +01:00
|
|
|
SCM_DEFINE (scm_instruction_list, "instruction-list", 0, 0, 0,
|
2013-05-23 14:52:29 +02:00
|
|
|
(void),
|
|
|
|
|
"")
|
2013-11-19 20:45:57 +01:00
|
|
|
#define FUNC_NAME s_scm_instruction_list
|
2013-05-23 14:52:29 +02:00
|
|
|
{
|
|
|
|
|
SCM list = SCM_EOL;
|
2013-11-21 22:51:38 +01:00
|
|
|
|
|
|
|
|
#define INIT(opcode, tag, name, meta) \
|
|
|
|
|
if (name) list = scm_cons (parse_instruction (opcode, name, meta), list);
|
|
|
|
|
FOR_EACH_VM_OPERATION (INIT);
|
|
|
|
|
#undef INIT
|
2013-05-23 14:52:29 +02:00
|
|
|
|
|
|
|
|
return scm_reverse_x (list, SCM_EOL);
|
|
|
|
|
}
|
|
|
|
|
#undef FUNC_NAME
|
|
|
|
|
|
big reorg of scheme modules -- e.g. programs.c -> (system vm program)
This reorganization kills the ugly module-export-all hacks in
bootstrap.scm and core.scm. In fact, it gets rid of core.scm entirely,
breaking out its functionality into separate files.
* module/system/vm/trace.scm:
* module/system/vm/profile.scm:
* module/system/vm/disasm.scm:
* module/system/vm/debug.scm:
* module/system/vm/conv.scm:
* module/system/vm/assemble.scm:
* module/system/repl/repl.scm:
* module/system/repl/common.scm:
* module/system/base/compile.scm:
* module/system/repl/command.scm: Update for changes, and fix a bug in
procedure-documentation.
* module/system/vm/bootstrap.scm: Just call scm_bootstrap_vm, which
handles setting load-compiled for us.
* module/system/vm/core.scm: Removed, functionality folded into other
modules.
* module/system/vm/frame.scm: Export the C frame procedures here; also
move scheme functions from core.scm here.
* module/system/vm/instruction.scm: New file, exports procedures from
instructions.c.
* module/system/vm/objcode.scm: New file, exports procedures from
objcodes.c.
* module/system/vm/program.scm: New file, exports procedures from
programs.c, and some scheme functions originally from core.scm.
* module/system/vm/vm.scm: New file, from vm.c and core.scm.
* src/Makefile.am (libguile_vm_la_SOURCES): Add bootstrap.h.
* src/bootstrap.h: New file, prototypes scm_bootstrap_vm (), which the
scm_init_* functions call.
* src/frames.h:
* src/frames.c (scm_init_frames):
* src/frames.c (scm_bootstrap_frames):
* src/vm.h:
* src/instructions.h:
* src/instructions.c (scm_init_instructions):
* src/instructions.c (scm_bootstrap_instructions):
* src/objcodes.h:
* src/objcodes.c (scm_bootstrap_objcodes):
* src/objcodes.c (scm_init_objcodes):
* src/programs.h:
* src/programs.c (scm_bootstrap_programs):
* src/programs.c (scm_init_programs):
* src/vm.c (scm_bootstrap_vm):
* src/vm.c (scm_init_vm): Call scm_bootstrap_vm() before doing anything
in an init function. Bootstrap_vm will call bootstrap_instructions(),
etc to initialize types, then set load-compiled to point to
load-compiled/vm.
* src/vm.c (scm_load_compiled_with_vm): Code to load .go files, if
they're present.
2008-08-07 13:11:27 +02:00
|
|
|
void
|
|
|
|
|
scm_bootstrap_instructions (void)
|
|
|
|
|
{
|
2010-03-16 21:18:12 +01:00
|
|
|
scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION,
|
|
|
|
|
"scm_init_instructions",
|
2009-03-27 18:40:15 -07:00
|
|
|
(scm_t_extension_init_func)scm_init_instructions,
|
|
|
|
|
NULL);
|
2013-11-19 20:45:57 +01:00
|
|
|
}
|
2013-05-23 14:52:29 +02:00
|
|
|
|
2013-11-19 20:45:57 +01:00
|
|
|
void
|
|
|
|
|
scm_init_instructions (void)
|
|
|
|
|
{
|
2013-05-23 14:52:29 +02:00
|
|
|
#define INIT(type) \
|
|
|
|
|
word_type_symbols[type] = scm_from_utf8_symbol (#type);
|
|
|
|
|
FOR_EACH_INSTRUCTION_WORD_TYPE (INIT)
|
|
|
|
|
#undef INIT
|
big reorg of scheme modules -- e.g. programs.c -> (system vm program)
This reorganization kills the ugly module-export-all hacks in
bootstrap.scm and core.scm. In fact, it gets rid of core.scm entirely,
breaking out its functionality into separate files.
* module/system/vm/trace.scm:
* module/system/vm/profile.scm:
* module/system/vm/disasm.scm:
* module/system/vm/debug.scm:
* module/system/vm/conv.scm:
* module/system/vm/assemble.scm:
* module/system/repl/repl.scm:
* module/system/repl/common.scm:
* module/system/base/compile.scm:
* module/system/repl/command.scm: Update for changes, and fix a bug in
procedure-documentation.
* module/system/vm/bootstrap.scm: Just call scm_bootstrap_vm, which
handles setting load-compiled for us.
* module/system/vm/core.scm: Removed, functionality folded into other
modules.
* module/system/vm/frame.scm: Export the C frame procedures here; also
move scheme functions from core.scm here.
* module/system/vm/instruction.scm: New file, exports procedures from
instructions.c.
* module/system/vm/objcode.scm: New file, exports procedures from
objcodes.c.
* module/system/vm/program.scm: New file, exports procedures from
programs.c, and some scheme functions originally from core.scm.
* module/system/vm/vm.scm: New file, from vm.c and core.scm.
* src/Makefile.am (libguile_vm_la_SOURCES): Add bootstrap.h.
* src/bootstrap.h: New file, prototypes scm_bootstrap_vm (), which the
scm_init_* functions call.
* src/frames.h:
* src/frames.c (scm_init_frames):
* src/frames.c (scm_bootstrap_frames):
* src/vm.h:
* src/instructions.h:
* src/instructions.c (scm_init_instructions):
* src/instructions.c (scm_bootstrap_instructions):
* src/objcodes.h:
* src/objcodes.c (scm_bootstrap_objcodes):
* src/objcodes.c (scm_init_objcodes):
* src/programs.h:
* src/programs.c (scm_bootstrap_programs):
* src/programs.c (scm_init_programs):
* src/vm.c (scm_bootstrap_vm):
* src/vm.c (scm_init_vm): Call scm_bootstrap_vm() before doing anything
in an init function. Bootstrap_vm will call bootstrap_instructions(),
etc to initialize types, then set load-compiled to point to
load-compiled/vm.
* src/vm.c (scm_load_compiled_with_vm): Code to load .go files, if
they're present.
2008-08-07 13:11:27 +02:00
|
|
|
|
2001-04-01 05:03:41 +00:00
|
|
|
#ifndef SCM_MAGIC_SNARFER
|
2009-03-16 23:39:29 +01:00
|
|
|
#include "libguile/instructions.x"
|
2001-04-01 05:03:41 +00:00
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Local Variables:
|
|
|
|
|
c-file-style: "gnu"
|
|
|
|
|
End:
|
|
|
|
|
*/
|