void _jit_gen_move_top(jit_gencode_t gen, int reg) { if(IS_FLOAT_REG(reg)) { jit_cache_setup_output(2); x86_fstp(inst, fp_stack_index(gen, reg)); jit_cache_end_output(); } }
void _jit_gen_spill_reg(jit_gencode_t gen, int reg, int other_reg, jit_value_t value) { int offset; /* Make sure that we have sufficient space */ jit_cache_setup_output(32); if(flush_if_too_far(gen)) { jit_gen_load_inst_ptr(gen, inst); } /* Output an appropriate instruction to spill the value */ if(value->has_global_register) { arm_mov_reg_reg(inst, _jit_reg_info[value->global_reg].cpu_reg, _jit_reg_info[reg].cpu_reg); } else { _jit_gen_fix_value(value); offset = (int)(value->frame_offset); if(reg < 16) { arm_store_membase(inst, reg, ARM_FP, offset); if(other_reg != -1) { /* Spill the other word register in a pair */ offset += sizeof(void *); arm_store_membase(inst, other_reg, ARM_FP, offset); } } else if(jit_type_normalize(value->type)->kind == JIT_TYPE_FLOAT32) { arm_store_membase_float32(inst, reg - 16, ARM_FP, offset); } else { arm_store_membase_float64(inst, reg - 16, ARM_FP, offset); } } /* End the code output process */ jit_cache_end_output(); }
void _jit_gen_spill_top(jit_gencode_t gen, int reg, jit_value_t value, int pop) { int offset; if(IS_FLOAT_REG(reg)) { /* Make sure that we have sufficient space */ jit_cache_setup_output(16); /* Fix the value in place within the local variable frame */ _jit_gen_fix_value(value); /* Output an appropriate instruction to spill the value */ offset = (int)(value->frame_offset); /* Spill the top of the floating-point register stack */ switch(jit_type_normalize(value->type)->kind) { case JIT_TYPE_FLOAT32: { x86_fst_membase(inst, X86_EBP, offset, 0, pop); } break; case JIT_TYPE_FLOAT64: { x86_fst_membase(inst, X86_EBP, offset, 1, pop); } break; case JIT_TYPE_NFLOAT: { x86_fst80_membase(inst, X86_EBP, offset); if(!pop) { x86_fld80_membase(inst, X86_EBP, offset); } } break; } /* End the code output process */ jit_cache_end_output(); } }
void _jit_gen_load_value (jit_gencode_t gen, int reg, int other_reg, jit_value_t value) { int offset; /* Make sure that we have sufficient space */ jit_cache_setup_output(32); if(flush_if_too_far(gen)) { jit_gen_load_inst_ptr(gen, inst); } if(value->is_constant) { /* Determine the type of constant to be loaded */ switch(jit_type_normalize(value->type)->kind) { case JIT_TYPE_SBYTE: case JIT_TYPE_UBYTE: case JIT_TYPE_SHORT: case JIT_TYPE_USHORT: case JIT_TYPE_INT: case JIT_TYPE_UINT: { mov_reg_imm(gen, &inst, _jit_reg_info[reg].cpu_reg, (jit_nint)(value->address)); } break; case JIT_TYPE_LONG: case JIT_TYPE_ULONG: { jit_long long_value; long_value = jit_value_get_long_constant(value); mov_reg_imm(gen, &inst, _jit_reg_info[reg].cpu_reg, (jit_int)long_value); mov_reg_imm(gen, &inst, _jit_reg_info[reg].cpu_reg + 1, (jit_int)(long_value >> 32)); } break; case JIT_TYPE_FLOAT32: { jit_float32 float32_value; float32_value = jit_value_get_float32_constant(value); if(reg < 16) { mov_reg_imm(gen, &inst, _jit_reg_info[reg].cpu_reg, *((int *)&float32_value)); } else { mov_freg_imm_32 (gen, &inst, _jit_reg_info[reg].cpu_reg, *((int *)&float32_value)); } } break; case JIT_TYPE_FLOAT64: case JIT_TYPE_NFLOAT: { jit_float64 float64_value; float64_value = jit_value_get_float64_constant(value); if(reg < 16) { mov_reg_imm (gen, &inst, _jit_reg_info[reg].cpu_reg, ((int *)&float64_value)[0]); mov_reg_imm (gen, &inst, _jit_reg_info[reg].cpu_reg + 1, ((int *)&float64_value)[1]); } else { mov_freg_imm_64 (gen, &inst, _jit_reg_info[reg].cpu_reg, ((int *)&float64_value)[0], ((int *)&float64_value)[1]); } } break; } } else if(value->has_global_register)
void _jit_gen_load_value(jit_gencode_t gen, int reg, int other_reg, jit_value_t value) { jit_type_t type; int src_reg, other_src_reg; void *ptr; int offset; /* Make sure that we have sufficient space */ jit_cache_setup_output(16); type = jit_type_normalize(value->type); /* Load zero */ if(value->is_constant) { switch(type->kind) { case JIT_TYPE_SBYTE: case JIT_TYPE_UBYTE: case JIT_TYPE_SHORT: case JIT_TYPE_USHORT: case JIT_TYPE_INT: case JIT_TYPE_UINT: { if((jit_nint)(value->address) == 0) { x86_clear_reg(inst, _jit_reg_info[reg].cpu_reg); } else { x86_mov_reg_imm(inst, _jit_reg_info[reg].cpu_reg, (jit_nint)(value->address)); } } break; case JIT_TYPE_LONG: case JIT_TYPE_ULONG: { jit_long long_value; long_value = jit_value_get_long_constant(value); if(long_value == 0) { #ifdef JIT_NATIVE_INT64 x86_clear_reg(inst, _jit_reg_info[reg].cpu_reg); #else x86_clear_reg(inst, _jit_reg_info[reg].cpu_reg); x86_clear_reg(inst, _jit_reg_info[other_reg].cpu_reg); #endif } else { #ifdef JIT_NATIVE_INT64 x86_mov_reg_imm(inst, _jit_reg_info[reg].cpu_reg, (jit_nint)long_value); #else x86_mov_reg_imm(inst, _jit_reg_info[reg].cpu_reg, (jit_int)long_value); x86_mov_reg_imm(inst, _jit_reg_info[other_reg].cpu_reg, (jit_int)(long_value >> 32)); #endif } } break; case JIT_TYPE_FLOAT32: { jit_float32 float32_value; float32_value = jit_value_get_float32_constant(value); if(IS_WORD_REG(reg)) { union { jit_float32 float32_value; jit_int int_value; } un; un.float32_value = float32_value; x86_mov_reg_imm(inst, _jit_reg_info[reg].cpu_reg, un.int_value); } else { if(float32_value == (jit_float32) 0.0) { x86_fldz(inst); } else if(float32_value == (jit_float32) 1.0) { x86_fld1(inst); } else { ptr = _jit_cache_alloc(&(gen->posn), sizeof(jit_float32)); jit_memcpy(ptr, &float32_value, sizeof(float32_value)); x86_fld(inst, ptr, 0); } } } break; case JIT_TYPE_FLOAT64: { jit_float64 float64_value; float64_value = jit_value_get_float64_constant(value); if(IS_WORD_REG(reg)) { union { jit_float64 float64_value; jit_int int_value[2]; } un; un.float64_value = float64_value; x86_mov_reg_imm(inst, _jit_reg_info[reg].cpu_reg, un.int_value[0]); x86_mov_reg_imm(inst, _jit_reg_info[other_reg].cpu_reg, un.int_value[1]); } else { if(float64_value == (jit_float64) 0.0) { x86_fldz(inst); } else if(float64_value == (jit_float64) 1.0) { x86_fld1(inst); } else { ptr = _jit_cache_alloc(&(gen->posn), sizeof(jit_float64)); jit_memcpy(ptr, &float64_value, sizeof(float64_value)); x86_fld(inst, ptr, 1); } } } break; case JIT_TYPE_NFLOAT: { jit_nfloat nfloat_value; nfloat_value = jit_value_get_nfloat_constant(value); if(IS_WORD_REG(reg) && sizeof(jit_nfloat) == sizeof(jit_float64)) { union { jit_nfloat nfloat_value; jit_int int_value[2]; } un; un.nfloat_value = nfloat_value; x86_mov_reg_imm(inst, _jit_reg_info[reg].cpu_reg, un.int_value[0]); x86_mov_reg_imm(inst, _jit_reg_info[other_reg].cpu_reg, un.int_value[1]); } else { if(nfloat_value == (jit_nfloat) 0.0) { x86_fldz(inst); } else if(nfloat_value == (jit_nfloat) 1.0) { x86_fld1(inst); } else { ptr = _jit_cache_alloc(&(gen->posn), sizeof(jit_nfloat)); jit_memcpy(ptr, &nfloat_value, sizeof(nfloat_value)); if(sizeof(jit_nfloat) == sizeof(jit_float64)) { x86_fld(inst, ptr, 1); } else { x86_fld80_mem(inst, ptr); } } } } break; } } else if(value->in_register || value->in_global_register)
void _jit_gen_spill_reg(jit_gencode_t gen, int reg, int other_reg, jit_value_t value) { int offset; /* Make sure that we have sufficient space */ jit_cache_setup_output(16); /* If the value is associated with a global register, then copy to that */ if(value->has_global_register) { reg = _jit_reg_info[reg].cpu_reg; other_reg = _jit_reg_info[value->global_reg].cpu_reg; x86_mov_reg_reg(inst, other_reg, reg, sizeof(void *)); jit_cache_end_output(); return; } /* Fix the value in place within the local variable frame */ _jit_gen_fix_value(value); /* Output an appropriate instruction to spill the value */ offset = (int)(value->frame_offset); if(IS_WORD_REG(reg)) { /* Spill a word register. If the value is smaller than a word, then we write the entire word. The local stack frame is allocated such that the extra bytes will be simply ignored */ reg = _jit_reg_info[reg].cpu_reg; x86_mov_membase_reg(inst, X86_EBP, offset, reg, 4); if(other_reg != -1) { /* Spill the other word register in a pair */ reg = _jit_reg_info[other_reg].cpu_reg; offset += sizeof(void *); x86_mov_membase_reg(inst, X86_EBP, offset, reg, 4); } } else { /* Spill the top of the floating-point register stack */ switch(jit_type_normalize(value->type)->kind) { case JIT_TYPE_FLOAT32: { x86_fst_membase(inst, X86_EBP, offset, 0, 1); } break; case JIT_TYPE_FLOAT64: { x86_fst_membase(inst, X86_EBP, offset, 1, 1); } break; case JIT_TYPE_NFLOAT: { x86_fst80_membase(inst, X86_EBP, offset); } break; } } /* End the code output process */ jit_cache_end_output(); }