mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-05-24 18:41:21 +00:00
Implement JIT IR for integer load/store opcodes (#1087)
This commit is contained in:
parent
5f0fab03a5
commit
166f12fef1
|
@ -426,7 +426,13 @@ static bool
|
|||
extend_r8_to_r32(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src,
|
||||
bool is_signed)
|
||||
{
|
||||
return false;
|
||||
if (is_signed) {
|
||||
a.movsx(regs_i32[reg_no_dst], regs_i8[reg_no_src]);
|
||||
}
|
||||
else {
|
||||
a.movzx(regs_i32[reg_no_dst], regs_i8[reg_no_src]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Encode extending register of word to register of dword
|
||||
|
@ -441,7 +447,13 @@ static bool
|
|||
extend_r16_to_r32(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src,
|
||||
bool is_signed)
|
||||
{
|
||||
return false;
|
||||
if (is_signed) {
|
||||
a.movsx(regs_i32[reg_no_dst], regs_i16[reg_no_src]);
|
||||
}
|
||||
else {
|
||||
a.movzx(regs_i32[reg_no_dst], regs_i16[reg_no_src]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -457,7 +469,13 @@ static bool
|
|||
extend_r8_to_r64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src,
|
||||
bool is_signed)
|
||||
{
|
||||
return false;
|
||||
if (is_signed) {
|
||||
a.movsx(regs_i64[reg_no_dst], regs_i8[reg_no_src]);
|
||||
}
|
||||
else {
|
||||
a.movzx(regs_i64[reg_no_dst], regs_i8[reg_no_src]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -473,7 +491,13 @@ static bool
|
|||
extend_r16_to_r64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src,
|
||||
bool is_signed)
|
||||
{
|
||||
return false;
|
||||
if (is_signed) {
|
||||
a.movsx(regs_i64[reg_no_dst], regs_i16[reg_no_src]);
|
||||
}
|
||||
else {
|
||||
a.movzx(regs_i64[reg_no_dst], regs_i16[reg_no_src]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -489,29 +513,40 @@ static bool
|
|||
extend_r32_to_r64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src,
|
||||
bool is_signed)
|
||||
{
|
||||
return false;
|
||||
if (is_signed) {
|
||||
a.movsxd(regs_i64[reg_no_dst], regs_i32[reg_no_src]);
|
||||
}
|
||||
else {
|
||||
a.xor_(regs_i64[reg_no_dst], regs_i64[reg_no_dst]);
|
||||
a.mov(regs_i32[reg_no_dst], regs_i32[reg_no_src]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
mov_r_to_r_i32(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src);
|
||||
|
||||
static bool
|
||||
mov_r_to_r_i64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src);
|
||||
|
||||
static void
|
||||
mov_r_to_r(x86::Assembler &a, uint32 kind_dst, int32 reg_no_dst,
|
||||
int32 reg_no_src)
|
||||
{
|
||||
if (reg_no_dst != reg_no_src) {
|
||||
if (kind_dst == JIT_REG_KIND_I32)
|
||||
a.mov(regs_i32[reg_no_dst], regs_i32[reg_no_src]);
|
||||
else if (kind_dst == JIT_REG_KIND_I64)
|
||||
a.mov(regs_i64[reg_no_dst], regs_i64[reg_no_src]);
|
||||
else if (kind_dst == JIT_REG_KIND_F32) {
|
||||
/* TODO */
|
||||
bh_assert(0);
|
||||
}
|
||||
else if (kind_dst == JIT_REG_KIND_F64) {
|
||||
/* TODO */
|
||||
bh_assert(0);
|
||||
}
|
||||
else {
|
||||
bh_assert(0);
|
||||
}
|
||||
if (kind_dst == JIT_REG_KIND_I32)
|
||||
mov_r_to_r_i32(a, reg_no_dst, reg_no_src);
|
||||
else if (kind_dst == JIT_REG_KIND_I64)
|
||||
mov_r_to_r_i64(a, reg_no_dst, reg_no_src);
|
||||
else if (kind_dst == JIT_REG_KIND_F32) {
|
||||
/* TODO */
|
||||
bh_assert(0);
|
||||
}
|
||||
else if (kind_dst == JIT_REG_KIND_F64) {
|
||||
/* TODO */
|
||||
bh_assert(0);
|
||||
}
|
||||
else {
|
||||
bh_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1109,7 +1144,9 @@ mov_r_to_r_f64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
|
|||
static bool
|
||||
convert_imm_i32_to_r_i8(x86::Assembler &a, int32 reg_no, int32 data)
|
||||
{
|
||||
return false;
|
||||
Imm imm((int8)data);
|
||||
a.mov(regs_i32[reg_no], imm);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1124,6 +1161,8 @@ convert_imm_i32_to_r_i8(x86::Assembler &a, int32 reg_no, int32 data)
|
|||
static bool
|
||||
convert_r_i32_to_r_i8(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
|
||||
{
|
||||
/* TODO */
|
||||
bh_assert(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1139,7 +1178,9 @@ convert_r_i32_to_r_i8(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
|
|||
static bool
|
||||
convert_imm_i32_to_r_u8(x86::Assembler &a, int32 reg_no, int32 data)
|
||||
{
|
||||
return false;
|
||||
Imm imm((uint8)data);
|
||||
a.mov(regs_i32[reg_no], imm);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1154,6 +1195,8 @@ convert_imm_i32_to_r_u8(x86::Assembler &a, int32 reg_no, int32 data)
|
|||
static bool
|
||||
convert_r_i32_to_r_u8(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
|
||||
{
|
||||
/* TODO */
|
||||
bh_assert(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1169,7 +1212,9 @@ convert_r_i32_to_r_u8(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
|
|||
static bool
|
||||
convert_imm_i32_to_r_i16(x86::Assembler &a, int32 reg_no, int32 data)
|
||||
{
|
||||
return false;
|
||||
Imm imm((int16)data);
|
||||
a.mov(regs_i32[reg_no], imm);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1184,6 +1229,8 @@ convert_imm_i32_to_r_i16(x86::Assembler &a, int32 reg_no, int32 data)
|
|||
static bool
|
||||
convert_r_i32_to_r_i16(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
|
||||
{
|
||||
/* TODO */
|
||||
bh_assert(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1199,7 +1246,9 @@ convert_r_i32_to_r_i16(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
|
|||
static bool
|
||||
convert_imm_i32_to_r_u16(x86::Assembler &a, int32 reg_no, int32 data)
|
||||
{
|
||||
return false;
|
||||
Imm imm((uint16)data);
|
||||
a.mov(regs_i32[reg_no], imm);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1214,11 +1263,13 @@ convert_imm_i32_to_r_u16(x86::Assembler &a, int32 reg_no, int32 data)
|
|||
static bool
|
||||
convert_r_i32_to_r_u16(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
|
||||
{
|
||||
/* TODO */
|
||||
bh_assert(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encoding convert int32 immediate data to uint64 register
|
||||
* Encoding convert int32 immediate data to int64 register
|
||||
*
|
||||
* @param a the assembler to emit the code
|
||||
* @param reg_no the dst register, need to be converted to uint64
|
||||
|
@ -1227,13 +1278,16 @@ convert_r_i32_to_r_u16(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
|
|||
* @return true if success, false otherwise
|
||||
*/
|
||||
static bool
|
||||
convert_imm_i32_to_r_u64(x86::Assembler &a, int32 reg_no, int32 data)
|
||||
convert_imm_i32_to_r_i64(x86::Assembler &a, int32 reg_no, int32 data)
|
||||
{
|
||||
return false;
|
||||
/* let compiler do sign-extending */
|
||||
Imm imm((int64)data);
|
||||
a.mov(regs_i64[reg_no], imm);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encoding convert int32 immediate data to uint64 register
|
||||
* Encoding convert int32 register data to int64 register with signed extension
|
||||
*
|
||||
* @param a the assembler to emit the code
|
||||
* @param reg_no_dst the dst register, need to be converted to uint64
|
||||
|
@ -1242,9 +1296,9 @@ convert_imm_i32_to_r_u64(x86::Assembler &a, int32 reg_no, int32 data)
|
|||
* @return true if success, false otherwise
|
||||
*/
|
||||
static bool
|
||||
convert_r_i32_to_r_u64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
|
||||
convert_r_i32_to_r_i64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
|
||||
{
|
||||
return false;
|
||||
return extend_r32_to_r64(a, reg_no_dst, reg_no_src, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1307,6 +1361,132 @@ convert_r_i32_to_r_f64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode converting uint32 immediate data to int64 register data
|
||||
*
|
||||
* @param a the assembler to emit the code
|
||||
* @param reg_no the no of dst int64 register
|
||||
* @param data the src immediate uint32 data
|
||||
*
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
static bool
|
||||
convert_imm_u32_to_r_i64(x86::Assembler &a, int32 reg_no, uint32 data)
|
||||
{
|
||||
Imm imm((uint64)data);
|
||||
a.mov(regs_i64[reg_no], imm);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode converting uint32 register data to int64 register data
|
||||
*
|
||||
* @param a the assembler to emit the code
|
||||
* @param reg_no_dst the no of dst uint32 register
|
||||
* @param reg_no_src the no of src int64 register
|
||||
*
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
static bool
|
||||
convert_r_u32_to_r_i64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
|
||||
{
|
||||
return extend_r32_to_r64(a, reg_no_dst, reg_no_src, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode converting int64 immediate data to int32 register data
|
||||
*
|
||||
* @param a the assembler to emit the code
|
||||
* @param reg_no the no of dst int32 register
|
||||
* @param data the src immediate int64 data
|
||||
*
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
static bool
|
||||
convert_imm_i64_to_r_i32(x86::Assembler &a, int32 reg_no, int64 data)
|
||||
{
|
||||
Imm imm((int32)data);
|
||||
a.mov(regs_i32[reg_no], imm);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode converting int64 register data to int32 register data
|
||||
*
|
||||
* @param a the assembler to emit the code
|
||||
* @param reg_no_dst the no of dst int32 register
|
||||
* @param reg_no_src the no of src int64 register
|
||||
*
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
static bool
|
||||
convert_r_i64_to_r_i32(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
|
||||
{
|
||||
/* TODO */
|
||||
bh_assert(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode converting int64 immediate data to float register data
|
||||
*
|
||||
* @param a the assembler to emit the code
|
||||
* @param reg_no the no of dst float register
|
||||
* @param data the src immediate int64 data
|
||||
*
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
static bool
|
||||
convert_imm_i64_to_r_f32(x86::Assembler &a, int32 reg_no_dst, int64 data)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode converting int64 register data to float register data
|
||||
*
|
||||
* @param a the assembler to emit the code
|
||||
* @param reg_no_dst the no of dst float register
|
||||
* @param reg_no_src the no of src int64 register
|
||||
*
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
static bool
|
||||
convert_r_i64_to_r_f32(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode converting int64 immediate data to double register data
|
||||
*
|
||||
* @param a the assembler to emit the code
|
||||
* @param reg_no the no of dst double register
|
||||
* @param data the src immediate int64 data
|
||||
*
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
static bool
|
||||
convert_imm_i64_to_r_f64(x86::Assembler &a, int32 reg_no_dst, int64 data)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode converting int64 register data to double register data
|
||||
*
|
||||
* @param a the assembler to emit the code
|
||||
* @param reg_no_dst the no of dst double register
|
||||
* @param reg_no_src the no of src int64 register
|
||||
*
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
static bool
|
||||
convert_r_i64_to_r_f64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode converting float immediate data to int32 register data
|
||||
*
|
||||
|
@ -1397,6 +1577,36 @@ convert_r_f64_to_r_i32(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode converting double immediate data to int64 register data
|
||||
*
|
||||
* @param a the assembler to emit the code
|
||||
* @param reg_no the no of dst int64 register
|
||||
* @param data the src immediate double data
|
||||
*
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
static bool
|
||||
convert_imm_f64_to_r_i64(x86::Assembler &a, int32 reg_no, double data)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode converting double register data to int64 register data
|
||||
*
|
||||
* @param a the assembler to emit the code
|
||||
* @param reg_no_dst the no of dst int64 register
|
||||
* @param reg_no_src the no of src double register
|
||||
*
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
static bool
|
||||
convert_r_f64_to_r_i64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode converting double immediate data to float register data
|
||||
*
|
||||
|
@ -3370,10 +3580,12 @@ fail:
|
|||
|
||||
/**
|
||||
* Encode insn convert: I32TOI8 r0, r1, or I32TOI16, I32TOF32, F32TOF64, etc.
|
||||
* @param kind0 the dst data kind, such as I32, I64, F32 and F64
|
||||
* @param kind1 the src data kind, such as I32, I64, F32 and F64
|
||||
* @param type0 the dst data type, such as int32, float and double
|
||||
* @param type1 the src data type, such as int32, float and double
|
||||
* @param kind0 the dst JIT_REG_KIND, such as I32, I64, F32 and F64
|
||||
* @param kind1 the src JIT_REG_KIND, such as I32, I64, F32 and F64
|
||||
* @param type0 the dst data type, such as i8, u8, i16, u16, i32, f32, i64, f32,
|
||||
* f64
|
||||
* @param type1 the src data type, such as i8, u8, i16, u16, i32, f32, i64, f32,
|
||||
* f64
|
||||
*/
|
||||
#define CONVERT_R_R(kind0, kind1, type0, type1, Type1) \
|
||||
do { \
|
||||
|
@ -3670,8 +3882,9 @@ fail:
|
|||
* @param cc the compiler context
|
||||
* @param a the assembler to emit the code
|
||||
* @param r0 dst jit register that contains the dst operand info
|
||||
* @param r1 src jit register that contains the first src operand info
|
||||
* @param r2 src jit register that contains the second src operand info
|
||||
* @param r1 condition jit register
|
||||
* @param r2 src jit register that contains the first src operand info
|
||||
* @param r3 src jit register that contains the second src operand info
|
||||
*
|
||||
* @return true if success, false if failed
|
||||
*/
|
||||
|
@ -4373,6 +4586,16 @@ jit_codegen_gen_native(JitCompContext *cc)
|
|||
CONVERT_R_R(I32, I32, u16, i32, int32);
|
||||
break;
|
||||
|
||||
case JIT_OP_I32TOI64:
|
||||
LOAD_2ARGS();
|
||||
CONVERT_R_R(I64, I32, i64, i32, int32);
|
||||
break;
|
||||
|
||||
case JIT_OP_U32TOI64:
|
||||
LOAD_2ARGS();
|
||||
CONVERT_R_R(I64, I32, i64, u32, int32);
|
||||
break;
|
||||
|
||||
case JIT_OP_I32TOF32:
|
||||
case JIT_OP_U32TOF32:
|
||||
LOAD_2ARGS();
|
||||
|
@ -4385,6 +4608,21 @@ jit_codegen_gen_native(JitCompContext *cc)
|
|||
CONVERT_R_R(F64, I32, f64, i32, int32);
|
||||
break;
|
||||
|
||||
case JIT_OP_I64TOI32:
|
||||
LOAD_2ARGS();
|
||||
CONVERT_R_R(I32, I64, i32, i64, int64);
|
||||
break;
|
||||
|
||||
case JIT_OP_I64TOF32:
|
||||
LOAD_2ARGS();
|
||||
CONVERT_R_R(F32, I64, f32, i64, int64);
|
||||
break;
|
||||
|
||||
case JIT_OP_I64TOF64:
|
||||
LOAD_2ARGS();
|
||||
CONVERT_R_R(F64, I64, f64, i64, int64);
|
||||
break;
|
||||
|
||||
case JIT_OP_F32TOI32:
|
||||
LOAD_2ARGS();
|
||||
CONVERT_R_R(I32, F32, i32, f32, int32);
|
||||
|
@ -4400,6 +4638,11 @@ jit_codegen_gen_native(JitCompContext *cc)
|
|||
CONVERT_R_R(I32, F64, i32, f64, float64);
|
||||
break;
|
||||
|
||||
case JIT_OP_F64TOI64:
|
||||
LOAD_2ARGS();
|
||||
CONVERT_R_R(I64, F64, i64, f64, float64);
|
||||
break;
|
||||
|
||||
case JIT_OP_F64TOF32:
|
||||
LOAD_2ARGS();
|
||||
CONVERT_R_R(F32, F64, f32, f64, float64);
|
||||
|
|
|
@ -5,11 +5,219 @@
|
|||
|
||||
#include "jit_emit_memory.h"
|
||||
#include "../jit_frontend.h"
|
||||
#include "fe/jit_emit_exception.h"
|
||||
|
||||
static JitReg
|
||||
get_memory_boundary(JitCompContext *cc, uint32 mem_idx, uint32 bytes)
|
||||
{
|
||||
JitReg memory_boundary;
|
||||
|
||||
switch (bytes) {
|
||||
case 1:
|
||||
{
|
||||
memory_boundary =
|
||||
get_mem_bound_check_1byte_reg(cc->jit_frame, mem_idx);
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
memory_boundary =
|
||||
get_mem_bound_check_2bytes_reg(cc->jit_frame, mem_idx);
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
memory_boundary =
|
||||
get_mem_bound_check_4bytes_reg(cc->jit_frame, mem_idx);
|
||||
break;
|
||||
}
|
||||
case 8:
|
||||
{
|
||||
memory_boundary =
|
||||
get_mem_bound_check_8bytes_reg(cc->jit_frame, mem_idx);
|
||||
break;
|
||||
}
|
||||
case 16:
|
||||
{
|
||||
memory_boundary =
|
||||
get_mem_bound_check_16bytes_reg(cc->jit_frame, mem_idx);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
bh_assert(0);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
return memory_boundary;
|
||||
fail:
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if UINTPTR_MAX == UINT64_MAX
|
||||
static JitReg
|
||||
check_and_seek_on_64bit_platform(JitCompContext *cc, JitReg addr, JitReg offset,
|
||||
JitReg memory_boundary)
|
||||
{
|
||||
JitReg long_addr, offset1;
|
||||
|
||||
/* long_addr = (int64_t)addr */
|
||||
long_addr = jit_cc_new_reg_I64(cc);
|
||||
GEN_INSN(U32TOI64, long_addr, addr);
|
||||
|
||||
/* offset1 = offset + long_addr */
|
||||
offset1 = jit_cc_new_reg_I64(cc);
|
||||
GEN_INSN(ADD, offset1, offset, long_addr);
|
||||
|
||||
/* if (offset1 > memory_boundary) goto EXCEPTION */
|
||||
GEN_INSN(CMP, cc->cmp_reg, offset1, memory_boundary);
|
||||
if (!jit_emit_exception(cc, EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS, JIT_OP_BGTU,
|
||||
cc->cmp_reg, NULL)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return offset1;
|
||||
fail:
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static JitReg
|
||||
check_and_seek_on_32bit_platform(JitCompContext *cc, JitReg addr, JitReg offset,
|
||||
JitReg memory_boundary)
|
||||
{
|
||||
JitReg offset1;
|
||||
|
||||
/* offset1 = offset + addr */
|
||||
offset1 = jit_cc_new_reg_I32(cc);
|
||||
GEN_INSN(ADD, offset1, offset, addr);
|
||||
|
||||
/* if (offset1 < addr) goto EXCEPTION */
|
||||
GEN_INSN(CMP, cc->cmp_reg, offset1, addr);
|
||||
if (!jit_emit_exception(cc, EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS, JIT_OP_BLTU,
|
||||
cc->cmp_reg, NULL)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* if (offset1 > memory_boundary) goto EXCEPTION */
|
||||
GEN_INSN(CMP, cc->cmp_reg, offset1, memory_boundary);
|
||||
if (!jit_emit_exception(cc, EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS, JIT_OP_BGTU,
|
||||
cc->cmp_reg, NULL)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return offset1;
|
||||
fail:
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static JitReg
|
||||
check_and_seek(JitCompContext *cc, JitReg addr, uint32 offset, uint32 bytes)
|
||||
{
|
||||
JitReg memory_boundary, offset1, memory_data, maddr;
|
||||
/* the default memory */
|
||||
uint32 mem_idx = 0;
|
||||
|
||||
/* ---------- check ---------- */
|
||||
/* 1. shortcut if the memory size is 0*/
|
||||
if (0 == cc->cur_wasm_module->memories[mem_idx].init_page_count) {
|
||||
JitReg memory_inst, cur_mem_page_count;
|
||||
|
||||
/* if (cur_mem_page_count == 0) goto EXCEPTION */
|
||||
memory_inst = get_memory_inst_reg(cc->jit_frame, mem_idx);
|
||||
cur_mem_page_count = jit_cc_new_reg_I32(cc);
|
||||
GEN_INSN(LDI32, cur_mem_page_count, memory_inst,
|
||||
NEW_CONST(I32, offsetof(WASMMemoryInstance, cur_page_count)));
|
||||
GEN_INSN(CMP, cc->cmp_reg, cur_mem_page_count, NEW_CONST(I32, 0));
|
||||
if (!jit_emit_exception(cc, EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS,
|
||||
JIT_OP_BEQ, cc->cmp_reg, NULL)) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* 2. a complete boundary check */
|
||||
memory_boundary = get_memory_boundary(cc, mem_idx, bytes);
|
||||
if (!memory_boundary)
|
||||
goto fail;
|
||||
|
||||
#if UINTPTR_MAX == UINT64_MAX
|
||||
offset1 = check_and_seek_on_64bit_platform(cc, addr, NEW_CONST(I64, offset),
|
||||
memory_boundary);
|
||||
if (!offset1)
|
||||
goto fail;
|
||||
#else
|
||||
offset1 = check_and_seek_on_32bit_platform(cc, addr, NEW_CONST(I32, offset),
|
||||
memory_boundary);
|
||||
if (!offset1)
|
||||
goto fail;
|
||||
#endif
|
||||
|
||||
/* ---------- seek ---------- */
|
||||
memory_data = get_memory_data_reg(cc->jit_frame, mem_idx);
|
||||
maddr = jit_cc_new_reg_ptr(cc);
|
||||
GEN_INSN(ADD, maddr, memory_data, offset1);
|
||||
|
||||
return maddr;
|
||||
fail:
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
jit_compile_op_i32_load(JitCompContext *cc, uint32 align, uint32 offset,
|
||||
uint32 bytes, bool sign, bool atomic)
|
||||
{
|
||||
JitReg addr, maddr, value;
|
||||
|
||||
POP_I32(addr);
|
||||
|
||||
maddr = check_and_seek(cc, addr, offset, bytes);
|
||||
if (!maddr) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
value = jit_cc_new_reg_I32(cc);
|
||||
switch (bytes) {
|
||||
case 1:
|
||||
{
|
||||
if (sign) {
|
||||
GEN_INSN(LDI8, value, maddr, NEW_CONST(I32, 0));
|
||||
}
|
||||
else {
|
||||
GEN_INSN(LDU8, value, maddr, NEW_CONST(I32, 0));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
if (sign) {
|
||||
GEN_INSN(LDI16, value, maddr, NEW_CONST(I32, 0));
|
||||
}
|
||||
else {
|
||||
GEN_INSN(LDU16, value, maddr, NEW_CONST(I32, 0));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
if (sign) {
|
||||
GEN_INSN(LDI32, value, maddr, NEW_CONST(I32, 0));
|
||||
}
|
||||
else {
|
||||
GEN_INSN(LDU32, value, maddr, NEW_CONST(I32, 0));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
bh_assert(0);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
PUSH_I32(value);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -17,6 +225,67 @@ bool
|
|||
jit_compile_op_i64_load(JitCompContext *cc, uint32 align, uint32 offset,
|
||||
uint32 bytes, bool sign, bool atomic)
|
||||
{
|
||||
JitReg addr, maddr, value;
|
||||
|
||||
POP_I32(addr);
|
||||
|
||||
maddr = check_and_seek(cc, addr, offset, bytes);
|
||||
if (!maddr) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
value = jit_cc_new_reg_I64(cc);
|
||||
switch (bytes) {
|
||||
case 1:
|
||||
{
|
||||
if (sign) {
|
||||
GEN_INSN(LDI8, value, maddr, NEW_CONST(I32, 0));
|
||||
}
|
||||
else {
|
||||
GEN_INSN(LDU8, value, maddr, NEW_CONST(I32, 0));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
if (sign) {
|
||||
GEN_INSN(LDI16, value, maddr, NEW_CONST(I32, 0));
|
||||
}
|
||||
else {
|
||||
GEN_INSN(LDU16, value, maddr, NEW_CONST(I32, 0));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
if (sign) {
|
||||
GEN_INSN(LDI16, value, maddr, NEW_CONST(I32, 0));
|
||||
}
|
||||
else {
|
||||
GEN_INSN(LDU16, value, maddr, NEW_CONST(I32, 0));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 8:
|
||||
{
|
||||
if (sign) {
|
||||
GEN_INSN(LDI64, value, maddr, NEW_CONST(I32, 0));
|
||||
}
|
||||
else {
|
||||
GEN_INSN(LDU64, value, maddr, NEW_CONST(I32, 0));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
bh_assert(0);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
PUSH_I64(value);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -36,6 +305,41 @@ bool
|
|||
jit_compile_op_i32_store(JitCompContext *cc, uint32 align, uint32 offset,
|
||||
uint32 bytes, bool atomic)
|
||||
{
|
||||
JitReg value, addr, maddr;
|
||||
|
||||
POP_I32(value);
|
||||
POP_I32(addr);
|
||||
|
||||
maddr = check_and_seek(cc, addr, offset, bytes);
|
||||
if (!maddr) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
switch (bytes) {
|
||||
case 1:
|
||||
{
|
||||
GEN_INSN(STI8, value, maddr, NEW_CONST(I32, 0));
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
GEN_INSN(STI16, value, maddr, NEW_CONST(I32, 0));
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
GEN_INSN(STI32, value, maddr, NEW_CONST(I32, 0));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
bh_assert(0);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -43,6 +347,46 @@ bool
|
|||
jit_compile_op_i64_store(JitCompContext *cc, uint32 align, uint32 offset,
|
||||
uint32 bytes, bool atomic)
|
||||
{
|
||||
JitReg value, addr, maddr;
|
||||
|
||||
POP_I64(value);
|
||||
POP_I32(addr);
|
||||
|
||||
maddr = check_and_seek(cc, addr, offset, bytes);
|
||||
if (!maddr) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
switch (bytes) {
|
||||
case 1:
|
||||
{
|
||||
GEN_INSN(STI8, value, maddr, NEW_CONST(I32, 0));
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
GEN_INSN(STI16, value, maddr, NEW_CONST(I32, 0));
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
GEN_INSN(STI32, value, maddr, NEW_CONST(I32, 0));
|
||||
break;
|
||||
}
|
||||
case 8:
|
||||
{
|
||||
GEN_INSN(STI64, value, maddr, NEW_CONST(I32, 0));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
bh_assert(0);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user