示例#1
0
文件: vm_core.c 项目: dev-zzo/mette
static void vm_save_frame(vm_context_t *ctx, uint8_t *pc)
{
	vm_callframe_t *frame;

	frame = vm_alloc(sizeof(*frame));
	frame->return_pc = pc;
	frame->locals = ctx->locals;
	frame->dstack_top = vm_stack_top(ctx->dstack);

	vm_stack_push(ctx->cstack, (vm_operand_t)frame);

	ctx->locals = NULL;
}
示例#2
0
文件: thread.c 项目: def44/mate
int thread_start(struct object *o) {
	struct thread *t;
	struct frame *frame;
	struct vm_stack *vm_stack;
	struct operand_stack *operand_stack;

	t = object_get_thread(o);
	vm_stack = t->vm_stack;

	if (t == NULL) {
		fprintf(stderr, "mvm: thread not initialized!\n");
		mvm_halt();
	}

	if (t->state != new_state) {
		fprintf(stderr, "mvm: thread cannot be started more than once!\n");
		mvm_halt();
	}

	t->ref = object_get_ref(o);

#ifdef DMP
	if (t->dmp != NULL)
		thread_dmp_thread_creation(t->dmp);
#endif	

	vm_stack_push(vm_stack, "thread_start", 0, 0, 0, 0, 0);
	frame = vm_stack_peek(vm_stack);
	operand_stack = frame_get_operand_stack(frame);
	operand_stack_push(operand_stack, t->ref);

	if (thread_pthread_create(t, thread_run0) != 0)
		mvm_halt();

	return 0;
}
示例#3
0
文件: vm_core.c 项目: dev-zzo/mette
/* Emulate one VM insn. */
void vm_step(vm_context_t *ctx)
{
#include "vm_opcodes.switch.tab"
	vm_operand_t r0, r1;
	vm_operand_t buf[3];
	uint8_t *pc = ctx->pc;
	unsigned ops_in, ops_out = 0;
	uint8_t opcode;
	
	opcode = *pc;
	DBGPRINT("vm_step: %08x -> %02x ", pc, opcode);
	pc += 1;
	ops_in = opcode >> 6; /* 2 highest bits make for operand count. */
	opcode &= 0x3F;
	DBGPRINT("(%s / %d)\n", vm_insn_to_name[opcode], ops_in);
	vm_stack_pop3(ctx->dstack, buf, ops_in);

	goto *(&&op_invalid + offtab[opcode]);
	
op_invalid:
	vm_panic("vm_step: unknown opcode.");

op_ADD:
	r0 = ARG2 + ARG1;
	goto push_1;
op_SUB:
	r0 = ARG2 - ARG1;
	goto push_1;
op_MULU: {
	TARGET_MULU(ARG1, ARG2, r0, r1);
	goto push_2;
}
op_MULS: {
	TARGET_MULS(ARG1, ARG2, r0, r1);
	goto push_2;
}
op_DIVU: {
	TARGET_DIVU(ARG2, ARG1);
	goto push_2;
}
op_DIVS: {
	TARGET_DIVS(ARG2, ARG1);
	goto push_2;
}
op_AND:
	r0 = ARG1 & ARG2;
	goto push_1;
op_OR:
	r0 = ARG1 | ARG2;
	goto push_1;
op_XOR:
	r0 = ARG1 ^ ARG2;
	goto push_1;
op_NOT:
	r0 = ~ARG1;
	goto push_1;
op_LSL:
	r0 = ARG2 << ARG1;
	goto push_1;
op_LSR:
	r0 = ((vm_uoperand_t)ARG2) >> ARG1;
	goto push_1;
op_ASR:
	r0 = ((vm_soperand_t)ARG2) >> ARG1;
	goto push_1;
op_CMP_LT:
	r0 = ((vm_soperand_t)ARG1) < ((vm_soperand_t)ARG2);
	goto push_1;
op_CMP_GT:
	r0 = ((vm_soperand_t)ARG1) > ((vm_soperand_t)ARG2);
	goto push_1;
op_CMP_B:
	r0 = ((vm_uoperand_t)ARG1) < ((vm_uoperand_t)ARG2);
	goto push_1;
op_CMP_A:
	r0 = ((vm_uoperand_t)ARG1) > ((vm_uoperand_t)ARG2);
	goto push_1;
op_CMP_EQ:
	r0 = ARG2 == ARG1;
	goto push_1;
op_LDC_0:
	r0 = 0;
	goto push_1;
op_LDC_1: 
	r0 = 1;
	goto push_1;
op_LDC_2: 
	r0 = 2;
	goto push_1;
op_LDC_UB:
	r0 = (vm_uoperand_t)*(uint8_t *)(pc);
	pc += 1;
	goto push_1;
op_LDC_SB:
	r0 = (vm_soperand_t)*(int8_t *)(pc);
	pc += 1;
	goto push_1;
op_LDC_W:
	r0 = vm_fetch32_ua(pc);
	pc += 4;
	goto push_1;
op_LEA:
	r0 = vm_fetch32_ua(pc);
	DBGPRINT("vm_step: PCREL offset %08x -> ", r0);
	pc += 4;
	r0 += (vm_uoperand_t)pc;
	DBGPRINT("%08x\n", r0);
	goto push_1;
op_LDM_UB:
	r0 = (vm_uoperand_t)*(uint8_t *)(ARG1);
	goto push_1;
op_LDM_SB:
	r0 = (vm_soperand_t)*(int8_t *)(ARG1);
	goto push_1;
op_LDM_UH:
	r0 = (vm_uoperand_t)*(uint16_t *)(ARG1);
	goto push_1;
op_LDM_SH:
	r0 = (vm_soperand_t)*(int16_t *)(ARG1);
	goto push_1;
op_LDM_W:
	r0 = *(vm_operand_t *)(ARG1);
	goto push_1;
op_STM_B:
	*(uint8_t *)(ARG1) = (uint8_t)ARG2;
	DBGPRINT("vm_step: %08x -> %08x\n", ARG2, ARG1);
	goto push_none;
op_STM_H:
	*(uint16_t *)(ARG1) = (uint16_t)ARG2;
	DBGPRINT("vm_step: %08x -> %08x\n", ARG2, ARG1);
	goto push_none;
op_STM_W:
	*(vm_operand_t *)(ARG1) = ARG2;
	DBGPRINT("vm_step: %08x -> %08x\n", ARG2, ARG1);
	goto push_none;
op_LOCALS: {
	uint8_t count = *(uint8_t *)(pc);
	pc += 1;
	ctx->locals = (vm_locals_t *)vm_alloc(sizeof(vm_locals_t) + (count - 1) * sizeof(vm_operand_t));
	ctx->locals->count = count;
	goto push_none;
}
op_LDLOC: {
	uint8_t index = *(uint8_t *)(pc);
	pc += 1;
	if (!ctx->locals) {
		vm_panic("vm_step: accessing locals where none have been allocated.");
	}
	if (index >= ctx->locals->count) {
		vm_panic("vm_step: local index out of bounds.");
	}
	r0 = ctx->locals->data[index];
	goto push_1;
}
op_STLOC: {
	uint8_t index = *(uint8_t *)(pc);
	pc += 1;
	if (!ctx->locals) {
		vm_panic("vm_step: accessing locals where none have been allocated.");
	}
	if (index >= ctx->locals->count) {
		vm_panic("vm_step: local index out of bounds.");
	}
	ctx->locals->data[index] = ARG1;
	goto push_none;
}
op_DUP:
	r1 = r0 = ARG1;
	goto push_2;
op_SWAP: {
	r1 = ARG1;
	r0 = ARG2;
	goto push_2;
}
op_POP:
	goto push_none;
op_BR: {
	int8_t offset = *(int8_t *)(pc);
	pc += 1;
	pc = pc + offset;
	goto push_none;
}
op_BR_T: {
	int8_t offset = *(int8_t *)(pc);
	pc += 1;
	if (ARG1) {
		pc = pc + offset;
	}
	goto push_none;
}
op_BR_F: {
	int8_t offset = *(int8_t *)(pc);
	pc += 1;
	if (!ARG1) {
		pc = pc + offset;
	}
	goto push_none;
}
op_CALL: {
	int32_t offset = (int32_t)vm_fetch32_ua(pc);
	pc += 4;
	vm_save_frame(ctx, pc);
	pc += offset;
	DBGPRINT("\n");
	goto push_none;
}
op_RET: {
	vm_callframe_t *frame;

	vm_free(ctx->locals);
	frame = (vm_callframe_t *)vm_stack_pop(ctx->cstack);
	ctx->locals = frame->locals;
	pc = frame->return_pc;

	DBGPRINT("vm_step: stack balance on return: %d\n\n", frame->dstack_top - vm_stack_top(ctx->dstack));
	vm_free(frame);
	goto push_none;
}
op_ICALL: {
	vm_save_frame(ctx, pc);
	pc = (uint8_t *)ARG1;
	goto push_none;
}
op_IJMP: {
	pc = (uint8_t *)ARG1;
	goto push_none;
}
op_NCALL: {
	int index = vm_fetch16_ua(pc); /* thunk index */
	pc += 2;
	if (!ctx->module->ncalls_table) {
		vm_panic("vm_step: no ncalls defined, but a ncall insn encountered.");
	}
	vm_thunk_t thunk = (vm_thunk_t)ctx->module->ncalls_table[index];
	DBGPRINT("vm_step: NCALL: calling %d @%08X\n", index, thunk);
	thunk(ctx);
	goto push_none;
}

push_2:
	vm_stack_push(ctx->dstack, r1);
push_1:
	vm_stack_push(ctx->dstack, r0);
push_none:
	
	ctx->pc = pc;
	return;
}