1 /* Copyright (C) 2001, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public License
5 * as published by the Free Software Foundation; either version 3 of
6 * the License, or (at your option) any later version.
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
27 #include "instructions.h"
30 SCM_SYMBOL (sym_left_arrow
, "<-");
31 SCM_SYMBOL (sym_bang
, "!");
34 #define OP_HAS_ARITY (1U << 0)
36 #define FOR_EACH_INSTRUCTION_WORD_TYPE(M) \
44 M(U32) /* Unsigned. */ \
45 M(I32) /* Immediate. */ \
46 M(A32) /* Immediate, high bits. */ \
47 M(B32) /* Immediate, low bits. */ \
48 M(N32) /* Non-immediate. */ \
49 M(S32) /* Scheme value (indirected). */ \
51 M(LO32) /* Label with offset. */ \
64 #define ENUM(type) type,
65 FOR_EACH_INSTRUCTION_WORD_TYPE (ENUM
)
69 static SCM word_type_symbols
[] =
71 #define FALSE(type) SCM_BOOL_F,
72 FOR_EACH_INSTRUCTION_WORD_TYPE (FALSE
)
76 #define OP(n,type) ((type) << (n*TYPE_WIDTH))
78 /* The VM_DEFINE_OP macro uses a CPP-based DSL to describe what kinds of
79 arguments each instruction takes. This piece of code is the only
80 bit that actually interprets that language. These macro definitions
81 encode the operand types into bits in a 32-bit integer.
83 (instruction-list) parses those encoded values into lists of symbols,
84 one for each 32-bit word that the operator takes. This list is used
85 by Scheme to generate assemblers and disassemblers for the
90 #define OP2(type0, type1) \
91 (OP (0, type0) | OP (1, type1))
92 #define OP3(type0, type1, type2) \
93 (OP (0, type0) | OP (1, type1) | OP (2, type2))
94 #define OP4(type0, type1, type2, type3) \
95 (OP (0, type0) | OP (1, type1) | OP (2, type2) | OP (3, type3))
96 #define OP5(type0, type1, type2, type3, type4) \
97 (OP (0, type0) | OP (1, type1) | OP (2, type2) | OP (3, type3) | OP (4, type4))
99 #define OP_DST (1 << (TYPE_WIDTH * 5))
101 #define WORD_TYPE(n, word) \
102 (((word) >> ((n) * TYPE_WIDTH)) & ((1 << TYPE_WIDTH) - 1))
104 struct scm_instruction
{
105 enum scm_rtl_opcode opcode
; /* opcode */
106 const char *name
; /* instruction name */
108 SCM symname
; /* filled in later */
112 static scm_i_pthread_mutex_t itable_lock
= SCM_I_PTHREAD_MUTEX_INITIALIZER
;
115 static const struct scm_instruction
*
116 fetch_instruction_table ()
118 static struct scm_instruction
*table
= NULL
;
120 scm_i_pthread_mutex_lock (&itable_lock
);
121 if (SCM_UNLIKELY (!table
))
123 size_t bytes
= SCM_VM_NUM_INSTRUCTIONS
* sizeof(struct scm_instruction
);
125 table
= malloc (bytes
);
126 memset (table
, 0, bytes
);
128 #define INIT(opcode, tag, name_, meta_) table[opcode].name = name_; table[opcode].meta = meta_;
129 FOR_EACH_VM_OPERATION (INIT
);
132 for (i
= 0; i
< SCM_VM_NUM_INSTRUCTIONS
; i
++)
136 table
[i
].symname
= scm_from_utf8_symbol (table
[i
].name
);
138 table
[i
].symname
= SCM_BOOL_F
;
141 scm_i_pthread_mutex_unlock (&itable_lock
);
147 /* Scheme interface */
149 SCM_DEFINE (scm_instruction_list
, "instruction-list", 0, 0, 0,
152 #define FUNC_NAME s_scm_instruction_list
156 const struct scm_instruction
*ip
= fetch_instruction_table ();
157 for (i
= 0; i
< SCM_VM_NUM_INSTRUCTIONS
; i
++)
160 scm_t_uint32 meta
= ip
[i
].meta
;
164 /* Format: (name opcode word0 word1 ...) */
166 if (WORD_TYPE (4, meta
))
168 else if (WORD_TYPE (3, meta
))
170 else if (WORD_TYPE (2, meta
))
172 else if (WORD_TYPE (1, meta
))
174 else if (WORD_TYPE (0, meta
))
182 tail
= scm_cons (word_type_symbols
[WORD_TYPE (4, meta
)], tail
);
184 tail
= scm_cons (word_type_symbols
[WORD_TYPE (3, meta
)], tail
);
186 tail
= scm_cons (word_type_symbols
[WORD_TYPE (2, meta
)], tail
);
188 tail
= scm_cons (word_type_symbols
[WORD_TYPE (1, meta
)], tail
);
190 tail
= scm_cons (word_type_symbols
[WORD_TYPE (0, meta
)], tail
);
192 tail
= scm_cons ((meta
& OP_DST
) ? sym_left_arrow
: sym_bang
, tail
);
193 tail
= scm_cons (scm_from_int (ip
[i
].opcode
), tail
);
194 tail
= scm_cons (ip
[i
].symname
, tail
);
198 list
= scm_cons (tail
, list
);
201 return scm_reverse_x (list
, SCM_EOL
);
206 scm_bootstrap_instructions (void)
208 scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION
,
209 "scm_init_instructions",
210 (scm_t_extension_init_func
)scm_init_instructions
,
215 scm_init_instructions (void)
218 word_type_symbols[type] = scm_from_utf8_symbol (#type);
219 FOR_EACH_INSTRUCTION_WORD_TYPE (INIT
)
222 #ifndef SCM_MAGIC_SNARFER
223 #include "libguile/instructions.x"