diff runtime/builtinworkers.c @ 176:327bcf35e094

Add bytecode interpreter
author Mike Pavone <pavone@retrodev.com>
date Wed, 08 Jun 2011 23:24:29 -0700
parents bac2c74801f0
children e57c151f351e
line wrap: on
line diff
--- a/runtime/builtinworkers.c	Wed Jun 08 23:24:15 2011 -0700
+++ b/runtime/builtinworkers.c	Wed Jun 08 23:24:29 2011 -0700
@@ -99,3 +99,112 @@
 EndFuncNoLocals
 DISPATCH
 
+f_RunSP_Bytecode:
+sf_RunSP_Bytecode:
+	Param(0, TYPE_ARRAY)
+	Param(1, TYPE_BOXEDARRAY)
+
+	if(((t_Array *)cdata->params[0])->payload.Eltype->bp->type_id != TYPE_UINT32)
+	{
+		printf("Array has element type of %d, but bytecode must be an array with element type UInt32\n", ((t_Array *)cdata->params[0])->payload.Eltype->bp->type_id);
+		goto _exception;
+	}
+	my_cdata = cdata;
+	bytecode = (uint32_t *)(((t_Array *)cdata->params[0])+1);
+	for(idx = 2; idx < (bytecode[0]+2); ++idx)
+		if(bytecode[idx+1])
+		{
+			Param(idx, bytecode[idx+1])
+		}
+	cur_instruction = bytecode+idx;
+	while(idx < cdata->num_params)
+		release_ref(cdata->params[idx++]);
+	cdata->num_params = bytecode[0];
+	interp_consts = (object **)(((t_BoxedSP_Array *)cdata->params[1])+1);
+	lv_RunSP_Bytecode = alloc_stack(ct, sizeof(object *)*(bytecode[1]+1));
+	
+	PrepCall(bytecode[2])
+	
+	goto *interp_dispatch[*(++cur_instruction)&0xF];
+interp_call:
+	*lv_RunSP_Bytecode = cur_instruction;
+	
+	cdata->func = RES_1_RunSP_Bytecode;
+	cdata->num_params = *cur_instruction >> 24;
+	cdata->vars = lv_RunSP_Bytecode;
+	func = *cur_instruction >> 4 & 0xFFFFF;
+	DISPATCH
+r1_RunSP_Bytecode:
+	my_cdata = cdata->lastframe;
+	lv_RunSP_Bytecode = cdata->vars;
+	
+	interp_consts = (object **)(((t_BoxedSP_Array *)my_cdata->params[1])+1);
+	cur_instruction = *lv_RunSP_Bytecode;
+	goto *interp_dispatch[*(++cur_instruction)&0xF];
+interp_param:
+	op1 = (*cur_instruction >> 4) & 0x3FFF;
+	SetParam(*cur_instruction >> 24, op1 >= 0x2000 ? interp_consts[op1-0x2000] : lv_RunSP_Bytecode[op1])
+	goto *interp_dispatch[*(++cur_instruction)&0xF];
+interp_load:
+	op1 = (*cur_instruction >> 4) & 0x3FFF;
+	accum = op1 >= 0x2000 ? interp_consts[op1-0x2000] : lv_RunSP_Bytecode[op1];
+	goto *interp_dispatch[*(++cur_instruction)&0xF];
+interp_and:
+	op1 = (*cur_instruction >> 4) & 0x3FFF;
+	op2 = *cur_instruction >> 18;
+	if (!op1)
+	{
+		accum = accum && (op2 >= 0x2000 ? interp_consts[op2-0x2000] : lv_RunSP_Bytecode[op2]);
+	} else {
+		accum = (op1 >= 0x2000 ? interp_consts[op1-0x2000] : lv_RunSP_Bytecode[op1]) && (op2 >= 0x2000 ? interp_consts[op2-0x2000] : lv_RunSP_Bytecode[op2]);
+	}
+	goto *interp_dispatch[*(++cur_instruction)&0xF];
+interp_or:
+	op1 = (*cur_instruction >> 4) & 0x3FFF;
+	op2 = *cur_instruction >> 18;
+	if (!op1)
+	{
+		accum = accum || (op2 >= 0x2000 ? interp_consts[op2-0x2000] : lv_RunSP_Bytecode[op2]);
+	} else {
+		accum = (op1 >= 0x2000 ? interp_consts[op1-0x2000] : lv_RunSP_Bytecode[op1]) || (op2 >= 0x2000 ? interp_consts[op2-0x2000] : lv_RunSP_Bytecode[op2]);
+	}
+	goto *interp_dispatch[*(++cur_instruction)&0xF];
+interp_not:
+	accum = !accum;
+	goto *interp_dispatch[*(++cur_instruction)&0xF];
+interp_branch:
+	if (accum)
+		if (*cur_instruction & 0x8)
+			cur_instruction += *cur_instruction >> 5;
+		else
+			cur_instruction -= *cur_instruction >> 5;
+	else
+		cur_instruction++;
+	goto *interp_dispatch[*cur_instruction];
+interp_saveresult:
+	op1 = (*cur_instruction >> 4) & 0x1FFF;
+	lv_RunSP_Bytecode[op1] = cdata->params[*cur_instruction >> 24];
+	goto *interp_dispatch[*(++cur_instruction)&0xF];
+interp_addref:
+	op1 = (*cur_instruction >> 4) & 0x3FFF;
+	add_ref(op1 >= 0x2000 ? interp_consts[op1-0x2000] : (object *)lv_RunSP_Bytecode[op1]);
+	goto *interp_dispatch[*(++cur_instruction)&0xF];
+interp_release:
+	op1 = (*cur_instruction >> 4) & 0x3FFF;
+	release_ref(op1 >= 0x2000 ? interp_consts[op1-0x2000] : lv_RunSP_Bytecode[op1]);
+	goto *interp_dispatch[*(++cur_instruction)&0xF];
+interp_nop:
+	goto *interp_dispatch[*(++cur_instruction)&0xF];
+interp_return:
+	FreeCall
+	release_ref(my_cdata->params[0]);
+	release_ref(my_cdata->params[1]);
+	op1 = (*cur_instruction >> 4) & 0x3FFF;
+	op2 = *cur_instruction >> 24;
+	for (idx = 0; idx < op2; ++idx)
+	{
+		Ret(idx, lv_RunSP_Bytecode[op1+idx])
+	}
+EndFunc(RunSP_Bytecode)
+DISPATCH
+