void jit_function::insn_branch_if(const jit_value& value, jit_label& label) { if(!jit_insn_branch_if(func, value.raw(), label.rawp())) { out_of_memory(); } }
void do_lds(jit_function_t func) { jit_value_t ldw = LOAD(LDWhich, jit_type_uint); jit_label_t label = jit_label_undefined; jit_insn_branch_if(func, jit_insn_eq(func, ldw, make_ubyte(35)), &label); jit_value_t raw = LOAD(_ReadAbsorbWhich, jit_type_ubyte); WGPR_VAL(ldw, LOAD(LDValue, jit_type_uint)); WRA(ldw, CAST(LOAD(LDAbsorb, jit_type_uint), jit_type_ubyte)); STORE(_ReadFudge, CAST(ldw, jit_type_ubyte)); STORE(_ReadAbsorbWhich, CAST(jit_insn_or(func, raw, jit_insn_and(func, ldw, make_uint(0x1F))), jit_type_ubyte)); jit_insn_label(func, &label); STORE(LDWhich, make_uint(35)); }
Compiler::value Match::compile(Compiler& c) const { auto v = value->compile(c); jit_value_t res = jit_value_create(c.F, VM::get_jit_type(type)); jit_label_t label_end = jit_label_undefined; for (size_t i = 0; i < pattern_list.size(); ++i) { bool is_default = false; for (const Pattern& pattern : pattern_list[i]) { is_default = is_default || pattern.is_default(); } if (is_default) { auto ret = returns[i]->compile(c); jit_insn_store(c.F, res, ret.v); jit_insn_label(c.F, &label_end); c.insn_delete_temporary(v); return {res, type}; } jit_label_t label_next = jit_label_undefined; if (pattern_list[i].size() == 1) { jit_value_t cond = pattern_list[i][0].match(c, v.v); jit_insn_branch_if_not(c.F, cond, &label_next); } else { jit_label_t label_match = jit_label_undefined; for (const Pattern& pattern : pattern_list[i]) { jit_value_t cond = pattern.match(c, v.v); jit_insn_branch_if(c.F, cond, &label_match); } jit_insn_branch(c.F, &label_next); jit_insn_label(c.F, &label_match); } auto ret = returns[i]->compile(c); jit_insn_store(c.F, res, ret.v); jit_insn_branch(c.F, &label_end); jit_insn_label(c.F, &label_next); } // In the case of no default pattern jit_insn_store(c.F, res, c.new_null().v); jit_insn_label(c.F, &label_end); c.insn_delete_temporary(v); return {res, type}; }
/* * Output an entry for a table-based switch statement. */ static void JITCoder_SwitchEntry(ILCoder *_coder, ILUInt32 dest) { ILJITCoder *jitCoder = _ILCoderToILJITCoder(_coder); ILJITLabel *label = _ILJitLabelGet(jitCoder, dest, _IL_JIT_LABEL_NORMAL); ILJitValue constant = jit_value_create_nint_constant(jitCoder->jitFunction, jit_type_nint, jitCoder->numSwitch); ILJitValue temp = jit_insn_eq(jitCoder->jitFunction, jitCoder->switchValue, constant); jit_insn_branch_if(jitCoder->jitFunction, temp, &(label->label)); ++jitCoder->numSwitch; }
/* * Output a branch instruction using a JIT coder. */ static void JITCoder_Branch(ILCoder *coder, int opcode, ILUInt32 dest, ILEngineType type1, ILEngineType type2) { ILJITCoder *jitCoder = _ILCoderToILJITCoder(coder); ILJITLabel *label = 0; ILJitValue temp = 0; _ILJitStackItemNew(value2); _ILJitStackItemNew(value1); #if !defined(IL_CONFIG_REDUCE_CODE) && !defined(IL_WITHOUT_TOOLS) if (jitCoder->flags & IL_CODER_FLAG_STATS) { ILMutexLock(globalTraceMutex); fprintf(stdout, "Branch: %i\n", dest); ILMutexUnlock(globalTraceMutex); } #endif /* Determine what form of branch to use */ switch(opcode) { case IL_OP_BR: case IL_OP_BR_S: case IL_OP_LEAVE: case IL_OP_LEAVE_S: { /* Unconditional branch */ label = _ILJitLabelGet(jitCoder, dest, _IL_JIT_LABEL_NORMAL); jit_insn_branch(jitCoder->jitFunction, &(label->label)); } break; case IL_OP_BRTRUE_S: case IL_OP_BRTRUE: { /* Branch if the top-most stack item is true */ _ILJitStackPop(jitCoder, value1); label = _ILJitLabelGet(jitCoder, dest, _IL_JIT_LABEL_NORMAL); jit_insn_branch_if(jitCoder->jitFunction, _ILJitStackItemValue(value1), &(label->label)); } break; case IL_OP_BRFALSE_S: case IL_OP_BRFALSE: { /* Branch if the top-most stack item is false */ _ILJitStackPop(jitCoder, value1); label = _ILJitLabelGet(jitCoder, dest, _IL_JIT_LABEL_NORMAL); jit_insn_branch_if_not(jitCoder->jitFunction, _ILJitStackItemValue(value1), &(label->label)); } break; default: { _ILJitStackPop(jitCoder, value2); _ILJitStackPop(jitCoder, value1); label = _ILJitLabelGet(jitCoder, dest, _IL_JIT_LABEL_NORMAL); switch(opcode) { case IL_OP_BEQ: case IL_OP_BEQ_S: { /* Equality testing branch */ temp = OutputCompare(jitCoder, IL_OP_BEQ, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); jit_insn_branch_if(jitCoder->jitFunction, temp, &(label->label)); } break; case IL_OP_BNE_UN: case IL_OP_BNE_UN_S: { /* Unsigned inequality testing branch */ temp = OutputCompare(jitCoder, IL_OP_BNE_UN, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); jit_insn_branch_if(jitCoder->jitFunction, temp, &(label->label)); } break; case IL_OP_BGT: case IL_OP_BGT_S: { /* Signed greater than testing branch */ temp = OutputCompare(jitCoder, IL_OP_BGT, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); jit_insn_branch_if(jitCoder->jitFunction, temp, &(label->label)); } break; case IL_OP_BGT_UN: case IL_OP_BGT_UN_S: { /* Unsigned greater than testing branch */ temp = OutputCompare(jitCoder, IL_OP_BGT_UN, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); jit_insn_branch_if(jitCoder->jitFunction, temp, &(label->label)); } break; case IL_OP_BGE: case IL_OP_BGE_S: { /* Signed greater than or equal testing branch */ temp = OutputCompare(jitCoder, IL_OP_BGE, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); jit_insn_branch_if(jitCoder->jitFunction, temp, &(label->label)); } break; case IL_OP_BGE_UN: case IL_OP_BGE_UN_S: { /* Unsigned greater than or equal testing branch */ temp = OutputCompare(jitCoder, IL_OP_BGE_UN, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); jit_insn_branch_if(jitCoder->jitFunction, temp, &(label->label)); } break; case IL_OP_BLT: case IL_OP_BLT_S: { /* Signed less than testing branch */ temp = OutputCompare(jitCoder, IL_OP_BLT, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); jit_insn_branch_if(jitCoder->jitFunction, temp, &(label->label)); } break; case IL_OP_BLT_UN: case IL_OP_BLT_UN_S: { /* Unsigned less than testing branch */ temp = OutputCompare(jitCoder, IL_OP_BLT_UN, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); jit_insn_branch_if(jitCoder->jitFunction, temp, &(label->label)); } break; case IL_OP_BLE: case IL_OP_BLE_S: { /* Signed less than or equal testing branch */ temp = OutputCompare(jitCoder, IL_OP_BLE, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); jit_insn_branch_if(jitCoder->jitFunction, temp, &(label->label)); } break; case IL_OP_BLE_UN: case IL_OP_BLE_UN_S: { /* Unsigned less than or equal testing branch */ temp = OutputCompare(jitCoder, IL_OP_BLE_UN, &(_ILJitStackItemValue(value1)), &(_ILJitStackItemValue(value2))); jit_insn_branch_if(jitCoder->jitFunction, temp, &(label->label)); } break; } } break; } }
// LIBJIT void vm_cpu_4(uint32_t newPC,int opt, int size) { int i; PC = newPC; nPC = 4; RF[0] = 0; //Register $zero must always be zero RF[31] = 1; //Return default (if the program does not set to zero, should put error) uint32_t HI = 0, LO = 0; uint32_t offset = 4; uint8_t halted = 0; uint32_t instr; uint8_t op; uint8_t rs; uint8_t rt; uint8_t rd; int16_t immediate; uint32_t address; uint8_t shamt; uint8_t funct; uint64_t mult; /*lib jit variables */ jit_context_t context; jit_type_t signature; jit_function_t function; jit_type_t params[VM_MEMORY_SZ+2]; jit_int result; jit_value_t constant_sum; jit_value_t constant_while; jit_value_t v_it; jit_value_t constant_update; jit_value_t compare; jit_value_t reg[32]; /* Reg */ jit_value_t mem[VM_MEMORY_SZ]; /* Memory */ jit_label_t labels[10]; /* Labs for jumping :D */ jit_value_t sum, t_sum; void *args[VM_MEMORY_SZ+2]; /* Args */ jit_int arg_uint[VM_MEMORY_SZ+2]; /* Create a context to hold the JIT's primary state */ context = jit_context_create(); /* Lock the context while we build and compile the function */ jit_context_build_start(context); for(i=0; i<(VM_MEMORY_SZ+2); i++) { params[i] = jit_type_int; } signature = jit_type_create_signature(jit_abi_cdecl, jit_type_int, params, VM_MEMORY_SZ+2, 1); /* Create the function object */ function = jit_function_create(context, signature); jit_type_free(signature); // Read memory and start registers for(i=0; i<VM_MEMORY_SZ; i++) { //printf("%d\n",i); mem[i] = jit_value_get_param(function, i); } reg[0] = jit_value_get_param(function, VM_MEMORY_SZ); reg[31] = jit_value_get_param(function, VM_MEMORY_SZ+1); /*int verify = 0 - 1; for (i=1; i<VM_MEMORY_SZ; i++) { if((i%2)==0) { verify = verify + (i); } else { verify = verify - i; } } printf("verify %d\n", verify); */ int l_index; // Only doing the micro benchmark, for analysis // Addiu #define loopSize 10000 #define smallerLoopSize 1000 #define opPerLoop 100 // v_it = 0 ; constant_while = loopSize ; constant_update = 1 v_it = jit_value_create(function, jit_type_uint); constant_update = jit_value_create_nint_constant(function, jit_type_int, (int)0); jit_insn_store(function, v_it, constant_update); reg[2] = jit_value_create(function, jit_type_uint); constant_while = jit_value_create_nint_constant(function, jit_type_int, 0); jit_insn_store(function, reg[2], constant_while); reg[3] = jit_value_create(function, jit_type_uint); constant_while = jit_value_create_nint_constant(function, jit_type_int, 1); jit_insn_store(function, reg[3], constant_while); // do while (v_it < constant_while) { jit_insn_label(function, &labels[0]); if (opt == 0) { constant_update = jit_insn_add(function, reg[2], reg[3]); } else if(opt == 1) { constant_update = jit_insn_xor(function, reg[2], reg[3]); } else if(opt == 2) { constant_update = jit_insn_load(function, mem[0]); } for (l_index = 1; l_index < opPerLoop; l_index++) { if (opt == 0) { constant_update = jit_insn_add(function, constant_update, reg[3]); } else if(opt == 1) { constant_update = jit_insn_xor(function, constant_update, reg[3]); } else if(opt == 2) { constant_update = jit_insn_load(function, mem[l_index % 5]); } } jit_insn_store(function, reg[2], constant_update); // do while constant_update = jit_value_create_nint_constant(function, jit_type_uint, 1); constant_sum = jit_insn_add(function, v_it, constant_update); jit_insn_store(function, v_it, constant_sum); if(size > 0) { constant_while = jit_value_create_nint_constant(function, jit_type_uint, loopSize); } else { constant_while = jit_value_create_nint_constant(function, jit_type_uint, smallerLoopSize); } compare = jit_insn_gt(function, constant_while, v_it); jit_insn_branch_if(function, compare, &labels[0]); // Return //jit_insn_return(function, reg[2]); jit_insn_return(function, reg[2]); // START OF FINAL PART /* Compile the function */ jit_function_compile(function); /* Unlock the context */ jit_context_build_end(context); // Put memory and first registers for (i=0; i<VM_MEMORY_SZ; i++) { arg_uint[i] = (int) VM_memory[i]; //arg_uint[i] = (int)i; args[i] = &(arg_uint[i]); } arg_uint[VM_MEMORY_SZ] = 0; args[VM_MEMORY_SZ] = &(arg_uint[VM_MEMORY_SZ]); arg_uint[VM_MEMORY_SZ+1] = 1; args[VM_MEMORY_SZ+1] = &(arg_uint[VM_MEMORY_SZ+1]); jit_function_apply(function, args, &result); //printf("%d\n", result); return; /* end lib jit variables */ }