#include "svm1-defns.h"
#include "cmpintmd/svm1.h"
\f
+#ifndef __GNUC__
+# define GNUC_PREREQ(x, y) 0
+#else
+# define GNUC_PREREQ(x, y) \
+ ((__GNUC__ > (x)) || ((__GNUC__ == (x)) && (__GNUC_MINOR__ >= (y))))
+#endif
+
+/* Don't trust pre-C99 inline. */
+#if __STDC_VERSION__ < 199901L
+# define inline
+#endif
+
+#if GNUC_PREREQ(2,96)
+# define predict_true(condition) __builtin_expect(((condition) != 0), 1)
+# define predict_false(condition) __builtin_expect(((condition) != 0), 0)
+#else
+#endif
+\f
typedef SCHEME_OBJECT word_t; /* convenience abbreviation */
#define N_WORD_REGISTERS 0x100
#define COND_OFFSET_PC(p, o) do \
{ \
- if (p) { PC = PC + (o); } \
+ if (predict_false (p)) { PC = PC + (o); } \
return (1); \
} while (0)
return (0); \
} while (0)
+#define ILL EXIT_VM (ERR_COMPILED_CODE_ERROR)
+
typedef struct address_s address_t;
typedef word_t address_value_t (address_t *);
-typedef void address_decoder_t (address_t *);
+typedef bool address_decoder_t (address_t *);
static address_decoder_t * address_decoders [256];
struct address_s
#define ADDRESS_VALUE(name) ((name.value) (&name))
#define DEFINE_ADDRESS_DECODER(name) \
- static void decode_addr_##name (address_t * address)
-#define DECODE_ADDRESS(name) address_t name; decode_address (&name)
-static void decode_address (address_t *);
+ static bool decode_addr_##name (address_t * address)
+#define ADDRESS_DECODED return (true)
+#define DECODE_ADDRESS(name) \
+ address_t name; if (predict_false (! (decode_address (&name)))) ILL
+static bool decode_address (address_t *);
typedef bool trap_0_t (void);
typedef bool trap_1_t (wreg_t);
{
unsigned int i;
- if (!initialized_p)
+ if (predict_false (!initialized_p))
{
compute_little_endian_p ();
initialize_decoder_tables ();
{
IMPORT_REGS ();
PC = address;
- while ((* (inst_defns[NEXT_BYTE])) ());
+ while (predict_true ((* (inst_defns[NEXT_BYTE])) ()));
EXPORT_REGS ();
return (svm1_result);
}
static bool
illegal_instruction (void)
{
- svm1_result = ERR_COMPILED_CODE_ERROR;
- return (0);
+ ILL;
}
#define TO_SIGNED(n) ((long) (n))
work (in machines that use 2's complement). */
#define TO_SIGNED(n) (to_signed (n))
-static long
+static inline long
to_signed (word_t n)
{
union { unsigned long n1; long n2; } us;
\f
/* Primitive decoders */
-#define DECODE_WORD_REGISTER(name) wreg_t name = (decode_wreg ())
-#define DECODE_FLOAT_REGISTER(name) freg_t name = (decode_freg ())
-#define DECODE_TYPE_WORD(name) tc_t name = (decode_type_word ())
+#define DECODE_WORD_REGISTER(name) wreg_t name; if (predict_false (! (decode_wreg (&name)))) ILL
+#define DECODE_FLOAT_REGISTER(name) freg_t name; if (predict_false (! (decode_freg (&name)))) ILL
+#define DECODE_TYPE_WORD(name) tc_t name; if (predict_false (! (decode_type_word (&name)))) ILL
#define DECODE_UNSIGNED_8(name) word_t name = (decode_unsigned_8 ())
#define DECODE_UNSIGNED_16(name) word_t name = (decode_unsigned_16 ())
#define DECODE_UNSIGNED_32(name) word_t name = (decode_unsigned_32 ())
#define DECODE_SIGNED_32(name) long name = (decode_signed_32 ())
#define DECODE_FLOAT(name) double name = (decode_float ())
-static wreg_t
-decode_wreg (void)
+static inline bool
+decode_wreg (wreg_t *wreg)
{
byte_t b = NEXT_BYTE;
- assert (WORD_REGISTER_P (b));
- return (b);
+ if (predict_false (! (WORD_REGISTER_P (b))))
+ return (false);
+ *wreg = b;
+ return (true);
}
-static freg_t
-decode_freg (void)
+static inline bool
+decode_freg (freg_t *freg)
{
byte_t b = NEXT_BYTE;
- assert (FLOAT_REGISTER_P (b));
- return (b);
+ if (predict_false (! (FLOAT_REGISTER_P (b))))
+ return (false);
+ *freg = b;
+ return (true);
}
-static tc_t
-decode_type_word (void)
+static inline bool
+decode_type_word (tc_t *tc)
{
byte_t b = NEXT_BYTE;
- assert (b < N_TYPE_CODES);
- return (b);
+ if (predict_false (! (b <= N_TYPE_CODES)))
+ return (false);
+ *tc = b;
+ return (true);
}
-static word_t
+static inline word_t
decode_unsigned_8 (void)
{
return (NEXT_BYTE);
}
-static word_t
+static inline word_t
decode_unsigned_16 (void)
{
word_t b0 = NEXT_BYTE;
return ((b1 << 8) | b0);
}
-static word_t
+static inline word_t
decode_unsigned_32 (void)
{
word_t b0 = NEXT_BYTE;
return ((b3 << 24) | (b2 << 16) | (b1 << 8) | b0);
}
-static uint64_t
+static inline uint64_t
decode_unsigned_64 (void)
{
uint64_t b0, b1, b2, b3, b4, b5, b6, b7;
| (b3 << 24) | (b2 << 16) | (b1 << 8) | b0);
}
\f
-static long
+static inline long
decode_signed_8 (void)
{
long b = NEXT_BYTE;
return ((b < 0x80) ? b : (b - 0x100));
}
-static long
+static inline long
decode_signed_16 (void)
{
long n = (decode_unsigned_16 ());
return ((n < 0x8000) ? n : (n - 0x10000));
}
-static long
+static inline long
decode_signed_32 (void)
{
word_t n = (decode_unsigned_32 ());
#endif
}
-static int64_t
+static inline int64_t
decode_signed_64 (void)
{
uint64_t n = (decode_unsigned_64 ());
}
}
-static double
+static inline double
decode_float (void)
{
int64_t significand = (decode_signed_64 ());
IJUMP (offset);
}
-static void
+static inline void
push_object (SCHEME_OBJECT object)
{
stack_pointer = ((SCHEME_OBJECT *) (WREG_REF (SVM1_REG_STACK_POINTER)));
WREG_SET (SVM1_REG_STACK_POINTER, ((SCHEME_OBJECT) stack_pointer));
}
-static void
+static inline void
push_entry (void)
{
push_object (MAKE_CC_ENTRY (PC + CC_ENTRY_HEADER_SIZE));
#define CMP_CMP(a, b) (cmp_cmp ((a), (b)))
#define CMP_NCMP(a, b) (!cmp_cmp ((a), (b)))
-static int
+static inline int
cmp_cmp (double a, double b)
{
return ((a < b) || (a > b) || (a == b));
static bool
illegal_trap_0 (void)
{
- svm1_result = ERR_COMPILED_CODE_ERROR;
- return (0);
+ ILL;
}
DEFINE_INST (trap_trap_1_wr)
static bool
illegal_trap_1 (wreg_t r1)
{
- svm1_result = ERR_COMPILED_CODE_ERROR;
- return (0);
+ ILL;
}
DEFINE_INST (trap_trap_2_wr)
static bool
illegal_trap_2 (wreg_t r1, wreg_t r2)
{
- svm1_result = ERR_COMPILED_CODE_ERROR;
- return (0);
+ ILL;
}
DEFINE_INST (trap_trap_3_wr)
static bool
illegal_trap_3 (wreg_t r1, wreg_t r2, wreg_t r3)
{
- svm1_result = ERR_COMPILED_CODE_ERROR;
- return (0);
+ ILL;
}
#define TRAP_PREFIX(result) \
#define DEFINE_INTERRUPT_TEST(name, a1, a2) \
DEFINE_INST (interrupt_test_##name) \
{ \
- if (INTERRUPT_TEST) \
+ if (predict_false (INTERRUPT_TEST)) \
{ \
TRAP_PREFIX(result); \
compiler_interrupt_common ((&result), (a1), (a2)); \
{
DECODE_SVM1_INST_ENTER_CLOSURE (index);
- if (INTERRUPT_TEST)
+ if (predict_false (INTERRUPT_TEST))
{
TRAP_PREFIX(result);
compiler_interrupt_common ((&result), PC - 3, SHARP_F);
\f
/* Address decoders */
-static void
+static inline bool
decode_address (address_t * address)
{
- (* (address_decoders[NEXT_BYTE])) (address);
-}
-
-static word_t
-illegal_address_value (address_t * address)
-{
- return (0);
+ return ((* (address_decoders[NEXT_BYTE])) (address));
}
-static void
+static bool
illegal_address (address_t * address)
{
- address->value = illegal_address_value;
+ (void) address; /* ignore */
+ return (false);
}
static word_t
(address->r1) = base;
(address->n1) = 0;
(address->value) = offset_address_value;
+ ADDRESS_DECODED;
}
#define MAKE_OFFSET_ADDRESS(base, offset, scale) \
{
DECODE_SVM1_ADDR_OFFSET_S8_B (base, offset);
MAKE_OFFSET_ADDRESS (base, offset, SBYTE);
+ ADDRESS_DECODED;
}
DEFINE_ADDRESS_DECODER (offset_s8_w)
{
DECODE_SVM1_ADDR_OFFSET_S8_W (base, offset);
MAKE_OFFSET_ADDRESS (base, offset, SWORD);
+ ADDRESS_DECODED;
}
DEFINE_ADDRESS_DECODER (offset_s8_f)
{
DECODE_SVM1_ADDR_OFFSET_S8_F (base, offset);
MAKE_OFFSET_ADDRESS (base, offset, SFLOAT);
+ ADDRESS_DECODED;
}
DEFINE_ADDRESS_DECODER (offset_s16_b)
{
DECODE_SVM1_ADDR_OFFSET_S16_B (base, offset);
MAKE_OFFSET_ADDRESS (base, offset, SBYTE);
+ ADDRESS_DECODED;
}
DEFINE_ADDRESS_DECODER (offset_s16_w)
{
DECODE_SVM1_ADDR_OFFSET_S16_W (base, offset);
MAKE_OFFSET_ADDRESS (base, offset, SWORD);
+ ADDRESS_DECODED;
}
DEFINE_ADDRESS_DECODER (offset_s16_f)
{
DECODE_SVM1_ADDR_OFFSET_S16_F (base, offset);
MAKE_OFFSET_ADDRESS (base, offset, SFLOAT);
+ ADDRESS_DECODED;
}
DEFINE_ADDRESS_DECODER (offset_s32_b)
{
DECODE_SVM1_ADDR_OFFSET_S32_B (base, offset);
MAKE_OFFSET_ADDRESS (base, offset, SBYTE);
+ ADDRESS_DECODED;
}
DEFINE_ADDRESS_DECODER (offset_s32_w)
{
DECODE_SVM1_ADDR_OFFSET_S32_W (base, offset);
MAKE_OFFSET_ADDRESS (base, offset, SWORD);
+ ADDRESS_DECODED;
}
DEFINE_ADDRESS_DECODER (offset_s32_f)
{
DECODE_SVM1_ADDR_OFFSET_S32_F (base, offset);
MAKE_OFFSET_ADDRESS (base, offset, SFLOAT);
+ ADDRESS_DECODED;
}
static word_t
{
DECODE_SVM1_ADDR_INDEX_B_B (base, offset, index);
MAKE_INDEXED_ADDRESS (base, offset, SBYTE, index, SBYTE);
+ ADDRESS_DECODED;
}
DEFINE_ADDRESS_DECODER (index_b_w)
{
DECODE_SVM1_ADDR_INDEX_B_W (base, offset, index);
MAKE_INDEXED_ADDRESS (base, offset, SBYTE, index, SWORD);
+ ADDRESS_DECODED;
}
DEFINE_ADDRESS_DECODER (index_b_f)
{
DECODE_SVM1_ADDR_INDEX_B_F (base, offset, index);
MAKE_INDEXED_ADDRESS (base, offset, SBYTE, index, SFLOAT);
+ ADDRESS_DECODED;
}
DEFINE_ADDRESS_DECODER (index_w_b)
{
DECODE_SVM1_ADDR_INDEX_W_B (base, offset, index);
MAKE_INDEXED_ADDRESS (base, offset, SWORD, index, SBYTE);
+ ADDRESS_DECODED;
}
DEFINE_ADDRESS_DECODER (index_w_w)
{
DECODE_SVM1_ADDR_INDEX_W_W (base, offset, index);
MAKE_INDEXED_ADDRESS (base, offset, SWORD, index, SWORD);
+ ADDRESS_DECODED;
}
DEFINE_ADDRESS_DECODER (index_w_f)
{
DECODE_SVM1_ADDR_INDEX_W_F (base, offset, index);
MAKE_INDEXED_ADDRESS (base, offset, SWORD, index, SFLOAT);
+ ADDRESS_DECODED;
}
DEFINE_ADDRESS_DECODER (index_f_b)
{
DECODE_SVM1_ADDR_INDEX_F_B (base, offset, index);
MAKE_INDEXED_ADDRESS (base, offset, SFLOAT, index, SBYTE);
+ ADDRESS_DECODED;
}
DEFINE_ADDRESS_DECODER (index_f_w)
{
DECODE_SVM1_ADDR_INDEX_F_W (base, offset, index);
MAKE_INDEXED_ADDRESS (base, offset, SFLOAT, index, SWORD);
+ ADDRESS_DECODED;
}
DEFINE_ADDRESS_DECODER (index_f_f)
{
DECODE_SVM1_ADDR_INDEX_F_F (base, offset, index);
MAKE_INDEXED_ADDRESS (base, offset, SFLOAT, index, SFLOAT);
+ ADDRESS_DECODED;
}
static word_t
{
DECODE_SVM1_ADDR_PREDEC_B (base);
MAKE_PREINC_ADDRESS (base, (- SBYTE));
+ ADDRESS_DECODED;
}
DEFINE_ADDRESS_DECODER (predec_w)
{
DECODE_SVM1_ADDR_PREDEC_W (base);
MAKE_PREINC_ADDRESS (base, (- SWORD));
+ ADDRESS_DECODED;
}
DEFINE_ADDRESS_DECODER (predec_f)
{
DECODE_SVM1_ADDR_PREDEC_F (base);
MAKE_PREINC_ADDRESS (base, (- SFLOAT));
+ ADDRESS_DECODED;
}
DEFINE_ADDRESS_DECODER (preinc_b)
{
DECODE_SVM1_ADDR_PREINC_B (base);
MAKE_PREINC_ADDRESS (base, SBYTE);
+ ADDRESS_DECODED;
}
DEFINE_ADDRESS_DECODER (preinc_w)
{
DECODE_SVM1_ADDR_PREINC_W (base);
MAKE_PREINC_ADDRESS (base, SWORD);
+ ADDRESS_DECODED;
}
DEFINE_ADDRESS_DECODER (preinc_f)
{
DECODE_SVM1_ADDR_PREINC_F (base);
MAKE_PREINC_ADDRESS (base, SFLOAT);
+ ADDRESS_DECODED;
}
static word_t
{
DECODE_SVM1_ADDR_POSTDEC_B (base);
MAKE_POSTINC_ADDRESS (base, (- SBYTE));
+ ADDRESS_DECODED;
}
DEFINE_ADDRESS_DECODER (postdec_w)
{
DECODE_SVM1_ADDR_POSTDEC_W (base);
MAKE_POSTINC_ADDRESS (base, (- SWORD));
+ ADDRESS_DECODED;
}
DEFINE_ADDRESS_DECODER (postdec_f)
{
DECODE_SVM1_ADDR_POSTDEC_F (base);
MAKE_POSTINC_ADDRESS (base, (- SFLOAT));
+ ADDRESS_DECODED;
}
DEFINE_ADDRESS_DECODER (postinc_b)
{
DECODE_SVM1_ADDR_POSTINC_B (base);
MAKE_POSTINC_ADDRESS (base, SBYTE);
+ ADDRESS_DECODED;
}
DEFINE_ADDRESS_DECODER (postinc_w)
{
DECODE_SVM1_ADDR_POSTINC_W (base);
MAKE_POSTINC_ADDRESS (base, SWORD);
+ ADDRESS_DECODED;
}
DEFINE_ADDRESS_DECODER (postinc_f)
{
DECODE_SVM1_ADDR_POSTINC_F (base);
MAKE_POSTINC_ADDRESS (base, SFLOAT);
+ ADDRESS_DECODED;
}
static word_t
{
DECODE_SVM1_ADDR_PCR_S8 (offset);
MAKE_PCR_ADDRESS (offset);
+ ADDRESS_DECODED;
}
DEFINE_ADDRESS_DECODER (pcr_s16)
{
DECODE_SVM1_ADDR_PCR_S16 (offset);
MAKE_PCR_ADDRESS (offset);
+ ADDRESS_DECODED;
}
DEFINE_ADDRESS_DECODER (pcr_s32)
{
DECODE_SVM1_ADDR_PCR_S32 (offset);
MAKE_PCR_ADDRESS (offset);
+ ADDRESS_DECODED;
}
\f
#define INITIALIZE_DECODER_TABLE(table, initial_value) do \