racket/c/pb.c
Matthew Flatt f78dc5724e add pb (portable bytecode) backend
This commit does four things:

 * Adds "pb.ss" and "pb.c", which implement a portable bytecode
   backend and interpreter that is intended for bootstrapping. A
   single set of pb bootfiles can support bootstrapping on all
   platforms --- as long as the C compiler supports a 64-bit integer
   type. The pb machine supports foreign calls for only a small set of
   recognized prototypes, and it does not support foriegn callables.
   Use `./configure --pb` to build the pb variant.

 * Changes the kernel's casts between `ptr` and `void*` types. In a pb
   build, the `ptr` type can be a 64-bit integer type while `void*` is
   a 32-bit pointer type, so casts must go through an intermediate
   integer type.

 * Adjusts the compiler to accomodate run-time-determined endianness.
   Making the compiler agnostic to word size is not practical, but
   only a few pieces depend on the target machine's endianness, and
   those can generally be deferred to a run-time choice of byte-based
   operations. The one exception is that ftype bit fields are not
   allowed unless accompanied by an explicit endianness declaration.

 * Start reducing duplication among platform-specific makefiles. For
   example, `Mf-ta6osx` chains to `Mf-a6osx` to avoid repeating most
   of it. A lot more can be done here.

original commit: 97533fa9d8b8400b0dc1a890768c7d30c91257e0
2020-07-24 13:13:46 -06:00

930 lines
39 KiB
C

#include "system.h"
#include <string.h>
#include <math.h>
/* Interpreter for portable bytecode. See "pb.ss". */
typedef uint32_t instruction_t;
#define INSTR_op(instr) ((instr) & 0xFF)
#define INSTR_d_dest(instr) (((instr) >> 8) & 0xF)
#define INSTR_dr_dest(instr) INSTR_d_dest(instr)
#define INSTR_dr_reg(instr) (((instr) >> 16) & 0xF)
#define INSTR_di_dest(instr) INSTR_d_dest(instr)
#define INSTR_di_imm(instr) (((int32_t)(instr)) >> 16)
#define INSTR_di_imm_unsigned(instr) ((instr) >> 16)
#define INSTR_drr_dest(instr) INSTR_d_dest(instr)
#define INSTR_drr_reg1(instr) (((instr) >> 12) & 0xF)
#define INSTR_drr_reg2(instr) (((instr) >> 16) & 0xF)
#define INSTR_dri_dest(instr) INSTR_d_dest(instr)
#define INSTR_dri_reg(instr) (((instr) >> 12) & 0xF)
#define INSTR_dri_imm(instr) (((int32_t)(instr)) >> 16)
#define INSTR_i_imm(instr) (((int32_t)(instr)) >> 8)
#define SHIFT_MASK(v) ((v) & (ptr_bits-1))
static uptr regs[16];
static double fpregs[8];
enum {
Cretval = 9,
Carg1 = 9,
Carg2,
Carg3,
Carg4,
Carg5,
Carg6,
Carg7
};
enum {
Cfpretval = 1,
Cfparg1 = 1,
Cfparg2,
Cfparg3,
Cfparg4,
Cfparg5,
Cfparg6
};
void S_machine_init() {}
#define SIGN_FLIP(r, a, b) ((~((a ^ b) | (r ^ ~b))) >> (ptr_bits-1))
#if __GNUC__ >= 5
# define USE_OVERFLOW_INTRINSICS 1
#else
# define USE_OVERFLOW_INTRINSICS 0
#endif
#if 0
# define TRACE(print, record) print
#elif 0
# define TRACE(print, record) record
static instruction_t *branch_from, *branch_to;
static instruction_t *jump_from, *jump_to;
static instruction_t *interp_from, *interp_to;
static instruction_t *call_from; static void *call_to;
#else
# define TRACE(print, record) /* empty */
#endif
void S_pb_interp(ptr tc, void *bytecode) {
instruction_t *ip = (instruction_t *)bytecode, *next_ip, instr;
int flag = 0;
regs[0] = (uptr)tc;
TRACE(printf("enter %p\n", ip), );
while (1) {
instr = *ip;
next_ip = ip + 1;
switch(INSTR_op(instr)) {
case pb_mov16_pb_zero_bits_pb_shift0:
regs[INSTR_di_dest(instr)] = (uptr)INSTR_di_imm_unsigned(instr);
break;
case pb_mov16_pb_zero_bits_pb_shift1:
regs[INSTR_di_dest(instr)] = (uptr)INSTR_di_imm_unsigned(instr) << 16;
break;
case pb_mov16_pb_zero_bits_pb_shift2:
#if ptr_bits == 64
regs[INSTR_di_dest(instr)] = (uptr)INSTR_di_imm_unsigned(instr) << 32;
#else
regs[INSTR_di_dest(instr)] = 0;
#endif
break;
case pb_mov16_pb_zero_bits_pb_shift3:
#if ptr_bits == 64
regs[INSTR_di_dest(instr)] = (uptr)INSTR_di_imm_unsigned(instr) << 48;
#else
regs[INSTR_di_dest(instr)] = 0;
#endif
break;
case pb_mov16_pb_keep_bits_pb_shift0:
regs[INSTR_di_dest(instr)] |= (uptr)INSTR_di_imm_unsigned(instr);
break;
case pb_mov16_pb_keep_bits_pb_shift1:
regs[INSTR_di_dest(instr)] |= (uptr)INSTR_di_imm_unsigned(instr) << 16;
break;
case pb_mov16_pb_keep_bits_pb_shift2:
#if ptr_bits == 64
regs[INSTR_di_dest(instr)] |= (uptr)INSTR_di_imm_unsigned(instr) << 32;
#endif
break;
case pb_mov16_pb_keep_bits_pb_shift3:
#if ptr_bits == 64
regs[INSTR_di_dest(instr)] |= (uptr)INSTR_di_imm_unsigned(instr) << 48;
#endif
break;
case pb_mov_pb_i_i:
regs[INSTR_dr_dest(instr)] = regs[INSTR_dr_reg(instr)];
break;
case pb_mov_pb_d_d:
fpregs[INSTR_dr_dest(instr)] = fpregs[INSTR_dr_reg(instr)];
break;
case pb_mov_pb_i_d:
fpregs[INSTR_dr_dest(instr)] = (double)(iptr)regs[INSTR_dr_reg(instr)];
break;
case pb_mov_pb_d_i:
regs[INSTR_dr_dest(instr)] = (iptr)fpregs[INSTR_dr_reg(instr)];
break;
#if ptr_bits == 64
case pb_mov_pb_i_bits_d_bits:
memcpy(&fpregs[INSTR_dr_dest(instr)], &regs[INSTR_dr_reg(instr)], sizeof(double));
break;
case pb_mov_pb_d_bits_i_bits:
memcpy(&regs[INSTR_dr_dest(instr)], &fpregs[INSTR_dr_reg(instr)], sizeof(double));
break;
#else
case pb_mov_pb_i_i_bits_d_bits:
{
uint64_t d;
d = regs[INSTR_drr_reg1(instr)] | ((uint64_t)regs[INSTR_drr_reg2(instr)] << 32);
memcpy(&fpregs[INSTR_drr_dest(instr)], &d, sizeof(double));
}
break;
case pb_mov_pb_d_lo_bits_i_bits:
{
uint64_t d;
memcpy(&d, &fpregs[INSTR_dr_reg(instr)], sizeof(double));
regs[INSTR_dr_dest(instr)] = d;
}
break;
case pb_mov_pb_d_hi_bits_i_bits:
{
uint64_t d;
memcpy(&d, &fpregs[INSTR_dr_reg(instr)], sizeof(double));
d >>= 32;
regs[INSTR_dr_dest(instr)] = d;
}
break;
#endif
case pb_mov_pb_s_d:
{
float f;
#ifdef PORTABLE_BYTECODE_BIGENDIAN
memcpy(&f, (char *)&fpregs[INSTR_dr_reg(instr)] + 4, sizeof(float));
#else
memcpy(&f, &fpregs[INSTR_dr_reg(instr)], sizeof(float));
#endif
fpregs[INSTR_dr_dest(instr)] = f;
}
break;
case pb_mov_pb_d_s:
{
float f;
f = fpregs[INSTR_dr_reg(instr)];
#ifdef PORTABLE_BYTECODE_BIGENDIAN
memcpy((char *)&fpregs[INSTR_dr_dest(instr)] + 4, &f, sizeof(float));
#else
memcpy(&fpregs[INSTR_dr_dest(instr)], &f, sizeof(float));
#endif
}
break;
case pb_bin_op_pb_no_signal_pb_add_pb_register:
regs[INSTR_drr_dest(instr)] = regs[INSTR_drr_reg1(instr)] + regs[INSTR_drr_reg2(instr)];
break;
case pb_bin_op_pb_no_signal_pb_add_pb_immediate:
regs[INSTR_dri_dest(instr)] = regs[INSTR_dri_reg(instr)] + (uptr)INSTR_dri_imm(instr);
break;
case pb_bin_op_pb_no_signal_pb_sub_pb_register:
regs[INSTR_drr_dest(instr)] = regs[INSTR_drr_reg1(instr)] - regs[INSTR_drr_reg2(instr)];
break;
case pb_bin_op_pb_no_signal_pb_sub_pb_immediate:
regs[INSTR_dri_dest(instr)] = regs[INSTR_dri_reg(instr)] - (uptr)INSTR_dri_imm(instr);
break;
case pb_bin_op_pb_no_signal_pb_mul_pb_register:
regs[INSTR_drr_dest(instr)] = regs[INSTR_drr_reg1(instr)] * regs[INSTR_drr_reg2(instr)];
break;
case pb_bin_op_pb_no_signal_pb_mul_pb_immediate:
regs[INSTR_dri_dest(instr)] = (uptr)regs[INSTR_dri_reg(instr)] * (uptr)INSTR_dri_imm(instr);
break;
case pb_bin_op_pb_no_signal_pb_div_pb_register:
regs[INSTR_drr_dest(instr)] = (iptr)regs[INSTR_drr_reg1(instr)] / (iptr)regs[INSTR_drr_reg2(instr)];
break;
case pb_bin_op_pb_no_signal_pb_div_pb_immediate:
regs[INSTR_dri_dest(instr)] = (iptr)regs[INSTR_dri_reg(instr)] / (iptr)INSTR_dri_imm(instr);
break;
case pb_bin_op_pb_no_signal_pb_and_pb_register:
regs[INSTR_drr_dest(instr)] = regs[INSTR_drr_reg1(instr)] & regs[INSTR_drr_reg2(instr)];
break;
case pb_bin_op_pb_no_signal_pb_and_pb_immediate:
regs[INSTR_dri_dest(instr)] = regs[INSTR_dri_reg(instr)] & (uptr)INSTR_dri_imm(instr);
break;
case pb_bin_op_pb_no_signal_pb_ior_pb_register:
regs[INSTR_drr_dest(instr)] = regs[INSTR_drr_reg1(instr)] | regs[INSTR_drr_reg2(instr)];
break;
case pb_bin_op_pb_no_signal_pb_ior_pb_immediate:
regs[INSTR_dri_dest(instr)] = regs[INSTR_dri_reg(instr)] | (uptr)INSTR_dri_imm(instr);
break;
case pb_bin_op_pb_no_signal_pb_xor_pb_register:
regs[INSTR_drr_dest(instr)] = regs[INSTR_drr_reg1(instr)] ^ regs[INSTR_drr_reg2(instr)];
break;
case pb_bin_op_pb_no_signal_pb_xor_pb_immediate:
regs[INSTR_dri_dest(instr)] = regs[INSTR_dri_reg(instr)] ^ (uptr)INSTR_dri_imm(instr);
break;
case pb_bin_op_pb_no_signal_pb_lsl_pb_register:
regs[INSTR_drr_dest(instr)] = regs[INSTR_drr_reg1(instr)] << SHIFT_MASK(regs[INSTR_drr_reg2(instr)]);
break;
case pb_bin_op_pb_no_signal_pb_lsl_pb_immediate:
regs[INSTR_dri_dest(instr)] = regs[INSTR_dri_reg(instr)] << SHIFT_MASK(INSTR_dri_imm(instr));
break;
case pb_bin_op_pb_no_signal_pb_lsr_pb_register:
regs[INSTR_drr_dest(instr)] = regs[INSTR_drr_reg1(instr)] >> SHIFT_MASK(regs[INSTR_drr_reg2(instr)]);
break;
case pb_bin_op_pb_no_signal_pb_lsr_pb_immediate:
regs[INSTR_dri_dest(instr)] = regs[INSTR_dri_reg(instr)] >> SHIFT_MASK(INSTR_dri_imm(instr));
break;
case pb_bin_op_pb_no_signal_pb_asr_pb_register:
regs[INSTR_drr_dest(instr)] = (iptr)regs[INSTR_drr_reg1(instr)] >> SHIFT_MASK(regs[INSTR_drr_reg2(instr)]);
break;
case pb_bin_op_pb_no_signal_pb_asr_pb_immediate:
regs[INSTR_dri_dest(instr)] = (iptr)regs[INSTR_dri_reg(instr)] >> SHIFT_MASK(INSTR_dri_imm(instr));
break;
case pb_bin_op_pb_no_signal_pb_lslo_pb_register:
#ifdef PORTABLE_BYTECODE_BIGENDIAN
regs[INSTR_drr_dest(instr)] = regs[INSTR_drr_reg1(instr)] >> regs[INSTR_drr_reg2(instr)];
#else
regs[INSTR_drr_dest(instr)] = regs[INSTR_drr_reg1(instr)] << regs[INSTR_drr_reg2(instr)];
#endif
break;
case pb_bin_op_pb_no_signal_pb_lslo_pb_immediate:
#ifdef PORTABLE_BYTECODE_BIGENDIAN
regs[INSTR_dri_dest(instr)] = regs[INSTR_dri_reg(instr)] >> INSTR_dri_imm(instr);
#else
regs[INSTR_dri_dest(instr)] = regs[INSTR_dri_reg(instr)] << INSTR_dri_imm(instr);
#endif
break;
case pb_bin_op_pb_signal_pb_add_pb_register:
{
#if USE_OVERFLOW_INTRINSICS
iptr a = (iptr)regs[INSTR_drr_reg1(instr)];
iptr b = (iptr)regs[INSTR_drr_reg2(instr)];
iptr r;
flag = __builtin_add_overflow(a, b, &r);
regs[INSTR_drr_dest(instr)] = (uptr)r;
#else
uptr a = regs[INSTR_drr_reg1(instr)];
uptr b = regs[INSTR_drr_reg2(instr)];
uptr r = a + b;
regs[INSTR_drr_dest(instr)] = r;
flag = SIGN_FLIP(r, a, b);
#endif
}
break;
case pb_bin_op_pb_signal_pb_add_pb_immediate:
{
#if USE_OVERFLOW_INTRINSICS
iptr a = (iptr)regs[INSTR_dri_reg(instr)];
iptr b = INSTR_dri_imm(instr);
iptr r;
flag = __builtin_add_overflow(a, b, &r);
regs[INSTR_drr_dest(instr)] = (uptr)r;
#else
uptr a = regs[INSTR_dri_reg(instr)];
uptr b = (uptr)INSTR_dri_imm(instr);
uptr r = a + b;
regs[INSTR_dri_dest(instr)] = r;
flag = SIGN_FLIP(r, a, b);
#endif
}
break;
case pb_bin_op_pb_signal_pb_sub_pb_register:
{
#if USE_OVERFLOW_INTRINSICS
iptr a = (iptr)regs[INSTR_drr_reg1(instr)];
iptr b = (iptr)regs[INSTR_drr_reg2(instr)];
iptr r;
flag = __builtin_sub_overflow(a, b, &r);
regs[INSTR_drr_dest(instr)] = (uptr)r;
#else
uptr a = regs[INSTR_drr_reg1(instr)];
uptr b = regs[INSTR_drr_reg2(instr)];
uptr r = a - b;
regs[INSTR_drr_dest(instr)] = r;
flag = SIGN_FLIP(r, a, ~b);
#endif
}
break;
case pb_bin_op_pb_signal_pb_sub_pb_immediate:
{
#if USE_OVERFLOW_INTRINSICS
iptr a = (iptr)regs[INSTR_dri_reg(instr)];
iptr b = INSTR_dri_imm(instr);
iptr r;
flag = __builtin_sub_overflow(a, b, &r);
regs[INSTR_drr_dest(instr)] = (uptr)r;
#else
uptr a = regs[INSTR_dri_reg(instr)];
uptr b = (uptr)INSTR_dri_imm(instr);
uptr r = a - b;
regs[INSTR_dri_dest(instr)] = r;
flag = SIGN_FLIP(r, a, ~b);
#endif
}
break;
case pb_bin_op_pb_signal_pb_mul_pb_register:
{
#if USE_OVERFLOW_INTRINSICS
iptr a = (iptr)regs[INSTR_drr_reg1(instr)];
iptr b = (iptr)regs[INSTR_drr_reg2(instr)];
iptr r;
flag = __builtin_mul_overflow(a, b, &r);
regs[INSTR_drr_dest(instr)] = (uptr)r;
#else
uptr a = regs[INSTR_drr_reg1(instr)];
uptr b = regs[INSTR_drr_reg2(instr)];
uptr r = a * b;
regs[INSTR_drr_dest(instr)] = r;
if (b != 0) {
if (b == (uptr)-1)
flag = (a != r * (uptr)-1);
else
flag = ((iptr)a != (iptr)r / (iptr)b);
} else
flag = 0;
#endif
}
break;
case pb_bin_op_pb_signal_pb_mul_pb_immediate:
{
#if USE_OVERFLOW_INTRINSICS
iptr a = (iptr)regs[INSTR_dri_reg(instr)];
iptr b = INSTR_dri_imm(instr);
iptr r;
flag = __builtin_mul_overflow(a, b, &r);
regs[INSTR_drr_dest(instr)] = (uptr)r;
#else
uptr a = regs[INSTR_dri_reg(instr)];
uptr b = (uptr)INSTR_dri_imm(instr);
uptr r = a * b;
regs[INSTR_dri_dest(instr)] = r;
if (b != 0) {
if (b == (uptr)-1)
flag = (a != r * (uptr)-1);
else
flag = ((iptr)a != (iptr)r / (iptr)b);
} else
flag = 0;
#endif
}
break;
case pb_bin_op_pb_signal_pb_subz_pb_register:
{
iptr r = regs[INSTR_drr_reg1(instr)] - regs[INSTR_drr_reg2(instr)];
regs[INSTR_drr_dest(instr)] = r;
flag = (r == 0);
}
break;
case pb_bin_op_pb_signal_pb_subz_pb_immediate:
{
iptr r = regs[INSTR_dri_reg(instr)] - (uptr)INSTR_dri_imm(instr);
regs[INSTR_dri_dest(instr)] = r;
flag = (r == 0);
}
break;
case pb_cmp_op_pb_eq_pb_register:
flag = regs[INSTR_dr_dest(instr)] == regs[INSTR_dr_reg(instr)];
break;
case pb_cmp_op_pb_eq_pb_immediate:
flag = regs[INSTR_di_dest(instr)] == (uptr)INSTR_di_imm(instr);
break;
case pb_cmp_op_pb_lt_pb_register:
flag = (iptr)regs[INSTR_dr_dest(instr)] < (iptr)regs[INSTR_dr_reg(instr)];
break;
case pb_cmp_op_pb_lt_pb_immediate:
flag = (iptr)regs[INSTR_di_dest(instr)] < (iptr)INSTR_di_imm(instr);
break;
case pb_cmp_op_pb_gt_pb_register:
flag = (iptr)regs[INSTR_dr_dest(instr)] > (iptr)regs[INSTR_dr_reg(instr)];
break;
case pb_cmp_op_pb_gt_pb_immediate:
flag = (iptr)regs[INSTR_di_dest(instr)] > (iptr)INSTR_di_imm(instr);
break;
case pb_cmp_op_pb_le_pb_register:
flag = (iptr)regs[INSTR_dr_dest(instr)] <= (iptr)regs[INSTR_dr_reg(instr)];
break;
case pb_cmp_op_pb_le_pb_immediate:
flag = (iptr)regs[INSTR_di_dest(instr)] <= (iptr)INSTR_di_imm(instr);
break;
case pb_cmp_op_pb_ge_pb_register:
flag = (iptr)regs[INSTR_dr_dest(instr)] >= (iptr)regs[INSTR_dr_reg(instr)];
break;
case pb_cmp_op_pb_ge_pb_immediate:
flag = (iptr)regs[INSTR_di_dest(instr)] >= (iptr)INSTR_di_imm(instr);
break;
case pb_cmp_op_pb_ab_pb_register:
flag = regs[INSTR_dr_dest(instr)] > regs[INSTR_dr_reg(instr)];
break;
case pb_cmp_op_pb_ab_pb_immediate:
flag = regs[INSTR_di_dest(instr)] > (uptr)INSTR_di_imm(instr);
break;
case pb_cmp_op_pb_bl_pb_register:
flag = regs[INSTR_dr_dest(instr)] < regs[INSTR_dr_reg(instr)];
break;
case pb_cmp_op_pb_bl_pb_immediate:
flag = regs[INSTR_di_dest(instr)] < (uptr)INSTR_di_imm(instr);
break;
case pb_cmp_op_pb_cs_pb_register:
flag = ((regs[INSTR_dr_dest(instr)] & regs[INSTR_dr_reg(instr)]) != 0);
break;
case pb_cmp_op_pb_cs_pb_immediate:
flag = ((regs[INSTR_di_dest(instr)] & (uptr)INSTR_di_imm(instr)) != 0);
break;
case pb_cmp_op_pb_cc_pb_register:
flag = ((regs[INSTR_dr_dest(instr)] & regs[INSTR_dr_reg(instr)]) == 0);
break;
case pb_cmp_op_pb_cc_pb_immediate:
flag = ((regs[INSTR_di_dest(instr)] & (uptr)INSTR_di_imm(instr)) == 0);
break;
case pb_fp_bin_op_pb_add_pb_register:
fpregs[INSTR_drr_dest(instr)] = fpregs[INSTR_drr_reg1(instr)] + fpregs[INSTR_drr_reg2(instr)];
break;
case pb_fp_bin_op_pb_sub_pb_register:
fpregs[INSTR_drr_dest(instr)] = fpregs[INSTR_drr_reg1(instr)] - fpregs[INSTR_drr_reg2(instr)];
break;
case pb_fp_bin_op_pb_mul_pb_register:
fpregs[INSTR_drr_dest(instr)] = fpregs[INSTR_drr_reg1(instr)] * fpregs[INSTR_drr_reg2(instr)];
break;
case pb_fp_bin_op_pb_div_pb_register:
fpregs[INSTR_drr_dest(instr)] = fpregs[INSTR_drr_reg1(instr)] / fpregs[INSTR_drr_reg2(instr)];
break;
case pb_un_op_pb_not_pb_register:
regs[INSTR_dr_dest(instr)] = ~(regs[INSTR_dr_reg(instr)]);
break;
case pb_un_op_pb_not_pb_immediate:
regs[INSTR_di_dest(instr)] = ~((uptr)(iptr)INSTR_di_imm(instr));
break;
case pb_fp_un_op_pb_sqrt_pb_register:
fpregs[INSTR_dr_dest(instr)] = sqrt(fpregs[INSTR_dr_reg(instr)]);
break;
case pb_fp_cmp_op_pb_eq_pb_register:
flag = fpregs[INSTR_dr_dest(instr)] == fpregs[INSTR_dr_reg(instr)];
break;
case pb_fp_cmp_op_pb_lt_pb_register:
flag = fpregs[INSTR_dr_dest(instr)] < fpregs[INSTR_dr_reg(instr)];
break;
case pb_fp_cmp_op_pb_le_pb_register:
flag = fpregs[INSTR_dr_dest(instr)] <= fpregs[INSTR_dr_reg(instr)];
break;
case pb_rev_op_pb_int16_pb_register:
#if ptr_bits == 64
regs[INSTR_dr_dest(instr)] = ((uptr)((iptr)(regs[INSTR_dr_reg(instr)] << 56) >> 48)
| ((regs[INSTR_dr_reg(instr)] & 0xFF00) >> 8));
#else
regs[INSTR_dr_dest(instr)] = ((uptr)((iptr)(regs[INSTR_dr_reg(instr)] << 24) >> 16)
| ((regs[INSTR_dr_reg(instr)] & 0xFF00) >> 8));
#endif
break;
case pb_rev_op_pb_uint16_pb_register:
regs[INSTR_dr_dest(instr)] = (((regs[INSTR_dr_reg(instr)] & 0x00FF) << 8)
| ((regs[INSTR_dr_reg(instr)] & 0xFF00) >> 8));
break;
case pb_rev_op_pb_int32_pb_register:
#if ptr_bits == 64
regs[INSTR_dr_dest(instr)] = ((uptr)((iptr)(regs[INSTR_dr_reg(instr)] << 56) >> 32)
| ((regs[INSTR_dr_reg(instr)] & (uptr)0xFF000000) >> 24)
| ((regs[INSTR_dr_reg(instr)] & (uptr)0x00FF0000) >> 8)
| ((regs[INSTR_dr_reg(instr)] & (uptr)0x0000FF00) << 8));
#else
regs[INSTR_dr_dest(instr)] = ((regs[INSTR_dr_reg(instr)] << 24)
| ((regs[INSTR_dr_reg(instr)] & (uptr)0xFF000000) >> 24)
| ((regs[INSTR_dr_reg(instr)] & (uptr)0x00FF0000) >> 8)
| ((regs[INSTR_dr_reg(instr)] & (uptr)0x0000FF00) << 8));
#endif
break;
case pb_rev_op_pb_uint32_pb_register:
regs[INSTR_dr_dest(instr)] = (((regs[INSTR_dr_reg(instr)] & (uptr)0x000000FF) << 24)
| ((regs[INSTR_dr_reg(instr)] & (uptr)0xFF000000) >> 24)
| ((regs[INSTR_dr_reg(instr)] & (uptr)0x00FF0000) >> 8)
| ((regs[INSTR_dr_reg(instr)] & (uptr)0x0000FF00) << 8));
break;
case pb_rev_op_pb_int64_pb_register:
#if ptr_bits == 64
regs[INSTR_dr_dest(instr)] = (((regs[INSTR_dr_reg(instr)] & (uptr)0x00000000000000FF) << 56)
| ((regs[INSTR_dr_reg(instr)] & (uptr)0x000000000000FF00) << 40)
| ((regs[INSTR_dr_reg(instr)] & (uptr)0x0000000000FF0000) << 24)
| ((regs[INSTR_dr_reg(instr)] & (uptr)0x00000000FF000000) << 8)
| ((regs[INSTR_dr_reg(instr)] & (uptr)0x000000FF00000000) >> 8)
| ((regs[INSTR_dr_reg(instr)] & (uptr)0x0000FF0000000000) >> 24)
| ((regs[INSTR_dr_reg(instr)] & (uptr)0x00FF000000000000) >> 40)
| ((regs[INSTR_dr_reg(instr)] & (uptr)0xFF00000000000000) >> 56));
#else
regs[INSTR_dr_dest(instr)] = (((regs[INSTR_dr_reg(instr)] & (uptr)0x000000FF) << 24)
| ((regs[INSTR_dr_reg(instr)] & (uptr)0xFF000000) >> 24)
| ((regs[INSTR_dr_reg(instr)] & (uptr)0x00FF0000) >> 8)
| ((regs[INSTR_dr_reg(instr)] & (uptr)0x0000FF00) << 8));
#endif
break;
case pb_ld_op_pb_int8_pb_register:
regs[INSTR_drr_dest(instr)] = *(int8_t *)TO_VOIDP(regs[INSTR_drr_reg1(instr)] + regs[INSTR_drr_reg2(instr)]);
break;
case pb_ld_op_pb_int8_pb_immediate:
regs[INSTR_dri_dest(instr)] = *(int8_t *)TO_VOIDP(regs[INSTR_dri_reg(instr)] + INSTR_dri_imm(instr));
break;
case pb_ld_op_pb_uint8_pb_register:
regs[INSTR_drr_dest(instr)] = *(uint8_t *)TO_VOIDP(regs[INSTR_drr_reg1(instr)] + regs[INSTR_drr_reg2(instr)]);
break;
case pb_ld_op_pb_uint8_pb_immediate:
regs[INSTR_dri_dest(instr)] = *(uint8_t *)TO_VOIDP(regs[INSTR_dri_reg(instr)] + INSTR_dri_imm(instr));
break;
case pb_ld_op_pb_int16_pb_register:
regs[INSTR_drr_dest(instr)] = *(int16_t *)TO_VOIDP(regs[INSTR_drr_reg1(instr)] + regs[INSTR_drr_reg2(instr)]);
break;
case pb_ld_op_pb_int16_pb_immediate:
regs[INSTR_dri_dest(instr)] = *(int16_t *)TO_VOIDP(regs[INSTR_dri_reg(instr)] + INSTR_dri_imm(instr));
break;
case pb_ld_op_pb_uint16_pb_register:
regs[INSTR_drr_dest(instr)] = *(uint16_t *)TO_VOIDP(regs[INSTR_drr_reg1(instr)] + regs[INSTR_drr_reg2(instr)]);
break;
case pb_ld_op_pb_uint16_pb_immediate:
regs[INSTR_dri_dest(instr)] = *(uint16_t *)TO_VOIDP(regs[INSTR_dri_reg(instr)] + INSTR_dri_imm(instr));
break;
case pb_ld_op_pb_int32_pb_register:
regs[INSTR_drr_dest(instr)] = *(int32_t *)TO_VOIDP(regs[INSTR_drr_reg1(instr)] + regs[INSTR_drr_reg2(instr)]);
break;
case pb_ld_op_pb_int32_pb_immediate:
regs[INSTR_dri_dest(instr)] = *(int32_t *)TO_VOIDP(regs[INSTR_dri_reg(instr)] + INSTR_dri_imm(instr));
break;
case pb_ld_op_pb_uint32_pb_register:
regs[INSTR_drr_dest(instr)] = *(uint32_t *)TO_VOIDP(regs[INSTR_drr_reg1(instr)] + regs[INSTR_drr_reg2(instr)]);
break;
case pb_ld_op_pb_uint32_pb_immediate:
regs[INSTR_dri_dest(instr)] = *(uint32_t *)TO_VOIDP(regs[INSTR_dri_reg(instr)] + INSTR_dri_imm(instr));
break;
case pb_ld_op_pb_int64_pb_register:
regs[INSTR_drr_dest(instr)] = *(uptr *)TO_VOIDP(regs[INSTR_drr_reg1(instr)] + regs[INSTR_drr_reg2(instr)]);
break;
case pb_ld_op_pb_int64_pb_immediate:
regs[INSTR_dri_dest(instr)] = *(uptr *)TO_VOIDP(regs[INSTR_dri_reg(instr)] + INSTR_dri_imm(instr));
break;
case pb_ld_op_pb_double_pb_register:
fpregs[INSTR_drr_dest(instr)] = *(double *)TO_VOIDP(regs[INSTR_drr_reg1(instr)] + regs[INSTR_drr_reg2(instr)]);
break;
case pb_ld_op_pb_double_pb_immediate:
fpregs[INSTR_dri_dest(instr)] = *(double *)TO_VOIDP(regs[INSTR_dri_reg(instr)] + INSTR_dri_imm(instr));
break;
case pb_ld_op_pb_single_pb_register:
fpregs[INSTR_drr_dest(instr)] = *(float *)TO_VOIDP(regs[INSTR_drr_reg1(instr)] + regs[INSTR_drr_reg2(instr)]);
break;
case pb_ld_op_pb_single_pb_immediate:
fpregs[INSTR_dri_dest(instr)] = *(float *)TO_VOIDP(regs[INSTR_dri_reg(instr)] + INSTR_dri_imm(instr));
break;
case pb_st_op_pb_int8_pb_register:
*(char *)TO_VOIDP(regs[INSTR_drr_reg1(instr)] + regs[INSTR_drr_reg2(instr)]) = (char)regs[INSTR_drr_dest(instr)];
break;
case pb_st_op_pb_int8_pb_immediate:
*(char *)TO_VOIDP(regs[INSTR_dri_reg(instr)] + INSTR_dri_imm(instr)) = (char)regs[INSTR_dri_dest(instr)];
break;
case pb_st_op_pb_int16_pb_register:
*(short *)TO_VOIDP(regs[INSTR_drr_reg1(instr)] + regs[INSTR_drr_reg2(instr)]) = (short)regs[INSTR_drr_dest(instr)];
break;
case pb_st_op_pb_int16_pb_immediate:
*(short *)TO_VOIDP(regs[INSTR_dri_reg(instr)] + INSTR_dri_imm(instr)) = (short)regs[INSTR_dri_dest(instr)];
break;
case pb_st_op_pb_int32_pb_register:
*(int *)TO_VOIDP(regs[INSTR_drr_reg1(instr)] + regs[INSTR_drr_reg2(instr)]) = (int)regs[INSTR_drr_dest(instr)];
break;
case pb_st_op_pb_int32_pb_immediate:
*(int *)TO_VOIDP(regs[INSTR_dri_reg(instr)] + INSTR_dri_imm(instr)) = (int)regs[INSTR_dri_dest(instr)];
break;
case pb_st_op_pb_int64_pb_register:
*(uptr *)TO_VOIDP(regs[INSTR_drr_reg1(instr)] + regs[INSTR_drr_reg2(instr)]) = regs[INSTR_drr_dest(instr)];
break;
case pb_st_op_pb_int64_pb_immediate:
*(uptr *)TO_VOIDP(regs[INSTR_dri_reg(instr)] + INSTR_dri_imm(instr)) = regs[INSTR_dri_dest(instr)];
break;
case pb_st_op_pb_double_pb_register:
*(double *)TO_VOIDP(regs[INSTR_drr_reg1(instr)] + regs[INSTR_drr_reg2(instr)]) = fpregs[INSTR_drr_dest(instr)];
break;
case pb_st_op_pb_double_pb_immediate:
*(double *)TO_VOIDP(regs[INSTR_dri_reg(instr)] + INSTR_dri_imm(instr)) = fpregs[INSTR_dri_dest(instr)];
break;
case pb_st_op_pb_single_pb_register:
*(float *)TO_VOIDP(regs[INSTR_drr_reg1(instr)] + regs[INSTR_drr_reg2(instr)]) = fpregs[INSTR_drr_dest(instr)];
break;
case pb_st_op_pb_single_pb_immediate:
*(float *)TO_VOIDP(regs[INSTR_dri_reg(instr)] + INSTR_dri_imm(instr)) = fpregs[INSTR_dri_dest(instr)];
break;
case pb_b_op_pb_fals_pb_register:
if (!flag) {
next_ip = (instruction_t *)TO_VOIDP(regs[INSTR_dr_reg(instr)]);
TRACE(printf("branch %p -> %p\n", ip, next_ip), { branch_from = ip; branch_to = next_ip; });
}
break;
case pb_b_op_pb_fals_pb_immediate:
if (!flag) {
next_ip = (instruction_t *)TO_VOIDP((char *)next_ip + INSTR_i_imm(instr));
TRACE(printf("branch %p -> %p\n", ip, next_ip), { branch_from = ip; branch_to = next_ip; });
}
break;
case pb_b_op_pb_true_pb_register:
if (flag) {
next_ip = (instruction_t *)TO_VOIDP(regs[INSTR_dr_reg(instr)]);
TRACE(printf("branch %p -> %p\n", ip, next_ip), { branch_from = ip; branch_to = next_ip; });
}
break;
case pb_b_op_pb_true_pb_immediate:
if (flag) {
next_ip = (instruction_t *)TO_VOIDP((char *)next_ip + INSTR_i_imm(instr));
TRACE(printf("branch %p -> %p\n", ip, next_ip), { branch_from = ip; branch_to = next_ip; });
}
break;
case pb_b_op_pb_always_pb_register:
next_ip = (instruction_t *)TO_VOIDP(regs[INSTR_dr_reg(instr)]);
TRACE(printf("jump %p -> %p\n", ip, next_ip), { jump_from = ip; jump_to = next_ip; });
break;
case pb_b_op_pb_always_pb_immediate:
next_ip = (instruction_t *)TO_VOIDP((char *)next_ip + INSTR_i_imm(instr));
TRACE(printf("jump %p -> %p\n", ip, next_ip), { jump_from = ip; jump_to = next_ip; });
break;
case pb_bs_op_pb_register:
next_ip = (instruction_t *)TO_VOIDP(*(uptr *)TO_VOIDP(regs[INSTR_dr_dest(instr)] + regs[INSTR_dr_reg(instr)]));
TRACE(printf("jump %p -> %p\n", ip, next_ip), { jump_from = ip; jump_to = next_ip; });
break;
case pb_bs_op_pb_immediate:
next_ip = (instruction_t *)TO_VOIDP(*(uptr *)TO_VOIDP(regs[INSTR_di_dest(instr)] + INSTR_di_imm(instr)));
TRACE(printf("jump %p -> %p\n", ip, next_ip), { jump_from = ip; jump_to = next_ip; });
break;
case pb_return:
return; /* <--- not break */
case pb_adr:
regs[INSTR_di_dest(instr)] = (uptr)TO_PTR(next_ip) + INSTR_di_imm(instr);
break;
case pb_interp:
{
void *code = TO_VOIDP(regs[INSTR_d_dest(instr)]);
TRACE(printf("interp %p -> %p\n", ip, code), { interp_from = ip; interp_to = (instruction_t *)regs[0]; });
S_pb_interp((ptr)regs[0], code);
}
break;
case pb_call:
{
void *proc = TO_VOIDP(regs[INSTR_dri_dest(instr)]);
TRACE(printf("call %p -> %p %x\n", ip, proc, INSTR_dri_imm(instr)), { call_from = ip; call_to = proc; });
switch (INSTR_dri_imm(instr)) {
case pb_call_void:
((pb_void_t)proc)();
break;
case pb_call_void_uptr:
((pb_void_uptr_t)proc)(regs[Carg1]);
break;
case pb_call_void_int32:
((pb_void_int32_t)proc)(regs[Carg1]);
break;
case pb_call_void_uint32:
((pb_void_uint32_t)proc)(regs[Carg1]);
break;
case pb_call_void_voids:
((pb_void_voids_t)proc)(TO_VOIDP(regs[Carg1]));
break;
case pb_call_void_uptr_uint32:
((pb_void_uptr_uint32_t)proc)(regs[Carg1], regs[Carg2]);
break;
case pb_call_void_int32_uptr:
((pb_void_int32_uptr_t)proc)(regs[Carg1], regs[Carg2]);
break;
case pb_call_void_int32_voids:
((pb_void_int32_voids_t)proc)(regs[Carg1], TO_VOIDP(regs[Carg2]));
break;
case pb_call_void_uptr_voids:
((pb_void_uptr_voids_t)proc)(regs[Carg1], TO_VOIDP(regs[Carg2]));
break;
case pb_call_void_int32_int32:
((pb_void_int32_int32_t)proc)(regs[Carg1], regs[Carg2]);
break;
case pb_call_void_uptr_uptr:
((pb_void_uptr_uptr_t)proc)(regs[Carg1], regs[Carg2]);
break;
case pb_call_void_voids_voids:
((pb_void_voids_voids_t)proc)(TO_VOIDP(regs[Carg1]), TO_VOIDP(regs[Carg2]));
break;
case pb_call_void_uptr_uptr_uptr:
((pb_void_uptr_uptr_uptr_t)proc)(regs[Carg1], regs[Carg2], regs[Carg3]);
break;
case pb_call_void_uptr_uptr_uptr_uptr_uptr:
((pb_void_uptr_uptr_uptr_uptr_uptr_t)proc)(regs[Carg1], regs[Carg2], regs[Carg3],
regs[Carg4], regs[Carg5]);
break;
case pb_call_int32:
regs[Cretval] = ((pb_int32_t)proc)();
break;
case pb_call_int32_uptr:
regs[Cretval] = ((pb_int32_uptr_t)proc)(regs[Carg1]);
break;
case pb_call_int32_voids:
regs[Cretval] = ((pb_int32_voids_t)proc)(TO_VOIDP(regs[Carg1]));
break;
case pb_call_int32_uptr_int32:
regs[Cretval] = ((pb_int32_uptr_int32_t)proc)(regs[Carg1], regs[Carg2]);
break;
case pb_call_int32_uptr_uptr:
regs[Cretval] = ((pb_int32_uptr_uptr_t)proc)(regs[Carg1], regs[Carg2]);
break;
case pb_call_int32_int32_int32:
regs[Cretval] = ((pb_int32_int32_int32_t)proc)(regs[Carg1], regs[Carg2]);
break;
case pb_call_int32_voids_int32:
regs[Cretval] = ((pb_int32_voids_int32_t)proc)(TO_VOIDP(regs[Carg1]), regs[Carg2]);
break;
case pb_call_int32_int32_voids:
regs[Cretval] = ((pb_int32_int32_voids_t)proc)(regs[Carg1], TO_VOIDP(regs[Carg2]));
break;
case pb_call_int32_double_double_double_double_double_double:
regs[Cretval] = ((pb_int32_double_double_double_double_double_double_t)proc)(fpregs[Cfparg1], fpregs[Cfparg2], fpregs[Cfparg3],
fpregs[Cfparg4], fpregs[Cfparg5], fpregs[Cfparg6]);
break;
case pb_call_uint32:
regs[Cretval] = ((pb_uint32_t)proc)();
break;
case pb_call_double_double:
fpregs[Cfpretval] = ((pb_double_double_t)proc)(fpregs[Cfparg1]);
break;
case pb_call_double_uptr:
fpregs[Cfpretval] = ((pb_double_uptr_t)proc)(regs[Carg1]);
break;
case pb_call_double_double_double:
fpregs[Cfpretval] = ((pb_double_double_double_t)proc)(fpregs[Cfparg1], fpregs[Cfparg2]);
break;
case pb_call_int32_int32:
regs[Cretval] = ((pb_int32_int32_t)proc)(regs[Carg1]);
break;
case pb_call_int32_int32_uptr:
regs[Cretval] = ((pb_int32_int32_uptr_t)proc)(regs[Carg1], regs[Carg2]);
break;
case pb_call_int32_voids_voids_voids_voids_uptr:
regs[Cretval] = ((pb_int32_voids_voids_voids_voids_uptr_t)proc)(TO_VOIDP(regs[Carg1]), TO_VOIDP(regs[Carg2]), TO_VOIDP(regs[Carg3]),
TO_VOIDP(regs[Carg4]), regs[Carg5]);
break;
case pb_call_uptr:
regs[Cretval] = ((pb_uptr_t)proc)();
break;
case pb_call_uptr_uptr:
regs[Cretval] = ((pb_uptr_uptr_t)proc)(regs[Carg1]);
break;
case pb_call_uptr_int32:
regs[Cretval] = ((pb_uptr_int32_t)proc)(regs[Carg1]);
break;
case pb_call_uptr_voids:
regs[Cretval] = ((pb_uptr_voids_t)proc)(TO_VOIDP(regs[Carg1]));
break;
case pb_call_uptr_uptr_uptr:
regs[Cretval] = ((pb_uptr_uptr_uptr_t)proc)(regs[Carg1], regs[Carg2]);
break;
case pb_call_uptr_uptr_int32:
regs[Cretval] = ((pb_uptr_uptr_int32_t)proc)(regs[Carg1], regs[Carg2]);
break;
case pb_call_uptr_uptr_int64:
#if ptr_bits == 64
regs[Cretval] = ((pb_uptr_uptr_int64_t)proc)(regs[Carg1], regs[Carg2]);
#else
regs[Cretval] = ((pb_uptr_uptr_int64_t)proc)(regs[Carg1], regs[Carg2] | ((int64_t)regs[Carg3] << 32));
#endif
break;
case pb_call_uptr_int32_uptr:
regs[Cretval] = ((pb_uptr_int32_uptr_t)proc)(regs[Carg1], regs[Carg2]);
break;
case pb_call_uptr_voids_uptr:
regs[Cretval] = ((pb_uptr_voids_uptr_t)proc)(TO_VOIDP(regs[Carg1]), regs[Carg2]);
break;
case pb_call_uptr_uptr_voids:
regs[Cretval] = ((pb_uptr_uptr_voids_t)proc)(regs[Carg1], TO_VOIDP(regs[Carg2]));
break;
case pb_call_uptr_voids_int32:
regs[Cretval] = ((pb_uptr_voids_int32_t)proc)(TO_VOIDP(regs[Carg1]), regs[Carg2]);
break;
case pb_call_uptr_voids_voids:
regs[Cretval] = ((pb_uptr_voids_voids_t)proc)(TO_VOIDP(regs[Carg1]), TO_VOIDP(regs[Carg2]));
break;
case pb_call_uptr_uptr_int32_int32:
regs[Cretval] = ((pb_uptr_uptr_int32_int32_t)proc)(regs[Carg1], regs[Carg2], regs[Carg3]);
break;
case pb_call_uptr_voids_int32_int32:
regs[Cretval] = ((pb_uptr_voids_int32_int32_t)proc)(TO_VOIDP(regs[Carg1]), regs[Carg2], regs[Carg3]);
break;
case pb_call_uptr_voids_uptr_uptr:
regs[Cretval] = ((pb_uptr_voids_uptr_uptr_t)proc)(TO_VOIDP(regs[Carg1]), regs[Carg2], regs[Carg3]);
break;
case pb_call_uptr_uptr_uptr_int32:
regs[Cretval] = ((pb_uptr_uptr_uptr_int32_t)proc)(regs[Carg1], regs[Carg2], regs[Carg3]);
break;
case pb_call_uptr_uptr_uptr_uptr:
regs[Cretval] = ((pb_uptr_uptr_uptr_uptr_t)proc)(regs[Carg1], regs[Carg2], regs[Carg3]);
break;
case pb_call_uptr_int32_int32_uptr:
regs[Cretval] = ((pb_uptr_int32_int32_uptr_t)proc)(regs[Carg1], regs[Carg2], regs[Carg3]);
break;
case pb_call_uptr_int32_uptr_uptr_uptr:
regs[Cretval] = ((pb_uptr_int32_uptr_uptr_uptr_t)proc)(regs[Carg1], regs[Carg2], regs[Carg3],
regs[Carg4]);
break;
case pb_call_uptr_uptr_uptr_uptr_uptr:
regs[Cretval] = ((pb_uptr_uptr_uptr_uptr_uptr_t)proc)(regs[Carg1], regs[Carg2], regs[Carg3],
regs[Carg4]);
break;
case pb_call_uptr_int32_int32_uptr_uptr:
regs[Cretval] = ((pb_uptr_int32_int32_uptr_uptr_t)proc)(regs[Carg1], regs[Carg2], regs[Carg3],
regs[Carg4]);
break;
case pb_call_uptr_int32_voids_uptr_uptr:
regs[Cretval] = ((pb_uptr_int32_voids_uptr_uptr_t)proc)(regs[Carg1], TO_VOIDP(regs[Carg2]), regs[Carg3],
regs[Carg4]);
break;
case pb_call_uptr_uptr_uptr_uptr_uptr_int32:
regs[Cretval] = ((pb_uptr_uptr_uptr_uptr_uptr_int32_t)proc)(regs[Carg1], regs[Carg2], regs[Carg3],
regs[Carg4], regs[Carg5]);
break;
case pb_call_uptr_uptr_uptr_uptr_uptr_uptr:
regs[Cretval] = ((pb_uptr_uptr_uptr_uptr_uptr_uptr_t)proc)(regs[Carg1], regs[Carg2], regs[Carg3],
regs[Carg4], regs[Carg5]);
break;
case pb_call_uptr_voids_voids_voids_voids_uptr:
regs[Cretval] = ((pb_uptr_voids_voids_voids_voids_uptr_t)proc)(TO_VOIDP(regs[Carg1]), TO_VOIDP(regs[Carg2]), TO_VOIDP(regs[Carg3]),
TO_VOIDP(regs[Carg4]), regs[Carg5]);
break;
case pb_call_uptr_uptr_int32_uptr_uptr_uptr_uptr:
regs[Cretval] = ((pb_uptr_uptr_int32_uptr_uptr_uptr_uptr_t)proc)(regs[Carg1], regs[Carg2], regs[Carg3],
regs[Carg4], regs[Carg5], regs[Carg6]);
break;
case pb_call_uptr_uptr_uptr_uptr_uptr_uptr_uptr:
regs[Cretval] = ((pb_uptr_uptr_uptr_uptr_uptr_uptr_uptr_t)proc)(regs[Carg1], regs[Carg2], regs[Carg3],
regs[Carg4], regs[Carg5], regs[Carg6]);
break;
case pb_call_uptr_uptr_uptr_uptr_uptr_uptr_uptr_int32:
regs[Cretval] = ((pb_uptr_uptr_uptr_uptr_uptr_uptr_uptr_int32_t)proc)(regs[Carg1], regs[Carg2], regs[Carg3],
regs[Carg4], regs[Carg5], regs[Carg6],
regs[Carg7]);
break;
case pb_call_uptr_uptr_uptr_uptr_uptr_uptr_uptr_uptr:
regs[Cretval] = ((pb_uptr_uptr_uptr_uptr_uptr_uptr_uptr_uptr_t)proc)(regs[Carg1], regs[Carg2], regs[Carg3],
regs[Carg4], regs[Carg5], regs[Carg6],
regs[Carg7]);
break;
case pb_call_uptr_double_double_double_double_double_double:
regs[Cretval] = ((pb_uptr_double_double_double_double_double_double_t)proc)(fpregs[Cfparg1], fpregs[Cfparg2], fpregs[Cfparg3],
fpregs[Cfparg4], fpregs[Cfparg5], fpregs[Cfparg6]);
break;
case pb_call_voids:
regs[Cretval] = TO_PTR(((pb_voids_t)proc)());
break;
case pb_call_voids_uptr:
regs[Cretval] = TO_PTR(((pb_voids_uptr_t)proc)(regs[Carg1]));
break;
default:
S_error_abort("unsupported call prototype");
break;
}
}
break;
case pb_inc_pb_register:
{
uptr r = *(uptr *)TO_VOIDP(regs[INSTR_dr_dest(instr)]) + regs[INSTR_dr_reg(instr)];
*(uptr *)TO_VOIDP(regs[INSTR_dr_dest(instr)]) = r;
flag = (r == 0);
}
break;
case pb_inc_pb_immediate:
{
uptr r = *(uptr *)TO_VOIDP(regs[INSTR_di_dest(instr)]) + INSTR_di_imm(instr);
*(uptr *)TO_VOIDP(regs[INSTR_di_dest(instr)]) = r;
flag = (r == 0);
}
break;
case pb_lock:
{
uptr *l = TO_VOIDP(regs[INSTR_d_dest(instr)]);
if (*l == 0) {
*l = 1;
flag = 1;
} else
flag = 0;
}
break;
case pb_cas:
{
uptr *l = TO_VOIDP(regs[INSTR_drr_dest(instr)]);
uptr old = regs[INSTR_drr_reg1(instr)];
uptr new = regs[INSTR_drr_reg2(instr)];
if (*l == old) {
*l = new;
flag = 1;
} else
flag = 0;
}
break;
default:
S_error_abort("illegal pb instruction");
break;
}
ip = next_ip;
}
}