From f7080facb41deaecf485703f8522edcea9256787 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Thu, 9 May 2019 16:02:39 +0200 Subject: [PATCH 01/33] Refactor to move temp register acquire to core --- lightening/lightening.c | 48 ++++++++++++++++++++++++++++++++++---- lightening/x86-cpu.c | 19 --------------- lightening/x86-sse.c | 51 +++++++++++++++-------------------------- lightening/x86.h | 3 --- 4 files changed, 62 insertions(+), 59 deletions(-) diff --git a/lightening/lightening.c b/lightening/lightening.c index 0973d8a69..719423857 100644 --- a/lightening/lightening.c +++ b/lightening/lightening.c @@ -189,6 +189,40 @@ jit_align(jit_state_t *_jit, unsigned align) jit_nop(_jit, there - here); } +static jit_gpr_t +get_temp_gpr(jit_state_t *_jit) +{ + ASSERT(!_jit->temp_gpr_saved); + _jit->temp_gpr_saved = 1; +#ifdef JIT_RTMP + return JIT_RTMP; +#else + return JIT_VTMP; +#endif +} + +static jit_fpr_t +get_temp_fpr(jit_state_t *_jit) +{ + ASSERT(!_jit->temp_fpr_saved); + _jit->temp_fpr_saved = 1; + return JIT_FTMP; +} + +static void +unget_temp_fpr(jit_state_t *_jit) +{ + ASSERT(_jit->temp_fpr_saved); + _jit->temp_fpr_saved = 0; +} + +static void +unget_temp_gpr(jit_state_t *_jit) +{ + ASSERT(_jit->temp_gpr_saved); + _jit->temp_gpr_saved = 0; +} + static inline void emit_u8(jit_state_t *_jit, uint8_t u8) { if (UNLIKELY(_jit->pc.uc + 1 > _jit->limit)) { _jit->overflow = 1; @@ -570,10 +604,10 @@ abi_mem_to_mem(jit_state_t *_jit, enum jit_operand_abi abi, jit_gpr_t base, abi_gpr_to_mem(_jit, abi, base, offset, tmp); unget_temp_gpr(_jit); } else { - jit_fpr_t tmp = get_temp_xpr(_jit); + jit_fpr_t tmp = get_temp_fpr(_jit); abi_mem_to_fpr(_jit, abi, tmp, src_base, src_offset); abi_fpr_to_mem(_jit, abi, base, offset, tmp); - unget_temp_xpr(_jit); + unget_temp_fpr(_jit); } } @@ -704,7 +738,7 @@ move_one(jit_state_t *_jit, jit_operand_t *dst, jit_operand_t *src, jit_operand_t tmp; if (is_fpr_arg (src[j].kind)) { tmp_fpr = 1; - tmp = jit_operand_fpr(src[j].abi, get_temp_xpr(_jit)); + tmp = jit_operand_fpr(src[j].abi, get_temp_fpr(_jit)); } else { tmp_gpr = 1; /* Preserve addend, if any, from source operand, to be applied @@ -729,7 +763,7 @@ move_one(jit_state_t *_jit, jit_operand_t *dst, jit_operand_t *src, if (tmp_gpr) unget_temp_gpr(_jit); else if (tmp_fpr) - unget_temp_xpr(_jit); + unget_temp_fpr(_jit); } static void @@ -868,6 +902,12 @@ static const jit_gpr_t V[] = { #endif #ifdef JIT_V7 , JIT_V7 +#endif +#ifdef JIT_V8 + , JIT_V8 +#endif +#ifdef JIT_V9 + , JIT_V9 #endif }; diff --git a/lightening/x86-cpu.c b/lightening/x86-cpu.c index 041c54906..0b39e5a15 100644 --- a/lightening/x86-cpu.c +++ b/lightening/x86-cpu.c @@ -265,25 +265,6 @@ popr(jit_state_t *_jit, int32_t r0) ic(_jit, 0x58 | r7(r0)); } -static jit_gpr_t -get_temp_gpr(jit_state_t *_jit) -{ - ASSERT(!_jit->temp_gpr_saved); - _jit->temp_gpr_saved = 1; -#ifdef JIT_RTMP - return JIT_RTMP; -#else - return JIT_VTMP; -#endif -} - -static void -unget_temp_gpr(jit_state_t *_jit) -{ - ASSERT(_jit->temp_gpr_saved); - _jit->temp_gpr_saved = 0; -} - static void nop(jit_state_t *_jit, int32_t count) { diff --git a/lightening/x86-sse.c b/lightening/x86-sse.c index 9f4084c85..59b7c7471 100644 --- a/lightening/x86-sse.c +++ b/lightening/x86-sse.c @@ -187,21 +187,6 @@ popr_d(jit_state_t *_jit, int32_t r0) unget_temp_gpr(_jit); } -static jit_fpr_t -get_temp_xpr(jit_state_t *_jit) -{ - ASSERT(!_jit->temp_fpr_saved); - _jit->temp_fpr_saved = 1; - return JIT_FTMP; -} - -static void -unget_temp_xpr(jit_state_t *_jit) -{ - ASSERT(_jit->temp_fpr_saved); - _jit->temp_fpr_saved = 0; -} - static void addssr(jit_state_t *_jit, int32_t r0, int32_t r1) { @@ -409,14 +394,14 @@ movi_d(jit_state_t *_jit, int32_t r0, jit_float64_t i0) movdqxr(_jit, r0, jit_gpr_regno(ireg)); unget_temp_gpr(_jit); #else - jit_fpr_t freg = get_temp_xpr(_jit); + jit_fpr_t freg = get_temp_fpr(_jit); movi(_jit, jit_gpr_regno(ireg), data.ii[1]); movdlxr(_jit, jit_fpr_regno(freg), jit_gpr_regno(ireg)); pslq(_jit, jit_fpr_regno(freg), 32); movi(_jit, jit_gpr_regno(ireg), data.ii[0]); movdlxr(_jit, r0, jit_gpr_regno(ireg)); orpdr(_jit, r0, jit_fpr_regno(freg)); - unget_temp_xpr(_jit); + unget_temp_fpr(_jit); unget_temp_gpr(_jit); #endif } @@ -543,11 +528,11 @@ subr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) if (r0 == r1) subssr(_jit, r0, r2); else if (r0 == r2) { - jit_fpr_t reg = get_temp_xpr(_jit); + jit_fpr_t reg = get_temp_fpr(_jit); movr_f(_jit, jit_fpr_regno(reg), r0); movr_f(_jit, r0, r1); subssr(_jit, r0, jit_fpr_regno(reg)); - unget_temp_xpr(_jit); + unget_temp_fpr(_jit); } else { movr_f(_jit, r0, r1); @@ -561,11 +546,11 @@ subr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) if (r0 == r1) subsdr(_jit, r0, r2); else if (r0 == r2) { - jit_fpr_t reg = get_temp_xpr(_jit); + jit_fpr_t reg = get_temp_fpr(_jit); movr_d(_jit, jit_fpr_regno(reg), r0); movr_d(_jit, r0, r1); subsdr(_jit, r0, jit_fpr_regno(reg)); - unget_temp_xpr(_jit); + unget_temp_fpr(_jit); } else { movr_d(_jit, r0, r1); @@ -605,11 +590,11 @@ divr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) if (r0 == r1) divssr(_jit, r0, r2); else if (r0 == r2) { - jit_fpr_t reg = get_temp_xpr(_jit); + jit_fpr_t reg = get_temp_fpr(_jit); movr_f(_jit, jit_fpr_regno(reg), r0); movr_f(_jit, r0, r1); divssr(_jit, r0, jit_fpr_regno(reg)); - unget_temp_xpr(_jit); + unget_temp_fpr(_jit); } else { movr_f(_jit, r0, r1); @@ -623,11 +608,11 @@ divr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) if (r0 == r1) divsdr(_jit, r0, r2); else if (r0 == r2) { - jit_fpr_t reg = get_temp_xpr(_jit); + jit_fpr_t reg = get_temp_fpr(_jit); movr_d(_jit, jit_fpr_regno(reg), r0); movr_d(_jit, r0, r1); divsdr(_jit, r0, jit_fpr_regno(reg)); - unget_temp_xpr(_jit); + unget_temp_fpr(_jit); } else { movr_d(_jit, r0, r1); @@ -639,11 +624,11 @@ static void absr_f(jit_state_t *_jit, int32_t r0, int32_t r1) { if (r0 == r1) { - jit_fpr_t reg = get_temp_xpr(_jit); + jit_fpr_t reg = get_temp_fpr(_jit); pcmpeqlr(_jit, jit_fpr_regno(reg), jit_fpr_regno(reg)); psrl(_jit, jit_fpr_regno(reg), 1); andpsr(_jit, r0, jit_fpr_regno(reg)); - unget_temp_xpr(_jit); + unget_temp_fpr(_jit); } else { pcmpeqlr(_jit, r0, r0); @@ -656,11 +641,11 @@ static void absr_d(jit_state_t *_jit, int32_t r0, int32_t r1) { if (r0 == r1) { - jit_fpr_t reg = get_temp_xpr(_jit); + jit_fpr_t reg = get_temp_fpr(_jit); pcmpeqlr(_jit, jit_fpr_regno(reg), jit_fpr_regno(reg)); psrq(_jit, jit_fpr_regno(reg), 1); andpdr(_jit, r0, jit_fpr_regno(reg)); - unget_temp_xpr(_jit); + unget_temp_fpr(_jit); } else { pcmpeqlr(_jit, r0, r0); @@ -675,10 +660,10 @@ negr_f(jit_state_t *_jit, int32_t r0, int32_t r1) jit_gpr_t ireg = get_temp_gpr(_jit); imovi(_jit, jit_gpr_regno(ireg), 0x80000000); if (r0 == r1) { - jit_fpr_t freg = get_temp_xpr(_jit); + jit_fpr_t freg = get_temp_fpr(_jit); movdlxr(_jit, jit_fpr_regno(freg), jit_gpr_regno(ireg)); xorpsr(_jit, r0, jit_fpr_regno(freg)); - unget_temp_xpr(_jit); + unget_temp_fpr(_jit); } else { movdlxr(_jit, r0, jit_gpr_regno(ireg)); xorpsr(_jit, r0, r1); @@ -692,11 +677,11 @@ negr_d(jit_state_t *_jit, int32_t r0, int32_t r1) jit_gpr_t ireg = get_temp_gpr(_jit); imovi(_jit, jit_gpr_regno(ireg), 0x80000000); if (r0 == r1) { - jit_fpr_t freg = get_temp_xpr(_jit); + jit_fpr_t freg = get_temp_fpr(_jit); movdlxr(_jit, jit_fpr_regno(freg), jit_gpr_regno(ireg)); pslq(_jit, jit_fpr_regno(freg), 32); xorpdr(_jit, r0, jit_fpr_regno(freg)); - unget_temp_xpr(_jit); + unget_temp_fpr(_jit); } else { movdlxr(_jit, r0, jit_gpr_regno(ireg)); pslq(_jit, r0, 32); diff --git a/lightening/x86.h b/lightening/x86.h index 6e029d631..41c136e27 100644 --- a/lightening/x86.h +++ b/lightening/x86.h @@ -20,9 +20,6 @@ #ifndef _jit_x86_h #define _jit_x86_h -/* - * Types - */ #if __WORDSIZE == 32 # if defined(__x86_64__) # define __X64 1 From fc9b474da6475a9154bfb5ca825e26e34ec03722 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Fri, 10 May 2019 14:14:32 +0200 Subject: [PATCH 02/33] Refactor some bits from x86 to lightening --- lightening.h | 28 ++++++++++++++-------------- lightening/lightening.c | 31 +++++++++++++++++++++++++++++++ lightening/x86.c | 29 ----------------------------- 3 files changed, 45 insertions(+), 43 deletions(-) diff --git a/lightening.h b/lightening.h index c3163486e..c36d73cb3 100644 --- a/lightening.h +++ b/lightening.h @@ -65,6 +65,20 @@ jit_same_fprs (jit_fpr_t a, jit_fpr_t b) return jit_fpr_regno (a) == jit_fpr_regno (b); } +#if defined(__i386__) || defined(__x86_64__) +# include "lightening/x86.h" +#elif defined(__mips__) +# include "lightening/mips.h" +#elif defined(__arm__) +# include "lightening/arm.h" +#elif defined(__ppc__) || defined(__powerpc__) +# include "lightening/ppc.h" +#elif defined(__aarch64__) +# include "lightening/aarch64.h" +#elif defined(__s390__) || defined(__s390x__) +# include "lightening/s390.h" +#endif + enum jit_reloc_kind { JIT_RELOC_ABSOLUTE, @@ -87,20 +101,6 @@ typedef struct jit_reloc # define JIT_API extern #endif -#if defined(__i386__) || defined(__x86_64__) -# include "lightening/x86.h" -#elif defined(__mips__) -# include "lightening/mips.h" -#elif defined(__arm__) -# include "lightening/arm.h" -#elif defined(__ppc__) || defined(__powerpc__) -# include "lightening/ppc.h" -#elif defined(__aarch64__) -# include "lightening/aarch64.h" -#elif defined(__s390__) || defined(__s390x__) -# include "lightening/s390.h" -#endif - typedef struct jit_state jit_state_t; enum jit_operand_abi diff --git a/lightening/lightening.c b/lightening/lightening.c index 719423857..49ab5abec 100644 --- a/lightening/lightening.c +++ b/lightening/lightening.c @@ -76,6 +76,8 @@ static void jit_try_shorten(jit_state_t *_jit, jit_reloc_t reloc, struct abi_arg_iterator; +static jit_bool_t is_fpr_arg(enum jit_operand_abi arg); +static jit_bool_t is_gpr_arg(enum jit_operand_abi arg); static void reset_abi_arg_iterator(struct abi_arg_iterator *iter, size_t argc, const jit_operand_t *args); static void next_abi_arg(struct abi_arg_iterator *iter, @@ -437,6 +439,35 @@ jit_patch_there(jit_state_t* _jit, jit_reloc_t reloc, jit_pointer_t addr) FOR_EACH_INSTRUCTION(IMPL_INSTRUCTION) #undef IMPL_INSTRUCTION +static jit_bool_t +is_fpr_arg(enum jit_operand_abi arg) +{ + switch (arg) + { + case JIT_OPERAND_ABI_UINT8: + case JIT_OPERAND_ABI_INT8: + case JIT_OPERAND_ABI_UINT16: + case JIT_OPERAND_ABI_INT16: + case JIT_OPERAND_ABI_UINT32: + case JIT_OPERAND_ABI_INT32: + case JIT_OPERAND_ABI_UINT64: + case JIT_OPERAND_ABI_INT64: + case JIT_OPERAND_ABI_POINTER: + return 0; + case JIT_OPERAND_ABI_FLOAT: + case JIT_OPERAND_ABI_DOUBLE: + return 1; + default: + abort(); + } +} + +static jit_bool_t +is_gpr_arg(enum jit_operand_abi arg) +{ + return !is_fpr_arg(arg); +} + static void abi_imm_to_gpr(jit_state_t *_jit, enum jit_operand_abi abi, jit_gpr_t dst, intptr_t imm) diff --git a/lightening/x86.c b/lightening/x86.c index a79d602aa..e1665bb88 100644 --- a/lightening/x86.c +++ b/lightening/x86.c @@ -216,35 +216,6 @@ jit_init(jit_state_t *_jit) return jit_cpu.sse2; } -static jit_bool_t -is_fpr_arg(enum jit_operand_abi arg) -{ - switch (arg) - { - case JIT_OPERAND_ABI_UINT8: - case JIT_OPERAND_ABI_INT8: - case JIT_OPERAND_ABI_UINT16: - case JIT_OPERAND_ABI_INT16: - case JIT_OPERAND_ABI_UINT32: - case JIT_OPERAND_ABI_INT32: - case JIT_OPERAND_ABI_UINT64: - case JIT_OPERAND_ABI_INT64: - case JIT_OPERAND_ABI_POINTER: - return 0; - case JIT_OPERAND_ABI_FLOAT: - case JIT_OPERAND_ABI_DOUBLE: - return 1; - default: - abort(); - } -} - -static jit_bool_t -is_gpr_arg(enum jit_operand_abi arg) -{ - return !is_fpr_arg(arg); -} - static const jit_gpr_t abi_gpr_args[] = { #if __X32 /* No GPRs in args. */ From 19e7712358be67e1b1a1d764c36e0b9eb72a5762 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Tue, 14 May 2019 15:46:19 +0200 Subject: [PATCH 03/33] First pass at aarch64 assembler port --- lightening/aarch64-cpu.c | 4881 +++++++++++++++++++++----------------- lightening/aarch64-fpu.c | 1468 ++++++------ lightening/aarch64.c | 1664 +------------ lightening/aarch64.h | 221 +- 4 files changed, 3648 insertions(+), 4586 deletions(-) diff --git a/lightening/aarch64-cpu.c b/lightening/aarch64-cpu.c index 98f2dabde..0a1f01eb1 100644 --- a/lightening/aarch64-cpu.c +++ b/lightening/aarch64-cpu.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2017 Free Software Foundation, Inc. + * Copyright (C) 2013-2017, 2019 Free Software Foundation, Inc. * * This file is part of GNU lightning. * @@ -14,2433 +14,2888 @@ * License for more details. * * Authors: - * Paulo Cesar Pereira de Andrade + * Paulo Cesar Pereira de Andrade */ -#if PROTO -typedef union { -/* aarch64-opc.c */ -# define ui uint32_t -# if __BYTE_ORDER == __LITTLE_ENDIAN - /* cond2: condition in truly conditional-executed inst. */ - struct { ui b: 4; } cond2; - /* nzcv: flag bit specifier, encoded in the "nzcv" field. */ - struct { ui b: 4; } nzcv; - /* defgh: d:e:f:g:h bits in AdvSIMD modified immediate. */ - struct { ui _: 5; ui b: 5; } defgh; - /* abc: a:b:c bits in AdvSIMD modified immediate. */ - struct { ui _: 16; ui b: 3; } abc; - /* imm19: e.g. in CBZ. */ - struct { ui _: 5; ui b: 19; } imm19; - /* immhi: e.g. in ADRP. */ - struct { ui _: 5; ui b: 19; } immhi; - /* immlo: e.g. in ADRP. */ - struct { ui _: 29; ui b: 2; } immlo; - /* size: in most AdvSIMD and floating-point instructions. */ - struct { ui _: 22; ui b: 2; } size; - /* vldst_size: size field in the AdvSIMD load/store inst. */ - struct { ui _: 10; ui b: 2; } vldst_size; - /* op: in AdvSIMD modified immediate instructions. */ - struct { ui _: 29; ui b: 1; } op; - /* Q: in most AdvSIMD instructions. */ - struct { ui _: 30; ui b: 1; } Q; - /* Rt: in load/store instructions. */ - struct { ui b: 5; } Rt; - /* Rd: in many integer instructions. */ - struct { ui b: 5; } Rd; - /* Rn: in many integer instructions. */ - struct { ui _: 5; ui b: 5; } Rn; - /* Rt2: in load/store pair instructions. */ - struct { ui _: 10; ui b: 5; } Rt2; - /* Ra: in fp instructions. */ - struct { ui _: 10; ui b: 5; } Ra; - /* op2: in the system instructions. */ - struct { ui _: 5; ui b: 3; } op2; - /* CRm: in the system instructions. */ - struct { ui _: 8; ui b: 4; } CRm; - /* CRn: in the system instructions. */ - struct { ui _: 12; ui b: 4; } CRn; - /* op1: in the system instructions. */ - struct { ui _: 16; ui b: 3; } op1; - /* op0: in the system instructions. */ - struct { ui _: 19; ui b: 2; } op0; - /* imm3: in add/sub extended reg instructions. */ - struct { ui _: 10; ui b: 3; } imm3; - /* cond: condition flags as a source operand. */ - struct { ui _: 12; ui b: 4; } cond; - /* opcode: in advsimd load/store instructions. */ - struct { ui _: 12; ui b: 4; } opcode; - /* cmode: in advsimd modified immediate instructions. */ - struct { ui _: 12; ui b: 4; } cmode; - /* asisdlso_opcode: opcode in advsimd ld/st single element. */ - struct { ui _: 13; ui b: 3; } asisdlso_opcode; - /* len: in advsimd tbl/tbx instructions. */ - struct { ui _: 13; ui b: 2; } len; - /* Rm: in ld/st reg offset and some integer inst. */ - struct { ui _: 16; ui b: 5; } Rm; - /* Rs: in load/store exclusive instructions. */ - struct { ui _: 16; ui b: 5; } Rs; - /* option: in ld/st reg offset + add/sub extended reg inst. */ - struct { ui _: 13; ui b: 3; } option; - /* S: in load/store reg offset instructions. */ - struct { ui _: 12; ui b: 1; } S; - /* hw: in move wide constant instructions. */ - struct { ui _: 21; ui b: 2; } hw; - /* opc: in load/store reg offset instructions. */ - struct { ui _: 22; ui b: 2; } opc; - /* opc1: in load/store reg offset instructions. */ - struct { ui _: 23; ui b: 1; } opc1; - /* shift: in add/sub reg/imm shifted instructions. */ - struct { ui _: 22; ui b: 2; } shift; - /* type: floating point type field in fp data inst. */ - struct { ui _: 22; ui b: 2; } type; - /* ldst_size: size field in ld/st reg offset inst. */ - struct { ui _: 30; ui b: 2; } ldst_size; - /* imm6: in add/sub reg shifted instructions. */ - struct { ui _: 10; ui b: 6; } imm6; - /* imm4: in advsimd ext and advsimd ins instructions. */ - struct { ui _: 11; ui b: 4; } imm4; - /* imm5: in conditional compare (immediate) instructions. */ - struct { ui _: 16; ui b: 5; } imm5; - /* imm7: in load/store pair pre/post index instructions. */ - struct { ui _: 15; ui b: 7; } imm7; - /* imm8: in floating-point scalar move immediate inst. */ - struct { ui _: 13; ui b: 8; } imm8; - /* imm9: in load/store pre/post index instructions. */ - struct { ui _: 12; ui b: 9; } imm9; - /* imm12: in ld/st unsigned imm or add/sub shifted inst. */ - struct { ui _: 10; ui b: 12; } imm12; - /* imm14: in test bit and branch instructions. */ - struct { ui _: 5; ui b: 14; } imm14; - /* imm16: in exception instructions. */ - struct { ui _: 5; ui b: 16; } imm16; - /* imm26: in unconditional branch instructions. */ - struct { ui b: 26; } imm26; - /* imms: in bitfield and logical immediate instructions. */ - struct { ui _: 10; ui b: 6; } imms; - /* immr: in bitfield and logical immediate instructions. */ - struct { ui _: 16; ui b: 6; } immr; - /* immb: in advsimd shift by immediate instructions. */ - struct { ui _: 16; ui b: 3; } immb; - /* immh: in advsimd shift by immediate instructions. */ - struct { ui _: 19; ui b: 4; } immh; - /* N: in logical (immediate) instructions. */ - struct { ui _: 22; ui b: 1; } N; - /* index: in ld/st inst deciding the pre/post-index. */ - struct { ui _: 11; ui b: 1; } index; - /* index2: in ld/st pair inst deciding the pre/post-index. */ - struct { ui _: 24; ui b: 1; } index2; - /* sf: in integer data processing instructions. */ - struct { ui _: 31; ui b: 1; } sf; - /* H: in advsimd scalar x indexed element instructions. */ - struct { ui _: 11; ui b: 1; } H; - /* L: in advsimd scalar x indexed element instructions. */ - struct { ui _: 21; ui b: 1; } L; - /* M: in advsimd scalar x indexed element instructions. */ - struct { ui _: 20; ui b: 1; } M; - /* b5: in the test bit and branch instructions. */ - struct { ui _: 31; ui b: 1; } b5; - /* b40: in the test bit and branch instructions. */ - struct { ui _: 19; ui b: 5; } b40; - /* scale: in the fixed-point scalar to fp converting inst. */ - struct { ui _: 10; ui b: 6; } scale; -# else - struct { ui _: 28; ui b: 4; } cond2; - struct { ui _: 28; ui b: 4; } nzcv; - struct { ui _: 22; ui b: 5; } defgh; - struct { ui _: 13; ui b: 3; } abc; - struct { ui _: 8; ui b: 19; } imm19; - struct { ui _: 8; ui b: 19; } immhi; - struct { ui _: 1; ui b: 29; } immlo; - struct { ui _: 8; ui b: 2; } size; - struct { ui _: 20; ui b: 2; } vldst_size; - struct { ui _: 2; ui b: 1; } op; - struct { ui _: 1; ui b: 1; } Q; - struct { ui _: 27; ui b: 1; } Rt; - struct { ui _: 27; ui b: 1; } Rd; - struct { ui _: 22; ui b: 5; } Rn; - struct { ui _: 17; ui b: 5; } Rt2; - struct { ui _: 17; ui b: 5; } Ra; - struct { ui _: 24; ui b: 3; } op2; - struct { ui _: 20; ui b: 4; } CRm; - struct { ui _: 16; ui b: 4; } CRn; - struct { ui _: 13; ui b: 3; } op1; - struct { ui _: 11; ui b: 2; } op0; - struct { ui _: 19; ui b: 3; } imm3; - struct { ui _: 16; ui b: 4; } cond; - struct { ui _: 16; ui b: 4; } opcode; - struct { ui _: 16; ui b: 4; } cmode; - struct { ui _: 16; ui b: 3; } asisdlso_opcode; - struct { ui _: 17; ui b: 2; } len; - struct { ui _: 11; ui b: 5; } Rm; - struct { ui _: 11; ui b: 5; } Rs; - struct { ui _: 16; ui b: 3; } option; - struct { ui _: 19; ui b: 1; } S; - struct { ui _: 9; ui b: 2; } hw; - struct { ui _: 8; ui b: 2; } opc; - struct { ui _: 8; ui b: 1; } opc1; - struct { ui _: 8; ui b: 2; } shift; - struct { ui _: 8; ui b: 2; } type; - struct { ui b: 2; } ldst_size; - struct { ui _: 16; ui b: 6; } imm6; - struct { ui _: 17; ui b: 4; } imm4; - struct { ui _: 11; ui b: 5; } imm5; - struct { ui _: 10; ui b: 7; } imm7; - struct { ui _: 11; ui b: 8; } imm8; - struct { ui _: 11; ui b: 9; } imm9; - struct { ui _: 10; ui b: 12; } imm12; - struct { ui _: 13; ui b: 14; } imm14; - struct { ui _: 11; ui b: 16; } imm16; - struct { ui _: 6; ui b: 26; } imm26; - struct { ui _: 16; ui b: 6; } imms; - struct { ui _: 10; ui b: 6; } immr; - struct { ui _: 13; ui b: 3; } immb; - struct { ui _: 9; ui b: 4; } immh; - struct { ui _: 9; ui b: 1; } N; - struct { ui _: 20; ui b: 1; } index; - struct { ui _: 7; ui b: 1; } index2; - struct { ui b: 1; } sf; - struct { ui _: 20; ui b: 1; } H; - struct { ui _: 10; ui b: 1; } L; - struct { ui _: 11; ui b: 1; } M; - struct { ui b: 1; } b5; - struct { ui _: 8; ui b: 5; } b40; - struct { ui _: 16; ui b: 6; } scale; -# endif - int32_t w; -# undef ui -} instr_t; -# define stack_framesize 160 -# define ii(i) *_jit->pc.ui++ = i -# define ldr(r0,r1) ldr_l(r0,r1) -# define ldxr(r0,r1,r2) ldxr_l(r0,r1,r2) -# define ldxi(r0,r1,i0) ldxi_l(r0,r1,i0) -# define stxi(i0,r0,r1) stxi_l(i0,r0,r1) -# define FP_REGNO 0x1d -# define LR_REGNO 0x1e -# define SP_REGNO 0x1f -# define XZR_REGNO 0x1f -# define WZR_REGNO XZR_REGNO -# define LSL_12 0x00400000 -# define MOVI_LSL_16 0x00200000 -# define MOVI_LSL_32 0x00400000 -# define MOVI_LSL_48 0x00600000 -# define XS 0x80000000 /* Wn -> Xn */ -# define DS 0x00400000 /* Sn -> Dn */ -# define CC_NE 0x0 -# define CC_EQ 0x1 -# define CC_CC 0x2 -# define CC_LO CC_CC -# define CC_CS 0x3 -# define CC_HS CC_CS -# define CC_PL 0x4 -# define CC_MI 0x5 -# define CC_VC 0x6 -# define CC_VS 0x7 -# define CC_LS 0x8 -# define CC_HI 0x9 -# define CC_LT 0xa -# define CC_GE 0xb -# define CC_LE 0xc -# define CC_GT 0xd -# define CC_NV 0xe -# define CC_AL 0xf -/* Branches need inverted condition */ -# define BCC_EQ 0x0 -# define BCC_NE 0x1 -# define BCC_CS 0x2 -# define BCC_HS BCC_CS -# define BCC_CC 0x3 -# define BCC_LO BCC_CC -# define BCC_MI 0x4 -# define BCC_PL 0x5 -# define BCC_VS 0x6 -# define BCC_VC 0x7 -# define BCC_HI 0x8 -# define BCC_LS 0x9 -# define BCC_GE 0xa -# define BCC_LT 0xb -# define BCC_GT 0xc -# define BCC_LE 0xd -# define BCC_AL 0xe -# define BCC_NV 0xf -/* adapted and cut down to only tested and required by lightning, - * from data in binutils/aarch64-tbl.h */ -# define A64_ADCS 0x3a000000 -# define A64_SBCS 0x7a000000 -# define A64_ADDI 0x11000000 -# define A64_ADDSI 0xb1000000 -# define A64_SUBI 0x51000000 -# define A64_SUBSI 0x71000000 -# define A64_ADD 0x0b000000 -# define A64_ADDS 0x2b000000 -# define A64_SUB 0x4b000000 -# define A64_NEG 0x4b0003e0 -# define A64_SUBS 0x6b000000 -# define A64_CMP 0x6b00001f -# define A64_SBFM 0x93400000 -# define A64_UBFM 0x53400000 -# define A64_UBFX 0x53000000 -# define A64_B 0x14000000 -# define A64_BL 0x94000000 -# define A64_BR 0xd61f0000 -# define A64_BLR 0xd63f0000 -# define A64_RET 0xd65f0000 -# define A64_CBZ 0x34000000 -# define A64_CBNZ 0x35000000 -# define A64_B_C 0x54000000 -# define A64_CSINC 0x1a800400 -# define A64_REV 0xdac00c00 -# define A64_UDIV 0x1ac00800 -# define A64_SDIV 0x1ac00c00 -# define A64_LSL 0x1ac02000 -# define A64_LSR 0x1ac02400 -# define A64_ASR 0x1ac02800 -# define A64_MUL 0x1b007c00 -# define A64_SMULL 0x9b207c00 -# define A64_SMULH 0x9b407c00 -# define A64_UMULL 0x9ba07c00 -# define A64_UMULH 0x9bc07c00 -# define A64_STRBI 0x39000000 -# define A64_LDRBI 0x39400000 -# define A64_LDRSBI 0x39800000 -# define A64_STRI 0xf9000000 -# define A64_LDRI 0xf9400000 -# define A64_STRHI 0x79000000 -# define A64_LDRHI 0x79400000 -# define A64_LDRSHI 0x79800000 -# define A64_STRWI 0xb9000000 -# define A64_LDRWI 0xb9400000 -# define A64_LDRSWI 0xb9800000 -# define A64_STRB 0x38206800 -# define A64_LDRB 0x38606800 -# define A64_LDRSB 0x38e06800 -# define A64_STR 0xf8206800 -# define A64_LDR 0xf8606800 -# define A64_STRH 0x78206800 -# define A64_LDRH 0x78606800 -# define A64_LDRSH 0x78a06800 -# define A64_STRW 0xb8206800 -# define A64_LDRW 0xb8606800 -# define A64_LDRSW 0xb8a06800 -# define A64_STURB 0x38000000 -# define A64_LDURB 0x38400000 -# define A64_LDURSB 0x38800000 -# define A64_STUR 0xf8000000 -# define A64_LDUR 0xf8400000 -# define A64_STURH 0x78000000 -# define A64_LDURH 0x78400000 -# define A64_LDURSH 0x78800000 -# define A64_STURW 0xb8000000 -# define A64_LDURW 0xb8400000 -# define A64_LDURSW 0xb8800000 -# define A64_STP 0x29000000 -# define A64_LDP 0x29400000 -# define A64_STP_POS 0x29800000 -# define A64_LDP_PRE 0x28c00000 -# define A64_ANDI 0x12400000 -# define A64_ORRI 0x32400000 -# define A64_EORI 0x52400000 -# define A64_ANDSI 0x72000000 -# define A64_AND 0x0a000000 -# define A64_ORR 0x2a000000 -# define A64_MOV 0x2a0003e0 /* AKA orr Rd,xzr,Rm */ -# define A64_MVN 0x2a2003e0 -# define A64_UXTW 0x2a0003e0 /* AKA MOV */ -# define A64_EOR 0x4a000000 -# define A64_ANDS 0x6a000000 -# define A64_MOVN 0x12800000 -# define A64_MOVZ 0x52800000 -# define A64_MOVK 0x72800000 -# define SBFM(Rd,Rn,ImmR,ImmS) oxxrs(A64_SBFM|XS,Rd,Rn,ImmR,ImmS) -# define UBFM(Rd,Rn,ImmR,ImmS) oxxrs(A64_UBFM|XS,Rd,Rn,ImmR,ImmS) -# define UBFX(Rd,Rn,ImmR,ImmS) oxxrs(A64_UBFX,Rd,Rn,ImmR,ImmS) -# define CMP(Rn,Rm) oxx_(A64_CMP|XS,Rn,Rm) -# define CMPI(Rn,Imm12) oxxi(A64_SUBSI|XS,XZR_REGNO,Rn,Imm12) -# define CMPI_12(Rn,Imm12) oxxi(A64_SUBSI|XS|LSL_12,XZR_REGNO,Rn,Imm12) -# define CMNI(Rn,Imm12) oxxi(A64_ADDSI|XS,XZR_REGNO,Rn,Imm12) -# define CMNI_12(Rn,Imm12) oxxi(A64_ADDSI|XS|LSL_12,XZR_REGNO,Rn,Imm12) -# define CSINC(Rd,Rn,Rm,Cc) oxxxc(A64_CSINC|XS,Rd,Rn,Rm,Cc) -# define TST(Rn,Rm) oxxx(A64_ANDS|XS,XZR_REGNO,Rn,Rm) -/* actually should use oxxrs but logical_immediate returns proper encoding */ -# define TSTI(Rn,Imm12) oxxi(A64_ANDSI,XZR_REGNO,Rn,Imm12) -# define MOV(Rd,Rm) ox_x(A64_MOV|XS,Rd,Rm) -# define MVN(Rd,Rm) ox_x(A64_MVN|XS,Rd,Rm) -# define NEG(Rd,Rm) ox_x(A64_NEG|XS,Rd,Rm) -# define MOVN(Rd,Imm16) ox_h(A64_MOVN|XS,Rd,Imm16) -# define MOVN_16(Rd,Imm16) ox_h(A64_MOVN|XS|MOVI_LSL_16,Rd,Imm16) -# define MOVN_32(Rd,Imm16) ox_h(A64_MOVN|XS|MOVI_LSL_32,Rd,Imm16) -# define MOVN_48(Rd,Imm16) ox_h(A64_MOVN|XS|MOVI_LSL_48,Rd,Imm16) -# define MOVZ(Rd,Imm16) ox_h(A64_MOVZ|XS,Rd,Imm16) -# define MOVZ_16(Rd,Imm16) ox_h(A64_MOVZ|XS|MOVI_LSL_16,Rd,Imm16) -# define MOVZ_32(Rd,Imm16) ox_h(A64_MOVZ|XS|MOVI_LSL_32,Rd,Imm16) -# define MOVZ_48(Rd,Imm16) ox_h(A64_MOVZ|XS|MOVI_LSL_48,Rd,Imm16) -# define MOVK(Rd,Imm16) ox_h(A64_MOVK|XS,Rd,Imm16) -# define MOVK_16(Rd,Imm16) ox_h(A64_MOVK|XS|MOVI_LSL_16,Rd,Imm16) -# define MOVK_32(Rd,Imm16) ox_h(A64_MOVK|XS|MOVI_LSL_32,Rd,Imm16) -# define MOVK_48(Rd,Imm16) ox_h(A64_MOVK|XS|MOVI_LSL_48,Rd,Imm16) -# define ADD(Rd,Rn,Rm) oxxx(A64_ADD|XS,Rd,Rn,Rm) -# define ADDI(Rd,Rn,Imm12) oxxi(A64_ADDI|XS,Rd,Rn,Imm12) -# define ADDI_12(Rd,Rn,Imm12) oxxi(A64_ADDI|XS|LSL_12,Rd,Rn,Imm12) -# define MOV_XSP(Rd,Rn) ADDI(Rd,Rn,0) -# define ADDS(Rd,Rn,Rm) oxxx(A64_ADDS|XS,Rd,Rn,Rm) -# define ADDSI(Rd,Rn,Imm12) oxxi(A64_ADDSI|XS,Rd,Rn,Imm12) -# define ADDSI_12(Rd,Rn,Imm12) oxxi(A64_ADDSI|XS|LSL_12,Rd,Rn,Imm12) -# define ADCS(Rd,Rn,Rm) oxxx(A64_ADCS|XS,Rd,Rn,Rm) -# define SUB(Rd,Rn,Rm) oxxx(A64_SUB|XS,Rd,Rn,Rm) -# define SUBI(Rd,Rn,Imm12) oxxi(A64_SUBI|XS,Rd,Rn,Imm12) -# define SUBI_12(Rd,Rn,Imm12) oxxi(A64_SUBI|XS|LSL_12,Rd,Rn,Imm12) -# define SUBS(Rd,Rn,Rm) oxxx(A64_SUBS|XS,Rd,Rn,Rm) -# define SUBSI(Rd,Rn,Imm12) oxxi(A64_SUBSI|XS,Rd,Rn,Imm12) -# define SUBSI_12(Rd,Rn,Imm12) oxxi(A64_SUBSI|XS|LSL_12,Rd,Rn,Imm12) -# define SBCS(Rd,Rn,Rm) oxxx(A64_SBCS|XS,Rd,Rn,Rm) -# define MUL(Rd,Rn,Rm) oxxx(A64_MUL|XS,Rd,Rn,Rm) -# define SMULL(Rd,Rn,Rm) oxxx(A64_SMULL,Rd,Rn,Rm) -# define SMULH(Rd,Rn,Rm) oxxx(A64_SMULH,Rd,Rn,Rm) -# define UMULL(Rd,Rn,Rm) oxxx(A64_UMULL,Rd,Rn,Rm) -# define UMULH(Rd,Rn,Rm) oxxx(A64_UMULH,Rd,Rn,Rm) -# define SDIV(Rd,Rn,Rm) oxxx(A64_SDIV|XS,Rd,Rn,Rm) -# define UDIV(Rd,Rn,Rm) oxxx(A64_UDIV|XS,Rd,Rn,Rm) -# define LSL(Rd,Rn,Rm) oxxx(A64_LSL|XS,Rd,Rn,Rm) -# define LSLI(r0,r1,i0) UBFM(r0,r1,(64-i0)&63,63-i0) -# define ASR(Rd,Rn,Rm) oxxx(A64_ASR|XS,Rd,Rn,Rm) -# define ASRI(r0,r1,i0) SBFM(r0,r1,i0,63) -# define LSR(Rd,Rn,Rm) oxxx(A64_LSR|XS,Rd,Rn,Rm) -# define LSRI(r0,r1,i0) UBFM(r0,r1,i0,63) -# define AND(Rd,Rn,Rm) oxxx(A64_AND|XS,Rd,Rn,Rm) -/* actually should use oxxrs but logical_immediate returns proper encoding */ -# define ANDI(Rd,Rn,Imm12) oxxi(A64_ANDI|XS,Rd,Rn,Imm12) -# define ORR(Rd,Rn,Rm) oxxx(A64_ORR|XS,Rd,Rn,Rm) -/* actually should use oxxrs but logical_immediate returns proper encoding */ -# define ORRI(Rd,Rn,Imm12) oxxi(A64_ORRI|XS,Rd,Rn,Imm12) -# define EOR(Rd,Rn,Rm) oxxx(A64_EOR|XS,Rd,Rn,Rm) -/* actually should use oxxrs but logical_immediate returns proper encoding */ -# define EORI(Rd,Rn,Imm12) oxxi(A64_EORI|XS,Rd,Rn,Imm12) -# define SXTB(Rd,Rn) SBFM(Rd,Rn,0,7) -# define SXTH(Rd,Rn) SBFM(Rd,Rn,0,15) -# define SXTW(Rd,Rn) SBFM(Rd,Rn,0,31) -# define UXTB(Rd,Rn) UBFX(Rd,Rn,0,7) -# define UXTH(Rd,Rn) UBFX(Rd,Rn,0,15) -# define UXTW(Rd,Rm) ox_x(A64_UXTW,Rd,Rm) -# define REV(Rd,Rn) o_xx(A64_REV,Rd,Rn) -# define LDRSB(Rt,Rn,Rm) oxxx(A64_LDRSB,Rt,Rn,Rm) -# define LDRSBI(Rt,Rn,Imm12) oxxi(A64_LDRSBI,Rt,Rn,Imm12) -# define LDURSB(Rt,Rn,Imm9) oxx9(A64_LDURSB,Rt,Rn,Imm9) -# define LDRB(Rt,Rn,Rm) oxxx(A64_LDRB,Rt,Rn,Rm) -# define LDRBI(Rt,Rn,Imm12) oxxi(A64_LDRBI,Rt,Rn,Imm12) -# define LDURB(Rt,Rn,Imm9) oxx9(A64_LDURB,Rt,Rn,Imm9) -# define LDRSH(Rt,Rn,Rm) oxxx(A64_LDRSH,Rt,Rn,Rm) -# define LDRSHI(Rt,Rn,Imm12) oxxi(A64_LDRSHI,Rt,Rn,Imm12) -# define LDURSH(Rt,Rn,Imm9) oxx9(A64_LDURSH,Rt,Rn,Imm9) -# define LDRH(Rt,Rn,Rm) oxxx(A64_LDRH,Rt,Rn,Rm) -# define LDRHI(Rt,Rn,Imm12) oxxi(A64_LDRHI,Rt,Rn,Imm12) -# define LDURH(Rt,Rn,Imm9) oxx9(A64_LDURH,Rt,Rn,Imm9) -# define LDRSW(Rt,Rn,Rm) oxxx(A64_LDRSW,Rt,Rn,Rm) -# define LDRSWI(Rt,Rn,Imm12) oxxi(A64_LDRSWI,Rt,Rn,Imm12) -# define LDURSW(Rt,Rn,Imm9) oxx9(A64_LDURSW,Rt,Rn,Imm9) -# define LDRW(Rt,Rn,Rm) oxxx(A64_LDRW,Rt,Rn,Rm) -# define LDRWI(Rt,Rn,Imm12) oxxi(A64_LDRWI,Rt,Rn,Imm12) -# define LDURW(Rt,Rn,Imm9) oxx9(A64_LDURW,Rt,Rn,Imm9) -# define LDR(Rt,Rn,Rm) oxxx(A64_LDR,Rt,Rn,Rm) -# define LDRI(Rt,Rn,Imm12) oxxi(A64_LDRI,Rt,Rn,Imm12) -# define LDUR(Rt,Rn,Imm9) oxx9(A64_LDUR,Rt,Rn,Imm9) -# define STRB(Rt,Rn,Rm) oxxx(A64_STRB,Rt,Rn,Rm) -# define STRBI(Rt,Rn,Imm12) oxxi(A64_STRBI,Rt,Rn,Imm12) -# define STURB(Rt,Rn,Imm9) oxx9(A64_STURB,Rt,Rn,Imm9) -# define STRH(Rt,Rn,Rm) oxxx(A64_STRH,Rt,Rn,Rm) -# define STRHI(Rt,Rn,Imm12) oxxi(A64_STRHI,Rt,Rn,Imm12) -# define STURH(Rt,Rn,Imm9) oxx9(A64_STURH,Rt,Rn,Imm9) -# define STRW(Rt,Rn,Rm) oxxx(A64_STRW,Rt,Rn,Rm) -# define STRWI(Rt,Rn,Imm12) oxxi(A64_STRWI,Rt,Rn,Imm12) -# define STURW(Rt,Rn,Imm9) oxx9(A64_STURW,Rt,Rn,Imm9) -# define STR(Rt,Rn,Rm) oxxx(A64_STR,Rt,Rn,Rm) -# define STRI(Rt,Rn,Imm12) oxxi(A64_STRI,Rt,Rn,Imm12) -# define STUR(Rt,Rn,Imm9) oxx9(A64_STUR,Rt,Rn,Imm9) -# define LDPI(Rt,Rt2,Rn,Simm7) oxxx7(A64_LDP|XS,Rt,Rt2,Rn,Simm7) -# define STPI(Rt,Rt2,Rn,Simm7) oxxx7(A64_STP|XS,Rt,Rt2,Rn,Simm7) -# define LDPI_PRE(Rt,Rt2,Rn,Simm7) oxxx7(A64_LDP_PRE|XS,Rt,Rt2,Rn,Simm7) -# define STPI_POS(Rt,Rt2,Rn,Simm7) oxxx7(A64_STP_POS|XS,Rt,Rt2,Rn,Simm7) -# define CSET(Rd,Cc) CSINC(Rd,XZR_REGNO,XZR_REGNO,Cc) -# define B(Simm26) o26(A64_B,Simm26) -# define BL(Simm26) o26(A64_BL,Simm26) -# define BR(Rn) o_x_(A64_BR,Rn) -# define BLR(Rn) o_x_(A64_BLR,Rn) -# define RET() o_x_(A64_RET,LR_REGNO) -# define B_C(Cc,Simm19) oc19(A64_B_C,Cc,Simm19) -# define CBZ(Rd,Simm19) ox19(A64_CBZ|XS,Rd,Simm19) -# define CBNZ(Rd,Simm19) ox19(A64_CBNZ|XS,Rd,Simm19) -# define NOP() ii(0xd503201f) -static int32_t logical_immediate(jit_word_t); -# define oxxx(Op,Rd,Rn,Rm) _oxxx(_jit,Op,Rd,Rn,Rm) -static void _oxxx(jit_state_t*,int32_t,int32_t,int32_t,int32_t); -# define oxxi(Op,Rd,Rn,Imm12) _oxxi(_jit,Op,Rd,Rn,Imm12) -static void _oxxi(jit_state_t*,int32_t,int32_t,int32_t,int32_t); -# define oxx9(Op,Rd,Rn,Imm9) _oxx9(_jit,Op,Rd,Rn,Imm9) -static void _oxx9(jit_state_t*,int32_t,int32_t,int32_t,int32_t); -# define ox19(Op,Rd,Simm19) _ox19(_jit,Op,Rd,Simm19) -static void _ox19(jit_state_t*,int32_t,int32_t,int32_t); -# define oc19(Op,Cc,Simm19) _oc19(_jit,Op,Cc,Simm19) -static void _oc19(jit_state_t*,int32_t,int32_t,int32_t); -# define o26(Op,Simm26) _o26(_jit,Op,Simm26) -static void _oc26(jit_state_t*,int32_t,int32_t); -# define ox_x(Op,Rd,Rn) _ox_x(_jit,Op,Rd,Rn) -static void _ox_x(jit_state_t*,int32_t,int32_t,int32_t); -# define o_xx(Op,Rd,Rn) _o_xx(_jit,Op,Rd,Rn) -static void _o_xx(jit_state_t*,int32_t,int32_t,int32_t); -# define oxx_(Op,Rn,Rm) _oxx_(_jit,Op,Rn,Rm) -static void _oxx_(jit_state_t*,int32_t,int32_t,int32_t); -# define o_x_(Op,Rn) _o_x_(_jit,Op,Rn) -static void _o_x_(jit_state_t*,int32_t,int32_t); -# define ox_h(Op,Rd,Imm16) _ox_h(_jit,Op,Rd,Imm16) -static void _ox_h(jit_state_t*,int32_t,int32_t,int32_t); -# define oxxrs(Op,Rd,Rn,R,S) _oxxrs(_jit,Op,Rd,Rn,R,S) -static void _oxxrs(jit_state_t*,int32_t,int32_t, - int32_t,int32_t,int32_t); -# define oxxxc(Op,Rd,Rn,Rm,Cc) _oxxxc(_jit,Op,Rd,Rn,Rm,Cc) -static void _oxxxc(jit_state_t*,int32_t,int32_t, - int32_t,int32_t,int32_t); -# define oxxx7(Op,Rt,Rt2,Rn,Simm7) _oxxx7(_jit,Op,Rt,Rt2,Rn,Simm7) -static void _oxxx7(jit_state_t*,int32_t, - int32_t,int32_t,int32_t,int32_t); -# define nop(i0) _nop(_jit,i0) -static void _nop(jit_state_t*,int32_t); -# define addr(r0,r1,r2) ADD(r0,r1,r2) -# define addi(r0,r1,i0) _addi(_jit,r0,r1,i0) -static void _addi(jit_state_t*,int32_t,int32_t,jit_word_t); -# define addcr(r0,r1,r2) ADDS(r0,r1,r2) -# define addci(r0,r1,i0) _addci(_jit,r0,r1,i0) -static void _addci(jit_state_t*,int32_t,int32_t,jit_word_t); -# define addxr(r0,r1,r2) ADCS(r0,r1,r2) -# define addxi(r0,r1,i0) _addxi(_jit,r0,r1,i0) -static void _addxi(jit_state_t*,int32_t,int32_t,jit_word_t); -# define subr(r0,r1,r2) SUB(r0,r1,r2) -# define subi(r0,r1,i0) _subi(_jit,r0,r1,i0) -static void _subi(jit_state_t*,int32_t,int32_t,jit_word_t); -# define subcr(r0,r1,r2) SUBS(r0,r1,r2) -# define subci(r0,r1,i0) _subci(_jit,r0,r1,i0) -static void _subci(jit_state_t*,int32_t,int32_t,jit_word_t); -# define subxr(r0,r1,r2) SBCS(r0,r1,r2) -# define subxi(r0,r1,i0) _subxi(_jit,r0,r1,i0) -static void _subxi(jit_state_t*,int32_t,int32_t,jit_word_t); -# define rsbi(r0, r1, i0) _rsbi(_jit, r0, r1, i0) -static void _rsbi(jit_state_t*,int32_t,int32_t,jit_word_t); -# define mulr(r0,r1,r2) MUL(r0,r1,r2) -# define muli(r0,r1,i0) _muli(_jit,r0,r1,i0) -static void _muli(jit_state_t*,int32_t,int32_t,jit_word_t); -# define qmulr(r0,r1,r2,r3) _qmulr(_jit,r0,r1,r2,r3) -static void _qmulr(jit_state_t*,int32_t, - int32_t,int32_t,int32_t); -# define qmuli(r0,r1,r2,i0) _qmuli(_jit,r0,r1,r2,i0) -static void _qmuli(jit_state_t*,int32_t, - int32_t,int32_t,jit_word_t); -# define qmulr_u(r0,r1,r2,r3) _qmulr_u(_jit,r0,r1,r2,r3) -static void _qmulr_u(jit_state_t*,int32_t, - int32_t,int32_t,int32_t); -# define qmuli_u(r0,r1,r2,i0) _qmuli_u(_jit,r0,r1,r2,i0) -static void _qmuli_u(jit_state_t*,int32_t, - int32_t,int32_t,jit_word_t); -# define divr(r0,r1,r2) SDIV(r0,r1,r2) -# define divi(r0,r1,i0) _divi(_jit,r0,r1,i0) -static void _divi(jit_state_t*,int32_t,int32_t,jit_word_t); -# define divr_u(r0,r1,r2) UDIV(r0,r1,r2) -# define divi_u(r0,r1,i0) _divi_u(_jit,r0,r1,i0) -static void _divi_u(jit_state_t*,int32_t,int32_t,jit_word_t); -# define qdivr(r0,r1,r2,r3) _iqdivr(_jit,1,r0,r1,r2,r3) -# define qdivr_u(r0,r1,r2,r3) _iqdivr(_jit,0,r0,r1,r2,r3) -static void _iqdivr(jit_state_t*,jit_bool_t, - int32_t,int32_t,int32_t,int32_t); -# define qdivi(r0,r1,r2,i0) _qdivi(_jit,r0,r1,r2,i0) -static void _qdivi(jit_state_t*,int32_t, - int32_t,int32_t,jit_word_t); -# define qdivi_u(r0,r1,r2,i0) _qdivi_u(_jit,r0,r1,r2,i0) -static void _qdivi_u(jit_state_t*,int32_t, - int32_t,int32_t,jit_word_t); -# define remr(r0,r1,r2) _remr(_jit,r0,r1,r2) -static void _remr(jit_state_t*,int32_t,int32_t,int32_t); -# define remi(r0,r1,i0) _remi(_jit,r0,r1,i0) -static void _remi(jit_state_t*,int32_t,int32_t,jit_word_t); -# define remr_u(r0,r1,r2) _remr_u(_jit,r0,r1,r2) -static void _remr_u(jit_state_t*,int32_t,int32_t,int32_t); -# define remi_u(r0,r1,i0) _remi_u(_jit,r0,r1,i0) -static void _remi_u(jit_state_t*,int32_t,int32_t,jit_word_t); -# define lshr(r0,r1,r2) LSL(r0,r1,r2) -# define lshi(r0,r1,i0) _lshi(_jit,r0,r1,i0) -static void _lshi(jit_state_t*,int32_t,int32_t,jit_word_t); -# define rshr(r0,r1,r2) ASR(r0,r1,r2) -# define rshi(r0,r1,i0) _rshi(_jit,r0,r1,i0) -static void _rshi(jit_state_t*,int32_t,int32_t,jit_word_t); -# define rshr_u(r0,r1,r2) LSR(r0,r1,r2) -# define rshi_u(r0,r1,i0) _rshi_u(_jit,r0,r1,i0) -static void _rshi_u(jit_state_t*,int32_t,int32_t,jit_word_t); -# define negr(r0,r1) NEG(r0,r1) -# define comr(r0,r1) MVN(r0,r1) -# define andr(r0,r1,r2) AND(r0,r1,r2) -# define andi(r0,r1,i0) _andi(_jit,r0,r1,i0) -static void _andi(jit_state_t*,int32_t,int32_t,jit_word_t); -# define orr(r0,r1,r2) ORR(r0,r1,r2) -# define ori(r0,r1,i0) _ori(_jit,r0,r1,i0) -static void _ori(jit_state_t*,int32_t,int32_t,jit_word_t); -# define xorr(r0,r1,r2) EOR(r0,r1,r2) -# define xori(r0,r1,i0) _xori(_jit,r0,r1,i0) -static void _xori(jit_state_t*,int32_t,int32_t,jit_word_t); -# define ldr_c(r0,r1) LDRSBI(r0,r1,0) -# define ldi_c(r0,i0) _ldi_c(_jit,r0,i0) -static void _ldi_c(jit_state_t*,int32_t,jit_word_t); -# define ldr_uc(r0,r1) _ldr_uc(_jit,r0,r1) -static void _ldr_uc(jit_state_t*,int32_t,int32_t); -# define ldi_uc(r0,i0) _ldi_uc(_jit,r0,i0) -static void _ldi_uc(jit_state_t*,int32_t,jit_word_t); -# define ldr_s(r0,r1) LDRSHI(r0,r1,0) -# define ldi_s(r0,i0) _ldi_s(_jit,r0,i0) -static void _ldi_s(jit_state_t*,int32_t,jit_word_t); -# define ldr_us(r0,r1) _ldr_us(_jit,r0,r1) -static void _ldr_us(jit_state_t*,int32_t,int32_t); -# define ldi_us(r0,i0) _ldi_us(_jit,r0,i0) -static void _ldi_us(jit_state_t*,int32_t,jit_word_t); -# define ldr_i(r0,r1) LDRSWI(r0,r1,0) -# define ldi_i(r0,i0) _ldi_i(_jit,r0,i0) -static void _ldi_i(jit_state_t*,int32_t,jit_word_t); -# define ldr_ui(r0,r1) _ldr_ui(_jit,r0,r1) -static void _ldr_ui(jit_state_t*,int32_t,int32_t); -# define ldi_ui(r0,i0) _ldi_ui(_jit,r0,i0) -static void _ldi_ui(jit_state_t*,int32_t,jit_word_t); -# define ldr_l(r0,r1) LDRI(r0,r1,0) -static void _ldr_l(jit_state_t*,int32_t,int32_t); -# define ldi_l(r0,i0) _ldi_l(_jit,r0,i0) -static void _ldi_l(jit_state_t*,int32_t,jit_word_t); -# define ldxr_c(r0,r1,r2) _ldxr_c(_jit,r0,r1,r2) -static void _ldxr_c(jit_state_t*,int32_t,int32_t,int32_t); -# define ldxi_c(r0,r1,i0) _ldxi_c(_jit,r0,r1,i0) -static void _ldxi_c(jit_state_t*,int32_t,int32_t,jit_word_t); -# define ldxr_uc(r0,r1,r2) _ldxr_uc(_jit,r0,r1,r2) -static void _ldxr_uc(jit_state_t*,int32_t,int32_t,int32_t); -# define ldxi_uc(r0,r1,i0) _ldxi_uc(_jit,r0,r1,i0) -static void _ldxi_uc(jit_state_t*,int32_t,int32_t,jit_word_t); -# define ldxr_s(r0,r1,r2) LDRSH(r0,r1,r2) -# define ldxi_s(r0,r1,i0) _ldxi_s(_jit,r0,r1,i0) -static void _ldxi_s(jit_state_t*,int32_t,int32_t,jit_word_t); -# define ldxr_us(r0,r1,r2) _ldxr_us(_jit,r0,r1,r2) -static void _ldxr_us(jit_state_t*,int32_t,int32_t,int32_t); -# define ldxi_us(r0,r1,i0) _ldxi_us(_jit,r0,r1,i0) -static void _ldxi_us(jit_state_t*,int32_t,int32_t,jit_word_t); -# define ldxr_i(r0,r1,r2) LDRSW(r0,r1,r2) -# define ldxi_i(r0,r1,i0) _ldxi_i(_jit,r0,r1,i0) -static void _ldxi_i(jit_state_t*,int32_t,int32_t,jit_word_t); -# define ldxr_ui(r0,r1,r2) _ldxr_ui(_jit,r0,r1,r2) -static void _ldxr_ui(jit_state_t*,int32_t,int32_t,int32_t); -# define ldxi_ui(r0,r1,i0) _ldxi_ui(_jit,r0,r1,i0) -static void _ldxi_ui(jit_state_t*,int32_t,int32_t,jit_word_t); -# define ldxr_l(r0,r1,r2) LDR(r0,r1,r2) -# define ldxi_l(r0,r1,i0) _ldxi_l(_jit,r0,r1,i0) -static void _ldxi_l(jit_state_t*,int32_t,int32_t,jit_word_t); -# define str_c(r0,r1) STRBI(r1,r0,0) -# define sti_c(i0,r0) _sti_c(_jit,i0,r0) -static void _sti_c(jit_state_t*,jit_word_t,int32_t); -# define str_s(r0,r1) STRHI(r1,r0,0) -# define sti_s(i0,r0) _sti_s(_jit,i0,r0) -static void _sti_s(jit_state_t*,jit_word_t,int32_t); -# define str_i(r0,r1) STRWI(r1,r0,0) -# define sti_i(i0,r0) _sti_i(_jit,i0,r0) -static void _sti_i(jit_state_t*,jit_word_t,int32_t); -# define str_l(r0,r1) STRI(r1,r0,0) -# define sti_l(i0,r0) _sti_l(_jit,i0,r0) -static void _sti_l(jit_state_t*,jit_word_t,int32_t); -# define stxr_c(r0,r1,r2) STRB(r2,r1,r0) -# define stxi_c(i0,r0,r1) _stxi_c(_jit,i0,r0,r1) -static void _stxi_c(jit_state_t*,jit_word_t,int32_t,int32_t); -# define stxr_s(r0,r1,r2) STRH(r2,r1,r0) -# define stxi_s(i0,r0,r1) _stxi_s(_jit,i0,r0,r1) -static void _stxi_s(jit_state_t*,jit_word_t,int32_t,int32_t); -# define stxr_i(r0,r1,r2) STRW(r2,r1,r0) -# define stxi_i(i0,r0,r1) _stxi_i(_jit,i0,r0,r1) -static void _stxi_i(jit_state_t*,jit_word_t,int32_t,int32_t); -# define stxr_l(r0,r1,r2) STR(r2,r1,r0) -# define stxi_l(i0,r0,r1) _stxi_l(_jit,i0,r0,r1) -static void _stxi_l(jit_state_t*,jit_word_t,int32_t,int32_t); -# if __BYTE_ORDER == __LITTLE_ENDIAN -# define bswapr_us(r0,r1) _bswapr_us(_jit,r0,r1) -static void _bswapr_us(jit_state_t*,int32_t,int32_t); -# define bswapr_ui(r0,r1) _bswapr_ui(_jit,r0,r1) -static void _bswapr_ui(jit_state_t*,int32_t,int32_t); -# define bswapr_ul(r0,r1) REV(r0,r1) -# else -# define bswapr_us(r0,r1) extr_us(r0,r1) -# define bswapr_ui(r0,r1) extr_ui(r0,r1) -# define bswapr_ul(r0,r1) movr(r0,r1) -# endif -# define extr_c(r0,r1) SXTB(r0,r1) -# define extr_uc(r0,r1) UXTB(r0,r1) -# define extr_s(r0,r1) SXTH(r0,r1) -# define extr_us(r0,r1) UXTH(r0,r1) -# define extr_i(r0,r1) SXTW(r0,r1) -# define extr_ui(r0,r1) UXTW(r0,r1) -# define movr(r0,r1) _movr(_jit,r0,r1) -static void _movr(jit_state_t*,int32_t,int32_t); -# define movi(r0,i0) _movi(_jit,r0,i0) -static void _movi(jit_state_t*,int32_t,jit_word_t); -# define movi_p(r0,i0) _movi_p(_jit,r0,i0) -static jit_word_t _movi_p(jit_state_t*,int32_t,jit_word_t); -# define ccr(cc,r0,r1,r2) _ccr(_jit,cc,r0,r1,r2) -static void _ccr(jit_state_t*,int32_t,int32_t,int32_t,int32_t); -# define cci(cc,r0,r1,i0) _cci(_jit,cc,r0,r1,i0) -static void _cci(jit_state_t*,int32_t,int32_t,int32_t,jit_word_t); -# define ltr(r0,r1,r2) ccr(CC_LT,r0,r1,r2) -# define lti(r0,r1,i0) cci(CC_LT,r0,r1,i0) -# define ltr_u(r0,r1,r2) ccr(CC_CC,r0,r1,r2) -# define lti_u(r0,r1,i0) cci(CC_CC,r0,r1,i0) -# define ler(r0,r1,r2) ccr(CC_LE,r0,r1,r2) -# define lei(r0,r1,i0) cci(CC_LE,r0,r1,i0) -# define ler_u(r0,r1,r2) ccr(CC_LS,r0,r1,r2) -# define lei_u(r0,r1,i0) cci(CC_LS,r0,r1,i0) -# define eqr(r0,r1,r2) ccr(CC_EQ,r0,r1,r2) -# define eqi(r0,r1,i0) cci(CC_EQ,r0,r1,i0) -# define ger(r0,r1,r2) ccr(CC_GE,r0,r1,r2) -# define gei(r0,r1,i0) cci(CC_GE,r0,r1,i0) -# define ger_u(r0,r1,r2) ccr(CC_CS,r0,r1,r2) -# define gei_u(r0,r1,i0) cci(CC_CS,r0,r1,i0) -# define gtr(r0,r1,r2) ccr(CC_GT,r0,r1,r2) -# define gti(r0,r1,i0) cci(CC_GT,r0,r1,i0) -# define gtr_u(r0,r1,r2) ccr(CC_HI,r0,r1,r2) -# define gti_u(r0,r1,i0) cci(CC_HI,r0,r1,i0) -# define ner(r0,r1,r2) ccr(CC_NE,r0,r1,r2) -# define nei(r0,r1,i0) cci(CC_NE,r0,r1,i0) -# define bccr(cc,i0,r0,r1) _bccr(_jit,cc,i0,r0,r1) -static jit_word_t -_bccr(jit_state_t*,int32_t,jit_word_t,int32_t,int32_t); -# define bcci(cc,i0,r0,i1) _bcci(_jit,cc,i0,r0,i1) -static jit_word_t -_bcci(jit_state_t*,int32_t,jit_word_t,int32_t,jit_word_t); -# define bltr(i0,r0,r1) bccr(BCC_LT,i0,r0,r1) -# define blti(i0,r0,i1) bcci(BCC_LT,i0,r0,i1) -# define bltr_u(i0,r0,r1) bccr(BCC_CC,i0,r0,r1) -# define blti_u(i0,r0,i1) bcci(BCC_CC,i0,r0,i1) -# define bler(i0,r0,r1) bccr(BCC_LE,i0,r0,r1) -# define blei(i0,r0,i1) bcci(BCC_LE,i0,r0,i1) -# define bler_u(i0,r0,r1) bccr(BCC_LS,i0,r0,r1) -# define blei_u(i0,r0,i1) bcci(BCC_LS,i0,r0,i1) -# define beqr(i0,r0,r1) bccr(BCC_EQ,i0,r0,r1) -# define beqi(i0,r0,i1) _beqi(_jit,i0,r0,i1) -static jit_word_t _beqi(jit_state_t*,jit_word_t,int32_t,jit_word_t); -# define bger(i0,r0,r1) bccr(BCC_GE,i0,r0,r1) -# define bgei(i0,r0,i1) bcci(BCC_GE,i0,r0,i1) -# define bger_u(i0,r0,r1) bccr(BCC_CS,i0,r0,r1) -# define bgei_u(i0,r0,i1) bcci(BCC_CS,i0,r0,i1) -# define bgtr(i0,r0,r1) bccr(BCC_GT,i0,r0,r1) -# define bgti(i0,r0,i1) bcci(BCC_GT,i0,r0,i1) -# define bgtr_u(i0,r0,r1) bccr(BCC_HI,i0,r0,r1) -# define bgti_u(i0,r0,i1) bcci(BCC_HI,i0,r0,i1) -# define bner(i0,r0,r1) bccr(BCC_NE,i0,r0,r1) -# define bnei(i0,r0,i1) _bnei(_jit,i0,r0,i1) -static jit_word_t _bnei(jit_state_t*,jit_word_t,int32_t,jit_word_t); -# define baddr(cc,i0,r0,r1) _baddr(_jit,cc,i0,r0,r1) -static jit_word_t -_baddr(jit_state_t*,int32_t,jit_word_t,int32_t,int32_t); -# define baddi(cc,i0,r0,i1) _baddi(_jit,cc,i0,r0,i1) -static jit_word_t -_baddi(jit_state_t*,int32_t,jit_word_t,int32_t,jit_word_t); -# define boaddr(i0,r0,r1) baddr(BCC_VS,i0,r0,r1) -# define boaddi(i0,r0,i1) baddi(BCC_VS,i0,r0,i1) -# define boaddr_u(i0,r0,r1) baddr(BCC_HS,i0,r0,r1) -# define boaddi_u(i0,r0,i1) baddi(BCC_HS,i0,r0,i1) -# define bxaddr(i0,r0,r1) baddr(BCC_VC,i0,r0,r1) -# define bxaddi(i0,r0,i1) baddi(BCC_VC,i0,r0,i1) -# define bxaddr_u(i0,r0,r1) baddr(BCC_LO,i0,r0,r1) -# define bxaddi_u(i0,r0,i1) baddi(BCC_LO,i0,r0,i1) -# define bsubr(cc,i0,r0,r1) _bsubr(_jit,cc,i0,r0,r1) -static jit_word_t -_bsubr(jit_state_t*,int32_t,jit_word_t,int32_t,int32_t); -# define bsubi(cc,i0,r0,i1) _bsubi(_jit,cc,i0,r0,i1) -static jit_word_t -_bsubi(jit_state_t*,int32_t,jit_word_t,int32_t,jit_word_t); -# define bosubr(i0,r0,r1) bsubr(BCC_VS,i0,r0,r1) -# define bosubi(i0,r0,i1) bsubi(BCC_VS,i0,r0,i1) -# define bosubr_u(i0,r0,r1) bsubr(BCC_LO,i0,r0,r1) -# define bosubi_u(i0,r0,i1) bsubi(BCC_LO,i0,r0,i1) -# define bxsubr(i0,r0,r1) bsubr(BCC_VC,i0,r0,r1) -# define bxsubi(i0,r0,i1) bsubi(BCC_VC,i0,r0,i1) -# define bxsubr_u(i0,r0,r1) bsubr(BCC_HS,i0,r0,r1) -# define bxsubi_u(i0,r0,i1) bsubi(BCC_HS,i0,r0,i1) -# define bmxr(cc,i0,r0,r1) _bmxr(_jit,cc,i0,r0,r1) -static jit_word_t -_bmxr(jit_state_t*,int32_t,jit_word_t,int32_t,int32_t); -# define bmxi(cc,i0,r0,r1) _bmxi(_jit,cc,i0,r0,r1) -static jit_word_t -_bmxi(jit_state_t*,int32_t,jit_word_t,int32_t,jit_word_t); -# define bmsr(i0,r0,r1) bmxr(BCC_NE,i0,r0,r1) -# define bmsi(i0,r0,i1) bmxi(BCC_NE,i0,r0,i1) -# define bmcr(i0,r0,r1) bmxr(BCC_EQ,i0,r0,r1) -# define bmci(i0,r0,i1) bmxi(BCC_EQ,i0,r0,i1) -# define jmpr(r0) BR(r0) -# define jmpi(i0) _jmpi(_jit,i0) -static void _jmpi(jit_state_t*,jit_word_t); -# define jmpi_p(i0) _jmpi_p(_jit,i0) -static jit_word_t _jmpi_p(jit_state_t*,jit_word_t); -# define callr(r0) BLR(r0) -# define calli(i0) _calli(_jit,i0) -static void _calli(jit_state_t*,jit_word_t); -# define calli_p(i0) _calli_p(_jit,i0) -static jit_word_t _calli_p(jit_state_t*,jit_word_t); -# define prolog(i0) _prolog(_jit,i0) -static void _prolog(jit_state_t*,jit_node_t*); -# define epilog(i0) _epilog(_jit,i0) -static void _epilog(jit_state_t*,jit_node_t*); -# define vastart(r0) _vastart(_jit, r0) -static void _vastart(jit_state_t*, int32_t); -# define vaarg(r0, r1) _vaarg(_jit, r0, r1) -static void _vaarg(jit_state_t*, int32_t, int32_t); -# define patch_at(jump,label) _patch_at(_jit,jump,label) -static void _patch_at(jit_state_t*,jit_word_t,jit_word_t); +#if __BYTE_ORDER != __LITTLE_ENDIAN +#error AArch64 requires little-endian host #endif -#if CODE +typedef union { + /* cond2: condition in truly conditional-executed inst. */ + struct { uint32_t b: 4; } cond2; + /* nzcv: flag bit specifier, encoded in the "nzcv" field. */ + struct { uint32_t b: 4; } nzcv; + /* defgh: d:e:f:g:h bits in AdvSIMD modified immediate. */ + struct { uint32_t _: 5; uint32_t b: 5; } defgh; + /* abc: a:b:c bits in AdvSIMD modified immediate. */ + struct { uint32_t _: 16; uint32_t b: 3; } abc; + /* imm19: e.g. in CBZ. */ + struct { uint32_t _: 5; uint32_t b: 19; } imm19; + /* immhi: e.g. in ADRP. */ + struct { uint32_t _: 5; uint32_t b: 19; } immhi; + /* immlo: e.g. in ADRP. */ + struct { uint32_t _: 29; uint32_t b: 2; } immlo; + /* size: in most AdvSIMD and floating-point instructions. */ + struct { uint32_t _: 22; uint32_t b: 2; } size; + /* vldst_size: size field in the AdvSIMD load/store inst. */ + struct { uint32_t _: 10; uint32_t b: 2; } vldst_size; + /* op: in AdvSIMD modified immediate instructions. */ + struct { uint32_t _: 29; uint32_t b: 1; } op; + /* Q: in most AdvSIMD instructions. */ + struct { uint32_t _: 30; uint32_t b: 1; } Q; + /* Rt: in load/store instructions. */ + struct { uint32_t b: 5; } Rt; + /* Rd: in many integer instructions. */ + struct { uint32_t b: 5; } Rd; + /* Rn: in many integer instructions. */ + struct { uint32_t _: 5; uint32_t b: 5; } Rn; + /* Rt2: in load/store pair instructions. */ + struct { uint32_t _: 10; uint32_t b: 5; } Rt2; + /* Ra: in fp instructions. */ + struct { uint32_t _: 10; uint32_t b: 5; } Ra; + /* op2: in the system instructions. */ + struct { uint32_t _: 5; uint32_t b: 3; } op2; + /* CRm: in the system instructions. */ + struct { uint32_t _: 8; uint32_t b: 4; } CRm; + /* CRn: in the system instructions. */ + struct { uint32_t _: 12; uint32_t b: 4; } CRn; + /* op1: in the system instructions. */ + struct { uint32_t _: 16; uint32_t b: 3; } op1; + /* op0: in the system instructions. */ + struct { uint32_t _: 19; uint32_t b: 2; } op0; + /* imm3: in add/sub extended reg instructions. */ + struct { uint32_t _: 10; uint32_t b: 3; } imm3; + /* cond: condition flags as a source operand. */ + struct { uint32_t _: 12; uint32_t b: 4; } cond; + /* opcode: in advsimd load/store instructions. */ + struct { uint32_t _: 12; uint32_t b: 4; } opcode; + /* cmode: in advsimd modified immediate instructions. */ + struct { uint32_t _: 12; uint32_t b: 4; } cmode; + /* asisdlso_opcode: opcode in advsimd ld/st single element. */ + struct { uint32_t _: 13; uint32_t b: 3; } asisdlso_opcode; + /* len: in advsimd tbl/tbx instructions. */ + struct { uint32_t _: 13; uint32_t b: 2; } len; + /* Rm: in ld/st reg offset and some integer inst. */ + struct { uint32_t _: 16; uint32_t b: 5; } Rm; + /* Rs: in load/store exclusive instructions. */ + struct { uint32_t _: 16; uint32_t b: 5; } Rs; + /* option: in ld/st reg offset + add/sub extended reg inst. */ + struct { uint32_t _: 13; uint32_t b: 3; } option; + /* S: in load/store reg offset instructions. */ + struct { uint32_t _: 12; uint32_t b: 1; } S; + /* hw: in move wide constant instructions. */ + struct { uint32_t _: 21; uint32_t b: 2; } hw; + /* opc: in load/store reg offset instructions. */ + struct { uint32_t _: 22; uint32_t b: 2; } opc; + /* opc1: in load/store reg offset instructions. */ + struct { uint32_t _: 23; uint32_t b: 1; } opc1; + /* shift: in add/sub reg/imm shifted instructions. */ + struct { uint32_t _: 22; uint32_t b: 2; } shift; + /* type: floating point type field in fp data inst. */ + struct { uint32_t _: 22; uint32_t b: 2; } type; + /* ldst_size: size field in ld/st reg offset inst. */ + struct { uint32_t _: 30; uint32_t b: 2; } ldst_size; + /* imm6: in add/sub reg shifted instructions. */ + struct { uint32_t _: 10; uint32_t b: 6; } imm6; + /* imm4: in advsimd ext and advsimd ins instructions. */ + struct { uint32_t _: 11; uint32_t b: 4; } imm4; + /* imm5: in conditional compare (immediate) instructions. */ + struct { uint32_t _: 16; uint32_t b: 5; } imm5; + /* imm7: in load/store pair pre/post index instructions. */ + struct { uint32_t _: 15; uint32_t b: 7; } imm7; + /* imm8: in floating-point scalar move immediate inst. */ + struct { uint32_t _: 13; uint32_t b: 8; } imm8; + /* imm9: in load/store pre/post index instructions. */ + struct { uint32_t _: 12; uint32_t b: 9; } imm9; + /* imm12: in ld/st unsigned imm or add/sub shifted inst. */ + struct { uint32_t _: 10; uint32_t b: 12; } imm12; + /* imm14: in test bit and branch instructions. */ + struct { uint32_t _: 5; uint32_t b: 14; } imm14; + /* imm16: in exception instructions. */ + struct { uint32_t _: 5; uint32_t b: 16; } imm16; + /* imm26: in unconditional branch instructions. */ + struct { uint32_t b: 26; } imm26; + /* imms: in bitfield and logical immediate instructions. */ + struct { uint32_t _: 10; uint32_t b: 6; } imms; + /* immr: in bitfield and logical immediate instructions. */ + struct { uint32_t _: 16; uint32_t b: 6; } immr; + /* immb: in advsimd shift by immediate instructions. */ + struct { uint32_t _: 16; uint32_t b: 3; } immb; + /* immh: in advsimd shift by immediate instructions. */ + struct { uint32_t _: 19; uint32_t b: 4; } immh; + /* N: in logical (immediate) instructions. */ + struct { uint32_t _: 22; uint32_t b: 1; } N; + /* index: in ld/st inst deciding the pre/post-index. */ + struct { uint32_t _: 11; uint32_t b: 1; } index; + /* index2: in ld/st pair inst deciding the pre/post-index. */ + struct { uint32_t _: 24; uint32_t b: 1; } index2; + /* sf: in integer data processing instructions. */ + struct { uint32_t _: 31; uint32_t b: 1; } sf; + /* H: in advsimd scalar x indexed element instructions. */ + struct { uint32_t _: 11; uint32_t b: 1; } H; + /* L: in advsimd scalar x indexed element instructions. */ + struct { uint32_t _: 21; uint32_t b: 1; } L; + /* M: in advsimd scalar x indexed element instructions. */ + struct { uint32_t _: 20; uint32_t b: 1; } M; + /* b5: in the test bit and branch instructions. */ + struct { uint32_t _: 31; uint32_t b: 1; } b5; + /* b40: in the test bit and branch instructions. */ + struct { uint32_t _: 19; uint32_t b: 5; } b40; + /* scale: in the fixed-point scalar to fp converting inst. */ + struct { uint32_t _: 10; uint32_t b: 6; } scale; + int32_t w; +} instr_t; + static int32_t logical_immediate(jit_word_t imm) { - /* There are 5334 possible immediate values, but to avoid the - * need of either too complex code or large lookup tables, - * only check for (simply) encodable common/small values */ - switch (imm) { - case -16: return (0xf3b); - case -15: return (0xf3c); - case -13: return (0xf3d); - case -9: return (0xf3e); - case -8: return (0xf7c); - case -7: return (0xf7d); - case -5: return (0xf7e); - case -4: return (0xfbd); - case -3: return (0xfbe); - case -2: return (0xffe); - case 1: return (0x000); - case 2: return (0xfc0); - case 3: return (0x001); - case 4: return (0xf80); - case 6: return (0xfc1); - case 7: return (0x002); - case 8: return (0xf40); - case 12: return (0xf81); - case 14: return (0xfc2); - case 15: return (0x003); - case 16: return (0xf00); - default: return (-1); + /* There are 5334 possible immediate values, but to avoid the + * need of either too complex code or large lookup tables, + * only check for (simply) encodable common/small values */ + switch (imm) { + case -16: return 0xf3b; + case -15: return 0xf3c; + case -13: return 0xf3d; + case -9: return 0xf3e; + case -8: return 0xf7c; + case -7: return 0xf7d; + case -5: return 0xf7e; + case -4: return 0xfbd; + case -3: return 0xfbe; + case -2: return 0xffe; + case 1: return 0x000; + case 2: return 0xfc0; + case 3: return 0x001; + case 4: return 0xf80; + case 6: return 0xfc1; + case 7: return 0x002; + case 8: return 0xf40; + case 12: return 0xf81; + case 14: return 0xfc2; + case 15: return 0x003; + case 16: return 0xf00; + default: return -1; + } +} + +static void +oxxx(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Rn, int32_t Rm) +{ + instr_t i; + ASSERT(!(Rd & ~0x1f)); + ASSERT(!(Rn & ~0x1f)); + ASSERT(!(Rm & ~0x1f)); + ASSERT(!(Op & ~0xffe0fc00)); + i.w = Op; + i.Rd.b = Rd; + i.Rn.b = Rn; + i.Rm.b = Rm; + emit_u32(_jit, i.w); +} + +static void +oxxi(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Rn, int32_t Imm12) +{ + instr_t i; + ASSERT(!(Rd & ~0x1f)); + ASSERT(!(Rn & ~0x1f)); + ASSERT(!(Imm12 & ~0xfff)); + ASSERT(!(Op & ~0xffe00000)); + i.w = Op; + i.Rd.b = Rd; + i.Rn.b = Rn; + i.imm12.b = Imm12; + emit_u32(_jit, i.w); +} + +static void +oxx9(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Rn, int32_t Imm9) +{ + instr_t i; + ASSERT(!(Rd & ~0x1f)); + ASSERT(!(Rn & ~0x1f)); + ASSERT(!(Imm9 & ~0x1ff)); + ASSERT(!(Op & ~0xffe00000)); + i.w = Op; + i.Rd.b = Rd; + i.Rn.b = Rn; + i.imm9.b = Imm9; + emit_u32(_jit, i.w); +} + +static uint32_t +encode_ox19(jit_state_t *_jit, int32_t Op, int32_t Rd) +{ + instr_t i; + ASSERT(!(Rd & ~0x1f)); + ASSERT(!(Op & ~0xff000000)); + i.w = Op; + i.Rd.b = Rd; + return i.w; +} + +static uint32_t +encode_oc19(jit_state_t *_jit, int32_t Op, int32_t Cc) +{ + instr_t i; + ASSERT(!(Cc & ~0xf)); + ASSERT(!(Op & ~0xff000000)); + i.w = Op; + i.cond2.b = Cc; + return i.w; +} + +static uint32_t +encode_o26(jit_state_t *_jit, int32_t Op) +{ + instr_t i; + ASSERT(!(Op & ~0xfc000000)); + i.w = Op; + return i.w; +} + +static void +ox_x(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Rm) +{ + instr_t i; + ASSERT(!(Rd & ~0x1f)); + ASSERT(!(Rm & ~0x1f)); + ASSERT(!(Op & ~0xffe0ffe0)); + i.w = Op; + i.Rd.b = Rd; + i.Rm.b = Rm; + emit_u32(_jit, i.w); +} + +static void +o_xx(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Rn) +{ + instr_t i; + ASSERT(!(Rd & ~0x1f)); + ASSERT(!(Rn & ~0x1f)); + ASSERT(!(Op & ~0xfffffc00)); + i.w = Op; + i.Rd.b = Rd; + i.Rn.b = Rn; + emit_u32(_jit, i.w); +} + +static void +oxx_(jit_state_t *_jit, int32_t Op, int32_t Rn, int32_t Rm) +{ + instr_t i; + ASSERT(!(Rn & ~0x1f)); + ASSERT(!(Rm & ~0x1f)); + ASSERT(!(Op & ~0xffc0fc1f)); + i.w = Op; + i.Rn.b = Rn; + i.Rm.b = Rm; + emit_u32(_jit, i.w); +} + +static void +o_x_(jit_state_t *_jit, int32_t Op, int32_t Rn) +{ + instr_t i; + ASSERT(!(Rn & ~0x1f)); + ASSERT(!(Op & 0x3e0)); + i.w = Op; + i.Rn.b = Rn; + emit_u32(_jit, i.w); +} + +static void +ox_h(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Imm16) +{ + instr_t i; + ASSERT(!(Rd & ~0x1f)); + ASSERT(!(Imm16 & ~0xffff)); + ASSERT(!(Op & ~0xffe00000)); + i.w = Op; + i.Rd.b = Rd; + i.imm16.b = Imm16; + emit_u32(_jit, i.w); +} + +static void +oxxrs(jit_state_t *_jit, int32_t Op, + int32_t Rd, int32_t Rn, int32_t R, int32_t S) +{ + instr_t i; + ASSERT(!(Rd & ~0x1f)); + ASSERT(!(Rn & ~0x1f)); + ASSERT(!(R & ~0x3f)); + ASSERT(!(S & ~0x3f)); + ASSERT(!(Op & ~0xffc00000)); + i.w = Op; + i.Rd.b = Rd; + i.Rn.b = Rn; + i.immr.b = R; + i.imms.b = S; + emit_u32(_jit, i.w); +} + +static void +oxxxc(jit_state_t *_jit, int32_t Op, + int32_t Rd, int32_t Rn, int32_t Rm, int32_t Cc) +{ + instr_t i; + ASSERT(!(Rd & ~0x1f)); + ASSERT(!(Rn & ~0x1f)); + ASSERT(!(Rm & ~0x1f)); + ASSERT(!(Cc & ~0xf)); + ASSERT(!(Op & ~0xffc00c00)); + i.w = Op; + i.Rd.b = Rd; + i.Rn.b = Rn; + i.Rm.b = Rm; + i.cond.b = Cc; + emit_u32(_jit, i.w); +} + +static void +oxxx7(jit_state_t *_jit, int32_t Op, + int32_t Rt, int32_t Rt2, int32_t Rn, int32_t Simm7) +{ + instr_t i; + ASSERT(!(Rt & ~0x1f)); + ASSERT(!(Rt2 & ~0x1f)); + ASSERT(!(Rn & ~0x1f)); + ASSERT(Simm7 >= -128 && Simm7 <= 127); + ASSERT(!(Op & ~0xffc003e0)); + i.w = Op; + i.Rt.b = Rt; + i.Rt2.b = Rt2; + i.Rn.b = Rn; + i.imm7.b = Simm7; + emit_u32(_jit, i.w); +} + +#define stack_framesize 160 +#define FP_REGNO 0x1d +#define LR_REGNO 0x1e +#define SP_REGNO 0x1f +#define XZR_REGNO 0x1f +#define WZR_REGNO XZR_REGNO +#define LSL_12 0x00400000 +#define MOVI_LSL_16 0x00200000 +#define MOVI_LSL_32 0x00400000 +#define MOVI_LSL_48 0x00600000 +#define XS 0x80000000 /* Wn -> Xn */ +#define DS 0x00400000 /* Sn -> Dn */ +#define CC_NE 0x0 +#define CC_EQ 0x1 +#define CC_CC 0x2 +#define CC_LO CC_CC +#define CC_CS 0x3 +#define CC_HS CC_CS +#define CC_PL 0x4 +#define CC_MI 0x5 +#define CC_VC 0x6 +#define CC_VS 0x7 +#define CC_LS 0x8 +#define CC_HI 0x9 +#define CC_LT 0xa +#define CC_GE 0xb +#define CC_LE 0xc +#define CC_GT 0xd +#define CC_NV 0xe +#define CC_AL 0xf +/* Branches need inverted condition */ +#define BCC_EQ 0x0 +#define BCC_NE 0x1 +#define BCC_CS 0x2 +#define BCC_HS BCC_CS +#define BCC_CC 0x3 +#define BCC_LO BCC_CC +#define BCC_MI 0x4 +#define BCC_PL 0x5 +#define BCC_VS 0x6 +#define BCC_VC 0x7 +#define BCC_HI 0x8 +#define BCC_LS 0x9 +#define BCC_GE 0xa +#define BCC_LT 0xb +#define BCC_GT 0xc +#define BCC_LE 0xd +#define BCC_AL 0xe +#define BCC_NV 0xf +/* adapted and cut down to only tested and required by lightning, + * from data in binutils/aarch64-tbl.h */ +#define A64_ADCS 0x3a000000 +#define A64_SBCS 0x7a000000 +#define A64_ADDI 0x11000000 +#define A64_ADDSI 0xb1000000 +#define A64_SUBI 0x51000000 +#define A64_SUBSI 0x71000000 +#define A64_ADD 0x0b000000 +#define A64_ADDS 0x2b000000 +#define A64_SUB 0x4b000000 +#define A64_NEG 0x4b0003e0 +#define A64_SUBS 0x6b000000 +#define A64_CMP 0x6b00001f +#define A64_SBFM 0x93400000 +#define A64_UBFM 0x53400000 +#define A64_UBFX 0x53000000 +#define A64_B 0x14000000 +#define A64_BL 0x94000000 +#define A64_BR 0xd61f0000 +#define A64_BLR 0xd63f0000 +#define A64_RET 0xd65f0000 +#define A64_CBZ 0x34000000 +#define A64_CBNZ 0x35000000 +#define A64_B_C 0x54000000 +#define A64_CSINC 0x1a800400 +#define A64_REV 0xdac00c00 +#define A64_UDIV 0x1ac00800 +#define A64_SDIV 0x1ac00c00 +#define A64_LSL 0x1ac02000 +#define A64_LSR 0x1ac02400 +#define A64_ASR 0x1ac02800 +#define A64_MUL 0x1b007c00 +#define A64_SMULL 0x9b207c00 +#define A64_SMULH 0x9b407c00 +#define A64_UMULL 0x9ba07c00 +#define A64_UMULH 0x9bc07c00 +#define A64_STRBI 0x39000000 +#define A64_LDRBI 0x39400000 +#define A64_LDRSBI 0x39800000 +#define A64_STRI 0xf9000000 +#define A64_LDRI 0xf9400000 +#define A64_LDRI_LITERAL 0x58000000 +#define A64_STRHI 0x79000000 +#define A64_LDRHI 0x79400000 +#define A64_LDRSHI 0x79800000 +#define A64_STRWI 0xb9000000 +#define A64_LDRWI 0xb9400000 +#define A64_LDRSWI 0xb9800000 +#define A64_STRB 0x38206800 +#define A64_LDRB 0x38606800 +#define A64_LDRSB 0x38e06800 +#define A64_STR 0xf8206800 +#define A64_LDR 0xf8606800 +#define A64_STRH 0x78206800 +#define A64_LDRH 0x78606800 +#define A64_LDRSH 0x78a06800 +#define A64_STRW 0xb8206800 +#define A64_LDRW 0xb8606800 +#define A64_LDRSW 0xb8a06800 +#define A64_STURB 0x38000000 +#define A64_LDURB 0x38400000 +#define A64_LDURSB 0x38800000 +#define A64_STUR 0xf8000000 +#define A64_LDUR 0xf8400000 +#define A64_STURH 0x78000000 +#define A64_LDURH 0x78400000 +#define A64_LDURSH 0x78800000 +#define A64_STURW 0xb8000000 +#define A64_LDURW 0xb8400000 +#define A64_LDURSW 0xb8800000 +#define A64_STP 0x29000000 +#define A64_LDP 0x29400000 +#define A64_STP_POS 0x29800000 +#define A64_LDP_PRE 0x28c00000 +#define A64_ANDI 0x12400000 +#define A64_ORRI 0x32400000 +#define A64_EORI 0x52400000 +#define A64_ANDSI 0x72000000 +#define A64_AND 0x0a000000 +#define A64_ORR 0x2a000000 +#define A64_MOV 0x2a0003e0 /* AKA orr Rd,xzr,Rm */ +#define A64_MVN 0x2a2003e0 +#define A64_UXTW 0x2a0003e0 /* AKA MOV */ +#define A64_EOR 0x4a000000 +#define A64_ANDS 0x6a000000 +#define A64_MOVN 0x12800000 +#define A64_MOVZ 0x52800000 +#define A64_MOVK 0x72800000 + +static void +SBFM(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t ImmR, int32_t ImmS) +{ + return oxxrs(_jit, A64_SBFM|XS,Rd,Rn,ImmR,ImmS); +} + +static void +UBFM(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t ImmR, int32_t ImmS) +{ + return oxxrs(_jit, A64_UBFM|XS,Rd,Rn,ImmR,ImmS); +} + +static void +UBFX(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t ImmR, int32_t ImmS) +{ + return oxxrs(_jit, A64_UBFX,Rd,Rn,ImmR,ImmS); +} + +static void +CMP(jit_state_t *_jit, int32_t Rn, int32_t Rm) +{ + return oxx_(_jit, A64_CMP|XS,Rn,Rm); +} + +static void +CMPI(jit_state_t *_jit, int32_t Rn, int32_t Imm12) +{ + return oxxi(_jit, A64_SUBSI|XS,XZR_REGNO,Rn,Imm12); +} + +static void +CMPI_12(jit_state_t *_jit, int32_t Rn, int32_t Imm12) +{ + return oxxi(_jit, A64_SUBSI|XS|LSL_12,XZR_REGNO,Rn,Imm12); +} + +static void +CMNI(jit_state_t *_jit, int32_t Rn, int32_t Imm12) +{ + return oxxi(_jit, A64_ADDSI|XS,XZR_REGNO,Rn,Imm12); +} + +static void +CMNI_12(jit_state_t *_jit, int32_t Rn, int32_t Imm12) +{ + return oxxi(_jit, A64_ADDSI|XS|LSL_12,XZR_REGNO,Rn,Imm12); +} + +static void +CSINC(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm, int32_t Cc) +{ + return oxxxc(_jit, A64_CSINC|XS,Rd,Rn,Rm,Cc); +} + +static void +TST(jit_state_t *_jit, int32_t Rn, int32_t Rm) +{ + return oxxx(_jit, A64_ANDS|XS,XZR_REGNO,Rn,Rm); +} + +/* actually should use oxxrs but logical_immediate returns proper encoding */ +static void +TSTI(jit_state_t *_jit, int32_t Rn, int32_t Imm12) +{ + return oxxi(_jit, A64_ANDSI,XZR_REGNO,Rn,Imm12); +} + +static void +MOV(jit_state_t *_jit, int32_t Rd, int32_t Rm) +{ + return ox_x(_jit, A64_MOV|XS,Rd,Rm); +} + +static void +MVN(jit_state_t *_jit, int32_t Rd, int32_t Rm) +{ + return ox_x(_jit, A64_MVN|XS,Rd,Rm); +} + +static void +NEG(jit_state_t *_jit, int32_t Rd, int32_t Rm) +{ + return ox_x(_jit, A64_NEG|XS,Rd,Rm); +} + +static void +MOVN(jit_state_t *_jit, int32_t Rd, int32_t Imm16) +{ + return ox_h(_jit, A64_MOVN|XS,Rd,Imm16); +} + +static void +MOVN_16(jit_state_t *_jit, int32_t Rd, int32_t Imm16) +{ + return ox_h(_jit, A64_MOVN|XS|MOVI_LSL_16,Rd,Imm16); +} + +static void +MOVN_32(jit_state_t *_jit, int32_t Rd, int32_t Imm16) +{ + return ox_h(_jit, A64_MOVN|XS|MOVI_LSL_32,Rd,Imm16); +} + +static void +MOVN_48(jit_state_t *_jit, int32_t Rd, int32_t Imm16) +{ + return ox_h(_jit, A64_MOVN|XS|MOVI_LSL_48,Rd,Imm16); +} + +static void +MOVZ(jit_state_t *_jit, int32_t Rd, int32_t Imm16) +{ + return ox_h(_jit, A64_MOVZ|XS,Rd,Imm16); +} + +static void +MOVZ_16(jit_state_t *_jit, int32_t Rd, int32_t Imm16) +{ + return ox_h(_jit, A64_MOVZ|XS|MOVI_LSL_16,Rd,Imm16); +} + +static void +MOVZ_32(jit_state_t *_jit, int32_t Rd, int32_t Imm16) +{ + return ox_h(_jit, A64_MOVZ|XS|MOVI_LSL_32,Rd,Imm16); +} + +static void +MOVZ_48(jit_state_t *_jit, int32_t Rd, int32_t Imm16) +{ + return ox_h(_jit, A64_MOVZ|XS|MOVI_LSL_48,Rd,Imm16); +} + +static void +MOVK(jit_state_t *_jit, int32_t Rd, int32_t Imm16) +{ + return ox_h(_jit, A64_MOVK|XS,Rd,Imm16); +} + +static void +MOVK_16(jit_state_t *_jit, int32_t Rd, int32_t Imm16) +{ + return ox_h(_jit, A64_MOVK|XS|MOVI_LSL_16,Rd,Imm16); +} + +static void +MOVK_32(jit_state_t *_jit, int32_t Rd, int32_t Imm16) +{ + return ox_h(_jit, A64_MOVK|XS|MOVI_LSL_32,Rd,Imm16); +} + +static void +MOVK_48(jit_state_t *_jit, int32_t Rd, int32_t Imm16) +{ + return ox_h(_jit, A64_MOVK|XS|MOVI_LSL_48,Rd,Imm16); +} + +static void +ADD(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) +{ + return oxxx(_jit, A64_ADD|XS,Rd,Rn,Rm); +} + +static void +ADDI(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Imm12) +{ + return oxxi(_jit, A64_ADDI|XS,Rd,Rn,Imm12); +} + +static void +ADDI_12(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Imm12) +{ + return oxxi(_jit, A64_ADDI|XS|LSL_12,Rd,Rn,Imm12); +} + +static void +MOV_XSP(jit_state_t *_jit, int32_t Rd, int32_t Rn) +{ + return ADDI(_jit, Rd,Rn,0); +} + +static void +ADDS(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) +{ + return oxxx(_jit, A64_ADDS|XS,Rd,Rn,Rm); +} + +static void +ADDSI(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Imm12) +{ + return oxxi(_jit, A64_ADDSI|XS,Rd,Rn,Imm12); +} + +static void +ADDSI_12(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Imm12) +{ + return oxxi(_jit, A64_ADDSI|XS|LSL_12,Rd,Rn,Imm12); +} + +static void +ADCS(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) +{ + return oxxx(_jit, A64_ADCS|XS,Rd,Rn,Rm); +} + +static void +SUB(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) +{ + return oxxx(_jit, A64_SUB|XS,Rd,Rn,Rm); +} + +static void +SUBI(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Imm12) +{ + return oxxi(_jit, A64_SUBI|XS,Rd,Rn,Imm12); +} + +static void +SUBI_12(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Imm12) +{ + return oxxi(_jit, A64_SUBI|XS|LSL_12,Rd,Rn,Imm12); +} + +static void +SUBS(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) +{ + return oxxx(_jit, A64_SUBS|XS,Rd,Rn,Rm); +} + +static void +SUBSI(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Imm12) +{ + return oxxi(_jit, A64_SUBSI|XS,Rd,Rn,Imm12); +} + +static void +SUBSI_12(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Imm12) +{ + return oxxi(_jit, A64_SUBSI|XS|LSL_12,Rd,Rn,Imm12); +} + +static void +SBCS(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) +{ + return oxxx(_jit, A64_SBCS|XS,Rd,Rn,Rm); +} + +static void +MUL(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) +{ + return oxxx(_jit, A64_MUL|XS,Rd,Rn,Rm); +} + +static void +SMULL(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) +{ + return oxxx(_jit, A64_SMULL,Rd,Rn,Rm); +} + +static void +SMULH(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) +{ + return oxxx(_jit, A64_SMULH,Rd,Rn,Rm); +} + +static void +UMULL(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) +{ + return oxxx(_jit, A64_UMULL,Rd,Rn,Rm); +} + +static void +UMULH(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) +{ + return oxxx(_jit, A64_UMULH,Rd,Rn,Rm); +} + +static void +SDIV(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) +{ + return oxxx(_jit, A64_SDIV|XS,Rd,Rn,Rm); +} + +static void +UDIV(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) +{ + return oxxx(_jit, A64_UDIV|XS,Rd,Rn,Rm); +} + +static void +LSL(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) +{ + return oxxx(_jit, A64_LSL|XS,Rd,Rn,Rm); +} + +static void +LSLI(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) +{ + return UBFM(_jit, r0,r1,(64-i0)&63,63-i0); +} + +static void +ASR(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) +{ + return oxxx(_jit, A64_ASR|XS,Rd,Rn,Rm); +} + +static void +ASRI(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) +{ + return SBFM(_jit, r0,r1,i0,63); +} + +static void +LSR(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) +{ + return oxxx(_jit, A64_LSR|XS,Rd,Rn,Rm); +} + +static void +LSRI(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) +{ + return UBFM(_jit, r0,r1,i0,63); +} + +static void +AND(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) +{ + return oxxx(_jit, A64_AND|XS,Rd,Rn,Rm); +} + +/* actually should use oxxrs but logical_immediate returns proper encoding */; +static void +ANDI(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Imm12) +{ + return oxxi(_jit, A64_ANDI|XS,Rd,Rn,Imm12); +} + +static void +ORR(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) +{ + return oxxx(_jit, A64_ORR|XS,Rd,Rn,Rm); +} + +/* actually should use oxxrs but logical_immediate returns proper encoding */ +static void +ORRI(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Imm12) +{ + return oxxi(_jit, A64_ORRI|XS,Rd,Rn,Imm12); +} + +static void +EOR(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) +{ + return oxxx(_jit, A64_EOR|XS,Rd,Rn,Rm); +} + +/* actually should use oxxrs but logical_immediate returns proper encoding */ +static void +EORI(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Imm12) +{ + return oxxi(_jit, A64_EORI|XS,Rd,Rn,Imm12); +} + +static void +SXTB(jit_state_t *_jit, int32_t Rd, int32_t Rn) +{ + return SBFM(_jit, Rd,Rn,0,7); +} + +static void +SXTH(jit_state_t *_jit, int32_t Rd, int32_t Rn) +{ + return SBFM(_jit, Rd,Rn,0,15); +} + +static void +SXTW(jit_state_t *_jit, int32_t Rd, int32_t Rn) +{ + return SBFM(_jit, Rd,Rn,0,31); +} + +static void +UXTB(jit_state_t *_jit, int32_t Rd, int32_t Rn) +{ + return UBFX(_jit, Rd,Rn,0,7); +} + +static void +UXTH(jit_state_t *_jit, int32_t Rd, int32_t Rn) +{ + return UBFX(_jit, Rd,Rn,0,15); +} + +static void +UXTW(jit_state_t *_jit, int32_t Rd, int32_t Rm) +{ + return ox_x(_jit, A64_UXTW,Rd,Rm); +} + +static void +REV(jit_state_t *_jit, int32_t Rd, int32_t Rn) +{ + return o_xx(_jit, A64_REV,Rd,Rn); +} + +static void +LDRSB(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Rm) +{ + return oxxx(_jit, A64_LDRSB,Rt,Rn,Rm); +} + +static void +LDRSBI(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm12) +{ + return oxxi(_jit, A64_LDRSBI,Rt,Rn,Imm12); +} + +static void +LDURSB(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm9) +{ + return oxx9(_jit, A64_LDURSB,Rt,Rn,Imm9); +} + +static void +LDRB(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Rm) +{ + return oxxx(_jit, A64_LDRB,Rt,Rn,Rm); +} + +static void +LDRBI(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm12) +{ + return oxxi(_jit, A64_LDRBI,Rt,Rn,Imm12); +} + +static void +LDURB(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm9) +{ + return oxx9(_jit, A64_LDURB,Rt,Rn,Imm9); +} + +static void +LDRSH(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Rm) +{ + return oxxx(_jit, A64_LDRSH,Rt,Rn,Rm); +} + +static void +LDRSHI(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm12) +{ + return oxxi(_jit, A64_LDRSHI,Rt,Rn,Imm12); +} + +static void +LDURSH(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm9) +{ + return oxx9(_jit, A64_LDURSH,Rt,Rn,Imm9); +} + +static void +LDRH(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Rm) +{ + return oxxx(_jit, A64_LDRH,Rt,Rn,Rm); +} + +static void +LDRHI(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm12) +{ + return oxxi(_jit, A64_LDRHI,Rt,Rn,Imm12); +} + +static void +LDURH(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm9) +{ + return oxx9(_jit, A64_LDURH,Rt,Rn,Imm9); +} + +static void +LDRSW(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Rm) +{ + return oxxx(_jit, A64_LDRSW,Rt,Rn,Rm); +} + +static void +LDRSWI(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm12) +{ + return oxxi(_jit, A64_LDRSWI,Rt,Rn,Imm12); +} + +static void +LDURSW(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm9) +{ + return oxx9(_jit, A64_LDURSW,Rt,Rn,Imm9); +} + +static void +LDRW(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Rm) +{ + return oxxx(_jit, A64_LDRW,Rt,Rn,Rm); +} + +static void +LDRWI(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm12) +{ + return oxxi(_jit, A64_LDRWI,Rt,Rn,Imm12); +} + +static void +LDURW(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm9) +{ + return oxx9(_jit, A64_LDURW,Rt,Rn,Imm9); +} + +static void +LDR(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Rm) +{ + return oxxx(_jit, A64_LDR,Rt,Rn,Rm); +} + +static void +LDRI(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm12) +{ + return oxxi(_jit, A64_LDRI,Rt,Rn,Imm12); +} + +static void +LDUR(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm9) +{ + return oxx9(_jit, A64_LDUR,Rt,Rn,Imm9); +} + +static void +STRB(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Rm) +{ + return oxxx(_jit, A64_STRB,Rt,Rn,Rm); +} + +static void +STRBI(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm12) +{ + return oxxi(_jit, A64_STRBI,Rt,Rn,Imm12); +} + +static void +STURB(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm9) +{ + return oxx9(_jit, A64_STURB,Rt,Rn,Imm9); +} + +static void +STRH(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Rm) +{ + return oxxx(_jit, A64_STRH,Rt,Rn,Rm); +} + +static void +STRHI(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm12) +{ + return oxxi(_jit, A64_STRHI,Rt,Rn,Imm12); +} + +static void +STURH(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm9) +{ + return oxx9(_jit, A64_STURH,Rt,Rn,Imm9); +} + +static void +STRW(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Rm) +{ + return oxxx(_jit, A64_STRW,Rt,Rn,Rm); +} + +static void +STRWI(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm12) +{ + return oxxi(_jit, A64_STRWI,Rt,Rn,Imm12); +} + +static void +STURW(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm9) +{ + return oxx9(_jit, A64_STURW,Rt,Rn,Imm9); +} + +static void +STR(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Rm) +{ + return oxxx(_jit, A64_STR,Rt,Rn,Rm); +} + +static void +STRI(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm12) +{ + return oxxi(_jit, A64_STRI,Rt,Rn,Imm12); +} + +static void +STUR(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm9) +{ + return oxx9(_jit, A64_STUR,Rt,Rn,Imm9); +} + +static void +LDPI(jit_state_t *_jit, int32_t Rt, int32_t Rt2, int32_t Rn, int32_t Simm7) +{ + return oxxx7(_jit, A64_LDP|XS,Rt,Rt2,Rn,Simm7); +} + +static void +STPI(jit_state_t *_jit, int32_t Rt, int32_t Rt2, int32_t Rn, int32_t Simm7) +{ + return oxxx7(_jit, A64_STP|XS,Rt,Rt2,Rn,Simm7); +} + +static void +LDPI_PRE(jit_state_t *_jit, int32_t Rt, int32_t Rt2, int32_t Rn, int32_t Simm7) +{ + return oxxx7(_jit, A64_LDP_PRE|XS,Rt,Rt2,Rn,Simm7); +} + +static void +STPI_POS(jit_state_t *_jit, int32_t Rt, int32_t Rt2, int32_t Rn, int32_t Simm7) +{ + return oxxx7(_jit, A64_STP_POS|XS,Rt,Rt2,Rn,Simm7); +} + +static void +CSET(jit_state_t *_jit, int32_t Rd, int32_t Cc) +{ + return CSINC(_jit, Rd,XZR_REGNO,XZR_REGNO,Cc); +} + +static jit_reloc_t +B(jit_state_t *_jit) +{ + return emit_jmp(_jit, encode_o26(_jit, A64_B)); +} + +static jit_reloc_t +BL(jit_state_t *_jit) +{ + return emit_jmp(_jit, encode_o26(_jit, A64_BL)); +} + +static void +BR(jit_state_t *_jit, int32_t Rn) +{ + return o_x_(_jit, A64_BR,Rn); +} + +static void +BLR(jit_state_t *_jit, int32_t Rn) +{ + return o_x_(_jit, A64_BLR,Rn); +} + +static void +RET(jit_state_t *_jit) +{ + return o_x_(_jit, A64_RET,LR_REGNO); +} + +static jit_reloc_t +B_C(jit_state_t *_jit, int32_t Cc) +{ + return emit_jcc(_jit, encode_oc19(_jit, A64_B_C, Cc)); +} + +static jit_reloc_t +CBZ(jit_state_t *_jit, int32_t Rd) +{ + return emit_jcc(_jit, encode_ox19(_jit, A64_CBZ|XS,Rd)); +} + +static jit_reloc_t +CBNZ(jit_state_t *_jit, int32_t Rd) +{ + return emit_jcc(_jit, encode_ox19(_jit, A64_CBNZ|XS,Rd)); +} + +static void +NOP(jit_state_t *_jit) +{ + return emit_u32(_jit, 0xd503201f); +} + +static jit_reloc_t +movi_from_pool(jit_state_t *_jit, int32_t Rt) +{ + return emit_load_from_pool(_jit, encode_ox19(_jit, A64_LDRI_LITERAL, Rt)); +} + +static void +movr(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + if (r0 != r1) + MOV(_jit, r0, r1); +} + +static void +addr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + return ADD(_jit,r0,r1,r2); +} + +static void +addcr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + return ADDS(_jit,r0,r1,r2); +} + +static void +addxr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + return ADCS(_jit,r0,r1,r2); +} + +static void +subr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + return SUB(_jit,r0,r1,r2); +} + +static void +subcr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + return SUBS(_jit,r0,r1,r2); +} + +static void +subxr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + return SBCS(_jit,r0,r1,r2); +} + +static void +mulr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + return MUL(_jit,r0,r1,r2); +} + +static void +divr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + return SDIV(_jit,r0,r1,r2); +} + +static void +divr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + return UDIV(_jit,r0,r1,r2); +} + +static void +iqdivr(jit_state_t *_jit, jit_bool_t sign, + int32_t r0, int32_t r1, int32_t r2, int32_t r3) +{ + int32_t rg0, rg1; + if (r0 == r2 || r0 == r3) { + rg0 = jit_gpr_regno(get_temp_gpr(_jit)); + } else { + rg0 = r0; + } + if (r1 == r2 || r1 == r3) { + rg1 = jit_gpr_regno(get_temp_gpr(_jit)); + } else { + rg1 = r1; + } + if (sign) + divr(_jit, rg0, r2, r3); + else + divr_u(_jit, rg0, r2, r3); + mulr(_jit, rg1, r3, rg0); + subr(_jit, rg1, r2, rg1); + if (rg0 != r0) { + movr(_jit, r0, rg0); + unget_temp_gpr(_jit); + } + if (rg1 != r1) { + movr(_jit, r1, rg1); + unget_temp_gpr(_jit); + } +} + +static void +qdivr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, int32_t r3) +{ + return iqdivr(_jit,1,r0,r1,r2,r3); +} + +static void +qdivr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, int32_t r3) +{ + return iqdivr(_jit,0,r0,r1,r2,r3); +} + +static void +lshr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + return LSL(_jit,r0,r1,r2); +} + +static void +rshr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + return ASR(_jit,r0,r1,r2); +} + +static void +rshr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + return LSR(_jit,r0,r1,r2); +} + +static void +negr(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return NEG(_jit,r0,r1); +} + +static void +comr(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return MVN(_jit,r0,r1); +} + +static void +andr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + return AND(_jit,r0,r1,r2); +} + +static void +orr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + return ORR(_jit,r0,r1,r2); +} + +static void +xorr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + return EOR(_jit,r0,r1,r2); +} + +static void +ldr_c(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return LDRSBI(_jit,r0,r1,0); +} + +static void +ldr_s(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return LDRSHI(_jit,r0,r1,0); +} + +static void +ldr_i(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return LDRSWI(_jit,r0,r1,0); +} + +static void +ldxr_s(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + return LDRSH(_jit,r0,r1,r2); +} + +static void +ldxr_i(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + return LDRSW(_jit,r0,r1,r2); +} + +static void +ldxr_l(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + return LDR(_jit,r0,r1,r2); +} + +static void +str_c(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return STRBI(_jit,r1,r0,0); +} + +static void +str_s(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return STRHI(_jit,r1,r0,0); +} + +static void +str_i(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return STRWI(_jit,r1,r0,0); +} + +static void +str_l(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return STRI(_jit,r1,r0,0); +} + +static void +stxr_c(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + return STRB(_jit,r2,r1,r0); +} + +static void +stxr_s(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + return STRH(_jit,r2,r1,r0); +} + +static void +stxr_i(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + return STRW(_jit,r2,r1,r0); +} + +static void +stxr_l(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + return STR(_jit,r2,r1,r0); +} + +static void +bswapr_ul(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return REV(_jit,r0,r1); +} + +static void +extr_c(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return SXTB(_jit,r0,r1); +} + +static void +extr_uc(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return UXTB(_jit,r0,r1); +} + +static void +extr_s(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return SXTH(_jit,r0,r1); +} + +static void +extr_us(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return UXTH(_jit,r0,r1); +} + +static void +extr_i(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return SXTW(_jit,r0,r1); +} + +static void +extr_ui(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return UXTW(_jit,r0,r1); +} + +static void +movi(jit_state_t *_jit, int32_t r0, jit_word_t i0) +{ + jit_word_t n0 = ~i0, ibit = 0, nbit = 0; + if (i0 & 0x000000000000ffffL) ibit |= 1; + if (i0 & 0x00000000ffff0000L) ibit |= 2; + if (i0 & 0x0000ffff00000000L) ibit |= 4; + if (i0 & 0xffff000000000000L) ibit |= 8; + if (n0 & 0x000000000000ffffL) nbit |= 1; + if (n0 & 0x00000000ffff0000L) nbit |= 2; + if (n0 & 0x0000ffff00000000L) nbit |= 4; + if (n0 & 0xffff000000000000L) nbit |= 8; + switch (ibit) { + case 0: + MOVZ (_jit, r0, 0); + break; + case 1: + MOVZ (_jit, r0, i0 & 0xffff); + break; + case 2: + MOVZ_16(_jit, r0, (i0 >> 16) & 0xffff); + break; + case 3: + MOVZ (_jit, r0, i0 & 0xffff); + MOVK_16(_jit, r0, (i0 >> 16) & 0xffff); + break; + case 4: + MOVZ_32(_jit, r0, (i0 >> 32) & 0xffff); + break; + case 5: + MOVZ (_jit, r0, i0 & 0xffff); + MOVK_32(_jit, r0, (i0 >> 32) & 0xffff); + break; + case 6: + MOVZ_16(_jit, r0, (i0 >> 16) & 0xffff); + MOVK_32(_jit, r0, (i0 >> 32) & 0xffff); + break; + case 7: + if (nbit == 8) { + MOVN_48(_jit, r0, (n0 >> 48) & 0xffff); + } else { + MOVZ (_jit, r0, i0 & 0xffff); + MOVK_16(_jit, r0, (i0 >> 16) & 0xffff); + MOVK_32(_jit, r0, (i0 >> 32) & 0xffff); } -} - -static void -_oxxx(jit_state_t *_jit, int32_t Op, - int32_t Rd, int32_t Rn, int32_t Rm) -{ - instr_t i; - assert(!(Rd & ~0x1f)); - assert(!(Rn & ~0x1f)); - assert(!(Rm & ~0x1f)); - assert(!(Op & ~0xffe0fc00)); - i.w = Op; - i.Rd.b = Rd; - i.Rn.b = Rn; - i.Rm.b = Rm; - ii(i.w); -} - -static void -_oxxi(jit_state_t *_jit, int32_t Op, - int32_t Rd, int32_t Rn, int32_t Imm12) -{ - instr_t i; - assert(!(Rd & ~0x1f)); - assert(!(Rn & ~0x1f)); - assert(!(Imm12 & ~0xfff)); - assert(!(Op & ~0xffe00000)); - i.w = Op; - i.Rd.b = Rd; - i.Rn.b = Rn; - i.imm12.b = Imm12; - ii(i.w); -} - -static void -_oxx9(jit_state_t *_jit, int32_t Op, - int32_t Rd, int32_t Rn, int32_t Imm9) -{ - instr_t i; - assert(!(Rd & ~0x1f)); - assert(!(Rn & ~0x1f)); - assert(!(Imm9 & ~0x1ff)); - assert(!(Op & ~0xffe00000)); - i.w = Op; - i.Rd.b = Rd; - i.Rn.b = Rn; - i.imm9.b = Imm9; - ii(i.w); -} - -static void -_ox19(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Simm19) -{ - instr_t i; - assert(!(Rd & ~0x1f)); - assert(Simm19 >= -262148 && Simm19 <= 262143); - assert(!(Op & ~0xff000000)); - i.w = Op; - i.Rd.b = Rd; - i.imm19.b = Simm19; - ii(i.w); -} - -static void -_oc19(jit_state_t *_jit, int32_t Op, int32_t Cc, int32_t Simm19) -{ - instr_t i; - assert(!(Cc & ~0xf)); - assert(Simm19 >= -262148 && Simm19 <= 262143); - assert(!(Op & ~0xff000000)); - i.w = Op; - i.cond2.b = Cc; - i.imm19.b = Simm19; - ii(i.w); -} - -static void -_o26(jit_state_t *_jit, int32_t Op, int32_t Simm26) -{ - instr_t i; - assert(Simm26 >= -33554432 && Simm26 <= 33554431); - assert(!(Op & ~0xfc000000)); - i.w = Op; - i.imm26.b = Simm26; - ii(i.w); -} - -static void -_ox_x(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Rm) -{ - instr_t i; - assert(!(Rd & ~0x1f)); - assert(!(Rm & ~0x1f)); - assert(!(Op & ~0xffe0ffe0)); - i.w = Op; - i.Rd.b = Rd; - i.Rm.b = Rm; - ii(i.w); -} - -static void -_o_xx(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Rn) -{ - instr_t i; - assert(!(Rd & ~0x1f)); - assert(!(Rn & ~0x1f)); - assert(!(Op & ~0xfffffc00)); - i.w = Op; - i.Rd.b = Rd; - i.Rn.b = Rn; - ii(i.w); -} - -static void -_oxx_(jit_state_t *_jit, int32_t Op, int32_t Rn, int32_t Rm) -{ - instr_t i; - assert(!(Rn & ~0x1f)); - assert(!(Rm & ~0x1f)); - assert(!(Op & ~0xffc0fc1f)); - i.w = Op; - i.Rn.b = Rn; - i.Rm.b = Rm; - ii(i.w); -} - -static void -_o_x_(jit_state_t *_jit, int32_t Op, int32_t Rn) -{ - instr_t i; - assert(!(Rn & ~0x1f)); - assert(!(Op & 0x3e0)); - i.w = Op; - i.Rn.b = Rn; - ii(i.w); -} - -static void -_ox_h(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Imm16) -{ - instr_t i; - assert(!(Rd & ~0x1f)); - assert(!(Imm16 & ~0xffff)); - assert(!(Op & ~0xffe00000)); - i.w = Op; - i.Rd.b = Rd; - i.imm16.b = Imm16; - ii(i.w); -} - -static void -_oxxrs(jit_state_t *_jit, int32_t Op, - int32_t Rd, int32_t Rn, int32_t R, int32_t S) -{ - instr_t i; - assert(!(Rd & ~0x1f)); - assert(!(Rn & ~0x1f)); - assert(!(R & ~0x3f)); - assert(!(S & ~0x3f)); - assert(!(Op & ~0xffc00000)); - i.w = Op; - i.Rd.b = Rd; - i.Rn.b = Rn; - i.immr.b = R; - i.imms.b = S; - ii(i.w); -} - -static void -_oxxxc(jit_state_t *_jit, int32_t Op, - int32_t Rd, int32_t Rn, int32_t Rm, int32_t Cc) -{ - instr_t i; - assert(!(Rd & ~0x1f)); - assert(!(Rn & ~0x1f)); - assert(!(Rm & ~0x1f)); - assert(!(Cc & ~0xf)); - assert(!(Op & ~0xffc00c00)); - i.w = Op; - i.Rd.b = Rd; - i.Rn.b = Rn; - i.Rm.b = Rm; - i.cond.b = Cc; - ii(i.w); -} - -static void -_oxxx7(jit_state_t *_jit, int32_t Op, - int32_t Rt, int32_t Rt2, int32_t Rn, int32_t Simm7) -{ - instr_t i; - assert(!(Rt & ~0x1f)); - assert(!(Rt2 & ~0x1f)); - assert(!(Rn & ~0x1f)); - assert(Simm7 >= -128 && Simm7 <= 127); - assert(!(Op & ~0xffc003e0)); - i.w = Op; - i.Rt.b = Rt; - i.Rt2.b = Rt2; - i.Rn.b = Rn; - i.imm7.b = Simm7; - ii(i.w); -} - -static void -_nop(jit_state_t *_jit, int32_t i0) -{ - for (; i0 > 0; i0 -= 4) - NOP(); - assert(i0 == 0); -} - -static void -_addi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) -{ - int32_t reg; - jit_word_t is = i0 >> 12; - jit_word_t in = -i0; - jit_word_t iS = in >> 12; - if ( i0 >= 0 && i0 <= 0xfff) - ADDI (r0, r1, i0); - else if ((is << 12) == i0 && is >= 0 && is <= 0xfff) - ADDI_12(r0, r1, is); - else if ( in >= 0 && in <= 0xfff) - SUBI (r0, r1, in); - else if ((iS << 12) == is && iS >= 0 && iS <= 0xfff) - SUBI_12(r0, r1, iS); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - addr(r0, r1, rn(reg)); - jit_unget_reg(reg); + break; + case 8: + MOVZ_48(_jit, r0, (i0 >> 48) & 0xffff); + break; + case 9: + MOVZ (_jit, r0, i0 & 0xffff); + MOVK_48(_jit, r0, (i0 >> 48) & 0xffff); + break; + case 10: + MOVZ_16(_jit, r0, (i0 >> 16) & 0xffff); + MOVK_48(_jit, r0, (i0 >> 48) & 0xffff); + break; + case 11: + if (nbit == 4) { + MOVN_32(_jit, r0, (n0 >> 32) & 0xffff); + } else { + MOVZ (_jit, r0, i0 & 0xffff); + MOVK_16(_jit, r0, (i0 >> 16) & 0xffff); + MOVK_48(_jit, r0, (i0 >> 48) & 0xffff); } -} - -static void -_addci(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) -{ - int32_t reg; - jit_word_t is = i0 >> 12; - jit_word_t in = -i0; - jit_word_t iS = in >> 12; - if ( i0 >= 0 && i0 <= 0xfff) - ADDSI (r0, r1, i0); - else if ((is << 12) == i0 && is >= 0 && is <= 0xfff) - ADDSI_12(r0, r1, is); - else if ( in >= 0 && in <= 0xfff) - SUBSI (r0, r1, in); - else if ((iS << 12) == is && iS >= 0 && iS <= 0xfff) - SUBSI_12(r0, r1, iS); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - addcr(r0, r1, rn(reg)); - jit_unget_reg(reg); + break; + case 12: + MOVZ_32(_jit, r0, (i0 >> 32) & 0xffff); + MOVK_48(_jit, r0, (i0 >> 48) & 0xffff); + break; + case 13: + if (nbit == 2) { + MOVN_16(_jit, r0, (n0 >> 16) & 0xffff); + } else { + MOVZ (_jit, r0, i0 & 0xffff); + MOVK_32(_jit, r0, (i0 >> 32) & 0xffff); + MOVK_48(_jit, r0, (i0 >> 48) & 0xffff); } -} - -static void -_addxi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) -{ - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - addxr(r0, r1, rn(reg)); - jit_unget_reg(reg); -} - -static void -_subi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) -{ - int32_t reg; - jit_word_t is = i0 >> 12; - if ( i0 >= 0 && i0 <= 0xfff) - SUBI (r0, r1, i0); - else if ((is << 12) == i0 && is >= 0 && is <= 0xfff) - SUBI_12(r0, r1, is); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - subr(r0, r1, rn(reg)); - jit_unget_reg(reg); + break; + case 14: + if (nbit == 1) { + MOVN (_jit, r0, (n0) & 0xffff); + } else { + MOVZ_16(_jit, r0, (i0 >> 16) & 0xffff); + MOVK_32(_jit, r0, (i0 >> 32) & 0xffff); + MOVK_48(_jit, r0, (i0 >> 48) & 0xffff); } -} - -static void -_subci(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) -{ - int32_t reg; - jit_word_t is = i0 >> 12; - if ( i0 >= 0 && i0 <= 0xfff) - SUBSI (r0, r1, i0); - else if ((is << 12) == i0 && is >= 0 && is <= 0xfff) - SUBSI_12(r0, r1, is); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - subcr(r0, r1, rn(reg)); - jit_unget_reg(reg); + break; + case 15: + if (nbit == 0) { + MOVN (_jit, r0, 0); + } else if (nbit == 1) { + MOVN (_jit, r0, n0 & 0xffff); + } else if (nbit == 8) { + MOVN_48(_jit, r0, (n0 >> 48) & 0xffff); + } else { + MOVZ (_jit, r0, i0 & 0xffff); + MOVK_16(_jit, r0, (i0 >> 16) & 0xffff); + MOVK_32(_jit, r0, (i0 >> 32) & 0xffff); + MOVK_48(_jit, r0, (i0 >> 48) & 0xffff); } + break; + default: + abort(); + } } static void -_subxi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +ccr(jit_state_t *_jit, int32_t cc, int32_t r0, int32_t r1, int32_t r2) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - subxr(r0, r1, rn(reg)); - jit_unget_reg(reg); + CMP(_jit, r1, r2); + CSET(_jit, r0, cc); } static void -_rsbi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +cci(jit_state_t *_jit, int32_t cc, int32_t r0, int32_t r1, jit_word_t i0) { - subi(r0, r1, i0); - negr(r0, r0); + jit_word_t is = i0 >> 12; + jit_word_t in = -i0; + jit_word_t iS = in >> 12; + if ( i0 >= 0 && i0 <= 0xfff) { + CMPI (_jit, r1, i0); + } else if ((is << 12) == i0 && is >= 0 && is <= 0xfff) { + CMPI_12(_jit, r1, is); + } else if ( in >= 0 && in <= 0xfff) { + CMNI (_jit, r1, in); + } else if ((iS << 12) == is && iS >= 0 && iS <= 0xfff) { + CMNI_12(_jit, r1, iS); + } else { + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + CMP(_jit, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } + CSET(_jit, r0, cc); } static void -_muli(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +ltr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - mulr(r0, r1, rn(reg)); - jit_unget_reg(reg); + return ccr(_jit,CC_LT,r0,r1,r2); } static void -_qmulr(jit_state_t *_jit, int32_t r0, - int32_t r1, int32_t r2, int32_t r3) +lti(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) { - int32_t reg; - if (r0 == r2 || r0 == r3) { - reg = jit_get_reg(jit_class_gpr); - mulr(rn(reg), r2, r3); + return cci(_jit,CC_LT,r0,r1,i0); +} + +static void +ltr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + return ccr(_jit,CC_CC,r0,r1,r2); +} + +static void +lti_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) +{ + return cci(_jit,CC_CC,r0,r1,i0); +} + +static void +ler(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + return ccr(_jit,CC_LE,r0,r1,r2); +} + +static void +lei(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) +{ + return cci(_jit,CC_LE,r0,r1,i0); +} + +static void +ler_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + return ccr(_jit,CC_LS,r0,r1,r2); +} + +static void +lei_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) +{ + return cci(_jit,CC_LS,r0,r1,i0); +} + +static void +eqr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + return ccr(_jit,CC_EQ,r0,r1,r2); +} + +static void +eqi(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) +{ + return cci(_jit,CC_EQ,r0,r1,i0); +} + +static void +ger(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + return ccr(_jit,CC_GE,r0,r1,r2); +} + +static void +gei(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) +{ + return cci(_jit,CC_GE,r0,r1,i0); +} + +static void +ger_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + return ccr(_jit,CC_CS,r0,r1,r2); +} + +static void +gei_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) +{ + return cci(_jit,CC_CS,r0,r1,i0); +} + +static void +gtr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + return ccr(_jit,CC_GT,r0,r1,r2); +} + +static void +gti(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) +{ + return cci(_jit,CC_GT,r0,r1,i0); +} + +static void +gtr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + return ccr(_jit,CC_HI,r0,r1,r2); +} + +static void +gti_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) +{ + return cci(_jit,CC_HI,r0,r1,i0); +} + +static void +ner(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + return ccr(_jit,CC_NE,r0,r1,r2); +} + +static void +nei(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) +{ + return cci(_jit,CC_NE,r0,r1,i0); +} + +static jit_reloc_t +bccr(jit_state_t *_jit, int32_t cc, int32_t r0, int32_t r1) +{ + CMP(_jit, r0, r1); + return B_C(_jit, cc); +} + +static jit_reloc_t +bcci(jit_state_t *_jit, int32_t cc, int32_t r0, jit_word_t i1) +{ + jit_word_t is = i1 >> 12; + jit_word_t in = -i1; + jit_word_t iS = in >> 12; + if ( i1 >= 0 && i1 <= 0xfff) { + CMPI (_jit, r0, i1); + } else if ((is << 12) == i1 && is >= 0 && is <= 0xfff) { + CMPI_12(_jit, r0, is); + } else if ( in >= 0 && in <= 0xfff) { + CMNI (_jit, r0, in); + } else if ((iS << 12) == is && iS >= 0 && iS <= 0xfff) { + CMNI_12(_jit, r0, iS); + } else { + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i1); + CMP(_jit, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } + return B_C(_jit, cc); +} + +static jit_reloc_t +bltr(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return bccr(_jit,BCC_LT,r0,r1); +} + +static jit_reloc_t +blti(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return bcci(_jit,BCC_LT,r0,i1); +} + +static jit_reloc_t +bltr_u(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return bccr(_jit,BCC_CC,r0,r1); +} + +static jit_reloc_t +blti_u(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return bcci(_jit,BCC_CC,r0,i1); +} + +static jit_reloc_t +bler(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return bccr(_jit,BCC_LE,r0,r1); +} + +static jit_reloc_t +blei(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return bcci(_jit,BCC_LE,r0,i1); +} + +static jit_reloc_t +bler_u(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return bccr(_jit,BCC_LS,r0,r1); +} + +static jit_reloc_t +blei_u(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return bcci(_jit,BCC_LS,r0,i1); +} + +static jit_reloc_t +beqr(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return bccr(_jit,BCC_EQ,r0,r1); +} + +static jit_reloc_t +bger(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return bccr(_jit,BCC_GE,r0,r1); +} + +static jit_reloc_t +bgei(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return bcci(_jit,BCC_GE,r0,i1); +} + +static jit_reloc_t +bger_u(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return bccr(_jit,BCC_CS,r0,r1); +} + +static jit_reloc_t +bgei_u(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return bcci(_jit,BCC_CS,r0,i1); +} + +static jit_reloc_t +bgtr(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return bccr(_jit,BCC_GT,r0,r1); +} + +static jit_reloc_t +bgti(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return bcci(_jit,BCC_GT,r0,i1); +} + +static jit_reloc_t +bgtr_u(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return bccr(_jit,BCC_HI,r0,r1); +} + +static jit_reloc_t +bgti_u(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return bcci(_jit,BCC_HI,r0,i1); +} + +static jit_reloc_t +bner(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return bccr(_jit,BCC_NE,r0,r1); +} + +static void +addi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + jit_word_t is = i0 >> 12; + jit_word_t in = -i0; + jit_word_t iS = in >> 12; + if ( i0 >= 0 && i0 <= 0xfff) { + ADDI (_jit, r0, r1, i0); + } else if ((is << 12) == i0 && is >= 0 && is <= 0xfff) { + ADDI_12(_jit, r0, r1, is); + } else if ( in >= 0 && in <= 0xfff) { + SUBI (_jit, r0, r1, in); + } else if ((iS << 12) == is && iS >= 0 && iS <= 0xfff) { + SUBI_12(_jit, r0, r1, iS); + } else { + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + addr(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } +} + +static void +addci(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + jit_word_t is = i0 >> 12; + jit_word_t in = -i0; + jit_word_t iS = in >> 12; + if ( i0 >= 0 && i0 <= 0xfff) { + ADDSI (_jit, r0, r1, i0); + } else if ((is << 12) == i0 && is >= 0 && is <= 0xfff) { + ADDSI_12(_jit, r0, r1, is); + } else if ( in >= 0 && in <= 0xfff) { + SUBSI (_jit, r0, r1, in); + } else if ((iS << 12) == is && iS >= 0 && iS <= 0xfff) { + SUBSI_12(_jit, r0, r1, iS); + } else { + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + addcr(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } +} + +static void +addxi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + addxr(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); +} + +static void +subi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + jit_word_t is = i0 >> 12; + if ( i0 >= 0 && i0 <= 0xfff) { + SUBI (_jit, r0, r1, i0); + } else if ((is << 12) == i0 && is >= 0 && is <= 0xfff) { + SUBI_12(_jit, r0, r1, is); + } else { + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + subr(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } +} + +static void +subci(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + jit_word_t is = i0 >> 12; + if ( i0 >= 0 && i0 <= 0xfff) { + SUBSI (_jit, r0, r1, i0); + } else if ((is << 12) == i0 && is >= 0 && is <= 0xfff) { + SUBSI_12(_jit, r0, r1, is); + } else { + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + subcr(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } +} + +static void +subxi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + subxr(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); +} + +static jit_reloc_t +baddr(jit_state_t *_jit, int32_t cc, int32_t r0, int32_t r1) +{ + addcr(_jit, r0, r0, r1); + return B_C(_jit, cc); +} + +static jit_reloc_t +baddi(jit_state_t *_jit, int32_t cc, int32_t r0, jit_word_t i1) +{ + addci(_jit, r0, r0, i1); + return B_C(_jit, cc); +} + +static jit_reloc_t +boaddr(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return baddr(_jit,BCC_VS,r0,r1); +} + +static jit_reloc_t +boaddi(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return baddi(_jit,BCC_VS,r0,i1); +} + +static jit_reloc_t +boaddr_u(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return baddr(_jit,BCC_HS,r0,r1); +} + +static jit_reloc_t +boaddi_u(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return baddi(_jit,BCC_HS,r0,i1); +} + +static jit_reloc_t +bxaddr(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return baddr(_jit,BCC_VC,r0,r1); +} + +static jit_reloc_t +bxaddi(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return baddi(_jit,BCC_VC,r0,i1); +} + +static jit_reloc_t +bxaddr_u(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return baddr(_jit,BCC_LO,r0,r1); +} + +static jit_reloc_t +bxaddi_u(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return baddi(_jit,BCC_LO,r0,i1); +} + +static jit_reloc_t +bsubr(jit_state_t *_jit, int32_t cc, int32_t r0, int32_t r1) +{ + subcr(_jit, r0, r0, r1); + return B_C(_jit, cc); +} + +static jit_reloc_t +bsubi(jit_state_t *_jit, int32_t cc, int32_t r0, jit_word_t i1) +{ + subci(_jit, r0, r0, i1); + return B_C(_jit, cc); +} + +static jit_reloc_t +bosubr(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return bsubr(_jit,BCC_VS,r0,r1); +} + +static jit_reloc_t +bosubi(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return bsubi(_jit,BCC_VS,r0,i1); +} + +static jit_reloc_t +bosubr_u(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return bsubr(_jit,BCC_LO,r0,r1); +} + +static jit_reloc_t +bosubi_u(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return bsubi(_jit,BCC_LO,r0,i1); +} + +static jit_reloc_t +bxsubr(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return bsubr(_jit,BCC_VC,r0,r1); +} + +static jit_reloc_t +bxsubi(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return bsubi(_jit,BCC_VC,r0,i1); +} + +static jit_reloc_t +bxsubr_u(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return bsubr(_jit,BCC_HS,r0,r1); +} + +static jit_reloc_t +bxsubi_u(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return bsubi(_jit,BCC_HS,r0,i1); +} + +static jit_reloc_t +bmxr(jit_state_t *_jit, int32_t cc, int32_t r0, int32_t r1) +{ + TST(_jit, r0, r1); + return B_C(_jit, cc); +} + +static jit_reloc_t +bmxi(jit_state_t *_jit, int32_t cc, int32_t r0, jit_word_t i1) +{ + int32_t imm; + imm = logical_immediate(i1); + if (imm != -1) { + TSTI(_jit, r0, imm); + } else { + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i1); + TST(_jit, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } + return B_C(_jit, cc); +} + +static jit_reloc_t +bmsr(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return bmxr(_jit,BCC_NE,r0,r1); +} + +static jit_reloc_t +bmsi(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return bmxi(_jit,BCC_NE,r0,i1); +} + +static jit_reloc_t +bmcr(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return bmxr(_jit,BCC_EQ,r0,r1); +} + +static jit_reloc_t +bmci(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return bmxi(_jit,BCC_EQ,r0,i1); +} + +static void +jmpr(jit_state_t *_jit, int32_t r0) +{ + return BR(_jit, r0); +} + +static void +callr(jit_state_t *_jit, int32_t r0) +{ + return BLR(_jit,r0); +} + +static void +nop(jit_state_t *_jit, int32_t i0) +{ + for (; i0 > 0; i0 -= 4) + NOP(_jit); + ASSERT(i0 == 0); +} + +static void +rsbi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + subi(_jit, r0, r1, i0); + negr(_jit, r0, r0); +} + +static void +muli(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + mulr(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); +} + +static void +qmulr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, int32_t r3) +{ + jit_gpr_t reg; + if (r0 == r2 || r0 == r3) { + reg = get_temp_gpr(_jit); + mulr(_jit, jit_gpr_regno(reg), r2, r3); + } else { + mulr(_jit, r0, r2, r3); + } + SMULH(_jit, r1, r2, r3); + if (r0 == r2 || r0 == r3) { + movr(_jit, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } +} + +static void +qmuli(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, jit_word_t i0) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + qmulr(_jit, r0, r1, r2, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); +} + +static void +qmulr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, int32_t r3) +{ + jit_gpr_t reg; + if (r0 == r2 || r0 == r3) { + reg = get_temp_gpr(_jit); + mulr(_jit, jit_gpr_regno(reg), r2, r3); + } else { + mulr(_jit, r0, r2, r3); + } + UMULH(_jit, r1, r2, r3); + if (r0 == r2 || r0 == r3) { + movr(_jit, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } +} + +static void +qmuli_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, jit_word_t i0) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + qmulr_u(_jit, r0, r1, r2, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); +} + +static void +divi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + divr(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); +} + +static void +divi_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + divr_u(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); +} + +static void +qdivi(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, jit_word_t i0) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + qdivr(_jit, r0, r1, r2, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); +} + +static void +qdivi_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, jit_word_t i0) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + qdivr_u(_jit, r0, r1, r2, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); +} + +static void +remr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + if (r0 == r1 || r0 == r2) { + jit_gpr_t reg = get_temp_gpr(_jit); + divr(_jit, jit_gpr_regno(reg), r1, r2); + mulr(_jit, jit_gpr_regno(reg), r2, jit_gpr_regno(reg)); + subr(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } else { + divr(_jit, r0, r1, r2); + mulr(_jit, r0, r2, r0); + subr(_jit, r0, r1, r0); + } +} + +static void +remi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + remr(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); +} + +static void +remr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + if (r0 == r1 || r0 == r2) { + jit_gpr_t reg = get_temp_gpr(_jit); + divr_u(_jit, jit_gpr_regno(reg), r1, r2); + mulr(_jit, jit_gpr_regno(reg), r2, jit_gpr_regno(reg)); + subr(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } else { + divr_u(_jit, r0, r1, r2); + mulr(_jit, r0, r2, r0); + subr(_jit, r0, r1, r0); + } +} + +static void +remi_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + remr_u(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); +} + +static void +lshi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + if (i0 == 0) { + movr(_jit, r0, r1); + } else { + ASSERT(i0 > 0 && i0 < 64); + LSLI(_jit, r0, r1, i0); + } +} + +static void +rshi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + if (i0 == 0) { + movr(_jit, r0, r1); + } else { + ASSERT(i0 > 0 && i0 < 64); + ASRI(_jit, r0, r1, i0); + } +} + +static void +rshi_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + if (i0 == 0) { + movr(_jit, r0, r1); + } else { + ASSERT(i0 > 0 && i0 < 64); + LSRI(_jit, r0, r1, i0); + } +} + +static void +andi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + int32_t imm; + if (i0 == 0) { + movi(_jit, r0, 0); + } else if (i0 == -1){ + movr(_jit, r0, r1); + } else { + imm = logical_immediate(i0); + if (imm != -1) { + ANDI(_jit, r0, r1, imm); + } else { + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + andr(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); } - else - mulr(r0, r2, r3); - SMULH(r1, r2, r3); - if (r0 == r2 || r0 == r3) { - movr(r0, rn(reg)); - jit_unget_reg(reg); + } +} + +static void +ori(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + int32_t imm; + if (i0 == 0) { + movr(_jit, r0, r1); + } else if (i0 == -1) { + movi(_jit, r0, -1); + } else { + imm = logical_immediate(i0); + if (imm != -1) { + ORRI(_jit, r0, r1, imm); + } else { + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + orr(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); } + } } static void -_qmuli(jit_state_t *_jit, int32_t r0, - int32_t r1, int32_t r2, jit_word_t i0) +xori(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - qmulr(r0, r1, r2, rn(reg)); - jit_unget_reg(reg); -} - -static void -_qmulr_u(jit_state_t *_jit, int32_t r0, - int32_t r1, int32_t r2, int32_t r3) -{ - int32_t reg; - if (r0 == r2 || r0 == r3) { - reg = jit_get_reg(jit_class_gpr); - mulr(rn(reg), r2, r3); - } - else - mulr(r0, r2, r3); - UMULH(r1, r2, r3); - if (r0 == r2 || r0 == r3) { - movr(r0, rn(reg)); - jit_unget_reg(reg); + int32_t imm; + if (i0 == 0) { + movr(_jit, r0, r1); + } else if (i0 == -1) { + comr(_jit, r0, r1); + } else { + imm = logical_immediate(i0); + if (imm != -1) { + EORI(_jit, r0, r1, imm); + } else { + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + xorr(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); } + } } static void -_qmuli_u(jit_state_t *_jit, int32_t r0, - int32_t r1, int32_t r2, jit_word_t i0) +bswapr_us(jit_state_t *_jit, int32_t r0, int32_t r1) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - qmulr_u(r0, r1, r2, rn(reg)); - jit_unget_reg(reg); + bswapr_ul(_jit, r0, r1); + rshi_u(_jit, r0, r0, 48); } static void -_divi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +bswapr_ui(jit_state_t *_jit, int32_t r0, int32_t r1) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - divr(r0, r1, rn(reg)); - jit_unget_reg(reg); + bswapr_ul(_jit, r0, r1); + rshi_u(_jit, r0, r0, 32); } static void -_divi_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +ldi_c(jit_state_t *_jit, int32_t r0, jit_word_t i0) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - divr_u(r0, r1, rn(reg)); - jit_unget_reg(reg); + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + ldr_c(_jit, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); } static void -_iqdivr(jit_state_t *_jit, jit_bool_t sign, - int32_t r0, int32_t r1, int32_t r2, int32_t r3) +ldr_uc(jit_state_t *_jit, int32_t r0, int32_t r1) { - int32_t sv0, rg0; - int32_t sv1, rg1; - if (r0 == r2 || r0 == r3) { - sv0 = jit_get_reg(jit_class_gpr); - rg0 = rn(sv0); - } - else - rg0 = r0; - if (r1 == r2 || r1 == r3) { - sv1 = jit_get_reg(jit_class_gpr); - rg1 = rn(sv1); - } - else - rg1 = r1; - if (sign) - divr(rg0, r2, r3); - else - divr_u(rg0, r2, r3); - mulr(rg1, r3, rg0); - subr(rg1, r2, rg1); - if (rg0 != r0) { - movr(r0, rg0); - jit_unget_reg(sv0); - } - if (rg1 != r1) { - movr(r1, rg1); - jit_unget_reg(sv1); - } -} - -static void -_qdivi(jit_state_t *_jit, int32_t r0, - int32_t r1, int32_t r2, jit_word_t i0) -{ - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - qdivr(r0, r1, r2, rn(reg)); - jit_unget_reg(reg); -} - -static void -_qdivi_u(jit_state_t *_jit, int32_t r0, - int32_t r1, int32_t r2, jit_word_t i0) -{ - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - qdivr_u(r0, r1, r2, rn(reg)); - jit_unget_reg(reg); -} - -static void -_remr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - int32_t reg; - if (r0 == r1 || r0 == r2) { - reg = jit_get_reg(jit_class_gpr); - divr(rn(reg), r1, r2); - mulr(rn(reg), r2, rn(reg)); - subr(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - else { - divr(r0, r1, r2); - mulr(r0, r2, r0); - subr(r0, r1, r0); - } -} - -static void -_remi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) -{ - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - remr(r0, r1, rn(reg)); - jit_unget_reg(reg); -} - -static void -_remr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - int32_t reg; - if (r0 == r1 || r0 == r2) { - reg = jit_get_reg(jit_class_gpr); - divr_u(rn(reg), r1, r2); - mulr(rn(reg), r2, rn(reg)); - subr(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - else { - divr_u(r0, r1, r2); - mulr(r0, r2, r0); - subr(r0, r1, r0); - } -} - -static void -_remi_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) -{ - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - remr_u(r0, r1, rn(reg)); - jit_unget_reg(reg); -} - -static void -_lshi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) -{ - if (i0 == 0) - movr(r0, r1); - else { - assert(i0 > 0 && i0 < 64); - LSLI(r0, r1, i0); - } -} - -static void -_rshi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) -{ - if (i0 == 0) - movr(r0, r1); - else { - assert(i0 > 0 && i0 < 64); - ASRI(r0, r1, i0); - } -} - -static void -_rshi_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) -{ - if (i0 == 0) - movr(r0, r1); - else { - assert(i0 > 0 && i0 < 64); - LSRI(r0, r1, i0); - } -} - -static void -_andi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) -{ - int32_t reg; - int32_t imm; - if (i0 == 0) - movi(r0, 0); - else if (i0 == -1) - movr(r0, r1); - else { - imm = logical_immediate(i0); - if (imm != -1) - ANDI(r0, r1, imm); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - andr(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - } -} - -static void -_ori(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) -{ - int32_t reg; - int32_t imm; - if (i0 == 0) - movr(r0, r1); - else if (i0 == -1) - movi(r0, -1); - else { - imm = logical_immediate(i0); - if (imm != -1) - ORRI(r0, r1, imm); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - orr(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - } -} - -static void -_xori(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) -{ - int32_t reg; - int32_t imm; - if (i0 == 0) - movr(r0, r1); - else if (i0 == -1) - comr(r0, r1); - else { - imm = logical_immediate(i0); - if (imm != -1) - EORI(r0, r1, imm); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - xorr(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - } -} - -#if __BYTE_ORDER == __LITTLE_ENDIAN -static void -_bswapr_us(jit_state_t *_jit, int32_t r0, int32_t r1) -{ - bswapr_ul(r0, r1); - rshi_u(r0, r0, 48); -} - -static void -_bswapr_ui(jit_state_t *_jit, int32_t r0, int32_t r1) -{ - bswapr, 2019_ul(r0, r1); - rshi_u(r0, r0, 32); -} -#endif - -static void -_ldi_c(jit_state_t *_jit, int32_t r0, jit_word_t i0) -{ - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - ldr_c(r0, rn(reg)); - jit_unget_reg(reg); -} - -static void -_ldr_uc(jit_state_t *_jit, int32_t r0, int32_t r1) -{ - LDRBI(r0, r1, 0); + LDRBI(_jit, r0, r1, 0); #if 0 - extr_uc(r0, r0); + extr_uc(_jit, r0, r0); #endif } static void -_ldi_uc(jit_state_t *_jit, int32_t r0, jit_word_t i0) +ldi_uc(jit_state_t *_jit, int32_t r0, jit_word_t i0) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - ldr_uc(r0, rn(reg)); - jit_unget_reg(reg); + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + ldr_uc(_jit, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); } static void -_ldi_s(jit_state_t *_jit, int32_t r0, jit_word_t i0) +ldi_s(jit_state_t *_jit, int32_t r0, jit_word_t i0) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - ldr_s(r0, rn(reg)); - jit_unget_reg(reg); + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + ldr_s(_jit, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); } static void -_ldr_us(jit_state_t *_jit, int32_t r0, int32_t r1) +ldr_us(jit_state_t *_jit, int32_t r0, int32_t r1) { - LDRHI(r0, r1, 0); + LDRHI(_jit, r0, r1, 0); #if 0 - extr_us(r0, r0); + extr_us(_jit, r0, r0); #endif } static void -_ldi_us(jit_state_t *_jit, int32_t r0, jit_word_t i0) +ldi_us(jit_state_t *_jit, int32_t r0, jit_word_t i0) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - ldr_us(r0, rn(reg)); - jit_unget_reg(reg); + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + ldr_us(_jit, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); } static void -_ldi_i(jit_state_t *_jit, int32_t r0, jit_word_t i0) +ldi_i(jit_state_t *_jit, int32_t r0, jit_word_t i0) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - ldr_i(r0, rn(reg)); - jit_unget_reg(reg); + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + ldr_i(_jit, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); } static void -_ldr_ui(jit_state_t *_jit, int32_t r0, int32_t r1) +ldr_ui(jit_state_t *_jit, int32_t r0, int32_t r1) { - LDRWI(r0, r1, 0); + LDRWI(_jit, r0, r1, 0); #if 0 - extr_ui(r0, r0); + extr_ui(_jit, r0, r0); #endif } static void -_ldi_ui(jit_state_t *_jit, int32_t r0, jit_word_t i0) +ldi_ui(jit_state_t *_jit, int32_t r0, jit_word_t i0) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - ldr_ui(r0, rn(reg)); - jit_unget_reg(reg); + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + ldr_ui(_jit, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); } static void -_ldi_l(jit_state_t *_jit, int32_t r0, jit_word_t i0) +ldr_l(jit_state_t *_jit, int32_t r0, int32_t r1) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - ldr_l(r0, rn(reg)); - jit_unget_reg(reg); + LDRI(_jit, r0, r1, 0); } static void -_ldxr_c(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +ldi_l(jit_state_t *_jit, int32_t r0, jit_word_t i0) { - LDRSB(r0, r1, r2); - extr_c(r0, r0); + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + ldr_l(_jit, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); } static void -_ldxi_c(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +ldxr_c(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - int32_t reg; - if (i0 >= 0 && i0 <= 4095) - LDRSBI(r0, r1, i0); - else if (i0 > -256 && i0 < 0) - LDURSB(r0, r1, i0 & 0x1ff); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - LDRSB(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - extr_c(r0, r0); + LDRSB(_jit, r0, r1, r2); + extr_c(_jit, r0, r0); } static void -_ldxr_uc(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +ldxi_c(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - LDRB(r0, r1, r2); + if (i0 >= 0 && i0 <= 4095) { + LDRSBI(_jit, r0, r1, i0); + } else if (i0 > -256 && i0 < 0) { + LDURSB(_jit, r0, r1, i0 & 0x1ff); + } else { + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + LDRSB(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } + extr_c(_jit, r0, r0); +} + +static void +ldxr_uc(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + LDRB(_jit, r0, r1, r2); #if 0 - extr_uc(r0, r0); + extr_uc(_jit, r0, r0); #endif } static void -_ldxi_uc(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +ldxi_uc(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - int32_t reg; - if (i0 >= 0 && i0 <= 4095) - LDRBI(r0, r1, i0); - else if (i0 > -256 && i0 < 0) - LDURB(r0, r1, i0 & 0x1ff); - else { - reg = jit_get_reg(jit_class_gpr); - addi(rn(reg), r1, i0); - ldr_uc(r0, rn(reg)); - jit_unget_reg(reg); - } + if (i0 >= 0 && i0 <= 4095) { + LDRBI(_jit, r0, r1, i0); + } else if (i0 > -256 && i0 < 0) { + LDURB(_jit, r0, r1, i0 & 0x1ff); + } else { + jit_gpr_t reg = get_temp_gpr(_jit); + addi(_jit, jit_gpr_regno(reg), r1, i0); + ldr_uc(_jit, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } #if 0 - extr_uc(r0, r0); + extr_uc(_jit, r0, r0); #endif } static void -_ldxi_s(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +ldxi_s(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - int32_t reg; - assert(!(i0 & 1)); - if (i0 >= 0 && i0 <= 8191) - LDRSHI(r0, r1, i0 >> 1); - else if (i0 > -256 && i0 < 0) - LDURSH(r0, r1, i0 & 0x1ff); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - LDRSH(r0, r1, rn(reg)); - jit_unget_reg(reg); - } + ASSERT(!(i0 & 1)); + if (i0 >= 0 && i0 <= 8191) { + LDRSHI(_jit, r0, r1, i0 >> 1); + } else if (i0 > -256 && i0 < 0) { + LDURSH(_jit, r0, r1, i0 & 0x1ff); + } else { + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + LDRSH(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } } static void -_ldxr_us(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +ldxr_us(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - LDRH(r0, r1, r2); + LDRH(_jit, r0, r1, r2); #if 0 - extr_us(r0, r0); + extr_us(_jit, r0, r0); #endif } static void -_ldxi_us(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +ldxi_us(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - int32_t reg; - assert(!(i0 & 1)); - if (i0 >= 0 && i0 <= 8191) - LDRHI(r0, r1, i0 >> 1); - else if (i0 > -256 && i0 < 0) - LDURH(r0, r1, i0 & 0x1ff); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - LDRH(r0, r1, rn(reg)); - jit_unget_reg(reg); - } + ASSERT(!(i0 & 1)); + if (i0 >= 0 && i0 <= 8191) { + LDRHI(_jit, r0, r1, i0 >> 1); + } else if (i0 > -256 && i0 < 0) { + LDURH(_jit, r0, r1, i0 & 0x1ff); + } else { + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + LDRH(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } #if 0 - extr_us(r0, r0); + extr_us(_jit, r0, r0); #endif } static void -_ldxi_i(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +ldxi_i(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - int32_t reg; - assert(!(i0 & 3)); - if (i0 >= 0 && i0 <= 16383) - LDRSWI(r0, r1, i0 >> 2); - else if (i0 > -256 && i0 < 0) - LDURSW(r0, r1, i0 & 0x1ff); - else { - reg = jit_get_reg(jit_class_gpr); - addi(rn(reg), r1, i0); - ldr_i(r0, rn(reg)); - jit_unget_reg(reg); - } + ASSERT(!(i0 & 3)); + if (i0 >= 0 && i0 <= 16383) { + LDRSWI(_jit, r0, r1, i0 >> 2); + } else if (i0 > -256 && i0 < 0) { + LDURSW(_jit, r0, r1, i0 & 0x1ff); + } else { + jit_gpr_t reg = get_temp_gpr(_jit); + addi(_jit, jit_gpr_regno(reg), r1, i0); + ldr_i(_jit, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } } static void -_ldxr_ui(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +ldxr_ui(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - LDRW(r0, r1, r2); + LDRW(_jit, r0, r1, r2); #if 0 - extr_ui(r0, r0); + extr_ui(_jit, r0, r0); #endif } static void -_ldxi_ui(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +ldxi_ui(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - int32_t reg; - assert(!(i0 & 3)); - if (i0 >= 0 && i0 <= 16383) - LDRWI(r0, r1, i0 >> 2); - else if (i0 > -256 && i0 < 0) - LDURW(r0, r1, i0 & 0x1ff); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - LDRW(r0, r1, rn(reg)); - jit_unget_reg(reg); - } + ASSERT(!(i0 & 3)); + if (i0 >= 0 && i0 <= 16383) { + LDRWI(_jit, r0, r1, i0 >> 2); + } else if (i0 > -256 && i0 < 0) { + LDURW(_jit, r0, r1, i0 & 0x1ff); + } else { + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + LDRW(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } #if 0 - extr_ui(r0, r0); + extr_ui(_jit, r0, r0); #endif } static void -_ldxi_l(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +ldxi_l(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - int32_t reg; - assert(!(i0 & 7)); - if (i0 >= 0 && i0 <= 32767) - LDRI(r0, r1, i0 >> 3); - else if (i0 > -256 && i0 < 0) - LDUR(r0, r1, i0 & 0x1ff); - else { - reg = jit_get_reg(jit_class_gpr); - addi(rn(reg), r1, i0); - ldr_l(r0, rn(reg)); - jit_unget_reg(reg); - } + ASSERT(!(i0 & 7)); + if (i0 >= 0 && i0 <= 32767) { + LDRI(_jit, r0, r1, i0 >> 3); + } else if (i0 > -256 && i0 < 0) { + LDUR(_jit, r0, r1, i0 & 0x1ff); + } else { + jit_gpr_t reg = get_temp_gpr(_jit); + addi(_jit, jit_gpr_regno(reg), r1, i0); + ldr_l(_jit, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } } static void -_sti_c(jit_state_t *_jit, jit_word_t i0, int32_t r0) +sti_c(jit_state_t *_jit, jit_word_t i0, int32_t r0) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - str_c(rn(reg), r0); - jit_unget_reg(reg); + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + str_c(_jit, jit_gpr_regno(reg), r0); + unget_temp_gpr(_jit); } static void -_sti_s(jit_state_t *_jit, jit_word_t i0, int32_t r0) +sti_s(jit_state_t *_jit, jit_word_t i0, int32_t r0) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - str_s(rn(reg), r0); - jit_unget_reg(reg); + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + str_s(_jit, jit_gpr_regno(reg), r0); + unget_temp_gpr(_jit); } static void -_sti_i(jit_state_t *_jit, jit_word_t i0, int32_t r0) +sti_i(jit_state_t *_jit, jit_word_t i0, int32_t r0) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - str_i(rn(reg), r0); - jit_unget_reg(reg); + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + str_i(_jit, jit_gpr_regno(reg), r0); + unget_temp_gpr(_jit); } static void -_sti_l(jit_state_t *_jit, jit_word_t i0, int32_t r0) +sti_l(jit_state_t *_jit, jit_word_t i0, int32_t r0) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - str_l(rn(reg), r0); - jit_unget_reg(reg); + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + str_l(_jit, jit_gpr_regno(reg), r0); + unget_temp_gpr(_jit); } static void -_stxi_c(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) +stxi_c(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) { - int32_t reg; - if (i0 >= 0 && i0 <= 4095) - STRBI(r1, r0, i0); - else if (i0 > -256 && i0 < 0) - STURB(r1, r0, i0 & 0x1ff); - else { - reg = jit_get_reg(jit_class_gpr); - addi(rn(reg), r0, i0); - str_c(rn(reg), r1); - jit_unget_reg(reg); - } + if (i0 >= 0 && i0 <= 4095) { + STRBI(_jit, r1, r0, i0); + } else if (i0 > -256 && i0 < 0) { + STURB(_jit, r1, r0, i0 & 0x1ff); + } else { + jit_gpr_t reg = get_temp_gpr(_jit); + addi(_jit, jit_gpr_regno(reg), r0, i0); + str_c(_jit, jit_gpr_regno(reg), r1); + unget_temp_gpr(_jit); + } } static void -_stxi_s(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) +stxi_s(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) { - int32_t reg; - assert(!(i0 & 1)); - if (i0 >= 0 && i0 <= 8191) - STRHI(r1, r0, i0 >> 1); - else if (i0 > -256 && i0 < 0) - STURH(r1, r0, i0 & 0x1ff); - else { - reg = jit_get_reg(jit_class_gpr); - addi(rn(reg), r0, i0); - str_s(rn(reg), r1); - jit_unget_reg(reg); - } + ASSERT(!(i0 & 1)); + if (i0 >= 0 && i0 <= 8191) { + STRHI(_jit, r1, r0, i0 >> 1); + } else if (i0 > -256 && i0 < 0) { + STURH(_jit, r1, r0, i0 & 0x1ff); + } else { + jit_gpr_t reg = get_temp_gpr(_jit); + addi(_jit, jit_gpr_regno(reg), r0, i0); + str_s(_jit, jit_gpr_regno(reg), r1); + unget_temp_gpr(_jit); + } } static void -_stxi_i(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) +stxi_i(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) { - int32_t reg; - assert(!(i0 & 3)); - if (i0 >= 0 && i0 <= 16383) - STRWI(r1, r0, i0 >> 2); - else if (i0 > -256 && i0 < 0) - STURW(r1, r0, i0 & 0x1ff); - else { - reg = jit_get_reg(jit_class_gpr); - addi(rn(reg), r0, i0); - str_i(rn(reg), r1); - jit_unget_reg(reg); - } + ASSERT(!(i0 & 3)); + if (i0 >= 0 && i0 <= 16383) { + STRWI(_jit, r1, r0, i0 >> 2); + } else if (i0 > -256 && i0 < 0) { + STURW(_jit, r1, r0, i0 & 0x1ff); + } else { + jit_gpr_t reg = get_temp_gpr(_jit); + addi(_jit, jit_gpr_regno(reg), r0, i0); + str_i(_jit, jit_gpr_regno(reg), r1); + unget_temp_gpr(_jit); + } } static void -_stxi_l(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) +stxi_l(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) { - int32_t reg; - assert(!(i0 & 7)); - if (i0 >= 0 && i0 <= 32767) - STRI(r1, r0, i0 >> 3); - else if (i0 > -256 && i0 < 0) - STUR(r1, r0, i0 & 0x1ff); - else { - reg = jit_get_reg(jit_class_gpr); - addi(rn(reg), r0, i0); - str_l(rn(reg), r1); - jit_unget_reg(reg); - } + ASSERT(!(i0 & 7)); + if (i0 >= 0 && i0 <= 32767) { + STRI(_jit, r1, r0, i0 >> 3); + } else if (i0 > -256 && i0 < 0) { + STUR(_jit, r1, r0, i0 & 0x1ff); + } else { + jit_gpr_t reg = get_temp_gpr(_jit); + addi(_jit, jit_gpr_regno(reg), r0, i0); + str_l(_jit, jit_gpr_regno(reg), r1); + unget_temp_gpr(_jit); + } +} + +static jit_reloc_t +mov_addr(jit_state_t *_jit, int32_t r0) +{ + return movi_from_pool(_jit, r0); +} + +static jit_reloc_t +beqi(jit_state_t *_jit, int32_t r0, jit_word_t i1) +{ + if (i1 == 0) { + return CBZ(_jit, r0); + } else { + return bcci(_jit, BCC_EQ, r0, i1); + } +} + +static jit_reloc_t +bnei(jit_state_t *_jit, int32_t r0, jit_word_t i1) +{ + if (i1 == 0) { + return CBNZ(_jit, r0); + } else { + return bcci(_jit, BCC_NE, r0, i1); + } +} + +static jit_reloc_t +jmp(jit_state_t *_jit) +{ + return B(_jit); } static void -_movr(jit_state_t *_jit, int32_t r0, int32_t r1) +jmpi(jit_state_t *_jit, jit_word_t i0) { - if (r0 != r1) - MOV(r0, r1); + return jit_patch_there(_jit, jmp(_jit), (void*)i0); +} + +static jit_reloc_t +call(jit_state_t *_jit) +{ + return BL(_jit); } static void -_movi(jit_state_t *_jit, int32_t r0, jit_word_t i0) +calli(jit_state_t *_jit, jit_word_t i0) { - jit_word_t n0, ibit, nbit; - n0 = ~i0; - ibit = nbit = 0; - if (i0 & 0x000000000000ffffL) ibit |= 1; - if (i0 & 0x00000000ffff0000L) ibit |= 2; - if (i0 & 0x0000ffff00000000L) ibit |= 4; - if (i0 & 0xffff000000000000L) ibit |= 8; - if (n0 & 0x000000000000ffffL) nbit |= 1; - if (n0 & 0x00000000ffff0000L) nbit |= 2; - if (n0 & 0x0000ffff00000000L) nbit |= 4; - if (n0 & 0xffff000000000000L) nbit |= 8; - switch (ibit) { - case 0: - MOVZ (r0, 0); - break; - case 1: - MOVZ (r0, i0 & 0xffff); - break; - case 2: - MOVZ_16(r0, (i0 >> 16) & 0xffff); - break; - case 3: - MOVZ (r0, i0 & 0xffff); - MOVK_16(r0, (i0 >> 16) & 0xffff); - break; - case 4: - MOVZ_32(r0, (i0 >> 32) & 0xffff); - break; - case 5: - MOVZ (r0, i0 & 0xffff); - MOVK_32(r0, (i0 >> 32) & 0xffff); - break; - case 6: - MOVZ_16(r0, (i0 >> 16) & 0xffff); - MOVK_32(r0, (i0 >> 32) & 0xffff); - break; - case 7: - if (nbit == 8) - MOVN_48(r0, (n0 >> 48) & 0xffff); - else { - MOVZ (r0, i0 & 0xffff); - MOVK_16(r0, (i0 >> 16) & 0xffff); - MOVK_32(r0, (i0 >> 32) & 0xffff); - } - break; - case 8: - MOVZ_48(r0, (i0 >> 48) & 0xffff); - break; - case 9: - MOVZ (r0, i0 & 0xffff); - MOVK_48(r0, (i0 >> 48) & 0xffff); - break; - case 10: - MOVZ_16(r0, (i0 >> 16) & 0xffff); - MOVK_48(r0, (i0 >> 48) & 0xffff); - break; - case 11: - if (nbit == 4) - MOVN_32(r0, (n0 >> 32) & 0xffff); - else { - MOVZ (r0, i0 & 0xffff); - MOVK_16(r0, (i0 >> 16) & 0xffff); - MOVK_48(r0, (i0 >> 48) & 0xffff); - } - break; - case 12: - MOVZ_32(r0, (i0 >> 32) & 0xffff); - MOVK_48(r0, (i0 >> 48) & 0xffff); - break; - case 13: - if (nbit == 2) - MOVN_16(r0, (n0 >> 16) & 0xffff); - else { - MOVZ (r0, i0 & 0xffff); - MOVK_32(r0, (i0 >> 32) & 0xffff); - MOVK_48(r0, (i0 >> 48) & 0xffff); - } - break; - case 14: - if (nbit == 1) - MOVN (r0, (n0) & 0xffff); - else { - MOVZ_16(r0, (i0 >> 16) & 0xffff); - MOVK_32(r0, (i0 >> 32) & 0xffff); - MOVK_48(r0, (i0 >> 48) & 0xffff); - } - break; - case 15: - if (nbit == 0) - MOVN (r0, 0); - else if (nbit == 1) - MOVN (r0, n0 & 0xffff); - else if (nbit == 8) - MOVN_48(r0, (n0 >> 48) & 0xffff); - else { - MOVZ (r0, i0 & 0xffff); - MOVK_16(r0, (i0 >> 16) & 0xffff); - MOVK_32(r0, (i0 >> 32) & 0xffff); - MOVK_48(r0, (i0 >> 48) & 0xffff); - } - break; - default: - abort(); - } -} - -static jit_word_t -_movi_p(jit_state_t *_jit, int32_t r0, jit_word_t i0) -{ - jit_word_t w; - w = _jit->pc.w; - MOVZ (r0, i0 & 0xffff); - MOVK_16(r0, (i0 >> 16) & 0xffff); - MOVK_32(r0, (i0 >> 32) & 0xffff); - MOVK_48(r0, (i0 >> 48) & 0xffff); - return (w); + return jit_patch_there(_jit, call(_jit), (void*)i0); } static void -_ccr(jit_state_t *_jit, int32_t cc, - int32_t r0, int32_t r1, int32_t r2) +ret(jit_state_t *_jit) { - CMP(r1, r2); - CSET(r0, cc); + RET(_jit); } static void -_cci(jit_state_t *_jit, int32_t cc, - int32_t r0, int32_t r1, jit_word_t i0) +retr(jit_state_t *_jit, int32_t r) { - int32_t reg; - jit_word_t is = i0 >> 12; - jit_word_t in = -i0; - jit_word_t iS = in >> 12; - if ( i0 >= 0 && i0 <= 0xfff) - CMPI (r1, i0); - else if ((is << 12) == i0 && is >= 0 && is <= 0xfff) - CMPI_12(r1, is); - else if ( in >= 0 && in <= 0xfff) - CMNI (r1, in); - else if ((iS << 12) == is && iS >= 0 && iS <= 0xfff) - CMNI_12(r1, iS); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - CMP(r1, rn(reg)); - jit_unget_reg(reg); - } - CSET(r0, cc); -} - -static jit_word_t -_bccr(jit_state_t *_jit, int32_t cc, - jit_word_t i0, int32_t r0, int32_t r1) -{ - jit_word_t w, d; - CMP(r0, r1); - w = _jit->pc.w; - d = (i0 - w) >> 2; - B_C(cc, d); - return (w); -} - -static jit_word_t -_bcci(jit_state_t *_jit, int32_t cc, - jit_word_t i0, int32_t r0, jit_word_t i1) -{ - int32_t reg; - jit_word_t w, d; - jit_word_t is = i1 >> 12; - jit_word_t in = -i1; - jit_word_t iS = in >> 12; - if ( i1 >= 0 && i1 <= 0xfff) - CMPI (r0, i1); - else if ((is << 12) == i0 && is >= 0 && is <= 0xfff) - CMPI_12(r0, is); - else if ( in >= 0 && in <= 0xfff) - CMNI (r0, in); - else if ((iS << 12) == is && iS >= 0 && iS <= 0xfff) - CMNI_12(r0, iS); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i1); - CMP(r0, rn(reg)); - jit_unget_reg(reg); - } - w = _jit->pc.w; - d = (i0 - w) >> 2; - B_C(cc, d); - return (w); -} - -static jit_word_t -_beqi(jit_state_t *_jit, jit_word_t i0, int32_t r0, jit_word_t i1) -{ - jit_word_t w; - if (i1 == 0) { - w = _jit->pc.w; - CBZ(r0, (i0 - w) >> 2); - } - else - w = bcci(BCC_EQ, i0, r0, i1); - return (w); -} - -static jit_word_t -_bnei(jit_state_t *_jit, jit_word_t i0, int32_t r0, jit_word_t i1) -{ - jit_word_t w; - if (i1 == 0) { - w = _jit->pc.w; - CBNZ(r0, (i0 - w) >> 2); - } - else - w = bcci(BCC_NE, i0, r0, i1); - return (w); -} - -static jit_word_t -_baddr(jit_state_t *_jit, int32_t cc, - jit_word_t i0, int32_t r0, int32_t r1) -{ - jit_word_t w; - addcr(r0, r0, r1); - w = _jit->pc.w; - B_C(cc, (i0 - w) >> 2); - return (w); -} - -static jit_word_t -_baddi(jit_state_t *_jit, int32_t cc, - jit_word_t i0, int32_t r0, jit_word_t i1) -{ - jit_word_t w; - addci(r0, r0, i1); - w = _jit->pc.w; - B_C(cc, (i0 - w) >> 2); - return (w); -} - -static jit_word_t -_bsubr(jit_state_t *_jit, int32_t cc, - jit_word_t i0, int32_t r0, int32_t r1) -{ - jit_word_t w; - subcr(r0, r0, r1); - w = _jit->pc.w; - B_C(cc, (i0 - w) >> 2); - return (w); -} - -static jit_word_t -_bsubi(jit_state_t *_jit, int32_t cc, - jit_word_t i0, int32_t r0, jit_word_t i1) -{ - jit_word_t w; - subci(r0, r0, i1); - w = _jit->pc.w; - B_C(cc, (i0 - w) >> 2); - return (w); -} - -static jit_word_t -_bmxr(jit_state_t *_jit, int32_t cc, - jit_word_t i0, int32_t r0, int32_t r1) -{ - jit_word_t w; - TST(r0, r1); - w = _jit->pc.w; - B_C(cc, (i0 - w) >> 2); - return (w); -} - -static jit_word_t -_bmxi(jit_state_t *_jit, int32_t cc, - jit_word_t i0, int32_t r0, jit_word_t i1) -{ - jit_word_t w; - int32_t reg; - int32_t imm; - imm = logical_immediate(i1); - if (imm != -1) - TSTI(r0, imm); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - TST(r0, rn(reg)); - jit_unget_reg(reg); - } - w = _jit->pc.w; - B_C(cc, (i0 - w) >> 2); - return (w); + movr(_jit, jit_gpr_regno(_X0), r); + ret(_jit); } static void -_jmpi(jit_state_t *_jit, jit_word_t i0) +reti(jit_state_t *_jit, int32_t i) { - jit_word_t w; - int32_t reg; - w = (i0 - _jit->pc.w) >> 2; - if (w >= -33554432 && w <= 33554431) - B(w); - else { - reg = jit_get_reg(jit_class_gpr|jit_class_nospill); - movi(rn(reg), i0); - jmpr(rn(reg)); - jit_unget_reg(reg); - } -} - -static jit_word_t -_jmpi_p(jit_state_t *_jit, jit_word_t i0) -{ - jit_word_t w; - int32_t reg; - reg = jit_get_reg(jit_class_gpr|jit_class_nospill); - w = movi_p(rn(reg), i0); - jmpr(rn(reg)); - jit_unget_reg(reg); - return (w); + movi(_jit, jit_gpr_regno(_X0), i); + ret(_jit); } static void -_calli(jit_state_t *_jit, jit_word_t i0) +retval_c(jit_state_t *_jit, int32_t r0) { - jit_word_t w; - int32_t reg; - w = (i0 - _jit->pc.w) >> 2; - if (w >= -33554432 && w <= 33554431) - BL(w); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - callr(rn(reg)); - jit_unget_reg(reg); - } -} - -static jit_word_t -_calli_p(jit_state_t *_jit, jit_word_t i0) -{ - jit_word_t w; - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - w = movi_p(rn(reg), i0); - callr(rn(reg)); - jit_unget_reg(reg); - return (w); -} - -/* - * prolog and epilog not as "optimized" as one would like, but the - * problem of overallocating stack space to save callee save registers - * exists on all ports, and is still a todo to use a variable - * stack_framesize - * value, what would cause needing to patch some calls, most likely - * the offset of jit_arg* of stack arguments. - */ -static void -_prolog(jit_state_t *_jit, jit_node_t *node) -{ - int32_t reg; - if (_jitc->function->define_frame || _jitc->function->assume_frame) { - int32_t frame = -_jitc->function->frame; - assert(_jitc->function->self.aoff >= frame); - if (_jitc->function->assume_frame) - return; - _jitc->function->self.aoff = frame; - } - if (_jitc->function->allocar) - _jitc->function->self.aoff &= -16; - _jitc->function->stack = ((_jitc->function->self.alen - - /* align stack at 16 bytes */ - _jitc->function->self.aoff) + 15) & -16; - STPI_POS(FP_REGNO, LR_REGNO, SP_REGNO, -(stack_framesize >> 3)); - MOV_XSP(FP_REGNO, SP_REGNO); -#define SPILL(L, R, O) \ - do { \ - if (jit_regset_tstbit(&_jitc->function->regset, _R##L)) { \ - if (jit_regset_tstbit(&_jitc->function->regset, _R##R)) \ - STPI(L, R, SP_REGNO, O); \ - else \ - STRI(L, SP_REGNO, O); \ - } \ - else if (jit_regset_tstbit(&_jitc->function->regset, _R##R)) \ - STRI(R, SP_REGNO, O + 1); \ - } while (0) - SPILL(19, 20, 2); - SPILL(21, 22, 4); - SPILL(23, 24, 6); - SPILL(25, 26, 8); - SPILL(27, 28, 10); -#undef SPILL -#define SPILL(R, O) \ - do { \ - if (jit_regset_tstbit(&_jitc->function->regset, _V##R)) \ - stxi_d(O, SP_REGNO, R); \ - } while (0) - SPILL( 8, 96); - SPILL( 9, 104); - SPILL(10, 112); - SPILL(11, 120); - SPILL(12, 128); - SPILL(13, 136); - SPILL(14, 144); - SPILL(15, 152); -#undef SPILL - if (_jitc->function->stack) - subi(SP_REGNO, SP_REGNO, _jitc->function->stack); - if (_jitc->function->allocar) { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), _jitc->function->self.aoff); - stxi_i(_jitc->function->aoffoff, FP_REGNO, rn(reg)); - jit_unget_reg(reg); - } - - if (_jitc->function->self.call & jit_call_varargs) { - /* Save gp registers in the save area, if any is a vararg */ - for (reg = 8 - _jitc->function->vagp / -8; - jit_arg_reg_p(reg); ++reg) - stxi(_jitc->function->vaoff + offsetof(jit_va_list_t, x0) + - reg * 8, FP_REGNO, rn(JIT_RA0 - reg)); - - for (reg = 8 - _jitc->function->vafp / -16; - jit_arg_f_reg_p(reg); ++reg) - /* Save fp registers in the save area, if any is a vararg */ - /* Note that the full 16 byte register is not saved, because - * lightning only handles float and double, and, while - * attempting to provide a va_list compatible pointer as - * jit_va_start return, does not guarantee it (on all ports). */ - stxi_d(_jitc->function->vaoff + offsetof(jit_va_list_t, q0) + - reg * 16 + offsetof(jit_qreg_t, l), FP_REGNO, rn(_V0 - reg)); - } + extr_c(_jit, r0, jit_gpr_regno(_X0)); } static void -_epilog(jit_state_t *_jit, jit_node_t *node) +retval_uc(jit_state_t *_jit, int32_t r0) { - if (_jitc->function->assume_frame) - return; - if (_jitc->function->stack) - MOV_XSP(SP_REGNO, FP_REGNO); -#define LOAD(L, R, O) \ - do { \ - if (jit_regset_tstbit(&_jitc->function->regset, _R##L)) { \ - if (jit_regset_tstbit(&_jitc->function->regset, _R##R)) \ - LDPI(L, R, SP_REGNO, O); \ - else \ - LDRI(L, SP_REGNO, O); \ - } \ - else if (jit_regset_tstbit(&_jitc->function->regset, _R##R)) \ - LDRI(R, SP_REGNO, O + 1); \ - } while (0) - LOAD(19, 20, 2); - LOAD(21, 22, 4); - LOAD(23, 24, 6); - LOAD(25, 26, 8); - LOAD(27, 28, 10); -#undef LOAD -#define LOAD(R, O) \ - do { \ - if (jit_regset_tstbit(&_jitc->function->regset, _V##R)) \ - ldxi_d(R, SP_REGNO, O); \ - } while (0) - LOAD( 8, 96); - LOAD( 9, 104); - LOAD(10, 112); - LOAD(11, 120); - LOAD(12, 128); - LOAD(13, 136); - LOAD(14, 144); - LOAD(15, 152); -#undef LOAD - LDPI_PRE(FP_REGNO, LR_REGNO, SP_REGNO, stack_framesize >> 3); - RET(); + extr_uc(_jit, r0, jit_gpr_regno(_X0)); } static void -_vastart(jit_state_t *_jit, int32_t r0) +retval_s(jit_state_t *_jit, int32_t r0) { - int32_t reg; - - assert(_jitc->function->self.call & jit_call_varargs); - - /* Return jit_va_list_t in the register argument */ - addi(r0, FP_REGNO, _jitc->function->vaoff); - - reg = jit_get_reg(jit_class_gpr); - - /* Initialize stack pointer to the first stack argument. */ - addi(rn(reg), FP_REGNO, _jitc->function->self.size); - stxi(offsetof(jit_va_list_t, stack), r0, rn(reg)); - - /* Initialize gp top pointer to the first stack argument. */ - addi(rn(reg), r0, va_gp_top_offset); - stxi(offsetof(jit_va_list_t, gptop), r0, rn(reg)); - - /* Initialize fp top pointer to the first stack argument. */ - addi(rn(reg), r0, va_fp_top_offset); - stxi(offsetof(jit_va_list_t, fptop), r0, rn(reg)); - - /* Initialize gp offset in the save area. */ - movi(rn(reg), _jitc->function->vagp); - stxi_i(offsetof(jit_va_list_t, gpoff), r0, rn(reg)); - - /* Initialize fp offset in the save area. */ - movi(rn(reg), _jitc->function->vafp); - stxi_i(offsetof(jit_va_list_t, fpoff), r0, rn(reg)); - - jit_unget_reg(reg); + extr_s(_jit, r0, jit_gpr_regno(_X0)); } static void -_vaarg(jit_state_t *_jit, int32_t r0, int32_t r1) +retval_us(jit_state_t *_jit, int32_t r0) { - jit_word_t ge_code; - jit_word_t lt_code; - int32_t rg0, rg1; - - assert(_jitc->function->self.call & jit_call_varargs); - - rg0 = jit_get_reg(jit_class_gpr); - rg1 = jit_get_reg(jit_class_gpr); - - /* Load the gp offset in save area in the first temporary. */ - ldxi_i(rn(rg0), r1, offsetof(jit_va_list_t, gpoff)); - - /* Jump over if there are no remaining arguments in the save area. */ - ge_code = bgei(_jit->pc.w, rn(rg0), 0); - - /* Load the gp save pointer in the second temporary. */ - ldxi(rn(rg1), r1, offsetof(jit_va_list_t, gptop)); - - /* Load the vararg argument in the first argument. */ - ldxr(r0, rn(rg1), rn(rg0)); - - /* Update the gp offset. */ - addi(rn(rg0), rn(rg0), 8); - stxi_i(offsetof(jit_va_list_t, gpoff), r1, rn(rg0)); - - /* Will only need one temporary register below. */ - jit_unget_reg(rg1); - - /* Jump over overflow code. */ - lt_code = jmpi_p(_jit->pc.w); - - /* Where to land if argument is in overflow area. */ - patch_at(ge_code, _jit->pc.w); - - /* Load stack pointer. */ - ldxi(rn(rg0), r1, offsetof(jit_va_list_t, stack)); - - /* Load argument. */ - ldr(r0, rn(rg0)); - - /* Update stack pointer. */ - addi(rn(rg0), rn(rg0), 8); - stxi(offsetof(jit_va_list_t, stack), r1, rn(rg0)); - - /* Where to land if argument is in gp save area. */ - patch_at(lt_code, _jit->pc.w); - - jit_unget_reg(rg0); + extr_us(_jit, r0, jit_gpr_regno(_X0)); } static void -_patch_at(jit_state_t *_jit, jit_word_t instr, jit_word_t label) +retval_i(jit_state_t *_jit, int32_t r0) { - instr_t i; - jit_word_t d; - int32_t fc, ff, ffc; - union { - int32_t *i; - jit_word_t w; - } u; - u.w = instr; - i.w = u.i[0]; - fc = i.w & 0xfc000000; - ff = i.w & 0xff000000; - ffc = i.w & 0xffc00000; - if (fc == A64_B || fc == A64_BL) { - d = (label - instr) >> 2; - assert(d >= -33554432 && d <= 33554431); - i.imm26.b = d; - u.i[0] = i.w; - } - else if (ff == A64_B_C || ff == (A64_CBZ|XS) || ff == (A64_CBNZ|XS)) { - d = (label - instr) >> 2; - assert(d >= -262148 && d <= 262143); - i.imm19.b = d; - u.i[0] = i.w; - } - else if (ffc == (A64_MOVZ|XS)) { - i.imm16.b = label; - u.i[0] = i.w; - i.w = u.i[1]; - assert((i.w & 0xffe00000) == (A64_MOVK|XS|MOVI_LSL_16)); - i.imm16.b = label >> 16; - u.i[1] = i.w; - i.w = u.i[2]; - assert((i.w & 0xffe00000) == (A64_MOVK|XS|MOVI_LSL_32)); - i.imm16.b = label >> 32; - u.i[2] = i.w; - i.w = u.i[3]; - assert((i.w & 0xffe00000) == (A64_MOVK|XS|MOVI_LSL_48)); - i.imm16.b = label >> 48; - u.i[3] = i.w; - } - else - abort(); + extr_i(_jit, r0, jit_gpr_regno(_X0)); +} + +static void +retval_ui(jit_state_t *_jit, int32_t r0) +{ + extr_ui(_jit, r0, jit_gpr_regno(_X0)); +} + +static void +retval_l(jit_state_t *_jit, int32_t r0) +{ + movr(_jit, r0, jit_gpr_regno(_X0)); +} + +static void +pushr(jit_state_t *_jit, int32_t r0) +{ + abort(); +} + +static void +popr(jit_state_t *_jit, int32_t r0) +{ + abort(); } -#endif diff --git a/lightening/aarch64-fpu.c b/lightening/aarch64-fpu.c index e1ccde65c..c55f9632f 100644 --- a/lightening/aarch64-fpu.c +++ b/lightening/aarch64-fpu.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2017 Free Software Foundation, Inc. + * Copyright (C) 2013-2019 Free Software Foundation, Inc. * * This file is part of GNU lightning. * @@ -14,901 +14,825 @@ * License for more details. * * Authors: - * Paulo Cesar Pereira de Andrade + * Paulo Cesar Pereira de Andrade */ -#if PROTO -# define A64_SCVTF 0x1e220000 -# define A64_FMOVWV 0x1e260000 -# define A64_FMOVVW 0x1e270000 -# define A64_FMOVXV 0x9e260000 -# define A64_FMOVVX 0x9e270000 -# define A64_FCVTZS 0x1e380000 -# define A64_FCMPE 0x1e202010 -# define A64_FMOV 0x1e204000 -# define A64_FABS 0x1e20c000 -# define A64_FNEG 0x1e214000 -# define A64_FSQRT 0x1e21c000 -# define A64_FCVTS 0x1e224000 -# define A64_FCVTD 0x1e22c000 -# define A64_FMUL 0x1e200800 -# define A64_FDIV 0x1e201800 -# define A64_FADD 0x1e202800 -# define A64_FSUB 0x1e203800 -# define FCMPES(Rn,Rm) os_vv(A64_FCMPE,0,Rn,Rm) -# define FCMPED(Rn,Rm) os_vv(A64_FCMPE,1,Rn,Rm) -# define FMOVS(Rd,Rn) osvv_(A64_FMOV,0,Rd,Rn) -# define FMOVD(Rd,Rn) osvv_(A64_FMOV,1,Rd,Rn) -# define FMOVWS(Rd,Rn) osvv_(A64_FMOVWV,0,Rd,Rn) -# define FMOVSW(Rd,Rn) osvv_(A64_FMOVVW,0,Rd,Rn) -# define FMOVXD(Rd,Rn) osvv_(A64_FMOVXV,1,Rd,Rn) -# define FMOVDX(Rd,Rn) osvv_(A64_FMOVVX,1,Rd,Rn) -# define FCVT_SD(Rd,Rn) osvv_(A64_FCVTS,1,Rd,Rn) -# define FCVT_DS(Rd,Rn) osvv_(A64_FCVTD,0,Rd,Rn) -# define SCVTFS(Rd,Rn) osvv_(A64_SCVTF|XS,0,Rd,Rn) -# define SCVTFD(Rd,Rn) osvv_(A64_SCVTF|XS,1,Rd,Rn) -# define FCVTSZ_WS(Rd,Rn) osvv_(A64_FCVTZS,0,Rd,Rn) -# define FCVTSZ_WD(Rd,Rn) osvv_(A64_FCVTZS,1,Rd,Rn) -# define FCVTSZ_XS(Rd,Rn) osvv_(A64_FCVTZS|XS,0,Rd,Rn) -# define FCVTSZ_XD(Rd,Rn) osvv_(A64_FCVTZS|XS,1,Rd,Rn) -# define FABSS(Rd,Rn) osvv_(A64_FABS,0,Rd,Rn) -# define FABSD(Rd,Rn) osvv_(A64_FABS,1,Rd,Rn) -# define FNEGS(Rd,Rn) osvv_(A64_FNEG,0,Rd,Rn) -# define FNEGD(Rd,Rn) osvv_(A64_FNEG,1,Rd,Rn) -# define FSQRTS(Rd,Rn) osvv_(A64_FSQRT,0,Rd,Rn) -# define FSQRTD(Rd,Rn) osvv_(A64_FSQRT,1,Rd,Rn) -# define FADDS(Rd,Rn,Rm) osvvv(A64_FADD,0,Rd,Rn,Rm) -# define FADDD(Rd,Rn,Rm) osvvv(A64_FADD,1,Rd,Rn,Rm) -# define FSUBS(Rd,Rn,Rm) osvvv(A64_FSUB,0,Rd,Rn,Rm) -# define FSUBD(Rd,Rn,Rm) osvvv(A64_FSUB,1,Rd,Rn,Rm) -# define FMULS(Rd,Rn,Rm) osvvv(A64_FMUL,0,Rd,Rn,Rm) -# define FMULD(Rd,Rn,Rm) osvvv(A64_FMUL,1,Rd,Rn,Rm) -# define FDIVS(Rd,Rn,Rm) osvvv(A64_FDIV,0,Rd,Rn,Rm) -# define FDIVD(Rd,Rn,Rm) osvvv(A64_FDIV,1,Rd,Rn,Rm) -# define osvvv(Op,Sz,Rd,Rn,Rm) _osvvv(_jit,Op,Sz,Rd,Rn,Rm) -static void _osvvv(jit_state_t*,int32_t,int32_t, - int32_t,int32_t,int32_t); -# define osvv_(Op,Sz,Rd,Rn) _osvv_(_jit,Op,Sz,Rd,Rn) -static void _osvv_(jit_state_t*,int32_t, - int32_t,int32_t,int32_t); -# define os_vv(Op,Sz,Rn,Rm) _os_vv(_jit,Op,Sz,Rn,Rm) -static void _os_vv(jit_state_t*,int32_t, - int32_t,int32_t,int32_t); -# define truncr_f_i(r0,r1) _truncr_f_i(_jit,r0,r1) -static void _truncr_f_i(jit_state_t*,int32_t,int32_t); -# define truncr_f_l(r0,r1) FCVTSZ_XS(r0,r1) -# define truncr_d_i(r0,r1) _truncr_d_i(_jit,r0,r1) -static void _truncr_d_i(jit_state_t*,int32_t,int32_t); -# define truncr_d_l(r0,r1) FCVTSZ_XD(r0,r1) -# define addr_f(r0,r1,r2) FADDS(r0,r1,r2) -# define addi_f(r0,r1,i0) _addi_f(_jit,r0,r1,i0) -static void _addi_f(jit_state_t*,int32_t,int32_t,jit_float32_t); -# define subr_f(r0,r1,r2) FSUBS(r0,r1,r2) -# define subi_f(r0,r1,i0) _subi_f(_jit,r0,r1,i0) -static void _subi_f(jit_state_t*,int32_t,int32_t,jit_float32_t); -# define rsbr_f(r0, r1, r2) subr_f(r0, r2, r1) -# define rsbi_f(r0, r1, i0) _rsbi_f(_jit, r0, r1, i0) -static void _rsbi_f(jit_state_t*,int32_t,int32_t,jit_float32_t); -# define mulr_f(r0,r1,r2) FMULS(r0,r1,r2) -# define muli_f(r0,r1,i0) _muli_f(_jit,r0,r1,i0) -static void _muli_f(jit_state_t*,int32_t,int32_t,jit_float32_t); -# define divr_f(r0,r1,r2) FDIVS(r0,r1,r2) -# define divi_f(r0,r1,i0) _divi_f(_jit,r0,r1,i0) -static void _divi_f(jit_state_t*,int32_t,int32_t,jit_float32_t); -# define absr_f(r0,r1) FABSS(r0,r1) -# define negr_f(r0,r1) FNEGS(r0,r1) -# define sqrtr_f(r0,r1) FSQRTS(r0,r1) -# define extr_f(r0,r1) SCVTFS(r0,r1) -# define ldr_f(r0,r1) _ldr_f(_jit,r0,r1) -static void _ldr_f(jit_state_t*,int32_t,int32_t); -# define ldi_f(r0,i0) _ldi_f(_jit,r0,i0) -static void _ldi_f(jit_state_t*,int32_t,jit_word_t); -# define ldxr_f(r0,r1,r2) _ldxr_f(_jit,r0,r1,r2) -static void _ldxr_f(jit_state_t*,int32_t,int32_t,int32_t); -# define ldxi_f(r0,r1,i0) _ldxi_f(_jit,r0,r1,i0) -static void _ldxi_f(jit_state_t*,int32_t,int32_t,jit_word_t); -# define str_f(r0,r1) _str_f(_jit,r0,r1) -static void _str_f(jit_state_t*,int32_t,int32_t); -# define sti_f(i0,r0) _sti_f(_jit,i0,r0) -static void _sti_f(jit_state_t*,jit_word_t,int32_t); -# define stxr_f(r0,r1,r2) _stxr_f(_jit,r0,r1,r2) -static void _stxr_f(jit_state_t*,int32_t,int32_t,int32_t); -# define stxi_f(i0,r0,r1) _stxi_f(_jit,i0,r0,r1) -static void _stxi_f(jit_state_t*,jit_word_t,int32_t,int32_t); -# define movr_f(r0,r1) _movr_f(_jit,r0,r1) -static void _movr_f(jit_state_t*,int32_t,int32_t); -# define movi_f(r0,i0) _movi_f(_jit,r0,i0) -static void _movi_f(jit_state_t*,int32_t,jit_float32_t); -# define extr_d_f(r0,r1) FCVT_SD(r0,r1) -# define fccr(cc,r0,r1,r2) _fccr(_jit,cc,r0,r1,r2) -static void _fccr(jit_state_t*,int32_t,int32_t,int32_t,int32_t); -# define fcci(cc,r0,r1,i0) _fcci(_jit,cc,r0,r1,i0) -static void _fcci(jit_state_t*, - int32_t,int32_t,int32_t,jit_float32_t); -# define ltr_f(r0,r1,r2) fccr(CC_MI,r0,r1,r2) -# define lti_f(r0,r1,i0) fcci(CC_MI,r0,r1,i0) -# define ler_f(r0,r1,r2) fccr(CC_LS,r0,r1,r2) -# define lei_f(r0,r1,i0) fcci(CC_LS,r0,r1,i0) -# define eqr_f(r0,r1,r2) fccr(CC_EQ,r0,r1,r2) -# define eqi_f(r0,r1,i0) fcci(CC_EQ,r0,r1,i0) -# define ger_f(r0,r1,r2) fccr(CC_GE,r0,r1,r2) -# define gei_f(r0,r1,i0) fcci(CC_GE,r0,r1,i0) -# define gtr_f(r0,r1,r2) fccr(CC_GT,r0,r1,r2) -# define gti_f(r0,r1,i0) fcci(CC_GT,r0,r1,i0) -# define ner_f(r0,r1,r2) fccr(CC_NE,r0,r1,r2) -# define nei_f(r0,r1,i0) fcci(CC_NE,r0,r1,i0) -# define unltr_f(r0,r1,r2) fccr(CC_LT,r0,r1,r2) -# define unlti_f(r0,r1,i0) fcci(CC_LT,r0,r1,i0) -# define unler_f(r0,r1,r2) fccr(CC_LE,r0,r1,r2) -# define unlei_f(r0,r1,i0) fcci(CC_LE,r0,r1,i0) -# define uneqr_f(r0,r1,r2) _uneqr_f(_jit,r0,r1,r2) -static void _uneqr_f(jit_state_t*,int32_t,int32_t,int32_t); -# define uneqi_f(r0,r1,i0) _uneqi_f(_jit,r0,r1,i0) -static void _uneqi_f(jit_state_t*,int32_t,int32_t,jit_float32_t); -# define unger_f(r0,r1,r2) fccr(CC_PL,r0,r1,r2) -# define ungei_f(r0,r1,i0) fcci(CC_PL,r0,r1,i0) -# define ungtr_f(r0,r1,r2) fccr(CC_HI,r0,r1,r2) -# define ungti_f(r0,r1,i0) fcci(CC_HI,r0,r1,i0) -# define ltgtr_f(r0,r1,r2) _ltgtr_f(_jit,r0,r1,r2) -static void _ltgtr_f(jit_state_t*,int32_t,int32_t,int32_t); -# define ltgti_f(r0,r1,i0) _ltgti_f(_jit,r0,r1,i0) -static void _ltgti_f(jit_state_t*,int32_t,int32_t,jit_float32_t); -# define ordr_f(r0,r1,r2) fccr(CC_VC,r0,r1,r2) -# define ordi_f(r0,r1,i0) fcci(CC_VC,r0,r1,i0) -# define unordr_f(r0,r1,r2) fccr(CC_VS,r0,r1,r2) -# define unordi_f(r0,r1,i0) fcci(CC_VS,r0,r1,i0) -#define fbccr(cc,i0,r0,r1) _fbccr(_jit,cc,i0,r0,r1) -static jit_word_t -_fbccr(jit_state_t*,int32_t,jit_word_t,int32_t,int32_t); -#define fbcci(cc,i0,r0,i1) _fbcci(_jit,cc,i0,r0,i1) -static jit_word_t -_fbcci(jit_state_t*,int32_t,jit_word_t,int32_t,jit_float32_t); -# define bltr_f(i0,r0,r1) fbccr(BCC_MI,i0,r0,r1) -# define blti_f(i0,r0,i1) fbcci(BCC_MI,i0,r0,i1) -# define bler_f(i0,r0,r1) fbccr(BCC_LS,i0,r0,r1) -# define blei_f(i0,r0,i1) fbcci(BCC_LS,i0,r0,i1) -# define beqr_f(i0,r0,r1) fbccr(BCC_EQ,i0,r0,r1) -# define beqi_f(i0,r0,i1) fbcci(BCC_EQ,i0,r0,i1) -# define bger_f(i0,r0,r1) fbccr(BCC_GE,i0,r0,r1) -# define bgei_f(i0,r0,i1) fbcci(BCC_GE,i0,r0,i1) -# define bgtr_f(i0,r0,r1) fbccr(BCC_GT,i0,r0,r1) -# define bgti_f(i0,r0,i1) fbcci(BCC_GT,i0,r0,i1) -# define bner_f(i0,r0,r1) fbccr(BCC_NE,i0,r0,r1) -# define bnei_f(i0,r0,i1) fbcci(BCC_NE,i0,r0,i1) -# define bunltr_f(i0,r0,r1) fbccr(BCC_LT,i0,r0,r1) -# define bunlti_f(i0,r0,i1) fbcci(BCC_LT,i0,r0,i1) -# define bunler_f(i0,r0,r1) fbccr(BCC_LE,i0,r0,r1) -# define bunlei_f(i0,r0,i1) fbcci(BCC_LE,i0,r0,i1) -# define buneqr_f(i0,r0,r1) _buneqr_f(_jit,i0,r0,r1) -static jit_word_t _buneqr_f(jit_state_t*,jit_word_t,int32_t,int32_t); -# define buneqi_f(i0,r0,i1) _buneqi_f(_jit,i0,r0,i1) -static jit_word_t _buneqi_f(jit_state_t*,jit_word_t,int32_t,jit_float32_t); -# define bunger_f(i0,r0,r1) fbccr(BCC_PL,i0,r0,r1) -# define bungei_f(i0,r0,i1) fbcci(BCC_PL,i0,r0,i1) -# define bungtr_f(i0,r0,r1) fbccr(BCC_HI,i0,r0,r1) -# define bungti_f(i0,r0,i1) fbcci(BCC_HI,i0,r0,i1) -# define bltgtr_f(i0,r0,r1) _bltgtr_f(_jit,i0,r0,r1) -static jit_word_t _bltgtr_f(jit_state_t*,jit_word_t,int32_t,int32_t); -# define bltgti_f(i0,r0,i1) _bltgti_f(_jit,i0,r0,i1) -static jit_word_t _bltgti_f(jit_state_t*,jit_word_t,int32_t,jit_float32_t); -# define bordr_f(i0,r0,r1) fbccr(BCC_VC,i0,r0,r1) -# define bordi_f(i0,r0,i1) fbcci(BCC_VC,i0,r0,i1) -# define bunordr_f(i0,r0,r1) fbccr(BCC_VS,i0,r0,r1) -# define bunordi_f(i0,r0,i1) fbcci(BCC_VS,i0,r0,i1) -# define addr_d(r0,r1,r2) FADDD(r0,r1,r2) -# define addi_d(r0,r1,i0) _addi_d(_jit,r0,r1,i0) -static void _addi_d(jit_state_t*,int32_t,int32_t,jit_float64_t); -# define subr_d(r0,r1,r2) FSUBD(r0,r1,r2) -# define subi_d(r0,r1,i0) _subi_d(_jit,r0,r1,i0) -static void _subi_d(jit_state_t*,int32_t,int32_t,jit_float64_t); -# define rsbr_d(r0, r1, r2) subr_d(r0, r2, r1) -# define rsbi_d(r0, r1, i0) _rsbi_d(_jit, r0, r1, i0) -static void _rsbi_d(jit_state_t*,int32_t,int32_t,jit_float64_t); -# define mulr_d(r0,r1,r2) FMULD(r0,r1,r2) -# define muli_d(r0,r1,i0) _muli_d(_jit,r0,r1,i0) -static void _muli_d(jit_state_t*,int32_t,int32_t,jit_float64_t); -# define divr_d(r0,r1,r2) FDIVD(r0,r1,r2) -# define divi_d(r0,r1,i0) _divi_d(_jit,r0,r1,i0) -static void _divi_d(jit_state_t*,int32_t,int32_t,jit_float64_t); -# define absr_d(r0,r1) FABSD(r0,r1) -# define negr_d(r0,r1) FNEGD(r0,r1) -# define sqrtr_d(r0,r1) FSQRTD(r0,r1) -# define extr_d(r0,r1) SCVTFD(r0,r1) -# define ldr_d(r0,r1) _ldr_d(_jit,r0,r1) -static void _ldr_d(jit_state_t*,int32_t,int32_t); -# define ldi_d(r0,i0) _ldi_d(_jit,r0,i0) -static void _ldi_d(jit_state_t*,int32_t,jit_word_t); -# define ldxr_d(r0,r1,r2) _ldxr_d(_jit,r0,r1,r2) -static void _ldxr_d(jit_state_t*,int32_t,int32_t,int32_t); -# define ldxi_d(r0,r1,i0) _ldxi_d(_jit,r0,r1,i0) -static void _ldxi_d(jit_state_t*,int32_t,int32_t,jit_word_t); -# define str_d(r0,r1) _str_d(_jit,r0,r1) -static void _str_d(jit_state_t*,int32_t,int32_t); -# define sti_d(i0,r0) _sti_d(_jit,i0,r0) -static void _sti_d(jit_state_t*,jit_word_t,int32_t); -# define stxr_d(r0,r1,r2) _stxr_d(_jit,r0,r1,r2) -static void _stxr_d(jit_state_t*,int32_t,int32_t,int32_t); -# define stxi_d(i0,r0,r1) _stxi_d(_jit,i0,r0,r1) -static void _stxi_d(jit_state_t*,jit_word_t,int32_t,int32_t); -# define movr_d(r0,r1) _movr_d(_jit,r0,r1) -static void _movr_d(jit_state_t*,int32_t,int32_t); -# define movi_d(r0,i0) _movi_d(_jit,r0,i0) -static void _movi_d(jit_state_t*,int32_t,jit_float64_t); -# define extr_f_d(r0,r1) FCVT_DS(r0,r1) -# define dccr(cc,r0,r1,r2) _dccr(_jit,cc,r0,r1,r2) -static void _dccr(jit_state_t*,int32_t,int32_t,int32_t,int32_t); -# define dcci(cc,r0,r1,i0) _dcci(_jit,cc,r0,r1,i0) -static void _dcci(jit_state_t*, - int32_t,int32_t,int32_t,jit_float64_t); -# define ltr_d(r0,r1,r2) dccr(CC_MI,r0,r1,r2) -# define lti_d(r0,r1,i0) dcci(CC_MI,r0,r1,i0) -# define ler_d(r0,r1,r2) dccr(CC_LS,r0,r1,r2) -# define lei_d(r0,r1,i0) dcci(CC_LS,r0,r1,i0) -# define eqr_d(r0,r1,r2) dccr(CC_EQ,r0,r1,r2) -# define eqi_d(r0,r1,i0) dcci(CC_EQ,r0,r1,i0) -# define ger_d(r0,r1,r2) dccr(CC_GE,r0,r1,r2) -# define gei_d(r0,r1,i0) dcci(CC_GE,r0,r1,i0) -# define gtr_d(r0,r1,r2) dccr(CC_GT,r0,r1,r2) -# define gti_d(r0,r1,i0) dcci(CC_GT,r0,r1,i0) -# define ner_d(r0,r1,r2) dccr(CC_NE,r0,r1,r2) -# define nei_d(r0,r1,i0) dcci(CC_NE,r0,r1,i0) -# define unltr_d(r0,r1,r2) dccr(CC_LT,r0,r1,r2) -# define unlti_d(r0,r1,i0) dcci(CC_LT,r0,r1,i0) -# define unler_d(r0,r1,r2) dccr(CC_LE,r0,r1,r2) -# define unlei_d(r0,r1,i0) dcci(CC_LE,r0,r1,i0) -# define uneqr_d(r0,r1,r2) _uneqr_d(_jit,r0,r1,r2) -static void _uneqr_d(jit_state_t*,int32_t,int32_t,int32_t); -# define uneqi_d(r0,r1,i0) _uneqi_d(_jit,r0,r1,i0) -static void _uneqi_d(jit_state_t*,int32_t,int32_t,jit_float64_t); -# define unger_d(r0,r1,r2) dccr(CC_PL,r0,r1,r2) -# define ungei_d(r0,r1,i0) dcci(CC_PL,r0,r1,i0) -# define ungtr_d(r0,r1,r2) dccr(CC_HI,r0,r1,r2) -# define ungti_d(r0,r1,i0) dcci(CC_HI,r0,r1,i0) -# define ltgtr_d(r0,r1,r2) _ltgtr_d(_jit,r0,r1,r2) -static void _ltgtr_d(jit_state_t*,int32_t,int32_t,int32_t); -# define ltgti_d(r0,r1,i0) _ltgti_d(_jit,r0,r1,i0) -static void _ltgti_d(jit_state_t*,int32_t,int32_t,jit_float64_t); -# define ordr_d(r0,r1,r2) dccr(CC_VC,r0,r1,r2) -# define ordi_d(r0,r1,i0) dcci(CC_VC,r0,r1,i0) -# define unordr_d(r0,r1,r2) dccr(CC_VS,r0,r1,r2) -# define unordi_d(r0,r1,i0) dcci(CC_VS,r0,r1,i0) -#define dbccr(cc,i0,r0,r1) _dbccr(_jit,cc,i0,r0,r1) -static jit_word_t -_dbccr(jit_state_t*,int32_t,jit_word_t,int32_t,int32_t); -#define dbcci(cc,i0,r0,i1) _dbcci(_jit,cc,i0,r0,i1) -static jit_word_t -_dbcci(jit_state_t*,int32_t,jit_word_t,int32_t,jit_float64_t); -# define bltr_d(i0,r0,r1) dbccr(BCC_MI,i0,r0,r1) -# define blti_d(i0,r0,i1) dbcci(BCC_MI,i0,r0,i1) -# define bler_d(i0,r0,r1) dbccr(BCC_LS,i0,r0,r1) -# define blei_d(i0,r0,i1) dbcci(BCC_LS,i0,r0,i1) -# define beqr_d(i0,r0,r1) dbccr(BCC_EQ,i0,r0,r1) -# define beqi_d(i0,r0,i1) dbcci(BCC_EQ,i0,r0,i1) -# define bger_d(i0,r0,r1) dbccr(BCC_GE,i0,r0,r1) -# define bgei_d(i0,r0,i1) dbcci(BCC_GE,i0,r0,i1) -# define bgtr_d(i0,r0,r1) dbccr(BCC_GT,i0,r0,r1) -# define bgti_d(i0,r0,i1) dbcci(BCC_GT,i0,r0,i1) -# define bner_d(i0,r0,r1) dbccr(BCC_NE,i0,r0,r1) -# define bnei_d(i0,r0,i1) dbcci(BCC_NE,i0,r0,i1) -# define bunltr_d(i0,r0,r1) dbccr(BCC_LT,i0,r0,r1) -# define bunlti_d(i0,r0,i1) dbcci(BCC_LT,i0,r0,i1) -# define bunler_d(i0,r0,r1) dbccr(BCC_LE,i0,r0,r1) -# define bunlei_d(i0,r0,i1) dbcci(BCC_LE,i0,r0,i1) -# define buneqr_d(i0,r0,r1) _buneqr_d(_jit,i0,r0,r1) -static jit_word_t _buneqr_d(jit_state_t*,jit_word_t,int32_t,int32_t); -# define buneqi_d(i0,r0,i1) _buneqi_d(_jit,i0,r0,i1) -static jit_word_t _buneqi_d(jit_state_t*,jit_word_t,int32_t,jit_float64_t); -# define bunger_d(i0,r0,r1) dbccr(BCC_PL,i0,r0,r1) -# define bungei_d(i0,r0,i1) dbcci(BCC_PL,i0,r0,i1) -# define bungtr_d(i0,r0,r1) dbccr(BCC_HI,i0,r0,r1) -# define bungti_d(i0,r0,i1) dbcci(BCC_HI,i0,r0,i1) -# define bltgtr_d(i0,r0,r1) _bltgtr_d(_jit,i0,r0,r1) -static jit_word_t _bltgtr_d(jit_state_t*,jit_word_t,int32_t,int32_t); -# define bltgti_d(i0,r0,i1) _bltgti_d(_jit,i0,r0,i1) -static jit_word_t _bltgti_d(jit_state_t*,jit_word_t,int32_t,jit_float64_t); -# define bordr_d(i0,r0,r1) dbccr(BCC_VC,i0,r0,r1) -# define bordi_d(i0,r0,i1) dbcci(BCC_VC,i0,r0,i1) -# define bunordr_d(i0,r0,r1) dbccr(BCC_VS,i0,r0,r1) -# define bunordi_d(i0,r0,i1) dbcci(BCC_VS,i0,r0,i1) -# define vaarg_d(r0, r1) _vaarg_d(_jit, r0, r1) -static void _vaarg_d(jit_state_t*, int32_t, int32_t); -#endif - -#if CODE static void -_osvvv(jit_state_t *_jit, int32_t Op, int32_t Sz, - int32_t Rd, int32_t Rn, int32_t Rm) +osvvv(jit_state_t *_jit, int32_t Op, int32_t Sz, int32_t Rd, int32_t Rn, + int32_t Rm) { - instr_t i; - assert(!(Rd & ~0x1f)); - assert(!(Rn & ~0x1f)); - assert(!(Rm & ~0x1f)); - assert(!(Sz & ~0x3)); - assert(!(Op & ~0xffe0fc00)); - i.w = Op; - i.size.b = Sz; - i.Rd.b = Rd; - i.Rn.b = Rn; - i.Rm.b = Rm; - ii(i.w); + ASSERT(!(Rd & ~0x1f)); + ASSERT(!(Rn & ~0x1f)); + ASSERT(!(Rm & ~0x1f)); + ASSERT(!(Sz & ~0x3)); + ASSERT(!(Op & ~0xffe0fc00)); + instr_t i; + i.w = Op; + i.size.b = Sz; + i.Rd.b = Rd; + i.Rn.b = Rn; + i.Rm.b = Rm; + emit_u32(_jit, i.w); } static void -_osvv_(jit_state_t *_jit, int32_t Op, - int32_t Sz, int32_t Rd, int32_t Rn) +osvv_(jit_state_t *_jit, int32_t Op, int32_t Sz, int32_t Rd, int32_t Rn) { - instr_t i; - assert(!(Rd & ~0x1f)); - assert(!(Rn & ~0x1f)); - assert(!(Sz & ~0x3)); - assert(!(Op & ~0xfffffc00)); - i.w = Op; - i.size.b = Sz; - i.Rd.b = Rd; - i.Rn.b = Rn; - ii(i.w); + ASSERT(!(Rd & ~0x1f)); + ASSERT(!(Rn & ~0x1f)); + ASSERT(!(Sz & ~0x3)); + ASSERT(!(Op & ~0xfffffc00)); + instr_t i; + i.w = Op; + i.size.b = Sz; + i.Rd.b = Rd; + i.Rn.b = Rn; + emit_u32(_jit, i.w); } static void -_os_vv(jit_state_t *_jit, int32_t Op, - int32_t Sz, int32_t Rn, int32_t Rm) +os_vv(jit_state_t *_jit, int32_t Op, int32_t Sz, int32_t Rn, int32_t Rm) { - instr_t i; - assert(!(Rn & ~0x1f)); - assert(!(Rm & ~0x1f)); - assert(!(Sz & ~0x3)); - assert(!(Op & ~0xff20fc1f)); - i.w = Op; - i.size.b = Sz; - i.Rn.b = Rn; - i.Rm.b = Rm; - ii(i.w); + ASSERT(!(Rn & ~0x1f)); + ASSERT(!(Rm & ~0x1f)); + ASSERT(!(Sz & ~0x3)); + ASSERT(!(Op & ~0xff20fc1f)); + instr_t i; + i.w = Op; + i.size.b = Sz; + i.Rn.b = Rn; + i.Rm.b = Rm; + emit_u32(_jit, i.w); } -#define fopi(name) \ -static void \ -_##name##i_f(jit_state_t *_jit, \ - int32_t r0, int32_t r1, jit_float32_t i0) \ -{ \ - int32_t reg = jit_get_reg(jit_class_fpr); \ - movi_f(rn(reg), i0); \ - name##r_f(r0, r1, rn(reg)); \ - jit_unget_reg(reg); \ -} -#define dopi(name) \ -static void \ -_##name##i_d(jit_state_t *_jit, \ - int32_t r0, int32_t r1, jit_float64_t i0) \ -{ \ - int32_t reg = jit_get_reg(jit_class_fpr); \ - movi_d(rn(reg), i0); \ - name##r_d(r0, r1, rn(reg)); \ - jit_unget_reg(reg); \ -} -#define fbopi(name) \ -static jit_word_t \ -_b##name##i_f(jit_state_t *_jit, \ - jit_word_t i0, int32_t r0, jit_float32_t i1) \ -{ \ - jit_word_t word; \ - int32_t reg = jit_get_reg(jit_class_fpr| \ - jit_class_nospill); \ - movi_f(rn(reg), i1); \ - word = b##name##r_f(i0, r0, rn(reg)); \ - jit_unget_reg(reg); \ - return (word); \ -} -#define dbopi(name) \ -static jit_word_t \ -_b##name##i_d(jit_state_t *_jit, \ - jit_word_t i0, int32_t r0, jit_float64_t i1) \ -{ \ - jit_word_t word; \ - int32_t reg = jit_get_reg(jit_class_fpr| \ - jit_class_nospill); \ - movi_d(rn(reg), i1); \ - word = b##name##r_d(i0, r0, rn(reg)); \ - jit_unget_reg(reg); \ - return (word); \ +#define A64_SCVTF 0x1e220000 +#define A64_FMOVWV 0x1e260000 +#define A64_FMOVVW 0x1e270000 +#define A64_FMOVXV 0x9e260000 +#define A64_FMOVVX 0x9e270000 +#define A64_FCVTZS 0x1e380000 +#define A64_FCMPE 0x1e202010 +#define A64_FMOV 0x1e204000 +#define A64_FABS 0x1e20c000 +#define A64_FNEG 0x1e214000 +#define A64_FSQRT 0x1e21c000 +#define A64_FCVTS 0x1e224000 +#define A64_FCVTD 0x1e22c000 +#define A64_FMUL 0x1e200800 +#define A64_FDIV 0x1e201800 +#define A64_FADD 0x1e202800 +#define A64_FSUB 0x1e203800 + +static void +FCMPES(jit_state_t *_jit, int32_t Rn, int32_t Rm) +{ + os_vv(_jit, A64_FCMPE, 0, Rn, Rm); } static void -_truncr_f_i(jit_state_t *_jit, int32_t r0, int32_t r1) +FCMPED(jit_state_t *_jit, int32_t Rn, int32_t Rm) { - FCVTSZ_WS(r0, r1); - extr_i(r0, r0); + os_vv(_jit, A64_FCMPE, 1, Rn, Rm); } static void -_truncr_d_i(jit_state_t *_jit, int32_t r0, int32_t r1) +FMOVS(jit_state_t *_jit, int32_t Rd, int32_t Rn) { - FCVTSZ_WD(r0, r1); - extr_i(r0, r0); -} - -fopi(add) -fopi(sub) -fopi(rsb) -fopi(mul) -fopi(div) - -static void -_ldr_f(jit_state_t *_jit, int32_t r0, int32_t r1) -{ - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - ldr_i(rn(reg), r1); - FMOVSW(r0, rn(reg)); - jit_unget_reg(reg); + osvv_(_jit, A64_FMOV, 0, Rd, Rn); } static void -_ldi_f(jit_state_t *_jit, int32_t r0, jit_word_t i0) +FMOVD(jit_state_t *_jit, int32_t Rd, int32_t Rn) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - ldi_i(rn(reg), i0); - FMOVSW(r0, rn(reg)); - jit_unget_reg(reg); + osvv_(_jit, A64_FMOV, 1, Rd, Rn); } static void -_ldxr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +FMOVWS(jit_state_t *_jit, int32_t Rd, int32_t Rn) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - ldxr_i(rn(reg), r1, r2); - FMOVSW(r0, rn(reg)); - jit_unget_reg(reg); + osvv_(_jit, A64_FMOVWV, 0, Rd, Rn); } static void -_ldxi_f(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +FMOVSW(jit_state_t *_jit, int32_t Rd, int32_t Rn) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - ldxi_i(rn(reg), r1, i0); - FMOVSW(r0, rn(reg)); - jit_unget_reg(reg); + osvv_(_jit, A64_FMOVVW, 0, Rd, Rn); } static void -_str_f(jit_state_t *_jit, int32_t r0, int32_t r1) +FMOVXD(jit_state_t *_jit, int32_t Rd, int32_t Rn) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - FMOVWS(rn(reg), r1); - str_i(r0, rn(reg)); - jit_unget_reg(reg); + osvv_(_jit, A64_FMOVXV, 1, Rd, Rn); } static void -_sti_f(jit_state_t *_jit, jit_word_t i0, int32_t r0) +FMOVDX(jit_state_t *_jit, int32_t Rd, int32_t Rn) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - FMOVWS(rn(reg), r0); - sti_i(i0, rn(reg)); - jit_unget_reg(reg); + osvv_(_jit, A64_FMOVVX, 1, Rd, Rn); } static void -_stxr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +FCVT_SD(jit_state_t *_jit, int32_t Rd, int32_t Rn) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - FMOVWS(rn(reg), r2); - stxr_i(r0, r1, rn(reg)); - jit_unget_reg(reg); + osvv_(_jit, A64_FCVTS, 1, Rd, Rn); } static void -_stxi_f(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) +FCVT_DS(jit_state_t *_jit, int32_t Rd, int32_t Rn) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - FMOVWS(rn(reg), r1); - stxi_i(i0, r0, rn(reg)); - jit_unget_reg(reg); + osvv_(_jit, A64_FCVTD, 0, Rd, Rn); } static void -_movr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +SCVTFS(jit_state_t *_jit, int32_t Rd, int32_t Rn) { - if (r0 != r1) - FMOVS(r0, r1); + osvv_(_jit, A64_SCVTF|XS, 0, Rd, Rn); } static void -_movi_f(jit_state_t *_jit, int32_t r0, jit_float32_t i0) +SCVTFD(jit_state_t *_jit, int32_t Rd, int32_t Rn) { - union { - int32_t i; - jit_float32_t f; - } u; - int32_t reg; - u.f = i0; - if (u.i == 0) - FMOVSW(r0, WZR_REGNO); - else { - reg = jit_get_reg(jit_class_gpr); - /* prevent generating unused top 32 bits */ - movi(rn(reg), ((jit_word_t)u.i) & 0xffffffff); - FMOVSW(r0, rn(reg)); - jit_unget_reg(reg); - } + osvv_(_jit, A64_SCVTF|XS, 1, Rd, Rn); } static void -_fccr(jit_state_t *_jit, int32_t cc, - int32_t r0, int32_t r1, int32_t r2) +FCVTSZ_WS(jit_state_t *_jit, int32_t Rd, int32_t Rn) { - FCMPES(r1, r2); - CSET(r0, cc); + osvv_(_jit, A64_FCVTZS, 0, Rd, Rn); } static void -_fcci(jit_state_t *_jit, int32_t cc, - int32_t r0, int32_t r1, jit_float32_t i0) +FCVTSZ_WD(jit_state_t *_jit, int32_t Rd, int32_t Rn) { - int32_t reg; - reg = jit_get_reg(jit_class_fpr); - movi_f(rn(reg), i0); - fccr(cc, r0, r1, rn(reg)); - jit_unget_reg(reg); + osvv_(_jit, A64_FCVTZS, 1, Rd, Rn); } static void -_uneqr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +FCVTSZ_XS(jit_state_t *_jit, int32_t Rd, int32_t Rn) { - jit_word_t w; - FCMPES(r1, r2); - CSET(r0, CC_VS); - w = _jit->pc.w; - B_C(BCC_VS, 1); /* unordered satisfies condition */ - CSET(r0, CC_EQ); /* equal satisfies condition */ - patch_at(w, _jit->pc.w); -} -fopi(uneq) - -static void -_ltgtr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - jit_word_t w; - FCMPES(r1, r2); - CSET(r0, CC_VC); /* set to 1 if ordered */ - w = _jit->pc.w; - B_C(BCC_VS, 1); /* unordered does not satisfy condition */ - CSET(r0, CC_NE); /* set to 1 if not equal */ - patch_at(w, _jit->pc.w); -} -fopi(ltgt) - -static jit_word_t -_fbccr(jit_state_t *_jit, int32_t cc, - jit_word_t i0, int32_t r0, int32_t r1) -{ - jit_word_t w, d; - FCMPES(r0, r1); - w = _jit->pc.w; - d = (i0 - w) >> 2; - B_C(cc, d); - return (w); -} - -static jit_word_t -_fbcci(jit_state_t *_jit, int32_t cc, - jit_word_t i0, int32_t r0, jit_float32_t i1) -{ - jit_word_t w; - int32_t reg; - reg = jit_get_reg(jit_class_fpr|jit_class_nospill); - movi_f(rn(reg), i1); - w = fbccr(cc, i0, r0, rn(reg)); - jit_unget_reg(reg); - return (w); -} - -static jit_word_t -_buneqr_f(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) -{ - jit_word_t u, v, w; - FCMPES(r0, r1); - u = _jit->pc.w; - B_C(BCC_VS, 1); /* unordered satisfies condition */ - v = _jit->pc.w; - B_C(BCC_NE, 1); /* not equal (or unordered) does not satisfy */ - patch_at(u, _jit->pc.w); - w = _jit->pc.w; - B((i0 - w) >> 2); - patch_at(v, _jit->pc.w); - return (w); -} -fbopi(uneq) - -static jit_word_t -_bltgtr_f(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) -{ - jit_word_t u, v, w; - FCMPES(r0, r1); - u = _jit->pc.w; - B_C(BCC_VS, 2); /* jump over if unordered */ - v = _jit->pc.w; - B_C(BCC_EQ, 1); /* jump over if equal */ - w = _jit->pc.w; - B((i0 - w) >> 2); - patch_at(u, _jit->pc.w); - patch_at(v, _jit->pc.w); - return (w); -} -fbopi(ltgt) - -dopi(add) -dopi(sub) -dopi(rsb) -dopi(mul) -dopi(div) - -static void -_ldr_d(jit_state_t *_jit, int32_t r0, int32_t r1) -{ - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - ldr_l(rn(reg), r1); - FMOVDX(r0, rn(reg)); - jit_unget_reg(reg); + osvv_(_jit, A64_FCVTZS|XS, 0, Rd, Rn); } static void -_ldi_d(jit_state_t *_jit, int32_t r0, jit_word_t i0) +FCVTSZ_XD(jit_state_t *_jit, int32_t Rd, int32_t Rn) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - ldi_l(rn(reg), i0); - FMOVDX(r0, rn(reg)); - jit_unget_reg(reg); + osvv_(_jit, A64_FCVTZS|XS, 1, Rd, Rn); } static void -_ldxr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +FABSS(jit_state_t *_jit, int32_t Rd, int32_t Rn) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - ldxr_l(rn(reg), r1, r2); - FMOVDX(r0, rn(reg)); - jit_unget_reg(reg); + osvv_(_jit, A64_FABS, 0, Rd, Rn); } static void -_ldxi_d(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +FABSD(jit_state_t *_jit, int32_t Rd, int32_t Rn) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - ldxi_l(rn(reg), r1, i0); - FMOVDX(r0, rn(reg)); - jit_unget_reg(reg); + osvv_(_jit, A64_FABS, 1, Rd, Rn); } static void -_str_d(jit_state_t *_jit, int32_t r0, int32_t r1) +FNEGS(jit_state_t *_jit, int32_t Rd, int32_t Rn) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - FMOVXD(rn(reg), r1); - str_l(r0, rn(reg)); - jit_unget_reg(reg); + osvv_(_jit, A64_FNEG, 0, Rd, Rn); } static void -_sti_d(jit_state_t *_jit, jit_word_t i0, int32_t r0) +FNEGD(jit_state_t *_jit, int32_t Rd, int32_t Rn) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - FMOVXD(rn(reg), r0); - sti_l(i0, rn(reg)); - jit_unget_reg(reg); + osvv_(_jit, A64_FNEG, 1, Rd, Rn); } static void -_stxr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +FSQRTS(jit_state_t *_jit, int32_t Rd, int32_t Rn) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - FMOVXD(rn(reg), r2); - stxr_l(r0, r1, rn(reg)); - jit_unget_reg(reg); + osvv_(_jit, A64_FSQRT, 0, Rd, Rn); } static void -_stxi_d(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) +FSQRTD(jit_state_t *_jit, int32_t Rd, int32_t Rn) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - FMOVXD(rn(reg), r1); - stxi_l(i0, r0, rn(reg)); - jit_unget_reg(reg); + osvv_(_jit, A64_FSQRT, 1, Rd, Rn); } static void -_movr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +FADDS(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) { - if (r0 != r1) - FMOVD(r0, r1); + osvvv(_jit, A64_FADD, 0, Rd, Rn, Rm); } static void -_movi_d(jit_state_t *_jit, int32_t r0, jit_float64_t i0) +FADDD(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) { - union { - int64_t l; - jit_float64_t d; - } u; - int32_t reg; - u.d = i0; - if (u.l == 0) - FMOVDX(r0, XZR_REGNO); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), u.l); - FMOVDX(r0, rn(reg)); - jit_unget_reg(reg); - } + osvvv(_jit, A64_FADD, 1, Rd, Rn, Rm); } static void -_dccr(jit_state_t *_jit, int32_t cc, - int32_t r0, int32_t r1, int32_t r2) +FSUBS(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) { - FCMPED(r1, r2); - CSET(r0, cc); + osvvv(_jit, A64_FSUB, 0, Rd, Rn, Rm); } static void -_dcci(jit_state_t *_jit, int32_t cc, - int32_t r0, int32_t r1, jit_float64_t i0) +FSUBD(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) { - int32_t reg; - reg = jit_get_reg(jit_class_fpr); - movi_d(rn(reg), i0); - dccr(cc, r0, r1, rn(reg)); - jit_unget_reg(reg); + osvvv(_jit, A64_FSUB, 1, Rd, Rn, Rm); } static void -_uneqr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +FMULS(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) { - jit_word_t w; - FCMPED(r1, r2); - CSET(r0, CC_VS); - w = _jit->pc.w; - B_C(BCC_VS, 1); /* unordered satisfies condition */ - CSET(r0, CC_EQ); /* equal satisfies condition */ - patch_at(w, _jit->pc.w); + osvvv(_jit, A64_FMUL, 0, Rd, Rn, Rm); } -dopi(uneq) static void -_ltgtr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +FMULD(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) { - jit_word_t w; - FCMPED(r1, r2); - CSET(r0, CC_VC); /* set to 1 if ordered */ - w = _jit->pc.w; - B_C(BCC_VS, 1); /* unordered does not satisfy condition */ - CSET(r0, CC_NE); /* set to 1 if not equal */ - patch_at(w, _jit->pc.w); + osvvv(_jit, A64_FMUL, 1, Rd, Rn, Rm); } -dopi(ltgt) - -static jit_word_t -_dbccr(jit_state_t *_jit, int32_t cc, - jit_word_t i0, int32_t r0, int32_t r1) -{ - jit_word_t w, d; - FCMPED(r0, r1); - w = _jit->pc.w; - d = (i0 - w) >> 2; - B_C(cc, d); - return (w); -} - -static jit_word_t -_dbcci(jit_state_t *_jit, int32_t cc, - jit_word_t i0, int32_t r0, jit_float64_t i1) -{ - jit_word_t w; - int32_t reg; - reg = jit_get_reg(jit_class_fpr|jit_class_nospill); - movi_d(rn(reg), i1); - w = dbccr(cc, i0, r0, rn(reg)); - jit_unget_reg(reg); - return (w); -} - -static jit_word_t -_buneqr_d(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) -{ - jit_word_t u, v, w; - FCMPED(r0, r1); - u = _jit->pc.w; - B_C(BCC_VS, 1); /* unordered satisfies condition */ - v = _jit->pc.w; - B_C(BCC_NE, 1); /* not equal (or unordered) does not satisfy */ - patch_at(u, _jit->pc.w); - w = _jit->pc.w; - B((i0 - w) >> 2); - patch_at(v, _jit->pc.w); - return (w); -} -dbopi(uneq) - -static jit_word_t -_bltgtr_d(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) -{ - jit_word_t u, v, w; - FCMPED(r0, r1); - u = _jit->pc.w; - B_C(BCC_VS, 2); /* jump over if unordered */ - v = _jit->pc.w; - B_C(BCC_EQ, 1); /* jump over if equal */ - w = _jit->pc.w; - B((i0 - w) >> 2); - patch_at(u, _jit->pc.w); - patch_at(v, _jit->pc.w); - return (w); -} -dbopi(ltgt) static void -_vaarg_d(jit_state_t *_jit, int32_t r0, int32_t r1) +FDIVS(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) { - jit_word_t ge_code; - jit_word_t lt_code; - int32_t rg0, rg1; - - assert(_jitc->function->self.call & jit_call_varargs); - - rg0 = jit_get_reg(jit_class_gpr); - rg1 = jit_get_reg(jit_class_gpr); - - /* Load the fp offset in save area in the first temporary. */ - ldxi_i(rn(rg0), r1, offsetof(jit_va_list_t, fpoff)); - - /* Jump over if there are no remaining arguments in the save area. */ - ge_code = bgei(_jit->pc.w, rn(rg0), 0); - - /* Load the gp save pointer in the second temporary. */ - ldxi(rn(rg1), r1, offsetof(jit_va_list_t, fptop)); - - /* Load the vararg argument in the first argument. */ - ldxr_d(r0, rn(rg1), rn(rg0)); - - /* Update the fp offset. */ - addi(rn(rg0), rn(rg0), 16); - stxi_i(offsetof(jit_va_list_t, fpoff), r1, rn(rg0)); - - /* Will only need one temporary register below. */ - jit_unget_reg(rg1); - - /* Jump over overflow code. */ - lt_code = jmpi_p(_jit->pc.w); - - /* Where to land if argument is in overflow area. */ - patch_at(ge_code, _jit->pc.w); - - /* Load stack pointer. */ - ldxi(rn(rg0), r1, offsetof(jit_va_list_t, stack)); - - /* Load argument. */ - ldr_d(r0, rn(rg0)); - - /* Update stack pointer. */ - addi(rn(rg0), rn(rg0), 8); - stxi(offsetof(jit_va_list_t, stack), r1, rn(rg0)); - - /* Where to land if argument is in gp save area. */ - patch_at(lt_code, _jit->pc.w); - - jit_unget_reg(rg0); + osvvv(_jit, A64_FDIV, 0, Rd, Rn, Rm); +} + +static void +FDIVD(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) +{ + osvvv(_jit, A64_FDIV, 1, Rd, Rn, Rm); +} + +static void +truncr_f_l(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + FCVTSZ_XS(_jit, r0, r1); +} + +static void +truncr_d_l(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + FCVTSZ_XD(_jit, r0, r1); +} + +static void +addr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + FADDS(_jit, r0, r1, r2); +} + +static void +subr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + FSUBS(_jit, r0, r1, r2); +} + +static void +mulr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + FMULS(_jit, r0, r1, r2); +} + +static void +divr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + FDIVS(_jit, r0, r1, r2); +} + +static void +absr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + FABSS(_jit, r0, r1); +} + +static void +negr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + FNEGS(_jit, r0, r1); +} + +static void +sqrtr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + FSQRTS(_jit, r0, r1); +} + +static void +extr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + SCVTFS(_jit, r0, r1); +} + +static void +extr_d_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + FCVT_SD(_jit, r0, r1); +} + +static jit_reloc_t +fbccr(jit_state_t *_jit, int32_t cc, int32_t r0, int32_t r1) +{ + FCMPES(_jit, r0, r1); + return B_C(_jit, cc); +} + +static jit_reloc_t +bltr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return fbccr(_jit, BCC_MI,r0, r1); +} + +static jit_reloc_t +bler_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return fbccr(_jit, BCC_LS,r0, r1); +} + +static jit_reloc_t +beqr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return fbccr(_jit, BCC_EQ,r0, r1); +} + +static jit_reloc_t +bger_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return fbccr(_jit, BCC_GE,r0, r1); +} + +static jit_reloc_t +bgtr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return fbccr(_jit, BCC_GT,r0, r1); +} + +static jit_reloc_t +bner_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return fbccr(_jit, BCC_NE,r0, r1); +} + +static jit_reloc_t +bunltr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return fbccr(_jit, BCC_LT,r0, r1); +} + +static jit_reloc_t +bunler_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return fbccr(_jit, BCC_LE,r0, r1); +} + +static jit_reloc_t +bunger_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return fbccr(_jit, BCC_PL,r0, r1); +} + +static jit_reloc_t +bungtr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return fbccr(_jit, BCC_HI,r0, r1); +} + +static jit_reloc_t +bordr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return fbccr(_jit, BCC_VC,r0, r1); +} + +static jit_reloc_t +bunordr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return fbccr(_jit, BCC_VS, r0, r1); +} + +static void +addr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + FADDD(_jit, r0, r1, r2); +} + +static void +subr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + FSUBD(_jit, r0, r1, r2); +} + +static void +mulr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + FMULD(_jit, r0, r1, r2); +} + +static void +divr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + FDIVD(_jit, r0, r1, r2); +} + +static void +absr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + FABSD(_jit, r0, r1); +} + +static void +negr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + FNEGD(_jit, r0, r1); +} + +static void +sqrtr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + FSQRTD(_jit, r0, r1); +} + +static void +extr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + SCVTFD(_jit, r0, r1); +} + +static void +extr_f_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + FCVT_DS(_jit, r0, r1); +} + +static jit_reloc_t +dbccr(jit_state_t *_jit, int32_t cc, int32_t r0, int32_t r1) +{ + FCMPED(_jit, r0, r1); + return B_C(_jit, cc); +} + +static jit_reloc_t +bltr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return dbccr(_jit, BCC_MI, r0, r1); +} + +static jit_reloc_t +bler_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return dbccr(_jit, BCC_LS, r0, r1); +} + +static jit_reloc_t +beqr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return dbccr(_jit, BCC_EQ, r0, r1); +} + +static jit_reloc_t +bger_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return dbccr(_jit, BCC_GE, r0, r1); +} + +static jit_reloc_t +bgtr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return dbccr(_jit, BCC_GT, r0, r1); +} + +static jit_reloc_t +bner_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return dbccr(_jit, BCC_NE, r0, r1); +} + +static jit_reloc_t +bunltr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return dbccr(_jit, BCC_LT, r0, r1); +} + +static jit_reloc_t +bunler_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return dbccr(_jit, BCC_LE, r0, r1); +} + +static jit_reloc_t +bunger_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return dbccr(_jit, BCC_PL, r0, r1); +} + +static jit_reloc_t +bungtr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return dbccr(_jit, BCC_HI, r0, r1); +} + +static jit_reloc_t +bordr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return dbccr(_jit, BCC_VC, r0, r1); +} + +static jit_reloc_t +bunordr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return dbccr(_jit, BCC_VS, r0, r1); +} + + +static void +truncr_f_i(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + FCVTSZ_WS(_jit, r0, r1); + extr_i(_jit, r0, r0); +} + +static void +truncr_d_i(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + FCVTSZ_WD(_jit, r0, r1); + extr_i(_jit, r0, r0); +} + +static void +ldr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + ldr_i(_jit, jit_gpr_regno(reg), r1); + FMOVSW(_jit, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); +} + +static void +ldi_f(jit_state_t *_jit, int32_t r0, jit_word_t i0) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + ldi_i(_jit, jit_gpr_regno(reg), i0); + FMOVSW(_jit, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); +} + +static void +ldxr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + ldxr_i(_jit, jit_gpr_regno(reg), r1, r2); + FMOVSW(_jit, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); +} + +static void +ldxi_f(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + ldxi_i(_jit, jit_gpr_regno(reg), r1, i0); + FMOVSW(_jit, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); +} + +static void +str_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + FMOVWS(_jit, jit_gpr_regno(reg), r1); + str_i(_jit, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); +} + +static void +sti_f(jit_state_t *_jit, jit_word_t i0, int32_t r0) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + FMOVWS(_jit, jit_gpr_regno(reg), r0); + sti_i(_jit, i0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); +} + +static void +stxr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + FMOVWS(_jit, jit_gpr_regno(reg), r2); + stxr_i(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); +} + +static void +stxi_f(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + FMOVWS(_jit, jit_gpr_regno(reg), r1); + stxi_i(_jit, i0, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); +} + +static void +movr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + if (r0 != r1) + FMOVS(_jit, r0, r1); +} + +static void +movi_f(jit_state_t *_jit, int32_t r0, float i0) +{ + union { + int32_t i; + float f; + } u; + u.f = i0; + if (u.i == 0) + FMOVSW(_jit, r0, WZR_REGNO); + else { + jit_gpr_t reg = get_temp_gpr(_jit); + /* prevent generating unused top 32 bits */ + movi(_jit, jit_gpr_regno(reg), ((jit_word_t)u.i) & 0xffffffff); + FMOVSW(_jit, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } +} + +static jit_reloc_t +buneqr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + FCMPES(_jit, r0, r1); + jit_reloc_t unordered = B_C(_jit, BCC_VS); /* unordered satisfies condition */ + jit_reloc_t neq = B_C(_jit, BCC_NE); /* not equal (or unordered) does not satisfy */ + jit_patch_here(_jit, unordered); + jit_reloc_t ret = B(_jit); + jit_patch_here(_jit, neq); + return ret; +} + +static jit_reloc_t +bltgtr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + FCMPES(_jit, r0, r1); + jit_reloc_t unordered = B_C(_jit, BCC_VS); /* jump over if unordered */ + jit_reloc_t eq = B_C(_jit, BCC_EQ); /* jump over if equal */ + jit_reloc_t ret = B(_jit); + jit_patch_here(_jit, unordered); + jit_patch_here(_jit, eq); + return ret; +} + +static void +ldr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + ldr_l(_jit, jit_gpr_regno(reg), r1); + FMOVDX(_jit, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); +} + +static void +ldi_d(jit_state_t *_jit, int32_t r0, jit_word_t i0) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + ldi_l(_jit, jit_gpr_regno(reg), i0); + FMOVDX(_jit, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); +} + +static void +ldxr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + ldxr_l(_jit, jit_gpr_regno(reg), r1, r2); + FMOVDX(_jit, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); +} + +static void +ldxi_d(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + ldxi_l(_jit, jit_gpr_regno(reg), r1, i0); + FMOVDX(_jit, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); +} + +static void +str_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + FMOVXD(_jit, jit_gpr_regno(reg), r1); + str_l(_jit, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); +} + +static void +sti_d(jit_state_t *_jit, jit_word_t i0, int32_t r0) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + FMOVXD(_jit, jit_gpr_regno(reg), r0); + sti_l(_jit, i0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); +} + +static void +stxr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + FMOVXD(_jit, jit_gpr_regno(reg), r2); + stxr_l(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); +} + +static void +stxi_d(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + FMOVXD(_jit, jit_gpr_regno(reg), r1); + stxi_l(_jit, i0, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); +} + +static void +movr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + if (r0 != r1) + FMOVD(_jit, r0, r1); +} + +static void +movi_d(jit_state_t *_jit, int32_t r0, double i0) +{ + union { + int64_t l; + double d; + } u; + u.d = i0; + if (u.l == 0) + FMOVDX(_jit, r0, XZR_REGNO); + else { + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), u.l); + FMOVDX(_jit, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } +} + +static jit_reloc_t +buneqr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + FCMPED(_jit, r0, r1); + jit_reloc_t unordered = B_C(_jit, BCC_VS); /* unordered satisfies condition */ + jit_reloc_t neq = B_C(_jit, BCC_NE); /* not equal (or unordered) does not satisfy */ + jit_patch_here(_jit, unordered); + jit_reloc_t ret = B(_jit); + jit_patch_here(_jit, neq); + return ret; +} + +static jit_reloc_t +bltgtr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + FCMPED(_jit, r0, r1); + jit_reloc_t unordered = B_C(_jit, BCC_VS); /* jump over if unordered */ + jit_reloc_t eq = B_C(_jit, BCC_EQ); /* jump over if equal */ + jit_reloc_t ret = B(_jit); + jit_patch_here(_jit, unordered); + jit_patch_here(_jit, eq); + return ret; +} + +static void +retr_d(jit_state_t *_jit, int32_t r) +{ + movr_d(_jit, jit_fpr_regno(_D0), r); + ret(_jit); +} + +static void +retr_f(jit_state_t *_jit, int32_t r) +{ + movr_f(_jit, jit_fpr_regno(_D0), r); + ret(_jit); +} + +static void +retval_f(jit_state_t *_jit, int32_t r0) +{ + movr_f(_jit, r0, jit_fpr_regno(_D0)); +} + +static void +retval_d(jit_state_t *_jit, int32_t r0) +{ + movr_d(_jit, r0, jit_fpr_regno(_D0)); +} + +static void +pushr_d(jit_state_t *_jit, int32_t r0) +{ + abort(); +} + +static void +popr_d(jit_state_t *_jit, int32_t r0) +{ + abort(); } -#endif diff --git a/lightening/aarch64.c b/lightening/aarch64.c index 65efb74c3..b6789082c 100644 --- a/lightening/aarch64.c +++ b/lightening/aarch64.c @@ -17,1572 +17,164 @@ * Paulo Cesar Pereira de Andrade */ -# define JIT_RA0 _R0 -# define JIT_FA0 _V0 -# define JIT_SP _SP -# define JIT_RET _R0 -# define JIT_FRET _V0 - -#define jit_arg_reg_p(i) ((i) >= 0 && (i) < 8) -#define jit_arg_f_reg_p(i) ((i) >= 0 && (i) < 8) - -typedef struct jit_qreg { - jit_float64_t l; - jit_float64_t h; -} jit_qreg_t; - -#define va_gp_top_offset offsetof(jit_va_list_t, q0) -#define va_fp_top_offset sizeof(jit_va_list_t) -typedef struct jit_va_list { - jit_pointer_t stack; - jit_pointer_t gptop; - jit_pointer_t fptop; - int32_t gpoff; - int32_t fpoff; - - int64_t x0; - int64_t x1; - int64_t x2; - int64_t x3; - int64_t x4; - int64_t x5; - int64_t x6; - int64_t x7; - - jit_qreg_t q0; - jit_qreg_t q1; - jit_qreg_t q2; - jit_qreg_t q3; - jit_qreg_t q4; - jit_qreg_t q5; - jit_qreg_t q6; - jit_qreg_t q7; -} jit_va_list_t; - -/* - * Prototypes - */ -#define patch(instr, node) _patch(_jit, instr, node) -static void _patch(jit_state_t*,jit_word_t,jit_node_t*); - /* libgcc */ extern void __clear_cache(void *, void *); -#define PROTO 1 -# include "aarch64-cpu.c" -# include "aarch64-fpu.c" -#undef PROTO -/* - * Initialization - */ -static const jit_register_t _rvs[] = { - { rc(gpr) | 0x08, "x8" }, - { rc(gpr) | 0x12, "x18" }, - { rc(gpr) | 0x11, "x17" }, - { rc(gpr) | 0x10, "x16" }, - { rc(gpr) | 0x09, "x9" }, - { rc(gpr) | 0x0a, "x10" }, - { rc(gpr) | 0x0b, "x11" }, - { rc(gpr) | 0x0c, "x12" }, - { rc(gpr) | 0x0d, "x13" }, - { rc(gpr) | 0x0e, "x14" }, - { rc(gpr) | 0x0f, "x15" }, - { rc(sav) | rc(gpr) | 0x13, "x19" }, - { rc(sav) | rc(gpr) | 0x14, "x20" }, - { rc(sav) | rc(gpr) | 0x15, "x21" }, - { rc(sav) | rc(gpr) | 0x16, "x22" }, - { rc(sav) | rc(gpr) | 0x17, "x23" }, - { rc(sav) | rc(gpr) | 0x18, "x24" }, - { rc(sav) | rc(gpr) | 0x19, "x25" }, - { rc(sav) | rc(gpr) | 0x1a, "x26" }, - { rc(sav) | rc(gpr) | 0x1b, "x27" }, - { rc(sav) | rc(gpr) | 0x1c, "x28" }, - { 0x1f, "sp" }, - { 0x1e, "lr" }, - { 0x1d, "fp" }, - { rc(arg) | rc(gpr) | 0x07, "x7" }, - { rc(arg) | rc(gpr) | 0x06, "x6" }, - { rc(arg) | rc(gpr) | 0x05, "x5" }, - { rc(arg) | rc(gpr) | 0x04, "x4" }, - { rc(arg) | rc(gpr) | 0x03, "x3" }, - { rc(arg) | rc(gpr) | 0x02, "x2" }, - { rc(arg) | rc(gpr) | 0x01, "x1" }, - { rc(arg) | rc(gpr) | 0x00, "x0" }, - { rc(fpr) | 0x1f, "v31" }, - { rc(fpr) | 0x1e, "v30" }, - { rc(fpr) | 0x1d, "v29" }, - { rc(fpr) | 0x1c, "v28" }, - { rc(fpr) | 0x1b, "v27" }, - { rc(fpr) | 0x1a, "v26" }, - { rc(fpr) | 0x19, "v25" }, - { rc(fpr) | 0x18, "v24" }, - { rc(fpr) | 0x17, "v23" }, - { rc(fpr) | 0x16, "v22" }, - { rc(fpr) | 0x15, "v21" }, - { rc(fpr) | 0x14, "v20" }, - { rc(fpr) | 0x13, "v19" }, - { rc(fpr) | 0x12, "v18" }, - { rc(fpr) | 0x11, "v17" }, - { rc(fpr) | 0x10, "v16" }, - { rc(sav) | rc(fpr) | 0x08, "v8" }, - { rc(sav) | rc(fpr) | 0x09, "v9" }, - { rc(sav) | rc(fpr) | 0x0a, "v10" }, - { rc(sav) | rc(fpr) | 0x0b, "v11" }, - { rc(sav) | rc(fpr) | 0x0c, "v12" }, - { rc(sav) | rc(fpr) | 0x0d, "v13" }, - { rc(sav) | rc(fpr) | 0x0e, "v14" }, - { rc(sav) | rc(fpr) | 0x0f, "v15" }, - { rc(arg) | rc(fpr) | 0x07, "v7" }, - { rc(arg) | rc(fpr) | 0x06, "v6" }, - { rc(arg) | rc(fpr) | 0x05, "v5" }, - { rc(arg) | rc(fpr) | 0x04, "v4" }, - { rc(arg) | rc(fpr) | 0x03, "v3" }, - { rc(arg) | rc(fpr) | 0x02, "v2" }, - { rc(arg) | rc(fpr) | 0x01, "v1" }, - { rc(arg) | rc(fpr) | 0x00, "v0" }, - { _NOREG, "" }, +static inline int32_t +read_offset(uint32_t *loc, uint8_t bits, uint8_t base) +{ + return (*((int32_t*)loc)) << (32 - bits - base) >> (32 - bits); +} + +static inline int +in_signed_range(ptrdiff_t diff, uint8_t bits) +{ + return (-1 << (bits - 1)) <= diff && diff < (1 << (bits - 1)); +} + +static inline int32_t +write_offset(uint32_t *loc, uint8_t bits, uint8_t base, ptrdiff_t offset) +{ + ASSERT(read_offset(loc, bits, base) == 0); + ASSERT(in_signed_range(offset, bits)); + *loc |= (((uint32_t) offset) & ((1 << bits) - 1)) << base; +} + +#define DEFINE_PATCHABLE_INSTRUCTION(name, bits, base, RELOC, rsh) \ + static const uint8_t name##_offset_bits = bits; \ + static const uint8_t name##_offset_base = base; \ + static int32_t \ + read_##name##_offset(uint32_t *loc) \ + { \ + return read_offset(loc, name##_offset_bits, name##_offset_base); \ + } \ + static int \ + in_##name##_range(ptrdiff_t diff) \ + { \ + return in_signed_range(diff, name##_offset_bits); \ + } \ + static int32_t \ + write_##name##_offset(uint32_t *loc, ptrdiff_t diff) \ + { \ + return write_offset(loc, name##_offset_bits, name##_offset_base, diff); \ + } \ + static jit_reloc_t \ + emit_##name(jit_state_t *_jit, uint32_t inst) \ + { \ + jit_reloc_t ret = jit_reloc (_jit, JIT_RELOC_##RELOC, 0, \ + _jit->pc.uc, _jit->pc.uc, rsh); \ + add_pending_literal(_jit, ret, name##_offset_bits); \ + emit_u32(_jit, inst); \ + return ret; \ + } + +DEFINE_PATCHABLE_INSTRUCTION(jmp, 26, 0, JCC_WITH_VENEER, 2); +DEFINE_PATCHABLE_INSTRUCTION(jcc, 19, 5, JMP_WITH_VENEER, 2); +DEFINE_PATCHABLE_INSTRUCTION(load_from_pool, 19, 5, LOAD_FROM_POOL, 2); + +struct veneer +{ + uint32_t ldr; + uint32_t br; + uint64_t addr; }; -/* - * Implementation - */ -void +static void +patch_veneer(uint32_t *loc, jit_pointer_t addr) +{ + struct veneer *v = (struct veneer*) v; + v->addr = (uint64_t) addr; +} + +#include "aarch64-cpu.c" +#include "aarch64-fpu.c" + +static const jit_gpr_t abi_gpr_args[] = { + _X0, _X1, _X2, _X3, _X4, _X5, _X6, _X7 +}; + +static const jit_fpr_t abi_fpr_args[] = { + _D0, _D1, _D2, _D3, _D4, _D5, _D6, _D7 +}; + +static const int abi_gpr_arg_count = sizeof(abi_gpr_args) / sizeof(abi_gpr_args[0]); +static const int abi_fpr_arg_count = sizeof(abi_fpr_args) / sizeof(abi_fpr_args[0]); + +struct abi_arg_iterator +{ + const jit_operand_t *args; + size_t argc; + + size_t arg_idx; + size_t gpr_idx; + size_t fpr_idx; + size_t stack_size; + size_t stack_padding; +}; + +static size_t page_size; + +jit_bool_t jit_get_cpu(void) { -} - -void -_jit_init(jit_state_t *_jit) -{ - _jitc->reglen = jit_size(_rvs) - 1; -} - -void -_jit_prolog(jit_state_t *_jit) -{ - int32_t offset; - - if (_jitc->function) - jit_epilog(); - assert(jit_regset_cmp_ui(&_jitc->regarg, 0) == 0); - jit_regset_set_ui(&_jitc->regsav, 0); - offset = _jitc->functions.offset; - if (offset >= _jitc->functions.length) { - jit_realloc((jit_pointer_t *)&_jitc->functions.ptr, - _jitc->functions.length * sizeof(jit_function_t), - (_jitc->functions.length + 16) * sizeof(jit_function_t)); - _jitc->functions.length += 16; - } - _jitc->function = _jitc->functions.ptr + _jitc->functions.offset++; - _jitc->function->self.size = stack_framesize; - _jitc->function->self.argi = _jitc->function->self.argf = - _jitc->function->self.alen = 0; - _jitc->function->self.aoff = 0; - _jitc->function->self.call = jit_call_default; - jit_alloc((jit_pointer_t *)&_jitc->function->regoff, - _jitc->reglen * sizeof(int32_t)); - - /* _no_link here does not mean the jit_link() call can be removed - * by rewriting as: - * _jitc->function->prolog = jit_new_node(jit_code_prolog); - */ - _jitc->function->prolog = jit_new_node_no_link(jit_code_prolog); - jit_link(_jitc->function->prolog); - _jitc->function->prolog->w.w = offset; - _jitc->function->epilog = jit_new_node_no_link(jit_code_epilog); - /* u: label value - * v: offset in blocks vector - * w: offset in functions vector - */ - _jitc->function->epilog->w.w = offset; - - jit_regset_new(&_jitc->function->regset); -} - -int32_t -_jit_allocai(jit_state_t *_jit, int32_t length) -{ - assert(_jitc->function); - switch (length) { - case 0: case 1: break; - case 2: _jitc->function->self.aoff &= -2; break; - case 3: case 4: _jitc->function->self.aoff &= -4; break; - default: _jitc->function->self.aoff &= -8; break; - } - _jitc->function->self.aoff -= length; - if (!_jitc->realize) { - jit_inc_synth_ww(allocai, _jitc->function->self.aoff, length); - jit_dec_synth(); - } - return (_jitc->function->self.aoff); -} - -void -_jit_allocar(jit_state_t *_jit, int32_t u, int32_t v) -{ - int32_t r0, r1; - assert(_jitc->function); - jit_inc_synth_ww(allocar, u, v); - if (!_jitc->function->allocar) { - _jitc->function->aoffoff = jit_allocai(sizeof(int32_t)); - _jitc->function->allocar = 1; - } - r0 = jit_get_reg(jit_class_gpr); - jit_negr(r0, v); - jit_andi(r0, r0, -16); - jit_ldxi_i(u, JIT_FP, _jitc->function->aoffoff); - jit_addr(u, u, r0); - /* Cannot "addr sp, sp, reg" because in this context "sp" is "[w|x]zr", - * the zero register */ -#if 0 - jit_addr(JIT_SP, JIT_SP, r0); -#else - r1 = jit_get_reg(jit_class_gpr); - /* note that "mov r1, sp" does not work, but the proper encoding - * can be triggered before actually emiting with "add r1, sp, 0" */ - jit_addi(r1, JIT_SP, 0); - jit_addr(r1, r1, r0); - jit_addi(JIT_SP, r1, 0); - jit_unget_reg(r1); -#endif - jit_stxi_i(_jitc->function->aoffoff, JIT_FP, u); - jit_unget_reg(r0); - jit_dec_synth(); -} - -void -_jit_ret(jit_state_t *_jit) -{ - jit_node_t *instr; - assert(_jitc->function); - jit_inc_synth(ret); - /* jump to epilog */ - instr = jit_jmpi(); - jit_patch_at(instr, _jitc->function->epilog); - jit_dec_synth(); -} - -void -_jit_retr(jit_state_t *_jit, int32_t u) -{ - jit_inc_synth_w(retr, u); - if (JIT_RET != u) - jit_movr(JIT_RET, u); - jit_live(JIT_RET); - jit_ret(); - jit_dec_synth(); -} - -void -_jit_reti(jit_state_t *_jit, jit_word_t u) -{ - jit_inc_synth_w(reti, u); - jit_movi(JIT_RET, u); - jit_ret(); - jit_dec_synth(); -} - -void -_jit_retr_f(jit_state_t *_jit, int32_t u) -{ - jit_inc_synth_w(retr_f, u); - if (u != JIT_FRET) - jit_movr_f(JIT_FRET, u); - else - jit_live(JIT_FRET); - jit_ret(); - jit_dec_synth(); -} - -void -_jit_reti_f(jit_state_t *_jit, jit_float32_t u) -{ - jit_inc_synth_f(reti_f, u); - jit_movi_f(JIT_FRET, u); - jit_ret(); - jit_dec_synth(); -} - -void -_jit_retr_d(jit_state_t *_jit, int32_t u) -{ - jit_inc_synth_w(retr_d, u); - if (u != JIT_FRET) - jit_movr_d(JIT_FRET, u); - else - jit_live(JIT_FRET); - jit_ret(); - jit_dec_synth(); -} - -void -_jit_reti_d(jit_state_t *_jit, jit_float64_t u) -{ - jit_inc_synth_d(reti_d, u); - jit_movi_d(JIT_FRET, u); - jit_ret(); - jit_dec_synth(); -} - -void -_jit_epilog(jit_state_t *_jit) -{ - assert(_jitc->function); - assert(_jitc->function->epilog->next == NULL); - jit_link(_jitc->function->epilog); - _jitc->function = NULL; + page_size = sysconf(_SC_PAGE_SIZE); + return 1; } jit_bool_t -_jit_arg_register_p(jit_state_t *_jit, jit_node_t *u) +jit_init(jit_state_t *_jit) { - if (u->code == jit_code_arg) - return (jit_arg_reg_p(u->u.w)); - assert(u->code == jit_code_arg_f || u->code == jit_code_arg_d); - return (jit_arg_f_reg_p(u->u.w)); + return 1; } -void -_jit_ellipsis(jit_state_t *_jit) +static size_t +jit_operand_abi_sizeof(enum jit_operand_abi abi) { - jit_inc_synth(ellipsis); - if (_jitc->prepare) { - jit_link_prepare(); - assert(!(_jitc->function->call.call & jit_call_varargs)); - _jitc->function->call.call |= jit_call_varargs; - } - else { - jit_link_prolog(); - assert(!(_jitc->function->self.call & jit_call_varargs)); - _jitc->function->self.call |= jit_call_varargs; - - /* Allocate va_list like object in the stack, - * with enough space to save all argument - * registers, and use fixed offsets for them. */ - _jitc->function->vaoff = jit_allocai(sizeof(jit_va_list_t)); - - /* Initialize gp offset in save area. */ - if (jit_arg_reg_p(_jitc->function->self.argi)) - _jitc->function->vagp = (8 - _jitc->function->self.argi) * -8; - else - _jitc->function->vagp = 0; - - /* Initialize fp offset in save area. */ - if (jit_arg_f_reg_p(_jitc->function->self.argf)) - _jitc->function->vafp = (8 - _jitc->function->self.argf) * -16; - else - _jitc->function->vafp = 0; - } - jit_dec_synth(); + return 8; } -void -_jit_va_push(jit_state_t *_jit, int32_t u) +static size_t +jit_initial_frame_size (void) { - jit_inc_synth_w(va_push, u); - jit_pushargr(u); - jit_dec_synth(); + return 0; } -jit_node_t * -_jit_arg(jit_state_t *_jit) +static void +reset_abi_arg_iterator(struct abi_arg_iterator *iter, size_t argc, + const jit_operand_t *args) { - jit_node_t *node; - int32_t offset; - assert(_jitc->function); - assert(!(_jitc->function->self.call & jit_call_varargs)); - if (jit_arg_reg_p(_jitc->function->self.argi)) - offset = _jitc->function->self.argi++; - else { - offset = _jitc->function->self.size; - _jitc->function->self.size += sizeof(jit_word_t); - } - node = jit_new_node_ww(jit_code_arg, offset, - ++_jitc->function->self.argn); - jit_link_prolog(); - return (node); + memset(iter, 0, sizeof *iter); + iter->argc = argc; + iter->args = args; } -jit_node_t * -_jit_arg_f(jit_state_t *_jit) +static void +next_abi_arg(struct abi_arg_iterator *iter, jit_operand_t *arg) { - jit_node_t *node; - int32_t offset; - assert(_jitc->function); - assert(!(_jitc->function->self.call & jit_call_varargs)); - if (jit_arg_f_reg_p(_jitc->function->self.argf)) - offset = _jitc->function->self.argf++; - else { - offset = _jitc->function->self.size; - _jitc->function->self.size += sizeof(jit_word_t); - } - node = jit_new_node_ww(jit_code_arg_f, offset, - ++_jitc->function->self.argn); - jit_link_prolog(); - return (node); + ASSERT(iter->arg_idx < iter->argc); + enum jit_operand_abi abi = iter->args[iter->arg_idx].abi; + if (is_gpr_arg(abi) && iter->gpr_idx < abi_gpr_arg_count) { + *arg = jit_operand_gpr (abi, abi_gpr_args[iter->gpr_idx++]); + } else if (is_fpr_arg(abi) && iter->fpr_idx < abi_fpr_arg_count) { + *arg = jit_operand_fpr (abi, abi_fpr_args[iter->fpr_idx++]); + } else { + *arg = jit_operand_mem (abi, JIT_SP, iter->stack_size); + iter->stack_size += 8; + } + iter->arg_idx++; } -jit_node_t * -_jit_arg_d(jit_state_t *_jit) -{ - jit_node_t *node; - int32_t offset; - assert(_jitc->function); - assert(!(_jitc->function->self.call & jit_call_varargs)); - if (jit_arg_f_reg_p(_jitc->function->self.argf)) - offset = _jitc->function->self.argf++; - else { - offset = _jitc->function->self.size; - _jitc->function->self.size += sizeof(jit_word_t); - } - node = jit_new_node_ww(jit_code_arg_d, offset, - ++_jitc->function->self.argn); - jit_link_prolog(); - return (node); -} - -void -_jit_getarg_c(jit_state_t *_jit, int32_t u, jit_node_t *v) -{ - assert(v->code == jit_code_arg); - jit_inc_synth_wp(getarg_c, u, v); - if (jit_arg_reg_p(v->u.w)) - jit_extr_c(u, JIT_RA0 - v->u.w); - else - jit_ldxi_c(u, JIT_FP, v->u.w); - jit_dec_synth(); -} - -void -_jit_getarg_uc(jit_state_t *_jit, int32_t u, jit_node_t *v) -{ - assert(v->code == jit_code_arg); - jit_inc_synth_wp(getarg_uc, u, v); - if (jit_arg_reg_p(v->u.w)) - jit_extr_uc(u, JIT_RA0 - v->u.w); - else - jit_ldxi_uc(u, JIT_FP, v->u.w); - jit_dec_synth(); -} - -void -_jit_getarg_s(jit_state_t *_jit, int32_t u, jit_node_t *v) -{ - assert(v->code == jit_code_arg); - jit_inc_synth_wp(getarg_s, u, v); - if (jit_arg_reg_p(v->u.w)) - jit_extr_s(u, JIT_RA0 - v->u.w); - else - jit_ldxi_s(u, JIT_FP, v->u.w); - jit_dec_synth(); -} - -void -_jit_getarg_us(jit_state_t *_jit, int32_t u, jit_node_t *v) -{ - assert(v->code == jit_code_arg); - jit_inc_synth_wp(getarg_us, u, v); - if (jit_arg_reg_p(v->u.w)) - jit_extr_us(u, JIT_RA0 - v->u.w); - else - jit_ldxi_us(u, JIT_FP, v->u.w); - jit_dec_synth(); -} - -void -_jit_getarg_i(jit_state_t *_jit, int32_t u, jit_node_t *v) -{ - assert(v->code == jit_code_arg); - jit_inc_synth_wp(getarg_i, u, v); - if (jit_arg_reg_p(v->u.w)) - jit_extr_i(u, JIT_RA0 - v->u.w); - else - jit_ldxi_i(u, JIT_FP, v->u.w); - jit_dec_synth(); -} - -void -_jit_getarg_ui(jit_state_t *_jit, int32_t u, jit_node_t *v) -{ - assert(v->code == jit_code_arg); - jit_inc_synth_wp(getarg_ui, u, v); - if (jit_arg_reg_p(v->u.w)) - jit_extr_ui(u, JIT_RA0 - v->u.w); - else - jit_ldxi_ui(u, JIT_FP, v->u.w); - jit_dec_synth(); -} - -void -_jit_getarg_l(jit_state_t *_jit, int32_t u, jit_node_t *v) -{ - assert(v->code == jit_code_arg); - jit_inc_synth_wp(getarg_l, u, v); - if (jit_arg_reg_p(v->u.w)) - jit_movr(u, JIT_RA0 - v->u.w); - else - jit_ldxi_l(u, JIT_FP, v->u.w); - jit_dec_synth(); -} - -void -_jit_putargr(jit_state_t *_jit, int32_t u, jit_node_t *v) -{ - assert(v->code == jit_code_arg); - jit_inc_synth_wp(putargr, u, v); - if (jit_arg_reg_p(v->u.w)) - jit_movr(JIT_RA0 - v->u.w, u); - else - jit_stxi(v->u.w, JIT_FP, u); - jit_dec_synth(); -} - -void -_jit_putargi(jit_state_t *_jit, jit_word_t u, jit_node_t *v) -{ - int32_t regno; - assert(v->code == jit_code_arg); - jit_inc_synth_wp(putargi, u, v); - if (jit_arg_reg_p(v->u.w)) - jit_movi(JIT_RA0 - v->u.w, u); - else { - regno = jit_get_reg(jit_class_gpr); - jit_movi(regno, u); - jit_stxi(v->u.w, JIT_FP, regno); - jit_unget_reg(regno); - } - jit_dec_synth(); -} - -void -_jit_getarg_f(jit_state_t *_jit, int32_t u, jit_node_t *v) -{ - assert(v->code == jit_code_arg_f); - jit_inc_synth_wp(getarg_f, u, v); - if (jit_arg_reg_p(v->u.w)) - jit_movr_f(u, JIT_FA0 - v->u.w); - else - jit_ldxi_f(u, JIT_FP, v->u.w); - jit_dec_synth(); -} - -void -_jit_putargr_f(jit_state_t *_jit, int32_t u, jit_node_t *v) -{ - assert(v->code == jit_code_arg_f); - jit_inc_synth_wp(putargr_f, u, v); - if (jit_arg_f_reg_p(v->u.w)) - jit_movr_f(JIT_FA0 - v->u.w, u); - else - jit_stxi_f(v->u.w, JIT_FP, u); - jit_dec_synth(); -} - -void -_jit_putargi_f(jit_state_t *_jit, jit_float32_t u, jit_node_t *v) -{ - int32_t regno; - assert(v->code == jit_code_arg_f); - jit_inc_synth_fp(putargi_f, u, v); - if (jit_arg_f_reg_p(v->u.w)) - jit_movi_f(JIT_FA0 - v->u.w, u); - else { - regno = jit_get_reg(jit_class_fpr); - jit_movi_f(regno, u); - jit_stxi_f(v->u.w, JIT_FP, regno); - jit_unget_reg(regno); - } - jit_dec_synth(); -} - -void -_jit_getarg_d(jit_state_t *_jit, int32_t u, jit_node_t *v) -{ - assert(v->code == jit_code_arg_d); - jit_inc_synth_wp(getarg_d, u, v); - if (jit_arg_f_reg_p(v->u.w)) - jit_movr_d(u, JIT_FA0 - v->u.w); - else - jit_ldxi_d(u, JIT_FP, v->u.w); - jit_dec_synth(); -} - -void -_jit_putargr_d(jit_state_t *_jit, int32_t u, jit_node_t *v) -{ - assert(v->code == jit_code_arg_d); - jit_inc_synth_wp(putargr_d, u, v); - if (jit_arg_reg_p(v->u.w)) - jit_movr_d(JIT_FA0 - v->u.w, u); - else - jit_stxi_d(v->u.w, JIT_FP, u); - jit_dec_synth(); -} - -void -_jit_putargi_d(jit_state_t *_jit, jit_float64_t u, jit_node_t *v) -{ - int32_t regno; - assert(v->code == jit_code_arg_d); - jit_inc_synth_dp(putargi_d, u, v); - if (jit_arg_reg_p(v->u.w)) - jit_movi_d(JIT_FA0 - v->u.w, u); - else { - regno = jit_get_reg(jit_class_fpr); - jit_movi_d(regno, u); - jit_stxi_d(v->u.w, JIT_FP, regno); - jit_unget_reg(regno); - } - jit_dec_synth(); -} - -void -_jit_pushargr(jit_state_t *_jit, int32_t u) -{ - assert(_jitc->function); - jit_inc_synth_w(pushargr, u); - jit_link_prepare(); - if (jit_arg_reg_p(_jitc->function->call.argi)) { - jit_movr(JIT_RA0 - _jitc->function->call.argi, u); - ++_jitc->function->call.argi; - } - else { - jit_stxi(_jitc->function->call.size, JIT_SP, u); - _jitc->function->call.size += sizeof(jit_word_t); - } - jit_dec_synth(); -} - -void -_jit_pushargi(jit_state_t *_jit, jit_word_t u) -{ - int32_t regno; - assert(_jitc->function); - jit_inc_synth_w(pushargi, u); - jit_link_prepare(); - if (jit_arg_reg_p(_jitc->function->call.argi)) { - jit_movi(JIT_RA0 - _jitc->function->call.argi, u); - ++_jitc->function->call.argi; - } - else { - regno = jit_get_reg(jit_class_gpr); - jit_movi(regno, u); - jit_stxi(_jitc->function->call.size, JIT_SP, regno); - jit_unget_reg(regno); - _jitc->function->call.size += sizeof(jit_word_t); - } - jit_dec_synth(); -} - -void -_jit_pushargr_f(jit_state_t *_jit, int32_t u) -{ - assert(_jitc->function); - jit_inc_synth_w(pushargr_f, u); - jit_link_prepare(); - if (jit_arg_f_reg_p(_jitc->function->call.argf)) { - jit_movr_f(JIT_FA0 - _jitc->function->call.argf, u); - ++_jitc->function->call.argf; - } - else { - jit_stxi_f(_jitc->function->call.size, JIT_SP, u); - _jitc->function->call.size += sizeof(jit_word_t); - } - jit_dec_synth(); -} - -void -_jit_pushargi_f(jit_state_t *_jit, jit_float32_t u) -{ - int32_t regno; - assert(_jitc->function); - jit_inc_synth_f(pushargi_f, u); - jit_link_prepare(); - if (jit_arg_f_reg_p(_jitc->function->call.argf)) { - jit_movi_f(JIT_FA0 - _jitc->function->call.argf, u); - ++_jitc->function->call.argf; - } - else { - regno = jit_get_reg(jit_class_fpr); - jit_movi_f(regno, u); - jit_stxi_f(_jitc->function->call.size, JIT_SP, regno); - jit_unget_reg(regno); - _jitc->function->call.size += sizeof(jit_word_t); - } - jit_dec_synth(); -} - -void -_jit_pushargr_d(jit_state_t *_jit, int32_t u) -{ - assert(_jitc->function); - jit_inc_synth_w(pushargr_d, u); - jit_link_prepare(); - if (jit_arg_f_reg_p(_jitc->function->call.argf)) { - jit_movr_d(JIT_FA0 - _jitc->function->call.argf, u); - ++_jitc->function->call.argf; - } - else { - jit_stxi_d(_jitc->function->call.size, JIT_SP, u); - _jitc->function->call.size += sizeof(jit_word_t); - } - jit_dec_synth(); -} - -void -_jit_pushargi_d(jit_state_t *_jit, jit_float64_t u) -{ - int32_t regno; - assert(_jitc->function); - jit_inc_synth_d(pushargi_d, u); - jit_link_prepare(); - if (jit_arg_f_reg_p(_jitc->function->call.argf)) { - jit_movi_d(JIT_FA0 - _jitc->function->call.argf, u); - ++_jitc->function->call.argf; - } - else { - regno = jit_get_reg(jit_class_fpr); - jit_movi_d(regno, u); - jit_stxi_d(_jitc->function->call.size, JIT_SP, regno); - jit_unget_reg(regno); - _jitc->function->call.size += sizeof(jit_word_t); - } - jit_dec_synth(); -} - -jit_bool_t -_jit_regarg_p(jit_state_t *_jit, jit_node_t *node, int32_t regno) -{ - int32_t spec; - spec = jit_class(_rvs[regno].spec); - if (spec & jit_class_arg) { - regno = JIT_RA0 - regno; - if (regno >= 0 && regno < node->v.w) - return (1); - if (spec & jit_class_fpr) { - regno = JIT_FA0 - regno; - if (regno >= 0 && regno < node->w.w) - return (1); - } - } - - return (0); -} - -void -_jit_finishr(jit_state_t *_jit, int32_t r0) -{ - jit_node_t *node; - assert(_jitc->function); - jit_inc_synth_w(finishr, r0); - if (_jitc->function->self.alen < _jitc->function->call.size) - _jitc->function->self.alen = _jitc->function->call.size; - node = jit_callr(r0); - node->v.w = _jitc->function->self.argi; - node->w.w = _jitc->function->call.argf; - _jitc->function->call.argi = _jitc->function->call.argf = - _jitc->function->call.size = 0; - _jitc->prepare = 0; - jit_dec_synth(); -} - -jit_node_t * -_jit_finishi(jit_state_t *_jit, jit_pointer_t i0) -{ - jit_node_t *node; - assert(_jitc->function); - jit_inc_synth_w(finishi, (jit_word_t)i0); - if (_jitc->function->self.alen < _jitc->function->call.size) - _jitc->function->self.alen = _jitc->function->call.size; - node = jit_calli(i0); - node->v.w = _jitc->function->call.argi; - node->w.w = _jitc->function->call.argf; - _jitc->function->call.argi = _jitc->function->call.argf = - _jitc->function->call.size = 0; - _jitc->prepare = 0; - jit_dec_synth(); - return (node); -} - -void -_jit_retval_c(jit_state_t *_jit, int32_t r0) -{ - jit_inc_synth_w(retval_c, r0); - jit_extr_c(r0, JIT_RET); - jit_dec_synth(); -} - -void -_jit_retval_uc(jit_state_t *_jit, int32_t r0) -{ - jit_inc_synth_w(retval_uc, r0); - jit_extr_uc(r0, JIT_RET); - jit_dec_synth(); -} - -void -_jit_retval_s(jit_state_t *_jit, int32_t r0) -{ - jit_inc_synth_w(retval_s, r0); - jit_extr_s(r0, JIT_RET); - jit_dec_synth(); -} - -void -_jit_retval_us(jit_state_t *_jit, int32_t r0) -{ - jit_inc_synth_w(retval_us, r0); - jit_extr_us(r0, JIT_RET); - jit_dec_synth(); -} - -void -_jit_retval_i(jit_state_t *_jit, int32_t r0) -{ - jit_inc_synth_w(retval_i, r0); - jit_extr_i(r0, JIT_RET); - jit_dec_synth(); -} - -void -_jit_retval_ui(jit_state_t *_jit, int32_t r0) -{ - jit_inc_synth_w(retval_ui, r0); - jit_extr_ui(r0, JIT_RET); - jit_dec_synth(); -} - -void -_jit_retval_l(jit_state_t *_jit, int32_t r0) -{ - jit_inc_synth_w(retval_l, r0); - if (r0 != JIT_RET) - jit_movr(r0, JIT_RET); - jit_dec_synth(); -} - -void -_jit_retval_f(jit_state_t *_jit, int32_t r0) -{ - jit_inc_synth_w(retval_f, r0); - if (r0 != JIT_FRET) - jit_movr_f(r0, JIT_FRET); - jit_dec_synth(); -} - -void -_jit_retval_d(jit_state_t *_jit, int32_t r0) -{ - jit_inc_synth_w(retval_d, r0); - if (r0 != JIT_FRET) - jit_movr_d(r0, JIT_FRET); - jit_dec_synth(); -} - -jit_pointer_t -_emit_code(jit_state_t *_jit) -{ - jit_node_t *node; - jit_node_t *temp; - jit_word_t word; - jit_word_t value; - int32_t offset; - struct { - jit_node_t *node; - uint8_t *data; - jit_word_t word; -#if DEVEL_DISASSEMBLER - jit_word_t prevw; -#endif - int32_t const_offset; - int32_t patch_offset; - } undo; -#if DEVEL_DISASSEMBLER - jit_word_t prevw; -#endif - - _jitc->function = NULL; - - jit_reglive_setup(); - - undo.word = 0; - undo.node = NULL; - undo.const_offset = undo.patch_offset = 0; -# define assert_data(node) /**/ -#define case_rr(name, type) \ - case jit_code_##name##r##type: \ - name##r##type(rn(node->u.w), rn(node->v.w)); \ - break -#define case_rw(name, type) \ - case jit_code_##name##i##type: \ - name##i##type(rn(node->u.w), node->v.w); \ - break -#define case_wr(name, type) \ - case jit_code_##name##i##type: \ - name##i##type(node->u.w, rn(node->v.w)); \ - break -#define case_rrr(name, type) \ - case jit_code_##name##r##type: \ - name##r##type(rn(node->u.w), \ - rn(node->v.w), rn(node->w.w)); \ - break -#define case_rrrr(name, type) \ - case jit_code_##name##r##type: \ - name##r##type(rn(node->u.q.l), rn(node->u.q.h), \ - rn(node->v.w), rn(node->w.w)); \ - break -#define case_rrw(name, type) \ - case jit_code_##name##i##type: \ - name##i##type(rn(node->u.w), rn(node->v.w), node->w.w); \ - break -#define case_rrrw(name, type) \ - case jit_code_##name##i##type: \ - name##i##type(rn(node->u.q.l), rn(node->u.q.h), \ - rn(node->v.w), node->w.w); \ - break -#define case_rrf(name) \ - case jit_code_##name##i_f: \ - assert_data(node); \ - name##i_f(rn(node->u.w), rn(node->v.w), node->w.f); \ - break -#define case_rrd(name) \ - case jit_code_##name##i_d: \ - assert_data(node); \ - name##i_d(rn(node->u.w), rn(node->v.w), node->w.d); \ - break -#define case_wrr(name, type) \ - case jit_code_##name##i##type: \ - name##i##type(node->u.w, rn(node->v.w), rn(node->w.w)); \ - break -#define case_brr(name, type) \ - case jit_code_##name##r##type: \ - temp = node->u.n; \ - assert(temp->code == jit_code_label || \ - temp->code == jit_code_epilog); \ - if (temp->flag & jit_flag_patch) \ - name##r##type(temp->u.w, rn(node->v.w), \ - rn(node->w.w)); \ - else { \ - word = name##r##type(_jit->pc.w, \ - rn(node->v.w), rn(node->w.w)); \ - patch(word, node); \ - } \ - break -#define case_brw(name, type) \ - case jit_code_##name##i##type: \ - temp = node->u.n; \ - assert(temp->code == jit_code_label || \ - temp->code == jit_code_epilog); \ - if (temp->flag & jit_flag_patch) \ - name##i##type(temp->u.w, \ - rn(node->v.w), node->w.w); \ - else { \ - word = name##i##type(_jit->pc.w, \ - rn(node->v.w), node->w.w); \ - patch(word, node); \ - } \ - break; -#define case_brf(name) \ - case jit_code_##name##i_f: \ - temp = node->u.n; \ - assert(temp->code == jit_code_label || \ - temp->code == jit_code_epilog); \ - if (temp->flag & jit_flag_patch) \ - name##i_f(temp->u.w, rn(node->v.w), node->w.f); \ - else { \ - word = name##i_f(_jit->pc.w, rn(node->v.w), \ - node->w.f); \ - patch(word, node); \ - } \ - break -#define case_brd(name) \ - case jit_code_##name##i_d: \ - temp = node->u.n; \ - assert(temp->code == jit_code_label || \ - temp->code == jit_code_epilog); \ - if (temp->flag & jit_flag_patch) \ - name##i_d(temp->u.w, rn(node->v.w), node->w.d); \ - else { \ - word = name##i_d(_jit->pc.w, rn(node->v.w), \ - node->w.d); \ - patch(word, node); \ - } \ - break -#if DEVEL_DISASSEMBLER - prevw = _jit->pc.w; -#endif - for (node = _jitc->head; node; node = node->next) { - if (_jit->pc.uc >= _jitc->code.end) - return (NULL); - -#if DEVEL_DISASSEMBLER - node->offset = (jit_uword_t)_jit->pc.w - (jit_uword_t)prevw; - prevw = _jit->pc.w; -#endif - value = jit_classify(node->code); - jit_regarg_set(node, value); - switch (node->code) { - case jit_code_align: - assert(!(node->u.w & (node->u.w - 1)) && - node->u.w <= sizeof(jit_word_t)); - if (node->u.w == sizeof(jit_word_t) && - (word = _jit->pc.w & (sizeof(jit_word_t) - 1))) - nop(sizeof(jit_word_t) - word); - break; - case jit_code_note: case jit_code_name: - node->u.w = _jit->pc.w; - break; - case jit_code_label: - /* remember label is defined */ - node->flag |= jit_flag_patch; - node->u.w = _jit->pc.w; - break; - case_rrr(add,); - case_rrw(add,); - case_rrr(addc,); - case_rrw(addc,); - case_rrr(addx,); - case_rrw(addx,); - case_rrr(sub,); - case_rrw(sub,); - case_rrr(subc,); - case_rrw(subc,); - case_rrr(subx,); - case_rrw(subx,); - case_rrw(rsb,); - case_rrr(mul,); - case_rrw(mul,); - case_rrrr(qmul,); - case_rrrw(qmul,); - case_rrrr(qmul, _u); - case_rrrw(qmul, _u); - case_rrr(div,); - case_rrw(div,); - case_rrr(div, _u); - case_rrw(div, _u); - case_rrrr(qdiv,); - case_rrrw(qdiv,); - case_rrrr(qdiv, _u); - case_rrrw(qdiv, _u); - case_rrr(rem,); - case_rrw(rem,); - case_rrr(rem, _u); - case_rrw(rem, _u); - case_rrr(lsh,); - case_rrw(lsh,); - case_rrr(rsh,); - case_rrw(rsh,); - case_rrr(rsh, _u); - case_rrw(rsh, _u); - case_rr(neg,); - case_rr(com,); - case_rrr(and,); - case_rrw(and,); - case_rrr(or,); - case_rrw(or,); - case_rrr(xor,); - case_rrw(xor,); - case_rr(trunc, _f_i); - case_rr(trunc, _d_i); - case_rr(trunc, _f_l); - case_rr(trunc, _d_l); - case_rr(ld, _c); - case_rw(ld, _c); - case_rr(ld, _uc); - case_rw(ld, _uc); - case_rr(ld, _s); - case_rw(ld, _s); - case_rr(ld, _us); - case_rw(ld, _us); - case_rr(ld, _i); - case_rw(ld, _i); - case_rr(ld, _ui); - case_rw(ld, _ui); - case_rr(ld, _l); - case_rw(ld, _l); - case_rrr(ldx, _c); - case_rrw(ldx, _c); - case_rrr(ldx, _uc); - case_rrw(ldx, _uc); - case_rrr(ldx, _s); - case_rrw(ldx, _s); - case_rrr(ldx, _us); - case_rrw(ldx, _us); - case_rrr(ldx, _i); - case_rrw(ldx, _i); - case_rrr(ldx, _ui); - case_rrw(ldx, _ui); - case_rrr(ldx, _l); - case_rrw(ldx, _l); - case_rr(st, _c); - case_wr(st, _c); - case_rr(st, _s); - case_wr(st, _s); - case_rr(st, _i); - case_wr(st, _i); - case_rr(st, _l); - case_wr(st, _l); - case_rrr(stx, _c); - case_wrr(stx, _c); - case_rrr(stx, _s); - case_wrr(stx, _s); - case_rrr(stx, _i); - case_wrr(stx, _i); - case_rrr(stx, _l); - case_wrr(stx, _l); - case_rr(hton, _us); - case_rr(hton, _ui); - case_rr(hton, _ul); - case_rr(ext, _c); - case_rr(ext, _uc); - case_rr(ext, _s); - case_rr(ext, _us); - case_rr(ext, _i); - case_rr(ext, _ui); - case_rr(mov,); - case jit_code_movi: - if (node->flag & jit_flag_node) { - temp = node->v.n; - if (temp->code == jit_code_data || - (temp->code == jit_code_label && - (temp->flag & jit_flag_patch))) - movi(rn(node->u.w), temp->u.w); - else { - assert(temp->code == jit_code_label || - temp->code == jit_code_epilog); - word = movi_p(rn(node->u.w), temp->u.w); - patch(word, node); - } - } - else - movi(rn(node->u.w), node->v.w); - break; - case_rrr(lt,); - case_rrw(lt,); - case_rrr(lt, _u); - case_rrw(lt, _u); - case_rrr(le,); - case_rrw(le,); - case_rrr(le, _u); - case_rrw(le, _u); - case_rrr(eq,); - case_rrw(eq,); - case_rrr(ge,); - case_rrw(ge,); - case_rrr(ge, _u); - case_rrw(ge, _u); - case_rrr(gt,); - case_rrw(gt,); - case_rrr(gt, _u); - case_rrw(gt, _u); - case_rrr(ne,); - case_rrw(ne,); - case_brr(blt,); - case_brw(blt,); - case_brr(blt, _u); - case_brw(blt, _u); - case_brr(ble,); - case_brw(ble,); - case_brr(ble, _u); - case_brw(ble, _u); - case_brr(beq,); - case_brw(beq,); - case_brr(bge,); - case_brw(bge,); - case_brr(bge, _u); - case_brw(bge, _u); - case_brr(bgt,); - case_brw(bgt,); - case_brr(bgt, _u); - case_brw(bgt, _u); - case_brr(bne,); - case_brw(bne,); - case_brr(boadd,); - case_brw(boadd,); - case_brr(boadd, _u); - case_brw(boadd, _u); - case_brr(bxadd,); - case_brw(bxadd,); - case_brr(bxadd, _u); - case_brw(bxadd, _u); - case_brr(bosub,); - case_brw(bosub,); - case_brr(bosub, _u); - case_brw(bosub, _u); - case_brr(bxsub,); - case_brw(bxsub,); - case_brr(bxsub, _u); - case_brw(bxsub, _u); - case_brr(bms,); - case_brw(bms,); - case_brr(bmc,); - case_brw(bmc,); - case_rrr(add, _f); - case_rrf(add); - case_rrr(sub, _f); - case_rrf(sub); - case_rrf(rsb); - case_rrr(mul, _f); - case_rrf(mul); - case_rrr(div, _f); - case_rrf(div); - case_rr(abs, _f); - case_rr(neg, _f); - case_rr(sqrt, _f); - case_rr(ext, _f); - case_rr(ld, _f); - case_rw(ld, _f); - case_rrr(ldx, _f); - case_rrw(ldx, _f); - case_rr(st, _f); - case_wr(st, _f); - case_rrr(stx, _f); - case_wrr(stx, _f); - case_rr(mov, _f); - case jit_code_movi_f: - assert_data(node); - movi_f(rn(node->u.w), node->v.f); - break; - case_rr(ext, _d_f); - case_rrr(lt, _f); - case_rrf(lt); - case_rrr(le, _f); - case_rrf(le); - case_rrr(eq, _f); - case_rrf(eq); - case_rrr(ge, _f); - case_rrf(ge); - case_rrr(gt, _f); - case_rrf(gt); - case_rrr(ne, _f); - case_rrf(ne); - case_rrr(unlt, _f); - case_rrf(unlt); - case_rrr(unle, _f); - case_rrf(unle); - case_rrr(uneq, _f); - case_rrf(uneq); - case_rrr(unge, _f); - case_rrf(unge); - case_rrr(ungt, _f); - case_rrf(ungt); - case_rrr(ltgt, _f); - case_rrf(ltgt); - case_rrr(ord, _f); - case_rrf(ord); - case_rrr(unord, _f); - case_rrf(unord); - case_brr(blt, _f); - case_brf(blt); - case_brr(ble, _f); - case_brf(ble); - case_brr(beq, _f); - case_brf(beq); - case_brr(bge, _f); - case_brf(bge); - case_brr(bgt, _f); - case_brf(bgt); - case_brr(bne, _f); - case_brf(bne); - case_brr(bunlt, _f); - case_brf(bunlt); - case_brr(bunle, _f); - case_brf(bunle); - case_brr(buneq, _f); - case_brf(buneq); - case_brr(bunge, _f); - case_brf(bunge); - case_brr(bungt, _f); - case_brf(bungt); - case_brr(bltgt, _f); - case_brf(bltgt); - case_brr(bord, _f); - case_brf(bord); - case_brr(bunord, _f); - case_brf(bunord); - case_rrr(add, _d); - case_rrd(add); - case_rrr(sub, _d); - case_rrd(sub); - case_rrd(rsb); - case_rrr(mul, _d); - case_rrd(mul); - case_rrr(div, _d); - case_rrd(div); - case_rr(abs, _d); - case_rr(neg, _d); - case_rr(sqrt, _d); - case_rr(ext, _d); - case_rr(ld, _d); - case_rw(ld, _d); - case_rrr(ldx, _d); - case_rrw(ldx, _d); - case_rr(st, _d); - case_wr(st, _d); - case_rrr(stx, _d); - case_wrr(stx, _d); - case_rr(mov, _d); - case jit_code_movi_d: - assert_data(node); - movi_d(rn(node->u.w), node->v.d); - break; - case_rr(ext, _f_d); - case_rrr(lt, _d); - case_rrd(lt); - case_rrr(le, _d); - case_rrd(le); - case_rrr(eq, _d); - case_rrd(eq); - case_rrr(ge, _d); - case_rrd(ge); - case_rrr(gt, _d); - case_rrd(gt); - case_rrr(ne, _d); - case_rrd(ne); - case_rrr(unlt, _d); - case_rrd(unlt); - case_rrr(unle, _d); - case_rrd(unle); - case_rrr(uneq, _d); - case_rrd(uneq); - case_rrr(unge, _d); - case_rrd(unge); - case_rrr(ungt, _d); - case_rrd(ungt); - case_rrr(ltgt, _d); - case_rrd(ltgt); - case_rrr(ord, _d); - case_rrd(ord); - case_rrr(unord, _d); - case_rrd(unord); - case_brr(blt, _d); - case_brd(blt); - case_brr(ble, _d); - case_brd(ble); - case_brr(beq, _d); - case_brd(beq); - case_brr(bge, _d); - case_brd(bge); - case_brr(bgt, _d); - case_brd(bgt); - case_brr(bne, _d); - case_brd(bne); - case_brr(bunlt, _d); - case_brd(bunlt); - case_brr(bunle, _d); - case_brd(bunle); - case_brr(buneq, _d); - case_brd(buneq); - case_brr(bunge, _d); - case_brd(bunge); - case_brr(bungt, _d); - case_brd(bungt); - case_brr(bltgt, _d); - case_brd(bltgt); - case_brr(bord, _d); - case_brd(bord); - case_brr(bunord, _d); - case_brd(bunord); - case jit_code_jmpr: - jmpr(rn(node->u.w)); - break; - case jit_code_jmpi: - if (node->flag & jit_flag_node) { - temp = node->u.n; - assert(temp->code == jit_code_label || - temp->code == jit_code_epilog); - if (temp->flag & jit_flag_patch) - jmpi(temp->u.w); - else { - word = jmpi_p(_jit->pc.w); - patch(word, node); - } - } - else - jmpi(node->u.w); - break; - case jit_code_callr: - callr(rn(node->u.w)); - break; - case jit_code_calli: - if (node->flag & jit_flag_node) { - temp = node->u.n; - assert(temp->code == jit_code_label || - temp->code == jit_code_epilog); - if (temp->flag & jit_flag_patch) - calli(temp->u.w); - else { - word = calli_p(_jit->pc.w); - patch(word, node); - } - } - else - calli(node->u.w); - break; - case jit_code_prolog: - _jitc->function = _jitc->functions.ptr + node->w.w; - undo.node = node; - undo.word = _jit->pc.w; -#if DEVEL_DISASSEMBLER - undo.prevw = prevw; -#endif - undo.patch_offset = _jitc->patches.offset; - restart_function: - _jitc->again = 0; - prolog(node); - break; - case jit_code_epilog: - assert(_jitc->function == _jitc->functions.ptr + node->w.w); - if (_jitc->again) { - for (temp = undo.node->next; - temp != node; temp = temp->next) { - if (temp->code == jit_code_label || - temp->code == jit_code_epilog) - temp->flag &= ~jit_flag_patch; - } - temp->flag &= ~jit_flag_patch; - node = undo.node; - _jit->pc.w = undo.word; -#if DEVEL_DISASSEMBLER - prevw = undo.prevw; -#endif - _jitc->patches.offset = undo.patch_offset; - goto restart_function; - } - /* remember label is defined */ - node->flag |= jit_flag_patch; - node->u.w = _jit->pc.w; - epilog(node); - _jitc->function = NULL; - break; - case jit_code_va_start: - vastart(rn(node->u.w)); - break; - case jit_code_va_arg: - vaarg(rn(node->u.w), rn(node->v.w)); - break; - case jit_code_va_arg_d: - vaarg_d(rn(node->u.w), rn(node->v.w)); - break; - case jit_code_live: case jit_code_ellipsis: - case jit_code_va_push: - case jit_code_allocai: case jit_code_allocar: - case jit_code_arg: - case jit_code_arg_f: case jit_code_arg_d: - case jit_code_va_end: - case jit_code_ret: - case jit_code_retr: case jit_code_reti: - case jit_code_retr_f: case jit_code_reti_f: - case jit_code_retr_d: case jit_code_reti_d: - case jit_code_getarg_c: case jit_code_getarg_uc: - case jit_code_getarg_s: case jit_code_getarg_us: - case jit_code_getarg_i: case jit_code_getarg_ui: - case jit_code_getarg_l: - case jit_code_getarg_f: case jit_code_getarg_d: - case jit_code_putargr: case jit_code_putargi: - case jit_code_putargr_f: case jit_code_putargi_f: - case jit_code_putargr_d: case jit_code_putargi_d: - case jit_code_pushargr: case jit_code_pushargi: - case jit_code_pushargr_f: case jit_code_pushargi_f: - case jit_code_pushargr_d: case jit_code_pushargi_d: - case jit_code_retval_c: case jit_code_retval_uc: - case jit_code_retval_s: case jit_code_retval_us: - case jit_code_retval_i: - case jit_code_retval_ui: case jit_code_retval_l: - case jit_code_retval_f: case jit_code_retval_d: - case jit_code_prepare: - case jit_code_finishr: case jit_code_finishi: - break; - default: - abort(); - } - jit_regarg_clr(node, value); - assert(_jitc->regarg == 0 && _jitc->synth == 0); - /* update register live state */ - jit_reglive(node); - } -#undef case_brw -#undef case_brr -#undef case_wrr -#undef case_rrw -#undef case_rrr -#undef case_wr -#undef case_rw -#undef case_rr - - for (offset = 0; offset < _jitc->patches.offset; offset++) { - node = _jitc->patches.ptr[offset].node; - word = _jitc->patches.ptr[offset].inst; - value = node->code == jit_code_movi ? node->v.n->u.w : node->u.n->u.w; - patch_at(word, value); - } - - jit_flush(_jit->code.ptr, _jit->pc.uc); - - return (_jit->code.ptr); -} - -#define CODE 1 -# include "aarch64-cpu.c" -# include ", 2018aarch64-fpu.c" -#undef CODE - void jit_flush(void *fptr, void *tptr) { -#if defined(__GNUC__) - jit_word_t f, t, s; - - s = sysconf(_SC_PAGE_SIZE); - f = (jit_word_t)fptr & -s; - t = (((jit_word_t)tptr) + s - 1) & -s; - __clear_cache((void *)f, (void *)t); -#endif + jit_word_t f = (jit_word_t)fptr & -page_size; + jit_word_t t = (((jit_word_t)tptr) + page_size - 1) & -page_size; + __clear_cache((void *)f, (void *)t); } -void -_emit_ldxi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +static inline size_t +jit_stack_alignment(void) { - ldxi(rn(r0), rn(r1), i0); -} - -void -_emit_stxi(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) -{ - stxi(i0, rn(r0), rn(r1)); -} - -void -_emit_ldxi_d(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) -{ - ldxi_d(rn(r0), rn(r1), i0); -} - -void -_emit_stxi_d(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) -{ - stxi_d(i0, rn(r0), rn(r1)); -} - -static void -_patch(jit_state_t *_jit, jit_word_t instr, jit_node_t *node) -{ - int32_t flag; - - assert(node->flag & jit_flag_node); - if (node->code == jit_code_movi) - flag = node->v.n->flag; - else - flag = node->u.n->flag; - assert(!(flag & jit_flag_patch)); - if (_jitc->patches.offset >= _jitc->patches.length) { - jit_realloc((jit_pointer_t *)&_jitc->patches.ptr, - _jitc->patches.length * sizeof(jit_patch_t), - (_jitc->patches.length + 1024) * sizeof(jit_patch_t)); - _jitc->patches.length += 1024; - } - _jitc->patches.ptr[_jitc->patches.offset].inst = instr; - _jitc->patches.ptr[_jitc->patches.offset].node = node; - ++_jitc->patches.offset; + return 16; } diff --git a/lightening/aarch64.h b/lightening/aarch64.h index 65723a6d2..3916d0def 100644 --- a/lightening/aarch64.h +++ b/lightening/aarch64.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2017 Free Software Foundation, Inc. + * Copyright (C) 2013-2017, 2019 Free Software Foundation, Inc. * * This file is part of GNU lightning. * @@ -20,70 +20,161 @@ #ifndef _jit_aarch64_h #define _jit_aarch64_h -#define JIT_HASH_CONSTS 0 -#define JIT_NUM_OPERANDS 3 -/* - * Types - */ -#define JIT_FP _R29 -typedef enum { -#define jit_r(i) (_R9 + (i)) -#define jit_r_num() 7 -#define jit_v(i) (_R19 + (i)) -#define jit_v_num() 10 -#define jit_f(i) (_V8 + (i)) -#define jit_f_num() 8 -#define JIT_R0 _R9 -#define JIT_R1 _R10 -#define JIT_R2 _R11 -#define JIT_R3 _R12 -#define JIT_R4 _R13 -#define JIT_R5 _R14 -#define JIT_R6 _R15 - _R8, /* indirect result */ - _R18, /* platform register */ - _R17, /* IP1 */ - _R16, /* IP0 */ - _R9, _R10, _R11, _R12, /* temporaries */ - _R13, _R14, _R15, -#define JIT_V0 _R19 -#define JIT_V1 _R20 -#define JIT_V2 _R21 -#define JIT_V3 _R22 -#define JIT_V4 _R23 -#define JIT_V5 _R24 -#define JIT_V6 _R25 -#define JIT_V7 _R26 -#define JIT_V8 _R27 -#define JIT_V9 _R28 - _R19, _R20, _R21, _R22, /* callee save */ - _R23, _R24, _R25, _R26, - _R27, _R28, - _SP, /* stack pointer */ - _R30, /* link register */ - _R29, /* frame pointer */ - _R7, _R6, _R5, _R4, - _R3, _R2, _R1, _R0, -#define JIT_F0 _V8 -#define JIT_F1 _V9 -#define JIT_F2 _V10 -#define JIT_F3 _V11 -#define JIT_F4 _V12 -#define JIT_F5 _V13 -#define JIT_F6 _V14 -#define JIT_F7 _V15 - _V31, _V30, _V29, _V28, /* temporaries */ - _V27, _V26, _V25, _V24, - _V23, _V22, _V21, _V20, - _V19, _V18, _V17, _V16, - /* callee save */ - _V8, _V9, _V10, _V11, - _V12, _V13, _V14, _V15, - _V7, _V6, _V5, _V4, /* arguments */ - _V3, _V2, _V1, _V0, - _NOREG, -#define JIT_NOREG _NOREG -} jit_reg_t; +#define JIT_NEEDS_LITERAL_POOL 1 + +#define _X0 JIT_GPR(0) +#define _X1 JIT_GPR(1) +#define _X2 JIT_GPR(2) +#define _X3 JIT_GPR(3) +#define _X4 JIT_GPR(4) +#define _X5 JIT_GPR(5) +#define _X6 JIT_GPR(6) +#define _X7 JIT_GPR(7) +#define _X8 JIT_GPR(8) +#define _X9 JIT_GPR(9) +#define _X10 JIT_GPR(10) +#define _X11 JIT_GPR(11) +#define _X12 JIT_GPR(12) +#define _X13 JIT_GPR(13) +#define _X14 JIT_GPR(14) +#define _X15 JIT_GPR(15) +#define _X16 JIT_GPR(16) +#define _X17 JIT_GPR(17) +#define _X18 JIT_GPR(18) +#define _X19 JIT_GPR(19) +#define _X20 JIT_GPR(20) +#define _X21 JIT_GPR(21) +#define _X22 JIT_GPR(22) +#define _X23 JIT_GPR(23) +#define _X24 JIT_GPR(24) +#define _X25 JIT_GPR(25) +#define _X26 JIT_GPR(26) +#define _X27 JIT_GPR(27) +#define _X28 JIT_GPR(28) +#define _X29 JIT_GPR(29) +#define _X30 JIT_GPR(30) +#define _X31 JIT_GPR(31) + +#define _D0 JIT_FPR(0) +#define _D1 JIT_FPR(1) +#define _D2 JIT_FPR(2) +#define _D3 JIT_FPR(3) +#define _D4 JIT_FPR(4) +#define _D5 JIT_FPR(5) +#define _D6 JIT_FPR(6) +#define _D7 JIT_FPR(7) +#define _D8 JIT_FPR(8) +#define _D9 JIT_FPR(9) +#define _D10 JIT_FPR(10) +#define _D11 JIT_FPR(11) +#define _D12 JIT_FPR(12) +#define _D13 JIT_FPR(13) +#define _D14 JIT_FPR(14) +#define _D15 JIT_FPR(15) +#define _D16 JIT_FPR(16) +#define _D17 JIT_FPR(17) +#define _D18 JIT_FPR(18) +#define _D19 JIT_FPR(19) +#define _D20 JIT_FPR(20) +#define _D21 JIT_FPR(21) +#define _D22 JIT_FPR(22) +#define _D23 JIT_FPR(23) +#define _D24 JIT_FPR(24) +#define _D25 JIT_FPR(25) +#define _D26 JIT_FPR(26) +#define _D27 JIT_FPR(27) +#define _D28 JIT_FPR(28) +#define _D29 JIT_FPR(29) +#define _D30 JIT_FPR(30) +#define _D31 JIT_FPR(31) + +static inline jit_bool_t +jit_gpr_is_callee_save (jit_gpr_t reg) +{ + // x19 to x28 are callee-save, and x29 is the frame pointer. + return 19 <= jit_gpr_regno (reg) && jit_gpr_regno (reg) <= 29; +} + +static inline jit_bool_t +jit_fpr_is_callee_save (jit_fpr_t reg) +{ + // v8 to v15 are callee-save. + return 8 <= jit_fpr_regno (reg) && jit_fpr_regno (reg) <= 15; +} + +#define JIT_R0 _X0 +#define JIT_R1 _X1 +#define JIT_R2 _X2 +#define JIT_R3 _X3 +#define JIT_R4 _X4 +#define JIT_R5 _X5 +#define JIT_R6 _X6 +#define JIT_R7 _X7 +#define JIT_R8 _X8 +#define JIT_R9 _X9 +#define JIT_R10 _X10 +#define JIT_R11 _X11 +#define JIT_R12 _X12 +#define JIT_R13 _X13 +#define JIT_R14 _X14 +#define JIT_R15 _X15 +#define JIT_R16 _X16 +#define JIT_R17 _X17 +#define JIT_RTMP _X18 +#define JIT_V0 _X19 +#define JIT_V1 _X20 +#define JIT_V2 _X21 +#define JIT_V3 _X22 +#define JIT_V4 _X23 +#define JIT_V5 _X24 +#define JIT_V6 _X25 +#define JIT_V7 _X26 +#define JIT_V8 _X27 +#define JIT_V9 _X28 +// x29 is frame pointer +// x30 is link register +// x31 is stack pointer + +#define JIT_SP _X31 + +#define JIT_F0 _D0 +#define JIT_F1 _D1 +#define JIT_F2 _D2 +#define JIT_F3 _D3 +#define JIT_F4 _D4 +#define JIT_F5 _D5 +#define JIT_F6 _D6 +#define JIT_F7 _D7 +#define JIT_F8 _D16 +#define JIT_F9 _D17 +#define JIT_F10 _D18 +#define JIT_F11 _D19 +#define JIT_F12 _D20 +#define JIT_F13 _D21 +#define JIT_F14 _D22 +#define JIT_F15 _D23 +#define JIT_F16 _D24 +#define JIT_F17 _D25 +#define JIT_F18 _D26 +#define JIT_F19 _D27 +#define JIT_F20 _D28 +#define JIT_F21 _D29 +#define JIT_F22 _D30 +#define JIT_FTMP _D31 + +#define JIT_VF0 _D8 +#define JIT_VF1 _D9 +#define JIT_VF2 _D10 +#define JIT_VF3 _D11 +#define JIT_VF4 _D12 +#define JIT_VF5 _D13 +#define JIT_VF6 _D14 +#define JIT_VF7 _D15 + +#define _FP _X29 +#define _LR _X30 +#define _SP _X31 + #endif /* _jit_aarch64_h */ From 0bfdcc7016d2c2b7ca0e28de4e44bb2c1cfb0df0 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Tue, 14 May 2019 15:53:25 +0200 Subject: [PATCH 04/33] Refactor to add support for constant tables, shifted relocs --- lightening.h | 7 ++ lightening/lightening.c | 248 +++++++++++++++++++++++++++++++++------- lightening/x86-cpu.c | 8 +- lightening/x86.c | 36 +++++- 4 files changed, 249 insertions(+), 50 deletions(-) diff --git a/lightening.h b/lightening.h index c36d73cb3..b0071aadc 100644 --- a/lightening.h +++ b/lightening.h @@ -86,12 +86,19 @@ enum jit_reloc_kind JIT_RELOC_REL16, JIT_RELOC_REL32, JIT_RELOC_REL64, +#ifdef JIT_NEEDS_LITERAL_POOL + JIT_RELOC_JMP_WITH_VENEER, + JIT_RELOC_JCC_WITH_VENEER, + JIT_RELOC_LOAD_FROM_POOL, +#endif }; typedef struct jit_reloc { uint8_t kind; uint8_t inst_start_offset; + uint8_t pc_base_offset; + uint8_t rsh; uint32_t offset; } jit_reloc_t; diff --git a/lightening/lightening.c b/lightening/lightening.c index 49ab5abec..3d1b26a1e 100644 --- a/lightening/lightening.c +++ b/lightening/lightening.c @@ -29,14 +29,16 @@ #include "../lightening.h" +#define ASSERT(x) do { if (!(x)) abort(); } while (0) + #if defined(__GNUC__) # define maybe_unused __attribute__ ((unused)) +# define UNLIKELY(exprn) __builtin_expect(exprn, 0) #else # define maybe_unused /**/ +# define UNLIKELY(exprn) exprn #endif -#define _NOREG 0xffff - union jit_pc { uint8_t *uc; @@ -47,6 +49,22 @@ union jit_pc uintptr_t uw; }; +#ifdef JIT_NEEDS_LITERAL_POOL +struct jit_literal_pool_entry +{ + jit_reloc_t reloc; + int64_t value; +}; + +struct jit_literal_pool +{ + uint32_t deadline; + uint32_t size; + uint32_t capacity; + struct jit_literal_pool_entry entries[]; +}; +#endif // JIT_NEEDS_LITERAL_POOL + struct jit_state { union jit_pc pc; @@ -57,17 +75,13 @@ struct jit_state uint8_t temp_fpr_saved; uint8_t overflow; int frame_size; // Used to know when to align stack. +#ifdef JIT_NEEDS_LITERAL_POOL + struct jit_literal_pool *pool; +#endif void* (*alloc)(size_t); void (*free)(void*); }; -#define ASSERT(x) do { if (!(x)) abort(); } while (0) -#if defined(__GNUC__) -# define UNLIKELY(exprn) __builtin_expect(exprn, 0) -#else -# define UNLIKELY(exprn) exprn -#endif - static jit_bool_t jit_get_cpu(void); static jit_bool_t jit_init(jit_state_t *); static void jit_flush(void *fptr, void *tptr); @@ -76,6 +90,112 @@ static void jit_try_shorten(jit_state_t *_jit, jit_reloc_t reloc, struct abi_arg_iterator; +#ifdef JIT_NEEDS_LITERAL_POOL +#define INITIAL_LITERAL_POOL_CAPACITY 12 +static struct jit_literal_pool* +alloc_literal_pool(jit_state_t *_jit, size_t capacity) +{ + struct jit_literal_pool *ret = + _jit->alloc (sizeof (struct jit_literal_pool) + + sizeof (struct jit_literal_pool_entry) * capacity); + ASSERT (ret); + ret->deadline = -1; + ret->size = 0; + ret->capacity = capacity; + return ret; +} + +static void +clear_literal_pool(struct jit_literal_pool *pool) +{ + pool->deadline = -1; + pool->size = 0; +} + +static void +grow_literal_pool(jit_state_t *_jit) +{ + struct jit_literal_pool *new_pool = + alloc_literal_pool(_jit, _jit->pool->capacity * 2); + + for (size_t i = 0; i < _jit->pool->size; i++) + new_pool->entries[new_pool->size++] = _jit->pool->entries[i]; + new_pool->deadline = _jit->pool->deadline; + + _jit->free (_jit->pool); + _jit->pool = new_pool; +} + +static void +add_literal_pool_entry(jit_state_t *_jit, struct jit_literal_pool_entry entry, + ptrdiff_t max_offset) +{ + if (_jit->pool->size == _jit->pool->capacity) + grow_literal_pool (_jit); + + max_offset <<= entry.reloc.rsh; + ptrdiff_t deadline = _jit->pc.uc - _jit->start + max_offset; + if (_jit->pool->size == 0) + // Assume that we might need a uint32_t for alignment, and another + // to branch over the table. + _jit->pool->deadline = deadline - 2 * sizeof(uint32_t); + else if (deadline < _jit->pool->deadline) + _jit->pool->deadline = deadline; + + // Assume that each entry takes a max of 16 bytes; + _jit->pool->deadline -= 16; + + _jit->pool->entries[_jit->pool->size++] = entry; +} + +static void +add_pending_literal(jit_state_t *_jit, jit_reloc_t src, + ptrdiff_t max_offset_bits) +{ + struct jit_literal_pool_entry entry = { src, 0 }; + add_literal_pool_entry(_jit, entry, + (1 << (max_offset_bits + src.rsh)) - 1); +} + +static void +remove_pending_literal(jit_state_t *_jit, jit_reloc_t src) +{ + for (size_t i = _jit->pool->size; i--; ) { + if (_jit->pool->entries[i].reloc.offset == src.offset) { + for (size_t j = i + 1; j < _jit->pool->size; j++) { + _jit->pool->entries[j-1] = _jit->pool->entries[j]; + _jit->pool->size--; + return; + } + } + } + abort(); +} + +static void +patch_pending_literal(jit_state_t *_jit, jit_reloc_t src, uint64_t value) +{ + for (size_t i = _jit->pool->size; i--; ) { + if (_jit->pool->entries[i].reloc.offset == src.offset) { + ASSERT(_jit->pool->entries[i].value == 0); + _jit->pool->entries[i].value = value; + return; + } + } + abort(); +} + +static void add_load_from_pool(jit_state_t *_jit, jit_reloc_t src); +static int32_t read_jmp_offset(uint32_t *loc); +static int offset_in_jmp_range(ptrdiff_t offset); +static void patch_jmp_offset(uint32_t *loc, ptrdiff_t offset); +static int32_t read_jcc_offset(uint32_t *loc); +static int offset_in_jcc_range(ptrdiff_t offset); +static void patch_jcc_offset(uint32_t *loc, ptrdiff_t offset); +static void patch_veneer(uint32_t *loc, jit_pointer_t addr); +static int32_t read_load_from_pool_offset(uint32_t *loc); +#endif + static jit_bool_t is_fpr_arg(enum jit_operand_abi arg); static jit_bool_t is_gpr_arg(enum jit_operand_abi arg); static void reset_abi_arg_iterator(struct abi_arg_iterator *iter, size_t argc, @@ -104,16 +224,26 @@ jit_new_state(void* (*alloc_fn)(size_t), void (*free_fn)(void*)) _jit->free = free_fn; if (!jit_init (_jit)) { +#ifdef JIT_NEEDS_LITERAL_POOL + free_fn (_jit->pool); +#endif free_fn (_jit); return NULL; } +#ifdef JIT_NEEDS_LITERAL_POOL + _jit->pool = alloc_literal_pool(_jit, INITIAL_LITERAL_POOL_CAPACITY); +#endif + return _jit; } void jit_destroy_state(jit_state_t *_jit) { +#ifdef JIT_NEEDS_LITERAL_POOL + _jit->free (_jit->pool); +#endif _jit->free (_jit); } @@ -133,6 +263,9 @@ jit_begin(jit_state_t *_jit, uint8_t* buf, size_t length) _jit->limit = buf + length; _jit->overflow = 0; _jit->frame_size = 0; +#ifdef JIT_NEEDS_LITERAL_POOL + clear_literal_pool(_jit->pool); +#endif } jit_bool_t @@ -149,6 +282,9 @@ jit_reset(jit_state_t *_jit) _jit->pc.uc = _jit->start = _jit->limit = NULL; _jit->overflow = 0; _jit->frame_size = 0; +#ifdef JIT_NEEDS_LITERAL_POOL + clear_literal_pool(_jit->pool); +#endif } void* @@ -171,6 +307,9 @@ jit_end(jit_state_t *_jit, size_t *length) _jit->pc.uc = _jit->start = _jit->limit = NULL; _jit->overflow = 0; _jit->frame_size = 0; +#ifdef JIT_NEEDS_LITERAL_POOL + clear_literal_pool(_jit->pool); +#endif return code; } @@ -259,38 +398,21 @@ static inline void emit_u64(jit_state_t *_jit, uint64_t u64) { static inline jit_reloc_t jit_reloc (jit_state_t *_jit, enum jit_reloc_kind kind, - uint8_t inst_start_offset) + uint8_t inst_start_offset, uint8_t *loc, uint8_t *pc_base, + uint8_t rsh) { jit_reloc_t ret; + ASSERT(rsh < __WORDSIZE); + ASSERT(pc_base >= (loc - inst_start_offset)); + ASSERT(pc_base - (loc - inst_start_offset) < 256); + ret.kind = kind; ret.inst_start_offset = inst_start_offset; - ret.offset = _jit->pc.uc - _jit->start; + ret.pc_base_offset = pc_base - (loc - inst_start_offset); + ret.rsh = rsh; + ret.offset = loc - _jit->start; - switch (kind) - { - case JIT_RELOC_ABSOLUTE: - if (sizeof(intptr_t) == 4) - emit_u32 (_jit, 0); - else - emit_u64 (_jit, 0); - break; - case JIT_RELOC_REL8: - emit_u8 (_jit, 0); - break; - case JIT_RELOC_REL16: - emit_u16 (_jit, 0); - break; - case JIT_RELOC_REL32: - emit_u32 (_jit, 0); - break; - case JIT_RELOC_REL64: - emit_u64 (_jit, 0); - break; - default: - abort (); - } - return ret; } @@ -308,7 +430,10 @@ jit_patch_there(jit_state_t* _jit, jit_reloc_t reloc, jit_pointer_t addr) union jit_pc loc; uint8_t *end; loc.uc = _jit->start + reloc.offset; - ptrdiff_t diff; + uint8_t *pc_base = loc.uc - reloc.inst_start_offset + reloc.pc_base_offset; + ptrdiff_t diff = (uint8_t*)addr - pc_base; + ASSERT((diff & ((1 << reloc.rsh) - 1)) == 0); + diff >>= reloc.rsh; switch (reloc.kind) { @@ -320,25 +445,68 @@ jit_patch_there(jit_state_t* _jit, jit_reloc_t reloc, jit_pointer_t addr) end = loc.uc + sizeof(diff); break; case JIT_RELOC_REL8: - diff = ((uint8_t*)addr) - (loc.uc + 1); ASSERT (INT8_MIN <= diff && diff <= INT8_MAX); *loc.uc = diff; end = loc.uc + 1; break; case JIT_RELOC_REL16: - diff = ((uint8_t*)addr) - (loc.uc + 2); ASSERT (INT16_MIN <= diff && diff <= INT16_MAX); *loc.us = diff; end = loc.uc + 2; break; +#ifdef JIT_NEEDS_LITERAL_POOL + case JIT_RELOC_JMP_WITH_VENEER: { + int32_t voff = read_jmp_offset(loc.ui); + if (voff == 0) { + // PC still in range to reify direct branch. + if (offset_in_jmp_range(diff)) { + // Target also in range: reify direct branch. + patch_jmp_offset(loc.ui, diff); + remove_pending_literal(_jit, reloc); + } else { + // Target out of range; branch to veneer. + patch_pending_literal(_jit, reloc, (uint64_t) addr); + } + } else { + // Already emitted a veneer. In this case, patch the veneer + // directly. + uint8_t *target = pc_base + (voff << reloc.rsh); + patch_veneer((uint32_t *) target, addr); + } + return; + } + case JIT_RELOC_JCC_WITH_VENEER: { + uint32_t voff = read_jcc_offset(loc.ui); + if (voff == 0) { + if (offset_in_jcc_range(diff)) { + patch_jcc_offset(loc.ui, diff); + remove_pending_literal(_jit, reloc); + } else { + patch_pending_literal(_jit, reloc, (uint64_t) addr); + } + } else { + uint8_t *target = pc_base + (voff << reloc.rsh); + patch_veneer((uint32_t *) target, addr); + } + return; + } + case JIT_RELOC_LOAD_FROM_POOL: { + uint32_t voff = read_load_from_pool_offset(loc.ui); + if (voff == 0) { + patch_pending_literal(_jit, reloc, (uint64_t) addr); + } else { + uint8_t *target = pc_base + (voff << reloc.rsh); + *(uintptr_t *) target = (uintptr_t) addr; + } + return; + } +#endif case JIT_RELOC_REL32: - diff = ((uint8_t*)addr) - (loc.uc + 4); ASSERT (INT32_MIN <= diff && diff <= INT32_MAX); *loc.ui = diff; end = loc.uc + 4; break; case JIT_RELOC_REL64: - diff = ((uint8_t*)addr) - (loc.uc + 8); *loc.ul = diff; end = loc.uc + 8; break; diff --git a/lightening/x86-cpu.c b/lightening/x86-cpu.c index 0b39e5a15..ab0da684e 100644 --- a/lightening/x86-cpu.c +++ b/lightening/x86-cpu.c @@ -378,7 +378,7 @@ mov_addr(jit_state_t *_jit, int32_t r0) rex(_jit, 0, WIDE, _NOREG, _NOREG, r0); ic(_jit, 0xb8 | r7(r0)); ptrdiff_t inst_start = _jit->pc.uc - pc_start; - return jit_reloc(_jit, JIT_RELOC_ABSOLUTE, inst_start); + return emit_abs_reloc(_jit, inst_start); } static void @@ -2109,7 +2109,7 @@ static jit_reloc_t jccs(jit_state_t *_jit, int32_t code) { ic(_jit, 0x70 | code); - return jit_reloc(_jit, JIT_RELOC_REL8, 1); + return emit_rel8_reloc(_jit, 1); } static jit_reloc_t @@ -2117,7 +2117,7 @@ jcc(jit_state_t *_jit, int32_t code) { ic(_jit, 0x0f); ic(_jit, 0x80 | code); - return jit_reloc(_jit, JIT_RELOC_REL32, 2); + return emit_rel32_reloc(_jit, 2); } static void @@ -2564,7 +2564,7 @@ static jit_reloc_t jmp(jit_state_t *_jit) { ic(_jit, 0xe9); - return jit_reloc(_jit, JIT_RELOC_REL32, 1); + return emit_rel32_reloc(_jit, 1); } static void diff --git a/lightening/x86.c b/lightening/x86.c index e1665bb88..9ff925031 100644 --- a/lightening/x86.c +++ b/lightening/x86.c @@ -17,6 +17,8 @@ * Paulo Cesar Pereira de Andrade */ +#define _NOREG 0xffff + typedef struct { /* x87 present */ uint32_t fpu : 1; @@ -58,6 +60,33 @@ typedef struct { static jit_cpu_t jit_cpu; +static inline jit_reloc_t +emit_rel8_reloc (jit_state_t *_jit, uint8_t inst_start) +{ + uint8_t *loc = _jit->pc.uc; + emit_u8 (_jit, 0); + return jit_reloc(_jit, JIT_RELOC_REL8, inst_start, loc, _jit->pc.uc, 0); +} + +static inline jit_reloc_t +emit_rel32_reloc (jit_state_t *_jit, uint8_t inst_start) +{ + uint8_t *loc = _jit->pc.uc; + emit_u32 (_jit, 0); + return jit_reloc(_jit, JIT_RELOC_REL32, inst_start, loc, _jit->pc.uc, 0); +} + +static inline jit_reloc_t +emit_abs_reloc (jit_state_t *_jit, uint8_t inst_start) +{ + uint8_t *loc = _jit->pc.uc; + if (sizeof(intptr_t) == 4) + emit_u32 (_jit, 0); + else + emit_u64 (_jit, 0); + return jit_reloc(_jit, JIT_RELOC_ABSOLUTE, inst_start, loc, _jit->pc.uc, 0); +} + #include "x86-cpu.c" #include "x86-sse.c" @@ -358,9 +387,6 @@ jit_try_shorten(jit_state_t *_jit, jit_reloc_t reloc, jit_pointer_t addr) ASSERT((loc[-1] & ~0xf) == 0x70 || loc[-1] == 0xeb); // JCCSI or JMPSI /* Nothing useful to do. */ return; - case JIT_RELOC_REL16: - /* We don't emit these. */ - abort (); case JIT_RELOC_REL32: _jit->pc.uc = start; if (start[0] == 0xe9) { // JMP @@ -368,10 +394,8 @@ jit_try_shorten(jit_state_t *_jit, jit_reloc_t reloc, jit_pointer_t addr) } ASSERT(start[0] == 0x0f); // JCC return jcci(_jit, start[1] & ~0x80, i0); - case JIT_RELOC_REL64: - /* We don't emit these. */ - abort (); default: + /* We don't emit other kinds of reloc. */ abort (); } } From 5b8262e804acc72cd6f4b3e99b28857115d69ac8 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Wed, 15 May 2019 15:41:02 +0200 Subject: [PATCH 05/33] Rework register saving to avoid push/pop Push and pop are not well supported on AArch64, so we might as well just bump the stack pointer once and fill in by offset. --- lightening.h | 5 - lightening/aarch64-cpu.c | 534 ++++++--------------------------------- lightening/aarch64-fpu.c | 60 ++--- lightening/aarch64.c | 96 +++++-- lightening/aarch64.h | 12 +- lightening/lightening.c | 72 +++--- lightening/x86-sse.c | 18 -- lightening/x86.h | 5 +- tests/pushpop.c | 35 --- 9 files changed, 206 insertions(+), 631 deletions(-) delete mode 100644 tests/pushpop.c diff --git a/lightening.h b/lightening.h index b0071aadc..6fe49ce17 100644 --- a/lightening.h +++ b/lightening.h @@ -580,11 +580,6 @@ jit_load_args_3(jit_state_t *_jit, jit_operand_t a, jit_operand_t b, M(_p___, jmpi) \ M(R____, jmp) \ \ - M(_G___, pushr) \ - M(_F___, pushr_d) \ - M(_G___, popr) \ - M(_F___, popr_d) \ - \ M(_____, ret) \ M(_G___, retr) \ M(_F___, retr_f) \ diff --git a/lightening/aarch64-cpu.c b/lightening/aarch64-cpu.c index 0a1f01eb1..a33128a6f 100644 --- a/lightening/aarch64-cpu.c +++ b/lightening/aarch64-cpu.c @@ -21,132 +21,6 @@ #error AArch64 requires little-endian host #endif -typedef union { - /* cond2: condition in truly conditional-executed inst. */ - struct { uint32_t b: 4; } cond2; - /* nzcv: flag bit specifier, encoded in the "nzcv" field. */ - struct { uint32_t b: 4; } nzcv; - /* defgh: d:e:f:g:h bits in AdvSIMD modified immediate. */ - struct { uint32_t _: 5; uint32_t b: 5; } defgh; - /* abc: a:b:c bits in AdvSIMD modified immediate. */ - struct { uint32_t _: 16; uint32_t b: 3; } abc; - /* imm19: e.g. in CBZ. */ - struct { uint32_t _: 5; uint32_t b: 19; } imm19; - /* immhi: e.g. in ADRP. */ - struct { uint32_t _: 5; uint32_t b: 19; } immhi; - /* immlo: e.g. in ADRP. */ - struct { uint32_t _: 29; uint32_t b: 2; } immlo; - /* size: in most AdvSIMD and floating-point instructions. */ - struct { uint32_t _: 22; uint32_t b: 2; } size; - /* vldst_size: size field in the AdvSIMD load/store inst. */ - struct { uint32_t _: 10; uint32_t b: 2; } vldst_size; - /* op: in AdvSIMD modified immediate instructions. */ - struct { uint32_t _: 29; uint32_t b: 1; } op; - /* Q: in most AdvSIMD instructions. */ - struct { uint32_t _: 30; uint32_t b: 1; } Q; - /* Rt: in load/store instructions. */ - struct { uint32_t b: 5; } Rt; - /* Rd: in many integer instructions. */ - struct { uint32_t b: 5; } Rd; - /* Rn: in many integer instructions. */ - struct { uint32_t _: 5; uint32_t b: 5; } Rn; - /* Rt2: in load/store pair instructions. */ - struct { uint32_t _: 10; uint32_t b: 5; } Rt2; - /* Ra: in fp instructions. */ - struct { uint32_t _: 10; uint32_t b: 5; } Ra; - /* op2: in the system instructions. */ - struct { uint32_t _: 5; uint32_t b: 3; } op2; - /* CRm: in the system instructions. */ - struct { uint32_t _: 8; uint32_t b: 4; } CRm; - /* CRn: in the system instructions. */ - struct { uint32_t _: 12; uint32_t b: 4; } CRn; - /* op1: in the system instructions. */ - struct { uint32_t _: 16; uint32_t b: 3; } op1; - /* op0: in the system instructions. */ - struct { uint32_t _: 19; uint32_t b: 2; } op0; - /* imm3: in add/sub extended reg instructions. */ - struct { uint32_t _: 10; uint32_t b: 3; } imm3; - /* cond: condition flags as a source operand. */ - struct { uint32_t _: 12; uint32_t b: 4; } cond; - /* opcode: in advsimd load/store instructions. */ - struct { uint32_t _: 12; uint32_t b: 4; } opcode; - /* cmode: in advsimd modified immediate instructions. */ - struct { uint32_t _: 12; uint32_t b: 4; } cmode; - /* asisdlso_opcode: opcode in advsimd ld/st single element. */ - struct { uint32_t _: 13; uint32_t b: 3; } asisdlso_opcode; - /* len: in advsimd tbl/tbx instructions. */ - struct { uint32_t _: 13; uint32_t b: 2; } len; - /* Rm: in ld/st reg offset and some integer inst. */ - struct { uint32_t _: 16; uint32_t b: 5; } Rm; - /* Rs: in load/store exclusive instructions. */ - struct { uint32_t _: 16; uint32_t b: 5; } Rs; - /* option: in ld/st reg offset + add/sub extended reg inst. */ - struct { uint32_t _: 13; uint32_t b: 3; } option; - /* S: in load/store reg offset instructions. */ - struct { uint32_t _: 12; uint32_t b: 1; } S; - /* hw: in move wide constant instructions. */ - struct { uint32_t _: 21; uint32_t b: 2; } hw; - /* opc: in load/store reg offset instructions. */ - struct { uint32_t _: 22; uint32_t b: 2; } opc; - /* opc1: in load/store reg offset instructions. */ - struct { uint32_t _: 23; uint32_t b: 1; } opc1; - /* shift: in add/sub reg/imm shifted instructions. */ - struct { uint32_t _: 22; uint32_t b: 2; } shift; - /* type: floating point type field in fp data inst. */ - struct { uint32_t _: 22; uint32_t b: 2; } type; - /* ldst_size: size field in ld/st reg offset inst. */ - struct { uint32_t _: 30; uint32_t b: 2; } ldst_size; - /* imm6: in add/sub reg shifted instructions. */ - struct { uint32_t _: 10; uint32_t b: 6; } imm6; - /* imm4: in advsimd ext and advsimd ins instructions. */ - struct { uint32_t _: 11; uint32_t b: 4; } imm4; - /* imm5: in conditional compare (immediate) instructions. */ - struct { uint32_t _: 16; uint32_t b: 5; } imm5; - /* imm7: in load/store pair pre/post index instructions. */ - struct { uint32_t _: 15; uint32_t b: 7; } imm7; - /* imm8: in floating-point scalar move immediate inst. */ - struct { uint32_t _: 13; uint32_t b: 8; } imm8; - /* imm9: in load/store pre/post index instructions. */ - struct { uint32_t _: 12; uint32_t b: 9; } imm9; - /* imm12: in ld/st unsigned imm or add/sub shifted inst. */ - struct { uint32_t _: 10; uint32_t b: 12; } imm12; - /* imm14: in test bit and branch instructions. */ - struct { uint32_t _: 5; uint32_t b: 14; } imm14; - /* imm16: in exception instructions. */ - struct { uint32_t _: 5; uint32_t b: 16; } imm16; - /* imm26: in unconditional branch instructions. */ - struct { uint32_t b: 26; } imm26; - /* imms: in bitfield and logical immediate instructions. */ - struct { uint32_t _: 10; uint32_t b: 6; } imms; - /* immr: in bitfield and logical immediate instructions. */ - struct { uint32_t _: 16; uint32_t b: 6; } immr; - /* immb: in advsimd shift by immediate instructions. */ - struct { uint32_t _: 16; uint32_t b: 3; } immb; - /* immh: in advsimd shift by immediate instructions. */ - struct { uint32_t _: 19; uint32_t b: 4; } immh; - /* N: in logical (immediate) instructions. */ - struct { uint32_t _: 22; uint32_t b: 1; } N; - /* index: in ld/st inst deciding the pre/post-index. */ - struct { uint32_t _: 11; uint32_t b: 1; } index; - /* index2: in ld/st pair inst deciding the pre/post-index. */ - struct { uint32_t _: 24; uint32_t b: 1; } index2; - /* sf: in integer data processing instructions. */ - struct { uint32_t _: 31; uint32_t b: 1; } sf; - /* H: in advsimd scalar x indexed element instructions. */ - struct { uint32_t _: 11; uint32_t b: 1; } H; - /* L: in advsimd scalar x indexed element instructions. */ - struct { uint32_t _: 21; uint32_t b: 1; } L; - /* M: in advsimd scalar x indexed element instructions. */ - struct { uint32_t _: 20; uint32_t b: 1; } M; - /* b5: in the test bit and branch instructions. */ - struct { uint32_t _: 31; uint32_t b: 1; } b5; - /* b40: in the test bit and branch instructions. */ - struct { uint32_t _: 19; uint32_t b: 5; } b40; - /* scale: in the fixed-point scalar to fp converting inst. */ - struct { uint32_t _: 10; uint32_t b: 6; } scale; - int32_t w; -} instr_t; - static int32_t logical_immediate(jit_word_t imm) { @@ -182,200 +56,136 @@ logical_immediate(jit_word_t imm) static void oxxx(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Rn, int32_t Rm) { - instr_t i; - ASSERT(!(Rd & ~0x1f)); - ASSERT(!(Rn & ~0x1f)); - ASSERT(!(Rm & ~0x1f)); - ASSERT(!(Op & ~0xffe0fc00)); - i.w = Op; - i.Rd.b = Rd; - i.Rn.b = Rn; - i.Rm.b = Rm; - emit_u32(_jit, i.w); + uint32_t inst = Op; + inst = write_Rd_bitfield(inst, Rd); + inst = write_Rn_bitfield(inst, Rn); + inst = write_Rm_bitfield(inst, Rm); + emit_u32(_jit, inst); } static void oxxi(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Rn, int32_t Imm12) { - instr_t i; - ASSERT(!(Rd & ~0x1f)); - ASSERT(!(Rn & ~0x1f)); - ASSERT(!(Imm12 & ~0xfff)); - ASSERT(!(Op & ~0xffe00000)); - i.w = Op; - i.Rd.b = Rd; - i.Rn.b = Rn; - i.imm12.b = Imm12; - emit_u32(_jit, i.w); + uint32_t inst = Op; + inst = write_Rd_bitfield(inst, Rd); + inst = write_Rn_bitfield(inst, Rn); + inst = write_imm12_bitfield(inst, Imm12); + emit_u32(_jit, inst); } static void -oxx9(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Rn, int32_t Imm9) +oxx9(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Rn, int32_t Simm9) { - instr_t i; - ASSERT(!(Rd & ~0x1f)); - ASSERT(!(Rn & ~0x1f)); - ASSERT(!(Imm9 & ~0x1ff)); - ASSERT(!(Op & ~0xffe00000)); - i.w = Op; - i.Rd.b = Rd; - i.Rn.b = Rn; - i.imm9.b = Imm9; - emit_u32(_jit, i.w); + uint32_t inst = Op; + inst = write_Rd_bitfield(inst, Rd); + inst = write_Rn_bitfield(inst, Rn); + inst = write_simm9_bitfield(inst, Simm9); + emit_u32(_jit, inst); } static uint32_t encode_ox19(jit_state_t *_jit, int32_t Op, int32_t Rd) { - instr_t i; - ASSERT(!(Rd & ~0x1f)); - ASSERT(!(Op & ~0xff000000)); - i.w = Op; - i.Rd.b = Rd; - return i.w; + uint32_t inst = Op; + inst = write_Rd_bitfield(inst, Rd); + return inst; } static uint32_t encode_oc19(jit_state_t *_jit, int32_t Op, int32_t Cc) { - instr_t i; - ASSERT(!(Cc & ~0xf)); - ASSERT(!(Op & ~0xff000000)); - i.w = Op; - i.cond2.b = Cc; - return i.w; + uint32_t inst = Op; + inst = write_cond2_bitfield(inst, Cc); + return inst; } static uint32_t encode_o26(jit_state_t *_jit, int32_t Op) { - instr_t i; - ASSERT(!(Op & ~0xfc000000)); - i.w = Op; - return i.w; + uint32_t inst = Op; + return inst; } static void ox_x(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Rm) { - instr_t i; - ASSERT(!(Rd & ~0x1f)); - ASSERT(!(Rm & ~0x1f)); - ASSERT(!(Op & ~0xffe0ffe0)); - i.w = Op; - i.Rd.b = Rd; - i.Rm.b = Rm; - emit_u32(_jit, i.w); + uint32_t inst = Op; + inst = write_Rd_bitfield(inst, Rd); + inst = write_Rm_bitfield(inst, Rm); + emit_u32(_jit, inst); } static void o_xx(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Rn) { - instr_t i; - ASSERT(!(Rd & ~0x1f)); - ASSERT(!(Rn & ~0x1f)); - ASSERT(!(Op & ~0xfffffc00)); - i.w = Op; - i.Rd.b = Rd; - i.Rn.b = Rn; - emit_u32(_jit, i.w); + uint32_t inst = Op; + inst = write_Rd_bitfield(inst, Rd); + inst = write_Rn_bitfield(inst, Rn); + emit_u32(_jit, inst); } static void oxx_(jit_state_t *_jit, int32_t Op, int32_t Rn, int32_t Rm) { - instr_t i; - ASSERT(!(Rn & ~0x1f)); - ASSERT(!(Rm & ~0x1f)); - ASSERT(!(Op & ~0xffc0fc1f)); - i.w = Op; - i.Rn.b = Rn; - i.Rm.b = Rm; - emit_u32(_jit, i.w); + uint32_t inst = Op; + inst = write_Rn_bitfield(inst, Rn); + inst = write_Rm_bitfield(inst, Rm); + emit_u32(_jit, inst); } static void o_x_(jit_state_t *_jit, int32_t Op, int32_t Rn) { - instr_t i; - ASSERT(!(Rn & ~0x1f)); - ASSERT(!(Op & 0x3e0)); - i.w = Op; - i.Rn.b = Rn; - emit_u32(_jit, i.w); + uint32_t inst = Op; + inst = write_Rn_bitfield(inst, Rn); + emit_u32(_jit, inst); } static void ox_h(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Imm16) { - instr_t i; - ASSERT(!(Rd & ~0x1f)); - ASSERT(!(Imm16 & ~0xffff)); - ASSERT(!(Op & ~0xffe00000)); - i.w = Op; - i.Rd.b = Rd; - i.imm16.b = Imm16; - emit_u32(_jit, i.w); + uint32_t inst = Op; + inst = write_Rd_bitfield(inst, Rd); + inst = write_imm16_bitfield(inst, Imm16); + emit_u32(_jit, inst); } static void oxxrs(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Rn, int32_t R, int32_t S) { - instr_t i; - ASSERT(!(Rd & ~0x1f)); - ASSERT(!(Rn & ~0x1f)); - ASSERT(!(R & ~0x3f)); - ASSERT(!(S & ~0x3f)); - ASSERT(!(Op & ~0xffc00000)); - i.w = Op; - i.Rd.b = Rd; - i.Rn.b = Rn; - i.immr.b = R; - i.imms.b = S; - emit_u32(_jit, i.w); + uint32_t inst = Op; + inst = write_Rd_bitfield(inst, Rd); + inst = write_Rn_bitfield(inst, Rn); + inst = write_immr_bitfield(inst, R); + inst = write_imms_bitfield(inst, S); + emit_u32(_jit, inst); } static void oxxxc(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Rn, int32_t Rm, int32_t Cc) { - instr_t i; - ASSERT(!(Rd & ~0x1f)); - ASSERT(!(Rn & ~0x1f)); - ASSERT(!(Rm & ~0x1f)); - ASSERT(!(Cc & ~0xf)); - ASSERT(!(Op & ~0xffc00c00)); - i.w = Op; - i.Rd.b = Rd; - i.Rn.b = Rn; - i.Rm.b = Rm; - i.cond.b = Cc; - emit_u32(_jit, i.w); + uint32_t inst = Op; + inst = write_Rd_bitfield(inst, Rd); + inst = write_Rn_bitfield(inst, Rn); + inst = write_Rm_bitfield(inst, Rm); + inst = write_cond_bitfield(inst, Cc); + emit_u32(_jit, inst); } static void oxxx7(jit_state_t *_jit, int32_t Op, int32_t Rt, int32_t Rt2, int32_t Rn, int32_t Simm7) { - instr_t i; - ASSERT(!(Rt & ~0x1f)); - ASSERT(!(Rt2 & ~0x1f)); - ASSERT(!(Rn & ~0x1f)); - ASSERT(Simm7 >= -128 && Simm7 <= 127); - ASSERT(!(Op & ~0xffc003e0)); - i.w = Op; - i.Rt.b = Rt; - i.Rt2.b = Rt2; - i.Rn.b = Rn; - i.imm7.b = Simm7; - emit_u32(_jit, i.w); + uint32_t inst = Op; + inst = write_Rt_bitfield(inst, Rt); + inst = write_Rt2_bitfield(inst, Rt2); + inst = write_Rn_bitfield(inst, Rn); + inst = write_simm7_bitfield(inst, Simm7); + emit_u32(_jit, inst); } -#define stack_framesize 160 -#define FP_REGNO 0x1d -#define LR_REGNO 0x1e -#define SP_REGNO 0x1f #define XZR_REGNO 0x1f #define WZR_REGNO XZR_REGNO #define LSL_12 0x00400000 @@ -383,26 +193,6 @@ oxxx7(jit_state_t *_jit, int32_t Op, #define MOVI_LSL_32 0x00400000 #define MOVI_LSL_48 0x00600000 #define XS 0x80000000 /* Wn -> Xn */ -#define DS 0x00400000 /* Sn -> Dn */ -#define CC_NE 0x0 -#define CC_EQ 0x1 -#define CC_CC 0x2 -#define CC_LO CC_CC -#define CC_CS 0x3 -#define CC_HS CC_CS -#define CC_PL 0x4 -#define CC_MI 0x5 -#define CC_VC 0x6 -#define CC_VS 0x7 -#define CC_LS 0x8 -#define CC_HI 0x9 -#define CC_LT 0xa -#define CC_GE 0xb -#define CC_LE 0xc -#define CC_GT 0xd -#define CC_NV 0xe -#define CC_AL 0xf -/* Branches need inverted condition */ #define BCC_EQ 0x0 #define BCC_NE 0x1 #define BCC_CS 0x2 @@ -421,7 +211,7 @@ oxxx7(jit_state_t *_jit, int32_t Op, #define BCC_LE 0xd #define BCC_AL 0xe #define BCC_NV 0xf -/* adapted and cut down to only tested and required by lightning, +/* adapted and cut down to only tested and required by lightening, * from data in binutils/aarch64-tbl.h */ #define A64_ADCS 0x3a000000 #define A64_SBCS 0x7a000000 @@ -492,10 +282,11 @@ oxxx7(jit_state_t *_jit, int32_t Op, #define A64_STURW 0xb8000000 #define A64_LDURW 0xb8400000 #define A64_LDURSW 0xb8800000 -#define A64_STP 0x29000000 -#define A64_LDP 0x29400000 #define A64_STP_POS 0x29800000 -#define A64_LDP_PRE 0x28c00000 +#define A64_LDP_POS 0x28c00000 +#define A64_STP_PRE 0x29800000 +#define A64_STR_PRE 0xf8000c00 +#define A64_LDR_POS 0xf8400c00 #define A64_ANDI 0x12400000 #define A64_ORRI 0x32400000 #define A64_EORI 0x52400000 @@ -1116,33 +907,27 @@ STUR(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm9) } static void -LDPI(jit_state_t *_jit, int32_t Rt, int32_t Rt2, int32_t Rn, int32_t Simm7) +STR_PRE(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Simm9) { - return oxxx7(_jit, A64_LDP|XS,Rt,Rt2,Rn,Simm7); + return oxx9(_jit, A64_STR_PRE,Rt,Rn,Simm9); } static void -STPI(jit_state_t *_jit, int32_t Rt, int32_t Rt2, int32_t Rn, int32_t Simm7) +LDR_POS(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Simm9) { - return oxxx7(_jit, A64_STP|XS,Rt,Rt2,Rn,Simm7); + return oxx9(_jit, A64_LDR_POS,Rt,Rn,Simm9); } static void -LDPI_PRE(jit_state_t *_jit, int32_t Rt, int32_t Rt2, int32_t Rn, int32_t Simm7) +STP_PRE(jit_state_t *_jit, int32_t Rt, int32_t Rt2, int32_t Rn, int32_t Simm7) { - return oxxx7(_jit, A64_LDP_PRE|XS,Rt,Rt2,Rn,Simm7); + return oxxx7(_jit, A64_STP_PRE|XS,Rt,Rt2,Rn,Simm7); } static void -STPI_POS(jit_state_t *_jit, int32_t Rt, int32_t Rt2, int32_t Rn, int32_t Simm7) +LDP_POS(jit_state_t *_jit, int32_t Rt, int32_t Rt2, int32_t Rn, int32_t Simm7) { - return oxxx7(_jit, A64_STP_POS|XS,Rt,Rt2,Rn,Simm7); -} - -static void -CSET(jit_state_t *_jit, int32_t Rd, int32_t Cc) -{ - return CSINC(_jit, Rd,XZR_REGNO,XZR_REGNO,Cc); + return oxxx7(_jit, A64_LDP_POS|XS,Rt,Rt2,Rn,Simm7); } static jit_reloc_t @@ -1172,7 +957,7 @@ BLR(jit_state_t *_jit, int32_t Rn) static void RET(jit_state_t *_jit) { - return o_x_(_jit, A64_RET,LR_REGNO); + return o_x_(_jit, A64_RET,jit_gpr_regno(_LR)); } static jit_reloc_t @@ -1590,156 +1375,6 @@ movi(jit_state_t *_jit, int32_t r0, jit_word_t i0) } } -static void -ccr(jit_state_t *_jit, int32_t cc, int32_t r0, int32_t r1, int32_t r2) -{ - CMP(_jit, r1, r2); - CSET(_jit, r0, cc); -} - -static void -cci(jit_state_t *_jit, int32_t cc, int32_t r0, int32_t r1, jit_word_t i0) -{ - jit_word_t is = i0 >> 12; - jit_word_t in = -i0; - jit_word_t iS = in >> 12; - if ( i0 >= 0 && i0 <= 0xfff) { - CMPI (_jit, r1, i0); - } else if ((is << 12) == i0 && is >= 0 && is <= 0xfff) { - CMPI_12(_jit, r1, is); - } else if ( in >= 0 && in <= 0xfff) { - CMNI (_jit, r1, in); - } else if ((iS << 12) == is && iS >= 0 && iS <= 0xfff) { - CMNI_12(_jit, r1, iS); - } else { - jit_gpr_t reg = get_temp_gpr(_jit); - movi(_jit, jit_gpr_regno(reg), i0); - CMP(_jit, r1, jit_gpr_regno(reg)); - unget_temp_gpr(_jit); - } - CSET(_jit, r0, cc); -} - -static void -ltr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - return ccr(_jit,CC_LT,r0,r1,r2); -} - -static void -lti(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) -{ - return cci(_jit,CC_LT,r0,r1,i0); -} - -static void -ltr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - return ccr(_jit,CC_CC,r0,r1,r2); -} - -static void -lti_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) -{ - return cci(_jit,CC_CC,r0,r1,i0); -} - -static void -ler(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - return ccr(_jit,CC_LE,r0,r1,r2); -} - -static void -lei(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) -{ - return cci(_jit,CC_LE,r0,r1,i0); -} - -static void -ler_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - return ccr(_jit,CC_LS,r0,r1,r2); -} - -static void -lei_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) -{ - return cci(_jit,CC_LS,r0,r1,i0); -} - -static void -eqr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - return ccr(_jit,CC_EQ,r0,r1,r2); -} - -static void -eqi(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) -{ - return cci(_jit,CC_EQ,r0,r1,i0); -} - -static void -ger(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - return ccr(_jit,CC_GE,r0,r1,r2); -} - -static void -gei(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) -{ - return cci(_jit,CC_GE,r0,r1,i0); -} - -static void -ger_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - return ccr(_jit,CC_CS,r0,r1,r2); -} - -static void -gei_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) -{ - return cci(_jit,CC_CS,r0,r1,i0); -} - -static void -gtr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - return ccr(_jit,CC_GT,r0,r1,r2); -} - -static void -gti(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) -{ - return cci(_jit,CC_GT,r0,r1,i0); -} - -static void -gtr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - return ccr(_jit,CC_HI,r0,r1,r2); -} - -static void -gti_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) -{ - return cci(_jit,CC_HI,r0,r1,i0); -} - -static void -ner(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - return ccr(_jit,CC_NE,r0,r1,r2); -} - -static void -nei(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) -{ - return cci(_jit,CC_NE,r0,r1,i0); -} - static jit_reloc_t bccr(jit_state_t *_jit, int32_t cc, int32_t r0, int32_t r1) { @@ -2163,13 +1798,6 @@ nop(jit_state_t *_jit, int32_t i0) ASSERT(i0 == 0); } -static void -rsbi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) -{ - subi(_jit, r0, r1, i0); - negr(_jit, r0, r0); -} - static void muli(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { @@ -2887,15 +2515,3 @@ retval_l(jit_state_t *_jit, int32_t r0) { movr(_jit, r0, jit_gpr_regno(_X0)); } - -static void -pushr(jit_state_t *_jit, int32_t r0) -{ - abort(); -} - -static void -popr(jit_state_t *_jit, int32_t r0) -{ - abort(); -} diff --git a/lightening/aarch64-fpu.c b/lightening/aarch64-fpu.c index c55f9632f..44f1eb0df 100644 --- a/lightening/aarch64-fpu.c +++ b/lightening/aarch64-fpu.c @@ -21,48 +21,32 @@ static void osvvv(jit_state_t *_jit, int32_t Op, int32_t Sz, int32_t Rd, int32_t Rn, int32_t Rm) { - ASSERT(!(Rd & ~0x1f)); - ASSERT(!(Rn & ~0x1f)); - ASSERT(!(Rm & ~0x1f)); - ASSERT(!(Sz & ~0x3)); - ASSERT(!(Op & ~0xffe0fc00)); - instr_t i; - i.w = Op; - i.size.b = Sz; - i.Rd.b = Rd; - i.Rn.b = Rn; - i.Rm.b = Rm; - emit_u32(_jit, i.w); + uint32_t inst = Op; + inst = write_size_bitfield(inst, Sz); + inst = write_Rd_bitfield(inst, Rd); + inst = write_Rn_bitfield(inst, Rn); + inst = write_Rm_bitfield(inst, Rm); + emit_u32(_jit, inst); } static void osvv_(jit_state_t *_jit, int32_t Op, int32_t Sz, int32_t Rd, int32_t Rn) { - ASSERT(!(Rd & ~0x1f)); - ASSERT(!(Rn & ~0x1f)); - ASSERT(!(Sz & ~0x3)); - ASSERT(!(Op & ~0xfffffc00)); - instr_t i; - i.w = Op; - i.size.b = Sz; - i.Rd.b = Rd; - i.Rn.b = Rn; - emit_u32(_jit, i.w); + uint32_t inst = Op; + inst = write_size_bitfield(inst, Sz); + inst = write_Rd_bitfield(inst, Rd); + inst = write_Rn_bitfield(inst, Rn); + emit_u32(_jit, inst); } static void os_vv(jit_state_t *_jit, int32_t Op, int32_t Sz, int32_t Rn, int32_t Rm) { - ASSERT(!(Rn & ~0x1f)); - ASSERT(!(Rm & ~0x1f)); - ASSERT(!(Sz & ~0x3)); - ASSERT(!(Op & ~0xff20fc1f)); - instr_t i; - i.w = Op; - i.size.b = Sz; - i.Rn.b = Rn; - i.Rm.b = Rm; - emit_u32(_jit, i.w); + uint32_t inst = Op; + inst = write_size_bitfield(inst, Sz); + inst = write_Rn_bitfield(inst, Rn); + inst = write_Rm_bitfield(inst, Rm); + emit_u32(_jit, inst); } #define A64_SCVTF 0x1e220000 @@ -824,15 +808,3 @@ retval_d(jit_state_t *_jit, int32_t r0) { movr_d(_jit, r0, jit_fpr_regno(_D0)); } - -static void -pushr_d(jit_state_t *_jit, int32_t r0) -{ - abort(); -} - -static void -popr_d(jit_state_t *_jit, int32_t r0) -{ - abort(); -} diff --git a/lightening/aarch64.c b/lightening/aarch64.c index b6789082c..b6734bd33 100644 --- a/lightening/aarch64.c +++ b/lightening/aarch64.c @@ -22,9 +22,15 @@ extern void __clear_cache(void *, void *); static inline int32_t -read_offset(uint32_t *loc, uint8_t bits, uint8_t base) +read_signed_bitfield(uint32_t word, uint8_t width, uint8_t shift) { - return (*((int32_t*)loc)) << (32 - bits - base) >> (32 - bits); + return ((int32_t)word) << (32 - width - shift) >> (32 - width); +} + +static inline uint32_t +read_unsigned_bitfield(uint32_t word, uint8_t width, uint8_t shift) +{ + return word << (32 - width - shift) >> (32 - width); } static inline int @@ -33,45 +39,84 @@ in_signed_range(ptrdiff_t diff, uint8_t bits) return (-1 << (bits - 1)) <= diff && diff < (1 << (bits - 1)); } -static inline int32_t -write_offset(uint32_t *loc, uint8_t bits, uint8_t base, ptrdiff_t offset) +static inline int +in_unsigned_range(uint32_t val, uint8_t bits) { - ASSERT(read_offset(loc, bits, base) == 0); - ASSERT(in_signed_range(offset, bits)); - *loc |= (((uint32_t) offset) & ((1 << bits) - 1)) << base; + ASSERT(bits < __WORDSIZE); + return val < (1 << bits); } -#define DEFINE_PATCHABLE_INSTRUCTION(name, bits, base, RELOC, rsh) \ - static const uint8_t name##_offset_bits = bits; \ - static const uint8_t name##_offset_base = base; \ +static inline uint32_t +write_unsigned_bitfield(uint32_t word, uint32_t val, uint8_t width, uint8_t shift) +{ + ASSERT(read_unsigned_bitfield(word, width, shift) == 0); + ASSERT(in_unsigned_range(val, width)); + return word | (val << shift); +} + +static inline int32_t +write_signed_bitfield(uint32_t word, ptrdiff_t val, uint8_t width, uint8_t shift) +{ + ASSERT(read_signed_bitfield(word, width, shift) == 0); + ASSERT(in_signed_range(val, width)); + return word | ((val & ((1 << width) - 1)) << shift); +} + +#define DEFINE_ENCODER(name, width, shift, kind, val_t) \ + static const uint8_t name##_width = width; \ + static const uint8_t name##_shift = shift; \ + static uint32_t \ + write_##name##_bitfield(uint32_t word, val_t val) \ + { \ + return write_##kind##_bitfield(word, val, name##_width, name##_shift); \ + } + +DEFINE_ENCODER(Rd, 5, 0, unsigned, uint32_t) +DEFINE_ENCODER(Rm, 5, 16, unsigned, uint32_t) +DEFINE_ENCODER(Rn, 5, 5, unsigned, uint32_t) +DEFINE_ENCODER(Rt, 5, 0, unsigned, uint32_t) +DEFINE_ENCODER(Rt2, 5, 10, unsigned, uint32_t) +DEFINE_ENCODER(cond, 4, 12, unsigned, uint32_t) +DEFINE_ENCODER(cond2, 4, 0, unsigned, uint32_t) +DEFINE_ENCODER(simm7, 7, 15, signed, ptrdiff_t) +DEFINE_ENCODER(simm9, 9, 12, signed, ptrdiff_t) +DEFINE_ENCODER(imm12, 12, 10, unsigned, uint32_t) +DEFINE_ENCODER(imm16, 16, 5, unsigned, uint32_t) +DEFINE_ENCODER(simm19, 19, 5, signed, ptrdiff_t) +DEFINE_ENCODER(simm26, 26, 0, signed, ptrdiff_t) +DEFINE_ENCODER(immr, 6, 16, unsigned, uint32_t) +DEFINE_ENCODER(imms, 6, 10, unsigned, uint32_t) +DEFINE_ENCODER(size, 2, 22, unsigned, uint32_t) + +#define DEFINE_PATCHABLE_INSTRUCTION(name, kind, RELOC, rsh) \ static int32_t \ read_##name##_offset(uint32_t *loc) \ { \ - return read_offset(loc, name##_offset_bits, name##_offset_base); \ + return read_signed_bitfield(*loc, kind##_width, kind##_shift); \ } \ static int \ - in_##name##_range(ptrdiff_t diff) \ + offset_in_##name##_range(ptrdiff_t diff) \ { \ - return in_signed_range(diff, name##_offset_bits); \ + return in_signed_range(diff, kind##_width); \ } \ - static int32_t \ - write_##name##_offset(uint32_t *loc, ptrdiff_t diff) \ + static void \ + patch_##name##_offset(uint32_t *loc, ptrdiff_t diff) \ { \ - return write_offset(loc, name##_offset_bits, name##_offset_base, diff); \ + *loc = write_##kind##_bitfield(*loc, diff); \ } \ static jit_reloc_t \ emit_##name(jit_state_t *_jit, uint32_t inst) \ { \ jit_reloc_t ret = jit_reloc (_jit, JIT_RELOC_##RELOC, 0, \ _jit->pc.uc, _jit->pc.uc, rsh); \ - add_pending_literal(_jit, ret, name##_offset_bits); \ + add_pending_literal(_jit, ret, kind##_width - 1); \ emit_u32(_jit, inst); \ return ret; \ } -DEFINE_PATCHABLE_INSTRUCTION(jmp, 26, 0, JCC_WITH_VENEER, 2); -DEFINE_PATCHABLE_INSTRUCTION(jcc, 19, 5, JMP_WITH_VENEER, 2); -DEFINE_PATCHABLE_INSTRUCTION(load_from_pool, 19, 5, LOAD_FROM_POOL, 2); +DEFINE_PATCHABLE_INSTRUCTION(jmp, simm26, JCC_WITH_VENEER, 2); +DEFINE_PATCHABLE_INSTRUCTION(jcc, simm19, JMP_WITH_VENEER, 2); +DEFINE_PATCHABLE_INSTRUCTION(load_from_pool, simm19, LOAD_FROM_POOL, 2); struct veneer { @@ -128,12 +173,6 @@ jit_init(jit_state_t *_jit) return 1; } -static size_t -jit_operand_abi_sizeof(enum jit_operand_abi abi) -{ - return 8; -} - static size_t jit_initial_frame_size (void) { @@ -178,3 +217,8 @@ jit_stack_alignment(void) { return 16; } + +static void +jit_try_shorten(jit_state_t *_jit, jit_reloc_t reloc, jit_pointer_t addr) +{ +} diff --git a/lightening/aarch64.h b/lightening/aarch64.h index 3916d0def..fe1b1810d 100644 --- a/lightening/aarch64.h +++ b/lightening/aarch64.h @@ -92,8 +92,9 @@ static inline jit_bool_t jit_gpr_is_callee_save (jit_gpr_t reg) { - // x19 to x28 are callee-save, and x29 is the frame pointer. - return 19 <= jit_gpr_regno (reg) && jit_gpr_regno (reg) <= 29; + // x19 to x28 are callee-save, x29 is the frame pointer, and x30 is + // the link register. + return 19 <= jit_gpr_regno (reg) && jit_gpr_regno (reg) <= 30; } static inline jit_bool_t @@ -132,10 +133,11 @@ jit_fpr_is_callee_save (jit_fpr_t reg) #define JIT_V7 _X26 #define JIT_V8 _X27 #define JIT_V9 _X28 -// x29 is frame pointer -// x30 is link register -// x31 is stack pointer +// x29 is frame pointer; x30 is link register. +#define JIT_PLATFORM_CALLEE_SAVE_GPRS _X29, _X30 + +// x31 is stack pointer. #define JIT_SP _X31 #define JIT_F0 _D0 diff --git a/lightening/lightening.c b/lightening/lightening.c index 3d1b26a1e..c08ebab6c 100644 --- a/lightening/lightening.c +++ b/lightening/lightening.c @@ -185,7 +185,6 @@ patch_pending_literal(jit_state_t *_jit, jit_reloc_t src, uint64_t value) abort(); } -static void add_load_from_pool(jit_state_t *_jit, jit_reloc_t src); static int32_t read_jmp_offset(uint32_t *loc); static int offset_in_jmp_range(ptrdiff_t offset); static void patch_jmp_offset(uint32_t *loc, ptrdiff_t offset); @@ -1082,10 +1081,11 @@ jit_shrink_stack(jit_state_t *_jit, size_t diff) _jit->frame_size -= diff; } -static const jit_gpr_t V[] = { -#ifdef JIT_VTMP - JIT_VTMP , -#endif +static const jit_gpr_t platform_callee_save_gprs[] = { + JIT_PLATFORM_CALLEE_SAVE_GPRS +}; + +static const jit_gpr_t user_callee_save_gprs[] = { JIT_V0, JIT_V1, JIT_V2 #ifdef JIT_V3 , JIT_V3 @@ -1110,10 +1110,7 @@ static const jit_gpr_t V[] = { #endif }; -static const jit_fpr_t VF[] = { -#ifdef JIT_VFTMP - JIT_VFTMP , -#endif +static const jit_fpr_t user_callee_save_fprs[] = { #ifdef JIT_VF0 JIT_VF0 #endif @@ -1140,55 +1137,54 @@ static const jit_fpr_t VF[] = { #endif }; -static const size_t v_count = sizeof(V) / sizeof(V[0]); -static const size_t vf_count = sizeof(VF) / sizeof(VF[0]); +#define ARRAY_SIZE(X) (sizeof (X)/sizeof ((X)[0])) +static const size_t pv_count = ARRAY_SIZE(platform_callee_save_gprs); +static const size_t v_count = ARRAY_SIZE(user_callee_save_gprs); +static const size_t vf_count = ARRAY_SIZE(user_callee_save_fprs); size_t jit_enter_jit_abi(jit_state_t *_jit, size_t v, size_t vf, size_t frame_size) { -#ifdef JIT_VTMP - v++; -#endif -#ifdef JIT_VFTMP - vf++; -#endif - ASSERT(v <= v_count); ASSERT(vf <= vf_count); ASSERT(_jit->frame_size == 0); _jit->frame_size = jit_initial_frame_size(); - /* Save values of callee-save registers. */ - for (size_t i = 0; i < v; i++) - jit_pushr (_jit, V[i]); - for (size_t i = 0; i < vf; i++) - jit_pushr_d (_jit, VF[i]); + size_t reserved = + jit_align_stack(_jit, (pv_count + v) * (__WORDSIZE / 8) + vf * 8); - return jit_align_stack(_jit, frame_size); + size_t offset = 0; + for (size_t i = 0; i < vf_count; i++, offset += 8) + jit_stxi_d(_jit, offset, JIT_SP, user_callee_save_fprs[i]); + for (size_t i = 0; i < v; i++, offset += __WORDSIZE / 8) + jit_stxi(_jit, offset, JIT_SP, user_callee_save_gprs[i]); + for (size_t i = 0; i < pv_count; i++, offset += __WORDSIZE / 8) + jit_stxi(_jit, offset, JIT_SP, platform_callee_save_gprs[i]); + ASSERT(offset <= reserved); + + return reserved; } void jit_leave_jit_abi(jit_state_t *_jit, size_t v, size_t vf, size_t frame_size) { -#ifdef JIT_VTMP - v++; -#endif -#ifdef JIT_VFTMP - vf++; -#endif + ASSERT(v <= v_count); + ASSERT(vf <= vf_count); + ASSERT((pv_count + v) * (__WORDSIZE / 8) + vf * 8 <= frame_size); + + size_t offset = 0; + for (size_t i = 0; i < vf_count; i++, offset += 8) + jit_ldxi_d(_jit, user_callee_save_fprs[i], JIT_SP, offset); + for (size_t i = 0; i < v; i++, offset += __WORDSIZE / 8) + jit_ldxi(_jit, user_callee_save_gprs[i], JIT_SP, offset); + for (size_t i = 0; i < pv_count; i++, offset += __WORDSIZE / 8) + jit_ldxi(_jit, platform_callee_save_gprs[i], JIT_SP, offset); + ASSERT(offset <= frame_size); jit_shrink_stack(_jit, frame_size); - - /* Restore callee-save registers. */ - for (size_t i = 0; i < vf; i++) - jit_popr_d (_jit, VF[vf - i - 1]); - - for (size_t i = 0; i < v; i++) - jit_popr (_jit, V[v - i - 1]); } - // Precondition: stack is already aligned. static size_t prepare_call_args(jit_state_t *_jit, size_t argc, jit_operand_t args[]) diff --git a/lightening/x86-sse.c b/lightening/x86-sse.c index 59b7c7471..15db27bca 100644 --- a/lightening/x86-sse.c +++ b/lightening/x86-sse.c @@ -169,24 +169,6 @@ movr_d(jit_state_t *_jit, int32_t r0, int32_t r1) ssexr(_jit, 0xf2, X86_SSE_MOV, r0, r1); } -static void -pushr_d(jit_state_t *_jit, int32_t r0) -{ - jit_gpr_t tmp = get_temp_gpr(_jit); - movdqxr(_jit, jit_gpr_regno(tmp), r0); - pushr(_jit, jit_gpr_regno(tmp)); - unget_temp_gpr(_jit); -} - -static void -popr_d(jit_state_t *_jit, int32_t r0) -{ - jit_gpr_t tmp = get_temp_gpr(_jit); - popr(_jit, jit_gpr_regno(tmp)); - ssexr(_jit, 0x66, X86_SSE_G2X, r0, jit_gpr_regno(tmp)); - unget_temp_gpr(_jit); -} - static void addssr(jit_state_t *_jit, int32_t r0, int32_t r1) { diff --git a/lightening/x86.h b/lightening/x86.h index 41c136e27..8ed27e85b 100644 --- a/lightening/x86.h +++ b/lightening/x86.h @@ -129,7 +129,7 @@ jit_fpr_is_callee_save (jit_fpr_t reg) # define JIT_V0 _RBP # define JIT_V1 _RSI # define JIT_V2 _RDI -# define JIT_VTMP _RBX +# define JIT_TMP _RBX # define JIT_F0 _XMM0 # define JIT_F1 _XMM1 # define JIT_F2 _XMM2 @@ -138,6 +138,7 @@ jit_fpr_is_callee_save (jit_fpr_t reg) # define JIT_F5 _XMM5 # define JIT_F6 _XMM6 # define JIT_FTMP _XMM7 +# define JIT_PLATFORM_CALLEE_SAVE_GPRS JIT_TMP #elif __CYGWIN__ # define JIT_R0 _RAX # define JIT_R1 _RCX @@ -169,6 +170,7 @@ jit_fpr_is_callee_save (jit_fpr_t reg) # define JIT_VF7 _XMM13 # define JIT_VF8 _XMM14 # define JIT_VF9 _XMM15 +# define JIT_PLATFORM_CALLEE_SAVE_GPRS /**/ #else # define JIT_R0 _RAX # define JIT_R1 _RCX @@ -200,6 +202,7 @@ jit_fpr_is_callee_save (jit_fpr_t reg) # define JIT_F13 _XMM13 # define JIT_F14 _XMM14 # define JIT_FTMP _XMM15 +# define JIT_PLATFORM_CALLEE_SAVE_GPRS /**/ #endif #endif /* _jit_x86_h */ diff --git a/tests/pushpop.c b/tests/pushpop.c deleted file mode 100644 index cd2420bdd..000000000 --- a/tests/pushpop.c +++ /dev/null @@ -1,35 +0,0 @@ -#include "test.h" - -static void -run_test(jit_state_t *j, uint8_t *arena_base, size_t arena_size) -{ - const jit_gpr_t gpr[] = { JIT_R0, JIT_R1, JIT_R2, JIT_V0, JIT_V1, JIT_V2 }; - const jit_fpr_t fpr[] = { JIT_F0, JIT_F1, JIT_F2 }; - - jit_begin(j, arena_base, arena_size); - size_t align = jit_enter_jit_abi(j, 3, 0, 0); - - jit_load_args_1(j, jit_operand_gpr (JIT_OPERAND_ABI_WORD, JIT_R0)); - - jit_pushr(j, JIT_R0); - - // Stomple registers. - for (int i=0; i<6; i++) - jit_movi(j, gpr[i], 0xcabba9e5); - for (int i=0; i<3; i++) - jit_extr_d(j, fpr[i], gpr[i]); - - jit_popr(j, JIT_R0); - - jit_leave_jit_abi(j, 3, 0, align); - jit_retr(j, JIT_R0); - - jit_word_t (*f)(jit_word_t) = jit_end(j, NULL); - ASSERT(f(42) == 42); -} - -int -main (int argc, char *argv[]) -{ - return main_helper(argc, argv, run_test); -} From 09e71475f4d86106708e8d5e77684e59c47cca48 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Wed, 15 May 2019 16:19:33 +0200 Subject: [PATCH 06/33] Allow a backend to have multiple temporary registers --- lightening/aarch64.h | 4 ++-- lightening/lightening.c | 30 +++++++++++++++++++----------- lightening/x86.h | 8 ++++---- 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/lightening/aarch64.h b/lightening/aarch64.h index fe1b1810d..13a0f1ca3 100644 --- a/lightening/aarch64.h +++ b/lightening/aarch64.h @@ -121,8 +121,8 @@ jit_fpr_is_callee_save (jit_fpr_t reg) #define JIT_R14 _X14 #define JIT_R15 _X15 #define JIT_R16 _X16 -#define JIT_R17 _X17 -#define JIT_RTMP _X18 +#define JIT_TMP0 _X17 +#define JIT_TMP1 _X18 #define JIT_V0 _X19 #define JIT_V1 _X20 #define JIT_V2 _X21 diff --git a/lightening/lightening.c b/lightening/lightening.c index c08ebab6c..fe71c58b2 100644 --- a/lightening/lightening.c +++ b/lightening/lightening.c @@ -332,35 +332,43 @@ jit_align(jit_state_t *_jit, unsigned align) static jit_gpr_t get_temp_gpr(jit_state_t *_jit) { - ASSERT(!_jit->temp_gpr_saved); - _jit->temp_gpr_saved = 1; -#ifdef JIT_RTMP - return JIT_RTMP; -#else - return JIT_VTMP; + switch(_jit->temp_gpr_saved++) + { + case 0: + return JIT_TMP0; +#ifdef JIT_TMP1 + case 1: + return JIT_TMP1; #endif + default: + abort(); + } } static jit_fpr_t get_temp_fpr(jit_state_t *_jit) { - ASSERT(!_jit->temp_fpr_saved); - _jit->temp_fpr_saved = 1; - return JIT_FTMP; + switch(_jit->temp_gpr_saved++) + { + case 0: + return JIT_FTMP; + default: + abort(); + } } static void unget_temp_fpr(jit_state_t *_jit) { ASSERT(_jit->temp_fpr_saved); - _jit->temp_fpr_saved = 0; + _jit->temp_fpr_saved--; } static void unget_temp_gpr(jit_state_t *_jit) { ASSERT(_jit->temp_gpr_saved); - _jit->temp_gpr_saved = 0; + _jit->temp_gpr_saved--; } static inline void emit_u8(jit_state_t *_jit, uint8_t u8) { diff --git a/lightening/x86.h b/lightening/x86.h index 8ed27e85b..647490380 100644 --- a/lightening/x86.h +++ b/lightening/x86.h @@ -129,7 +129,7 @@ jit_fpr_is_callee_save (jit_fpr_t reg) # define JIT_V0 _RBP # define JIT_V1 _RSI # define JIT_V2 _RDI -# define JIT_TMP _RBX +# define JIT_TMP0 _RBX # define JIT_F0 _XMM0 # define JIT_F1 _XMM1 # define JIT_F2 _XMM2 @@ -138,7 +138,7 @@ jit_fpr_is_callee_save (jit_fpr_t reg) # define JIT_F5 _XMM5 # define JIT_F6 _XMM6 # define JIT_FTMP _XMM7 -# define JIT_PLATFORM_CALLEE_SAVE_GPRS JIT_TMP +# define JIT_PLATFORM_CALLEE_SAVE_GPRS JIT_TMP0 #elif __CYGWIN__ # define JIT_R0 _RAX # define JIT_R1 _RCX @@ -146,7 +146,7 @@ jit_fpr_is_callee_save (jit_fpr_t reg) # define JIT_R3 _R8 # define JIT_R4 _R9 # define JIT_R5 _R10 -# define JIT_RTMP _R11 +# define JIT_TMP0 _R11 # define JIT_V0 _RBX # define JIT_V1 _RSI # define JIT_V2 _RDI @@ -180,7 +180,7 @@ jit_fpr_is_callee_save (jit_fpr_t reg) # define JIT_R5 _R8 # define JIT_R6 _R9 # define JIT_R7 _R10 -# define JIT_RTMP _R11 +# define JIT_TMP0 _R11 # define JIT_V0 _RBX # define JIT_V1 _R12 # define JIT_V2 _R13 From 7e0b0be1baae91bc6db11cc858812313c774b00b Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Wed, 15 May 2019 16:26:18 +0200 Subject: [PATCH 07/33] Fix GPR temporary selection --- lightening/lightening.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lightening/lightening.c b/lightening/lightening.c index fe71c58b2..806fbe3a8 100644 --- a/lightening/lightening.c +++ b/lightening/lightening.c @@ -348,7 +348,7 @@ get_temp_gpr(jit_state_t *_jit) static jit_fpr_t get_temp_fpr(jit_state_t *_jit) { - switch(_jit->temp_gpr_saved++) + switch(_jit->temp_fpr_saved++) { case 0: return JIT_FTMP; From a643f99d6860f8168b1260cdf118f56711b6b66d Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Thu, 16 May 2019 10:19:02 +0200 Subject: [PATCH 08/33] Fix compilation on aarch64 --- lightening/aarch64-cpu.c | 16 +++ lightening/aarch64.c | 3 +- lightening/lightening.c | 280 +++++++++++++++++++++++++-------------- lightening/x86.c | 2 +- 4 files changed, 198 insertions(+), 103 deletions(-) diff --git a/lightening/aarch64-cpu.c b/lightening/aarch64-cpu.c index a33128a6f..374f040c3 100644 --- a/lightening/aarch64-cpu.c +++ b/lightening/aarch64-cpu.c @@ -990,6 +990,22 @@ movi_from_pool(jit_state_t *_jit, int32_t Rt) return emit_load_from_pool(_jit, encode_ox19(_jit, A64_LDRI_LITERAL, Rt)); } +static void +emit_veneer(jit_state_t *_jit, jit_pointer_t target) +{ + jit_gpr_t tmp = get_temp_gpr(_jit); + uint32_t inst = encode_ox19(_jit, A64_LDRI_LITERAL, jit_gpr_regno(tmp)); + uint32_t *loc = _jit->pc.ui; + emit_u32(_jit, inst); + BR(_jit, jit_gpr_regno(tmp)); + unget_temp_gpr(_jit); + if (_jit->overflow) + return; + // Patch load to here, divided by 4. + patch_load_from_pool_offset(loc, _jit->pc.ui - loc); + emit_u64(_jit, (uint64_t) target); +} + static void movr(jit_state_t *_jit, int32_t r0, int32_t r1) { diff --git a/lightening/aarch64.c b/lightening/aarch64.c index b6734bd33..be1d5f7e0 100644 --- a/lightening/aarch64.c +++ b/lightening/aarch64.c @@ -94,6 +94,7 @@ DEFINE_ENCODER(size, 2, 22, unsigned, uint32_t) { \ return read_signed_bitfield(*loc, kind##_width, kind##_shift); \ } \ + static int offset_in_##name##_range(ptrdiff_t diff) maybe_unused; \ static int \ offset_in_##name##_range(ptrdiff_t diff) \ { \ @@ -204,7 +205,7 @@ next_abi_arg(struct abi_arg_iterator *iter, jit_operand_t *arg) iter->arg_idx++; } -void +static void jit_flush(void *fptr, void *tptr) { jit_word_t f = (jit_word_t)fptr & -page_size; diff --git a/lightening/lightening.c b/lightening/lightening.c index 806fbe3a8..46cd0d389 100644 --- a/lightening/lightening.c +++ b/lightening/lightening.c @@ -60,6 +60,7 @@ struct jit_literal_pool { uint32_t deadline; uint32_t size; + uint32_t byte_size; uint32_t capacity; struct jit_literal_pool_entry entries[]; }; @@ -91,99 +92,20 @@ static void jit_try_shorten(jit_state_t *_jit, jit_reloc_t reloc, struct abi_arg_iterator; #ifdef JIT_NEEDS_LITERAL_POOL -#define INITIAL_LITERAL_POOL_CAPACITY 12 -static struct jit_literal_pool* -alloc_literal_pool(jit_state_t *_jit, size_t capacity) -{ - struct jit_literal_pool *ret = - _jit->alloc (sizeof (struct jit_literal_pool) + - sizeof (struct jit_literal_pool_entry) * capacity); - ASSERT (ret); - ret->deadline = -1; - ret->size = 0; - ret->capacity = capacity; - return ret; -} - -static void -clear_literal_pool(struct jit_literal_pool *pool) -{ - pool->deadline = -1; - pool->size = 0; -} - -static void -grow_literal_pool(jit_state_t *_jit) -{ - struct jit_literal_pool *new_pool = - alloc_literal_pool(_jit, _jit->pool->capacity * 2); - - for (size_t i = 0; i < _jit->pool->size; i++) - new_pool->entries[new_pool->size++] = _jit->pool->entries[i]; - new_pool->deadline = _jit->pool->deadline; - - _jit->free (_jit->pool); - _jit->pool = new_pool; -} - -static void -add_literal_pool_entry(jit_state_t *_jit, struct jit_literal_pool_entry entry, - ptrdiff_t max_offset) -{ - if (_jit->pool->size == _jit->pool->capacity) - grow_literal_pool (_jit); - - max_offset <<= entry.reloc.rsh; - ptrdiff_t deadline = _jit->pc.uc - _jit->start + max_offset; - if (_jit->pool->size == 0) - // Assume that we might need a uint32_t for alignment, and another - // to branch over the table. - _jit->pool->deadline = deadline - 2 * sizeof(uint32_t); - else if (deadline < _jit->pool->deadline) - _jit->pool->deadline = deadline; - - // Assume that each entry takes a max of 16 bytes; - _jit->pool->deadline -= 16; - - _jit->pool->entries[_jit->pool->size++] = entry; -} - -static void -add_pending_literal(jit_state_t *_jit, jit_reloc_t src, - ptrdiff_t max_offset_bits) -{ - struct jit_literal_pool_entry entry = { src, 0 }; - add_literal_pool_entry(_jit, entry, - (1 << (max_offset_bits + src.rsh)) - 1); -} - -static void -remove_pending_literal(jit_state_t *_jit, jit_reloc_t src) -{ - for (size_t i = _jit->pool->size; i--; ) { - if (_jit->pool->entries[i].reloc.offset == src.offset) { - for (size_t j = i + 1; j < _jit->pool->size; j++) { - _jit->pool->entries[j-1] = _jit->pool->entries[j]; - _jit->pool->size--; - return; - } - } - } - abort(); -} - -static void -patch_pending_literal(jit_state_t *_jit, jit_reloc_t src, uint64_t value) -{ - for (size_t i = _jit->pool->size; i--; ) { - if (_jit->pool->entries[i].reloc.offset == src.offset) { - ASSERT(_jit->pool->entries[i].value == 0); - _jit->pool->entries[i].value = value; - return; - } - } - abort(); -} +static struct jit_literal_pool* alloc_literal_pool(jit_state_t *_jit, + size_t capacity); +static void clear_literal_pool(struct jit_literal_pool *pool); +static void grow_literal_pool(jit_state_t *_jit); +static void add_literal_pool_entry(jit_state_t *_jit, + struct jit_literal_pool_entry entry, + ptrdiff_t max_offset); +static void add_pending_literal(jit_state_t *_jit, jit_reloc_t src, + ptrdiff_t max_offset_bits); +static void remove_pending_literal(jit_state_t *_jit, jit_reloc_t src); +static void patch_pending_literal(jit_state_t *_jit, jit_reloc_t src, + uint64_t value); +enum guard_pool { GUARD_NEEDED, NO_GUARD_NEEDED }; +static void emit_literal_pool(jit_state_t *_jit, enum guard_pool guard); static int32_t read_jmp_offset(uint32_t *loc); static int offset_in_jmp_range(ptrdiff_t offset); @@ -231,7 +153,7 @@ jit_new_state(void* (*alloc_fn)(size_t), void (*free_fn)(void*)) } #ifdef JIT_NEEDS_LITERAL_POOL - _jit->pool = alloc_literal_pool(_jit, INITIAL_LITERAL_POOL_CAPACITY); + _jit->pool = alloc_literal_pool(_jit, 0); #endif return _jit; @@ -289,18 +211,25 @@ jit_reset(jit_state_t *_jit) void* jit_end(jit_state_t *_jit, size_t *length) { - uint8_t *code = _jit->start; +#ifdef JIT_NEEDS_LITERAL_POOL + if (_jit->pool->size) + emit_literal_pool(_jit, NO_GUARD_NEEDED); +#endif + + if (_jit->overflow) + return NULL; + + uint8_t *start = _jit->start; uint8_t *end = _jit->pc.uc; - ASSERT (code); - ASSERT (code <= end); + ASSERT (start); + ASSERT (start <= end); ASSERT (end <= _jit->limit); - ASSERT (!_jit->overflow); - jit_flush (code, end); + jit_flush (start, end); if (length) { - *length = end - code; + *length = end - start; } _jit->pc.uc = _jit->start = _jit->limit = NULL; @@ -310,7 +239,7 @@ jit_end(jit_state_t *_jit, size_t *length) clear_literal_pool(_jit->pool); #endif - return code; + return start; } static int @@ -392,6 +321,10 @@ static inline void emit_u32(jit_state_t *_jit, uint32_t u32) { _jit->overflow = 1; } else { *_jit->pc.ui++ = u32; +#ifdef JIT_NEEDS_LITERAL_POOL + if (UNLIKELY(_jit->pc.uc >= _jit->start + _jit->pool->deadline)) + emit_literal_pool(_jit, GUARD_NEEDED); +#endif } } @@ -1272,3 +1205,148 @@ jit_load_args(jit_state_t *_jit, size_t argc, jit_operand_t args[]) jit_locate_args(_jit, argc, src); jit_move_operands(_jit, args, src, argc); } + +#ifdef JIT_NEEDS_LITERAL_POOL +#define INITIAL_LITERAL_POOL_CAPACITY 12 +static struct jit_literal_pool* +alloc_literal_pool(jit_state_t *_jit, size_t capacity) +{ + if (capacity == 0) capacity = INITIAL_LITERAL_POOL_CAPACITY; + + struct jit_literal_pool *ret = + _jit->alloc (sizeof (struct jit_literal_pool) + + sizeof (struct jit_literal_pool_entry) * capacity); + ASSERT (ret); + ret->deadline = -1; + ret->size = 0; + ret->capacity = capacity; + return ret; +} + +static void +clear_literal_pool(struct jit_literal_pool *pool) +{ + pool->deadline = -1; + pool->size = 0; +} + +static void +grow_literal_pool(jit_state_t *_jit) +{ + struct jit_literal_pool *new_pool = + alloc_literal_pool(_jit, _jit->pool->capacity * 2); + + for (size_t i = 0; i < _jit->pool->size; i++) + new_pool->entries[new_pool->size++] = _jit->pool->entries[i]; + new_pool->deadline = _jit->pool->deadline; + + _jit->free (_jit->pool); + _jit->pool = new_pool; +} + +static void +add_literal_pool_entry(jit_state_t *_jit, struct jit_literal_pool_entry entry, + ptrdiff_t max_offset) +{ + if (_jit->pool->size == _jit->pool->capacity) + grow_literal_pool (_jit); + + max_offset <<= entry.reloc.rsh; + ptrdiff_t deadline = + _jit->pc.uc - _jit->start + max_offset - _jit->pool->byte_size; + if (_jit->pool->size == 0) + // Assume that we might need a uint32_t for alignment, and another + // to branch over the table. + _jit->pool->deadline = deadline - 2 * sizeof(uint32_t); + else if (deadline < _jit->pool->deadline) + _jit->pool->deadline = deadline; + + // Assume that each entry takes a max of 16 bytes. + _jit->pool->byte_size += 16; + + _jit->pool->entries[_jit->pool->size++] = entry; +} + +static void +add_pending_literal(jit_state_t *_jit, jit_reloc_t src, + ptrdiff_t max_offset_bits) +{ + struct jit_literal_pool_entry entry = { src, 0 }; + add_literal_pool_entry(_jit, entry, + (1 << (max_offset_bits + src.rsh)) - 1); +} + +static void +remove_pending_literal(jit_state_t *_jit, jit_reloc_t src) +{ + for (size_t i = _jit->pool->size; i--; ) { + if (_jit->pool->entries[i].reloc.offset == src.offset) { + for (size_t j = i + 1; j < _jit->pool->size; j++) { + _jit->pool->entries[j-1] = _jit->pool->entries[j]; + _jit->pool->size--; + return; + } + } + } + abort(); +} + +static void +patch_pending_literal(jit_state_t *_jit, jit_reloc_t src, uint64_t value) +{ + for (size_t i = _jit->pool->size; i--; ) { + if (_jit->pool->entries[i].reloc.offset == src.offset) { + ASSERT(_jit->pool->entries[i].value == 0); + _jit->pool->entries[i].value = value; + return; + } + } + abort(); +} + +static void +emit_literal_pool(jit_state_t *_jit, enum guard_pool guard) +{ + _jit->pool->deadline = -1; + + if (!_jit->pool->size) + return; + + jit_reloc_t skip; + if (guard == GUARD_NEEDED) + skip = jit_jmp(_jit); + + // FIXME: Could de-duplicate constants. + for (size_t i = 0; i < _jit->pool->size; i++) { + jit_align(_jit, 8); + struct jit_literal_pool_entry *entry = &_jit->pool->entries[i]; + uint8_t *loc = _jit->start + entry->reloc.offset; + uint8_t *pc_base = + loc - entry->reloc.inst_start_offset + entry->reloc.pc_base_offset; + ptrdiff_t diff = _jit->pc.uc - pc_base; + diff >>= entry->reloc.rsh; + + switch (entry->reloc.kind) { + case JIT_RELOC_JMP_WITH_VENEER: + patch_jmp_offset((uint32_t*) loc, diff); + emit_veneer(_jit, (void*) entry->value); + break; + case JIT_RELOC_JCC_WITH_VENEER: + patch_jcc_offset((uint32_t*) loc, diff); + emit_veneer(_jit, (void*) entry->value); + break; + case JIT_RELOC_LOAD_FROM_POOL: + patch_load_from_pool_offset((uint32_t*) loc, diff); + emit_u64(_jit, entry->value); + break; + default: + abort(); + } + } + + if (guard == GUARD_NEEDED) + jit_patch_here(_jit, skip); + + clear_literal_pool(_jit->pool); +} +#endif diff --git a/lightening/x86.c b/lightening/x86.c index 9ff925031..4d0f7b9a2 100644 --- a/lightening/x86.c +++ b/lightening/x86.c @@ -353,7 +353,7 @@ next_abi_arg(struct abi_arg_iterator *iter, jit_operand_t *arg) iter->arg_idx++; } -void +static void jit_flush(void *fptr, void *tptr) { } From 9c9389ad2b5bed2b7232cb6ced2a1417e6d1852a Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Thu, 16 May 2019 10:45:44 +0200 Subject: [PATCH 09/33] Fix enter/leave JIT ABI --- lightening/lightening.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lightening/lightening.c b/lightening/lightening.c index 46cd0d389..c58f577a5 100644 --- a/lightening/lightening.c +++ b/lightening/lightening.c @@ -1096,7 +1096,7 @@ jit_enter_jit_abi(jit_state_t *_jit, size_t v, size_t vf, size_t frame_size) jit_align_stack(_jit, (pv_count + v) * (__WORDSIZE / 8) + vf * 8); size_t offset = 0; - for (size_t i = 0; i < vf_count; i++, offset += 8) + for (size_t i = 0; i < vf; i++, offset += 8) jit_stxi_d(_jit, offset, JIT_SP, user_callee_save_fprs[i]); for (size_t i = 0; i < v; i++, offset += __WORDSIZE / 8) jit_stxi(_jit, offset, JIT_SP, user_callee_save_gprs[i]); @@ -1115,7 +1115,7 @@ jit_leave_jit_abi(jit_state_t *_jit, size_t v, size_t vf, size_t frame_size) ASSERT((pv_count + v) * (__WORDSIZE / 8) + vf * 8 <= frame_size); size_t offset = 0; - for (size_t i = 0; i < vf_count; i++, offset += 8) + for (size_t i = 0; i < vf; i++, offset += 8) jit_ldxi_d(_jit, user_callee_save_fprs[i], JIT_SP, offset); for (size_t i = 0; i < v; i++, offset += __WORDSIZE / 8) jit_ldxi(_jit, user_callee_save_gprs[i], JIT_SP, offset); From 9638e4f169457890effd7f7b8de8d5dad5a0ec49 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Thu, 16 May 2019 11:03:49 +0200 Subject: [PATCH 10/33] Fix a couple bugs related to aarch64 literal pools --- lightening/aarch64.c | 4 ++-- lightening/lightening.c | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lightening/aarch64.c b/lightening/aarch64.c index be1d5f7e0..1964cb9bd 100644 --- a/lightening/aarch64.c +++ b/lightening/aarch64.c @@ -115,8 +115,8 @@ DEFINE_ENCODER(size, 2, 22, unsigned, uint32_t) return ret; \ } -DEFINE_PATCHABLE_INSTRUCTION(jmp, simm26, JCC_WITH_VENEER, 2); -DEFINE_PATCHABLE_INSTRUCTION(jcc, simm19, JMP_WITH_VENEER, 2); +DEFINE_PATCHABLE_INSTRUCTION(jmp, simm26, JMP_WITH_VENEER, 2); +DEFINE_PATCHABLE_INSTRUCTION(jcc, simm19, JCC_WITH_VENEER, 2); DEFINE_PATCHABLE_INSTRUCTION(load_from_pool, simm19, LOAD_FROM_POOL, 2); struct veneer diff --git a/lightening/lightening.c b/lightening/lightening.c index c58f577a5..e073103c9 100644 --- a/lightening/lightening.c +++ b/lightening/lightening.c @@ -1281,11 +1281,10 @@ remove_pending_literal(jit_state_t *_jit, jit_reloc_t src) { for (size_t i = _jit->pool->size; i--; ) { if (_jit->pool->entries[i].reloc.offset == src.offset) { - for (size_t j = i + 1; j < _jit->pool->size; j++) { + for (size_t j = i + 1; j < _jit->pool->size; j++) _jit->pool->entries[j-1] = _jit->pool->entries[j]; - _jit->pool->size--; - return; - } + _jit->pool->size--; + return; } } abort(); From f2d7321504331427e3a5577b3d2bc3c350a9f6e1 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Thu, 16 May 2019 11:28:10 +0200 Subject: [PATCH 11/33] Aarch64 backend avoids needless temporary register allocation --- lightening/aarch64-cpu.c | 213 ++++++++++++++++++++------------------- 1 file changed, 109 insertions(+), 104 deletions(-) diff --git a/lightening/aarch64-cpu.c b/lightening/aarch64-cpu.c index 374f040c3..b9aea687c 100644 --- a/lightening/aarch64-cpu.c +++ b/lightening/aarch64-cpu.c @@ -1544,10 +1544,11 @@ addi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) } else if ((iS << 12) == is && iS >= 0 && iS <= 0xfff) { SUBI_12(_jit, r0, r1, iS); } else { - jit_gpr_t reg = get_temp_gpr(_jit); - movi(_jit, jit_gpr_regno(reg), i0); - addr(_jit, r0, r1, jit_gpr_regno(reg)); - unget_temp_gpr(_jit); + int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0; + movi(_jit, r2, i0); + addr(_jit, r0, r1, r2); + if (r0 == r1) + unget_temp_gpr(_jit); } } @@ -1566,20 +1567,22 @@ addci(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) } else if ((iS << 12) == is && iS >= 0 && iS <= 0xfff) { SUBSI_12(_jit, r0, r1, iS); } else { - jit_gpr_t reg = get_temp_gpr(_jit); - movi(_jit, jit_gpr_regno(reg), i0); - addcr(_jit, r0, r1, jit_gpr_regno(reg)); - unget_temp_gpr(_jit); + int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0; + movi(_jit, r2, i0); + addcr(_jit, r0, r1, r2); + if (r0 == r1) + unget_temp_gpr(_jit); } } static void addxi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - jit_gpr_t reg = get_temp_gpr(_jit); - movi(_jit, jit_gpr_regno(reg), i0); - addxr(_jit, r0, r1, jit_gpr_regno(reg)); - unget_temp_gpr(_jit); + int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0; + movi(_jit, r2, i0); + addxr(_jit, r0, r1, r2); + if (r0 == r1) + unget_temp_gpr(_jit); } static void @@ -1591,10 +1594,11 @@ subi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) } else if ((is << 12) == i0 && is >= 0 && is <= 0xfff) { SUBI_12(_jit, r0, r1, is); } else { - jit_gpr_t reg = get_temp_gpr(_jit); - movi(_jit, jit_gpr_regno(reg), i0); - subr(_jit, r0, r1, jit_gpr_regno(reg)); - unget_temp_gpr(_jit); + int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0; + movi(_jit, r2, i0); + subr(_jit, r0, r1, r2); + if (r0 == r1) + unget_temp_gpr(_jit); } } @@ -1607,20 +1611,22 @@ subci(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) } else if ((is << 12) == i0 && is >= 0 && is <= 0xfff) { SUBSI_12(_jit, r0, r1, is); } else { - jit_gpr_t reg = get_temp_gpr(_jit); - movi(_jit, jit_gpr_regno(reg), i0); - subcr(_jit, r0, r1, jit_gpr_regno(reg)); - unget_temp_gpr(_jit); + int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0; + movi(_jit, r2, i0); + subcr(_jit, r0, r1, r2); + if (r0 == r1) + unget_temp_gpr(_jit); } } static void subxi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - jit_gpr_t reg = get_temp_gpr(_jit); - movi(_jit, jit_gpr_regno(reg), i0); - subxr(_jit, r0, r1, jit_gpr_regno(reg)); - unget_temp_gpr(_jit); + int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0; + movi(_jit, r2, i0); + subxr(_jit, r0, r1, r2); + if (r0 == r1) + unget_temp_gpr(_jit); } static jit_reloc_t @@ -1817,10 +1823,11 @@ nop(jit_state_t *_jit, int32_t i0) static void muli(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - jit_gpr_t reg = get_temp_gpr(_jit); - movi(_jit, jit_gpr_regno(reg), i0); - mulr(_jit, r0, r1, jit_gpr_regno(reg)); - unget_temp_gpr(_jit); + int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0; + movi(_jit, r2, i0); + mulr(_jit, r0, r1, r2); + if (r0 == r1) + unget_temp_gpr(_jit); } static void @@ -1878,19 +1885,21 @@ qmuli_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, jit_word_t i0) static void divi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - jit_gpr_t reg = get_temp_gpr(_jit); - movi(_jit, jit_gpr_regno(reg), i0); - divr(_jit, r0, r1, jit_gpr_regno(reg)); - unget_temp_gpr(_jit); + int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0; + movi(_jit, r2, i0); + divr(_jit, r0, r1, r2); + if (r0 == r1) + unget_temp_gpr(_jit); } static void divi_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - jit_gpr_t reg = get_temp_gpr(_jit); - movi(_jit, jit_gpr_regno(reg), i0); - divr_u(_jit, r0, r1, jit_gpr_regno(reg)); - unget_temp_gpr(_jit); + int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0; + movi(_jit, r2, i0); + divr_u(_jit, r0, r1, r2); + if (r0 == r1) + unget_temp_gpr(_jit); } static void @@ -2007,10 +2016,11 @@ andi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) if (imm != -1) { ANDI(_jit, r0, r1, imm); } else { - jit_gpr_t reg = get_temp_gpr(_jit); - movi(_jit, jit_gpr_regno(reg), i0); - andr(_jit, r0, r1, jit_gpr_regno(reg)); - unget_temp_gpr(_jit); + int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0; + movi(_jit, r2, i0); + andr(_jit, r0, r1, r2); + if (r0 == r1) + unget_temp_gpr(_jit); } } } @@ -2028,10 +2038,11 @@ ori(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) if (imm != -1) { ORRI(_jit, r0, r1, imm); } else { - jit_gpr_t reg = get_temp_gpr(_jit); - movi(_jit, jit_gpr_regno(reg), i0); - orr(_jit, r0, r1, jit_gpr_regno(reg)); - unget_temp_gpr(_jit); + int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0; + movi(_jit, r2, i0); + orr(_jit, r0, r1, r2); + if (r0 == r1) + unget_temp_gpr(_jit); } } } @@ -2049,10 +2060,11 @@ xori(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) if (imm != -1) { EORI(_jit, r0, r1, imm); } else { - jit_gpr_t reg = get_temp_gpr(_jit); - movi(_jit, jit_gpr_regno(reg), i0); - xorr(_jit, r0, r1, jit_gpr_regno(reg)); - unget_temp_gpr(_jit); + int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0; + movi(_jit, r2, i0); + xorr(_jit, r0, r1, r2); + if (r0 == r1) + unget_temp_gpr(_jit); } } } @@ -2074,10 +2086,8 @@ bswapr_ui(jit_state_t *_jit, int32_t r0, int32_t r1) static void ldi_c(jit_state_t *_jit, int32_t r0, jit_word_t i0) { - jit_gpr_t reg = get_temp_gpr(_jit); - movi(_jit, jit_gpr_regno(reg), i0); - ldr_c(_jit, r0, jit_gpr_regno(reg)); - unget_temp_gpr(_jit); + movi(_jit, r0, i0); + ldr_c(_jit, r0, r0); } static void @@ -2092,19 +2102,15 @@ ldr_uc(jit_state_t *_jit, int32_t r0, int32_t r1) static void ldi_uc(jit_state_t *_jit, int32_t r0, jit_word_t i0) { - jit_gpr_t reg = get_temp_gpr(_jit); - movi(_jit, jit_gpr_regno(reg), i0); - ldr_uc(_jit, r0, jit_gpr_regno(reg)); - unget_temp_gpr(_jit); + movi(_jit, r0, i0); + ldr_uc(_jit, r0, r0); } static void ldi_s(jit_state_t *_jit, int32_t r0, jit_word_t i0) { - jit_gpr_t reg = get_temp_gpr(_jit); - movi(_jit, jit_gpr_regno(reg), i0); - ldr_s(_jit, r0, jit_gpr_regno(reg)); - unget_temp_gpr(_jit); + movi(_jit, r0, i0); + ldr_s(_jit, r0, r0); } static void @@ -2119,19 +2125,15 @@ ldr_us(jit_state_t *_jit, int32_t r0, int32_t r1) static void ldi_us(jit_state_t *_jit, int32_t r0, jit_word_t i0) { - jit_gpr_t reg = get_temp_gpr(_jit); - movi(_jit, jit_gpr_regno(reg), i0); - ldr_us(_jit, r0, jit_gpr_regno(reg)); - unget_temp_gpr(_jit); + movi(_jit, r0, i0); + ldr_us(_jit, r0, r0); } static void ldi_i(jit_state_t *_jit, int32_t r0, jit_word_t i0) { - jit_gpr_t reg = get_temp_gpr(_jit); - movi(_jit, jit_gpr_regno(reg), i0); - ldr_i(_jit, r0, jit_gpr_regno(reg)); - unget_temp_gpr(_jit); + movi(_jit, r0, i0); + ldr_i(_jit, r0, r0); } static void @@ -2146,10 +2148,8 @@ ldr_ui(jit_state_t *_jit, int32_t r0, int32_t r1) static void ldi_ui(jit_state_t *_jit, int32_t r0, jit_word_t i0) { - jit_gpr_t reg = get_temp_gpr(_jit); - movi(_jit, jit_gpr_regno(reg), i0); - ldr_ui(_jit, r0, jit_gpr_regno(reg)); - unget_temp_gpr(_jit); + movi(_jit, r0, i0); + ldr_ui(_jit, r0, r0); } static void @@ -2161,10 +2161,8 @@ ldr_l(jit_state_t *_jit, int32_t r0, int32_t r1) static void ldi_l(jit_state_t *_jit, int32_t r0, jit_word_t i0) { - jit_gpr_t reg = get_temp_gpr(_jit); - movi(_jit, jit_gpr_regno(reg), i0); - ldr_l(_jit, r0, jit_gpr_regno(reg)); - unget_temp_gpr(_jit); + movi(_jit, r0, i0); + ldr_l(_jit, r0, r0); } static void @@ -2182,10 +2180,11 @@ ldxi_c(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) } else if (i0 > -256 && i0 < 0) { LDURSB(_jit, r0, r1, i0 & 0x1ff); } else { - jit_gpr_t reg = get_temp_gpr(_jit); - movi(_jit, jit_gpr_regno(reg), i0); - LDRSB(_jit, r0, r1, jit_gpr_regno(reg)); - unget_temp_gpr(_jit); + int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0; + movi(_jit, r2, i0); + LDRSB(_jit, r0, r1, r2); + if (r0 == r1) + unget_temp_gpr(_jit); } extr_c(_jit, r0, r0); } @@ -2207,10 +2206,11 @@ ldxi_uc(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) } else if (i0 > -256 && i0 < 0) { LDURB(_jit, r0, r1, i0 & 0x1ff); } else { - jit_gpr_t reg = get_temp_gpr(_jit); - addi(_jit, jit_gpr_regno(reg), r1, i0); - ldr_uc(_jit, r0, jit_gpr_regno(reg)); - unget_temp_gpr(_jit); + int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0; + addi(_jit, r2, r1, i0); + ldr_uc(_jit, r0, r2); + if (r0 == r1) + unget_temp_gpr(_jit); } #if 0 extr_uc(_jit, r0, r0); @@ -2226,10 +2226,11 @@ ldxi_s(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) } else if (i0 > -256 && i0 < 0) { LDURSH(_jit, r0, r1, i0 & 0x1ff); } else { - jit_gpr_t reg = get_temp_gpr(_jit); - movi(_jit, jit_gpr_regno(reg), i0); - LDRSH(_jit, r0, r1, jit_gpr_regno(reg)); - unget_temp_gpr(_jit); + int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0; + movi(_jit, r2, i0); + LDRSH(_jit, r0, r1, r2); + if (r0 == r1) + unget_temp_gpr(_jit); } } @@ -2251,10 +2252,11 @@ ldxi_us(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) } else if (i0 > -256 && i0 < 0) { LDURH(_jit, r0, r1, i0 & 0x1ff); } else { - jit_gpr_t reg = get_temp_gpr(_jit); - movi(_jit, jit_gpr_regno(reg), i0); - LDRH(_jit, r0, r1, jit_gpr_regno(reg)); - unget_temp_gpr(_jit); + int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0; + movi(_jit, r2, i0); + LDRH(_jit, r0, r1, r2); + if (r0 == r1) + unget_temp_gpr(_jit); } #if 0 extr_us(_jit, r0, r0); @@ -2270,10 +2272,11 @@ ldxi_i(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) } else if (i0 > -256 && i0 < 0) { LDURSW(_jit, r0, r1, i0 & 0x1ff); } else { - jit_gpr_t reg = get_temp_gpr(_jit); - addi(_jit, jit_gpr_regno(reg), r1, i0); - ldr_i(_jit, r0, jit_gpr_regno(reg)); - unget_temp_gpr(_jit); + int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0; + addi(_jit, r2, r1, i0); + ldr_i(_jit, r0, r2); + if (r0 == r1) + unget_temp_gpr(_jit); } } @@ -2295,10 +2298,11 @@ ldxi_ui(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) } else if (i0 > -256 && i0 < 0) { LDURW(_jit, r0, r1, i0 & 0x1ff); } else { - jit_gpr_t reg = get_temp_gpr(_jit); - movi(_jit, jit_gpr_regno(reg), i0); - LDRW(_jit, r0, r1, jit_gpr_regno(reg)); - unget_temp_gpr(_jit); + int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0; + movi(_jit, r2, i0); + LDRW(_jit, r0, r1, r2); + if (r0 == r1) + unget_temp_gpr(_jit); } #if 0 extr_ui(_jit, r0, r0); @@ -2314,10 +2318,11 @@ ldxi_l(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) } else if (i0 > -256 && i0 < 0) { LDUR(_jit, r0, r1, i0 & 0x1ff); } else { - jit_gpr_t reg = get_temp_gpr(_jit); - addi(_jit, jit_gpr_regno(reg), r1, i0); - ldr_l(_jit, r0, jit_gpr_regno(reg)); - unget_temp_gpr(_jit); + int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0; + addi(_jit, r2, r1, i0); + ldr_l(_jit, r0, r2); + if (r0 == r1) + unget_temp_gpr(_jit); } } From 9d4185af2be47f1ef8069f0ad2683e98957fb11e Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Thu, 16 May 2019 11:40:24 +0200 Subject: [PATCH 12/33] Remove jit_nop Instead, jit_align will call nop() internally. You can't nop 3 bytes on most architectures. --- lightening.h | 2 -- lightening/lightening.c | 20 ++++++++++---------- tests/nop.c | 26 -------------------------- 3 files changed, 10 insertions(+), 38 deletions(-) delete mode 100644 tests/nop.c diff --git a/lightening.h b/lightening.h index 6fe49ce17..23635a01d 100644 --- a/lightening.h +++ b/lightening.h @@ -574,8 +574,6 @@ jit_load_args_3(jit_state_t *_jit, jit_operand_t a, jit_operand_t b, M(RGG__, bxsubr_u) \ M(RGu__, bxsubi_u) \ \ - M(_i___, nop) \ - \ M(_G___, jmpr) \ M(_p___, jmpi) \ M(R____, jmp) \ diff --git a/lightening/lightening.c b/lightening/lightening.c index e073103c9..2838891c0 100644 --- a/lightening/lightening.c +++ b/lightening/lightening.c @@ -248,16 +248,6 @@ is_power_of_two (unsigned x) return x && !(x & (x-1)); } -void -jit_align(jit_state_t *_jit, unsigned align) -{ - ASSERT (is_power_of_two (align)); - uintptr_t here = _jit->pc.w; - uintptr_t there = (here + align - 1) & ~(align - 1); - if (there - here) - jit_nop(_jit, there - here); -} - static jit_gpr_t get_temp_gpr(jit_state_t *_jit) { @@ -547,6 +537,16 @@ jit_patch_there(jit_state_t* _jit, jit_reloc_t reloc, jit_pointer_t addr) FOR_EACH_INSTRUCTION(IMPL_INSTRUCTION) #undef IMPL_INSTRUCTION +void +jit_align(jit_state_t *_jit, unsigned align) +{ + ASSERT (is_power_of_two (align)); + uintptr_t here = _jit->pc.w; + uintptr_t there = (here + align - 1) & ~(align - 1); + if (there - here) + nop(_jit, there - here); +} + static jit_bool_t is_fpr_arg(enum jit_operand_abi arg) { diff --git a/tests/nop.c b/tests/nop.c deleted file mode 100644 index c029954d2..000000000 --- a/tests/nop.c +++ /dev/null @@ -1,26 +0,0 @@ -#include "test.h" - -static void -run_test(jit_state_t *j, uint8_t *arena_base, size_t arena_size) -{ - jit_begin(j, arena_base, arena_size); - size_t align = jit_enter_jit_abi(j, 0, 0, 0); - - size_t total = 0; - char *start = jit_address(j); - for (size_t i = 1; i < 10; total += i, i++) - jit_nop(j, i); - char *end = jit_address(j); - ASSERT(end - start == total); - jit_leave_jit_abi(j, 0, 0, align); - jit_reti(j, 42); - - jit_word_t (*f)(void) = jit_end(j, NULL); - ASSERT(f() == 42); -} - -int -main (int argc, char *argv[]) -{ - return main_helper(argc, argv, run_test); -} From 926275e123f72db3edd09922182be545a00ef993 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Thu, 16 May 2019 12:03:38 +0200 Subject: [PATCH 13/33] Add support for aarch64 in CI --- .gitlab-ci.yml | 13 ++++++++++--- tests/Makefile | 22 ++++++++++++++++++++-- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 891112e87..f3600ae8e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -4,9 +4,11 @@ image: debian before_script: - - dpkg --add-architecture i386 + - dpkg --add-architecture i386 --add-architecture arm64 - apt-get update -qq - - apt-get install -y libc6-dev:amd64 libc6-dev:i386 gcc gcc-multilib make + - apt-get install -y \ + libc6-dev:amd64 libc6-dev:i386 libc6-dev:arm64 \ + gcc gcc-multilib gcc-aarch64-linux-gnu make x86-64: stage: test @@ -16,4 +18,9 @@ x86-64: i686: stage: test script: - - make -C tests test-ia32 + - make -C tests test-ia32 CC_IA32='gcc -m32' + +aarch64: + stage: test + script: + - make -C tests test-aarch64 CC_AARCH64=gcc-aarch64-linux-gnu diff --git a/tests/Makefile b/tests/Makefile index 7b6bbd49d..a3b988c52 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,8 +1,22 @@ TESTS=$(sort $(basename $(wildcard *.c))) -TARGETS=native +TARGETS=native ia32 aarch64 +# Suitable values of cross-compiler variables for Debian, having previously done: +# +# CC_IA32 = gcc -m32 +# CC_AARCH64 = gcc-aarch64-linux-gnu +# +# The relevant packages that you need to run this: +# +# dpkg --add-architecture i386 --add-architecture arm64 +# apt-get update -qq +# apt-get install -y \ +# libc6-dev:amd64 libc6-dev:i386 libc6-dev:arm64 \ +# gcc gcc-multilib gcc-aarch64-linux-gnu make +# CC = gcc -CC_IA32 = gcc -m32 +CC_IA32='guix environment --pure -s i686-linux --ad-hoc gcc-toolchain glibc -- gcc' +CC_AARCH64='guix environment --pure -s aarch64-linux --ad-hoc gcc-toolchain glibc -- gcc' CFLAGS = -Wall -O0 -g all: $(foreach TARGET,$(TARGETS),$(addprefix test-$(TARGET)-,$(TESTS))) @@ -29,6 +43,10 @@ test-ia32-%: CC = $(CC_IA32) test-ia32-%: %.c lightening-ia32.o test.h $(CC) $(CFLAGS) $(CPPFLAGS) -I.. -o $@ lightening-ia32.o $< +test-aarch64-%: CC = $(CC_AARCH64) +test-aarch64-%: %.c lightening-aarch64.o test.h + $(CC) $(CFLAGS) $(CPPFLAGS) -I.. -o $@ lightening-aarch64.o $< + .PRECIOUS: $(foreach TARGET,$(TARGETS),$(addprefix test-$(TARGET)-,$(TESTS))) .PRECIOUS: $(foreach TARGET,$(TARGETS),lightening-$(TARGET).o) From 826d5a95c346f046f97745aebd05f427ec453a37 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Thu, 16 May 2019 12:08:22 +0200 Subject: [PATCH 14/33] Fix dpkg --add-architecture invocation --- .gitlab-ci.yml | 3 ++- tests/Makefile | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f3600ae8e..03993fa1d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -4,7 +4,8 @@ image: debian before_script: - - dpkg --add-architecture i386 --add-architecture arm64 + - dpkg --add-architecture i386 + - dpkg --add-architecture arm64 - apt-get update -qq - apt-get install -y \ libc6-dev:amd64 libc6-dev:i386 libc6-dev:arm64 \ diff --git a/tests/Makefile b/tests/Makefile index a3b988c52..1b3cd881d 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -8,7 +8,8 @@ TARGETS=native ia32 aarch64 # # The relevant packages that you need to run this: # -# dpkg --add-architecture i386 --add-architecture arm64 +# dpkg --add-architecture i386 +# dpkg --add-architecture arm64 # apt-get update -qq # apt-get install -y \ # libc6-dev:amd64 libc6-dev:i386 libc6-dev:arm64 \ From 8977016a89dc57a03dc6ebf163cf4c5fe025ac99 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Thu, 16 May 2019 12:11:12 +0200 Subject: [PATCH 15/33] Fix YAML for CI --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 03993fa1d..3eb046be0 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -7,8 +7,8 @@ before_script: - dpkg --add-architecture i386 - dpkg --add-architecture arm64 - apt-get update -qq - - apt-get install -y \ - libc6-dev:amd64 libc6-dev:i386 libc6-dev:arm64 \ + - apt-get install -y + libc6-dev:amd64 libc6-dev:i386 libc6-dev:arm64 gcc gcc-multilib gcc-aarch64-linux-gnu make x86-64: From f679e9e8afa641f8bca34e8e4a4981c508f4c0f4 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Thu, 16 May 2019 12:22:18 +0200 Subject: [PATCH 16/33] Attempt to fix CI on Debian --- .gitlab-ci.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3eb046be0..3f6a6c8c2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,15 +1,11 @@ -# use the official gcc image, based on debian -# can use verions as well, like gcc:5.2 -# see https://hub.docker.com/_/gcc/ image: debian before_script: - dpkg --add-architecture i386 - - dpkg --add-architecture arm64 - apt-get update -qq - apt-get install -y - libc6-dev:amd64 libc6-dev:i386 libc6-dev:arm64 - gcc gcc-multilib gcc-aarch64-linux-gnu make + libc6-dev:amd64 libc6-dev:i386 gcc gcc-multilib make + gcc-aarch64-linux-gnu libc-dev-arm64-cross x86-64: stage: test From d6e23795d10ac76a45226934b3d70cd3c0918131 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Thu, 16 May 2019 12:24:00 +0200 Subject: [PATCH 17/33] Attempt to fix CI on Debian --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3f6a6c8c2..5f3b79d4b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -5,7 +5,7 @@ before_script: - apt-get update -qq - apt-get install -y libc6-dev:amd64 libc6-dev:i386 gcc gcc-multilib make - gcc-aarch64-linux-gnu libc-dev-arm64-cross + gcc-8-aarch64-linux-gnu libc-dev-arm64-cross x86-64: stage: test From 2badf61add49fe322980ef876cb1023cdac1e7c2 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Thu, 16 May 2019 12:26:35 +0200 Subject: [PATCH 18/33] Attempt to fix CI on Debian --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5f3b79d4b..3f6a6c8c2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -5,7 +5,7 @@ before_script: - apt-get update -qq - apt-get install -y libc6-dev:amd64 libc6-dev:i386 gcc gcc-multilib make - gcc-8-aarch64-linux-gnu libc-dev-arm64-cross + gcc-aarch64-linux-gnu libc-dev-arm64-cross x86-64: stage: test From da98f48ce7e41513f9b58d9c61e7a0b8aa1ae8cf Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Thu, 16 May 2019 12:28:07 +0200 Subject: [PATCH 19/33] Attempt to fix CI on Debian --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3f6a6c8c2..582ba9fd4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -4,7 +4,7 @@ before_script: - dpkg --add-architecture i386 - apt-get update -qq - apt-get install -y - libc6-dev:amd64 libc6-dev:i386 gcc gcc-multilib make + libc6-dev:amd64 libc6-dev:i386 gcc make gcc-aarch64-linux-gnu libc-dev-arm64-cross x86-64: From 77c4b56a6df8199f6d11ff1b580f2cdbf85f3e1c Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Thu, 16 May 2019 12:37:54 +0200 Subject: [PATCH 20/33] Attempt to fix CI on Debian --- .gitlab-ci.yml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 582ba9fd4..3da15bade 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,11 +1,13 @@ -image: debian +image: debian:testing before_script: - dpkg --add-architecture i386 + - dpkg --add-architecture arm64 - apt-get update -qq - apt-get install -y - libc6-dev:amd64 libc6-dev:i386 gcc make - gcc-aarch64-linux-gnu libc-dev-arm64-cross + libc6-dev:amd64 gcc make + gcc-i686-linux-gnu libc6-dev-i386-cross libc6:i386 + gcc-aarch64-linux-gnu libc6-dev-arm64-cross libc6:arm64 x86-64: stage: test @@ -15,9 +17,9 @@ x86-64: i686: stage: test script: - - make -C tests test-ia32 CC_IA32='gcc -m32' + - make -C tests test-ia32 CC_IA32=i686-linux-gnu-gcc aarch64: stage: test script: - - make -C tests test-aarch64 CC_AARCH64=gcc-aarch64-linux-gnu + - make -C tests test-aarch64 CC_AARCH64=aarch64-linux-gnu-gcc From 43ea9aee2c560ef408de860a8896101e54f4939a Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Thu, 16 May 2019 12:43:35 +0200 Subject: [PATCH 21/33] Attempt to fix CI on Debian for AArch64 --- .gitlab-ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3da15bade..a445b678c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -6,8 +6,10 @@ before_script: - apt-get update -qq - apt-get install -y libc6-dev:amd64 gcc make + qemu binfmt-support qemu-user-static gcc-i686-linux-gnu libc6-dev-i386-cross libc6:i386 gcc-aarch64-linux-gnu libc6-dev-arm64-cross libc6:arm64 + - update-binfmts --display x86-64: stage: test From c0e9302e9fbeda58ace0385404074f9846915496 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Thu, 16 May 2019 13:56:56 +0200 Subject: [PATCH 22/33] Update README and guix invocations in test suite --- README.md | 28 +++++++++++++++++++++++----- tests/Makefile | 15 ++++++++------- 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 7eb499435..14e33783b 100644 --- a/README.md +++ b/README.md @@ -28,10 +28,28 @@ Guile needs a simple, light-weight code generation library. The GNU Lightning architecture-specific backends provide the bulk of this functionality, and Lightening wraps it all in a lightweight API. +## Supported targets + +Lightening can generate code for the x86-64, i686, and AArch64 +architectures. It supports the calling conventions of MS Windows, +GNU/Linux, and Mac OS. + +Lightening is automatically tested using GitLab's continuous integration +for under the supported architectures, for GNU/Linux; for a list of +recent jobs, see [the CI +page](https://gitlab.com/wingo/lightening/-/jobs). + +## Future targets + +ARMv7 support will come soon. + +Lightening has some inherited code from GNU Lightning for MIPS, PPC64, +and s390. Patches to adapt this code to the Lightening code structure +are quite welcome. + +RISC-V support would be fun too. + ## Status -Only the x86-64 port is currently usable. I plan to re-enable 32-bit -x86 shortly, and then work on 32-bit and 64-bit ARM. Other -architectures may come with time, but help is very much appreciated -there. The test suite is still in progress but will be fairly -comprehensive in terms of API surface. +Lightening is used in GNU Guile since version 2.9.2 and seems to work +well. diff --git a/tests/Makefile b/tests/Makefile index 1b3cd881d..02d34af64 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,10 +1,9 @@ TESTS=$(sort $(basename $(wildcard *.c))) TARGETS=native ia32 aarch64 -# Suitable values of cross-compiler variables for Debian, having previously done: +# Suitable values of cross-compiler variables for Debian: # -# CC_IA32 = gcc -m32 -# CC_AARCH64 = gcc-aarch64-linux-gnu +# make test CC_IA32=i668-linux-gnu-gcc CC_AARCH64=aarch64-linux-gnu-gcc # # The relevant packages that you need to run this: # @@ -12,12 +11,14 @@ TARGETS=native ia32 aarch64 # dpkg --add-architecture arm64 # apt-get update -qq # apt-get install -y \ -# libc6-dev:amd64 libc6-dev:i386 libc6-dev:arm64 \ -# gcc gcc-multilib gcc-aarch64-linux-gnu make +# libc6-dev:amd64 gcc make \ +# qemu binfmt-support qemu-user-static \ +# gcc-i686-linux-gnu libc6-dev-i386-cross libc6:i386 \ +# gcc-aarch64-linux-gnu libc6-dev-arm64-cross libc6:arm64 # CC = gcc -CC_IA32='guix environment --pure -s i686-linux --ad-hoc gcc-toolchain glibc -- gcc' -CC_AARCH64='guix environment --pure -s aarch64-linux --ad-hoc gcc-toolchain glibc -- gcc' +CC_IA32=guix environment --pure -s i686-linux --ad-hoc gcc-toolchain glibc -- gcc +CC_AARCH64=guix environment --pure -s aarch64-linux --ad-hoc gcc-toolchain glibc -- gcc CFLAGS = -Wall -O0 -g all: $(foreach TARGET,$(TARGETS),$(addprefix test-$(TARGET)-,$(TESTS))) From eaf702765d9a55397b5db9bd2b8c4b356af9195d Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Thu, 16 May 2019 16:44:39 +0200 Subject: [PATCH 23/33] Remove software floating-point ARMv7 support; ARMv7 test env --- lightening/arm-swf.c | 2640 ------------------------------------------ lightening/arm.c | 4 +- tests/Makefile | 14 +- 3 files changed, 11 insertions(+), 2647 deletions(-) delete mode 100644 lightening/arm-swf.c diff --git a/lightening/arm-swf.c b/lightening/arm-swf.c deleted file mode 100644 index 2b8bfa139..000000000 --- a/lightening/arm-swf.c +++ /dev/null @@ -1,2640 +0,0 @@ -/* - * Copyright (C) 2012-2018 Free Software Foundation, Inc. - * - * This file is part of GNU lightning. - * - * GNU lightning is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU lightning is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * Authors: - * Paulo Cesar Pereira de Andrade - */ - -#if PROTO -/* match vfpv3 result */ -#define NAN_TO_INT_IS_ZERO 1 -extern float sqrtf(float); -extern double sqrt(double); -extern float __addsf3(float, float); -extern double __adddf3(double, double); -extern float __aeabi_fsub(float, float); -extern double __aeabi_dsub(double, double); -extern float __aeabi_fmul(float, float); -extern double __aeabi_dmul(double, double); -extern float __aeabi_fdiv(float, float); -extern double __aeabi_ddiv(double, double); -extern float __aeabi_i2f(int); -extern double __aeabi_i2d(int); -extern float __aeabi_d2f(double); -extern double __aeabi_f2d(float); -extern int __aeabi_f2iz(float); -extern int __aeabi_d2iz(double); -extern int __aeabi_fcmplt(float, float); -extern int __aeabi_dcmplt(double, double); -extern int __aeabi_fcmple(float, float); -extern int __aeabi_dcmple(double, double); -extern int __aeabi_fcmpeq(float, float); -extern int __aeabi_dcmpeq(double, double); -extern int __aeabi_fcmpge(float, float); -extern int __aeabi_dcmpge(double, double); -extern int __aeabi_fcmpgt(float, float); -extern int __aeabi_dcmpgt(double, double); -extern int __aeabi_fcmpun(float, float); -extern int __aeabi_dcmpun(double, double); -# define swf_ff(i0,r0,r1) _swf_ff(_jit,i0,r0,r1) -static void -_swf_ff(jit_state_t*,float(*)(float),int32_t,int32_t) maybe_unused; -# define swf_dd(i0,r0,r1) _swf_dd(_jit,i0,r0,r1) -static void -_swf_dd(jit_state_t*,double(*)(double),int32_t,int32_t) maybe_unused; -# define swf_fff(i0,r0,r1,r2) _swf_fff(_jit,i0,r0,r1,r2) -static void _swf_fff(jit_state_t*,float(*)(float,float), - int32_t,int32_t,int32_t); -# define swf_ddd(i0,r0,r1,r2) _swf_ddd(_jit,i0,r0,r1,r2) -static void _swf_ddd(jit_state_t*,double(*)(double,double), - int32_t,int32_t,int32_t); -# define swf_fff_(i0,r0,r1,i1) _swf_fff_(_jit,i0,r0,r1,i1) -static void _swf_fff_(jit_state_t*,float(*)(float,float), - int32_t,int32_t,jit_float32_t); -# define swf_ddd_(i0,r0,r1,i1) _swf_ddd_(_jit,i0,r0,r1,i1) -static void _swf_ddd_(jit_state_t*,double(*)(double,double), - int32_t,int32_t,jit_float64_t); -# define swf_iff(i0,r0,r1,r2) _swf_iff(_jit,i0,r0,r1,r2) -static void _swf_iff(jit_state_t*,int(*)(float,float), - int32_t,int32_t,int32_t); -# define swf_idd(i0,r0,r1,r2) _swf_idd(_jit,i0,r0,r1,r2) -static void _swf_idd(jit_state_t*,int(*)(double,double), - int32_t,int32_t,int32_t); -# define swf_iff_(i0,r0,r1,r2) _swf_iff_(_jit,i0,r0,r1,r2) -static void _swf_iff_(jit_state_t*,int(*)(float,float), - int32_t,int32_t,jit_float32_t); -# define swf_idd_(i0,r0,r1,r2) _swf_idd_(_jit,i0,r0,r1,r2) -static void _swf_idd_(jit_state_t*,int(*)(double,double), - int32_t,int32_t,jit_float64_t); -# define swf_iunff(i0,r0,r1,r2) _swf_iunff(_jit,i0,r0,r1,r2) -static void _swf_iunff(jit_state_t*,int(*)(float,float), - int32_t,int32_t,int32_t); -# define swf_iundd(i0,r0,r1,r2) _swf_iundd(_jit,i0,r0,r1,r2) -static void _swf_iundd(jit_state_t*,int(*)(double,double), - int32_t,int32_t,int32_t); -# define swf_iunff_(i0,r0,r1,i1) _swf_iunff_(_jit,i0,r0,r1,i1) -static void _swf_iunff_(jit_state_t*,int(*)(float,float), - int32_t,int32_t,jit_float32_t); -# define swf_iundd_(i0,r0,r1,i1) _swf_iundd_(_jit,i0,r0,r1,i1) -static void _swf_iundd_(jit_state_t*,int(*)(double,double), - int32_t,int32_t,jit_float64_t); -# define swf_bff(i0,cc,i1,r0,r1) _swf_bff(_jit,i0,cc,i1,r0,r1) -static jit_word_t _swf_bff(jit_state_t*,int(*)(float,float),int, - jit_word_t,int32_t,int32_t); -# define swf_bdd(i0,cc,i1,r0,r1) _swf_bdd(_jit,i0,cc,i1,r0,r1) -static jit_word_t _swf_bdd(jit_state_t*,int(*)(double,double),int, - jit_word_t,int32_t,int32_t); -# define swf_bff_(i0,cc,i1,r0,i2) _swf_bff_(_jit,i0,cc,i1,r0,i2) -static jit_word_t _swf_bff_(jit_state_t*,int(*)(float,float),int, - jit_word_t,int32_t,jit_float32_t); -# define swf_bdd_(i0,cc,i1,r0,i2) _swf_bdd_(_jit,i0,cc,i1,r0,i2) -static jit_word_t _swf_bdd_(jit_state_t*,int(*)(double,double),int, - jit_word_t,int32_t,jit_float64_t); -# define swf_bunff(eq,i0,r0,r1) _swf_bunff(_jit,eq,i0,r0,r1) -static jit_word_t _swf_bunff(jit_state_t*,int, - jit_word_t,int32_t,int32_t); -# define swf_bundd(eq,i0,r0,r1) _swf_bundd(_jit,eq,i0,r0,r1) -static jit_word_t _swf_bundd(jit_state_t*,int, - jit_word_t,int32_t,int32_t); -# define swf_bunff_(eq,i0,r0,i1) _swf_bunff_(_jit,eq,i0,r0,i1) -static jit_word_t _swf_bunff_(jit_state_t*,int, - jit_word_t,int32_t,jit_float32_t); -# define swf_bundd_(eq,i0,r0,i1) _swf_bundd_(_jit,eq,i0,r0,i1) -static jit_word_t _swf_bundd_(jit_state_t*,int, - jit_word_t,int32_t,jit_float64_t); -# define swf_extr_f(r0,r1) _swf_extr_f(_jit,r0,r1) -static void _swf_extr_f(jit_state_t*,int32_t,int32_t); -# define swf_extr_d(r0,r1) _swf_extr_d(_jit,r0,r1) -static void _swf_extr_d(jit_state_t*,int32_t,int32_t); -# define swf_extr_d_f(r0,r1) _swf_extr_d_f(_jit,r0,r1) -static void _swf_extr_d_f(jit_state_t*,int32_t,int32_t); -# define swf_extr_f_d(r0,r1) _swf_extr_f_d(_jit,r0,r1) -static void _swf_extr_f_d(jit_state_t*,int32_t,int32_t); -# define swf_truncr_f_i(r0,r1) _swf_truncr_f_i(_jit,r0,r1) -static void _swf_truncr_f_i(jit_state_t*,int32_t,int32_t); -# define swf_truncr_d_i(r0,r1) _swf_truncr_d_i(_jit,r0,r1) -static void _swf_truncr_d_i(jit_state_t*,int32_t,int32_t); -# define swf_movr_f(r0,r1) _swf_movr_f(_jit,r0,r1) -static void _swf_movr_f(jit_state_t*,int32_t,int32_t); -# define swf_movr_d(r0,r1) _swf_movr_d(_jit,r0,r1) -static void _swf_movr_d(jit_state_t*,int32_t,int32_t); -# define swf_movi_f(r0,i0) _swf_movi_f(_jit,r0,i0) -static void _swf_movi_f(jit_state_t*,int32_t,jit_float32_t); -# define swf_movi_d(r0,i0) _swf_movi_d(_jit,r0,i0) -static void _swf_movi_d(jit_state_t*,int32_t,jit_float64_t); -# define swf_absr_f(r0,r1) _swf_absr_f(_jit,r0,r1) -static void _swf_absr_f(jit_state_t*,int32_t,int32_t); -# define swf_absr_d(r0,r1) _swf_absr_d(_jit,r0,r1) -static void _swf_absr_d(jit_state_t*,int32_t,int32_t); -# define swf_negr_f(r0,r1) _swf_negr_f(_jit,r0,r1) -static void _swf_negr_f(jit_state_t*,int32_t,int32_t); -# define swf_negr_d(r0,r1) _swf_negr_d(_jit,r0,r1) -static void _swf_negr_d(jit_state_t*,int32_t,int32_t); -# define swf_sqrtr_f(r0,r1) swf_ff(sqrtf,r0,r1) -# define swf_sqrtr_d(r0,r1) swf_dd(sqrt,r0,r1) -# define swf_addr_f(r0,r1,r2) swf_fff(__addsf3,r0,r1,r2) -# define swf_addi_f(r0,r1,i0) swf_fff_(__addsf3,r0,r1,i0) -# define swf_addr_d(r0,r1,r2) swf_ddd(__adddf3,r0,r1,r2) -# define swf_addi_d(r0,r1,i0) swf_ddd_(__adddf3,r0,r1,i0) -# define swf_subr_f(r0,r1,r2) swf_fff(__aeabi_fsub,r0,r1,r2) -# define swf_subi_f(r0,r1,i0) swf_fff_(__aeabi_fsub,r0,r1,i0) -# define swf_subr_d(r0,r1,r2) swf_ddd(__aeabi_dsub,r0,r1,r2) -# define swf_subi_d(r0,r1,i0) swf_ddd_(__aeabi_dsub,r0,r1,i0) -# define swf_rsbr_f(r0, r1, r2) swf_subr_f(r0, r2, r1) -# define swf_rsbi_f(r0, r1, i0) _swf_rsbi_f(_jit, r0, r1, i0) -static void _swf_rsbi_f(jit_state_t*,int32_t,int32_t,jit_float32_t); -# define swf_rsbr_d(r0, r1, r2) swf_subr_d(r0, r2, r1) -# define swf_rsbi_d(r0, r1, i0) _swf_rsbi_d(_jit, r0, r1, i0) -static void _swf_rsbi_d(jit_state_t*,int32_t,int32_t,jit_float64_t); -# define swf_mulr_f(r0,r1,r2) swf_fff(__aeabi_fmul,r0,r1,r2) -# define swf_muli_f(r0,r1,i0) swf_fff_(__aeabi_fmul,r0,r1,i0) -# define swf_mulr_d(r0,r1,r2) swf_ddd(__aeabi_dmul,r0,r1,r2) -# define swf_muli_d(r0,r1,i0) swf_ddd_(__aeabi_dmul,r0,r1,i0) -# define swf_divr_f(r0,r1,r2) swf_fff(__aeabi_fdiv,r0,r1,r2) -# define swf_divi_f(r0,r1,i0) swf_fff_(__aeabi_fdiv,r0,r1,i0) -# define swf_divr_d(r0,r1,r2) swf_ddd(__aeabi_ddiv,r0,r1,r2) -# define swf_divi_d(r0,r1,i0) swf_ddd_(__aeabi_ddiv,r0,r1,i0) -# define swf_ltr_f(r0,r1,r2) swf_iff(__aeabi_fcmplt,r0,r1,r2) -# define swf_lti_f(r0,r1,i0) swf_iff_(__aeabi_fcmplt,r0,r1,i0) -# define swf_ltr_d(r0,r1,r2) swf_idd(__aeabi_dcmplt,r0,r1,r2) -# define swf_lti_d(r0,r1,i0) swf_idd_(__aeabi_dcmplt,r0,r1,i0) -# define swf_ler_f(r0,r1,r2) swf_iff(__aeabi_fcmple,r0,r1,r2) -# define swf_lei_f(r0,r1,i0) swf_iff_(__aeabi_fcmple,r0,r1,i0) -# define swf_ler_d(r0,r1,r2) swf_idd(__aeabi_dcmple,r0,r1,r2) -# define swf_lei_d(r0,r1,i0) swf_idd_(__aeabi_dcmple,r0,r1,i0) -# define swf_eqr_f(r0,r1,r2) swf_iff(__aeabi_fcmpeq,r0,r1,r2) -# define swf_eqi_f(r0,r1,i0) swf_iff_(__aeabi_fcmpeq,r0,r1,i0) -# define swf_eqr_d(r0,r1,r2) swf_idd(__aeabi_dcmpeq,r0,r1,r2) -# define swf_eqi_d(r0,r1,i0) swf_idd_(__aeabi_dcmpeq,r0,r1,i0) -# define swf_ger_f(r0,r1,r2) swf_iff(__aeabi_fcmpge,r0,r1,r2) -# define swf_gei_f(r0,r1,i0) swf_iff_(__aeabi_fcmpge,r0,r1,i0) -# define swf_ger_d(r0,r1,r2) swf_idd(__aeabi_dcmpge,r0,r1,r2) -# define swf_gei_d(r0,r1,i0) swf_idd_(__aeabi_dcmpge,r0,r1,i0) -# define swf_gtr_f(r0,r1,r2) swf_iff(__aeabi_fcmpgt,r0,r1,r2) -# define swf_gti_f(r0,r1,i0) swf_iff_(__aeabi_fcmpgt,r0,r1,i0) -# define swf_gtr_d(r0,r1,r2) swf_idd(__aeabi_dcmpgt,r0,r1,r2) -# define swf_gti_d(r0,r1,i0) swf_idd_(__aeabi_dcmpgt,r0,r1,i0) -# define swf_ner_f(r0,r1,r2) _swf_ner_f(_jit,r0,r1,r2) -static void _swf_ner_f(jit_state_t*,int32_t,int32_t,int32_t); -# define swf_nei_f(r0,r1,i0) _swf_nei_f(_jit,r0,r1,i0) -static void _swf_nei_f(jit_state_t*,int32_t,int32_t,jit_float32_t); -# define swf_ner_d(r0,r1,r2) _swf_ner_d(_jit,r0,r1,r2) -static void _swf_ner_d(jit_state_t*,int32_t,int32_t,int32_t); -# define swf_nei_d(r0,r1,i0) _swf_nei_d(_jit,r0,r1,i0) -static void _swf_nei_d(jit_state_t*,int32_t,int32_t,jit_float64_t); -# define swf_unltr_f(r0,r1,r2) swf_iunff(__aeabi_fcmplt,r0,r1,r2) -# define swf_unlti_f(r0,r1,i0) swf_iunff_(__aeabi_fcmplt,r0,r1,i0) -# define swf_unltr_d(r0,r1,r2) swf_iundd(__aeabi_dcmplt,r0,r1,r2) -# define swf_unlti_d(r0,r1,i0) swf_iundd_(__aeabi_dcmplt,r0,r1,i0) -# define swf_unler_f(r0,r1,r2) swf_iunff(__aeabi_fcmple,r0,r1,r2) -# define swf_unlei_f(r0,r1,i0) swf_iunff_(__aeabi_fcmple,r0,r1,i0) -# define swf_unler_d(r0,r1,r2) swf_iundd(__aeabi_dcmple,r0,r1,r2) -# define swf_unlei_d(r0,r1,i0) swf_iundd_(__aeabi_dcmple,r0,r1,i0) -# define swf_uneqr_f(r0,r1,r2) swf_iunff(__aeabi_fcmpeq,r0,r1,r2) -# define swf_uneqi_f(r0,r1,i0) swf_iunff_(__aeabi_fcmpeq,r0,r1,i0) -# define swf_uneqr_d(r0,r1,r2) swf_iundd(__aeabi_dcmpeq,r0,r1,r2) -# define swf_uneqi_d(r0,r1,i0) swf_iundd_(__aeabi_dcmpeq,r0,r1,i0) -# define swf_unger_f(r0,r1,r2) swf_iunff(__aeabi_fcmpge,r0,r1,r2) -# define swf_ungei_f(r0,r1,i0) swf_iunff_(__aeabi_fcmpge,r0,r1,i0) -# define swf_unger_d(r0,r1,r2) swf_iundd(__aeabi_dcmpge,r0,r1,r2) -# define swf_ungei_d(r0,r1,i0) swf_iundd_(__aeabi_dcmpge,r0,r1,i0) -# define swf_ungtr_f(r0,r1,r2) swf_iunff(__aeabi_fcmpgt,r0,r1,r2) -# define swf_ungti_f(r0,r1,i0) swf_iunff_(__aeabi_fcmpgt,r0,r1,i0) -# define swf_ungtr_d(r0,r1,r2) swf_iundd(__aeabi_dcmpgt,r0,r1,r2) -# define swf_ungti_d(r0,r1,i0) swf_iundd_(__aeabi_dcmpgt,r0,r1,i0) -# define swf_ltgtr_f(r0,r1,r2) _swf_ltgtr_f(_jit,r0,r1,r2) -static void _swf_ltgtr_f(jit_state_t*,int32_t,int32_t,int32_t); -# define swf_ltgti_f(r0,r1,i0) _swf_ltgti_f(_jit,r0,r1,i0) -static void _swf_ltgti_f(jit_state_t*,int32_t,int32_t,jit_float32_t); -# define swf_ltgtr_d(r0,r1,r2) _swf_ltgtr_d(_jit,r0,r1,r2) -static void _swf_ltgtr_d(jit_state_t*,int32_t,int32_t,int32_t); -# define swf_ltgti_d(r0,r1,i0) _swf_ltgti_d(_jit,r0,r1,i0) -static void _swf_ltgti_d(jit_state_t*,int32_t,int32_t,jit_float64_t); -# define swf_ordr_f(r0,r1,r2) _swf_ordr_f(_jit,r0,r1,r2) -static void _swf_ordr_f(jit_state_t*,int32_t,int32_t,int32_t); -# define swf_ordi_f(r0,r1,i0) _swf_ordi_f(_jit,r0,r1,i0) -static void _swf_ordi_f(jit_state_t*,int32_t,int32_t,jit_float32_t); -# define swf_ordr_d(r0,r1,r2) _swf_ordr_d(_jit,r0,r1,r2) -static void _swf_ordr_d(jit_state_t*,int32_t,int32_t,int32_t); -# define swf_ordi_d(r0,r1,i0) _swf_ordi_d(_jit,r0,r1,i0) -static void _swf_ordi_d(jit_state_t*,int32_t,int32_t,jit_float64_t); -# define swf_unordr_f(r0,r1,r2) swf_iunff(__aeabi_fcmpun,r0,r1,r2) -# define swf_unordi_f(r0,r1,i0) swf_iunff_(__aeabi_fcmpun,r0,r1,i0) -# define swf_unordr_d(r0,r1,r2) swf_iundd(__aeabi_dcmpun,r0,r1,r2) -# define swf_unordi_d(r0,r1,i0) swf_iundd_(__aeabi_dcmpun,r0,r1,i0) -# define swf_bltr_f(i0,r0,r1) swf_bff(__aeabi_fcmplt,ARM_CC_NE,i0,r0,r1) -# define swf_blti_f(i0,r0,i1) swf_bff_(__aeabi_fcmplt,ARM_CC_NE,i0,r0,i1) -# define swf_bltr_d(i0,r0,r1) swf_bdd(__aeabi_dcmplt,ARM_CC_NE,i0,r0,r1) -# define swf_blti_d(i0,r0,i1) swf_bdd_(__aeabi_dcmplt,ARM_CC_NE,i0,r0,i1) -# define swf_bler_f(i0,r0,r1) swf_bff(__aeabi_fcmple,ARM_CC_NE,i0,r0,r1) -# define swf_blei_f(i0,r0,i1) swf_bff_(__aeabi_fcmple,ARM_CC_NE,i0,r0,i1) -# define swf_bler_d(i0,r0,r1) swf_bdd(__aeabi_dcmple,ARM_CC_NE,i0,r0,r1) -# define swf_blei_d(i0,r0,i1) swf_bdd_(__aeabi_dcmple,ARM_CC_NE,i0,r0,i1) -# define swf_beqr_f(i0,r0,r1) swf_bff(__aeabi_fcmpeq,ARM_CC_NE,i0,r0,r1) -# define swf_beqi_f(i0,r0,i1) swf_bff_(__aeabi_fcmpeq,ARM_CC_NE,i0,r0,i1) -# define swf_beqr_d(i0,r0,r1) swf_bdd(__aeabi_dcmpeq,ARM_CC_NE,i0,r0,r1) -# define swf_beqi_d(i0,r0,i1) swf_bdd_(__aeabi_dcmpeq,ARM_CC_NE,i0,r0,i1) -# define swf_bger_f(i0,r0,r1) swf_bff(__aeabi_fcmpge,ARM_CC_NE,i0,r0,r1) -# define swf_bgei_f(i0,r0,i1) swf_bff_(__aeabi_fcmpge,ARM_CC_NE,i0,r0,i1) -# define swf_bger_d(i0,r0,r1) swf_bdd(__aeabi_dcmpge,ARM_CC_NE,i0,r0,r1) -# define swf_bgei_d(i0,r0,i1) swf_bdd_(__aeabi_dcmpge,ARM_CC_NE,i0,r0,i1) -# define swf_bgtr_f(i0,r0,r1) swf_bff(__aeabi_fcmpgt,ARM_CC_NE,i0,r0,r1) -# define swf_bgti_f(i0,r0,i1) swf_bff_(__aeabi_fcmpgt,ARM_CC_NE,i0,r0,i1) -# define swf_bgtr_d(i0,r0,r1) swf_bdd(__aeabi_dcmpgt,ARM_CC_NE,i0,r0,r1) -# define swf_bgti_d(i0,r0,i1) swf_bdd_(__aeabi_dcmpgt,ARM_CC_NE,i0,r0,i1) -# define swf_bner_f(i0,r0,r1) swf_bff(__aeabi_fcmpeq,ARM_CC_EQ,i0,r0,r1) -# define swf_bnei_f(i0,r0,i1) swf_bff_(__aeabi_fcmpeq,ARM_CC_EQ,i0,r0,i1) -# define swf_bner_d(i0,r0,r1) swf_bdd(__aeabi_dcmpeq,ARM_CC_EQ,i0,r0,r1) -# define swf_bnei_d(i0,r0,i1) swf_bdd_(__aeabi_dcmpeq,ARM_CC_EQ,i0,r0,i1) -# define swf_bunltr_f(i0,r0,r1) swf_bff(__aeabi_fcmpge,ARM_CC_EQ,i0,r0,r1) -# define swf_bunlti_f(i0,r0,i1) swf_bff_(__aeabi_fcmpge,ARM_CC_EQ,i0,r0,i1) -# define swf_bunltr_d(i0,r0,r1) swf_bdd(__aeabi_dcmpge,ARM_CC_EQ,i0,r0,r1) -# define swf_bunlti_d(i0,r0,i1) swf_bdd_(__aeabi_dcmpge,ARM_CC_EQ,i0,r0,i1) -# define swf_bunler_f(i0,r0,r1) swf_bff(__aeabi_fcmpgt,ARM_CC_EQ,i0,r0,r1) -# define swf_bunlei_f(i0,r0,i1) swf_bff_(__aeabi_fcmpgt,ARM_CC_EQ,i0,r0,i1) -# define swf_bunler_d(i0,r0,r1) swf_bdd(__aeabi_dcmpgt,ARM_CC_EQ,i0,r0,r1) -# define swf_bunlei_d(i0,r0,i1) swf_bdd_(__aeabi_dcmpgt,ARM_CC_EQ,i0,r0,i1) -# define swf_buneqr_f(i0,r0,r1) swf_bunff(1,i0,r0,r1) -# define swf_buneqi_f(i0,r0,i1) swf_bunff_(1,i0,r0,i1) -# define swf_buneqr_d(i0,r0,r1) swf_bundd(1,i0,r0,r1) -# define swf_buneqi_d(i0,r0,i1) swf_bundd_(1,i0,r0,i1) -# define swf_bunger_f(i0,r0,r1) swf_bff(__aeabi_fcmplt,ARM_CC_EQ,i0,r0,r1) -# define swf_bungei_f(i0,r0,i1) swf_bff_(__aeabi_fcmplt,ARM_CC_EQ,i0,r0,i1) -# define swf_bunger_d(i0,r0,r1) swf_bdd(__aeabi_dcmplt,ARM_CC_EQ,i0,r0,r1) -# define swf_bungei_d(i0,r0,i1) swf_bdd_(__aeabi_dcmplt,ARM_CC_EQ,i0,r0,i1) -# define swf_bungtr_f(i0,r0,r1) swf_bff(__aeabi_fcmple,ARM_CC_EQ,i0,r0,r1) -# define swf_bungti_f(i0,r0,i1) swf_bff_(__aeabi_fcmple,ARM_CC_EQ,i0,r0,i1) -# define swf_bungtr_d(i0,r0,r1) swf_bdd(__aeabi_dcmple,ARM_CC_EQ,i0,r0,r1) -# define swf_bungti_d(i0,r0,i1) swf_bdd_(__aeabi_dcmple,ARM_CC_EQ,i0,r0,i1) -# define swf_bltgtr_f(i0,r0,r1) swf_bunff(0,i0,r0,r1) -# define swf_bltgti_f(i0,r0,i1) swf_bunff_(0,i0,r0,i1) -# define swf_bltgtr_d(i0,r0,r1) swf_bundd(0,i0,r0,r1) -# define swf_bltgti_d(i0,r0,i1) swf_bundd_(0,i0,r0,i1) -# define swf_bordr_f(i0,r0,r1) swf_bff(__aeabi_fcmpun,ARM_CC_EQ,i0,r0,r1) -# define swf_bordi_f(i0,r0,i1) swf_bff_(__aeabi_fcmpun,ARM_CC_EQ,i0,r0,i1) -# define swf_bordr_d(i0,r0,r1) swf_bdd(__aeabi_dcmpun,ARM_CC_EQ,i0,r0,r1) -# define swf_bordi_d(i0,r0,i1) swf_bdd_(__aeabi_dcmpun,ARM_CC_EQ,i0,r0,i1) -# define swf_bunordr_f(i0,r0,r1) swf_bff(__aeabi_fcmpun,ARM_CC_NE,i0,r0,r1) -# define swf_bunordi_f(i0,r0,i1) swf_bff_(__aeabi_fcmpun,ARM_CC_NE,i0,r0,i1) -# define swf_bunordr_d(i0,r0,r1) swf_bdd(__aeabi_dcmpun,ARM_CC_NE,i0,r0,r1) -# define swf_bunordi_d(i0,r0,i1) swf_bdd_(__aeabi_dcmpun,ARM_CC_NE,i0,r0,i1) -# define swf_ldr_f(r0,r1) _swf_ldr_f(_jit,r0,r1) -static void _swf_ldr_f(jit_state_t*,int32_t,int32_t); -# define swf_ldr_d(r0,r1) _swf_ldr_d(_jit,r0,r1) -static void _swf_ldr_d(jit_state_t*,int32_t,int32_t); -# define swf_ldi_f(r0,i0) _swf_ldi_f(_jit,r0,i0) -static void _swf_ldi_f(jit_state_t*,int32_t,jit_word_t); -# define swf_ldi_d(r0,i0) _swf_ldi_d(_jit,r0,i0) -static void _swf_ldi_d(jit_state_t*,int32_t,jit_word_t); -# define swf_ldxr_f(r0,r1,r2) _swf_ldxr_f(_jit,r0,r1,r2) -static void _swf_ldxr_f(jit_state_t*,int32_t,int32_t,int32_t); -# define swf_ldxr_d(r0,r1,r2) _swf_ldxr_d(_jit,r0,r1,r2) -static void _swf_ldxr_d(jit_state_t*,int32_t,int32_t,int32_t); -# define swf_ldxi_f(r0,r1,i0) _swf_ldxi_f(_jit,r0,r1,i0) -static void _swf_ldxi_f(jit_state_t*,int32_t,int32_t,jit_word_t); -# define swf_ldxi_d(r0,r1,i0) _swf_ldxi_d(_jit,r0,r1,i0) -static void _swf_ldxi_d(jit_state_t*,int32_t,int32_t,jit_word_t); -# define swf_str_f(r0,r1) _swf_str_f(_jit,r0,r1) -static void _swf_str_f(jit_state_t*,int32_t,int32_t); -# define swf_str_d(r0,r1) _swf_str_d(_jit,r0,r1) -static void _swf_str_d(jit_state_t*,int32_t,int32_t); -# define swf_sti_f(r0,i0) _swf_sti_f(_jit,r0,i0) -static void _swf_sti_f(jit_state_t*,jit_word_t,int32_t); -# define swf_sti_d(r0,i0) _swf_sti_d(_jit,r0,i0) -static void _swf_sti_d(jit_state_t*,jit_word_t,int32_t); -# define swf_stxr_f(r0,r1,r2) _swf_stxr_f(_jit,r0,r1,r2) -static void _swf_stxr_f(jit_state_t*,int32_t,int32_t,int32_t); -# define swf_stxr_d(r0,r1,r2) _swf_stxr_d(_jit,r0,r1,r2) -static void _swf_stxr_d(jit_state_t*,int32_t,int32_t,int32_t); -# define swf_stxi_f(r0,r1,i0) _swf_stxi_f(_jit,r0,r1,i0) -static void _swf_stxi_f(jit_state_t*,jit_word_t,int32_t,int32_t); -# define swf_stxi_d(r0,r1,i0) _swf_stxi_d(_jit,r0,r1,i0) -static void _swf_stxi_d(jit_state_t*,jit_word_t,int32_t,int32_t); -# define swf_vaarg_d(r0, r1) _swf_vaarg_d(_jit, r0, r1) -static void _swf_vaarg_d(jit_state_t*, int32_t, int32_t); -#endif - -#if CODE -#define swf_off(rn) ((rn - 16) << 2) - -#define swf_call(function, label, regno) \ - do { \ - jit_word_t d; \ - if (!jit_exchange_p()) { \ - if (jit_thumb_p()) \ - d = (((jit_word_t)function - _jit->pc.w) >> 1) - 2; \ - else \ - d = (((jit_word_t)function - _jit->pc.w) >> 2) - 2; \ - if (_s24P(d)) { \ - if (jit_thumb_p()) \ - T2_BLI(encode_thumb_jump(d)); \ - else \ - BLI(d & 0x00ffffff); \ - } \ - else \ - goto label; \ - } \ - else { \ - label: \ - movi(regno, (jit_word_t)function); \ - if (jit_thumb_p()) \ - T1_BLX(regno); \ - else \ - BLX(regno); \ - } \ - } while (0) -#define swf_call_with_get_reg(function, label) \ - do { \ - jit_word_t d; \ - int32_t reg; \ - if (!jit_exchange_p()) { \ - if (jit_thumb_p()) \ - d = (((jit_word_t)function - _jit->pc.w) >> 1) - 2; \ - else \ - d = (((jit_word_t)function - _jit->pc.w) >> 2) - 2; \ - if (_s24P(d)) { \ - if (jit_thumb_p()) \ - T2_BLI(encode_thumb_jump(d)); \ - else \ - BLI(d & 0x00ffffff); \ - } \ - else \ - goto label; \ - } \ - else { \ - label: \ - reg = jit_get_reg(jit_class_gpr); \ - movi(rn(reg), (jit_word_t)function); \ - if (jit_thumb_p()) \ - T1_BLX(rn(reg)); \ - else \ - BLX(rn(reg)); \ - jit_unget_reg(reg); \ - } \ - } while (0) -#define swf_ldrin(rt, rn, im) \ - do { \ - if (jit_thumb_p()) T2_LDRIN(rt, rn, im); \ - else LDRIN(rt, rn, im); \ - } while (0) -#define swf_strin(rt, rn, im) \ - do { \ - if (jit_thumb_p()) T2_STRIN(rt, rn, im); \ - else STRIN(rt, rn, im); \ - } while (0) -#define swf_bici(rt, rn, im) \ - do { \ - if (jit_thumb_p()) \ - T2_BICI(rt, rn, encode_thumb_immediate(im)); \ - else \ - BICI(rt, rn, encode_arm_immediate(im)); \ - } while (0) - -#if !defined(__GNUC__) -float __addsf3(float u, float v) -{ - return (u + v); -} - -double -__adddf3(double u, double v) -{ - return (u + v); -} - -float -__aeabi_fsub(float u, float v) -{ - return (u - v); -} - -double -__aeabi_dsub(double u, double v) -{ - return (u - v); -} - -float -__aeabi_fmul(float u, float v) -{ - return (u * v); -} - -double -__aeabi_dmul(double u, double v) -{ - return (u * v); -} - -float -__aeabi_fdiv(float u, float v) -{ - return (u / v); -} - -double -__aeabi_ddiv(double u, double v) -{ - return (u / v); -} - -float -__aeabi_i2f(int u) -{ - return (u); -} - -double -__aeabi_i2d(int u) -{ - return (u); -} - -float -__aeabi_d2f(double u) -{ - return (u); -} - -double -__aeabi_f2d(float u) -{ - return (u); -} - -int -__aeabi_f2iz(float u) -{ - return (u); -} - -int -__aeabi_d2iz(double u) -{ - return (u); -} - -int -__aeabi_fcmplt(float u, float v) -{ - return (u < v); -} - -int -__aeabi_dcmplt(double u, double v) -{ - return (u < v); -} - -int -__aeabi_fcmple(float u, float v) -{ - return (u <= v); -} - -int -__aeabi_dcmple(double u, double v) -{ - return (u <= v); -} - -int -__aeabi_fcmpeq(float u, float v) -{ - return (u == v); -} - -int -__aeabi_dcmpeq(double u, double v) -{ - return (u == v); -} - -int -__aeabi_fcmpge(float u, float v) -{ - return (u >= v); -} - -int -__aeabi_dcmpge(double u, double v) -{ - return (u >= v); -} - -int -__aeabi_fcmpgt(float u, float v) -{ - return (u > v); -} - -int -__aeabi_dcmpgt(double u, double v) -{ - return (u > v); -} - -int -__aeabi_fcmpun(float u, float v) -{ - return ((u != u) || (v != v)); -} - -int -__aeabi_dcmpun(double u, double v) -{ - return ((u != u) || (v != v)); -} -#endif - -static void -_swf_ff(jit_state_t *_jit, float(*i0)(float), - int32_t r0, int32_t r1) -{ - jit_get_reg_args(); - if (jit_fpr_p(r1)) - swf_ldrin(_R0_REGNO, _FP_REGNO, swf_off(r1) + 8); - else - movr(_R0_REGNO, r1); - swf_call(i0, fallback, _R1_REGNO); - if (jit_fpr_p(r0)) - swf_strin(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - else - movr(r0, _R0_REGNO); - jit_unget_reg_args(); -} - -static void -_swf_dd(jit_state_t *_jit, double (*i0)(double), - int32_t r0, int32_t r1) -{ - jit_get_reg_args(); - if (jit_fpr_p(r1)) { - if (!jit_thumb_p() && jit_armv5e_p()) - LDRDIN(_R0_REGNO, _FP_REGNO, swf_off(r1) + 8); - else { - swf_ldrin(_R0_REGNO, _FP_REGNO, swf_off(r1) + 8); - swf_ldrin(_R1_REGNO, _FP_REGNO, swf_off(r1) + 4); - } - } - else { - movr(_R0_REGNO, r1); - movr(_R1_REGNO, r1 + 1); - } - swf_call(i0, fallback, _R2_REGNO); - if (jit_fpr_p(r0)) { - if (!jit_thumb_p() && jit_armv5e_p()) - STRDIN(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - else { - swf_strin(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - swf_strin(_R1_REGNO, _FP_REGNO, swf_off(r0) + 4); - } - } - else { - movr(r0, _R0_REGNO); - movr(r0 + 1, _R1_REGNO); - } - jit_unget_reg_args(); -} - -static void -_swf_fff(jit_state_t *_jit, float (*i0)(float, float), - int32_t r0, int32_t r1, int32_t r2) -{ - jit_get_reg_args(); - if (jit_fpr_p(r1)) - swf_ldrin(_R0_REGNO, _FP_REGNO, swf_off(r1) + 8); - else - movr(_R0_REGNO, r1); - if (jit_fpr_p(r2)) - swf_ldrin(_R1_REGNO, _FP_REGNO, swf_off(r2) + 8); - else - movr(_R1_REGNO, r1); - swf_call(i0, fallback, _R3_REGNO); - if (jit_fpr_p(r0)) - swf_strin(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - else - movr(r0, _R0_REGNO); - jit_unget_reg_args(); -} - -static void -_swf_ddd(jit_state_t *_jit, double (*i0)(double, double), - int32_t r0, int32_t r1, int32_t r2) -{ - jit_get_reg_args(); - if (jit_fpr_p(r1)) { - if (!jit_thumb_p() && jit_armv5e_p()) - LDRDIN(_R0_REGNO, _FP_REGNO, swf_off(r1) + 8); - else { - swf_ldrin(_R0_REGNO, _FP_REGNO, swf_off(r1) + 8); - swf_ldrin(_R1_REGNO, _FP_REGNO, swf_off(r1) + 4); - } - } - else { - movr(_R0_REGNO, r1); - movr(_R1_REGNO, r1 + 1); - } - if (jit_fpr_p(r2)) { - if (!jit_thumb_p() && jit_armv5e_p()) - LDRDIN(_R2_REGNO, _FP_REGNO, swf_off(r2) + 8); - else { - swf_ldrin(_R2_REGNO, _FP_REGNO, swf_off(r2) + 8); - swf_ldrin(_R3_REGNO, _FP_REGNO, swf_off(r2) + 4); - } - } - else { - movr(_R2_REGNO, r2); - movr(_R3_REGNO, r2 + 1); - } - swf_call_with_get_reg(i0, fallback); - if (jit_fpr_p(r0)) { - if (!jit_thumb_p() && jit_armv5e_p()) - STRDIN(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - else { - swf_strin(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - swf_strin(_R1_REGNO, _FP_REGNO, swf_off(r0) + 4); - } - } - else { - movr(r0, _R0_REGNO); - movr(r0 + 1, _R1_REGNO); - } - jit_unget_reg_args(); -} - -static void -_swf_fff_(jit_state_t *_jit, float (*i0)(float, float), - int32_t r0, int32_t r1, jit_float32_t i1) -{ - union { - int32_t i; - jit_float32_t f; - } data; - jit_get_reg_args(); - data.f = i1; - if (jit_fpr_p(r1)) - swf_ldrin(_R0_REGNO, _FP_REGNO, swf_off(r1) + 8); - else - movr(_R0_REGNO, r1); - movi(_R1_REGNO, data.i); - swf_call(i0, fallback, _R3_REGNO); - if (jit_fpr_p(r0)) - swf_strin(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - else - movr(r0, _R0_REGNO); - jit_unget_reg_args(); -} - -static void -_swf_rsbi_f(jit_state_t *_jit, int32_t r0, int32_t r1, jit_float32_t i0) -{ - union { - int32_t i; - jit_float32_t f; - } data; - jit_get_reg_args(); - data.f = i0; - movi(_R0_REGNO, data.i); - if (jit_fpr_p(r1)) - swf_ldrin(_R1_REGNO, _FP_REGNO, swf_off(r1) + 8); - else - movr(_R1_REGNO, r1); - swf_call(__aeabi_fsub, fallback, _R3_REGNO); - if (jit_fpr_p(r0)) - swf_strin(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - else - movr(r0, _R0_REGNO); - jit_unget_reg_args(); -} - -static void -_swf_ddd_(jit_state_t *_jit, double (*i0)(double, double), - int32_t r0, int32_t r1, jit_float64_t i1) -{ - union { - int32_t i[2]; - jit_float64_t d; - } data; - jit_get_reg_args(); - - data.d = i1; - if (jit_fpr_p(r1)) { - if (!jit_thumb_p() && jit_armv5e_p()) - LDRDIN(_R0_REGNO, _FP_REGNO, swf_off(r1) + 8); - else { - swf_ldrin(_R0_REGNO, _FP_REGNO, swf_off(r1) + 8); - swf_ldrin(_R1_REGNO, _FP_REGNO, swf_off(r1) + 4); - } - } - else { - movr(_R0_REGNO, r1); - movr(_R1_REGNO, r1 + 1); - } - movi(_R2_REGNO, data.i[0]); - movi(_R3_REGNO, data.i[1]); - swf_call_with_get_reg(i0, fallback); - if (jit_fpr_p(r0)) { - if (!jit_thumb_p() && jit_armv5e_p()) - STRDIN(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - else { - swf_strin(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - swf_strin(_R1_REGNO, _FP_REGNO, swf_off(r0) + 4); - } - } - else { - movr(r0, _R0_REGNO); - movr(r0 + 1, _R1_REGNO); - } - jit_unget_reg_args(); -} - -static void -_swf_rsbi_d(jit_state_t *_jit, int32_t r0, int32_t r1, jit_float64_t i0) -{ - union { - int32_t i[2]; - jit_float64_t d; - } data; - jit_get_reg_args(); - data.d = i0; - movi(_R0_REGNO, data.i[0]); - movi(_R1_REGNO, data.i[1]); - if (jit_fpr_p(r1)) { - if (!jit_thumb_p() && jit_armv5e_p()) - LDRDIN(_R2_REGNO, _FP_REGNO, swf_off(r1) + 8); - else { - swf_ldrin(_R2_REGNO, _FP_REGNO, swf_off(r1) + 8); - swf_ldrin(_R3_REGNO, _FP_REGNO, swf_off(r1) + 4); - } - } - else { - movr(_R2_REGNO, r1); - movr(_R3_REGNO, r1 + 1); - } - swf_call_with_get_reg(__aeabi_dsub, fallback); - if (jit_fpr_p(r0)) { - if (!jit_thumb_p() && jit_armv5e_p()) - STRDIN(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - else { - swf_strin(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - swf_strin(_R1_REGNO, _FP_REGNO, swf_off(r0) + 4); - } - } - else { - movr(r0, _R0_REGNO); - movr(r0 + 1, _R1_REGNO); - } - jit_unget_reg_args(); -} - -static void -_swf_iff(jit_state_t *_jit, int (*i0)(float, float), - int32_t r0, int32_t r1, int32_t r2) -{ - jit_get_reg_args(); - if (jit_fpr_p(r1)) - swf_ldrin(_R0_REGNO, _FP_REGNO, swf_off(r1) + 8); - else - movr(_R0_REGNO, r1); - if (jit_fpr_p(r2)) - swf_ldrin(_R1_REGNO, _FP_REGNO, swf_off(r2) + 8); - else - movr(_R1_REGNO, r2); - swf_call(i0, fallback, _R2_REGNO); - movr(r0, _R0_REGNO); - jit_unget_reg_args(); -} - -static void -_swf_idd(jit_state_t *_jit, int (*i0)(double, double), - int32_t r0, int32_t r1, int32_t r2) -{ - jit_get_reg_args(); - if (jit_fpr_p(r1)) { - if (!jit_thumb_p() && jit_armv5e_p()) - LDRDIN(_R0_REGNO, _FP_REGNO, swf_off(r1) + 8); - else { - swf_ldrin(_R0_REGNO, _FP_REGNO, swf_off(r1) + 8); - swf_ldrin(_R1_REGNO, _FP_REGNO, swf_off(r1) + 4); - } - } - else { - movr(_R0_REGNO, r1); - movr(_R1_REGNO, r1 + 1); - } - if (jit_fpr_p(r2)) { - if (!jit_thumb_p() && jit_armv5e_p()) - LDRDIN(_R2_REGNO, _FP_REGNO, swf_off(r2) + 8); - else { - swf_ldrin(_R2_REGNO, _FP_REGNO, swf_off(r2) + 8); - swf_ldrin(_R3_REGNO, _FP_REGNO, swf_off(r2) + 4); - } - } - else { - movr(_R2_REGNO, r2); - movr(_R3_REGNO, r2 + 1); - } - swf_call_with_get_reg(i0, fallback); - movr(r0, _R0_REGNO); - jit_unget_reg_args(); -} - -static void -_swf_iff_(jit_state_t *_jit, int (*i0)(float, float), - int32_t r0, int32_t r1, jit_float32_t i1) -{ - union { - int32_t i; - jit_float32_t f; - } data; - jit_get_reg_args(); - data.f = i1; - if (jit_fpr_p(r1)) - swf_ldrin(_R0_REGNO, _FP_REGNO, swf_off(r1) + 8); - else - movr(_R0_REGNO, r1); - movi(_R1_REGNO, data.i); - swf_call(i0, fallback, _R2_REGNO); - movr(r0, _R0_REGNO); - jit_unget_reg_args(); -} - -static void -_swf_idd_(jit_state_t *_jit, int (*i0)(double, double), - int32_t r0, int32_t r1, jit_float64_t i1) -{ - union { - int32_t i[2]; - jit_float64_t d; - } data; - jit_get_reg_args(); - data.d = i1; - if (jit_fpr_p(r1)) { - if (!jit_thumb_p() && jit_armv5e_p()) - LDRDIN(_R0_REGNO, _FP_REGNO, swf_off(r1) + 8); - else { - swf_ldrin(_R0_REGNO, _FP_REGNO, swf_off(r1) + 8); - swf_ldrin(_R1_REGNO, _FP_REGNO, swf_off(r1) + 4); - } - } - else { - movr(_R0_REGNO, r1); - movr(_R1_REGNO, r1 + 1); - } - movi(_R2_REGNO, data.i[0]); - movi(_R3_REGNO, data.i[1]); - swf_call_with_get_reg(i0, fallback); - movr(r0, _R0_REGNO); - jit_unget_reg_args(); -} - -static void -_swf_iunff(jit_state_t *_jit, int (*i0)(float, float), - int32_t r0, int32_t r1, int32_t r2) -{ - jit_word_t instr; - jit_get_reg_args(); - if (jit_fpr_p(r1)) - swf_ldrin(_R0_REGNO, _FP_REGNO, swf_off(r1) + 8); - else - movr(_R0_REGNO, r1); - if (jit_fpr_p(r2)) - swf_ldrin(_R1_REGNO, _FP_REGNO, swf_off(r2) + 8); - else - movr(_R1_REGNO, r2); - swf_call(__aeabi_fcmpun, fcmpun, _R2_REGNO); - if (jit_thumb_p()) { - T1_CMPI(_R0_REGNO, 0); - IT(ARM_CC_NE); - if (r0 < 8) - T1_MOVI(r0, 1); - else - T2_MOVI(r0, 1); - instr = _jit->pc.w; - T2_CC_B(ARM_CC_NE, 0); - } - else { - CMPI(_R0_REGNO, 0); - CC_MOVI(ARM_CC_NE, r0, 1); - instr = _jit->pc.w; - CC_B(ARM_CC_NE, 0); - } - if (jit_fpr_p(r1)) - swf_ldrin(_R0_REGNO, _FP_REGNO, swf_off(r1) + 8); - else - movr(_R0_REGNO, r1); - if (jit_fpr_p(r2)) - swf_ldrin(_R1_REGNO, _FP_REGNO, swf_off(r2) + 8); - else - movr(_R1_REGNO, r2); - swf_call(i0, fallback, _R2_REGNO); - movr(r0, _R0_REGNO); - patch_at(arm_patch_jump, instr, _jit->pc.w); - jit_unget_reg_args(); -} - -static void -_swf_iundd(jit_state_t *_jit, int (*i0)(double, double), - int32_t r0, int32_t r1, int32_t r2) -{ - jit_word_t instr; - jit_get_reg_args(); - if (jit_fpr_p(r1)) { - if (!jit_thumb_p() && jit_armv5e_p()) - LDRDIN(_R0_REGNO, _FP_REGNO, swf_off(r1) + 8); - else { - swf_ldrin(_R0_REGNO, _FP_REGNO, swf_off(r1) + 8); - swf_ldrin(_R1_REGNO, _FP_REGNO, swf_off(r1) + 4); - } - } - else { - movr(_R0_REGNO, r1); - movr(_R1_REGNO, r1 + 1); - } - if (jit_fpr_p(r2)) { - if (!jit_thumb_p() && jit_armv5e_p()) - LDRDIN(_R2_REGNO, _FP_REGNO, swf_off(r2) + 8); - else { - swf_ldrin(_R2_REGNO, _FP_REGNO, swf_off(r2) + 8); - swf_ldrin(_R3_REGNO, _FP_REGNO, swf_off(r2) + 4); - } - } - else { - movr(_R2_REGNO, r2); - movr(_R3_REGNO, r2 + 1); - } - swf_call_with_get_reg(__aeabi_dcmpun, dcmpun); - if (jit_thumb_p()) { - T1_CMPI(_R0_REGNO, 0); - IT(ARM_CC_NE); - if (r0 < 8) - T1_MOVI(r0, 1); - else - T2_MOVI(r0, 1); - instr = _jit->pc.w; - T2_CC_B(ARM_CC_NE, 0); - } - else { - CMPI(_R0_REGNO, 0); - CC_MOVI(ARM_CC_NE, r0, 1); - instr = _jit->pc.w; - CC_B(ARM_CC_NE, 0); - } - if (jit_fpr_p(r1)) { - if (!jit_thumb_p() && jit_armv5e_p()) - LDRDIN(_R0_REGNO, _FP_REGNO, swf_off(r1) + 8); - else { - swf_ldrin(_R0_REGNO, _FP_REGNO, swf_off(r1) + 8); - swf_ldrin(_R1_REGNO, _FP_REGNO, swf_off(r1) + 4); - } - } - else { - movr(_R0_REGNO, r1); - movr(_R1_REGNO, r1 + 1); - } - if (jit_fpr_p(r2)) { - if (!jit_thumb_p() && jit_armv5e_p()) - LDRDIN(_R2_REGNO, _FP_REGNO, swf_off(r2) + 8); - else { - swf_ldrin(_R2_REGNO, _FP_REGNO, swf_off(r2) + 8); - swf_ldrin(_R3_REGNO, _FP_REGNO, swf_off(r2) + 4); - } - } - else { - movr(_R2_REGNO, r2); - movr(_R3_REGNO, r2 + 1); - } - swf_call_with_get_reg(i0, fallback); - movr(r0, _R0_REGNO); - patch_at(arm_patch_jump, instr, _jit->pc.w); - jit_unget_reg_args(); -} - -static void -_swf_iunff_(jit_state_t *_jit, int (*i0)(float, float), - int32_t r0, int32_t r1, jit_float32_t i1) -{ - jit_word_t instr; - union { - int32_t i; - jit_float32_t f; - } data; - jit_get_reg_args(); - data.f = i1; - if (jit_fpr_p(r1)) - swf_ldrin(_R0_REGNO, _FP_REGNO, swf_off(r1) + 8); - else - movr(_R0_REGNO, r1); - movi(_R1_REGNO, data.i); - swf_call(__aeabi_fcmpun, fcmpun, _R2_REGNO); - if (jit_thumb_p()) { - T1_CMPI(_R0_REGNO, 0); - IT(ARM_CC_NE); - if (r0 < 8) - T1_MOVI(r0, 1); - else - T2_MOVI(r0, 1); - instr = _jit->pc.w; - T2_CC_B(ARM_CC_NE, 0); - } - else { - CMPI(_R0_REGNO, 0); - CC_MOVI(ARM_CC_NE, r0, 1); - instr = _jit->pc.w; - CC_B(ARM_CC_NE, 0); - } - if (jit_fpr_p(r1)) - swf_ldrin(_R0_REGNO, _FP_REGNO, swf_off(r1) + 8); - else - movr(_R0_REGNO, r1); - movi(_R1_REGNO, data.i); - swf_call(i0, fallback, _R2_REGNO); - movr(r0, _R0_REGNO); - patch_at(arm_patch_jump, instr, _jit->pc.w); - jit_unget_reg_args(); -} - -static void -_swf_iundd_(jit_state_t *_jit, int (*i0)(double, double), - int32_t r0, int32_t r1, jit_float64_t i1) -{ - jit_word_t instr; - union { - int32_t i[2]; - jit_float64_t d; - } data; - jit_get_reg_args(); - data.d = i1; - if (jit_fpr_p(r1)) { - if (!jit_thumb_p() && jit_armv5e_p()) - LDRDIN(_R0_REGNO, _FP_REGNO, swf_off(r1) + 8); - else { - swf_ldrin(_R0_REGNO, _FP_REGNO, swf_off(r1) + 8); - swf_ldrin(_R1_REGNO, _FP_REGNO, swf_off(r1) + 4); - } - } - else { - movr(_R0_REGNO, r1); - movr(_R1_REGNO, r1 + 1); - } - movi(_R2_REGNO, data.i[0]); - movi(_R3_REGNO, data.i[1]); - swf_call_with_get_reg(__aeabi_dcmpun, dcmpun); - if (jit_thumb_p()) { - T1_CMPI(_R0_REGNO, 0); - IT(ARM_CC_NE); - if (r0 < 8) - T1_MOVI(r0, 1); - else - T2_MOVI(r0, 1); - instr = _jit->pc.w; - T2_CC_B(ARM_CC_NE, 0); - } - else { - CMPI(_R0_REGNO, 0); - CC_MOVI(ARM_CC_NE, r0, 1); - instr = _jit->pc.w; - CC_B(ARM_CC_NE, 0); - } - if (jit_fpr_p(r1)) { - if (!jit_thumb_p() && jit_armv5e_p()) - LDRDIN(_R0_REGNO, _FP_REGNO, swf_off(r1) + 8); - else { - swf_ldrin(_R0_REGNO, _FP_REGNO, swf_off(r1) + 8); - swf_ldrin(_R1_REGNO, _FP_REGNO, swf_off(r1) + 4); - } - } - else { - movr(_R0_REGNO, r1); - movr(_R1_REGNO, r1 + 1); - } - movi(_R2_REGNO, data.i[0]); - movi(_R3_REGNO, data.i[1]); - swf_call_with_get_reg(i0, fallback); - movr(r0, _R0_REGNO); - patch_at(arm_patch_jump, instr, _jit->pc.w); - jit_unget_reg_args(); -} - -static jit_word_t -_swf_bff(jit_state_t *_jit, int (*i0)(float, float), int cc, - jit_word_t i1, int32_t r0, int32_t r1) -{ - jit_word_t w, d; - jit_get_reg_args(); - if (jit_fpr_p(r0)) - swf_ldrin(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - else - movr(_R0_REGNO, r0); - if (jit_fpr_p(r1)) - swf_ldrin(_R1_REGNO, _FP_REGNO, swf_off(r1) + 8); - else - movr(_R1_REGNO, r1); - swf_call(i0, fallback, _R2_REGNO); - if (jit_thumb_p()) { - T1_CMPI(_R0_REGNO, 0); - w = _jit->pc.w; - d = ((i1 - w) >> 1) - 2; - assert(_s20P(d)); - T2_CC_B(cc, encode_thumb_cc_jump(d)); - } - else { - CMPI(_R0_REGNO, 0); - w = _jit->pc.w; - d = ((i1 - w) >> 2) - 2; - assert(_s24P(d)); - CC_B(cc, d & 0x00ffffff); - } - jit_unget_reg_args(); - return (w); -} - -static jit_word_t -_swf_bdd(jit_state_t *_jit, int (*i0)(double, double), int cc, - jit_word_t i1, int32_t r0, int32_t r1) -{ - jit_word_t w, d; - jit_get_reg_args(); - if (jit_fpr_p(r0)) { - if (!jit_thumb_p() && jit_armv5e_p()) - LDRDIN(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - else { - swf_ldrin(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - swf_ldrin(_R1_REGNO, _FP_REGNO, swf_off(r0) + 4); - } - } - else { - movr(_R0_REGNO, r0); - movr(_R1_REGNO, r0 + 1); - } - if (jit_fpr_p(r1)) { - if (!jit_thumb_p() && jit_armv5e_p()) - LDRDIN(_R2_REGNO, _FP_REGNO, swf_off(r1) + 8); - else { - swf_ldrin(_R2_REGNO, _FP_REGNO, swf_off(r1) + 8); - swf_ldrin(_R3_REGNO, _FP_REGNO, swf_off(r1) + 4); - } - } - else { - movr(_R2_REGNO, r1); - movr(_R3_REGNO, r1 + 1); - } - swf_call_with_get_reg(i0, fallback); - if (jit_thumb_p()) { - T1_CMPI(_R0_REGNO, 0); - w = _jit->pc.w; - d = ((i1 - w) >> 1) - 2; - assert(_s20P(d)); - T2_CC_B(cc, encode_thumb_cc_jump(d)); - } - else { - CMPI(_R0_REGNO, 0); - w = _jit->pc.w; - d = ((i1 - w) >> 2) - 2; - assert(_s24P(d)); - CC_B(cc, d & 0x00ffffff); - } - jit_unget_reg_args(); - return (w); -} - -static jit_word_t -_swf_bff_(jit_state_t *_jit, int (*i0)(float, float), int cc, - jit_word_t i1, int32_t r0, jit_float32_t i2) -{ - union { - int32_t i; - jit_float32_t f; - } data; - jit_word_t w, d; - jit_get_reg_args(); - data.f = i2; - if (jit_fpr_p(r0)) - swf_ldrin(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - else - movr(_R0_REGNO, r0); - movi(_R1_REGNO, data.i); - swf_call(i0, fallback, _R2_REGNO); - if (jit_thumb_p()) { - T1_CMPI(_R0_REGNO, 0); - w = _jit->pc.w; - d = ((i1 - w) >> 1) - 2; - assert(_s20P(d)); - T2_CC_B(cc, encode_thumb_cc_jump(d)); - } - else { - CMPI(_R0_REGNO, 0); - w = _jit->pc.w; - d = ((i1 - w) >> 2) - 2; - assert(_s24P(d)); - CC_B(cc, d & 0x00ffffff); - } - jit_unget_reg_args(); - return (w); -} - -static jit_word_t -_swf_bdd_(jit_state_t *_jit, int (*i0)(double, double), int cc, - jit_word_t i1, int32_t r0, jit_float64_t i2) -{ - jit_word_t w, d; - union { - int32_t i[2]; - jit_float64_t d; - } data; - jit_get_reg_args(); - data.d = i2; - if (jit_fpr_p(r0)) { - if (!jit_thumb_p() && jit_armv5e_p()) - LDRDIN(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - else { - swf_ldrin(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - swf_ldrin(_R1_REGNO, _FP_REGNO, swf_off(r0) + 4); - } - } - else { - movr(_R0_REGNO, r0); - movr(_R1_REGNO, r0 + 1); - } - movi(_R2_REGNO, data.i[0]); - movi(_R3_REGNO, data.i[1]); - swf_call_with_get_reg(i0, fallback); - if (jit_thumb_p()) { - T1_CMPI(_R0_REGNO, 0); - w = _jit->pc.w; - d = ((i1 - w) >> 1) - 2; - assert(_s20P(d)); - T2_CC_B(cc, encode_thumb_cc_jump(d)); - } - else { - CMPI(_R0_REGNO, 0); - w = _jit->pc.w; - d = ((i1 - w) >> 2) - 2; - assert(_s24P(d)); - CC_B(cc, d & 0x00ffffff); - } - jit_unget_reg_args(); - return (w); -} - -static jit_word_t -_swf_bunff(jit_state_t *_jit, int eq, - jit_word_t i0, int32_t r0, int32_t r1) -{ - jit_word_t w, d, j0, j1; - jit_get_reg_args(); - if (jit_fpr_p(r0)) - swf_ldrin(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - else - movr(_R0_REGNO, r0); - if (jit_fpr_p(r1)) - swf_ldrin(_R1_REGNO, _FP_REGNO, swf_off(r1) + 8); - else - movr(_R1_REGNO, r1); - swf_call(__aeabi_fcmpun, fcmpun, _R2_REGNO); - /* if unordered */ - if (jit_thumb_p()) { - T1_CMPI(_R0_REGNO, 0); - j0 = _jit->pc.w; - T2_CC_B(ARM_CC_NE, 0); - } - else { - CMPI(_R0_REGNO, 0); - j0 = _jit->pc.w; - CC_B(ARM_CC_NE, 0); - } - if (jit_fpr_p(r0)) - swf_ldrin(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - else - movr(_R0_REGNO, r0); - if (jit_fpr_p(r1)) - swf_ldrin(_R1_REGNO, _FP_REGNO, swf_off(r1) + 8); - else - movr(_R1_REGNO, r1); - swf_call(__aeabi_fcmpeq, fcmpeq, _R2_REGNO); - if (jit_thumb_p()) { - T1_CMPI(_R0_REGNO, 0); - j1 = _jit->pc.w; - if (eq) { - T2_CC_B(ARM_CC_EQ, 0); - patch_at(arm_patch_jump, j0, _jit->pc.w); - } - else - T2_CC_B(ARM_CC_NE, 0); - w = _jit->pc.w; - d = ((i0 - w) >> 1) - 2; - assert(_s24P(d)); - T2_B(encode_thumb_jump(d)); - } - else { - CMPI(_R0_REGNO, 0); - j1 = _jit->pc.w; - if (eq) { - CC_B(ARM_CC_EQ, 0); - patch_at(arm_patch_jump, j0, _jit->pc.w); - } - else - CC_B(ARM_CC_NE, 0); - w = _jit->pc.w; - d = ((i0 - w) >> 2) - 2; - assert(_s24P(d)); - B(d & 0x00ffffff); - } - if (!eq) - patch_at(arm_patch_jump, j0, _jit->pc.w); - patch_at(arm_patch_jump, j1, _jit->pc.w); - jit_unget_reg_args(); - return (w); -} - -static jit_word_t -_swf_bundd(jit_state_t *_jit, int eq, - jit_word_t i0, int32_t r0, int32_t r1) -{ - jit_word_t w, d, j0, j1; - jit_get_reg_args(); - if (jit_fpr_p(r0)) { - if (!jit_thumb_p() && jit_armv5e_p()) - LDRDIN(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - else { - swf_ldrin(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - swf_ldrin(_R1_REGNO, _FP_REGNO, swf_off(r0) + 4); - } - } - else { - movr(_R0_REGNO, r0); - movr(_R1_REGNO, r0 + 1); - } - if (jit_fpr_p(r1)) { - if (!jit_thumb_p() && jit_armv5e_p()) - LDRDIN(_R2_REGNO, _FP_REGNO, swf_off(r1) + 8); - else { - swf_ldrin(_R2_REGNO, _FP_REGNO, swf_off(r1) + 8); - swf_ldrin(_R3_REGNO, _FP_REGNO, swf_off(r1) + 4); - } - } - else { - movr(_R2_REGNO, r0); - movr(_R3_REGNO, r0 + 1); - } - swf_call_with_get_reg(__aeabi_dcmpun, dcmpun); - /* if unordered */ - if (jit_thumb_p()) { - T1_CMPI(_R0_REGNO, 0); - j0 = _jit->pc.w; - T2_CC_B(ARM_CC_NE, 0); - } - else { - CMPI(_R0_REGNO, 0); - j0 = _jit->pc.w; - CC_B(ARM_CC_NE, 0); - } - if (jit_fpr_p(r0)) { - if (!jit_thumb_p() && jit_armv5e_p()) - LDRDIN(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - else { - swf_ldrin(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - swf_ldrin(_R1_REGNO, _FP_REGNO, swf_off(r0) + 4); - } - } - else { - movr(_R0_REGNO, r0); - movr(_R1_REGNO, r0 + 1); - } - if (jit_fpr_p(r1)) { - if (!jit_thumb_p() && jit_armv5e_p()) - LDRDIN(_R2_REGNO, _FP_REGNO, swf_off(r1) + 8); - else { - swf_ldrin(_R2_REGNO, _FP_REGNO, swf_off(r1) + 8); - swf_ldrin(_R3_REGNO, _FP_REGNO, swf_off(r1) + 4); - } - } - else { - movr(_R2_REGNO, r0); - movr(_R3_REGNO, r0 + 1); - } - swf_call_with_get_reg(__aeabi_dcmpeq, dcmpeq); - if (jit_thumb_p()) { - T1_CMPI(_R0_REGNO, 0); - j1 = _jit->pc.w; - if (eq) { - T2_CC_B(ARM_CC_EQ, 0); - patch_at(arm_patch_jump, j0, _jit->pc.w); - } - else - T2_CC_B(ARM_CC_NE, 0); - w = _jit->pc.w; - d = ((i0 - w) >> 1) - 2; - assert(_s24P(d)); - T2_B(encode_thumb_jump(d)); - } - else { - CMPI(_R0_REGNO, 0); - j1 = _jit->pc.w; - if (eq) { - CC_B(ARM_CC_EQ, 0); - patch_at(arm_patch_jump, j0, _jit->pc.w); - } - else - CC_B(ARM_CC_NE, 0); - w = _jit->pc.w; - d = ((i0 - w) >> 2) - 2; - assert(_s24P(d)); - B(d & 0x00ffffff); - } - if (!eq) - patch_at(arm_patch_jump, j0, _jit->pc.w); - patch_at(arm_patch_jump, j1, _jit->pc.w); - jit_unget_reg_args(); - return (w); -} - -static jit_word_t -_swf_bunff_(jit_state_t *_jit, int eq, - jit_word_t i0, int32_t r0, jit_float32_t i1) -{ - union { - int32_t i; - jit_float32_t f; - } data; - jit_word_t w, d, j0, j1; - data.f = i1; - jit_get_reg_args(); - if (jit_fpr_p(r0)) - swf_ldrin(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - else - movr(_R0_REGNO, r0); - movi(_R1_REGNO, data.i); - swf_call(__aeabi_fcmpun, fcmpun, _R2_REGNO); - /* if unordered */ - if (jit_thumb_p()) { - T1_CMPI(_R0_REGNO, 0); - j0 = _jit->pc.w; - T2_CC_B(ARM_CC_NE, 0); - } - else { - CMPI(_R0_REGNO, 0); - j0 = _jit->pc.w; - CC_B(ARM_CC_NE, 0); - } - if (jit_fpr_p(r0)) - swf_ldrin(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - else - movr(_R0_REGNO, r0); - movi(_R1_REGNO, data.i); - swf_call(__aeabi_fcmpeq, fcmpeq, _R2_REGNO); - if (jit_thumb_p()) { - T1_CMPI(_R0_REGNO, 0); - j1 = _jit->pc.w; - if (eq) { - T2_CC_B(ARM_CC_EQ, 0); - patch_at(arm_patch_jump, j0, _jit->pc.w); - } - else - T2_CC_B(ARM_CC_NE, 0); - w = _jit->pc.w; - d = ((i0 - w) >> 1) - 2; - assert(_s24P(d)); - T2_B(encode_thumb_jump(d)); - } - else { - CMPI(_R0_REGNO, 0); - j1 = _jit->pc.w; - if (eq) { - CC_B(ARM_CC_EQ, 0); - patch_at(arm_patch_jump, j0, _jit->pc.w); - } - else - CC_B(ARM_CC_NE, 0); - w = _jit->pc.w; - d = ((i0 - w) >> 2) - 2; - assert(_s24P(d)); - B(d & 0x00ffffff); - } - if (!eq) - patch_at(arm_patch_jump, j0, _jit->pc.w); - patch_at(arm_patch_jump, j1, _jit->pc.w); - jit_unget_reg_args(); - return (w); -} - -static jit_word_t -_swf_bundd_(jit_state_t *_jit, int eq, - jit_word_t i0, int32_t r0, jit_float64_t i1) -{ - jit_word_t w, d, j0, j1; - union { - int32_t i[2]; - jit_float64_t d; - } data; - jit_get_reg_args(); - data.d = i1; - if (jit_fpr_p(r0)) { - if (!jit_thumb_p() && jit_armv5e_p()) - LDRDIN(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - else { - swf_ldrin(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - swf_ldrin(_R1_REGNO, _FP_REGNO, swf_off(r0) + 4); - } - } - else { - movr(_R0_REGNO, r0); - movr(_R1_REGNO, r0 + 1); - } - movi(_R2_REGNO, data.i[0]); - movi(_R3_REGNO, data.i[1]); - swf_call_with_get_reg(__aeabi_dcmpun, fcmpun); - /* if unordered */ - if (jit_thumb_p()) { - T1_CMPI(_R0_REGNO, 0); - j0 = _jit->pc.w; - T2_CC_B(ARM_CC_NE, 0); - } - else { - CMPI(_R0_REGNO, 0); - j0 = _jit->pc.w; - CC_B(ARM_CC_NE, 0); - } - if (jit_fpr_p(r0)) { - if (!jit_thumb_p() && jit_armv5e_p()) - LDRDIN(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - else { - swf_ldrin(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - swf_ldrin(_R1_REGNO, _FP_REGNO, swf_off(r0) + 4); - } - } - else { - movr(_R0_REGNO, r0); - movr(_R1_REGNO, r0 + 1); - } - movi(_R2_REGNO, data.i[0]); - movi(_R3_REGNO, data.i[1]); - swf_call_with_get_reg(__aeabi_dcmpeq, fcmpeq); - if (jit_thumb_p()) { - T1_CMPI(_R0_REGNO, 0); - j1 = _jit->pc.w; - if (eq) { - T2_CC_B(ARM_CC_EQ, 0); - patch_at(arm_patch_jump, j0, _jit->pc.w); - } - else - T2_CC_B(ARM_CC_NE, 0); - w = _jit->pc.w; - d = ((i0 - w) >> 1) - 2; - assert(_s24P(d)); - T2_B(encode_thumb_jump(d)); - } - else { - CMPI(_R0_REGNO, 0); - j1 = _jit->pc.w; - if (eq) { - CC_B(ARM_CC_EQ, 0); - patch_at(arm_patch_jump, j0, _jit->pc.w); - } - else - CC_B(ARM_CC_NE, 0); - w = _jit->pc.w; - d = ((i0 - w) >> 2) - 2; - assert(_s24P(d)); - B(d & 0x00ffffff); - } - if (!eq) - patch_at(arm_patch_jump, j0, _jit->pc.w); - patch_at(arm_patch_jump, j1, _jit->pc.w); - jit_unget_reg_args(); - return (w); -} - -static void -_swf_extr_f(jit_state_t *_jit, int32_t r0, int32_t r1) -{ - jit_get_reg_args(); - movr(_R0_REGNO, r1); - swf_call(__aeabi_i2f, i2f, _R1_REGNO); - if (jit_fpr_p(r0)) - swf_strin(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - else - movr(r0, _R0_REGNO); - jit_unget_reg_args(); -} - -static void -_swf_extr_d(jit_state_t *_jit, int32_t r0, int32_t r1) -{ - jit_get_reg_args(); - movr(_R0_REGNO, r1); - swf_call(__aeabi_i2d, i2d, _R2_REGNO); - if (jit_fpr_p(r0)) { - if (!jit_thumb_p() && jit_armv5e_p()) - STRDIN(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - else { - swf_strin(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - swf_strin(_R1_REGNO, _FP_REGNO, swf_off(r0) + 4); - } - } - else { - movr(r0, _R0_REGNO); - movr(r0 + 1, _R1_REGNO); - } - jit_unget_reg_args(); -} - -static void -_swf_extr_d_f(jit_state_t *_jit, int32_t r0, int32_t r1) -{ - jit_get_reg_args(); - if (jit_fpr_p(r1)) { - if (!jit_thumb_p() && jit_armv5e_p()) - LDRDIN(_R0_REGNO, _FP_REGNO, swf_off(r1) + 8); - else { - swf_ldrin(_R0_REGNO, _FP_REGNO, swf_off(r1) + 8); - swf_ldrin(_R1_REGNO, _FP_REGNO, swf_off(r1) + 4); - } - } - else { - movr(_R0_REGNO, r1); - movr(_R1_REGNO, r1 + 1); - } - swf_call(__aeabi_d2f, d2f, _R2_REGNO); - if (jit_fpr_p(r0)) - swf_strin(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - else - movr(r0, _R0_REGNO); - jit_unget_reg_args(); -} - -static void -_swf_extr_f_d(jit_state_t *_jit, int32_t r0, int32_t r1) -{ - jit_get_reg_args(); - if (jit_fpr_p(r1)) - swf_ldrin(_R0_REGNO, _FP_REGNO, swf_off(r1) + 8); - else - movr(_R0_REGNO, r1); - swf_call(__aeabi_f2d, f2d, _R1_REGNO); - if (jit_fpr_p(r0)) { - if (!jit_thumb_p() && jit_armv5e_p()) - STRDIN(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - else { - swf_strin(_R0_REGNO, _FP_REGNO, swf_off(r0) + 8); - swf_strin(_R1_REGNO, _FP_REGNO, swf_off(r0) + 4); - } - } - else { - movr(r0, _R0_REGNO); - movr(r0 + 1, _R1_REGNO); - } - jit_unget_reg_args(); -} - -static void -_swf_truncr_f_i(jit_state_t *_jit, int32_t r0, int32_t r1) -{ -#if !NAN_TO_INT_IS_ZERO - jit_word_t is_nan; - jit_word_t fast_not_nan; - jit_word_t slow_not_nan; -#endif - jit_get_reg_args(); - if (jit_fpr_p(r1)) - swf_ldrin(_R0_REGNO, _FP_REGNO, swf_off(r1) + 8); - else - movr(_R0_REGNO, r1); -#if !NAN_TO_INT_IS_ZERO - /* >> based on fragment of __aeabi_fcmpun */ - lshi(_R2_REGNO, _R0_REGNO, 1); - if (jit_thumb_p()) - torrrs(THUMB2_MVN|ARM_S, _R0_REGNO, _R3_REGNO, _R2_REGNO, - encode_thumb_shift(24, ARM_ASR)); - else - corrrs(ARM_CC_AL, ARM_MVN|ARM_S|ARM_ASR, - _R0_REGNO, _R3_REGNO, _R2_REGNO, 24); - fast_not_nan = _jit->pc.w; - if (jit_thumb_p()) { - T2_CC_B(ARM_CC_NE, 0); - tshift(THUMB2_LSLI|ARM_S, _R0_REGNO, _R3_REGNO, 9); - } - else { - CC_B(ARM_CC_NE, 0); - cshift(ARM_CC_AL, ARM_S|ARM_LSL, _R0_REGNO, _R3_REGNO, _R0_REGNO, 9); - } - slow_not_nan = _jit->pc.w; - if (jit_thumb_p()) - T2_CC_B(ARM_CC_EQ, 0); - else - CC_B(ARM_CC_EQ, 0); - movi(r0, 0x80000000); - is_nan = _jit->pc.w; - if (jit_thumb_p()) - T2_B(0); - else - B(0); - patch_at(arm_patch_jump, fast_not_nan, _jit->pc.w); - patch_at(arm_patch_jump, slow_not_nan, _jit->pc.w); - /* << based on fragment of __aeabi_fcmpun */ -#endif - swf_call(__aeabi_f2iz, f2iz, _R2_REGNO); - movr(r0, _R0_REGNO); -#if !NAN_TO_INT_IS_ZERO - patch_at(arm_patch_jump, is_nan, _jit->pc.w); -#endif - jit_unget_reg_args(); -} - -static void -_swf_truncr_d_i(jit_state_t *_jit, int32_t r0, int32_t r1) -{ -#if !NAN_TO_INT_IS_ZERO - jit_word_t is_nan; - jit_word_t fast_not_nan; - jit_word_t slow_not_nan; -#endif - jit_get_reg_args(); - if (jit_fpr_p(r1)) { - if (!jit_thumb_p() && jit_armv5e_p()) - LDRDIN(_R0_REGNO, _FP_REGNO, swf_off(r1) + 8); - else { - swf_ldrin(_R0_REGNO, _FP_REGNO, swf_off(r1) + 8); - swf_ldrin(_R1_REGNO, _FP_REGNO, swf_off(r1) + 4); - } - } - else { - movr(_R0_REGNO, r1); - movr(_R1_REGNO, r1 + 1); - } -#if !NAN_TO_INT_IS_ZERO - /* >> based on fragment of __aeabi_dcmpun */ - lshi(_R3_REGNO, _R1_REGNO, 1); - if (jit_thumb_p()) - torrrs(THUMB2_MVN|ARM_S, _R0_REGNO, _R3_REGNO, _R3_REGNO, - encode_thumb_shift(21, ARM_ASR)); - else - corrrs(ARM_CC_AL, ARM_MVN|ARM_S|ARM_ASR, - _R0_REGNO, _R3_REGNO, _R3_REGNO, 21); - fast_not_nan = _jit->pc.w; - if (jit_thumb_p()) { - T2_CC_B(ARM_CC_NE, 0); - torrrs(THUMB2_ORR|ARM_S, _R0_REGNO, _R3_REGNO, _R1_REGNO, - encode_thumb_shift(12, ARM_LSL)); - } - else { - CC_B(ARM_CC_NE, 0); - corrrs(ARM_CC_AL, ARM_ORR|ARM_S|ARM_LSL, - _R0_REGNO, _R3_REGNO, _R1_REGNO, 12); - } - slow_not_nan = _jit->pc.w; - if (jit_thumb_p()) - T2_CC_B(ARM_CC_EQ, 0); - else - CC_B(ARM_CC_EQ, 0); - movi(r0, 0x80000000); - is_nan = _jit->pc.w; - if (jit_thumb_p()) - T2_B(0); - else - B(0); - patch_at(arm_patch_jump, fast_not_nan, _jit->pc.w); - patch_at(arm_patch_jump, slow_not_nan, _jit->pc.w); - /* << based on fragment of __aeabi_dcmpun */ -#endif - swf_call(__aeabi_d2iz, d2iz, _R3_REGNO); - movr(r0, _R0_REGNO); -#if !NAN_TO_INT_IS_ZERO - patch_at(arm_patch_jump, is_nan, _jit->pc.w); -#endif - jit_unget_reg_args(); -} - -static void -_swf_movr_f(jit_state_t *_jit, int32_t r0, int32_t r1) -{ - int32_t reg; - if (r0 != r1) { - if (jit_fpr_p(r1)) { - reg = jit_get_reg(jit_class_gpr); - swf_ldrin(rn(reg), _FP_REGNO, swf_off(r1) + 8); - if (jit_fpr_p(r0)) - swf_strin(rn(reg), _FP_REGNO, swf_off(r0) + 8); - else - movr(r0, rn(reg)); - jit_unget_reg(reg); - } - else if (jit_fpr_p(r0)) - swf_strin(r1, _FP_REGNO, swf_off(r0) + 8); - else - movr(r0, r1); - } -} - -static void -_swf_movr_d(jit_state_t *_jit, int32_t r0, int32_t r1) -{ - int32_t reg; - if (r0 != r1) { - if (jit_fpr_p(r1)) { - if (!jit_thumb_p() && jit_armv5e_p() && - (reg = jit_get_reg_pair()) != JIT_NOREG) { - LDRDIN(rn(reg), _FP_REGNO, swf_off(r1) + 8); - if (jit_fpr_p(r0)) - STRDIN(rn(reg), _FP_REGNO, swf_off(r0) + 8); - else { - movr(r0, rn(reg)); - movr(r0 + 1, rn(reg) + 1); - } - jit_unget_reg_pair(reg); - } - else { - reg = jit_get_reg(jit_class_gpr); - swf_ldrin(rn(reg), _FP_REGNO, swf_off(r1) + 8); - if (jit_fpr_p(r0)) - swf_strin(rn(reg), _FP_REGNO, swf_off(r0) + 8); - else - movr(r0, rn(reg)); - swf_ldrin(rn(reg), _FP_REGNO, swf_off(r1) + 4); - if (jit_fpr_p(r0)) - swf_strin(rn(reg), _FP_REGNO, swf_off(r0) + 4); - else - movr(r0 + 1, rn(reg)); - jit_unget_reg(reg); - } - } - else if (jit_fpr_p(r0)) { - if (!jit_thumb_p() && jit_armv5e_p() && !(r1 & 1)) - STRDIN(r1, _FP_REGNO, swf_off(r0) + 8); - else { - swf_strin(r1, _FP_REGNO, swf_off(r0) + 8); - swf_strin(r1 + 1, _FP_REGNO, swf_off(r0) + 4); - } - } - else { - movr(r0, r1); - movr(r0 + 1, r1 + 1); - } - } -} - -static void -_swf_movi_f(jit_state_t *_jit, int32_t r0, jit_float32_t i0) -{ - union { - int32_t i; - jit_float32_t f; - } data; - int32_t reg; - data.f = i0; - if (jit_fpr_p(r0)) { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), data.i); - swf_strin(rn(reg), _FP_REGNO, swf_off(r0) + 8); - jit_unget_reg(reg); - } - else - movi(r0, data.i); -} - -static void -_swf_movi_d(jit_state_t *_jit, int32_t r0, jit_float64_t i0) -{ - int32_t reg; - union { - int32_t i[2]; - jit_float64_t d; - } data; - data.d = i0; - if (jit_fpr_p(r0)) { - if (!jit_thumb_p() && jit_armv5e_p() && - (reg = jit_get_reg_pair()) != JIT_NOREG) { - movi(rn(reg), data.i[0]); - movi(rn(reg) + 1, data.i[1]); - STRDIN(rn(reg), _FP_REGNO, swf_off(r0) + 8); - jit_unget_reg_pair(reg); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), data.i[0]); - swf_strin(rn(reg), _FP_REGNO, swf_off(r0) + 8); - movi(rn(reg), data.i[1]); - swf_strin(rn(reg), _FP_REGNO, swf_off(r0) + 4); - jit_unget_reg(reg); - } - } - else { - movi(r0, data.i[0]); - movi(r0 + 1, data.i[1]); - } -} - -static void -_swf_absr_f(jit_state_t *_jit, int32_t r0, int32_t r1) -{ - int32_t reg; - if (jit_fpr_p(r1)) { - reg = jit_get_reg(jit_class_gpr); - swf_ldrin(rn(reg), _FP_REGNO, swf_off(r1) + 8); - swf_bici(rn(reg), rn(reg), 0x80000000); - if (jit_fpr_p(r0)) - swf_strin(rn(reg), _FP_REGNO, swf_off(r0) + 8); - else - movr(r0, rn(reg)); - jit_unget_reg(reg); - } - else if (jit_fpr_p(r0)) { - reg = jit_get_reg(jit_class_gpr); - movr(rn(reg), r1); - swf_bici(rn(reg), rn(reg), 0x80000000); - swf_strin(rn(reg), _FP_REGNO, swf_off(r0) + 8); - jit_unget_reg(reg); - } - else - swf_bici(r0, r1, 0x80000000); -} - -static void -_swf_absr_d(jit_state_t *_jit, int32_t r0, int32_t r1) -{ - int32_t reg; - if (jit_fpr_p(r1)) { - if (jit_fpr_p(r0) && !jit_thumb_p() && jit_armv5e_p() && - r0 != r1 && (reg = jit_get_reg_pair()) != JIT_NOREG) { - LDRDIN(rn(reg), _FP_REGNO, swf_off(r1) + 8); - swf_bici(rn(reg) + 1, rn(reg) + 1, 0x80000000); - STRDIN(rn(reg), _FP_REGNO, swf_off(r0) + 8); - jit_unget_reg_pair(reg); - } - else { - reg = jit_get_reg(jit_class_gpr); - swf_ldrin(rn(reg), _FP_REGNO, swf_off(r1) + 4); - swf_bici(rn(reg), rn(reg), 0x80000000); - if (jit_fpr_p(r0)) { - swf_strin(rn(reg), _FP_REGNO, swf_off(r0) + 4); - if (r0 != r1) { - swf_ldrin(rn(reg), _FP_REGNO, swf_off(r1) + 8); - swf_strin(rn(reg), _FP_REGNO, swf_off(r0) + 8); - } - } - else { - movr(r0, rn(reg)); - swf_ldrin(rn(reg), _FP_REGNO, swf_off(r1) + 8); - movr(r0 + 1, rn(reg)); - } - jit_unget_reg(reg); - } - } - else if (jit_fpr_p(r0)) { - reg = jit_get_reg(jit_class_gpr); - movr(rn(reg), r1); - swf_bici(rn(reg), rn(reg), 0x80000000); - swf_strin(rn(reg), _FP_REGNO, swf_off(r0) + 4); - movr(rn(reg), r1 + 1); - swf_strin(rn(reg), _FP_REGNO, swf_off(r0) + 8); - jit_unget_reg(reg); - } - else { - swf_bici(r0, r1, 0x80000000); - if (r0 != r1) - movr(r0 + 1, r1 + 1); - } -} - -static void -_swf_negr_f(jit_state_t *_jit, int32_t r0, int32_t r1) -{ - int32_t reg; - if (jit_fpr_p(r1)) { - reg = jit_get_reg(jit_class_gpr); - swf_ldrin(rn(reg), _FP_REGNO, swf_off(r1) + 8); - xori(rn(reg), rn(reg), 0x80000000); - if (jit_fpr_p(r0)) - swf_strin(rn(reg), _FP_REGNO, swf_off(r0) + 8); - else - movr(r0, rn(reg)); - jit_unget_reg(reg); - } - else if (jit_fpr_p(r0)) { - reg = jit_get_reg(jit_class_gpr); - movr(rn(reg), r1); - xori(rn(reg), rn(reg), 0x80000000); - swf_strin(rn(reg), _FP_REGNO, swf_off(r0) + 8); - jit_unget_reg(reg); - } - else - xori(r0, r1, 0x80000000); -} - -static void -_swf_negr_d(jit_state_t *_jit, int32_t r0, int32_t r1) -{ - int32_t reg; - if (jit_fpr_p(r1)) { - if (jit_fpr_p(r0) && !jit_thumb_p() && jit_armv5e_p() && - r0 != r1 && (reg = jit_get_reg_pair()) != JIT_NOREG) { - LDRDIN(rn(reg), _FP_REGNO, swf_off(r1) + 8); - EORI(rn(reg) + 1, rn(reg) + 1, encode_arm_immediate(0x80000000)); - STRDIN(rn(reg), _FP_REGNO, swf_off(r0) + 8); - jit_unget_reg_pair(reg); - } - else { - reg = jit_get_reg(jit_class_gpr); - swf_ldrin(rn(reg), _FP_REGNO, swf_off(r1) + 4); - xori(rn(reg), rn(reg), 0x80000000); - if (jit_fpr_p(r0)) { - swf_strin(rn(reg), _FP_REGNO, swf_off(r0) + 4); - if (r0 != r1) { - swf_ldrin(rn(reg), _FP_REGNO, swf_off(r1) + 8); - swf_strin(rn(reg), _FP_REGNO, swf_off(r0) + 8); - } - } - else { - movr(r0, rn(reg)); - swf_ldrin(rn(reg), _FP_REGNO, swf_off(r1) + 8); - movr(r0 + 1, rn(reg)); - } - jit_unget_reg(reg); - } - } - else if (jit_fpr_p(r0)) { - reg = jit_get_reg(jit_class_gpr); - movr(rn(reg), r1); - xori(rn(reg), rn(reg), 0x80000000); - swf_strin(rn(reg), _FP_REGNO, swf_off(r0) + 4); - movr(rn(reg), r1 + 1); - swf_strin(rn(reg), _FP_REGNO, swf_off(r0) + 8); - jit_unget_reg(reg); - } - else { - xori(r0, r1, 0x80000000); - if (r0 != r1) - movr(r0 + 1, r1 + 1); - } -} - -static void -_swf_ner_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - swf_iff(__aeabi_fcmpeq, r0, r1, r2); - xori(r0, r0, 1); -} - -static void -_swf_nei_f(jit_state_t *_jit, int32_t r0, int32_t r1, jit_float32_t i0) -{ - swf_iff_(__aeabi_fcmpeq, r0, r1, i0); - xori(r0, r0, 1); -} - -static void -_swf_ner_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - swf_idd(__aeabi_dcmpeq, r0, r1, r2); - xori(r0, r0, 1); -} - -static void -_swf_nei_d(jit_state_t *_jit, int32_t r0, int32_t r1, jit_float64_t i0) -{ - swf_idd_(__aeabi_dcmpeq, r0, r1, i0); - xori(r0, r0, 1); -} - -static void -_swf_ltgtr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - swf_iunff(__aeabi_fcmpeq, r0, r1, r2); - xori(r0, r0, 1); -} - -static void -_swf_ltgti_f(jit_state_t *_jit, int32_t r0, int32_t r1, jit_float32_t i0) -{ - swf_iunff_(__aeabi_fcmpeq, r0, r1, i0); - xori(r0, r0, 1); -} - -static void -_swf_ltgtr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - swf_iundd(__aeabi_dcmpeq, r0, r1, r2); - xori(r0, r0, 1); -} - -static void -_swf_ltgti_d(jit_state_t *_jit, int32_t r0, int32_t r1, jit_float64_t i0) -{ - swf_iundd_(__aeabi_dcmpeq, r0, r1, i0); - xori(r0, r0, 1); -} - -static void -_swf_ordr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - swf_iff(__aeabi_fcmpun, r0, r1, r2); - xori(r0, r0, 1); -} - -static void -_swf_ordi_f(jit_state_t *_jit, int32_t r0, int32_t r1, jit_float32_t i0) -{ - swf_iff_(__aeabi_fcmpun, r0, r1, i0); - xori(r0, r0, 1); -} - -static void -_swf_ordr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - swf_idd(__aeabi_dcmpun, r0, r1, r2); - xori(r0, r0, 1); -} - -static void -_swf_ordi_d(jit_state_t *_jit, int32_t r0, int32_t r1, jit_float64_t i0) -{ - swf_idd_(__aeabi_dcmpun, r0, r1, i0); - xori(r0, r0, 1); -} - -static void -_swf_ldr_f(jit_state_t *_jit, int32_t r0, int32_t r1) -{ - int32_t reg; - if (jit_fpr_p(r0)) { - reg = jit_get_reg(jit_class_gpr); - ldxi_i(rn(reg), r1, 0); - swf_strin(rn(reg), _FP_REGNO, swf_off(r0) + 8); - jit_unget_reg(reg); - } - else - ldxi_i(r0, r1, 0); -} - -static void -_swf_ldr_d(jit_state_t *_jit, int32_t r0, int32_t r1) -{ - int32_t reg; - if (jit_fpr_p(r0)) { - if (!jit_thumb_p() && jit_armv5e_p() && - (reg = jit_get_reg_pair()) != JIT_NOREG) { - LDRDI(rn(reg), r1, 0); - STRDIN(rn(reg), _FP_REGNO, swf_off(r0) + 8); - jit_unget_reg_pair(reg); - } - else { - reg = jit_get_reg(jit_class_gpr); - ldxi_i(rn(reg), r1, 0); - swf_strin(rn(reg), _FP_REGNO, swf_off(r0) + 8); - ldxi_i(rn(reg), r1, 4); - swf_strin(rn(reg), _FP_REGNO, swf_off(r0) + 4); - jit_unget_reg(reg); - } - } - else if (!jit_thumb_p() && jit_armv5e_p() && !(r0 & 1)) - LDRDI(r0, r1, 0); - else { - ldxi_i(r0, r1, 0); - ldxi_i(r0 + 1, r1, 4); - } -} - -static void -_swf_ldi_f(jit_state_t *_jit, int32_t r0, jit_word_t i0) -{ - int32_t reg; - if (jit_fpr_p(r0)) { - reg = jit_get_reg(jit_class_gpr); - ldi_i(rn(reg), i0); - swf_strin(rn(reg), _FP_REGNO, swf_off(r0) + 8); - jit_unget_reg(reg); - } - else - ldi_i(r0, i0); -} - -static void -_swf_ldi_d(jit_state_t *_jit, int32_t r0, jit_word_t i0) -{ - int32_t rg0, rg1; - if (jit_fpr_p(r0) && !jit_thumb_p() && jit_armv5e_p() && - (rg0 = jit_get_reg_pair()) != JIT_NOREG) { - movi(rn(rg0), i0); - LDRDI(rn(rg0), rn(rg0), 0); - STRDIN(rn(rg0), _FP_REGNO, swf_off(r0) + 8); - jit_unget_reg_pair(rg0); - } - else { - rg1 = jit_get_reg(jit_class_gpr); - movi(rn(rg1), i0); - if (jit_fpr_p(r0)) { - rg0 = jit_get_reg(jit_class_gpr); - ldxi_i(rn(rg0), rn(rg1), 0); - swf_strin(rn(rg0), _FP_REGNO, swf_off(r0) + 8); - ldxi_i(rn(rg0), rn(rg1), 4); - swf_strin(rn(rg0), _FP_REGNO, swf_off(r0) + 4); - jit_unget_reg(rg0); - } - else if (!jit_thumb_p() && jit_armv5e_p() && !(r0 & 1)) - LDRDI(r0, rn(rg1), 0); - else { - ldxi_i(r0, rn(rg1), 0); - ldxi_i(r0 + 1, rn(rg1), 0); - } - jit_unget_reg(rg1); - } -} - -static void -_swf_ldxr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - int32_t reg; - if (jit_fpr_p(r0)) { - reg = jit_get_reg(jit_class_gpr); - ldxr_i(rn(reg), r1, r2); - swf_strin(rn(reg), _FP_REGNO, swf_off(r0) + 8); - jit_unget_reg(reg); - } - else - ldxr_i(r0, r1, r2); -} - -static void -_swf_ldxr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - int32_t rg0, rg1; - if (jit_fpr_p(r0)) { - if (!jit_thumb_p() && jit_armv5e_p() && - (rg0 = jit_get_reg_pair()) != JIT_NOREG) { - LDRD(rn(rg0), r1, r2); - STRDIN(rn(rg0), _FP_REGNO, swf_off(r0) + 8); - jit_unget_reg_pair(rg0); - } - else { - rg1 = jit_get_reg(jit_class_gpr); - addr(rn(rg1), r1, r2); - rg0 = jit_get_reg(jit_class_gpr); - ldxi_i(rn(rg0), rn(rg1), 0); - swf_strin(rn(rg0), _FP_REGNO, swf_off(r0) + 8); - ldxi_i(rn(rg0), rn(rg1), 4); - swf_strin(rn(rg0), _FP_REGNO, swf_off(r0) + 4); - jit_unget_reg(rg0); - jit_unget_reg(rg1); - } - } - else { - if (!jit_thumb_p() && jit_armv5e_p() && !(r0 & 1)) - LDRD(r0, r1, r2); - else { - rg1 = jit_get_reg(jit_class_gpr); - addr(rn(rg1), r1, r2); - ldxi_i(r0, rn(rg1), 0); - ldxi_i(r0 + 1, rn(rg1), 4); - jit_unget_reg(rg1); - } - } -} - -static void -_swf_ldxi_f(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) -{ - int32_t reg; - if (jit_fpr_p(r0)) { - reg = jit_get_reg(jit_class_gpr); - ldxi_i(rn(reg), r1, i0); - swf_strin(rn(reg), _FP_REGNO, swf_off(r0) + 8); - jit_unget_reg(reg); - } - else - ldxi_i(r0, r1, i0); -} - -static void -_swf_ldxi_d(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) -{ - int32_t rg0, rg1; - if (jit_fpr_p(r0)) { - if (!jit_thumb_p() && jit_armv5e_p() && - ((i0 >= 0 && i0 <= 255) || (i0 < 0 && i0 >= -255)) && - (rg0 = jit_get_reg_pair()) != JIT_NOREG) { - if (i0 >= 0) - LDRDI(rn(rg0), r1, i0); - else - LDRDIN(rn(rg0), r1, -i0); - STRDIN(rn(rg0), _FP_REGNO, swf_off(r0) + 8); - jit_unget_reg_pair(rg0); - } - else if (i0 >= 0 && i0 + 4 <= 4095) { - rg0 = jit_get_reg(jit_class_gpr); - ldxi_i(rn(rg0), r1, i0); - swf_strin(rn(rg0), _FP_REGNO, swf_off(r0) + 8); - ldxi_i(rn(rg0), r1, i0 + 4); - swf_strin(rn(rg0), _FP_REGNO, swf_off(r0) + 4); - jit_unget_reg(rg0); - } - else if (i0 < 0 && ((jit_thumb_p() && i0 >= -255) || - (!jit_thumb_p() && i0 >= -4095))) { - rg0 = jit_get_reg(jit_class_gpr); - swf_ldrin(rn(rg0), r1, -i0); - swf_strin(rn(rg0), _FP_REGNO, swf_off(r0) + 8); - swf_ldrin(rn(rg0), r1, -(i0 + 4)); - swf_strin(rn(rg0), _FP_REGNO, swf_off(r0) + 4); - jit_unget_reg(rg0); - } - else { - rg0 = jit_get_reg(jit_class_gpr); - rg1 = jit_get_reg(jit_class_gpr); - addi(rn(rg1), r1, i0); - ldxi_i(rn(rg0), rn(rg1), 0); - swf_strin(rn(rg0), _FP_REGNO, swf_off(r0) + 8); - ldxi_i(rn(rg0), rn(rg1), 4); - swf_strin(rn(rg0), _FP_REGNO, swf_off(r0) + 4); - jit_unget_reg(rg1); - jit_unget_reg(rg0); - } - } - else { - if (!jit_thumb_p() && jit_armv5e_p() && - i0 >= 0 && i0 <= 255 && !(r0 & 1)) - LDRDI(r0, r1, i0); - else if (!jit_thumb_p() && jit_armv5e_p() && - i0 < 0 && i0 >= -255 && !(r0 & 1)) - LDRDIN(r0, r1, -i0); - else if (i0 >= 0 && i0 + 4 <= 4095) { - ldxi_i(r0, r1, i0); - ldxi_i(r0 + 1, r1, i0 + 4); - } - else if (i0 < 0 && i0 >= -4095) { - swf_ldrin(r0, r1, -i0); - swf_ldrin(r0 + 1, r1, -(i0 + 4)); - } - else { - rg0 = jit_get_reg(jit_class_gpr); - addi(rn(rg0), r1, i0); - ldxi_i(r0, rn(rg0), 0); - ldxi_i(r0 + 1, rn(rg0), 4); - jit_unget_reg(rg0); - } - } -} - -static void -_swf_str_f(jit_state_t *_jit, int32_t r0, int32_t r1) -{ - int32_t reg; - if (jit_fpr_p(r1)) { - reg = jit_get_reg(jit_class_gpr); - swf_ldrin(rn(reg), _FP_REGNO, swf_off(r1) + 8); - stxi_i(0, r0, rn(reg)); - jit_unget_reg(reg); - } - else - str_i(r0, r1); -} - -static void -_swf_str_d(jit_state_t *_jit, int32_t r0, int32_t r1) -{ - int32_t reg; - if (jit_fpr_p(r1)) { - if (!jit_thumb_p() && jit_armv5e_p() && - (reg = jit_get_reg_pair()) != JIT_NOREG) { - LDRDIN(rn(reg), _FP_REGNO, swf_off(r1) + 8); - STRDI(rn(reg), r0, 0); - jit_unget_reg_pair(reg); - } - else { - reg = jit_get_reg(jit_class_gpr); - swf_ldrin(rn(reg), _FP_REGNO, swf_off(r1) + 8); - stxi_i(0, r0, rn(reg)); - swf_ldrin(rn(reg), _FP_REGNO, swf_off(r1) + 4); - stxi_i(4, r0, rn(reg)); - jit_unget_reg(reg); - } - } - else { - if (!jit_thumb_p() && jit_armv5e_p() && !(r1 & 1)) - STRDI(r1, r0, 0); - else { - stxi_i(0, r0, r1); - stxi_i(4, r0, r1 + 1); - } - } -} - -static void -_swf_sti_f(jit_state_t *_jit, jit_word_t i0, int32_t r0) -{ - int32_t reg; - if (jit_fpr_p(r0)) { - reg = jit_get_reg(jit_class_gpr); - swf_ldrin(rn(reg), _FP_REGNO, swf_off(r0) + 8); - sti_i(i0, rn(reg)); - jit_unget_reg(reg); - } - else - sti_i(i0, r0); -} - -static void -_swf_sti_d(jit_state_t *_jit, jit_word_t i0, int32_t r0) -{ - int32_t rg0, rg1; - if (jit_fpr_p(r0)) { - if (!jit_thumb_p() && jit_armv5e_p() && - (rg0 = jit_get_reg_pair()) != JIT_NOREG) { - rg1 = jit_get_reg(jit_class_gpr); - movi(rn(rg1), i0); - LDRDIN(rn(rg0), _FP_REGNO, swf_off(r0) + 8); - STRDI(rn(rg0), rn(rg1), 0); - jit_unget_reg(rg1); - jit_unget_reg_pair(rg0); - } - else { - rg1 = jit_get_reg(jit_class_gpr); - movi(rn(rg1), i0); - rg0 = jit_get_reg(jit_class_gpr); - swf_ldrin(rn(rg0), _FP_REGNO, swf_off(r0) + 8); - stxi_i(0, rn(rg1), rn(rg0)); - swf_ldrin(rn(rg0), _FP_REGNO, swf_off(r0) + 4); - stxi_i(4, rn(rg1), rn(rg0)); - jit_unget_reg(rg1); - jit_unget_reg(rg0); - } - } - else { - rg1 = jit_get_reg(jit_class_gpr); - movi(rn(rg1), i0); - if (!jit_thumb_p() && jit_armv5e_p() && !(r0 & 1)) - STRDI(r0, rn(rg1), 0); - else { - stxi_i(0, rn(rg1), r0); - stxi_i(4, rn(rg1), r0 + 1); - } - jit_unget_reg(rg1); - } -} - -static void -_swf_stxr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - int32_t reg; - if (jit_fpr_p(r2)) { - reg = jit_get_reg(jit_class_gpr); - swf_ldrin(rn(reg), _FP_REGNO, swf_off(r2) + 8); - stxr_i(r1, r0, rn(reg)); - jit_unget_reg(reg); - } - else - stxr_i(r0, r1, r2); -} - -static void -_swf_stxr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - int32_t rg0, rg1; - if (jit_fpr_p(r2)) { - if (!jit_thumb_p() && jit_armv5e_p() && - (rg0 = jit_get_reg_pair()) != JIT_NOREG) { - LDRDIN(rn(rg0), _FP_REGNO, swf_off(r2) + 8); - STRD(rn(rg0), r0, r1); - jit_unget_reg_pair(rg0); - } - else { - rg1 = jit_get_reg(jit_class_gpr); - addr(rn(rg1), r0, r1); - rg0 = jit_get_reg(jit_class_gpr); - swf_ldrin(rn(rg0), _FP_REGNO, swf_off(r2) + 8); - stxi_i(0, rn(rg1), rn(rg0)); - swf_ldrin(rn(rg0), _FP_REGNO, swf_off(r2) + 4); - stxi_i(4, rn(rg1), rn(rg0)); - jit_unget_reg(rg0); - jit_unget_reg(rg1); - } - } - else { - if (!jit_thumb_p() && jit_armv5e_p() && !(r2 & 1)) - STRD(r0, r1, r2); - else { - rg1 = jit_get_reg(jit_class_gpr); - addr(rn(rg1), r0, r1); - stxi_i(0, rn(rg1), r2); - stxi_i(4, rn(rg1), r2 + 1); - jit_unget_reg(rg1); - } - } -} - -static void -_swf_stxi_f(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) -{ - int32_t reg; - if (jit_fpr_p(r1)) { - reg = jit_get_reg(jit_class_gpr); - swf_ldrin(rn(reg), _FP_REGNO, swf_off(r1) + 8); - stxi_i(i0, r0, rn(reg)); - jit_unget_reg(reg); - } - else - stxi_i(i0, r0, r1); -} - -static void -_swf_stxi_d(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) -{ - int32_t rg0, rg1; - if (jit_fpr_p(r1)) { - if (!jit_thumb_p() && jit_armv5e_p() && - ((i0 >= 0 && i0 <= 255) || (i0 < 0 && i0 >= -255)) && - (rg0 = jit_get_reg_pair()) != JIT_NOREG) { - LDRDIN(rn(rg0), _FP_REGNO, swf_off(r1) + 8); - if (i0 >= 0 && i0 <= 255) - STRDI(rn(rg0), r0, i0); - else - STRDIN(rn(rg0), r0, -i0); - jit_unget_reg_pair(rg0); - } - else if (i0 >= 0 && i0 + 4 <= 4095) { - rg0 = jit_get_reg(jit_class_gpr); - swf_ldrin(rn(rg0), _FP_REGNO, swf_off(r1) + 8); - stxi_i(i0, r0, rn(rg0)); - swf_ldrin(rn(rg0), _FP_REGNO, swf_off(r1) + 4); - stxi_i(i0 + 4, r0, rn(rg0)); - jit_unget_reg(rg0); - } - else if (i0 < 0 && ((jit_thumb_p() && i0 >= -255) || - (!jit_thumb_p() && i0 >= -4095))) { - rg0 = jit_get_reg(jit_class_gpr); - swf_ldrin(rn(rg0), _FP_REGNO, swf_off(r1) + 8); - swf_strin(rn(rg0), r0, -i0); - swf_ldrin(rn(rg0), _FP_REGNO, swf_off(r1) + 4); - swf_strin(rn(rg0), r0, -(i0 + 4)); - jit_unget_reg(rg0); - } - else { - rg1 = jit_get_reg(jit_class_gpr); - addi(rn(rg1), r0, i0); - rg0 = jit_get_reg(jit_class_gpr); - swf_ldrin(rn(rg0), _FP_REGNO, swf_off(r1) + 8); - stxi_i(0, rn(rg1), rn(rg0)); - swf_ldrin(rn(rg0), _FP_REGNO, swf_off(r1) + 4); - stxi_i(4, rn(rg1), rn(rg0)); - jit_unget_reg(rg0); - jit_unget_reg(rg1); - } - } - else { - if (!jit_thumb_p() && jit_armv5e_p() && - i0 >= 0 && i0 <= 255 && !(r1 & 1)) - STRDI(r1, r0, i0); - else if (!jit_thumb_p() && jit_armv5e_p() && - i0 < 0 && i0 >= -255 && !(r1 & 1)) - STRDIN(r1, r0, -i0); - else if (i0 >= 0 && i0 + 4 <= 4095) { - stxi_i(i0, r0, r1); - stxi_i(i0 + 4, r0, r1 + 1); - } - else if (i0 < 0 && ((jit_thumb_p() && i0 >= 255) || - (!jit_thumb_p() && i0 >= -4095))) { - swf_strin(r1, r0, -i0); - swf_strin(r1 + 1, r0, -(i0 + 4)); - } - else { - rg1 = jit_get_reg(jit_class_gpr); - addi(rn(rg1), r0, i0); - stxi_i(0, rn(rg1), r1); - stxi_i(4, rn(rg1), r1 + 1); - jit_unget_reg(rg1); - } - } -} - -static void -_swf_vaarg_d(jit_state_t *_jit, int32_t r0, int32_t r1) -{ - int32_t reg; - - assert(_jitc->function->self.call & jit_call_varargs); - - /* Adjust pointer. */ - reg = jit_get_reg(jit_class_gpr); - andi(rn(reg), r1, 7); - addr(r1, r1, rn(reg)); - jit_unget_reg(reg); - - /* Load argument. */ - swf_ldr_d(r0, r1); - - /* Update stack pointer. */ - addi(r1, r1, sizeof(jit_float64_t)); -} - -#endif diff --git a/lightening/arm.c b/lightening/arm.c index 0df47814e..12a728664 100644 --- a/lightening/arm.c +++ b/lightening/arm.c @@ -98,7 +98,6 @@ extern void __clear_cache(void *, void *); #define PROTO 1 # include "rewind.c" # include "arm-cpu.c" -# include "arm-swf.c" # include "arm-vfp.c" #undef PROTO @@ -2007,8 +2006,7 @@ _emit_code(jit_state_t *_jit) #define CODE 1 # include "rewind.c" # include "arm-cpu.c" -# include "arm-swf.c" -# include ", 2018arm-vfp.c" +# include "arm-vfp.c" #undef CODE void diff --git a/tests/Makefile b/tests/Makefile index 02d34af64..2a048501d 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,5 +1,6 @@ TESTS=$(sort $(basename $(wildcard *.c))) TARGETS=native ia32 aarch64 +ALL_TARGETS=$(TARGETS) armv7 # Suitable values of cross-compiler variables for Debian: # @@ -19,6 +20,7 @@ TARGETS=native ia32 aarch64 CC = gcc CC_IA32=guix environment --pure -s i686-linux --ad-hoc gcc-toolchain glibc -- gcc CC_AARCH64=guix environment --pure -s aarch64-linux --ad-hoc gcc-toolchain glibc -- gcc +CC_ARMv7=guix environment --pure -s armhf-linux --ad-hoc gcc-toolchain glibc -- gcc CFLAGS = -Wall -O0 -g all: $(foreach TARGET,$(TARGETS),$(addprefix test-$(TARGET)-,$(TESTS))) @@ -49,9 +51,13 @@ test-aarch64-%: CC = $(CC_AARCH64) test-aarch64-%: %.c lightening-aarch64.o test.h $(CC) $(CFLAGS) $(CPPFLAGS) -I.. -o $@ lightening-aarch64.o $< -.PRECIOUS: $(foreach TARGET,$(TARGETS),$(addprefix test-$(TARGET)-,$(TESTS))) -.PRECIOUS: $(foreach TARGET,$(TARGETS),lightening-$(TARGET).o) +test-armv7-%: CC = $(CC_ARMv7) +test-armv7-%: %.c lightening-armv7.o test.h + $(CC) $(CFLAGS) $(CPPFLAGS) -I.. -o $@ lightening-armv7.o $< + +.PRECIOUS: $(foreach TARGET,$(ALL_TARGETS),$(addprefix test-$(TARGET)-,$(TESTS))) +.PRECIOUS: $(foreach TARGET,$(ALL_TARGETS),lightening-$(TARGET).o) clean: - rm -f $(foreach TARGET,$(TARGETS),$(addprefix test-$(TARGET)-,$(TESTS))) - rm -f $(foreach TARGET,$(TARGETS),lightening-$(TARGET).o) + rm -f $(foreach TARGET,$(ALL_TARGETS),$(addprefix test-$(TARGET)-,$(TESTS))) + rm -f $(foreach TARGET,$(ALL_TARGETS),lightening-$(TARGET).o) From 0da87968d1444b5708d4855f0a6ace3837c50d4b Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Fri, 17 May 2019 10:59:05 +0200 Subject: [PATCH 24/33] Remove unused jit_{gpr,fpr}_is_callee_save --- lightening/aarch64.h | 15 -------------- lightening/x86.h | 48 -------------------------------------------- 2 files changed, 63 deletions(-) diff --git a/lightening/aarch64.h b/lightening/aarch64.h index 13a0f1ca3..0e675a9ee 100644 --- a/lightening/aarch64.h +++ b/lightening/aarch64.h @@ -89,21 +89,6 @@ #define _D30 JIT_FPR(30) #define _D31 JIT_FPR(31) -static inline jit_bool_t -jit_gpr_is_callee_save (jit_gpr_t reg) -{ - // x19 to x28 are callee-save, x29 is the frame pointer, and x30 is - // the link register. - return 19 <= jit_gpr_regno (reg) && jit_gpr_regno (reg) <= 30; -} - -static inline jit_bool_t -jit_fpr_is_callee_save (jit_fpr_t reg) -{ - // v8 to v15 are callee-save. - return 8 <= jit_fpr_regno (reg) && jit_fpr_regno (reg) <= 15; -} - #define JIT_R0 _X0 #define JIT_R1 _X1 #define JIT_R2 _X2 diff --git a/lightening/x86.h b/lightening/x86.h index 647490380..64ee00637 100644 --- a/lightening/x86.h +++ b/lightening/x86.h @@ -73,54 +73,6 @@ # define _XMM15 JIT_FPR(15) #endif -static inline jit_bool_t -jit_gpr_is_callee_save (jit_gpr_t reg) -{ -#if __X32 - return jit_same_gprs (reg, _RBX) || - jit_same_gprs (reg, _RBP) || - jit_same_gprs (reg, _RSI) || - jit_same_gprs (reg, _RDI); -#elif __CYGWIN__ - return jit_same_gprs (reg, _RBX) || - jit_same_gprs (reg, _RBP) || - jit_same_gprs (reg, _RSI) || - jit_same_gprs (reg, _RDI) || - jit_same_gprs (reg, _R12) || - jit_same_gprs (reg, _R13) || - jit_same_gprs (reg, _R14) || - jit_same_gprs (reg, _R15); -#else - return jit_same_gprs (reg, _RBX) || - jit_same_gprs (reg, _RBP) || - jit_same_gprs (reg, _R12) || - jit_same_gprs (reg, _R13) || - jit_same_gprs (reg, _R14) || - jit_same_gprs (reg, _R15); -#endif -} - -static inline jit_bool_t -jit_fpr_is_callee_save (jit_fpr_t reg) -{ -#if __X32 - return 0; -#elif __CYGWIN__ - return jit_same_fprs (reg, _XMM6) || - jit_same_fprs (reg, _XMM7) || - jit_same_fprs (reg, _XMM8) || - jit_same_fprs (reg, _XMM9) || - jit_same_fprs (reg, _XMM10) || - jit_same_fprs (reg, _XMM11) || - jit_same_fprs (reg, _XMM12) || - jit_same_fprs (reg, _XMM13) || - jit_same_fprs (reg, _XMM14) || - jit_same_fprs (reg, _XMM15); -#else - return 0; -#endif -} - #define JIT_SP _RSP #if __X32 # define JIT_R0 _RAX From b71ddba1f776643f50e9d6eb2cbe262e1d014465 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Fri, 17 May 2019 10:59:59 +0200 Subject: [PATCH 25/33] Beginnings of ARMv7 backend --- lightening/arm-cpu.c | 4971 +++++++++++++++++++++--------------------- lightening/arm.c | 2298 +------------------ lightening/arm.h | 205 +- 3 files changed, 2660 insertions(+), 4814 deletions(-) diff --git a/lightening/arm-cpu.c b/lightening/arm-cpu.c index 9d44699b9..923db7bbf 100644 --- a/lightening/arm-cpu.c +++ b/lightening/arm-cpu.c @@ -14,311 +14,300 @@ * License for more details. * * Authors: - * Paulo Cesar Pereira de Andrade + * Paulo Cesar Pereira de Andrade */ -#if PROTO -# define stxi(i0,r0,r1) stxi_i(i0,r0,r1) -# define ldxi(r0,r1,i0) ldxi_i(r0,r1,i0) -# define ldr(r0,r1) ldr_i(r0,r1) -# define _s20P(d) ((d) >= -(int)0x80000 && d <= 0x7ffff) -# define _s24P(d) ((d) >= -(int)0x800000 && d <= 0x7fffff) -# define _u3(v) ((v) & 0x7) -# define _u4(v) ((v) & 0xf) -# define _u5(v) ((v) & 0x1f) -# define _u8(v) ((v) & 0xff) -# define _u12(v) ((v) & 0xfff) -# define _u13(v) ((v) & 0x1fff) -# define _u16(v) ((v) & 0xffff) -# define _u24(v) ((v) & 0xffffff) -# define jit_thumb_p() jit_cpu.thumb -# define jit_no_set_flags() _jitc->no_set_flags -# define jit_armv5_p() (jit_cpu.version >= 5) -# define jit_armv5e_p() (jit_cpu.version > 5 || (jit_cpu.version == 5 && jit_cpu.extend)) -# define jit_armv6_p() (jit_cpu.version >= 6) -# define jit_armv7r_p() 0 -# define stack_framesize 48 -extern int __aeabi_idivmod(int, int); -extern unsigned __aeabi_uidivmod(unsigned, unsigned); -# define _R0_REGNO 0x00 -# define _R1_REGNO 0x01 -# define _R2_REGNO 0x02 -# define _R3_REGNO 0x03 -# define _R4_REGNO 0x04 -# define _R5_REGNO 0x05 -# define _R6_REGNO 0x06 -# define _R7_REGNO 0x07 -# define _R8_REGNO 0x08 -# define _R9_REGNO 0x09 -# define _R10_REGNO 0x0a -# define _R11_REGNO 0x0b -# define _R12_REGNO 0x0c -# define _R13_REGNO 0x0d -# define _R14_REGNO 0x0e -# define _R15_REGNO 0x0f -# define _FP_REGNO _R11_REGNO -# define _SP_REGNO _R13_REGNO -# define _LR_REGNO _R14_REGNO -# define _PC_REGNO _R15_REGNO -# define ARM_CC_EQ 0x00000000 /* Z=1 */ -# define ARM_CC_NE 0x10000000 /* Z=0 */ -# define ARM_CC_HS 0x20000000 /* C=1 */ -# define ARM_CC_CS ARM_CC_HS -# define ARM_CC_LO 0x30000000 /* C=0 */ -# define ARM_CC_CC ARM_CC_LO -# define ARM_CC_MI 0x40000000 /* N=1 */ -# define ARM_CC_PL 0x50000000 /* N=0 */ -# define ARM_CC_VS 0x60000000 /* V=1 */ -# define ARM_CC_VC 0x70000000 /* V=0 */ -# define ARM_CC_HI 0x80000000 /* C=1 && Z=0 */ -# define ARM_CC_LS 0x90000000 /* C=0 || Z=1 */ -# define ARM_CC_GE 0xa0000000 /* N=V */ -# define ARM_CC_LT 0xb0000000 /* N!=V */ -# define ARM_CC_GT 0xc0000000 /* Z=0 && N=V */ -# define ARM_CC_LE 0xd0000000 /* Z=1 || N!=V */ -# define ARM_CC_AL 0xe0000000 /* always */ -# define ARM_CC_NV 0xf0000000 /* reserved */ -# define THUMB2_IT 0 -# define THUMB2_ITT 1 -# define THUMB2_ITE 2 -# define THUMB2_ITTT 3 -# define THUMB2_ITET 4 -# define THUMB2_ITTE 5 -# define THUMB2_ITEE 6 -# define THUMB2_ITTTT 7 -# define THUMB2_ITETT 8 -# define THUMB2_ITTET 9 -# define THUMB2_ITEET 10 -# define THUMB2_ITTTE 11 -# define THUMB2_ITETE 12 -# define THUMB2_ITTEE 13 -# define THUMB2_ITEEE 14 -# define ARM_MOV 0x01a00000 -# define THUMB_MOV 0x4600 -# define ARM_MOVWI 0x03000000 /* v6t2, v7 */ -# define THUMB_MOVI 0x2000 -# define THUMB2_MOVI 0xf0400000 -# define THUMB2_MOVWI 0xf2400000 -# define ARM_MOVTI 0x03400000 -# define THUMB2_MOVTI 0xf2c00000 -# define ARM_MVN 0x01e00000 -# define THUMB_MVN 0x43c0 -# define THUMB2_MVN 0xea600000 -# define THUMB2_MVNI 0xf0600000 -# define ARM_I 0x02000000 /* immediate */ -# define ARM_S 0x00100000 /* set flags */ -# define ARM_ADD 0x00800000 -# define THUMB_ADD 0x1800 -# define THUMB_ADDX 0x4400 -# define THUMB2_ADD 0xeb000000 -# define THUMB_ADDI3 0x1c00 -# define THUMB_ADDI8 0x3000 -# define THUMB2_ADDI 0xf1000000 -# define THUMB2_ADDWI 0xf2000000 -# define ARM_ADC 0x00a00000 -# define THUMB_ADC 0x4140 -# define THUMB2_ADC 0xeb400000 -# define THUMB2_ADCI 0xf1400000 -# define ARM_SUB 0x00400000 -# define THUMB_SUB 0x1a00 -# define THUMB2_SUB 0xeba00000 -# define THUMB_SUBI3 0x1e00 -# define THUMB_SUBI8 0x3800 -# define THUMB2_SUBI 0xf1a00000 -# define THUMB2_SUBWI 0xf2a00000 -# define ARM_SBC 0x00c00000 -# define THUMB_SBC 0x4180 -# define THUMB2_SBC 0xeb600000 -# define THUMB2_SBCI 0xf1600000 -# define ARM_RSB 0x00600000 -# define THUMB_RSBI 0x4240 -# define THUMB2_RSBI 0xf1c00000 -# define ARM_MUL 0x00000090 -# define THUMB_MUL 0x4340 -# define THUMB2_MUL 0xfb00f000 -# define ARM_UMULL 0x00800090 -# define THUMB2_UMULL 0xfba00000 -# define ARM_SMULL 0x00c00090 -# define THUMB2_SMULL 0xfb800000 -# define THUMB2_SDIV 0xfb90f0f0 -# define THUMB2_UDIV 0xfbb0f0f0 -# define ARM_AND 0x00000000 -# define THUMB_AND 0x4000 -# define THUMB2_AND 0xea000000 -# define THUMB2_ANDI 0xf0000000 -# define ARM_BIC 0x01c00000 -# define THUMB2_BIC 0xea200000 -# define THUMB2_BICI 0xf0200000 -# define ARM_ORR 0x01800000 -# define THUMB_ORR 0x4300 -# define THUMB2_ORR 0xea400000 -# define THUMB2_ORRI 0xf0400000 -# define ARM_EOR 0x00200000 -# define THUMB_EOR 0x4040 -# define THUMB2_EOR 0xea800000 -# define THUMB2_EORI 0xf0800000 +#define _s20P(d) ((d) >= -(int)0x80000 && d <= 0x7ffff) +#define _s24P(d) ((d) >= -(int)0x800000 && d <= 0x7fffff) +#define _u3(v) ((v) & 0x7) +#define _u4(v) ((v) & 0xf) +#define _u5(v) ((v) & 0x1f) +#define _u8(v) ((v) & 0xff) +#define _u12(v) ((v) & 0xfff) +#define _u13(v) ((v) & 0x1fff) +#define _u16(v) ((v) & 0xffff) +#define _u24(v) ((v) & 0xffffff) +extern int __aeabi_idivmod(int, int); +extern unsigned __aeabi_uidivmod(unsigned, unsigned); +# define _R0_REGNO 0x00 +# define _R1_REGNO 0x01 +# define _R2_REGNO 0x02 +# define _R3_REGNO 0x03 +# define _R4_REGNO 0x04 +# define _R5_REGNO 0x05 +# define _R6_REGNO 0x06 +# define _R7_REGNO 0x07 +# define _R8_REGNO 0x08 +# define _R9_REGNO 0x09 +# define _R10_REGNO 0x0a +# define _R11_REGNO 0x0b +# define _R12_REGNO 0x0c +# define _R13_REGNO 0x0d +# define _R14_REGNO 0x0e +# define _R15_REGNO 0x0f +# define _FP_REGNO _R11_REGNO +# define _SP_REGNO _R13_REGNO +# define _LR_REGNO _R14_REGNO +# define _PC_REGNO _R15_REGNO +# define ARM_CC_EQ 0x00000000 /* Z=1 */ +# define ARM_CC_NE 0x10000000 /* Z=0 */ +# define ARM_CC_HS 0x20000000 /* C=1 */ +# define ARM_CC_CS ARM_CC_HS +# define ARM_CC_LO 0x30000000 /* C=0 */ +# define ARM_CC_CC ARM_CC_LO +# define ARM_CC_MI 0x40000000 /* N=1 */ +# define ARM_CC_PL 0x50000000 /* N=0 */ +# define ARM_CC_VS 0x60000000 /* V=1 */ +# define ARM_CC_VC 0x70000000 /* V=0 */ +# define ARM_CC_HI 0x80000000 /* C=1 && Z=0 */ +# define ARM_CC_LS 0x90000000 /* C=0 || Z=1 */ +# define ARM_CC_GE 0xa0000000 /* N=V */ +# define ARM_CC_LT 0xb0000000 /* N!=V */ +# define ARM_CC_GT 0xc0000000 /* Z=0 && N=V */ +# define ARM_CC_LE 0xd0000000 /* Z=1 || N!=V */ +# define ARM_CC_AL 0xe0000000 /* always */ +# define ARM_CC_NV 0xf0000000 /* reserved */ +# define THUMB2_IT 0 +# define THUMB2_ITT 1 +# define THUMB2_ITE 2 +# define THUMB2_ITTT 3 +# define THUMB2_ITET 4 +# define THUMB2_ITTE 5 +# define THUMB2_ITEE 6 +# define THUMB2_ITTTT 7 +# define THUMB2_ITETT 8 +# define THUMB2_ITTET 9 +# define THUMB2_ITEET 10 +# define THUMB2_ITTTE 11 +# define THUMB2_ITETE 12 +# define THUMB2_ITTEE 13 +# define THUMB2_ITEEE 14 +# define ARM_MOV 0x01a00000 +# define THUMB_MOV 0x4600 +# define ARM_MOVWI 0x03000000 /* v6t2, v7 */ +# define THUMB_MOVI 0x2000 +# define THUMB2_MOVI 0xf0400000 +# define THUMB2_MOVWI 0xf2400000 +# define ARM_MOVTI 0x03400000 +# define THUMB2_MOVTI 0xf2c00000 +# define ARM_MVN 0x01e00000 +# define THUMB_MVN 0x43c0 +# define THUMB2_MVN 0xea600000 +# define THUMB2_MVNI 0xf0600000 +# define ARM_I 0x02000000 /* immediate */ +# define ARM_S 0x00100000 /* set flags */ +# define ARM_ADD 0x00800000 +# define THUMB_ADD 0x1800 +# define THUMB_ADDX 0x4400 +# define THUMB2_ADD 0xeb000000 +# define THUMB_ADDI3 0x1c00 +# define THUMB_ADDI8 0x3000 +# define THUMB2_ADDI 0xf1000000 +# define THUMB2_ADDWI 0xf2000000 +# define ARM_ADC 0x00a00000 +# define THUMB_ADC 0x4140 +# define THUMB2_ADC 0xeb400000 +# define THUMB2_ADCI 0xf1400000 +# define ARM_SUB 0x00400000 +# define THUMB_SUB 0x1a00 +# define THUMB2_SUB 0xeba00000 +# define THUMB_SUBI3 0x1e00 +# define THUMB_SUBI8 0x3800 +# define THUMB2_SUBI 0xf1a00000 +# define THUMB2_SUBWI 0xf2a00000 +# define ARM_SBC 0x00c00000 +# define THUMB_SBC 0x4180 +# define THUMB2_SBC 0xeb600000 +# define THUMB2_SBCI 0xf1600000 +# define ARM_RSB 0x00600000 +# define THUMB_RSBI 0x4240 +# define THUMB2_RSBI 0xf1c00000 +# define ARM_MUL 0x00000090 +# define THUMB_MUL 0x4340 +# define THUMB2_MUL 0xfb00f000 +# define ARM_UMULL 0x00800090 +# define THUMB2_UMULL 0xfba00000 +# define ARM_SMULL 0x00c00090 +# define THUMB2_SMULL 0xfb800000 +# define THUMB2_SDIV 0xfb90f0f0 +# define THUMB2_UDIV 0xfbb0f0f0 +# define ARM_AND 0x00000000 +# define THUMB_AND 0x4000 +# define THUMB2_AND 0xea000000 +# define THUMB2_ANDI 0xf0000000 +# define ARM_BIC 0x01c00000 +# define THUMB2_BIC 0xea200000 +# define THUMB2_BICI 0xf0200000 +# define ARM_ORR 0x01800000 +# define THUMB_ORR 0x4300 +# define THUMB2_ORR 0xea400000 +# define THUMB2_ORRI 0xf0400000 +# define ARM_EOR 0x00200000 +# define THUMB_EOR 0x4040 +# define THUMB2_EOR 0xea800000 +# define THUMB2_EORI 0xf0800000 /* >> ARMv6* */ -# define ARM_REV 0x06bf0f30 -# define THUMB_REV 0xba00 -# define THUMB2_REV 0xfa90f080 -# define ARM_REV16 0x06bf0fb0 -# define THUMB_REV16 0xba40 -# define THUMB2_REV16 0xfa90f090 -# define ARM_SXTB 0x06af0070 -# define THUMB_SXTB 0xb240 -# define THUMB2_SXTB 0xfa40f080 -# define ARM_UXTB 0x06ef0070 -# define THUMB_UXTB 0xb2c0 -# define THUMB2_UXTB 0xfa50f080 -# define ARM_SXTH 0x06bf0070 -# define THUMB_SXTH 0xb200 -# define THUMB2_SXTH 0xfa00f080 -# define ARM_UXTH 0x06ff0070 -# define THUMB_UXTH 0xb280 -# define THUMB2_UXTH 0xfa10f080 -# define ARM_XTR8 0x00000400 /* ?xt? rotate 8 bits */ -# define ARM_XTR16 0x00000800 /* ?xt? rotate 16 bits */ -# define ARM_XTR24 0x00000c00 /* ?xt? rotate 24 bits */ +# define ARM_REV 0x06bf0f30 +# define THUMB_REV 0xba00 +# define THUMB2_REV 0xfa90f080 +# define ARM_REV16 0x06bf0fb0 +# define THUMB_REV16 0xba40 +# define THUMB2_REV16 0xfa90f090 +# define ARM_SXTB 0x06af0070 +# define THUMB_SXTB 0xb240 +# define THUMB2_SXTB 0xfa40f080 +# define ARM_UXTB 0x06ef0070 +# define THUMB_UXTB 0xb2c0 +# define THUMB2_UXTB 0xfa50f080 +# define ARM_SXTH 0x06bf0070 +# define THUMB_SXTH 0xb200 +# define THUMB2_SXTH 0xfa00f080 +# define ARM_UXTH 0x06ff0070 +# define THUMB_UXTH 0xb280 +# define THUMB2_UXTH 0xfa10f080 +# define ARM_XTR8 0x00000400 /* ?xt? rotate 8 bits */ +# define ARM_XTR16 0x00000800 /* ?xt? rotate 16 bits */ +# define ARM_XTR24 0x00000c00 /* ?xt? rotate 24 bits */ /* << ARMv6* */ -# define ARM_SHIFT 0x01a00000 -# define ARM_R 0x00000010 /* register shift */ -# define ARM_LSL 0x00000000 -# define THUMB_LSL 0x4080 -# define THUMB2_LSL 0xfa00f000 -# define THUMB_LSLI 0x0000 -# define THUMB2_LSLI 0xea4f0000 -# define ARM_LSR 0x00000020 -# define THUMB_LSR 0x40c0 -# define THUMB2_LSR 0xfa20f000 -# define THUMB_LSRI 0x0800 -# define THUMB2_LSRI 0xea4f0010 -# define ARM_ASR 0x00000040 -# define THUMB_ASR 0x4100 -# define THUMB2_ASR 0xfa40f000 -# define THUMB_ASRI 0x1000 -# define THUMB2_ASRI 0xea4f0020 -# define ARM_ROR 0x00000060 -# define ARM_CMP 0x01500000 -# define THUMB_CMP 0x4280 -# define THUMB_CMPX 0x4500 -# define THUMB2_CMP 0xebb00000 -# define THUMB_CMPI 0x2800 -# define THUMB2_CMPI 0xf1b00000 -# define ARM_CMN 0x01700000 -# define THUMB_CMN 0x42c0 -# define THUMB2_CMN 0xeb100000 -# define THUMB2_CMNI 0xf1100000 -# define ARM_TST 0x01100000 -# define THUMB_TST 0x4200 -# define THUMB2_TST 0xea100000 -# define THUMB2_TSTI 0xf0100000 -# define ARM_TEQ 0x01300000 +# define ARM_SHIFT 0x01a00000 +# define ARM_R 0x00000010 /* register shift */ +# define ARM_LSL 0x00000000 +# define THUMB_LSL 0x4080 +# define THUMB2_LSL 0xfa00f000 +# define THUMB_LSLI 0x0000 +# define THUMB2_LSLI 0xea4f0000 +# define ARM_LSR 0x00000020 +# define THUMB_LSR 0x40c0 +# define THUMB2_LSR 0xfa20f000 +# define THUMB_LSRI 0x0800 +# define THUMB2_LSRI 0xea4f0010 +# define ARM_ASR 0x00000040 +# define THUMB_ASR 0x4100 +# define THUMB2_ASR 0xfa40f000 +# define THUMB_ASRI 0x1000 +# define THUMB2_ASRI 0xea4f0020 +# define ARM_ROR 0x00000060 +# define ARM_CMP 0x01500000 +# define THUMB_CMP 0x4280 +# define THUMB_CMPX 0x4500 +# define THUMB2_CMP 0xebb00000 +# define THUMB_CMPI 0x2800 +# define THUMB2_CMPI 0xf1b00000 +# define ARM_CMN 0x01700000 +# define THUMB_CMN 0x42c0 +# define THUMB2_CMN 0xeb100000 +# define THUMB2_CMNI 0xf1100000 +# define ARM_TST 0x01100000 +# define THUMB_TST 0x4200 +# define THUMB2_TST 0xea100000 +# define THUMB2_TSTI 0xf0100000 +# define ARM_TEQ 0x01300000 /* branch */ -# define ARM_BX 0x012fff10 -# define ARM_BLX 0x012fff30 -# define THUMB_BLX 0x4780 -# define ARM_BLXI 0xfa000000 -# define THUMB2_BLXI 0xf000c000 -# define ARM_B 0x0a000000 -# define THUMB_CC_B 0xd000 -# define THUMB_B 0xe000 -# define THUMB2_CC_B 0xf0008000 -# define THUMB2_B 0xf0009000 -# define ARM_BLI 0x0b000000 -# define THUMB2_BLI 0xf000d000 +# define ARM_BX 0x012fff10 +# define ARM_BLX 0x012fff30 +# define THUMB_BLX 0x4780 +# define ARM_BLXI 0xfa000000 +# define THUMB2_BLXI 0xf000c000 +# define ARM_B 0x0a000000 +# define THUMB_CC_B 0xd000 +# define THUMB_B 0xe000 +# define THUMB2_CC_B 0xf0008000 +# define THUMB2_B 0xf0009000 +# define ARM_BLI 0x0b000000 +# define THUMB2_BLI 0xf000d000 /* ldr/str */ -# define ARM_P 0x00800000 /* positive offset */ -# define THUMB2_P 0x00000400 -# define THUMB2_U 0x00000200 -# define THUMB2_W 0x00000100 -# define ARM_LDRSB 0x011000d0 -# define THUMB_LDRSB 0x5600 -# define THUMB2_LDRSB 0xf9100000 -# define ARM_LDRSBI 0x015000d0 -# define THUMB2_LDRSBI 0xf9100c00 -# define THUMB2_LDRSBWI 0xf9900000 -# define ARM_LDRB 0x07500000 -# define THUMB_LDRB 0x5c00 -# define THUMB2_LDRB 0xf8100000 -# define ARM_LDRBI 0x05500000 -# define THUMB_LDRBI 0x7800 -# define THUMB2_LDRBI 0xf8100c00 -# define THUMB2_LDRBWI 0xf8900000 -# define ARM_LDRSH 0x011000f0 -# define THUMB_LDRSH 0x5e00 -# define THUMB2_LDRSH 0xf9300000 -# define ARM_LDRSHI 0x015000f0 -# define THUMB2_LDRSHI 0xf9300c00 -# define THUMB2_LDRSHWI 0xf9b00000 -# define ARM_LDRH 0x011000b0 -# define THUMB_LDRH 0x5a00 -# define THUMB2_LDRH 0xf8300000 -# define ARM_LDRHI 0x015000b0 -# define THUMB_LDRHI 0x8800 -# define THUMB2_LDRHI 0xf8300c00 -# define THUMB2_LDRHWI 0xf8b00000 -# define ARM_LDR 0x07100000 -# define THUMB_LDR 0x5800 -# define THUMB2_LDR 0xf8500000 -# define ARM_LDRI 0x05100000 -# define THUMB_LDRI 0x6800 -# define THUMB_LDRISP 0x9800 -# define THUMB2_LDRI 0xf8500c00 -# define THUMB2_LDRWI 0xf8d00000 -# define ARM_LDRD 0x010000d0 -# define ARM_LDRDI 0x014000d0 -# define THUMB2_LDRDI 0xe8500000 -# define ARM_STRB 0x07400000 -# define THUMB_STRB 0x5400 -# define THUMB2_STRB 0xf8000000 -# define ARM_STRBI 0x05400000 -# define THUMB_STRBI 0x7000 -# define THUMB2_STRBI 0xf8000c00 -# define THUMB2_STRBWI 0xf8800000 -# define ARM_STRH 0x010000b0 -# define THUMB_STRH 0x5200 -# define THUMB2_STRH 0xf8200000 -# define ARM_STRHI 0x014000b0 -# define THUMB_STRHI 0x8000 -# define THUMB2_STRHI 0xf8200c00 -# define THUMB2_STRHWI 0xf8a00000 -# define ARM_STR 0x07000000 -# define THUMB_STR 0x5000 -# define THUMB2_STR 0xf8400000 -# define ARM_STRI 0x05000000 -# define THUMB_STRI 0x6000 -# define THUMB2_STRWI 0xf8c00000 -# define THUMB_STRISP 0x9000 -# define THUMB2_STRI 0xf8400c00 -# define ARM_STRD 0x010000f0 -# define ARM_STRDI 0x014000f0 -# define THUMB2_STRDI 0xe8400000 +# define ARM_P 0x00800000 /* positive offset */ +# define THUMB2_P 0x00000400 +# define THUMB2_U 0x00000200 +# define THUMB2_W 0x00000100 +# define ARM_LDRSB 0x011000d0 +# define THUMB_LDRSB 0x5600 +# define THUMB2_LDRSB 0xf9100000 +# define ARM_LDRSBI 0x015000d0 +# define THUMB2_LDRSBI 0xf9100c00 +# define THUMB2_LDRSBWI 0xf9900000 +# define ARM_LDRB 0x07500000 +# define THUMB_LDRB 0x5c00 +# define THUMB2_LDRB 0xf8100000 +# define ARM_LDRBI 0x05500000 +# define THUMB_LDRBI 0x7800 +# define THUMB2_LDRBI 0xf8100c00 +# define THUMB2_LDRBWI 0xf8900000 +# define ARM_LDRSH 0x011000f0 +# define THUMB_LDRSH 0x5e00 +# define THUMB2_LDRSH 0xf9300000 +# define ARM_LDRSHI 0x015000f0 +# define THUMB2_LDRSHI 0xf9300c00 +# define THUMB2_LDRSHWI 0xf9b00000 +# define ARM_LDRH 0x011000b0 +# define THUMB_LDRH 0x5a00 +# define THUMB2_LDRH 0xf8300000 +# define ARM_LDRHI 0x015000b0 +# define THUMB_LDRHI 0x8800 +# define THUMB2_LDRHI 0xf8300c00 +# define THUMB2_LDRHWI 0xf8b00000 +# define ARM_LDR 0x07100000 +# define THUMB_LDR 0x5800 +# define THUMB2_LDR 0xf8500000 +# define ARM_LDRI 0x05100000 +# define THUMB_LDRI 0x6800 +# define THUMB_LDRISP 0x9800 +# define THUMB2_LDRI 0xf8500c00 +# define THUMB2_LDRWI 0xf8d00000 +# define ARM_LDRD 0x010000d0 +# define ARM_LDRDI 0x014000d0 +# define THUMB2_LDRDI 0xe8500000 +# define ARM_STRB 0x07400000 +# define THUMB_STRB 0x5400 +# define THUMB2_STRB 0xf8000000 +# define ARM_STRBI 0x05400000 +# define THUMB_STRBI 0x7000 +# define THUMB2_STRBI 0xf8000c00 +# define THUMB2_STRBWI 0xf8800000 +# define ARM_STRH 0x010000b0 +# define THUMB_STRH 0x5200 +# define THUMB2_STRH 0xf8200000 +# define ARM_STRHI 0x014000b0 +# define THUMB_STRHI 0x8000 +# define THUMB2_STRHI 0xf8200c00 +# define THUMB2_STRHWI 0xf8a00000 +# define ARM_STR 0x07000000 +# define THUMB_STR 0x5000 +# define THUMB2_STR 0xf8400000 +# define ARM_STRI 0x05000000 +# define THUMB_STRI 0x6000 +# define THUMB2_STRWI 0xf8c00000 +# define THUMB_STRISP 0x9000 +# define THUMB2_STRI 0xf8400c00 +# define ARM_STRD 0x010000f0 +# define ARM_STRDI 0x014000f0 +# define THUMB2_STRDI 0xe8400000 /* ldm/stm */ -# define ARM_M 0x08000000 -# define ARM_M_L 0x00100000 /* load; store if not set */ -# define ARM_M_I 0x00800000 /* inc; dec if not set */ -# define ARM_M_B 0x01000000 /* before; after if not set */ -# define ARM_M_U 0x00200000 /* update Rn */ -# define THUMB2_LDM_W 0x00200000 -# define THUMB2_LDM_P 0x00008000 -# define THUMB2_LDM_M 0x00004000 -# define THUMB_LDMIA 0xc800 -# define THUMB2_LDMIA 0xe8900000 -# define THUMB2_LDMB 0xe9100000 -# define THUMB_PUSH 0xb400 -# define THUMB2_PUSH 0xe92d0000 -# define THUMB_POP 0xbc00 -# define THUMB2_POP 0xe8bd0000 -# define ii(i) *_jit->pc.ui++ = i -# define is(i) *_jit->pc.us++ = i +# define ARM_M 0x08000000 +# define ARM_M_L 0x00100000 /* load; store if not set */ +# define ARM_M_I 0x00800000 /* inc; dec if not set */ +# define ARM_M_B 0x01000000 /* before; after if not set */ +# define ARM_M_U 0x00200000 /* update Rn */ +# define THUMB2_LDM_W 0x00200000 +# define THUMB2_LDM_P 0x00008000 +# define THUMB2_LDM_M 0x00004000 +# define THUMB_LDMIA 0xc800 +# define THUMB2_LDMIA 0xe8900000 +# define THUMB2_LDMB 0xe9100000 +# define THUMB_PUSH 0xb400 +# define THUMB2_PUSH 0xe92d0000 +# define THUMB_POP 0xbc00 +# define THUMB2_POP 0xe8bd0000 +# define ii(i) *_jit->pc.ui++ = i +# define is(i) *_jit->pc.us++ = i # if __BYTE_ORDER == __LITTLE_ENDIAN -# define iss(i, j) do { is(j); is(i); } while (0) -# define code2thumb(t0, t1, c0, c1) do { t1 = c0; t0 = c1; } while (0) -# define thumb2code(t0, t1, c0, c1) do { c0 = t1; c1 = t0; } while (0) +# define iss(i, j) do { is(j); is(i); } while (0) +# define code2thumb(t0, t1, c0, c1) do { t1 = c0; t0 = c1; } while (0) +# define thumb2code(t0, t1, c0, c1) do { c0 = t1; c1 = t0; } while (0) # else -# define iss(i, j) do { is(i); is(j); } while (0) -# define code2thumb(t0, t1, c0, c1) do { t0 = c0; t1 = c1; } while (0) -# define thumb2code(t0, t1, c0, c1) do { c0 = t0; c1 = t1; } while (0) +# define iss(i, j) do { is(i); is(j); } while (0) +# define code2thumb(t0, t1, c0, c1) do { t0 = c0; t1 = c1; } while (0) +# define thumb2code(t0, t1, c0, c1) do { c0 = t0; c1 = t1; } while (0) # endif static int encode_arm_immediate(unsigned int v); static int encode_thumb_immediate(unsigned int v); @@ -326,817 +315,817 @@ static int encode_thumb_word_immediate(unsigned int v); static int encode_thumb_jump(int v); static int encode_thumb_cc_jump(int v); static int encode_thumb_shift(int v, int type) maybe_unused; -# define corrr(cc,o,rn,rd,rm) _corrr(_jit,cc,o,rn,rd,rm) +# define corrr(cc,o,rn,rd,rm) _corrr(_jit,cc,o,rn,rd,rm) static void _corrr(jit_state_t*,int,int,int,int,int); -# define corri(cc,o,rn,rd,im) _corri(_jit,cc,o,rn,rd,im) +# define corri(cc,o,rn,rd,im) _corri(_jit,cc,o,rn,rd,im) static void _corri(jit_state_t*,int,int,int,int,int); -#define corri8(cc,o,rn,rt,im) _corri8(_jit,cc,o,rn,rt,im) +#define corri8(cc,o,rn,rt,im) _corri8(_jit,cc,o,rn,rt,im) static void _corri8(jit_state_t*,int,int,int,int,int); -# define torrr(o,rn,rd,rm) _torrr(_jit,o,rn,rd,rm) +# define torrr(o,rn,rd,rm) _torrr(_jit,o,rn,rd,rm) static void _torrr(jit_state_t*,int,int,int,int); -# define torrrs(o,rn,rd,rm,im) _torrrs(_jit,o,rn,rd,rm,im) +# define torrrs(o,rn,rd,rm,im) _torrrs(_jit,o,rn,rd,rm,im) static void _torrrs(jit_state_t*,int,int,int,int,int) maybe_unused; -# define torxr(o,rn,rt,rm) _torxr(_jit,o,rn,rt,rm) +# define torxr(o,rn,rt,rm) _torxr(_jit,o,rn,rt,rm) static void _torxr(jit_state_t*,int,int,int,int); -# define torrrr(o,rn,rl,rh,rm) _torrrr(_jit,o,rn,rl,rh,rm) +# define torrrr(o,rn,rl,rh,rm) _torrrr(_jit,o,rn,rl,rh,rm) static void _torrrr(jit_state_t*,int,int,int,int,int) maybe_unused; -# define torrri8(o,rn,rt,rt2,im) _torrri8(_jit,o,rn,rt,rt2,im) +# define torrri8(o,rn,rt,rt2,im) _torrri8(_jit,o,rn,rt,rt2,im) static void _torrri8(jit_state_t*,int,int,int,int,int) maybe_unused; -# define coriw(cc,o,rd,im) _coriw(_jit,cc,o,rd,im) +# define coriw(cc,o,rd,im) _coriw(_jit,cc,o,rd,im) static void _coriw(jit_state_t*,int,int,int,int); -# define torri(o,rd,rn,im) _torri(_jit,o,rd,rn,im) +# define torri(o,rd,rn,im) _torri(_jit,o,rd,rn,im) static void _torri(jit_state_t*,int,int,int,int); -# define torri8(o,rn,rt,im) _torri8(_jit,o,rn,rt,im) +# define torri8(o,rn,rt,im) _torri8(_jit,o,rn,rt,im) static void _torri8(jit_state_t*,int,int,int,int); -# define torri12(o,rn,rt,im) _torri12(_jit,o,rn,rt,im) +# define torri12(o,rn,rt,im) _torri12(_jit,o,rn,rt,im) static void _torri12(jit_state_t*,int,int,int,int); -# define tshift(o,rd,rm,im) _tshift(_jit,o,rd,rm,im) +# define tshift(o,rd,rm,im) _tshift(_jit,o,rd,rm,im) static void _tshift(jit_state_t*,int,int,int,int); -# define toriw(o,rd,im) _toriw(_jit,o,rd,im) +# define toriw(o,rd,im) _toriw(_jit,o,rd,im) static void _toriw(jit_state_t*,int,int,int); -# define tc8(cc,im) _tc8(_jit,cc,im) +# define tc8(cc,im) _tc8(_jit,cc,im) static void _tc8(jit_state_t*,int,int) maybe_unused; -# define t11(im) _t11(_jit,im) +# define t11(im) _t11(_jit,im) static void _t11(jit_state_t*,int); -# define tcb(cc,im) _tcb(_jit,cc,im) +# define tcb(cc,im) _tcb(_jit,cc,im) static void _tcb(jit_state_t*,int,int); -# define blxi(im) _blxi(_jit,im) +# define blxi(im) _blxi(_jit,im) static void _blxi(jit_state_t*,int) maybe_unused; -# define tb(o,im) _tb(_jit,o,im) +# define tb(o,im) _tb(_jit,o,im) static void _tb(jit_state_t*,int,int); -# define corrrr(cc,o,rh,rl,rm,rn) _corrrr(_jit,cc,o,rh,rl,rm,rn) +# define corrrr(cc,o,rh,rl,rm,rn) _corrrr(_jit,cc,o,rh,rl,rm,rn) static void _corrrr(jit_state_t*,int,int,int,int,int,int); -# define corrrs(cc,o,rn,rd,rm,im) _corrrs(_jit,cc,o,rn,rd,rm,im) +# define corrrs(cc,o,rn,rd,rm,im) _corrrs(_jit,cc,o,rn,rd,rm,im) static void _corrrs(jit_state_t*,int,int,int,int,int,int); -# define cshift(cc,o,rd,rm,rn,im) _cshift(_jit,cc,o,rd,rm,rn,im) +# define cshift(cc,o,rd,rm,rn,im) _cshift(_jit,cc,o,rd,rm,rn,im) static void _cshift(jit_state_t*,int,int,int,int,int,int); -# define cb(cc,o,im) _cb(_jit,cc,o,im) +# define cb(cc,o,im) _cb(_jit,cc,o,im) static void _cb(jit_state_t*,int,int,int); -# define cbx(cc,o,rm) _cbx(_jit,cc,o,rm) +# define cbx(cc,o,rm) _cbx(_jit,cc,o,rm) static void _cbx(jit_state_t*,int,int,int); -# define corl(cc,o,r0,i0) _corl(_jit,cc,o,r0,i0) +# define corl(cc,o,r0,i0) _corl(_jit,cc,o,r0,i0) static void _corl(jit_state_t*,int,int,int,int); -# define c6orr(cc,o,r0,r1) _c6orr(_jit,cc,o,r0,r1) +# define c6orr(cc,o,r0,r1) _c6orr(_jit,cc,o,r0,r1) static void _c6orr(jit_state_t*,int,int,int,int); -# define tcit(cc,it) _tcit(_jit,cc,it) +# define tcit(cc,it) _tcit(_jit,cc,it) static void _tcit(jit_state_t*,unsigned int,int); -# define IT(cc) tcit(cc,THUMB2_IT) -# define ITT(cc) tcit(cc,THUMB2_ITT) -# define ITE(cc) tcit(cc,THUMB2_ITE) -# define ITTT(cc) tcit(cc,THUMB2_ITTT) -# define ITTE(cc) tcit(cc,THUMB2_ITTE) -# define ITET(cc) tcit(cc,THUMB2_ITET) -# define ITEE(cc) tcit(cc,THUMB2_ITEE) -# define ITTTT(cc) tcit(cc,THUMB2_ITTTT) -# define ITETT(cc) tcit(cc,THUMB2_ITETT) -# define ITTET(cc) tcit(cc,THUMB2_ITTET) -# define ITEET(cc) tcit(cc,THUMB2_ITEET) -# define ITTTE(cc) tcit(cc,THUMB2_ITTTE) -# define ITETE(cc) tcit(cc,THUMB2_ITETE) -# define ITTEE(cc) tcit(cc,THUMB2_ITTEE) -# define ITEEE(cc) tcit(cc,THUMB2_ITEEE) -# define tpp(o,im) _tpp(_jit,o,im) +# define IT(cc) tcit(cc,THUMB2_IT) +# define ITT(cc) tcit(cc,THUMB2_ITT) +# define ITE(cc) tcit(cc,THUMB2_ITE) +# define ITTT(cc) tcit(cc,THUMB2_ITTT) +# define ITTE(cc) tcit(cc,THUMB2_ITTE) +# define ITET(cc) tcit(cc,THUMB2_ITET) +# define ITEE(cc) tcit(cc,THUMB2_ITEE) +# define ITTTT(cc) tcit(cc,THUMB2_ITTTT) +# define ITETT(cc) tcit(cc,THUMB2_ITETT) +# define ITTET(cc) tcit(cc,THUMB2_ITTET) +# define ITEET(cc) tcit(cc,THUMB2_ITEET) +# define ITTTE(cc) tcit(cc,THUMB2_ITTTE) +# define ITETE(cc) tcit(cc,THUMB2_ITETE) +# define ITTEE(cc) tcit(cc,THUMB2_ITTEE) +# define ITEEE(cc) tcit(cc,THUMB2_ITEEE) +# define tpp(o,im) _tpp(_jit,o,im) static void _tpp(jit_state_t*,int,int); -# define torl(o,rn,im) _torl(_jit,o,rn,im) +# define torl(o,rn,im) _torl(_jit,o,rn,im) static void _torl(jit_state_t*,int,int,int) maybe_unused; -# define CC_MOV(cc,rd,rm) corrr(cc,ARM_MOV,0,rd,rm) -# define MOV(rd,rm) CC_MOV(ARM_CC_AL,rd,rm) -# define T1_MOV(rd,rm) is(THUMB_MOV|((_u4(rd)&8)<<4)|(_u4(rm)<<3)|(rd&7)) -# define T2_MOV(rd,rm) T2_ORR(rd,_R15_REGNO,rm) -# define CC_MOVI(cc,rd,im) corri(cc,ARM_MOV|ARM_I,0,rd,im) -# define MOVI(rd,im) CC_MOVI(ARM_CC_AL,rd,im) -# define CC_MOVWI(cc,rd,im) coriw(cc,ARM_MOVWI,rd,im) -# define MOVWI(rd,im) CC_MOVWI(ARM_CC_AL,rd,im) -# define T1_MOVI(rd,im) is(THUMB_MOVI|(_u3(rd)<<8)|_u8(im)) -# define T2_MOVI(rd,im) torri(THUMB2_MOVI,_R15_REGNO,rd,im) -# define T2_MOVWI(rd,im) toriw(THUMB2_MOVWI,rd,im) -# define CC_MOVTI(cc,rd,im) coriw(cc,ARM_MOVTI,rd,im) -# define MOVTI(rd,im) CC_MOVTI(ARM_CC_AL,rd,im) -# define T2_MOVTI(rd,im) toriw(THUMB2_MOVTI,rd,im) -# define CC_MVN(cc,rd,rm) corrr(cc,ARM_MVN,0,rd,rm) -# define MVN(rd,rm) CC_MVN(ARM_CC_AL,rd,rm) -# define T1_MVN(rd,rm) is(THUMB_MVN|(_u3(rm)<<3)|_u3(rd)) -# define T2_MVN(rd,rm) torrr(THUMB2_MVN,_R15_REGNO,rd,rm) -# define CC_MVNI(cc,rd,im) corri(cc,ARM_MVN|ARM_I,0,rd,im) -# define MVNI(rd,im) CC_MVNI(ARM_CC_AL,rd,im) -# define T2_MVNI(rd,im) torri(THUMB2_MVNI,_R15_REGNO,rd,im) -# define CC_NOT(cc,rd,rm) CC_MVN(cc,rd,rm) -# define NOT(rd,rm) CC_NOT(ARM_CC_AL,rd,rm) -# define T1_NOT(rd,rm) T1_MVN(rd,rm) -# define T2_NOT(rd,rm) T2_MVN(rd,rm) -# define NOP() MOV(_R0_REGNO, _R0_REGNO) -# define T1_NOP() is(0xbf00) -# define CC_ADD(cc,rd,rn,rm) corrr(cc,ARM_ADD,rn,rd,rm) -# define ADD(rd,rn,rm) CC_ADD(ARM_CC_AL,rd,rn,rm) -# define T1_ADD(rd,rn,rm) is(THUMB_ADD|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rd)) -# define T1_ADDX(rdn,rm) is(THUMB_ADDX|((_u4(rdn)&8)<<4)|(_u4(rm)<<3)|(rdn&7)) -# define T2_ADD(rd,rn,rm) torrr(THUMB2_ADD,rn,rd,rm) -# define CC_ADDI(cc,rd,rn,im) corri(cc,ARM_ADD|ARM_I,rn,rd,im) -# define ADDI(rd,rn,im) CC_ADDI(ARM_CC_AL,rd,rn,im) -# define T1_ADDI3(rd,rn,im) is(THUMB_ADDI3|(_u3(im)<<6)|(_u3(rn)<<3)|_u3(rd)) -# define T1_ADDI8(rdn,im) is(THUMB_ADDI8|(_u3(rdn)<<8)|_u8(im)) -# define T2_ADDI(rd,rn,im) torri(THUMB2_ADDI,rn,rd,im) -# define T2_ADDWI(rd,rn,im) torri(THUMB2_ADDWI,rn,rd,im) -# define CC_ADDS(cc,rd,rn,rm) corrr(cc,ARM_ADD|ARM_S,rn,rd,rm) -# define ADDS(rd,rn,rm) CC_ADDS(ARM_CC_AL,rd,rn,rm) -# define T2_ADDS(rd,rn,rm) torrr(THUMB2_ADD|ARM_S,rn,rd,rm) -# define ADDSI(rd,rn,im) corri(ARM_CC_AL,ARM_ADD|ARM_S|ARM_I,rn,rd,im) -# define T2_ADDSI(rd,rn,im) torri(THUMB2_ADDI|ARM_S,rn,rd,im) -# define CC_ADC(cc,rd,rn,rm) corrr(cc,ARM_ADC,rn,rd,rm) -# define ADC(rd,rn,rm) CC_ADC(ARM_CC_AL,rd,rn,rm) -# define T1_ADC(rdn,rm) is(THUMB_ADC|(_u3(rm)<<3)|_u3(rdn)) -# define T2_ADC(rd,rn,rm) torrr(THUMB2_ADC,rn,rd,rm) -# define CC_ADCI(cc,rd,rn,im) corri(cc,ARM_ADC|ARM_I,rn,rd,im) -# define ADCI(rd,rn,im) CC_ADCI(ARM_CC_AL,rd,rn,im) -# define T2_ADCI(rd,rn,im) torri(THUMB2_ADCI,rn,rd,im) -# define CC_ADCS(cc,rd,rn,rm) corrr(cc,ARM_ADC|ARM_S,rn,rd,rm) -# define ADCS(rd,rn,rm) CC_ADCS(ARM_CC_AL,rd,rn,rm) -# define T2_ADCS(rd,rn,rm) torrr(THUMB2_ADC|ARM_S,rn,rd,rm) -# define CC_ADCSI(cc,rd,rn,im) corri(cc,ARM_ADC|ARM_S|ARM_I,rn,rd,im) -# define ADCSI(rd,rn,im) CC_ADCSI(ARM_CC_AL,rd,rn,im) -# define T2_ADCSI(rd,rn,im) torri(THUMB2_ADCI|ARM_S,rn,rd,im) -# define CC_SUB(cc,rd,rn,rm) corrr(cc,ARM_SUB,rn,rd,rm) -# define SUB(rd,rn,rm) CC_SUB(ARM_CC_AL,rd,rn,rm) -# define T1_SUB(rd,rn,rm) is(THUMB_SUB|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rd)) -# define T2_SUB(rd,rn,rm) torrr(THUMB2_SUB,rn,rd,rm) -# define CC_SUBI(cc,rd,rn,im) corri(cc,ARM_SUB|ARM_I,rn,rd,im) -# define SUBI(rd,rn,im) CC_SUBI(ARM_CC_AL,rd,rn,im) -# define T1_SUBI3(rd,rn,im) is(THUMB_SUBI3|(_u3(im)<<6)|(_u3(rn)<<3)|_u3(rd)) -# define T1_SUBI8(rdn,im) is(THUMB_SUBI8|(_u3(rdn)<<8)|_u8(im)) -# define T2_SUBI(rd,rn,im) torri(THUMB2_SUBI,rn,rd,im) -# define T2_SUBWI(rd,rn,im) torri(THUMB2_SUBWI,rn,rd,im) -# define CC_SUBS(cc,rd,rn,rm) corrr(cc,ARM_SUB|ARM_S,rn,rd,rm) -# define SUBS(rd,rn,rm) CC_SUBS(ARM_CC_AL,rd,rn,rm) -# define T2_SUBS(rd,rn,rm) torrr(THUMB2_SUB|ARM_S,rn,rd,rm) -# define CC_SUBSI(cc,rd,rn,im) corri(cc,ARM_SUB|ARM_S|ARM_I,rn,rd,im) -# define SUBSI(rd,rn,im) CC_SUBSI(ARM_CC_AL,rd,rn,im) -# define T2_SUBSI(rd,rn,im) torri(THUMB2_SUBI|ARM_S,rn,rd,im) -# define CC_SBC(cc,rd,rn,rm) corrr(cc,ARM_SBC,rn,rd,rm) -# define SBC(rd,rn,rm) CC_SBC(ARM_CC_AL,rd,rn,rm) -# define T1_SBC(rdn,rm) is(THUMB_SBC|(_u3(rm)<<3)|_u3(rdn)) -# define T2_SBC(rd,rn,rm) torrr(THUMB2_SBC,rn,rd,rm) -# define CC_SBCI(cc,rd,rn,im) corri(cc,ARM_SBC|ARM_I,rn,rd,im) -# define SBCI(rd,rn,im) CC_SBCI(ARM_CC_AL,rd,rn,im) -# define T2_SBCI(rd,rn,im) torri(THUMB2_SBCI,rn,rd,im) -# define CC_SBCS(cc,rd,rn,rm) corrr(cc,ARM_SBC|ARM_S,rn,rd,rm) -# define SBCS(rd,rn,rm) CC_SBCS(ARM_CC_AL,rd,rn,rm) -# define T2_SBCS(rd,rn,rm) torrr(THUMB2_SBC|ARM_S,rn,rd,rm) -# define CC_SBCSI(cc,rd,rn,im) corri(cc,ARM_SBC|ARM_S|ARM_I,rn,rd,im) -# define SBCSI(rd,rn,im) CC_SBCSI(ARM_CC_AL,rd,rn,im) -# define T2_SBCSI(rd,rn,im) torri(THUMB2_SBCI|ARM_S,rn,rd,im) -# define CC_RSB(cc,rd,rn,rm) corrr(cc,ARM_RSB,rn,rd,rm) -# define RSB(rd,rn,rm) CC_RSB(ARM_CC_AL,rd,rn,rm) -# define T2_RSB(rd,rn,rm) torrr(THUMB2_RSB,rn,rd,rm) -# define CC_RSBI(cc,rd,rn,im) corri(cc,ARM_RSB|ARM_I,rn,rd,im) -# define RSBI(rd,rn,im) CC_RSBI(ARM_CC_AL,rd,rn,im) -# define T1_RSBI(rd,rn) is(THUMB_RSBI|(_u3(rn)<<3)|_u3(rd)) -# define T2_RSBI(rd,rn,im) torri(THUMB2_RSBI,rn,rd,im) -# define CC_MUL(cc,rl,rn,rm) corrrr(cc,ARM_MUL,rl,0,rm,rn) -# define MUL(rl,rn,rm) CC_MUL(ARM_CC_AL,rl,rn,rm) -# define T1_MUL(rdm,rn) is(THUMB_MUL|(_u3(rn)<<3)|_u3(rdm)) -# define T2_MUL(rd,rn,rm) torrr(THUMB2_MUL,rn,rd,rm) -# define CC_SMULL(cc,rl,rh,rn,rm) corrrr(cc,ARM_SMULL,rh,rl,rm,rn) -# define SMULL(rl,rh,rn,rm) CC_SMULL(ARM_CC_AL,rl,rh,rn,rm) -# define T2_SMULL(rl,rh,rn,rm) torrrr(THUMB2_SMULL,rn,rl,rh,rm) -# define CC_UMULL(cc,rl,rh,rn,rm) corrrr(cc,ARM_UMULL,rh,rl,rm,rn) -# define UMULL(rl,rh,rn,rm) CC_UMULL(ARM_CC_AL,rl,rh,rn,rm) -# define T2_UMULL(rl,rh,rn,rm) torrrr(THUMB2_UMULL,rn,rl,rh,rm) -# define T2_SDIV(rd,rn,rm) torrr(THUMB2_SDIV,rn,rd,rm) -# define T2_UDIV(rd,rn,rm) torrr(THUMB2_UDIV,rn,rd,rm) -# define CC_AND(cc,rd,rn,rm) corrr(cc,ARM_AND,rn,rd,rm) -# define AND(rd,rn,rm) CC_AND(ARM_CC_AL,rd,rn,rm) -# define T1_AND(rdn,rm) is(THUMB_AND|(_u3(rm)<<3)|_u3(rdn)) -# define T2_AND(rd,rn,rm) torrr(THUMB2_AND,rn,rd,rm) -# define CC_ANDI(cc,rd,rn,im) corri(cc,ARM_AND|ARM_I,rn,rd,im) -# define ANDI(rd,rn,im) CC_ANDI(ARM_CC_AL,rd,rn,im) -# define T2_ANDI(rd,rn,im) torri(THUMB2_ANDI,rn,rd,im) -# define CC_ANDS(cc,rd,rn,rm) corrr(cc,ARM_AND|ARM_S,rn,rd,rm) -# define ANDS(rd,rn,rm) CC_ANDS(ARM_CC_AL,rd,rn,rm) -# define T2_ANDS(rd,rn,rm) torrr(THUMB2_AND|ARM_S,rn,rd,rm) -# define CC_ANDSI(cc,rd,rn,im) corri(cc,ARM_AND|ARM_S|ARM_I,rn,rd,im) -# define ANDSI(rd,rn,im) CC_ANDSI(ARM_CC_AL,rd,rn,im) -# define T2_ANDSI(rd,rn,im) torri(ARM_CC_AL,THUMB2_ANDI|ARM_S,rn,rd,im) -# define CC_BIC(cc,rd,rn,rm) corrr(cc,ARM_BIC,rn,rd,rm) -# define BIC(rd,rn,rm) CC_BIC(ARM_CC_AL,rd,rn,rm) -# define T2_BIC(rd,rn,rm) torrr(THUMB2_BIC,rn,rd,rm) -# define CC_BICI(cc,rd,rn,im) corri(cc,ARM_BIC|ARM_I,rn,rd,im) -# define BICI(rd,rn,im) CC_BICI(ARM_CC_AL,rd,rn,im) -# define T2_BICI(rd,rn,im) torri(THUMB2_BICI,rn,rd,im) -# define CC_BICS(cc,rd,rn,rm) corrr(cc,ARM_BIC|ARM_S,rn,rd,rm) -# define BICS(rd,rn,rm) CC_BICS(ARM_CC_AL,rd,rn,rm) -# define T2_BICS(rd,rn,rm) torrr(THUMB2_BIC|ARM_S,rn,rd,rm) -# define CC_BICSI(cc,rd,rn,im) corri(cc,ARM_BIC|ARM_S|ARM_I,rn,rd,im) -# define BICSI(rd,rn,im) CC_BICSI(ARM_CC_AL,rd,rn,im) -# define T2_BICSI(rd,rn,im) torri(ARM_CC_AL,THUMB2_BICI|ARM_S,rn,rd,im) -# define CC_ORR(cc,rd,rn,rm) corrr(cc,ARM_ORR,rn,rd,rm) -# define ORR(rd,rn,rm) CC_ORR(ARM_CC_AL,rd,rn,rm) -# define T1_ORR(rdn,rm) is(THUMB_ORR|(_u3(rm)<<3)|_u3(rdn)) -# define T2_ORR(rd,rn,rm) torrr(THUMB2_ORR,rn,rd,rm) -# define CC_ORR_SI(cc,rd,rn,rt,sh,im) corrrs(cc,ARM_ORR|sh,rn,rd,rm,im) -# define ORR_SI(r0,r1,r2,sh,im) CC_ORR_SI(ARM_CC_AL,r0,r1,r2,sh,im) -# define CC_ORRI(cc,rd,rn,im) corri(cc,ARM_ORR|ARM_I,rn,rd,im) -# define ORRI(rd,rn,im) CC_ORRI(ARM_CC_AL,rd,rn,im) -# define T2_ORRI(rd,rn,im) torri(THUMB2_ORRI,rn,rd,im) -# define CC_EOR(cc,rd,rn,rm) corrr(cc,ARM_EOR,rn,rd,rm) -# define EOR(rd,rn,rm) CC_EOR(ARM_CC_AL,rd,rn,rm) -# define T1_EOR(rdn,rm) is(THUMB_EOR|(_u3(rm)<<3)|_u3(rdn)) -# define T2_EOR(rd,rn,rm) torrr(THUMB2_EOR,rn,rd,rm) -# define CC_EOR_SI(cc,rd,rn,rm,sh,im) corrrs(cc,ARM_EOR|sh,rn,rd,rm,im) -# define EOR_SI(r0,r1,r2,sh,im) CC_EOR_SI(ARM_CC_AL,r0,r1,r2,sh,im) -# define CC_EORI(cc,rd,rn,im) corri(cc,ARM_EOR|ARM_I,rn,rd,im) -# define EORI(rd,rn,im) CC_EORI(ARM_CC_AL,rd,rn,im) -# define T2_EORI(rd,rn,im) torri(THUMB2_EORI,rn,rd,im) -# define CC_REV(cc,rd,rm) c6orr(cc,ARM_REV,rd,rm) -# define REV(rd,rm) CC_REV(ARM_CC_AL,rd,rm) -# define T1_REV(rd,rm) is(THUMB_REV|(_u3(rm)<<3)|_u3(rd)) -# define T2_REV(rd,rm) torrr(THUMB2_REV,rm,rd,rm) -# define CC_REV16(cc,rd,rm) c6orr(cc,ARM_REV16,rd,rm) -# define REV16(rd,rm) CC_REV16(ARM_CC_AL,rd,rm) -# define T1_REV16(rd,rm) is(THUMB_REV16|(_u3(rm)<<3)|_u3(rd)) -# define T2_REV16(rd,rm) torrr(THUMB2_REV16,rm,rd,rm) -# define CC_SXTB(cc,rd,rm) c6orr(cc,ARM_SXTB,rd,rm) -# define SXTB(rd,rm) CC_SXTB(ARM_CC_AL,rd,rm) -# define T1_SXTB(rd,rm) is(THUMB_SXTB|(_u3(rm)<<3)|_u3(rd)) -# define T2_SXTB(rd,rm) torrr(THUMB2_SXTB,_R15_REGNO,rd,rm) -# define CC_UXTB(cc,rd,rm) c6orr(cc,ARM_UXTB,rd,rm) -# define UXTB(rd,rm) CC_UXTB(ARM_CC_AL,rd,rm) -# define T1_UXTB(rd,rm) is(THUMB_UXTB|(_u3(rm)<<3)|_u3(rd)) -# define T2_UXTB(rd,rm) torrr(THUMB2_UXTB,_R15_REGNO,rd,rm) -# define CC_SXTH(cc,rd,rm) c6orr(cc,ARM_SXTH,rd,rm) -# define SXTH(rd,rm) CC_SXTH(ARM_CC_AL,rd,rm) -# define T1_SXTH(rd,rm) is(THUMB_SXTH|(_u3(rm)<<3)|_u3(rd)) -# define T2_SXTH(rd,rm) torrr(THUMB2_SXTH,_R15_REGNO,rd,rm) -# define CC_UXTH(cc,rd,rm) c6orr(cc,ARM_UXTH,rd,rm) -# define UXTH(rd,rm) CC_UXTH(ARM_CC_AL,rd,rm) -# define T1_UXTH(rd,rm) is(THUMB_UXTH|(_u3(rm)<<3)|_u3(rd)) -# define T2_UXTH(rd,rm) torrr(THUMB2_UXTH,_R15_REGNO,rd,rm) -# define CC_SHIFT(cc,o,rd,rm,rn,im) cshift(cc,o,rd,rm,rn,im) -# define CC_LSL(cc,rd,rn,rm) CC_SHIFT(cc,ARM_LSL|ARM_R,rd,rm,rn,0) -# define LSL(rd,rn,rm) CC_LSL(ARM_CC_AL,rd,rn,rm) -# define T1_LSL(rdn,rm) is(THUMB_LSL|(_u3(rm)<<3)|_u3(rdn)) -# define T2_LSL(rd,rn,rm) torrr(THUMB2_LSL,rn,rd,rm) -# define CC_LSLI(cc,rd,rn,im) CC_SHIFT(cc,ARM_LSL,rd,0,rn,im) -# define LSLI(rd,rn,im) CC_LSLI(ARM_CC_AL,rd,rn,im) -# define T1_LSLI(rd,rm,im) is(THUMB_LSLI|(_u5(im)<<6)|(_u3(rm)<<3)|_u3(rd)) -# define T2_LSLI(rd,rm,im) tshift(THUMB2_LSLI,rd,rm,im) -# define CC_LSR(cc,rd,rn,rm) CC_SHIFT(cc,ARM_LSR|ARM_R,rd,rm,rn,0) -# define LSR(rd,rn,rm) CC_LSR(ARM_CC_AL,rd,rn,rm) -# define T1_LSR(rdn,rm) is(THUMB_LSR|(_u3(rm)<<3)|_u3(rdn)) -# define T2_LSR(rd,rn,rm) torrr(THUMB2_LSR,rn,rd,rm) -# define CC_LSRI(cc,rd,rn,im) CC_SHIFT(cc,ARM_LSR,rd,0,rn,im) -# define LSRI(rd,rn,im) CC_LSRI(ARM_CC_AL,rd,rn,im) -# define T1_LSRI(rd,rm,im) is(THUMB_LSRI|(_u5(im)<<6)|(_u3(rm)<<3)|_u3(rd)) -# define T2_LSRI(rd,rm,im) tshift(THUMB2_LSRI,rd,rm,im) -# define CC_ASR(cc,rd,rn,rm) CC_SHIFT(cc,ARM_ASR|ARM_R,rd,rm,rn,0) -# define ASR(rd,rn,rm) CC_ASR(ARM_CC_AL,rd,rn,rm) -# define T1_ASR(rdn,rm) is(THUMB_ASR|(_u3(rm)<<3)|_u3(rdn)) -# define T2_ASR(rd,rn,rm) torrr(THUMB2_ASR,rn,rd,rm) -# define CC_ASRI(cc,rd,rn,im) CC_SHIFT(cc,ARM_ASR,rd,0,rn,im) -# define ASRI(rd,rn,im) CC_ASRI(ARM_CC_AL,rd,rn,im) -# define T1_ASRI(rd,rm,im) is(THUMB_ASRI|(_u5(im)<<6)|(_u3(rm)<<3)|_u3(rd)) -# define T2_ASRI(rd,rm,im) tshift(THUMB2_ASRI,rd,rm,im) -# define CC_CMP(cc,rn,rm) corrr(cc,ARM_CMP,rn,0,rm) -# define CMP(rn,rm) CC_CMP(ARM_CC_AL,rn,rm) -# define T1_CMP(rn,rm) is(THUMB_CMP|(_u3(rm)<<3)|_u3(rn)) -# define T1_CMPX(rn,rm) is(THUMB_CMPX|((_u4(rn)&8)<<4)|(_u4(rm)<<3)|(rn&7)) -# define T2_CMP(rn,rm) torrr(THUMB2_CMP,rn,_R15_REGNO,rm) -# define CC_CMPI(cc,rn,im) corri(cc,ARM_CMP|ARM_I,rn,0,im) -# define CMPI(rn,im) CC_CMPI(ARM_CC_AL,rn,im) -# define T1_CMPI(rn,im) is(THUMB_CMPI|(_u3(rn)<<8)|_u8(im)) -# define T2_CMPI(rn,im) torri(THUMB2_CMPI,rn,_R15_REGNO,im) -# define CC_CMN(cc,rn,rm) corrr(cc,ARM_CMN,rn,0,rm) -# define CMN(rn,rm) CC_CMN(ARM_CC_AL,rn,rm) -# define T1_CMN(rn,rm) is(THUMB_CMN|(_u3(rm)<<3)|_u3(rm)) -# define T2_CMN(rn,rm) torrr(THUMB2_CMN,rn,_R15_REGNO,rm) -# define CC_CMNI(cc,rn,im) corri(cc,ARM_CMN|ARM_I,rn,0,im) -# define CMNI(rn,im) CC_CMNI(ARM_CC_AL,rn,im) -# define T2_CMNI(rn,im) torri(THUMB2_CMNI,rn,_R15_REGNO,im) -# define CC_TST(cc,rn,rm) corrr(cc,ARM_TST,rn,r0,rm) -# define TST(rn,rm) CC_TST(ARM_CC_AL,rn,rm) -# define T1_TST(rn,rm) is(THUMB_TST|(_u3(rm)<<3)|_u3(rn)) -# define T2_TST(rn,rm) torrr(THUMB2_TST,rn,_R15_REGNO,rm) -# define CC_TSTI(cc,rn,im) corri(cc,ARM_TST|ARM_I,rn,0,im) -# define TSTI(rn,im) CC_TSTI(ARM_CC_AL,rn,im) -# define T2_TSTI(rn,im) torri(THUMB2_TSTI,rn,_R15_REGNO,im) -# define CC_TEQ(cc,rn,rm) corrr(cc,ARM_TEQ,rn,0,rm) -# define TEQ(rn,rm) CC_TEQ(ARM_CC_AL,rn,rm) -# define CC_TEQI(cc,rm,im) corri(cc,ARM_TEQ|ARM_I,rn,0,im) -# define TEQI(rn,im) CC_TEQI(ARM_CC_AL,rn,im) -# define CC_BX(cc,rm) cbx(cc,ARM_BX,rm) -# define BX(rm) CC_BX(ARM_CC_AL,rm) -# define T1_BX(rm) is(0x4700|(_u4(rm)<<3)) -# define CC_BLX(cc,rm) cbx(cc,ARM_BLX,rm) -# define BLX(rm) CC_BLX(ARM_CC_AL,rm) -# define T1_BLX(rm) is(THUMB_BLX|(_u4(rm)<<3)) -# define BLXI(im) blxi(im) -# define T2_BLXI(im) tb(THUMB2_BLXI,im) -# define CC_B(cc,im) cb(cc,ARM_B,im) -# define B(im) CC_B(ARM_CC_AL,im) -# define T1_CC_B(cc,im) tc8(cc,im) -# define T1_B(im) t11(im) -# define T2_CC_B(cc,im) tcb(cc,im) -# define T2_B(im) tb(THUMB2_B,im) -# define CC_BLI(cc,im) cb(cc,ARM_BLI,im) -# define BLI(im) CC_BLI(ARM_CC_AL,im) -# define T2_BLI(im) tb(THUMB2_BLI,im) -# define CC_LDRSB(cc,rt,rn,rm) corrr(cc,ARM_LDRSB|ARM_P,rn,rt,rm) -# define LDRSB(rt,rn,rm) CC_LDRSB(ARM_CC_AL,rt,rn,rm) -# define T1_LDRSB(rt,rn,rm) is(THUMB_LDRSB|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt)) -# define T2_LDRSB(rt,rn,rm) torxr(THUMB2_LDRSB,rn,rt,rm) -# define CC_LDRSBN(cc,rt,rn,rm) corrr(cc,ARM_LDRSB,rn,rt,rm) -# define LDRSBN(rt,rn,rm) CC_LDRSBN(ARM_CC_AL,rt,rn,rm) -# define CC_LDRSBI(cc,rt,rn,im) corri8(cc,ARM_LDRSBI|ARM_P,rn,rt,im) -# define LDRSBI(rt,rn,im) CC_LDRSBI(ARM_CC_AL,rt,rn,im) -# define T2_LDRSBI(rt,rn,im) torri8(THUMB2_LDRSBI|THUMB2_U,rn,rt,im) -# define T2_LDRSBWI(rt,rn,im) torri12(THUMB2_LDRSBWI,rn,rt,im) -# define CC_LDRSBIN(cc,rt,rn,im) corri8(cc,ARM_LDRSBI,rn,rt,im) -# define LDRSBIN(rt,rn,im) CC_LDRSBIN(ARM_CC_AL,rt,rn,im) -# define T2_LDRSBIN(rt,rn,im) torri8(THUMB2_LDRSBI,rn,rt,im) -# define CC_LDRB(cc,rt,rn,rm) corrr(cc,ARM_LDRB|ARM_P,rn,rt,rm) -# define LDRB(rt,rn,rm) CC_LDRB(ARM_CC_AL,rt,rn,rm) -# define T1_LDRB(rt,rn,rm) is(THUMB_LDRB|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt)) -# define T2_LDRB(rt,rn,rm) torxr(THUMB2_LDRB,rn,rt,rm) -# define CC_LDRBN(cc,rt,rn,rm) corrr(cc,ARM_LDRB,rn,rt,rm) -# define LDRBN(rt,rn,rm) CC_LDRBN(ARM_CC_AL,rt,rn,rm) -# define CC_LDRBI(cc,rt,rn,im) corri(cc,ARM_LDRBI|ARM_P,rn,rt,im) -# define LDRBI(rt,rn,im) CC_LDRBI(ARM_CC_AL,rt,rn,im) -# define T1_LDRBI(rt,rn,im) is(THUMB_LDRBI|(_u5(im)<<6)|(_u3(rn)<<3)|_u3(rt)) -# define T2_LDRBI(rt,rn,im) torri8(THUMB2_LDRBI|THUMB2_U,rn,rt,im) -# define T2_LDRBWI(rt,rn,im) torri12(THUMB2_LDRBWI,rn,rt,im) -# define CC_LDRBIN(cc,rt,rn,im) corri(cc,ARM_LDRBI,rn,rt,im) -# define LDRBIN(rt,rn,im) CC_LDRBIN(ARM_CC_AL,rt,rn,im) -# define T2_LDRBIN(rt,rn,im) torri8(THUMB2_LDRBI,rn,rt,im) -# define CC_LDRSH(cc,rt,rn,rm) corrr(cc,ARM_LDRSH|ARM_P,rn,rt,rm) -# define LDRSH(rt,rn,rm) CC_LDRSH(ARM_CC_AL,rt,rn,rm) -# define T1_LDRSH(rt,rn,rm) is(THUMB_LDRSH|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt)) -# define T2_LDRSH(rt,rn,rm) torxr(THUMB2_LDRSH,rn,rt,rm) -# define CC_LDRSHN(cc,rt,rn,rm) corrr(cc,ARM_LDRSH,rn,rt,rm) -# define LDRSHN(rt,rn,rm) CC_LDRSHN(ARM_CC_AL,rt,rn,rm) -# define CC_LDRSHI(cc,rt,rn,im) corri8(cc,ARM_LDRSHI|ARM_P,rn,rt,im) -# define LDRSHI(rt,rn,im) CC_LDRSHI(ARM_CC_AL,rt,rn,im) -# define T2_LDRSHI(rt,rn,im) torri8(THUMB2_LDRSHI|THUMB2_U,rn,rt,im) -# define T2_LDRSHWI(rt,rn,im) torri12(THUMB2_LDRSHWI,rn,rt,im) -# define CC_LDRSHIN(cc,rt,rn,im) corri8(cc,ARM_LDRSHI,rn,rt,im) -# define LDRSHIN(rt,rn,im) CC_LDRSHIN(ARM_CC_AL,rt,rn,im) -# define T2_LDRSHIN(rt,rn,im) torri8(THUMB2_LDRSHI,rn,rt,im) -# define CC_LDRH(cc,rt,rn,rm) corrr(cc,ARM_LDRH|ARM_P,rn,rt,rm) -# define LDRH(rt,rn,rm) CC_LDRH(ARM_CC_AL,rt,rn,rm) -# define T1_LDRH(rt,rn,rm) is(THUMB_LDRH|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt)) -# define T2_LDRH(rt,rn,rm) torxr(THUMB2_LDRH,rn,rt,rm) -# define CC_LDRHN(cc,rt,rn,rm) corrr(cc,ARM_LDRH,rn,rt,rm) -# define LDRHN(rt,rn,rm) CC_LDRHN(ARM_CC_AL,rt,rn,rm) -# define CC_LDRHI(cc,rt,rn,im) corri8(cc,ARM_LDRHI|ARM_P,rn,rt,im) -# define LDRHI(rt,rn,im) CC_LDRHI(ARM_CC_AL,rt,rn,im) -# define T1_LDRHI(rt,rn,im) is(THUMB_LDRHI|(_u5(im)<<6)|(_u3(rn)<<3)|_u3(rt)) -# define T2_LDRHI(rt,rn,im) torri8(THUMB2_LDRHI|THUMB2_U,rn,rt,im) -# define T2_LDRHWI(rt,rn,im) torri12(THUMB2_LDRHWI,rn,rt,im) -# define CC_LDRHIN(cc,rt,rn,im) corri8(cc,ARM_LDRHI,rn,rt,im) -# define LDRHIN(rt,rn,im) CC_LDRHIN(ARM_CC_AL,rt,rn,im) -# define T2_LDRHIN(rt,rn,im) torri8(THUMB2_LDRHI,rn,rt,im) -# define CC_LDR(cc,rt,rn,rm) corrr(cc,ARM_LDR|ARM_P,rn,rt,rm) -# define LDR(rt,rn,rm) CC_LDR(ARM_CC_AL,rt,rn,rm) -# define T1_LDR(rt,rn,rm) is(THUMB_LDR|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt)) -# define T2_LDR(rt,rn,rm) torxr(THUMB2_LDR,rn,rt,rm) -# define CC_LDRN(cc,rt,rn,rm) corrr(cc,ARM_LDR,rn,rt,rm) -# define LDRN(rt,rn,rm) CC_LDRN(ARM_CC_AL,rt,rn,rm) -# define CC_LDRI(cc,rt,rn,im) corri(cc,ARM_LDRI|ARM_P,rn,rt,im) -# define LDRI(rt,rn,im) CC_LDRI(ARM_CC_AL,rt,rn,im) -# define T1_LDRI(rt,rn,im) is(THUMB_LDRI|(_u5(im)<<6)|(_u3(rn)<<3)|_u3(rt)) -# define T1_LDRISP(rt,im) is(THUMB_LDRISP|(_u3(rt)<<8)|_u8(im)) -# define T2_LDRI(rt,rn,im) torri8(THUMB2_LDRI|THUMB2_U,rn,rt,im) -# define T2_LDRWI(rt,rn,im) torri12(THUMB2_LDRWI,rn,rt,im) -# define CC_LDRIN(cc,rt,rn,im) corri(cc,ARM_LDRI,rn,rt,im) -# define LDRIN(rt,rn,im) CC_LDRIN(ARM_CC_AL,rt,rn,im) -# define T2_LDRIN(rt,rn,im) torri8(THUMB2_LDRI,rn,rt,im) -# define CC_LDRD(cc,rt,rn,rm) corrr(cc,ARM_LDRD|ARM_P,rn,rt,rm) -# define LDRD(rt,rn,rm) CC_LDRD(ARM_CC_AL,rt,rn,rm) -# define T2_LDRDI(rt,rt2,rn,im) torrri8(THUMB2_LDRDI|ARM_P,rn,rt,rt2,im) -# define CC_LDRDN(cc,rt,rn,rm) corrr(cc,ARM_LDRD,rn,rt,rm) -# define LDRDN(rd,rn,rm) CC_LDRDN(ARM_CC_AL,rt,rn,rm) -# define CC_LDRDI(cc,rt,rn,im) corri8(cc,ARM_LDRDI|ARM_P,rn,rt,im) -# define LDRDI(rt,rn,im) CC_LDRDI(ARM_CC_AL,rt,rn,im) -# define CC_LDRDIN(cc,rt,rn,im) corri8(cc,ARM_LDRDI,rn,rt,im) -# define LDRDIN(rt,rn,im) CC_LDRDIN(ARM_CC_AL,rt,rn,im) -# define T2_LDRDIN(rt,rt2,rn,im) torrri8(THUMB2_LDRDI,rn,rt,rt2,im) -# define CC_STRB(cc,rt,rn,rm) corrr(cc,ARM_STRB|ARM_P,rn,rt,rm) -# define STRB(rt,rn,rm) CC_STRB(ARM_CC_AL,rt,rn,rm) -# define T1_STRB(rt,rn,rm) is(THUMB_STRB|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt)) -# define T2_STRB(rt,rn,rm) torxr(THUMB2_STRB,rn,rt,rm) -# define CC_STRBN(cc,rt,rn,rm) corrr(cc,ARM_STRB,rn,rt,rm) -# define STRBN(rt,rn,rm) CC_STRBN(ARM_CC_AL,rt,rn,rm) -# define CC_STRBI(cc,rt,rn,im) corri(cc,ARM_STRBI|ARM_P,rn,rt,im) -# define STRBI(rt,rn,im) CC_STRBI(ARM_CC_AL,rt,rn,im) -# define T1_STRBI(rt,rn,im) is(THUMB_STRBI|(_u5(im)<<6)|(_u3(rn)<<3)|_u3(rt)) -# define T2_STRBI(rt,rn,im) torri8(THUMB2_STRBI|THUMB2_U,rn,rt,im) -# define T2_STRBWI(rt,rn,im) torri12(THUMB2_STRBWI,rn,rt,im) -# define CC_STRBIN(cc,rt,rn,im) corri(cc,ARM_STRBI,rn,rt,im) -# define STRBIN(rt,rn,im) CC_STRBIN(ARM_CC_AL,rt,rn,im) -# define T2_STRBIN(rt,rn,im) torri8(THUMB2_STRBI,rn,rt,im) -# define CC_STRH(cc,rt,rn,rm) corrr(cc,ARM_STRH|ARM_P,rn,rt,rm) -# define STRH(rt,rn,rm) CC_STRH(ARM_CC_AL,rt,rn,rm) -# define T1_STRH(rt,rn,rm) is(THUMB_STRH|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt)) -# define T2_STRH(rt,rn,rm) torxr(THUMB2_STRH,rn,rt,rm) -# define CC_STRHN(cc,rt,rn,rm) corrr(cc,ARM_STRH,rn,rt,rm) -# define STRHN(rt,rn,rm) CC_STRHN(ARM_CC_AL,rt,rn,rm) -# define CC_STRHI(cc,rt,rn,im) corri8(cc,ARM_STRHI|ARM_P,rn,rt,im) -# define STRHI(rt,rn,im) CC_STRHI(ARM_CC_AL,rt,rn,im) -# define T1_STRHI(rt,rn,im) is(THUMB_STRHI|(_u5(im)<<6)|(_u3(rn)<<3)|_u3(rt)) -# define T2_STRHI(rt,rn,im) torri8(THUMB2_STRHI|THUMB2_U,rn,rt,im) -# define T2_STRHWI(rt,rn,im) torri12(THUMB2_STRHWI,rn,rt,im) -# define CC_STRHIN(cc,rt,rn,im) corri8(cc,ARM_STRHI,rn,rt,im) -# define STRHIN(rt,rn,im) CC_STRHIN(ARM_CC_AL,rt,rn,im) -# define T2_STRHIN(rt,rn,im) torri8(THUMB2_STRHI,rn,rt,im) -# define CC_STR(cc,rt,rn,rm) corrr(cc,ARM_STR|ARM_P,rn,rt,rm) -# define STR(rt,rn,rm) CC_STR(ARM_CC_AL,rt,rn,rm) -# define T1_STR(rt,rn,rm) is(THUMB_STR|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt)) -# define T2_STR(rt,rn,rm) torxr(THUMB2_STR,rn,rt,rm) -# define CC_STRN(cc,rt,rn,rm) corrr(cc,ARM_STR,rn,rt,rm) -# define STRN(rt,rn,rm) CC_STRN(ARM_CC_AL,rt,rn,rm) -# define CC_STRI(cc,rt,rn,im) corri(cc,ARM_STRI|ARM_P,rn,rt,im) -# define STRI(rt,rn,im) CC_STRI(ARM_CC_AL,rt,rn,im) -# define T1_STRI(rt,rn,im) is(THUMB_STRI|(_u5(im)<<6)|(_u3(rn)<<3)|_u3(rt)) -# define T1_STRISP(rt,im) is(THUMB_STRISP|(_u3(rt)<<8)|(_u8(im))) -# define T2_STRI(rt,rn,im) torri8(THUMB2_STRI|THUMB2_U,rn,rt,im) -# define T2_STRWI(rt,rn,im) torri12(THUMB2_STRWI,rn,rt,im) -# define CC_STRIN(cc,rt,rn,im) corri(cc,ARM_STRI,rn,rt,im) -# define STRIN(rt,rn,im) CC_STRIN(ARM_CC_AL,rt,rn,im) -# define T2_STRIN(rt,rn,im) torri8(THUMB2_STRI,rn,rt,im) -# define CC_STRD(cc,rt,rn,rm) corrr(cc,ARM_STRD|ARM_P,rn,rt,rm) -# define STRD(rt,rn,rm) CC_STRD(ARM_CC_AL,rt,rn,rm) -# define CC_STRDN(cc,rt,rn,rm) corrr(cc,ARM_STRD,rn,rt,rm) -# define STRDN(rt,rn,rm) CC_STRDN(ARM_CC_AL,rt,rn,rm) -# define CC_STRDI(cc,rt,rn,im) corri8(cc,ARM_STRDI|ARM_P,rn,rt,im) -# define STRDI(rt,rn,im) CC_STRDI(ARM_CC_AL,rt,rn,im) -# define T2_STRDI(rt,rt2,rn,im) torrri8(THUMB2_STRDI|ARM_P,rn,rt,rt2,im) -# define CC_STRDIN(cc,rt,rn,im) corri8(cc,ARM_STRDI,rn,rt,im) -# define STRDIN(rt,rn,im) CC_STRDIN(ARM_CC_AL,rt,rn,im) -# define T2_STRDIN(rt,rt2,rn,im) torrri8(THUMB2_STRDI,rn,rt,rt2,im) -# define CC_LDMIA(cc,rn,im) corl(cc,ARM_M|ARM_M_L|ARM_M_I,rn,im) -# define LDMIA(rn,im) CC_LDMIA(ARM_CC_AL,rn,im) -# define CC_LDM(cc,rn,im) CC_LDMIA(cc,rn,im) -# define LDM(rn,im) LDMIA(rn,im) -# define T1_LDMIA(rn,im) is(THUMB_LDMIA|(_u3(rn)<<8)|im) -# define T2_LDMIA(rn,im) torl(THUMB2_LDMIA,rn,im) -# define CC_LDMIA_U(cc,rn,im) corl(cc,ARM_M|ARM_M_L|ARM_M_I|ARM_M_U,rn,im) -# define LDMIA_U(rn,im) CC_LDMIA_U(ARM_CC_AL,rn,im) -# define LDM_U(r0,i0) LDMIA_U(r0,i0) -# define CC_LDMIB(cc,rn,im) corl(cc,ARM_M|ARM_M_L|ARM_M_I|ARM_M_B,rn,im) -# define LDMIB(rn,im) CC_LDMIB(ARM_CC_AL,rn,im) -# define CC_LDMIB_U(cc,rn,im) corl(cc,ARM_M|ARM_M_L|ARM_M_I|ARM_M_B|ARM_M_U,rn,im) -# define LDMIB_U(rn,im) CC_LDMIB_U(ARM_CC_AL,rn,im) -# define CC_LDMDA(cc,rn,im) corl(cc,ARM_M|ARM_M_L,rn,im) -# define LDMDA(rn,im) CC_LDMDA(ARM_CC_AL,rn,im) -# define CC_LDMDA_U(cc,rn,im) corl(cc,ARM_M|ARM_M_L|ARM_M_U,rn,im) -# define LDMDA_U(rn,im) CC_LDMDA_U(ARM_CC_AL,rn,im) -# define CC_LDMDB(cc,rn,im) corl(cc,ARM_M|ARM_M_L|ARM_M_B,rn,im) -# define LDMDB(rn,im) CC_LDMDB(ARM_CC_AL,rn,im) -# define T2_LDMDB(rn,im) torl(THUMB2_LDMDB,rn,im) -# define CC_LDMDB_U(cc,rn,im) corl(cc,ARM_M|ARM_M_L|ARM_M_B|ARM_M_U,rn,im) -# define LDMDB_U(rn,im) CC_LDMDB_U(ARM_CC_AL,rn,im) -# define CC_STMIA(cc,rn,im) corl(cc,ARM_M|ARM_M_I,rn,im) -# define STMIA(rn,im) CC_STMIA(ARM_CC_AL,rn,im) -# define CC_STM(cc,rn,im) CC_STMIA(cc,rn,im) -# define STM(rn,im) STMIA(rn,im) -# define CC_STMIA_U(cc,rn,im) corl(cc,ARM_M|ARM_M_I|ARM_M_U,rn,im) -# define STMIA_U(rn,im) CC_STMIA_U(ARM_CC_AL,rn,im) -# define CC_STM_U(cc,rn,im) CC_STMIA_U(cc,rn,im) -# define STM_U(rn,im) STMIA_U(rn,im) -# define CC_STMIB(cc,rn,im) corl(cc,ARM_M|ARM_M_I|ARM_M_B,rn,im) -# define STMIB(rn,im) CC_STMIB(ARM_CC_AL,rn,im) -# define CC_STMIB_U(cc,rn,im) corl(cc,ARM_M|ARM_M_I|ARM_M_B|ARM_M_U,rn,im) -# define STMIB_U(rn,im) CC_STMIB_U(ARM_CC_AL,rn,im) -# define CC_STMDA(cc,rn,im) corl(cc,ARM_M,rn,im) -# define STMDA(rn,im) CC_STMDA(ARM_CC_AL,rn,im) -# define CC_STMDA_U(cc,rn,im) corl(cc,ARM_M|ARM_M_U,rn,im) -# define STMDA_U(rn,im) CC_STMDA_U(ARM_CC_AL,rn,im) -# define CC_STMDB(cc,rn,im) corl(cc,ARM_M|ARM_M_B,rn,im) -# define STMDB(rn,im) CC_STMDB(ARM_CC_AL,rn,im) -# define CC_STMDB_U(cc,rn,im) corl(cc,ARM_M|ARM_M_B|ARM_M_U,rn,im) -# define STMDB_U(rn,im) CC_STMDB_U(ARM_CC_AL,rn,im) -# define CC_PUSH(cc,im) CC_STMDB_U(cc,_SP_REGNO,im) -# define PUSH(im) STMDB_U(_SP_REGNO,im) -# define T1_PUSH(im) is(THUMB_PUSH|((im&0x4000)>>6)|(im&0xff)) -# define T2_PUSH(im) tpp(THUMB2_PUSH,im) -# define CC_POP(cc,im) LDMIA_U(cc,_SP_REGNO,im) -# define POP(im) LDMIA_U(_SP_REGNO,im) -# define T1_POP(im) is(THUMB_POP|((im&0x8000)>>7)|(im&0xff)) -# define T2_POP(im) tpp(THUMB2_POP,im) -# define jit_get_reg_args() \ - do { \ - (void)jit_get_reg(_R0|jit_class_named|jit_class_gpr); \ - (void)jit_get_reg(_R1|jit_class_named|jit_class_gpr); \ - (void)jit_get_reg(_R2|jit_class_named|jit_class_gpr); \ - (void)jit_get_reg(_R3|jit_class_named|jit_class_gpr); \ +# define CC_MOV(cc,rd,rm) corrr(cc,ARM_MOV,0,rd,rm) +# define MOV(rd,rm) CC_MOV(ARM_CC_AL,rd,rm) +# define T1_MOV(rd,rm) is(THUMB_MOV|((_u4(rd)&8)<<4)|(_u4(rm)<<3)|(rd&7)) +# define T2_MOV(rd,rm) T2_ORR(rd,_R15_REGNO,rm) +# define CC_MOVI(cc,rd,im) corri(cc,ARM_MOV|ARM_I,0,rd,im) +# define MOVI(rd,im) CC_MOVI(ARM_CC_AL,rd,im) +# define CC_MOVWI(cc,rd,im) coriw(cc,ARM_MOVWI,rd,im) +# define MOVWI(rd,im) CC_MOVWI(ARM_CC_AL,rd,im) +# define T1_MOVI(rd,im) is(THUMB_MOVI|(_u3(rd)<<8)|_u8(im)) +# define T2_MOVI(rd,im) torri(THUMB2_MOVI,_R15_REGNO,rd,im) +# define T2_MOVWI(rd,im) toriw(THUMB2_MOVWI,rd,im) +# define CC_MOVTI(cc,rd,im) coriw(cc,ARM_MOVTI,rd,im) +# define MOVTI(rd,im) CC_MOVTI(ARM_CC_AL,rd,im) +# define T2_MOVTI(rd,im) toriw(THUMB2_MOVTI,rd,im) +# define CC_MVN(cc,rd,rm) corrr(cc,ARM_MVN,0,rd,rm) +# define MVN(rd,rm) CC_MVN(ARM_CC_AL,rd,rm) +# define T1_MVN(rd,rm) is(THUMB_MVN|(_u3(rm)<<3)|_u3(rd)) +# define T2_MVN(rd,rm) torrr(THUMB2_MVN,_R15_REGNO,rd,rm) +# define CC_MVNI(cc,rd,im) corri(cc,ARM_MVN|ARM_I,0,rd,im) +# define MVNI(rd,im) CC_MVNI(ARM_CC_AL,rd,im) +# define T2_MVNI(rd,im) torri(THUMB2_MVNI,_R15_REGNO,rd,im) +# define CC_NOT(cc,rd,rm) CC_MVN(cc,rd,rm) +# define NOT(rd,rm) CC_NOT(ARM_CC_AL,rd,rm) +# define T1_NOT(rd,rm) T1_MVN(rd,rm) +# define T2_NOT(rd,rm) T2_MVN(rd,rm) +# define NOP() MOV(_R0_REGNO, _R0_REGNO) +# define T1_NOP() is(0xbf00) +# define CC_ADD(cc,rd,rn,rm) corrr(cc,ARM_ADD,rn,rd,rm) +# define ADD(rd,rn,rm) CC_ADD(ARM_CC_AL,rd,rn,rm) +# define T1_ADD(rd,rn,rm) is(THUMB_ADD|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rd)) +# define T1_ADDX(rdn,rm) is(THUMB_ADDX|((_u4(rdn)&8)<<4)|(_u4(rm)<<3)|(rdn&7)) +# define T2_ADD(rd,rn,rm) torrr(THUMB2_ADD,rn,rd,rm) +# define CC_ADDI(cc,rd,rn,im) corri(cc,ARM_ADD|ARM_I,rn,rd,im) +# define ADDI(rd,rn,im) CC_ADDI(ARM_CC_AL,rd,rn,im) +# define T1_ADDI3(rd,rn,im) is(THUMB_ADDI3|(_u3(im)<<6)|(_u3(rn)<<3)|_u3(rd)) +# define T1_ADDI8(rdn,im) is(THUMB_ADDI8|(_u3(rdn)<<8)|_u8(im)) +# define T2_ADDI(rd,rn,im) torri(THUMB2_ADDI,rn,rd,im) +# define T2_ADDWI(rd,rn,im) torri(THUMB2_ADDWI,rn,rd,im) +# define CC_ADDS(cc,rd,rn,rm) corrr(cc,ARM_ADD|ARM_S,rn,rd,rm) +# define ADDS(rd,rn,rm) CC_ADDS(ARM_CC_AL,rd,rn,rm) +# define T2_ADDS(rd,rn,rm) torrr(THUMB2_ADD|ARM_S,rn,rd,rm) +# define ADDSI(rd,rn,im) corri(ARM_CC_AL,ARM_ADD|ARM_S|ARM_I,rn,rd,im) +# define T2_ADDSI(rd,rn,im) torri(THUMB2_ADDI|ARM_S,rn,rd,im) +# define CC_ADC(cc,rd,rn,rm) corrr(cc,ARM_ADC,rn,rd,rm) +# define ADC(rd,rn,rm) CC_ADC(ARM_CC_AL,rd,rn,rm) +# define T1_ADC(rdn,rm) is(THUMB_ADC|(_u3(rm)<<3)|_u3(rdn)) +# define T2_ADC(rd,rn,rm) torrr(THUMB2_ADC,rn,rd,rm) +# define CC_ADCI(cc,rd,rn,im) corri(cc,ARM_ADC|ARM_I,rn,rd,im) +# define ADCI(rd,rn,im) CC_ADCI(ARM_CC_AL,rd,rn,im) +# define T2_ADCI(rd,rn,im) torri(THUMB2_ADCI,rn,rd,im) +# define CC_ADCS(cc,rd,rn,rm) corrr(cc,ARM_ADC|ARM_S,rn,rd,rm) +# define ADCS(rd,rn,rm) CC_ADCS(ARM_CC_AL,rd,rn,rm) +# define T2_ADCS(rd,rn,rm) torrr(THUMB2_ADC|ARM_S,rn,rd,rm) +# define CC_ADCSI(cc,rd,rn,im) corri(cc,ARM_ADC|ARM_S|ARM_I,rn,rd,im) +# define ADCSI(rd,rn,im) CC_ADCSI(ARM_CC_AL,rd,rn,im) +# define T2_ADCSI(rd,rn,im) torri(THUMB2_ADCI|ARM_S,rn,rd,im) +# define CC_SUB(cc,rd,rn,rm) corrr(cc,ARM_SUB,rn,rd,rm) +# define SUB(rd,rn,rm) CC_SUB(ARM_CC_AL,rd,rn,rm) +# define T1_SUB(rd,rn,rm) is(THUMB_SUB|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rd)) +# define T2_SUB(rd,rn,rm) torrr(THUMB2_SUB,rn,rd,rm) +# define CC_SUBI(cc,rd,rn,im) corri(cc,ARM_SUB|ARM_I,rn,rd,im) +# define SUBI(rd,rn,im) CC_SUBI(ARM_CC_AL,rd,rn,im) +# define T1_SUBI3(rd,rn,im) is(THUMB_SUBI3|(_u3(im)<<6)|(_u3(rn)<<3)|_u3(rd)) +# define T1_SUBI8(rdn,im) is(THUMB_SUBI8|(_u3(rdn)<<8)|_u8(im)) +# define T2_SUBI(rd,rn,im) torri(THUMB2_SUBI,rn,rd,im) +# define T2_SUBWI(rd,rn,im) torri(THUMB2_SUBWI,rn,rd,im) +# define CC_SUBS(cc,rd,rn,rm) corrr(cc,ARM_SUB|ARM_S,rn,rd,rm) +# define SUBS(rd,rn,rm) CC_SUBS(ARM_CC_AL,rd,rn,rm) +# define T2_SUBS(rd,rn,rm) torrr(THUMB2_SUB|ARM_S,rn,rd,rm) +# define CC_SUBSI(cc,rd,rn,im) corri(cc,ARM_SUB|ARM_S|ARM_I,rn,rd,im) +# define SUBSI(rd,rn,im) CC_SUBSI(ARM_CC_AL,rd,rn,im) +# define T2_SUBSI(rd,rn,im) torri(THUMB2_SUBI|ARM_S,rn,rd,im) +# define CC_SBC(cc,rd,rn,rm) corrr(cc,ARM_SBC,rn,rd,rm) +# define SBC(rd,rn,rm) CC_SBC(ARM_CC_AL,rd,rn,rm) +# define T1_SBC(rdn,rm) is(THUMB_SBC|(_u3(rm)<<3)|_u3(rdn)) +# define T2_SBC(rd,rn,rm) torrr(THUMB2_SBC,rn,rd,rm) +# define CC_SBCI(cc,rd,rn,im) corri(cc,ARM_SBC|ARM_I,rn,rd,im) +# define SBCI(rd,rn,im) CC_SBCI(ARM_CC_AL,rd,rn,im) +# define T2_SBCI(rd,rn,im) torri(THUMB2_SBCI,rn,rd,im) +# define CC_SBCS(cc,rd,rn,rm) corrr(cc,ARM_SBC|ARM_S,rn,rd,rm) +# define SBCS(rd,rn,rm) CC_SBCS(ARM_CC_AL,rd,rn,rm) +# define T2_SBCS(rd,rn,rm) torrr(THUMB2_SBC|ARM_S,rn,rd,rm) +# define CC_SBCSI(cc,rd,rn,im) corri(cc,ARM_SBC|ARM_S|ARM_I,rn,rd,im) +# define SBCSI(rd,rn,im) CC_SBCSI(ARM_CC_AL,rd,rn,im) +# define T2_SBCSI(rd,rn,im) torri(THUMB2_SBCI|ARM_S,rn,rd,im) +# define CC_RSB(cc,rd,rn,rm) corrr(cc,ARM_RSB,rn,rd,rm) +# define RSB(rd,rn,rm) CC_RSB(ARM_CC_AL,rd,rn,rm) +# define T2_RSB(rd,rn,rm) torrr(THUMB2_RSB,rn,rd,rm) +# define CC_RSBI(cc,rd,rn,im) corri(cc,ARM_RSB|ARM_I,rn,rd,im) +# define RSBI(rd,rn,im) CC_RSBI(ARM_CC_AL,rd,rn,im) +# define T1_RSBI(rd,rn) is(THUMB_RSBI|(_u3(rn)<<3)|_u3(rd)) +# define T2_RSBI(rd,rn,im) torri(THUMB2_RSBI,rn,rd,im) +# define CC_MUL(cc,rl,rn,rm) corrrr(cc,ARM_MUL,rl,0,rm,rn) +# define MUL(rl,rn,rm) CC_MUL(ARM_CC_AL,rl,rn,rm) +# define T1_MUL(rdm,rn) is(THUMB_MUL|(_u3(rn)<<3)|_u3(rdm)) +# define T2_MUL(rd,rn,rm) torrr(THUMB2_MUL,rn,rd,rm) +# define CC_SMULL(cc,rl,rh,rn,rm) corrrr(cc,ARM_SMULL,rh,rl,rm,rn) +# define SMULL(rl,rh,rn,rm) CC_SMULL(ARM_CC_AL,rl,rh,rn,rm) +# define T2_SMULL(rl,rh,rn,rm) torrrr(THUMB2_SMULL,rn,rl,rh,rm) +# define CC_UMULL(cc,rl,rh,rn,rm) corrrr(cc,ARM_UMULL,rh,rl,rm,rn) +# define UMULL(rl,rh,rn,rm) CC_UMULL(ARM_CC_AL,rl,rh,rn,rm) +# define T2_UMULL(rl,rh,rn,rm) torrrr(THUMB2_UMULL,rn,rl,rh,rm) +# define T2_SDIV(rd,rn,rm) torrr(THUMB2_SDIV,rn,rd,rm) +# define T2_UDIV(rd,rn,rm) torrr(THUMB2_UDIV,rn,rd,rm) +# define CC_AND(cc,rd,rn,rm) corrr(cc,ARM_AND,rn,rd,rm) +# define AND(rd,rn,rm) CC_AND(ARM_CC_AL,rd,rn,rm) +# define T1_AND(rdn,rm) is(THUMB_AND|(_u3(rm)<<3)|_u3(rdn)) +# define T2_AND(rd,rn,rm) torrr(THUMB2_AND,rn,rd,rm) +# define CC_ANDI(cc,rd,rn,im) corri(cc,ARM_AND|ARM_I,rn,rd,im) +# define ANDI(rd,rn,im) CC_ANDI(ARM_CC_AL,rd,rn,im) +# define T2_ANDI(rd,rn,im) torri(THUMB2_ANDI,rn,rd,im) +# define CC_ANDS(cc,rd,rn,rm) corrr(cc,ARM_AND|ARM_S,rn,rd,rm) +# define ANDS(rd,rn,rm) CC_ANDS(ARM_CC_AL,rd,rn,rm) +# define T2_ANDS(rd,rn,rm) torrr(THUMB2_AND|ARM_S,rn,rd,rm) +# define CC_ANDSI(cc,rd,rn,im) corri(cc,ARM_AND|ARM_S|ARM_I,rn,rd,im) +# define ANDSI(rd,rn,im) CC_ANDSI(ARM_CC_AL,rd,rn,im) +# define T2_ANDSI(rd,rn,im) torri(ARM_CC_AL,THUMB2_ANDI|ARM_S,rn,rd,im) +# define CC_BIC(cc,rd,rn,rm) corrr(cc,ARM_BIC,rn,rd,rm) +# define BIC(rd,rn,rm) CC_BIC(ARM_CC_AL,rd,rn,rm) +# define T2_BIC(rd,rn,rm) torrr(THUMB2_BIC,rn,rd,rm) +# define CC_BICI(cc,rd,rn,im) corri(cc,ARM_BIC|ARM_I,rn,rd,im) +# define BICI(rd,rn,im) CC_BICI(ARM_CC_AL,rd,rn,im) +# define T2_BICI(rd,rn,im) torri(THUMB2_BICI,rn,rd,im) +# define CC_BICS(cc,rd,rn,rm) corrr(cc,ARM_BIC|ARM_S,rn,rd,rm) +# define BICS(rd,rn,rm) CC_BICS(ARM_CC_AL,rd,rn,rm) +# define T2_BICS(rd,rn,rm) torrr(THUMB2_BIC|ARM_S,rn,rd,rm) +# define CC_BICSI(cc,rd,rn,im) corri(cc,ARM_BIC|ARM_S|ARM_I,rn,rd,im) +# define BICSI(rd,rn,im) CC_BICSI(ARM_CC_AL,rd,rn,im) +# define T2_BICSI(rd,rn,im) torri(ARM_CC_AL,THUMB2_BICI|ARM_S,rn,rd,im) +# define CC_ORR(cc,rd,rn,rm) corrr(cc,ARM_ORR,rn,rd,rm) +# define ORR(rd,rn,rm) CC_ORR(ARM_CC_AL,rd,rn,rm) +# define T1_ORR(rdn,rm) is(THUMB_ORR|(_u3(rm)<<3)|_u3(rdn)) +# define T2_ORR(rd,rn,rm) torrr(THUMB2_ORR,rn,rd,rm) +# define CC_ORR_SI(cc,rd,rn,rt,sh,im) corrrs(cc,ARM_ORR|sh,rn,rd,rm,im) +# define ORR_SI(r0,r1,r2,sh,im) CC_ORR_SI(ARM_CC_AL,r0,r1,r2,sh,im) +# define CC_ORRI(cc,rd,rn,im) corri(cc,ARM_ORR|ARM_I,rn,rd,im) +# define ORRI(rd,rn,im) CC_ORRI(ARM_CC_AL,rd,rn,im) +# define T2_ORRI(rd,rn,im) torri(THUMB2_ORRI,rn,rd,im) +# define CC_EOR(cc,rd,rn,rm) corrr(cc,ARM_EOR,rn,rd,rm) +# define EOR(rd,rn,rm) CC_EOR(ARM_CC_AL,rd,rn,rm) +# define T1_EOR(rdn,rm) is(THUMB_EOR|(_u3(rm)<<3)|_u3(rdn)) +# define T2_EOR(rd,rn,rm) torrr(THUMB2_EOR,rn,rd,rm) +# define CC_EOR_SI(cc,rd,rn,rm,sh,im) corrrs(cc,ARM_EOR|sh,rn,rd,rm,im) +# define EOR_SI(r0,r1,r2,sh,im) CC_EOR_SI(ARM_CC_AL,r0,r1,r2,sh,im) +# define CC_EORI(cc,rd,rn,im) corri(cc,ARM_EOR|ARM_I,rn,rd,im) +# define EORI(rd,rn,im) CC_EORI(ARM_CC_AL,rd,rn,im) +# define T2_EORI(rd,rn,im) torri(THUMB2_EORI,rn,rd,im) +# define CC_REV(cc,rd,rm) c6orr(cc,ARM_REV,rd,rm) +# define REV(rd,rm) CC_REV(ARM_CC_AL,rd,rm) +# define T1_REV(rd,rm) is(THUMB_REV|(_u3(rm)<<3)|_u3(rd)) +# define T2_REV(rd,rm) torrr(THUMB2_REV,rm,rd,rm) +# define CC_REV16(cc,rd,rm) c6orr(cc,ARM_REV16,rd,rm) +# define REV16(rd,rm) CC_REV16(ARM_CC_AL,rd,rm) +# define T1_REV16(rd,rm) is(THUMB_REV16|(_u3(rm)<<3)|_u3(rd)) +# define T2_REV16(rd,rm) torrr(THUMB2_REV16,rm,rd,rm) +# define CC_SXTB(cc,rd,rm) c6orr(cc,ARM_SXTB,rd,rm) +# define SXTB(rd,rm) CC_SXTB(ARM_CC_AL,rd,rm) +# define T1_SXTB(rd,rm) is(THUMB_SXTB|(_u3(rm)<<3)|_u3(rd)) +# define T2_SXTB(rd,rm) torrr(THUMB2_SXTB,_R15_REGNO,rd,rm) +# define CC_UXTB(cc,rd,rm) c6orr(cc,ARM_UXTB,rd,rm) +# define UXTB(rd,rm) CC_UXTB(ARM_CC_AL,rd,rm) +# define T1_UXTB(rd,rm) is(THUMB_UXTB|(_u3(rm)<<3)|_u3(rd)) +# define T2_UXTB(rd,rm) torrr(THUMB2_UXTB,_R15_REGNO,rd,rm) +# define CC_SXTH(cc,rd,rm) c6orr(cc,ARM_SXTH,rd,rm) +# define SXTH(rd,rm) CC_SXTH(ARM_CC_AL,rd,rm) +# define T1_SXTH(rd,rm) is(THUMB_SXTH|(_u3(rm)<<3)|_u3(rd)) +# define T2_SXTH(rd,rm) torrr(THUMB2_SXTH,_R15_REGNO,rd,rm) +# define CC_UXTH(cc,rd,rm) c6orr(cc,ARM_UXTH,rd,rm) +# define UXTH(rd,rm) CC_UXTH(ARM_CC_AL,rd,rm) +# define T1_UXTH(rd,rm) is(THUMB_UXTH|(_u3(rm)<<3)|_u3(rd)) +# define T2_UXTH(rd,rm) torrr(THUMB2_UXTH,_R15_REGNO,rd,rm) +# define CC_SHIFT(cc,o,rd,rm,rn,im) cshift(cc,o,rd,rm,rn,im) +# define CC_LSL(cc,rd,rn,rm) CC_SHIFT(cc,ARM_LSL|ARM_R,rd,rm,rn,0) +# define LSL(rd,rn,rm) CC_LSL(ARM_CC_AL,rd,rn,rm) +# define T1_LSL(rdn,rm) is(THUMB_LSL|(_u3(rm)<<3)|_u3(rdn)) +# define T2_LSL(rd,rn,rm) torrr(THUMB2_LSL,rn,rd,rm) +# define CC_LSLI(cc,rd,rn,im) CC_SHIFT(cc,ARM_LSL,rd,0,rn,im) +# define LSLI(rd,rn,im) CC_LSLI(ARM_CC_AL,rd,rn,im) +# define T1_LSLI(rd,rm,im) is(THUMB_LSLI|(_u5(im)<<6)|(_u3(rm)<<3)|_u3(rd)) +# define T2_LSLI(rd,rm,im) tshift(THUMB2_LSLI,rd,rm,im) +# define CC_LSR(cc,rd,rn,rm) CC_SHIFT(cc,ARM_LSR|ARM_R,rd,rm,rn,0) +# define LSR(rd,rn,rm) CC_LSR(ARM_CC_AL,rd,rn,rm) +# define T1_LSR(rdn,rm) is(THUMB_LSR|(_u3(rm)<<3)|_u3(rdn)) +# define T2_LSR(rd,rn,rm) torrr(THUMB2_LSR,rn,rd,rm) +# define CC_LSRI(cc,rd,rn,im) CC_SHIFT(cc,ARM_LSR,rd,0,rn,im) +# define LSRI(rd,rn,im) CC_LSRI(ARM_CC_AL,rd,rn,im) +# define T1_LSRI(rd,rm,im) is(THUMB_LSRI|(_u5(im)<<6)|(_u3(rm)<<3)|_u3(rd)) +# define T2_LSRI(rd,rm,im) tshift(THUMB2_LSRI,rd,rm,im) +# define CC_ASR(cc,rd,rn,rm) CC_SHIFT(cc,ARM_ASR|ARM_R,rd,rm,rn,0) +# define ASR(rd,rn,rm) CC_ASR(ARM_CC_AL,rd,rn,rm) +# define T1_ASR(rdn,rm) is(THUMB_ASR|(_u3(rm)<<3)|_u3(rdn)) +# define T2_ASR(rd,rn,rm) torrr(THUMB2_ASR,rn,rd,rm) +# define CC_ASRI(cc,rd,rn,im) CC_SHIFT(cc,ARM_ASR,rd,0,rn,im) +# define ASRI(rd,rn,im) CC_ASRI(ARM_CC_AL,rd,rn,im) +# define T1_ASRI(rd,rm,im) is(THUMB_ASRI|(_u5(im)<<6)|(_u3(rm)<<3)|_u3(rd)) +# define T2_ASRI(rd,rm,im) tshift(THUMB2_ASRI,rd,rm,im) +# define CC_CMP(cc,rn,rm) corrr(cc,ARM_CMP,rn,0,rm) +# define CMP(rn,rm) CC_CMP(ARM_CC_AL,rn,rm) +# define T1_CMP(rn,rm) is(THUMB_CMP|(_u3(rm)<<3)|_u3(rn)) +# define T1_CMPX(rn,rm) is(THUMB_CMPX|((_u4(rn)&8)<<4)|(_u4(rm)<<3)|(rn&7)) +# define T2_CMP(rn,rm) torrr(THUMB2_CMP,rn,_R15_REGNO,rm) +# define CC_CMPI(cc,rn,im) corri(cc,ARM_CMP|ARM_I,rn,0,im) +# define CMPI(rn,im) CC_CMPI(ARM_CC_AL,rn,im) +# define T1_CMPI(rn,im) is(THUMB_CMPI|(_u3(rn)<<8)|_u8(im)) +# define T2_CMPI(rn,im) torri(THUMB2_CMPI,rn,_R15_REGNO,im) +# define CC_CMN(cc,rn,rm) corrr(cc,ARM_CMN,rn,0,rm) +# define CMN(rn,rm) CC_CMN(ARM_CC_AL,rn,rm) +# define T1_CMN(rn,rm) is(THUMB_CMN|(_u3(rm)<<3)|_u3(rm)) +# define T2_CMN(rn,rm) torrr(THUMB2_CMN,rn,_R15_REGNO,rm) +# define CC_CMNI(cc,rn,im) corri(cc,ARM_CMN|ARM_I,rn,0,im) +# define CMNI(rn,im) CC_CMNI(ARM_CC_AL,rn,im) +# define T2_CMNI(rn,im) torri(THUMB2_CMNI,rn,_R15_REGNO,im) +# define CC_TST(cc,rn,rm) corrr(cc,ARM_TST,rn,r0,rm) +# define TST(rn,rm) CC_TST(ARM_CC_AL,rn,rm) +# define T1_TST(rn,rm) is(THUMB_TST|(_u3(rm)<<3)|_u3(rn)) +# define T2_TST(rn,rm) torrr(THUMB2_TST,rn,_R15_REGNO,rm) +# define CC_TSTI(cc,rn,im) corri(cc,ARM_TST|ARM_I,rn,0,im) +# define TSTI(rn,im) CC_TSTI(ARM_CC_AL,rn,im) +# define T2_TSTI(rn,im) torri(THUMB2_TSTI,rn,_R15_REGNO,im) +# define CC_TEQ(cc,rn,rm) corrr(cc,ARM_TEQ,rn,0,rm) +# define TEQ(rn,rm) CC_TEQ(ARM_CC_AL,rn,rm) +# define CC_TEQI(cc,rm,im) corri(cc,ARM_TEQ|ARM_I,rn,0,im) +# define TEQI(rn,im) CC_TEQI(ARM_CC_AL,rn,im) +# define CC_BX(cc,rm) cbx(cc,ARM_BX,rm) +# define BX(rm) CC_BX(ARM_CC_AL,rm) +# define T1_BX(rm) is(0x4700|(_u4(rm)<<3)) +# define CC_BLX(cc,rm) cbx(cc,ARM_BLX,rm) +# define BLX(rm) CC_BLX(ARM_CC_AL,rm) +# define T1_BLX(rm) is(THUMB_BLX|(_u4(rm)<<3)) +# define BLXI(im) blxi(im) +# define T2_BLXI(im) tb(THUMB2_BLXI,im) +# define CC_B(cc,im) cb(cc,ARM_B,im) +# define B(im) CC_B(ARM_CC_AL,im) +# define T1_CC_B(cc,im) tc8(cc,im) +# define T1_B(im) t11(im) +# define T2_CC_B(cc,im) tcb(cc,im) +# define T2_B(im) tb(THUMB2_B,im) +# define CC_BLI(cc,im) cb(cc,ARM_BLI,im) +# define BLI(im) CC_BLI(ARM_CC_AL,im) +# define T2_BLI(im) tb(THUMB2_BLI,im) +# define CC_LDRSB(cc,rt,rn,rm) corrr(cc,ARM_LDRSB|ARM_P,rn,rt,rm) +# define LDRSB(rt,rn,rm) CC_LDRSB(ARM_CC_AL,rt,rn,rm) +# define T1_LDRSB(rt,rn,rm) is(THUMB_LDRSB|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt)) +# define T2_LDRSB(rt,rn,rm) torxr(THUMB2_LDRSB,rn,rt,rm) +# define CC_LDRSBN(cc,rt,rn,rm) corrr(cc,ARM_LDRSB,rn,rt,rm) +# define LDRSBN(rt,rn,rm) CC_LDRSBN(ARM_CC_AL,rt,rn,rm) +# define CC_LDRSBI(cc,rt,rn,im) corri8(cc,ARM_LDRSBI|ARM_P,rn,rt,im) +# define LDRSBI(rt,rn,im) CC_LDRSBI(ARM_CC_AL,rt,rn,im) +# define T2_LDRSBI(rt,rn,im) torri8(THUMB2_LDRSBI|THUMB2_U,rn,rt,im) +# define T2_LDRSBWI(rt,rn,im) torri12(THUMB2_LDRSBWI,rn,rt,im) +# define CC_LDRSBIN(cc,rt,rn,im) corri8(cc,ARM_LDRSBI,rn,rt,im) +# define LDRSBIN(rt,rn,im) CC_LDRSBIN(ARM_CC_AL,rt,rn,im) +# define T2_LDRSBIN(rt,rn,im) torri8(THUMB2_LDRSBI,rn,rt,im) +# define CC_LDRB(cc,rt,rn,rm) corrr(cc,ARM_LDRB|ARM_P,rn,rt,rm) +# define LDRB(rt,rn,rm) CC_LDRB(ARM_CC_AL,rt,rn,rm) +# define T1_LDRB(rt,rn,rm) is(THUMB_LDRB|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt)) +# define T2_LDRB(rt,rn,rm) torxr(THUMB2_LDRB,rn,rt,rm) +# define CC_LDRBN(cc,rt,rn,rm) corrr(cc,ARM_LDRB,rn,rt,rm) +# define LDRBN(rt,rn,rm) CC_LDRBN(ARM_CC_AL,rt,rn,rm) +# define CC_LDRBI(cc,rt,rn,im) corri(cc,ARM_LDRBI|ARM_P,rn,rt,im) +# define LDRBI(rt,rn,im) CC_LDRBI(ARM_CC_AL,rt,rn,im) +# define T1_LDRBI(rt,rn,im) is(THUMB_LDRBI|(_u5(im)<<6)|(_u3(rn)<<3)|_u3(rt)) +# define T2_LDRBI(rt,rn,im) torri8(THUMB2_LDRBI|THUMB2_U,rn,rt,im) +# define T2_LDRBWI(rt,rn,im) torri12(THUMB2_LDRBWI,rn,rt,im) +# define CC_LDRBIN(cc,rt,rn,im) corri(cc,ARM_LDRBI,rn,rt,im) +# define LDRBIN(rt,rn,im) CC_LDRBIN(ARM_CC_AL,rt,rn,im) +# define T2_LDRBIN(rt,rn,im) torri8(THUMB2_LDRBI,rn,rt,im) +# define CC_LDRSH(cc,rt,rn,rm) corrr(cc,ARM_LDRSH|ARM_P,rn,rt,rm) +# define LDRSH(rt,rn,rm) CC_LDRSH(ARM_CC_AL,rt,rn,rm) +# define T1_LDRSH(rt,rn,rm) is(THUMB_LDRSH|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt)) +# define T2_LDRSH(rt,rn,rm) torxr(THUMB2_LDRSH,rn,rt,rm) +# define CC_LDRSHN(cc,rt,rn,rm) corrr(cc,ARM_LDRSH,rn,rt,rm) +# define LDRSHN(rt,rn,rm) CC_LDRSHN(ARM_CC_AL,rt,rn,rm) +# define CC_LDRSHI(cc,rt,rn,im) corri8(cc,ARM_LDRSHI|ARM_P,rn,rt,im) +# define LDRSHI(rt,rn,im) CC_LDRSHI(ARM_CC_AL,rt,rn,im) +# define T2_LDRSHI(rt,rn,im) torri8(THUMB2_LDRSHI|THUMB2_U,rn,rt,im) +# define T2_LDRSHWI(rt,rn,im) torri12(THUMB2_LDRSHWI,rn,rt,im) +# define CC_LDRSHIN(cc,rt,rn,im) corri8(cc,ARM_LDRSHI,rn,rt,im) +# define LDRSHIN(rt,rn,im) CC_LDRSHIN(ARM_CC_AL,rt,rn,im) +# define T2_LDRSHIN(rt,rn,im) torri8(THUMB2_LDRSHI,rn,rt,im) +# define CC_LDRH(cc,rt,rn,rm) corrr(cc,ARM_LDRH|ARM_P,rn,rt,rm) +# define LDRH(rt,rn,rm) CC_LDRH(ARM_CC_AL,rt,rn,rm) +# define T1_LDRH(rt,rn,rm) is(THUMB_LDRH|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt)) +# define T2_LDRH(rt,rn,rm) torxr(THUMB2_LDRH,rn,rt,rm) +# define CC_LDRHN(cc,rt,rn,rm) corrr(cc,ARM_LDRH,rn,rt,rm) +# define LDRHN(rt,rn,rm) CC_LDRHN(ARM_CC_AL,rt,rn,rm) +# define CC_LDRHI(cc,rt,rn,im) corri8(cc,ARM_LDRHI|ARM_P,rn,rt,im) +# define LDRHI(rt,rn,im) CC_LDRHI(ARM_CC_AL,rt,rn,im) +# define T1_LDRHI(rt,rn,im) is(THUMB_LDRHI|(_u5(im)<<6)|(_u3(rn)<<3)|_u3(rt)) +# define T2_LDRHI(rt,rn,im) torri8(THUMB2_LDRHI|THUMB2_U,rn,rt,im) +# define T2_LDRHWI(rt,rn,im) torri12(THUMB2_LDRHWI,rn,rt,im) +# define CC_LDRHIN(cc,rt,rn,im) corri8(cc,ARM_LDRHI,rn,rt,im) +# define LDRHIN(rt,rn,im) CC_LDRHIN(ARM_CC_AL,rt,rn,im) +# define T2_LDRHIN(rt,rn,im) torri8(THUMB2_LDRHI,rn,rt,im) +# define CC_LDR(cc,rt,rn,rm) corrr(cc,ARM_LDR|ARM_P,rn,rt,rm) +# define LDR(rt,rn,rm) CC_LDR(ARM_CC_AL,rt,rn,rm) +# define T1_LDR(rt,rn,rm) is(THUMB_LDR|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt)) +# define T2_LDR(rt,rn,rm) torxr(THUMB2_LDR,rn,rt,rm) +# define CC_LDRN(cc,rt,rn,rm) corrr(cc,ARM_LDR,rn,rt,rm) +# define LDRN(rt,rn,rm) CC_LDRN(ARM_CC_AL,rt,rn,rm) +# define CC_LDRI(cc,rt,rn,im) corri(cc,ARM_LDRI|ARM_P,rn,rt,im) +# define LDRI(rt,rn,im) CC_LDRI(ARM_CC_AL,rt,rn,im) +# define T1_LDRI(rt,rn,im) is(THUMB_LDRI|(_u5(im)<<6)|(_u3(rn)<<3)|_u3(rt)) +# define T1_LDRISP(rt,im) is(THUMB_LDRISP|(_u3(rt)<<8)|_u8(im)) +# define T2_LDRI(rt,rn,im) torri8(THUMB2_LDRI|THUMB2_U,rn,rt,im) +# define T2_LDRWI(rt,rn,im) torri12(THUMB2_LDRWI,rn,rt,im) +# define CC_LDRIN(cc,rt,rn,im) corri(cc,ARM_LDRI,rn,rt,im) +# define LDRIN(rt,rn,im) CC_LDRIN(ARM_CC_AL,rt,rn,im) +# define T2_LDRIN(rt,rn,im) torri8(THUMB2_LDRI,rn,rt,im) +# define CC_LDRD(cc,rt,rn,rm) corrr(cc,ARM_LDRD|ARM_P,rn,rt,rm) +# define LDRD(rt,rn,rm) CC_LDRD(ARM_CC_AL,rt,rn,rm) +# define T2_LDRDI(rt,rt2,rn,im) torrri8(THUMB2_LDRDI|ARM_P,rn,rt,rt2,im) +# define CC_LDRDN(cc,rt,rn,rm) corrr(cc,ARM_LDRD,rn,rt,rm) +# define LDRDN(rd,rn,rm) CC_LDRDN(ARM_CC_AL,rt,rn,rm) +# define CC_LDRDI(cc,rt,rn,im) corri8(cc,ARM_LDRDI|ARM_P,rn,rt,im) +# define LDRDI(rt,rn,im) CC_LDRDI(ARM_CC_AL,rt,rn,im) +# define CC_LDRDIN(cc,rt,rn,im) corri8(cc,ARM_LDRDI,rn,rt,im) +# define LDRDIN(rt,rn,im) CC_LDRDIN(ARM_CC_AL,rt,rn,im) +# define T2_LDRDIN(rt,rt2,rn,im) torrri8(THUMB2_LDRDI,rn,rt,rt2,im) +# define CC_STRB(cc,rt,rn,rm) corrr(cc,ARM_STRB|ARM_P,rn,rt,rm) +# define STRB(rt,rn,rm) CC_STRB(ARM_CC_AL,rt,rn,rm) +# define T1_STRB(rt,rn,rm) is(THUMB_STRB|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt)) +# define T2_STRB(rt,rn,rm) torxr(THUMB2_STRB,rn,rt,rm) +# define CC_STRBN(cc,rt,rn,rm) corrr(cc,ARM_STRB,rn,rt,rm) +# define STRBN(rt,rn,rm) CC_STRBN(ARM_CC_AL,rt,rn,rm) +# define CC_STRBI(cc,rt,rn,im) corri(cc,ARM_STRBI|ARM_P,rn,rt,im) +# define STRBI(rt,rn,im) CC_STRBI(ARM_CC_AL,rt,rn,im) +# define T1_STRBI(rt,rn,im) is(THUMB_STRBI|(_u5(im)<<6)|(_u3(rn)<<3)|_u3(rt)) +# define T2_STRBI(rt,rn,im) torri8(THUMB2_STRBI|THUMB2_U,rn,rt,im) +# define T2_STRBWI(rt,rn,im) torri12(THUMB2_STRBWI,rn,rt,im) +# define CC_STRBIN(cc,rt,rn,im) corri(cc,ARM_STRBI,rn,rt,im) +# define STRBIN(rt,rn,im) CC_STRBIN(ARM_CC_AL,rt,rn,im) +# define T2_STRBIN(rt,rn,im) torri8(THUMB2_STRBI,rn,rt,im) +# define CC_STRH(cc,rt,rn,rm) corrr(cc,ARM_STRH|ARM_P,rn,rt,rm) +# define STRH(rt,rn,rm) CC_STRH(ARM_CC_AL,rt,rn,rm) +# define T1_STRH(rt,rn,rm) is(THUMB_STRH|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt)) +# define T2_STRH(rt,rn,rm) torxr(THUMB2_STRH,rn,rt,rm) +# define CC_STRHN(cc,rt,rn,rm) corrr(cc,ARM_STRH,rn,rt,rm) +# define STRHN(rt,rn,rm) CC_STRHN(ARM_CC_AL,rt,rn,rm) +# define CC_STRHI(cc,rt,rn,im) corri8(cc,ARM_STRHI|ARM_P,rn,rt,im) +# define STRHI(rt,rn,im) CC_STRHI(ARM_CC_AL,rt,rn,im) +# define T1_STRHI(rt,rn,im) is(THUMB_STRHI|(_u5(im)<<6)|(_u3(rn)<<3)|_u3(rt)) +# define T2_STRHI(rt,rn,im) torri8(THUMB2_STRHI|THUMB2_U,rn,rt,im) +# define T2_STRHWI(rt,rn,im) torri12(THUMB2_STRHWI,rn,rt,im) +# define CC_STRHIN(cc,rt,rn,im) corri8(cc,ARM_STRHI,rn,rt,im) +# define STRHIN(rt,rn,im) CC_STRHIN(ARM_CC_AL,rt,rn,im) +# define T2_STRHIN(rt,rn,im) torri8(THUMB2_STRHI,rn,rt,im) +# define CC_STR(cc,rt,rn,rm) corrr(cc,ARM_STR|ARM_P,rn,rt,rm) +# define STR(rt,rn,rm) CC_STR(ARM_CC_AL,rt,rn,rm) +# define T1_STR(rt,rn,rm) is(THUMB_STR|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt)) +# define T2_STR(rt,rn,rm) torxr(THUMB2_STR,rn,rt,rm) +# define CC_STRN(cc,rt,rn,rm) corrr(cc,ARM_STR,rn,rt,rm) +# define STRN(rt,rn,rm) CC_STRN(ARM_CC_AL,rt,rn,rm) +# define CC_STRI(cc,rt,rn,im) corri(cc,ARM_STRI|ARM_P,rn,rt,im) +# define STRI(rt,rn,im) CC_STRI(ARM_CC_AL,rt,rn,im) +# define T1_STRI(rt,rn,im) is(THUMB_STRI|(_u5(im)<<6)|(_u3(rn)<<3)|_u3(rt)) +# define T1_STRISP(rt,im) is(THUMB_STRISP|(_u3(rt)<<8)|(_u8(im))) +# define T2_STRI(rt,rn,im) torri8(THUMB2_STRI|THUMB2_U,rn,rt,im) +# define T2_STRWI(rt,rn,im) torri12(THUMB2_STRWI,rn,rt,im) +# define CC_STRIN(cc,rt,rn,im) corri(cc,ARM_STRI,rn,rt,im) +# define STRIN(rt,rn,im) CC_STRIN(ARM_CC_AL,rt,rn,im) +# define T2_STRIN(rt,rn,im) torri8(THUMB2_STRI,rn,rt,im) +# define CC_STRD(cc,rt,rn,rm) corrr(cc,ARM_STRD|ARM_P,rn,rt,rm) +# define STRD(rt,rn,rm) CC_STRD(ARM_CC_AL,rt,rn,rm) +# define CC_STRDN(cc,rt,rn,rm) corrr(cc,ARM_STRD,rn,rt,rm) +# define STRDN(rt,rn,rm) CC_STRDN(ARM_CC_AL,rt,rn,rm) +# define CC_STRDI(cc,rt,rn,im) corri8(cc,ARM_STRDI|ARM_P,rn,rt,im) +# define STRDI(rt,rn,im) CC_STRDI(ARM_CC_AL,rt,rn,im) +# define T2_STRDI(rt,rt2,rn,im) torrri8(THUMB2_STRDI|ARM_P,rn,rt,rt2,im) +# define CC_STRDIN(cc,rt,rn,im) corri8(cc,ARM_STRDI,rn,rt,im) +# define STRDIN(rt,rn,im) CC_STRDIN(ARM_CC_AL,rt,rn,im) +# define T2_STRDIN(rt,rt2,rn,im) torrri8(THUMB2_STRDI,rn,rt,rt2,im) +# define CC_LDMIA(cc,rn,im) corl(cc,ARM_M|ARM_M_L|ARM_M_I,rn,im) +# define LDMIA(rn,im) CC_LDMIA(ARM_CC_AL,rn,im) +# define CC_LDM(cc,rn,im) CC_LDMIA(cc,rn,im) +# define LDM(rn,im) LDMIA(rn,im) +# define T1_LDMIA(rn,im) is(THUMB_LDMIA|(_u3(rn)<<8)|im) +# define T2_LDMIA(rn,im) torl(THUMB2_LDMIA,rn,im) +# define CC_LDMIA_U(cc,rn,im) corl(cc,ARM_M|ARM_M_L|ARM_M_I|ARM_M_U,rn,im) +# define LDMIA_U(rn,im) CC_LDMIA_U(ARM_CC_AL,rn,im) +# define LDM_U(r0,i0) LDMIA_U(r0,i0) +# define CC_LDMIB(cc,rn,im) corl(cc,ARM_M|ARM_M_L|ARM_M_I|ARM_M_B,rn,im) +# define LDMIB(rn,im) CC_LDMIB(ARM_CC_AL,rn,im) +# define CC_LDMIB_U(cc,rn,im) corl(cc,ARM_M|ARM_M_L|ARM_M_I|ARM_M_B|ARM_M_U,rn,im) +# define LDMIB_U(rn,im) CC_LDMIB_U(ARM_CC_AL,rn,im) +# define CC_LDMDA(cc,rn,im) corl(cc,ARM_M|ARM_M_L,rn,im) +# define LDMDA(rn,im) CC_LDMDA(ARM_CC_AL,rn,im) +# define CC_LDMDA_U(cc,rn,im) corl(cc,ARM_M|ARM_M_L|ARM_M_U,rn,im) +# define LDMDA_U(rn,im) CC_LDMDA_U(ARM_CC_AL,rn,im) +# define CC_LDMDB(cc,rn,im) corl(cc,ARM_M|ARM_M_L|ARM_M_B,rn,im) +# define LDMDB(rn,im) CC_LDMDB(ARM_CC_AL,rn,im) +# define T2_LDMDB(rn,im) torl(THUMB2_LDMDB,rn,im) +# define CC_LDMDB_U(cc,rn,im) corl(cc,ARM_M|ARM_M_L|ARM_M_B|ARM_M_U,rn,im) +# define LDMDB_U(rn,im) CC_LDMDB_U(ARM_CC_AL,rn,im) +# define CC_STMIA(cc,rn,im) corl(cc,ARM_M|ARM_M_I,rn,im) +# define STMIA(rn,im) CC_STMIA(ARM_CC_AL,rn,im) +# define CC_STM(cc,rn,im) CC_STMIA(cc,rn,im) +# define STM(rn,im) STMIA(rn,im) +# define CC_STMIA_U(cc,rn,im) corl(cc,ARM_M|ARM_M_I|ARM_M_U,rn,im) +# define STMIA_U(rn,im) CC_STMIA_U(ARM_CC_AL,rn,im) +# define CC_STM_U(cc,rn,im) CC_STMIA_U(cc,rn,im) +# define STM_U(rn,im) STMIA_U(rn,im) +# define CC_STMIB(cc,rn,im) corl(cc,ARM_M|ARM_M_I|ARM_M_B,rn,im) +# define STMIB(rn,im) CC_STMIB(ARM_CC_AL,rn,im) +# define CC_STMIB_U(cc,rn,im) corl(cc,ARM_M|ARM_M_I|ARM_M_B|ARM_M_U,rn,im) +# define STMIB_U(rn,im) CC_STMIB_U(ARM_CC_AL,rn,im) +# define CC_STMDA(cc,rn,im) corl(cc,ARM_M,rn,im) +# define STMDA(rn,im) CC_STMDA(ARM_CC_AL,rn,im) +# define CC_STMDA_U(cc,rn,im) corl(cc,ARM_M|ARM_M_U,rn,im) +# define STMDA_U(rn,im) CC_STMDA_U(ARM_CC_AL,rn,im) +# define CC_STMDB(cc,rn,im) corl(cc,ARM_M|ARM_M_B,rn,im) +# define STMDB(rn,im) CC_STMDB(ARM_CC_AL,rn,im) +# define CC_STMDB_U(cc,rn,im) corl(cc,ARM_M|ARM_M_B|ARM_M_U,rn,im) +# define STMDB_U(rn,im) CC_STMDB_U(ARM_CC_AL,rn,im) +# define CC_PUSH(cc,im) CC_STMDB_U(cc,_SP_REGNO,im) +# define PUSH(im) STMDB_U(_SP_REGNO,im) +# define T1_PUSH(im) is(THUMB_PUSH|((im&0x4000)>>6)|(im&0xff)) +# define T2_PUSH(im) tpp(THUMB2_PUSH,im) +# define CC_POP(cc,im) LDMIA_U(cc,_SP_REGNO,im) +# define POP(im) LDMIA_U(_SP_REGNO,im) +# define T1_POP(im) is(THUMB_POP|((im&0x8000)>>7)|(im&0xff)) +# define T2_POP(im) tpp(THUMB2_POP,im) +# define jit_get_reg_args() \ + do { \ + (void)jit_get_reg(_R0|jit_class_named|jit_class_gpr); \ + (void)jit_get_reg(_R1|jit_class_named|jit_class_gpr); \ + (void)jit_get_reg(_R2|jit_class_named|jit_class_gpr); \ + (void)jit_get_reg(_R3|jit_class_named|jit_class_gpr); \ } while (0) -# define jit_unget_reg_args() \ - do { \ - jit_unget_reg(_R3); \ - jit_unget_reg(_R2); \ - jit_unget_reg(_R1); \ - jit_unget_reg(_R0); \ +# define jit_unget_reg_args() \ + do { \ + jit_unget_reg(_R3); \ + jit_unget_reg(_R2); \ + jit_unget_reg(_R1); \ + jit_unget_reg(_R0); \ } while (0) -# define nop(i0) _nop(_jit,i0) +# define nop(i0) _nop(_jit,i0) static void _nop(jit_state_t*,int32_t); -# define movr(r0,r1) _movr(_jit,r0,r1) +# define movr(r0,r1) _movr(_jit,r0,r1) static void _movr(jit_state_t*,int32_t,int32_t); -# define movi(r0,i0) _movi(_jit,r0,i0) +# define movi(r0,i0) _movi(_jit,r0,i0) static void _movi(jit_state_t*,int32_t,jit_word_t); -# define movi_p(r0,i0) _movi_p(_jit,r0,i0) +# define movi_p(r0,i0) _movi_p(_jit,r0,i0) static jit_word_t _movi_p(jit_state_t*,int32_t,jit_word_t); -# define comr(r0,r1) _comr(_jit,r0,r1) +# define comr(r0,r1) _comr(_jit,r0,r1) static void _comr(jit_state_t*,int32_t,int32_t); -# define negr(r0,r1) _negr(_jit,r0,r1) +# define negr(r0,r1) _negr(_jit,r0,r1) static void _negr(jit_state_t*,int32_t,int32_t); -# define addr(r0,r1,r2) _addr(_jit,r0,r1,r2) +# define addr(r0,r1,r2) _addr(_jit,r0,r1,r2) static void _addr(jit_state_t*,int32_t,int32_t,int32_t); -# define addi(r0,r1,i0) _addi(_jit,r0,r1,i0) +# define addi(r0,r1,i0) _addi(_jit,r0,r1,i0) static void _addi(jit_state_t*,int32_t,int32_t,jit_word_t); -# define addcr(r0,r1,r2) _addcr(_jit,r0,r1,r2) +# define addcr(r0,r1,r2) _addcr(_jit,r0,r1,r2) static void _addcr(jit_state_t*,int32_t,int32_t,int32_t); -# define addci(r0,r1,i0) _addci(_jit,r0,r1,i0) +# define addci(r0,r1,i0) _addci(_jit,r0,r1,i0) static void _addci(jit_state_t*,int32_t,int32_t,jit_word_t); -# define addxr(r0,r1,r2) _addxr(_jit,r0,r1,r2) +# define addxr(r0,r1,r2) _addxr(_jit,r0,r1,r2) static void _addxr(jit_state_t*,int32_t,int32_t,int32_t); -# define addxi(r0,r1,i0) _addxi(_jit,r0,r1,i0) +# define addxi(r0,r1,i0) _addxi(_jit,r0,r1,i0) static void _addxi(jit_state_t*,int32_t,int32_t,jit_word_t); -# define subr(r0,r1,r2) _subr(_jit,r0,r1,r2) +# define subr(r0,r1,r2) _subr(_jit,r0,r1,r2) static void _subr(jit_state_t*,int32_t,int32_t,int32_t); -# define subi(r0,r1,i0) _subi(_jit,r0,r1,i0) +# define subi(r0,r1,i0) _subi(_jit,r0,r1,i0) static void _subi(jit_state_t*,int32_t,int32_t,jit_word_t); -# define subcr(r0,r1,r2) _subcr(_jit,r0,r1,r2) +# define subcr(r0,r1,r2) _subcr(_jit,r0,r1,r2) static void _subcr(jit_state_t*,int32_t,int32_t,int32_t); -# define subci(r0,r1,i0) _subci(_jit,r0,r1,i0) +# define subci(r0,r1,i0) _subci(_jit,r0,r1,i0) static void _subci(jit_state_t*,int32_t,int32_t,jit_word_t); -# define subxr(r0,r1,r2) _subxr(_jit,r0,r1,r2) +# define subxr(r0,r1,r2) _subxr(_jit,r0,r1,r2) static void _subxr(jit_state_t*,int32_t,int32_t,int32_t); -# define subxi(r0,r1,i0) _subxi(_jit,r0,r1,i0) +# define subxi(r0,r1,i0) _subxi(_jit,r0,r1,i0) static void _subxi(jit_state_t*,int32_t,int32_t,jit_word_t); -# define rsbi(r0, r1, i0) _rsbi(_jit, r0, r1, i0) +# define rsbi(r0, r1, i0) _rsbi(_jit, r0, r1, i0) static void _rsbi(jit_state_t*,int32_t,int32_t,jit_word_t); -# define mulr(r0,r1,r2) _mulr(_jit,r0,r1,r2) +# define mulr(r0,r1,r2) _mulr(_jit,r0,r1,r2) static void _mulr(jit_state_t*,int32_t,int32_t,int32_t); -# define muli(r0,r1,i0) _muli(_jit,r0,r1,i0) +# define muli(r0,r1,i0) _muli(_jit,r0,r1,i0) static void _muli(jit_state_t*,int32_t,int32_t,jit_word_t); -# define qmulr(r0,r1,r2,r3) iqmulr(r0,r1,r2,r3,1) -# define qmulr_u(r0,r1,r2,r3) iqmulr(r0,r1,r2,r3,0) -# define iqmulr(r0,r1,r2,r3,cc) _iqmulr(_jit,r0,r1,r2,r3,cc) +# define qmulr(r0,r1,r2,r3) iqmulr(r0,r1,r2,r3,1) +# define qmulr_u(r0,r1,r2,r3) iqmulr(r0,r1,r2,r3,0) +# define iqmulr(r0,r1,r2,r3,cc) _iqmulr(_jit,r0,r1,r2,r3,cc) static void _iqmulr(jit_state_t*,int32_t,int32_t, - int32_t,int32_t,jit_bool_t); -# define qmuli(r0,r1,r2,i0) iqmuli(r0,r1,r2,i0,1) -# define qmuli_u(r0,r1,r2,i0) iqmuli(r0,r1,r2,i0,0) -# define iqmuli(r0,r1,r2,i0,cc) _iqmuli(_jit,r0,r1,r2,i0,cc) + int32_t,int32_t,jit_bool_t); +# define qmuli(r0,r1,r2,i0) iqmuli(r0,r1,r2,i0,1) +# define qmuli_u(r0,r1,r2,i0) iqmuli(r0,r1,r2,i0,0) +# define iqmuli(r0,r1,r2,i0,cc) _iqmuli(_jit,r0,r1,r2,i0,cc) static void _iqmuli(jit_state_t*,int32_t,int32_t, - int32_t,jit_word_t,jit_bool_t); -# define divrem(d,s,r0,r1,r2) _divrem(_jit,d,s,r0,r1,r2) + int32_t,jit_word_t,jit_bool_t); +# define divrem(d,s,r0,r1,r2) _divrem(_jit,d,s,r0,r1,r2) static void _divrem(jit_state_t*,int,int,int32_t,int32_t,int32_t); -# define divr(r0,r1,r2) _divr(_jit,r0,r1,r2) +# define divr(r0,r1,r2) _divr(_jit,r0,r1,r2) static void _divr(jit_state_t*,int32_t,int32_t,int32_t); -# define divi(r0,r1,i0) _divi(_jit,r0,r1,i0) +# define divi(r0,r1,i0) _divi(_jit,r0,r1,i0) static void _divi(jit_state_t*,int32_t,int32_t,jit_word_t); -# define divr_u(r0,r1,r2) _divr_u(_jit,r0,r1,r2) +# define divr_u(r0,r1,r2) _divr_u(_jit,r0,r1,r2) static void _divr_u(jit_state_t*,int32_t,int32_t,int32_t); -# define divi_u(r0,r1,i0) _divi_u(_jit,r0,r1,i0) +# define divi_u(r0,r1,i0) _divi_u(_jit,r0,r1,i0) static void _divi_u(jit_state_t*,int32_t,int32_t,jit_word_t); -# define qdivr(r0,r1,r2,r3) iqdivr(r0,r1,r2,r3,1) -# define qdivr_u(r0,r1,r2,r3) iqdivr(r0,r1,r2,r3,0) -# define iqdivr(r0,r1,r2,r3,cc) _iqdivr(_jit,r0,r1,r2,r3,cc) +# define qdivr(r0,r1,r2,r3) iqdivr(r0,r1,r2,r3,1) +# define qdivr_u(r0,r1,r2,r3) iqdivr(r0,r1,r2,r3,0) +# define iqdivr(r0,r1,r2,r3,cc) _iqdivr(_jit,r0,r1,r2,r3,cc) static void _iqdivr(jit_state_t*,int32_t,int32_t, - int32_t,int32_t,jit_bool_t); -# define qdivi(r0,r1,r2,i0) iqdivi(r0,r1,r2,i0,1) -# define qdivi_u(r0,r1,r2,i0) iqdivi(r0,r1,r2,i0,0) -# define iqdivi(r0,r1,r2,i0,cc) _iqdivi(_jit,r0,r1,r2,i0,cc) + int32_t,int32_t,jit_bool_t); +# define qdivi(r0,r1,r2,i0) iqdivi(r0,r1,r2,i0,1) +# define qdivi_u(r0,r1,r2,i0) iqdivi(r0,r1,r2,i0,0) +# define iqdivi(r0,r1,r2,i0,cc) _iqdivi(_jit,r0,r1,r2,i0,cc) static void _iqdivi(jit_state_t*,int32_t,int32_t, - int32_t,jit_word_t,jit_bool_t); -# define remr(r0,r1,r2) _remr(_jit,r0,r1,r2) + int32_t,jit_word_t,jit_bool_t); +# define remr(r0,r1,r2) _remr(_jit,r0,r1,r2) static void _remr(jit_state_t*,int32_t,int32_t,int32_t); -# define remi(r0,r1,i0) _remi(_jit,r0,r1,i0) +# define remi(r0,r1,i0) _remi(_jit,r0,r1,i0) static void _remi(jit_state_t*,int32_t,int32_t,jit_word_t); -# define remr_u(r0,r1,r2) _remr_u(_jit,r0,r1,r2) +# define remr_u(r0,r1,r2) _remr_u(_jit,r0,r1,r2) static void _remr_u(jit_state_t*,int32_t,int32_t,int32_t); -# define remi_u(r0,r1,i0) _remi_u(_jit,r0,r1,i0) +# define remi_u(r0,r1,i0) _remi_u(_jit,r0,r1,i0) static void _remi_u(jit_state_t*,int32_t,int32_t,jit_word_t); -# define andr(r0,r1,r2) _andr(_jit,r0,r1,r2) +# define andr(r0,r1,r2) _andr(_jit,r0,r1,r2) static void _andr(jit_state_t*,int32_t,int32_t,int32_t); -# define andi(r0,r1,i0) _andi(_jit,r0,r1,i0) +# define andi(r0,r1,i0) _andi(_jit,r0,r1,i0) static void _andi(jit_state_t*,int32_t,int32_t,jit_word_t); -# define orr(r0,r1,r2) _orr(_jit,r0,r1,r2) +# define orr(r0,r1,r2) _orr(_jit,r0,r1,r2) static void _orr(jit_state_t*,int32_t,int32_t,int32_t); -# define ori(r0,r1,i0) _ori(_jit,r0,r1,i0) +# define ori(r0,r1,i0) _ori(_jit,r0,r1,i0) static void _ori(jit_state_t*,int32_t,int32_t,jit_word_t); -# define xorr(r0,r1,r2) _xorr(_jit,r0,r1,r2) +# define xorr(r0,r1,r2) _xorr(_jit,r0,r1,r2) static void _xorr(jit_state_t*,int32_t,int32_t,int32_t); -# define xori(r0,r1,i0) _xori(_jit,r0,r1,i0) +# define xori(r0,r1,i0) _xori(_jit,r0,r1,i0) static void _xori(jit_state_t*,int32_t,int32_t,jit_word_t); -# define lshr(r0,r1,r2) _lshr(_jit,r0,r1,r2) +# define lshr(r0,r1,r2) _lshr(_jit,r0,r1,r2) static void _lshr(jit_state_t*,int32_t,int32_t,int32_t); -# define lshi(r0,r1,i0) _lshi(_jit,r0,r1,i0) +# define lshi(r0,r1,i0) _lshi(_jit,r0,r1,i0) static void _lshi(jit_state_t*,int32_t,int32_t,jit_word_t); -# define rshr(r0,r1,r2) _rshr(_jit,r0,r1,r2) +# define rshr(r0,r1,r2) _rshr(_jit,r0,r1,r2) static void _rshr(jit_state_t*,int32_t,int32_t,int32_t); -# define rshi(r0,r1,i0) _rshi(_jit,r0,r1,i0) +# define rshi(r0,r1,i0) _rshi(_jit,r0,r1,i0) static void _rshi(jit_state_t*,int32_t,int32_t,jit_word_t); -# define rshr_u(r0,r1,r2) _rshr_u(_jit,r0,r1,r2) +# define rshr_u(r0,r1,r2) _rshr_u(_jit,r0,r1,r2) static void _rshr_u(jit_state_t*,int32_t,int32_t,int32_t); -# define rshi_u(r0,r1,i0) _rshi_u(_jit,r0,r1,i0) +# define rshi_u(r0,r1,i0) _rshi_u(_jit,r0,r1,i0) static void _rshi_u(jit_state_t*,int32_t,int32_t,jit_word_t); -# define ccr(ct,cf,r0,r1,r2) _ccr(_jit,ct,cf,r0,r1,r2) +# define ccr(ct,cf,r0,r1,r2) _ccr(_jit,ct,cf,r0,r1,r2) static void _ccr(jit_state_t*,int,int,int32_t,int32_t,int32_t); -# define cci(ct,cf,r0,r1,i0) _cci(_jit,ct,cf,r0,r1,i0) +# define cci(ct,cf,r0,r1,i0) _cci(_jit,ct,cf,r0,r1,i0) static void _cci(jit_state_t*,int,int,int32_t,int32_t,jit_word_t); -# define ltr(r0, r1, r2) ccr(ARM_CC_LT,ARM_CC_GE,r0,r1,r2) -# define lti(r0, r1, i0) cci(ARM_CC_LT,ARM_CC_GE,r0,r1,i0) -# define ltr_u(r0, r1, r2) ccr(ARM_CC_LO,ARM_CC_HS,r0,r1,r2) -# define lti_u(r0, r1, i0) cci(ARM_CC_LO,ARM_CC_HS,r0,r1,i0) -# define ler(r0, r1, r2) ccr(ARM_CC_LE,ARM_CC_GT,r0,r1,r2) -# define lei(r0, r1, i0) cci(ARM_CC_LE,ARM_CC_GT,r0,r1,i0) -# define ler_u(r0, r1, r2) ccr(ARM_CC_LS,ARM_CC_HI,r0,r1,r2) -# define lei_u(r0, r1, i0) cci(ARM_CC_LS,ARM_CC_HI,r0,r1,i0) -# define eqr(r0, r1, r2) ccr(ARM_CC_EQ,ARM_CC_NE,r0,r1,r2) -# define eqi(r0, r1, i0) cci(ARM_CC_EQ,ARM_CC_NE,r0,r1,i0) -# define ger(r0, r1, r2) ccr(ARM_CC_GE,ARM_CC_LT,r0,r1,r2) -# define gei(r0, r1, i0) cci(ARM_CC_GE,ARM_CC_LT,r0,r1,i0) -# define ger_u(r0, r1, r2) ccr(ARM_CC_HS,ARM_CC_LO,r0,r1,r2) -# define gei_u(r0, r1, i0) cci(ARM_CC_HS,ARM_CC_LO,r0,r1,i0) -# define gtr(r0, r1, r2) ccr(ARM_CC_GT,ARM_CC_LE,r0,r1,r2) -# define gti(r0, r1, i0) cci(ARM_CC_GT,ARM_CC_LE,r0,r1,i0) -# define gtr_u(r0, r1, r2) ccr(ARM_CC_HI,ARM_CC_LS,r0,r1,r2) -# define gti_u(r0, r1, i0) cci(ARM_CC_HI,ARM_CC_LS,r0,r1,i0) -# define ner(r0,r1,r2) _ner(_jit,r0,r1,r2) +# define ltr(r0, r1, r2) ccr(ARM_CC_LT,ARM_CC_GE,r0,r1,r2) +# define lti(r0, r1, i0) cci(ARM_CC_LT,ARM_CC_GE,r0,r1,i0) +# define ltr_u(r0, r1, r2) ccr(ARM_CC_LO,ARM_CC_HS,r0,r1,r2) +# define lti_u(r0, r1, i0) cci(ARM_CC_LO,ARM_CC_HS,r0,r1,i0) +# define ler(r0, r1, r2) ccr(ARM_CC_LE,ARM_CC_GT,r0,r1,r2) +# define lei(r0, r1, i0) cci(ARM_CC_LE,ARM_CC_GT,r0,r1,i0) +# define ler_u(r0, r1, r2) ccr(ARM_CC_LS,ARM_CC_HI,r0,r1,r2) +# define lei_u(r0, r1, i0) cci(ARM_CC_LS,ARM_CC_HI,r0,r1,i0) +# define eqr(r0, r1, r2) ccr(ARM_CC_EQ,ARM_CC_NE,r0,r1,r2) +# define eqi(r0, r1, i0) cci(ARM_CC_EQ,ARM_CC_NE,r0,r1,i0) +# define ger(r0, r1, r2) ccr(ARM_CC_GE,ARM_CC_LT,r0,r1,r2) +# define gei(r0, r1, i0) cci(ARM_CC_GE,ARM_CC_LT,r0,r1,i0) +# define ger_u(r0, r1, r2) ccr(ARM_CC_HS,ARM_CC_LO,r0,r1,r2) +# define gei_u(r0, r1, i0) cci(ARM_CC_HS,ARM_CC_LO,r0,r1,i0) +# define gtr(r0, r1, r2) ccr(ARM_CC_GT,ARM_CC_LE,r0,r1,r2) +# define gti(r0, r1, i0) cci(ARM_CC_GT,ARM_CC_LE,r0,r1,i0) +# define gtr_u(r0, r1, r2) ccr(ARM_CC_HI,ARM_CC_LS,r0,r1,r2) +# define gti_u(r0, r1, i0) cci(ARM_CC_HI,ARM_CC_LS,r0,r1,i0) +# define ner(r0,r1,r2) _ner(_jit,r0,r1,r2) static void _ner(jit_state_t*,int32_t,int32_t,int32_t); -# define nei(r0,r1,i0) _nei(_jit,r0,r1,i0) +# define nei(r0,r1,i0) _nei(_jit,r0,r1,i0) static void _nei(jit_state_t*,int32_t,int32_t,jit_word_t); -# define jmpr(r0) _jmpr(_jit,r0) +# define jmpr(r0) _jmpr(_jit,r0) static void _jmpr(jit_state_t*,int32_t); -# define jmpi(i0) _jmpi(_jit,i0) +# define jmpi(i0) _jmpi(_jit,i0) static void _jmpi(jit_state_t*,jit_word_t); -# define jmpi_p(i0, i1) _jmpi_p(_jit,i0, i1) +# define jmpi_p(i0, i1) _jmpi_p(_jit,i0, i1) static jit_word_t _jmpi_p(jit_state_t*,jit_word_t,jit_bool_t); -# define bccr(cc,i0,r0,r1) _bccr(_jit,cc,i0,r0,r1) +# define bccr(cc,i0,r0,r1) _bccr(_jit,cc,i0,r0,r1) static jit_word_t _bccr(jit_state_t*,int,jit_word_t,int32_t,int32_t); -# define bcci(cc,i0,r0,i1) _bcci(_jit,cc,i0,r0,i1) +# define bcci(cc,i0,r0,i1) _bcci(_jit,cc,i0,r0,i1) static jit_word_t _bcci(jit_state_t*,int,jit_word_t,int32_t,jit_word_t); -# define bltr(i0, r0, r1) bccr(ARM_CC_LT,i0,r0,r1) -# define blti(i0, r0, i1) bcci(ARM_CC_LT,i0,r0,i1) -# define bltr_u(i0, r0, r1) bccr(ARM_CC_LO,i0,r0,r1) -# define blti_u(i0, r0, i1) bcci(ARM_CC_LO,i0,r0,i1) -# define bler(i0, r0, r1) bccr(ARM_CC_LE,i0,r0,r1) -# define blei(i0, r0, i1) bcci(ARM_CC_LE,i0,r0,i1) -# define bler_u(i0, r0, r1) bccr(ARM_CC_LS,i0,r0,r1) -# define blei_u(i0, r0, i1) bcci(ARM_CC_LS,i0,r0,i1) -# define beqr(i0, r0, r1) bccr(ARM_CC_EQ,i0,r0,r1) -# define beqi(i0, r0, i1) bcci(ARM_CC_EQ,i0,r0,i1) -# define bger(i0, r0, r1) bccr(ARM_CC_GE,i0,r0,r1) -# define bgei(i0, r0, i1) bcci(ARM_CC_GE,i0,r0,i1) -# define bger_u(i0, r0, r1) bccr(ARM_CC_HS,i0,r0,r1) -# define bgei_u(i0, r0, i1) bcci(ARM_CC_HS,i0,r0,i1) -# define bgtr(i0, r0, r1) bccr(ARM_CC_GT,i0,r0,r1) -# define bgti(i0, r0, i1) bcci(ARM_CC_GT,i0,r0,i1) -# define bgtr_u(i0, r0, r1) bccr(ARM_CC_HI,i0,r0,r1) -# define bgti_u(i0, r0, i1) bcci(ARM_CC_HI,i0,r0,i1) -# define bner(i0, r0, r1) bccr(ARM_CC_NE,i0,r0,r1) -# define bnei(i0, r0, i1) bcci(ARM_CC_NE,i0,r0,i1) -# define baddr(cc,i0,r0,r1) _baddr(_jit,cc,i0,r0,r1) +# define bltr(i0, r0, r1) bccr(ARM_CC_LT,i0,r0,r1) +# define blti(i0, r0, i1) bcci(ARM_CC_LT,i0,r0,i1) +# define bltr_u(i0, r0, r1) bccr(ARM_CC_LO,i0,r0,r1) +# define blti_u(i0, r0, i1) bcci(ARM_CC_LO,i0,r0,i1) +# define bler(i0, r0, r1) bccr(ARM_CC_LE,i0,r0,r1) +# define blei(i0, r0, i1) bcci(ARM_CC_LE,i0,r0,i1) +# define bler_u(i0, r0, r1) bccr(ARM_CC_LS,i0,r0,r1) +# define blei_u(i0, r0, i1) bcci(ARM_CC_LS,i0,r0,i1) +# define beqr(i0, r0, r1) bccr(ARM_CC_EQ,i0,r0,r1) +# define beqi(i0, r0, i1) bcci(ARM_CC_EQ,i0,r0,i1) +# define bger(i0, r0, r1) bccr(ARM_CC_GE,i0,r0,r1) +# define bgei(i0, r0, i1) bcci(ARM_CC_GE,i0,r0,i1) +# define bger_u(i0, r0, r1) bccr(ARM_CC_HS,i0,r0,r1) +# define bgei_u(i0, r0, i1) bcci(ARM_CC_HS,i0,r0,i1) +# define bgtr(i0, r0, r1) bccr(ARM_CC_GT,i0,r0,r1) +# define bgti(i0, r0, i1) bcci(ARM_CC_GT,i0,r0,i1) +# define bgtr_u(i0, r0, r1) bccr(ARM_CC_HI,i0,r0,r1) +# define bgti_u(i0, r0, i1) bcci(ARM_CC_HI,i0,r0,i1) +# define bner(i0, r0, r1) bccr(ARM_CC_NE,i0,r0,r1) +# define bnei(i0, r0, i1) bcci(ARM_CC_NE,i0,r0,i1) +# define baddr(cc,i0,r0,r1) _baddr(_jit,cc,i0,r0,r1) static jit_word_t _baddr(jit_state_t*,int,jit_word_t,int32_t,int32_t); -# define baddi(cc,i0,r0,r1) _baddi(_jit,cc,i0,r0,r1) +# define baddi(cc,i0,r0,r1) _baddi(_jit,cc,i0,r0,r1) static jit_word_t _baddi(jit_state_t*,int,jit_word_t,int32_t,jit_word_t); -# define boaddr(i0,r0,r1) baddr(ARM_CC_VS,i0,r0,r1) -# define boaddi(i0,r0,i1) baddi(ARM_CC_VS,i0,r0,i1) -# define boaddr_u(i0,r0,r1) baddr(ARM_CC_HS,i0,r0,r1) -# define boaddi_u(i0,r0,i1) baddi(ARM_CC_HS,i0,r0,i1) -# define bxaddr(i0,r0,r1) baddr(ARM_CC_VC,i0,r0,r1) -# define bxaddi(i0,r0,i1) baddi(ARM_CC_VC,i0,r0,i1) -# define bxaddr_u(i0,r0,r1) baddr(ARM_CC_LO,i0,r0,r1) -# define bxaddi_u(i0,r0,i1) baddi(ARM_CC_LO,i0,r0,i1) -# define bsubr(cc,i0,r0,r1) _bsubr(_jit,cc,i0,r0,r1) +# define boaddr(i0,r0,r1) baddr(ARM_CC_VS,i0,r0,r1) +# define boaddi(i0,r0,i1) baddi(ARM_CC_VS,i0,r0,i1) +# define boaddr_u(i0,r0,r1) baddr(ARM_CC_HS,i0,r0,r1) +# define boaddi_u(i0,r0,i1) baddi(ARM_CC_HS,i0,r0,i1) +# define bxaddr(i0,r0,r1) baddr(ARM_CC_VC,i0,r0,r1) +# define bxaddi(i0,r0,i1) baddi(ARM_CC_VC,i0,r0,i1) +# define bxaddr_u(i0,r0,r1) baddr(ARM_CC_LO,i0,r0,r1) +# define bxaddi_u(i0,r0,i1) baddi(ARM_CC_LO,i0,r0,i1) +# define bsubr(cc,i0,r0,r1) _bsubr(_jit,cc,i0,r0,r1) static jit_word_t _bsubr(jit_state_t*,int,jit_word_t,int32_t,int32_t); -# define bsubi(cc,i0,r0,r1) _bsubi(_jit,cc,i0,r0,r1) +# define bsubi(cc,i0,r0,r1) _bsubi(_jit,cc,i0,r0,r1) static jit_word_t _bsubi(jit_state_t*,int,jit_word_t,int32_t,jit_word_t); -# define bosubr(i0,r0,r1) bsubr(ARM_CC_VS,i0,r0,r1) -# define bosubi(i0,r0,i1) bsubi(ARM_CC_VS,i0,r0,i1) -# define bosubr_u(i0,r0,r1) bsubr(ARM_CC_LO,i0,r0,r1) -# define bosubi_u(i0,r0,i1) bsubi(ARM_CC_LO,i0,r0,i1) -# define bxsubr(i0,r0,r1) bsubr(ARM_CC_VC,i0,r0,r1) -# define bxsubi(i0,r0,i1) bsubi(ARM_CC_VC,i0,r0,i1) -# define bxsubr_u(i0,r0,r1) bsubr(ARM_CC_HS,i0,r0,r1) -# define bxsubi_u(i0,r0,i1) bsubi(ARM_CC_HS,i0,r0,i1) -# define bmxr(cc,i0,r0,r1) _bmxr(_jit,cc,i0,r0,r1) +# define bosubr(i0,r0,r1) bsubr(ARM_CC_VS,i0,r0,r1) +# define bosubi(i0,r0,i1) bsubi(ARM_CC_VS,i0,r0,i1) +# define bosubr_u(i0,r0,r1) bsubr(ARM_CC_LO,i0,r0,r1) +# define bosubi_u(i0,r0,i1) bsubi(ARM_CC_LO,i0,r0,i1) +# define bxsubr(i0,r0,r1) bsubr(ARM_CC_VC,i0,r0,r1) +# define bxsubi(i0,r0,i1) bsubi(ARM_CC_VC,i0,r0,i1) +# define bxsubr_u(i0,r0,r1) bsubr(ARM_CC_HS,i0,r0,r1) +# define bxsubi_u(i0,r0,i1) bsubi(ARM_CC_HS,i0,r0,i1) +# define bmxr(cc,i0,r0,r1) _bmxr(_jit,cc,i0,r0,r1) static jit_word_t _bmxr(jit_state_t*,int,jit_word_t,int32_t,int32_t); -# define bmxi(cc,i0,r0,r1) _bmxi(_jit,cc,i0,r0,r1) +# define bmxi(cc,i0,r0,r1) _bmxi(_jit,cc,i0,r0,r1) static jit_word_t _bmxi(jit_state_t*,int,jit_word_t,int32_t,jit_word_t); -# define bmsr(i0,r0,r1) bmxr(ARM_CC_NE,i0,r0,r1) -# define bmsi(i0,r0,i1) bmxi(ARM_CC_NE,i0,r0,i1) -# define bmcr(i0,r0,r1) bmxr(ARM_CC_EQ,i0,r0,r1) -# define bmci(i0,r0,i1) bmxi(ARM_CC_EQ,i0,r0,i1) -# define ldr_c(r0,r1) _ldr_c(_jit,r0,r1) +# define bmsr(i0,r0,r1) bmxr(ARM_CC_NE,i0,r0,r1) +# define bmsi(i0,r0,i1) bmxi(ARM_CC_NE,i0,r0,i1) +# define bmcr(i0,r0,r1) bmxr(ARM_CC_EQ,i0,r0,r1) +# define bmci(i0,r0,i1) bmxi(ARM_CC_EQ,i0,r0,i1) +# define ldr_c(r0,r1) _ldr_c(_jit,r0,r1) static void _ldr_c(jit_state_t*,int32_t,int32_t); -# define ldi_c(r0,i0) _ldi_c(_jit,r0,i0) +# define ldi_c(r0,i0) _ldi_c(_jit,r0,i0) static void _ldi_c(jit_state_t*,int32_t,jit_word_t); -# define ldxr_c(r0,r1,r2) _ldxr_c(_jit,r0,r1,r2) +# define ldxr_c(r0,r1,r2) _ldxr_c(_jit,r0,r1,r2) static void _ldxr_c(jit_state_t*,int32_t,int32_t,int32_t); -# define ldxi_c(r0,r1,i0) _ldxi_c(_jit,r0,r1,i0) +# define ldxi_c(r0,r1,i0) _ldxi_c(_jit,r0,r1,i0) static void _ldxi_c(jit_state_t*,int32_t,int32_t,jit_word_t); -# define ldr_uc(r0,r1) _ldr_uc(_jit,r0,r1) +# define ldr_uc(r0,r1) _ldr_uc(_jit,r0,r1) static void _ldr_uc(jit_state_t*,int32_t,int32_t); -# define ldi_uc(r0,i0) _ldi_uc(_jit,r0,i0) +# define ldi_uc(r0,i0) _ldi_uc(_jit,r0,i0) static void _ldi_uc(jit_state_t*,int32_t,jit_word_t); -# define ldxr_uc(r0,r1,r2) _ldxr_uc(_jit,r0,r1,r2) +# define ldxr_uc(r0,r1,r2) _ldxr_uc(_jit,r0,r1,r2) static void _ldxr_uc(jit_state_t*,int32_t,int32_t,int32_t); -# define ldxi_uc(r0,r1,i0) _ldxi_uc(_jit,r0,r1,i0) +# define ldxi_uc(r0,r1,i0) _ldxi_uc(_jit,r0,r1,i0) static void _ldxi_uc(jit_state_t*,int32_t,int32_t,jit_word_t); -# define ldr_s(r0,r1) _ldr_s(_jit,r0,r1) +# define ldr_s(r0,r1) _ldr_s(_jit,r0,r1) static void _ldr_s(jit_state_t*,int32_t,int32_t); -# define ldi_s(r0,i0) _ldi_s(_jit,r0,i0) +# define ldi_s(r0,i0) _ldi_s(_jit,r0,i0) static void _ldi_s(jit_state_t*,int32_t,jit_word_t); -# define ldxr_s(r0,r1,r2) _ldxr_s(_jit,r0,r1,r2) +# define ldxr_s(r0,r1,r2) _ldxr_s(_jit,r0,r1,r2) static void _ldxr_s(jit_state_t*,int32_t,int32_t,int32_t); -# define ldxi_s(r0,r1,i0) _ldxi_s(_jit,r0,r1,i0) +# define ldxi_s(r0,r1,i0) _ldxi_s(_jit,r0,r1,i0) static void _ldxi_s(jit_state_t*,int32_t,int32_t,jit_word_t); -# define ldr_us(r0,r1) _ldr_us(_jit,r0,r1) +# define ldr_us(r0,r1) _ldr_us(_jit,r0,r1) static void _ldr_us(jit_state_t*,int32_t,int32_t); -# define ldi_us(r0,i0) _ldi_us(_jit,r0,i0) +# define ldi_us(r0,i0) _ldi_us(_jit,r0,i0) static void _ldi_us(jit_state_t*,int32_t,jit_word_t); -# define ldxr_us(r0,r1,r2) _ldxr_us(_jit,r0,r1,r2) +# define ldxr_us(r0,r1,r2) _ldxr_us(_jit,r0,r1,r2) static void _ldxr_us(jit_state_t*,int32_t,int32_t,int32_t); -# define ldxi_us(r0,r1,i0) _ldxi_us(_jit,r0,r1,i0) +# define ldxi_us(r0,r1,i0) _ldxi_us(_jit,r0,r1,i0) static void _ldxi_us(jit_state_t*,int32_t,int32_t,jit_word_t); -# define ldr_i(r0,r1) _ldr_i(_jit,r0,r1) +# define ldr_i(r0,r1) _ldr_i(_jit,r0,r1) static void _ldr_i(jit_state_t*,int32_t,int32_t); -# define ldi_i(r0,i0) _ldi_i(_jit,r0,i0) +# define ldi_i(r0,i0) _ldi_i(_jit,r0,i0) static void _ldi_i(jit_state_t*,int32_t,jit_word_t); -# define ldxr_i(r0,r1,r2) _ldxr_i(_jit,r0,r1,r2) +# define ldxr_i(r0,r1,r2) _ldxr_i(_jit,r0,r1,r2) static void _ldxr_i(jit_state_t*,int32_t,int32_t,int32_t); -# define ldxi_i(r0,r1,i0) _ldxi_i(_jit,r0,r1,i0) +# define ldxi_i(r0,r1,i0) _ldxi_i(_jit,r0,r1,i0) static void _ldxi_i(jit_state_t*,int32_t,int32_t,jit_word_t); -# define str_c(r0,r1) _str_c(_jit,r0,r1) +# define str_c(r0,r1) _str_c(_jit,r0,r1) static void _str_c(jit_state_t*,int32_t,int32_t); -# define sti_c(i0,r0) _sti_c(_jit,i0,r0) +# define sti_c(i0,r0) _sti_c(_jit,i0,r0) static void _sti_c(jit_state_t*,jit_word_t,int32_t); -# define stxr_c(r0,r1,r2) _stxr_c(_jit,r0,r1,r2) +# define stxr_c(r0,r1,r2) _stxr_c(_jit,r0,r1,r2) static void _stxr_c(jit_state_t*,int32_t,int32_t,int32_t); -# define stxi_c(r0,r1,i0) _stxi_c(_jit,r0,r1,i0) +# define stxi_c(r0,r1,i0) _stxi_c(_jit,r0,r1,i0) static void _stxi_c(jit_state_t*,jit_word_t,int32_t,int32_t); -# define str_s(r0,r1) _str_s(_jit,r0,r1) +# define str_s(r0,r1) _str_s(_jit,r0,r1) static void _str_s(jit_state_t*,int32_t,int32_t); -# define sti_s(i0,r0) _sti_s(_jit,i0,r0) +# define sti_s(i0,r0) _sti_s(_jit,i0,r0) static void _sti_s(jit_state_t*,jit_word_t,int32_t); -# define stxr_s(r0,r1,r2) _stxr_s(_jit,r0,r1,r2) +# define stxr_s(r0,r1,r2) _stxr_s(_jit,r0,r1,r2) static void _stxr_s(jit_state_t*,int32_t,int32_t,int32_t); -# define stxi_s(r0,r1,i0) _stxi_s(_jit,r0,r1,i0) +# define stxi_s(r0,r1,i0) _stxi_s(_jit,r0,r1,i0) static void _stxi_s(jit_state_t*,jit_word_t,int32_t,int32_t); -# define str_i(r0,r1) _str_i(_jit,r0,r1) +# define str_i(r0,r1) _str_i(_jit,r0,r1) static void _str_i(jit_state_t*,int32_t,int32_t); -# define sti_i(i0,r0) _sti_i(_jit,i0,r0) +# define sti_i(i0,r0) _sti_i(_jit,i0,r0) static void _sti_i(jit_state_t*,jit_word_t,int32_t); -# define stxr_i(r0,r1,r2) _stxr_i(_jit,r0,r1,r2) +# define stxr_i(r0,r1,r2) _stxr_i(_jit,r0,r1,r2) static void _stxr_i(jit_state_t*,jit_word_t,int32_t,int32_t); -# define stxi_i(r0,r1,i0) _stxi_i(_jit,r0,r1,i0) +# define stxi_i(r0,r1,i0) _stxi_i(_jit,r0,r1,i0) static void _stxi_i(jit_state_t*,jit_word_t,int32_t,int32_t); # if __BYTE_ORDER == __LITTLE_ENDIAN -# define bswapr_us(r0,r1) _bswapr_us(_jit,r0,r1) +# define bswapr_us(r0,r1) _bswapr_us(_jit,r0,r1) static void _bswapr_us(jit_state_t*,int32_t,int32_t); -# define bswapr_ui(r0,r1) _bswapr_ui(_jit,r0,r1) +# define bswapr_ui(r0,r1) _bswapr_ui(_jit,r0,r1) static void _bswapr_ui(jit_state_t*,int32_t,int32_t); # else -# define bswapr_us(r0,r1) extr_us(r0,r1) -# define bswapr(r0,r1) movr(r0,r1) +# define bswapr_us(r0,r1) extr_us(r0,r1) +# define bswapr(r0,r1) movr(r0,r1) # endif -# define extr_c(r0,r1) _extr_c(_jit,r0,r1) +# define extr_c(r0,r1) _extr_c(_jit,r0,r1) static void _extr_c(jit_state_t*,int32_t,int32_t); -# define extr_uc(r0,r1) _extr_uc(_jit,r0,r1) +# define extr_uc(r0,r1) _extr_uc(_jit,r0,r1) static void _extr_uc(jit_state_t*,int32_t,int32_t); -# define extr_s(r0,r1) _extr_s(_jit,r0,r1) +# define extr_s(r0,r1) _extr_s(_jit,r0,r1) static void _extr_s(jit_state_t*,int32_t,int32_t); -# define extr_us(r0,r1) _extr_us(_jit,r0,r1) +# define extr_us(r0,r1) _extr_us(_jit,r0,r1) static void _extr_us(jit_state_t*,int32_t,int32_t); -# define prolog(i0) _prolog(_jit,i0) +# define prolog(i0) _prolog(_jit,i0) static void _prolog(jit_state_t*,jit_node_t*); -# define epilog(i0) _epilog(_jit,i0) +# define epilog(i0) _epilog(_jit,i0) static void _epilog(jit_state_t*,jit_node_t*); -# define callr(r0) _callr(_jit,r0) +# define callr(r0) _callr(_jit,r0) static void _callr(jit_state_t*,int32_t); -# define calli(i0) _calli(_jit,i0) +# define calli(i0) _calli(_jit,i0) static void _calli(jit_state_t*,jit_word_t); -# define calli_p(i0) _calli_p(_jit,i0) +# define calli_p(i0) _calli_p(_jit,i0) static jit_word_t _calli_p(jit_state_t*,jit_word_t); -# define vastart(r0) _vastart(_jit, r0) +# define vastart(r0) _vastart(_jit, r0) static void _vastart(jit_state_t*, int32_t); -# define vaarg(r0, r1) _vaarg(_jit, r0, r1) +# define vaarg(r0, r1) _vaarg(_jit, r0, r1) static void _vaarg(jit_state_t*, int32_t, int32_t); -# define patch_at(kind,jump,label) _patch_at(_jit,kind,jump,label) +# define patch_at(kind,jump,label) _patch_at(_jit,kind,jump,label) static void _patch_at(jit_state_t*,int32_t,jit_word_t,jit_word_t); #endif #if CODE /* from binutils */ -# define rotate_left(v, n) (v << n | v >> (32 - n)) +# define rotate_left(v, n) (v << n | v >> (32 - n)) static int encode_arm_immediate(unsigned int v) { - unsigned int a, i; + unsigned int a, i; for (i = 0; i < 32; i += 2) - if ((a = rotate_left(v, i)) <= 0xff) - return (a | (i << 7)); + if ((a = rotate_left(v, i)) <= 0xff) + return (a | (i << 7)); return (-1); } @@ -1144,33 +1133,33 @@ encode_arm_immediate(unsigned int v) static int encode_thumb_immediate(unsigned int v) { - int i; - unsigned int m; - unsigned int n; + int i; + unsigned int m; + unsigned int n; /* 00000000 00000000 00000000 abcdefgh */ if ((v & 0xff) == v) - return (v); + return (v); /* 00000000 abcdefgh 00000000 abcdefgh */ if ((v & 0xff00ff) == v && ((v & 0xff0000) >> 16) == (v & 0xff)) - return ((v & 0xff) | (1 << 12)); + return ((v & 0xff) | (1 << 12)); /* abcdefgh 00000000 abcdefgh 00000000 */ if (((v & 0xffff0000) >> 16) == (v & 0xffff) && (v & 0xff) == 0) - return ((v & 0x000000ff) | (2 << 12)); + return ((v & 0x000000ff) | (2 << 12)); /* abcdefgh abcdefgh abcdefgh abcdefgh */ if ( (v & 0xff) == ((v & 0xff00) >> 8) && - ((v & 0xff00) >> 8) == ((v & 0xff0000) >> 16) && - ((v & 0xff0000) << 8) == (v & 0xff000000)) - return ((v & 0xff) | (3 << 12)); + ((v & 0xff00) >> 8) == ((v & 0xff0000) >> 16) && + ((v & 0xff0000) << 8) == (v & 0xff000000)) + return ((v & 0xff) | (3 << 12)); /* 1bcdefgh << 24 ... 1bcdefgh << 1 */ for (i = 8, m = 0xff000000, n = 0x80000000; - i < 23; i++, m >>= 1, n >>= 1) { - if ((v & m) == v && (v & n)) { - v >>= 32 - i; - if (!(i & 1)) - v &= 0x7f; - i >>= 1; - return (((i & 7) << 12) | ((i & 8) << 23) | v); - } + i < 23; i++, m >>= 1, n >>= 1) { + if ((v & m) == v && (v & n)) { + v >>= 32 - i; + if (!(i & 1)) + v &= 0x7f; + i >>= 1; + return (((i & 7) << 12) | ((i & 8) << 23) | v); + } } return (-1); } @@ -1179,21 +1168,21 @@ static int encode_thumb_word_immediate(unsigned int v) { if ((v & 0xfffff000) == 0) - return (((v & 0x800) << 15) | ((v & 0x700) << 4) | (v & 0xff)); + return (((v & 0x800) << 15) | ((v & 0x700) << 4) | (v & 0xff)); return (-1); } static int encode_thumb_jump(int v) { - int s, i1, i2, j1, j2; + int s, i1, i2, j1, j2; if (v >= (int)-0x800000 && v <= 0x7fffff) { - s = !!(v & 0x800000); - i1 = !!(v & 0x400000); - i2 = !!(v & 0x200000); - j1 = s ? i1 : !i1; - j2 = s ? i2 : !i2; - return ((s<<26)|((v&0x1ff800)<<5)|(j1<<13)|(j2<<11)|(v&0x7ff)); + s = !!(v & 0x800000); + i1 = !!(v & 0x400000); + i2 = !!(v & 0x200000); + j1 = s ? i1 : !i1; + j2 = s ? i2 : !i2; + return ((s<<26)|((v&0x1ff800)<<5)|(j1<<13)|(j2<<11)|(v&0x7ff)); } return (-1); } @@ -1201,12 +1190,12 @@ encode_thumb_jump(int v) static int encode_thumb_cc_jump(int v) { - int s, j1, j2; + int s, j1, j2; if (v >= (int)-0x80000 && v <= 0x7ffff) { - s = !!(v & 0x80000); - j1 = !!(v & 0x20000); - j2 = !!(v & 0x40000); - return ((s<<26)|((v&0x1f800)<<5)|(j1<<13)|(j2<<11)|(v&0x7ff)); + s = !!(v & 0x80000); + j1 = !!(v & 0x20000); + j2 = !!(v & 0x40000); + return ((s<<26)|((v&0x1f800)<<5)|(j1<<13)|(j2<<11)|(v&0x7ff)); } return (-1); } @@ -1215,10 +1204,10 @@ static int encode_thumb_shift(int v, int type) { switch (type) { - case ARM_ASR: - case ARM_LSL: - case ARM_LSR: type >>= 1; break; - default: assert(!"handled shift"); + case ARM_ASR: + case ARM_LSL: + case ARM_LSR: type >>= 1; break; + default: assert(!"handled shift"); } assert(v >= 0 && v <= 31); return (((v & 0x1c) << 10) | ((v & 3) << 6) | type); @@ -1227,27 +1216,27 @@ encode_thumb_shift(int v, int type) static void _tcit(jit_state_t *_jit, unsigned int tc, int it) { - int c; - int m; + int c; + int m; c = (tc >> 28) & 1; assert(!(tc & 0xfffffff) && tc != ARM_CC_NV); switch (it) { - case THUMB2_IT: m = 1<<3; break; - case THUMB2_ITT: m = (c<<3)| (1<<2); break; - case THUMB2_ITE: m = (!c<<3)| (1<<2); break; - case THUMB2_ITTT: m = (c<<3)| (c<<2)| (1<<1); break; - case THUMB2_ITET: m = (!c<<3)| (c<<2)| (1<<1); break; - case THUMB2_ITTE: m = (c<<3)|(!c<<2)| (1<<1); break; - case THUMB2_ITEE: m = (!c<<3)|(!c<<2)| (1<<1); break; - case THUMB2_ITTTT: m = (c<<3)| (c<<2)| (c<<1)|1; break; - case THUMB2_ITETT: m = (!c<<3)| (c<<2)| (c<<1)|1; break; - case THUMB2_ITTET: m = (c<<3)|(!c<<2)| (c<<1)|1; break; - case THUMB2_ITEET: m = (!c<<3)|(!c<<2)| (c<<1)|1; break; - case THUMB2_ITTTE: m = (c<<3)| (c<<2)|(!c<<1)|1; break; - case THUMB2_ITETE: m = (!c<<3)| (c<<2)|(!c<<1)|1; break; - case THUMB2_ITTEE: m = (c<<3)|(!c<<2)|(!c<<1)|1; break; - case THUMB2_ITEEE: m = (!c<<3)|(!c<<2)|(!c<<1)|1; break; - default: abort(); + case THUMB2_IT: m = 1<<3; break; + case THUMB2_ITT: m = (c<<3)| (1<<2); break; + case THUMB2_ITE: m = (!c<<3)| (1<<2); break; + case THUMB2_ITTT: m = (c<<3)| (c<<2)| (1<<1); break; + case THUMB2_ITET: m = (!c<<3)| (c<<2)| (1<<1); break; + case THUMB2_ITTE: m = (c<<3)|(!c<<2)| (1<<1); break; + case THUMB2_ITEE: m = (!c<<3)|(!c<<2)| (1<<1); break; + case THUMB2_ITTTT: m = (c<<3)| (c<<2)| (c<<1)|1; break; + case THUMB2_ITETT: m = (!c<<3)| (c<<2)| (c<<1)|1; break; + case THUMB2_ITTET: m = (c<<3)|(!c<<2)| (c<<1)|1; break; + case THUMB2_ITEET: m = (!c<<3)|(!c<<2)| (c<<1)|1; break; + case THUMB2_ITTTE: m = (c<<3)| (c<<2)|(!c<<1)|1; break; + case THUMB2_ITETE: m = (!c<<3)| (c<<2)|(!c<<1)|1; break; + case THUMB2_ITTEE: m = (c<<3)|(!c<<2)|(!c<<1)|1; break; + case THUMB2_ITEEE: m = (!c<<3)|(!c<<2)|(!c<<1)|1; break; + default: abort(); } assert(m && (tc != ARM_CC_AL || !(m & (m - 1)))); is(0xbf00 | (tc >> 24) | m); @@ -1291,7 +1280,7 @@ _coriw(jit_state_t *_jit, int cc, int o, int rd, int im) static void _torrr(jit_state_t *_jit, int o, int rn, int rd, int rm) { - jit_thumb_t thumb; + jit_thumb_t thumb; assert(!(o & 0xf0f0f)); thumb.i = o|(_u4(rn)<<16)|(_u4(rd)<<8)|_u4(rm); iss(thumb.s[0], thumb.s[1]); @@ -1300,7 +1289,7 @@ _torrr(jit_state_t *_jit, int o, int rn, int rd, int rm) static void _torrrs(jit_state_t *_jit, int o, int rn, int rd, int rm, int im) { - jit_thumb_t thumb; + jit_thumb_t thumb; assert(!(o & 0x000f0f0f)); assert(!(im & 0xffff8f0f)); thumb.i = o|(_u4(rn)<<16)|(_u4(rd)<<8)|im|_u4(rm); @@ -1310,7 +1299,7 @@ _torrrs(jit_state_t *_jit, int o, int rn, int rd, int rm, int im) static void _torxr(jit_state_t *_jit, int o, int rn, int rt, int rm) { - jit_thumb_t thumb; + jit_thumb_t thumb; assert(!(o & 0xf0f0f)); thumb.i = o|(_u4(rn)<<16)|(_u4(rt)<<12)|_u4(rm); iss(thumb.s[0], thumb.s[1]); @@ -1319,7 +1308,7 @@ _torxr(jit_state_t *_jit, int o, int rn, int rt, int rm) static void _torrrr(jit_state_t *_jit, int o, int rn, int rl, int rh, int rm) { - jit_thumb_t thumb; + jit_thumb_t thumb; assert(!(o & 0x000fff0f)); thumb.i = o|(_u4(rn)<<16)|(_u4(rl)<<12)|(_u4(rh)<<8)|_u4(rm); iss(thumb.s[0], thumb.s[1]); @@ -1328,7 +1317,7 @@ _torrrr(jit_state_t *_jit, int o, int rn, int rl, int rh, int rm) static void _torrri8(jit_state_t *_jit, int o, int rn, int rt, int rt2, int im) { - jit_thumb_t thumb; + jit_thumb_t thumb; assert(!(o & 0x000fffff)); assert(!(im & 0xffffff00)); thumb.i = o|(_u4(rn)<<16)|(_u4(rt)<<12)|(_u4(rt2)<<8)|im; @@ -1338,7 +1327,7 @@ _torrri8(jit_state_t *_jit, int o, int rn, int rt, int rt2, int im) static void _torri(jit_state_t *_jit, int o, int rn, int rd, int im) { - jit_thumb_t thumb; + jit_thumb_t thumb; assert(!(o & 0x0c0f7fff)); assert(!(im & 0xfbff8f00)); thumb.i = o|(_u4(rn)<<16)|(_u4(rd)<<8)|im; @@ -1348,7 +1337,7 @@ _torri(jit_state_t *_jit, int o, int rn, int rd, int im) static void _torri8(jit_state_t *_jit, int o, int rn, int rt, int im) { - jit_thumb_t thumb; + jit_thumb_t thumb; assert(!(o & 0x000ff0ff)); assert(!(im & 0xffffff00)); thumb.i = o|(_u4(rn)<<16)|(_u4(rt)<<12)|im; @@ -1358,7 +1347,7 @@ _torri8(jit_state_t *_jit, int o, int rn, int rt, int im) static void _torri12(jit_state_t *_jit, int o, int rn, int rt, int im) { - jit_thumb_t thumb; + jit_thumb_t thumb; assert(!(o & 0x000fffff)); assert(!(im & 0xfffff000)); thumb.i = o|(_u4(rn)<<16)|(_u4(rt)<<12)|im; @@ -1368,7 +1357,7 @@ _torri12(jit_state_t *_jit, int o, int rn, int rt, int im) static void _tshift(jit_state_t *_jit, int o, int rd, int rm, int im) { - jit_thumb_t thumb; + jit_thumb_t thumb; assert(!(o & 0x7fcf)); assert(im >= 0 && im < 32); thumb.i = o|((im&0x1c)<<10)|(_u4(rd)<<8)|((im&3)<<6)|_u4(rm); @@ -1378,7 +1367,7 @@ _tshift(jit_state_t *_jit, int o, int rd, int rm, int im) static void _toriw(jit_state_t *_jit, int o, int rd, int im) { - jit_thumb_t thumb; + jit_thumb_t thumb; assert(!(im & 0xffff0000)); thumb.i = o|((im&0xf000)<<4)|((im&0x800)<<15)|((im&0x700)<<4)|(_u4(rd)<<8)|(im&0xff); iss(thumb.s[0], thumb.s[1]); @@ -1403,7 +1392,7 @@ _t11(jit_state_t *_jit, int im) static void _tcb(jit_state_t *_jit, int cc, int im) { - jit_thumb_t thumb; + jit_thumb_t thumb; assert(!(cc & 0xfffffff)); assert(cc != ARM_CC_AL && cc != ARM_CC_NV); cc = ((uint32_t)cc) >> 6; @@ -1422,7 +1411,7 @@ _blxi(jit_state_t *_jit, int im) static void _tb(jit_state_t *_jit, int o, int im) { - jit_thumb_t thumb; + jit_thumb_t thumb; assert(!(o & 0x07ff2fff)); assert(!(o & im)); thumb.i = o|im; @@ -1489,10 +1478,10 @@ _c6orr(jit_state_t *_jit, int cc, int o, int rd, int rm) static void _tpp(jit_state_t *_jit, int o, int im) { - jit_thumb_t thumb; + jit_thumb_t thumb; assert(!(o & 0x0000ffff)); if (o == THUMB2_PUSH) - assert(!(im & 0x8000)); + assert(!(im & 0x8000)); assert(__builtin_popcount(im & 0x1fff) > 1); thumb.i = o|im; iss(thumb.s[0], thumb.s[1]); @@ -1501,7 +1490,7 @@ _tpp(jit_state_t *_jit, int o, int im) static void _torl(jit_state_t *_jit, int o, int rn, int im) { - jit_thumb_t thumb; + jit_thumb_t thumb; assert(!(o & 0xf1fff)); assert(rn != _R15 || !im || ((o & 0xc000) == 0xc000)); assert(!(o & THUMB2_LDM_W) || !(im & (1 << rn))); @@ -1513,12 +1502,12 @@ static void _nop(jit_state_t *_jit, int32_t i0) { if (jit_thumb_p()) { - for (; i0 > 0; i0 -= 2) - T1_NOP(); + for (; i0 > 0; i0 -= 2) + T1_NOP(); } else { - for (; i0 > 0; i0 -= 4) - NOP(); + for (; i0 > 0; i0 -= 4) + NOP(); } assert(i0 == 0); } @@ -1527,58 +1516,58 @@ static void _movr(jit_state_t *_jit, int32_t r0, int32_t r1) { if (r0 != r1) { - if (jit_thumb_p()) - T1_MOV(r0, r1); - else - MOV(r0, r1); + if (jit_thumb_p()) + T1_MOV(r0, r1); + else + MOV(r0, r1); } } static void _movi(jit_state_t *_jit, int32_t r0, jit_word_t i0) { - int i; + int i; if (jit_thumb_p()) { - if (!jit_no_set_flags() && r0 < 8 && !(i0 & 0xffffff80)) - T1_MOVI(r0, i0); - else if ((i = encode_thumb_immediate(i0)) != -1) - T2_MOVI(r0, i); - else if ((i = encode_thumb_immediate(~i0)) != -1) - T2_MVNI(r0, i); - else { - T2_MOVWI(r0, (uint16_t)i0); - if (i0 & 0xffff0000) - T2_MOVTI(r0, (uint16_t)((unsigned)i0 >> 16)); - } + if (!jit_no_set_flags() && r0 < 8 && !(i0 & 0xffffff80)) + T1_MOVI(r0, i0); + else if ((i = encode_thumb_immediate(i0)) != -1) + T2_MOVI(r0, i); + else if ((i = encode_thumb_immediate(~i0)) != -1) + T2_MVNI(r0, i); + else { + T2_MOVWI(r0, (uint16_t)i0); + if (i0 & 0xffff0000) + T2_MOVTI(r0, (uint16_t)((unsigned)i0 >> 16)); + } } else { - if (jit_armv6_p() && !(i0 & 0xffff0000)) - MOVWI(r0, i0); - else if ((i = encode_arm_immediate(i0)) != -1) - MOVI(r0, i); - else if ((i = encode_arm_immediate(~i0)) != -1) - MVNI(r0, i); - else if (jit_armv6_p()) { - MOVWI(r0, (uint16_t)(i0)); - if ((i0 & 0xffff0000)) - MOVTI(r0, (uint16_t)((unsigned)i0 >> 16)); - } - else - load_const(0, r0, i0); + if (jit_armv6_p() && !(i0 & 0xffff0000)) + MOVWI(r0, i0); + else if ((i = encode_arm_immediate(i0)) != -1) + MOVI(r0, i); + else if ((i = encode_arm_immediate(~i0)) != -1) + MVNI(r0, i); + else if (jit_armv6_p()) { + MOVWI(r0, (uint16_t)(i0)); + if ((i0 & 0xffff0000)) + MOVTI(r0, (uint16_t)((unsigned)i0 >> 16)); + } + else + load_const(0, r0, i0); } } static jit_word_t _movi_p(jit_state_t *_jit, int32_t r0, jit_word_t i0) { - jit_word_t w; + jit_word_t w; w = _jit->pc.w; if (jit_thumb_p()) { - T2_MOVWI(r0, (uint16_t)(i0)); - T2_MOVTI(r0, (uint16_t)((unsigned)i0 >> 16)); + T2_MOVWI(r0, (uint16_t)(i0)); + T2_MOVTI(r0, (uint16_t)((unsigned)i0 >> 16)); } else - load_const(1, r0, 0); + load_const(1, r0, 0); return (w); } @@ -1586,87 +1575,87 @@ static void _comr(jit_state_t *_jit, int32_t r0, int32_t r1) { if (jit_thumb_p()) { - if (!jit_no_set_flags() && (r0|r1) < 8) - T1_NOT(r0, r1); - else - T2_NOT(r0, r1); + if (!jit_no_set_flags() && (r0|r1) < 8) + T1_NOT(r0, r1); + else + T2_NOT(r0, r1); } else - NOT(r0, r1); + NOT(r0, r1); } static void _negr(jit_state_t *_jit, int32_t r0, int32_t r1) { if (jit_thumb_p()) { - if (!jit_no_set_flags() && (r0|r1) < 8) - T1_RSBI(r0, r1); - else - T2_RSBI(r0, r1, 0); + if (!jit_no_set_flags() && (r0|r1) < 8) + T1_RSBI(r0, r1); + else + T2_RSBI(r0, r1, 0); } else - RSBI(r0, r1, 0); + RSBI(r0, r1, 0); } static void _addr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { if (jit_thumb_p()) { - if (!jit_no_set_flags() && (r0|r1|r2) < 8) - T1_ADD(r0, r1, r2); - else if (r0 == r1 || r0 == r2) - T1_ADDX(r0, r0 == r1 ? r2 : r1); - else - T2_ADD(r0, r1, r2); + if (!jit_no_set_flags() && (r0|r1|r2) < 8) + T1_ADD(r0, r1, r2); + else if (r0 == r1 || r0 == r2) + T1_ADDX(r0, r0 == r1 ? r2 : r1); + else + T2_ADD(r0, r1, r2); } else - ADD(r0, r1, r2); + ADD(r0, r1, r2); } static void _addi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - int i; - int32_t reg; + int i; + int32_t reg; if (jit_thumb_p()) { - if (!jit_no_set_flags() && (r0|r1) < 8 && !(i0 & ~7)) - T1_ADDI3(r0, r1, i0); - else if (!jit_no_set_flags() && (r0|r1) < 8 && !(-i0 & ~7)) - T1_SUBI3(r0, r1, -i0); - else if (!jit_no_set_flags() && r0 < 8 && r0 == r1 && !(i0 & ~0xff)) - T1_ADDI8(r0, i0); - else if (!jit_no_set_flags() && r0 < 8 && r0 == r1 && !(-i0 & ~0xff)) - T1_SUBI8(r0, -i0); - else if ((i = encode_thumb_immediate(i0)) != -1) - T2_ADDI(r0, r1, i); - else if ((i = encode_thumb_immediate(-i0)) != -1) - T2_SUBI(r0, r1, i); - else if ((i = encode_thumb_word_immediate(i0)) != -1) - T2_ADDWI(r0, r1, i); - else if ((i = encode_thumb_word_immediate(-i0)) != -1) - T2_SUBWI(r0, r1, i); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - T2_ADD(r0, r1, rn(reg)); - jit_unget_reg(reg); - } + if (!jit_no_set_flags() && (r0|r1) < 8 && !(i0 & ~7)) + T1_ADDI3(r0, r1, i0); + else if (!jit_no_set_flags() && (r0|r1) < 8 && !(-i0 & ~7)) + T1_SUBI3(r0, r1, -i0); + else if (!jit_no_set_flags() && r0 < 8 && r0 == r1 && !(i0 & ~0xff)) + T1_ADDI8(r0, i0); + else if (!jit_no_set_flags() && r0 < 8 && r0 == r1 && !(-i0 & ~0xff)) + T1_SUBI8(r0, -i0); + else if ((i = encode_thumb_immediate(i0)) != -1) + T2_ADDI(r0, r1, i); + else if ((i = encode_thumb_immediate(-i0)) != -1) + T2_SUBI(r0, r1, i); + else if ((i = encode_thumb_word_immediate(i0)) != -1) + T2_ADDWI(r0, r1, i); + else if ((i = encode_thumb_word_immediate(-i0)) != -1) + T2_SUBWI(r0, r1, i); + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + T2_ADD(r0, r1, rn(reg)); + jit_unget_reg(reg); + } } else { - if ((i = encode_arm_immediate(i0)) != -1) - ADDI(r0, r1, i); - else if ((i = encode_arm_immediate(-i0)) != -1) - SUBI(r0, r1, i); - else if (r0 != r1) { - movi(r0, i0); - ADD(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - ADD(r0, r1, rn(reg)); - jit_unget_reg(reg); - } + if ((i = encode_arm_immediate(i0)) != -1) + ADDI(r0, r1, i); + else if ((i = encode_arm_immediate(-i0)) != -1) + SUBI(r0, r1, i); + else if (r0 != r1) { + movi(r0, i0); + ADD(r0, r1, r0); + } + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + ADD(r0, r1, rn(reg)); + jit_unget_reg(reg); + } } } @@ -1674,56 +1663,56 @@ static void _addcr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { if (jit_thumb_p()) { - /* thumb auto set carry if not inside IT block */ - if ((r0|r1|r2) < 8) - T1_ADD(r0, r1, r2); - else - T2_ADDS(r0, r1, r2); + /* thumb auto set carry if not inside IT block */ + if ((r0|r1|r2) < 8) + T1_ADD(r0, r1, r2); + else + T2_ADDS(r0, r1, r2); } else - ADDS(r0, r1, r2); + ADDS(r0, r1, r2); } static void _addci(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - int i; - int32_t reg; + int i; + int32_t reg; if (jit_thumb_p()) { - if ((r0|r1) < 8 && !(i0 & ~7)) - T1_ADDI3(r0, r1, i0); - else if ((r0|r1) < 8 && !(-i0 & ~7)) - T1_SUBI3(r0, r1, -i0); - else if (r0 < 8 && r0 == r1 && !(i0 & ~0xff)) - T1_ADDI8(r0, i0); - else if (r0 < 8 && r0 == r1 && !(-i0 & ~0xff)) - T1_SUBI8(r0, -i0); - else if ((i = encode_thumb_immediate(i0)) != -1) - T2_ADDSI(r0, r1, i); - else if ((i = encode_thumb_immediate(-i0)) != -1) - T2_SUBSI(r0, r1, i); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - T2_ADDS(r0, r1, rn(reg)); - jit_unget_reg(reg); - } + if ((r0|r1) < 8 && !(i0 & ~7)) + T1_ADDI3(r0, r1, i0); + else if ((r0|r1) < 8 && !(-i0 & ~7)) + T1_SUBI3(r0, r1, -i0); + else if (r0 < 8 && r0 == r1 && !(i0 & ~0xff)) + T1_ADDI8(r0, i0); + else if (r0 < 8 && r0 == r1 && !(-i0 & ~0xff)) + T1_SUBI8(r0, -i0); + else if ((i = encode_thumb_immediate(i0)) != -1) + T2_ADDSI(r0, r1, i); + else if ((i = encode_thumb_immediate(-i0)) != -1) + T2_SUBSI(r0, r1, i); + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + T2_ADDS(r0, r1, rn(reg)); + jit_unget_reg(reg); + } } else { - if ((i = encode_arm_immediate(i0)) != -1) - ADDSI(r0, r1, i); - else if ((i = encode_arm_immediate(-i0)) != -1) - SUBSI(r0, r1, i); - else if (r0 != r1) { - movi(r0, i0); - ADDS(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - ADDS(r0, r1, rn(reg)); - jit_unget_reg(reg); - } + if ((i = encode_arm_immediate(i0)) != -1) + ADDSI(r0, r1, i); + else if ((i = encode_arm_immediate(-i0)) != -1) + SUBSI(r0, r1, i); + else if (r0 != r1) { + movi(r0, i0); + ADDS(r0, r1, r0); + } + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + ADDS(r0, r1, rn(reg)); + jit_unget_reg(reg); + } } } @@ -1732,56 +1721,56 @@ _addxr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { /* keep setting carry because don't know last ADC */ if (jit_thumb_p()) { - /* thumb auto set carry if not inside IT block */ - if ((r0|r1|r2) < 8 && (r0 == r1 || r0 == r2)) - T1_ADC(r0, r0 == r1 ? r2 : r1); - else - T2_ADCS(r0, r1, r2); + /* thumb auto set carry if not inside IT block */ + if ((r0|r1|r2) < 8 && (r0 == r1 || r0 == r2)) + T1_ADC(r0, r0 == r1 ? r2 : r1); + else + T2_ADCS(r0, r1, r2); } else - ADCS(r0, r1, r2); + ADCS(r0, r1, r2); } static void _addxi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - int i; - int32_t reg; - int no_set_flags; + int i; + int32_t reg; + int no_set_flags; if (jit_thumb_p()) { - no_set_flags = jit_no_set_flags(); - jit_no_set_flags() = 1; - if ((i = encode_thumb_immediate(i0)) != -1) - T2_ADCSI(r0, r1, i); - else if ((i = encode_thumb_immediate(-i0)) != -1) - T2_SBCSI(r0, r1, i); - else if (r0 != r1) { - movi(r0, i0); - T2_ADCS(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - T2_ADCS(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - jit_no_set_flags() = no_set_flags; + no_set_flags = jit_no_set_flags(); + jit_no_set_flags() = 1; + if ((i = encode_thumb_immediate(i0)) != -1) + T2_ADCSI(r0, r1, i); + else if ((i = encode_thumb_immediate(-i0)) != -1) + T2_SBCSI(r0, r1, i); + else if (r0 != r1) { + movi(r0, i0); + T2_ADCS(r0, r1, r0); + } + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + T2_ADCS(r0, r1, rn(reg)); + jit_unget_reg(reg); + } + jit_no_set_flags() = no_set_flags; } else { - if ((i = encode_arm_immediate(i0)) != -1) - ADCSI(r0, r1, i); - else if ((i = encode_arm_immediate(-i0)) != -1) - SBCSI(r0, r1, i); - else if (r0 != r1) { - movi(r0, i0); - ADCS(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - ADCS(r0, r1, rn(reg)); - jit_unget_reg(reg); - } + if ((i = encode_arm_immediate(i0)) != -1) + ADCSI(r0, r1, i); + else if ((i = encode_arm_immediate(-i0)) != -1) + SBCSI(r0, r1, i); + else if (r0 != r1) { + movi(r0, i0); + ADCS(r0, r1, r0); + } + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + ADCS(r0, r1, rn(reg)); + jit_unget_reg(reg); + } } } @@ -1789,59 +1778,59 @@ static void _subr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { if (jit_thumb_p()) { - if (!jit_no_set_flags() && (r0|r1|r2) < 8) - T1_SUB(r0, r1, r2); - else - T2_SUB(r0, r1, r2); + if (!jit_no_set_flags() && (r0|r1|r2) < 8) + T1_SUB(r0, r1, r2); + else + T2_SUB(r0, r1, r2); } else - SUB(r0, r1, r2); + SUB(r0, r1, r2); } static void _subi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - int i; - int32_t reg; + int i; + int32_t reg; if (jit_thumb_p()) { - if (!jit_no_set_flags() && (r0|r1) < 8 && !(i0 & ~7)) - T1_SUBI3(r0, r1, i0); - else if (!jit_no_set_flags() && (r0|r1) < 8 && !(-i0 & ~7)) - T1_ADDI3(r0, r1, -i0); - else if (!jit_no_set_flags() && r0 < 8 && r0 == r1 && !(i0 & ~0xff)) - T1_SUBI8(r0, i0); - else if (!jit_no_set_flags() && r0 < 8 && r0 == r1 && !(-i0 & ~0xff)) - T1_ADDI8(r0, -i0); - else if ((i = encode_thumb_immediate(i0)) != -1) - T2_SUBI(r0, r1, i); - else if ((i = encode_thumb_immediate(-i0)) != -1) - T2_ADDI(r0, r1, i); - else if ((i = encode_thumb_word_immediate(i0)) != -1) - T2_SUBWI(r0, r1, i); - else if ((i = encode_thumb_word_immediate(-i0)) != -1) - T2_ADDWI(r0, r1, i); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - T2_SUB(r0, r1, rn(reg)); - jit_unget_reg(reg); - } + if (!jit_no_set_flags() && (r0|r1) < 8 && !(i0 & ~7)) + T1_SUBI3(r0, r1, i0); + else if (!jit_no_set_flags() && (r0|r1) < 8 && !(-i0 & ~7)) + T1_ADDI3(r0, r1, -i0); + else if (!jit_no_set_flags() && r0 < 8 && r0 == r1 && !(i0 & ~0xff)) + T1_SUBI8(r0, i0); + else if (!jit_no_set_flags() && r0 < 8 && r0 == r1 && !(-i0 & ~0xff)) + T1_ADDI8(r0, -i0); + else if ((i = encode_thumb_immediate(i0)) != -1) + T2_SUBI(r0, r1, i); + else if ((i = encode_thumb_immediate(-i0)) != -1) + T2_ADDI(r0, r1, i); + else if ((i = encode_thumb_word_immediate(i0)) != -1) + T2_SUBWI(r0, r1, i); + else if ((i = encode_thumb_word_immediate(-i0)) != -1) + T2_ADDWI(r0, r1, i); + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + T2_SUB(r0, r1, rn(reg)); + jit_unget_reg(reg); + } } else { - if ((i = encode_arm_immediate(i0)) != -1) - SUBI(r0, r1, i); - else if ((i = encode_arm_immediate(-i0)) != -1) - ADDI(r0, r1, i); - else if (r0 != r1) { - movi(r0, i0); - SUB(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - SUB(r0, r1, rn(reg)); - jit_unget_reg(reg); - } + if ((i = encode_arm_immediate(i0)) != -1) + SUBI(r0, r1, i); + else if ((i = encode_arm_immediate(-i0)) != -1) + ADDI(r0, r1, i); + else if (r0 != r1) { + movi(r0, i0); + SUB(r0, r1, r0); + } + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + SUB(r0, r1, rn(reg)); + jit_unget_reg(reg); + } } } @@ -1849,56 +1838,56 @@ static void _subcr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { if (jit_thumb_p()) { - /* thumb auto set carry if not inside IT block */ - if ((r0|r1|r2) < 8) - T1_SUB(r0, r1, r2); - else - T2_SUBS(r0, r1, r2); + /* thumb auto set carry if not inside IT block */ + if ((r0|r1|r2) < 8) + T1_SUB(r0, r1, r2); + else + T2_SUBS(r0, r1, r2); } else - SUBS(r0, r1, r2); + SUBS(r0, r1, r2); } static void _subci(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - int i; - int32_t reg; + int i; + int32_t reg; if (jit_thumb_p()) { - if ((r0|r1) < 8 && !(i0 & ~7)) - T1_SUBI3(r0, r1, i0); - else if ((r0|r1) < 8 && !(-i0 & ~7)) - T1_ADDI3(r0, r1, -i0); - else if (r0 < 8 && r0 == r1 && !(i0 & ~0xff)) - T1_SUBI8(r0, i0); - else if (r0 < 8 && r0 == r1 && !(-i0 & ~0xff)) - T1_ADDI8(r0, -i0); - else if ((i = encode_thumb_immediate(i0)) != -1) - T2_SUBSI(r0, r1, i); - else if ((i = encode_thumb_immediate(-i0)) != -1) - T2_ADDSI(r0, r1, i); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - T2_SUBS(r0, r1, rn(reg)); - jit_unget_reg(reg); - } + if ((r0|r1) < 8 && !(i0 & ~7)) + T1_SUBI3(r0, r1, i0); + else if ((r0|r1) < 8 && !(-i0 & ~7)) + T1_ADDI3(r0, r1, -i0); + else if (r0 < 8 && r0 == r1 && !(i0 & ~0xff)) + T1_SUBI8(r0, i0); + else if (r0 < 8 && r0 == r1 && !(-i0 & ~0xff)) + T1_ADDI8(r0, -i0); + else if ((i = encode_thumb_immediate(i0)) != -1) + T2_SUBSI(r0, r1, i); + else if ((i = encode_thumb_immediate(-i0)) != -1) + T2_ADDSI(r0, r1, i); + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + T2_SUBS(r0, r1, rn(reg)); + jit_unget_reg(reg); + } } else { - if ((i = encode_arm_immediate(i0)) != -1) - SUBSI(r0, r1, i); - else if ((i = encode_arm_immediate(-i0)) != -1) - ADDSI(r0, r1, i); - else if (r0 != r1) { - movi(r0, i0); - SUBS(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - SUBS(r0, r1, rn(reg)); - jit_unget_reg(reg); - } + if ((i = encode_arm_immediate(i0)) != -1) + SUBSI(r0, r1, i); + else if ((i = encode_arm_immediate(-i0)) != -1) + ADDSI(r0, r1, i); + else if (r0 != r1) { + movi(r0, i0); + SUBS(r0, r1, r0); + } + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + SUBS(r0, r1, rn(reg)); + jit_unget_reg(reg); + } } } @@ -1907,56 +1896,56 @@ _subxr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { /* keep setting carry because don't know last SBC */ if (jit_thumb_p()) { - /* thumb auto set carry if not inside IT block */ - if ((r0|r1|r2) < 8 && r0 == r1) - T1_SBC(r0, r2); - else - T2_SBCS(r0, r1, r2); + /* thumb auto set carry if not inside IT block */ + if ((r0|r1|r2) < 8 && r0 == r1) + T1_SBC(r0, r2); + else + T2_SBCS(r0, r1, r2); } else - SBCS(r0, r1, r2); + SBCS(r0, r1, r2); } static void _subxi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - int i; - int32_t reg; - int no_set_flags; + int i; + int32_t reg; + int no_set_flags; if (jit_thumb_p()) { - no_set_flags = jit_no_set_flags(); - jit_no_set_flags() = 1; - if ((i = encode_arm_immediate(i0)) != -1) - T2_SBCSI(r0, r1, i); - else if ((i = encode_arm_immediate(-i0)) != -1) - T2_ADCSI(r0, r1, i); - else if (r0 != r1) { - movi(r0, i0); - T2_SBCS(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - SBCS(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - jit_no_set_flags() = no_set_flags; + no_set_flags = jit_no_set_flags(); + jit_no_set_flags() = 1; + if ((i = encode_arm_immediate(i0)) != -1) + T2_SBCSI(r0, r1, i); + else if ((i = encode_arm_immediate(-i0)) != -1) + T2_ADCSI(r0, r1, i); + else if (r0 != r1) { + movi(r0, i0); + T2_SBCS(r0, r1, r0); + } + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + SBCS(r0, r1, rn(reg)); + jit_unget_reg(reg); + } + jit_no_set_flags() = no_set_flags; } else { - if ((i = encode_arm_immediate(i0)) != -1) - SBCSI(r0, r1, i); - else if ((i = encode_arm_immediate(-i0)) != -1) - ADCSI(r0, r1, i); - else if (r0 != r1) { - movi(r0, i0); - SBCS(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - SBCS(r0, r1, rn(reg)); - jit_unget_reg(reg); - } + if ((i = encode_arm_immediate(i0)) != -1) + SBCSI(r0, r1, i); + else if ((i = encode_arm_immediate(-i0)) != -1) + ADCSI(r0, r1, i); + else if (r0 != r1) { + movi(r0, i0); + SBCS(r0, r1, r0); + } + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + SBCS(r0, r1, rn(reg)); + jit_unget_reg(reg); + } } } @@ -1970,35 +1959,35 @@ _rsbi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) static void _mulr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - int32_t reg; + int32_t reg; if (jit_thumb_p()) { - if (!jit_no_set_flags() && r0 == r2 && (r0|r1) < 8) - T1_MUL(r0, r1); - else if (!jit_no_set_flags() && r0 == r1 && (r0|r2) < 8) - T1_MUL(r0, r2); - else - T2_MUL(r0, r1, r2); + if (!jit_no_set_flags() && r0 == r2 && (r0|r1) < 8) + T1_MUL(r0, r1); + else if (!jit_no_set_flags() && r0 == r1 && (r0|r2) < 8) + T1_MUL(r0, r2); + else + T2_MUL(r0, r1, r2); } else { - if (r0 == r1 && !jit_armv6_p()) { - if (r0 != r2) - MUL(r0, r2, r1); - else { - reg = jit_get_reg(jit_class_gpr); - MOV(rn(reg), r1); - MUL(r0, rn(reg), r2); - jit_unget_reg(reg); - } - } - else - MUL(r0, r1, r2); + if (r0 == r1 && !jit_armv6_p()) { + if (r0 != r2) + MUL(r0, r2, r1); + else { + reg = jit_get_reg(jit_class_gpr); + MOV(rn(reg), r1); + MUL(r0, rn(reg), r2); + jit_unget_reg(reg); + } + } + else + MUL(r0, r1, r2); } } static void _muli(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - int32_t reg; + int32_t reg; reg = jit_get_reg(jit_class_gpr); movi(rn(reg), i0); mulr(r0, r1, rn(reg)); @@ -2007,62 +1996,62 @@ _muli(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) static void _iqmulr(jit_state_t *_jit, int32_t r0, int32_t r1, - int32_t r2, int32_t r3, jit_bool_t sign) + int32_t r2, int32_t r3, jit_bool_t sign) { - int32_t reg; + int32_t reg; if (jit_thumb_p()) { - if (r2 == r3) { - reg = jit_get_reg(jit_class_gpr); - movr(rn(reg), r2); - if (sign) - T2_SMULL(r0, r1, rn(reg), r2); - else - T2_UMULL(r0, r1, rn(reg), r2); - jit_unget_reg(reg); - } - else if (r0 != r2 && r1 != r2) { - if (sign) - T2_SMULL(r0, r1, r2, r3); - else - T2_UMULL(r0, r1, r2, r3); - } - else { - if (sign) - T2_SMULL(r0, r1, r3, r2); - else - T2_UMULL(r0, r1, r3, r2); - } + if (r2 == r3) { + reg = jit_get_reg(jit_class_gpr); + movr(rn(reg), r2); + if (sign) + T2_SMULL(r0, r1, rn(reg), r2); + else + T2_UMULL(r0, r1, rn(reg), r2); + jit_unget_reg(reg); + } + else if (r0 != r2 && r1 != r2) { + if (sign) + T2_SMULL(r0, r1, r2, r3); + else + T2_UMULL(r0, r1, r2, r3); + } + else { + if (sign) + T2_SMULL(r0, r1, r3, r2); + else + T2_UMULL(r0, r1, r3, r2); + } } else { - if (r2 == r3) { - reg = jit_get_reg(jit_class_gpr); - movr(rn(reg), r2); - if (sign) - SMULL(r0, r1, rn(reg), r2); - else - UMULL(r0, r1, rn(reg), r2); - jit_unget_reg(reg); - } - else if (r0 != r2 && r1 != r2) { - if (sign) - SMULL(r0, r1, r2, r3); - else - UMULL(r0, r1, r2, r3); - } - else { - if (sign) - SMULL(r0, r1, r3, r2); - else - UMULL(r0, r1, r3, r2); - } + if (r2 == r3) { + reg = jit_get_reg(jit_class_gpr); + movr(rn(reg), r2); + if (sign) + SMULL(r0, r1, rn(reg), r2); + else + UMULL(r0, r1, rn(reg), r2); + jit_unget_reg(reg); + } + else if (r0 != r2 && r1 != r2) { + if (sign) + SMULL(r0, r1, r2, r3); + else + UMULL(r0, r1, r2, r3); + } + else { + if (sign) + SMULL(r0, r1, r3, r2); + else + UMULL(r0, r1, r3, r2); + } } } static void _iqmuli(jit_state_t *_jit, int32_t r0, int32_t r1, - int32_t r2, jit_word_t i0, jit_bool_t sign) + int32_t r2, jit_word_t i0, jit_bool_t sign) { - int32_t reg; + int32_t reg; reg = jit_get_reg(jit_class_gpr); movi(rn(reg), i0); iqmulr(r0, r1, r2, rn(reg), sign); @@ -2071,32 +2060,32 @@ _iqmuli(jit_state_t *_jit, int32_t r0, int32_t r1, static void _divrem(jit_state_t *_jit, int div, int sign, - int32_t r0, int32_t r1, int32_t r2) + int32_t r0, int32_t r1, int32_t r2) { - jit_word_t d; - jit_word_t w; + jit_word_t d; + jit_word_t w; jit_get_reg_args(); movr(_R0_REGNO, r1); movr(_R1_REGNO, r2); - if (sign) w = (jit_word_t)__aeabi_idivmod; - else w = (jit_word_t)__aeabi_uidivmod; + if (sign) w = (jit_word_t)__aeabi_idivmod; + else w = (jit_word_t)__aeabi_uidivmod; if (!jit_exchange_p()) { - if (jit_thumb_p()) d = ((w - _jit->pc.w) >> 1) - 2; - else d = ((w - _jit->pc.w) >> 2) - 2; - if (_s24P(d)) { - if (jit_thumb_p()) T2_BLI(encode_thumb_jump(d)); - else BLI(d & 0x00ffffff); - } - else goto fallback; + if (jit_thumb_p()) d = ((w - _jit->pc.w) >> 1) - 2; + else d = ((w - _jit->pc.w) >> 2) - 2; + if (_s24P(d)) { + if (jit_thumb_p()) T2_BLI(encode_thumb_jump(d)); + else BLI(d & 0x00ffffff); + } + else goto fallback; } else { fallback: - movi(_R2_REGNO, w); - if (jit_thumb_p()) T1_BLX(_R2_REGNO); - else BLX(_R2_REGNO); + movi(_R2_REGNO, w); + if (jit_thumb_p()) T1_BLX(_R2_REGNO); + else BLX(_R2_REGNO); } - if (div) movr(r0, _R0_REGNO); - else movr(r0, _R1_REGNO); + if (div) movr(r0, _R0_REGNO); + else movr(r0, _R1_REGNO); jit_unget_reg_args(); } @@ -2104,15 +2093,15 @@ static void _divr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { if (jit_armv7r_p() && jit_thumb_p()) - T2_SDIV(r0, r1, r2); + T2_SDIV(r0, r1, r2); else - divrem(1, 1, r0, r1, r2); + divrem(1, 1, r0, r1, r2); } static void _divi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - int32_t reg; + int32_t reg; reg = jit_get_reg(jit_class_gpr); movi(rn(reg), i0); divr(r0, r1, rn(reg)); @@ -2123,15 +2112,15 @@ static void _divr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { if (jit_armv7r_p() && jit_thumb_p()) - T2_UDIV(r0, r1, r2); + T2_UDIV(r0, r1, r2); else - divrem(1, 0, r0, r1, r2); + divrem(1, 0, r0, r1, r2); } static void _divi_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - int32_t reg; + int32_t reg; reg = jit_get_reg(jit_class_gpr); movi(rn(reg), i0); divr_u(r0, r1, rn(reg)); @@ -2140,29 +2129,29 @@ _divi_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) static void _iqdivr(jit_state_t *_jit, int32_t r0, int32_t r1, - int32_t r2, int32_t r3, jit_bool_t sign) + int32_t r2, int32_t r3, jit_bool_t sign) { - jit_word_t d; - jit_word_t w; + jit_word_t d; + jit_word_t w; jit_get_reg_args(); movr(_R0_REGNO, r2); movr(_R1_REGNO, r3); - if (sign) w = (jit_word_t)__aeabi_idivmod; - else w = (jit_word_t)__aeabi_uidivmod; + if (sign) w = (jit_word_t)__aeabi_idivmod; + else w = (jit_word_t)__aeabi_uidivmod; if (!jit_exchange_p()) { - if (jit_thumb_p()) d = ((w - _jit->pc.w) >> 1) - 2; - else d = ((w - _jit->pc.w) >> 2) - 2; - if (_s24P(d)) { - if (jit_thumb_p()) T2_BLI(encode_thumb_jump(d)); - else BLI(d & 0x00ffffff); - } - else goto fallback; + if (jit_thumb_p()) d = ((w - _jit->pc.w) >> 1) - 2; + else d = ((w - _jit->pc.w) >> 2) - 2; + if (_s24P(d)) { + if (jit_thumb_p()) T2_BLI(encode_thumb_jump(d)); + else BLI(d & 0x00ffffff); + } + else goto fallback; } else { fallback: - movi(_R2_REGNO, w); - if (jit_thumb_p()) T1_BLX(_R2_REGNO); - else BLX(_R2_REGNO); + movi(_R2_REGNO, w); + if (jit_thumb_p()) T1_BLX(_R2_REGNO); + else BLX(_R2_REGNO); } movr(r0, _R0_REGNO); movr(r1, _R1_REGNO); @@ -2171,9 +2160,9 @@ _iqdivr(jit_state_t *_jit, int32_t r0, int32_t r1, static void _iqdivi(jit_state_t *_jit, int32_t r0, int32_t r1, - int32_t r2, jit_word_t i0, jit_bool_t sign) + int32_t r2, jit_word_t i0, jit_bool_t sign) { - int32_t reg; + int32_t reg; reg = jit_get_reg(jit_class_gpr); movi(rn(reg), i0); iqdivr(r0, r1, r2, rn(reg), sign); @@ -2189,7 +2178,7 @@ _remr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) static void _remi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - int32_t reg; + int32_t reg; reg = jit_get_reg(jit_class_gpr); movi(rn(reg), i0); remr(r0, r1, rn(reg)); @@ -2205,7 +2194,7 @@ _remr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) static void _remi_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - int32_t reg; + int32_t reg; reg = jit_get_reg(jit_class_gpr); movi(rn(reg), i0); remr_u(r0, r1,rn(reg)); @@ -2216,51 +2205,51 @@ static void _andr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { if (jit_thumb_p()) { - if (!jit_no_set_flags() && (r0|r1|r2) < 8 && (r0 == r1 || r0 == r2)) - T1_AND(r0, r0 == r1 ? r2 : r1); - else - T2_AND(r0, r1, r2); + if (!jit_no_set_flags() && (r0|r1|r2) < 8 && (r0 == r1 || r0 == r2)) + T1_AND(r0, r0 == r1 ? r2 : r1); + else + T2_AND(r0, r1, r2); } else - AND(r0, r1, r2); + AND(r0, r1, r2); } static void _andi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - int i; - int32_t reg; + int i; + int32_t reg; if (jit_thumb_p()) { - if ((i = encode_thumb_immediate(i0)) != -1) - T2_ANDI(r0, r1, i); - else if ((i = encode_thumb_immediate(~i0)) != -1) - T2_BICI(r0, r1, i); - else if (r0 != r1) { - movi(r0, i0); - T2_AND(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - T2_AND(r0, r1, rn(reg)); - jit_unget_reg(reg); - } + if ((i = encode_thumb_immediate(i0)) != -1) + T2_ANDI(r0, r1, i); + else if ((i = encode_thumb_immediate(~i0)) != -1) + T2_BICI(r0, r1, i); + else if (r0 != r1) { + movi(r0, i0); + T2_AND(r0, r1, r0); + } + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + T2_AND(r0, r1, rn(reg)); + jit_unget_reg(reg); + } } else { - if ((i = encode_arm_immediate(i0)) != -1) - ANDI(r0, r1, i); - else if ((i = encode_arm_immediate(~i0)) != -1) - BICI(r0, r1, i); - else if (r0 != r1) { - movi(r0, i0); - AND(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - AND(r0, r1, rn(reg)); - jit_unget_reg(reg); - } + if ((i = encode_arm_immediate(i0)) != -1) + ANDI(r0, r1, i); + else if ((i = encode_arm_immediate(~i0)) != -1) + BICI(r0, r1, i); + else if (r0 != r1) { + movi(r0, i0); + AND(r0, r1, r0); + } + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + AND(r0, r1, rn(reg)); + jit_unget_reg(reg); + } } } @@ -2268,47 +2257,47 @@ static void _orr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { if (jit_thumb_p()) { - if (!jit_no_set_flags() && (r0|r1|r2) < 8 && (r0 == r1 || r0 == r2)) - T1_ORR(r0, r0 == r1 ? r2 : r1); - else - T2_ORR(r0, r1, r2); + if (!jit_no_set_flags() && (r0|r1|r2) < 8 && (r0 == r1 || r0 == r2)) + T1_ORR(r0, r0 == r1 ? r2 : r1); + else + T2_ORR(r0, r1, r2); } else - ORR(r0, r1, r2); + ORR(r0, r1, r2); } static void _ori(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - int i; - int32_t reg; + int i; + int32_t reg; if (jit_thumb_p()) { - if ((i = encode_thumb_immediate(i0)) != -1) - T2_ORRI(r0, r1, i); - else if (r0 != r1) { - movi(r0, i0); - T2_ORR(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - T2_ORR(r0, r1, rn(reg)); - jit_unget_reg(reg); - } + if ((i = encode_thumb_immediate(i0)) != -1) + T2_ORRI(r0, r1, i); + else if (r0 != r1) { + movi(r0, i0); + T2_ORR(r0, r1, r0); + } + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + T2_ORR(r0, r1, rn(reg)); + jit_unget_reg(reg); + } } else { - if ((i = encode_arm_immediate(i0)) != -1) - ORRI(r0, r1, i); - else if (r0 != r1) { - movi(r0, i0); - ORR(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - ORR(r0, r1, rn(reg)); - jit_unget_reg(reg); - } + if ((i = encode_arm_immediate(i0)) != -1) + ORRI(r0, r1, i); + else if (r0 != r1) { + movi(r0, i0); + ORR(r0, r1, r0); + } + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + ORR(r0, r1, rn(reg)); + jit_unget_reg(reg); + } } } @@ -2316,47 +2305,47 @@ static void _xorr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { if (jit_thumb_p()) { - if (!jit_no_set_flags() && (r0|r1|r2) < 8 && (r0 == r1 || r0 == r2)) - T1_EOR(r0, r0 == r1 ? r2 : r1); - else - T2_EOR(r0, r1, r2); + if (!jit_no_set_flags() && (r0|r1|r2) < 8 && (r0 == r1 || r0 == r2)) + T1_EOR(r0, r0 == r1 ? r2 : r1); + else + T2_EOR(r0, r1, r2); } else - EOR(r0, r1, r2); + EOR(r0, r1, r2); } static void _xori(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - int i; - int32_t reg; + int i; + int32_t reg; if (jit_thumb_p()) { - if ((i = encode_thumb_immediate(i0)) != -1) - T2_EORI(r0, r1, i); - else if (r0 != r1) { - movi(r0, i0); - T2_EOR(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - T2_EOR(r0, r1, rn(reg)); - jit_unget_reg(reg); - } + if ((i = encode_thumb_immediate(i0)) != -1) + T2_EORI(r0, r1, i); + else if (r0 != r1) { + movi(r0, i0); + T2_EOR(r0, r1, r0); + } + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + T2_EOR(r0, r1, rn(reg)); + jit_unget_reg(reg); + } } else { - if ((i = encode_arm_immediate(i0)) != -1) - EORI(r0, r1, i); - else if (r0 != r1) { - movi(r0, i0); - EOR(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - EOR(r0, r1, rn(reg)); - jit_unget_reg(reg); - } + if ((i = encode_arm_immediate(i0)) != -1) + EORI(r0, r1, i); + else if (r0 != r1) { + movi(r0, i0); + EOR(r0, r1, r0); + } + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + EOR(r0, r1, rn(reg)); + jit_unget_reg(reg); + } } } @@ -2364,13 +2353,13 @@ static void _lshr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { if (jit_thumb_p()) { - if (!jit_no_set_flags() && (r0|r1|r2) < 8 && r0 == r1) - T1_LSL(r0, r2); - else - T2_LSL(r0, r1, r2); + if (!jit_no_set_flags() && (r0|r1|r2) < 8 && r0 == r1) + T1_LSL(r0, r2); + else + T2_LSL(r0, r1, r2); } else - LSL(r0, r1, r2); + LSL(r0, r1, r2); } static void @@ -2378,28 +2367,28 @@ _lshi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { assert(i0 >= 0 && i0 <= 31); if (i0 == 0) - movr(r0, r1); + movr(r0, r1); else if (jit_thumb_p()) { - if (!jit_no_set_flags() && (r0|r1) < 8) - T1_LSLI(r0, r1, i0); - else - T2_LSLI(r0, r1, i0); + if (!jit_no_set_flags() && (r0|r1) < 8) + T1_LSLI(r0, r1, i0); + else + T2_LSLI(r0, r1, i0); } else - LSLI(r0, r1, i0); + LSLI(r0, r1, i0); } static void _rshr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { if (jit_thumb_p()) { - if (!jit_no_set_flags() && (r0|r1|r2) < 8 && r0 == r1) - T1_ASR(r0, r2); - else - T2_ASR(r0, r1, r2); + if (!jit_no_set_flags() && (r0|r1|r2) < 8 && r0 == r1) + T1_ASR(r0, r2); + else + T2_ASR(r0, r1, r2); } else - ASR(r0, r1, r2); + ASR(r0, r1, r2); } static void @@ -2407,28 +2396,28 @@ _rshi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { assert(i0 >= 0 && i0 <= 31); if (i0 == 0) - movr(r0, r1); + movr(r0, r1); else if (jit_thumb_p()) { - if (!jit_no_set_flags() && (r0|r1) < 8) - T1_ASRI(r0, r1, i0); - else - T2_ASRI(r0, r1, i0); + if (!jit_no_set_flags() && (r0|r1) < 8) + T1_ASRI(r0, r1, i0); + else + T2_ASRI(r0, r1, i0); } else - ASRI(r0, r1, i0); + ASRI(r0, r1, i0); } static void _rshr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { if (jit_thumb_p()) { - if (!jit_no_set_flags() && (r0|r1|r2) < 8 && r0 == r1) - T1_LSR(r0, r2); - else - T2_LSR(r0, r1, r2); + if (!jit_no_set_flags() && (r0|r1|r2) < 8 && r0 == r1) + T1_LSR(r0, r2); + else + T2_LSR(r0, r1, r2); } else - LSR(r0, r1, r2); + LSR(r0, r1, r2); } static void @@ -2436,15 +2425,15 @@ _rshi_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { assert(i0 >= 0 && i0 <= 31); if (i0 == 0) - movr(r0, r1); + movr(r0, r1); else if (jit_thumb_p()) { - if (!jit_no_set_flags() && (r0|r1) < 8) - T1_LSRI(r0, r1, i0); - else - T2_LSRI(r0, r1, i0); + if (!jit_no_set_flags() && (r0|r1) < 8) + T1_LSRI(r0, r1, i0); + else + T2_LSRI(r0, r1, i0); } else - LSRI(r0, r1, i0); + LSRI(r0, r1, i0); } static void @@ -2452,27 +2441,27 @@ _ccr(jit_state_t *_jit, int ct, int cf, int32_t r0, int32_t r1, int32_t r2) { if (jit_thumb_p()) { - assert((ct ^ cf) >> 28 == 1); - if ((r1|r2) < 8) - T1_CMP(r1, r2); - else if ((r1&r2) & 8) - T1_CMPX(r1, r2); - else - T2_CMP(r1, r2); - ITE(ct); - if (r0 < 8) { - T1_MOVI(r0, 1); - T1_MOVI(r0, 0); - } - else { - T2_MOVI(r0, 1); - T2_MOVI(r0, 0); - } + assert((ct ^ cf) >> 28 == 1); + if ((r1|r2) < 8) + T1_CMP(r1, r2); + else if ((r1&r2) & 8) + T1_CMPX(r1, r2); + else + T2_CMP(r1, r2); + ITE(ct); + if (r0 < 8) { + T1_MOVI(r0, 1); + T1_MOVI(r0, 0); + } + else { + T2_MOVI(r0, 1); + T2_MOVI(r0, 0); + } } else { - CMP(r1, r2); - CC_MOVI(ct, r0, 1); - CC_MOVI(cf, r0, 0); + CMP(r1, r2); + CC_MOVI(ct, r0, 1); + CC_MOVI(cf, r0, 0); } } @@ -2480,49 +2469,49 @@ static void _cci(jit_state_t *_jit, int ct, int cf, int32_t r0, int32_t r1, jit_word_t i0) { - int i; - int32_t reg; + int i; + int32_t reg; if (jit_thumb_p()) { - if (r1 < 7 && !(i0 & 0xffffff00)) - T1_CMPI(r1, i0); - else if ((i = encode_thumb_immediate(i0)) != -1) - T2_CMPI(r1, i); - else if ((i = encode_thumb_immediate(-i0)) != -1) - T2_CMNI(r1, i); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - ccr(ct, cf, r0, r1, rn(reg)); - jit_unget_reg(reg); - return; - } - ITE(ct); - if (r0 < 8) { - T1_MOVI(r0, 1); - T1_MOVI(r0, 0); - } - else { - T2_MOVI(r0, 1); - T2_MOVI(r0, 0); - } + if (r1 < 7 && !(i0 & 0xffffff00)) + T1_CMPI(r1, i0); + else if ((i = encode_thumb_immediate(i0)) != -1) + T2_CMPI(r1, i); + else if ((i = encode_thumb_immediate(-i0)) != -1) + T2_CMNI(r1, i); + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + ccr(ct, cf, r0, r1, rn(reg)); + jit_unget_reg(reg); + return; + } + ITE(ct); + if (r0 < 8) { + T1_MOVI(r0, 1); + T1_MOVI(r0, 0); + } + else { + T2_MOVI(r0, 1); + T2_MOVI(r0, 0); + } } else { - if ((i = encode_arm_immediate(i0)) != -1) - CMPI(r1, i); - else if ((i = encode_arm_immediate(-i0)) != -1) - CMNI(r1, i); - else if (r0 != r1) { - movi(r0, i0); - CMP(r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - CMP(r1, rn(reg)); - jit_unget_reg(reg); - } - CC_MOVI(ct, r0, 1); - CC_MOVI(cf, r0, 0); + if ((i = encode_arm_immediate(i0)) != -1) + CMPI(r1, i); + else if ((i = encode_arm_immediate(-i0)) != -1) + CMNI(r1, i); + else if (r0 != r1) { + movi(r0, i0); + CMP(r1, r0); + } + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + CMP(r1, rn(reg)); + jit_unget_reg(reg); + } + CC_MOVI(ct, r0, 1); + CC_MOVI(cf, r0, 0); } } @@ -2530,36 +2519,36 @@ static void _ner(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { if (jit_thumb_p()) - ccr(ARM_CC_NE, ARM_CC_EQ, r0, r1, r2); + ccr(ARM_CC_NE, ARM_CC_EQ, r0, r1, r2); else { - SUBS(r0, r1, r2); - CC_MOVI(ARM_CC_NE, r0, 1); + SUBS(r0, r1, r2); + CC_MOVI(ARM_CC_NE, r0, 1); } } static void _nei(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - int i; - int32_t reg; + int i; + int32_t reg; if (jit_thumb_p()) - cci(ARM_CC_NE, ARM_CC_EQ, r0, r1, i0); + cci(ARM_CC_NE, ARM_CC_EQ, r0, r1, i0); else { - if ((i = encode_arm_immediate(i0)) != -1) - SUBSI(r0, r1, i); - else if ((i = encode_arm_immediate(-i0)) != -1) - ADDSI(r0, r1, i); - else if (r0 != r1) { - movi(r0, i0); - SUBS(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - SUBS(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - CC_MOVI(ARM_CC_NE, r0, 1); + if ((i = encode_arm_immediate(i0)) != -1) + SUBSI(r0, r1, i); + else if ((i = encode_arm_immediate(-i0)) != -1) + ADDSI(r0, r1, i); + else if (r0 != r1) { + movi(r0, i0); + SUBS(r0, r1, r0); + } + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + SUBS(r0, r1, rn(reg)); + jit_unget_reg(reg); + } + CC_MOVI(ARM_CC_NE, r0, 1); } } @@ -2567,71 +2556,71 @@ static void _jmpr(jit_state_t *_jit, int32_t r0) { if (jit_thumb_p()) - T1_MOV(_R15_REGNO, r0); + T1_MOV(_R15_REGNO, r0); else - MOV(_R15_REGNO, r0); + MOV(_R15_REGNO, r0); } static void _jmpi(jit_state_t *_jit, jit_word_t i0) { - jit_word_t w; - jit_word_t d; - int32_t reg; + jit_word_t w; + jit_word_t d; + int32_t reg; w = _jit->pc.w; /* if thumb and in thumb mode */ if (jit_thumb_p() && _jitc->thumb) { - d = ((i0 - w) >> 1) - 2; - if (d >= -1024 && d <= 1023) - T1_B(d & 0x7ff); - else if (_s24P(d)) - T2_B(encode_thumb_jump(d)); - else { - reg = jit_get_reg(jit_class_gpr|jit_class_nospill); - movi(rn(reg), i0); - jmpr(rn(reg)); - jit_unget_reg(reg); - } + d = ((i0 - w) >> 1) - 2; + if (d >= -1024 && d <= 1023) + T1_B(d & 0x7ff); + else if (_s24P(d)) + T2_B(encode_thumb_jump(d)); + else { + reg = jit_get_reg(jit_class_gpr|jit_class_nospill); + movi(rn(reg), i0); + jmpr(rn(reg)); + jit_unget_reg(reg); + } } else { - d = ((i0 - w) >> 2) - 2; - if (_s24P(d)) - B(d & 0x00ffffff); - else { - reg = jit_get_reg(jit_class_gpr|jit_class_nospill); - movi(rn(reg), i0); - jmpr(rn(reg)); - jit_unget_reg(reg); - } + d = ((i0 - w) >> 2) - 2; + if (_s24P(d)) + B(d & 0x00ffffff); + else { + reg = jit_get_reg(jit_class_gpr|jit_class_nospill); + movi(rn(reg), i0); + jmpr(rn(reg)); + jit_unget_reg(reg); + } } } static jit_word_t _jmpi_p(jit_state_t *_jit, jit_word_t i0, jit_bool_t i1) { - jit_word_t w; - jit_word_t d; - int32_t reg; + jit_word_t w; + jit_word_t d; + int32_t reg; if (i1) { - /* Assume jump is not longer than 23 bits if inside jit */ - w = _jit->pc.w; - /* if thumb and in thumb mode */ - if (jit_thumb_p() && _jitc->thumb) { - d = ((i0 - w) >> 1) - 2; - assert(_s24P(d)); - T2_B(encode_thumb_jump(d)); - } - else { - d = ((i0 - w) >> 2) - 2; - assert(_s24P(d)); - B(d & 0x00ffffff); - } + /* Assume jump is not longer than 23 bits if inside jit */ + w = _jit->pc.w; + /* if thumb and in thumb mode */ + if (jit_thumb_p() && _jitc->thumb) { + d = ((i0 - w) >> 1) - 2; + assert(_s24P(d)); + T2_B(encode_thumb_jump(d)); + } + else { + d = ((i0 - w) >> 2) - 2; + assert(_s24P(d)); + B(d & 0x00ffffff); + } } else { - reg = jit_get_reg(jit_class_gpr|jit_class_nospill); - w = movi_p(rn(reg), i0); - jmpr(rn(reg)); - jit_unget_reg(reg); + reg = jit_get_reg(jit_class_gpr|jit_class_nospill); + w = movi_p(rn(reg), i0); + jmpr(rn(reg)); + jit_unget_reg(reg); } return (w); } @@ -2639,27 +2628,27 @@ _jmpi_p(jit_state_t *_jit, jit_word_t i0, jit_bool_t i1) static jit_word_t _bccr(jit_state_t *_jit, int cc, jit_word_t i0, int32_t r0, int32_t r1) { - jit_word_t w; - jit_word_t d; + jit_word_t w; + jit_word_t d; if (jit_thumb_p()) { - if ((r0|r1) < 8) - T1_CMP(r0, r1); - else if ((r0&r1) & 8) - T1_CMPX(r0, r1); - else - T2_CMP(r0, r1); - /* use only thumb2 conditional as does not know if will be patched */ - w = _jit->pc.w; - d = ((i0 - w) >> 1) - 2; - assert(_s20P(d)); - T2_CC_B(cc, encode_thumb_cc_jump(d)); + if ((r0|r1) < 8) + T1_CMP(r0, r1); + else if ((r0&r1) & 8) + T1_CMPX(r0, r1); + else + T2_CMP(r0, r1); + /* use only thumb2 conditional as does not know if will be patched */ + w = _jit->pc.w; + d = ((i0 - w) >> 1) - 2; + assert(_s20P(d)); + T2_CC_B(cc, encode_thumb_cc_jump(d)); } else { - CMP(r0, r1); - w = _jit->pc.w; - d = ((i0 - w) >> 2) - 2; - assert(_s24P(d)); - CC_B(cc, d & 0x00ffffff); + CMP(r0, r1); + w = _jit->pc.w; + d = ((i0 - w) >> 2) - 2; + assert(_s24P(d)); + CC_B(cc, d & 0x00ffffff); } return (w); } @@ -2667,44 +2656,44 @@ _bccr(jit_state_t *_jit, int cc, jit_word_t i0, int32_t r0, int32_t r1) static jit_word_t _bcci(jit_state_t *_jit, int cc, jit_word_t i0, int32_t r0, jit_word_t i1) { - jit_word_t w; - jit_word_t d; - int i; - int32_t reg; + jit_word_t w; + jit_word_t d; + int i; + int32_t reg; if (jit_thumb_p()) { - if (r0 < 7 && !(i1 & 0xffffff00)) - T1_CMPI(r0, i1); - else if ((i = encode_thumb_immediate(i1)) != -1) - T2_CMPI(r0, i); - else if ((i = encode_thumb_immediate(-i1)) != -1) - T2_CMNI(r0, i); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i1); - T2_CMP(r0, rn(reg)); - jit_unget_reg(reg); - } - /* use only thumb2 conditional as does not know if will be patched */ - w = _jit->pc.w; - d = ((i0 - w) >> 1) - 2; - assert(_s20P(d)); - T2_CC_B(cc, encode_thumb_cc_jump(d)); + if (r0 < 7 && !(i1 & 0xffffff00)) + T1_CMPI(r0, i1); + else if ((i = encode_thumb_immediate(i1)) != -1) + T2_CMPI(r0, i); + else if ((i = encode_thumb_immediate(-i1)) != -1) + T2_CMNI(r0, i); + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i1); + T2_CMP(r0, rn(reg)); + jit_unget_reg(reg); + } + /* use only thumb2 conditional as does not know if will be patched */ + w = _jit->pc.w; + d = ((i0 - w) >> 1) - 2; + assert(_s20P(d)); + T2_CC_B(cc, encode_thumb_cc_jump(d)); } else { - if ((i = encode_arm_immediate(i1)) != -1) - CMPI(r0, i); - else if ((i = encode_arm_immediate(-i1)) != -1) - CMNI(r0, i); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i1); - CMP(r0, rn(reg)); - jit_unget_reg(reg); - } - w = _jit->pc.w; - d = ((i0 - w) >> 2) - 2; - assert(_s24P(d)); - CC_B(cc, d & 0x00ffffff); + if ((i = encode_arm_immediate(i1)) != -1) + CMPI(r0, i); + else if ((i = encode_arm_immediate(-i1)) != -1) + CMNI(r0, i); + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i1); + CMP(r0, rn(reg)); + jit_unget_reg(reg); + } + w = _jit->pc.w; + d = ((i0 - w) >> 2) - 2; + assert(_s24P(d)); + CC_B(cc, d & 0x00ffffff); } return (w); } @@ -2712,24 +2701,24 @@ _bcci(jit_state_t *_jit, int cc, jit_word_t i0, int32_t r0, jit_word_t i1) static jit_word_t _baddr(jit_state_t *_jit, int cc, jit_word_t i0, int32_t r0, int32_t r1) { - jit_word_t w; - jit_word_t d; + jit_word_t w; + jit_word_t d; if (jit_thumb_p()) { - if ((r0|r1) < 8) - T1_ADD(r0, r0, r1); - else - T2_ADDS(r0, r0, r1); - w = _jit->pc.w; - d = ((i0 - w) >> 1) - 2; - assert(_s20P(d)); - T2_CC_B(cc, encode_thumb_cc_jump(d)); + if ((r0|r1) < 8) + T1_ADD(r0, r0, r1); + else + T2_ADDS(r0, r0, r1); + w = _jit->pc.w; + d = ((i0 - w) >> 1) - 2; + assert(_s20P(d)); + T2_CC_B(cc, encode_thumb_cc_jump(d)); } else { - ADDS(r0, r0, r1); - w = _jit->pc.w; - d = ((i0 - w) >> 2) - 2; - assert(_s24P(d)); - CC_B(cc, d & 0x00ffffff); + ADDS(r0, r0, r1); + w = _jit->pc.w; + d = ((i0 - w) >> 2) - 2; + assert(_s24P(d)); + CC_B(cc, d & 0x00ffffff); } return (w); } @@ -2737,49 +2726,49 @@ _baddr(jit_state_t *_jit, int cc, jit_word_t i0, int32_t r0, int32_t r1) static jit_word_t _baddi(jit_state_t *_jit, int cc, jit_word_t i0, int32_t r0, int i1) { - int i; - jit_word_t w; - jit_word_t d; - int32_t reg; + int i; + jit_word_t w; + jit_word_t d; + int32_t reg; if (jit_thumb_p()) { - if (r0 < 8 && !(i1 & ~7)) - T1_ADDI3(r0, r0, i1); - else if (r0 < 8 && !(-i1 & ~7)) - T1_SUBI3(r0, r0, -i1); - else if (r0 < 8 && !(i1 & ~0xff)) - T1_ADDI8(r0, i1); - else if (r0 < 8 && !(-i1 & ~0xff)) - T1_SUBI8(r0, -i1); - else if ((i = encode_thumb_immediate(i1)) != -1) - T2_ADDSI(r0, r0, i); - else if ((i = encode_thumb_immediate(-i1)) != -1) - T2_SUBSI(r0, r0, i); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i1); - T2_ADDS(r0, r0, rn(reg)); - jit_unget_reg(reg); - } - w = _jit->pc.w; - d = ((i0 - w) >> 1) - 2; - assert(_s20P(d)); - T2_CC_B(cc, encode_thumb_cc_jump(d)); + if (r0 < 8 && !(i1 & ~7)) + T1_ADDI3(r0, r0, i1); + else if (r0 < 8 && !(-i1 & ~7)) + T1_SUBI3(r0, r0, -i1); + else if (r0 < 8 && !(i1 & ~0xff)) + T1_ADDI8(r0, i1); + else if (r0 < 8 && !(-i1 & ~0xff)) + T1_SUBI8(r0, -i1); + else if ((i = encode_thumb_immediate(i1)) != -1) + T2_ADDSI(r0, r0, i); + else if ((i = encode_thumb_immediate(-i1)) != -1) + T2_SUBSI(r0, r0, i); + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i1); + T2_ADDS(r0, r0, rn(reg)); + jit_unget_reg(reg); + } + w = _jit->pc.w; + d = ((i0 - w) >> 1) - 2; + assert(_s20P(d)); + T2_CC_B(cc, encode_thumb_cc_jump(d)); } else { - if ((i = encode_arm_immediate(i1)) != -1) - ADDSI(r0, r0, i); - else if ((i = encode_arm_immediate(-i1)) != -1) - SUBSI(r0, r0, i); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i1); - ADDS(r0, r0, rn(reg)); - jit_unget_reg(reg); - } - w = _jit->pc.w; - d = ((i0 - w) >> 2) - 2; - assert(_s24P(d)); - CC_B(cc, d & 0x00ffffff); + if ((i = encode_arm_immediate(i1)) != -1) + ADDSI(r0, r0, i); + else if ((i = encode_arm_immediate(-i1)) != -1) + SUBSI(r0, r0, i); + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i1); + ADDS(r0, r0, rn(reg)); + jit_unget_reg(reg); + } + w = _jit->pc.w; + d = ((i0 - w) >> 2) - 2; + assert(_s24P(d)); + CC_B(cc, d & 0x00ffffff); } return (w); } @@ -2787,24 +2776,24 @@ _baddi(jit_state_t *_jit, int cc, jit_word_t i0, int32_t r0, int i1) static jit_word_t _bsubr(jit_state_t *_jit, int cc, jit_word_t i0, int32_t r0, int32_t r1) { - jit_word_t w; - jit_word_t d; + jit_word_t w; + jit_word_t d; if (jit_thumb_p()) { - if ((r0|r1) < 8) - T1_SUB(r0, r0, r1); - else - T2_SUBS(r0, r0, r1); - w = _jit->pc.w; - d = ((i0 - w) >> 1) - 2; - assert(_s20P(d)); - T2_CC_B(cc, encode_thumb_cc_jump(d)); + if ((r0|r1) < 8) + T1_SUB(r0, r0, r1); + else + T2_SUBS(r0, r0, r1); + w = _jit->pc.w; + d = ((i0 - w) >> 1) - 2; + assert(_s20P(d)); + T2_CC_B(cc, encode_thumb_cc_jump(d)); } else { - SUBS(r0, r0, r1); - w = _jit->pc.w; - d = ((i0 - w) >> 2) - 2; - assert(_s24P(d)); - CC_B(cc, d & 0x00ffffff); + SUBS(r0, r0, r1); + w = _jit->pc.w; + d = ((i0 - w) >> 2) - 2; + assert(_s24P(d)); + CC_B(cc, d & 0x00ffffff); } return (w); } @@ -2812,49 +2801,49 @@ _bsubr(jit_state_t *_jit, int cc, jit_word_t i0, int32_t r0, int32_t r1) static jit_word_t _bsubi(jit_state_t *_jit, int cc, jit_word_t i0, int32_t r0, int i1) { - int i; - jit_word_t w; - jit_word_t d; - int32_t reg; + int i; + jit_word_t w; + jit_word_t d; + int32_t reg; if (jit_thumb_p()) { - if (r0 < 8 && !(i1 & ~7)) - T1_SUBI3(r0, r0, i1); - else if (r0 < 8 && !(-i1 & ~7)) - T1_ADDI3(r0, r0, -i1); - else if (r0 < 8 && !(i1 & ~0xff)) - T1_SUBI8(r0, i1); - else if (r0 < 8 && !(-i1 & ~0xff)) - T1_ADDI8(r0, -i1); - else if ((i = encode_thumb_immediate(i1)) != -1) - T2_SUBSI(r0, r0, i); - else if ((i = encode_thumb_immediate(-i1)) != -1) - T2_SUBSI(r0, r0, i); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i1); - T2_SUBS(r0, r0, rn(reg)); - jit_unget_reg(reg); - } - w = _jit->pc.w; - d = ((i0 - w) >> 1) - 2; - assert(_s20P(d)); - T2_CC_B(cc, encode_thumb_cc_jump(d)); + if (r0 < 8 && !(i1 & ~7)) + T1_SUBI3(r0, r0, i1); + else if (r0 < 8 && !(-i1 & ~7)) + T1_ADDI3(r0, r0, -i1); + else if (r0 < 8 && !(i1 & ~0xff)) + T1_SUBI8(r0, i1); + else if (r0 < 8 && !(-i1 & ~0xff)) + T1_ADDI8(r0, -i1); + else if ((i = encode_thumb_immediate(i1)) != -1) + T2_SUBSI(r0, r0, i); + else if ((i = encode_thumb_immediate(-i1)) != -1) + T2_SUBSI(r0, r0, i); + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i1); + T2_SUBS(r0, r0, rn(reg)); + jit_unget_reg(reg); + } + w = _jit->pc.w; + d = ((i0 - w) >> 1) - 2; + assert(_s20P(d)); + T2_CC_B(cc, encode_thumb_cc_jump(d)); } else { - if ((i = encode_arm_immediate(i1)) != -1) - SUBSI(r0, r0, i); - else if ((i = encode_arm_immediate(-i1)) != -1) - ADDSI(r0, r0, i); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i1); - SUBS(r0, r0, rn(reg)); - jit_unget_reg(reg); - } - w = _jit->pc.w; - d = ((i0 - w) >> 2) - 2; - assert(_s24P(d)); - CC_B(cc, d & 0x00ffffff); + if ((i = encode_arm_immediate(i1)) != -1) + SUBSI(r0, r0, i); + else if ((i = encode_arm_immediate(-i1)) != -1) + ADDSI(r0, r0, i); + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i1); + SUBS(r0, r0, rn(reg)); + jit_unget_reg(reg); + } + w = _jit->pc.w; + d = ((i0 - w) >> 2) - 2; + assert(_s24P(d)); + CC_B(cc, d & 0x00ffffff); } return (w); } @@ -2862,31 +2851,31 @@ _bsubi(jit_state_t *_jit, int cc, jit_word_t i0, int32_t r0, int i1) static jit_word_t _bmxr(jit_state_t *_jit, int cc, jit_word_t i0, int32_t r0, int32_t r1) { - jit_word_t w; - jit_word_t d; - int32_t reg; + jit_word_t w; + jit_word_t d; + int32_t reg; if (jit_thumb_p()) { - if ((r0|r1) < 8) - T1_TST(r0, r1); - else - T2_TST(r0, r1); - w = _jit->pc.w; - d = ((i0 - w) >> 1) - 2; - assert(_s20P(d)); - T2_CC_B(cc, encode_thumb_cc_jump(d)); + if ((r0|r1) < 8) + T1_TST(r0, r1); + else + T2_TST(r0, r1); + w = _jit->pc.w; + d = ((i0 - w) >> 1) - 2; + assert(_s20P(d)); + T2_CC_B(cc, encode_thumb_cc_jump(d)); } else { - if (jit_armv5_p()) - TST(r0, r1); - else { - reg = jit_get_reg(jit_class_gpr); - ANDS(rn(reg), r0, r1); - jit_unget_reg(reg); - } - w = _jit->pc.w; - d = ((i0 - w) >> 2) - 2; - assert(_s24P(d)); - CC_B(cc, d & 0x00ffffff); + if (jit_armv5_p()) + TST(r0, r1); + else { + reg = jit_get_reg(jit_class_gpr); + ANDS(rn(reg), r0, r1); + jit_unget_reg(reg); + } + w = _jit->pc.w; + d = ((i0 - w) >> 2) - 2; + assert(_s24P(d)); + CC_B(cc, d & 0x00ffffff); } return (w); } @@ -2894,51 +2883,51 @@ _bmxr(jit_state_t *_jit, int cc, jit_word_t i0, int32_t r0, int32_t r1) static jit_word_t _bmxi(jit_state_t *_jit, int cc, jit_word_t i0, int32_t r0, jit_word_t i1) { - int i; - jit_word_t w; - jit_word_t d; - int32_t reg; + int i; + jit_word_t w; + jit_word_t d; + int32_t reg; if (jit_thumb_p()) { - if ((i = encode_thumb_immediate(i1)) != -1) - T2_TSTI(r0, i); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i1); - T2_TST(r0, rn(reg)); - jit_unget_reg(reg); - } - w = _jit->pc.w; - d = ((i0 - w) >> 1) - 2; - assert(_s20P(d)); - T2_CC_B(cc, encode_thumb_cc_jump(d)); + if ((i = encode_thumb_immediate(i1)) != -1) + T2_TSTI(r0, i); + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i1); + T2_TST(r0, rn(reg)); + jit_unget_reg(reg); + } + w = _jit->pc.w; + d = ((i0 - w) >> 1) - 2; + assert(_s20P(d)); + T2_CC_B(cc, encode_thumb_cc_jump(d)); } else { - if (jit_armv5_p()) { - if ((i = encode_arm_immediate(i1)) != -1) - TSTI(r0, i); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i1); - TST(r0, rn(reg)); - jit_unget_reg(reg); - } - } - else { - reg = jit_get_reg(jit_class_gpr); - if ((i = encode_arm_immediate(i1)) != -1) - ANDSI(rn(reg), r0, i); - else if ((i = encode_arm_immediate(~i1)) != -1) - BICSI(rn(reg), r0, i); - else { - movi(rn(reg), i1); - ANDS(rn(reg), r0, rn(reg)); - } - jit_unget_reg(reg); - } - w = _jit->pc.w; - d = ((i0 - w) >> 2) - 2; - assert(_s24P(d)); - CC_B(cc, d & 0x00ffffff); + if (jit_armv5_p()) { + if ((i = encode_arm_immediate(i1)) != -1) + TSTI(r0, i); + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i1); + TST(r0, rn(reg)); + jit_unget_reg(reg); + } + } + else { + reg = jit_get_reg(jit_class_gpr); + if ((i = encode_arm_immediate(i1)) != -1) + ANDSI(rn(reg), r0, i); + else if ((i = encode_arm_immediate(~i1)) != -1) + BICSI(rn(reg), r0, i); + else { + movi(rn(reg), i1); + ANDS(rn(reg), r0, rn(reg)); + } + jit_unget_reg(reg); + } + w = _jit->pc.w; + d = ((i0 - w) >> 2) - 2; + assert(_s24P(d)); + CC_B(cc, d & 0x00ffffff); } return (w); } @@ -2947,21 +2936,21 @@ static void _ldr_c(jit_state_t *_jit, int32_t r0, int32_t r1) { if (jit_thumb_p()) - T2_LDRSBI(r0, r1, 0); + T2_LDRSBI(r0, r1, 0); else - LDRSBI(r0, r1, 0); + LDRSBI(r0, r1, 0); } static void _ldi_c(jit_state_t *_jit, int32_t r0, jit_word_t i0) { - int32_t reg; + int32_t reg; reg = jit_get_reg(jit_class_gpr); movi(rn(reg), i0); if (jit_thumb_p()) - T2_LDRSBI(r0, rn(reg), 0); + T2_LDRSBI(r0, rn(reg), 0); else - LDRSBI(r0, rn(reg), 0); + LDRSBI(r0, rn(reg), 0); jit_unget_reg(reg); } @@ -2969,58 +2958,60 @@ static void _ldxr_c(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { if (jit_thumb_p()) { - if ((r0|r1|r2) < 8) - T1_LDRSB(r0, r1, r2); - else - T2_LDRSB(r0, r1, r2); + if ((r0|r1|r2) < 8) + T1_LDRSB(r0, r1, r2); + else + T2_LDRSB(r0, r1, r2); } else - LDRSB(r0, r1, r2); + LDRSB(r0, r1, r2); } +#define jit_ldrt_strt_p() 0 + static void _ldxi_c(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - int32_t reg; + int32_t reg; if (jit_thumb_p()) { - if (jit_ldrt_strt_p() && i0 >= 0 && i0 <= 255) - T2_LDRSBI(r0, r1, i0); - else if (i0 < 0 && i0 >= -255) - T2_LDRSBIN(r0, r1, -i0); - else if (i0 >= 0 && i0 <= 4095) - T2_LDRSBWI(r0, r1, i0); - else if (r0 != r1) { - movi(r0, i0); - if ((r0|r1) < 8) - T1_LDRSB(r0, r1, r0); - else - T2_LDRSB(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - if ((r0|r1|rn(reg)) < 8) - T1_LDRSB(r0, r1, rn(reg)); - else - T2_LDRSB(r0, r1, rn(reg)); - jit_unget_reg(reg); - } + if (jit_ldrt_strt_p() && i0 >= 0 && i0 <= 255) + T2_LDRSBI(r0, r1, i0); + else if (i0 < 0 && i0 >= -255) + T2_LDRSBIN(r0, r1, -i0); + else if (i0 >= 0 && i0 <= 4095) + T2_LDRSBWI(r0, r1, i0); + else if (r0 != r1) { + movi(r0, i0); + if ((r0|r1) < 8) + T1_LDRSB(r0, r1, r0); + else + T2_LDRSB(r0, r1, r0); + } + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + if ((r0|r1|rn(reg)) < 8) + T1_LDRSB(r0, r1, rn(reg)); + else + T2_LDRSB(r0, r1, rn(reg)); + jit_unget_reg(reg); + } } else { - if (i0 >= 0 && i0 <= 255) - LDRSBI(r0, r1, i0); - else if (i0 < 0 && i0 >= -255) - LDRSBIN(r0, r1, -i0); - else if (r0 != r1) { - movi(r0, i0); - LDRSB(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - LDRSB(r0, r1, rn(reg)); - jit_unget_reg(reg); - } + if (i0 >= 0 && i0 <= 255) + LDRSBI(r0, r1, i0); + else if (i0 < 0 && i0 >= -255) + LDRSBIN(r0, r1, -i0); + else if (r0 != r1) { + movi(r0, i0); + LDRSB(r0, r1, r0); + } + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + LDRSB(r0, r1, rn(reg)); + jit_unget_reg(reg); + } } } @@ -3028,21 +3019,21 @@ static void _ldr_uc(jit_state_t *_jit, int32_t r0, int32_t r1) { if (jit_thumb_p()) - T2_LDRBI(r0, r1, 0); + T2_LDRBI(r0, r1, 0); else - LDRBI(r0, r1, 0); + LDRBI(r0, r1, 0); } static void _ldi_uc(jit_state_t *_jit, int32_t r0, jit_word_t i0) { - int32_t reg; + int32_t reg; reg = jit_get_reg(jit_class_gpr); movi(rn(reg), i0); if (jit_thumb_p()) - T2_LDRBI(r0, rn(reg), 0); + T2_LDRBI(r0, rn(reg), 0); else - LDRBI(r0, rn(reg), 0); + LDRBI(r0, rn(reg), 0); jit_unget_reg(reg); } @@ -3050,60 +3041,60 @@ static void _ldxr_uc(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { if (jit_thumb_p()) { - if ((r0|r1|r2) < 8) - T1_LDRB(r0, r1, r2); - else - T2_LDRB(r0, r1, r2); + if ((r0|r1|r2) < 8) + T1_LDRB(r0, r1, r2); + else + T2_LDRB(r0, r1, r2); } else - LDRB(r0, r1, r2); + LDRB(r0, r1, r2); } static void _ldxi_uc(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - int32_t reg; + int32_t reg; if (jit_thumb_p()) { - if ((r0|r1) < 8 && i0 >= 0 && i0 < 0x20) - T1_LDRBI(r0, r1, i0); - else if (jit_ldrt_strt_p() && i0 >= 0 && i0 <= 255) - T2_LDRBI(r0, r1, i0); - else if (i0 < 0 && i0 >= -255) - T2_LDRBIN(r0, r1, -i0); - else if (i0 >= 0 && i0 <= 4095) - T2_LDRBWI(r0, r1, i0); - else if (r0 != r1) { - movi(r0, i0); - if ((r0|r1) < 8) - T1_LDRB(r0, r1, r0); - else - T2_LDRB(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - if ((r0|r1|rn(reg)) < 8) - T1_LDRB(r0, r1, rn(reg)); - else - T2_LDRB(r0, r1, rn(reg)); - jit_unget_reg(reg); - } + if ((r0|r1) < 8 && i0 >= 0 && i0 < 0x20) + T1_LDRBI(r0, r1, i0); + else if (jit_ldrt_strt_p() && i0 >= 0 && i0 <= 255) + T2_LDRBI(r0, r1, i0); + else if (i0 < 0 && i0 >= -255) + T2_LDRBIN(r0, r1, -i0); + else if (i0 >= 0 && i0 <= 4095) + T2_LDRBWI(r0, r1, i0); + else if (r0 != r1) { + movi(r0, i0); + if ((r0|r1) < 8) + T1_LDRB(r0, r1, r0); + else + T2_LDRB(r0, r1, r0); + } + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + if ((r0|r1|rn(reg)) < 8) + T1_LDRB(r0, r1, rn(reg)); + else + T2_LDRB(r0, r1, rn(reg)); + jit_unget_reg(reg); + } } else { - if (i0 >= 0 && i0 <= 4095) - LDRBI(r0, r1, i0); - else if (i0 < 0 && i0 >= -4095) - LDRBIN(r0, r1, -i0); - else if (r0 != r1) { - movi(r0, i0); - LDRB(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - LDRB(r0, r1, rn(reg)); - jit_unget_reg(reg); - } + if (i0 >= 0 && i0 <= 4095) + LDRBI(r0, r1, i0); + else if (i0 < 0 && i0 >= -4095) + LDRBIN(r0, r1, -i0); + else if (r0 != r1) { + movi(r0, i0); + LDRB(r0, r1, r0); + } + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + LDRB(r0, r1, rn(reg)); + jit_unget_reg(reg); + } } } @@ -3111,21 +3102,21 @@ static void _ldr_s(jit_state_t *_jit, int32_t r0, int32_t r1) { if (jit_thumb_p()) - T2_LDRSHI(r0, r1, 0); + T2_LDRSHI(r0, r1, 0); else - LDRSHI(r0, r1, 0); + LDRSHI(r0, r1, 0); } static void _ldi_s(jit_state_t *_jit, int32_t r0, jit_word_t i0) { - int32_t reg; + int32_t reg; reg = jit_get_reg(jit_class_gpr); movi(rn(reg), i0); if (jit_thumb_p()) - T2_LDRSHI(r0, rn(reg), 0); + T2_LDRSHI(r0, rn(reg), 0); else - LDRSHI(r0, rn(reg), 0); + LDRSHI(r0, rn(reg), 0); jit_unget_reg(reg); } @@ -3133,58 +3124,58 @@ static void _ldxr_s(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { if (jit_thumb_p()) { - if ((r0|r1|r2) < 8) - T1_LDRSH(r0, r1, r2); - else - T2_LDRSH(r0, r1, r2); + if ((r0|r1|r2) < 8) + T1_LDRSH(r0, r1, r2); + else + T2_LDRSH(r0, r1, r2); } else - LDRSH(r0, r1, r2); + LDRSH(r0, r1, r2); } static void _ldxi_s(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - int32_t reg; + int32_t reg; if (jit_thumb_p()) { - if (jit_ldrt_strt_p() && i0 >= 0 && i0 <= 255) - T2_LDRSHI(r0, r1, i0); - else if (i0 < 0 && i0 >= -255) - T2_LDRSHIN(r0, r1, -i0); - else if (i0 >= 0 && i0 <= 4095) - T2_LDRSHWI(r0, r1, i0); - else if (r0 != r1) { - movi(r0, i0); - if ((r0|r1) < 8) - T1_LDRSH(r0, r1, r0); - else - T2_LDRSH(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - if ((r0|r1|rn(reg)) < 8) - T1_LDRSH(r0, r1, rn(reg)); - else - T2_LDRSH(r0, r1, rn(reg)); - jit_unget_reg(reg); - } + if (jit_ldrt_strt_p() && i0 >= 0 && i0 <= 255) + T2_LDRSHI(r0, r1, i0); + else if (i0 < 0 && i0 >= -255) + T2_LDRSHIN(r0, r1, -i0); + else if (i0 >= 0 && i0 <= 4095) + T2_LDRSHWI(r0, r1, i0); + else if (r0 != r1) { + movi(r0, i0); + if ((r0|r1) < 8) + T1_LDRSH(r0, r1, r0); + else + T2_LDRSH(r0, r1, r0); + } + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + if ((r0|r1|rn(reg)) < 8) + T1_LDRSH(r0, r1, rn(reg)); + else + T2_LDRSH(r0, r1, rn(reg)); + jit_unget_reg(reg); + } } else { - if (i0 >= 0 && i0 <= 255) - LDRSHI(r0, r1, i0); - else if (i0 < 0 && i0 >= -255) - LDRSHIN(r0, r1, -i0); - else if (r0 != r1) { - movi(r0, i0); - LDRSH(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - LDRSH(r0, r1, rn(reg)); - jit_unget_reg(reg); - } + if (i0 >= 0 && i0 <= 255) + LDRSHI(r0, r1, i0); + else if (i0 < 0 && i0 >= -255) + LDRSHIN(r0, r1, -i0); + else if (r0 != r1) { + movi(r0, i0); + LDRSH(r0, r1, r0); + } + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + LDRSH(r0, r1, rn(reg)); + jit_unget_reg(reg); + } } } @@ -3192,21 +3183,21 @@ static void _ldr_us(jit_state_t *_jit, int32_t r0, int32_t r1) { if (jit_thumb_p()) - T2_LDRHI(r0, r1, 0); + T2_LDRHI(r0, r1, 0); else - LDRHI(r0, r1, 0); + LDRHI(r0, r1, 0); } static void _ldi_us(jit_state_t *_jit, int32_t r0, jit_word_t i0) { - int32_t reg; + int32_t reg; reg = jit_get_reg(jit_class_gpr); movi(rn(reg), i0); if (jit_thumb_p()) - T2_LDRHI(r0, rn(reg), 0); + T2_LDRHI(r0, rn(reg), 0); else - LDRHI(r0, rn(reg), 0); + LDRHI(r0, rn(reg), 0); jit_unget_reg(reg); } @@ -3214,60 +3205,60 @@ static void _ldxr_us(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { if (jit_thumb_p()) { - if ((r0|r1|r2) < 8) - T1_LDRH(r0, r1, r2); - else - T2_LDRH(r0, r1, r2); + if ((r0|r1|r2) < 8) + T1_LDRH(r0, r1, r2); + else + T2_LDRH(r0, r1, r2); } else - LDRH(r0, r1, r2); + LDRH(r0, r1, r2); } static void _ldxi_us(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - int32_t reg; + int32_t reg; if (jit_thumb_p()) { - if ((r0|r1) < 8 && i0 >= 0 && !(i0 & 1) && (i0 >> 1) < 0x20) - T1_LDRHI(r0, r1, i0 >> 1); - else if (jit_ldrt_strt_p() && i0 >= 0 && i0 <= 255) - T2_LDRHI(r0, r1, i0); - else if (i0 < 0 && i0 >= -255) - T2_LDRHIN(r0, r1, -i0); - else if (i0 >= 0 && i0 <= 4095) - T2_LDRHWI(r0, r1, i0); - else if (r0 != r1) { - movi(r0, i0); - if ((r0|r1) < 8) - T1_LDRH(r0, r1, r0); - else - T2_LDRH(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - if ((r0|r1|rn(reg)) < 8) - T1_LDRH(r0, r1, rn(reg)); - else - T2_LDRH(r0, r1, rn(reg)); - jit_unget_reg(reg); - } + if ((r0|r1) < 8 && i0 >= 0 && !(i0 & 1) && (i0 >> 1) < 0x20) + T1_LDRHI(r0, r1, i0 >> 1); + else if (jit_ldrt_strt_p() && i0 >= 0 && i0 <= 255) + T2_LDRHI(r0, r1, i0); + else if (i0 < 0 && i0 >= -255) + T2_LDRHIN(r0, r1, -i0); + else if (i0 >= 0 && i0 <= 4095) + T2_LDRHWI(r0, r1, i0); + else if (r0 != r1) { + movi(r0, i0); + if ((r0|r1) < 8) + T1_LDRH(r0, r1, r0); + else + T2_LDRH(r0, r1, r0); + } + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + if ((r0|r1|rn(reg)) < 8) + T1_LDRH(r0, r1, rn(reg)); + else + T2_LDRH(r0, r1, rn(reg)); + jit_unget_reg(reg); + } } else { - if (i0 >= 0 && i0 <= 255) - LDRHI(r0, r1, i0); - else if (i0 < 0 && i0 >= -255) - LDRHIN(r0, r1, -i0); - else if (r0 != r1) { - movi(r0, i0); - LDRH(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - LDRH(r0, r1, rn(reg)); - jit_unget_reg(reg); - } + if (i0 >= 0 && i0 <= 255) + LDRHI(r0, r1, i0); + else if (i0 < 0 && i0 >= -255) + LDRHIN(r0, r1, -i0); + else if (r0 != r1) { + movi(r0, i0); + LDRH(r0, r1, r0); + } + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + LDRH(r0, r1, rn(reg)); + jit_unget_reg(reg); + } } } @@ -3275,21 +3266,21 @@ static void _ldr_i(jit_state_t *_jit, int32_t r0, int32_t r1) { if (jit_thumb_p()) - T2_LDRI(r0, r1, 0); + T2_LDRI(r0, r1, 0); else - LDRI(r0, r1, 0); + LDRI(r0, r1, 0); } static void _ldi_i(jit_state_t *_jit, int32_t r0, jit_word_t i0) { - int32_t reg; + int32_t reg; reg = jit_get_reg(jit_class_gpr); movi(rn(reg), i0); if (jit_thumb_p()) - T2_LDRI(r0, rn(reg), 0); + T2_LDRI(r0, rn(reg), 0); else - LDRI(r0, rn(reg), 0); + LDRI(r0, rn(reg), 0); jit_unget_reg(reg); } @@ -3297,63 +3288,63 @@ static void _ldxr_i(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { if (jit_thumb_p()) { - if ((r0|r1|r2) < 8) - T1_LDR(r0, r1, r2); - else - T2_LDR(r0, r1, r2); + if ((r0|r1|r2) < 8) + T1_LDR(r0, r1, r2); + else + T2_LDR(r0, r1, r2); } else - LDR(r0, r1, r2); + LDR(r0, r1, r2); } static void _ldxi_i(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - int32_t reg; + int32_t reg; if (jit_thumb_p()) { - if ((r0|r1) < 8 && i0 >= 0 && !(i0 & 3) && (i0 >> 2) < 0x20) - T1_LDRI(r0, r1, i0 >> 2); - else if (r1 == _R13_REGNO && r0 < 8 && - i0 >= 0 && !(i0 & 3) && (i0 >> 2) <= 255) - T1_LDRISP(r0, i0 >> 2); - else if (jit_ldrt_strt_p() && i0 >= 0 && i0 <= 255) - T2_LDRI(r0, r1, i0); - else if (i0 < 0 && i0 > -255) - T2_LDRIN(r0, r1, -i0); - else if (i0 >= 0 && i0 <= 4095) - T2_LDRWI(r0, r1, i0); - else if (r0 != r1) { - movi(r0, i0); - if ((r0|r1) < 8) - T1_LDR(r0, r1, r0); - else - T2_LDR(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - if ((r0|r1|rn(reg)) < 8) - T1_LDR(r0, r1, rn(reg)); - else - T2_LDR(r0, r1, rn(reg)); - jit_unget_reg(reg); - } + if ((r0|r1) < 8 && i0 >= 0 && !(i0 & 3) && (i0 >> 2) < 0x20) + T1_LDRI(r0, r1, i0 >> 2); + else if (r1 == _R13_REGNO && r0 < 8 && + i0 >= 0 && !(i0 & 3) && (i0 >> 2) <= 255) + T1_LDRISP(r0, i0 >> 2); + else if (jit_ldrt_strt_p() && i0 >= 0 && i0 <= 255) + T2_LDRI(r0, r1, i0); + else if (i0 < 0 && i0 > -255) + T2_LDRIN(r0, r1, -i0); + else if (i0 >= 0 && i0 <= 4095) + T2_LDRWI(r0, r1, i0); + else if (r0 != r1) { + movi(r0, i0); + if ((r0|r1) < 8) + T1_LDR(r0, r1, r0); + else + T2_LDR(r0, r1, r0); + } + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + if ((r0|r1|rn(reg)) < 8) + T1_LDR(r0, r1, rn(reg)); + else + T2_LDR(r0, r1, rn(reg)); + jit_unget_reg(reg); + } } else { - if (i0 >= 0 && i0 <= 4095) - LDRI(r0, r1, i0); - else if (i0 < 0 && i0 >= -4095) - LDRIN(r0, r1, -i0); - else if (r0 != r1) { - movi(r0, i0); - LDR(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - LDR(r0, r1, rn(reg)); - jit_unget_reg(reg); - } + if (i0 >= 0 && i0 <= 4095) + LDRI(r0, r1, i0); + else if (i0 < 0 && i0 >= -4095) + LDRIN(r0, r1, -i0); + else if (r0 != r1) { + movi(r0, i0); + LDR(r0, r1, r0); + } + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + LDR(r0, r1, rn(reg)); + jit_unget_reg(reg); + } } } @@ -3361,21 +3352,21 @@ static void _str_c(jit_state_t *_jit, int32_t r0, int32_t r1) { if (jit_thumb_p()) - T2_STRBI(r1, r0, 0); + T2_STRBI(r1, r0, 0); else - STRBI(r1, r0, 0); + STRBI(r1, r0, 0); } static void _sti_c(jit_state_t *_jit, jit_word_t i0, int32_t r0) { - int32_t reg; + int32_t reg; reg = jit_get_reg(jit_class_gpr); movi(rn(reg), i0); if (jit_thumb_p()) - T2_STRBI(r0, rn(reg), 0); + T2_STRBI(r0, rn(reg), 0); else - STRBI(r0, rn(reg), 0); + STRBI(r0, rn(reg), 0); jit_unget_reg(reg); } @@ -3383,49 +3374,49 @@ static void _stxr_c(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { if (jit_thumb_p()) { - if ((r0|r1|r2) < 8) - T1_STRB(r2, r1, r0); - else - T2_STRB(r2, r1, r0); + if ((r0|r1|r2) < 8) + T1_STRB(r2, r1, r0); + else + T2_STRB(r2, r1, r0); } else - STRB(r2, r1, r0); + STRB(r2, r1, r0); } static void _stxi_c(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) { - int32_t reg; + int32_t reg; if (jit_thumb_p()) { - if ((r0|r1) < 8 && i0 >= 0 && i0 < 0x20) - T1_STRBI(r1, r0, i0); - else if (jit_ldrt_strt_p() && i0 >= 0 && i0 <= 255) - T2_STRBI(r1, r0, i0); - else if (i0 < 0 && i0 >= -255) - T2_STRBIN(r1, r0, -i0); - else if (i0 >= 0 && i0 <= 4095) - T2_STRBWI(r1, r0, i0); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - if ((r0|r1|rn(reg)) < 8) - T1_STRB(r1, r0, rn(reg)); - else - T2_STRB(r1, r0, rn(reg)); - jit_unget_reg(reg); - } + if ((r0|r1) < 8 && i0 >= 0 && i0 < 0x20) + T1_STRBI(r1, r0, i0); + else if (jit_ldrt_strt_p() && i0 >= 0 && i0 <= 255) + T2_STRBI(r1, r0, i0); + else if (i0 < 0 && i0 >= -255) + T2_STRBIN(r1, r0, -i0); + else if (i0 >= 0 && i0 <= 4095) + T2_STRBWI(r1, r0, i0); + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + if ((r0|r1|rn(reg)) < 8) + T1_STRB(r1, r0, rn(reg)); + else + T2_STRB(r1, r0, rn(reg)); + jit_unget_reg(reg); + } } else { - if (i0 >= 0 && i0 <= 4095) - STRBI(r1, r0, i0); - else if (i0 < 0 && i0 >= -4095) - STRBIN(r1, r0, -i0); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - STRB(r1, r0, rn(reg)); - jit_unget_reg(reg); - } + if (i0 >= 0 && i0 <= 4095) + STRBI(r1, r0, i0); + else if (i0 < 0 && i0 >= -4095) + STRBIN(r1, r0, -i0); + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + STRB(r1, r0, rn(reg)); + jit_unget_reg(reg); + } } } @@ -3433,21 +3424,21 @@ static void _str_s(jit_state_t *_jit, int32_t r0, int32_t r1) { if (jit_thumb_p()) - T2_STRHI(r1, r0, 0); + T2_STRHI(r1, r0, 0); else - STRHI(r1, r0, 0); + STRHI(r1, r0, 0); } static void _sti_s(jit_state_t *_jit, jit_word_t i0, int32_t r0) { - int32_t reg; + int32_t reg; reg = jit_get_reg(jit_class_gpr); movi(rn(reg), i0); if (jit_thumb_p()) - T2_STRHI(r0, rn(reg), 0); + T2_STRHI(r0, rn(reg), 0); else - STRHI(r0, rn(reg), 0); + STRHI(r0, rn(reg), 0); jit_unget_reg(reg); } @@ -3455,49 +3446,49 @@ static void _stxr_s(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { if (jit_thumb_p()) { - if ((r0|r1|r2) < 8) - T1_STRH(r2, r1, r0); - else - T2_STRH(r2, r1, r0); + if ((r0|r1|r2) < 8) + T1_STRH(r2, r1, r0); + else + T2_STRH(r2, r1, r0); } else - STRH(r2, r1, r0); + STRH(r2, r1, r0); } static void _stxi_s(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) { - int32_t reg; + int32_t reg; if (jit_thumb_p()) { - if ((r0|r1) < 8 && i0 >= 0 && !(i0 & 1) && (i0 >> 1) < 0x20) - T1_STRHI(r1, r0, i0 >> 1); - else if (jit_ldrt_strt_p() && i0 >= 0 && i0 <= 255) - T2_STRHI(r1, r0, i0); - else if (i0 < 0 && i0 >= -255) - T2_STRHIN(r1, r0, -i0); - else if (i0 >= 0 && i0 <= 4095) - T2_STRHWI(r1, r0, i0); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - if ((r0|r1|rn(reg)) < 8) - T1_STRH(r1, r0, rn(reg)); - else - T2_STRH(r1, r0, rn(reg)); - jit_unget_reg(reg); - } + if ((r0|r1) < 8 && i0 >= 0 && !(i0 & 1) && (i0 >> 1) < 0x20) + T1_STRHI(r1, r0, i0 >> 1); + else if (jit_ldrt_strt_p() && i0 >= 0 && i0 <= 255) + T2_STRHI(r1, r0, i0); + else if (i0 < 0 && i0 >= -255) + T2_STRHIN(r1, r0, -i0); + else if (i0 >= 0 && i0 <= 4095) + T2_STRHWI(r1, r0, i0); + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + if ((r0|r1|rn(reg)) < 8) + T1_STRH(r1, r0, rn(reg)); + else + T2_STRH(r1, r0, rn(reg)); + jit_unget_reg(reg); + } } else { - if (i0 >= 0 && i0 <= 255) - STRHI(r1, r0, i0); - else if (i0 < 0 && i0 >= -255) - STRHIN(r1, r0, -i0); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - STRH(r1, r0, rn(reg)); - jit_unget_reg(reg); - } + if (i0 >= 0 && i0 <= 255) + STRHI(r1, r0, i0); + else if (i0 < 0 && i0 >= -255) + STRHIN(r1, r0, -i0); + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + STRH(r1, r0, rn(reg)); + jit_unget_reg(reg); + } } } @@ -3505,21 +3496,21 @@ static void _str_i(jit_state_t *_jit, int32_t r0, int32_t r1) { if (jit_thumb_p()) - T2_STRI(r1, r0, 0); + T2_STRI(r1, r0, 0); else - STRI(r1, r0, 0); + STRI(r1, r0, 0); } static void _sti_i(jit_state_t *_jit, jit_word_t i0, int32_t r0) { - int32_t reg; + int32_t reg; reg = jit_get_reg(jit_class_gpr); movi(rn(reg), i0); if (jit_thumb_p()) - T2_STRI(r0, rn(reg), 0); + T2_STRI(r0, rn(reg), 0); else - STRI(r0, rn(reg), 0); + STRI(r0, rn(reg), 0); jit_unget_reg(reg); } @@ -3527,52 +3518,52 @@ static void _stxr_i(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { if (jit_thumb_p()) { - if ((r0|r1|r2) < 8) - T1_STR(r2, r1, r0); - else - T2_STR(r2, r1, r0); + if ((r0|r1|r2) < 8) + T1_STR(r2, r1, r0); + else + T2_STR(r2, r1, r0); } else - STR(r2, r1, r0); + STR(r2, r1, r0); } static void _stxi_i(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) { - int32_t reg; + int32_t reg; if (jit_thumb_p()) { - if ((r0|r1) < 8 && i0 >= 0 && !(i0 & 3) && (i0 >> 2) < 0x20) - T1_STRI(r1, r0, i0 >> 2); - else if (r0 == _R13_REGNO && r1 < 8 && - i0 >= 0 && !(i0 & 3) && (i0 >> 2) <= 255) - T1_STRISP(r1, i0 >> 2); - else if (jit_ldrt_strt_p() && i0 >= 0 && i0 <= 255) - T2_STRI(r1, r0, i0); - else if (i0 < 0 && i0 >= -255) - T2_STRIN(r1, r0, -i0); - else if (i0 >= 0 && i0 <= 4095) - T2_STRWI(r1, r0, i0); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - if ((r0|r1|rn(reg)) < 8) - T1_STR(r1, r0, rn(reg)); - else - T2_STR(r1, r0, rn(reg)); - jit_unget_reg(reg); - } + if ((r0|r1) < 8 && i0 >= 0 && !(i0 & 3) && (i0 >> 2) < 0x20) + T1_STRI(r1, r0, i0 >> 2); + else if (r0 == _R13_REGNO && r1 < 8 && + i0 >= 0 && !(i0 & 3) && (i0 >> 2) <= 255) + T1_STRISP(r1, i0 >> 2); + else if (jit_ldrt_strt_p() && i0 >= 0 && i0 <= 255) + T2_STRI(r1, r0, i0); + else if (i0 < 0 && i0 >= -255) + T2_STRIN(r1, r0, -i0); + else if (i0 >= 0 && i0 <= 4095) + T2_STRWI(r1, r0, i0); + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + if ((r0|r1|rn(reg)) < 8) + T1_STR(r1, r0, rn(reg)); + else + T2_STR(r1, r0, rn(reg)); + jit_unget_reg(reg); + } } else { - if (i0 >= 0 && i0 <= 4095) - STRI(r1, r0, i0); - else if (i0 < 0 && i0 >= -4095) - STRIN(r1, r0, -i0); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - STR(r1, r0, rn(reg)); - jit_unget_reg(reg); - } + if (i0 >= 0 && i0 <= 4095) + STRI(r1, r0, i0); + else if (i0 < 0 && i0 >= -4095) + STRIN(r1, r0, -i0); + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + STR(r1, r0, rn(reg)); + jit_unget_reg(reg); + } } } @@ -3580,28 +3571,28 @@ _stxi_i(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) static void _bswapr_us(jit_state_t *_jit, int32_t r0, int32_t r1) { - int32_t t0; + int32_t t0; if (jit_thumb_p()) { - if ((r0|r1) < 8) - T1_REV(r0, r1); - else - T2_REV(r0, r1); - rshi_u(r0, r0, 16); + if ((r0|r1) < 8) + T1_REV(r0, r1); + else + T2_REV(r0, r1); + rshi_u(r0, r0, 16); } else { - if (jit_armv6_p()) { - REV(r0, r1); - rshi_u(r0, r0, 16); - } - else { - t0 = jit_get_reg(jit_class_gpr); - rshi(rn(t0), r1, 8); - andi(r0, r1, 0xff); - andi(rn(t0), rn(t0), 0xff); - lshi(r0, r0, 8); - orr(r0, r0, rn(t0)); - jit_unget_reg(t0); - } + if (jit_armv6_p()) { + REV(r0, r1); + rshi_u(r0, r0, 16); + } + else { + t0 = jit_get_reg(jit_class_gpr); + rshi(rn(t0), r1, 8); + andi(r0, r1, 0xff); + andi(rn(t0), rn(t0), 0xff); + lshi(r0, r0, 8); + orr(r0, r0, rn(t0)); + jit_unget_reg(t0); + } } } @@ -3609,24 +3600,24 @@ _bswapr_us(jit_state_t *_jit, int32_t r0, int32_t r1) static void _bswapr_ui(jit_state_t *_jit, int32_t r0, int32_t r1) { - int32_t reg; + int32_t reg; if (jit_thumb_p()) { - if ((r0|r1) < 8) - T1_REV(r0, r1); - else - T2_REV(r0, r1); + if ((r0|r1) < 8) + T1_REV(r0, r1); + else + T2_REV(r0, r1); } else { - if (jit_armv6_p()) - REV(r0, r1); - else { - reg = jit_get_reg(jit_class_gpr); - EOR_SI(rn(reg), r1, r1, ARM_ROR, 16); - LSRI(rn(reg), rn(reg), 8); - BICI(rn(reg), rn(reg), encode_arm_immediate(0xff00)); - EOR_SI(r0, rn(reg), r1, ARM_ROR, 8); - jit_unget_reg(reg); - } + if (jit_armv6_p()) + REV(r0, r1); + else { + reg = jit_get_reg(jit_class_gpr); + EOR_SI(rn(reg), r1, r1, ARM_ROR, 16); + LSRI(rn(reg), rn(reg), 8); + BICI(rn(reg), rn(reg), encode_arm_immediate(0xff00)); + EOR_SI(r0, rn(reg), r1, ARM_ROR, 8); + jit_unget_reg(reg); + } } } #endif @@ -3635,18 +3626,18 @@ static void _extr_c(jit_state_t *_jit, int32_t r0, int32_t r1) { if (jit_thumb_p()) { - if ((r0|r1) < 8) - T1_SXTB(r0, r1); - else - T2_SXTB(r0, r1); + if ((r0|r1) < 8) + T1_SXTB(r0, r1); + else + T2_SXTB(r0, r1); } else { - if (jit_armv6_p()) - SXTB(r0, r1); - else { - LSLI(r0, r1, 24); - ASRI(r0, r0, 24); - } + if (jit_armv6_p()) + SXTB(r0, r1); + else { + LSLI(r0, r1, 24); + ASRI(r0, r0, 24); + } } } @@ -3654,16 +3645,16 @@ static void _extr_uc(jit_state_t *_jit, int32_t r0, int32_t r1) { if (jit_thumb_p()) { - if ((r0|r1) < 8) - T1_UXTB(r0, r1); - else - T2_UXTB(r0, r1); + if ((r0|r1) < 8) + T1_UXTB(r0, r1); + else + T2_UXTB(r0, r1); } else { - if (jit_armv6_p()) - UXTB(r0, r1); - else - ANDI(r0, r1, 0xff); + if (jit_armv6_p()) + UXTB(r0, r1); + else + ANDI(r0, r1, 0xff); } } @@ -3671,18 +3662,18 @@ static void _extr_s(jit_state_t *_jit, int32_t r0, int32_t r1) { if (jit_thumb_p()) { - if ((r0|r1) < 8) - T1_SXTH(r0, r1); - else - T2_SXTH(r0, r1); + if ((r0|r1) < 8) + T1_SXTH(r0, r1); + else + T2_SXTH(r0, r1); } else { - if (jit_armv6_p()) - SXTH(r0, r1); - else { - LSLI(r0, r1, 16); - ASRI(r0, r0, 16); - } + if (jit_armv6_p()) + SXTH(r0, r1); + else { + LSLI(r0, r1, 16); + ASRI(r0, r0, 16); + } } } @@ -3690,18 +3681,18 @@ static void _extr_us(jit_state_t *_jit, int32_t r0, int32_t r1) { if (jit_thumb_p()) { - if ((r0|r1) < 8) - T1_UXTH(r0, r1); - else - T2_UXTH(r0, r1); + if ((r0|r1) < 8) + T1_UXTH(r0, r1); + else + T2_UXTH(r0, r1); } else { - if (jit_armv6_p()) - UXTH(r0, r1); - else { - LSLI(r0, r1, 16); - LSRI(r0, r0, 16); - } + if (jit_armv6_p()) + UXTH(r0, r1); + else { + LSLI(r0, r1, 16); + LSRI(r0, r0, 16); + } } } @@ -3709,42 +3700,42 @@ static void _callr(jit_state_t *_jit, int32_t r0) { if (jit_thumb_p()) - T1_BLX(r0); + T1_BLX(r0); else - BLX(r0); + BLX(r0); } static void _calli(jit_state_t *_jit, jit_word_t i0) { - jit_word_t d; - int32_t reg; + jit_word_t d; + int32_t reg; d = ((i0 - _jit->pc.w) >> 2) - 2; if (!jit_exchange_p() && !jit_thumb_p() && _s24P(d)) - BLI(d & 0x00ffffff); + BLI(d & 0x00ffffff); else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - if (jit_thumb_p()) - T1_BLX(rn(reg)); - else - BLX(rn(reg)); - jit_unget_reg(reg); + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + if (jit_thumb_p()) + T1_BLX(rn(reg)); + else + BLX(rn(reg)); + jit_unget_reg(reg); } } static jit_word_t _calli_p(jit_state_t *_jit, jit_word_t i0) { - jit_word_t w; - int32_t reg; + jit_word_t w; + int32_t reg; reg = jit_get_reg(jit_class_gpr); w = _jit->pc.w; movi_p(rn(reg), i0); if (jit_thumb_p()) - T1_BLX(rn(reg)); + T1_BLX(rn(reg)); else - BLX(rn(reg)); + BLX(rn(reg)); jit_unget_reg(reg); return (w); } @@ -3752,61 +3743,61 @@ _calli_p(jit_state_t *_jit, jit_word_t i0) static void _prolog(jit_state_t *_jit, jit_node_t *node) { - int32_t reg; + int32_t reg; if (_jitc->function->define_frame || _jitc->function->assume_frame) { - int32_t frame = -_jitc->function->frame; - assert(_jitc->function->self.aoff >= frame); - if (_jitc->function->assume_frame) { - if (jit_thumb_p() && !_jitc->thumb) - _jitc->thumb = _jit->pc.w; - return; - } - _jitc->function->self.aoff = frame; + int32_t frame = -_jitc->function->frame; + assert(_jitc->function->self.aoff >= frame); + if (_jitc->function->assume_frame) { + if (jit_thumb_p() && !_jitc->thumb) + _jitc->thumb = _jit->pc.w; + return; + } + _jitc->function->self.aoff = frame; } if (_jitc->function->allocar) - _jitc->function->self.aoff &= -8; + _jitc->function->self.aoff &= -8; _jitc->function->stack = ((_jitc->function->self.alen - - /* align stack at 8 bytes */ - _jitc->function->self.aoff) + 7) & -8; + /* align stack at 8 bytes */ + _jitc->function->self.aoff) + 7) & -8; if (jit_thumb_p()) { - /* switch to thumb mode (better approach would be to - * ORR 1 address being called, but no clear distinction - * of what is a pointer to a jit function, or if patching - * a pointer to a jit function) */ - ADDI(_R12_REGNO, _R15_REGNO, 1); - BX(_R12_REGNO); - if (!_jitc->thumb) - _jitc->thumb = _jit->pc.w; - if (jit_cpu.abi) { - T2_PUSH(0xf); - T2_PUSH(0x3f0|(1<<_FP_REGNO)|(1<<_LR_REGNO)); - VPUSH_F64(_D8_REGNO, 8); - } - else { - T2_PUSH(0xf); - T2_PUSH(0x3f0|(1<<_FP_REGNO)|(1<<_LR_REGNO)); - } + /* switch to thumb mode (better approach would be to + * ORR 1 address being called, but no clear distinction + * of what is a pointer to a jit function, or if patching + * a pointer to a jit function) */ + ADDI(_R12_REGNO, _R15_REGNO, 1); + BX(_R12_REGNO); + if (!_jitc->thumb) + _jitc->thumb = _jit->pc.w; + if (jit_cpu.abi) { + T2_PUSH(0xf); + T2_PUSH(0x3f0|(1<<_FP_REGNO)|(1<<_LR_REGNO)); + VPUSH_F64(_D8_REGNO, 8); + } + else { + T2_PUSH(0xf); + T2_PUSH(0x3f0|(1<<_FP_REGNO)|(1<<_LR_REGNO)); + } } else { - if (jit_cpu.abi) { - PUSH(0xf); - PUSH(0x3f0|(1<<_FP_REGNO)|(1<<_LR_REGNO)); - VPUSH_F64(_D8_REGNO, 8); - } - else { - PUSH(0xf); - PUSH(0x3f0|(1<<_FP_REGNO)|(1<<_LR_REGNO)); - } + if (jit_cpu.abi) { + PUSH(0xf); + PUSH(0x3f0|(1<<_FP_REGNO)|(1<<_LR_REGNO)); + VPUSH_F64(_D8_REGNO, 8); + } + else { + PUSH(0xf); + PUSH(0x3f0|(1<<_FP_REGNO)|(1<<_LR_REGNO)); + } } movr(_FP_REGNO, _SP_REGNO); if (_jitc->function->stack) - subi(_SP_REGNO, _SP_REGNO, _jitc->function->stack); + subi(_SP_REGNO, _SP_REGNO, _jitc->function->stack); if (_jitc->function->allocar) { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), _jitc->function->self.aoff); - stxi_i(_jitc->function->aoffoff, _FP_REGNO, rn(reg)); - jit_unget_reg(reg); + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), _jitc->function->self.aoff); + stxi_i(_jitc->function->aoffoff, _FP_REGNO, rn(reg)); + jit_unget_reg(reg); } } @@ -3814,22 +3805,22 @@ static void _epilog(jit_state_t *_jit, jit_node_t *node) { if (_jitc->function->assume_frame) - return; + return; movr(_SP_REGNO, _FP_REGNO); if (jit_cpu.abi) - VPOP_F64(_D8_REGNO, 8); + VPOP_F64(_D8_REGNO, 8); if (jit_thumb_p()) - T2_POP(0x3f0|(1<<_FP_REGNO)|(1<<_LR_REGNO)); + T2_POP(0x3f0|(1<<_FP_REGNO)|(1<<_LR_REGNO)); else - POP(0x3f0|(1<<_FP_REGNO)|(1<<_LR_REGNO)); + POP(0x3f0|(1<<_FP_REGNO)|(1<<_LR_REGNO)); addi(_SP_REGNO, _SP_REGNO, 16); if (jit_thumb_p()) - T1_BX(_LR_REGNO); + T1_BX(_LR_REGNO); else - BX(_LR_REGNO); + BX(_LR_REGNO); if (jit_thumb_p() && (_jit->pc.w & 2)) - T1_NOP(); + T1_NOP(); } static void @@ -3842,7 +3833,7 @@ _vastart(jit_state_t *_jit, int32_t r0) * always saved, and _jitc->function->vagp is to account * for declared arguments. */ addi(r0, _FP_REGNO, _jitc->function->self.size - - 16 + _jitc->function->vagp); + 16 + _jitc->function->vagp); } static void @@ -3859,97 +3850,97 @@ _vaarg(jit_state_t *_jit, int32_t r0, int32_t r1) static void _patch_at(jit_state_t *_jit, - int32_t kind, jit_word_t instr, jit_word_t label) + int32_t kind, jit_word_t instr, jit_word_t label) { - jit_word_t d; - jit_thumb_t thumb; + jit_word_t d; + jit_thumb_t thumb; union { - int16_t *s; - int32_t *i; - jit_word_t w; + int16_t *s; + int32_t *i; + jit_word_t w; } u; u.w = instr; if (kind == arm_patch_jump) { - if (jit_thumb_p() && (jit_uword_t)instr >= _jitc->thumb) { - code2thumb(thumb.s[0], thumb.s[1], u.s[0], u.s[1]); - if ((thumb.i & THUMB2_B) == THUMB2_B) { - d = ((label - instr) >> 1) - 2; - assert(_s24P(d)); - thumb.i = THUMB2_B | encode_thumb_jump(d); - thumb2code(thumb.s[0], thumb.s[1], u.s[0], u.s[1]); - } - else if ((thumb.i & THUMB2_B) == THUMB2_CC_B) { - d = ((label - instr) >> 1) - 2; - assert(_s20P(d)); - thumb.i = THUMB2_CC_B | (thumb.i & 0x3c00000) | - encode_thumb_cc_jump(d); - thumb2code(thumb.s[0], thumb.s[1], u.s[0], u.s[1]); - } - else { - /* for the sake of simplicity in case choose to - * movw+movt+[bx|blx], e.g. if changing to instead - * of asserting target is reachable, load constant - * and do indirect jump if not reachable */ - if ((thumb.i & 0xfbf00000) == THUMB2_MOVWI) - goto indirect_jump; - assert(!"handled branch opcode"); - } - } - else { - thumb.i = u.i[0]; - /* 0x0e000000 because 0x01000000 is (branch&) link modifier */ - assert((thumb.i & 0x0e000000) == ARM_B); - d = ((label - instr) >> 2) - 2; - assert(_s24P(d)); - u.i[0] = (thumb.i & 0xff000000) | (d & 0x00ffffff); - } + if (jit_thumb_p() && (jit_uword_t)instr >= _jitc->thumb) { + code2thumb(thumb.s[0], thumb.s[1], u.s[0], u.s[1]); + if ((thumb.i & THUMB2_B) == THUMB2_B) { + d = ((label - instr) >> 1) - 2; + assert(_s24P(d)); + thumb.i = THUMB2_B | encode_thumb_jump(d); + thumb2code(thumb.s[0], thumb.s[1], u.s[0], u.s[1]); + } + else if ((thumb.i & THUMB2_B) == THUMB2_CC_B) { + d = ((label - instr) >> 1) - 2; + assert(_s20P(d)); + thumb.i = THUMB2_CC_B | (thumb.i & 0x3c00000) | + encode_thumb_cc_jump(d); + thumb2code(thumb.s[0], thumb.s[1], u.s[0], u.s[1]); + } + else { + /* for the sake of simplicity in case choose to + * movw+movt+[bx|blx], e.g. if changing to instead + * of asserting target is reachable, load constant + * and do indirect jump if not reachable */ + if ((thumb.i & 0xfbf00000) == THUMB2_MOVWI) + goto indirect_jump; + assert(!"handled branch opcode"); + } + } + else { + thumb.i = u.i[0]; + /* 0x0e000000 because 0x01000000 is (branch&) link modifier */ + assert((thumb.i & 0x0e000000) == ARM_B); + d = ((label - instr) >> 2) - 2; + assert(_s24P(d)); + u.i[0] = (thumb.i & 0xff000000) | (d & 0x00ffffff); + } } else if (kind == arm_patch_load) { - /* offset may be negative for a forward patch because it - * is relative to pc + 8, for example: - * ldr r0, [pc, #-4] - * bx r0 ;; [pc, #-8] - * .data ... ;; [pc, #-4] - * ... ;; [pc] - */ - assert(!jit_thumb_p()); - thumb.i = u.i[0]; - assert((thumb.i & 0x0f700000) == ARM_LDRI); - d = label - (instr + 8); - if (d < 0) { - thumb.i &= ~ARM_P; - d = -d; - } - else - thumb.i |= ARM_P; - assert(!(d & 0xfffff000)); - u.i[0] = (thumb.i & 0xfffff000) | d; + /* offset may be negative for a forward patch because it + * is relative to pc + 8, for example: + * ldr r0, [pc, #-4] + * bx r0 ;; [pc, #-8] + * .data ... ;; [pc, #-4] + * ... ;; [pc] + */ + assert(!jit_thumb_p()); + thumb.i = u.i[0]; + assert((thumb.i & 0x0f700000) == ARM_LDRI); + d = label - (instr + 8); + if (d < 0) { + thumb.i &= ~ARM_P; + d = -d; + } + else + thumb.i |= ARM_P; + assert(!(d & 0xfffff000)); + u.i[0] = (thumb.i & 0xfffff000) | d; } else if (kind == arm_patch_word) { - if (jit_thumb_p()) { - code2thumb(thumb.s[0], thumb.s[1], u.s[0], u.s[1]); - assert((thumb.i & 0xfbf00000) == THUMB2_MOVWI); - indirect_jump: - thumb.i = ((thumb.i & 0xfbf00f00) | - ( (label & 0x0000f000) << 4) | - ( (label & 0x00000800) << 15) | - ( (label & 0x00000700) << 4) | - ( label & 0x000000ff)); - thumb2code(thumb.s[0], thumb.s[1], u.s[0], u.s[1]); - label >>= 16; - code2thumb(thumb.s[0], thumb.s[1], u.s[2], u.s[3]); - assert((thumb.i & 0xfbf00000) == THUMB2_MOVTI); - thumb.i = ((thumb.i & 0xfbf00f00) | - ( (label & 0x0000f000) << 4) | - ( (label & 0x00000800) << 15) | - ( (label & 0x00000700) << 4) | - ( label & 0x000000ff)); - thumb2code(thumb.s[0], thumb.s[1], u.s[2], u.s[3]); - } - else - u.i[0] = label; + if (jit_thumb_p()) { + code2thumb(thumb.s[0], thumb.s[1], u.s[0], u.s[1]); + assert((thumb.i & 0xfbf00000) == THUMB2_MOVWI); + indirect_jump: + thumb.i = ((thumb.i & 0xfbf00f00) | + ( (label & 0x0000f000) << 4) | + ( (label & 0x00000800) << 15) | + ( (label & 0x00000700) << 4) | + ( label & 0x000000ff)); + thumb2code(thumb.s[0], thumb.s[1], u.s[0], u.s[1]); + label >>= 16; + code2thumb(thumb.s[0], thumb.s[1], u.s[2], u.s[3]); + assert((thumb.i & 0xfbf00000) == THUMB2_MOVTI); + thumb.i = ((thumb.i & 0xfbf00f00) | + ( (label & 0x0000f000) << 4) | + ( (label & 0x00000800) << 15) | + ( (label & 0x00000700) << 4) | + ( label & 0x000000ff)); + thumb2code(thumb.s[0], thumb.s[1], u.s[2], u.s[3]); + } + else + u.i[0] = label; } else - assert(!"handled patch"); + assert(!"handled patch"); } #endif diff --git a/lightening/arm.c b/lightening/arm.c index 12a728664..be0e629e8 100644 --- a/lightening/arm.c +++ b/lightening/arm.c @@ -14,2269 +14,119 @@ * License for more details. * * Authors: - * Paulo Cesar Pereira de Andrade + * Paulo Cesar Pereira de Andrade */ -#if defined(__linux__) -# include -#endif - -# define JIT_RA0 _R0 -# define JIT_FA0 _D0 -# define JIT_SP _R13 -# define JIT_RET _R0 -# if defined(__ARM_PCS_VFP) -# define JIT_FRET _D0 -# else -# define JIT_FRET _R0 -# endif - -#define jit_arg_reg_p(i) ((i) >= 0 && (i) < 4) -#define jit_arg_f_reg_p(i) ((i) >= 0 && (i) < 16) -#define jit_arg_d_reg_p(i) ((i) >= 0 && (i) < 15) - -#define arm_patch_node 0x80000000 -#define arm_patch_word 0x40000000 -#define arm_patch_jump 0x20000000 -#define arm_patch_load 0x00000000 - -#define jit_fpr_p(rn) ((rn) > 15) - -#define arg_base() \ - (stack_framesize - 16 + (jit_cpu.abi ? 64 : 0)) -#define arg_offset(n) \ - ((n) < 4 ? arg_base() + ((n) << 2) : (n)) - -/* Assume functions called never match jit instruction set, that is - * libc, gmp, mpfr, etc functions are in thumb mode and jit is in - * arm mode, what may cause a crash upon return of that function - * if generating jit for a relative jump. - */ -#define jit_exchange_p() 1 - -/* FIXME is it really required to not touch _R10? */ - /* * Types */ typedef union _jit_thumb_t { - int32_t i; - int16_t s[2]; + int32_t i; + int16_t s[2]; } jit_thumb_t; -typedef jit_pointer_t jit_va_list; - -/* - * Prototypes - */ -#define jit_make_arg(node) _jit_make_arg(_jit,node) -static jit_node_t *_jit_make_arg(jit_state_t*,jit_node_t*); -#define jit_make_arg_f(node) _jit_make_arg_f(_jit,node) -static jit_node_t *_jit_make_arg_f(jit_state_t*,jit_node_t*); -#define jit_make_arg_d(node) _jit_make_arg_d(_jit,node) -static jit_node_t *_jit_make_arg_d(jit_state_t*,jit_node_t*); -#define jit_get_reg_pair() _jit_get_reg_pair(_jit) -static int32_t _jit_get_reg_pair(jit_state_t*); -#define jit_unget_reg_pair(rn) _jit_unget_reg_pair(_jit,rn) -static void _jit_unget_reg_pair(jit_state_t*,int32_t); -# define must_align_p(node) _must_align_p(_jit, node) -static jit_bool_t _must_align_p(jit_state_t*,jit_node_t*); -#define load_const(uniq,r0,i0) _load_const(_jit,uniq,r0,i0) -static void _load_const(jit_state_t*,jit_bool_t,int32_t,jit_word_t); -#define flush_consts() _flush_consts(_jit) -static void _flush_consts(jit_state_t*); -#define invalidate_consts() _invalidate_consts(_jit) -static void _invalidate_consts(jit_state_t*); -#define patch(instr, node) _patch(_jit, instr, node) -static void _patch(jit_state_t*,jit_word_t,jit_node_t*); - -#if defined(__GNUC__) /* libgcc */ extern void __clear_cache(void *, void *); -#endif -#define PROTO 1 -# include "rewind.c" -# include "arm-cpu.c" -# include "arm-vfp.c" -#undef PROTO +#include "arm-cpu.c" +#include "arm-vfp.c" -/* - * Initialization - */ -jit_cpu_t jit_cpu; -static const jit_register_t _rvs[] = { - { rc(gpr) | 0x0c, "ip" }, - { rc(sav) | rc(gpr) | 0x04, "r4" }, - { rc(sav) | rc(gpr) | 0x05, "r5" }, - { rc(sav) | rc(gpr) | 0x06, "r6" }, - { rc(sav) | rc(gpr) | 0x07, "r7" }, - { rc(sav) | rc(gpr) | 0x08, "r8" }, - { rc(sav) | rc(gpr) | 0x09, "r9" }, - { rc(sav) | 0x0a, "sl" }, - { rc(sav) | 0x0b, "fp" }, - { rc(sav) | 0x0d, "sp" }, - { rc(sav) | 0x0e, "lr" }, - { 0x0f, "pc" }, - { rc(arg) | rc(gpr) | 0x03, "r3" }, - { rc(arg) | rc(gpr) | 0x02, "r2" }, - { rc(arg) | rc(gpr) | 0x01, "r1" }, - { rc(arg) | rc(gpr) | 0x00, "r0" }, - { rc(fpr) | 0x20, "d8" }, - { 0x21, "s17" }, - { rc(fpr) | 0x22, "d9" }, - { 0x23, "s19" }, - { rc(fpr) | 0x24, "d10" }, - { 0x25, "s21" }, - { rc(fpr) | 0x26, "d11" }, - { 0x27, "s23" }, - { rc(fpr) | 0x28, "d12" }, - { 0x29, "s25" }, - { rc(fpr) | 0x2a, "d13" }, - { 0x2b, "s27" }, - { rc(fpr) | 0x2c, "d14" }, - { 0x2d, "s29" }, - { rc(fpr) | 0x2e, "d15" }, - { 0x2f, "s31" }, - { rc(arg) | 0x1f, "s15" }, - { rc(arg)|rc(sft)|rc(fpr)|0x1e, "d7" }, - { rc(arg) | 0x1d, "s13" }, - { rc(arg)|rc(sft)|rc(fpr)|0x1c, "d6" }, - { rc(arg) | 0x1b, "s11" }, - { rc(arg)|rc(sft)|rc(fpr)|0x1a, "d5" }, - { rc(arg) | 0x19, "s9" }, - { rc(arg)|rc(sft)|rc(fpr)|0x18, "d4" }, - { rc(arg) | 0x17, "s7" }, - { rc(arg)|rc(sft)|rc(fpr)|0x16, "d3" }, - { rc(arg) | 0x15, "s5" }, - { rc(arg)|rc(sft)|rc(fpr)|0x14, "d2" }, - { rc(arg) | 0x13, "s3" }, - { rc(arg)|rc(sft)|rc(fpr)|0x12, "d1" }, - { rc(arg) | 0x11, "s1" }, - { rc(arg)|rc(sft)|rc(fpr)|0x10, "d0" }, - { _NOREG, "" }, +static const jit_gpr_t abi_gpr_args[] = { + _R0, _R1, _R2, _R3 +}; +static const int abi_gpr_arg_count = sizeof(abi_gpr_args) / sizeof(abi_gpr_args[0]); + +struct abi_arg_iterator +{ + const jit_operand_t *args; + size_t argc; + + size_t arg_idx; + size_t gpr_idx; + uint32_t vfp_used_registers; + size_t stack_size; + size_t stack_padding; }; -/* - * Implementation - */ -void +static size_t page_size; + +jit_bool_t jit_get_cpu(void) { -#if defined(__linux__) - FILE *fp; - char *ptr; - char buf[128]; - - if ((fp = fopen("/proc/cpuinfo", "r")) != NULL) { - while (fgets(buf, sizeof(buf), fp)) { - if (strncmp(buf, "CPU architecture:", 17) == 0) { - jit_cpu.version = strtol(buf + 17, &ptr, 10); - while (*ptr) { - if (*ptr == 'T' || *ptr == 't') { - ++ptr; - jit_cpu.thumb = 1; - } - else if (*ptr == 'E' || *ptr == 'e') { - jit_cpu.extend = 1; - ++ptr; - } - else - ++ptr; - } - } - else if (strncmp(buf, "Features\t:", 10) == 0) { - if ((ptr = strstr(buf + 10, "vfpv"))) - jit_cpu.vfp = strtol(ptr + 4, NULL, 0); - if ((ptr = strstr(buf + 10, "neon"))) - jit_cpu.neon = 1; - if ((ptr = strstr(buf + 10, "thumb"))) - jit_cpu.thumb = 1; - } - } - fclose(fp); - } -#endif -#if defined(__ARM_PCS_VFP) - if (!jit_cpu.vfp) - jit_cpu.vfp = 3; - if (!jit_cpu.version) - jit_cpu.version = 7; - jit_cpu.abi = 1; -#endif -#if defined(__thumb2__) - jit_cpu.thumb = 1; -#endif - /* armv6t2 todo (software float and thumb2) */ - if (!jit_cpu.vfp && jit_cpu.thumb) - jit_cpu.thumb = 0; -} - -void -_jit_init(jit_state_t *_jit) -{ - int32_t regno; - static jit_bool_t first = 1; - - _jitc->reglen = jit_size(_rvs) - 1; - if (first) { - /* jit_get_cpu() should have been already called, and only once */ - if (!jit_cpu.vfp) { - /* cause register to never be allocated, because simple - * software float only allocates stack space for 8 slots */ - for (regno = _D8; regno < _D7; regno++) - _rvs[regno].spec = 0; - } - if (!jit_cpu.abi) { - for (regno = _S15; regno <= _D0; regno++) - _rvs[regno].spec &= ~rc(arg); - } - first = 0; - } -} - -void -_jit_prolog(jit_state_t *_jit) -{ - int32_t offset; - - if (_jitc->function) - jit_epilog(); - assert(jit_regset_cmp_ui(&_jitc->regarg, 0) == 0); - jit_regset_set_ui(&_jitc->regsav, 0); - offset = _jitc->functions.offset; - if (offset >= _jitc->functions.length) { - jit_realloc((jit_pointer_t *)&_jitc->functions.ptr, - _jitc->functions.length * sizeof(jit_function_t), - (_jitc->functions.length + 16) * sizeof(jit_function_t)); - _jitc->functions.length += 16; - } - _jitc->function = _jitc->functions.ptr + _jitc->functions.offset++; - _jitc->function->self.size = stack_framesize; - if (jit_cpu.abi) - _jitc->function->self.size += 64; - _jitc->function->self.argi = _jitc->function->self.argf = - _jitc->function->self.alen = 0; - if (jit_swf_p()) - /* 8 soft float registers */ - _jitc->function->self.aoff = -64; - else - _jitc->function->self.aoff = 0; - _jitc->function->self.call = jit_call_default; - jit_alloc((jit_pointer_t *)&_jitc->function->regoff, - _jitc->reglen * sizeof(int32_t)); - - /* _no_link here does not mean the jit_link() call can be removed - * by rewriting as: - * _jitc->function->prolog = jit_new_node(jit_code_prolog); - */ - _jitc->function->prolog = jit_new_node_no_link(jit_code_prolog); - jit_link(_jitc->function->prolog); - _jitc->function->prolog->w.w = offset; - _jitc->function->epilog = jit_new_node_no_link(jit_code_epilog); - /* u: label value - * v: offset in blocks vector - * w: offset in functions vector - */ - _jitc->function->epilog->w.w = offset; - - jit_regset_new(&_jitc->function->regset); -} - -int32_t -_jit_allocai(jit_state_t *_jit, int32_t length) -{ - assert(_jitc->function); - switch (length) { - case 0: case 1: break; - case 2: _jitc->function->self.aoff &= -2; break; - case 3: case 4: _jitc->function->self.aoff &= -4; break; - default: _jitc->function->self.aoff &= -8; break; - } - _jitc->function->self.aoff -= length; - if (!_jitc->realize) { - jit_inc_synth_ww(allocai, _jitc->function->self.aoff, length); - jit_dec_synth(); - } - return (_jitc->function->self.aoff); -} - -void -_jit_allocar(jit_state_t *_jit, int32_t u, int32_t v) -{ - int32_t reg; - assert(_jitc->function); - jit_inc_synth_ww(allocar, u, v); - if (!_jitc->function->allocar) { - _jitc->function->aoffoff = jit_allocai(sizeof(int32_t)); - _jitc->function->allocar = 1; - } - reg = jit_get_reg(jit_class_gpr); - jit_negr(reg, v); - jit_andi(reg, reg, -8); - jit_ldxi_i(u, JIT_FP, _jitc->function->aoffoff); - jit_addr(u, u, reg); - jit_addr(JIT_SP, JIT_SP, reg); - jit_stxi_i(_jitc->function->aoffoff, JIT_FP, u); - jit_unget_reg(reg); - jit_dec_synth(); -} - -void -_jit_ret(jit_state_t *_jit) -{ - jit_node_t *instr; - assert(_jitc->function); - jit_inc_synth(ret); - /* jump to epilog */ - instr = jit_jmpi(); - jit_patch_at(instr, _jitc->function->epilog); - jit_dec_synth(); -} - -void -_jit_retr(jit_state_t *_jit, int32_t u) -{ - jit_inc_synth_w(retr, u); - if (JIT_RET != u) - jit_movr(JIT_RET, u); - jit_live(JIT_RET); - jit_ret(); - jit_dec_synth(); -} - -void -_jit_reti(jit_state_t *_jit, jit_word_t u) -{ - jit_inc_synth_w(reti, u); - jit_movi(JIT_RET, u); - jit_ret(); - jit_dec_synth(); -} - -void -_jit_retr_f(jit_state_t *_jit, int32_t u) -{ - jit_inc_synth_w(retr_f, u); - if (jit_cpu.abi) { - if (u != JIT_FRET) - jit_movr_f(JIT_FRET, u); - else - jit_live(JIT_FRET); - } - else { - if (u != JIT_RET) - jit_movr_f_w(JIT_RET, u); - else - jit_live(JIT_RET); - } - jit_ret(); - jit_dec_synth(); -} - -void -_jit_reti_f(jit_state_t *_jit, jit_float32_t u) -{ - jit_inc_synth_f(reti_f, u); - if (jit_cpu.abi) - jit_movi_f(JIT_FRET, u); - else - jit_movi_f_w(JIT_RET, u); - jit_ret(); - jit_dec_synth(); -} - -void -_jit_retr_d(jit_state_t *_jit, int32_t u) -{ - jit_inc_synth_w(retr_d, u); - if (jit_cpu.abi) { - if (u != JIT_FRET) - jit_movr_d(JIT_FRET, u); - else - jit_live(JIT_FRET); - } - else { - if (u != JIT_RET) - jit_movr_d_ww(JIT_RET, _R1, u); - else - jit_live(JIT_RET); - } - jit_ret(); - jit_dec_synth(); -} - -void -_jit_reti_d(jit_state_t *_jit, jit_float64_t u) -{ - jit_inc_synth_d(reti_d, u); - if (jit_cpu.abi) - jit_movi_d(JIT_FRET, u); - else - jit_movi_d_ww(JIT_RET, _R1, u); - jit_ret(); - jit_dec_synth(); -} - -void -_jit_epilog(jit_state_t *_jit) -{ - assert(_jitc->function); - assert(_jitc->function->epilog->next == NULL); - jit_link(_jitc->function->epilog); - _jitc->function = NULL; + page_size = sysconf(_SC_PAGE_SIZE); + // FIXME check version, thumb, hardware fp support + return 1; } jit_bool_t -_jit_arg_register_p(jit_state_t *_jit, jit_node_t *u) +jit_init(jit_state_t *_jit) { - if (u->code != jit_code_arg) { - if (u->code == jit_code_arg_f) { - if (jit_cpu.abi) - return (jit_arg_f_reg_p(u->u.w)); - } - else { - assert(u->code == jit_code_arg_d); - if (jit_cpu.abi) - return (jit_arg_d_reg_p(u->u.w)); - } - } - return (jit_arg_reg_p(u->u.w)); + return 1; } -static jit_node_t * -_jit_make_arg(jit_state_t *_jit, jit_node_t *node) +static size_t +jit_initial_frame_size (void) { - int32_t offset; - if (jit_arg_reg_p(_jitc->function->self.argi)) - offset = _jitc->function->self.argi++; - else { - offset = _jitc->function->self.size; - _jitc->function->self.size += sizeof(jit_word_t); - } - if (node == (jit_node_t *)0) - node = jit_new_node(jit_code_arg); - else - link_node(node); - node->u.w = offset; - node->v.w = ++_jitc->function->self.argn; - jit_link_prolog(); - return (node); + return 0; } -jit_node_t * -_jit_make_arg_f(jit_state_t *_jit, jit_node_t *node) +static void +reset_abi_arg_iterator(struct abi_arg_iterator *iter, size_t argc, + const jit_operand_t *args) { - int32_t offset; - if (jit_cpu.abi && !(_jitc->function->self.call & jit_call_varargs)) { - if (jit_arg_f_reg_p(_jitc->function->self.argf)) { - offset = _jitc->function->self.argf++; - goto done; - } - } - else { - if (jit_arg_reg_p(_jitc->function->self.argi)) { - offset = _jitc->function->self.argi++; - goto done; - } - } - offset = _jitc->function->self.size; - _jitc->function->self.size += sizeof(jit_float32_t); -done: - if (node == (jit_node_t *)0) - node = jit_new_node(jit_code_arg_f); - else - link_node(node); - node->u.w = offset; - node->v.w = ++_jitc->function->self.argn; - jit_link_prolog(); - return (node); + memset(iter, 0, sizeof *iter); + iter->argc = argc; + iter->args = args; } -jit_node_t * -_jit_make_arg_d(jit_state_t *_jit, jit_node_t *node) +static void +next_abi_arg(struct abi_arg_iterator *iter, jit_operand_t *arg) { - int32_t offset; - if (jit_cpu.abi && !(_jitc->function->self.call & jit_call_varargs)) { - if (jit_arg_d_reg_p(_jitc->function->self.argf)) { - if (_jitc->function->self.argf & 1) - ++_jitc->function->self.argf; - offset = _jitc->function->self.argf; - _jitc->function->self.argf += 2; - goto done; - } + ASSERT(iter->arg_idx < iter->argc); + enum jit_operand_abi abi = iter->args[iter->arg_idx].abi; + iter->arg_idx++; + if (is_gpr_arg(abi) && iter->gpr_idx < abi_gpr_arg_count) { + *arg = jit_operand_gpr (abi, abi_gpr_args[iter->gpr_idx++]); + return; + } + if (is_fpr_arg(abi)) { + // The ARM VFP ABI passes floating-point arguments in d0-d7 + // (s0-s15), and allows for "back-filling". Say you have a + // function: + // + // void f(float a, double b, float c); + // + // A gets allocated to s0, then b to d1 (which aliases s2+s3), then + // c to s1. + uint32_t width = abi == JIT_OPERAND_ABI_FLOAT ? 1 : 2; + uint32_t mask = (1 << width) - 1; + for (size_t i = 0; i < 16; i += width) { + if ((iter->vfp_used_registers & (mask << i)) == 0) { + iter->vfp_used_registers |= (mask << i); + *arg = jit_operand_fpr (abi, JIT_FPR(i)); + return; + } } - else { - if (_jitc->function->self.argi & 1) - ++_jitc->function->self.argi; - if (jit_arg_reg_p(_jitc->function->self.argi)) { - offset = _jitc->function->self.argi; - _jitc->function->self.argi += 2; - goto done; - } - } - if (_jitc->function->self.size & 7) - _jitc->function->self.size += 4; - offset = _jitc->function->self.size; - _jitc->function->self.size += sizeof(jit_float64_t); -done: - if (node == (jit_node_t *)0) - node = jit_new_node(jit_code_arg_d); - else - link_node(node); - node->u.w = offset; - node->v.w = ++_jitc->function->self.argn; - jit_link_prolog(); - return (node); + } + *arg = jit_operand_mem (abi, JIT_SP, iter->stack_size); + iter->stack_size += 8; } -void -_jit_ellipsis(jit_state_t *_jit) -{ - if (_jitc->prepare) { - assert(!(_jitc->function->call.call & jit_call_varargs)); - _jitc->function->call.call |= jit_call_varargs; - if (jit_cpu.abi && _jitc->function->call.argf) - rewind_prepare(); - } - else { - assert(!(_jitc->function->self.call & jit_call_varargs)); - _jitc->function->self.call |= jit_call_varargs; - if (jit_cpu.abi && _jitc->function->self.argf) - rewind_prolog(); - /* First 4 stack addresses are always spilled r0-r3 */ - if (jit_arg_reg_p(_jitc->function->self.argi)) - _jitc->function->vagp = _jitc->function->self.argi * 4; - else - _jitc->function->vagp = 16; - } - jit_inc_synth(ellipsis); - if (_jitc->prepare) - jit_link_prepare(); - else - jit_link_prolog(); - jit_dec_synth(); -} - -void -_jit_va_push(jit_state_t *_jit, int32_t u) -{ - jit_inc_synth_w(va_push, u); - jit_pushargr(u); - jit_dec_synth(); -} - -jit_node_t * -_jit_arg(jit_state_t *_jit) -{ - assert(_jitc->function); - return (jit_make_arg((jit_node_t*)0)); -} - -jit_node_t * -_jit_arg_f(jit_state_t *_jit) -{ - assert(_jitc->function); - return (jit_make_arg_f((jit_node_t*)0)); -} - -jit_node_t * -_jit_arg_d(jit_state_t *_jit) -{ - assert(_jitc->function); - return (jit_make_arg_d((jit_node_t*)0)); -} - -void -_jit_getarg_c(jit_state_t *_jit, int32_t u, jit_node_t *v) -{ - assert(v->code == jit_code_arg); - jit_inc_synth_wp(getarg_c, u, v); - if (jit_swf_p()) - jit_ldxi_c(u, JIT_FP, arg_offset(v->u.w)); - else if (jit_arg_reg_p(v->u.w)) - jit_extr_c(u, JIT_RA0 - v->u.w); - else - jit_ldxi_c(u, JIT_FP, v->u.w); - jit_dec_synth(); -} - -void -_jit_getarg_uc(jit_state_t *_jit, int32_t u, jit_node_t *v) -{ - assert(v->code == jit_code_arg); - jit_inc_synth_wp(getarg_uc, u, v); - if (jit_swf_p()) - jit_ldxi_uc(u, JIT_FP, arg_offset(v->u.w)); - else if (jit_arg_reg_p(v->u.w)) - jit_extr_uc(u, JIT_RA0 - v->u.w); - else - jit_ldxi_uc(u, JIT_FP, v->u.w); - jit_dec_synth(); -} - -void -_jit_getarg_s(jit_state_t *_jit, int32_t u, jit_node_t *v) -{ - assert(v->code == jit_code_arg); - jit_inc_synth_wp(getarg_s, u, v); - if (jit_swf_p()) - jit_ldxi_s(u, JIT_FP, arg_offset(v->u.w)); - else if (jit_arg_reg_p(v->u.w)) - jit_extr_s(u, JIT_RA0 - v->u.w); - else - jit_ldxi_s(u, JIT_FP, v->u.w); - jit_dec_synth(); -} - -void -_jit_getarg_us(jit_state_t *_jit, int32_t u, jit_node_t *v) -{ - assert(v->code == jit_code_arg); - jit_inc_synth_wp(getarg_us, u, v); - if (jit_swf_p()) - jit_ldxi_us(u, JIT_FP, arg_offset(v->u.w)); - else if (jit_arg_reg_p(v->u.w)) - jit_extr_us(u, JIT_RA0 - v->u.w); - else - jit_ldxi_us(u, JIT_FP, v->u.w); - jit_dec_synth(); -} - -void -_jit_getarg_i(jit_state_t *_jit, int32_t u, jit_node_t *v) -{ - assert(v->code == jit_code_arg); - jit_inc_synth_wp(getarg_i, u, v); - if (jit_swf_p()) - jit_ldxi_i(u, JIT_FP, arg_offset(v->u.w)); - else if (jit_arg_reg_p(v->u.w)) - jit_movr(u, JIT_RA0 - v->u.w); - else - jit_ldxi_i(u, JIT_FP, v->u.w); - jit_dec_synth(); -} - -void -_jit_putargr(jit_state_t *_jit, int32_t u, jit_node_t *v) -{ - assert(v->code == jit_code_arg); - jit_inc_synth_wp(putargr, u, v); - if (jit_swf_p()) - jit_stxi(arg_offset(v->u.w), JIT_FP, u); - else if (jit_arg_reg_p(v->u.w)) - jit_movr(JIT_RA0 - v->u.w, u); - else - jit_stxi(v->u.w, JIT_FP, u); - jit_dec_synth(); -} - -void -_jit_putargi(jit_state_t *_jit, jit_word_t u, jit_node_t *v) -{ - int32_t regno; - assert(v->code == jit_code_arg); - jit_inc_synth_wp(putargi, u, v); - if (jit_swf_p()) { - regno = jit_get_reg(jit_class_gpr); - jit_movi(regno, u); - jit_stxi(arg_offset(v->u.w), JIT_FP, regno); - jit_unget_reg(regno); - } - else if (jit_arg_reg_p(v->u.w)) - jit_movi(JIT_RA0 - v->u.w, u); - else { - regno = jit_get_reg(jit_class_gpr); - jit_movi(regno, u); - jit_stxi(v->u.w, JIT_FP, regno); - jit_unget_reg(regno); - } - jit_dec_synth(); -} - -void -_jit_getarg_f(jit_state_t *_jit, int32_t u, jit_node_t *v) -{ - assert(v->code == jit_code_arg_f); - jit_inc_synth_wp(getarg_f, u, v); - if (jit_cpu.abi && !(_jitc->function->self.call & jit_call_varargs)) { - if (jit_arg_f_reg_p(v->u.w)) - jit_movr_f(u, JIT_FA0 - v->u.w); - else - jit_ldxi_f(u, JIT_FP, v->u.w); - } - else if (jit_swf_p()) - jit_ldxi_f(u, JIT_FP, arg_offset(v->u.w)); - else { - if (jit_arg_reg_p(v->u.w)) - jit_movr_w_f(u, JIT_RA0 - v->u.w); - else - jit_ldxi_f(u, JIT_FP, v->u.w); - } - jit_dec_synth(); -} - -void -_jit_putargr_f(jit_state_t *_jit, int32_t u, jit_node_t *v) -{ - assert(v->code == jit_code_arg_f); - jit_inc_synth_wp(putargr_f, u, v); - if (jit_cpu.abi) { - if (jit_arg_f_reg_p(v->u.w)) - jit_movr_f(JIT_FA0 - v->u.w, u); - else - jit_stxi_f(v->u.w, JIT_FP, u); - } - else if (jit_swf_p()) - jit_stxi_f(arg_offset(v->u.w), JIT_FP, u); - else { - if (jit_arg_reg_p(v->u.w)) - jit_movr_f_w(JIT_RA0 - v->u.w, u); - else - jit_stxi_f(v->u.w, JIT_FP, u); - } - jit_dec_synth(); -} - -void -_jit_putargi_f(jit_state_t *_jit, jit_float32_t u, jit_node_t *v) -{ - int32_t regno; - assert(v->code == jit_code_arg_f); - jit_inc_synth_fp(putargi_f, u, v); - if (jit_cpu.abi) { - if (jit_arg_f_reg_p(v->u.w)) - jit_movi_f(JIT_FA0 - v->u.w, u); - else { - regno = jit_get_reg(jit_class_fpr); - jit_movi_f(regno, u); - jit_stxi_f(v->u.w, JIT_FP, regno); - jit_unget_reg(regno); - } - } - else if (jit_swf_p()) { - regno = jit_get_reg(jit_class_fpr); - jit_movi_f(regno, u); - jit_stxi_f(arg_offset(v->u.w), JIT_FP, regno); - jit_unget_reg(regno); - } - else { - regno = jit_get_reg(jit_class_fpr); - jit_movi_f(regno, u); - if (jit_arg_reg_p(v->u.w)) - jit_movr_f_w(JIT_RA0 - v->u.w, regno); - else - jit_stxi_f(v->u.w, JIT_FP, regno); - jit_unget_reg(regno); - } - jit_dec_synth(); -} - -void -_jit_getarg_d(jit_state_t *_jit, int32_t u, jit_node_t *v) -{ - assert(v->code == jit_code_arg_d); - jit_inc_synth_wp(getarg_d, u, v); - if (jit_cpu.abi && !(_jitc->function->self.call & jit_call_varargs)) { - if (jit_arg_f_reg_p(v->u.w)) - jit_movr_d(u, JIT_FA0 - v->u.w); - else - jit_ldxi_d(u, JIT_FP, v->u.w); - } - else if (jit_swf_p()) - jit_ldxi_d(u, JIT_FP, arg_offset(v->u.w)); - else { - if (jit_arg_reg_p(v->u.w)) - jit_movr_ww_d(u, JIT_RA0 - v->u.w, JIT_RA0 - (v->u.w + 1)); - else - jit_ldxi_d(u, JIT_FP, v->u.w); - } - jit_dec_synth(); -} - -void -_jit_putargr_d(jit_state_t *_jit, int32_t u, jit_node_t *v) -{ - assert(v->code == jit_code_arg_d); - jit_inc_synth_wp(putargr_d, u, v); - if (jit_cpu.abi) { - if (jit_arg_f_reg_p(v->u.w)) - jit_movr_d(JIT_FA0 - v->u.w, u); - else - jit_stxi_d(v->u.w, JIT_FP, u); - } - else if (jit_swf_p()) - jit_stxi_d(arg_offset(v->u.w), JIT_FP, u); - else { - if (jit_arg_reg_p(v->u.w)) - jit_movr_d_ww(JIT_RA0 - v->u.w, JIT_RA0 - (v->u.w + 1), u); - else - jit_stxi_d(v->u.w, JIT_FP, u); - } - jit_dec_synth(); -} - -void -_jit_putargi_d(jit_state_t *_jit, jit_float64_t u, jit_node_t *v) -{ - int32_t regno; - assert(v->code == jit_code_arg_d); - jit_inc_synth_dp(putargi_d, u, v); - if (jit_cpu.abi) { - if (jit_arg_f_reg_p(v->u.w)) - jit_movi_d(JIT_FA0 - v->u.w, u); - else { - regno = jit_get_reg(jit_class_fpr); - jit_movi_d(regno, u); - jit_stxi_d(v->u.w, JIT_FP, regno); - jit_unget_reg(regno); - } - } - else if (jit_swf_p()) { - regno = jit_get_reg(jit_class_fpr); - jit_movi_d(regno, u); - jit_stxi_d(arg_offset(v->u.w), JIT_FP, regno); - jit_unget_reg(regno); - } - else { - regno = jit_get_reg(jit_class_fpr); - jit_movi_d(regno, u); - if (jit_arg_reg_p(v->u.w)) - jit_movr_d_ww(JIT_RA0 - v->u.w, JIT_RA0 - (v->u.w + 1), regno); - else - jit_stxi_d(v->u.w, JIT_FP, regno); - jit_unget_reg(regno); - } - jit_dec_synth(); -} - -void -_jit_pushargr(jit_state_t *_jit, int32_t u) -{ - assert(_jitc->function); - jit_inc_synth_w(pushargr, u); - jit_link_prepare(); - if (jit_arg_reg_p(_jitc->function->call.argi)) { - jit_movr(JIT_RA0 - _jitc->function->call.argi, u); - ++_jitc->function->call.argi; - } - else { - jit_stxi(_jitc->function->call.size, JIT_SP, u); - _jitc->function->call.size += sizeof(jit_word_t); - } - jit_dec_synth(); -} - -void -_jit_pushargi(jit_state_t *_jit, jit_word_t u) -{ - int32_t regno; - assert(_jitc->function); - jit_inc_synth_w(pushargi, u); - jit_link_prepare(); - if (jit_arg_reg_p(_jitc->function->call.argi)) { - jit_movi(JIT_RA0 - _jitc->function->call.argi, u); - ++_jitc->function->call.argi; - } - else { - regno = jit_get_reg(jit_class_gpr); - jit_movi(regno, u); - jit_stxi(_jitc->function->call.size, JIT_SP, regno); - jit_unget_reg(regno); - _jitc->function->call.size += sizeof(jit_word_t); - } - jit_dec_synth(); -} - -void -_jit_pushargr_f(jit_state_t *_jit, int32_t u) -{ - assert(_jitc->function); - jit_inc_synth_w(pushargr_f, u); - jit_link_prepare(); - if (jit_cpu.abi && !(_jitc->function->call.call & jit_call_varargs)) { - if (jit_arg_f_reg_p(_jitc->function->call.argf)) { - jit_movr_f(JIT_FA0 - _jitc->function->call.argf, u); - ++_jitc->function->call.argf; - goto done; - } - } - else { - if (jit_arg_reg_p(_jitc->function->call.argi)) { - jit_movr_f_w(JIT_RA0 - _jitc->function->call.argi, u); - ++_jitc->function->call.argi; - goto done; - } - } - jit_stxi_f(_jitc->function->call.size, JIT_SP, u); - _jitc->function->call.size += sizeof(jit_word_t); -done: - jit_dec_synth(); -} - -void -_jit_pushargi_f(jit_state_t *_jit, jit_float32_t u) -{ - int32_t regno; - assert(_jitc->function); - jit_inc_synth_f(pushargi_f, u); - jit_link_prepare(); - if (jit_cpu.abi && !(_jitc->function->call.call & jit_call_varargs)) { - if (jit_arg_f_reg_p(_jitc->function->call.argf)) { - /* cannot jit_movi_f in the argument register because - * float arguments are packed, and that would cause - * either an assertion in debug mode, or overwritting - * two registers */ - regno = jit_get_reg(jit_class_fpr); - jit_movi_f(regno, u); - jit_movr_f(JIT_FA0 - _jitc->function->call.argf, regno); - jit_unget_reg(regno); - ++_jitc->function->call.argf; - goto done; - } - } - else { - if (jit_arg_reg_p(_jitc->function->call.argi)) { - jit_movi_f_w(JIT_RA0 - _jitc->function->call.argi, u); - ++_jitc->function->call.argi; - goto done; - } - } - regno = jit_get_reg(jit_class_fpr); - jit_movi_f(regno, u); - jit_stxi_f(_jitc->function->call.size, JIT_SP, regno); - jit_unget_reg(regno); - _jitc->function->call.size += sizeof(jit_word_t); -done: - jit_dec_synth(); -} - -void -_jit_pushargr_d(jit_state_t *_jit, int32_t u) -{ - assert(_jitc->function); - jit_inc_synth_w(pushargr_d, u); - jit_link_prepare(); - if (jit_cpu.abi && !(_jitc->function->call.call & jit_call_varargs)) { - if (jit_arg_d_reg_p(_jitc->function->call.argf)) { - if (_jitc->function->call.argf & 1) - ++_jitc->function->call.argf; - jit_movr_d(JIT_FA0 - _jitc->function->call.argf, u); - _jitc->function->call.argf += 2; - goto done; - } - } - else { - if (_jitc->function->call.argi & 1) - ++_jitc->function->call.argi; - if (jit_arg_reg_p(_jitc->function->call.argi)) { - jit_movr_d_ww(JIT_RA0 - _jitc->function->call.argi, - JIT_RA0 - (_jitc->function->call.argi + 1), - u); - _jitc->function->call.argi += 2; - goto done; - } - } - if (_jitc->function->call.size & 7) - _jitc->function->call.size += 4; - jit_stxi_d(_jitc->function->call.size, JIT_SP, u); - _jitc->function->call.size += sizeof(jit_float64_t); -done: - jit_dec_synth(); -} - -void -_jit_pushargi_d(jit_state_t *_jit, jit_float64_t u) -{ - int32_t regno; - assert(_jitc->function); - jit_inc_synth_d(pushargi_d, u); - jit_link_prepare(); - if (jit_cpu.abi && !(_jitc->function->call.call & jit_call_varargs)) { - if (jit_arg_d_reg_p(_jitc->function->call.argf)) { - if (_jitc->function->call.argf & 1) - ++_jitc->function->call.argf; - jit_movi_d(JIT_FA0 - _jitc->function->call.argf, u); - _jitc->function->call.argf += 2; - goto done; - } - } - else { - if (_jitc->function->call.argi & 1) - ++_jitc->function->call.argi; - if (jit_arg_reg_p(_jitc->function->call.argi)) { - jit_movi_d_ww(JIT_RA0 - _jitc->function->call.argi, - JIT_RA0 - (_jitc->function->call.argi + 1), - u); - _jitc->function->call.argi += 2; - goto done; - } - } - if (_jitc->function->call.size & 7) - _jitc->function->call.size += 4; - regno = jit_get_reg(jit_class_fpr); - jit_movi_d(regno, u); - jit_stxi_d(_jitc->function->call.size, JIT_SP, regno); - jit_unget_reg(regno); - _jitc->function->call.size += sizeof(jit_float64_t); -done: - jit_dec_synth(); -} - -jit_bool_t -_jit_regarg_p(jit_state_t *_jit, jit_node_t *node, int32_t regno) -{ - int32_t spec; - spec = jit_class(_rvs[regno].spec); - if (spec & jit_class_arg) { - regno = JIT_RA0 - regno; - if (regno >= 0 && regno < node->v.w) - return (1); - if (jit_cpu.abi && spec & jit_class_fpr) { - regno = JIT_FA0 - regno; - if (regno >= 0 && regno < node->w.w) - return (1); - } - } - - return (0); -} - -void -_jit_finishr(jit_state_t *_jit, int32_t r0) -{ - jit_node_t *node; - assert(_jitc->function); - jit_inc_synth_w(finishr, r0); - if (_jitc->function->self.alen < _jitc->function->call.size) - _jitc->function->self.alen = _jitc->function->call.size; - node = jit_callr(r0); - node->v.w = _jitc->function->self.argi; - node->w.w = _jitc->function->call.argf; - _jitc->function->call.argi = _jitc->function->call.argf = - _jitc->function->call.size = 0; - _jitc->prepare = 0; - jit_dec_synth(); -} - -jit_node_t * -_jit_finishi(jit_state_t *_jit, jit_pointer_t i0) -{ - jit_node_t *node; - assert(_jitc->function); - jit_inc_synth_w(finishi, (jit_word_t)i0); - if (_jitc->function->self.alen < _jitc->function->call.size) - _jitc->function->self.alen = _jitc->function->call.size; - node = jit_calli(i0); - node->v.w = _jitc->function->call.argi; - node->w.w = _jitc->function->call.argf; - _jitc->function->call.argi = _jitc->function->call.argf = - _jitc->function->call.size = 0; - _jitc->prepare = 0; - jit_dec_synth(); - return (node); -} - -void -_jit_retval_c(jit_state_t *_jit, int32_t r0) -{ - jit_inc_synth_w(retval_c, r0); - jit_extr_c(r0, JIT_RET); - jit_dec_synth(); -} - -void -_jit_retval_uc(jit_state_t *_jit, int32_t r0) -{ - jit_inc_synth_w(retval_uc, r0); - jit_extr_uc(r0, JIT_RET); - jit_dec_synth(); -} - -void -_jit_retval_s(jit_state_t *_jit, int32_t r0) -{ - jit_inc_synth_w(retval_s, r0); - jit_extr_s(r0, JIT_RET); - jit_dec_synth(); -} - -void -_jit_retval_us(jit_state_t *_jit, int32_t r0) -{ - jit_inc_synth_w(retval_us, r0); - jit_extr_us(r0, JIT_RET); - jit_dec_synth(); -} - -void -_jit_retval_i(jit_state_t *_jit, int32_t r0) -{ - jit_inc_synth_w(retval_i, r0); - if (r0 != JIT_RET) - jit_movr(r0, JIT_RET); - jit_dec_synth(); -} - -void -_jit_retval_f(jit_state_t *_jit, int32_t r0) -{ - jit_inc_synth_w(retval_f, r0); - if (jit_cpu.abi) { - if (r0 != JIT_FRET) - jit_movr_f(r0, JIT_FRET); - } - else if (r0 != JIT_RET) - jit_movr_w_f(r0, JIT_RET); - jit_dec_synth(); -} - -void -_jit_retval_d(jit_state_t *_jit, int32_t r0) -{ - jit_inc_synth_w(retval_d, r0); - if (jit_cpu.abi) { - if (r0 != JIT_FRET) - jit_movr_d(r0, JIT_FRET); - } - else if (r0 != JIT_RET) - jit_movr_ww_d(r0, JIT_RET, _R1); - jit_dec_synth(); -} - -jit_pointer_t -_emit_code(jit_state_t *_jit) -{ - jit_node_t *node; - jit_node_t *temp; - jit_word_t word; - int32_t value; - int32_t offset; - struct { - jit_node_t *node; - uint8_t *data; - jit_word_t word; -#if DEVEL_DISASSEMBLER - jit_word_t prevw; -#endif - jit_uword_t thumb; -#if DISASSEMBLER - int32_t info_offset; -#endif - int32_t const_offset; - int32_t patch_offset; - } undo; -#if DEVEL_DISASSEMBLER - jit_word_t prevw; -#endif - - _jitc->function = NULL; - _jitc->thumb = 0; - - jit_reglive_setup(); - - _jitc->consts.data = NULL; - _jitc->consts.offset = _jitc->consts.length = 0; - - undo.word = 0; - undo.node = NULL; - undo.data = NULL; - undo.thumb = 0; -#if DISASSEMBLER - undo.info_offset = -#endif - undo.const_offset = undo.patch_offset = 0; -# define assert_data(node) /**/ -#define case_rr(name, type) \ - case jit_code_##name##r##type: \ - name##r##type(rn(node->u.w), rn(node->v.w)); \ - break -#define case_rw(name, type) \ - case jit_code_##name##i##type: \ - name##i##type(rn(node->u.w), node->v.w); \ - break -#define case_vv(name, type) \ - case jit_code_##name##r##type: \ - if (jit_swf_p()) \ - swf_##name##r##type(rn(node->u.w), rn(node->v.w)); \ - else \ - vfp_##name##r##type(rn(node->u.w), rn(node->v.w)); \ - break -#define case_vw(name, type) \ - case jit_code_##name##i##type: \ - if (jit_swf_p()) \ - swf_##name##i##type(rn(node->u.w), node->v.w); \ - else \ - vfp_##name##i##type(rn(node->u.w), node->v.w); \ - break -#define case_wr(name, type) \ - case jit_code_##name##i##type: \ - name##i##type(node->u.w, rn(node->v.w)); \ - break -#define case_wv(name, type) \ - case jit_code_##name##i##type: \ - if (jit_swf_p()) \ - swf_##name##i##type(node->u.w, rn(node->v.w)); \ - else \ - vfp_##name##i##type(node->u.w, rn(node->v.w)); \ - break -#define case_rrr(name, type) \ - case jit_code_##name##r##type: \ - name##r##type(rn(node->u.w), \ - rn(node->v.w), rn(node->w.w)); \ - break -#define case_rrrr(name, type) \ - case jit_code_##name##r##type: \ - name##r##type(rn(node->u.q.l), rn(node->u.q.h), \ - rn(node->v.w), rn(node->w.w)); \ - break -#define case_vvv(name, type) \ - case jit_code_##name##r##type: \ - if (jit_swf_p()) \ - swf_##name##r##type(rn(node->u.w), \ - rn(node->v.w), rn(node->w.w)); \ - else \ - vfp_##name##r##type(rn(node->u.w), \ - rn(node->v.w), rn(node->w.w)); \ - break -#define case_rrw(name, type) \ - case jit_code_##name##i##type: \ - name##i##type(rn(node->u.w), rn(node->v.w), node->w.w); \ - break -#define case_rrrw(name, type) \ - case jit_code_##name##i##type: \ - name##i##type(rn(node->u.q.l), rn(node->u.q.h), \ - rn(node->v.w), node->w.w); \ - break -#define case_vvw(name, type) \ - case jit_code_##name##i##type: \ - if (jit_swf_p()) \ - swf_##name##i##type(rn(node->u.w), \ - rn(node->v.w), node->w.w); \ - else \ - vfp_##name##i##type(rn(node->u.w), \ - rn(node->v.w), node->w.w); \ - break -#define case_vvf(name) \ - case jit_code_##name##i_f: \ - assert_data(node); \ - if (jit_swf_p()) \ - swf_##name##i_f(rn(node->u.w), rn(node->v.w), \ - node->w.f); \ - else \ - vfp_##name##i_f(rn(node->u.w), rn(node->v.w), \ - node->w.f); \ - break -#define case_vvd(name) \ - case jit_code_##name##i_d: \ - assert_data(node); \ - if (jit_swf_p()) \ - swf_##name##i_d(rn(node->u.w), rn(node->v.w), \ - node->w.d); \ - else \ - vfp_##name##i_d(rn(node->u.w), rn(node->v.w), \ - node->w.d); \ - break -#define case_wrr(name, type) \ - case jit_code_##name##i##type: \ - name##i##type(node->u.w, rn(node->v.w), rn(node->w.w)); \ - break -#define case_wvv(name, type) \ - case jit_code_##name##i##type: \ - if (jit_swf_p()) \ - swf_##name##i##type(node->u.w, \ - rn(node->v.w), rn(node->w.w)); \ - else \ - vfp_##name##i##type(node->u.w, \ - rn(node->v.w), rn(node->w.w)); \ - break -#define case_brr(name, type) \ - case jit_code_##name##r##type: \ - temp = node->u.n; \ - assert(temp->code == jit_code_label || \ - temp->code == jit_code_epilog); \ - if (temp->flag & jit_flag_patch) \ - name##r##type(temp->u.w, rn(node->v.w), \ - rn(node->w.w)); \ - else { \ - word = name##r##type(_jit->pc.w, \ - rn(node->v.w), rn(node->w.w)); \ - patch(word, node); \ - } \ - break -#define case_bvv(name, type) \ - case jit_code_##name##r##type: \ - temp = node->u.n; \ - assert(temp->code == jit_code_label || \ - temp->code == jit_code_epilog); \ - if (temp->flag & jit_flag_patch) { \ - if (jit_swf_p()) \ - swf_##name##r##type(temp->u.w, rn(node->v.w), \ - rn(node->w.w)); \ - else \ - vfp_##name##r##type(temp->u.w, rn(node->v.w), \ - rn(node->w.w)); \ - } \ - else { \ - if (jit_swf_p()) \ - word = swf_##name##r##type(_jit->pc.w, \ - rn(node->v.w), \ - rn(node->w.w)); \ - else \ - word = vfp_##name##r##type(_jit->pc.w, \ - rn(node->v.w), \ - rn(node->w.w)); \ - patch(word, node); \ - } \ - break -#define case_brw(name, type) \ - case jit_code_##name##i##type: \ - temp = node->u.n; \ - assert(temp->code == jit_code_label || \ - temp->code == jit_code_epilog); \ - if (temp->flag & jit_flag_patch) \ - name##i##type(temp->u.w, \ - rn(node->v.w), node->w.w); \ - else { \ - word = name##i##type(_jit->pc.w, \ - rn(node->v.w), node->w.w); \ - patch(word, node); \ - } \ - break; -#define case_bvf(name) \ - case jit_code_##name##i_f: \ - temp = node->u.n; \ - assert(temp->code == jit_code_label || \ - temp->code == jit_code_epilog); \ - if (temp->flag & jit_flag_patch) { \ - if (jit_swf_p()) \ - swf_##name##i_f(temp->u.w, rn(node->v.w), \ - node->w.f); \ - else \ - vfp_##name##i_f(temp->u.w, rn(node->v.w), \ - node->w.f); \ - } \ - else { \ - if (jit_swf_p()) \ - word = swf_##name##i_f(_jit->pc.w, \ - rn(node->v.w), \ - node->w.f); \ - else \ - word = vfp_##name##i_f(_jit->pc.w, \ - rn(node->v.w), \ - node->w.f); \ - patch(word, node); \ - } \ - break -#define case_bvd(name) \ - case jit_code_##name##i_d: \ - temp = node->u.n; \ - assert(temp->code == jit_code_label || \ - temp->code == jit_code_epilog); \ - if (temp->flag & jit_flag_patch) { \ - if (jit_swf_p()) \ - swf_##name##i_d(temp->u.w, rn(node->v.w), \ - node->w.d); \ - else \ - vfp_##name##i_d(temp->u.w, rn(node->v.w), \ - node->w.d); \ - } \ - else { \ - if (jit_swf_p()) \ - word = swf_##name##i_d(_jit->pc.w, \ - rn(node->v.w), \ - node->w.d); \ - else \ - word = vfp_##name##i_d(_jit->pc.w, \ - rn(node->v.w), \ - node->w.d); \ - patch(word, node); \ - } \ - break -#if DEVEL_DISASSEMBLER - prevw = _jit->pc.w; -#endif - for (node = _jitc->head; node; node = node->next) { - if (_jit->pc.uc >= _jitc->code.end) - return (NULL); - -#if DEVEL_DISASSEMBLER - node->offset = (jit_uword_t)_jit->pc.w - (jit_uword_t)prevw; - prevw = _jit->pc.w; -#endif - value = jit_classify(node->code); - jit_regarg_set(node, value); - switch (node->code) { - case jit_code_align: - assert(!(node->u.w & (node->u.w - 1)) && - node->u.w <= sizeof(jit_word_t)); - if (node->u.w == sizeof(jit_word_t) && - (word = _jit->pc.w & (sizeof(jit_word_t) - 1))) - nop(sizeof(jit_word_t) - word); - break; - case jit_code_note: case jit_code_name: - if (must_align_p(node->next)) - nop(2); - node->u.w = _jit->pc.w; - break; - case jit_code_label: - if (must_align_p(node->next)) - nop(2); - /* remember label is defined */ - node->flag |= jit_flag_patch; - node->u.w = _jit->pc.w; - break; - case_rrr(add,); - case_rrw(add,); - case_rrr(addc,); - case_rrw(addc,); - case_rrr(addx,); - case_rrw(addx,); - case_rrr(sub,); - case_rrw(sub,); - case_rrr(subc,); - case_rrw(subc,); - case_rrr(subx,); - case_rrw(subx,); - case_rrw(rsb,); - case_rrr(mul,); - case_rrw(mul,); - case_rrrr(qmul,); - case_rrrw(qmul,); - case_rrrr(qmul, _u); - case_rrrw(qmul, _u); - case_rrr(div,); - case_rrw(div,); - case_rrr(div, _u); - case_rrw(div, _u); - case_rrrr(qdiv,); - case_rrrw(qdiv,); - case_rrrr(qdiv, _u); - case_rrrw(qdiv, _u); - case_rrr(rem,); - case_rrw(rem,); - case_rrr(rem, _u); - case_rrw(rem, _u); - case_rrr(lsh,); - case_rrw(lsh,); - case_rrr(rsh,); - case_rrw(rsh,); - case_rrr(rsh, _u); - case_rrw(rsh, _u); - case_rr(neg,); - case_rr(com,); - case_rrr(and,); - case_rrw(and,); - case_rrr(or,); - case_rrw(or,); - case_rrr(xor,); - case_rrw(xor,); - case_vv(trunc, _f_i); - case_vv(trunc, _d_i); - case_rr(ld, _c); - case_rw(ld, _c); - case_rr(ld, _uc); - case_rw(ld, _uc); - case_rr(ld, _s); - case_rw(ld, _s); - case_rr(ld, _us); - case_rw(ld, _us); - case_rr(ld, _i); - case_rw(ld, _i); - case_rrr(ldx, _c); - case_rrw(ldx, _c); - case_rrr(ldx, _uc); - case_rrw(ldx, _uc); - case_rrr(ldx, _s); - case_rrw(ldx, _s); - case_rrr(ldx, _us); - case_rrw(ldx, _us); - case_rrr(ldx, _i); - case_rrw(ldx, _i); - case_rr(st, _c); - case_wr(st, _c); - case_rr(st, _s); - case_wr(st, _s); - case_rr(st, _i); - case_wr(st, _i); - case_rrr(stx, _c); - case_wrr(stx, _c); - case_rrr(stx, _s); - case_wrr(stx, _s); - case_rrr(stx, _i); - case_wrr(stx, _i); - case_rr(hton, _us); - case_rr(hton, _ui); - case_rr(ext, _c); - case_rr(ext, _uc); - case_rr(ext, _s); - case_rr(ext, _us); - case_rr(mov,); - case jit_code_movi: - if (node->flag & jit_flag_node) { - temp = node->v.n; - if (temp->code == jit_code_data || - (temp->code == jit_code_label && - (temp->flag & jit_flag_patch))) - movi(rn(node->u.w), temp->u.w); - else { - assert(temp->code == jit_code_label || - temp->code == jit_code_epilog); - word = movi_p(rn(node->u.w), temp->u.w); - patch(word, node); - } - } - else - movi(rn(node->u.w), node->v.w); - break; - case_rrr(lt,); - case_rrw(lt,); - case_rrr(lt, _u); - case_rrw(lt, _u); - case_rrr(le,); - case_rrw(le,); - case_rrr(le, _u); - case_rrw(le, _u); - case_rrr(eq,); - case_rrw(eq,); - case_rrr(ge,); - case_rrw(ge,); - case_rrr(ge, _u); - case_rrw(ge, _u); - case_rrr(gt,); - case_rrw(gt,); - case_rrr(gt, _u); - case_rrw(gt, _u); - case_rrr(ne,); - case_rrw(ne,); - case_brr(blt,); - case_brw(blt,); - case_brr(blt, _u); - case_brw(blt, _u); - case_brr(ble,); - case_brw(ble,); - case_brr(ble, _u); - case_brw(ble, _u); - case_brr(beq,); - case_brw(beq,); - case_brr(bge,); - case_brw(bge,); - case_brr(bge, _u); - case_brw(bge, _u); - case_brr(bgt,); - case_brw(bgt,); - case_brr(bgt, _u); - case_brw(bgt, _u); - case_brr(bne,); - case_brw(bne,); - case_brr(boadd,); - case_brw(boadd,); - case_brr(boadd, _u); - case_brw(boadd, _u); - case_brr(bxadd,); - case_brw(bxadd,); - case_brr(bxadd, _u); - case_brw(bxadd, _u); - case_brr(bosub,); - case_brw(bosub,); - case_brr(bosub, _u); - case_brw(bosub, _u); - case_brr(bxsub,); - case_brw(bxsub,); - case_brr(bxsub, _u); - case_brw(bxsub, _u); - case_brr(bms,); - case_brw(bms,); - case_brr(bmc,); - case_brw(bmc,); - case_vvv(add, _f); - case_vvf(add); - case_vvv(sub, _f); - case_vvf(sub); - case_vvf(rsb); - case_vvv(mul, _f); - case_vvf(mul); - case_vvv(div, _f); - case_vvf(div); - case_vv(abs, _f); - case_vv(neg, _f); - case_vv(sqrt, _f); - case_vv(ext, _f); - case_vv(ld, _f); - case_vw(ld, _f); - case_vvv(ldx, _f); - case_vvw(ldx, _f); - case_vv(st, _f); - case_wv(st, _f); - case_vvv(stx, _f); - case_wvv(stx, _f); - case_vv(mov, _f); - case jit_code_movi_f: - assert_data(node); - if (jit_swf_p()) - swf_movi_f(rn(node->u.w), node->v.f); - else - vfp_movi_f(rn(node->u.w), node->v.f); - break; - case_vv(ext, _d_f); - case_vvv(lt, _f); - case_vvf(lt); - case_vvv(le, _f); - case_vvf(le); - case_vvv(eq, _f); - case_vvf(eq); - case_vvv(ge, _f); - case_vvf(ge); - case_vvv(gt, _f); - case_vvf(gt); - case_vvv(ne, _f); - case_vvf(ne); - case_vvv(unlt, _f); - case_vvf(unlt); - case_vvv(unle, _f); - case_vvf(unle); - case_vvv(uneq, _f); - case_vvf(uneq); - case_vvv(unge, _f); - case_vvf(unge); - case_vvv(ungt, _f); - case_vvf(ungt); - case_vvv(ltgt, _f); - case_vvf(ltgt); - case_vvv(ord, _f); - case_vvf(ord); - case_vvv(unord, _f); - case_vvf(unord); - case_bvv(blt, _f); - case_bvf(blt); - case_bvv(ble, _f); - case_bvf(ble); - case_bvv(beq, _f); - case_bvf(beq); - case_bvv(bge, _f); - case_bvf(bge); - case_bvv(bgt, _f); - case_bvf(bgt); - case_bvv(bne, _f); - case_bvf(bne); - case_bvv(bunlt, _f); - case_bvf(bunlt); - case_bvv(bunle, _f); - case_bvf(bunle); - case_bvv(buneq, _f); - case_bvf(buneq); - case_bvv(bunge, _f); - case_bvf(bunge); - case_bvv(bungt, _f); - case_bvf(bungt); - case_bvv(bltgt, _f); - case_bvf(bltgt); - case_bvv(bord, _f); - case_bvf(bord); - case_bvv(bunord, _f); - case_bvf(bunord); - case_vvv(add, _d); - case_vvd(add); - case_vvv(sub, _d); - case_vvd(sub); - case_vvd(rsb); - case_vvv(mul, _d); - case_vvd(mul); - case_vvv(div, _d); - case_vvd(div); - case_vv(abs, _d); - case_vv(neg, _d); - case_vv(sqrt, _d); - case_vv(ext, _d); - case_vv(ld, _d); - case_vw(ld, _d); - case_vvv(ldx, _d); - case_vvw(ldx, _d); - case_vv(st, _d); - case_wv(st, _d); - case_vvv(stx, _d); - case_wvv(stx, _d); - case_vv(mov, _d); - case jit_code_movi_d: - assert_data(node); - if (jit_swf_p()) - swf_movi_d(rn(node->u.w), node->v.d); - else - vfp_movi_d(rn(node->u.w), node->v.d); - break; - case_vv(ext, _f_d); - case_vvv(lt, _d); - case_vvd(lt); - case_vvv(le, _d); - case_vvd(le); - case_vvv(eq, _d); - case_vvd(eq); - case_vvv(ge, _d); - case_vvd(ge); - case_vvv(gt, _d); - case_vvd(gt); - case_vvv(ne, _d); - case_vvd(ne); - case_vvv(unlt, _d); - case_vvd(unlt); - case_vvv(unle, _d); - case_vvd(unle); - case_vvv(uneq, _d); - case_vvd(uneq); - case_vvv(unge, _d); - case_vvd(unge); - case_vvv(ungt, _d); - case_vvd(ungt); - case_vvv(ltgt, _d); - case_vvd(ltgt); - case_vvv(ord, _d); - case_vvd(ord); - case_vvv(unord, _d); - case_vvd(unord); - case_bvv(blt, _d); - case_bvd(blt); - case_bvv(ble, _d); - case_bvd(ble); - case_bvv(beq, _d); - case_bvd(beq); - case_bvv(bge, _d); - case_bvd(bge); - case_bvv(bgt, _d); - case_bvd(bgt); - case_bvv(bne, _d); - case_bvd(bne); - case_bvv(bunlt, _d); - case_bvd(bunlt); - case_bvv(bunle, _d); - case_bvd(bunle); - case_bvv(buneq, _d); - case_bvd(buneq); - case_bvv(bunge, _d); - case_bvd(bunge); - case_bvv(bungt, _d); - case_bvd(bungt); - case_bvv(bltgt, _d); - case_bvd(bltgt); - case_bvv(bord, _d); - case_bvd(bord); - case_bvv(bunord, _d); - case_bvd(bunord); - case jit_code_jmpr: - jmpr(rn(node->u.w)); - flush_consts(); - break; - case jit_code_jmpi: - if (node->flag & jit_flag_node) { - temp = node->u.n; - assert(temp->code == jit_code_label || - temp->code == jit_code_epilog); - if (temp->flag & jit_flag_patch) - jmpi(temp->u.w); - else { - word = jmpi_p(_jit->pc.w, 1); - patch(word, node); - } - } - else - jmpi(node->u.w); - flush_consts(); - break; - case jit_code_callr: - callr(rn(node->u.w)); - break; - case jit_code_calli: - if (node->flag & jit_flag_node) { - temp = node->u.n; - assert(temp->code == jit_code_label || - temp->code == jit_code_epilog); - if (temp->flag & jit_flag_patch) - calli(temp->u.w); - else { - word = calli_p(_jit->pc.w); - patch(word, node); - } - } - else - calli(node->u.w); - break; - case jit_code_prolog: - _jitc->function = _jitc->functions.ptr + node->w.w; - undo.node = node; - undo.word = _jit->pc.w; -#if DEVEL_DISASSEMBLER - undo.prevw = prevw; -#endif - undo.data = _jitc->consts.data; - undo.thumb = _jitc->thumb; - undo.const_offset = _jitc->consts.offset; - undo.patch_offset = _jitc->patches.offset; -#if DISASSEMBLER - if (_jitc->data_info.ptr) - undo.info_offset = _jitc->data_info.offset; -#endif - restart_function: - _jitc->again = 0; - prolog(node); - break; - case jit_code_epilog: - assert(_jitc->function == _jitc->functions.ptr + node->w.w); - if (_jitc->again) { - for (temp = undo.node->next; - temp != node; temp = temp->next) { - if (temp->code == jit_code_label || - temp->code == jit_code_epilog) - temp->flag &= ~jit_flag_patch; - } - temp->flag &= ~jit_flag_patch; - node = undo.node; - _jit->pc.w = undo.word; -#if DEVEL_DISASSEMBLER - prevw = undo.prevw; -#endif - invalidate_consts(); - _jitc->consts.data = undo.data; - _jitc->thumb = undo.thumb; - _jitc->consts.offset = undo.const_offset; - _jitc->patches.offset = undo.patch_offset; -#if DISASSEMBLER - if (_jitc->data_info.ptr) - _jitc->data_info.offset = undo.info_offset; -#endif - goto restart_function; - } - /* remember label is defined */ - node->flag |= jit_flag_patch; - node->u.w = _jit->pc.w; - epilog(node); - _jitc->function = NULL; - flush_consts(); - break; - case jit_code_movr_w_f: - if (jit_swf_p()) - swf_movr_f(rn(node->u.w), rn(node->v.w)); - else - vfp_movr_f(rn(node->u.w), rn(node->v.w)); - break; - case jit_code_movr_f_w: - if (jit_swf_p()) - swf_movr_f(rn(node->u.w), rn(node->v.w)); - else - vfp_movr_f(rn(node->u.w), rn(node->v.w)); - break; - case jit_code_movi_f_w: - assert_data(node); - if (jit_swf_p()) - swf_movi_f(rn(node->u.w), node->v.f); - else - vfp_movi_f(rn(node->u.w), node->v.f); - break; - case jit_code_movr_ww_d: - if (jit_swf_p()) - swf_movr_d(rn(node->u.w), rn(node->v.w)); - else - vfp_movr_d(rn(node->u.w), rn(node->v.w)); - break; - case jit_code_movr_d_ww: - if (jit_swf_p()) - swf_movr_d(rn(node->u.w), rn(node->w.w)); - else - vfp_movr_d(rn(node->u.w), rn(node->w.w)); - break; - case jit_code_movi_d_ww: - assert_data(node); - if (jit_swf_p()) - swf_movi_d(rn(node->u.w), node->w.d); - else - vfp_movi_d(rn(node->u.w), node->w.d); - break; - case jit_code_va_start: - vastart(rn(node->u.w)); - break; - case jit_code_va_arg: - vaarg(rn(node->u.w), rn(node->v.w)); - break; - case jit_code_va_arg_d: - if (jit_swf_p()) - swf_vaarg_d(rn(node->u.w), rn(node->v.w)); - else - vfp_vaarg_d(rn(node->u.w), rn(node->v.w)); - break; - case jit_code_live: case jit_code_ellipsis: - case jit_code_va_push: - case jit_code_allocai: case jit_code_allocar: - case jit_code_arg: - case jit_code_arg_f: case jit_code_arg_d: - case jit_code_va_end: - case jit_code_ret: - case jit_code_retr: case jit_code_reti: - case jit_code_retr_f: case jit_code_reti_f: - case jit_code_retr_d: case jit_code_reti_d: - case jit_code_getarg_c: case jit_code_getarg_uc: - case jit_code_getarg_s: case jit_code_getarg_us: - case jit_code_getarg_i: - case jit_code_getarg_f: case jit_code_getarg_d: - case jit_code_putargr: case jit_code_putargi: - case jit_code_putargr_f: case jit_code_putargi_f: - case jit_code_putargr_d: case jit_code_putargi_d: - case jit_code_pushargr: case jit_code_pushargi: - case jit_code_pushargr_f: case jit_code_pushargi_f: - case jit_code_pushargr_d: case jit_code_pushargi_d: - case jit_code_retval_c: case jit_code_retval_uc: - case jit_code_retval_s: case jit_code_retval_us: - case jit_code_retval_i: - case jit_code_retval_f: case jit_code_retval_d: - case jit_code_prepare: - case jit_code_finishr: case jit_code_finishi: - break; - default: - abort(); - } - jit_regarg_clr(node, value); - assert(_jitc->regarg == 0 && _jitc->synth == 0); - /* update register live state */ - jit_reglive(node); - - if (_jitc->consts.length && - (_jit->pc.uc - _jitc->consts.data >= 3968 || - (jit_uword_t)_jit->pc.uc - - (jit_uword_t)_jitc->consts.patches[0] >= 3968)) { - /* longest sequence should be 64 bytes, but preventively - * do not let it go past 128 remaining bytes before a flush */ - if (node->next && - node->next->code != jit_code_jmpi && - node->next->code != jit_code_jmpr && - node->next->code != jit_code_epilog) { - /* insert a jump, flush constants and continue */ - word = _jit->pc.w; - assert(!jit_thumb_p()); - B(0); - flush_consts(); - patch_at(arm_patch_jump, word, _jit->pc.w); - } - } - } -#undef case_bvd -#undef case_bvf -#undef case_brw -#undef case_bvv -#undef case_brr -#undef case_wvv -#undef case_wrr -#undef case_vvd -#undef case_vvf -#undef case_vvw -#undef case_rrw -#undef case_vvv -#undef case_rrr -#undef case_wv -#undef case_wr -#undef case_vw -#undef case_vv -#undef case_rw -#undef case_rr - - flush_consts(); - for (offset = 0; offset < _jitc->patches.offset; offset++) { - assert(_jitc->patches.ptr[offset].kind & arm_patch_node); - node = _jitc->patches.ptr[offset].node; - word = _jitc->patches.ptr[offset].inst; - if (!jit_thumb_p() && - (node->code == jit_code_movi || node->code == jit_code_calli)) { - /* calculate where to patch word */ - value = *(int32_t *)word; - assert((value & 0x0f700000) == ARM_LDRI); - /* offset may become negative (-4) if last instruction - * before unconditional branch and data following - * FIXME can this cause issues in the preprocessor prefetch - * or something else? should not, as the constants are after - * an unconditional jump */ - if (value & ARM_P) value = value & 0x00000fff; - else value = -(value & 0x00000fff); - word = word + 8 + value; - } - value = node->code == jit_code_movi ? node->v.n->u.w : node->u.n->u.w; - patch_at(_jitc->patches.ptr[offset].kind & ~arm_patch_node, word, value); - } - - jit_flush(_jit->code.ptr, _jit->pc.uc); - - return (_jit->code.ptr); -} - -#define CODE 1 -# include "rewind.c" -# include "arm-cpu.c" -# include "arm-vfp.c" -#undef CODE - -void +static void jit_flush(void *fptr, void *tptr) { -#if defined(__GNUC__) - jit_uword_t i, f, t, s; - - s = sysconf(_SC_PAGE_SIZE); - f = (jit_uword_t)fptr & -s; - t = (((jit_uword_t)tptr) + s - 1) & -s; - for (i = f; i < t; i += s) - __clear_cache((void *)i, (void *)(i + s)); -#endif + jit_word_t f = (jit_word_t)fptr & -page_size; + jit_word_t t = (((jit_word_t)tptr) + page_size - 1) & -page_size; + __clear_cache((void *)f, (void *)t); } -void -_emit_ldxi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +static inline size_t +jit_stack_alignment(void) { - ldxi_i(rn(r0), rn(r1), i0); -} - -void -_emit_stxi(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) -{ - stxi_i(i0, rn(r0), rn(r1)); -} - -void -_emit_ldxi_d(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) -{ - if (jit_swf_p()) - swf_ldxi_d(rn(r0), rn(r1), i0); - else - vfp_ldxi_d(rn(r0), rn(r1), i0); -} - -void -_emit_stxi_d(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) -{ - if (jit_swf_p()) - swf_stxi_d(i0, rn(r0), rn(r1)); - else - vfp_stxi_d(i0, rn(r0), rn(r1)); -} - -static int32_t -_jit_get_reg_pair(jit_state_t *_jit) -{ - /* bypass jit_get_reg() with argument or'ed with jit_class_chk - * and try to find an consecutive, even free register pair, or - * return JIT_NOREG if fail, as the cost of spills is greater - * than splitting a double load/store in two operations. */ - if (jit_reg_free_p(_R0) && jit_reg_free_p(_R1)) { - jit_regset_setbit(&_jitc->regarg, _R0); - jit_regset_setbit(&_jitc->regarg, _R1); - return (_R0); - } - if (jit_reg_free_p(_R2) && jit_reg_free_p(_R3)) { - jit_regset_setbit(&_jitc->regarg, _R2); - jit_regset_setbit(&_jitc->regarg, _R3); - return (_R2); - } - if (jit_reg_free_p(_R4) && jit_reg_free_p(_R5)) { - jit_regset_setbit(&_jitc->regarg, _R4); - jit_regset_setbit(&_jitc->regarg, _R5); - return (_R4); - } - if (jit_reg_free_p(_R6) && jit_reg_free_p(_R7)) { - jit_regset_setbit(&_jitc->regarg, _R6); - jit_regset_setbit(&_jitc->regarg, _R7); - return (_R6); - } - if (jit_reg_free_p(_R8) && jit_reg_free_p(_R9)) { - jit_regset_setbit(&_jitc->regarg, _R8); - jit_regset_setbit(&_jitc->regarg, _R9); - return (_R8); - } - return (JIT_NOREG); + return 8; } static void -_jit_unget_reg_pair(jit_state_t *_jit, int32_t reg) +jit_try_shorten(jit_state_t *_jit, jit_reloc_t reloc, jit_pointer_t addr) { - jit_unget_reg(reg); - switch (reg) { - case _R0: jit_unget_reg(_R1); break; - case _R2: jit_unget_reg(_R3); break; - case _R4: jit_unget_reg(_R5); break; - case _R6: jit_unget_reg(_R7); break; - case _R8: jit_unget_reg(_R9); break; - default: abort(); - } -} - -/* A prolog must be aligned at mod 4 bytes boundary. - * This condition was not being required to be tested by - * accident previously, but with the jit_frame and jit_tramp - * code it is required */ -static jit_bool_t -_must_align_p(jit_state_t *_jit, jit_node_t *node) -{ - if (jit_thumb_p() && (_jit->pc.w & 3)) { - for (; node; node = node->next) { - switch (node->code) { - case jit_code_note: - case jit_code_name: - case jit_code_label: - break; - case jit_code_prolog: - return (1); - default: - return (0); - } - } - } - return (0); -} - -static void -_load_const(jit_state_t *_jit, jit_bool_t uniq, int32_t r0, jit_word_t i0) -{ - jit_word_t w; - jit_word_t d; - jit_word_t base; - int32_t *data; - int32_t size; - int32_t offset; - - assert(!jit_thumb_p()); - if (!uniq) { - /* use zero, a valid directly encoded immediate, to avoid the - * need of a bitmask to know what offsets will be patched, so - * that comparison will always fail for constants that cannot - * be encoded */ - assert(i0 != 0); - - /* Actually, code is (currently at least) not self modifying, - * so, any value reachable backwards is valid as a constant. */ - - /* FIXME a quickly updateable/mutable hash table could be - * better here, but most times only a few comparisons - * should be done - */ - - /* search in previous constant pool */ - if ((data = (int32_t *)_jitc->consts.data)) { - w = (jit_word_t)data; - /* maximum backwards offset */ - base = (_jit->pc.w + 8) - 4092; - if (base <= w) - /* can scan all possible available backward constants */ - base = 0; - else - base = (base - w) >> 2; - size = _jitc->consts.size >> 2; - for (offset = size - 1; offset >= base; offset--) { - if (data[offset] == i0) { - w = (jit_word_t)(data + offset); - d = (_jit->pc.w + 8) - w; - LDRIN(r0, _R15_REGNO, d); - return; - } - } - } - } - else - assert(i0 == 0); - - _jitc->consts.patches[_jitc->consts.offset++] = _jit->pc.w; - /* (probably) positive forward offset */ - LDRI(r0, _R15_REGNO, 0); - - if (!uniq) { - /* search already requested values */ - for (offset = 0; offset < _jitc->consts.length; offset++) { - if (_jitc->consts.values[offset] == i0) { - _jitc->consts.patches[_jitc->consts.offset++] = offset; - return; - } - } - } - -#if DEBUG - /* cannot run out of space because of limited range - * but assert anyway to catch logic errors */ - assert(_jitc->consts.length < 1024); - assert(_jitc->consts.offset < 2048); -#endif - _jitc->consts.patches[_jitc->consts.offset++] = _jitc->consts.length; - _jitc->consts.values[_jitc->consts.length++] = i0; -} - -static void -_flush_consts(jit_state_t *_jit) -{ - jit_word_t word; - int32_t offset; - - /* if no forward constants */ - if (!_jitc->consts.length) - return; - assert(!jit_thumb_p()); - word = _jit->pc.w; - _jitc->consts.data = _jit->pc.uc; - _jitc->consts.size = _jitc->consts.length << 2; - /* FIXME check will not overrun, otherwise, need to reallocate - * code buffer and start over */ - jit_memcpy(_jitc->consts.data, _jitc->consts.values, _jitc->consts.size); - _jit->pc.w += _jitc->consts.size; - -#if DISASSEMBLER - if (_jitc->data_info.ptr) { - if (_jitc->data_info.offset >= _jitc->data_info.length) { - jit_realloc((jit_pointer_t *)&_jitc->data_info.ptr, - _jitc->data_info.length * sizeof(jit_data_info_t), - (_jitc->data_info.length + 1024) * - sizeof(jit_data_info_t)); - _jitc->data_info.length += 1024; - } - _jitc->data_info.ptr[_jitc->data_info.offset].code = word; - _jitc->data_info.ptr[_jitc->data_info.offset].length = _jitc->consts.size; - ++_jitc->data_info.offset; - } -#endif - - for (offset = 0; offset < _jitc->consts.offset; offset += 2) - patch_at(arm_patch_load, _jitc->consts.patches[offset], - word + (_jitc->consts.patches[offset + 1] << 2)); - _jitc->consts.length = _jitc->consts.offset = 0; -} - -/* to be called if needing to start over a function */ -static void -_invalidate_consts(jit_state_t *_jit) -{ - /* if no forward constants */ - if (_jitc->consts.length) - _jitc->consts.length = _jitc->consts.offset = 0; -} - -static void -_patch(jit_state_t *_jit, jit_word_t instr, jit_node_t *node) -{ - int32_t flag; - int32_t kind; - - assert(node->flag & jit_flag_node); - if (node->code == jit_code_movi) { - flag = node->v.n->flag; - kind = arm_patch_word; - } - else { - flag = node->u.n->flag; - if (node->code == jit_code_calli || - (node->code == jit_code_jmpi && !(node->flag & jit_flag_node))) - kind = arm_patch_word; - else - kind = arm_patch_jump; - } - assert(!(flag & jit_flag_patch)); - kind |= arm_patch_node; - if (_jitc->patches.offset >= _jitc->patches.length) { - jit_realloc((jit_pointer_t *)&_jitc->patches.ptr, - _jitc->patches.length * sizeof(jit_patch_t), - (_jitc->patches.length + 1024) * sizeof(jit_patch_t)); - _jitc->patches.length += 1024; - } - _jitc->patches.ptr[_jitc->patches.offset].kind = kind; - _jitc->patches.ptr[_jitc->patches.offset].inst = instr; - _jitc->patches.ptr[_jitc->patches.offset].node = node; - ++_jitc->patches.offset; } diff --git a/lightening/arm.h b/lightening/arm.h index 9177f1354..94fc86c5b 100644 --- a/lightening/arm.h +++ b/lightening/arm.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2018 Free Software Foundation, Inc. + * Copyright (C) 2012-2019 Free Software Foundation, Inc. * * This file is part of GNU lightning. * @@ -20,108 +20,113 @@ #ifndef _jit_arm_h #define _jit_arm_h -#define JIT_HASH_CONSTS 0 -#define JIT_NUM_OPERANDS 3 -/* - * Types - */ -#define jit_swf_p() (jit_cpu.vfp == 0) -#define jit_hardfp_p() jit_cpu.abi -#define jit_ldrt_strt_p() jit_cpu.ldrt_strt +#define JIT_NEEDS_LITERAL_POOL 1 -#define JIT_FP _R11 -typedef enum { -#define jit_r(i) (_R4 + (i)) -#define jit_r_num() 3 -#define jit_v(i) (_R7 + (i)) -#define jit_v_num() 3 -#define jit_f(i) (jit_cpu.abi ? _D8 + ((i)<<1) : _D0 - ((i)<<1)) -#define jit_f_num() 8 - _R12, /* ip - temporary */ -#define JIT_R0 _R4 -#define JIT_R1 _R5 -#define JIT_R2 _R6 - _R4, /* r4 - variable */ - _R5, /* r5 - variable */ - _R6, /* r6 - variable */ -#define JIT_V0 _R7 -#define JIT_V1 _R8 -#define JIT_V2 _R9 - _R7, /* r7 - variable */ - _R8, /* r8 - variable */ - _R9, /* r9 - variable */ - _R10, /* sl - stack limit */ - _R11, /* fp - frame pointer */ - _R13, /* sp - stack pointer */ - _R14, /* lr - link register */ - _R15, /* pc - program counter */ - _R3, /* r3 - argument/result */ - _R2, /* r2 - argument/result */ - _R1, /* r1 - argument/result */ - _R0, /* r0 - argument/result */ -#define JIT_F0 (jit_hardfp_p() ? _D8 : _D0) -#define JIT_F1 (jit_hardfp_p() ? _D9 : _D1) -#define JIT_F2 (jit_hardfp_p() ? _D10 : _D2) -#define JIT_F3 (jit_hardfp_p() ? _D11 : _D3) -#define JIT_F4 (jit_hardfp_p() ? _D12 : _D4) -#define JIT_F5 (jit_hardfp_p() ? _D13 : _D5) -#define JIT_F6 (jit_hardfp_p() ? _D14 : _D6) -#define JIT_F7 (jit_hardfp_p() ? _D15 : _D7) - _S16, _D8 = _S16, _Q4 = _D8, - _S17, - _S18, _D9 = _S18, - _S19, - _S20, _D10 = _S20, _Q5 = _D10, - _S21, - _S22, _D11 = _S22, - _S23, - _S24, _D12 = _S24, _Q6 = _D12, - _S25, - _S26, _D13 = _S26, - _S27, - _S28, _D14 = _S28, _Q7 = _D14, - _S29, - _S30, _D15 = _S30, - _S31, - _S15, - _S14, _D7 = _S14, - _S13, - _S12, _D6 = _S12, _Q3 = _D6, - _S11, - _S10, _D5 = _S10, - _S9, - _S8, _D4 = _S8, _Q2 = _D4, - _S7, - _S6, _D3 = _S6, - _S5, - _S4, _D2 = _S4, _Q1 = _D2, - _S3, - _S2, _D1 = _S2, - _S1, - _S0, _D0 = _S0, _Q0 = _D0, - _NOREG, -#define JIT_NOREG _NOREG -} jit_reg_t; +#define _R0 JIT_GPR(0) +#define _R1 JIT_GPR(1) +#define _R2 JIT_GPR(2) +#define _R3 JIT_GPR(3) +#define _R4 JIT_GPR(4) +#define _R5 JIT_GPR(5) +#define _R6 JIT_GPR(6) +#define _R7 JIT_GPR(7) +#define _R8 JIT_GPR(8) +#define _R9 JIT_GPR(9) +#define _R10 JIT_GPR(10) +#define _R11 JIT_GPR(11) +#define _R12 JIT_GPR(12) +#define _R13 JIT_GPR(13) +#define _R14 JIT_GPR(14) +#define _R15 JIT_GPR(15) -typedef struct { - uint32_t version : 4; - uint32_t extend : 1; - /* only generate thumb instructions for thumb2 */ - uint32_t thumb : 1; - uint32_t vfp : 3; - uint32_t neon : 1; - uint32_t abi : 2; - /* use strt+offset instead of str.w? - * on special cases it causes a SIGILL at least on qemu, probably - * due to some memory ordering constraint not being respected, so, - * disable by default */ - uint32_t ldrt_strt : 1; -} jit_cpu_t; +#define _D0 JIT_FPR(0) +#define _D1 JIT_FPR(2) +#define _D2 JIT_FPR(4) +#define _D3 JIT_FPR(6) +#define _D4 JIT_FPR(8) +#define _D5 JIT_FPR(10) +#define _D6 JIT_FPR(12) +#define _D7 JIT_FPR(14) +#define _D8 JIT_FPR(16) +#define _D9 JIT_FPR(18) +#define _D10 JIT_FPR(20) +#define _D11 JIT_FPR(22) +#define _D12 JIT_FPR(24) +#define _D13 JIT_FPR(26) +#define _D14 JIT_FPR(28) +#define _D15 JIT_FPR(30) + +#define _S0 JIT_FPR(0) +#define _S1 JIT_FPR(1) +#define _S2 JIT_FPR(2) +#define _S3 JIT_FPR(3) +#define _S4 JIT_FPR(4) +#define _S5 JIT_FPR(5) +#define _S6 JIT_FPR(6) +#define _S7 JIT_FPR(7) +#define _S8 JIT_FPR(8) +#define _S9 JIT_FPR(9) +#define _S10 JIT_FPR(10) +#define _S11 JIT_FPR(11) +#define _S12 JIT_FPR(12) +#define _S13 JIT_FPR(13) +#define _S14 JIT_FPR(14) +#define _S15 JIT_FPR(15) +#define _S16 JIT_FPR(16) +#define _S17 JIT_FPR(17) +#define _S18 JIT_FPR(18) +#define _S19 JIT_FPR(19) +#define _S20 JIT_FPR(20) +#define _S21 JIT_FPR(21) +#define _S22 JIT_FPR(22) +#define _S23 JIT_FPR(23) +#define _S24 JIT_FPR(24) +#define _S25 JIT_FPR(25) +#define _S26 JIT_FPR(26) +#define _S27 JIT_FPR(27) +#define _S28 JIT_FPR(28) +#define _S29 JIT_FPR(29) +#define _S30 JIT_FPR(30) +#define _S31 JIT_FPR(31) + +#define _SP _R13 +#define _LR _R14 +#define _PC _R15 + +#define JIT_R0 _R0 +#define JIT_R1 _R1 +#define JIT_R2 _R2 +#define JIT_R3 _R3 + +#define JIT_V0 _R4 +#define JIT_V1 _R5 +#define JIT_V2 _R6 +#define JIT_V3 _R7 +#define JIT_V4 _R8 +#define JIT_V5 _R9 +#define JIT_V6 _R10 +#define JIT_V7 _R11 + +#define JIT_F0 _D0 +#define JIT_F1 _D1 +#define JIT_F2 _D2 +#define JIT_F3 _D3 +#define JIT_F4 _D4 +#define JIT_F5 _D5 +#define JIT_F6 _D6 +#define JIT_F7 _D7 + +#define JIT_VF0 _D8 +#define JIT_VF1 _D9 +#define JIT_VF2 _D10 +#define JIT_VF3 _D11 +#define JIT_VF4 _D12 +#define JIT_VF5 _D13 +#define JIT_VF6 _D14 +#define JIT_VF7 _D15 + +#define JIT_PLATFORM_CALLEE_SAVE_GPRS _LR -/* - * Initialization - */ -JIT_API jit_cpu_t jit_cpu; #endif /* _jit_arm_h */ From 1ea34693cb0e8137eb1c5568cb9d0af9fd04bedf Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Sun, 19 May 2019 22:21:50 +0200 Subject: [PATCH 26/33] Port of arm-cpu.c to current lightening --- lightening/arm-cpu.c | 5993 ++++++++++++++++----------------------- lightening/arm-vfp.c | 487 +--- lightening/arm.h | 13 +- lightening/lightening.c | 6 +- 4 files changed, 2509 insertions(+), 3990 deletions(-) diff --git a/lightening/arm-cpu.c b/lightening/arm-cpu.c index 923db7bbf..3c3c20757 100644 --- a/lightening/arm-cpu.c +++ b/lightening/arm-cpu.c @@ -27,3920 +27,2923 @@ #define _u13(v) ((v) & 0x1fff) #define _u16(v) ((v) & 0xffff) #define _u24(v) ((v) & 0xffffff) -extern int __aeabi_idivmod(int, int); -extern unsigned __aeabi_uidivmod(unsigned, unsigned); -# define _R0_REGNO 0x00 -# define _R1_REGNO 0x01 -# define _R2_REGNO 0x02 -# define _R3_REGNO 0x03 -# define _R4_REGNO 0x04 -# define _R5_REGNO 0x05 -# define _R6_REGNO 0x06 -# define _R7_REGNO 0x07 -# define _R8_REGNO 0x08 -# define _R9_REGNO 0x09 -# define _R10_REGNO 0x0a -# define _R11_REGNO 0x0b -# define _R12_REGNO 0x0c -# define _R13_REGNO 0x0d -# define _R14_REGNO 0x0e -# define _R15_REGNO 0x0f -# define _FP_REGNO _R11_REGNO -# define _SP_REGNO _R13_REGNO -# define _LR_REGNO _R14_REGNO -# define _PC_REGNO _R15_REGNO -# define ARM_CC_EQ 0x00000000 /* Z=1 */ -# define ARM_CC_NE 0x10000000 /* Z=0 */ -# define ARM_CC_HS 0x20000000 /* C=1 */ -# define ARM_CC_CS ARM_CC_HS -# define ARM_CC_LO 0x30000000 /* C=0 */ -# define ARM_CC_CC ARM_CC_LO -# define ARM_CC_MI 0x40000000 /* N=1 */ -# define ARM_CC_PL 0x50000000 /* N=0 */ -# define ARM_CC_VS 0x60000000 /* V=1 */ -# define ARM_CC_VC 0x70000000 /* V=0 */ -# define ARM_CC_HI 0x80000000 /* C=1 && Z=0 */ -# define ARM_CC_LS 0x90000000 /* C=0 || Z=1 */ -# define ARM_CC_GE 0xa0000000 /* N=V */ -# define ARM_CC_LT 0xb0000000 /* N!=V */ -# define ARM_CC_GT 0xc0000000 /* Z=0 && N=V */ -# define ARM_CC_LE 0xd0000000 /* Z=1 || N!=V */ -# define ARM_CC_AL 0xe0000000 /* always */ -# define ARM_CC_NV 0xf0000000 /* reserved */ -# define THUMB2_IT 0 -# define THUMB2_ITT 1 -# define THUMB2_ITE 2 -# define THUMB2_ITTT 3 -# define THUMB2_ITET 4 -# define THUMB2_ITTE 5 -# define THUMB2_ITEE 6 -# define THUMB2_ITTTT 7 -# define THUMB2_ITETT 8 -# define THUMB2_ITTET 9 -# define THUMB2_ITEET 10 -# define THUMB2_ITTTE 11 -# define THUMB2_ITETE 12 -# define THUMB2_ITTEE 13 -# define THUMB2_ITEEE 14 -# define ARM_MOV 0x01a00000 -# define THUMB_MOV 0x4600 -# define ARM_MOVWI 0x03000000 /* v6t2, v7 */ -# define THUMB_MOVI 0x2000 -# define THUMB2_MOVI 0xf0400000 -# define THUMB2_MOVWI 0xf2400000 -# define ARM_MOVTI 0x03400000 -# define THUMB2_MOVTI 0xf2c00000 -# define ARM_MVN 0x01e00000 -# define THUMB_MVN 0x43c0 -# define THUMB2_MVN 0xea600000 -# define THUMB2_MVNI 0xf0600000 -# define ARM_I 0x02000000 /* immediate */ -# define ARM_S 0x00100000 /* set flags */ -# define ARM_ADD 0x00800000 -# define THUMB_ADD 0x1800 -# define THUMB_ADDX 0x4400 -# define THUMB2_ADD 0xeb000000 -# define THUMB_ADDI3 0x1c00 -# define THUMB_ADDI8 0x3000 -# define THUMB2_ADDI 0xf1000000 -# define THUMB2_ADDWI 0xf2000000 -# define ARM_ADC 0x00a00000 -# define THUMB_ADC 0x4140 -# define THUMB2_ADC 0xeb400000 -# define THUMB2_ADCI 0xf1400000 -# define ARM_SUB 0x00400000 -# define THUMB_SUB 0x1a00 -# define THUMB2_SUB 0xeba00000 -# define THUMB_SUBI3 0x1e00 -# define THUMB_SUBI8 0x3800 -# define THUMB2_SUBI 0xf1a00000 -# define THUMB2_SUBWI 0xf2a00000 -# define ARM_SBC 0x00c00000 -# define THUMB_SBC 0x4180 -# define THUMB2_SBC 0xeb600000 -# define THUMB2_SBCI 0xf1600000 -# define ARM_RSB 0x00600000 -# define THUMB_RSBI 0x4240 -# define THUMB2_RSBI 0xf1c00000 -# define ARM_MUL 0x00000090 -# define THUMB_MUL 0x4340 -# define THUMB2_MUL 0xfb00f000 -# define ARM_UMULL 0x00800090 -# define THUMB2_UMULL 0xfba00000 -# define ARM_SMULL 0x00c00090 -# define THUMB2_SMULL 0xfb800000 -# define THUMB2_SDIV 0xfb90f0f0 -# define THUMB2_UDIV 0xfbb0f0f0 -# define ARM_AND 0x00000000 -# define THUMB_AND 0x4000 -# define THUMB2_AND 0xea000000 -# define THUMB2_ANDI 0xf0000000 -# define ARM_BIC 0x01c00000 -# define THUMB2_BIC 0xea200000 -# define THUMB2_BICI 0xf0200000 -# define ARM_ORR 0x01800000 -# define THUMB_ORR 0x4300 -# define THUMB2_ORR 0xea400000 -# define THUMB2_ORRI 0xf0400000 -# define ARM_EOR 0x00200000 -# define THUMB_EOR 0x4040 -# define THUMB2_EOR 0xea800000 -# define THUMB2_EORI 0xf0800000 -/* >> ARMv6* */ -# define ARM_REV 0x06bf0f30 -# define THUMB_REV 0xba00 -# define THUMB2_REV 0xfa90f080 -# define ARM_REV16 0x06bf0fb0 -# define THUMB_REV16 0xba40 -# define THUMB2_REV16 0xfa90f090 -# define ARM_SXTB 0x06af0070 -# define THUMB_SXTB 0xb240 -# define THUMB2_SXTB 0xfa40f080 -# define ARM_UXTB 0x06ef0070 -# define THUMB_UXTB 0xb2c0 -# define THUMB2_UXTB 0xfa50f080 -# define ARM_SXTH 0x06bf0070 -# define THUMB_SXTH 0xb200 -# define THUMB2_SXTH 0xfa00f080 -# define ARM_UXTH 0x06ff0070 -# define THUMB_UXTH 0xb280 -# define THUMB2_UXTH 0xfa10f080 -# define ARM_XTR8 0x00000400 /* ?xt? rotate 8 bits */ -# define ARM_XTR16 0x00000800 /* ?xt? rotate 16 bits */ -# define ARM_XTR24 0x00000c00 /* ?xt? rotate 24 bits */ -/* << ARMv6* */ -# define ARM_SHIFT 0x01a00000 -# define ARM_R 0x00000010 /* register shift */ -# define ARM_LSL 0x00000000 -# define THUMB_LSL 0x4080 -# define THUMB2_LSL 0xfa00f000 -# define THUMB_LSLI 0x0000 -# define THUMB2_LSLI 0xea4f0000 -# define ARM_LSR 0x00000020 -# define THUMB_LSR 0x40c0 -# define THUMB2_LSR 0xfa20f000 -# define THUMB_LSRI 0x0800 -# define THUMB2_LSRI 0xea4f0010 -# define ARM_ASR 0x00000040 -# define THUMB_ASR 0x4100 -# define THUMB2_ASR 0xfa40f000 -# define THUMB_ASRI 0x1000 -# define THUMB2_ASRI 0xea4f0020 -# define ARM_ROR 0x00000060 -# define ARM_CMP 0x01500000 -# define THUMB_CMP 0x4280 -# define THUMB_CMPX 0x4500 -# define THUMB2_CMP 0xebb00000 -# define THUMB_CMPI 0x2800 -# define THUMB2_CMPI 0xf1b00000 -# define ARM_CMN 0x01700000 -# define THUMB_CMN 0x42c0 -# define THUMB2_CMN 0xeb100000 -# define THUMB2_CMNI 0xf1100000 -# define ARM_TST 0x01100000 -# define THUMB_TST 0x4200 -# define THUMB2_TST 0xea100000 -# define THUMB2_TSTI 0xf0100000 -# define ARM_TEQ 0x01300000 -/* branch */ -# define ARM_BX 0x012fff10 -# define ARM_BLX 0x012fff30 -# define THUMB_BLX 0x4780 -# define ARM_BLXI 0xfa000000 -# define THUMB2_BLXI 0xf000c000 -# define ARM_B 0x0a000000 -# define THUMB_CC_B 0xd000 -# define THUMB_B 0xe000 -# define THUMB2_CC_B 0xf0008000 -# define THUMB2_B 0xf0009000 -# define ARM_BLI 0x0b000000 -# define THUMB2_BLI 0xf000d000 -/* ldr/str */ -# define ARM_P 0x00800000 /* positive offset */ -# define THUMB2_P 0x00000400 -# define THUMB2_U 0x00000200 -# define THUMB2_W 0x00000100 -# define ARM_LDRSB 0x011000d0 -# define THUMB_LDRSB 0x5600 -# define THUMB2_LDRSB 0xf9100000 -# define ARM_LDRSBI 0x015000d0 -# define THUMB2_LDRSBI 0xf9100c00 -# define THUMB2_LDRSBWI 0xf9900000 -# define ARM_LDRB 0x07500000 -# define THUMB_LDRB 0x5c00 -# define THUMB2_LDRB 0xf8100000 -# define ARM_LDRBI 0x05500000 -# define THUMB_LDRBI 0x7800 -# define THUMB2_LDRBI 0xf8100c00 -# define THUMB2_LDRBWI 0xf8900000 -# define ARM_LDRSH 0x011000f0 -# define THUMB_LDRSH 0x5e00 -# define THUMB2_LDRSH 0xf9300000 -# define ARM_LDRSHI 0x015000f0 -# define THUMB2_LDRSHI 0xf9300c00 -# define THUMB2_LDRSHWI 0xf9b00000 -# define ARM_LDRH 0x011000b0 -# define THUMB_LDRH 0x5a00 -# define THUMB2_LDRH 0xf8300000 -# define ARM_LDRHI 0x015000b0 -# define THUMB_LDRHI 0x8800 -# define THUMB2_LDRHI 0xf8300c00 -# define THUMB2_LDRHWI 0xf8b00000 -# define ARM_LDR 0x07100000 -# define THUMB_LDR 0x5800 -# define THUMB2_LDR 0xf8500000 -# define ARM_LDRI 0x05100000 -# define THUMB_LDRI 0x6800 -# define THUMB_LDRISP 0x9800 -# define THUMB2_LDRI 0xf8500c00 -# define THUMB2_LDRWI 0xf8d00000 -# define ARM_LDRD 0x010000d0 -# define ARM_LDRDI 0x014000d0 -# define THUMB2_LDRDI 0xe8500000 -# define ARM_STRB 0x07400000 -# define THUMB_STRB 0x5400 -# define THUMB2_STRB 0xf8000000 -# define ARM_STRBI 0x05400000 -# define THUMB_STRBI 0x7000 -# define THUMB2_STRBI 0xf8000c00 -# define THUMB2_STRBWI 0xf8800000 -# define ARM_STRH 0x010000b0 -# define THUMB_STRH 0x5200 -# define THUMB2_STRH 0xf8200000 -# define ARM_STRHI 0x014000b0 -# define THUMB_STRHI 0x8000 -# define THUMB2_STRHI 0xf8200c00 -# define THUMB2_STRHWI 0xf8a00000 -# define ARM_STR 0x07000000 -# define THUMB_STR 0x5000 -# define THUMB2_STR 0xf8400000 -# define ARM_STRI 0x05000000 -# define THUMB_STRI 0x6000 -# define THUMB2_STRWI 0xf8c00000 -# define THUMB_STRISP 0x9000 -# define THUMB2_STRI 0xf8400c00 -# define ARM_STRD 0x010000f0 -# define ARM_STRDI 0x014000f0 -# define THUMB2_STRDI 0xe8400000 -/* ldm/stm */ -# define ARM_M 0x08000000 -# define ARM_M_L 0x00100000 /* load; store if not set */ -# define ARM_M_I 0x00800000 /* inc; dec if not set */ -# define ARM_M_B 0x01000000 /* before; after if not set */ -# define ARM_M_U 0x00200000 /* update Rn */ -# define THUMB2_LDM_W 0x00200000 -# define THUMB2_LDM_P 0x00008000 -# define THUMB2_LDM_M 0x00004000 -# define THUMB_LDMIA 0xc800 -# define THUMB2_LDMIA 0xe8900000 -# define THUMB2_LDMB 0xe9100000 -# define THUMB_PUSH 0xb400 -# define THUMB2_PUSH 0xe92d0000 -# define THUMB_POP 0xbc00 -# define THUMB2_POP 0xe8bd0000 -# define ii(i) *_jit->pc.ui++ = i -# define is(i) *_jit->pc.us++ = i -# if __BYTE_ORDER == __LITTLE_ENDIAN -# define iss(i, j) do { is(j); is(i); } while (0) -# define code2thumb(t0, t1, c0, c1) do { t1 = c0; t0 = c1; } while (0) -# define thumb2code(t0, t1, c0, c1) do { c0 = t1; c1 = t0; } while (0) -# else -# define iss(i, j) do { is(i); is(j); } while (0) -# define code2thumb(t0, t1, c0, c1) do { t0 = c0; t1 = c1; } while (0) -# define thumb2code(t0, t1, c0, c1) do { c0 = t0; c1 = t1; } while (0) -# endif -static int encode_arm_immediate(unsigned int v); -static int encode_thumb_immediate(unsigned int v); -static int encode_thumb_word_immediate(unsigned int v); -static int encode_thumb_jump(int v); -static int encode_thumb_cc_jump(int v); -static int encode_thumb_shift(int v, int type) maybe_unused; -# define corrr(cc,o,rn,rd,rm) _corrr(_jit,cc,o,rn,rd,rm) -static void _corrr(jit_state_t*,int,int,int,int,int); -# define corri(cc,o,rn,rd,im) _corri(_jit,cc,o,rn,rd,im) -static void _corri(jit_state_t*,int,int,int,int,int); -#define corri8(cc,o,rn,rt,im) _corri8(_jit,cc,o,rn,rt,im) -static void _corri8(jit_state_t*,int,int,int,int,int); -# define torrr(o,rn,rd,rm) _torrr(_jit,o,rn,rd,rm) -static void _torrr(jit_state_t*,int,int,int,int); -# define torrrs(o,rn,rd,rm,im) _torrrs(_jit,o,rn,rd,rm,im) -static void _torrrs(jit_state_t*,int,int,int,int,int) maybe_unused; -# define torxr(o,rn,rt,rm) _torxr(_jit,o,rn,rt,rm) -static void _torxr(jit_state_t*,int,int,int,int); -# define torrrr(o,rn,rl,rh,rm) _torrrr(_jit,o,rn,rl,rh,rm) -static void _torrrr(jit_state_t*,int,int,int,int,int) maybe_unused; -# define torrri8(o,rn,rt,rt2,im) _torrri8(_jit,o,rn,rt,rt2,im) -static void _torrri8(jit_state_t*,int,int,int,int,int) maybe_unused; -# define coriw(cc,o,rd,im) _coriw(_jit,cc,o,rd,im) -static void _coriw(jit_state_t*,int,int,int,int); -# define torri(o,rd,rn,im) _torri(_jit,o,rd,rn,im) -static void _torri(jit_state_t*,int,int,int,int); -# define torri8(o,rn,rt,im) _torri8(_jit,o,rn,rt,im) -static void _torri8(jit_state_t*,int,int,int,int); -# define torri12(o,rn,rt,im) _torri12(_jit,o,rn,rt,im) -static void _torri12(jit_state_t*,int,int,int,int); -# define tshift(o,rd,rm,im) _tshift(_jit,o,rd,rm,im) -static void _tshift(jit_state_t*,int,int,int,int); -# define toriw(o,rd,im) _toriw(_jit,o,rd,im) -static void _toriw(jit_state_t*,int,int,int); -# define tc8(cc,im) _tc8(_jit,cc,im) -static void _tc8(jit_state_t*,int,int) maybe_unused; -# define t11(im) _t11(_jit,im) -static void _t11(jit_state_t*,int); -# define tcb(cc,im) _tcb(_jit,cc,im) -static void _tcb(jit_state_t*,int,int); -# define blxi(im) _blxi(_jit,im) -static void _blxi(jit_state_t*,int) maybe_unused; -# define tb(o,im) _tb(_jit,o,im) -static void _tb(jit_state_t*,int,int); -# define corrrr(cc,o,rh,rl,rm,rn) _corrrr(_jit,cc,o,rh,rl,rm,rn) -static void _corrrr(jit_state_t*,int,int,int,int,int,int); -# define corrrs(cc,o,rn,rd,rm,im) _corrrs(_jit,cc,o,rn,rd,rm,im) -static void _corrrs(jit_state_t*,int,int,int,int,int,int); -# define cshift(cc,o,rd,rm,rn,im) _cshift(_jit,cc,o,rd,rm,rn,im) -static void _cshift(jit_state_t*,int,int,int,int,int,int); -# define cb(cc,o,im) _cb(_jit,cc,o,im) -static void _cb(jit_state_t*,int,int,int); -# define cbx(cc,o,rm) _cbx(_jit,cc,o,rm) -static void _cbx(jit_state_t*,int,int,int); -# define corl(cc,o,r0,i0) _corl(_jit,cc,o,r0,i0) -static void _corl(jit_state_t*,int,int,int,int); -# define c6orr(cc,o,r0,r1) _c6orr(_jit,cc,o,r0,r1) -static void _c6orr(jit_state_t*,int,int,int,int); -# define tcit(cc,it) _tcit(_jit,cc,it) -static void _tcit(jit_state_t*,unsigned int,int); -# define IT(cc) tcit(cc,THUMB2_IT) -# define ITT(cc) tcit(cc,THUMB2_ITT) -# define ITE(cc) tcit(cc,THUMB2_ITE) -# define ITTT(cc) tcit(cc,THUMB2_ITTT) -# define ITTE(cc) tcit(cc,THUMB2_ITTE) -# define ITET(cc) tcit(cc,THUMB2_ITET) -# define ITEE(cc) tcit(cc,THUMB2_ITEE) -# define ITTTT(cc) tcit(cc,THUMB2_ITTTT) -# define ITETT(cc) tcit(cc,THUMB2_ITETT) -# define ITTET(cc) tcit(cc,THUMB2_ITTET) -# define ITEET(cc) tcit(cc,THUMB2_ITEET) -# define ITTTE(cc) tcit(cc,THUMB2_ITTTE) -# define ITETE(cc) tcit(cc,THUMB2_ITETE) -# define ITTEE(cc) tcit(cc,THUMB2_ITTEE) -# define ITEEE(cc) tcit(cc,THUMB2_ITEEE) -# define tpp(o,im) _tpp(_jit,o,im) -static void _tpp(jit_state_t*,int,int); -# define torl(o,rn,im) _torl(_jit,o,rn,im) -static void _torl(jit_state_t*,int,int,int) maybe_unused; -# define CC_MOV(cc,rd,rm) corrr(cc,ARM_MOV,0,rd,rm) -# define MOV(rd,rm) CC_MOV(ARM_CC_AL,rd,rm) -# define T1_MOV(rd,rm) is(THUMB_MOV|((_u4(rd)&8)<<4)|(_u4(rm)<<3)|(rd&7)) -# define T2_MOV(rd,rm) T2_ORR(rd,_R15_REGNO,rm) -# define CC_MOVI(cc,rd,im) corri(cc,ARM_MOV|ARM_I,0,rd,im) -# define MOVI(rd,im) CC_MOVI(ARM_CC_AL,rd,im) -# define CC_MOVWI(cc,rd,im) coriw(cc,ARM_MOVWI,rd,im) -# define MOVWI(rd,im) CC_MOVWI(ARM_CC_AL,rd,im) -# define T1_MOVI(rd,im) is(THUMB_MOVI|(_u3(rd)<<8)|_u8(im)) -# define T2_MOVI(rd,im) torri(THUMB2_MOVI,_R15_REGNO,rd,im) -# define T2_MOVWI(rd,im) toriw(THUMB2_MOVWI,rd,im) -# define CC_MOVTI(cc,rd,im) coriw(cc,ARM_MOVTI,rd,im) -# define MOVTI(rd,im) CC_MOVTI(ARM_CC_AL,rd,im) -# define T2_MOVTI(rd,im) toriw(THUMB2_MOVTI,rd,im) -# define CC_MVN(cc,rd,rm) corrr(cc,ARM_MVN,0,rd,rm) -# define MVN(rd,rm) CC_MVN(ARM_CC_AL,rd,rm) -# define T1_MVN(rd,rm) is(THUMB_MVN|(_u3(rm)<<3)|_u3(rd)) -# define T2_MVN(rd,rm) torrr(THUMB2_MVN,_R15_REGNO,rd,rm) -# define CC_MVNI(cc,rd,im) corri(cc,ARM_MVN|ARM_I,0,rd,im) -# define MVNI(rd,im) CC_MVNI(ARM_CC_AL,rd,im) -# define T2_MVNI(rd,im) torri(THUMB2_MVNI,_R15_REGNO,rd,im) -# define CC_NOT(cc,rd,rm) CC_MVN(cc,rd,rm) -# define NOT(rd,rm) CC_NOT(ARM_CC_AL,rd,rm) -# define T1_NOT(rd,rm) T1_MVN(rd,rm) -# define T2_NOT(rd,rm) T2_MVN(rd,rm) -# define NOP() MOV(_R0_REGNO, _R0_REGNO) -# define T1_NOP() is(0xbf00) -# define CC_ADD(cc,rd,rn,rm) corrr(cc,ARM_ADD,rn,rd,rm) -# define ADD(rd,rn,rm) CC_ADD(ARM_CC_AL,rd,rn,rm) -# define T1_ADD(rd,rn,rm) is(THUMB_ADD|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rd)) -# define T1_ADDX(rdn,rm) is(THUMB_ADDX|((_u4(rdn)&8)<<4)|(_u4(rm)<<3)|(rdn&7)) -# define T2_ADD(rd,rn,rm) torrr(THUMB2_ADD,rn,rd,rm) -# define CC_ADDI(cc,rd,rn,im) corri(cc,ARM_ADD|ARM_I,rn,rd,im) -# define ADDI(rd,rn,im) CC_ADDI(ARM_CC_AL,rd,rn,im) -# define T1_ADDI3(rd,rn,im) is(THUMB_ADDI3|(_u3(im)<<6)|(_u3(rn)<<3)|_u3(rd)) -# define T1_ADDI8(rdn,im) is(THUMB_ADDI8|(_u3(rdn)<<8)|_u8(im)) -# define T2_ADDI(rd,rn,im) torri(THUMB2_ADDI,rn,rd,im) -# define T2_ADDWI(rd,rn,im) torri(THUMB2_ADDWI,rn,rd,im) -# define CC_ADDS(cc,rd,rn,rm) corrr(cc,ARM_ADD|ARM_S,rn,rd,rm) -# define ADDS(rd,rn,rm) CC_ADDS(ARM_CC_AL,rd,rn,rm) -# define T2_ADDS(rd,rn,rm) torrr(THUMB2_ADD|ARM_S,rn,rd,rm) -# define ADDSI(rd,rn,im) corri(ARM_CC_AL,ARM_ADD|ARM_S|ARM_I,rn,rd,im) -# define T2_ADDSI(rd,rn,im) torri(THUMB2_ADDI|ARM_S,rn,rd,im) -# define CC_ADC(cc,rd,rn,rm) corrr(cc,ARM_ADC,rn,rd,rm) -# define ADC(rd,rn,rm) CC_ADC(ARM_CC_AL,rd,rn,rm) -# define T1_ADC(rdn,rm) is(THUMB_ADC|(_u3(rm)<<3)|_u3(rdn)) -# define T2_ADC(rd,rn,rm) torrr(THUMB2_ADC,rn,rd,rm) -# define CC_ADCI(cc,rd,rn,im) corri(cc,ARM_ADC|ARM_I,rn,rd,im) -# define ADCI(rd,rn,im) CC_ADCI(ARM_CC_AL,rd,rn,im) -# define T2_ADCI(rd,rn,im) torri(THUMB2_ADCI,rn,rd,im) -# define CC_ADCS(cc,rd,rn,rm) corrr(cc,ARM_ADC|ARM_S,rn,rd,rm) -# define ADCS(rd,rn,rm) CC_ADCS(ARM_CC_AL,rd,rn,rm) -# define T2_ADCS(rd,rn,rm) torrr(THUMB2_ADC|ARM_S,rn,rd,rm) -# define CC_ADCSI(cc,rd,rn,im) corri(cc,ARM_ADC|ARM_S|ARM_I,rn,rd,im) -# define ADCSI(rd,rn,im) CC_ADCSI(ARM_CC_AL,rd,rn,im) -# define T2_ADCSI(rd,rn,im) torri(THUMB2_ADCI|ARM_S,rn,rd,im) -# define CC_SUB(cc,rd,rn,rm) corrr(cc,ARM_SUB,rn,rd,rm) -# define SUB(rd,rn,rm) CC_SUB(ARM_CC_AL,rd,rn,rm) -# define T1_SUB(rd,rn,rm) is(THUMB_SUB|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rd)) -# define T2_SUB(rd,rn,rm) torrr(THUMB2_SUB,rn,rd,rm) -# define CC_SUBI(cc,rd,rn,im) corri(cc,ARM_SUB|ARM_I,rn,rd,im) -# define SUBI(rd,rn,im) CC_SUBI(ARM_CC_AL,rd,rn,im) -# define T1_SUBI3(rd,rn,im) is(THUMB_SUBI3|(_u3(im)<<6)|(_u3(rn)<<3)|_u3(rd)) -# define T1_SUBI8(rdn,im) is(THUMB_SUBI8|(_u3(rdn)<<8)|_u8(im)) -# define T2_SUBI(rd,rn,im) torri(THUMB2_SUBI,rn,rd,im) -# define T2_SUBWI(rd,rn,im) torri(THUMB2_SUBWI,rn,rd,im) -# define CC_SUBS(cc,rd,rn,rm) corrr(cc,ARM_SUB|ARM_S,rn,rd,rm) -# define SUBS(rd,rn,rm) CC_SUBS(ARM_CC_AL,rd,rn,rm) -# define T2_SUBS(rd,rn,rm) torrr(THUMB2_SUB|ARM_S,rn,rd,rm) -# define CC_SUBSI(cc,rd,rn,im) corri(cc,ARM_SUB|ARM_S|ARM_I,rn,rd,im) -# define SUBSI(rd,rn,im) CC_SUBSI(ARM_CC_AL,rd,rn,im) -# define T2_SUBSI(rd,rn,im) torri(THUMB2_SUBI|ARM_S,rn,rd,im) -# define CC_SBC(cc,rd,rn,rm) corrr(cc,ARM_SBC,rn,rd,rm) -# define SBC(rd,rn,rm) CC_SBC(ARM_CC_AL,rd,rn,rm) -# define T1_SBC(rdn,rm) is(THUMB_SBC|(_u3(rm)<<3)|_u3(rdn)) -# define T2_SBC(rd,rn,rm) torrr(THUMB2_SBC,rn,rd,rm) -# define CC_SBCI(cc,rd,rn,im) corri(cc,ARM_SBC|ARM_I,rn,rd,im) -# define SBCI(rd,rn,im) CC_SBCI(ARM_CC_AL,rd,rn,im) -# define T2_SBCI(rd,rn,im) torri(THUMB2_SBCI,rn,rd,im) -# define CC_SBCS(cc,rd,rn,rm) corrr(cc,ARM_SBC|ARM_S,rn,rd,rm) -# define SBCS(rd,rn,rm) CC_SBCS(ARM_CC_AL,rd,rn,rm) -# define T2_SBCS(rd,rn,rm) torrr(THUMB2_SBC|ARM_S,rn,rd,rm) -# define CC_SBCSI(cc,rd,rn,im) corri(cc,ARM_SBC|ARM_S|ARM_I,rn,rd,im) -# define SBCSI(rd,rn,im) CC_SBCSI(ARM_CC_AL,rd,rn,im) -# define T2_SBCSI(rd,rn,im) torri(THUMB2_SBCI|ARM_S,rn,rd,im) -# define CC_RSB(cc,rd,rn,rm) corrr(cc,ARM_RSB,rn,rd,rm) -# define RSB(rd,rn,rm) CC_RSB(ARM_CC_AL,rd,rn,rm) -# define T2_RSB(rd,rn,rm) torrr(THUMB2_RSB,rn,rd,rm) -# define CC_RSBI(cc,rd,rn,im) corri(cc,ARM_RSB|ARM_I,rn,rd,im) -# define RSBI(rd,rn,im) CC_RSBI(ARM_CC_AL,rd,rn,im) -# define T1_RSBI(rd,rn) is(THUMB_RSBI|(_u3(rn)<<3)|_u3(rd)) -# define T2_RSBI(rd,rn,im) torri(THUMB2_RSBI,rn,rd,im) -# define CC_MUL(cc,rl,rn,rm) corrrr(cc,ARM_MUL,rl,0,rm,rn) -# define MUL(rl,rn,rm) CC_MUL(ARM_CC_AL,rl,rn,rm) -# define T1_MUL(rdm,rn) is(THUMB_MUL|(_u3(rn)<<3)|_u3(rdm)) -# define T2_MUL(rd,rn,rm) torrr(THUMB2_MUL,rn,rd,rm) -# define CC_SMULL(cc,rl,rh,rn,rm) corrrr(cc,ARM_SMULL,rh,rl,rm,rn) -# define SMULL(rl,rh,rn,rm) CC_SMULL(ARM_CC_AL,rl,rh,rn,rm) -# define T2_SMULL(rl,rh,rn,rm) torrrr(THUMB2_SMULL,rn,rl,rh,rm) -# define CC_UMULL(cc,rl,rh,rn,rm) corrrr(cc,ARM_UMULL,rh,rl,rm,rn) -# define UMULL(rl,rh,rn,rm) CC_UMULL(ARM_CC_AL,rl,rh,rn,rm) -# define T2_UMULL(rl,rh,rn,rm) torrrr(THUMB2_UMULL,rn,rl,rh,rm) -# define T2_SDIV(rd,rn,rm) torrr(THUMB2_SDIV,rn,rd,rm) -# define T2_UDIV(rd,rn,rm) torrr(THUMB2_UDIV,rn,rd,rm) -# define CC_AND(cc,rd,rn,rm) corrr(cc,ARM_AND,rn,rd,rm) -# define AND(rd,rn,rm) CC_AND(ARM_CC_AL,rd,rn,rm) -# define T1_AND(rdn,rm) is(THUMB_AND|(_u3(rm)<<3)|_u3(rdn)) -# define T2_AND(rd,rn,rm) torrr(THUMB2_AND,rn,rd,rm) -# define CC_ANDI(cc,rd,rn,im) corri(cc,ARM_AND|ARM_I,rn,rd,im) -# define ANDI(rd,rn,im) CC_ANDI(ARM_CC_AL,rd,rn,im) -# define T2_ANDI(rd,rn,im) torri(THUMB2_ANDI,rn,rd,im) -# define CC_ANDS(cc,rd,rn,rm) corrr(cc,ARM_AND|ARM_S,rn,rd,rm) -# define ANDS(rd,rn,rm) CC_ANDS(ARM_CC_AL,rd,rn,rm) -# define T2_ANDS(rd,rn,rm) torrr(THUMB2_AND|ARM_S,rn,rd,rm) -# define CC_ANDSI(cc,rd,rn,im) corri(cc,ARM_AND|ARM_S|ARM_I,rn,rd,im) -# define ANDSI(rd,rn,im) CC_ANDSI(ARM_CC_AL,rd,rn,im) -# define T2_ANDSI(rd,rn,im) torri(ARM_CC_AL,THUMB2_ANDI|ARM_S,rn,rd,im) -# define CC_BIC(cc,rd,rn,rm) corrr(cc,ARM_BIC,rn,rd,rm) -# define BIC(rd,rn,rm) CC_BIC(ARM_CC_AL,rd,rn,rm) -# define T2_BIC(rd,rn,rm) torrr(THUMB2_BIC,rn,rd,rm) -# define CC_BICI(cc,rd,rn,im) corri(cc,ARM_BIC|ARM_I,rn,rd,im) -# define BICI(rd,rn,im) CC_BICI(ARM_CC_AL,rd,rn,im) -# define T2_BICI(rd,rn,im) torri(THUMB2_BICI,rn,rd,im) -# define CC_BICS(cc,rd,rn,rm) corrr(cc,ARM_BIC|ARM_S,rn,rd,rm) -# define BICS(rd,rn,rm) CC_BICS(ARM_CC_AL,rd,rn,rm) -# define T2_BICS(rd,rn,rm) torrr(THUMB2_BIC|ARM_S,rn,rd,rm) -# define CC_BICSI(cc,rd,rn,im) corri(cc,ARM_BIC|ARM_S|ARM_I,rn,rd,im) -# define BICSI(rd,rn,im) CC_BICSI(ARM_CC_AL,rd,rn,im) -# define T2_BICSI(rd,rn,im) torri(ARM_CC_AL,THUMB2_BICI|ARM_S,rn,rd,im) -# define CC_ORR(cc,rd,rn,rm) corrr(cc,ARM_ORR,rn,rd,rm) -# define ORR(rd,rn,rm) CC_ORR(ARM_CC_AL,rd,rn,rm) -# define T1_ORR(rdn,rm) is(THUMB_ORR|(_u3(rm)<<3)|_u3(rdn)) -# define T2_ORR(rd,rn,rm) torrr(THUMB2_ORR,rn,rd,rm) -# define CC_ORR_SI(cc,rd,rn,rt,sh,im) corrrs(cc,ARM_ORR|sh,rn,rd,rm,im) -# define ORR_SI(r0,r1,r2,sh,im) CC_ORR_SI(ARM_CC_AL,r0,r1,r2,sh,im) -# define CC_ORRI(cc,rd,rn,im) corri(cc,ARM_ORR|ARM_I,rn,rd,im) -# define ORRI(rd,rn,im) CC_ORRI(ARM_CC_AL,rd,rn,im) -# define T2_ORRI(rd,rn,im) torri(THUMB2_ORRI,rn,rd,im) -# define CC_EOR(cc,rd,rn,rm) corrr(cc,ARM_EOR,rn,rd,rm) -# define EOR(rd,rn,rm) CC_EOR(ARM_CC_AL,rd,rn,rm) -# define T1_EOR(rdn,rm) is(THUMB_EOR|(_u3(rm)<<3)|_u3(rdn)) -# define T2_EOR(rd,rn,rm) torrr(THUMB2_EOR,rn,rd,rm) -# define CC_EOR_SI(cc,rd,rn,rm,sh,im) corrrs(cc,ARM_EOR|sh,rn,rd,rm,im) -# define EOR_SI(r0,r1,r2,sh,im) CC_EOR_SI(ARM_CC_AL,r0,r1,r2,sh,im) -# define CC_EORI(cc,rd,rn,im) corri(cc,ARM_EOR|ARM_I,rn,rd,im) -# define EORI(rd,rn,im) CC_EORI(ARM_CC_AL,rd,rn,im) -# define T2_EORI(rd,rn,im) torri(THUMB2_EORI,rn,rd,im) -# define CC_REV(cc,rd,rm) c6orr(cc,ARM_REV,rd,rm) -# define REV(rd,rm) CC_REV(ARM_CC_AL,rd,rm) -# define T1_REV(rd,rm) is(THUMB_REV|(_u3(rm)<<3)|_u3(rd)) -# define T2_REV(rd,rm) torrr(THUMB2_REV,rm,rd,rm) -# define CC_REV16(cc,rd,rm) c6orr(cc,ARM_REV16,rd,rm) -# define REV16(rd,rm) CC_REV16(ARM_CC_AL,rd,rm) -# define T1_REV16(rd,rm) is(THUMB_REV16|(_u3(rm)<<3)|_u3(rd)) -# define T2_REV16(rd,rm) torrr(THUMB2_REV16,rm,rd,rm) -# define CC_SXTB(cc,rd,rm) c6orr(cc,ARM_SXTB,rd,rm) -# define SXTB(rd,rm) CC_SXTB(ARM_CC_AL,rd,rm) -# define T1_SXTB(rd,rm) is(THUMB_SXTB|(_u3(rm)<<3)|_u3(rd)) -# define T2_SXTB(rd,rm) torrr(THUMB2_SXTB,_R15_REGNO,rd,rm) -# define CC_UXTB(cc,rd,rm) c6orr(cc,ARM_UXTB,rd,rm) -# define UXTB(rd,rm) CC_UXTB(ARM_CC_AL,rd,rm) -# define T1_UXTB(rd,rm) is(THUMB_UXTB|(_u3(rm)<<3)|_u3(rd)) -# define T2_UXTB(rd,rm) torrr(THUMB2_UXTB,_R15_REGNO,rd,rm) -# define CC_SXTH(cc,rd,rm) c6orr(cc,ARM_SXTH,rd,rm) -# define SXTH(rd,rm) CC_SXTH(ARM_CC_AL,rd,rm) -# define T1_SXTH(rd,rm) is(THUMB_SXTH|(_u3(rm)<<3)|_u3(rd)) -# define T2_SXTH(rd,rm) torrr(THUMB2_SXTH,_R15_REGNO,rd,rm) -# define CC_UXTH(cc,rd,rm) c6orr(cc,ARM_UXTH,rd,rm) -# define UXTH(rd,rm) CC_UXTH(ARM_CC_AL,rd,rm) -# define T1_UXTH(rd,rm) is(THUMB_UXTH|(_u3(rm)<<3)|_u3(rd)) -# define T2_UXTH(rd,rm) torrr(THUMB2_UXTH,_R15_REGNO,rd,rm) -# define CC_SHIFT(cc,o,rd,rm,rn,im) cshift(cc,o,rd,rm,rn,im) -# define CC_LSL(cc,rd,rn,rm) CC_SHIFT(cc,ARM_LSL|ARM_R,rd,rm,rn,0) -# define LSL(rd,rn,rm) CC_LSL(ARM_CC_AL,rd,rn,rm) -# define T1_LSL(rdn,rm) is(THUMB_LSL|(_u3(rm)<<3)|_u3(rdn)) -# define T2_LSL(rd,rn,rm) torrr(THUMB2_LSL,rn,rd,rm) -# define CC_LSLI(cc,rd,rn,im) CC_SHIFT(cc,ARM_LSL,rd,0,rn,im) -# define LSLI(rd,rn,im) CC_LSLI(ARM_CC_AL,rd,rn,im) -# define T1_LSLI(rd,rm,im) is(THUMB_LSLI|(_u5(im)<<6)|(_u3(rm)<<3)|_u3(rd)) -# define T2_LSLI(rd,rm,im) tshift(THUMB2_LSLI,rd,rm,im) -# define CC_LSR(cc,rd,rn,rm) CC_SHIFT(cc,ARM_LSR|ARM_R,rd,rm,rn,0) -# define LSR(rd,rn,rm) CC_LSR(ARM_CC_AL,rd,rn,rm) -# define T1_LSR(rdn,rm) is(THUMB_LSR|(_u3(rm)<<3)|_u3(rdn)) -# define T2_LSR(rd,rn,rm) torrr(THUMB2_LSR,rn,rd,rm) -# define CC_LSRI(cc,rd,rn,im) CC_SHIFT(cc,ARM_LSR,rd,0,rn,im) -# define LSRI(rd,rn,im) CC_LSRI(ARM_CC_AL,rd,rn,im) -# define T1_LSRI(rd,rm,im) is(THUMB_LSRI|(_u5(im)<<6)|(_u3(rm)<<3)|_u3(rd)) -# define T2_LSRI(rd,rm,im) tshift(THUMB2_LSRI,rd,rm,im) -# define CC_ASR(cc,rd,rn,rm) CC_SHIFT(cc,ARM_ASR|ARM_R,rd,rm,rn,0) -# define ASR(rd,rn,rm) CC_ASR(ARM_CC_AL,rd,rn,rm) -# define T1_ASR(rdn,rm) is(THUMB_ASR|(_u3(rm)<<3)|_u3(rdn)) -# define T2_ASR(rd,rn,rm) torrr(THUMB2_ASR,rn,rd,rm) -# define CC_ASRI(cc,rd,rn,im) CC_SHIFT(cc,ARM_ASR,rd,0,rn,im) -# define ASRI(rd,rn,im) CC_ASRI(ARM_CC_AL,rd,rn,im) -# define T1_ASRI(rd,rm,im) is(THUMB_ASRI|(_u5(im)<<6)|(_u3(rm)<<3)|_u3(rd)) -# define T2_ASRI(rd,rm,im) tshift(THUMB2_ASRI,rd,rm,im) -# define CC_CMP(cc,rn,rm) corrr(cc,ARM_CMP,rn,0,rm) -# define CMP(rn,rm) CC_CMP(ARM_CC_AL,rn,rm) -# define T1_CMP(rn,rm) is(THUMB_CMP|(_u3(rm)<<3)|_u3(rn)) -# define T1_CMPX(rn,rm) is(THUMB_CMPX|((_u4(rn)&8)<<4)|(_u4(rm)<<3)|(rn&7)) -# define T2_CMP(rn,rm) torrr(THUMB2_CMP,rn,_R15_REGNO,rm) -# define CC_CMPI(cc,rn,im) corri(cc,ARM_CMP|ARM_I,rn,0,im) -# define CMPI(rn,im) CC_CMPI(ARM_CC_AL,rn,im) -# define T1_CMPI(rn,im) is(THUMB_CMPI|(_u3(rn)<<8)|_u8(im)) -# define T2_CMPI(rn,im) torri(THUMB2_CMPI,rn,_R15_REGNO,im) -# define CC_CMN(cc,rn,rm) corrr(cc,ARM_CMN,rn,0,rm) -# define CMN(rn,rm) CC_CMN(ARM_CC_AL,rn,rm) -# define T1_CMN(rn,rm) is(THUMB_CMN|(_u3(rm)<<3)|_u3(rm)) -# define T2_CMN(rn,rm) torrr(THUMB2_CMN,rn,_R15_REGNO,rm) -# define CC_CMNI(cc,rn,im) corri(cc,ARM_CMN|ARM_I,rn,0,im) -# define CMNI(rn,im) CC_CMNI(ARM_CC_AL,rn,im) -# define T2_CMNI(rn,im) torri(THUMB2_CMNI,rn,_R15_REGNO,im) -# define CC_TST(cc,rn,rm) corrr(cc,ARM_TST,rn,r0,rm) -# define TST(rn,rm) CC_TST(ARM_CC_AL,rn,rm) -# define T1_TST(rn,rm) is(THUMB_TST|(_u3(rm)<<3)|_u3(rn)) -# define T2_TST(rn,rm) torrr(THUMB2_TST,rn,_R15_REGNO,rm) -# define CC_TSTI(cc,rn,im) corri(cc,ARM_TST|ARM_I,rn,0,im) -# define TSTI(rn,im) CC_TSTI(ARM_CC_AL,rn,im) -# define T2_TSTI(rn,im) torri(THUMB2_TSTI,rn,_R15_REGNO,im) -# define CC_TEQ(cc,rn,rm) corrr(cc,ARM_TEQ,rn,0,rm) -# define TEQ(rn,rm) CC_TEQ(ARM_CC_AL,rn,rm) -# define CC_TEQI(cc,rm,im) corri(cc,ARM_TEQ|ARM_I,rn,0,im) -# define TEQI(rn,im) CC_TEQI(ARM_CC_AL,rn,im) -# define CC_BX(cc,rm) cbx(cc,ARM_BX,rm) -# define BX(rm) CC_BX(ARM_CC_AL,rm) -# define T1_BX(rm) is(0x4700|(_u4(rm)<<3)) -# define CC_BLX(cc,rm) cbx(cc,ARM_BLX,rm) -# define BLX(rm) CC_BLX(ARM_CC_AL,rm) -# define T1_BLX(rm) is(THUMB_BLX|(_u4(rm)<<3)) -# define BLXI(im) blxi(im) -# define T2_BLXI(im) tb(THUMB2_BLXI,im) -# define CC_B(cc,im) cb(cc,ARM_B,im) -# define B(im) CC_B(ARM_CC_AL,im) -# define T1_CC_B(cc,im) tc8(cc,im) -# define T1_B(im) t11(im) -# define T2_CC_B(cc,im) tcb(cc,im) -# define T2_B(im) tb(THUMB2_B,im) -# define CC_BLI(cc,im) cb(cc,ARM_BLI,im) -# define BLI(im) CC_BLI(ARM_CC_AL,im) -# define T2_BLI(im) tb(THUMB2_BLI,im) -# define CC_LDRSB(cc,rt,rn,rm) corrr(cc,ARM_LDRSB|ARM_P,rn,rt,rm) -# define LDRSB(rt,rn,rm) CC_LDRSB(ARM_CC_AL,rt,rn,rm) -# define T1_LDRSB(rt,rn,rm) is(THUMB_LDRSB|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt)) -# define T2_LDRSB(rt,rn,rm) torxr(THUMB2_LDRSB,rn,rt,rm) -# define CC_LDRSBN(cc,rt,rn,rm) corrr(cc,ARM_LDRSB,rn,rt,rm) -# define LDRSBN(rt,rn,rm) CC_LDRSBN(ARM_CC_AL,rt,rn,rm) -# define CC_LDRSBI(cc,rt,rn,im) corri8(cc,ARM_LDRSBI|ARM_P,rn,rt,im) -# define LDRSBI(rt,rn,im) CC_LDRSBI(ARM_CC_AL,rt,rn,im) -# define T2_LDRSBI(rt,rn,im) torri8(THUMB2_LDRSBI|THUMB2_U,rn,rt,im) -# define T2_LDRSBWI(rt,rn,im) torri12(THUMB2_LDRSBWI,rn,rt,im) -# define CC_LDRSBIN(cc,rt,rn,im) corri8(cc,ARM_LDRSBI,rn,rt,im) -# define LDRSBIN(rt,rn,im) CC_LDRSBIN(ARM_CC_AL,rt,rn,im) -# define T2_LDRSBIN(rt,rn,im) torri8(THUMB2_LDRSBI,rn,rt,im) -# define CC_LDRB(cc,rt,rn,rm) corrr(cc,ARM_LDRB|ARM_P,rn,rt,rm) -# define LDRB(rt,rn,rm) CC_LDRB(ARM_CC_AL,rt,rn,rm) -# define T1_LDRB(rt,rn,rm) is(THUMB_LDRB|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt)) -# define T2_LDRB(rt,rn,rm) torxr(THUMB2_LDRB,rn,rt,rm) -# define CC_LDRBN(cc,rt,rn,rm) corrr(cc,ARM_LDRB,rn,rt,rm) -# define LDRBN(rt,rn,rm) CC_LDRBN(ARM_CC_AL,rt,rn,rm) -# define CC_LDRBI(cc,rt,rn,im) corri(cc,ARM_LDRBI|ARM_P,rn,rt,im) -# define LDRBI(rt,rn,im) CC_LDRBI(ARM_CC_AL,rt,rn,im) -# define T1_LDRBI(rt,rn,im) is(THUMB_LDRBI|(_u5(im)<<6)|(_u3(rn)<<3)|_u3(rt)) -# define T2_LDRBI(rt,rn,im) torri8(THUMB2_LDRBI|THUMB2_U,rn,rt,im) -# define T2_LDRBWI(rt,rn,im) torri12(THUMB2_LDRBWI,rn,rt,im) -# define CC_LDRBIN(cc,rt,rn,im) corri(cc,ARM_LDRBI,rn,rt,im) -# define LDRBIN(rt,rn,im) CC_LDRBIN(ARM_CC_AL,rt,rn,im) -# define T2_LDRBIN(rt,rn,im) torri8(THUMB2_LDRBI,rn,rt,im) -# define CC_LDRSH(cc,rt,rn,rm) corrr(cc,ARM_LDRSH|ARM_P,rn,rt,rm) -# define LDRSH(rt,rn,rm) CC_LDRSH(ARM_CC_AL,rt,rn,rm) -# define T1_LDRSH(rt,rn,rm) is(THUMB_LDRSH|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt)) -# define T2_LDRSH(rt,rn,rm) torxr(THUMB2_LDRSH,rn,rt,rm) -# define CC_LDRSHN(cc,rt,rn,rm) corrr(cc,ARM_LDRSH,rn,rt,rm) -# define LDRSHN(rt,rn,rm) CC_LDRSHN(ARM_CC_AL,rt,rn,rm) -# define CC_LDRSHI(cc,rt,rn,im) corri8(cc,ARM_LDRSHI|ARM_P,rn,rt,im) -# define LDRSHI(rt,rn,im) CC_LDRSHI(ARM_CC_AL,rt,rn,im) -# define T2_LDRSHI(rt,rn,im) torri8(THUMB2_LDRSHI|THUMB2_U,rn,rt,im) -# define T2_LDRSHWI(rt,rn,im) torri12(THUMB2_LDRSHWI,rn,rt,im) -# define CC_LDRSHIN(cc,rt,rn,im) corri8(cc,ARM_LDRSHI,rn,rt,im) -# define LDRSHIN(rt,rn,im) CC_LDRSHIN(ARM_CC_AL,rt,rn,im) -# define T2_LDRSHIN(rt,rn,im) torri8(THUMB2_LDRSHI,rn,rt,im) -# define CC_LDRH(cc,rt,rn,rm) corrr(cc,ARM_LDRH|ARM_P,rn,rt,rm) -# define LDRH(rt,rn,rm) CC_LDRH(ARM_CC_AL,rt,rn,rm) -# define T1_LDRH(rt,rn,rm) is(THUMB_LDRH|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt)) -# define T2_LDRH(rt,rn,rm) torxr(THUMB2_LDRH,rn,rt,rm) -# define CC_LDRHN(cc,rt,rn,rm) corrr(cc,ARM_LDRH,rn,rt,rm) -# define LDRHN(rt,rn,rm) CC_LDRHN(ARM_CC_AL,rt,rn,rm) -# define CC_LDRHI(cc,rt,rn,im) corri8(cc,ARM_LDRHI|ARM_P,rn,rt,im) -# define LDRHI(rt,rn,im) CC_LDRHI(ARM_CC_AL,rt,rn,im) -# define T1_LDRHI(rt,rn,im) is(THUMB_LDRHI|(_u5(im)<<6)|(_u3(rn)<<3)|_u3(rt)) -# define T2_LDRHI(rt,rn,im) torri8(THUMB2_LDRHI|THUMB2_U,rn,rt,im) -# define T2_LDRHWI(rt,rn,im) torri12(THUMB2_LDRHWI,rn,rt,im) -# define CC_LDRHIN(cc,rt,rn,im) corri8(cc,ARM_LDRHI,rn,rt,im) -# define LDRHIN(rt,rn,im) CC_LDRHIN(ARM_CC_AL,rt,rn,im) -# define T2_LDRHIN(rt,rn,im) torri8(THUMB2_LDRHI,rn,rt,im) -# define CC_LDR(cc,rt,rn,rm) corrr(cc,ARM_LDR|ARM_P,rn,rt,rm) -# define LDR(rt,rn,rm) CC_LDR(ARM_CC_AL,rt,rn,rm) -# define T1_LDR(rt,rn,rm) is(THUMB_LDR|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt)) -# define T2_LDR(rt,rn,rm) torxr(THUMB2_LDR,rn,rt,rm) -# define CC_LDRN(cc,rt,rn,rm) corrr(cc,ARM_LDR,rn,rt,rm) -# define LDRN(rt,rn,rm) CC_LDRN(ARM_CC_AL,rt,rn,rm) -# define CC_LDRI(cc,rt,rn,im) corri(cc,ARM_LDRI|ARM_P,rn,rt,im) -# define LDRI(rt,rn,im) CC_LDRI(ARM_CC_AL,rt,rn,im) -# define T1_LDRI(rt,rn,im) is(THUMB_LDRI|(_u5(im)<<6)|(_u3(rn)<<3)|_u3(rt)) -# define T1_LDRISP(rt,im) is(THUMB_LDRISP|(_u3(rt)<<8)|_u8(im)) -# define T2_LDRI(rt,rn,im) torri8(THUMB2_LDRI|THUMB2_U,rn,rt,im) -# define T2_LDRWI(rt,rn,im) torri12(THUMB2_LDRWI,rn,rt,im) -# define CC_LDRIN(cc,rt,rn,im) corri(cc,ARM_LDRI,rn,rt,im) -# define LDRIN(rt,rn,im) CC_LDRIN(ARM_CC_AL,rt,rn,im) -# define T2_LDRIN(rt,rn,im) torri8(THUMB2_LDRI,rn,rt,im) -# define CC_LDRD(cc,rt,rn,rm) corrr(cc,ARM_LDRD|ARM_P,rn,rt,rm) -# define LDRD(rt,rn,rm) CC_LDRD(ARM_CC_AL,rt,rn,rm) -# define T2_LDRDI(rt,rt2,rn,im) torrri8(THUMB2_LDRDI|ARM_P,rn,rt,rt2,im) -# define CC_LDRDN(cc,rt,rn,rm) corrr(cc,ARM_LDRD,rn,rt,rm) -# define LDRDN(rd,rn,rm) CC_LDRDN(ARM_CC_AL,rt,rn,rm) -# define CC_LDRDI(cc,rt,rn,im) corri8(cc,ARM_LDRDI|ARM_P,rn,rt,im) -# define LDRDI(rt,rn,im) CC_LDRDI(ARM_CC_AL,rt,rn,im) -# define CC_LDRDIN(cc,rt,rn,im) corri8(cc,ARM_LDRDI,rn,rt,im) -# define LDRDIN(rt,rn,im) CC_LDRDIN(ARM_CC_AL,rt,rn,im) -# define T2_LDRDIN(rt,rt2,rn,im) torrri8(THUMB2_LDRDI,rn,rt,rt2,im) -# define CC_STRB(cc,rt,rn,rm) corrr(cc,ARM_STRB|ARM_P,rn,rt,rm) -# define STRB(rt,rn,rm) CC_STRB(ARM_CC_AL,rt,rn,rm) -# define T1_STRB(rt,rn,rm) is(THUMB_STRB|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt)) -# define T2_STRB(rt,rn,rm) torxr(THUMB2_STRB,rn,rt,rm) -# define CC_STRBN(cc,rt,rn,rm) corrr(cc,ARM_STRB,rn,rt,rm) -# define STRBN(rt,rn,rm) CC_STRBN(ARM_CC_AL,rt,rn,rm) -# define CC_STRBI(cc,rt,rn,im) corri(cc,ARM_STRBI|ARM_P,rn,rt,im) -# define STRBI(rt,rn,im) CC_STRBI(ARM_CC_AL,rt,rn,im) -# define T1_STRBI(rt,rn,im) is(THUMB_STRBI|(_u5(im)<<6)|(_u3(rn)<<3)|_u3(rt)) -# define T2_STRBI(rt,rn,im) torri8(THUMB2_STRBI|THUMB2_U,rn,rt,im) -# define T2_STRBWI(rt,rn,im) torri12(THUMB2_STRBWI,rn,rt,im) -# define CC_STRBIN(cc,rt,rn,im) corri(cc,ARM_STRBI,rn,rt,im) -# define STRBIN(rt,rn,im) CC_STRBIN(ARM_CC_AL,rt,rn,im) -# define T2_STRBIN(rt,rn,im) torri8(THUMB2_STRBI,rn,rt,im) -# define CC_STRH(cc,rt,rn,rm) corrr(cc,ARM_STRH|ARM_P,rn,rt,rm) -# define STRH(rt,rn,rm) CC_STRH(ARM_CC_AL,rt,rn,rm) -# define T1_STRH(rt,rn,rm) is(THUMB_STRH|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt)) -# define T2_STRH(rt,rn,rm) torxr(THUMB2_STRH,rn,rt,rm) -# define CC_STRHN(cc,rt,rn,rm) corrr(cc,ARM_STRH,rn,rt,rm) -# define STRHN(rt,rn,rm) CC_STRHN(ARM_CC_AL,rt,rn,rm) -# define CC_STRHI(cc,rt,rn,im) corri8(cc,ARM_STRHI|ARM_P,rn,rt,im) -# define STRHI(rt,rn,im) CC_STRHI(ARM_CC_AL,rt,rn,im) -# define T1_STRHI(rt,rn,im) is(THUMB_STRHI|(_u5(im)<<6)|(_u3(rn)<<3)|_u3(rt)) -# define T2_STRHI(rt,rn,im) torri8(THUMB2_STRHI|THUMB2_U,rn,rt,im) -# define T2_STRHWI(rt,rn,im) torri12(THUMB2_STRHWI,rn,rt,im) -# define CC_STRHIN(cc,rt,rn,im) corri8(cc,ARM_STRHI,rn,rt,im) -# define STRHIN(rt,rn,im) CC_STRHIN(ARM_CC_AL,rt,rn,im) -# define T2_STRHIN(rt,rn,im) torri8(THUMB2_STRHI,rn,rt,im) -# define CC_STR(cc,rt,rn,rm) corrr(cc,ARM_STR|ARM_P,rn,rt,rm) -# define STR(rt,rn,rm) CC_STR(ARM_CC_AL,rt,rn,rm) -# define T1_STR(rt,rn,rm) is(THUMB_STR|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt)) -# define T2_STR(rt,rn,rm) torxr(THUMB2_STR,rn,rt,rm) -# define CC_STRN(cc,rt,rn,rm) corrr(cc,ARM_STR,rn,rt,rm) -# define STRN(rt,rn,rm) CC_STRN(ARM_CC_AL,rt,rn,rm) -# define CC_STRI(cc,rt,rn,im) corri(cc,ARM_STRI|ARM_P,rn,rt,im) -# define STRI(rt,rn,im) CC_STRI(ARM_CC_AL,rt,rn,im) -# define T1_STRI(rt,rn,im) is(THUMB_STRI|(_u5(im)<<6)|(_u3(rn)<<3)|_u3(rt)) -# define T1_STRISP(rt,im) is(THUMB_STRISP|(_u3(rt)<<8)|(_u8(im))) -# define T2_STRI(rt,rn,im) torri8(THUMB2_STRI|THUMB2_U,rn,rt,im) -# define T2_STRWI(rt,rn,im) torri12(THUMB2_STRWI,rn,rt,im) -# define CC_STRIN(cc,rt,rn,im) corri(cc,ARM_STRI,rn,rt,im) -# define STRIN(rt,rn,im) CC_STRIN(ARM_CC_AL,rt,rn,im) -# define T2_STRIN(rt,rn,im) torri8(THUMB2_STRI,rn,rt,im) -# define CC_STRD(cc,rt,rn,rm) corrr(cc,ARM_STRD|ARM_P,rn,rt,rm) -# define STRD(rt,rn,rm) CC_STRD(ARM_CC_AL,rt,rn,rm) -# define CC_STRDN(cc,rt,rn,rm) corrr(cc,ARM_STRD,rn,rt,rm) -# define STRDN(rt,rn,rm) CC_STRDN(ARM_CC_AL,rt,rn,rm) -# define CC_STRDI(cc,rt,rn,im) corri8(cc,ARM_STRDI|ARM_P,rn,rt,im) -# define STRDI(rt,rn,im) CC_STRDI(ARM_CC_AL,rt,rn,im) -# define T2_STRDI(rt,rt2,rn,im) torrri8(THUMB2_STRDI|ARM_P,rn,rt,rt2,im) -# define CC_STRDIN(cc,rt,rn,im) corri8(cc,ARM_STRDI,rn,rt,im) -# define STRDIN(rt,rn,im) CC_STRDIN(ARM_CC_AL,rt,rn,im) -# define T2_STRDIN(rt,rt2,rn,im) torrri8(THUMB2_STRDI,rn,rt,rt2,im) -# define CC_LDMIA(cc,rn,im) corl(cc,ARM_M|ARM_M_L|ARM_M_I,rn,im) -# define LDMIA(rn,im) CC_LDMIA(ARM_CC_AL,rn,im) -# define CC_LDM(cc,rn,im) CC_LDMIA(cc,rn,im) -# define LDM(rn,im) LDMIA(rn,im) -# define T1_LDMIA(rn,im) is(THUMB_LDMIA|(_u3(rn)<<8)|im) -# define T2_LDMIA(rn,im) torl(THUMB2_LDMIA,rn,im) -# define CC_LDMIA_U(cc,rn,im) corl(cc,ARM_M|ARM_M_L|ARM_M_I|ARM_M_U,rn,im) -# define LDMIA_U(rn,im) CC_LDMIA_U(ARM_CC_AL,rn,im) -# define LDM_U(r0,i0) LDMIA_U(r0,i0) -# define CC_LDMIB(cc,rn,im) corl(cc,ARM_M|ARM_M_L|ARM_M_I|ARM_M_B,rn,im) -# define LDMIB(rn,im) CC_LDMIB(ARM_CC_AL,rn,im) -# define CC_LDMIB_U(cc,rn,im) corl(cc,ARM_M|ARM_M_L|ARM_M_I|ARM_M_B|ARM_M_U,rn,im) -# define LDMIB_U(rn,im) CC_LDMIB_U(ARM_CC_AL,rn,im) -# define CC_LDMDA(cc,rn,im) corl(cc,ARM_M|ARM_M_L,rn,im) -# define LDMDA(rn,im) CC_LDMDA(ARM_CC_AL,rn,im) -# define CC_LDMDA_U(cc,rn,im) corl(cc,ARM_M|ARM_M_L|ARM_M_U,rn,im) -# define LDMDA_U(rn,im) CC_LDMDA_U(ARM_CC_AL,rn,im) -# define CC_LDMDB(cc,rn,im) corl(cc,ARM_M|ARM_M_L|ARM_M_B,rn,im) -# define LDMDB(rn,im) CC_LDMDB(ARM_CC_AL,rn,im) -# define T2_LDMDB(rn,im) torl(THUMB2_LDMDB,rn,im) -# define CC_LDMDB_U(cc,rn,im) corl(cc,ARM_M|ARM_M_L|ARM_M_B|ARM_M_U,rn,im) -# define LDMDB_U(rn,im) CC_LDMDB_U(ARM_CC_AL,rn,im) -# define CC_STMIA(cc,rn,im) corl(cc,ARM_M|ARM_M_I,rn,im) -# define STMIA(rn,im) CC_STMIA(ARM_CC_AL,rn,im) -# define CC_STM(cc,rn,im) CC_STMIA(cc,rn,im) -# define STM(rn,im) STMIA(rn,im) -# define CC_STMIA_U(cc,rn,im) corl(cc,ARM_M|ARM_M_I|ARM_M_U,rn,im) -# define STMIA_U(rn,im) CC_STMIA_U(ARM_CC_AL,rn,im) -# define CC_STM_U(cc,rn,im) CC_STMIA_U(cc,rn,im) -# define STM_U(rn,im) STMIA_U(rn,im) -# define CC_STMIB(cc,rn,im) corl(cc,ARM_M|ARM_M_I|ARM_M_B,rn,im) -# define STMIB(rn,im) CC_STMIB(ARM_CC_AL,rn,im) -# define CC_STMIB_U(cc,rn,im) corl(cc,ARM_M|ARM_M_I|ARM_M_B|ARM_M_U,rn,im) -# define STMIB_U(rn,im) CC_STMIB_U(ARM_CC_AL,rn,im) -# define CC_STMDA(cc,rn,im) corl(cc,ARM_M,rn,im) -# define STMDA(rn,im) CC_STMDA(ARM_CC_AL,rn,im) -# define CC_STMDA_U(cc,rn,im) corl(cc,ARM_M|ARM_M_U,rn,im) -# define STMDA_U(rn,im) CC_STMDA_U(ARM_CC_AL,rn,im) -# define CC_STMDB(cc,rn,im) corl(cc,ARM_M|ARM_M_B,rn,im) -# define STMDB(rn,im) CC_STMDB(ARM_CC_AL,rn,im) -# define CC_STMDB_U(cc,rn,im) corl(cc,ARM_M|ARM_M_B|ARM_M_U,rn,im) -# define STMDB_U(rn,im) CC_STMDB_U(ARM_CC_AL,rn,im) -# define CC_PUSH(cc,im) CC_STMDB_U(cc,_SP_REGNO,im) -# define PUSH(im) STMDB_U(_SP_REGNO,im) -# define T1_PUSH(im) is(THUMB_PUSH|((im&0x4000)>>6)|(im&0xff)) -# define T2_PUSH(im) tpp(THUMB2_PUSH,im) -# define CC_POP(cc,im) LDMIA_U(cc,_SP_REGNO,im) -# define POP(im) LDMIA_U(_SP_REGNO,im) -# define T1_POP(im) is(THUMB_POP|((im&0x8000)>>7)|(im&0xff)) -# define T2_POP(im) tpp(THUMB2_POP,im) -# define jit_get_reg_args() \ - do { \ - (void)jit_get_reg(_R0|jit_class_named|jit_class_gpr); \ - (void)jit_get_reg(_R1|jit_class_named|jit_class_gpr); \ - (void)jit_get_reg(_R2|jit_class_named|jit_class_gpr); \ - (void)jit_get_reg(_R3|jit_class_named|jit_class_gpr); \ - } while (0) -# define jit_unget_reg_args() \ - do { \ - jit_unget_reg(_R3); \ - jit_unget_reg(_R2); \ - jit_unget_reg(_R1); \ - jit_unget_reg(_R0); \ - } while (0) -# define nop(i0) _nop(_jit,i0) -static void _nop(jit_state_t*,int32_t); -# define movr(r0,r1) _movr(_jit,r0,r1) -static void _movr(jit_state_t*,int32_t,int32_t); -# define movi(r0,i0) _movi(_jit,r0,i0) -static void _movi(jit_state_t*,int32_t,jit_word_t); -# define movi_p(r0,i0) _movi_p(_jit,r0,i0) -static jit_word_t _movi_p(jit_state_t*,int32_t,jit_word_t); -# define comr(r0,r1) _comr(_jit,r0,r1) -static void _comr(jit_state_t*,int32_t,int32_t); -# define negr(r0,r1) _negr(_jit,r0,r1) -static void _negr(jit_state_t*,int32_t,int32_t); -# define addr(r0,r1,r2) _addr(_jit,r0,r1,r2) -static void _addr(jit_state_t*,int32_t,int32_t,int32_t); -# define addi(r0,r1,i0) _addi(_jit,r0,r1,i0) -static void _addi(jit_state_t*,int32_t,int32_t,jit_word_t); -# define addcr(r0,r1,r2) _addcr(_jit,r0,r1,r2) -static void _addcr(jit_state_t*,int32_t,int32_t,int32_t); -# define addci(r0,r1,i0) _addci(_jit,r0,r1,i0) -static void _addci(jit_state_t*,int32_t,int32_t,jit_word_t); -# define addxr(r0,r1,r2) _addxr(_jit,r0,r1,r2) -static void _addxr(jit_state_t*,int32_t,int32_t,int32_t); -# define addxi(r0,r1,i0) _addxi(_jit,r0,r1,i0) -static void _addxi(jit_state_t*,int32_t,int32_t,jit_word_t); -# define subr(r0,r1,r2) _subr(_jit,r0,r1,r2) -static void _subr(jit_state_t*,int32_t,int32_t,int32_t); -# define subi(r0,r1,i0) _subi(_jit,r0,r1,i0) -static void _subi(jit_state_t*,int32_t,int32_t,jit_word_t); -# define subcr(r0,r1,r2) _subcr(_jit,r0,r1,r2) -static void _subcr(jit_state_t*,int32_t,int32_t,int32_t); -# define subci(r0,r1,i0) _subci(_jit,r0,r1,i0) -static void _subci(jit_state_t*,int32_t,int32_t,jit_word_t); -# define subxr(r0,r1,r2) _subxr(_jit,r0,r1,r2) -static void _subxr(jit_state_t*,int32_t,int32_t,int32_t); -# define subxi(r0,r1,i0) _subxi(_jit,r0,r1,i0) -static void _subxi(jit_state_t*,int32_t,int32_t,jit_word_t); -# define rsbi(r0, r1, i0) _rsbi(_jit, r0, r1, i0) -static void _rsbi(jit_state_t*,int32_t,int32_t,jit_word_t); -# define mulr(r0,r1,r2) _mulr(_jit,r0,r1,r2) -static void _mulr(jit_state_t*,int32_t,int32_t,int32_t); -# define muli(r0,r1,i0) _muli(_jit,r0,r1,i0) -static void _muli(jit_state_t*,int32_t,int32_t,jit_word_t); -# define qmulr(r0,r1,r2,r3) iqmulr(r0,r1,r2,r3,1) -# define qmulr_u(r0,r1,r2,r3) iqmulr(r0,r1,r2,r3,0) -# define iqmulr(r0,r1,r2,r3,cc) _iqmulr(_jit,r0,r1,r2,r3,cc) -static void _iqmulr(jit_state_t*,int32_t,int32_t, - int32_t,int32_t,jit_bool_t); -# define qmuli(r0,r1,r2,i0) iqmuli(r0,r1,r2,i0,1) -# define qmuli_u(r0,r1,r2,i0) iqmuli(r0,r1,r2,i0,0) -# define iqmuli(r0,r1,r2,i0,cc) _iqmuli(_jit,r0,r1,r2,i0,cc) -static void _iqmuli(jit_state_t*,int32_t,int32_t, - int32_t,jit_word_t,jit_bool_t); -# define divrem(d,s,r0,r1,r2) _divrem(_jit,d,s,r0,r1,r2) -static void _divrem(jit_state_t*,int,int,int32_t,int32_t,int32_t); -# define divr(r0,r1,r2) _divr(_jit,r0,r1,r2) -static void _divr(jit_state_t*,int32_t,int32_t,int32_t); -# define divi(r0,r1,i0) _divi(_jit,r0,r1,i0) -static void _divi(jit_state_t*,int32_t,int32_t,jit_word_t); -# define divr_u(r0,r1,r2) _divr_u(_jit,r0,r1,r2) -static void _divr_u(jit_state_t*,int32_t,int32_t,int32_t); -# define divi_u(r0,r1,i0) _divi_u(_jit,r0,r1,i0) -static void _divi_u(jit_state_t*,int32_t,int32_t,jit_word_t); -# define qdivr(r0,r1,r2,r3) iqdivr(r0,r1,r2,r3,1) -# define qdivr_u(r0,r1,r2,r3) iqdivr(r0,r1,r2,r3,0) -# define iqdivr(r0,r1,r2,r3,cc) _iqdivr(_jit,r0,r1,r2,r3,cc) -static void _iqdivr(jit_state_t*,int32_t,int32_t, - int32_t,int32_t,jit_bool_t); -# define qdivi(r0,r1,r2,i0) iqdivi(r0,r1,r2,i0,1) -# define qdivi_u(r0,r1,r2,i0) iqdivi(r0,r1,r2,i0,0) -# define iqdivi(r0,r1,r2,i0,cc) _iqdivi(_jit,r0,r1,r2,i0,cc) -static void _iqdivi(jit_state_t*,int32_t,int32_t, - int32_t,jit_word_t,jit_bool_t); -# define remr(r0,r1,r2) _remr(_jit,r0,r1,r2) -static void _remr(jit_state_t*,int32_t,int32_t,int32_t); -# define remi(r0,r1,i0) _remi(_jit,r0,r1,i0) -static void _remi(jit_state_t*,int32_t,int32_t,jit_word_t); -# define remr_u(r0,r1,r2) _remr_u(_jit,r0,r1,r2) -static void _remr_u(jit_state_t*,int32_t,int32_t,int32_t); -# define remi_u(r0,r1,i0) _remi_u(_jit,r0,r1,i0) -static void _remi_u(jit_state_t*,int32_t,int32_t,jit_word_t); -# define andr(r0,r1,r2) _andr(_jit,r0,r1,r2) -static void _andr(jit_state_t*,int32_t,int32_t,int32_t); -# define andi(r0,r1,i0) _andi(_jit,r0,r1,i0) -static void _andi(jit_state_t*,int32_t,int32_t,jit_word_t); -# define orr(r0,r1,r2) _orr(_jit,r0,r1,r2) -static void _orr(jit_state_t*,int32_t,int32_t,int32_t); -# define ori(r0,r1,i0) _ori(_jit,r0,r1,i0) -static void _ori(jit_state_t*,int32_t,int32_t,jit_word_t); -# define xorr(r0,r1,r2) _xorr(_jit,r0,r1,r2) -static void _xorr(jit_state_t*,int32_t,int32_t,int32_t); -# define xori(r0,r1,i0) _xori(_jit,r0,r1,i0) -static void _xori(jit_state_t*,int32_t,int32_t,jit_word_t); -# define lshr(r0,r1,r2) _lshr(_jit,r0,r1,r2) -static void _lshr(jit_state_t*,int32_t,int32_t,int32_t); -# define lshi(r0,r1,i0) _lshi(_jit,r0,r1,i0) -static void _lshi(jit_state_t*,int32_t,int32_t,jit_word_t); -# define rshr(r0,r1,r2) _rshr(_jit,r0,r1,r2) -static void _rshr(jit_state_t*,int32_t,int32_t,int32_t); -# define rshi(r0,r1,i0) _rshi(_jit,r0,r1,i0) -static void _rshi(jit_state_t*,int32_t,int32_t,jit_word_t); -# define rshr_u(r0,r1,r2) _rshr_u(_jit,r0,r1,r2) -static void _rshr_u(jit_state_t*,int32_t,int32_t,int32_t); -# define rshi_u(r0,r1,i0) _rshi_u(_jit,r0,r1,i0) -static void _rshi_u(jit_state_t*,int32_t,int32_t,jit_word_t); -# define ccr(ct,cf,r0,r1,r2) _ccr(_jit,ct,cf,r0,r1,r2) -static void _ccr(jit_state_t*,int,int,int32_t,int32_t,int32_t); -# define cci(ct,cf,r0,r1,i0) _cci(_jit,ct,cf,r0,r1,i0) -static void _cci(jit_state_t*,int,int,int32_t,int32_t,jit_word_t); -# define ltr(r0, r1, r2) ccr(ARM_CC_LT,ARM_CC_GE,r0,r1,r2) -# define lti(r0, r1, i0) cci(ARM_CC_LT,ARM_CC_GE,r0,r1,i0) -# define ltr_u(r0, r1, r2) ccr(ARM_CC_LO,ARM_CC_HS,r0,r1,r2) -# define lti_u(r0, r1, i0) cci(ARM_CC_LO,ARM_CC_HS,r0,r1,i0) -# define ler(r0, r1, r2) ccr(ARM_CC_LE,ARM_CC_GT,r0,r1,r2) -# define lei(r0, r1, i0) cci(ARM_CC_LE,ARM_CC_GT,r0,r1,i0) -# define ler_u(r0, r1, r2) ccr(ARM_CC_LS,ARM_CC_HI,r0,r1,r2) -# define lei_u(r0, r1, i0) cci(ARM_CC_LS,ARM_CC_HI,r0,r1,i0) -# define eqr(r0, r1, r2) ccr(ARM_CC_EQ,ARM_CC_NE,r0,r1,r2) -# define eqi(r0, r1, i0) cci(ARM_CC_EQ,ARM_CC_NE,r0,r1,i0) -# define ger(r0, r1, r2) ccr(ARM_CC_GE,ARM_CC_LT,r0,r1,r2) -# define gei(r0, r1, i0) cci(ARM_CC_GE,ARM_CC_LT,r0,r1,i0) -# define ger_u(r0, r1, r2) ccr(ARM_CC_HS,ARM_CC_LO,r0,r1,r2) -# define gei_u(r0, r1, i0) cci(ARM_CC_HS,ARM_CC_LO,r0,r1,i0) -# define gtr(r0, r1, r2) ccr(ARM_CC_GT,ARM_CC_LE,r0,r1,r2) -# define gti(r0, r1, i0) cci(ARM_CC_GT,ARM_CC_LE,r0,r1,i0) -# define gtr_u(r0, r1, r2) ccr(ARM_CC_HI,ARM_CC_LS,r0,r1,r2) -# define gti_u(r0, r1, i0) cci(ARM_CC_HI,ARM_CC_LS,r0,r1,i0) -# define ner(r0,r1,r2) _ner(_jit,r0,r1,r2) -static void _ner(jit_state_t*,int32_t,int32_t,int32_t); -# define nei(r0,r1,i0) _nei(_jit,r0,r1,i0) -static void _nei(jit_state_t*,int32_t,int32_t,jit_word_t); -# define jmpr(r0) _jmpr(_jit,r0) -static void _jmpr(jit_state_t*,int32_t); -# define jmpi(i0) _jmpi(_jit,i0) -static void _jmpi(jit_state_t*,jit_word_t); -# define jmpi_p(i0, i1) _jmpi_p(_jit,i0, i1) -static jit_word_t _jmpi_p(jit_state_t*,jit_word_t,jit_bool_t); -# define bccr(cc,i0,r0,r1) _bccr(_jit,cc,i0,r0,r1) -static jit_word_t _bccr(jit_state_t*,int,jit_word_t,int32_t,int32_t); -# define bcci(cc,i0,r0,i1) _bcci(_jit,cc,i0,r0,i1) -static jit_word_t _bcci(jit_state_t*,int,jit_word_t,int32_t,jit_word_t); -# define bltr(i0, r0, r1) bccr(ARM_CC_LT,i0,r0,r1) -# define blti(i0, r0, i1) bcci(ARM_CC_LT,i0,r0,i1) -# define bltr_u(i0, r0, r1) bccr(ARM_CC_LO,i0,r0,r1) -# define blti_u(i0, r0, i1) bcci(ARM_CC_LO,i0,r0,i1) -# define bler(i0, r0, r1) bccr(ARM_CC_LE,i0,r0,r1) -# define blei(i0, r0, i1) bcci(ARM_CC_LE,i0,r0,i1) -# define bler_u(i0, r0, r1) bccr(ARM_CC_LS,i0,r0,r1) -# define blei_u(i0, r0, i1) bcci(ARM_CC_LS,i0,r0,i1) -# define beqr(i0, r0, r1) bccr(ARM_CC_EQ,i0,r0,r1) -# define beqi(i0, r0, i1) bcci(ARM_CC_EQ,i0,r0,i1) -# define bger(i0, r0, r1) bccr(ARM_CC_GE,i0,r0,r1) -# define bgei(i0, r0, i1) bcci(ARM_CC_GE,i0,r0,i1) -# define bger_u(i0, r0, r1) bccr(ARM_CC_HS,i0,r0,r1) -# define bgei_u(i0, r0, i1) bcci(ARM_CC_HS,i0,r0,i1) -# define bgtr(i0, r0, r1) bccr(ARM_CC_GT,i0,r0,r1) -# define bgti(i0, r0, i1) bcci(ARM_CC_GT,i0,r0,i1) -# define bgtr_u(i0, r0, r1) bccr(ARM_CC_HI,i0,r0,r1) -# define bgti_u(i0, r0, i1) bcci(ARM_CC_HI,i0,r0,i1) -# define bner(i0, r0, r1) bccr(ARM_CC_NE,i0,r0,r1) -# define bnei(i0, r0, i1) bcci(ARM_CC_NE,i0,r0,i1) -# define baddr(cc,i0,r0,r1) _baddr(_jit,cc,i0,r0,r1) -static jit_word_t _baddr(jit_state_t*,int,jit_word_t,int32_t,int32_t); -# define baddi(cc,i0,r0,r1) _baddi(_jit,cc,i0,r0,r1) -static jit_word_t _baddi(jit_state_t*,int,jit_word_t,int32_t,jit_word_t); -# define boaddr(i0,r0,r1) baddr(ARM_CC_VS,i0,r0,r1) -# define boaddi(i0,r0,i1) baddi(ARM_CC_VS,i0,r0,i1) -# define boaddr_u(i0,r0,r1) baddr(ARM_CC_HS,i0,r0,r1) -# define boaddi_u(i0,r0,i1) baddi(ARM_CC_HS,i0,r0,i1) -# define bxaddr(i0,r0,r1) baddr(ARM_CC_VC,i0,r0,r1) -# define bxaddi(i0,r0,i1) baddi(ARM_CC_VC,i0,r0,i1) -# define bxaddr_u(i0,r0,r1) baddr(ARM_CC_LO,i0,r0,r1) -# define bxaddi_u(i0,r0,i1) baddi(ARM_CC_LO,i0,r0,i1) -# define bsubr(cc,i0,r0,r1) _bsubr(_jit,cc,i0,r0,r1) -static jit_word_t _bsubr(jit_state_t*,int,jit_word_t,int32_t,int32_t); -# define bsubi(cc,i0,r0,r1) _bsubi(_jit,cc,i0,r0,r1) -static jit_word_t _bsubi(jit_state_t*,int,jit_word_t,int32_t,jit_word_t); -# define bosubr(i0,r0,r1) bsubr(ARM_CC_VS,i0,r0,r1) -# define bosubi(i0,r0,i1) bsubi(ARM_CC_VS,i0,r0,i1) -# define bosubr_u(i0,r0,r1) bsubr(ARM_CC_LO,i0,r0,r1) -# define bosubi_u(i0,r0,i1) bsubi(ARM_CC_LO,i0,r0,i1) -# define bxsubr(i0,r0,r1) bsubr(ARM_CC_VC,i0,r0,r1) -# define bxsubi(i0,r0,i1) bsubi(ARM_CC_VC,i0,r0,i1) -# define bxsubr_u(i0,r0,r1) bsubr(ARM_CC_HS,i0,r0,r1) -# define bxsubi_u(i0,r0,i1) bsubi(ARM_CC_HS,i0,r0,i1) -# define bmxr(cc,i0,r0,r1) _bmxr(_jit,cc,i0,r0,r1) -static jit_word_t _bmxr(jit_state_t*,int,jit_word_t,int32_t,int32_t); -# define bmxi(cc,i0,r0,r1) _bmxi(_jit,cc,i0,r0,r1) -static jit_word_t _bmxi(jit_state_t*,int,jit_word_t,int32_t,jit_word_t); -# define bmsr(i0,r0,r1) bmxr(ARM_CC_NE,i0,r0,r1) -# define bmsi(i0,r0,i1) bmxi(ARM_CC_NE,i0,r0,i1) -# define bmcr(i0,r0,r1) bmxr(ARM_CC_EQ,i0,r0,r1) -# define bmci(i0,r0,i1) bmxi(ARM_CC_EQ,i0,r0,i1) -# define ldr_c(r0,r1) _ldr_c(_jit,r0,r1) -static void _ldr_c(jit_state_t*,int32_t,int32_t); -# define ldi_c(r0,i0) _ldi_c(_jit,r0,i0) -static void _ldi_c(jit_state_t*,int32_t,jit_word_t); -# define ldxr_c(r0,r1,r2) _ldxr_c(_jit,r0,r1,r2) -static void _ldxr_c(jit_state_t*,int32_t,int32_t,int32_t); -# define ldxi_c(r0,r1,i0) _ldxi_c(_jit,r0,r1,i0) -static void _ldxi_c(jit_state_t*,int32_t,int32_t,jit_word_t); -# define ldr_uc(r0,r1) _ldr_uc(_jit,r0,r1) -static void _ldr_uc(jit_state_t*,int32_t,int32_t); -# define ldi_uc(r0,i0) _ldi_uc(_jit,r0,i0) -static void _ldi_uc(jit_state_t*,int32_t,jit_word_t); -# define ldxr_uc(r0,r1,r2) _ldxr_uc(_jit,r0,r1,r2) -static void _ldxr_uc(jit_state_t*,int32_t,int32_t,int32_t); -# define ldxi_uc(r0,r1,i0) _ldxi_uc(_jit,r0,r1,i0) -static void _ldxi_uc(jit_state_t*,int32_t,int32_t,jit_word_t); -# define ldr_s(r0,r1) _ldr_s(_jit,r0,r1) -static void _ldr_s(jit_state_t*,int32_t,int32_t); -# define ldi_s(r0,i0) _ldi_s(_jit,r0,i0) -static void _ldi_s(jit_state_t*,int32_t,jit_word_t); -# define ldxr_s(r0,r1,r2) _ldxr_s(_jit,r0,r1,r2) -static void _ldxr_s(jit_state_t*,int32_t,int32_t,int32_t); -# define ldxi_s(r0,r1,i0) _ldxi_s(_jit,r0,r1,i0) -static void _ldxi_s(jit_state_t*,int32_t,int32_t,jit_word_t); -# define ldr_us(r0,r1) _ldr_us(_jit,r0,r1) -static void _ldr_us(jit_state_t*,int32_t,int32_t); -# define ldi_us(r0,i0) _ldi_us(_jit,r0,i0) -static void _ldi_us(jit_state_t*,int32_t,jit_word_t); -# define ldxr_us(r0,r1,r2) _ldxr_us(_jit,r0,r1,r2) -static void _ldxr_us(jit_state_t*,int32_t,int32_t,int32_t); -# define ldxi_us(r0,r1,i0) _ldxi_us(_jit,r0,r1,i0) -static void _ldxi_us(jit_state_t*,int32_t,int32_t,jit_word_t); -# define ldr_i(r0,r1) _ldr_i(_jit,r0,r1) -static void _ldr_i(jit_state_t*,int32_t,int32_t); -# define ldi_i(r0,i0) _ldi_i(_jit,r0,i0) -static void _ldi_i(jit_state_t*,int32_t,jit_word_t); -# define ldxr_i(r0,r1,r2) _ldxr_i(_jit,r0,r1,r2) -static void _ldxr_i(jit_state_t*,int32_t,int32_t,int32_t); -# define ldxi_i(r0,r1,i0) _ldxi_i(_jit,r0,r1,i0) -static void _ldxi_i(jit_state_t*,int32_t,int32_t,jit_word_t); -# define str_c(r0,r1) _str_c(_jit,r0,r1) -static void _str_c(jit_state_t*,int32_t,int32_t); -# define sti_c(i0,r0) _sti_c(_jit,i0,r0) -static void _sti_c(jit_state_t*,jit_word_t,int32_t); -# define stxr_c(r0,r1,r2) _stxr_c(_jit,r0,r1,r2) -static void _stxr_c(jit_state_t*,int32_t,int32_t,int32_t); -# define stxi_c(r0,r1,i0) _stxi_c(_jit,r0,r1,i0) -static void _stxi_c(jit_state_t*,jit_word_t,int32_t,int32_t); -# define str_s(r0,r1) _str_s(_jit,r0,r1) -static void _str_s(jit_state_t*,int32_t,int32_t); -# define sti_s(i0,r0) _sti_s(_jit,i0,r0) -static void _sti_s(jit_state_t*,jit_word_t,int32_t); -# define stxr_s(r0,r1,r2) _stxr_s(_jit,r0,r1,r2) -static void _stxr_s(jit_state_t*,int32_t,int32_t,int32_t); -# define stxi_s(r0,r1,i0) _stxi_s(_jit,r0,r1,i0) -static void _stxi_s(jit_state_t*,jit_word_t,int32_t,int32_t); -# define str_i(r0,r1) _str_i(_jit,r0,r1) -static void _str_i(jit_state_t*,int32_t,int32_t); -# define sti_i(i0,r0) _sti_i(_jit,i0,r0) -static void _sti_i(jit_state_t*,jit_word_t,int32_t); -# define stxr_i(r0,r1,r2) _stxr_i(_jit,r0,r1,r2) -static void _stxr_i(jit_state_t*,jit_word_t,int32_t,int32_t); -# define stxi_i(r0,r1,i0) _stxi_i(_jit,r0,r1,i0) -static void _stxi_i(jit_state_t*,jit_word_t,int32_t,int32_t); -# if __BYTE_ORDER == __LITTLE_ENDIAN -# define bswapr_us(r0,r1) _bswapr_us(_jit,r0,r1) -static void _bswapr_us(jit_state_t*,int32_t,int32_t); -# define bswapr_ui(r0,r1) _bswapr_ui(_jit,r0,r1) -static void _bswapr_ui(jit_state_t*,int32_t,int32_t); -# else -# define bswapr_us(r0,r1) extr_us(r0,r1) -# define bswapr(r0,r1) movr(r0,r1) -# endif -# define extr_c(r0,r1) _extr_c(_jit,r0,r1) -static void _extr_c(jit_state_t*,int32_t,int32_t); -# define extr_uc(r0,r1) _extr_uc(_jit,r0,r1) -static void _extr_uc(jit_state_t*,int32_t,int32_t); -# define extr_s(r0,r1) _extr_s(_jit,r0,r1) -static void _extr_s(jit_state_t*,int32_t,int32_t); -# define extr_us(r0,r1) _extr_us(_jit,r0,r1) -static void _extr_us(jit_state_t*,int32_t,int32_t); -# define prolog(i0) _prolog(_jit,i0) -static void _prolog(jit_state_t*,jit_node_t*); -# define epilog(i0) _epilog(_jit,i0) -static void _epilog(jit_state_t*,jit_node_t*); -# define callr(r0) _callr(_jit,r0) -static void _callr(jit_state_t*,int32_t); -# define calli(i0) _calli(_jit,i0) -static void _calli(jit_state_t*,jit_word_t); -# define calli_p(i0) _calli_p(_jit,i0) -static jit_word_t _calli_p(jit_state_t*,jit_word_t); -# define vastart(r0) _vastart(_jit, r0) -static void _vastart(jit_state_t*, int32_t); -# define vaarg(r0, r1) _vaarg(_jit, r0, r1) -static void _vaarg(jit_state_t*, int32_t, int32_t); -# define patch_at(kind,jump,label) _patch_at(_jit,kind,jump,label) -static void _patch_at(jit_state_t*,int32_t,jit_word_t,jit_word_t); -#endif -#if CODE +#define ARM_CC_EQ 0x00000000 /* Z=1 */ +#define ARM_CC_NE 0x10000000 /* Z=0 */ +#define ARM_CC_HS 0x20000000 /* C=1 */ +#define ARM_CC_CS ARM_CC_HS +#define ARM_CC_LO 0x30000000 /* C=0 */ +#define ARM_CC_CC ARM_CC_LO +#define ARM_CC_MI 0x40000000 /* N=1 */ +#define ARM_CC_PL 0x50000000 /* N=0 */ +#define ARM_CC_VS 0x60000000 /* V=1 */ +#define ARM_CC_VC 0x70000000 /* V=0 */ +#define ARM_CC_HI 0x80000000 /* C=1 && Z=0 */ +#define ARM_CC_LS 0x90000000 /* C=0 || Z=1 */ +#define ARM_CC_GE 0xa0000000 /* N=V */ +#define ARM_CC_LT 0xb0000000 /* N!=V */ +#define ARM_CC_GT 0xc0000000 /* Z=0 && N=V */ +#define ARM_CC_LE 0xd0000000 /* Z=1 || N!=V */ +#define ARM_CC_AL 0xe0000000 /* always */ +#define ARM_CC_NV 0xf0000000 /* reserved */ +#define THUMB_MOV 0x4600 +#define THUMB_MOVI 0x2000 +#define THUMB2_MOVI 0xf0400000 +#define THUMB2_MOVWI 0xf2400000 +#define THUMB2_MOVTI 0xf2c00000 +#define THUMB_MVN 0x43c0 +#define THUMB2_MVN 0xea600000 +#define THUMB2_MVNI 0xf0600000 +#define ARM_S 0x00100000 /* set flags */ +#define ARM_ADD 0x00800000 +#define THUMB_ADD 0x1800 +#define THUMB_ADDX 0x4400 +#define THUMB2_ADD 0xeb000000 +#define THUMB_ADDI3 0x1c00 +#define THUMB_ADDI8 0x3000 +#define THUMB2_ADDI 0xf1000000 +#define THUMB2_ADDWI 0xf2000000 +#define ARM_ADC 0x00a00000 +#define THUMB_ADC 0x4140 +#define THUMB2_ADC 0xeb400000 +#define THUMB2_ADCI 0xf1400000 +#define THUMB_SUB 0x1a00 +#define THUMB2_SUB 0xeba00000 +#define THUMB_SUBI3 0x1e00 +#define THUMB_SUBI8 0x3800 +#define THUMB2_SUBI 0xf1a00000 +#define THUMB2_SUBWI 0xf2a00000 +#define THUMB_SBC 0x4180 +#define THUMB2_SBC 0xeb600000 +#define THUMB2_SBCI 0xf1600000 +#define ARM_RSB 0x00600000 +#define THUMB_RSBI 0x4240 +#define THUMB2_RSBI 0xf1c00000 +#define ARM_MUL 0x00000090 +#define THUMB_MUL 0x4340 +#define THUMB2_MUL 0xfb00f000 +#define ARM_UMULL 0x00800090 +#define THUMB2_UMULL 0xfba00000 +#define THUMB2_SMULL 0xfb800000 +#define THUMB_MLS 0xfb000010 +#define THUMB2_SDIV 0xfb90f0f0 +#define THUMB2_UDIV 0xfbb0f0f0 +#define ARM_AND 0x00000000 +#define THUMB_AND 0x4000 +#define THUMB2_AND 0xea000000 +#define THUMB2_ANDI 0xf0000000 +#define ARM_BIC 0x01c00000 +#define THUMB2_BIC 0xea200000 +#define THUMB2_BICI 0xf0200000 +#define ARM_ORR 0x01800000 +#define THUMB_ORR 0x4300 +#define THUMB2_ORR 0xea400000 +#define THUMB2_ORRI 0xf0400000 +#define ARM_EOR 0x00200000 +#define THUMB_EOR 0x4040 +#define THUMB2_EOR 0xea800000 +#define THUMB2_EORI 0xf0800000 +/* >> ARMv6* */ +#define ARM_REV 0x06bf0f30 +#define THUMB_REV 0xba00 +#define THUMB2_REV 0xfa90f080 +#define ARM_REV16 0x06bf0fb0 +#define THUMB_REV16 0xba40 +#define THUMB2_REV16 0xfa90f090 +#define THUMB_SXTB 0xb240 +#define THUMB2_SXTB 0xfa40f080 +#define ARM_UXTB 0x06ef0070 +#define THUMB_UXTB 0xb2c0 +#define THUMB2_UXTB 0xfa50f080 +#define THUMB_SXTH 0xb200 +#define THUMB2_SXTH 0xfa00f080 +#define ARM_UXTH 0x06ff0070 +#define THUMB_UXTH 0xb280 +#define THUMB2_UXTH 0xfa10f080 +#define ARM_XTR8 0x00000400 /* ?xt? rotate 8 bits */ +#define ARM_XTR16 0x00000800 /* ?xt? rotate 16 bits */ +#define ARM_XTR24 0x00000c00 /* ?xt? rotate 24 bits */ +/* << ARMv6* */ +#define ARM_R 0x00000010 /* register shift */ +#define ARM_LSL 0x00000000 +#define THUMB_LSL 0x4080 +#define THUMB2_LSL 0xfa00f000 +#define THUMB_LSLI 0x0000 +#define THUMB2_LSLI 0xea4f0000 +#define ARM_LSR 0x00000020 +#define THUMB_LSR 0x40c0 +#define THUMB2_LSR 0xfa20f000 +#define THUMB_LSRI 0x0800 +#define THUMB2_LSRI 0xea4f0010 +#define ARM_ASR 0x00000040 +#define THUMB_ASR 0x4100 +#define THUMB2_ASR 0xfa40f000 +#define THUMB_ASRI 0x1000 +#define THUMB2_ASRI 0xea4f0020 +#define ARM_ROR 0x00000060 +#define ARM_CMP 0x01500000 +#define THUMB_CMP 0x4280 +#define THUMB_CMPX 0x4500 +#define THUMB2_CMP 0xebb00000 +#define THUMB_CMPI 0x2800 +#define THUMB2_CMPI 0xf1b00000 +#define ARM_CMN 0x01700000 +#define THUMB_CMN 0x42c0 +#define THUMB2_CMN 0xeb100000 +#define THUMB2_CMNI 0xf1100000 +#define ARM_TST 0x01100000 +#define THUMB_TST 0x4200 +#define THUMB2_TST 0xea100000 +#define THUMB2_TSTI 0xf0100000 +#define ARM_TEQ 0x01300000 +/* branch */ +#define ARM_B 0x0a000000 +#define THUMB_CC_B 0xd000 +#define THUMB_B 0xe000 +#define THUMB2_CC_B 0xf0008000 +#define THUMB2_B 0xf0009000 +#define ARM_BLI 0x0b000000 +#define THUMB2_BLI 0xf000d000 +/* ldr/str */ +#define ARM_P 0x00800000 /* positive offset */ +#define THUMB2_P 0x00000400 +#define THUMB2_U 0x00000200 +#define THUMB2_W 0x00000100 +#define ARM_LDRSB 0x011000d0 +#define THUMB_LDRSB 0x5600 +#define THUMB2_LDRSB 0xf9100000 +#define ARM_LDRSBI 0x015000d0 +#define THUMB2_LDRSBI 0xf9100c00 +#define THUMB2_LDRSBWI 0xf9900000 +#define ARM_LDRB 0x07500000 +#define THUMB_LDRB 0x5c00 +#define THUMB2_LDRB 0xf8100000 +#define ARM_LDRBI 0x05500000 +#define THUMB_LDRBI 0x7800 +#define THUMB2_LDRBI 0xf8100c00 +#define THUMB2_LDRBWI 0xf8900000 +#define ARM_LDRSH 0x011000f0 +#define THUMB_LDRSH 0x5e00 +#define THUMB2_LDRSH 0xf9300000 +#define ARM_LDRSHI 0x015000f0 +#define THUMB2_LDRSHI 0xf9300c00 +#define THUMB2_LDRSHWI 0xf9b00000 +#define ARM_LDRH 0x011000b0 +#define THUMB_LDRH 0x5a00 +#define THUMB2_LDRH 0xf8300000 +#define ARM_LDRHI 0x015000b0 +#define THUMB_LDRHI 0x8800 +#define THUMB2_LDRHI 0xf8300c00 +#define THUMB2_LDRHWI 0xf8b00000 +#define ARM_LDR 0x07100000 +#define THUMB_LDR 0x5800 +#define THUMB2_LDR 0xf8500000 +#define THUMB2_LDRP 0xf85f0000 +#define ARM_LDRI 0x05100000 +#define THUMB_LDRI 0x6800 +#define THUMB_LDRISP 0x9800 +#define THUMB2_LDRI 0xf8500c00 +#define THUMB2_LDRWI 0xf8d00000 +#define ARM_LDRD 0x010000d0 +#define ARM_LDRDI 0x014000d0 +#define THUMB2_LDRDI 0xe8500000 +#define THUMB_STRB 0x5400 +#define THUMB2_STRB 0xf8000000 +#define THUMB_STRBI 0x7000 +#define THUMB2_STRBI 0xf8000c00 +#define THUMB2_STRBWI 0xf8800000 +#define THUMB_STRH 0x5200 +#define THUMB2_STRH 0xf8200000 +#define THUMB_STRHI 0x8000 +#define THUMB2_STRHI 0xf8200c00 +#define THUMB2_STRHWI 0xf8a00000 +#define THUMB_STR 0x5000 +#define THUMB2_STR 0xf8400000 +#define THUMB_STRI 0x6000 +#define THUMB2_STRWI 0xf8c00000 +#define THUMB_STRISP 0x9000 +#define THUMB2_STRI 0xf8400c00 +#define THUMB2_STRDI 0xe8400000 +/* ldm/stm */ +#define ARM_M 0x08000000 +#define ARM_M_L 0x00100000 /* load; store if not set */ +#define ARM_M_I 0x00800000 /* inc; dec if not set */ +#define ARM_M_B 0x01000000 /* before; after if not set */ +#define ARM_M_U 0x00200000 /* update Rn */ +#define THUMB2_LDM_W 0x00200000 +#define THUMB2_LDM_P 0x00008000 +#define THUMB2_LDM_M 0x00004000 +#define THUMB_LDMIA 0xc800 +#define THUMB2_LDMIA 0xe8900000 +#define THUMB2_LDMB 0xe9100000 +#define THUMB_PUSH 0xb400 +#define THUMB2_PUSH 0xe92d0000 +#define THUMB_POP 0xbc00 +#define THUMB2_POP 0xe8bd0000 + +#define _NOREG (jit_gpr_regno(_PC)) + +static void +emit_wide_thumb(jit_state_t *_jit, uint32_t inst) +{ + emit_u16(_jit, inst >> 16); + emit_u16(_jit, inst & 0xffff); +} + /* from binutils */ # define rotate_left(v, n) (v << n | v >> (32 - n)) static int encode_arm_immediate(unsigned int v) { - unsigned int a, i; + unsigned int a, i; - for (i = 0; i < 32; i += 2) - if ((a = rotate_left(v, i)) <= 0xff) - return (a | (i << 7)); + for (i = 0; i < 32; i += 2) + if ((a = rotate_left(v, i)) <= 0xff) + return (a | (i << 7)); - return (-1); + return (-1); } static int encode_thumb_immediate(unsigned int v) { - int i; - unsigned int m; - unsigned int n; - /* 00000000 00000000 00000000 abcdefgh */ - if ((v & 0xff) == v) - return (v); - /* 00000000 abcdefgh 00000000 abcdefgh */ - if ((v & 0xff00ff) == v && ((v & 0xff0000) >> 16) == (v & 0xff)) - return ((v & 0xff) | (1 << 12)); - /* abcdefgh 00000000 abcdefgh 00000000 */ - if (((v & 0xffff0000) >> 16) == (v & 0xffff) && (v & 0xff) == 0) - return ((v & 0x000000ff) | (2 << 12)); - /* abcdefgh abcdefgh abcdefgh abcdefgh */ - if ( (v & 0xff) == ((v & 0xff00) >> 8) && - ((v & 0xff00) >> 8) == ((v & 0xff0000) >> 16) && - ((v & 0xff0000) << 8) == (v & 0xff000000)) - return ((v & 0xff) | (3 << 12)); - /* 1bcdefgh << 24 ... 1bcdefgh << 1 */ - for (i = 8, m = 0xff000000, n = 0x80000000; - i < 23; i++, m >>= 1, n >>= 1) { - if ((v & m) == v && (v & n)) { - v >>= 32 - i; - if (!(i & 1)) - v &= 0x7f; - i >>= 1; - return (((i & 7) << 12) | ((i & 8) << 23) | v); - } + int i; + unsigned int m; + unsigned int n; + /* 00000000 00000000 00000000 abcdefgh */ + if ((v & 0xff) == v) + return (v); + /* 00000000 abcdefgh 00000000 abcdefgh */ + if ((v & 0xff00ff) == v && ((v & 0xff0000) >> 16) == (v & 0xff)) + return ((v & 0xff) | (1 << 12)); + /* abcdefgh 00000000 abcdefgh 00000000 */ + if (((v & 0xffff0000) >> 16) == (v & 0xffff) && (v & 0xff) == 0) + return ((v & 0x000000ff) | (2 << 12)); + /* abcdefgh abcdefgh abcdefgh abcdefgh */ + if ( (v & 0xff) == ((v & 0xff00) >> 8) && + ((v & 0xff00) >> 8) == ((v & 0xff0000) >> 16) && + ((v & 0xff0000) << 8) == (v & 0xff000000)) + return ((v & 0xff) | (3 << 12)); + /* 1bcdefgh << 24 ... 1bcdefgh << 1 */ + for (i = 8, m = 0xff000000, n = 0x80000000; + i < 23; i++, m >>= 1, n >>= 1) { + if ((v & m) == v && (v & n)) { + v >>= 32 - i; + if (!(i & 1)) + v &= 0x7f; + i >>= 1; + return (((i & 7) << 12) | ((i & 8) << 23) | v); } - return (-1); + } + return (-1); } static int encode_thumb_word_immediate(unsigned int v) { - if ((v & 0xfffff000) == 0) - return (((v & 0x800) << 15) | ((v & 0x700) << 4) | (v & 0xff)); - return (-1); + if ((v & 0xfffff000) == 0) + return (((v & 0x800) << 15) | ((v & 0x700) << 4) | (v & 0xff)); + return (-1); } static int -encode_thumb_jump(int v) +offset_in_thumb_jump_range(int32_t offset) { - int s, i1, i2, j1, j2; - if (v >= (int)-0x800000 && v <= 0x7fffff) { - s = !!(v & 0x800000); - i1 = !!(v & 0x400000); - i2 = !!(v & 0x200000); - j1 = s ? i1 : !i1; - j2 = s ? i2 : !i2; - return ((s<<26)|((v&0x1ff800)<<5)|(j1<<13)|(j2<<11)|(v&0x7ff)); - } - return (-1); + return -0x800000 <= offset && offset <= 0x7fffff; +} + +static int32_t +decode_thumb_jump(uint32_t v) +{ + uint32_t s = (v >> 26) & 1; + uint32_t j1 = (v >> 13) & 1; + uint32_t j2 = (v >> 11) & 1; + uint32_t i1 = s ? j1 : !j1; + uint32_t i2 = s ? j2 : !j2; + uint32_t hi = (v >> 16) & 0x3ff; + uint32_t lo = v & 0x7ff; + + int32_t ret = s << 31; + ret >>= 8; + ret |= i1 << 22; + ret |= i2 << 21; + ret |= hi << 11; + ret |= lo; + return ret; +} + +static const uint32_t thumb_jump_mask = 0xf800d000; + +static uint32_t +encode_thumb_jump(int32_t v) +{ + ASSERT(offset_in_thumb_jump_range(v)); + uint32_t s = !!(v & 0x800000); + uint32_t i1 = !!(v & 0x400000); + uint32_t i2 = !!(v & 0x200000); + uint32_t j1 = s ? i1 : !i1; + uint32_t j2 = s ? i2 : !i2; + uint32_t ret = (s<<26)|((v&0x1ff800)<<5)|(j1<<13)|(j2<<11)|(v&0x7ff); + ASSERT(decode_thumb_jump(ret) == v); + ASSERT((ret & thumb_jump_mask) == 0); + return ret; +} + +static uint32_t +patch_thumb_jump(uint32_t inst, int32_t v) +{ + return (inst & thumb_jump_mask) | encode_thumb_jump(v); +} + +static jit_reloc_t +emit_thumb_jump(jit_state_t *_jit, uint32_t inst) +{ + uint8_t *pc_base = _jit->pc.uc + 4; + uint8_t rsh = 1; + int32_t off = (_jit->pc.uc - pc_base) >> rsh; + jit_reloc_t ret = + jit_reloc (_jit, JIT_RELOC_JMP_WITH_VENEER, 0, _jit->pc.uc, pc_base, rsh); + uint8_t thumb_jump_width = 24; + add_pending_literal(_jit, ret, thumb_jump_width - 1); + emit_wide_thumb(_jit, patch_thumb_jump(inst, off)); + return ret; } static int -encode_thumb_cc_jump(int v) +offset_in_thumb_cc_jump_range(int32_t v) { - int s, j1, j2; - if (v >= (int)-0x80000 && v <= 0x7ffff) { - s = !!(v & 0x80000); - j1 = !!(v & 0x20000); - j2 = !!(v & 0x40000); - return ((s<<26)|((v&0x1f800)<<5)|(j1<<13)|(j2<<11)|(v&0x7ff)); - } - return (-1); + return -0x80000 <= v && v <= 0x7ffff; +} + +static int32_t +decode_thumb_cc_jump(uint32_t v) +{ + uint32_t s = (v >> 26) & 1; + uint32_t j1 = (v >> 13) & 1; + uint32_t j2 = (v >> 11) & 1; + uint32_t i1 = s ? j1 : !j1; + uint32_t i2 = s ? j2 : !j2; + uint32_t hi = (v >> 16) & 0x3f; + uint32_t lo = v & 0x7ff; + + int32_t ret = s << 31; + ret >>= 12; + ret |= i1 << 18; + ret |= i2 << 17; + ret |= hi << 11; + ret |= lo; + return ret; +} + +static const uint32_t thumb_cc_jump_mask = 0xfbc0d000; + +static uint32_t +encode_thumb_cc_jump(int32_t v) +{ + ASSERT(offset_in_thumb_cc_jump_range(v)); + uint32_t s = !!(v & 0x80000); + uint32_t j1 = !!(v & 0x40000); + uint32_t j2 = !!(v & 0x20000); + uint32_t ret = (s<<26)|((v&0x1f800)<<5)|(j1<<13)|(j2<<11)|(v&0x7ff); + ASSERT(decode_thumb_cc_jump(ret) == v); + ASSERT((ret & thumb_cc_jump_mask) == 0); + return ret; +} + +static uint32_t +patch_thumb_cc_jump(uint32_t inst, int32_t v) +{ + return (inst & thumb_cc_jump_mask) | encode_thumb_cc_jump(v); +} + +static jit_reloc_t +emit_thumb_cc_jump(jit_state_t *_jit, uint32_t inst) +{ + uint8_t *pc_base = _jit->pc.uc + 4; + uint8_t rsh = 1; + int32_t off = (_jit->pc.uc - pc_base) >> rsh; + jit_reloc_t ret = + jit_reloc (_jit, JIT_RELOC_JCC_WITH_VENEER, 0, _jit->pc.uc, pc_base, rsh); + uint8_t thumb_cc_jump_width = 20; + add_pending_literal(_jit, ret, thumb_cc_jump_width - 1); + emit_wide_thumb(_jit, patch_thumb_cc_jump(inst, off)); + return ret; } static int encode_thumb_shift(int v, int type) { - switch (type) { - case ARM_ASR: - case ARM_LSL: - case ARM_LSR: type >>= 1; break; - default: assert(!"handled shift"); - } - assert(v >= 0 && v <= 31); - return (((v & 0x1c) << 10) | ((v & 3) << 6) | type); + switch (type) { + case ARM_ASR: + case ARM_LSL: + case ARM_LSR: type >>= 1; break; + default: assert(!"handled shift"); + } + assert(v >= 0 && v <= 31); + return (((v & 0x1c) << 10) | ((v & 3) << 6) | type); } static void -_tcit(jit_state_t *_jit, unsigned int tc, int it) +torrr(jit_state_t *_jit, int o, int rn, int rd, int rm) { - int c; - int m; - c = (tc >> 28) & 1; - assert(!(tc & 0xfffffff) && tc != ARM_CC_NV); - switch (it) { - case THUMB2_IT: m = 1<<3; break; - case THUMB2_ITT: m = (c<<3)| (1<<2); break; - case THUMB2_ITE: m = (!c<<3)| (1<<2); break; - case THUMB2_ITTT: m = (c<<3)| (c<<2)| (1<<1); break; - case THUMB2_ITET: m = (!c<<3)| (c<<2)| (1<<1); break; - case THUMB2_ITTE: m = (c<<3)|(!c<<2)| (1<<1); break; - case THUMB2_ITEE: m = (!c<<3)|(!c<<2)| (1<<1); break; - case THUMB2_ITTTT: m = (c<<3)| (c<<2)| (c<<1)|1; break; - case THUMB2_ITETT: m = (!c<<3)| (c<<2)| (c<<1)|1; break; - case THUMB2_ITTET: m = (c<<3)|(!c<<2)| (c<<1)|1; break; - case THUMB2_ITEET: m = (!c<<3)|(!c<<2)| (c<<1)|1; break; - case THUMB2_ITTTE: m = (c<<3)| (c<<2)|(!c<<1)|1; break; - case THUMB2_ITETE: m = (!c<<3)| (c<<2)|(!c<<1)|1; break; - case THUMB2_ITTEE: m = (c<<3)|(!c<<2)|(!c<<1)|1; break; - case THUMB2_ITEEE: m = (!c<<3)|(!c<<2)|(!c<<1)|1; break; - default: abort(); - } - assert(m && (tc != ARM_CC_AL || !(m & (m - 1)))); - is(0xbf00 | (tc >> 24) | m); + assert(!(o & 0xf0f0f)); + emit_wide_thumb(_jit, o|(_u4(rn)<<16)|(_u4(rd)<<8)|_u4(rm)); } static void -_corrr(jit_state_t *_jit, int cc, int o, int rn, int rd, int rm) +torrrs(jit_state_t *_jit, int o, int rn, int rd, int rm, int im) { - assert(!(cc & 0x0fffffff)); - assert(!(o & 0xf00fff0f)); - ii(cc|o|(_u4(rn)<<16)|(_u4(rd)<<12)|_u4(rm)); + assert(!(o & 0x000f0f0f)); + assert(!(im & 0xffff8f0f)); + emit_wide_thumb(_jit, o|(_u4(rn)<<16)|(_u4(rd)<<8)|im|_u4(rm)); } static void -_corri(jit_state_t *_jit, int cc, int o, int rn, int rd, int im) +torxr(jit_state_t *_jit, int o, int rn, int rt, int rm) { - assert(!(cc & 0x0fffffff)); - assert(!(o & 0xf00fffff)); - assert(!(im & 0xfffff000)); - ii(cc|o|(_u4(rn)<<16)|(_u4(rd)<<12)|_u12(im)); + assert(!(o & 0xf0f0f)); + emit_wide_thumb(_jit, o|(_u4(rn)<<16)|(_u4(rt)<<12)|_u4(rm)); } static void -_corri8(jit_state_t *_jit, int cc, int o, int rn, int rt, int im) +torrrr(jit_state_t *_jit, int o, int rn, int rl, int rh, int rm) { - assert(!(cc & 0x0fffffff)); - assert(!(o & 0xf00fff0f)); - assert(!(im & 0xffffff00)); - ii(cc|o|(_u4(rn)<<16)|(_u4(rt)<<12)|((im&0xf0)<<4)|(im&0x0f)); + assert(!(o & 0x000fff0f)); + emit_wide_thumb(_jit, o|(_u4(rn)<<16)|(_u4(rl)<<12)|(_u4(rh)<<8)|_u4(rm)); } static void -_coriw(jit_state_t *_jit, int cc, int o, int rd, int im) +torrri8(jit_state_t *_jit, int o, int rn, int rt, int rt2, int im) { - assert(!(cc & 0x0fffffff)); - assert(!(o & 0xf00fffff)); - assert(!(im & 0xffff0000)); - ii(cc|o|((im&0xf000)<<4)|(_u4(rd)<<12)|(im&0xfff)); + assert(!(o & 0x000fffff)); + assert(!(im & 0xffffff00)); + emit_wide_thumb(_jit, o|(_u4(rn)<<16)|(_u4(rt)<<12)|(_u4(rt2)<<8)|im); } static void -_torrr(jit_state_t *_jit, int o, int rn, int rd, int rm) +torri(jit_state_t *_jit, int o, int rn, int rd, int im) { - jit_thumb_t thumb; - assert(!(o & 0xf0f0f)); - thumb.i = o|(_u4(rn)<<16)|(_u4(rd)<<8)|_u4(rm); - iss(thumb.s[0], thumb.s[1]); + assert(!(o & 0x0c0f7fff)); + assert(!(im & 0xfbff8f00)); + emit_wide_thumb(_jit, o|(_u4(rn)<<16)|(_u4(rd)<<8)|im); } static void -_torrrs(jit_state_t *_jit, int o, int rn, int rd, int rm, int im) +torri8(jit_state_t *_jit, int o, int rn, int rt, int im) { - jit_thumb_t thumb; - assert(!(o & 0x000f0f0f)); - assert(!(im & 0xffff8f0f)); - thumb.i = o|(_u4(rn)<<16)|(_u4(rd)<<8)|im|_u4(rm); - iss(thumb.s[0], thumb.s[1]); + assert(!(o & 0x000ff0ff)); + assert(!(im & 0xffffff00)); + emit_wide_thumb(_jit, o|(_u4(rn)<<16)|(_u4(rt)<<12)|im); } static void -_torxr(jit_state_t *_jit, int o, int rn, int rt, int rm) +torri12(jit_state_t *_jit, int o, int rn, int rt, int im) { - jit_thumb_t thumb; - assert(!(o & 0xf0f0f)); - thumb.i = o|(_u4(rn)<<16)|(_u4(rt)<<12)|_u4(rm); - iss(thumb.s[0], thumb.s[1]); + assert(!(o & 0x000fffff)); + assert(!(im & 0xfffff000)); + emit_wide_thumb(_jit, o|(_u4(rn)<<16)|(_u4(rt)<<12)|im); } static void -_torrrr(jit_state_t *_jit, int o, int rn, int rl, int rh, int rm) +tshift(jit_state_t *_jit, int o, int rd, int rm, int im) { - jit_thumb_t thumb; - assert(!(o & 0x000fff0f)); - thumb.i = o|(_u4(rn)<<16)|(_u4(rl)<<12)|(_u4(rh)<<8)|_u4(rm); - iss(thumb.s[0], thumb.s[1]); + assert(!(o & 0x7fcf)); + assert(im >= 0 && im < 32); + emit_wide_thumb(_jit, o|((im&0x1c)<<10)|(_u4(rd)<<8)|((im&3)<<6)|_u4(rm)); } static void -_torrri8(jit_state_t *_jit, int o, int rn, int rt, int rt2, int im) +toriw(jit_state_t *_jit, int o, int rd, int im) { - jit_thumb_t thumb; - assert(!(o & 0x000fffff)); - assert(!(im & 0xffffff00)); - thumb.i = o|(_u4(rn)<<16)|(_u4(rt)<<12)|(_u4(rt2)<<8)|im; - iss(thumb.s[0], thumb.s[1]); + assert(!(im & 0xffff0000)); + emit_wide_thumb(_jit, o|((im&0xf000)<<4)|((im&0x800)<<15)|((im&0x700)<<4)|(_u4(rd)<<8)|(im&0xff)); } static void -_torri(jit_state_t *_jit, int o, int rn, int rd, int im) +tc8(jit_state_t *_jit, int cc, int im) { - jit_thumb_t thumb; - assert(!(o & 0x0c0f7fff)); - assert(!(im & 0xfbff8f00)); - thumb.i = o|(_u4(rn)<<16)|(_u4(rd)<<8)|im; - iss(thumb.s[0], thumb.s[1]); + assert(!(cc & 0x0fffffff)); + assert(cc != ARM_CC_AL && cc != ARM_CC_NV); + assert(im >= -128 && im <= 127); + emit_u16(_jit, THUMB_CC_B|(cc>>20)|(im&0xff)); } static void -_torri8(jit_state_t *_jit, int o, int rn, int rt, int im) +t11(jit_state_t *_jit, int im) { - jit_thumb_t thumb; - assert(!(o & 0x000ff0ff)); - assert(!(im & 0xffffff00)); - thumb.i = o|(_u4(rn)<<16)|(_u4(rt)<<12)|im; - iss(thumb.s[0], thumb.s[1]); + assert(!(im & 0xfffff800)); + emit_u16(_jit, THUMB_B|im); +} + +static jit_reloc_t +tcb(jit_state_t *_jit, int cc) +{ + assert(!(cc & 0xfffffff)); + assert(cc != ARM_CC_AL && cc != ARM_CC_NV); + cc = ((uint32_t)cc) >> 6; + return emit_thumb_cc_jump(_jit, THUMB2_CC_B|cc); +} + +static jit_reloc_t +tb(jit_state_t *_jit, int o) +{ + assert(!(o & 0x07ff2fff)); + return emit_thumb_jump(_jit, o); } static void -_torri12(jit_state_t *_jit, int o, int rn, int rt, int im) +tpp(jit_state_t *_jit, int o, int im) { - jit_thumb_t thumb; - assert(!(o & 0x000fffff)); - assert(!(im & 0xfffff000)); - thumb.i = o|(_u4(rn)<<16)|(_u4(rt)<<12)|im; - iss(thumb.s[0], thumb.s[1]); + assert(!(o & 0x0000ffff)); + if (o == THUMB2_PUSH) + assert(!(im & 0x8000)); + assert(__builtin_popcount(im & 0x1fff) > 1); + emit_wide_thumb(_jit, o|im); } static void -_tshift(jit_state_t *_jit, int o, int rd, int rm, int im) +torl(jit_state_t *_jit, int o, int rn, int im) { - jit_thumb_t thumb; - assert(!(o & 0x7fcf)); - assert(im >= 0 && im < 32); - thumb.i = o|((im&0x1c)<<10)|(_u4(rd)<<8)|((im&3)<<6)|_u4(rm); - iss(thumb.s[0], thumb.s[1]); + assert(!(o & 0xf1fff)); + assert(rn != _NOREG || !im || ((o & 0xc000) == 0xc000)); + assert(!(o & THUMB2_LDM_W) || !(im & (1 << rn))); + emit_wide_thumb(_jit, o | (_u4(rn)<<16)|_u13(im)); } static void -_toriw(jit_state_t *_jit, int o, int rd, int im) +T1_ORR(jit_state_t *_jit, int32_t rdn, int32_t rm) { - jit_thumb_t thumb; - assert(!(im & 0xffff0000)); - thumb.i = o|((im&0xf000)<<4)|((im&0x800)<<15)|((im&0x700)<<4)|(_u4(rd)<<8)|(im&0xff); - iss(thumb.s[0], thumb.s[1]); + return emit_u16(_jit, THUMB_ORR|(_u3(rm)<<3)|_u3(rdn)); } static void -_tc8(jit_state_t *_jit, int cc, int im) +T2_ORR(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t rm) { - assert(!(cc & 0x0fffffff)); - assert(cc != ARM_CC_AL && cc != ARM_CC_NV); - assert(im >= -128 && im <= 127); - is(THUMB_CC_B|(cc>>20)|(im&0xff)); + return torrr(_jit, THUMB2_ORR,rn,rd,rm); } static void -_t11(jit_state_t *_jit, int im) +T2_ORRI(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t im) { - assert(!(im & 0xfffff800)); - is(THUMB_B|im); + return torri(_jit, THUMB2_ORRI,rn,rd,im); } static void -_tcb(jit_state_t *_jit, int cc, int im) +T1_EOR(jit_state_t *_jit, int32_t rdn, int32_t rm) { - jit_thumb_t thumb; - assert(!(cc & 0xfffffff)); - assert(cc != ARM_CC_AL && cc != ARM_CC_NV); - cc = ((uint32_t)cc) >> 6; - assert(!(im & (THUMB2_CC_B|cc))); - thumb.i = THUMB2_CC_B|cc|im; - iss(thumb.s[0], thumb.s[1]); + return emit_u16(_jit, THUMB_EOR|(_u3(rm)<<3)|_u3(rdn)); } static void -_blxi(jit_state_t *_jit, int im) +T2_EOR(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t rm) { - assert(!(im & 0xfe000000)); - ii(ARM_BLXI|im); + return torrr(_jit, THUMB2_EOR,rn,rd,rm); } static void -_tb(jit_state_t *_jit, int o, int im) +T2_EORI(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t im) { - jit_thumb_t thumb; - assert(!(o & 0x07ff2fff)); - assert(!(o & im)); - thumb.i = o|im; - iss(thumb.s[0], thumb.s[1]); + return torri(_jit, THUMB2_EORI,rn,rd,im); } static void -_corrrr(jit_state_t *_jit, int cc, int o, int rh, int rl, int rm, int rn) +T1_MOV(jit_state_t *_jit, int32_t rd, int32_t rm) { - assert(!(cc & 0x0fffffff)); - assert(!(o & 0xf00fff0f)); - ii(cc|o|(_u4(rh)<<16)|(_u4(rl)<<12)|(_u4(rm)<<8)|_u4(rn)); + return emit_u16(_jit, THUMB_MOV|((_u4(rd)&8)<<4)|(_u4(rm)<<3)|(rd&7)); } static void -_corrrs(jit_state_t *_jit, int cc, int o, int rn, int rd, int rm, int im) +T2_MOV(jit_state_t *_jit, int32_t rd, int32_t rm) { - assert(!(cc & 0x0fffffff)); - assert(!(o & 0xf000ff8f)); - ii(cc|o|(_u4(rd)<<12)|(_u4(rn)<<16)|(im<<7)|_u4(rm)); + return T2_ORR(_jit, rd,_NOREG,rm); } static void -_cshift(jit_state_t *_jit, int cc, int o, int rd, int rm, int rn, int im) +T1_MOVI(jit_state_t *_jit, int32_t rd, int32_t im) { - assert(!(cc & 0x0fffffff)); - assert(!(o & 0xffe0ff8f)); - assert(((_u4(rm)<<8)&(im<<7)) == 0); - ii(cc|ARM_SHIFT|o|(_u4(rd)<<12)|(_u4(rm)<<8)|(im<<7)|_u4(rn)); + return emit_u16(_jit, THUMB_MOVI|(_u3(rd)<<8)|_u8(im)); } static void -_cb(jit_state_t *_jit, int cc, int o, int im) +T2_MOVI(jit_state_t *_jit, int32_t rd, int32_t im) { - assert(!(cc & 0x0fffffff)); - assert(!(o & 0xf0ffffff)); - ii(cc|o|_u24(im)); + return torri(_jit, THUMB2_MOVI,_NOREG,rd,im); } static void -_cbx(jit_state_t *_jit, int cc, int o, int rm) +T2_MOVWI(jit_state_t *_jit, int32_t rd, int32_t im) { - assert(!(cc & 0x0fffffff)); - assert(!(o & 0xf000000f)); - ii(cc|o|_u4(rm)); + return toriw(_jit, THUMB2_MOVWI,rd,im); } static void -_corl(jit_state_t *_jit, int cc, int o, int r0, int i0) +T2_MOVTI(jit_state_t *_jit, int32_t rd, int32_t im) { - assert(!(cc & 0x0fffffff)); - assert(!(o & 0xf00fffff)); - ii(cc|o|(_u4(r0)<<16)|_u16(i0)); + return toriw(_jit, THUMB2_MOVTI,rd,im); } static void -_c6orr(jit_state_t *_jit, int cc, int o, int rd, int rm) +T1_MVN(jit_state_t *_jit, int32_t rd, int32_t rm) { - assert(!(cc & 0x0fffffff)); - assert(!(o & 0xf000f00f)); - ii(cc|o|(_u4(rd)<<12)|_u4(rm)); + return emit_u16(_jit, THUMB_MVN|(_u3(rm)<<3)|_u3(rd)); } static void -_tpp(jit_state_t *_jit, int o, int im) +T2_MVN(jit_state_t *_jit, int32_t rd, int32_t rm) { - jit_thumb_t thumb; - assert(!(o & 0x0000ffff)); - if (o == THUMB2_PUSH) - assert(!(im & 0x8000)); - assert(__builtin_popcount(im & 0x1fff) > 1); - thumb.i = o|im; - iss(thumb.s[0], thumb.s[1]); + return torrr(_jit, THUMB2_MVN,_NOREG,rd,rm); } static void -_torl(jit_state_t *_jit, int o, int rn, int im) +T2_MVNI(jit_state_t *_jit, int32_t rd, int32_t im) { - jit_thumb_t thumb; - assert(!(o & 0xf1fff)); - assert(rn != _R15 || !im || ((o & 0xc000) == 0xc000)); - assert(!(o & THUMB2_LDM_W) || !(im & (1 << rn))); - thumb.i = o | (_u4(rn)<<16)|_u13(im); - iss(thumb.s[0], thumb.s[1]); + return torri(_jit, THUMB2_MVNI,_NOREG,rd,im); } static void -_nop(jit_state_t *_jit, int32_t i0) +T1_NOT(jit_state_t *_jit, int32_t rd, int32_t rm) { - if (jit_thumb_p()) { - for (; i0 > 0; i0 -= 2) - T1_NOP(); - } - else { - for (; i0 > 0; i0 -= 4) - NOP(); - } - assert(i0 == 0); + return T1_MVN(_jit, rd,rm); } static void -_movr(jit_state_t *_jit, int32_t r0, int32_t r1) +T2_NOT(jit_state_t *_jit, int32_t rd, int32_t rm) { - if (r0 != r1) { - if (jit_thumb_p()) - T1_MOV(r0, r1); - else - MOV(r0, r1); - } + return T2_MVN(_jit, rd,rm); } static void -_movi(jit_state_t *_jit, int32_t r0, jit_word_t i0) +T1_NOP(jit_state_t *_jit) { - int i; - if (jit_thumb_p()) { - if (!jit_no_set_flags() && r0 < 8 && !(i0 & 0xffffff80)) - T1_MOVI(r0, i0); - else if ((i = encode_thumb_immediate(i0)) != -1) - T2_MOVI(r0, i); - else if ((i = encode_thumb_immediate(~i0)) != -1) - T2_MVNI(r0, i); - else { - T2_MOVWI(r0, (uint16_t)i0); - if (i0 & 0xffff0000) - T2_MOVTI(r0, (uint16_t)((unsigned)i0 >> 16)); - } - } - else { - if (jit_armv6_p() && !(i0 & 0xffff0000)) - MOVWI(r0, i0); - else if ((i = encode_arm_immediate(i0)) != -1) - MOVI(r0, i); - else if ((i = encode_arm_immediate(~i0)) != -1) - MVNI(r0, i); - else if (jit_armv6_p()) { - MOVWI(r0, (uint16_t)(i0)); - if ((i0 & 0xffff0000)) - MOVTI(r0, (uint16_t)((unsigned)i0 >> 16)); - } - else - load_const(0, r0, i0); - } -} - -static jit_word_t -_movi_p(jit_state_t *_jit, int32_t r0, jit_word_t i0) -{ - jit_word_t w; - w = _jit->pc.w; - if (jit_thumb_p()) { - T2_MOVWI(r0, (uint16_t)(i0)); - T2_MOVTI(r0, (uint16_t)((unsigned)i0 >> 16)); - } - else - load_const(1, r0, 0); - return (w); + return emit_u16(_jit, 0xbf00); } static void -_comr(jit_state_t *_jit, int32_t r0, int32_t r1) +T1_ADD(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t rm) { - if (jit_thumb_p()) { - if (!jit_no_set_flags() && (r0|r1) < 8) - T1_NOT(r0, r1); - else - T2_NOT(r0, r1); - } - else - NOT(r0, r1); + return emit_u16(_jit, THUMB_ADD|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rd)); } static void -_negr(jit_state_t *_jit, int32_t r0, int32_t r1) +T1_ADDX(jit_state_t *_jit, int32_t rdn, int32_t rm) { - if (jit_thumb_p()) { - if (!jit_no_set_flags() && (r0|r1) < 8) - T1_RSBI(r0, r1); - else - T2_RSBI(r0, r1, 0); - } - else - RSBI(r0, r1, 0); + return emit_u16(_jit, THUMB_ADDX|((_u4(rdn)&8)<<4)|(_u4(rm)<<3)|(rdn&7)); } static void -_addr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +T2_ADD(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t rm) { - if (jit_thumb_p()) { - if (!jit_no_set_flags() && (r0|r1|r2) < 8) - T1_ADD(r0, r1, r2); - else if (r0 == r1 || r0 == r2) - T1_ADDX(r0, r0 == r1 ? r2 : r1); - else - T2_ADD(r0, r1, r2); - } - else - ADD(r0, r1, r2); + return torrr(_jit, THUMB2_ADD,rn,rd,rm); } static void -_addi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +T1_ADDI3(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t im) { - int i; - int32_t reg; - if (jit_thumb_p()) { - if (!jit_no_set_flags() && (r0|r1) < 8 && !(i0 & ~7)) - T1_ADDI3(r0, r1, i0); - else if (!jit_no_set_flags() && (r0|r1) < 8 && !(-i0 & ~7)) - T1_SUBI3(r0, r1, -i0); - else if (!jit_no_set_flags() && r0 < 8 && r0 == r1 && !(i0 & ~0xff)) - T1_ADDI8(r0, i0); - else if (!jit_no_set_flags() && r0 < 8 && r0 == r1 && !(-i0 & ~0xff)) - T1_SUBI8(r0, -i0); - else if ((i = encode_thumb_immediate(i0)) != -1) - T2_ADDI(r0, r1, i); - else if ((i = encode_thumb_immediate(-i0)) != -1) - T2_SUBI(r0, r1, i); - else if ((i = encode_thumb_word_immediate(i0)) != -1) - T2_ADDWI(r0, r1, i); - else if ((i = encode_thumb_word_immediate(-i0)) != -1) - T2_SUBWI(r0, r1, i); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - T2_ADD(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - } - else { - if ((i = encode_arm_immediate(i0)) != -1) - ADDI(r0, r1, i); - else if ((i = encode_arm_immediate(-i0)) != -1) - SUBI(r0, r1, i); - else if (r0 != r1) { - movi(r0, i0); - ADD(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - ADD(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - } + return emit_u16(_jit, THUMB_ADDI3|(_u3(im)<<6)|(_u3(rn)<<3)|_u3(rd)); } static void -_addcr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +T1_ADDI8(jit_state_t *_jit, int32_t rdn, int32_t im) { - if (jit_thumb_p()) { - /* thumb auto set carry if not inside IT block */ - if ((r0|r1|r2) < 8) - T1_ADD(r0, r1, r2); - else - T2_ADDS(r0, r1, r2); - } - else - ADDS(r0, r1, r2); + return emit_u16(_jit, THUMB_ADDI8|(_u3(rdn)<<8)|_u8(im)); } static void -_addci(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +T2_ADDI(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t im) { - int i; - int32_t reg; - if (jit_thumb_p()) { - if ((r0|r1) < 8 && !(i0 & ~7)) - T1_ADDI3(r0, r1, i0); - else if ((r0|r1) < 8 && !(-i0 & ~7)) - T1_SUBI3(r0, r1, -i0); - else if (r0 < 8 && r0 == r1 && !(i0 & ~0xff)) - T1_ADDI8(r0, i0); - else if (r0 < 8 && r0 == r1 && !(-i0 & ~0xff)) - T1_SUBI8(r0, -i0); - else if ((i = encode_thumb_immediate(i0)) != -1) - T2_ADDSI(r0, r1, i); - else if ((i = encode_thumb_immediate(-i0)) != -1) - T2_SUBSI(r0, r1, i); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - T2_ADDS(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - } - else { - if ((i = encode_arm_immediate(i0)) != -1) - ADDSI(r0, r1, i); - else if ((i = encode_arm_immediate(-i0)) != -1) - SUBSI(r0, r1, i); - else if (r0 != r1) { - movi(r0, i0); - ADDS(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - ADDS(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - } + return torri(_jit, THUMB2_ADDI,rn,rd,im); } static void -_addxr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +T2_ADDWI(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t im) { - /* keep setting carry because don't know last ADC */ - if (jit_thumb_p()) { - /* thumb auto set carry if not inside IT block */ - if ((r0|r1|r2) < 8 && (r0 == r1 || r0 == r2)) - T1_ADC(r0, r0 == r1 ? r2 : r1); - else - T2_ADCS(r0, r1, r2); - } - else - ADCS(r0, r1, r2); + return torri(_jit, THUMB2_ADDWI,rn,rd,im); } static void -_addxi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +T2_ADDS(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t rm) { - int i; - int32_t reg; - int no_set_flags; - if (jit_thumb_p()) { - no_set_flags = jit_no_set_flags(); - jit_no_set_flags() = 1; - if ((i = encode_thumb_immediate(i0)) != -1) - T2_ADCSI(r0, r1, i); - else if ((i = encode_thumb_immediate(-i0)) != -1) - T2_SBCSI(r0, r1, i); - else if (r0 != r1) { - movi(r0, i0); - T2_ADCS(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - T2_ADCS(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - jit_no_set_flags() = no_set_flags; - } - else { - if ((i = encode_arm_immediate(i0)) != -1) - ADCSI(r0, r1, i); - else if ((i = encode_arm_immediate(-i0)) != -1) - SBCSI(r0, r1, i); - else if (r0 != r1) { - movi(r0, i0); - ADCS(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - ADCS(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - } + return torrr(_jit, THUMB2_ADD|ARM_S,rn,rd,rm); } static void -_subr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +T2_ADDSI(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t im) { - if (jit_thumb_p()) { - if (!jit_no_set_flags() && (r0|r1|r2) < 8) - T1_SUB(r0, r1, r2); - else - T2_SUB(r0, r1, r2); - } - else - SUB(r0, r1, r2); + return torri(_jit, THUMB2_ADDI|ARM_S,rn,rd,im); } static void -_subi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +T1_ADC(jit_state_t *_jit, int32_t rdn, int32_t rm) { - int i; - int32_t reg; - if (jit_thumb_p()) { - if (!jit_no_set_flags() && (r0|r1) < 8 && !(i0 & ~7)) - T1_SUBI3(r0, r1, i0); - else if (!jit_no_set_flags() && (r0|r1) < 8 && !(-i0 & ~7)) - T1_ADDI3(r0, r1, -i0); - else if (!jit_no_set_flags() && r0 < 8 && r0 == r1 && !(i0 & ~0xff)) - T1_SUBI8(r0, i0); - else if (!jit_no_set_flags() && r0 < 8 && r0 == r1 && !(-i0 & ~0xff)) - T1_ADDI8(r0, -i0); - else if ((i = encode_thumb_immediate(i0)) != -1) - T2_SUBI(r0, r1, i); - else if ((i = encode_thumb_immediate(-i0)) != -1) - T2_ADDI(r0, r1, i); - else if ((i = encode_thumb_word_immediate(i0)) != -1) - T2_SUBWI(r0, r1, i); - else if ((i = encode_thumb_word_immediate(-i0)) != -1) - T2_ADDWI(r0, r1, i); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - T2_SUB(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - } - else { - if ((i = encode_arm_immediate(i0)) != -1) - SUBI(r0, r1, i); - else if ((i = encode_arm_immediate(-i0)) != -1) - ADDI(r0, r1, i); - else if (r0 != r1) { - movi(r0, i0); - SUB(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - SUB(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - } + return emit_u16(_jit, THUMB_ADC|(_u3(rm)<<3)|_u3(rdn)); } static void -_subcr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +T2_ADCS(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t rm) { - if (jit_thumb_p()) { - /* thumb auto set carry if not inside IT block */ - if ((r0|r1|r2) < 8) - T1_SUB(r0, r1, r2); - else - T2_SUBS(r0, r1, r2); - } - else - SUBS(r0, r1, r2); + return torrr(_jit, THUMB2_ADC|ARM_S,rn,rd,rm); } static void -_subci(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +T2_ADCSI(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t im) { - int i; - int32_t reg; - if (jit_thumb_p()) { - if ((r0|r1) < 8 && !(i0 & ~7)) - T1_SUBI3(r0, r1, i0); - else if ((r0|r1) < 8 && !(-i0 & ~7)) - T1_ADDI3(r0, r1, -i0); - else if (r0 < 8 && r0 == r1 && !(i0 & ~0xff)) - T1_SUBI8(r0, i0); - else if (r0 < 8 && r0 == r1 && !(-i0 & ~0xff)) - T1_ADDI8(r0, -i0); - else if ((i = encode_thumb_immediate(i0)) != -1) - T2_SUBSI(r0, r1, i); - else if ((i = encode_thumb_immediate(-i0)) != -1) - T2_ADDSI(r0, r1, i); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - T2_SUBS(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - } - else { - if ((i = encode_arm_immediate(i0)) != -1) - SUBSI(r0, r1, i); - else if ((i = encode_arm_immediate(-i0)) != -1) - ADDSI(r0, r1, i); - else if (r0 != r1) { - movi(r0, i0); - SUBS(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - SUBS(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - } + return torri(_jit, THUMB2_ADCI|ARM_S,rn,rd,im); } static void -_subxr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +T1_SUB(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t rm) { - /* keep setting carry because don't know last SBC */ - if (jit_thumb_p()) { - /* thumb auto set carry if not inside IT block */ - if ((r0|r1|r2) < 8 && r0 == r1) - T1_SBC(r0, r2); - else - T2_SBCS(r0, r1, r2); - } - else - SBCS(r0, r1, r2); + return emit_u16(_jit, THUMB_SUB|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rd)); } static void -_subxi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +T2_SUB(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t rm) { - int i; - int32_t reg; - int no_set_flags; - if (jit_thumb_p()) { - no_set_flags = jit_no_set_flags(); - jit_no_set_flags() = 1; - if ((i = encode_arm_immediate(i0)) != -1) - T2_SBCSI(r0, r1, i); - else if ((i = encode_arm_immediate(-i0)) != -1) - T2_ADCSI(r0, r1, i); - else if (r0 != r1) { - movi(r0, i0); - T2_SBCS(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - SBCS(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - jit_no_set_flags() = no_set_flags; - } - else { - if ((i = encode_arm_immediate(i0)) != -1) - SBCSI(r0, r1, i); - else if ((i = encode_arm_immediate(-i0)) != -1) - ADCSI(r0, r1, i); - else if (r0 != r1) { - movi(r0, i0); - SBCS(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - SBCS(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - } + return torrr(_jit, THUMB2_SUB,rn,rd,rm); } static void -_rsbi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +T1_SUBI3(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t im) { - subi(r0, r1, i0); - negr(r0, r0); + return emit_u16(_jit, THUMB_SUBI3|(_u3(im)<<6)|(_u3(rn)<<3)|_u3(rd)); } static void -_mulr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +T1_SUBI8(jit_state_t *_jit, int32_t rdn, int32_t im) { - int32_t reg; - if (jit_thumb_p()) { - if (!jit_no_set_flags() && r0 == r2 && (r0|r1) < 8) - T1_MUL(r0, r1); - else if (!jit_no_set_flags() && r0 == r1 && (r0|r2) < 8) - T1_MUL(r0, r2); - else - T2_MUL(r0, r1, r2); - } - else { - if (r0 == r1 && !jit_armv6_p()) { - if (r0 != r2) - MUL(r0, r2, r1); - else { - reg = jit_get_reg(jit_class_gpr); - MOV(rn(reg), r1); - MUL(r0, rn(reg), r2); - jit_unget_reg(reg); - } - } - else - MUL(r0, r1, r2); - } + return emit_u16(_jit, THUMB_SUBI8|(_u3(rdn)<<8)|_u8(im)); } static void -_muli(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +T2_SUBI(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t im) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - mulr(r0, r1, rn(reg)); - jit_unget_reg(reg); + return torri(_jit, THUMB2_SUBI,rn,rd,im); } static void -_iqmulr(jit_state_t *_jit, int32_t r0, int32_t r1, +T2_SUBWI(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t im) +{ + return torri(_jit, THUMB2_SUBWI,rn,rd,im); +} + +static void +T2_SUBS(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t rm) +{ + return torrr(_jit, THUMB2_SUB|ARM_S,rn,rd,rm); +} + +static void +T2_SUBSI(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t im) +{ + return torri(_jit, THUMB2_SUBI|ARM_S,rn,rd,im); +} + +static void +T1_SBC(jit_state_t *_jit, int32_t rdn, int32_t rm) +{ + return emit_u16(_jit, THUMB_SBC|(_u3(rm)<<3)|_u3(rdn)); +} + +static void +T2_SBCS(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t rm) +{ + return torrr(_jit, THUMB2_SBC|ARM_S,rn,rd,rm); +} + +static void +T2_SBCSI(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t im) +{ + return torri(_jit, THUMB2_SBCI|ARM_S,rn,rd,im); +} + +static void +T1_RSBI(jit_state_t *_jit, int32_t rd, int32_t rn) +{ + return emit_u16(_jit, THUMB_RSBI|(_u3(rn)<<3)|_u3(rd)); +} + +static void +T2_RSBI(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t im) +{ + return torri(_jit, THUMB2_RSBI,rn,rd,im); +} + +static void +T1_MUL(jit_state_t *_jit, int32_t rdm, int32_t rn) +{ + return emit_u16(_jit, THUMB_MUL|(_u3(rn)<<3)|_u3(rdm)); +} + +static void +T2_MUL(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t rm) +{ + return torrr(_jit, THUMB2_MUL,rn,rd,rm); +} + +static void +T2_SMULL(jit_state_t *_jit, int32_t rl, int32_t rh, int32_t rn, int32_t rm) +{ + return torrrr(_jit, THUMB2_SMULL,rn,rl,rh,rm); +} + +static void +T2_UMULL(jit_state_t *_jit, int32_t rl, int32_t rh, int32_t rn, int32_t rm) +{ + return torrrr(_jit, THUMB2_UMULL,rn,rl,rh,rm); +} + +static void +T2_SDIV(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t rm) +{ + return torrr(_jit, THUMB2_SDIV,rn,rd,rm); +} + +static void +T2_UDIV(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t rm) +{ + return torrr(_jit, THUMB2_UDIV,rn,rd,rm); +} + +static void +T1_MLS(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t rm, int32_t ra) +{ + return torrrr(_jit, THUMB_MLS, ra, rn, rd, rm); +} + +static void +T1_AND(jit_state_t *_jit, int32_t rdn, int32_t rm) +{ + return emit_u16(_jit, THUMB_AND|(_u3(rm)<<3)|_u3(rdn)); +} + +static void +T2_AND(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t rm) +{ + return torrr(_jit, THUMB2_AND,rn,rd,rm); +} + +static void +T2_ANDI(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t im) +{ + return torri(_jit, THUMB2_ANDI,rn,rd,im); +} + +static void +T2_BICI(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t im) +{ + return torri(_jit, THUMB2_BICI,rn,rd,im); +} + +static void +T1_REV(jit_state_t *_jit, int32_t rd, int32_t rm) +{ + return emit_u16(_jit, THUMB_REV|(_u3(rm)<<3)|_u3(rd)); +} + +static void +T2_REV(jit_state_t *_jit, int32_t rd, int32_t rm) +{ + return torrr(_jit, THUMB2_REV,rm,rd,rm); +} + +static void +T1_SXTB(jit_state_t *_jit, int32_t rd, int32_t rm) +{ + return emit_u16(_jit, THUMB_SXTB|(_u3(rm)<<3)|_u3(rd)); +} + +static void +T2_SXTB(jit_state_t *_jit, int32_t rd, int32_t rm) +{ + return torrr(_jit, THUMB2_SXTB,_NOREG,rd,rm); +} + +static void +T1_UXTB(jit_state_t *_jit, int32_t rd, int32_t rm) +{ + return emit_u16(_jit, THUMB_UXTB|(_u3(rm)<<3)|_u3(rd)); +} + +static void +T2_UXTB(jit_state_t *_jit, int32_t rd, int32_t rm) +{ + return torrr(_jit, THUMB2_UXTB,_NOREG,rd,rm); +} + +static void +T1_SXTH(jit_state_t *_jit, int32_t rd, int32_t rm) +{ + return emit_u16(_jit, THUMB_SXTH|(_u3(rm)<<3)|_u3(rd)); +} + +static void +T2_SXTH(jit_state_t *_jit, int32_t rd, int32_t rm) +{ + return torrr(_jit, THUMB2_SXTH,_NOREG,rd,rm); +} + +static void +T1_UXTH(jit_state_t *_jit, int32_t rd, int32_t rm) +{ + return emit_u16(_jit, THUMB_UXTH|(_u3(rm)<<3)|_u3(rd)); +} + +static void +T2_UXTH(jit_state_t *_jit, int32_t rd, int32_t rm) +{ + return torrr(_jit, THUMB2_UXTH,_NOREG,rd,rm); +} + +static void +T1_LSL(jit_state_t *_jit, int32_t rdn, int32_t rm) +{ + return emit_u16(_jit, THUMB_LSL|(_u3(rm)<<3)|_u3(rdn)); +} + +static void +T2_LSL(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t rm) +{ + return torrr(_jit, THUMB2_LSL,rn,rd,rm); +} + +static void +T1_LSLI(jit_state_t *_jit, int32_t rd, int32_t rm, int32_t im) +{ + return emit_u16(_jit, THUMB_LSLI|(_u5(im)<<6)|(_u3(rm)<<3)|_u3(rd)); +} + +static void +T2_LSLI(jit_state_t *_jit, int32_t rd, int32_t rm, int32_t im) +{ + return tshift(_jit, THUMB2_LSLI,rd,rm,im); +} + +static void +T1_LSR(jit_state_t *_jit, int32_t rdn, int32_t rm) +{ + return emit_u16(_jit, THUMB_LSR|(_u3(rm)<<3)|_u3(rdn)); +} + +static void +T2_LSR(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t rm) +{ + return torrr(_jit, THUMB2_LSR,rn,rd,rm); +} + +static void +T1_LSRI(jit_state_t *_jit, int32_t rd, int32_t rm, int32_t im) +{ + return emit_u16(_jit, THUMB_LSRI|(_u5(im)<<6)|(_u3(rm)<<3)|_u3(rd)); +} + +static void +T2_LSRI(jit_state_t *_jit, int32_t rd, int32_t rm, int32_t im) +{ + return tshift(_jit, THUMB2_LSRI,rd,rm,im); +} + +static void +T1_ASR(jit_state_t *_jit, int32_t rdn, int32_t rm) +{ + return emit_u16(_jit, THUMB_ASR|(_u3(rm)<<3)|_u3(rdn)); +} + +static void +T2_ASR(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t rm) +{ + return torrr(_jit, THUMB2_ASR,rn,rd,rm); +} + +static void +T1_ASRI(jit_state_t *_jit, int32_t rd, int32_t rm, int32_t im) +{ + return emit_u16(_jit, THUMB_ASRI|(_u5(im)<<6)|(_u3(rm)<<3)|_u3(rd)); +} + +static void +T2_ASRI(jit_state_t *_jit, int32_t rd, int32_t rm, int32_t im) +{ + return tshift(_jit, THUMB2_ASRI,rd,rm,im); +} + +static void +T1_CMP(jit_state_t *_jit, int32_t rn, int32_t rm) +{ + return emit_u16(_jit, THUMB_CMP|(_u3(rm)<<3)|_u3(rn)); +} + +static void +T1_CMPX(jit_state_t *_jit, int32_t rn, int32_t rm) +{ + return emit_u16(_jit, THUMB_CMPX|((_u4(rn)&8)<<4)|(_u4(rm)<<3)|(rn&7)); +} + +static void +T2_CMP(jit_state_t *_jit, int32_t rn, int32_t rm) +{ + return torrr(_jit, THUMB2_CMP,rn,_NOREG,rm); +} + +static void +T1_CMPI(jit_state_t *_jit, int32_t rn, int32_t im) +{ + return emit_u16(_jit, THUMB_CMPI|(_u3(rn)<<8)|_u8(im)); +} + +static void +T2_CMPI(jit_state_t *_jit, int32_t rn, int32_t im) +{ + return torri(_jit, THUMB2_CMPI,rn,_NOREG,im); +} + +static void +T2_CMNI(jit_state_t *_jit, int32_t rn, int32_t im) +{ + return torri(_jit, THUMB2_CMNI,rn,_NOREG,im); +} + +static void +T1_TST(jit_state_t *_jit, int32_t rn, int32_t rm) +{ + return emit_u16(_jit, THUMB_TST|(_u3(rm)<<3)|_u3(rn)); +} + +static void +T2_TST(jit_state_t *_jit, int32_t rn, int32_t rm) +{ + return torrr(_jit, THUMB2_TST,rn,_NOREG,rm); +} + +static void +T2_TSTI(jit_state_t *_jit, int32_t rn, int32_t im) +{ + return torri(_jit, THUMB2_TSTI,rn,_NOREG,im); +} + +static void +T1_B(jit_state_t *_jit, int32_t im) +{ + return t11(_jit, im); +} + +static jit_reloc_t +T2_CC_B(jit_state_t *_jit, uint8_t cc) +{ + return tcb(_jit, cc); +} + +static jit_reloc_t +T2_B(jit_state_t *_jit) +{ + return tb(_jit, THUMB2_B); +} + +static jit_reloc_t +T2_BLI(jit_state_t *_jit) +{ + return tb(_jit, THUMB2_BLI); +} + +static void +T1_LDRSB(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t rm) +{ + return emit_u16(_jit, THUMB_LDRSB|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt)); +} + +static void +T2_LDRSB(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t rm) +{ + return torxr(_jit, THUMB2_LDRSB,rn,rt,rm); +} + +static void +T2_LDRSBI(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t im) +{ + return torri8(_jit, THUMB2_LDRSBI|THUMB2_U,rn,rt,im); +} + +static void +T2_LDRSBWI(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t im) +{ + return torri12(_jit, THUMB2_LDRSBWI,rn,rt,im); +} + +static void +T2_LDRSBIN(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t im) +{ + return torri8(_jit, THUMB2_LDRSBI,rn,rt,im); +} + +static void +T1_LDRB(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t rm) +{ + return emit_u16(_jit, THUMB_LDRB|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt)); +} + +static void +T2_LDRB(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t rm) +{ + return torxr(_jit, THUMB2_LDRB,rn,rt,rm); +} + +static void +T1_LDRBI(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t im) +{ + return emit_u16(_jit, THUMB_LDRBI|(_u5(im)<<6)|(_u3(rn)<<3)|_u3(rt)); +} + +static void +T2_LDRBI(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t im) +{ + return torri8(_jit, THUMB2_LDRBI|THUMB2_U,rn,rt,im); +} + +static void +T2_LDRBWI(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t im) +{ + return torri12(_jit, THUMB2_LDRBWI,rn,rt,im); +} + +static void +T2_LDRBIN(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t im) +{ + return torri8(_jit, THUMB2_LDRBI,rn,rt,im); +} + +static void +T1_LDRSH(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t rm) +{ + return emit_u16(_jit, THUMB_LDRSH|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt)); +} + +static void +T2_LDRSH(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t rm) +{ + return torxr(_jit, THUMB2_LDRSH,rn,rt,rm); +} + +static void +T2_LDRSHI(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t im) +{ + return torri8(_jit, THUMB2_LDRSHI|THUMB2_U,rn,rt,im); +} + +static void +T2_LDRSHWI(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t im) +{ + return torri12(_jit, THUMB2_LDRSHWI,rn,rt,im); +} + +static void +T2_LDRSHIN(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t im) +{ + return torri8(_jit, THUMB2_LDRSHI,rn,rt,im); +} + +static void +T1_LDRH(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t rm) +{ + return emit_u16(_jit, THUMB_LDRH|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt)); +} + +static void +T2_LDRH(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t rm) +{ + return torxr(_jit, THUMB2_LDRH,rn,rt,rm); +} + +static void +T1_LDRHI(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t im) +{ + return emit_u16(_jit, THUMB_LDRHI|(_u5(im)<<6)|(_u3(rn)<<3)|_u3(rt)); +} + +static void +T2_LDRHI(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t im) +{ + return torri8(_jit, THUMB2_LDRHI|THUMB2_U,rn,rt,im); +} + +static void +T2_LDRHWI(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t im) +{ + return torri12(_jit, THUMB2_LDRHWI,rn,rt,im); +} + +static void +T2_LDRHIN(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t im) +{ + return torri8(_jit, THUMB2_LDRHI,rn,rt,im); +} + +static void +T1_LDR(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t rm) +{ + return emit_u16(_jit, THUMB_LDR|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt)); +} + +static void +T2_LDR(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t rm) +{ + return torxr(_jit, THUMB2_LDR,rn,rt,rm); +} + +static void +T1_LDRI(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t im) +{ + return emit_u16(_jit, THUMB_LDRI|(_u5(im)<<6)|(_u3(rn)<<3)|_u3(rt)); +} + +static void +T1_LDRISP(jit_state_t *_jit, int32_t rt, int32_t im) +{ + return emit_u16(_jit, THUMB_LDRISP|(_u3(rt)<<8)|_u8(im)); +} + +static void +T2_LDRI(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t im) +{ + return torri8(_jit, THUMB2_LDRI|THUMB2_U,rn,rt,im); +} + +static void +T2_LDRWI(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t im) +{ + return torri12(_jit, THUMB2_LDRWI,rn,rt,im); +} + +static void +T2_LDRIN(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t im) +{ + return torri8(_jit, THUMB2_LDRI,rn,rt,im); +} + +static void +T1_STRB(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t rm) +{ + return emit_u16(_jit, THUMB_STRB|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt)); +} + +static void +T2_STRB(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t rm) +{ + return torxr(_jit, THUMB2_STRB,rn,rt,rm); +} + +static void +T1_STRBI(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t im) +{ + emit_u16(_jit, THUMB_STRBI | (_u5(im) << 6) | (_u3(rn) << 3) | _u3(rt)); +} + +static void +T2_STRBI(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t im) +{ + return torri8(_jit, THUMB2_STRBI|THUMB2_U,rn,rt,im); +} + +static void +T2_STRBWI(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t im) +{ + return torri12(_jit, THUMB2_STRBWI,rn,rt,im); +} + +static void +T2_STRBIN(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t im) +{ + return torri8(_jit, THUMB2_STRBI,rn,rt,im); +} + +static void +T1_STRH(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t rm) +{ + return emit_u16(_jit, THUMB_STRH|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt)); +} + +static void +T2_STRH(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t rm) +{ + return torxr(_jit, THUMB2_STRH,rn,rt,rm); +} + +static void +T1_STRHI(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t im) +{ + return emit_u16(_jit, THUMB_STRHI|(_u5(im)<<6)|(_u3(rn)<<3)|_u3(rt)); +} + +static void +T2_STRHI(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t im) +{ + return torri8(_jit, THUMB2_STRHI|THUMB2_U,rn,rt,im); +} + +static void +T2_STRHWI(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t im) +{ + return torri12(_jit, THUMB2_STRHWI,rn,rt,im); +} + +static void +T2_STRHIN(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t im) +{ + return torri8(_jit, THUMB2_STRHI,rn,rt,im); +} + +static void +T1_STR(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t rm) +{ + return emit_u16(_jit, THUMB_STR|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt)); +} + +static void +T2_STR(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t rm) +{ + return torxr(_jit, THUMB2_STR,rn,rt,rm); +} + +static void +T1_STRI(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t im) +{ + return emit_u16(_jit, THUMB_STRI|(_u5(im)<<6)|(_u3(rn)<<3)|_u3(rt)); +} + +static void +T1_STRISP(jit_state_t *_jit, int32_t rt, int32_t im) +{ + return emit_u16(_jit, THUMB_STRISP|(_u3(rt)<<8)|(_u8(im))); +} + +static void +T2_STRI(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t im) +{ + return torri8(_jit, THUMB2_STRI|THUMB2_U,rn,rt,im); +} + +static void +T2_STRWI(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t im) +{ + return torri12(_jit, THUMB2_STRWI,rn,rt,im); +} + +static void +T2_STRIN(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t im) +{ + return torri8(_jit, THUMB2_STRI,rn,rt,im); +} + +static void +nop(jit_state_t *_jit, int32_t i0) +{ + for (; i0 > 0; i0 -= 2) + T1_NOP(_jit); + + assert(i0 == 0); +} + +static void +movr(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + if (r0 != r1) { + T1_MOV(_jit, r0, r1); + } +} + +enum preserve_flags { PRESERVE_FLAGS, FLAGS_UNIMPORTANT }; + +static void +_movi(jit_state_t *_jit, int32_t r0, jit_word_t i0, enum preserve_flags flags) +{ + int i; + + if (flags == PRESERVE_FLAGS && r0 < 8 && !(i0 & 0xffffff80)) + T1_MOVI(_jit, r0, i0); + else if (r0 < 8 && !(i0 & 0xffffff80)) + T1_MOVI(_jit, r0, i0); + else if ((i = encode_thumb_immediate(i0)) != -1) + T2_MOVI(_jit, r0, i); + else if ((i = encode_thumb_immediate(~i0)) != -1) + T2_MVNI(_jit, r0, i); + else { + T2_MOVWI(_jit, r0, (uint16_t)i0); + if (i0 & 0xffff0000) + T2_MOVTI(_jit, r0, (uint16_t)((unsigned)i0 >> 16)); + } +} + +static void +movi(jit_state_t *_jit, int32_t r0, jit_word_t i0) +{ + return _movi(_jit, r0, i0, FLAGS_UNIMPORTANT); +} + +static int32_t +decode_load_from_pool_offset(uint32_t inst) +{ + int32_t ret = inst & 0xfff; + return ((inst >> 23) & 1) ? ret : -ret; +} + +static uint32_t +encode_load_from_pool_offset(int32_t off) +{ + ASSERT(-0xfff <= off && off <= 0xfff); + uint32_t u; + if (off >= 0) + u = 1; + else + u = 0, off = -off; + uint32_t ret = (off & 0xfff) | (u << 23); + ASSERT(decode_load_from_pool_offset(ret) == off); + return ret; +} + +static uint32_t +patch_load_from_pool(uint32_t inst, int32_t off) +{ + uint32_t load_from_pool_mask = THUMB2_LDRP | (0xf << 12); + return (inst & load_from_pool_mask) | encode_load_from_pool_offset(off); +} + +static jit_reloc_t +emit_load_from_pool(jit_state_t *_jit, uint32_t inst) +{ + uint8_t *pc_base = (uint8_t *)((_jit->pc.w + 4) & ~3); + uint8_t rsh = 0; + int32_t off = (_jit->pc.uc - pc_base) >> rsh; + jit_reloc_t ret = + jit_reloc (_jit, JIT_RELOC_LOAD_FROM_POOL, 0, _jit->pc.uc, pc_base, rsh); + uint8_t load_from_pool_width = 12; + add_pending_literal(_jit, ret, load_from_pool_width); + emit_wide_thumb(_jit, patch_load_from_pool(inst, off)); + return ret; +} + +static jit_reloc_t +movi_from_pool(jit_state_t *_jit, int32_t Rt) +{ + return emit_load_from_pool(_jit, THUMB2_LDRP | (_u4(Rt) << 12)); +} + +static jit_reloc_t +mov_addr(jit_state_t *_jit, int32_t r0) +{ + return movi_from_pool(_jit, r0); +} + +static void +comr(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + if ((r0|r1) < 8) + T1_NOT(_jit, r0, r1); + else + T2_NOT(_jit, r0, r1); +} + +static void +negr(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + if ((r0|r1) < 8) + T1_RSBI(_jit, r0, r1); + else + T2_RSBI(_jit, r0, r1, 0); +} + +static void +addr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + if ((r0|r1|r2) < 8) + T1_ADD(_jit, r0, r1, r2); + else if (r0 == r1 || r0 == r2) + T1_ADDX(_jit, r0, r0 == r1 ? r2 : r1); + else + T2_ADD(_jit, r0, r1, r2); +} + +static void +addi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + int i; + + if ((r0|r1) < 8 && !(i0 & ~7)) + T1_ADDI3(_jit, r0, r1, i0); + else if ((r0|r1) < 8 && !(-i0 & ~7)) + T1_SUBI3(_jit, r0, r1, -i0); + else if (r0 < 8 && r0 == r1 && !(i0 & ~0xff)) + T1_ADDI8(_jit, r0, i0); + else if (r0 < 8 && r0 == r1 && !(-i0 & ~0xff)) + T1_SUBI8(_jit, r0, -i0); + else if ((i = encode_thumb_immediate(i0)) != -1) + T2_ADDI(_jit, r0, r1, i); + else if ((i = encode_thumb_immediate(-i0)) != -1) + T2_SUBI(_jit, r0, r1, i); + else if ((i = encode_thumb_word_immediate(i0)) != -1) + T2_ADDWI(_jit, r0, r1, i); + else if ((i = encode_thumb_word_immediate(-i0)) != -1) + T2_SUBWI(_jit, r0, r1, i); + else { + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + T2_ADD(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } +} + +static void +addcr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + /* thumb auto set carry if not inside IT block */ + if ((r0|r1|r2) < 8) + T1_ADD(_jit, r0, r1, r2); + else + T2_ADDS(_jit, r0, r1, r2); +} + +static void +addci(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + int i; + + if ((r0|r1) < 8 && !(i0 & ~7)) + T1_ADDI3(_jit, r0, r1, i0); + else if ((r0|r1) < 8 && !(-i0 & ~7)) + T1_SUBI3(_jit, r0, r1, -i0); + else if (r0 < 8 && r0 == r1 && !(i0 & ~0xff)) + T1_ADDI8(_jit, r0, i0); + else if (r0 < 8 && r0 == r1 && !(-i0 & ~0xff)) + T1_SUBI8(_jit, r0, -i0); + else if ((i = encode_thumb_immediate(i0)) != -1) + T2_ADDSI(_jit, r0, r1, i); + else if ((i = encode_thumb_immediate(-i0)) != -1) + T2_SUBSI(_jit, r0, r1, i); + else { + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + T2_ADDS(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } +} + +static void +addxr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + /* keep setting carry because don't know last ADC */ + + /* thumb auto set carry if not inside IT block */ + if ((r0|r1|r2) < 8 && (r0 == r1 || r0 == r2)) + T1_ADC(_jit, r0, r0 == r1 ? r2 : r1); + else + T2_ADCS(_jit, r0, r1, r2); +} + +static void +addxi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + int i; + if ((i = encode_thumb_immediate(i0)) != -1) + T2_ADCSI(_jit, r0, r1, i); + else if ((i = encode_thumb_immediate(-i0)) != -1) + T2_SBCSI(_jit, r0, r1, i); + else if (r0 != r1) { + _movi(_jit, r0, i0, PRESERVE_FLAGS); + T2_ADCS(_jit, r0, r1, r0); + } else { + jit_gpr_t reg = get_temp_gpr(_jit); + _movi(_jit, jit_gpr_regno(reg), i0, PRESERVE_FLAGS); + T2_ADCS(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } +} + +static void +subr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + if ((r0|r1|r2) < 8) + T1_SUB(_jit, r0, r1, r2); + else + T2_SUB(_jit, r0, r1, r2); +} + +static void +subi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + int i; + + if ((r0|r1) < 8 && !(i0 & ~7)) + T1_SUBI3(_jit, r0, r1, i0); + else if ((r0|r1) < 8 && !(-i0 & ~7)) + T1_ADDI3(_jit, r0, r1, -i0); + else if (r0 < 8 && r0 == r1 && !(i0 & ~0xff)) + T1_SUBI8(_jit, r0, i0); + else if (r0 < 8 && r0 == r1 && !(-i0 & ~0xff)) + T1_ADDI8(_jit, r0, -i0); + else if ((i = encode_thumb_immediate(i0)) != -1) + T2_SUBI(_jit, r0, r1, i); + else if ((i = encode_thumb_immediate(-i0)) != -1) + T2_ADDI(_jit, r0, r1, i); + else if ((i = encode_thumb_word_immediate(i0)) != -1) + T2_SUBWI(_jit, r0, r1, i); + else if ((i = encode_thumb_word_immediate(-i0)) != -1) + T2_ADDWI(_jit, r0, r1, i); + else { + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + T2_SUB(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } +} + +static void +subcr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + /* thumb auto set carry if not inside IT block */ + if ((r0|r1|r2) < 8) + T1_SUB(_jit, r0, r1, r2); + else + T2_SUBS(_jit, r0, r1, r2); +} + +static void +subci(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + int i; + + if ((r0|r1) < 8 && !(i0 & ~7)) + T1_SUBI3(_jit, r0, r1, i0); + else if ((r0|r1) < 8 && !(-i0 & ~7)) + T1_ADDI3(_jit, r0, r1, -i0); + else if (r0 < 8 && r0 == r1 && !(i0 & ~0xff)) + T1_SUBI8(_jit, r0, i0); + else if (r0 < 8 && r0 == r1 && !(-i0 & ~0xff)) + T1_ADDI8(_jit, r0, -i0); + else if ((i = encode_thumb_immediate(i0)) != -1) + T2_SUBSI(_jit, r0, r1, i); + else if ((i = encode_thumb_immediate(-i0)) != -1) + T2_ADDSI(_jit, r0, r1, i); + else { + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + T2_SUBS(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } +} + +static void +subxr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + /* keep setting carry because don't know last SBC */ + + /* thumb auto set carry if not inside IT block */ + if ((r0|r1|r2) < 8 && r0 == r1) + T1_SBC(_jit, r0, r2); + else + T2_SBCS(_jit, r0, r1, r2); +} + +static void +subxi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + int i; + if ((i = encode_arm_immediate(i0)) != -1) + T2_SBCSI(_jit, r0, r1, i); + else if ((i = encode_arm_immediate(-i0)) != -1) + T2_ADCSI(_jit, r0, r1, i); + else if (r0 != r1) { + _movi(_jit, r0, i0, PRESERVE_FLAGS); + T2_SBCS(_jit, r0, r1, r0); + } else { + jit_gpr_t reg = get_temp_gpr(_jit); + _movi(_jit, jit_gpr_regno(reg), i0, PRESERVE_FLAGS); + T2_SBCS(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } +} + +static void +mulr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + if (r0 == r2 && (r0|r1) < 8) + T1_MUL(_jit, r0, r1); + else if (r0 == r1 && (r0|r2) < 8) + T1_MUL(_jit, r0, r2); + else + T2_MUL(_jit, r0, r1, r2); +} + +static void +muli(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + mulr(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); +} + +static void +iqmulr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, int32_t r3, jit_bool_t sign) { - int32_t reg; - if (jit_thumb_p()) { - if (r2 == r3) { - reg = jit_get_reg(jit_class_gpr); - movr(rn(reg), r2); - if (sign) - T2_SMULL(r0, r1, rn(reg), r2); - else - T2_UMULL(r0, r1, rn(reg), r2); - jit_unget_reg(reg); - } - else if (r0 != r2 && r1 != r2) { - if (sign) - T2_SMULL(r0, r1, r2, r3); - else - T2_UMULL(r0, r1, r2, r3); - } - else { - if (sign) - T2_SMULL(r0, r1, r3, r2); - else - T2_UMULL(r0, r1, r3, r2); - } - } - else { - if (r2 == r3) { - reg = jit_get_reg(jit_class_gpr); - movr(rn(reg), r2); - if (sign) - SMULL(r0, r1, rn(reg), r2); - else - UMULL(r0, r1, rn(reg), r2); - jit_unget_reg(reg); - } - else if (r0 != r2 && r1 != r2) { - if (sign) - SMULL(r0, r1, r2, r3); - else - UMULL(r0, r1, r2, r3); - } - else { - if (sign) - SMULL(r0, r1, r3, r2); - else - UMULL(r0, r1, r3, r2); - } - } + if (r2 == r3) { + jit_gpr_t reg = get_temp_gpr(_jit); + movr(_jit, jit_gpr_regno(reg), r2); + if (sign) + T2_SMULL(_jit, r0, r1, jit_gpr_regno(reg), r2); + else + T2_UMULL(_jit, r0, r1, jit_gpr_regno(reg), r2); + unget_temp_gpr(_jit); + } else if (r0 != r2 && r1 != r2) { + if (sign) + T2_SMULL(_jit, r0, r1, r2, r3); + else + T2_UMULL(_jit, r0, r1, r2, r3); + } else { + if (sign) + T2_SMULL(_jit, r0, r1, r3, r2); + else + T2_UMULL(_jit, r0, r1, r3, r2); + } } static void -_iqmuli(jit_state_t *_jit, int32_t r0, int32_t r1, +iqmuli(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, jit_word_t i0, jit_bool_t sign) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - iqmulr(r0, r1, r2, rn(reg), sign); - jit_unget_reg(reg); + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + iqmulr(_jit, r0, r1, r2, jit_gpr_regno(reg), sign); + unget_temp_gpr(_jit); } static void -_divrem(jit_state_t *_jit, int div, int sign, - int32_t r0, int32_t r1, int32_t r2) +qmulr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, int32_t r3) { - jit_word_t d; - jit_word_t w; - jit_get_reg_args(); - movr(_R0_REGNO, r1); - movr(_R1_REGNO, r2); - if (sign) w = (jit_word_t)__aeabi_idivmod; - else w = (jit_word_t)__aeabi_uidivmod; - if (!jit_exchange_p()) { - if (jit_thumb_p()) d = ((w - _jit->pc.w) >> 1) - 2; - else d = ((w - _jit->pc.w) >> 2) - 2; - if (_s24P(d)) { - if (jit_thumb_p()) T2_BLI(encode_thumb_jump(d)); - else BLI(d & 0x00ffffff); - } - else goto fallback; - } - else { - fallback: - movi(_R2_REGNO, w); - if (jit_thumb_p()) T1_BLX(_R2_REGNO); - else BLX(_R2_REGNO); - } - if (div) movr(r0, _R0_REGNO); - else movr(r0, _R1_REGNO); - jit_unget_reg_args(); + return iqmulr(_jit, r0,r1,r2,r3,1); } static void -_divr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +qmulr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, int32_t r3) { - if (jit_armv7r_p() && jit_thumb_p()) - T2_SDIV(r0, r1, r2); - else - divrem(1, 1, r0, r1, r2); + return iqmulr(_jit, r0,r1,r2,r3,0); } static void -_divi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +qmuli(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, int32_t i0) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - divr(r0, r1, rn(reg)); - jit_unget_reg(reg); + return iqmuli(_jit, r0,r1,r2,i0,1); } static void -_divr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +qmuli_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, int32_t i0) { - if (jit_armv7r_p() && jit_thumb_p()) - T2_UDIV(r0, r1, r2); - else - divrem(1, 0, r0, r1, r2); + return iqmuli(_jit, r0,r1,r2,i0,0); } static void -_divi_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +divr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - divr_u(r0, r1, rn(reg)); - jit_unget_reg(reg); + T2_SDIV(_jit, r0, r1, r2); } static void -_iqdivr(jit_state_t *_jit, int32_t r0, int32_t r1, +divi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + divr(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); +} + +static void +divr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + T2_UDIV(_jit, r0, r1, r2); +} + +static void +divi_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + divr_u(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); +} + +static void +iqdivr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, int32_t r3, jit_bool_t sign) { - jit_word_t d; - jit_word_t w; - jit_get_reg_args(); - movr(_R0_REGNO, r2); - movr(_R1_REGNO, r3); - if (sign) w = (jit_word_t)__aeabi_idivmod; - else w = (jit_word_t)__aeabi_uidivmod; - if (!jit_exchange_p()) { - if (jit_thumb_p()) d = ((w - _jit->pc.w) >> 1) - 2; - else d = ((w - _jit->pc.w) >> 2) - 2; - if (_s24P(d)) { - if (jit_thumb_p()) T2_BLI(encode_thumb_jump(d)); - else BLI(d & 0x00ffffff); - } - else goto fallback; + int need_tmp = r0 == r2 || r0 == r3; + if (need_tmp) { + int32_t tmp = jit_gpr_regno(get_temp_gpr(_jit)); + if (r0 == r2) { + movr(_jit, tmp, r2); + r2 = tmp; } - else { - fallback: - movi(_R2_REGNO, w); - if (jit_thumb_p()) T1_BLX(_R2_REGNO); - else BLX(_R2_REGNO); + if (r0 == r3) { + if (r2 != r3) + movr(_jit, tmp, r3); + r3 = tmp; } - movr(r0, _R0_REGNO); - movr(r1, _R1_REGNO); - jit_unget_reg_args(); + } + if (sign) + divr(_jit, r0, r2, r3); + else + divr_u(_jit, r0, r2, r3); + T1_MLS(_jit, r1, r0, r3, r2); + if (need_tmp) + unget_temp_gpr(_jit); } static void -_iqdivi(jit_state_t *_jit, int32_t r0, int32_t r1, +iqdivi(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, jit_word_t i0, jit_bool_t sign) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - iqdivr(r0, r1, r2, rn(reg), sign); - jit_unget_reg(reg); + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + iqdivr(_jit, r0, r1, r2, jit_gpr_regno(reg), sign); + unget_temp_gpr(_jit); } static void -_remr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +qdivr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, int32_t r3) { - divrem(0, 1, r0, r1, r2); + return iqdivr(_jit, r0,r1,r2,r3,1); } static void -_remi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +qdivr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, int32_t r3) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - remr(r0, r1, rn(reg)); - jit_unget_reg(reg); + return iqdivr(_jit, r0,r1,r2,r3,0); } static void -_remr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +qdivi(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, int32_t i0) { - divrem(0, 0, r0, r1, r2); + return iqdivi(_jit, r0,r1,r2,i0,1); } static void -_remi_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +qdivi_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, int32_t i0) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - remr_u(r0, r1,rn(reg)); - jit_unget_reg(reg); + return iqdivi(_jit, r0,r1,r2,i0,0); } static void -_andr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +iremr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, jit_bool_t sign) { - if (jit_thumb_p()) { - if (!jit_no_set_flags() && (r0|r1|r2) < 8 && (r0 == r1 || r0 == r2)) - T1_AND(r0, r0 == r1 ? r2 : r1); - else - T2_AND(r0, r1, r2); - } + return iqdivr(_jit, r0, r0, r1, r2, 1); +} + +static void +remr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + return iremr(_jit, r0, r1, r2, 1); +} + +static void +remi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + remr(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); +} + +static void +remr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + return iremr(_jit, r0, r1, r2, 0); +} + +static void +remi_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + remr_u(_jit, r0, r1,jit_gpr_regno(reg)); + unget_temp_gpr(_jit); +} + +static void +andr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + if ((r0|r1|r2) < 8 && (r0 == r1 || r0 == r2)) + T1_AND(_jit, r0, r0 == r1 ? r2 : r1); + else + T2_AND(_jit, r0, r1, r2); +} + +static void +andi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + int i; + + if ((i = encode_thumb_immediate(i0)) != -1) + T2_ANDI(_jit, r0, r1, i); + else if ((i = encode_thumb_immediate(~i0)) != -1) + T2_BICI(_jit, r0, r1, i); + else if (r0 != r1) { + movi(_jit, r0, i0); + T2_AND(_jit, r0, r1, r0); + } else { + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + T2_AND(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } +} + +static void +orr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + if ((r0|r1|r2) < 8 && (r0 == r1 || r0 == r2)) + T1_ORR(_jit, r0, r0 == r1 ? r2 : r1); + else + T2_ORR(_jit, r0, r1, r2); +} + +static void +ori(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + int i; + + if ((i = encode_thumb_immediate(i0)) != -1) + T2_ORRI(_jit, r0, r1, i); + else if (r0 != r1) { + movi(_jit, r0, i0); + T2_ORR(_jit, r0, r1, r0); + } else { + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + T2_ORR(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } +} + +static void +xorr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + if ((r0|r1|r2) < 8 && (r0 == r1 || r0 == r2)) + T1_EOR(_jit, r0, r0 == r1 ? r2 : r1); + else + T2_EOR(_jit, r0, r1, r2); +} + +static void +xori(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + int i; + + if ((i = encode_thumb_immediate(i0)) != -1) + T2_EORI(_jit, r0, r1, i); + else if (r0 != r1) { + movi(_jit, r0, i0); + T2_EOR(_jit, r0, r1, r0); + } else { + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + T2_EOR(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } +} + +static void +lshr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + if ((r0|r1|r2) < 8 && r0 == r1) + T1_LSL(_jit, r0, r2); + else + T2_LSL(_jit, r0, r1, r2); +} + +static void +lshi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + assert(i0 >= 0 && i0 <= 31); + if (i0 == 0) + movr(_jit, r0, r1); + else { + if ((r0|r1) < 8) + T1_LSLI(_jit, r0, r1, i0); else - AND(r0, r1, r2); + T2_LSLI(_jit, r0, r1, i0); + } } static void -_andi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +rshr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - int i; - int32_t reg; - if (jit_thumb_p()) { - if ((i = encode_thumb_immediate(i0)) != -1) - T2_ANDI(r0, r1, i); - else if ((i = encode_thumb_immediate(~i0)) != -1) - T2_BICI(r0, r1, i); - else if (r0 != r1) { - movi(r0, i0); - T2_AND(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - T2_AND(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - } - else { - if ((i = encode_arm_immediate(i0)) != -1) - ANDI(r0, r1, i); - else if ((i = encode_arm_immediate(~i0)) != -1) - BICI(r0, r1, i); - else if (r0 != r1) { - movi(r0, i0); - AND(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - AND(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - } + if ((r0|r1|r2) < 8 && r0 == r1) + T1_ASR(_jit, r0, r2); + else + T2_ASR(_jit, r0, r1, r2); } static void -_orr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +rshi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - if (jit_thumb_p()) { - if (!jit_no_set_flags() && (r0|r1|r2) < 8 && (r0 == r1 || r0 == r2)) - T1_ORR(r0, r0 == r1 ? r2 : r1); - else - T2_ORR(r0, r1, r2); - } + assert(i0 >= 0 && i0 <= 31); + if (i0 == 0) + movr(_jit, r0, r1); + else { + if ((r0|r1) < 8) + T1_ASRI(_jit, r0, r1, i0); else - ORR(r0, r1, r2); + T2_ASRI(_jit, r0, r1, i0); + } } static void -_ori(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +rshr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - int i; - int32_t reg; - if (jit_thumb_p()) { - if ((i = encode_thumb_immediate(i0)) != -1) - T2_ORRI(r0, r1, i); - else if (r0 != r1) { - movi(r0, i0); - T2_ORR(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - T2_ORR(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - } - else { - if ((i = encode_arm_immediate(i0)) != -1) - ORRI(r0, r1, i); - else if (r0 != r1) { - movi(r0, i0); - ORR(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - ORR(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - } + if ((r0|r1|r2) < 8 && r0 == r1) + T1_LSR(_jit, r0, r2); + else + T2_LSR(_jit, r0, r1, r2); } static void -_xorr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +rshi_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - if (jit_thumb_p()) { - if (!jit_no_set_flags() && (r0|r1|r2) < 8 && (r0 == r1 || r0 == r2)) - T1_EOR(r0, r0 == r1 ? r2 : r1); - else - T2_EOR(r0, r1, r2); - } + assert(i0 >= 0 && i0 <= 31); + if (i0 == 0) + movr(_jit, r0, r1); + else { + if ((r0|r1) < 8) + T1_LSRI(_jit, r0, r1, i0); else - EOR(r0, r1, r2); + T2_LSRI(_jit, r0, r1, i0); + } } static void -_xori(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +jmpr(jit_state_t *_jit, int32_t r0) { - int i; - int32_t reg; - if (jit_thumb_p()) { - if ((i = encode_thumb_immediate(i0)) != -1) - T2_EORI(r0, r1, i); - else if (r0 != r1) { - movi(r0, i0); - T2_EOR(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - T2_EOR(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - } - else { - if ((i = encode_arm_immediate(i0)) != -1) - EORI(r0, r1, i); - else if (r0 != r1) { - movi(r0, i0); - EOR(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - EOR(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - } + T1_MOV(_jit, jit_gpr_regno(_PC), r0); +} + +static jit_reloc_t +jmp(jit_state_t *_jit) +{ + return T2_B(_jit); } static void -_lshr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +jmpi(jit_state_t *_jit, jit_word_t i0) { - if (jit_thumb_p()) { - if (!jit_no_set_flags() && (r0|r1|r2) < 8 && r0 == r1) - T1_LSL(r0, r2); - else - T2_LSL(r0, r1, r2); - } - else - LSL(r0, r1, r2); + return jit_patch_there(_jit, jmp(_jit), (void*)i0); +} + +static jit_reloc_t +bccr(jit_state_t *_jit, int cc, int32_t r0, int32_t r1) +{ + if ((r0|r1) < 8) + T1_CMP(_jit, r0, r1); + else if ((r0&r1) & 8) + T1_CMPX(_jit, r0, r1); + else + T2_CMP(_jit, r0, r1); + return T2_CC_B(_jit, cc); +} + +static jit_reloc_t +bcci(jit_state_t *_jit, int cc, int32_t r0, jit_word_t i1) +{ + int i; + if (r0 < 7 && !(i1 & 0xffffff00)) + T1_CMPI(_jit, r0, i1); + else if ((i = encode_thumb_immediate(i1)) != -1) + T2_CMPI(_jit, r0, i); + else if ((i = encode_thumb_immediate(-i1)) != -1) + T2_CMNI(_jit, r0, i); + else { + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i1); + T2_CMP(_jit, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } + return T2_CC_B(_jit, cc); +} + +static jit_reloc_t +bltr(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return bccr(_jit, ARM_CC_LT, r0, r1); +} + +static jit_reloc_t +blti(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return bcci(_jit, ARM_CC_LT, r0, i1); +} + +static jit_reloc_t +bltr_u(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return bccr(_jit, ARM_CC_LO, r0, r1); +} + +static jit_reloc_t +blti_u(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return bcci(_jit, ARM_CC_LO, r0, i1); +} + +static jit_reloc_t +bler(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return bccr(_jit, ARM_CC_LE, r0, r1); +} + +static jit_reloc_t +blei(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return bcci(_jit, ARM_CC_LE, r0, i1); +} + +static jit_reloc_t +bler_u(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return bccr(_jit, ARM_CC_LS, r0, r1); +} + +static jit_reloc_t +blei_u(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return bcci(_jit, ARM_CC_LS, r0, i1); +} + +static jit_reloc_t +beqr(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return bccr(_jit, ARM_CC_EQ, r0, r1); +} + +static jit_reloc_t +beqi(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return bcci(_jit, ARM_CC_EQ, r0, i1); +} + +static jit_reloc_t +bger(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return bccr(_jit, ARM_CC_GE, r0, r1); +} + +static jit_reloc_t +bgei(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return bcci(_jit, ARM_CC_GE, r0, i1); +} + +static jit_reloc_t +bger_u(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return bccr(_jit, ARM_CC_HS, r0, r1); +} + +static jit_reloc_t +bgei_u(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return bcci(_jit, ARM_CC_HS, r0, i1); +} + +static jit_reloc_t +bgtr(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return bccr(_jit, ARM_CC_GT, r0, r1); +} + +static jit_reloc_t +bgti(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return bcci(_jit, ARM_CC_GT, r0, i1); +} + +static jit_reloc_t +bgtr_u(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return bccr(_jit, ARM_CC_HI, r0, r1); +} + +static jit_reloc_t +bgti_u(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return bcci(_jit, ARM_CC_HI, r0, i1); +} + +static jit_reloc_t +bner(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return bccr(_jit, ARM_CC_NE, r0, r1); +} + +static jit_reloc_t +bnei(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return bcci(_jit, ARM_CC_NE, r0, i1); +} + +static jit_reloc_t +baddr(jit_state_t *_jit, int cc, int32_t r0, int32_t r1) +{ + if ((r0|r1) < 8) + T1_ADD(_jit, r0, r0, r1); + else + T2_ADDS(_jit, r0, r0, r1); + return T2_CC_B(_jit, cc); +} + +static jit_reloc_t +baddi(jit_state_t *_jit, int cc, int32_t r0, int i1) +{ + int i; + if (r0 < 8 && !(i1 & ~7)) + T1_ADDI3(_jit, r0, r0, i1); + else if (r0 < 8 && !(-i1 & ~7)) + T1_SUBI3(_jit, r0, r0, -i1); + else if (r0 < 8 && !(i1 & ~0xff)) + T1_ADDI8(_jit, r0, i1); + else if (r0 < 8 && !(-i1 & ~0xff)) + T1_SUBI8(_jit, r0, -i1); + else if ((i = encode_thumb_immediate(i1)) != -1) + T2_ADDSI(_jit, r0, r0, i); + else if ((i = encode_thumb_immediate(-i1)) != -1) + T2_SUBSI(_jit, r0, r0, i); + else { + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i1); + T2_ADDS(_jit, r0, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } + return T2_CC_B(_jit, cc); +} + +static jit_reloc_t +boaddr(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return baddr(_jit, ARM_CC_VS, r0, r1); +} + +static jit_reloc_t +boaddi(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return baddi(_jit, ARM_CC_VS, r0, i1); +} + +static jit_reloc_t +boaddr_u(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return baddr(_jit, ARM_CC_HS, r0, r1); +} + +static jit_reloc_t +boaddi_u(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return baddi(_jit, ARM_CC_HS, r0, i1); +} + +static jit_reloc_t +bxaddr(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return baddr(_jit, ARM_CC_VC, r0, r1); +} + +static jit_reloc_t +bxaddi(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return baddi(_jit, ARM_CC_VC, r0, i1); +} + +static jit_reloc_t +bxaddr_u(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return baddr(_jit, ARM_CC_LO, r0, r1); +} + +static jit_reloc_t +bxaddi_u(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return baddi(_jit, ARM_CC_LO, r0, i1); +} + +static jit_reloc_t +bsubr(jit_state_t *_jit, int cc, int32_t r0, int32_t r1) +{ + if ((r0|r1) < 8) + T1_SUB(_jit, r0, r0, r1); + else + T2_SUBS(_jit, r0, r0, r1); + return T2_CC_B(_jit, cc); +} + +static jit_reloc_t +bsubi(jit_state_t *_jit, int cc, int32_t r0, int i1) +{ + int i; + if (r0 < 8 && !(i1 & ~7)) + T1_SUBI3(_jit, r0, r0, i1); + else if (r0 < 8 && !(-i1 & ~7)) + T1_ADDI3(_jit, r0, r0, -i1); + else if (r0 < 8 && !(i1 & ~0xff)) + T1_SUBI8(_jit, r0, i1); + else if (r0 < 8 && !(-i1 & ~0xff)) + T1_ADDI8(_jit, r0, -i1); + else if ((i = encode_thumb_immediate(i1)) != -1) + T2_SUBSI(_jit, r0, r0, i); + else if ((i = encode_thumb_immediate(-i1)) != -1) + T2_SUBSI(_jit, r0, r0, i); + else { + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i1); + T2_SUBS(_jit, r0, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } + return T2_CC_B(_jit, cc); +} + +static jit_reloc_t +bosubr(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return bsubr(_jit, ARM_CC_VS, r0, r1); +} + +static jit_reloc_t +bosubi(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return bsubi(_jit, ARM_CC_VS, r0, i1); +} + +static jit_reloc_t +bosubr_u(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return bsubr(_jit, ARM_CC_LO, r0, r1); +} + +static jit_reloc_t +bosubi_u(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return bsubi(_jit, ARM_CC_LO, r0, i1); +} + +static jit_reloc_t +bxsubr(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return bsubr(_jit, ARM_CC_VC, r0, r1); +} + +static jit_reloc_t +bxsubi(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return bsubi(_jit, ARM_CC_VC, r0, i1); +} + +static jit_reloc_t +bxsubr_u(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return bsubr(_jit, ARM_CC_HS, r0, r1); +} + +static jit_reloc_t +bxsubi_u(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return bsubi(_jit, ARM_CC_HS, r0, i1); +} + +static jit_reloc_t +bmxr(jit_state_t *_jit, int cc, int32_t r0, int32_t r1) +{ + if ((r0|r1) < 8) + T1_TST(_jit, r0, r1); + else + T2_TST(_jit, r0, r1); + return T2_CC_B(_jit, cc); +} + +static jit_reloc_t +bmxi(jit_state_t *_jit, int cc, int32_t r0, jit_word_t i1) +{ + int i; + if ((i = encode_thumb_immediate(i1)) != -1) + T2_TSTI(_jit, r0, i); + else { + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i1); + T2_TST(_jit, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } + return T2_CC_B(_jit, cc); +} + +static jit_reloc_t +bmsr(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return bmxr(_jit, ARM_CC_NE, r0, r1); +} + +static jit_reloc_t +bmsi(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return bmxi(_jit, ARM_CC_NE, r0, i1); +} + +static jit_reloc_t +bmcr(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return bmxr(_jit, ARM_CC_EQ, r0, r1); +} + +static jit_reloc_t +bmci(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return bmxi(_jit, ARM_CC_EQ, r0, i1); } static void -_lshi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +ldr_c(jit_state_t *_jit, int32_t r0, int32_t r1) { - assert(i0 >= 0 && i0 <= 31); - if (i0 == 0) - movr(r0, r1); - else if (jit_thumb_p()) { - if (!jit_no_set_flags() && (r0|r1) < 8) - T1_LSLI(r0, r1, i0); - else - T2_LSLI(r0, r1, i0); - } - else - LSLI(r0, r1, i0); + T2_LDRSBI(_jit, r0, r1, 0); } static void -_rshr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +ldi_c(jit_state_t *_jit, int32_t r0, jit_word_t i0) { - if (jit_thumb_p()) { - if (!jit_no_set_flags() && (r0|r1|r2) < 8 && r0 == r1) - T1_ASR(r0, r2); - else - T2_ASR(r0, r1, r2); - } - else - ASR(r0, r1, r2); + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + T2_LDRSBI(_jit, r0, jit_gpr_regno(reg), 0); + unget_temp_gpr(_jit); } static void -_rshi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +ldxr_c(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - assert(i0 >= 0 && i0 <= 31); - if (i0 == 0) - movr(r0, r1); - else if (jit_thumb_p()) { - if (!jit_no_set_flags() && (r0|r1) < 8) - T1_ASRI(r0, r1, i0); - else - T2_ASRI(r0, r1, i0); - } - else - ASRI(r0, r1, i0); -} - -static void -_rshr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - if (jit_thumb_p()) { - if (!jit_no_set_flags() && (r0|r1|r2) < 8 && r0 == r1) - T1_LSR(r0, r2); - else - T2_LSR(r0, r1, r2); - } - else - LSR(r0, r1, r2); -} - -static void -_rshi_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) -{ - assert(i0 >= 0 && i0 <= 31); - if (i0 == 0) - movr(r0, r1); - else if (jit_thumb_p()) { - if (!jit_no_set_flags() && (r0|r1) < 8) - T1_LSRI(r0, r1, i0); - else - T2_LSRI(r0, r1, i0); - } - else - LSRI(r0, r1, i0); -} - -static void -_ccr(jit_state_t *_jit, int ct, int cf, - int32_t r0, int32_t r1, int32_t r2) -{ - if (jit_thumb_p()) { - assert((ct ^ cf) >> 28 == 1); - if ((r1|r2) < 8) - T1_CMP(r1, r2); - else if ((r1&r2) & 8) - T1_CMPX(r1, r2); - else - T2_CMP(r1, r2); - ITE(ct); - if (r0 < 8) { - T1_MOVI(r0, 1); - T1_MOVI(r0, 0); - } - else { - T2_MOVI(r0, 1); - T2_MOVI(r0, 0); - } - } - else { - CMP(r1, r2); - CC_MOVI(ct, r0, 1); - CC_MOVI(cf, r0, 0); - } -} - -static void -_cci(jit_state_t *_jit, int ct, int cf, - int32_t r0, int32_t r1, jit_word_t i0) -{ - int i; - int32_t reg; - if (jit_thumb_p()) { - if (r1 < 7 && !(i0 & 0xffffff00)) - T1_CMPI(r1, i0); - else if ((i = encode_thumb_immediate(i0)) != -1) - T2_CMPI(r1, i); - else if ((i = encode_thumb_immediate(-i0)) != -1) - T2_CMNI(r1, i); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - ccr(ct, cf, r0, r1, rn(reg)); - jit_unget_reg(reg); - return; - } - ITE(ct); - if (r0 < 8) { - T1_MOVI(r0, 1); - T1_MOVI(r0, 0); - } - else { - T2_MOVI(r0, 1); - T2_MOVI(r0, 0); - } - } - else { - if ((i = encode_arm_immediate(i0)) != -1) - CMPI(r1, i); - else if ((i = encode_arm_immediate(-i0)) != -1) - CMNI(r1, i); - else if (r0 != r1) { - movi(r0, i0); - CMP(r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - CMP(r1, rn(reg)); - jit_unget_reg(reg); - } - CC_MOVI(ct, r0, 1); - CC_MOVI(cf, r0, 0); - } -} - -static void -_ner(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - if (jit_thumb_p()) - ccr(ARM_CC_NE, ARM_CC_EQ, r0, r1, r2); - else { - SUBS(r0, r1, r2); - CC_MOVI(ARM_CC_NE, r0, 1); - } -} - -static void -_nei(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) -{ - int i; - int32_t reg; - if (jit_thumb_p()) - cci(ARM_CC_NE, ARM_CC_EQ, r0, r1, i0); - else { - if ((i = encode_arm_immediate(i0)) != -1) - SUBSI(r0, r1, i); - else if ((i = encode_arm_immediate(-i0)) != -1) - ADDSI(r0, r1, i); - else if (r0 != r1) { - movi(r0, i0); - SUBS(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - SUBS(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - CC_MOVI(ARM_CC_NE, r0, 1); - } -} - -static void -_jmpr(jit_state_t *_jit, int32_t r0) -{ - if (jit_thumb_p()) - T1_MOV(_R15_REGNO, r0); - else - MOV(_R15_REGNO, r0); -} - -static void -_jmpi(jit_state_t *_jit, jit_word_t i0) -{ - jit_word_t w; - jit_word_t d; - int32_t reg; - w = _jit->pc.w; - /* if thumb and in thumb mode */ - if (jit_thumb_p() && _jitc->thumb) { - d = ((i0 - w) >> 1) - 2; - if (d >= -1024 && d <= 1023) - T1_B(d & 0x7ff); - else if (_s24P(d)) - T2_B(encode_thumb_jump(d)); - else { - reg = jit_get_reg(jit_class_gpr|jit_class_nospill); - movi(rn(reg), i0); - jmpr(rn(reg)); - jit_unget_reg(reg); - } - } - else { - d = ((i0 - w) >> 2) - 2; - if (_s24P(d)) - B(d & 0x00ffffff); - else { - reg = jit_get_reg(jit_class_gpr|jit_class_nospill); - movi(rn(reg), i0); - jmpr(rn(reg)); - jit_unget_reg(reg); - } - } -} - -static jit_word_t -_jmpi_p(jit_state_t *_jit, jit_word_t i0, jit_bool_t i1) -{ - jit_word_t w; - jit_word_t d; - int32_t reg; - if (i1) { - /* Assume jump is not longer than 23 bits if inside jit */ - w = _jit->pc.w; - /* if thumb and in thumb mode */ - if (jit_thumb_p() && _jitc->thumb) { - d = ((i0 - w) >> 1) - 2; - assert(_s24P(d)); - T2_B(encode_thumb_jump(d)); - } - else { - d = ((i0 - w) >> 2) - 2; - assert(_s24P(d)); - B(d & 0x00ffffff); - } - } - else { - reg = jit_get_reg(jit_class_gpr|jit_class_nospill); - w = movi_p(rn(reg), i0); - jmpr(rn(reg)); - jit_unget_reg(reg); - } - return (w); -} - -static jit_word_t -_bccr(jit_state_t *_jit, int cc, jit_word_t i0, int32_t r0, int32_t r1) -{ - jit_word_t w; - jit_word_t d; - if (jit_thumb_p()) { - if ((r0|r1) < 8) - T1_CMP(r0, r1); - else if ((r0&r1) & 8) - T1_CMPX(r0, r1); - else - T2_CMP(r0, r1); - /* use only thumb2 conditional as does not know if will be patched */ - w = _jit->pc.w; - d = ((i0 - w) >> 1) - 2; - assert(_s20P(d)); - T2_CC_B(cc, encode_thumb_cc_jump(d)); - } - else { - CMP(r0, r1); - w = _jit->pc.w; - d = ((i0 - w) >> 2) - 2; - assert(_s24P(d)); - CC_B(cc, d & 0x00ffffff); - } - return (w); -} - -static jit_word_t -_bcci(jit_state_t *_jit, int cc, jit_word_t i0, int32_t r0, jit_word_t i1) -{ - jit_word_t w; - jit_word_t d; - int i; - int32_t reg; - if (jit_thumb_p()) { - if (r0 < 7 && !(i1 & 0xffffff00)) - T1_CMPI(r0, i1); - else if ((i = encode_thumb_immediate(i1)) != -1) - T2_CMPI(r0, i); - else if ((i = encode_thumb_immediate(-i1)) != -1) - T2_CMNI(r0, i); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i1); - T2_CMP(r0, rn(reg)); - jit_unget_reg(reg); - } - /* use only thumb2 conditional as does not know if will be patched */ - w = _jit->pc.w; - d = ((i0 - w) >> 1) - 2; - assert(_s20P(d)); - T2_CC_B(cc, encode_thumb_cc_jump(d)); - } - else { - if ((i = encode_arm_immediate(i1)) != -1) - CMPI(r0, i); - else if ((i = encode_arm_immediate(-i1)) != -1) - CMNI(r0, i); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i1); - CMP(r0, rn(reg)); - jit_unget_reg(reg); - } - w = _jit->pc.w; - d = ((i0 - w) >> 2) - 2; - assert(_s24P(d)); - CC_B(cc, d & 0x00ffffff); - } - return (w); -} - -static jit_word_t -_baddr(jit_state_t *_jit, int cc, jit_word_t i0, int32_t r0, int32_t r1) -{ - jit_word_t w; - jit_word_t d; - if (jit_thumb_p()) { - if ((r0|r1) < 8) - T1_ADD(r0, r0, r1); - else - T2_ADDS(r0, r0, r1); - w = _jit->pc.w; - d = ((i0 - w) >> 1) - 2; - assert(_s20P(d)); - T2_CC_B(cc, encode_thumb_cc_jump(d)); - } - else { - ADDS(r0, r0, r1); - w = _jit->pc.w; - d = ((i0 - w) >> 2) - 2; - assert(_s24P(d)); - CC_B(cc, d & 0x00ffffff); - } - return (w); -} - -static jit_word_t -_baddi(jit_state_t *_jit, int cc, jit_word_t i0, int32_t r0, int i1) -{ - int i; - jit_word_t w; - jit_word_t d; - int32_t reg; - if (jit_thumb_p()) { - if (r0 < 8 && !(i1 & ~7)) - T1_ADDI3(r0, r0, i1); - else if (r0 < 8 && !(-i1 & ~7)) - T1_SUBI3(r0, r0, -i1); - else if (r0 < 8 && !(i1 & ~0xff)) - T1_ADDI8(r0, i1); - else if (r0 < 8 && !(-i1 & ~0xff)) - T1_SUBI8(r0, -i1); - else if ((i = encode_thumb_immediate(i1)) != -1) - T2_ADDSI(r0, r0, i); - else if ((i = encode_thumb_immediate(-i1)) != -1) - T2_SUBSI(r0, r0, i); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i1); - T2_ADDS(r0, r0, rn(reg)); - jit_unget_reg(reg); - } - w = _jit->pc.w; - d = ((i0 - w) >> 1) - 2; - assert(_s20P(d)); - T2_CC_B(cc, encode_thumb_cc_jump(d)); - } - else { - if ((i = encode_arm_immediate(i1)) != -1) - ADDSI(r0, r0, i); - else if ((i = encode_arm_immediate(-i1)) != -1) - SUBSI(r0, r0, i); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i1); - ADDS(r0, r0, rn(reg)); - jit_unget_reg(reg); - } - w = _jit->pc.w; - d = ((i0 - w) >> 2) - 2; - assert(_s24P(d)); - CC_B(cc, d & 0x00ffffff); - } - return (w); -} - -static jit_word_t -_bsubr(jit_state_t *_jit, int cc, jit_word_t i0, int32_t r0, int32_t r1) -{ - jit_word_t w; - jit_word_t d; - if (jit_thumb_p()) { - if ((r0|r1) < 8) - T1_SUB(r0, r0, r1); - else - T2_SUBS(r0, r0, r1); - w = _jit->pc.w; - d = ((i0 - w) >> 1) - 2; - assert(_s20P(d)); - T2_CC_B(cc, encode_thumb_cc_jump(d)); - } - else { - SUBS(r0, r0, r1); - w = _jit->pc.w; - d = ((i0 - w) >> 2) - 2; - assert(_s24P(d)); - CC_B(cc, d & 0x00ffffff); - } - return (w); -} - -static jit_word_t -_bsubi(jit_state_t *_jit, int cc, jit_word_t i0, int32_t r0, int i1) -{ - int i; - jit_word_t w; - jit_word_t d; - int32_t reg; - if (jit_thumb_p()) { - if (r0 < 8 && !(i1 & ~7)) - T1_SUBI3(r0, r0, i1); - else if (r0 < 8 && !(-i1 & ~7)) - T1_ADDI3(r0, r0, -i1); - else if (r0 < 8 && !(i1 & ~0xff)) - T1_SUBI8(r0, i1); - else if (r0 < 8 && !(-i1 & ~0xff)) - T1_ADDI8(r0, -i1); - else if ((i = encode_thumb_immediate(i1)) != -1) - T2_SUBSI(r0, r0, i); - else if ((i = encode_thumb_immediate(-i1)) != -1) - T2_SUBSI(r0, r0, i); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i1); - T2_SUBS(r0, r0, rn(reg)); - jit_unget_reg(reg); - } - w = _jit->pc.w; - d = ((i0 - w) >> 1) - 2; - assert(_s20P(d)); - T2_CC_B(cc, encode_thumb_cc_jump(d)); - } - else { - if ((i = encode_arm_immediate(i1)) != -1) - SUBSI(r0, r0, i); - else if ((i = encode_arm_immediate(-i1)) != -1) - ADDSI(r0, r0, i); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i1); - SUBS(r0, r0, rn(reg)); - jit_unget_reg(reg); - } - w = _jit->pc.w; - d = ((i0 - w) >> 2) - 2; - assert(_s24P(d)); - CC_B(cc, d & 0x00ffffff); - } - return (w); -} - -static jit_word_t -_bmxr(jit_state_t *_jit, int cc, jit_word_t i0, int32_t r0, int32_t r1) -{ - jit_word_t w; - jit_word_t d; - int32_t reg; - if (jit_thumb_p()) { - if ((r0|r1) < 8) - T1_TST(r0, r1); - else - T2_TST(r0, r1); - w = _jit->pc.w; - d = ((i0 - w) >> 1) - 2; - assert(_s20P(d)); - T2_CC_B(cc, encode_thumb_cc_jump(d)); - } - else { - if (jit_armv5_p()) - TST(r0, r1); - else { - reg = jit_get_reg(jit_class_gpr); - ANDS(rn(reg), r0, r1); - jit_unget_reg(reg); - } - w = _jit->pc.w; - d = ((i0 - w) >> 2) - 2; - assert(_s24P(d)); - CC_B(cc, d & 0x00ffffff); - } - return (w); -} - -static jit_word_t -_bmxi(jit_state_t *_jit, int cc, jit_word_t i0, int32_t r0, jit_word_t i1) -{ - int i; - jit_word_t w; - jit_word_t d; - int32_t reg; - if (jit_thumb_p()) { - if ((i = encode_thumb_immediate(i1)) != -1) - T2_TSTI(r0, i); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i1); - T2_TST(r0, rn(reg)); - jit_unget_reg(reg); - } - w = _jit->pc.w; - d = ((i0 - w) >> 1) - 2; - assert(_s20P(d)); - T2_CC_B(cc, encode_thumb_cc_jump(d)); - } - else { - if (jit_armv5_p()) { - if ((i = encode_arm_immediate(i1)) != -1) - TSTI(r0, i); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i1); - TST(r0, rn(reg)); - jit_unget_reg(reg); - } - } - else { - reg = jit_get_reg(jit_class_gpr); - if ((i = encode_arm_immediate(i1)) != -1) - ANDSI(rn(reg), r0, i); - else if ((i = encode_arm_immediate(~i1)) != -1) - BICSI(rn(reg), r0, i); - else { - movi(rn(reg), i1); - ANDS(rn(reg), r0, rn(reg)); - } - jit_unget_reg(reg); - } - w = _jit->pc.w; - d = ((i0 - w) >> 2) - 2; - assert(_s24P(d)); - CC_B(cc, d & 0x00ffffff); - } - return (w); -} - -static void -_ldr_c(jit_state_t *_jit, int32_t r0, int32_t r1) -{ - if (jit_thumb_p()) - T2_LDRSBI(r0, r1, 0); - else - LDRSBI(r0, r1, 0); -} - -static void -_ldi_c(jit_state_t *_jit, int32_t r0, jit_word_t i0) -{ - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - if (jit_thumb_p()) - T2_LDRSBI(r0, rn(reg), 0); - else - LDRSBI(r0, rn(reg), 0); - jit_unget_reg(reg); -} - -static void -_ldxr_c(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - if (jit_thumb_p()) { - if ((r0|r1|r2) < 8) - T1_LDRSB(r0, r1, r2); - else - T2_LDRSB(r0, r1, r2); - } - else - LDRSB(r0, r1, r2); + if ((r0|r1|r2) < 8) + T1_LDRSB(_jit, r0, r1, r2); + else + T2_LDRSB(_jit, r0, r1, r2); } #define jit_ldrt_strt_p() 0 static void -_ldxi_c(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +ldxi_c(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - int32_t reg; - if (jit_thumb_p()) { - if (jit_ldrt_strt_p() && i0 >= 0 && i0 <= 255) - T2_LDRSBI(r0, r1, i0); - else if (i0 < 0 && i0 >= -255) - T2_LDRSBIN(r0, r1, -i0); - else if (i0 >= 0 && i0 <= 4095) - T2_LDRSBWI(r0, r1, i0); - else if (r0 != r1) { - movi(r0, i0); - if ((r0|r1) < 8) - T1_LDRSB(r0, r1, r0); - else - T2_LDRSB(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - if ((r0|r1|rn(reg)) < 8) - T1_LDRSB(r0, r1, rn(reg)); - else - T2_LDRSB(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - } - else { - if (i0 >= 0 && i0 <= 255) - LDRSBI(r0, r1, i0); - else if (i0 < 0 && i0 >= -255) - LDRSBIN(r0, r1, -i0); - else if (r0 != r1) { - movi(r0, i0); - LDRSB(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - LDRSB(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - } -} - -static void -_ldr_uc(jit_state_t *_jit, int32_t r0, int32_t r1) -{ - if (jit_thumb_p()) - T2_LDRBI(r0, r1, 0); + + if (jit_ldrt_strt_p() && i0 >= 0 && i0 <= 255) + T2_LDRSBI(_jit, r0, r1, i0); + else if (i0 < 0 && i0 >= -255) + T2_LDRSBIN(_jit, r0, r1, -i0); + else if (i0 >= 0 && i0 <= 4095) + T2_LDRSBWI(_jit, r0, r1, i0); + else if (r0 != r1) { + movi(_jit, r0, i0); + if ((r0|r1) < 8) + T1_LDRSB(_jit, r0, r1, r0); else - LDRBI(r0, r1, 0); -} - -static void -_ldi_uc(jit_state_t *_jit, int32_t r0, jit_word_t i0) -{ - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - if (jit_thumb_p()) - T2_LDRBI(r0, rn(reg), 0); + T2_LDRSB(_jit, r0, r1, r0); + } else { + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + if ((r0|r1|jit_gpr_regno(reg)) < 8) + T1_LDRSB(_jit, r0, r1, jit_gpr_regno(reg)); else - LDRBI(r0, rn(reg), 0); - jit_unget_reg(reg); + T2_LDRSB(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } } static void -_ldxr_uc(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +ldr_uc(jit_state_t *_jit, int32_t r0, int32_t r1) { - if (jit_thumb_p()) { - if ((r0|r1|r2) < 8) - T1_LDRB(r0, r1, r2); - else - T2_LDRB(r0, r1, r2); - } + T2_LDRBI(_jit, r0, r1, 0); +} + +static void +ldi_uc(jit_state_t *_jit, int32_t r0, jit_word_t i0) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + T2_LDRBI(_jit, r0, jit_gpr_regno(reg), 0); + unget_temp_gpr(_jit); +} + +static void +ldxr_uc(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + if ((r0|r1|r2) < 8) + T1_LDRB(_jit, r0, r1, r2); + else + T2_LDRB(_jit, r0, r1, r2); +} + +static void +ldxi_uc(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + if ((r0|r1) < 8 && i0 >= 0 && i0 < 0x20) + T1_LDRBI(_jit, r0, r1, i0); + else if (jit_ldrt_strt_p() && i0 >= 0 && i0 <= 255) + T2_LDRBI(_jit, r0, r1, i0); + else if (i0 < 0 && i0 >= -255) + T2_LDRBIN(_jit, r0, r1, -i0); + else if (i0 >= 0 && i0 <= 4095) + T2_LDRBWI(_jit, r0, r1, i0); + else if (r0 != r1) { + movi(_jit, r0, i0); + if ((r0|r1) < 8) + T1_LDRB(_jit, r0, r1, r0); else - LDRB(r0, r1, r2); -} - -static void -_ldxi_uc(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) -{ - int32_t reg; - if (jit_thumb_p()) { - if ((r0|r1) < 8 && i0 >= 0 && i0 < 0x20) - T1_LDRBI(r0, r1, i0); - else if (jit_ldrt_strt_p() && i0 >= 0 && i0 <= 255) - T2_LDRBI(r0, r1, i0); - else if (i0 < 0 && i0 >= -255) - T2_LDRBIN(r0, r1, -i0); - else if (i0 >= 0 && i0 <= 4095) - T2_LDRBWI(r0, r1, i0); - else if (r0 != r1) { - movi(r0, i0); - if ((r0|r1) < 8) - T1_LDRB(r0, r1, r0); - else - T2_LDRB(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - if ((r0|r1|rn(reg)) < 8) - T1_LDRB(r0, r1, rn(reg)); - else - T2_LDRB(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - } - else { - if (i0 >= 0 && i0 <= 4095) - LDRBI(r0, r1, i0); - else if (i0 < 0 && i0 >= -4095) - LDRBIN(r0, r1, -i0); - else if (r0 != r1) { - movi(r0, i0); - LDRB(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - LDRB(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - } -} - -static void -_ldr_s(jit_state_t *_jit, int32_t r0, int32_t r1) -{ - if (jit_thumb_p()) - T2_LDRSHI(r0, r1, 0); + T2_LDRB(_jit, r0, r1, r0); + } else { + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + if ((r0|r1|jit_gpr_regno(reg)) < 8) + T1_LDRB(_jit, r0, r1, jit_gpr_regno(reg)); else - LDRSHI(r0, r1, 0); + T2_LDRB(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } } static void -_ldi_s(jit_state_t *_jit, int32_t r0, jit_word_t i0) +ldr_s(jit_state_t *_jit, int32_t r0, int32_t r1) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - if (jit_thumb_p()) - T2_LDRSHI(r0, rn(reg), 0); + T2_LDRSHI(_jit, r0, r1, 0); +} + +static void +ldi_s(jit_state_t *_jit, int32_t r0, jit_word_t i0) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + T2_LDRSHI(_jit, r0, jit_gpr_regno(reg), 0); + unget_temp_gpr(_jit); +} + +static void +ldxr_s(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + if ((r0|r1|r2) < 8) + T1_LDRSH(_jit, r0, r1, r2); + else + T2_LDRSH(_jit, r0, r1, r2); +} + +static void +ldxi_s(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + if (jit_ldrt_strt_p() && i0 >= 0 && i0 <= 255) + T2_LDRSHI(_jit, r0, r1, i0); + else if (i0 < 0 && i0 >= -255) + T2_LDRSHIN(_jit, r0, r1, -i0); + else if (i0 >= 0 && i0 <= 4095) + T2_LDRSHWI(_jit, r0, r1, i0); + else if (r0 != r1) { + movi(_jit, r0, i0); + if ((r0|r1) < 8) + T1_LDRSH(_jit, r0, r1, r0); else - LDRSHI(r0, rn(reg), 0); - jit_unget_reg(reg); -} - -static void -_ldxr_s(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - if (jit_thumb_p()) { - if ((r0|r1|r2) < 8) - T1_LDRSH(r0, r1, r2); - else - T2_LDRSH(r0, r1, r2); - } + T2_LDRSH(_jit, r0, r1, r0); + } else { + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + if ((r0|r1|jit_gpr_regno(reg)) < 8) + T1_LDRSH(_jit, r0, r1, jit_gpr_regno(reg)); else - LDRSH(r0, r1, r2); + T2_LDRSH(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } } static void -_ldxi_s(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +ldr_us(jit_state_t *_jit, int32_t r0, int32_t r1) { - int32_t reg; - if (jit_thumb_p()) { - if (jit_ldrt_strt_p() && i0 >= 0 && i0 <= 255) - T2_LDRSHI(r0, r1, i0); - else if (i0 < 0 && i0 >= -255) - T2_LDRSHIN(r0, r1, -i0); - else if (i0 >= 0 && i0 <= 4095) - T2_LDRSHWI(r0, r1, i0); - else if (r0 != r1) { - movi(r0, i0); - if ((r0|r1) < 8) - T1_LDRSH(r0, r1, r0); - else - T2_LDRSH(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - if ((r0|r1|rn(reg)) < 8) - T1_LDRSH(r0, r1, rn(reg)); - else - T2_LDRSH(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - } - else { - if (i0 >= 0 && i0 <= 255) - LDRSHI(r0, r1, i0); - else if (i0 < 0 && i0 >= -255) - LDRSHIN(r0, r1, -i0); - else if (r0 != r1) { - movi(r0, i0); - LDRSH(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - LDRSH(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - } + T2_LDRHI(_jit, r0, r1, 0); } static void -_ldr_us(jit_state_t *_jit, int32_t r0, int32_t r1) +ldi_us(jit_state_t *_jit, int32_t r0, jit_word_t i0) { - if (jit_thumb_p()) - T2_LDRHI(r0, r1, 0); + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + T2_LDRHI(_jit, r0, jit_gpr_regno(reg), 0); + unget_temp_gpr(_jit); +} + +static void +ldxr_us(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + + if ((r0|r1|r2) < 8) + T1_LDRH(_jit, r0, r1, r2); + else + T2_LDRH(_jit, r0, r1, r2); +} + +static void +ldxi_us(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + if ((r0|r1) < 8 && i0 >= 0 && !(i0 & 1) && (i0 >> 1) < 0x20) + T1_LDRHI(_jit, r0, r1, i0 >> 1); + else if (jit_ldrt_strt_p() && i0 >= 0 && i0 <= 255) + T2_LDRHI(_jit, r0, r1, i0); + else if (i0 < 0 && i0 >= -255) + T2_LDRHIN(_jit, r0, r1, -i0); + else if (i0 >= 0 && i0 <= 4095) + T2_LDRHWI(_jit, r0, r1, i0); + else if (r0 != r1) { + movi(_jit, r0, i0); + if ((r0|r1) < 8) + T1_LDRH(_jit, r0, r1, r0); else - LDRHI(r0, r1, 0); -} - -static void -_ldi_us(jit_state_t *_jit, int32_t r0, jit_word_t i0) -{ - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - if (jit_thumb_p()) - T2_LDRHI(r0, rn(reg), 0); + T2_LDRH(_jit, r0, r1, r0); + } else { + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + if ((r0|r1|jit_gpr_regno(reg)) < 8) + T1_LDRH(_jit, r0, r1, jit_gpr_regno(reg)); else - LDRHI(r0, rn(reg), 0); - jit_unget_reg(reg); + T2_LDRH(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } } static void -_ldxr_us(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +ldr_i(jit_state_t *_jit, int32_t r0, int32_t r1) { - if (jit_thumb_p()) { - if ((r0|r1|r2) < 8) - T1_LDRH(r0, r1, r2); - else - T2_LDRH(r0, r1, r2); - } + T2_LDRI(_jit, r0, r1, 0); +} + +static void +ldi_i(jit_state_t *_jit, int32_t r0, jit_word_t i0) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + T2_LDRI(_jit, r0, jit_gpr_regno(reg), 0); + unget_temp_gpr(_jit); +} + +static void +ldxr_i(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + if ((r0|r1|r2) < 8) + T1_LDR(_jit, r0, r1, r2); + else + T2_LDR(_jit, r0, r1, r2); +} + +static void +ldxi_i(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + if ((r0|r1) < 8 && i0 >= 0 && !(i0 & 3) && (i0 >> 2) < 0x20) + T1_LDRI(_jit, r0, r1, i0 >> 2); + else if (r1 == jit_gpr_regno(_SP) && r0 < 8 && + i0 >= 0 && !(i0 & 3) && (i0 >> 2) <= 255) + T1_LDRISP(_jit, r0, i0 >> 2); + else if (jit_ldrt_strt_p() && i0 >= 0 && i0 <= 255) + T2_LDRI(_jit, r0, r1, i0); + else if (i0 < 0 && i0 > -255) + T2_LDRIN(_jit, r0, r1, -i0); + else if (i0 >= 0 && i0 <= 4095) + T2_LDRWI(_jit, r0, r1, i0); + else if (r0 != r1) { + movi(_jit, r0, i0); + if ((r0|r1) < 8) + T1_LDR(_jit, r0, r1, r0); else - LDRH(r0, r1, r2); -} - -static void -_ldxi_us(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) -{ - int32_t reg; - if (jit_thumb_p()) { - if ((r0|r1) < 8 && i0 >= 0 && !(i0 & 1) && (i0 >> 1) < 0x20) - T1_LDRHI(r0, r1, i0 >> 1); - else if (jit_ldrt_strt_p() && i0 >= 0 && i0 <= 255) - T2_LDRHI(r0, r1, i0); - else if (i0 < 0 && i0 >= -255) - T2_LDRHIN(r0, r1, -i0); - else if (i0 >= 0 && i0 <= 4095) - T2_LDRHWI(r0, r1, i0); - else if (r0 != r1) { - movi(r0, i0); - if ((r0|r1) < 8) - T1_LDRH(r0, r1, r0); - else - T2_LDRH(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - if ((r0|r1|rn(reg)) < 8) - T1_LDRH(r0, r1, rn(reg)); - else - T2_LDRH(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - } - else { - if (i0 >= 0 && i0 <= 255) - LDRHI(r0, r1, i0); - else if (i0 < 0 && i0 >= -255) - LDRHIN(r0, r1, -i0); - else if (r0 != r1) { - movi(r0, i0); - LDRH(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - LDRH(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - } -} - -static void -_ldr_i(jit_state_t *_jit, int32_t r0, int32_t r1) -{ - if (jit_thumb_p()) - T2_LDRI(r0, r1, 0); + T2_LDR(_jit, r0, r1, r0); + } else { + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + if ((r0|r1|jit_gpr_regno(reg)) < 8) + T1_LDR(_jit, r0, r1, jit_gpr_regno(reg)); else - LDRI(r0, r1, 0); + T2_LDR(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } } static void -_ldi_i(jit_state_t *_jit, int32_t r0, jit_word_t i0) +str_c(jit_state_t *_jit, int32_t r0, int32_t r1) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - if (jit_thumb_p()) - T2_LDRI(r0, rn(reg), 0); + T2_STRBI(_jit, r1, r0, 0); +} + +static void +sti_c(jit_state_t *_jit, jit_word_t i0, int32_t r0) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + T2_STRBI(_jit, r0, jit_gpr_regno(reg), 0); + unget_temp_gpr(_jit); +} + +static void +stxr_c(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + if ((r0|r1|r2) < 8) + T1_STRB(_jit, r2, r1, r0); + else + T2_STRB(_jit, r2, r1, r0); +} + +static void +stxi_c(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) +{ + if ((r0|r1) < 8 && i0 >= 0 && i0 < 0x20) + T1_STRBI(_jit, r1, r0, i0); + else if (jit_ldrt_strt_p() && i0 >= 0 && i0 <= 255) + T2_STRBI(_jit, r1, r0, i0); + else if (i0 < 0 && i0 >= -255) + T2_STRBIN(_jit, r1, r0, -i0); + else if (i0 >= 0 && i0 <= 4095) + T2_STRBWI(_jit, r1, r0, i0); + else { + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + if ((r0|r1|jit_gpr_regno(reg)) < 8) + T1_STRB(_jit, r1, r0, jit_gpr_regno(reg)); else - LDRI(r0, rn(reg), 0); - jit_unget_reg(reg); + T2_STRB(_jit, r1, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } } static void -_ldxr_i(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +str_s(jit_state_t *_jit, int32_t r0, int32_t r1) { - if (jit_thumb_p()) { - if ((r0|r1|r2) < 8) - T1_LDR(r0, r1, r2); - else - T2_LDR(r0, r1, r2); - } + T2_STRHI(_jit, r1, r0, 0); +} + +static void +sti_s(jit_state_t *_jit, jit_word_t i0, int32_t r0) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + T2_STRHI(_jit, r0, jit_gpr_regno(reg), 0); + unget_temp_gpr(_jit); +} + +static void +stxr_s(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + if ((r0|r1|r2) < 8) + T1_STRH(_jit, r2, r1, r0); + else + T2_STRH(_jit, r2, r1, r0); +} + +static void +stxi_s(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) +{ + if ((r0|r1) < 8 && i0 >= 0 && !(i0 & 1) && (i0 >> 1) < 0x20) + T1_STRHI(_jit, r1, r0, i0 >> 1); + else if (jit_ldrt_strt_p() && i0 >= 0 && i0 <= 255) + T2_STRHI(_jit, r1, r0, i0); + else if (i0 < 0 && i0 >= -255) + T2_STRHIN(_jit, r1, r0, -i0); + else if (i0 >= 0 && i0 <= 4095) + T2_STRHWI(_jit, r1, r0, i0); + else { + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + if ((r0|r1|jit_gpr_regno(reg)) < 8) + T1_STRH(_jit, r1, r0, jit_gpr_regno(reg)); else - LDR(r0, r1, r2); + T2_STRH(_jit, r1, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } } static void -_ldxi_i(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +str_i(jit_state_t *_jit, int32_t r0, int32_t r1) { - int32_t reg; - if (jit_thumb_p()) { - if ((r0|r1) < 8 && i0 >= 0 && !(i0 & 3) && (i0 >> 2) < 0x20) - T1_LDRI(r0, r1, i0 >> 2); - else if (r1 == _R13_REGNO && r0 < 8 && - i0 >= 0 && !(i0 & 3) && (i0 >> 2) <= 255) - T1_LDRISP(r0, i0 >> 2); - else if (jit_ldrt_strt_p() && i0 >= 0 && i0 <= 255) - T2_LDRI(r0, r1, i0); - else if (i0 < 0 && i0 > -255) - T2_LDRIN(r0, r1, -i0); - else if (i0 >= 0 && i0 <= 4095) - T2_LDRWI(r0, r1, i0); - else if (r0 != r1) { - movi(r0, i0); - if ((r0|r1) < 8) - T1_LDR(r0, r1, r0); - else - T2_LDR(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - if ((r0|r1|rn(reg)) < 8) - T1_LDR(r0, r1, rn(reg)); - else - T2_LDR(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - } - else { - if (i0 >= 0 && i0 <= 4095) - LDRI(r0, r1, i0); - else if (i0 < 0 && i0 >= -4095) - LDRIN(r0, r1, -i0); - else if (r0 != r1) { - movi(r0, i0); - LDR(r0, r1, r0); - } - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - LDR(r0, r1, rn(reg)); - jit_unget_reg(reg); - } - } + T2_STRI(_jit, r1, r0, 0); } static void -_str_c(jit_state_t *_jit, int32_t r0, int32_t r1) +sti_i(jit_state_t *_jit, jit_word_t i0, int32_t r0) { - if (jit_thumb_p()) - T2_STRBI(r1, r0, 0); + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + T2_STRI(_jit, r0, jit_gpr_regno(reg), 0); + unget_temp_gpr(_jit); +} + +static void +stxr_i(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + if ((r0|r1|r2) < 8) + T1_STR(_jit, r2, r1, r0); + else + T2_STR(_jit, r2, r1, r0); +} + +static void +stxi_i(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) +{ + if ((r0|r1) < 8 && i0 >= 0 && !(i0 & 3) && (i0 >> 2) < 0x20) + T1_STRI(_jit, r1, r0, i0 >> 2); + else if (r0 == jit_gpr_regno(_SP) && r1 < 8 && + i0 >= 0 && !(i0 & 3) && (i0 >> 2) <= 255) + T1_STRISP(_jit, r1, i0 >> 2); + else if (jit_ldrt_strt_p() && i0 >= 0 && i0 <= 255) + T2_STRI(_jit, r1, r0, i0); + else if (i0 < 0 && i0 >= -255) + T2_STRIN(_jit, r1, r0, -i0); + else if (i0 >= 0 && i0 <= 4095) + T2_STRWI(_jit, r1, r0, i0); + else { + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + if ((r0|r1|jit_gpr_regno(reg)) < 8) + T1_STR(_jit, r1, r0, jit_gpr_regno(reg)); else - STRBI(r1, r0, 0); + T2_STR(_jit, r1, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } } static void -_sti_c(jit_state_t *_jit, jit_word_t i0, int32_t r0) +bswapr_us(jit_state_t *_jit, int32_t r0, int32_t r1) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - if (jit_thumb_p()) - T2_STRBI(r0, rn(reg), 0); - else - STRBI(r0, rn(reg), 0); - jit_unget_reg(reg); -} - -static void -_stxr_c(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - if (jit_thumb_p()) { - if ((r0|r1|r2) < 8) - T1_STRB(r2, r1, r0); - else - T2_STRB(r2, r1, r0); - } - else - STRB(r2, r1, r0); -} - -static void -_stxi_c(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) -{ - int32_t reg; - if (jit_thumb_p()) { - if ((r0|r1) < 8 && i0 >= 0 && i0 < 0x20) - T1_STRBI(r1, r0, i0); - else if (jit_ldrt_strt_p() && i0 >= 0 && i0 <= 255) - T2_STRBI(r1, r0, i0); - else if (i0 < 0 && i0 >= -255) - T2_STRBIN(r1, r0, -i0); - else if (i0 >= 0 && i0 <= 4095) - T2_STRBWI(r1, r0, i0); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - if ((r0|r1|rn(reg)) < 8) - T1_STRB(r1, r0, rn(reg)); - else - T2_STRB(r1, r0, rn(reg)); - jit_unget_reg(reg); - } - } - else { - if (i0 >= 0 && i0 <= 4095) - STRBI(r1, r0, i0); - else if (i0 < 0 && i0 >= -4095) - STRBIN(r1, r0, -i0); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - STRB(r1, r0, rn(reg)); - jit_unget_reg(reg); - } - } -} - -static void -_str_s(jit_state_t *_jit, int32_t r0, int32_t r1) -{ - if (jit_thumb_p()) - T2_STRHI(r1, r0, 0); - else - STRHI(r1, r0, 0); -} - -static void -_sti_s(jit_state_t *_jit, jit_word_t i0, int32_t r0) -{ - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - if (jit_thumb_p()) - T2_STRHI(r0, rn(reg), 0); - else - STRHI(r0, rn(reg), 0); - jit_unget_reg(reg); -} - -static void -_stxr_s(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - if (jit_thumb_p()) { - if ((r0|r1|r2) < 8) - T1_STRH(r2, r1, r0); - else - T2_STRH(r2, r1, r0); - } - else - STRH(r2, r1, r0); -} - -static void -_stxi_s(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) -{ - int32_t reg; - if (jit_thumb_p()) { - if ((r0|r1) < 8 && i0 >= 0 && !(i0 & 1) && (i0 >> 1) < 0x20) - T1_STRHI(r1, r0, i0 >> 1); - else if (jit_ldrt_strt_p() && i0 >= 0 && i0 <= 255) - T2_STRHI(r1, r0, i0); - else if (i0 < 0 && i0 >= -255) - T2_STRHIN(r1, r0, -i0); - else if (i0 >= 0 && i0 <= 4095) - T2_STRHWI(r1, r0, i0); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - if ((r0|r1|rn(reg)) < 8) - T1_STRH(r1, r0, rn(reg)); - else - T2_STRH(r1, r0, rn(reg)); - jit_unget_reg(reg); - } - } - else { - if (i0 >= 0 && i0 <= 255) - STRHI(r1, r0, i0); - else if (i0 < 0 && i0 >= -255) - STRHIN(r1, r0, -i0); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - STRH(r1, r0, rn(reg)); - jit_unget_reg(reg); - } - } -} - -static void -_str_i(jit_state_t *_jit, int32_t r0, int32_t r1) -{ - if (jit_thumb_p()) - T2_STRI(r1, r0, 0); - else - STRI(r1, r0, 0); -} - -static void -_sti_i(jit_state_t *_jit, jit_word_t i0, int32_t r0) -{ - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - if (jit_thumb_p()) - T2_STRI(r0, rn(reg), 0); - else - STRI(r0, rn(reg), 0); - jit_unget_reg(reg); -} - -static void -_stxr_i(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - if (jit_thumb_p()) { - if ((r0|r1|r2) < 8) - T1_STR(r2, r1, r0); - else - T2_STR(r2, r1, r0); - } - else - STR(r2, r1, r0); -} - -static void -_stxi_i(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) -{ - int32_t reg; - if (jit_thumb_p()) { - if ((r0|r1) < 8 && i0 >= 0 && !(i0 & 3) && (i0 >> 2) < 0x20) - T1_STRI(r1, r0, i0 >> 2); - else if (r0 == _R13_REGNO && r1 < 8 && - i0 >= 0 && !(i0 & 3) && (i0 >> 2) <= 255) - T1_STRISP(r1, i0 >> 2); - else if (jit_ldrt_strt_p() && i0 >= 0 && i0 <= 255) - T2_STRI(r1, r0, i0); - else if (i0 < 0 && i0 >= -255) - T2_STRIN(r1, r0, -i0); - else if (i0 >= 0 && i0 <= 4095) - T2_STRWI(r1, r0, i0); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - if ((r0|r1|rn(reg)) < 8) - T1_STR(r1, r0, rn(reg)); - else - T2_STR(r1, r0, rn(reg)); - jit_unget_reg(reg); - } - } - else { - if (i0 >= 0 && i0 <= 4095) - STRI(r1, r0, i0); - else if (i0 < 0 && i0 >= -4095) - STRIN(r1, r0, -i0); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - STR(r1, r0, rn(reg)); - jit_unget_reg(reg); - } - } -} - -# if __BYTE_ORDER == __LITTLE_ENDIAN -static void -_bswapr_us(jit_state_t *_jit, int32_t r0, int32_t r1) -{ - int32_t t0; - if (jit_thumb_p()) { - if ((r0|r1) < 8) - T1_REV(r0, r1); - else - T2_REV(r0, r1); - rshi_u(r0, r0, 16); - } - else { - if (jit_armv6_p()) { - REV(r0, r1); - rshi_u(r0, r0, 16); - } - else { - t0 = jit_get_reg(jit_class_gpr); - rshi(rn(t0), r1, 8); - andi(r0, r1, 0xff); - andi(rn(t0), rn(t0), 0xff); - lshi(r0, r0, 8); - orr(r0, r0, rn(t0)); - jit_unget_reg(t0); - } - } + if ((r0|r1) < 8) + T1_REV(_jit, r0, r1); + else + T2_REV(_jit, r0, r1); + rshi_u(_jit, r0, r0, 16); } /* inline glibc htonl (without register clobber) */ static void -_bswapr_ui(jit_state_t *_jit, int32_t r0, int32_t r1) +bswapr_ui(jit_state_t *_jit, int32_t r0, int32_t r1) { - int32_t reg; - if (jit_thumb_p()) { - if ((r0|r1) < 8) - T1_REV(r0, r1); - else - T2_REV(r0, r1); - } - else { - if (jit_armv6_p()) - REV(r0, r1); - else { - reg = jit_get_reg(jit_class_gpr); - EOR_SI(rn(reg), r1, r1, ARM_ROR, 16); - LSRI(rn(reg), rn(reg), 8); - BICI(rn(reg), rn(reg), encode_arm_immediate(0xff00)); - EOR_SI(r0, rn(reg), r1, ARM_ROR, 8); - jit_unget_reg(reg); - } - } -} -#endif - -static void -_extr_c(jit_state_t *_jit, int32_t r0, int32_t r1) -{ - if (jit_thumb_p()) { - if ((r0|r1) < 8) - T1_SXTB(r0, r1); - else - T2_SXTB(r0, r1); - } - else { - if (jit_armv6_p()) - SXTB(r0, r1); - else { - LSLI(r0, r1, 24); - ASRI(r0, r0, 24); - } - } + if ((r0|r1) < 8) + T1_REV(_jit, r0, r1); + else + T2_REV(_jit, r0, r1); } static void -_extr_uc(jit_state_t *_jit, int32_t r0, int32_t r1) +extr_c(jit_state_t *_jit, int32_t r0, int32_t r1) { - if (jit_thumb_p()) { - if ((r0|r1) < 8) - T1_UXTB(r0, r1); - else - T2_UXTB(r0, r1); - } - else { - if (jit_armv6_p()) - UXTB(r0, r1); - else - ANDI(r0, r1, 0xff); - } + + if ((r0|r1) < 8) + T1_SXTB(_jit, r0, r1); + else + T2_SXTB(_jit, r0, r1); } static void -_extr_s(jit_state_t *_jit, int32_t r0, int32_t r1) +extr_uc(jit_state_t *_jit, int32_t r0, int32_t r1) { - if (jit_thumb_p()) { - if ((r0|r1) < 8) - T1_SXTH(r0, r1); - else - T2_SXTH(r0, r1); - } - else { - if (jit_armv6_p()) - SXTH(r0, r1); - else { - LSLI(r0, r1, 16); - ASRI(r0, r0, 16); - } - } + if ((r0|r1) < 8) + T1_UXTB(_jit, r0, r1); + else + T2_UXTB(_jit, r0, r1); } static void -_extr_us(jit_state_t *_jit, int32_t r0, int32_t r1) +extr_s(jit_state_t *_jit, int32_t r0, int32_t r1) { - if (jit_thumb_p()) { - if ((r0|r1) < 8) - T1_UXTH(r0, r1); - else - T2_UXTH(r0, r1); - } - else { - if (jit_armv6_p()) - UXTH(r0, r1); - else { - LSLI(r0, r1, 16); - LSRI(r0, r0, 16); - } - } + if ((r0|r1) < 8) + T1_SXTH(_jit, r0, r1); + else + T2_SXTH(_jit, r0, r1); } static void -_callr(jit_state_t *_jit, int32_t r0) +extr_us(jit_state_t *_jit, int32_t r0, int32_t r1) { - if (jit_thumb_p()) - T1_BLX(r0); - else - BLX(r0); + if ((r0|r1) < 8) + T1_UXTH(_jit, r0, r1); + else + T2_UXTH(_jit, r0, r1); } static void -_calli(jit_state_t *_jit, jit_word_t i0) +callr(jit_state_t *_jit, int32_t r0) { - jit_word_t d; - int32_t reg; - d = ((i0 - _jit->pc.w) >> 2) - 2; - if (!jit_exchange_p() && !jit_thumb_p() && _s24P(d)) - BLI(d & 0x00ffffff); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - if (jit_thumb_p()) - T1_BLX(rn(reg)); - else - BLX(rn(reg)); - jit_unget_reg(reg); - } -} - -static jit_word_t -_calli_p(jit_state_t *_jit, jit_word_t i0) -{ - jit_word_t w; - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - w = _jit->pc.w; - movi_p(rn(reg), i0); - if (jit_thumb_p()) - T1_BLX(rn(reg)); - else - BLX(rn(reg)); - jit_unget_reg(reg); - return (w); + T1_MOV(_jit, jit_gpr_regno(_LR), jit_gpr_regno(_PC)); + T1_MOV(_jit, jit_gpr_regno(_PC), r0); + // LR will point here: 4 bytes after the MOV LR,PC instruction. } static void -_prolog(jit_state_t *_jit, jit_node_t *node) +calli(jit_state_t *_jit, jit_word_t i0) { - int32_t reg; - if (_jitc->function->define_frame || _jitc->function->assume_frame) { - int32_t frame = -_jitc->function->frame; - assert(_jitc->function->self.aoff >= frame); - if (_jitc->function->assume_frame) { - if (jit_thumb_p() && !_jitc->thumb) - _jitc->thumb = _jit->pc.w; - return; - } - _jitc->function->self.aoff = frame; - } - if (_jitc->function->allocar) - _jitc->function->self.aoff &= -8; - _jitc->function->stack = ((_jitc->function->self.alen - - /* align stack at 8 bytes */ - _jitc->function->self.aoff) + 7) & -8; - - if (jit_thumb_p()) { - /* switch to thumb mode (better approach would be to - * ORR 1 address being called, but no clear distinction - * of what is a pointer to a jit function, or if patching - * a pointer to a jit function) */ - ADDI(_R12_REGNO, _R15_REGNO, 1); - BX(_R12_REGNO); - if (!_jitc->thumb) - _jitc->thumb = _jit->pc.w; - if (jit_cpu.abi) { - T2_PUSH(0xf); - T2_PUSH(0x3f0|(1<<_FP_REGNO)|(1<<_LR_REGNO)); - VPUSH_F64(_D8_REGNO, 8); - } - else { - T2_PUSH(0xf); - T2_PUSH(0x3f0|(1<<_FP_REGNO)|(1<<_LR_REGNO)); - } - } - else { - if (jit_cpu.abi) { - PUSH(0xf); - PUSH(0x3f0|(1<<_FP_REGNO)|(1<<_LR_REGNO)); - VPUSH_F64(_D8_REGNO, 8); - } - else { - PUSH(0xf); - PUSH(0x3f0|(1<<_FP_REGNO)|(1<<_LR_REGNO)); - } - } - movr(_FP_REGNO, _SP_REGNO); - if (_jitc->function->stack) - subi(_SP_REGNO, _SP_REGNO, _jitc->function->stack); - if (_jitc->function->allocar) { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), _jitc->function->self.aoff); - stxi_i(_jitc->function->aoffoff, _FP_REGNO, rn(reg)); - jit_unget_reg(reg); - } + jit_patch_there(_jit, T2_BLI(_jit), (void*)i0); } static void -_epilog(jit_state_t *_jit, jit_node_t *node) +emit_veneer(jit_state_t *_jit, jit_pointer_t target) { - if (_jitc->function->assume_frame) - return; - - movr(_SP_REGNO, _FP_REGNO); - if (jit_cpu.abi) - VPOP_F64(_D8_REGNO, 8); - if (jit_thumb_p()) - T2_POP(0x3f0|(1<<_FP_REGNO)|(1<<_LR_REGNO)); - else - POP(0x3f0|(1<<_FP_REGNO)|(1<<_LR_REGNO)); - addi(_SP_REGNO, _SP_REGNO, 16); - if (jit_thumb_p()) - T1_BX(_LR_REGNO); - else - BX(_LR_REGNO); - if (jit_thumb_p() && (_jit->pc.w & 2)) - T1_NOP(); + uint16_t thumb1_ldr = 0x4800; + int32_t tmp = jit_gpr_regno(get_temp_gpr(_jit)); + ASSERT(tmp < 8); + // Loaded addr is 4 bytes after the LDR, which is aligned, so offset is 0. + emit_u16(_jit, thumb1_ldr | (tmp << 8)); + T1_MOV(_jit, jit_gpr_regno(_PC), tmp); + unget_temp_gpr(_jit); + emit_u32(_jit, (uint32_t) target); } - -static void -_vastart(jit_state_t *_jit, int32_t r0) -{ - assert(_jitc->function->self.call & jit_call_varargs); - - /* Initialize stack pointer to the first stack argument. - * The -16 is to account for the 4 argument registers - * always saved, and _jitc->function->vagp is to account - * for declared arguments. */ - addi(r0, _FP_REGNO, _jitc->function->self.size - - 16 + _jitc->function->vagp); -} - -static void -_vaarg(jit_state_t *_jit, int32_t r0, int32_t r1) -{ - assert(_jitc->function->self.call & jit_call_varargs); - - /* Load argument. */ - ldr(r0, r1); - - /* Update stack pointer. */ - addi(r1, r1, sizeof(jit_word_t)); -} - -static void -_patch_at(jit_state_t *_jit, - int32_t kind, jit_word_t instr, jit_word_t label) -{ - jit_word_t d; - jit_thumb_t thumb; - union { - int16_t *s; - int32_t *i; - jit_word_t w; - } u; - u.w = instr; - if (kind == arm_patch_jump) { - if (jit_thumb_p() && (jit_uword_t)instr >= _jitc->thumb) { - code2thumb(thumb.s[0], thumb.s[1], u.s[0], u.s[1]); - if ((thumb.i & THUMB2_B) == THUMB2_B) { - d = ((label - instr) >> 1) - 2; - assert(_s24P(d)); - thumb.i = THUMB2_B | encode_thumb_jump(d); - thumb2code(thumb.s[0], thumb.s[1], u.s[0], u.s[1]); - } - else if ((thumb.i & THUMB2_B) == THUMB2_CC_B) { - d = ((label - instr) >> 1) - 2; - assert(_s20P(d)); - thumb.i = THUMB2_CC_B | (thumb.i & 0x3c00000) | - encode_thumb_cc_jump(d); - thumb2code(thumb.s[0], thumb.s[1], u.s[0], u.s[1]); - } - else { - /* for the sake of simplicity in case choose to - * movw+movt+[bx|blx], e.g. if changing to instead - * of asserting target is reachable, load constant - * and do indirect jump if not reachable */ - if ((thumb.i & 0xfbf00000) == THUMB2_MOVWI) - goto indirect_jump; - assert(!"handled branch opcode"); - } - } - else { - thumb.i = u.i[0]; - /* 0x0e000000 because 0x01000000 is (branch&) link modifier */ - assert((thumb.i & 0x0e000000) == ARM_B); - d = ((label - instr) >> 2) - 2; - assert(_s24P(d)); - u.i[0] = (thumb.i & 0xff000000) | (d & 0x00ffffff); - } - } - else if (kind == arm_patch_load) { - /* offset may be negative for a forward patch because it - * is relative to pc + 8, for example: - * ldr r0, [pc, #-4] - * bx r0 ;; [pc, #-8] - * .data ... ;; [pc, #-4] - * ... ;; [pc] - */ - assert(!jit_thumb_p()); - thumb.i = u.i[0]; - assert((thumb.i & 0x0f700000) == ARM_LDRI); - d = label - (instr + 8); - if (d < 0) { - thumb.i &= ~ARM_P; - d = -d; - } - else - thumb.i |= ARM_P; - assert(!(d & 0xfffff000)); - u.i[0] = (thumb.i & 0xfffff000) | d; - } - else if (kind == arm_patch_word) { - if (jit_thumb_p()) { - code2thumb(thumb.s[0], thumb.s[1], u.s[0], u.s[1]); - assert((thumb.i & 0xfbf00000) == THUMB2_MOVWI); - indirect_jump: - thumb.i = ((thumb.i & 0xfbf00f00) | - ( (label & 0x0000f000) << 4) | - ( (label & 0x00000800) << 15) | - ( (label & 0x00000700) << 4) | - ( label & 0x000000ff)); - thumb2code(thumb.s[0], thumb.s[1], u.s[0], u.s[1]); - label >>= 16; - code2thumb(thumb.s[0], thumb.s[1], u.s[2], u.s[3]); - assert((thumb.i & 0xfbf00000) == THUMB2_MOVTI); - thumb.i = ((thumb.i & 0xfbf00f00) | - ( (label & 0x0000f000) << 4) | - ( (label & 0x00000800) << 15) | - ( (label & 0x00000700) << 4) | - ( label & 0x000000ff)); - thumb2code(thumb.s[0], thumb.s[1], u.s[2], u.s[3]); - } - else - u.i[0] = label; - } - else - assert(!"handled patch"); -} -#endif diff --git a/lightening/arm-vfp.c b/lightening/arm-vfp.c index d17a77844..1511e7fbb 100644 --- a/lightening/arm-vfp.c +++ b/lightening/arm-vfp.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2017 Free Software Foundation, Inc. + * Copyright (C) 2012-2017, 2019 Free Software Foundation, Inc. * * This file is part of GNU lightning. * @@ -17,7 +17,6 @@ * Paulo Cesar Pereira de Andrade */ -#if PROTO /* as per vfp_regno macro, required due to "support" to soft float registers * or using integer registers as arguments to float operations */ # define _D8_REGNO 32 @@ -526,120 +525,14 @@ static void _vfp_divi_d(jit_state_t*,int32_t,int32_t,jit_float64_t); static void _vfp_cmp_f(jit_state_t*,int32_t,int32_t); # define vfp_cmp_d(r0,r1) _vfp_cmp_d(_jit,r0,r1) static void _vfp_cmp_d(jit_state_t*,int32_t,int32_t); -# define vcmp01_x(c0,c1,r0) _vcmp01_x(_jit,c0,c1,r0) -static void _vcmp01_x(jit_state_t*,int,int,int32_t); -# define vcmp01_f(c0,c1,r0,r1,r2) _vcmp01_f(_jit,c0,c1,r0,r1,r2) -static void _vcmp01_f(jit_state_t*,int,int,int32_t,int32_t,int32_t); -# define vcmp01_d(c0,c1,r0,r1,r2) _vcmp01_d(_jit,c0,c1,r0,r1,r2) -static void _vcmp01_d(jit_state_t*,int,int,int32_t,int32_t,int32_t); -# define vfp_ltr_f(r0,r1,r2) vcmp01_f(ARM_CC_PL,ARM_CC_MI,r0,r1,r2) -# define vfp_lti_f(r0,r1,i0) _vfp_lti_f(_jit,r0,r1,i0) -static void _vfp_lti_f(jit_state_t*,int32_t,int32_t,jit_float32_t); -# define vfp_ltr_d(r0,r1,r2) vcmp01_d(ARM_CC_PL,ARM_CC_MI,r0,r1,r2) -# define vfp_lti_d(r0,r1,i0) _vfp_lti_d(_jit,r0,r1,i0) -static void _vfp_lti_d(jit_state_t*,int32_t,int32_t,jit_float64_t); -# define vfp_ler_f(r0,r1,r2) vcmp01_f(ARM_CC_HS,ARM_CC_LS,r0,r1,r2) -# define vfp_lei_f(r0,r1,i0) _vfp_lei_f(_jit,r0,r1,i0) -static void _vfp_lei_f(jit_state_t*,int32_t,int32_t,jit_float32_t); -# define vfp_ler_d(r0,r1,r2) vcmp01_d(ARM_CC_HS,ARM_CC_LS,r0,r1,r2) -# define vfp_lei_d(r0,r1,i0) _vfp_lei_d(_jit,r0,r1,i0) -static void _vfp_lei_d(jit_state_t*,int32_t,int32_t,jit_float64_t); -# define vfp_eqr_f(r0,r1,r2) vcmp01_f(ARM_CC_NE,ARM_CC_EQ,r0,r1,r2) -# define vfp_eqi_f(r0,r1,i0) _vfp_eqi_f(_jit,r0,r1,i0) -static void _vfp_eqi_f(jit_state_t*,int32_t,int32_t,jit_float32_t); -# define vfp_eqr_d(r0,r1,r2) vcmp01_d(ARM_CC_NE,ARM_CC_EQ,r0,r1,r2) -# define vfp_eqi_d(r0,r1,i0) _vfp_eqi_d(_jit,r0,r1,i0) -static void _vfp_eqi_d(jit_state_t*,int32_t,int32_t,jit_float64_t); -# define vfp_ger_f(r0,r1,r2) vcmp01_f(ARM_CC_LT,ARM_CC_GE,r0,r1,r2) -# define vfp_gei_f(r0,r1,i0) _vfp_gei_f(_jit,r0,r1,i0) -static void _vfp_gei_f(jit_state_t*,int32_t,int32_t,jit_float32_t); -# define vfp_ger_d(r0,r1,r2) vcmp01_d(ARM_CC_LT,ARM_CC_GE,r0,r1,r2) -# define vfp_gei_d(r0,r1,i0) _vfp_gei_d(_jit,r0,r1,i0) -static void _vfp_gei_d(jit_state_t*,int32_t,int32_t,jit_float64_t); -# define vfp_gtr_f(r0,r1,r2) vcmp01_f(ARM_CC_LE,ARM_CC_GT,r0,r1,r2) -# define vfp_gti_f(r0,r1,i0) _vfp_gti_f(_jit,r0,r1,i0) -static void _vfp_gti_f(jit_state_t*,int32_t,int32_t,jit_float32_t); -# define vfp_gtr_d(r0,r1,r2) vcmp01_d(ARM_CC_LE,ARM_CC_GT,r0,r1,r2) -# define vfp_gti_d(r0,r1,i0) _vfp_gti_d(_jit,r0,r1,i0) -static void _vfp_gti_d(jit_state_t*,int32_t,int32_t,jit_float64_t); -# define vfp_ner_f(r0,r1,r2) vcmp01_f(ARM_CC_EQ,ARM_CC_NE,r0,r1,r2) -# define vfp_nei_f(r0,r1,i0) _vfp_nei_f(_jit,r0,r1,i0) -static void _vfp_nei_f(jit_state_t*,int32_t,int32_t,jit_float32_t); -# define vfp_ner_d(r0,r1,r2) vcmp01_d(ARM_CC_EQ,ARM_CC_NE,r0,r1,r2) -# define vfp_nei_d(r0,r1,i0) _vfp_nei_d(_jit,r0,r1,i0) -static void _vfp_nei_d(jit_state_t*,int32_t,int32_t,jit_float64_t); # define vcmp10_x(c0,r0) _vcmp10_x(_jit,c0,r0) static void _vcmp10_x(jit_state_t*,int,int32_t); -# define vcmp_10_f(c0,r0,r1,r2) _vcmp_10_f(_jit,c0,r0,r1,r2) -static void _vcmp_10_f(jit_state_t*,int,int32_t,int32_t,int32_t); -# define vcmp_10_d(c0,r0,r1,r2) _vcmp_10_d(_jit,c0,r0,r1,r2) -static void _vcmp_10_d(jit_state_t*,int,int32_t,int32_t,int32_t); -# define vfp_unltr_f(r0,r1,r2) vcmp_10_f(ARM_CC_GE,r0,r1,r2) -# define vfp_unlti_f(r0,r1,i0) _vfp_unlti_f(_jit,r0,r1,i0) -static void _vfp_unlti_f(jit_state_t*,int32_t,int32_t,jit_float32_t); -# define vfp_unltr_d(r0,r1,r2) vcmp_10_d(ARM_CC_GE,r0,r1,r2) -# define vfp_unlti_d(r0,r1,i0) _vfp_unlti_d(_jit,r0,r1,i0) -static void _vfp_unlti_d(jit_state_t*,int32_t,int32_t,jit_float64_t); -# define vfp_unler_f(r0,r1,r2) vcmp_10_f(ARM_CC_GT,r0,r1,r2) -# define vfp_unlei_f(r0,r1,i0) _vfp_unlei_f(_jit,r0,r1,i0) -static void _vfp_unlei_f(jit_state_t*,int32_t,int32_t,jit_float32_t); -# define vfp_unler_d(r0,r1,r2) vcmp_10_d(ARM_CC_GT,r0,r1,r2) -# define vfp_unlei_d(r0,r1,i0) _vfp_unlei_d(_jit,r0,r1,i0) -static void _vfp_unlei_d(jit_state_t*,int32_t,int32_t,jit_float64_t); -# define vfp_uneqr_x(r0) _vfp_uneqr_x(_jit,r0) -static void _vfp_uneqr_x(jit_state_t*,int32_t); -# define vfp_uneqr_f(r0,r1,r2) _vfp_uneqr_f(_jit,r0,r1,r2) -static void _vfp_uneqr_f(jit_state_t*,int32_t,int32_t,int32_t); -# define vfp_uneqi_f(r0,r1,i0) _vfp_uneqi_f(_jit,r0,r1,i0) -static void _vfp_uneqi_f(jit_state_t*,int32_t,int32_t,jit_float32_t); -# define vfp_uneqr_d(r0,r1,r2) _vfp_uneqr_d(_jit,r0,r1,r2) -static void _vfp_uneqr_d(jit_state_t*,int32_t,int32_t,int32_t); -# define vfp_uneqi_d(r0,r1,i0) _vfp_uneqi_d(_jit,r0,r1,i0) -static void _vfp_uneqi_d(jit_state_t*,int32_t,int32_t,jit_float64_t); # define vcmp_01_x(c0,r0) _vcmp_01_x(_jit,c0,r0) static void _vcmp_01_x(jit_state_t*,int,int32_t); # define vcmp_01_f(c0,r0,r1,r2) _vcmp_01_f(_jit,c0,r0,r1,r2) static void _vcmp_01_f(jit_state_t*,int,int32_t,int32_t,int32_t); # define vcmp_01_d(c0,r0,r1,r2) _vcmp_01_d(_jit,c0,r0,r1,r2) static void _vcmp_01_d(jit_state_t*,int,int32_t,int32_t,int32_t); -# define vfp_unger_f(r0,r1,r2) vcmp_01_f(ARM_CC_CS,r0,r1,r2) -# define vfp_ungei_f(r0,r1,i0) _vfp_ungei_f(_jit,r0,r1,i0) -static void _vfp_ungei_f(jit_state_t*,int32_t,int32_t,jit_float32_t); -# define vfp_unger_d(r0,r1,r2) vcmp_01_d(ARM_CC_CS,r0,r1,r2) -# define vfp_ungei_d(r0,r1,i0) _vfp_ungei_d(_jit,r0,r1,i0) -static void _vfp_ungei_d(jit_state_t*,int32_t,int32_t,jit_float64_t); -# define vfp_ungtr_f(r0,r1,r2) vcmp_01_f(ARM_CC_HI,r0,r1,r2) -# define vfp_ungti_f(r0,r1,i0) _vfp_ungti_f(_jit,r0,r1,i0) -static void _vfp_ungti_f(jit_state_t*,int32_t,int32_t,jit_float32_t); -# define vfp_ungtr_d(r0,r1,r2) vcmp_01_d(ARM_CC_HI,r0,r1,r2) -# define vfp_ungti_d(r0,r1,i0) _vfp_ungti_d(_jit,r0,r1,i0) -static void _vfp_ungti_d(jit_state_t*,int32_t,int32_t,jit_float64_t); -# define vfp_ltgtr_x(r0) _vfp_ltgtr_x(_jit,r0) -static void _vfp_ltgtr_x(jit_state_t*,int32_t); -# define vfp_ltgtr_f(r0,r1,r2) _vfp_ltgtr_f(_jit,r0,r1,r2) -static void _vfp_ltgtr_f(jit_state_t*,int32_t,int32_t,int32_t); -# define vfp_ltgti_f(r0,r1,i0) _vfp_ltgti_f(_jit,r0,r1,i0) -static void _vfp_ltgti_f(jit_state_t*,int32_t,int32_t,jit_float32_t); -# define vfp_ltgtr_d(r0,r1,r2) _vfp_ltgtr_d(_jit,r0,r1,r2) -static void _vfp_ltgtr_d(jit_state_t*,int32_t,int32_t,int32_t); -# define vfp_ltgti_d(r0,r1,i0) _vfp_ltgti_d(_jit,r0,r1,i0) -static void _vfp_ltgti_d(jit_state_t*,int32_t,int32_t,jit_float64_t); -# define vfp_ordr_f(r0,r1,r2) _vfp_ordr_f(_jit,r0,r1,r2) -static void _vfp_ordr_f(jit_state_t*,int32_t,int32_t,int32_t); -# define vfp_ordi_f(r0,r1,i0) _vfp_ordi_f(_jit,r0,r1,i0) -static void _vfp_ordi_f(jit_state_t*,int32_t,int32_t,jit_float32_t); -# define vfp_ordr_d(r0,r1,r2) _vfp_ordr_d(_jit,r0,r1,r2) -static void _vfp_ordr_d(jit_state_t*,int32_t,int32_t,int32_t); -# define vfp_ordi_d(r0,r1,i0) _vfp_ordi_d(_jit,r0,r1,i0) -static void _vfp_ordi_d(jit_state_t*,int32_t,int32_t,jit_float64_t); -# define vfp_unordr_f(r0,r1,r2) _vfp_unordr_f(_jit,r0,r1,r2) -static void _vfp_unordr_f(jit_state_t*,int32_t,int32_t,int32_t); -# define vfp_unordi_f(r0,r1,i0) _vfp_unordi_f(_jit,r0,r1,i0) -static void _vfp_unordi_f(jit_state_t*,int32_t,int32_t,jit_float32_t); -# define vfp_unordr_d(r0,r1,r2) _vfp_unordr_d(_jit,r0,r1,r2) -static void _vfp_unordr_d(jit_state_t*,int32_t,int32_t,int32_t); -# define vfp_unordi_d(r0,r1,i0) _vfp_unordi_d(_jit,r0,r1,i0) -static void _vfp_unordi_d(jit_state_t*,int32_t,int32_t,jit_float64_t); # define vbcmp_x(cc,i0) _vbcmp_x(_jit,cc,i0) static jit_word_t _vbcmp_x(jit_state_t*,int,jit_word_t); # define vbcmp_f(cc,i0,r0,r1) _vbcmp_f(_jit,cc,i0,r0,r1) @@ -806,9 +699,7 @@ static void _vfp_stxi_f(jit_state_t*,jit_word_t,int32_t,int32_t); static void _vfp_stxi_d(jit_state_t*,jit_word_t,int32_t,int32_t); # define vfp_vaarg_d(r0, r1) _vfp_vaarg_d(_jit, r0, r1) static void _vfp_vaarg_d(jit_state_t*, int32_t, int32_t); -#endif -#if CODE # define vfp_regno(rn) (((rn) - 16) >> 1) static int @@ -1416,64 +1307,6 @@ _vfp_truncr_d_i(jit_state_t *_jit, int32_t r0, int32_t r1) jit_unget_reg(reg); } -# define fopi(name) \ -static void \ -_vfp_##name##i_f(jit_state_t *_jit, \ - int32_t r0, int32_t r1, jit_float32_t i0) \ -{ \ - int32_t reg = jit_get_reg(jit_class_fpr); \ - vfp_movi_f(rn(reg), i0); \ - vfp_##name##r_f(r0, r1, rn(reg)); \ - jit_unget_reg(reg); \ -} -# define dopi(name) \ -static void \ -_vfp_##name##i_d(jit_state_t *_jit, \ - int32_t r0, int32_t r1, jit_float64_t i0) \ -{ \ - int32_t reg = jit_get_reg(jit_class_fpr); \ - vfp_movi_d(rn(reg), i0); \ - vfp_##name##r_d(r0, r1, rn(reg)); \ - jit_unget_reg(reg); \ -} -# define fbopi(name) \ -static jit_word_t \ -_vfp_b##name##i_f(jit_state_t *_jit, \ - int32_t r0, int32_t r1, jit_float32_t i0) \ -{ \ - jit_word_t word; \ - int32_t reg = jit_get_reg(jit_class_fpr| \ - jit_class_nospill); \ - vfp_movi_f(rn(reg), i0); \ - word = vfp_b##name##r_f(r0, r1, rn(reg)); \ - jit_unget_reg(reg); \ - return (word); \ -} -# define dbopi(name) \ -static jit_word_t \ -_vfp_b##name##i_d(jit_state_t *_jit, \ - int32_t r0, int32_t r1, jit_float64_t i0) \ -{ \ - jit_word_t word; \ - int32_t reg = jit_get_reg(jit_class_fpr| \ - jit_class_nospill); \ - vfp_movi_d(rn(reg), i0); \ - word = vfp_b##name##r_d(r0, r1, rn(reg)); \ - jit_unget_reg(reg); \ - return (word); \ -} - -fopi(add) -dopi(add) -fopi(sub) -fopi(rsb) -dopi(rsb) -dopi(sub) -fopi(mul) -dopi(mul) -fopi(div) -dopi(div) - static void _vfp_cmp_f(jit_state_t *_jit, int32_t r0, int32_t r1) { @@ -1532,284 +1365,6 @@ _vfp_cmp_d(jit_state_t *_jit, int32_t r0, int32_t r1) } } -static void -_vcmp01_x(jit_state_t *_jit, int c0, int c1, int32_t r0) -{ - VMRS(_R15_REGNO); - if (jit_thumb_p()) { - if ((c0 ^ c1) >> 28 == 1) { - ITE(c0); - if (r0 < 8) { - T1_MOVI(r0, 0); - T1_MOVI(r0, 1); - } - else { - T2_MOVI(r0, 0); - T2_MOVI(r0, 1); - } - } - else { - if (r0 < 8) { - IT(c0); - T1_MOVI(r0, 0); - IT(c1); - T1_MOVI(r0, 1); - } - else { - IT(c0); - T2_MOVI(r0, 0); - IT(c1); - T2_MOVI(r0, 1); - } - } - } - else { - CC_MOVI(c0, r0, 0); - CC_MOVI(c1, r0, 1); - } -} - -static void -_vcmp01_f(jit_state_t *_jit, int c0, int c1, - int32_t r0, int32_t r1, int32_t r2) -{ - vfp_cmp_f(r1, r2); - vcmp01_x(c0, c1, r0); -} - -static void -_vcmp01_d(jit_state_t *_jit, int c0, int c1, - int32_t r0, int32_t r1, int32_t r2) -{ - vfp_cmp_d(r1, r2); - vcmp01_x(c0, c1, r0); -} - -static void -_vcmp10_x(jit_state_t *_jit, int cc, int32_t r0) -{ - if (jit_thumb_p()) { - if (r0 < 8) { - T1_MOVI(r0, 1); - VMRS(_R15_REGNO); - IT(cc); - T1_MOVI(r0, 0); - } - else { - T2_MOVI(r0, 1); - VMRS(_R15_REGNO); - IT(cc); - T2_MOVI(r0, 0); - } - } - else { - VMRS(_R15_REGNO); - MOVI(r0, 1); - CC_MOVI(cc, r0, 0); - } -} -static void -_vcmp_10_f(jit_state_t *_jit, int cc, - int32_t r0, int32_t r1, int32_t r2) -{ - vfp_cmp_f(r1, r2); - vcmp10_x(cc, r0); -} - -static void -_vcmp_10_d(jit_state_t *_jit, int cc, - int32_t r0, int32_t r1, int32_t r2) -{ - vfp_cmp_d(r1, r2); - vcmp10_x(cc, r0); -} - -fopi(lt) -dopi(lt) -fopi(le) -dopi(le) -fopi(eq) -dopi(eq) -fopi(ge) -dopi(ge) -fopi(gt) -dopi(gt) -fopi(ne) -dopi(ne) -fopi(unlt) -dopi(unlt) -fopi(unle) -dopi(unle) - -static void -_vfp_uneqr_x(jit_state_t *_jit, int32_t r0) -{ - VMRS(_R15_REGNO); - if (jit_thumb_p()) { - ITE(ARM_CC_NE); - if (r0 < 8) { - T1_MOVI(r0, 0); - T1_MOVI(r0, 1); - IT(ARM_CC_VS); - T1_MOVI(r0, 1); - } - else { - T2_MOVI(r0, 0); - T2_MOVI(r0, 1); - IT(ARM_CC_VS); - T2_MOVI(r0, 1); - } - } - else { - CC_MOVI(ARM_CC_NE, r0, 0); - CC_MOVI(ARM_CC_EQ, r0, 1); - CC_MOVI(ARM_CC_VS, r0, 1); - } -} - -static void -_vfp_uneqr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - vfp_cmp_f(r1, r2); - vfp_uneqr_x(r0); -} - -fopi(uneq) - -static void -_vfp_uneqr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - vfp_cmp_d(r1, r2); - vfp_uneqr_x(r0); -} - -dopi(uneq) - -static void -_vcmp_01_x(jit_state_t *_jit, int cc, int32_t r0) -{ - if (jit_thumb_p()) { - if (r0 < 8) { - T1_MOVI(r0, 0); - VMRS(_R15_REGNO); - IT(cc); - T1_MOVI(r0, 1); - } - else { - T2_MOVI(r0, 0); - VMRS(_R15_REGNO); - IT(cc); - T2_MOVI(r0, 1); - } - } - else { - MOVI(r0, 0); - VMRS(_R15_REGNO); - CC_MOVI(cc, r0, 1); - } -} - -static void -_vcmp_01_f(jit_state_t *_jit, int cc, - int32_t r0, int32_t r1, int32_t r2) -{ - vfp_cmp_f(r1, r2); - vcmp_01_x(cc, r0); -} - -static void -_vcmp_01_d(jit_state_t *_jit, int cc, - int32_t r0, int32_t r1, int32_t r2) -{ - vfp_cmp_d(r1, r2); - vcmp_01_x(cc, r0); -} - -fopi(unge) -dopi(unge) -fopi(ungt) -dopi(ungt) - -static void -_vfp_ltgtr_x(jit_state_t *_jit, int32_t r0) -{ - VMRS(_R15_REGNO); - if (jit_thumb_p()) { - ITE(ARM_CC_NE); - if (r0 < 8) { - T1_MOVI(r0, 1); - T1_MOVI(r0, 0); - IT(ARM_CC_VS); - T1_MOVI(r0, 0); - } - else { - T2_MOVI(r0, 1); - T2_MOVI(r0, 0); - IT(ARM_CC_VS); - T2_MOVI(r0, 0); - } - } - else { - CC_MOVI(ARM_CC_NE, r0, 1); - CC_MOVI(ARM_CC_EQ, r0, 0); - CC_MOVI(ARM_CC_VS, r0, 0); - } -} - -static void -_vfp_ltgtr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - vfp_cmp_f(r1, r2); - vfp_ltgtr_x(r0); -} - -fopi(ltgt) - -static void -_vfp_ltgtr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - vfp_cmp_d(r1, r2); - vfp_ltgtr_x(r0); -} - -dopi(ltgt) - -static void -_vfp_ordr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - vfp_cmp_f(r1, r2); - vcmp10_x(ARM_CC_VS, r0); -} - -fopi(ord) - -static void -_vfp_ordr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - vfp_cmp_d(r1, r2); - vcmp10_x(ARM_CC_VS, r0); -} - -dopi(ord) - -static void -_vfp_unordr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - vfp_cmp_f(r1, r2); - vcmp_01_x(ARM_CC_VS, r0); -} - -fopi(unord) - -static void -_vfp_unordr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - vfp_cmp_d(r1, r2); - vcmp_01_x(ARM_CC_VS, r0); -} - -dopi(unord) - static jit_word_t _vbcmp_x(jit_state_t *_jit, int cc, jit_word_t i0) { @@ -1886,23 +1441,6 @@ _vbncmp_d(jit_state_t *_jit, int cc, return (vbncmp_x(cc, i0)); } -fbopi(lt) -dbopi(lt) -fbopi(le) -dbopi(le) -fbopi(eq) -dbopi(eq) -fbopi(ge) -dbopi(ge) -fbopi(gt) -dbopi(gt) -fbopi(ne) -dbopi(ne) -fbopi(unlt) -dbopi(unlt) -fbopi(unle) -dbopi(unle) - static jit_word_t _vfp_buneqr_x(jit_state_t *_jit, jit_word_t i0) { @@ -1940,8 +1478,6 @@ _vfp_buneqr_f(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) return (vfp_buneqr_x(i0)); } -fbopi(uneq) - static jit_word_t _vfp_buneqr_d(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) { @@ -1949,8 +1485,6 @@ _vfp_buneqr_d(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) return (vfp_buneqr_x(i0)); } -dbopi(uneq) - static jit_word_t _vfp_bunger_x(jit_state_t *_jit, jit_word_t i0) { @@ -1982,8 +1516,6 @@ _vfp_bunger_f(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) return (vfp_bunger_x(i0)); } -fbopi(unge) - static jit_word_t _vfp_bunger_d(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) { @@ -1991,8 +1523,6 @@ _vfp_bunger_d(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) return (vfp_bunger_x(i0)); } -dbopi(unge) - static jit_word_t _vfp_bltgtr_x(jit_state_t *_jit, jit_word_t i0) { @@ -2029,10 +1559,6 @@ _vfp_bltgtr_f(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) return (vfp_bltgtr_x(i0)); } -fbopi(ungt) -dbopi(ungt) -fbopi(ltgt) - static jit_word_t _vfp_bltgtr_d(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) { @@ -2040,12 +1566,6 @@ _vfp_bltgtr_d(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) return (vfp_bltgtr_x(i0)); } -dbopi(ltgt) -fbopi(ord) -dbopi(ord) -fbopi(unord) -dbopi(unord) - static void _vfp_ldi_f(jit_state_t *_jit, int32_t r0, jit_word_t i0) { @@ -2323,8 +1843,3 @@ _vfp_vaarg_d(jit_state_t *_jit, int32_t r0, int32_t r1) /* Update stack pointer. */ addi(r1, r1, sizeof(jit_float64_t)); } -# undef dbopi -# undef fbopi -# undef dopi -# undef fopi -#endif diff --git a/lightening/arm.h b/lightening/arm.h index 94fc86c5b..b4f64667d 100644 --- a/lightening/arm.h +++ b/lightening/arm.h @@ -90,14 +90,11 @@ #define _S30 JIT_FPR(30) #define _S31 JIT_FPR(31) -#define _SP _R13 -#define _LR _R14 -#define _PC _R15 - #define JIT_R0 _R0 #define JIT_R1 _R1 #define JIT_R2 _R2 -#define JIT_R3 _R3 +#define JIT_R3 _R12 +#define JIT_TMP0 _R3 #define JIT_V0 _R4 #define JIT_V1 _R5 @@ -108,6 +105,10 @@ #define JIT_V6 _R10 #define JIT_V7 _R11 +#define _SP _R13 +#define _LR _R14 +#define _PC _R15 + #define JIT_F0 _D0 #define JIT_F1 _D1 #define JIT_F2 _D2 @@ -115,7 +116,7 @@ #define JIT_F4 _D4 #define JIT_F5 _D5 #define JIT_F6 _D6 -#define JIT_F7 _D7 +#define JIT_FTMP _D7 #define JIT_VF0 _D8 #define JIT_VF1 _D9 diff --git a/lightening/lightening.c b/lightening/lightening.c index 2838891c0..e03dbda4c 100644 --- a/lightening/lightening.c +++ b/lightening/lightening.c @@ -395,7 +395,7 @@ jit_patch_there(jit_state_t* _jit, jit_reloc_t reloc, jit_pointer_t addr) remove_pending_literal(_jit, reloc); } else { // Target out of range; branch to veneer. - patch_pending_literal(_jit, reloc, (uint64_t) addr); + patch_pending_literal(_jit, reloc, (uintptr_t) addr); } } else { // Already emitted a veneer. In this case, patch the veneer @@ -412,7 +412,7 @@ jit_patch_there(jit_state_t* _jit, jit_reloc_t reloc, jit_pointer_t addr) patch_jcc_offset(loc.ui, diff); remove_pending_literal(_jit, reloc); } else { - patch_pending_literal(_jit, reloc, (uint64_t) addr); + patch_pending_literal(_jit, reloc, (uintptr_t) addr); } } else { uint8_t *target = pc_base + (voff << reloc.rsh); @@ -423,7 +423,7 @@ jit_patch_there(jit_state_t* _jit, jit_reloc_t reloc, jit_pointer_t addr) case JIT_RELOC_LOAD_FROM_POOL: { uint32_t voff = read_load_from_pool_offset(loc.ui); if (voff == 0) { - patch_pending_literal(_jit, reloc, (uint64_t) addr); + patch_pending_literal(_jit, reloc, (uintptr_t) addr); } else { uint8_t *target = pc_base + (voff << reloc.rsh); *(uintptr_t *) target = (uintptr_t) addr; From 8ce07131f1d710d07311ca57ef01ef02724b2e33 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Sun, 19 May 2019 23:29:10 +0200 Subject: [PATCH 27/33] Beginnings of VFP port to lightening --- lightening/arm-cpu.c | 65 - lightening/arm-vfp.c | 2758 +++++++++++++++++++----------------------- 2 files changed, 1228 insertions(+), 1595 deletions(-) diff --git a/lightening/arm-cpu.c b/lightening/arm-cpu.c index 3c3c20757..44988976e 100644 --- a/lightening/arm-cpu.c +++ b/lightening/arm-cpu.c @@ -31,11 +31,7 @@ #define ARM_CC_EQ 0x00000000 /* Z=1 */ #define ARM_CC_NE 0x10000000 /* Z=0 */ #define ARM_CC_HS 0x20000000 /* C=1 */ -#define ARM_CC_CS ARM_CC_HS #define ARM_CC_LO 0x30000000 /* C=0 */ -#define ARM_CC_CC ARM_CC_LO -#define ARM_CC_MI 0x40000000 /* N=1 */ -#define ARM_CC_PL 0x50000000 /* N=0 */ #define ARM_CC_VS 0x60000000 /* V=1 */ #define ARM_CC_VC 0x70000000 /* V=0 */ #define ARM_CC_HI 0x80000000 /* C=1 && Z=0 */ @@ -55,7 +51,6 @@ #define THUMB2_MVN 0xea600000 #define THUMB2_MVNI 0xf0600000 #define ARM_S 0x00100000 /* set flags */ -#define ARM_ADD 0x00800000 #define THUMB_ADD 0x1800 #define THUMB_ADDX 0x4400 #define THUMB2_ADD 0xeb000000 @@ -63,7 +58,6 @@ #define THUMB_ADDI8 0x3000 #define THUMB2_ADDI 0xf1000000 #define THUMB2_ADDWI 0xf2000000 -#define ARM_ADC 0x00a00000 #define THUMB_ADC 0x4140 #define THUMB2_ADC 0xeb400000 #define THUMB2_ADCI 0xf1400000 @@ -76,55 +70,36 @@ #define THUMB_SBC 0x4180 #define THUMB2_SBC 0xeb600000 #define THUMB2_SBCI 0xf1600000 -#define ARM_RSB 0x00600000 #define THUMB_RSBI 0x4240 #define THUMB2_RSBI 0xf1c00000 -#define ARM_MUL 0x00000090 #define THUMB_MUL 0x4340 #define THUMB2_MUL 0xfb00f000 -#define ARM_UMULL 0x00800090 #define THUMB2_UMULL 0xfba00000 #define THUMB2_SMULL 0xfb800000 #define THUMB_MLS 0xfb000010 #define THUMB2_SDIV 0xfb90f0f0 #define THUMB2_UDIV 0xfbb0f0f0 -#define ARM_AND 0x00000000 #define THUMB_AND 0x4000 #define THUMB2_AND 0xea000000 #define THUMB2_ANDI 0xf0000000 -#define ARM_BIC 0x01c00000 #define THUMB2_BIC 0xea200000 #define THUMB2_BICI 0xf0200000 -#define ARM_ORR 0x01800000 #define THUMB_ORR 0x4300 #define THUMB2_ORR 0xea400000 #define THUMB2_ORRI 0xf0400000 -#define ARM_EOR 0x00200000 #define THUMB_EOR 0x4040 #define THUMB2_EOR 0xea800000 #define THUMB2_EORI 0xf0800000 -/* >> ARMv6* */ -#define ARM_REV 0x06bf0f30 #define THUMB_REV 0xba00 #define THUMB2_REV 0xfa90f080 -#define ARM_REV16 0x06bf0fb0 -#define THUMB_REV16 0xba40 -#define THUMB2_REV16 0xfa90f090 #define THUMB_SXTB 0xb240 #define THUMB2_SXTB 0xfa40f080 -#define ARM_UXTB 0x06ef0070 #define THUMB_UXTB 0xb2c0 #define THUMB2_UXTB 0xfa50f080 #define THUMB_SXTH 0xb200 #define THUMB2_SXTH 0xfa00f080 -#define ARM_UXTH 0x06ff0070 #define THUMB_UXTH 0xb280 #define THUMB2_UXTH 0xfa10f080 -#define ARM_XTR8 0x00000400 /* ?xt? rotate 8 bits */ -#define ARM_XTR16 0x00000800 /* ?xt? rotate 16 bits */ -#define ARM_XTR24 0x00000c00 /* ?xt? rotate 24 bits */ -/* << ARMv6* */ -#define ARM_R 0x00000010 /* register shift */ #define ARM_LSL 0x00000000 #define THUMB_LSL 0x4080 #define THUMB2_LSL 0xfa00f000 @@ -140,73 +115,48 @@ #define THUMB2_ASR 0xfa40f000 #define THUMB_ASRI 0x1000 #define THUMB2_ASRI 0xea4f0020 -#define ARM_ROR 0x00000060 -#define ARM_CMP 0x01500000 #define THUMB_CMP 0x4280 #define THUMB_CMPX 0x4500 #define THUMB2_CMP 0xebb00000 #define THUMB_CMPI 0x2800 #define THUMB2_CMPI 0xf1b00000 -#define ARM_CMN 0x01700000 -#define THUMB_CMN 0x42c0 #define THUMB2_CMN 0xeb100000 #define THUMB2_CMNI 0xf1100000 -#define ARM_TST 0x01100000 #define THUMB_TST 0x4200 #define THUMB2_TST 0xea100000 #define THUMB2_TSTI 0xf0100000 -#define ARM_TEQ 0x01300000 -/* branch */ -#define ARM_B 0x0a000000 #define THUMB_CC_B 0xd000 #define THUMB_B 0xe000 #define THUMB2_CC_B 0xf0008000 #define THUMB2_B 0xf0009000 -#define ARM_BLI 0x0b000000 #define THUMB2_BLI 0xf000d000 -/* ldr/str */ -#define ARM_P 0x00800000 /* positive offset */ #define THUMB2_P 0x00000400 #define THUMB2_U 0x00000200 -#define THUMB2_W 0x00000100 -#define ARM_LDRSB 0x011000d0 #define THUMB_LDRSB 0x5600 #define THUMB2_LDRSB 0xf9100000 -#define ARM_LDRSBI 0x015000d0 #define THUMB2_LDRSBI 0xf9100c00 #define THUMB2_LDRSBWI 0xf9900000 -#define ARM_LDRB 0x07500000 #define THUMB_LDRB 0x5c00 #define THUMB2_LDRB 0xf8100000 -#define ARM_LDRBI 0x05500000 #define THUMB_LDRBI 0x7800 #define THUMB2_LDRBI 0xf8100c00 #define THUMB2_LDRBWI 0xf8900000 -#define ARM_LDRSH 0x011000f0 #define THUMB_LDRSH 0x5e00 #define THUMB2_LDRSH 0xf9300000 -#define ARM_LDRSHI 0x015000f0 #define THUMB2_LDRSHI 0xf9300c00 #define THUMB2_LDRSHWI 0xf9b00000 -#define ARM_LDRH 0x011000b0 #define THUMB_LDRH 0x5a00 #define THUMB2_LDRH 0xf8300000 -#define ARM_LDRHI 0x015000b0 #define THUMB_LDRHI 0x8800 #define THUMB2_LDRHI 0xf8300c00 #define THUMB2_LDRHWI 0xf8b00000 -#define ARM_LDR 0x07100000 #define THUMB_LDR 0x5800 #define THUMB2_LDR 0xf8500000 #define THUMB2_LDRP 0xf85f0000 -#define ARM_LDRI 0x05100000 #define THUMB_LDRI 0x6800 #define THUMB_LDRISP 0x9800 #define THUMB2_LDRI 0xf8500c00 #define THUMB2_LDRWI 0xf8d00000 -#define ARM_LDRD 0x010000d0 -#define ARM_LDRDI 0x014000d0 -#define THUMB2_LDRDI 0xe8500000 #define THUMB_STRB 0x5400 #define THUMB2_STRB 0xf8000000 #define THUMB_STRBI 0x7000 @@ -223,23 +173,8 @@ #define THUMB2_STRWI 0xf8c00000 #define THUMB_STRISP 0x9000 #define THUMB2_STRI 0xf8400c00 -#define THUMB2_STRDI 0xe8400000 -/* ldm/stm */ -#define ARM_M 0x08000000 -#define ARM_M_L 0x00100000 /* load; store if not set */ -#define ARM_M_I 0x00800000 /* inc; dec if not set */ -#define ARM_M_B 0x01000000 /* before; after if not set */ -#define ARM_M_U 0x00200000 /* update Rn */ #define THUMB2_LDM_W 0x00200000 -#define THUMB2_LDM_P 0x00008000 -#define THUMB2_LDM_M 0x00004000 -#define THUMB_LDMIA 0xc800 -#define THUMB2_LDMIA 0xe8900000 -#define THUMB2_LDMB 0xe9100000 -#define THUMB_PUSH 0xb400 #define THUMB2_PUSH 0xe92d0000 -#define THUMB_POP 0xbc00 -#define THUMB2_POP 0xe8bd0000 #define _NOREG (jit_gpr_regno(_PC)) diff --git a/lightening/arm-vfp.c b/lightening/arm-vfp.c index 1511e7fbb..885f2db47 100644 --- a/lightening/arm-vfp.c +++ b/lightening/arm-vfp.c @@ -14,1832 +14,1530 @@ * License for more details. * * Authors: - * Paulo Cesar Pereira de Andrade + * Paulo Cesar Pereira de Andrade */ /* as per vfp_regno macro, required due to "support" to soft float registers * or using integer registers as arguments to float operations */ -# define _D8_REGNO 32 -# define ARM_V_Q 0x00000040 -# define FPSCR_N 0x80000000 /* Negative flag */ -# define FPSCR_Z 0x40000000 /* Zero flag */ -# define FPSCR_C 0x20000000 /* Carry flag */ -# define FPSCR_V 0x10000000 /* Overflow flag */ -# define FPSCR_QC 0x08000000 /* Cumulative saturation */ -# define FPSCR_AHP 0x04000000 /* Alt. half-precision */ -# define FPSCR_DN 0x02000000 /* Default NaN mode */ -# define FPSCR_FZ 0x01000000 /* Flush to zero */ -# define FPSCR_RMASK 0x00c00000 -# define FPSCR_RN 0x00000000 /* Round to Nearest */ -# define FPSCR_RP 0x00400000 /* Round to Plus Infinity */ -# define FPSCR_RM 0x00800000 /* Round to Minus Infinity */ -# define FPSCR_RZ 0x00c00000 /* Round towards Zero */ -# define FPSCR_STRIDE 0x00300000 -# define FPSCR_RES1 0x00080000 /* Reserved, UNK/SBZP */ -# define FPSCR_LEN 0x00070000 -# define FPSCR_IDE 0x00008000 /* Input Denormal trap */ -# define FPSCR_IXE 0x00001000 /* Inexact trap */ -# define FPSCR_UFE 0x00000800 /* Underflow trap */ -# define FPSCR_OFE 0x00000400 /* Overflow trap */ -# define FPSCR_DZE 0x00000200 /* Division by zero trap */ -# define FPSCR_IOE 0x00000100 /* Invalid Operation trap */ -# define FPSCR_IDC 0x00000080 /* Input Denormal flag */ -# define FPSCR_RES0 0x00000060 /* Reserved, UNK/SBZP */ -# define FPSCR_IXC 0x00000010 /* Inexact flag */ -# define FPSCR_UFC 0x00000008 /* Underflow flag */ -# define FPSCR_OFC 0x00000004 /* Overflow flag */ -# define FPSCR_DZC 0x00000002 /* Division by zero flag */ -# define FPSCR_IOC 0x00000001 /* Invalid Operation flag */ -# define ARM_V_E 0x00000080 /* ARM_VCMP except if NaN */ -# define ARM_V_Z 0x00010000 /* ARM_VCMP with zero */ -# define ARM_V_F64 0x00000100 -# define ARM_VADD_F 0x0e300a00 -# define ARM_VSUB_F 0x0e300a40 -# define ARM_VMUL_F 0x0e200a00 -# define ARM_VDIV_F 0x0e800a00 -# define ARM_VABS_F 0x0eb00ac0 -# define ARM_VNEG_F 0x0eb10a40 -# define ARM_VSQRT_F 0x0eb10ac0 -# define ARM_VMOV_F 0x0eb00a40 -# define ARM_VMOV_A_S 0x0e100a10 /* vmov rn, sn */ -# define ARM_VMOV_S_A 0x0e000a10 /* vmov sn, rn */ -# define ARM_VMOV_AA_D 0x0c500b10 /* vmov rn,rn, dn */ -# define ARM_VMOV_D_AA 0x0c400b10 /* vmov dn, rn,rn */ -# define ARM_VCMP 0x0eb40a40 -# define ARM_VMRS 0x0ef10a10 -# define ARM_VMSR 0x0ee10a10 -# define ARM_VCVT_2I 0x00040000 /* to integer */ -# define ARM_VCVT_2S 0x00010000 /* to signed */ -# define ARM_VCVT_RS 0x00000080 /* round to zero or signed */ -# define ARM_VCVT 0x0eb80a40 -# define ARM_VCVT_S32_F32 ARM_VCVT|ARM_VCVT_2I|ARM_VCVT_2S|ARM_VCVT_RS -# define ARM_VCVT_U32_F32 ARM_VCVT|ARM_VCVT_2I|ARM_VCVT_RS -# define ARM_VCVT_S32_F64 ARM_VCVT|ARM_VCVT_2I|ARM_VCVT_2S|ARM_VCVT_RS|ARM_V_F64 -# define ARM_VCVT_U32_F64 ARM_VCVT|ARM_VCVT_2I|ARM_VCVT_RS|ARM_V_F64 -# define ARM_VCVT_F32_S32 ARM_VCVT|ARM_VCVT_RS -# define ARM_VCVT_F32_U32 ARM_VCVT -# define ARM_VCVT_F64_S32 ARM_VCVT|ARM_VCVT_RS|ARM_V_F64 -# define ARM_VCVT_F64_U32 ARM_VCVT|ARM_V_F64 -# define ARM_VCVT_F 0x0eb70ac0 -# define ARM_VCVT_F32_F64 ARM_VCVT_F -# define ARM_VCVT_F64_F32 ARM_VCVT_F|ARM_V_F64 -# define ARM_VCVTR_S32_F32 ARM_VCVT|ARM_VCVT_2I|ARM_VCVT_2S -# define ARM_VCVTR_U32_F32 ARM_VCVT|ARM_VCVT_2I -# define ARM_VCVTR_S32_F64 ARM_VCVT|ARM_VCVT_2I|ARM_VCVT_2S|ARM_V_F64 -# define ARM_VCVTR_U32_F64 ARM_VCVT|ARM_VCVT_2I|ARM_V_F64 -# define ARM_V_D 0x00400000 -# define ARM_V_N 0x00000080 -# define ARM_V_Q 0x00000040 -# define ARM_V_M 0x00000020 -# define ARM_V_U 0x01000000 -# define ARM_V_I16 0x00100000 -# define ARM_V_I32 0x00200000 -# define ARM_V_I64 0x00300000 -# define ARM_V_S16 0x00040000 -# define ARM_V_S32 0x00080000 -# define ARM_VADD_I 0x02000800 -# define ARM_VQADD_I 0x02000010 /* set flag on over/carry */ -# define ARM_VADDL_I 0x02800000 /* q=d+d */ -# define ARM_VADDW_I 0x02800100 /* q=q+d */ -# define ARM_VSUB_I 0x03000800 -# define ARM_VQSUB_I 0x02000210 /* set flag on over/carry */ -# define ARM_VSUBL_I 0x02800200 -# define ARM_VSUBW_I 0x02800300 -# define ARM_VMUL_I 0x02000910 -# define ARM_VMULL_I 0x02800c00 -# define ARM_VABS_I 0x03b10300 -# define ARM_VQABS_I 0x03b00700 /* sets flag on overflow */ -# define ARM_VNEG_I 0x03b10380 -# define ARM_VQNEG_I 0x03b00780 /* sets flag on overflow */ -# define ARM_VAND 0x02000110 -# define ARM_VBIC 0x02100110 -# define ARM_VORR 0x02200110 -# define ARM_VORN 0x02300110 -# define ARM_VEOR 0x03000110 -# define ARM_VMOVL_S8 0x00080000 -# define ARM_VMOVL_S16 0x00100000 -# define ARM_VMOVL_S32 0x00200000 -# define ARM_VMOVL_I 0x02800a10 -# define ARM_VMOVI 0x02800010 -# define ARM_VMVNI 0x02800030 -# define ARM_VLDR 0x0d100a00 -# define ARM_VSTR 0x0d000a00 -# define ARM_VM 0x0c000a00 -# define ARM_VMOV_ADV_U 0x00800000 /* zero extend */ -# define ARM_VMOV_ADV_8 0x00400000 -# define ARM_VMOV_ADV_16 0x00000020 -# define ARM_VMOV_A_D 0x0e100b10 -# define ARM_VMOV_D_A 0x0e000b10 +#define _D8_REGNO 32 +#define ARM_V_F64 0x00000100 +#define ARM_VADD_F 0x0e300a00 +#define ARM_VSUB_F 0x0e300a40 +#define ARM_VMUL_F 0x0e200a00 +#define ARM_VDIV_F 0x0e800a00 +#define ARM_VABS_F 0x0eb00ac0 +#define ARM_VNEG_F 0x0eb10a40 +#define ARM_VSQRT_F 0x0eb10ac0 +#define ARM_VMOV_F 0x0eb00a40 +#define ARM_VMOV_A_S 0x0e100a10 /* vmov rn, sn */ +#define ARM_VMOV_S_A 0x0e000a10 /* vmov sn, rn */ +#define ARM_VMOV_AA_D 0x0c500b10 /* vmov rn,rn, dn */ +#define ARM_VMOV_D_AA 0x0c400b10 /* vmov dn, rn,rn */ +#define ARM_VCMP 0x0eb40a40 +#define ARM_VMRS 0x0ef10a10 +#define ARM_VCVT_2I 0x00040000 /* to integer */ +#define ARM_VCVT_2S 0x00010000 /* to signed */ +#define ARM_VCVT_RS 0x00000080 /* round to zero or signed */ +#define ARM_VCVT 0x0eb80a40 +#define ARM_VCVT_S32_F32 ARM_VCVT|ARM_VCVT_2I|ARM_VCVT_2S|ARM_VCVT_RS +#define ARM_VCVT_S32_F64 ARM_VCVT|ARM_VCVT_2I|ARM_VCVT_2S|ARM_VCVT_RS|ARM_V_F64 +#define ARM_VCVT_F32_S32 ARM_VCVT|ARM_VCVT_RS +#define ARM_VCVT_F64_S32 ARM_VCVT|ARM_VCVT_RS|ARM_V_F64 +#define ARM_VCVT_F 0x0eb70ac0 +#define ARM_VCVT_F32_F64 ARM_VCVT_F +#define ARM_VCVT_F64_F32 ARM_VCVT_F|ARM_V_F64 +#define ARM_V_D 0x00400000 +#define ARM_V_N 0x00000080 +#define ARM_V_M 0x00000020 +#define ARM_V_I32 0x00200000 +#define ARM_VMOVI 0x02800010 +#define ARM_VMVNI 0x02800030 +#define ARM_VLDR 0x0d100a00 +#define ARM_VSTR 0x0d000a00 +#define ARM_VM 0x0c000a00 +#define ARM_VMOV_A_D 0x0e100b10 +#define ARM_VMOV_D_A 0x0e000b10 -# define vodi(oi,r0) _vodi(_jit,oi,r0) -static void _vodi(jit_state_t*,int,int) maybe_unused; -# define voqi(oi,r0) _voqi(_jit,oi,r0) -static void _voqi(jit_state_t*,int,int) maybe_unused; -# define vo_ss(o,r0,r1) _cc_vo_ss(_jit,ARM_CC_NV,o,r0,r1) -# define cc_vo_ss(cc,o,r0,r1) _cc_vo_ss(_jit,cc,o,r0,r1) -static void _cc_vo_ss(jit_state_t*,int,int,int,int); -# define vo_dd(o,r0,r1) _cc_vo_dd(_jit,ARM_CC_NV,o,r0,r1) -# define cc_vo_dd(cc,o,r0,r1) _cc_vo_dd(_jit,cc,o,r0,r1) -static void _cc_vo_dd(jit_state_t*,int,int,int,int); -# define vo_qd(o,r0,r1) _cc_vo_qd(_jit,ARM_CC_NV,o,r0,r1) -# define cc_vo_qd(cc,o,r0,r1) _cc_vo_qd(_jit,cc,o,r0,r1) -static void _cc_vo_qd(jit_state_t*,int,int,int,int) maybe_unused; -# define vo_qq(o,r0,r1) _cc_vo_qq(_jit,ARM_CC_NV,o,r0,r1) -# define cc_vo_qq(cc,o,r0,r1) _cc_vo_qq(_jit,cc,o,r0,r1) -static void _cc_vo_qq(jit_state_t*,int,int,int,int) maybe_unused; -# define vorr_(o,r0,r1) _cc_vorr_(_jit,ARM_CC_NV,o,r0,r1) -# define cc_vorr_(cc,o,r0,r1) _cc_vorr_(_jit,cc,o,r0,r1) -static void _cc_vorr_(jit_state_t*,int,int,int,int); -# define vors_(o,r0,r1) _cc_vors_(_jit,ARM_CC_NV,o,r0,r1) -# define cc_vors_(cc,o,r0,r1) _cc_vors_(_jit,cc,o,r0,r1) -static void _cc_vors_(jit_state_t*,int,int,int,int); -# define vorv_(o,r0,r1) _cc_vorv_(_jit,ARM_CC_NV,o,r0,r1) -# define cc_vorv_(cc,o,r0,r1) _cc_vorv_(_jit,cc,o,r0,r1) -static void _cc_vorv_(jit_state_t*,int,int,int,int) maybe_unused; -# define vori_(o,r0,r1) _cc_vori_(_jit,ARM_CC_NV,o,r0,r1) -# define cc_vori_(cc,o,r0,r1) _cc_vori_(_jit,cc,o,r0,r1) -static void _cc_vori_(jit_state_t*,int,int,int,int); -# define vorrd(o,r0,r1,r2) _cc_vorrd(_jit,ARM_CC_NV,o,r0,r1,r2) -# define cc_vorrd(cc,o,r0,r1,r2) _cc_vorrd(_jit,cc,o,r0,r1,r2) -static void _cc_vorrd(jit_state_t*,int,int,int,int,int); -# define vosss(o,r0,r1,r2) _cc_vosss(_jit,ARM_CC_NV,o,r0,r1,r2) -# define cc_vosss(cc,o,r0,r1,r2) _cc_vosss(_jit,cc,o,r0,r1,r2) -static void _cc_vosss(jit_state_t*,int,int,int,int,int); -# define voddd(o,r0,r1,r2) _cc_voddd(_jit,ARM_CC_NV,o,r0,r1,r2) -# define cc_voddd(cc,o,r0,r1,r2) _cc_voddd(_jit,cc,o,r0,r1,r2) -static void _cc_voddd(jit_state_t*,int,int,int,int,int); -# define voqdd(o,r0,r1,r2) _cc_voqdd(_jit,ARM_CC_NV,o,r0,r1,r2) -# define cc_voqdd(cc,o,r0,r1,r2) _cc_voqdd(_jit,cc,o,r0,r1,r2) -static void _cc_voqdd(jit_state_t*,int,int,int,int,int) maybe_unused; -# define voqqd(o,r0,r1,r2) _cc_voqqd(_jit,ARM_CC_NV,o,r0,r1,r2) -# define cc_voqqd(cc,o,r0,r1,r2) _cc_voqqd(_jit,cc,o,r0,r1,r2) -static void _cc_voqqd(jit_state_t*,int,int,int,int,int) maybe_unused; -# define voqqq(o,r0,r1,r2) _cc_voqqq(_jit,ARM_CC_NV,o,r0,r1,r2) -# define cc_voqqq(cc,o,r0,r1,r2) _cc_voqqq(_jit,cc,o,r0,r1,r2) -static void _cc_voqqq(jit_state_t*,int,int,int,int,int) maybe_unused; -# define cc_vldst(cc,o,r0,r1,i0) _cc_vldst(_jit,cc,o,r0,r1,i0) -static void _cc_vldst(jit_state_t*,int,int,int,int,int); -# define cc_vorsl(cc,o,r0,r1,i0) _cc_vorsl(_jit,cc,o,r0,r1,i0) -static void _cc_vorsl(jit_state_t*,int,int,int,int,int); -# define CC_VADD_F32(cc,r0,r1,r2) cc_vosss(cc,ARM_VADD_F,r0,r1,r2) -# define VADD_F32(r0,r1,r2) CC_VADD_F32(ARM_CC_AL,r0,r1,r2) -# define CC_VADD_F64(cc,r0,r1,r2) cc_voddd(cc,ARM_VADD_F|ARM_V_F64,r0,r1,r2) -# define VADD_F64(r0,r1,r2) CC_VADD_F64(ARM_CC_AL,r0,r1,r2) -# define CC_VSUB_F32(cc,r0,r1,r2) cc_vosss(cc,ARM_VSUB_F,r0,r1,r2) -# define VSUB_F32(r0,r1,r2) CC_VSUB_F32(ARM_CC_AL,r0,r1,r2) -# define CC_VSUB_F64(cc,r0,r1,r2) cc_voddd(cc,ARM_VSUB_F|ARM_V_F64,r0,r1,r2) -# define VSUB_F64(r0,r1,r2) CC_VSUB_F64(ARM_CC_AL,r0,r1,r2) -# define CC_VMUL_F32(cc,r0,r1,r2) cc_vosss(cc,ARM_VMUL_F,r0,r1,r2) -# define VMUL_F32(r0,r1,r2) CC_VMUL_F32(ARM_CC_AL,r0,r1,r2) -# define CC_VMUL_F64(cc,r0,r1,r2) cc_voddd(cc,ARM_VMUL_F|ARM_V_F64,r0,r1,r2) -# define VMUL_F64(r0,r1,r2) CC_VMUL_F64(ARM_CC_AL,r0,r1,r2) -# define CC_VDIV_F32(cc,r0,r1,r2) cc_vosss(cc,ARM_VDIV_F,r0,r1,r2) -# define VDIV_F32(r0,r1,r2) CC_VDIV_F32(ARM_CC_AL,r0,r1,r2) -# define CC_VDIV_F64(cc,r0,r1,r2) cc_voddd(cc,ARM_VDIV_F|ARM_V_F64,r0,r1,r2) -# define VDIV_F64(r0,r1,r2) CC_VDIV_F64(ARM_CC_AL,r0,r1,r2) -# define CC_VABS_F32(cc,r0,r1) cc_vo_ss(cc,ARM_VABS_F,r0,r1) -# define VABS_F32(r0,r1) CC_VABS_F32(ARM_CC_AL,r0,r1) -# define CC_VABS_F64(cc,r0,r1) cc_vo_dd(cc,ARM_VABS_F|ARM_V_F64,r0,r1) -# define VABS_F64(r0,r1) CC_VABS_F64(ARM_CC_AL,r0,r1) -# define CC_VNEG_F32(cc,r0,r1) cc_vo_ss(cc,ARM_VNEG_F,r0,r1) -# define VNEG_F32(r0,r1) CC_VNEG_F32(ARM_CC_AL,r0,r1) -# define CC_VNEG_F64(cc,r0,r1) cc_vo_dd(cc,ARM_VNEG_F|ARM_V_F64,r0,r1) -# define VNEG_F64(r0,r1) CC_VNEG_F64(ARM_CC_AL,r0,r1) -# define CC_VSQRT_F32(cc,r0,r1) cc_vo_ss(cc,ARM_VSQRT_F,r0,r1) -# define VSQRT_F32(r0,r1) CC_VSQRT_F32(ARM_CC_AL,r0,r1) -# define CC_VSQRT_F64(cc,r0,r1) cc_vo_dd(cc,ARM_VSQRT_F|ARM_V_F64,r0,r1) -# define VSQRT_F64(r0,r1) CC_VSQRT_F64(ARM_CC_AL,r0,r1) -# define CC_VMOV_F32(cc,r0,r1) cc_vo_ss(cc,ARM_VMOV_F,r0,r1) -# define VMOV_F32(r0,r1) CC_VMOV_F32(ARM_CC_AL,r0,r1) -# define CC_VMOV_F64(cc,r0,r1) cc_vo_dd(cc,ARM_VMOV_F|ARM_V_F64,r0,r1) -# define VMOV_F64(r0,r1) CC_VMOV_F64(ARM_CC_AL,r0,r1) -# define CC_VMOV_AA_D(cc,r0,r1,r2) cc_vorrd(cc,ARM_VMOV_AA_D,r0,r1,r2) -# define VMOV_AA_D(r0,r1,r2) CC_VMOV_AA_D(ARM_CC_AL,r0,r1,r2) -# define CC_VMOV_D_AA(cc,r0,r1,r2) cc_vorrd(cc,ARM_VMOV_D_AA,r1,r2,r0) -# define VMOV_D_AA(r0,r1,r2) CC_VMOV_D_AA(ARM_CC_AL,r0,r1,r2) -# define CC_VMOV_A_S(cc,r0,r1) cc_vors_(cc,ARM_VMOV_A_S,r0,r1) -# define VMOV_A_S(r0,r1) CC_VMOV_A_S(ARM_CC_AL,r0,r1) -# define CC_VMOV_S_A(cc,r0,r1) cc_vors_(cc,ARM_VMOV_S_A,r1,r0) -# define VMOV_S_A(r0,r1) CC_VMOV_S_A(ARM_CC_AL,r0,r1) -# define CC_VCMP_F32(cc,r0,r1) cc_vo_ss(cc,ARM_VCMP,r0,r1) -# define VCMP_F32(r0,r1) CC_VCMP_F32(ARM_CC_AL,r0,r1) -# define CC_VCMP_F64(cc,r0,r1) cc_vo_dd(cc,ARM_VCMP|ARM_V_F64,r0,r1) -# define VCMP_F64(r0,r1) CC_VCMP_F64(ARM_CC_AL,r0,r1) -# define CC_VCMPE_F32(cc,r0,r1) cc_vo_ss(cc,ARM_VCMP|ARM_V_E,r0,r1) -# define VCMPE_F32(r0,r1) CC_VCMPE_F32(ARM_CC_AL,r0,r1) -# define CC_VCMPE_F64(cc,r0,r1) cc_vo_dd(cc,ARM_VCMP|ARM_V_E|ARM_V_F64,r0,r1) -# define VCMPE_F64(r0,r1) CC_VCMPE_F64(ARM_CC_AL,r0,r1) -# define CC_VCMPZ_F32(cc,r0) cc_vo_ss(cc,ARM_VCMP|ARM_V_Z,r0,0) -# define VCMPZ_F32(r0) CC_VCMPZ_F32(ARM_CC_AL,r0) -# define CC_VCMPZ_F64(cc,r0) cc_vo_dd(cc,ARM_VCMP|ARM_V_Z|ARM_V_F64,r0,0) -# define VCMPZ_F64(r0) CC_VCMPZ_F64(ARM_CC_AL,r0) -# define CC_VCMPEZ_F32(cc,r0) cc_vo_ss(cc,ARM_VCMP|ARM_V_Z|ARM_V_E,r0,0) -# define VCMPEZ_F32(r0) CC_VCMPEZ_F32(ARM_CC_AL,r0) -# define CC_VCMPEZ_F64(cc,r0) cc_vo_dd(cc,ARM_VCMP|ARM_V_Z|ARM_V_E|ARM_V_F64,r0,0) -# define VCMPEZ_F64(r0) CC_VCMPEZ_F64(ARM_CC_AL,r0) -# define CC_VMRS(cc,r0) cc_vorr_(cc,ARM_VMRS,r0,0) -# define VMRS(r0) CC_VMRS(ARM_CC_AL,r0) -# define CC_VMSR(cc,r0) cc_vorr_(cc,ARM_VMSR,r0,0) -# define VMSR(r0) CC_VMSR(ARM_CC_AL,r0) -# define CC_VCVT_S32_F32(cc,r0,r1) cc_vo_ss(cc,ARM_VCVT_S32_F32,r0,r1) -# define VCVT_S32_F32(r0,r1) CC_VCVT_S32_F32(ARM_CC_AL,r0,r1) -# define CC_VCVT_U32_F32(cc,r0,r1) cc_vo_ss(cc,ARM_VCVT_U32_F32,r0,r1) -# define VCVT_U32_F32(r0,r1) CC_VCVT_U32_F32(ARM_CC_AL,r0,r1) -# define CC_VCVT_S32_F64(cc,r0,r1) cc_vo_ss(cc,ARM_VCVT_S32_F64,r0,r1) -# define VCVT_S32_F64(r0,r1) CC_VCVT_S32_F64(ARM_CC_AL,r0,r1) -# define CC_VCVT_U32_F64(cc,r0,r1) cc_vo_ss(cc,ARM_VCVT_U32_F64,r0,r1) -# define VCVT_U32_F64(r0,r1) CC_VCVT_U32_F64(ARM_CC_AL,r0,r1) -# define CC_VCVT_F32_S32(cc,r0,r1) cc_vo_ss(cc,ARM_VCVT_F32_S32,r0,r1) -# define VCVT_F32_S32(r0,r1) CC_VCVT_F32_S32(ARM_CC_AL,r0,r1) -# define CC_VCVT_F32_U32(cc,r0,r1) cc_vo_ss(cc,ARM_VCVT_F32_U32,r0,r1) -# define VCVT_F32_U32(r0,r1) CC_VCVT_F32_U32(ARM_CC_AL,r0,r1) -# define CC_VCVT_F64_S32(cc,r0,r1) cc_vo_ss(cc,ARM_VCVT_F64_S32,r0,r1) -# define VCVT_F64_S32(r0,r1) CC_VCVT_F64_S32(ARM_CC_AL,r0,r1) -# define CC_VCVT_F64_U32(cc,r0,r1) cc_vo_ss(cc,ARM_VCVT_F64_U32,r0,r1) -# define VCVT_F64_U32(r0,r1) CC_VCVT_F64_U32(ARM_CC_AL,r0,r1) -# define CC_VCVT_F32_F64(cc,r0,r1) cc_vo_ss(cc,ARM_VCVT_F32_F64,r0,r1) -# define VCVT_F32_F64(r0,r1) CC_VCVT_F32_F64(ARM_CC_AL,r0,r1) -# define CC_VCVT_F64_F32(cc,r0,r1) cc_vo_ss(cc,ARM_VCVT_F64_F32,r0,r1) -# define VCVT_F64_F32(r0,r1) CC_VCVT_F64_F32(ARM_CC_AL,r0,r1) -# define CC_VCVTR_S32_F32(cc,r0,r1) cc_vo_ss(cc,ARM_VCVTR_S32_F32,r0,r1) -# define VCVTR_S32_F32(r0,r1) CC_VCVTR_S32_F32(ARM_CC_AL,r0,r1) -# define CC_VCVTR_U32_F32(cc,r0,r1) cc_vo_ss(cc,ARM_VCVTR_U32_F32,r0,r1) -# define VCVTR_U32_F32(r0,r1) CC_VCVTR_U32_F32(ARM_CC_AL,r0,r1) -# define CC_VCVTR_S32_F64(cc,r0,r1) cc_vo_ss(cc,ARM_VCVTR_S32_F64,r0,r1) -# define VCVTR_S32_F64(r0,r1) CC_VCVTR_S32_F64(ARM_CC_AL,r0,r1) -# define CC_VCVTR_U32_F64(cc,r0,r1) cc_vo_ss(cc,ARM_VCVTR_U32_F64,r0,r1) -# define VCVTR_U32_F64(r0,r1) CC_VCVTR_U32_F64(ARM_CC_AL,r0,r1) -# define CC_VLDMIA_F32(cc,r0,r1,i0) cc_vorsl(cc,ARM_VM|ARM_M_L|ARM_M_I,r0,r1,i0) -# define VLDMIA_F32(r0,r1,i0) CC_VLDMIA_F32(ARM_CC_AL,r0,r1,i0) -# define CC_VLDMIA_F64(cc,r0,r1,i0) cc_vorsl(cc,ARM_VM|ARM_M_L|ARM_M_I|ARM_V_F64,r0,r1,i0) -# define VLDMIA_F64(r0,r1,i0) CC_VLDMIA_F64(ARM_CC_AL,r0,r1,i0) -# define CC_VSTMIA_F32(cc,r0,r1,i0) cc_vorsl(cc,ARM_VM|ARM_M_I,r0,r1,i0) -# define VSTMIA_F32(r0,r1,i0) CC_VSTMIA_F32(ARM_CC_AL,r0,r1,i0) -# define CC_VSTMIA_F64(cc,r0,r1,i0) cc_vorsl(cc,ARM_VM|ARM_M_I|ARM_V_F64,r0,r1,i0) -# define VSTMIA_F64(r0,r1,i0) CC_VSTMIA_F64(ARM_CC_AL,r0,r1,i0) -# define CC_VLDMIA_U_F32(cc,r0,r1,i0) cc_vorsl(cc,ARM_VM|ARM_M_L|ARM_M_I|ARM_M_U,r0,r1,i0) -# define VLDMIA_U_F32(r0,r1,i0) CC_VLDMIA_U_F32(ARM_CC_AL,r0,r1,i0) -# define CC_VLDMIA_U_F64(cc,r0,r1,i0) cc_vorsl(cc,ARM_VM|ARM_M_L|ARM_M_I|ARM_M_U|ARM_V_F64,r0,r1,i0) -# define VLDMIA_U_F64(r0,r1,i0) CC_VLDMIA_U_F64(ARM_CC_AL,r0,r1,i0) -# define CC_VSTMIA_U_F32(cc,r0,r1,i0) cc_vorsl(cc,ARM_VM|ARM_M_I|ARM_M_U,r0,r1,i0) -# define VSTMIA_U_F32(r0,r1,i0) CC_VSTMIA_U_F32(ARM_CC_AL,r0,r1,i0) -# define CC_VSTMIA_U_F64(cc,r0,r1,i0) cc_vorsl(cc,ARM_VM|ARM_M_I|ARM_M_U|ARM_V_F64,r0,r1,i0) -# define VSTMIA_U_F64(r0,r1,i0) CC_VSTMIA_U_F64(ARM_CC_AL,r0,r1,i0) -# define CC_VLDMDB_U_F32(cc,r0,r1,i0) cc_vorsl(cc,ARM_VM|ARM_M_L|ARM_M_B|ARM_M_U,r0,r1,i0) -# define VLDMDB_U_F32(r0,r1,i0) CC_VLDMDB_U_F32(ARM_CC_AL,r0,r1,i0) -# define CC_VLDMDB_U_F64(cc,r0,r1,i0) cc_vorsl(cc,ARM_VM|ARM_M_L|ARM_M_B|ARM_M_U|ARM_V_F64,r0,r1,i0) -# define VLDMDB_U_F64(r0,r1,i0) CC_VLDMDB_U_F64(ARM_CC_AL,r0,r1,i0) -# define CC_VSTMDB_U_F32(cc,r0,r1,i0) cc_vorsl(cc,ARM_VM|ARM_M_B|ARM_M_U,r0,r1,i0) -# define VSTMDB_U_F32(r0,r1,i0) CC_VSTMDB_U_F32(ARM_CC_AL,r0,r1,i0) -# define CC_VSTMDB_U_F64(cc,r0,r1,i0) cc_vorsl(cc,ARM_VM|ARM_M_B|ARM_M_U|ARM_V_F64,r0,r1,i0) -# define VSTMDB_U_F64(r0,r1,i0) CC_VSTMDB_U_F64(ARM_CC_AL,r0,r1,i0) -# define CC_VPUSH_F32(cc,r0,i0) CC_VSTMDB_U_F32(cc,_SP_REGNO,r0,i0) -# define VPUSH_F32(r0,i0) CC_VPUSH_F32(ARM_CC_AL,r0,i0) -# define CC_VPUSH_F64(cc,r0,i0) CC_VSTMDB_U_F64(cc,_SP_REGNO,r0,i0) -# define VPUSH_F64(r0,i0) CC_VPUSH_F64(ARM_CC_AL,r0,i0) -# define CC_VPOP_F32(cc,r0,i0) CC_VLDMIA_U_F32(cc,_SP_REGNO,r0,i0) -# define VPOP_F32(r0,i0) CC_VPOP_F32(ARM_CC_AL,r0,i0) -# define CC_VPOP_F64(cc,r0,i0) CC_VLDMIA_U_F64(cc,_SP_REGNO,r0,i0) -# define VPOP_F64(r0,i0) CC_VPOP_F64(ARM_CC_AL,r0,i0) -# define CC_VMOV_A_S8(cc,r0,r1) cc_vorv_(cc,ARM_VMOV_A_D|ARM_VMOV_ADV_8,r0,r1) -# define VMOV_A_S8(r0,r1) CC_VMOV_A_S8(ARM_CC_AL,r0,r1) -# define CC_VMOV_A_U8(cc,r0,r1) cc_vorv_(cc,ARM_VMOV_A_D|ARM_VMOV_ADV_8|ARM_VMOV_ADV_U,r0,r1) -# define VMOV_A_U8(r0,r1) CC_VMOV_A_U8(ARM_CC_AL,r0,r1) -# define CC_VMOV_A_S16(cc,r0,r1) cc_vorv_(cc,ARM_VMOV_A_D|ARM_VMOV_ADV_16,r0,r1) -# define VMOV_A_S16(r0,r1) CC_VMOV_A_S16(ARM_CC_AL,r0,r1) -# define CC_VMOV_A_U16(cc,r0,r1) cc_vorv_(cc,ARM_VMOV_A_D|ARM_VMOV_ADV_16|ARM_VMOV_ADV_U,r0,r1) -# define VMOV_A_U16(r0,r1) CC_VMOV_A_U16(ARM_CC_AL,r0,r1) -# define CC_VMOV_A_S32(cc,r0,r1) cc_vori_(cc,ARM_VMOV_A_D,r0,r1) -# define VMOV_A_S32(r0,r1) CC_VMOV_A_S32(ARM_CC_AL,r0,r1) -# define CC_VMOV_A_U32(cc,r0,r1) cc_vori_(cc,ARM_VMOV_A_D|ARM_VMOV_ADV_U,r0,r1) -# define VMOV_A_U32(r0,r1) CC_VMOV_A_U32(ARM_CC_AL,r0,r1) -# define CC_VMOV_V_I8(cc,r0,r1) cc_vorv_(cc,ARM_VMOV_D_A|ARM_VMOV_ADV_8,r1,r0) -# define VMOV_V_I8(r0,r1) CC_VMOV_V_I8(ARM_CC_AL,r0,r1) -# define CC_VMOV_V_I16(cc,r0,r1) cc_vorv_(cc,ARM_VMOV_D_A|ARM_VMOV_ADV_16,r1,r0) -# define VMOV_V_I16(r0,r1) CC_VMOV_V_I16(ARM_CC_AL,r0,r1) -# define CC_VMOV_V_I32(cc,r0,r1) cc_vori_(cc,ARM_VMOV_D_A,r1,r0) -# define VMOV_V_I32(r0,r1) CC_VMOV_V_I32(ARM_CC_AL,r0,r1) -# define VADD_I8(r0,r1,r2) voddd(ARM_VADD_I,r0,r1,r2) -# define VADDQ_I8(r0,r1,r2) voqqq(ARM_VADD_I|ARM_V_Q,r0,r1,r2) -# define VADD_I16(r0,r1,r2) voddd(ARM_VADD_I|ARM_V_I16,r0,r1,r2) -# define VADDQ_I16(r0,r1,r2) voqqq(ARM_VADD_I|ARM_V_I16|ARM_V_Q,r0,r1,r2) -# define VADD_I32(r0,r1,r2) voddd(ARM_VADD_I|ARM_V_I32,r0,r1,r2) -# define VADDQ_I32(r0,r1,r2) voqqq(ARM_VADD_I|ARM_V_I32|ARM_V_Q,r0,r1,r2) -# define VADD_I64(r0,r1,r2) voddd(ARM_VADD_I|ARM_V_I64,r0,r1,r2) -# define VADDQ_I64(r0,r1,r2) voqqq(ARM_VADD_I|ARM_V_I64|ARM_V_Q,r0,r1,r2) -# define VQADD_S8(r0,r1,r2) voddd(ARM_VQADD_I,r0,r1,r2) -# define VQADDQ_S8(r0,r1,r2) voqqq(ARM_VQADD_I|ARM_V_Q,r0,r1,r2) -# define VQADD_U8(r0,r1,r2) voddd(ARM_VQADD_I|ARM_V_U,r0,r1,r2) -# define VQADDQ_U8(r0,r1,r2) voqqq(ARM_VQADD_I|ARM_V_U|ARM_V_Q,r0,r1,r2) -# define VQADD_S16(r0,r1,r2) voddd(ARM_VQADD_I|ARM_V_I16,r0,r1,r2) -# define VQADDQ_S16(r0,r1,r2) voqqq(ARM_VQADD_I|ARM_V_I16|ARM_V_Q,r0,r1,r2) -# define VQADD_U16(r0,r1,r2) voddd(ARM_VQADD_I|ARM_V_I16|ARM_V_U,r0,r1,r2) -# define VQADDQ_U16(r0,r1,r2) voqqq(ARM_VQADD_I|ARM_V_I16|ARM_V_U|ARM_V_Q,r0,r1,r2) -# define VQADD_S32(r0,r1,r2) voddd(ARM_VQADD_I|ARM_V_I32,r0,r1,r2) -# define VQADDQ_S32(r0,r1,r2) voqqq(ARM_VQADD_I|ARM_V_I32|ARM_V_Q,r0,r1,r2) -# define VQADD_U32(r0,r1,r2) voddd(ARM_VQADD_I|ARM_V_I32|ARM_V_U,r0,r1,r2) -# define VQADDQ_U32(r0,r1,r2) voqqq(ARM_VQADD_I|ARM_V_I32|ARM_V_U|ARM_V_Q,r0,r1,r2) -# define VQADD_S64(r0,r1,r2) voddd(ARM_VQADD_I|ARM_V_I64,r0,r1,r2) -# define VQADDQ_S64(r0,r1,r2) voqqq(ARM_VQADD_I|ARM_V_I64|ARM_V_Q,r0,r1,r2) -# define VQADD_U64(r0,r1,r2) voddd(ARM_VQADD_I|ARM_V_I64|ARM_V_U,r0,r1,r2) -# define VQADDQ_U64(r0,r1,r2) voqqq(ARM_VQADD_I|ARM_V_I64|ARM_V_U|ARM_V_Q,r0,r1,r2) -# define VADDL_S8(r0,r1,r2) voqdd(ARM_VADDL_I,r0,r1,r2) -# define VADDL_U8(r0,r1,r2) voqdd(ARM_VADDL_I|ARM_V_U,r0,r1,r2) -# define VADDL_S16(r0,r1,r2) voqdd(ARM_VADDL_I|ARM_V_I16,r0,r1,r2) -# define VADDL_U16(r0,r1,r2) voqdd(ARM_VADDL_I|ARM_V_I16|ARM_V_U,r0,r1,r2) -# define VADDL_S32(r0,r1,r2) voqdd(ARM_VADDL_I|ARM_V_I32,r0,r1,r2) -# define VADDL_U32(r0,r1,r2) voqdd(ARM_VADDL_I|ARM_V_I32|ARM_V_U,r0,r1,r2) -# define VADDW_S8(r0,r1,r2) voqqd(ARM_VADDW_I,r0,r1,r2) -# define VADDW_U8(r0,r1,r2) voqqd(ARM_VADDW_I|ARM_V_U,r0,r1,r2) -# define VADDW_S16(r0,r1,r2) voqqd(ARM_VADDW_I|ARM_V_I16,r0,r1,r2) -# define VADDW_U16(r0,r1,r2) voqqd(ARM_VADDW_I|ARM_V_I16|ARM_V_U,r0,r1,r2) -# define VADDW_S32(r0,r1,r2) voqqd(ARM_VADDW_I|ARM_V_I32,r0,r1,r2) -# define VADDW_U32(r0,r1,r2) voqqd(ARM_VADDW_I|ARM_V_I32|ARM_V_U,r0,r1,r2) -# define VSUB_I8(r0,r1,r2) voddd(ARM_VSUB_I,r0,r1,r2) -# define VSUBQ_I8(r0,r1,r2) voqqq(ARM_VSUB_I|ARM_V_Q,r0,r1,r2) -# define VSUB_I16(r0,r1,r2) voddd(ARM_VSUB_I|ARM_V_I16,r0,r1,r2) -# define VSUBQ_I16(r0,r1,r2) voqqq(ARM_VSUB_I|ARM_V_I16|ARM_V_Q,r0,r1,r2) -# define VSUB_I32(r0,r1,r2) voddd(ARM_VSUB_I|ARM_V_I32,r0,r1,r2) -# define VSUBQ_I32(r0,r1,r2) voqqq(ARM_VSUB_I|ARM_V_I32|ARM_V_Q,r0,r1,r2) -# define VSUB_I64(r0,r1,r2) voddd(ARM_VSUB_I|ARM_V_I64,r0,r1,r2) -# define VSUBQ_I64(r0,r1,r2) voqqq(ARM_VSUB_I|ARM_V_I64|ARM_V_Q,r0,r1,r2) -# define VQSUB_S8(r0,r1,r2) voddd(ARM_VQSUB_I,r0,r1,r2) -# define VQSUBQ_S8(r0,r1,r2) voqqq(ARM_VQSUB_I|ARM_V_Q,r0,r1,r2) -# define VQSUB_U8(r0,r1,r2) voddd(ARM_VQSUB_I|ARM_V_U,r0,r1,r2) -# define VQSUBQ_U8(r0,r1,r2) voqqq(ARM_VQSUB_I|ARM_V_U|ARM_V_Q,r0,r1,r2) -# define VQSUB_S16(r0,r1,r2) voddd(ARM_VQSUB_I|ARM_V_I16,r0,r1,r2) -# define VQSUBQ_S16(r0,r1,r2) voqqq(ARM_VQSUB_I|ARM_V_I16|ARM_V_Q,r0,r1,r2) -# define VQSUB_U16(r0,r1,r2) voddd(ARM_VQSUB_I|ARM_V_I16|ARM_V_U,r0,r1,r2) -# define VQSUBQ_U16(r0,r1,r2) voqqq(ARM_VQSUB_I|ARM_V_I16|ARM_V_U|ARM_V_Q,r0,r1,r2) -# define VQSUB_S32(r0,r1,r2) voddd(ARM_VQSUB_I|ARM_V_I32,r0,r1,r2) -# define VQSUBQ_S32(r0,r1,r2) voqqq(ARM_VQSUB_I|ARM_V_I32|ARM_V_Q,r0,r1,r2) -# define VQSUB_U32(r0,r1,r2) voddd(ARM_VQSUB_I|ARM_V_I32|ARM_V_U,r0,r1,r2) -# define VQSUBQ_U32(r0,r1,r2) voqqq(ARM_VQSUB_I|ARM_V_I32|ARM_V_U|ARM_V_Q,r0,r1,r2) -# define VQSUB_S64(r0,r1,r2) voddd(ARM_VQSUB_I|ARM_V_I64,r0,r1,r2) -# define VQSUBQ_S64(r0,r1,r2) voqqq(ARM_VQSUB_I|ARM_V_I64|ARM_V_Q,r0,r1,r2) -# define VQSUB_U64(r0,r1,r2) voddd(ARM_VQSUB_I|ARM_V_I64|ARM_V_U,r0,r1,r2) -# define VQSUBQ_U64(r0,r1,r2) voqqq(ARM_VQSUB_I|ARM_V_I64|ARM_V_U|ARM_V_Q,r0,r1,r2) -# define VSUBL_S8(r0,r1,r2) voqdd(ARM_VSUBL_I,r0,r1,r2) -# define VSUBL_U8(r0,r1,r2) voqdd(ARM_VSUBL_I|ARM_V_U,r0,r1,r2) -# define VSUBL_S16(r0,r1,r2) voqdd(ARM_VSUBL_I|ARM_V_I16,r0,r1,r2) -# define VSUBL_U16(r0,r1,r2) voqdd(ARM_VSUBL_I|ARM_V_I16|ARM_V_U,r0,r1,r2) -# define VSUBL_S32(r0,r1,r2) voqdd(ARM_VSUBL_I|ARM_V_I32,r0,r1,r2) -# define VSUBL_U32(r0,r1,r2) voqdd(ARM_VSUBL_I|ARM_V_I32|ARM_V_U,r0,r1,r2) -# define VSUBW_S8(r0,r1,r2) voqqd(ARM_VSUBW_I,r0,r1,r2) -# define VSUBW_U8(r0,r1,r2) voqqd(ARM_VSUBW_I|ARM_V_U,r0,r1,r2) -# define VSUBW_S16(r0,r1,r2) voqqd(ARM_VSUBW_I|ARM_V_I16,r0,r1,r2) -# define VSUBW_U16(r0,r1,r2) voqqd(ARM_VSUBW_I|ARM_V_I16|ARM_V_U,r0,r1,r2) -# define VSUBW_S32(r0,r1,r2) voqqd(ARM_VSUBW_I|ARM_V_I32,r0,r1,r2) -# define VSUBW_U32(r0,r1,r2) voqqd(ARM_VSUBW_I|ARM_V_I32|ARM_V_U,r0,r1,r2) -# define VMUL_I8(r0,r1,r2) voddd(ARM_VMUL_I,r0,r1,r2) -# define VMULQ_I8(r0,r1,r2) voqqq(ARM_VMUL_I|ARM_V_Q,r0,r1,r2) -# define VMUL_I16(r0,r1,r2) voddd(ARM_VMUL_I|ARM_V_I16,r0,r1,r2) -# define VMULQ_I16(r0,r1,r2) voqqq(ARM_VMUL_I|ARM_V_Q|ARM_V_I16,r0,r1,r2) -# define VMUL_I32(r0,r1,r2) voddd(ARM_VMUL_I|ARM_V_I32,r0,r1,r2) -# define VMULQ_I32(r0,r1,r2) voqqq(ARM_VMUL_I|ARM_V_Q|ARM_V_I32,r0,r1,r2) -# define VMULL_S8(r0,r1,r2) voddd(ARM_VMULL_I,r0,r1,r2) -# define VMULL_U8(r0,r1,r2) voqqq(ARM_VMULL_I|ARM_V_U,r0,r1,r2) -# define VMULL_S16(r0,r1,r2) voddd(ARM_VMULL_I|ARM_V_I16,r0,r1,r2) -# define VMULL_U16(r0,r1,r2) voqqq(ARM_VMULL_I|ARM_V_U|ARM_V_I16,r0,r1,r2) -# define VMULL_S32(r0,r1,r2) voddd(ARM_VMULL_I|ARM_V_I32,r0,r1,r2) -# define VMULL_U32(r0,r1,r2) voqqq(ARM_VMULL_I|ARM_V_U|ARM_V_I32,r0,r1,r2) -# define VABS_S8(r0,r1) vo_dd(ARM_VABS_I,r0,r1) -# define VABSQ_S8(r0,r1) vo_qq(ARM_VABS_I|ARM_V_Q,r0,r1) -# define VABS_S16(r0,r1) vo_dd(ARM_VABS_I|ARM_V_S16,r0,r1) -# define VABSQ_S16(r0,r1) vo_qq(ARM_VABS_I|ARM_V_S16|ARM_V_Q,r0,r1) -# define VABS_S32(r0,r1) vo_dd(ARM_VABS_I|ARM_V_S32,r0,r1) -# define VABSQ_S32(r0,r1) vo_qq(ARM_VABS_I|ARM_V_S32|ARM_V_Q,r0,r1) -# define VQABS_S8(r0,r1) vo_dd(ARM_VQABS_I,r0,r1) -# define VQABSQ_S8(r0,r1) vo_qq(ARM_VQABS_I|ARM_V_Q,r0,r1) -# define VQABS_S16(r0,r1) vo_dd(ARM_VQABS_I|ARM_V_S16,r0,r1) -# define VQABSQ_S16(r0,r1) vo_qq(ARM_VQABS_I|ARM_V_S16|ARM_V_Q,r0,r1) -# define VQABS_S32(r0,r1) vo_dd(ARM_VQABS_I|ARM_V_S32,r0,r1) -# define VQABSQ_S32(r0,r1) vo_qq(ARM_VQABS_I|ARM_V_S32|ARM_V_Q,r0,r1) -# define VNEG_S8(r0,r1) vo_dd(ARM_VNEG_I,r0,r1) -# define VNEGQ_S8(r0,r1) vo_qq(ARM_VNEG_I|ARM_V_Q,r0,r1) -# define VNEG_S16(r0,r1) vo_dd(ARM_VNEG_I|ARM_V_S16,r0,r1) -# define VNEGQ_S16(r0,r1) vo_qq(ARM_VNEG_I|ARM_V_S16|ARM_V_Q,r0,r1) -# define VNEG_S32(r0,r1) vo_dd(ARM_VNEG_I|ARM_V_S32,r0,r1) -# define VNEGQ_S32(r0,r1) vo_qq(ARM_VNEG_I|ARM_V_S32|ARM_V_Q,r0,r1) -# define VQNEG_S8(r0,r1) vo_dd(ARM_VQNEG_I,r0,r1) -# define VQNEGQ_S8(r0,r1) vo_qq(ARM_VQNEG_I|ARM_V_Q,r0,r1) -# define VQNEG_S16(r0,r1) vo_dd(ARM_VQNEG_I|ARM_V_S16,r0,r1) -# define VQNEGQ_S16(r0,r1) vo_qq(ARM_VQNEG_I|ARM_V_S16|ARM_V_Q,r0,r1) -# define VQNEG_S32(r0,r1) vo_dd(ARM_VQNEG_I|ARM_V_S32,r0,r1) -# define VQNEGQ_S32(r0,r1) vo_qq(ARM_VQNEG_I|ARM_V_S32|ARM_V_Q,r0,r1) -# define VAND(r0,r1,r2) voddd(ARM_VAND,r0,r1,r2) -# define VANDQ(r0,r1,r2) voqqq(ARM_VAND|ARM_V_Q,r0,r1,r2) -# define VBIC(r0,r1,r2) voddd(ARM_VBIC,r0,r1,r2) -# define VBICQ(r0,r1,r2) voqqq(ARM_VBIC|ARM_V_Q,r0,r1,r2) -# define VORR(r0,r1,r2) voddd(ARM_VORR,r0,r1,r2) -# define VORRQ(r0,r1,r2) voqqq(ARM_VORR|ARM_V_Q,r0,r1,r2) -# define VORN(r0,r1,r2) voddd(ARM_VORN,r0,r1,r2) -# define VORNQ(r0,r1,r2) voqqq(ARM_VORN|ARM_V_Q,r0,r1,r2) -# define VEOR(r0,r1,r2) voddd(ARM_VEOR,r0,r1,r2) -# define VEORQ(r0,r1,r2) voqqq(ARM_VEOR|ARM_V_Q,r0,r1,r2) -# define VMOV(r0,r1) VORR(r0,r1,r1) -# define VMOVQ(r0,r1) VORRQ(r0,r1,r1) -# define VMOVL_S8(r0,r1) vo_qd(ARM_VMOVL_I|ARM_VMOVL_S8,r0,r1) -# define VMOVL_U8(r0,r1) vo_qd(ARM_VMOVL_I|ARM_V_U|ARM_VMOVL_S8,r0,r1) -# define VMOVL_S16(r0,r1) vo_qd(ARM_VMOVL_I|ARM_VMOVL_S16,r0,r1) -# define VMOVL_U16(r0,r1) vo_qd(ARM_VMOVL_I|ARM_V_U|ARM_VMOVL_S16,r0,r1) -# define VMOVL_S32(r0,r1) vo_qd(ARM_VMOVL_I|ARM_VMOVL_S32,r0,r1) -# define VMOVL_U32(r0,r1) vo_qd(ARM_VMOVL_I|ARM_V_U|ARM_VMOVL_S32,r0,r1) -/* "oi" should be the result of encode_vfp_double */ -# define VIMM(oi,r0) vodi(oi,r0) -# define VIMMQ(oi,r0) voqi(oi|ARM_V_Q,r0) -/* index is multipled by four */ -# define CC_VLDRN_F32(cc,r0,r1,i0) cc_vldst(cc,ARM_VLDR,r0,r1,i0) -# define VLDRN_F32(r0,r1,i0) CC_VLDRN_F32(ARM_CC_AL,r0,r1,i0) -# define CC_VLDR_F32(cc,r0,r1,i0) cc_vldst(cc,ARM_VLDR|ARM_P,r0,r1,i0) -# define VLDR_F32(r0,r1,i0) CC_VLDR_F32(ARM_CC_AL,r0,r1,i0) -# define CC_VLDRN_F64(cc,r0,r1,i0) cc_vldst(cc,ARM_VLDR|ARM_V_F64,r0,r1,i0) -# define VLDRN_F64(r0,r1,i0) CC_VLDRN_F64(ARM_CC_AL,r0,r1,i0) -# define CC_VLDR_F64(cc,r0,r1,i0) cc_vldst(cc,ARM_VLDR|ARM_V_F64|ARM_P,r0,r1,i0) -# define VLDR_F64(r0,r1,i0) CC_VLDR_F64(ARM_CC_AL,r0,r1,i0) -# define CC_VSTRN_F32(cc,r0,r1,i0) cc_vldst(cc,ARM_VSTR,r0,r1,i0) -# define VSTRN_F32(r0,r1,i0) CC_VSTRN_F32(ARM_CC_AL,r0,r1,i0) -# define CC_VSTR_F32(cc,r0,r1,i0) cc_vldst(cc,ARM_VSTR|ARM_P,r0,r1,i0) -# define VSTR_F32(r0,r1,i0) CC_VSTR_F32(ARM_CC_AL,r0,r1,i0) -# define CC_VSTRN_F64(cc,r0,r1,i0) cc_vldst(cc,ARM_VSTR|ARM_V_F64,r0,r1,i0) -# define VSTRN_F64(r0,r1,i0) CC_VSTRN_F64(ARM_CC_AL,r0,r1,i0) -# define CC_VSTR_F64(cc,r0,r1,i0) cc_vldst(cc,ARM_VSTR|ARM_V_F64|ARM_P,r0,r1,i0) -# define VSTR_F64(r0,r1,i0) CC_VSTR_F64(ARM_CC_AL,r0,r1,i0) -# define vfp_movr_f(r0,r1) _vfp_movr_f(_jit,r0,r1) -static void _vfp_movr_f(jit_state_t*,int32_t,int32_t); -# define vfp_movr_d(r0,r1) _vfp_movr_d(_jit,r0,r1) -static void _vfp_movr_d(jit_state_t*,int32_t,int32_t); -# define vfp_movi_f(r0,i0) _vfp_movi_f(_jit,r0,i0) -static void _vfp_movi_f(jit_state_t*,int32_t,jit_float32_t); -# define vfp_movi_d(r0,i0) _vfp_movi_d(_jit,r0,i0) -static void _vfp_movi_d(jit_state_t*,int32_t,jit_float64_t); -# define vfp_extr_f(r0,r1) _vfp_extr_f(_jit,r0,r1) -static void _vfp_extr_f(jit_state_t*,int32_t,int32_t); -# define vfp_extr_d(r0,r1) _vfp_extr_d(_jit,r0,r1) -static void _vfp_extr_d(jit_state_t*,int32_t,int32_t); -# define vfp_extr_d_f(r0,r1) _vfp_extr_d_f(_jit,r0,r1) -static void _vfp_extr_d_f(jit_state_t*,int32_t,int32_t); -# define vfp_extr_f_d(r0,r1) _vfp_extr_f_d(_jit,r0,r1) -static void _vfp_extr_f_d(jit_state_t*,int32_t,int32_t); -# define vfp_truncr_f_i(r0,r1) _vfp_truncr_f_i(_jit,r0,r1) -static void _vfp_truncr_f_i(jit_state_t*,int32_t,int32_t); -# define vfp_truncr_d_i(r0,r1) _vfp_truncr_d_i(_jit,r0,r1) -static void _vfp_truncr_d_i(jit_state_t*,int32_t,int32_t); -# define vfp_absr_f(r0,r1) VABS_F32(r0,r1) -# define vfp_absr_d(r0,r1) VABS_F64(r0,r1) -# define vfp_negr_f(r0,r1) VNEG_F32(r0,r1) -# define vfp_negr_d(r0,r1) VNEG_F64(r0,r1) -# define vfp_sqrtr_f(r0,r1) VSQRT_F32(r0,r1) -# define vfp_sqrtr_d(r0,r1) VSQRT_F64(r0,r1) -# define vfp_addr_f(r0,r1,r2) VADD_F32(r0,r1,r2) -# define vfp_addi_f(r0,r1,i0) _vfp_addi_f(_jit,r0,r1,i0) -static void _vfp_addi_f(jit_state_t*,int32_t,int32_t,jit_float32_t); -# define vfp_addr_d(r0,r1,r2) VADD_F64(r0,r1,r2) -# define vfp_addi_d(r0,r1,i0) _vfp_addi_d(_jit,r0,r1,i0) -static void _vfp_addi_d(jit_state_t*,int32_t,int32_t,jit_float64_t); -# define vfp_subr_f(r0,r1,r2) VSUB_F32(r0,r1,r2) -# define vfp_subi_f(r0,r1,i0) _vfp_subi_f(_jit,r0,r1,i0) -static void _vfp_subi_f(jit_state_t*,int32_t,int32_t,jit_float32_t); -# define vfp_subr_d(r0,r1,r2) VSUB_F64(r0,r1,r2) -# define vfp_subi_d(r0,r1,i0) _vfp_subi_d(_jit,r0,r1,i0) -static void _vfp_subi_d(jit_state_t*,int32_t,int32_t,jit_float64_t); -# define vfp_rsbr_f(r0,r1,r2) vfp_subr_f(r0,r2,r1) -# define vfp_rsbi_f(r0,r1,i0) _vfp_rsbi_f(_jit,r0,r1,i0) -static void _vfp_rsbi_f(jit_state_t*,int32_t,int32_t,jit_float32_t); -# define vfp_rsbr_d(r0,r1,r2) vfp_subr_d(r0,r2,r1) -# define vfp_rsbi_d(r0,r1,i0) _vfp_rsbi_d(_jit,r0,r1,i0) -static void _vfp_rsbi_d(jit_state_t*,int32_t,int32_t,jit_float64_t); -# define vfp_mulr_f(r0,r1,r2) VMUL_F32(r0,r1,r2) -# define vfp_muli_f(r0,r1,i0) _vfp_muli_f(_jit,r0,r1,i0) -static void _vfp_muli_f(jit_state_t*,int32_t,int32_t,jit_float32_t); -# define vfp_mulr_d(r0,r1,r2) VMUL_F64(r0,r1,r2) -# define vfp_muli_d(r0,r1,i0) _vfp_muli_d(_jit,r0,r1,i0) -static void _vfp_muli_d(jit_state_t*,int32_t,int32_t,jit_float64_t); -# define vfp_divr_f(r0,r1,r2) VDIV_F32(r0,r1,r2) -# define vfp_divi_f(r0,r1,i0) _vfp_divi_f(_jit,r0,r1,i0) -static void _vfp_divi_f(jit_state_t*,int32_t,int32_t,jit_float32_t); -# define vfp_divr_d(r0,r1,r2) VDIV_F64(r0,r1,r2) -# define vfp_divi_d(r0,r1,i0) _vfp_divi_d(_jit,r0,r1,i0) -static void _vfp_divi_d(jit_state_t*,int32_t,int32_t,jit_float64_t); -# define vfp_cmp_f(r0,r1) _vfp_cmp_f(_jit,r0,r1) -static void _vfp_cmp_f(jit_state_t*,int32_t,int32_t); -# define vfp_cmp_d(r0,r1) _vfp_cmp_d(_jit,r0,r1) -static void _vfp_cmp_d(jit_state_t*,int32_t,int32_t); -# define vcmp10_x(c0,r0) _vcmp10_x(_jit,c0,r0) -static void _vcmp10_x(jit_state_t*,int,int32_t); -# define vcmp_01_x(c0,r0) _vcmp_01_x(_jit,c0,r0) -static void _vcmp_01_x(jit_state_t*,int,int32_t); -# define vcmp_01_f(c0,r0,r1,r2) _vcmp_01_f(_jit,c0,r0,r1,r2) -static void _vcmp_01_f(jit_state_t*,int,int32_t,int32_t,int32_t); -# define vcmp_01_d(c0,r0,r1,r2) _vcmp_01_d(_jit,c0,r0,r1,r2) -static void _vcmp_01_d(jit_state_t*,int,int32_t,int32_t,int32_t); -# define vbcmp_x(cc,i0) _vbcmp_x(_jit,cc,i0) -static jit_word_t _vbcmp_x(jit_state_t*,int,jit_word_t); -# define vbcmp_f(cc,i0,r0,r1) _vbcmp_f(_jit,cc,i0,r0,r1) -static jit_word_t -_vbcmp_f(jit_state_t*,int,jit_word_t,int32_t,int32_t); -# define vbcmp_x(cc,i0) _vbcmp_x(_jit,cc,i0) -static jit_word_t _vbcmp_x(jit_state_t*,int,jit_word_t); -# define vbcmp_d(cc,i0,r0,r1) _vbcmp_d(_jit,cc,i0,r0,r1) -static jit_word_t -_vbcmp_d(jit_state_t*,int,jit_word_t,int32_t,int32_t); -# define vfp_bltr_f(i0,r0,r1) vbcmp_f(ARM_CC_MI,i0,r0,r1) -# define vfp_blti_f(i0,r0,i1) _vfp_blti_f(_jit,i0,r0,i1) -static jit_word_t _vfp_blti_f(jit_state_t*,jit_word_t,int32_t,jit_float32_t); -# define vfp_bltr_d(i0,r0,r1) vbcmp_d(ARM_CC_MI,i0,r0,r1) -static jit_word_t _vfp_blti_d(jit_state_t*,jit_word_t,int32_t,jit_float64_t); -# define vfp_blti_d(i0,r0,i1) _vfp_blti_d(_jit,i0,r0,i1) -# define vfp_bler_f(i0,r0,r1) vbcmp_f(ARM_CC_LS,i0,r0,r1) -# define vfp_blei_f(i0,r0,i1) _vfp_blei_f(_jit,i0,r0,i1) -static jit_word_t _vfp_blei_f(jit_state_t*,jit_word_t,int32_t,jit_float32_t); -# define vfp_bler_d(i0,r0,r1) vbcmp_d(ARM_CC_LS,i0,r0,r1) -# define vfp_blei_d(i0,r0,i1) _vfp_blei_d(_jit,i0,r0,i1) -static jit_word_t _vfp_blei_d(jit_state_t*,jit_word_t,int32_t,jit_float64_t); -# define vfp_beqr_f(i0,r0,r1) vbcmp_f(ARM_CC_EQ,i0,r0,r1) -# define vfp_beqi_f(i0,r0,i1) _vfp_beqi_f(_jit,i0,r0,i1) -static jit_word_t _vfp_beqi_f(jit_state_t*,jit_word_t,int32_t,jit_float32_t); -# define vfp_beqr_d(i0,r0,r1) vbcmp_d(ARM_CC_EQ,i0,r0,r1) -# define vfp_beqi_d(i0,r0,i1) _vfp_beqi_d(_jit,i0,r0,i1) -static jit_word_t _vfp_beqi_d(jit_state_t*,jit_word_t,int32_t,jit_float64_t); -# define vfp_bger_f(i0,r0,r1) vbcmp_f(ARM_CC_GE,i0,r0,r1) -# define vfp_bgei_f(i0,r0,i1) _vfp_bgei_f(_jit,i0,r0,i1) -static jit_word_t _vfp_bgei_f(jit_state_t*,jit_word_t,int32_t,jit_float32_t); -# define vfp_bger_d(i0,r0,r1) vbcmp_d(ARM_CC_GE,i0,r0,r1) -# define vfp_bgei_d(i0,r0,i1) _vfp_bgei_d(_jit,i0,r0,i1) -static jit_word_t _vfp_bgei_d(jit_state_t*,jit_word_t,int32_t,jit_float64_t); -# define vfp_bgtr_f(i0,r0,r1) vbcmp_f(ARM_CC_GT,i0,r0,r1) -# define vfp_bgti_f(i0,r0,i1) _vfp_bgti_f(_jit,i0,r0,i1) -static jit_word_t _vfp_bgti_f(jit_state_t*,jit_word_t,int32_t,jit_float32_t); -# define vfp_bgtr_d(i0,r0,r1) vbcmp_d(ARM_CC_GT,i0,r0,r1) -# define vfp_bgti_d(i0,r0,i1) _vfp_bgti_d(_jit,i0,r0,i1) -static jit_word_t _vfp_bgti_d(jit_state_t*,jit_word_t,int32_t,jit_float64_t); -# define vfp_bner_f(i0,r0,r1) vbcmp_f(ARM_CC_NE,i0,r0,r1) -# define vfp_bnei_f(i0,r0,i1) _vfp_bnei_f(_jit,i0,r0,i1) -static jit_word_t _vfp_bnei_f(jit_state_t*,jit_word_t,int32_t,jit_float32_t); -# define vfp_bner_d(i0,r0,r1) vbcmp_d(ARM_CC_NE,i0,r0,r1) -# define vfp_bnei_d(i0,r0,i1) _vfp_bnei_d(_jit,i0,r0,i1) -static jit_word_t _vfp_bnei_d(jit_state_t*,jit_word_t,int32_t,jit_float64_t); -# define vbncmp_x(cc,i0) _vbncmp_x(_jit,cc,i0) -static jit_word_t _vbncmp_x(jit_state_t*,int,jit_word_t); -# define vbncmp_f(cc,i0,r0,r1) _vbncmp_f(_jit,cc,i0,r0,r1) -static jit_word_t -_vbncmp_f(jit_state_t*,int,jit_word_t,int32_t,int32_t); -# define vbncmp_d(cc,i0,r0,r1) _vbncmp_d(_jit,cc,i0,r0,r1) -static jit_word_t -_vbncmp_d(jit_state_t*,int,jit_word_t,int32_t,int32_t); -# define vfp_bunltr_f(i0,r0,r1) vbncmp_f(ARM_CC_GE,i0,r0,r1) -# define vfp_bunlti_f(i0,r0,i1) _vfp_bunlti_f(_jit,i0,r0,i1) -static jit_word_t -_vfp_bunlti_f(jit_state_t*,jit_word_t,int32_t,jit_float32_t); -# define vfp_bunltr_d(i0,r0,r1) vbncmp_d(ARM_CC_GE,i0,r0,r1) -# define vfp_bunlti_d(i0,r0,i1) _vfp_bunlti_d(_jit,i0,r0,i1) -static jit_word_t -_vfp_bunlti_d(jit_state_t*,jit_word_t,int32_t,jit_float64_t); -# define vfp_bunler_f(i0,r0,r1) vbncmp_f(ARM_CC_GT,i0,r0,r1) -# define vfp_bunlei_f(i0,r0,i1) _vfp_bunlei_f(_jit,i0,r0,i1) -static jit_word_t -_vfp_bunlei_f(jit_state_t*,jit_word_t,int32_t,jit_float32_t); -# define vfp_bunler_d(i0,r0,r1) vbncmp_d(ARM_CC_GT,i0,r0,r1) -# define vfp_bunlei_d(i0,r0,i1) _vfp_bunlei_d(_jit,i0,r0,i1) -static jit_word_t -_vfp_bunlei_d(jit_state_t*,jit_word_t,int32_t,jit_float64_t); -# define vfp_buneqr_x(i0) _vfp_buneqr_x(_jit,i0) -static jit_word_t _vfp_buneqr_x(jit_state_t*,jit_word_t); -# define vfp_buneqr_f(i0,r0,r1) _vfp_buneqr_f(_jit,i0,r0,r1) -static jit_word_t -_vfp_buneqr_f(jit_state_t*,jit_word_t,int32_t,int32_t); -# define vfp_buneqi_f(i0,r0,i1) _vfp_buneqi_f(_jit,i0,r0,i1) -static jit_word_t -_vfp_buneqi_f(jit_state_t*,jit_word_t,int32_t,jit_float32_t); -# define vfp_buneqr_d(i0,r0,r1) _vfp_buneqr_d(_jit,i0,r0,r1) -static jit_word_t -_vfp_buneqr_d(jit_state_t*,jit_word_t,int32_t,int32_t); -# define vfp_buneqi_d(i0,r0,i1) _vfp_buneqi_d(_jit,i0,r0,i1) -static jit_word_t -_vfp_buneqi_d(jit_state_t*,jit_word_t,int32_t,jit_float64_t); -# define vfp_bunger_x(i0) _vfp_bunger_x(_jit,i0) -static jit_word_t _vfp_bunger_x(jit_state_t*,jit_word_t); -# define vfp_bunger_f(i0,r0,r1) _vfp_bunger_f(_jit,i0,r0,r1) -static jit_word_t -_vfp_bunger_f(jit_state_t*,jit_word_t,int32_t,int32_t); -# define vfp_bungei_f(i0,r0,i1) _vfp_bungei_f(_jit,i0,r0,i1) -static jit_word_t -_vfp_bungei_f(jit_state_t*,jit_word_t,int32_t,jit_float32_t); -# define vfp_bunger_d(i0,r0,r1) _vfp_bunger_d(_jit,i0,r0,r1) -static jit_word_t -_vfp_bunger_d(jit_state_t*,jit_word_t,int32_t,int32_t); -# define vfp_bungei_d(i0,r0,i1) _vfp_bungei_d(_jit,i0,r0,i1) -static jit_word_t -_vfp_bungei_d(jit_state_t*,jit_word_t,int32_t,jit_float64_t); -# define vfp_bungtr_f(i0,r0,r1) vbcmp_f(ARM_CC_HI,i0,r0,r1) -# define vfp_bungti_f(i0,r0,i1) _vfp_bungti_f(_jit,i0,r0,i1) -static jit_word_t -_vfp_bungti_f(jit_state_t*,jit_word_t,int32_t,jit_float32_t); -# define vfp_bungtr_d(i0,r0,r1) vbcmp_d(ARM_CC_HI,i0,r0,r1) -# define vfp_bungti_d(i0,r0,i1) _vfp_bungti_d(_jit,i0,r0,i1) -static jit_word_t -_vfp_bungti_d(jit_state_t*,jit_word_t,int32_t,jit_float64_t); -# define vfp_bltgtr_x(i0) _vfp_bltgtr_x(_jit,i0) -static jit_word_t _vfp_bltgtr_x(jit_state_t*,jit_word_t); -# define vfp_bltgtr_f(i0,r0,r1) _vfp_bltgtr_f(_jit,i0,r0,r1) -static jit_word_t -_vfp_bltgtr_f(jit_state_t*,jit_word_t,int32_t,int32_t); -# define vfp_bltgti_f(i0,r0,i1) _vfp_bltgti_f(_jit,i0,r0,i1) -static jit_word_t -_vfp_bltgti_f(jit_state_t*,jit_word_t,int32_t,jit_float32_t); -# define vfp_bltgtr_d(i0,r0,r1) _vfp_bltgtr_d(_jit,i0,r0,r1) -static jit_word_t -_vfp_bltgtr_d(jit_state_t*,jit_word_t,int32_t,int32_t); -# define vfp_bltgti_d(i0,r0,i1) _vfp_bltgti_d(_jit,i0,r0,i1) -static jit_word_t -_vfp_bltgti_d(jit_state_t*,jit_word_t,int32_t,jit_float64_t); -# define vfp_bordr_f(i0,r0,r1) vbcmp_f(ARM_CC_VC,i0,r0,r1) -# define vfp_bordi_f(i0,r0,i1) _vfp_bordi_f(_jit,i0,r0,i1) -static jit_word_t -_vfp_bordi_f(jit_state_t*,jit_word_t,int32_t,jit_float32_t); -# define vfp_bordr_d(i0,r0,r1) vbcmp_d(ARM_CC_VC,i0,r0,r1) -# define vfp_bordi_d(i0,r0,i1) _vfp_bordi_d(_jit,i0,r0,i1) -static jit_word_t -_vfp_bordi_d(jit_state_t*,jit_word_t,int32_t,jit_float64_t); -# define vfp_bunordr_f(i0,r0,r1) vbcmp_f(ARM_CC_VS,i0,r0,r1) -# define vfp_bunordi_f(i0,r0,i1) _vfp_bunordi_f(_jit,i0,r0,i1) -static jit_word_t -_vfp_bunordi_f(jit_state_t*,jit_word_t,int32_t,jit_float32_t); -# define vfp_bunordr_d(i0,r0,r1) vbcmp_d(ARM_CC_VS,i0,r0,r1) -# define vfp_bunordi_d(i0,r0,i1) _vfp_bunordi_d(_jit,i0,r0,i1) -static jit_word_t -_vfp_bunordi_d(jit_state_t*,jit_word_t,int32_t,jit_float64_t); -# define vfp_ldr_f(r0,r1) VLDR_F32(r0,r1,0) -# define vfp_ldr_d(r0,r1) VLDR_F64(r0,r1,0) -# define vfp_ldi_f(r0,i0) _vfp_ldi_f(_jit,r0,i0) -static void _vfp_ldi_f(jit_state_t*,int32_t,jit_word_t); -# define vfp_ldi_d(r0,i0) _vfp_ldi_d(_jit,r0,i0) -static void _vfp_ldi_d(jit_state_t*,int32_t,jit_word_t); -# define vfp_ldxr_f(r0,r1,r2) _vfp_ldxr_f(_jit,r0,r1,r2) -static void _vfp_ldxr_f(jit_state_t*,int32_t,int32_t,int32_t); -# define vfp_ldxr_d(r0,r1,r2) _vfp_ldxr_d(_jit,r0,r1,r2) -static void _vfp_ldxr_d(jit_state_t*,int32_t,int32_t,int32_t); -# define vfp_ldxi_f(r0,r1,i0) _vfp_ldxi_f(_jit,r0,r1,i0) -static void _vfp_ldxi_f(jit_state_t*,int32_t,int32_t,jit_word_t); -# define vfp_ldxi_d(r0,r1,i0) _vfp_ldxi_d(_jit,r0,r1,i0) -static void _vfp_ldxi_d(jit_state_t*,int32_t,int32_t,jit_word_t); -# define vfp_str_f(r0,r1) VSTR_F32(r1,r0,0) -# define vfp_str_d(r0,r1) VSTR_F64(r1,r0,0) -# define vfp_sti_f(i0,r0) _vfp_sti_f(_jit,i0,r0) -static void _vfp_sti_f(jit_state_t*,jit_word_t,int32_t); -# define vfp_sti_d(i0,r0) _vfp_sti_d(_jit,i0,r0) -static void _vfp_sti_d(jit_state_t*,jit_word_t,int32_t); -# define vfp_stxr_f(r0,r1,r2) _vfp_stxr_f(_jit,r0,r1,r2) -static void _vfp_stxr_f(jit_state_t*,int32_t,int32_t,int32_t); -# define vfp_stxr_d(r0,r1,r2) _vfp_stxr_d(_jit,r0,r1,r2) -static void _vfp_stxr_d(jit_state_t*,int32_t,int32_t,int32_t); -# define vfp_stxi_f(i0,r0,r1) _vfp_stxi_f(_jit,i0,r0,r1) -static void _vfp_stxi_f(jit_state_t*,jit_word_t,int32_t,int32_t); -# define vfp_stxi_d(i0,r0,r1) _vfp_stxi_d(_jit,i0,r0,r1) -static void _vfp_stxi_d(jit_state_t*,jit_word_t,int32_t,int32_t); -# define vfp_vaarg_d(r0, r1) _vfp_vaarg_d(_jit, r0, r1) -static void _vfp_vaarg_d(jit_state_t*, int32_t, int32_t); - -# define vfp_regno(rn) (((rn) - 16) >> 1) - -static int -encode_vfp_double(int mov, int inv, unsigned lo, unsigned hi) -{ - int code, mode, imm, mask; - - if (hi != lo) { - if (mov && !inv) { - /* (I64) - * aaaaaaaabbbbbbbbccccccccddddddddeeeeeeeeffffffffgggggggghhhhhhhh - */ - for (mode = 0, mask = 0xff; mode < 4; mask <<= 8, mode++) { - imm = lo & mask; - if (imm != mask && imm != 0) - goto fail; - imm = hi & mask; - if (imm != mask && imm != 0) - goto fail; - } - mode = 0xe20; - imm = (((hi & 0x80000000) >> 24) | ((hi & 0x00800000) >> 17) | - ((hi & 0x00008000) >> 10) | ((hi & 0x00000080) >> 3) | - ((lo & 0x80000000) >> 28) | ((lo & 0x00800000) >> 21) | - ((lo & 0x00008000) >> 14) | ((lo & 0x00000080) >> 7)); - goto success; - } - goto fail; - } - /* (I32) - * 00000000 00000000 00000000 abcdefgh - * 00000000 00000000 abcdefgh 00000000 - * 00000000 abcdefgh 00000000 00000000 - * abcdefgh 00000000 00000000 00000000 */ - for (mode = 0, mask = 0xff; mode < 4; mask <<= 8, mode++) { - if ((lo & mask) == lo) { - imm = lo >> (mode << 3); - mode <<= 9; - goto success; - } - } - /* (I16) - * 00000000 abcdefgh 00000000 abcdefgh - * abcdefgh 00000000 abcdefgh 00000000 */ - for (mode = 0, mask = 0xff; mode < 2; mask <<= 8, mode++) { - if ((lo & mask) && ((lo & (mask << 16)) >> 16) == (lo & mask)) { - imm = lo >> (mode << 3); - mode = 0x800 | (mode << 9); - goto success; - } - } - if (mov) { - /* (I32) - * 00000000 00000000 abcdefgh 11111111 - * 00000000 abcdefgh 11111111 11111111 */ - for (mode = 0, mask = 0xff; mode < 2; - mask = (mask << 8) | 0xff, mode++) { - if ((lo & mask) == mask && - !((lo & ~mask) >> 8) && - (imm = lo >> (8 + (mode << 8)))) { - mode = 0xc00 | (mode << 8); - goto success; - } - } - if (!inv) { - /* (F32) - * aBbbbbbc defgh000 00000000 00000000 - * from the ARM Architecture Reference Manual: - * In this entry, B = NOT(b). The bit pattern represents the - * floating-point number (-1)^s* 2^exp * mantissa, where - * S = UInt(a), - * exp = UInt(NOT(b):c:d)-3 and - * mantissa = (16+UInt(e:f:g:h))/16. */ - if ((lo & 0x7ffff) == 0 && - (((lo & 0x7e000000) == 0x3e000000) || - ((lo & 0x7e000000) == 0x40000000))) { - mode = 0xf00; - imm = ((lo >> 24) & 0x80) | ((lo >> 19) & 0x7f); - goto success; - } - } - } - -fail: - /* need another approach (load from memory, move from arm register, etc) */ - return (-1); - -success: - code = inv ? ARM_VMVNI : ARM_VMOVI; - switch ((mode & 0xf00) >> 8) { - case 0x0: case 0x2: case 0x4: case 0x6: - case 0x8: case 0xa: - if (inv) mode |= 0x20; - if (!mov) mode |= 0x100; - break; - case 0x1: case 0x3: case 0x5: case 0x7: - /* should actually not reach here */ - assert(!inv); - case 0x9: case 0xb: - assert(!mov); - break; - case 0xc: case 0xd: - /* should actually not reach here */ - assert(inv); - case 0xe: - assert(mode & 0x20); - assert(mov && !inv); - break; - default: - assert(!(mode & 0x20)); - break; - } - imm = ((imm & 0x80) << 17) | ((imm & 0x70) << 12) | (imm & 0x0f); - code |= mode | imm; - if (jit_thumb_p()) { - if (code & 0x1000000) - code |= 0xff000000; - else - code |= 0xef000000; - } - else - code |= ARM_CC_NV; - return (code); -} +#define vfp_regno(rn) (((rn) - 16) >> 1) static void -_vodi(jit_state_t *_jit, int oi, int r0) +vodi(jit_state_t *_jit, int oi, int r0) { - jit_thumb_t thumb; - assert(!(oi & 0x0000f000)); - assert(!(r0 & 1)); r0 = vfp_regno(r0); - thumb.i = oi|(_u4(r0)<<12); - if (jit_thumb_p()) - iss(thumb.s[0], thumb.s[1]); - else - ii(thumb.i); + jit_thumb_t thumb; + assert(!(oi & 0x0000f000)); + assert(!(r0 & 1)); r0 = vfp_regno(r0); + thumb.i = oi|(_u4(r0)<<12); + iss(thumb.s[0], thumb.s[1]); } static void _voqi(jit_state_t *_jit, int oi, int r0) { - jit_thumb_t thumb; - assert(!(oi & 0x0000f000)); - assert(!(r0 & 3)); r0 = vfp_regno(r0); - thumb.i = oi|(_u4(r0)<<12); - if (jit_thumb_p()) - iss(thumb.s[0], thumb.s[1]); - else - ii(thumb.i); + jit_thumb_t thumb; + assert(!(oi & 0x0000f000)); + assert(!(r0 & 3)); r0 = vfp_regno(r0); + thumb.i = oi|(_u4(r0)<<12); + iss(thumb.s[0], thumb.s[1]); } static void -_cc_vo_ss(jit_state_t *_jit, int cc, int o, int r0, int r1) +vo_ss(jit_state_t *_jit, int o, int r0, int r1) { - jit_thumb_t thumb; - assert(!(cc & 0x0fffffff)); - assert(!(o & 0xf000f00f)); - if (r0 & 1) o |= ARM_V_D; r0 = vfp_regno(r0); - if (r1 & 1) o |= ARM_V_M; r1 = vfp_regno(r1); - thumb.i = cc|o|(_u4(r0)<<12)|_u4(r1); - if (jit_thumb_p()) - iss(thumb.s[0], thumb.s[1]); - else - ii(thumb.i); + assert(!(o & 0xf000f00f)); + if (r0 & 1) o |= ARM_V_D; r0 = vfp_regno(r0); + if (r1 & 1) o |= ARM_V_M; r1 = vfp_regno(r1); + emit_wide_thumb(_jit, ARM_CC_AL|o|(_u4(r0)<<12)|_u4(r1)); } static void -_cc_vo_dd(jit_state_t *_jit, int cc, int o, int r0, int r1) +vo_dd(jit_state_t *_jit, int o, int r0, int r1) { - jit_thumb_t thumb; - assert(!(cc & 0x0fffffff)); - assert(!(o & 0xf000f00f)); - assert(!(r0 & 1) && !(r1 & 1)); - r0 = vfp_regno(r0); r1 = vfp_regno(r1); - thumb.i = cc|o|(_u4(r0)<<12)|_u4(r1); - if (jit_thumb_p()) - iss(thumb.s[0], thumb.s[1]); - else - ii(thumb.i); + assert(!(o & 0xf000f00f)); + assert(!(r0 & 1) && !(r1 & 1)); + r0 = vfp_regno(r0); r1 = vfp_regno(r1); + emit_wide_thumb(_jit, ARM_CC_AL|o|(_u4(r0)<<12)|_u4(r1)); } static void -_cc_vo_qd(jit_state_t *_jit, int cc, int o, int r0, int r1) +vo_qd(jit_state_t *_jit, int o, int r0, int r1) { - jit_thumb_t thumb; - assert(!(cc & 0x0fffffff)); - assert(!(o & 0xf000f00f)); - assert(!(r0 & 3) && !(r1 & 1)); - r0 = vfp_regno(r0); r1 = vfp_regno(r1); - thumb.i = cc|o|(_u4(r0)<<12)|_u4(r1); - if (jit_thumb_p()) - iss(thumb.s[0], thumb.s[1]); - else - ii(thumb.i); + assert(!(o & 0xf000f00f)); + assert(!(r0 & 3) && !(r1 & 1)); + r0 = vfp_regno(r0); r1 = vfp_regno(r1); + emit_wide_thumb(_jit, ARM_CC_AL|o|(_u4(r0)<<12)|_u4(r1)); } static void -_cc_vo_qq(jit_state_t *_jit, int cc, int o, int r0, int r1) +vo_qq(jit_state_t *_jit, int o, int r0, int r1) { - jit_thumb_t thumb; - assert(!(cc & 0x0fffffff)); - assert(!(o & 0xf000f00f)); - assert(!(r0 & 3) && !(r1 & 3)); - r0 = vfp_regno(r0); r1 = vfp_regno(r1); - thumb.i = cc|o|(_u4(r0)<<12)|_u4(r1); - if (jit_thumb_p()) - iss(thumb.s[0], thumb.s[1]); - else - ii(thumb.i); + assert(!(o & 0xf000f00f)); + assert(!(r0 & 3) && !(r1 & 3)); + r0 = vfp_regno(r0); r1 = vfp_regno(r1); + emit_wide_thumb(_jit, ARM_CC_AL|o|(_u4(r0)<<12)|_u4(r1)); } static void -_cc_vorr_(jit_state_t *_jit, int cc, int o, int r0, int r1) +vorr_(jit_state_t *_jit, int o, int r0, int r1) { - jit_thumb_t thumb; - assert(!(cc & 0x0fffffff)); - assert(!(o & 0xf000f00f)); - thumb.i = cc|o|(_u4(r1)<<16)|(_u4(r0)<<12); - if (jit_thumb_p()) - iss(thumb.s[0], thumb.s[1]); - else - ii(thumb.i); + assert(!(o & 0xf000f00f)); + emit_wide_thumb(_jit, ARM_CC_AL|o|(_u4(r1)<<16)|(_u4(r0)<<12)); } static void -_cc_vors_(jit_state_t *_jit, int cc, int o, int r0, int r1) +vors_(jit_state_t *_jit, int o, int r0, int r1) { - jit_thumb_t thumb; - assert(!(cc & 0x0fffffff)); - assert(!(o & 0xf000f00f)); - if (r1 & 1) o |= ARM_V_N; r1 = vfp_regno(r1); - thumb.i = cc|o|(_u4(r1)<<16)|(_u4(r0)<<12); - if (jit_thumb_p()) - iss(thumb.s[0], thumb.s[1]); - else - ii(thumb.i); + assert(!(o & 0xf000f00f)); + if (r1 & 1) o |= ARM_V_N; r1 = vfp_regno(r1); + emit_wide_thumb(_jit, ARM_CC_AL|o|(_u4(r1)<<16)|(_u4(r0)<<12)); } static void -_cc_vorv_(jit_state_t *_jit, int cc, int o, int r0, int r1) +vorv_(jit_state_t *_jit, int o, int r0, int r1) { - jit_thumb_t thumb; - assert(!(cc & 0x0fffffff)); - assert(!(o & 0xf000f00f)); - if (r1 & 1) o |= ARM_V_M; r1 = vfp_regno(r1); - thumb.i = cc|o|(_u4(r1)<<16)|(_u4(r0)<<12); - if (jit_thumb_p()) - iss(thumb.s[0], thumb.s[1]); - else - ii(thumb.i); + assert(!(o & 0xf000f00f)); + if (r1 & 1) o |= ARM_V_M; r1 = vfp_regno(r1); + emit_wide_thumb(_jit, ARM_CC_AL|o|(_u4(r1)<<16)|(_u4(r0)<<12)); } static void -_cc_vori_(jit_state_t *_jit, int cc, int o, int r0, int r1) +vori_(jit_state_t *_jit, int o, int r0, int r1) { - jit_thumb_t thumb; - assert(!(cc & 0x0fffffff)); - assert(!(o & 0xf000f00f)); - /* use same bit pattern, to set opc1... */ - if (r1 & 1) o |= ARM_V_I32; r1 = vfp_regno(r1); - thumb.i = cc|o|(_u4(r1)<<16)|(_u4(r0)<<12); - if (jit_thumb_p()) - iss(thumb.s[0], thumb.s[1]); - else - ii(thumb.i); + assert(!(o & 0xf000f00f)); + /* use same bit pattern, to set opc1... */ + if (r1 & 1) o |= ARM_V_I32; r1 = vfp_regno(r1); + emit_wide_thumb(_jit, ARM_CC_AL|o|(_u4(r1)<<16)|(_u4(r0)<<12)); } static void -_cc_vorrd(jit_state_t *_jit, int cc, int o, int r0, int r1, int r2) +vorrd(jit_state_t *_jit, int o, int r0, int r1, int r2) { - jit_thumb_t thumb; - assert(!(cc & 0x0fffffff)); - assert(!(o & 0xf00ff00f)); - assert(!(r2 & 1)); - r2 = vfp_regno(r2); - thumb.i = cc|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u4(r2); - if (jit_thumb_p()) - iss(thumb.s[0], thumb.s[1]); - else - ii(thumb.i); + assert(!(o & 0xf00ff00f)); + assert(!(r2 & 1)); + r2 = vfp_regno(r2); + emit_wide_thumb(_jit, ARM_CC_AL|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u4(r2)); } static void -_cc_vosss(jit_state_t *_jit, int cc, int o, int r0, int r1, int r2) +vosss(jit_state_t *_jit, int o, int r0, int r1, int r2) { - jit_thumb_t thumb; - assert(!(cc & 0x0fffffff)); - assert(!(o & 0xf00ff00f)); - if (r0 & 1) o |= ARM_V_D; r0 = vfp_regno(r0); - if (r1 & 1) o |= ARM_V_N; r1 = vfp_regno(r1); - if (r2 & 1) o |= ARM_V_M; r2 = vfp_regno(r2); - thumb.i = cc|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u4(r2); - if (jit_thumb_p()) - iss(thumb.s[0], thumb.s[1]); - else - ii(thumb.i); + assert(!(o & 0xf00ff00f)); + if (r0 & 1) o |= ARM_V_D; r0 = vfp_regno(r0); + if (r1 & 1) o |= ARM_V_N; r1 = vfp_regno(r1); + if (r2 & 1) o |= ARM_V_M; r2 = vfp_regno(r2); + emit_wide_thumb(_jit, ARM_CC_AL|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u4(r2)); } static void -_cc_voddd(jit_state_t *_jit, int cc, int o, int r0, int r1, int r2) +voddd(jit_state_t *_jit, int o, int r0, int r1, int r2) { - jit_thumb_t thumb; - assert(!(cc & 0x0fffffff)); - assert(!(o & 0xf00ff00f)); - assert(!(r0 & 1) && !(r1 & 1) && !(r2 & 1)); - r0 = vfp_regno(r0); r1 = vfp_regno(r1); r2 = vfp_regno(r2); - thumb.i = cc|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u4(r2); - if (jit_thumb_p()) - iss(thumb.s[0], thumb.s[1]); - else - ii(thumb.i); + assert(!(o & 0xf00ff00f)); + assert(!(r0 & 1) && !(r1 & 1) && !(r2 & 1)); + r0 = vfp_regno(r0); r1 = vfp_regno(r1); r2 = vfp_regno(r2); + emit_wide_thumb(_jit, ARM_CC_AL|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u4(r2)); } static void -_cc_voqdd(jit_state_t *_jit, int cc, int o, int r0, int r1, int r2) +voqdd(jit_state_t *_jit, int o, int r0, int r1, int r2) { - jit_thumb_t thumb; - assert(!(cc & 0x0fffffff)); - assert(!(o & 0xf00ff00f)); - assert(!(r0 & 3) && !(r1 & 1) && !(r2 & 1)); - r0 = vfp_regno(r0); r1 = vfp_regno(r1); r2 = vfp_regno(r2); - thumb.i = cc|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u4(r2); - if (jit_thumb_p()) - iss(thumb.s[0], thumb.s[1]); - else - ii(thumb.i); + assert(!(o & 0xf00ff00f)); + assert(!(r0 & 3) && !(r1 & 1) && !(r2 & 1)); + r0 = vfp_regno(r0); r1 = vfp_regno(r1); r2 = vfp_regno(r2); + emit_wide_thumb(_jit, ARM_CC_AL|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u4(r2)); } static void -_cc_voqqd(jit_state_t *_jit, int cc, int o, int r0, int r1, int r2) +voqqd(jit_state_t *_jit, int o, int r0, int r1, int r2) { - jit_thumb_t thumb; - assert(!(cc & 0x0fffffff)); - assert(!(o & 0xf00ff00f)); - assert(!(r0 & 3) && !(r1 & 3) && !(r2 & 1)); - r0 = vfp_regno(r0); r1 = vfp_regno(r1); r2 = vfp_regno(r2); - thumb.i = cc|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u4(r2); - if (jit_thumb_p()) - iss(thumb.s[0], thumb.s[1]); - else - ii(thumb.i); + assert(!(o & 0xf00ff00f)); + assert(!(r0 & 3) && !(r1 & 3) && !(r2 & 1)); + r0 = vfp_regno(r0); r1 = vfp_regno(r1); r2 = vfp_regno(r2); + emit_wide_thumb(_jit, ARM_CC_AL|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u4(r2)); } static void -_cc_voqqq(jit_state_t *_jit, int cc, int o, int r0, int r1, int r2) +voqqq(jit_state_t *_jit, int o, int r0, int r1, int r2) { - jit_thumb_t thumb; - assert(!(cc & 0x0fffffff)); - assert(!(o & 0xf00ff00f)); - assert(!(r0 & 3) && !(r1 & 3) && !(r2 & 3)); - r0 = vfp_regno(r0); r1 = vfp_regno(r1); r2 = vfp_regno(r2); - thumb.i = cc|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u4(r2); - if (jit_thumb_p()) - iss(thumb.s[0], thumb.s[1]); - else - ii(thumb.i); + assert(!(o & 0xf00ff00f)); + assert(!(r0 & 3) && !(r1 & 3) && !(r2 & 3)); + r0 = vfp_regno(r0); r1 = vfp_regno(r1); r2 = vfp_regno(r2); + emit_wide_thumb(_jit, ARM_CC_AL|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u4(r2)); } static void -_cc_vldst(jit_state_t *_jit, int cc, int o, int r0, int r1, int i0) +vldst(jit_state_t *_jit, int o, int r0, int r1, int i0) { - jit_thumb_t thumb; - /* i0 << 2 is byte offset */ - assert(!(cc & 0x0fffffff)); - assert(!(o & 0xf00ff0ff)); - if (r0 & 1) { - assert(!(o & ARM_V_F64)); - o |= ARM_V_D; + /* i0 << 2 is byte offset */ + assert(!(o & 0xf00ff0ff)); + if (r0 & 1) { + assert(!(o & ARM_V_F64)); + o |= ARM_V_D; + } + r0 = vfp_regno(r0); + emit_wide_thumb(_jit, ARM_CC_AL|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u8(i0)); +} + +static void +vorsl(jit_state_t *_jit, int o, int r0, int r1, int i0) +{ + assert(!(o & 0xf00ff0ff)); + /* save i0 double precision registers */ + if (o & ARM_V_F64) i0 <<= 1; + /* if (r1 & 1) cc & ARM_V_F64 must be false */ + if (r1 & 1) o |= ARM_V_D; r1 = vfp_regno(r1); + assert(i0 && !(i0 & 1) && r1 + i0 <= 32); + emit_wide_thumb(_jit, ARM_CC_AL|o|(_u4(r0)<<16)|(_u4(r1)<<12)|_u8(i0)); +} + +static void +VADD_F32(jit_state_t *_jit, int32_t r0,r1,r2) +{ + vosss(_jit,ARM_VADD_F,r0,r1,r2); +} + +static void +VADD_F64(jit_state_t *_jit, int32_t r0,r1,r2) +{ + voddd(_jit,ARM_VADD_F|ARM_V_F64,r0,r1,r2); +} + +static void +VSUB_F32(jit_state_t *_jit, int32_t r0,r1,r2) +{ + vosss(_jit,ARM_VSUB_F,r0,r1,r2); +} + +static void +VSUB_F64(jit_state_t *_jit, int32_t r0,r1,r2) +{ + voddd(_jit,ARM_VSUB_F|ARM_V_F64,r0,r1,r2); +} + +static void +VMUL_F32(jit_state_t *_jit, int32_t r0,r1,r2) +{ + vosss(_jit,ARM_VMUL_F,r0,r1,r2); +} + +static void +VMUL_F64(jit_state_t *_jit, int32_t r0,r1,r2) +{ + voddd(_jit,ARM_VMUL_F|ARM_V_F64,r0,r1,r2); +} + +static void +VDIV_F32(jit_state_t *_jit, int32_t r0,r1,r2) +{ + vosss(_jit,ARM_VDIV_F,r0,r1,r2); +} + +static void +VDIV_F64(jit_state_t *_jit, int32_t r0,r1,r2) +{ + voddd(_jit,ARM_VDIV_F|ARM_V_F64,r0,r1,r2); +} + +static void +VABS_F32(jit_state_t *_jit, int32_t r0,r1) +{ + vo_ss(_jit,ARM_VABS_F,r0,r1); +} + +static void +VABS_F64(jit_state_t *_jit, int32_t r0,r1) +{ + vo_dd(_jit,ARM_VABS_F|ARM_V_F64,r0,r1); +} + +static void +VNEG_F32(jit_state_t *_jit, int32_t r0,r1) +{ + vo_ss(_jit,ARM_VNEG_F,r0,r1); +} + +static void +VNEG_F64(jit_state_t *_jit, int32_t r0,r1) +{ + vo_dd(_jit,ARM_VNEG_F|ARM_V_F64,r0,r1); +} + +static void +VSQRT_F32(jit_state_t *_jit, int32_t r0,r1) +{ + vo_ss(_jit,ARM_VSQRT_F,r0,r1); +} + +static void +VSQRT_F64(jit_state_t *_jit, int32_t r0,r1) +{ + vo_dd(_jit,ARM_VSQRT_F|ARM_V_F64,r0,r1); +} + +static void +VMOV_F32(jit_state_t *_jit, int32_t r0,r1) +{ + vo_ss(_jit,ARM_VMOV_F,r0,r1); +} + +static void +VMOV_F64(jit_state_t *_jit, int32_t r0,r1) +{ + vo_dd(_jit,ARM_VMOV_F|ARM_V_F64,r0,r1); +} + +static void +VMOV_AA_D(jit_state_t *_jit, int32_t r0,r1,r2) +{ + vorrd(_jit,ARM_VMOV_AA_D,r0,r1,r2); +} + +static void +VMOV_D_AA(jit_state_t *_jit, int32_t r0,r1,r2) +{ + vorrd(_jit,ARM_VMOV_D_AA,r1,r2,r0); +} + +static void +VMOV_A_S(jit_state_t *_jit, int32_t r0,r1) +{ + vors_(_jit,ARM_VMOV_A_S,r0,r1); +} + +static void +VMOV_S_A(jit_state_t *_jit, int32_t r0,r1) +{ + vors_(_jit,ARM_VMOV_S_A,r1,r0); +} + +static void +VCMP_F32(jit_state_t *_jit, int32_t r0,r1) +{ + vo_ss(_jit,ARM_VCMP,r0,r1); +} + +static void +VCMP_F64(jit_state_t *_jit, int32_t r0,r1) +{ + vo_dd(_jit,ARM_VCMP|ARM_V_F64,r0,r1); +} + +static void +VMRS(jit_state_t *_jit, int32_t r0) +{ + vorr_(_jit,ARM_VMRS,r0,0); +} + +static void +VCVT_S32_F32(jit_state_t *_jit, int32_t r0,r1) +{ + vo_ss(_jit,ARM_VCVT_S32_F32,r0,r1); +} + +static void +VCVT_S32_F64(jit_state_t *_jit, int32_t r0,r1) +{ + vo_ss(_jit,ARM_VCVT_S32_F64,r0,r1); +} + +static void +VCVT_F32_S32(jit_state_t *_jit, int32_t r0,r1) +{ + vo_ss(_jit,ARM_VCVT_F32_S32,r0,r1); +} + +static void +VCVT_F64_S32(jit_state_t *_jit, int32_t r0,r1) +{ + vo_ss(_jit,ARM_VCVT_F64_S32,r0,r1); +} + +static void +VCVT_F32_F64(jit_state_t *_jit, int32_t r0,r1) +{ + vo_ss(_jit,ARM_VCVT_F32_F64,r0,r1); +} + +static void +VCVT_F64_F32(jit_state_t *_jit, int32_t r0,r1) +{ + vo_ss(_jit,ARM_VCVT_F64_F32,r0,r1); +} + +static void +VMOV_A_S32(jit_state_t *_jit, int32_t r0,r1) +{ + vori_(_jit,ARM_VMOV_A_D,r0,r1); +} + +static void +VMOV_V_I32(jit_state_t *_jit, int32_t r0,r1) +{ + vori_(_jit,ARM_VMOV_D_A,r1,r0); +} + +/* "oi" should be the result of encode_vfp_double */ +static void +VIMM(jit_state_t *_jit, int32_t oi,r0) +{ + vodi(_jit, oi,r0); +} + +/* index is multipled by four */ +static void +VLDRN_F32(jit_state_t *_jit, int32_t r0,r1,i0) +{ + vldst(_jit,ARM_VLDR,r0,r1,i0); +} + +static void +VLDR_F32(jit_state_t *_jit, int32_t r0,r1,i0) +{ + vldst(_jit,ARM_VLDR|ARM_P,r0,r1,i0); +} + +static void +VLDRN_F64(jit_state_t *_jit, int32_t r0,r1,i0) +{ + vldst(_jit,ARM_VLDR|ARM_V_F64,r0,r1,i0); +} + +static void +VLDR_F64(jit_state_t *_jit, int32_t r0,r1,i0) +{ + vldst(_jit,ARM_VLDR|ARM_V_F64|ARM_P,r0,r1,i0); +} + +static void +VSTRN_F32(jit_state_t *_jit, int32_t r0,r1,i0) +{ + vldst(_jit,ARM_VSTR,r0,r1,i0); +} + +static void +VSTR_F32(jit_state_t *_jit, int32_t r0,r1,i0) +{ + vldst(_jit,ARM_VSTR|ARM_P,r0,r1,i0); +} + +static void +VSTRN_F64(jit_state_t *_jit, int32_t r0,r1,i0) +{ + vldst(_jit,ARM_VSTR|ARM_V_F64,r0,r1,i0); +} + +static void +VSTR_F64(jit_state_t *_jit, int32_t r0,r1,i0) +{ + vldst(_jit,ARM_VSTR|ARM_V_F64|ARM_P,r0,r1,i0); +} + +static void +vfp_absr_f(jit_state_t *_jit, int32_t r0,r1) +{ + VABS_F32(_jit, r0,r1); +} + +static void +vfp_absr_d(jit_state_t *_jit, int32_t r0,r1) +{ + VABS_F64(_jit, r0,r1); +} + +static void +vfp_negr_f(jit_state_t *_jit, int32_t r0,r1) +{ + VNEG_F32(_jit, r0,r1); +} + +static void +vfp_negr_d(jit_state_t *_jit, int32_t r0,r1) +{ + VNEG_F64(_jit, r0,r1); +} + +static void +vfp_sqrtr_f(jit_state_t *_jit, int32_t r0,r1) +{ + VSQRT_F32(_jit, r0,r1); +} + +static void +vfp_sqrtr_d(jit_state_t *_jit, int32_t r0,r1) +{ + VSQRT_F64(_jit, r0,r1); +} + +static void +vfp_addr_f(jit_state_t *_jit, int32_t r0,r1,r2) +{ + VADD_F32(_jit, r0,r1,r2); +} + +static void +vfp_addr_d(jit_state_t *_jit, int32_t r0,r1,r2) +{ + VADD_F64(_jit, r0,r1,r2); +} + +static void +vfp_subr_f(jit_state_t *_jit, int32_t r0,r1,r2) +{ + VSUB_F32(_jit, r0,r1,r2); +} + +static void +vfp_subr_d(jit_state_t *_jit, int32_t r0,r1,r2) +{ + VSUB_F64(_jit, r0,r1,r2); +} + +static void +vfp_mulr_f(jit_state_t *_jit, int32_t r0,r1,r2) +{ + VMUL_F32(_jit, r0,r1,r2); +} + +static void +vfp_mulr_d(jit_state_t *_jit, int32_t r0,r1,r2) +{ + VMUL_F64(_jit, r0,r1,r2); +} + +static void +vfp_divr_f(jit_state_t *_jit, int32_t r0,r1,r2) +{ + VDIV_F32(_jit, r0,r1,r2); +} + +static void +vfp_divr_d(jit_state_t *_jit, int32_t r0,r1,r2) +{ + VDIV_F64(_jit, r0,r1,r2); +} + +static jit_reloc_t +vfp_bltr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return vbcmp_f(_jit, ARM_CC_MI, r0, r1); +} + +static jit_reloc_t +vfp_bltr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return vbcmp_d(_jit, ARM_CC_MI, r0, r1); +} + +static jit_reloc_t +vfp_bler_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return vbcmp_f(_jit, ARM_CC_LS, r0, r1); +} + +static jit_reloc_t +vfp_bler_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return vbcmp_d(_jit, ARM_CC_LS, r0, r1); +} + +static jit_reloc_t +vfp_beqr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return vbcmp_f(_jit, ARM_CC_EQ, r0, r1); +} + +static jit_reloc_t +vfp_beqr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return vbcmp_d(_jit, ARM_CC_EQ, r0, r1); +} + +static jit_reloc_t +vfp_bger_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return vbcmp_f(_jit, ARM_CC_GE, r0, r1); +} + +static jit_reloc_t +vfp_bger_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return vbcmp_d(_jit, ARM_CC_GE, r0, r1); +} + +static jit_reloc_t +vfp_bgtr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return vbcmp_f(_jit, ARM_CC_GT, r0, r1); +} + +static jit_reloc_t +vfp_bgtr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return vbcmp_d(_jit, ARM_CC_GT, r0, r1); +} + +static jit_reloc_t +vfp_bner_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return vbcmp_f(_jit, ARM_CC_NE, r0, r1); +} + +static jit_reloc_t +vfp_bner_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return vbcmp_d(_jit, ARM_CC_NE, r0, r1); +} + +static jit_reloc_t +vfp_bunltr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return vbncmp_f(_jit, ARM_CC_GE, r0, r1); +} + +static jit_reloc_t +vfp_bunltr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return vbncmp_d(_jit, ARM_CC_GE, r0, r1); +} + +static jit_reloc_t +vfp_bunler_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return vbncmp_f(_jit, ARM_CC_GT, r0, r1); +} + +static jit_reloc_t +vfp_bunler_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return vbncmp_d(_jit, ARM_CC_GT, r0, r1); +} + +static jit_reloc_t +vfp_bungtr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return vbcmp_f(_jit, ARM_CC_HI, r0, r1); +} + +static jit_reloc_t +vfp_bungtr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return vbcmp_d(_jit, ARM_CC_HI, r0, r1); +} + +static jit_reloc_t +vfp_bordr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return vbcmp_f(_jit, ARM_CC_VC, r0, r1); +} + +static jit_reloc_t +vfp_bordr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return vbcmp_d(_jit, ARM_CC_VC, r0, r1); +} + +static jit_reloc_t +vfp_bunordr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return vbcmp_f(_jit, ARM_CC_VS, r0, r1); +} + +static jit_reloc_t +vfp_bunordr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return vbcmp_d(_jit, ARM_CC_VS, r0, r1); +} + +static void +vfp_ldr_f(jit_state_t *_jit, int32_t r0,r1) +{ + VLDR_F32(_jit, r0,r1,0); +} + +static void +vfp_ldr_d(jit_state_t *_jit, int32_t r0,r1) +{ + VLDR_F64(_jit, r0,r1,0); +} + +static void +vfp_str_f(jit_state_t *_jit, int32_t r0,r1) +{ + VSTR_F32(_jit, r1,r0,0); +} + +static void +vfp_str_d(jit_state_t *_jit, int32_t r0,r1) +{ + VSTR_F64(_jit, r1,r0,0); +} + +static void +vfp_movr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + if (r0 != r1) { + if (jit_fpr_p(r1)) { + if (jit_fpr_p(r0)) + VMOV_F32(r0, r1); + else + VMOV_A_S(r0, r1); } - r0 = vfp_regno(r0); - thumb.i = cc|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u8(i0); - if (jit_thumb_p()) - iss(thumb.s[0], thumb.s[1]); + else if (jit_fpr_p(r0)) + VMOV_S_A(r0, r1); else - ii(thumb.i); + movr(r0, r1); + } } static void -_cc_vorsl(jit_state_t *_jit, int cc, int o, int r0, int r1, int i0) +vfp_movr_d(jit_state_t *_jit, int32_t r0, int32_t r1) { - jit_thumb_t thumb; - assert(!(cc & 0x0fffffff)); - assert(!(o & 0xf00ff0ff)); - /* save i0 double precision registers */ - if (o & ARM_V_F64) i0 <<= 1; - /* if (r1 & 1) cc & ARM_V_F64 must be false */ - if (r1 & 1) o |= ARM_V_D; r1 = vfp_regno(r1); - assert(i0 && !(i0 & 1) && r1 + i0 <= 32); - thumb.i = cc|o|(_u4(r0)<<16)|(_u4(r1)<<12)|_u8(i0); - if (jit_thumb_p()) - iss(thumb.s[0], thumb.s[1]); - else - ii(thumb.i); -} - -static void -_vfp_movr_f(jit_state_t *_jit, int32_t r0, int32_t r1) -{ - if (r0 != r1) { - if (jit_fpr_p(r1)) { - if (jit_fpr_p(r0)) - VMOV_F32(r0, r1); - else - VMOV_A_S(r0, r1); - } - else if (jit_fpr_p(r0)) - VMOV_S_A(r0, r1); - else - movr(r0, r1); + if (r0 != r1) { + if (jit_fpr_p(r1)) { + if (jit_fpr_p(r0)) + VMOV_F64(r0, r1); + else + VMOV_AA_D(r0, r0 + 1, r1); } + else if (jit_fpr_p(r0)) + VMOV_D_AA(r0, r1, r1 + 1); + else { + /* minor consistency check */ + assert(r0 + 1 != r1 && r0 -1 != r1); + movr(r0, r1); + movr(r0 + 1, r1 + 1); + } + } } -static void -_vfp_movr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +static int +encode_vfp_double(int mov, int inv, unsigned lo, unsigned hi) { - if (r0 != r1) { - if (jit_fpr_p(r1)) { - if (jit_fpr_p(r0)) - VMOV_F64(r0, r1); - else - VMOV_AA_D(r0, r0 + 1, r1); - } - else if (jit_fpr_p(r0)) - VMOV_D_AA(r0, r1, r1 + 1); - else { - /* minor consistency check */ - assert(r0 + 1 != r1 && r0 -1 != r1); - movr(r0, r1); - movr(r0 + 1, r1 + 1); - } + int code, mode, imm, mask; + + if (hi != lo) { + if (mov && !inv) { + /* (I64) + * aaaaaaaabbbbbbbbccccccccddddddddeeeeeeeeffffffffgggggggghhhhhhhh + */ + for (mode = 0, mask = 0xff; mode < 4; mask <<= 8, mode++) { + imm = lo & mask; + if (imm != mask && imm != 0) + goto fail; + imm = hi & mask; + if (imm != mask && imm != 0) + goto fail; + } + mode = 0xe20; + imm = (((hi & 0x80000000) >> 24) | ((hi & 0x00800000) >> 17) | + ((hi & 0x00008000) >> 10) | ((hi & 0x00000080) >> 3) | + ((lo & 0x80000000) >> 28) | ((lo & 0x00800000) >> 21) | + ((lo & 0x00008000) >> 14) | ((lo & 0x00000080) >> 7)); + goto success; } + goto fail; + } + /* (I32) + * 00000000 00000000 00000000 abcdefgh + * 00000000 00000000 abcdefgh 00000000 + * 00000000 abcdefgh 00000000 00000000 + * abcdefgh 00000000 00000000 00000000 */ + for (mode = 0, mask = 0xff; mode < 4; mask <<= 8, mode++) { + if ((lo & mask) == lo) { + imm = lo >> (mode << 3); + mode <<= 9; + goto success; + } + } + /* (I16) + * 00000000 abcdefgh 00000000 abcdefgh + * abcdefgh 00000000 abcdefgh 00000000 */ + for (mode = 0, mask = 0xff; mode < 2; mask <<= 8, mode++) { + if ((lo & mask) && ((lo & (mask << 16)) >> 16) == (lo & mask)) { + imm = lo >> (mode << 3); + mode = 0x800 | (mode << 9); + goto success; + } + } + if (mov) { + /* (I32) + * 00000000 00000000 abcdefgh 11111111 + * 00000000 abcdefgh 11111111 11111111 */ + for (mode = 0, mask = 0xff; mode < 2; + mask = (mask << 8) | 0xff, mode++) { + if ((lo & mask) == mask && + !((lo & ~mask) >> 8) && + (imm = lo >> (8 + (mode << 8)))) { + mode = 0xc00 | (mode << 8); + goto success; + } + } + if (!inv) { + /* (F32) + * aBbbbbbc defgh000 00000000 00000000 + * from the ARM Architecture Reference Manual: + * In this entry, B = NOT(b). The bit pattern represents the + * floating-point number (-1)^s* 2^exp * mantissa, where + * S = UInt(a), + * exp = UInt(NOT(b):c:d)-3 and + * mantissa = (16+UInt(e:f:g:h))/16. */ + if ((lo & 0x7ffff) == 0 && + (((lo & 0x7e000000) == 0x3e000000) || + ((lo & 0x7e000000) == 0x40000000))) { + mode = 0xf00; + imm = ((lo >> 24) & 0x80) | ((lo >> 19) & 0x7f); + goto success; + } + } + } + +fail: + /* need another approach (load from memory, move from arm register, etc) */ + return (-1); + +success: + code = inv ? ARM_VMVNI : ARM_VMOVI; + switch ((mode & 0xf00) >> 8) { + case 0x0: case 0x2: case 0x4: case 0x6: + case 0x8: case 0xa: + if (inv) mode |= 0x20; + if (!mov) mode |= 0x100; + break; + case 0x1: case 0x3: case 0x5: case 0x7: + /* should actually not reach here */ + assert(!inv); + case 0x9: case 0xb: + assert(!mov); + break; + case 0xc: case 0xd: + /* should actually not reach here */ + assert(inv); + case 0xe: + assert(mode & 0x20); + assert(mov && !inv); + break; + default: + assert(!(mode & 0x20)); + break; + } + imm = ((imm & 0x80) << 17) | ((imm & 0x70) << 12) | (imm & 0x0f); + code |= mode | imm; + + if (code & 0x1000000) + code |= 0xff000000; + else + code |= 0xef000000; + + return (code); } static void _vfp_movi_f(jit_state_t *_jit, int32_t r0, jit_float32_t i0) { - union { - int32_t i; - jit_float32_t f; - } u; - int32_t reg; - int32_t code; - u.f = i0; - if (jit_fpr_p(r0)) { - /* float arguments are packed, for others, - * lightning only address even registers */ - if (!(r0 & 1) && (r0 - 16) >= 0 && - ((code = encode_vfp_double(1, 0, u.i, u.i)) != -1 || - (code = encode_vfp_double(1, 1, ~u.i, ~u.i)) != -1)) - VIMM(code, r0); - else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), u.i); - VMOV_S_A(r0, rn(reg)); - jit_unget_reg(reg); - } + union { + int32_t i; + jit_float32_t f; + } u; + int32_t reg; + int32_t code; + u.f = i0; + if (jit_fpr_p(r0)) { + /* float arguments are packed, for others, + * lightning only address even registers */ + if (!(r0 & 1) && (r0 - 16) >= 0 && + ((code = encode_vfp_double(1, 0, u.i, u.i)) != -1 || + (code = encode_vfp_double(1, 1, ~u.i, ~u.i)) != -1)) + VIMM(code, r0); + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), u.i); + VMOV_S_A(r0, rn(reg)); + jit_unget_reg(reg); } - else - movi(r0, u.i); + } + else + movi(r0, u.i); } static void _vfp_movi_d(jit_state_t *_jit, int32_t r0, jit_float64_t i0) { - union { - int32_t i[2]; - jit_float64_t d; - } u; - int32_t code; - int32_t rg0, rg1; - u.d = i0; - if (jit_fpr_p(r0)) { - if ((code = encode_vfp_double(1, 0, u.i[0], u.i[1])) != -1 || - (code = encode_vfp_double(1, 1, ~u.i[0], ~u.i[1])) != -1) - VIMM(code, r0); - else { - rg0 = jit_get_reg(jit_class_gpr); - rg1 = jit_get_reg(jit_class_gpr); - movi(rn(rg0), u.i[0]); - movi(rn(rg1), u.i[1]); - VMOV_D_AA(r0, rn(rg0), rn(rg1)); - jit_unget_reg(rg1); - jit_unget_reg(rg0); - } - } + union { + int32_t i[2]; + jit_float64_t d; + } u; + int32_t code; + int32_t rg0, rg1; + u.d = i0; + if (jit_fpr_p(r0)) { + if ((code = encode_vfp_double(1, 0, u.i[0], u.i[1])) != -1 || + (code = encode_vfp_double(1, 1, ~u.i[0], ~u.i[1])) != -1) + VIMM(code, r0); else { - movi(r0, u.i[0]); - movi(r0 + 1, u.i[1]); + rg0 = jit_get_reg(jit_class_gpr); + rg1 = jit_get_reg(jit_class_gpr); + movi(rn(rg0), u.i[0]); + movi(rn(rg1), u.i[1]); + VMOV_D_AA(r0, rn(rg0), rn(rg1)); + jit_unget_reg(rg1); + jit_unget_reg(rg0); } + } + else { + movi(r0, u.i[0]); + movi(r0 + 1, u.i[1]); + } } static void _vfp_extr_d_f(jit_state_t *_jit, int32_t r0, int32_t r1) { - int32_t reg; - if (jit_fpr_p(r1)) { - if (jit_fpr_p(r0)) - VCVT_F64_F32(r0, r1); - else { - reg = jit_get_reg(jit_class_fpr); - VCVT_F64_F32(rn(reg), r1); - VMOV_A_S(r0, rn(reg)); - jit_unget_reg(reg); - } - } + int32_t reg; + if (jit_fpr_p(r1)) { + if (jit_fpr_p(r0)) + VCVT_F64_F32(r0, r1); else { - reg = jit_get_reg(jit_class_fpr); - VMOV_S_A(rn(reg), r1); - VCVT_F64_F32(rn(reg), rn(reg)); - if (jit_fpr_p(r0)) - VMOV_F32(r0, rn(reg)); - else - VMOV_A_S(r0, rn(reg)); - jit_unget_reg(reg); + reg = jit_get_reg(jit_class_fpr); + VCVT_F64_F32(rn(reg), r1); + VMOV_A_S(r0, rn(reg)); + jit_unget_reg(reg); } + } + else { + reg = jit_get_reg(jit_class_fpr); + VMOV_S_A(rn(reg), r1); + VCVT_F64_F32(rn(reg), rn(reg)); + if (jit_fpr_p(r0)) + VMOV_F32(r0, rn(reg)); + else + VMOV_A_S(r0, rn(reg)); + jit_unget_reg(reg); + } } static void _vfp_extr_f_d(jit_state_t *_jit, int32_t r0, int32_t r1) { - int32_t reg; - if (jit_fpr_p(r1)) { - if (jit_fpr_p(r0)) - VCVT_F32_F64(r0, r1); - else { - reg = jit_get_reg(jit_class_fpr); - VCVT_F32_F64(rn(reg), r1); - VMOV_AA_D(r0, r0 + 1, rn(reg)); - jit_unget_reg(reg); - } - } + int32_t reg; + if (jit_fpr_p(r1)) { + if (jit_fpr_p(r0)) + VCVT_F32_F64(r0, r1); else { - reg = jit_get_reg(jit_class_fpr); - VMOV_D_AA(rn(reg), r1, r1 + 1); - VCVT_F32_F64(rn(reg), rn(reg)); - if (jit_fpr_p(r0)) - VMOV_F64(r0, rn(reg)); - else - VMOV_AA_D(r0, r0 + 1, rn(reg)); - jit_unget_reg(reg); + reg = jit_get_reg(jit_class_fpr); + VCVT_F32_F64(rn(reg), r1); + VMOV_AA_D(r0, r0 + 1, rn(reg)); + jit_unget_reg(reg); } + } + else { + reg = jit_get_reg(jit_class_fpr); + VMOV_D_AA(rn(reg), r1, r1 + 1); + VCVT_F32_F64(rn(reg), rn(reg)); + if (jit_fpr_p(r0)) + VMOV_F64(r0, rn(reg)); + else + VMOV_AA_D(r0, r0 + 1, rn(reg)); + jit_unget_reg(reg); + } } static void _vfp_extr_f(jit_state_t *_jit, int32_t r0, int32_t r1) { - int32_t reg; - if (jit_fpr_p(r0)) { - VMOV_V_I32(r0, r1); - VCVT_F32_S32(r0, r0); - } - else { - reg = jit_get_reg(jit_class_fpr); - VMOV_V_I32(rn(reg), r1); - VCVT_F32_S32(rn(reg), rn(reg)); - VMOV_F32(r0, rn(reg)); - jit_unget_reg(reg); - } + int32_t reg; + if (jit_fpr_p(r0)) { + VMOV_V_I32(r0, r1); + VCVT_F32_S32(r0, r0); + } + else { + reg = jit_get_reg(jit_class_fpr); + VMOV_V_I32(rn(reg), r1); + VCVT_F32_S32(rn(reg), rn(reg)); + VMOV_F32(r0, rn(reg)); + jit_unget_reg(reg); + } } static void _vfp_extr_d(jit_state_t *_jit, int32_t r0, int32_t r1) { - int32_t reg; - if (jit_fpr_p(r0)) { - VMOV_V_I32(r0, r1); - VCVT_F64_S32(r0, r0); - } - else { - reg = jit_get_reg(jit_class_fpr); - VMOV_V_I32(rn(reg), r1); - VCVT_F64_S32(rn(reg), rn(reg)); - VMOV_F64(r0, rn(reg)); - jit_unget_reg(reg); - } + int32_t reg; + if (jit_fpr_p(r0)) { + VMOV_V_I32(r0, r1); + VCVT_F64_S32(r0, r0); + } + else { + reg = jit_get_reg(jit_class_fpr); + VMOV_V_I32(rn(reg), r1); + VCVT_F64_S32(rn(reg), rn(reg)); + VMOV_F64(r0, rn(reg)); + jit_unget_reg(reg); + } } static void _vfp_truncr_f_i(jit_state_t *_jit, int32_t r0, int32_t r1) { - int32_t reg; - reg = jit_get_reg(jit_class_fpr); - if (jit_fpr_p(r1)) - VCVT_S32_F32(rn(reg), r1); - else { - VMOV_V_I32(rn(reg), r1); - VCVT_S32_F32(rn(reg), rn(reg)); - } - VMOV_A_S32(r0, rn(reg)); - jit_unget_reg(reg); + int32_t reg; + reg = jit_get_reg(jit_class_fpr); + if (jit_fpr_p(r1)) + VCVT_S32_F32(rn(reg), r1); + else { + VMOV_V_I32(rn(reg), r1); + VCVT_S32_F32(rn(reg), rn(reg)); + } + VMOV_A_S32(r0, rn(reg)); + jit_unget_reg(reg); } static void _vfp_truncr_d_i(jit_state_t *_jit, int32_t r0, int32_t r1) { - int32_t reg; - reg = jit_get_reg(jit_class_fpr); - if (jit_fpr_p(r1)) - VCVT_S32_F64(rn(reg), r1); - else { - VMOV_V_I32(rn(reg), r1); - VCVT_S32_F64(rn(reg), rn(reg)); - } - VMOV_A_S32(r0, rn(reg)); - jit_unget_reg(reg); + int32_t reg; + reg = jit_get_reg(jit_class_fpr); + if (jit_fpr_p(r1)) + VCVT_S32_F64(rn(reg), r1); + else { + VMOV_V_I32(rn(reg), r1); + VCVT_S32_F64(rn(reg), rn(reg)); + } + VMOV_A_S32(r0, rn(reg)); + jit_unget_reg(reg); } static void _vfp_cmp_f(jit_state_t *_jit, int32_t r0, int32_t r1) { - int32_t rg0, rg1; - if (jit_fpr_p(r0)) { - if (jit_fpr_p(r1)) - VCMP_F32(r0, r1); - else { - rg1 = jit_get_reg(jit_class_fpr); - VMOV_S_A(rn(rg1), r1); - VCMP_F32(r0, rn(rg1)); - jit_unget_reg(rg1); - } - } + int32_t rg0, rg1; + if (jit_fpr_p(r0)) { + if (jit_fpr_p(r1)) + VCMP_F32(r0, r1); else { - rg0 = jit_get_reg(jit_class_fpr); - VMOV_S_A(rn(rg0), r0); - if (jit_fpr_p(r1)) - VCMP_F32(rn(rg0), r1); - else { - rg1 = jit_get_reg(jit_class_fpr); - VMOV_S_A(rn(rg1), r1); - VCMP_F32(rn(rg0), rn(rg1)); - jit_unget_reg(rg1); - } - jit_unget_reg(rg0); + rg1 = jit_get_reg(jit_class_fpr); + VMOV_S_A(rn(rg1), r1); + VCMP_F32(r0, rn(rg1)); + jit_unget_reg(rg1); } + } + else { + rg0 = jit_get_reg(jit_class_fpr); + VMOV_S_A(rn(rg0), r0); + if (jit_fpr_p(r1)) + VCMP_F32(rn(rg0), r1); + else { + rg1 = jit_get_reg(jit_class_fpr); + VMOV_S_A(rn(rg1), r1); + VCMP_F32(rn(rg0), rn(rg1)); + jit_unget_reg(rg1); + } + jit_unget_reg(rg0); + } } static void _vfp_cmp_d(jit_state_t *_jit, int32_t r0, int32_t r1) { - int32_t rg0, rg1; - if (jit_fpr_p(r0)) { - if (jit_fpr_p(r1)) - VCMP_F64(r0, r1); - else { - rg1 = jit_get_reg(jit_class_fpr); - VMOV_D_AA(rn(rg1), r1, r1 + 1); - VCMP_F64(r0, rn(rg1)); - jit_unget_reg(rg1); - } - } + int32_t rg0, rg1; + if (jit_fpr_p(r0)) { + if (jit_fpr_p(r1)) + VCMP_F64(r0, r1); else { - rg0 = jit_get_reg(jit_class_fpr); - VMOV_D_AA(rn(rg0), r0, r0 + 1); - if (jit_fpr_p(r1)) - VCMP_F64(rn(rg0), r1); - else { - rg1 = jit_get_reg(jit_class_fpr); - VMOV_D_AA(rn(rg1), r1, r1 + 1); - VCMP_F64(rn(rg0), rn(rg1)); - jit_unget_reg(rg1); - } - jit_unget_reg(rg0); + rg1 = jit_get_reg(jit_class_fpr); + VMOV_D_AA(rn(rg1), r1, r1 + 1); + VCMP_F64(r0, rn(rg1)); + jit_unget_reg(rg1); } + } + else { + rg0 = jit_get_reg(jit_class_fpr); + VMOV_D_AA(rn(rg0), r0, r0 + 1); + if (jit_fpr_p(r1)) + VCMP_F64(rn(rg0), r1); + else { + rg1 = jit_get_reg(jit_class_fpr); + VMOV_D_AA(rn(rg1), r1, r1 + 1); + VCMP_F64(rn(rg0), rn(rg1)); + jit_unget_reg(rg1); + } + jit_unget_reg(rg0); + } } static jit_word_t _vbcmp_x(jit_state_t *_jit, int cc, jit_word_t i0) { - jit_word_t d, w; - VMRS(_R15_REGNO); - w = _jit->pc.w; - if (jit_thumb_p()) { - d = ((i0 - w) >> 1) - 2; - assert(_s20P(d)); - T2_CC_B(cc, encode_thumb_cc_jump(d)); - } - else { - d = ((i0 - w) >> 2) - 2; - assert(_s24P(d)); - CC_B(cc, d & 0x00ffffff); - } - return (w); + jit_word_t d, w; + VMRS(_R15_REGNO); + w = _jit->pc.w; + + d = ((i0 - w) >> 1) - 2; + assert(_s20P(d)); + T2_CC_B(cc, encode_thumb_cc_jump(d)); + + return (w); } static jit_word_t _vbcmp_f(jit_state_t *_jit, int cc, - jit_word_t i0, int32_t r0, int32_t r1) + jit_word_t i0, int32_t r0, int32_t r1) { - vfp_cmp_f(r0, r1); - return (vbcmp_x(cc, i0)); + vfp_cmp_f(r0, r1); + return (vbcmp_x(cc, i0)); } static jit_word_t _vbcmp_d(jit_state_t *_jit, int cc, - jit_word_t i0, int32_t r0, int32_t r1) + jit_word_t i0, int32_t r0, int32_t r1) { - vfp_cmp_d(r0, r1); - return (vbcmp_x(cc, i0)); + vfp_cmp_d(r0, r1); + return (vbcmp_x(cc, i0)); } static jit_word_t _vbncmp_x(jit_state_t *_jit, int cc, jit_word_t i0) { - jit_word_t d, p, w; - VMRS(_R15_REGNO); - p = _jit->pc.w; - if (jit_thumb_p()) { - T2_CC_B(cc, 0); - w = _jit->pc.w; - d = ((i0 - w) >> 1) - 2; - assert(_s20P(d)); - T2_B(encode_thumb_jump(d)); - } - else { - CC_B(cc, 0); - w = _jit->pc.w; - d = ((i0 - w) >> 2) - 2; - assert(_s24P(d)); - B(d & 0x00ffffff); - } - patch_at(arm_patch_jump, p, _jit->pc.w); - return (w); + jit_word_t d, p, w; + VMRS(_R15_REGNO); + p = _jit->pc.w; + + T2_CC_B(cc, 0); + w = _jit->pc.w; + d = ((i0 - w) >> 1) - 2; + assert(_s20P(d)); + T2_B(encode_thumb_jump(d)); + + patch_at(arm_patch_jump, p, _jit->pc.w); + return (w); } static jit_word_t _vbncmp_f(jit_state_t *_jit, int cc, - jit_word_t i0, int32_t r0, int32_t r1) + jit_word_t i0, int32_t r0, int32_t r1) { - vfp_cmp_f(r0, r1); - return (vbncmp_x(cc, i0)); + vfp_cmp_f(r0, r1); + return (vbncmp_x(cc, i0)); } static jit_word_t _vbncmp_d(jit_state_t *_jit, int cc, - jit_word_t i0, int32_t r0, int32_t r1) + jit_word_t i0, int32_t r0, int32_t r1) { - vfp_cmp_d(r0, r1); - return (vbncmp_x(cc, i0)); + vfp_cmp_d(r0, r1); + return (vbncmp_x(cc, i0)); } static jit_word_t _vfp_buneqr_x(jit_state_t *_jit, jit_word_t i0) { - jit_word_t d, p, q, w; - VMRS(_R15_REGNO); - p = _jit->pc.w; - if (jit_thumb_p()) { - T2_CC_B(ARM_CC_VS, 0); - q = _jit->pc.w; - T2_CC_B(ARM_CC_NE, 0); - patch_at(arm_patch_jump, p, _jit->pc.w); - w = _jit->pc.w; - d = ((i0 - w) >> 1) - 2; - assert(_s20P(d)); - T2_B(encode_thumb_jump(d)); - } - else { - CC_B(ARM_CC_VS, 0); - q = _jit->pc.w; - CC_B(ARM_CC_NE, 0); - patch_at(arm_patch_jump, p, _jit->pc.w); - w = _jit->pc.w; - d = ((i0 - w) >> 2) - 2; - assert(_s24P(d)); - B(d & 0x00ffffff); - } - patch_at(arm_patch_jump, q, _jit->pc.w); - return (w); + jit_word_t d, p, q, w; + VMRS(_R15_REGNO); + p = _jit->pc.w; + + T2_CC_B(ARM_CC_VS, 0); + q = _jit->pc.w; + T2_CC_B(ARM_CC_NE, 0); + patch_at(arm_patch_jump, p, _jit->pc.w); + w = _jit->pc.w; + d = ((i0 - w) >> 1) - 2; + assert(_s20P(d)); + T2_B(encode_thumb_jump(d)); + + patch_at(arm_patch_jump, q, _jit->pc.w); + return (w); } static jit_word_t _vfp_buneqr_f(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) { - vfp_cmp_f(r0, r1); - return (vfp_buneqr_x(i0)); + vfp_cmp_f(r0, r1); + return (vfp_buneqr_x(i0)); } static jit_word_t _vfp_buneqr_d(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) { - vfp_cmp_d(r0, r1); - return (vfp_buneqr_x(i0)); + vfp_cmp_d(r0, r1); + return (vfp_buneqr_x(i0)); } static jit_word_t _vfp_bunger_x(jit_state_t *_jit, jit_word_t i0) { - jit_word_t d, p, w; - VMRS(_R15_REGNO); - p = _jit->pc.w; - if (jit_thumb_p()) { - T2_CC_B(ARM_CC_MI, 0); - w = _jit->pc.w; - d = ((i0 - w) >> 1) - 2; - assert(_s20P(d)); - T2_CC_B(ARM_CC_HS, encode_thumb_cc_jump(d)); - } - else { - CC_B(ARM_CC_MI, 0); - w = _jit->pc.w; - d = ((i0 - w) >> 2) - 2; - assert(_s24P(d)); - CC_B(ARM_CC_HS, d & 0x00ffffff); - } - patch_at(arm_patch_jump, p, _jit->pc.w); - return (w); + jit_word_t d, p, w; + VMRS(_R15_REGNO); + p = _jit->pc.w; + + T2_CC_B(ARM_CC_MI, 0); + w = _jit->pc.w; + d = ((i0 - w) >> 1) - 2; + assert(_s20P(d)); + T2_CC_B(ARM_CC_HS, encode_thumb_cc_jump(d)); + + patch_at(arm_patch_jump, p, _jit->pc.w); + return (w); } static jit_word_t _vfp_bunger_f(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) { - vfp_cmp_f(r0, r1); - return (vfp_bunger_x(i0)); + vfp_cmp_f(r0, r1); + return (vfp_bunger_x(i0)); } static jit_word_t _vfp_bunger_d(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) { - vfp_cmp_d(r0, r1); - return (vfp_bunger_x(i0)); + vfp_cmp_d(r0, r1); + return (vfp_bunger_x(i0)); } static jit_word_t _vfp_bltgtr_x(jit_state_t *_jit, jit_word_t i0) { - jit_word_t d, p, q, w; - VMRS(_R15_REGNO); - p = _jit->pc.w; - if (jit_thumb_p()) { - T2_CC_B(ARM_CC_VS, 0); - q = _jit->pc.w; - T2_CC_B(ARM_CC_EQ, 0); - w = _jit->pc.w; - d = ((i0 - w) >> 1) - 2; - assert(_s20P(d)); - T2_B(encode_thumb_jump(d)); - } - else { - CC_B(ARM_CC_VS, 0); - q = _jit->pc.w; - CC_B(ARM_CC_EQ, 0); - w = _jit->pc.w; - d = ((i0 - w) >> 2) - 2; - assert(_s24P(d)); - B(d & 0x00ffffff); - } - patch_at(arm_patch_jump, p, _jit->pc.w); - patch_at(arm_patch_jump, q, _jit->pc.w); - return (w); + jit_word_t d, p, q, w; + VMRS(_R15_REGNO); + p = _jit->pc.w; + + T2_CC_B(ARM_CC_VS, 0); + q = _jit->pc.w; + T2_CC_B(ARM_CC_EQ, 0); + w = _jit->pc.w; + d = ((i0 - w) >> 1) - 2; + assert(_s20P(d)); + T2_B(encode_thumb_jump(d)); + + patch_at(arm_patch_jump, p, _jit->pc.w); + patch_at(arm_patch_jump, q, _jit->pc.w); + return (w); } static jit_word_t _vfp_bltgtr_f(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) { - vfp_cmp_f(r0, r1); - return (vfp_bltgtr_x(i0)); + vfp_cmp_f(r0, r1); + return (vfp_bltgtr_x(i0)); } static jit_word_t _vfp_bltgtr_d(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) { - vfp_cmp_d(r0, r1); - return (vfp_bltgtr_x(i0)); + vfp_cmp_d(r0, r1); + return (vfp_bltgtr_x(i0)); } static void _vfp_ldi_f(jit_state_t *_jit, int32_t r0, jit_word_t i0) { - int32_t gpr; - if (jit_fpr_p(r0)) { - gpr = jit_get_reg(jit_class_gpr); - movi(rn(gpr), i0); - VLDR_F32(r0, rn(gpr), 0); - jit_unget_reg(gpr); - } - else - ldi_i(r0, i0); + int32_t gpr; + if (jit_fpr_p(r0)) { + gpr = jit_get_reg(jit_class_gpr); + movi(rn(gpr), i0); + VLDR_F32(r0, rn(gpr), 0); + jit_unget_reg(gpr); + } + else + ldi_i(r0, i0); } static void _vfp_ldi_d(jit_state_t *_jit, int32_t r0, jit_word_t i0) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - if (jit_fpr_p(r0)) - VLDR_F64(r0, rn(reg), 0); - else { - ldr_i(r0, rn(reg)); - ldxi_i(r0 + 1, rn(reg), 4); - } - jit_unget_reg(reg); + int32_t reg; + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + if (jit_fpr_p(r0)) + VLDR_F64(r0, rn(reg), 0); + else { + ldr_i(r0, rn(reg)); + ldxi_i(r0 + 1, rn(reg), 4); + } + jit_unget_reg(reg); } static void _vfp_ldxr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - int32_t reg; - if (jit_fpr_p(r0)) { - reg = jit_get_reg(jit_class_gpr); - addr(rn(reg), r1, r2); - VLDR_F32(r0, rn(reg), 0); - jit_unget_reg(reg); - } - else - ldxr_i(r0, r1, r2); + int32_t reg; + if (jit_fpr_p(r0)) { + reg = jit_get_reg(jit_class_gpr); + addr(rn(reg), r1, r2); + VLDR_F32(r0, rn(reg), 0); + jit_unget_reg(reg); + } + else + ldxr_i(r0, r1, r2); } static void _vfp_ldxr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - addr(rn(reg), r1, r2); - if (jit_fpr_p(r0)) - VLDR_F64(r0, rn(reg), 0); - else { - ldr_i(r0, rn(reg)); - ldxi_i(r0 + 1, rn(reg), 4); - } - jit_unget_reg(reg); + int32_t reg; + reg = jit_get_reg(jit_class_gpr); + addr(rn(reg), r1, r2); + if (jit_fpr_p(r0)) + VLDR_F64(r0, rn(reg), 0); + else { + ldr_i(r0, rn(reg)); + ldxi_i(r0 + 1, rn(reg), 4); + } + jit_unget_reg(reg); } static void _vfp_ldxi_f(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - int32_t reg; - if (jit_fpr_p(r0)) { - if (i0 >= 0) { - assert(!(i0 & 3)); - if (i0 < 1024) - VLDR_F32(r0, r1, i0 >> 2); - else { - reg = jit_get_reg(jit_class_gpr); - addi(rn(reg), r1, i0); - VLDR_F32(r0, rn(reg), 0); - jit_unget_reg(reg); - } - } - else { - i0 = -i0; - assert(!(i0 & 3)); - if (i0 < 1024) - VLDRN_F32(r0, r1, i0 >> 2); - else { - reg = jit_get_reg(jit_class_gpr); - subi(rn(reg), r1, i0); - VLDR_F32(r0, rn(reg), 0); - jit_unget_reg(reg); - } - } + int32_t reg; + if (jit_fpr_p(r0)) { + if (i0 >= 0) { + assert(!(i0 & 3)); + if (i0 < 1024) + VLDR_F32(r0, r1, i0 >> 2); + else { + reg = jit_get_reg(jit_class_gpr); + addi(rn(reg), r1, i0); + VLDR_F32(r0, rn(reg), 0); + jit_unget_reg(reg); + } } - else - ldxi_i(r0, r1, i0); + else { + i0 = -i0; + assert(!(i0 & 3)); + if (i0 < 1024) + VLDRN_F32(r0, r1, i0 >> 2); + else { + reg = jit_get_reg(jit_class_gpr); + subi(rn(reg), r1, i0); + VLDR_F32(r0, rn(reg), 0); + jit_unget_reg(reg); + } + } + } + else + ldxi_i(r0, r1, i0); } static void _vfp_ldxi_d(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - int32_t reg; - if (jit_fpr_p(r0)) { - if (i0 >= 0) { - assert(!(i0 & 3)); - if (i0 < 1024) - VLDR_F64(r0, r1, i0 >> 2); - else { - reg = jit_get_reg(jit_class_gpr); - addi(rn(reg), r1, i0); - VLDR_F64(r0, rn(reg), 0); - jit_unget_reg(reg); - } - } - else { - i0 = -i0; - assert(!(i0 & 3)); - if (i0 < 1024) - VLDRN_F64(r0, r1, i0 >> 2); - else { - reg = jit_get_reg(jit_class_gpr); - subi(rn(reg), r1, i0); - VLDR_F64(r0, rn(reg), 0); - jit_unget_reg(reg); - } - } + int32_t reg; + if (jit_fpr_p(r0)) { + if (i0 >= 0) { + assert(!(i0 & 3)); + if (i0 < 1024) + VLDR_F64(r0, r1, i0 >> 2); + else { + reg = jit_get_reg(jit_class_gpr); + addi(rn(reg), r1, i0); + VLDR_F64(r0, rn(reg), 0); + jit_unget_reg(reg); + } } else { - reg = jit_get_reg(jit_class_gpr); - addi(rn(reg), r1, i0); - ldr_i(r0, rn(reg)); - ldxi_i(r0 + 1, rn(reg), 4); - jit_unget_reg(reg); + i0 = -i0; + assert(!(i0 & 3)); + if (i0 < 1024) + VLDRN_F64(r0, r1, i0 >> 2); + else { + reg = jit_get_reg(jit_class_gpr); + subi(rn(reg), r1, i0); + VLDR_F64(r0, rn(reg), 0); + jit_unget_reg(reg); + } } + } + else { + reg = jit_get_reg(jit_class_gpr); + addi(rn(reg), r1, i0); + ldr_i(r0, rn(reg)); + ldxi_i(r0 + 1, rn(reg), 4); + jit_unget_reg(reg); + } } static void _vfp_sti_f(jit_state_t *_jit, jit_word_t i0, int32_t r0) { - int32_t reg; - if (jit_fpr_p(r0)) { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - VSTR_F32(r0, rn(reg), 0); - jit_unget_reg(reg); - } - else - sti_i(i0, r0); + int32_t reg; + if (jit_fpr_p(r0)) { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + VSTR_F32(r0, rn(reg), 0); + jit_unget_reg(reg); + } + else + sti_i(i0, r0); } static void _vfp_sti_d(jit_state_t *_jit, jit_word_t i0, int32_t r0) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - if (jit_fpr_p(r0)) - VSTR_F64(r0, rn(reg), 0); - else { - str_i(rn(reg), r0); - stxi_i(4, rn(reg), r0 + 1); - } - jit_unget_reg(reg); + int32_t reg; + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + if (jit_fpr_p(r0)) + VSTR_F64(r0, rn(reg), 0); + else { + str_i(rn(reg), r0); + stxi_i(4, rn(reg), r0 + 1); + } + jit_unget_reg(reg); } static void _vfp_stxr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - int32_t reg; - if (jit_fpr_p(r2)) { - reg = jit_get_reg(jit_class_gpr); - addr(rn(reg), r0, r1); - VSTR_F32(r2, rn(reg), 0); - jit_unget_reg(reg); - } - else - stxr_i(r0, r1, r2); + int32_t reg; + if (jit_fpr_p(r2)) { + reg = jit_get_reg(jit_class_gpr); + addr(rn(reg), r0, r1); + VSTR_F32(r2, rn(reg), 0); + jit_unget_reg(reg); + } + else + stxr_i(r0, r1, r2); } static void _vfp_stxr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - addr(rn(reg), r0, r1); - if (jit_fpr_p(r2)) - VSTR_F64(r2, rn(reg), 0); - else { - str_i(rn(reg), r2); - stxi_i(4, rn(reg), r2 + 1); - } - jit_unget_reg(reg); + int32_t reg; + reg = jit_get_reg(jit_class_gpr); + addr(rn(reg), r0, r1); + if (jit_fpr_p(r2)) + VSTR_F64(r2, rn(reg), 0); + else { + str_i(rn(reg), r2); + stxi_i(4, rn(reg), r2 + 1); + } + jit_unget_reg(reg); } static void _vfp_stxi_f(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) { - int32_t reg; - if (jit_fpr_p(r1)) { - if (i0 >= 0) { - assert(!(i0 & 3)); - if (i0 < 1024) - VSTR_F32(r1, r0, i0 >> 2); - else { - reg = jit_get_reg(jit_class_gpr); - addi(rn(reg), r0, i0); - VSTR_F32(r1, rn(reg), 0); - jit_unget_reg(reg); - } - } - else { - i0 = -i0; - assert(!(i0 & 3)); - if (i0 < 1024) - VSTRN_F32(r1, r0, i0 >> 2); - else { - reg = jit_get_reg(jit_class_gpr); - subi(rn(reg), r0, i0); - VSTR_F32(r1, rn(reg), 0); - jit_unget_reg(reg); - } - } + int32_t reg; + if (jit_fpr_p(r1)) { + if (i0 >= 0) { + assert(!(i0 & 3)); + if (i0 < 1024) + VSTR_F32(r1, r0, i0 >> 2); + else { + reg = jit_get_reg(jit_class_gpr); + addi(rn(reg), r0, i0); + VSTR_F32(r1, rn(reg), 0); + jit_unget_reg(reg); + } } - else - stxi_i(i0, r0, r1); + else { + i0 = -i0; + assert(!(i0 & 3)); + if (i0 < 1024) + VSTRN_F32(r1, r0, i0 >> 2); + else { + reg = jit_get_reg(jit_class_gpr); + subi(rn(reg), r0, i0); + VSTR_F32(r1, rn(reg), 0); + jit_unget_reg(reg); + } + } + } + else + stxi_i(i0, r0, r1); } static void _vfp_stxi_d(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) { - int32_t reg; - if (jit_fpr_p(r1)) { - if (i0 >= 0) { - assert(!(i0 & 3)); - if (i0 < 0124) - VSTR_F64(r1, r0, i0 >> 2); - else { - reg = jit_get_reg(jit_class_gpr); - addi(rn(reg), r0, i0); - VSTR_F64(r1, rn(reg), 0); - jit_unget_reg(reg); - } - } - else { - i0 = -i0; - assert(!(i0 & 3)); - if (i0 < 1024) - VSTRN_F64(r1, r0, i0 >> 2); - else { - reg = jit_get_reg(jit_class_gpr); - subi(rn(reg), r0, i0); - VSTR_F64(r1, rn(reg), 0); - jit_unget_reg(reg); - } - } + int32_t reg; + if (jit_fpr_p(r1)) { + if (i0 >= 0) { + assert(!(i0 & 3)); + if (i0 < 0124) + VSTR_F64(r1, r0, i0 >> 2); + else { + reg = jit_get_reg(jit_class_gpr); + addi(rn(reg), r0, i0); + VSTR_F64(r1, rn(reg), 0); + jit_unget_reg(reg); + } } else { - reg = jit_get_reg(jit_class_gpr); - addi(rn(reg), r0, i0); - str_i(rn(reg), r1); - stxi_i(4, rn(reg), r1 + 1); - jit_unget_reg(reg); + i0 = -i0; + assert(!(i0 & 3)); + if (i0 < 1024) + VSTRN_F64(r1, r0, i0 >> 2); + else { + reg = jit_get_reg(jit_class_gpr); + subi(rn(reg), r0, i0); + VSTR_F64(r1, rn(reg), 0); + jit_unget_reg(reg); + } } + } + else { + reg = jit_get_reg(jit_class_gpr); + addi(rn(reg), r0, i0); + str_i(rn(reg), r1); + stxi_i(4, rn(reg), r1 + 1); + jit_unget_reg(reg); + } } static void _vfp_vaarg_d(jit_state_t *_jit, int32_t r0, int32_t r1) { - int32_t reg; + int32_t reg; - assert(_jitc->function->self.call & jit_call_varargs); + assert(_jitc->function->self.call & jit_call_varargs); - /* Adjust pointer. */ - reg = jit_get_reg(jit_class_gpr); - andi(rn(reg), r1, 7); - addr(r1, r1, rn(reg)); - jit_unget_reg(reg); + /* Adjust pointer. */ + reg = jit_get_reg(jit_class_gpr); + andi(rn(reg), r1, 7); + addr(r1, r1, rn(reg)); + jit_unget_reg(reg); - /* Load argument. */ - vfp_ldr_d(r0, r1); + /* Load argument. */ + vfp_ldr_d(r0, r1); - /* Update stack pointer. */ - addi(r1, r1, sizeof(jit_float64_t)); + /* Update stack pointer. */ + addi(r1, r1, sizeof(jit_float64_t)); } From 7dd18bddd7ec28ee4c6e1591c9ab56ceb594f5f2 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Mon, 20 May 2019 11:02:21 +0200 Subject: [PATCH 28/33] ARMv7 backend compiling without warnings --- lightening/arm-cpu.c | 214 ++++--- lightening/arm-vfp.c | 1309 ++++++++++++++------------------------- lightening/arm.h | 14 +- lightening/lightening.c | 4 +- 4 files changed, 606 insertions(+), 935 deletions(-) diff --git a/lightening/arm-cpu.c b/lightening/arm-cpu.c index 44988976e..012b73ae8 100644 --- a/lightening/arm-cpu.c +++ b/lightening/arm-cpu.c @@ -32,6 +32,7 @@ #define ARM_CC_NE 0x10000000 /* Z=0 */ #define ARM_CC_HS 0x20000000 /* C=1 */ #define ARM_CC_LO 0x30000000 /* C=0 */ +#define ARM_CC_MI 0x40000000 /* N=1 */ #define ARM_CC_VS 0x60000000 /* V=1 */ #define ARM_CC_VC 0x70000000 /* V=0 */ #define ARM_CC_HI 0x80000000 /* C=1 && Z=0 */ @@ -241,8 +242,23 @@ encode_thumb_word_immediate(unsigned int v) return (-1); } +static uint32_t +read_wide_thumb(uint32_t *loc) +{ + uint16_t *sloc = (uint16_t*)sloc; + return (((uint32_t)sloc[0]) << 16) | sloc[1]; +} + +static void +write_wide_thumb(uint32_t *loc, uint32_t v) +{ + uint16_t *sloc = (uint16_t *)loc; + sloc[0] = v >> 16; + sloc[1] = v & 0xffff; +} + static int -offset_in_thumb_jump_range(int32_t offset) +offset_in_jmp_range(int32_t offset) { return -0x800000 <= offset && offset <= 0x7fffff; } @@ -272,7 +288,7 @@ static const uint32_t thumb_jump_mask = 0xf800d000; static uint32_t encode_thumb_jump(int32_t v) { - ASSERT(offset_in_thumb_jump_range(v)); + ASSERT(offset_in_jmp_range(v)); uint32_t s = !!(v & 0x800000); uint32_t i1 = !!(v & 0x400000); uint32_t i2 = !!(v & 0x200000); @@ -290,6 +306,18 @@ patch_thumb_jump(uint32_t inst, int32_t v) return (inst & thumb_jump_mask) | encode_thumb_jump(v); } +static int32_t +read_jmp_offset(uint32_t *loc) +{ + return decode_thumb_jump(read_wide_thumb(loc)); +} + +static void +patch_jmp_offset(uint32_t *loc, int32_t v) +{ + write_wide_thumb(loc, patch_thumb_jump(read_wide_thumb(loc), v)); +} + static jit_reloc_t emit_thumb_jump(jit_state_t *_jit, uint32_t inst) { @@ -305,7 +333,7 @@ emit_thumb_jump(jit_state_t *_jit, uint32_t inst) } static int -offset_in_thumb_cc_jump_range(int32_t v) +offset_in_jcc_range(int32_t v) { return -0x80000 <= v && v <= 0x7ffff; } @@ -335,7 +363,7 @@ static const uint32_t thumb_cc_jump_mask = 0xfbc0d000; static uint32_t encode_thumb_cc_jump(int32_t v) { - ASSERT(offset_in_thumb_cc_jump_range(v)); + ASSERT(offset_in_jcc_range(v)); uint32_t s = !!(v & 0x80000); uint32_t j1 = !!(v & 0x40000); uint32_t j2 = !!(v & 0x20000); @@ -351,6 +379,18 @@ patch_thumb_cc_jump(uint32_t inst, int32_t v) return (inst & thumb_cc_jump_mask) | encode_thumb_cc_jump(v); } +static int32_t +read_jcc_offset(uint32_t *loc) +{ + return decode_thumb_cc_jump(read_wide_thumb(loc)); +} + +static void +patch_jcc_offset(uint32_t *loc, int32_t v) +{ + write_wide_thumb(loc, patch_thumb_cc_jump(read_wide_thumb(loc), v)); +} + static jit_reloc_t emit_thumb_cc_jump(jit_state_t *_jit, uint32_t inst) { @@ -365,19 +405,6 @@ emit_thumb_cc_jump(jit_state_t *_jit, uint32_t inst) return ret; } -static int -encode_thumb_shift(int v, int type) -{ - switch (type) { - case ARM_ASR: - case ARM_LSL: - case ARM_LSR: type >>= 1; break; - default: assert(!"handled shift"); - } - assert(v >= 0 && v <= 31); - return (((v & 0x1c) << 10) | ((v & 3) << 6) | type); -} - static void torrr(jit_state_t *_jit, int o, int rn, int rd, int rm) { @@ -385,14 +412,6 @@ torrr(jit_state_t *_jit, int o, int rn, int rd, int rm) emit_wide_thumb(_jit, o|(_u4(rn)<<16)|(_u4(rd)<<8)|_u4(rm)); } -static void -torrrs(jit_state_t *_jit, int o, int rn, int rd, int rm, int im) -{ - assert(!(o & 0x000f0f0f)); - assert(!(im & 0xffff8f0f)); - emit_wide_thumb(_jit, o|(_u4(rn)<<16)|(_u4(rd)<<8)|im|_u4(rm)); -} - static void torxr(jit_state_t *_jit, int o, int rn, int rt, int rm) { @@ -407,14 +426,6 @@ torrrr(jit_state_t *_jit, int o, int rn, int rl, int rh, int rm) emit_wide_thumb(_jit, o|(_u4(rn)<<16)|(_u4(rl)<<12)|(_u4(rh)<<8)|_u4(rm)); } -static void -torrri8(jit_state_t *_jit, int o, int rn, int rt, int rt2, int im) -{ - assert(!(o & 0x000fffff)); - assert(!(im & 0xffffff00)); - emit_wide_thumb(_jit, o|(_u4(rn)<<16)|(_u4(rt)<<12)|(_u4(rt2)<<8)|im); -} - static void torri(jit_state_t *_jit, int o, int rn, int rd, int im) { @@ -454,22 +465,6 @@ toriw(jit_state_t *_jit, int o, int rd, int im) emit_wide_thumb(_jit, o|((im&0xf000)<<4)|((im&0x800)<<15)|((im&0x700)<<4)|(_u4(rd)<<8)|(im&0xff)); } -static void -tc8(jit_state_t *_jit, int cc, int im) -{ - assert(!(cc & 0x0fffffff)); - assert(cc != ARM_CC_AL && cc != ARM_CC_NV); - assert(im >= -128 && im <= 127); - emit_u16(_jit, THUMB_CC_B|(cc>>20)|(im&0xff)); -} - -static void -t11(jit_state_t *_jit, int im) -{ - assert(!(im & 0xfffff800)); - emit_u16(_jit, THUMB_B|im); -} - static jit_reloc_t tcb(jit_state_t *_jit, int cc) { @@ -486,25 +481,6 @@ tb(jit_state_t *_jit, int o) return emit_thumb_jump(_jit, o); } -static void -tpp(jit_state_t *_jit, int o, int im) -{ - assert(!(o & 0x0000ffff)); - if (o == THUMB2_PUSH) - assert(!(im & 0x8000)); - assert(__builtin_popcount(im & 0x1fff) > 1); - emit_wide_thumb(_jit, o|im); -} - -static void -torl(jit_state_t *_jit, int o, int rn, int im) -{ - assert(!(o & 0xf1fff)); - assert(rn != _NOREG || !im || ((o & 0xc000) == 0xc000)); - assert(!(o & THUMB2_LDM_W) || !(im & (1 << rn))); - emit_wide_thumb(_jit, o | (_u4(rn)<<16)|_u13(im)); -} - static void T1_ORR(jit_state_t *_jit, int32_t rdn, int32_t rm) { @@ -547,12 +523,6 @@ T1_MOV(jit_state_t *_jit, int32_t rd, int32_t rm) return emit_u16(_jit, THUMB_MOV|((_u4(rd)&8)<<4)|(_u4(rm)<<3)|(rd&7)); } -static void -T2_MOV(jit_state_t *_jit, int32_t rd, int32_t rm) -{ - return T2_ORR(_jit, rd,_NOREG,rm); -} - static void T1_MOVI(jit_state_t *_jit, int32_t rd, int32_t im) { @@ -1015,14 +985,8 @@ T2_TSTI(jit_state_t *_jit, int32_t rn, int32_t im) return torri(_jit, THUMB2_TSTI,rn,_NOREG,im); } -static void -T1_B(jit_state_t *_jit, int32_t im) -{ - return t11(_jit, im); -} - static jit_reloc_t -T2_CC_B(jit_state_t *_jit, uint8_t cc) +T2_CC_B(jit_state_t *_jit, uint32_t cc) { return tcb(_jit, cc); } @@ -1372,6 +1336,12 @@ movi(jit_state_t *_jit, int32_t r0, jit_word_t i0) return _movi(_jit, r0, i0, FLAGS_UNIMPORTANT); } +static int +offset_in_load_from_pool_range(int32_t offset) +{ + return -0xfff <= offset && offset <= 0xfff; +} + static int32_t decode_load_from_pool_offset(uint32_t inst) { @@ -1382,7 +1352,7 @@ decode_load_from_pool_offset(uint32_t inst) static uint32_t encode_load_from_pool_offset(int32_t off) { - ASSERT(-0xfff <= off && off <= 0xfff); + ASSERT(offset_in_load_from_pool_range(off)); uint32_t u; if (off >= 0) u = 1; @@ -1400,6 +1370,18 @@ patch_load_from_pool(uint32_t inst, int32_t off) return (inst & load_from_pool_mask) | encode_load_from_pool_offset(off); } +static int32_t +read_load_from_pool_offset(uint32_t *loc) +{ + return decode_load_from_pool_offset(read_wide_thumb(loc)); +} + +static void +patch_load_from_pool_offset(uint32_t *loc, int32_t v) +{ + write_wide_thumb(loc, patch_load_from_pool(read_wide_thumb(loc), v)); +} + static jit_reloc_t emit_load_from_pool(jit_state_t *_jit, uint32_t inst) { @@ -2632,7 +2614,7 @@ ldxi_i(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { if ((r0|r1) < 8 && i0 >= 0 && !(i0 & 3) && (i0 >> 2) < 0x20) T1_LDRI(_jit, r0, r1, i0 >> 2); - else if (r1 == jit_gpr_regno(_SP) && r0 < 8 && + else if (r1 == jit_gpr_regno(JIT_SP) && r0 < 8 && i0 >= 0 && !(i0 & 3) && (i0 >> 2) <= 255) T1_LDRISP(_jit, r0, i0 >> 2); else if (jit_ldrt_strt_p() && i0 >= 0 && i0 <= 255) @@ -2779,7 +2761,7 @@ stxi_i(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) { if ((r0|r1) < 8 && i0 >= 0 && !(i0 & 3) && (i0 >> 2) < 0x20) T1_STRI(_jit, r1, r0, i0 >> 2); - else if (r0 == jit_gpr_regno(_SP) && r1 < 8 && + else if (r0 == jit_gpr_regno(JIT_SP) && r1 < 8 && i0 >= 0 && !(i0 & 3) && (i0 >> 2) <= 255) T1_STRISP(_jit, r1, i0 >> 2); else if (jit_ldrt_strt_p() && i0 >= 0 && i0 <= 255) @@ -2870,6 +2852,70 @@ calli(jit_state_t *_jit, jit_word_t i0) jit_patch_there(_jit, T2_BLI(_jit), (void*)i0); } +static void +ret(jit_state_t *_jit) +{ + movr(_jit, jit_gpr_regno(_PC), jit_gpr_regno(_LR)); +} + +static void +reti(jit_state_t *_jit, int32_t i0) +{ + movi(_jit, jit_gpr_regno(_R0), i0); + ret(_jit); +} + +static void +retr(jit_state_t *_jit, int32_t r0) +{ + movr(_jit, jit_gpr_regno(_R0), r0); + ret(_jit); +} + +static void +retval_c(jit_state_t *_jit, int32_t r0) +{ + extr_c(_jit, r0, jit_gpr_regno(_R0)); +} + +static void +retval_uc(jit_state_t *_jit, int32_t r0) +{ + extr_uc(_jit, r0, jit_gpr_regno(_R0)); +} + +static void +retval_s(jit_state_t *_jit, int32_t r0) +{ + extr_s(_jit, r0, jit_gpr_regno(_R0)); +} + +static void +retval_us(jit_state_t *_jit, int32_t r0) +{ + extr_us(_jit, r0, jit_gpr_regno(_R0)); +} + +static void +retval_i(jit_state_t *_jit, int32_t r0) +{ + movr(_jit, r0, jit_gpr_regno(_R0)); +} + +struct veneer +{ + uint16_t ldr; + uint16_t br; + uint32_t addr; +}; + +static void +patch_veneer(uint32_t *loc, jit_pointer_t addr) +{ + struct veneer *v = (struct veneer*) v; + v->addr = (uintptr_t) addr; +} + static void emit_veneer(jit_state_t *_jit, jit_pointer_t target) { diff --git a/lightening/arm-vfp.c b/lightening/arm-vfp.c index 885f2db47..208edc316 100644 --- a/lightening/arm-vfp.c +++ b/lightening/arm-vfp.c @@ -17,9 +17,6 @@ * Paulo Cesar Pereira de Andrade */ -/* as per vfp_regno macro, required due to "support" to soft float registers - * or using integer registers as arguments to float operations */ -#define _D8_REGNO 32 #define ARM_V_F64 0x00000100 #define ARM_VADD_F 0x0e300a00 #define ARM_VSUB_F 0x0e300a40 @@ -31,7 +28,6 @@ #define ARM_VMOV_F 0x0eb00a40 #define ARM_VMOV_A_S 0x0e100a10 /* vmov rn, sn */ #define ARM_VMOV_S_A 0x0e000a10 /* vmov sn, rn */ -#define ARM_VMOV_AA_D 0x0c500b10 /* vmov rn,rn, dn */ #define ARM_VMOV_D_AA 0x0c400b10 /* vmov dn, rn,rn */ #define ARM_VCMP 0x0eb40a40 #define ARM_VMRS 0x0ef10a10 @@ -46,6 +42,7 @@ #define ARM_VCVT_F 0x0eb70ac0 #define ARM_VCVT_F32_F64 ARM_VCVT_F #define ARM_VCVT_F64_F32 ARM_VCVT_F|ARM_V_F64 +#define ARM_P 0x00800000 /* positive offset */ #define ARM_V_D 0x00400000 #define ARM_V_N 0x00000080 #define ARM_V_M 0x00000020 @@ -58,148 +55,81 @@ #define ARM_VMOV_A_D 0x0e100b10 #define ARM_VMOV_D_A 0x0e000b10 -#define vfp_regno(rn) (((rn) - 16) >> 1) +#define vfp_regno(rn) ((rn) >> 1) static void vodi(jit_state_t *_jit, int oi, int r0) { - jit_thumb_t thumb; - assert(!(oi & 0x0000f000)); - assert(!(r0 & 1)); r0 = vfp_regno(r0); - thumb.i = oi|(_u4(r0)<<12); - iss(thumb.s[0], thumb.s[1]); -} - -static void -_voqi(jit_state_t *_jit, int oi, int r0) -{ - jit_thumb_t thumb; - assert(!(oi & 0x0000f000)); - assert(!(r0 & 3)); r0 = vfp_regno(r0); - thumb.i = oi|(_u4(r0)<<12); - iss(thumb.s[0], thumb.s[1]); + ASSERT(!(oi & 0x0000f000)); + ASSERT(!(r0 & 1)); + r0 >>= 1; + emit_wide_thumb(_jit, oi|(_u4(r0)<<12)); } static void vo_ss(jit_state_t *_jit, int o, int r0, int r1) { - assert(!(o & 0xf000f00f)); - if (r0 & 1) o |= ARM_V_D; r0 = vfp_regno(r0); - if (r1 & 1) o |= ARM_V_M; r1 = vfp_regno(r1); + ASSERT(!(o & 0xf000f00f)); + if (r0 & 1) o |= ARM_V_D; + if (r1 & 1) o |= ARM_V_M; + r0 >>= 1; r1 >>= 1; emit_wide_thumb(_jit, ARM_CC_AL|o|(_u4(r0)<<12)|_u4(r1)); } static void vo_dd(jit_state_t *_jit, int o, int r0, int r1) { - assert(!(o & 0xf000f00f)); - assert(!(r0 & 1) && !(r1 & 1)); - r0 = vfp_regno(r0); r1 = vfp_regno(r1); + ASSERT(!(o & 0xf000f00f)); + ASSERT(!(r0 & 1) && !(r1 & 1)); + r0 >>= 1; r1 >>= 1; emit_wide_thumb(_jit, ARM_CC_AL|o|(_u4(r0)<<12)|_u4(r1)); } -static void -vo_qd(jit_state_t *_jit, int o, int r0, int r1) -{ - assert(!(o & 0xf000f00f)); - assert(!(r0 & 3) && !(r1 & 1)); - r0 = vfp_regno(r0); r1 = vfp_regno(r1); - emit_wide_thumb(_jit, ARM_CC_AL|o|(_u4(r0)<<12)|_u4(r1)); -} - -static void -vo_qq(jit_state_t *_jit, int o, int r0, int r1) -{ - assert(!(o & 0xf000f00f)); - assert(!(r0 & 3) && !(r1 & 3)); - r0 = vfp_regno(r0); r1 = vfp_regno(r1); - emit_wide_thumb(_jit, ARM_CC_AL|o|(_u4(r0)<<12)|_u4(r1)); -} - -static void -vorr_(jit_state_t *_jit, int o, int r0, int r1) -{ - assert(!(o & 0xf000f00f)); - emit_wide_thumb(_jit, ARM_CC_AL|o|(_u4(r1)<<16)|(_u4(r0)<<12)); -} - static void vors_(jit_state_t *_jit, int o, int r0, int r1) { - assert(!(o & 0xf000f00f)); - if (r1 & 1) o |= ARM_V_N; r1 = vfp_regno(r1); - emit_wide_thumb(_jit, ARM_CC_AL|o|(_u4(r1)<<16)|(_u4(r0)<<12)); -} - -static void -vorv_(jit_state_t *_jit, int o, int r0, int r1) -{ - assert(!(o & 0xf000f00f)); - if (r1 & 1) o |= ARM_V_M; r1 = vfp_regno(r1); + ASSERT(!(o & 0xf000f00f)); + if (r1 & 1) o |= ARM_V_N; + r1 >>= 1; emit_wide_thumb(_jit, ARM_CC_AL|o|(_u4(r1)<<16)|(_u4(r0)<<12)); } static void vori_(jit_state_t *_jit, int o, int r0, int r1) { - assert(!(o & 0xf000f00f)); + ASSERT(!(o & 0xf000f00f)); /* use same bit pattern, to set opc1... */ - if (r1 & 1) o |= ARM_V_I32; r1 = vfp_regno(r1); + if (r1 & 1) o |= ARM_V_I32; + r1 >>= 1; emit_wide_thumb(_jit, ARM_CC_AL|o|(_u4(r1)<<16)|(_u4(r0)<<12)); } static void vorrd(jit_state_t *_jit, int o, int r0, int r1, int r2) { - assert(!(o & 0xf00ff00f)); - assert(!(r2 & 1)); - r2 = vfp_regno(r2); + ASSERT(!(o & 0xf00ff00f)); + ASSERT(!(r2 & 1)); + r2 >>= 1; emit_wide_thumb(_jit, ARM_CC_AL|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u4(r2)); } static void vosss(jit_state_t *_jit, int o, int r0, int r1, int r2) { - assert(!(o & 0xf00ff00f)); - if (r0 & 1) o |= ARM_V_D; r0 = vfp_regno(r0); - if (r1 & 1) o |= ARM_V_N; r1 = vfp_regno(r1); - if (r2 & 1) o |= ARM_V_M; r2 = vfp_regno(r2); + ASSERT(!(o & 0xf00ff00f)); + if (r0 & 1) o |= ARM_V_D; + if (r1 & 1) o |= ARM_V_N; + if (r2 & 1) o |= ARM_V_M; + r0 >>= 1; r1 >>= 1; r2 >>= 1; emit_wide_thumb(_jit, ARM_CC_AL|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u4(r2)); } static void voddd(jit_state_t *_jit, int o, int r0, int r1, int r2) { - assert(!(o & 0xf00ff00f)); - assert(!(r0 & 1) && !(r1 & 1) && !(r2 & 1)); - r0 = vfp_regno(r0); r1 = vfp_regno(r1); r2 = vfp_regno(r2); - emit_wide_thumb(_jit, ARM_CC_AL|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u4(r2)); -} - -static void -voqdd(jit_state_t *_jit, int o, int r0, int r1, int r2) -{ - assert(!(o & 0xf00ff00f)); - assert(!(r0 & 3) && !(r1 & 1) && !(r2 & 1)); - r0 = vfp_regno(r0); r1 = vfp_regno(r1); r2 = vfp_regno(r2); - emit_wide_thumb(_jit, ARM_CC_AL|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u4(r2)); -} - -static void -voqqd(jit_state_t *_jit, int o, int r0, int r1, int r2) -{ - assert(!(o & 0xf00ff00f)); - assert(!(r0 & 3) && !(r1 & 3) && !(r2 & 1)); - r0 = vfp_regno(r0); r1 = vfp_regno(r1); r2 = vfp_regno(r2); - emit_wide_thumb(_jit, ARM_CC_AL|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u4(r2)); -} - -static void -voqqq(jit_state_t *_jit, int o, int r0, int r1, int r2) -{ - assert(!(o & 0xf00ff00f)); - assert(!(r0 & 3) && !(r1 & 3) && !(r2 & 3)); - r0 = vfp_regno(r0); r1 = vfp_regno(r1); r2 = vfp_regno(r2); + ASSERT(!(o & 0xf00ff00f)); + ASSERT(!(r0 & 1) && !(r1 & 1) && !(r2 & 1)); + r0 >>= 1; r1 >>= 1; r2 >>= 1; emit_wide_thumb(_jit, ARM_CC_AL|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u4(r2)); } @@ -207,545 +137,630 @@ static void vldst(jit_state_t *_jit, int o, int r0, int r1, int i0) { /* i0 << 2 is byte offset */ - assert(!(o & 0xf00ff0ff)); + ASSERT(!(o & 0xf00ff0ff)); if (r0 & 1) { - assert(!(o & ARM_V_F64)); + ASSERT(!(o & ARM_V_F64)); o |= ARM_V_D; } - r0 = vfp_regno(r0); + r0 >>= 1; emit_wide_thumb(_jit, ARM_CC_AL|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u8(i0)); } static void -vorsl(jit_state_t *_jit, int o, int r0, int r1, int i0) -{ - assert(!(o & 0xf00ff0ff)); - /* save i0 double precision registers */ - if (o & ARM_V_F64) i0 <<= 1; - /* if (r1 & 1) cc & ARM_V_F64 must be false */ - if (r1 & 1) o |= ARM_V_D; r1 = vfp_regno(r1); - assert(i0 && !(i0 & 1) && r1 + i0 <= 32); - emit_wide_thumb(_jit, ARM_CC_AL|o|(_u4(r0)<<16)|(_u4(r1)<<12)|_u8(i0)); -} - -static void -VADD_F32(jit_state_t *_jit, int32_t r0,r1,r2) +VADD_F32(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { vosss(_jit,ARM_VADD_F,r0,r1,r2); } static void -VADD_F64(jit_state_t *_jit, int32_t r0,r1,r2) +VADD_F64(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { voddd(_jit,ARM_VADD_F|ARM_V_F64,r0,r1,r2); } static void -VSUB_F32(jit_state_t *_jit, int32_t r0,r1,r2) +VSUB_F32(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { vosss(_jit,ARM_VSUB_F,r0,r1,r2); } static void -VSUB_F64(jit_state_t *_jit, int32_t r0,r1,r2) +VSUB_F64(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { voddd(_jit,ARM_VSUB_F|ARM_V_F64,r0,r1,r2); } static void -VMUL_F32(jit_state_t *_jit, int32_t r0,r1,r2) +VMUL_F32(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { vosss(_jit,ARM_VMUL_F,r0,r1,r2); } static void -VMUL_F64(jit_state_t *_jit, int32_t r0,r1,r2) +VMUL_F64(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { voddd(_jit,ARM_VMUL_F|ARM_V_F64,r0,r1,r2); } static void -VDIV_F32(jit_state_t *_jit, int32_t r0,r1,r2) +VDIV_F32(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { vosss(_jit,ARM_VDIV_F,r0,r1,r2); } static void -VDIV_F64(jit_state_t *_jit, int32_t r0,r1,r2) +VDIV_F64(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { voddd(_jit,ARM_VDIV_F|ARM_V_F64,r0,r1,r2); } static void -VABS_F32(jit_state_t *_jit, int32_t r0,r1) +VABS_F32(jit_state_t *_jit, int32_t r0, int32_t r1) { vo_ss(_jit,ARM_VABS_F,r0,r1); } static void -VABS_F64(jit_state_t *_jit, int32_t r0,r1) +VABS_F64(jit_state_t *_jit, int32_t r0, int32_t r1) { vo_dd(_jit,ARM_VABS_F|ARM_V_F64,r0,r1); } static void -VNEG_F32(jit_state_t *_jit, int32_t r0,r1) +VNEG_F32(jit_state_t *_jit, int32_t r0, int32_t r1) { vo_ss(_jit,ARM_VNEG_F,r0,r1); } static void -VNEG_F64(jit_state_t *_jit, int32_t r0,r1) +VNEG_F64(jit_state_t *_jit, int32_t r0, int32_t r1) { vo_dd(_jit,ARM_VNEG_F|ARM_V_F64,r0,r1); } static void -VSQRT_F32(jit_state_t *_jit, int32_t r0,r1) +VSQRT_F32(jit_state_t *_jit, int32_t r0, int32_t r1) { vo_ss(_jit,ARM_VSQRT_F,r0,r1); } static void -VSQRT_F64(jit_state_t *_jit, int32_t r0,r1) +VSQRT_F64(jit_state_t *_jit, int32_t r0, int32_t r1) { vo_dd(_jit,ARM_VSQRT_F|ARM_V_F64,r0,r1); } static void -VMOV_F32(jit_state_t *_jit, int32_t r0,r1) +VMOV_F32(jit_state_t *_jit, int32_t r0, int32_t r1) { vo_ss(_jit,ARM_VMOV_F,r0,r1); } static void -VMOV_F64(jit_state_t *_jit, int32_t r0,r1) +VMOV_F64(jit_state_t *_jit, int32_t r0, int32_t r1) { vo_dd(_jit,ARM_VMOV_F|ARM_V_F64,r0,r1); } static void -VMOV_AA_D(jit_state_t *_jit, int32_t r0,r1,r2) -{ - vorrd(_jit,ARM_VMOV_AA_D,r0,r1,r2); -} - -static void -VMOV_D_AA(jit_state_t *_jit, int32_t r0,r1,r2) +VMOV_D_AA(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { vorrd(_jit,ARM_VMOV_D_AA,r1,r2,r0); } static void -VMOV_A_S(jit_state_t *_jit, int32_t r0,r1) -{ - vors_(_jit,ARM_VMOV_A_S,r0,r1); -} - -static void -VMOV_S_A(jit_state_t *_jit, int32_t r0,r1) +VMOV_S_A(jit_state_t *_jit, int32_t r0, int32_t r1) { vors_(_jit,ARM_VMOV_S_A,r1,r0); } static void -VCMP_F32(jit_state_t *_jit, int32_t r0,r1) +VCMP_F32(jit_state_t *_jit, int32_t r0, int32_t r1) { vo_ss(_jit,ARM_VCMP,r0,r1); } static void -VCMP_F64(jit_state_t *_jit, int32_t r0,r1) +VCMP_F64(jit_state_t *_jit, int32_t r0, int32_t r1) { vo_dd(_jit,ARM_VCMP|ARM_V_F64,r0,r1); } static void -VMRS(jit_state_t *_jit, int32_t r0) +VMRS(jit_state_t *_jit) { - vorr_(_jit,ARM_VMRS,r0,0); + emit_wide_thumb(_jit, ARM_CC_AL|ARM_VMRS|(0xf<<12)); } static void -VCVT_S32_F32(jit_state_t *_jit, int32_t r0,r1) +VCVT_S32_F32(jit_state_t *_jit, int32_t r0, int32_t r1) { vo_ss(_jit,ARM_VCVT_S32_F32,r0,r1); } static void -VCVT_S32_F64(jit_state_t *_jit, int32_t r0,r1) +VCVT_S32_F64(jit_state_t *_jit, int32_t r0, int32_t r1) { vo_ss(_jit,ARM_VCVT_S32_F64,r0,r1); } static void -VCVT_F32_S32(jit_state_t *_jit, int32_t r0,r1) +VCVT_F32_S32(jit_state_t *_jit, int32_t r0, int32_t r1) { vo_ss(_jit,ARM_VCVT_F32_S32,r0,r1); } static void -VCVT_F64_S32(jit_state_t *_jit, int32_t r0,r1) +VCVT_F64_S32(jit_state_t *_jit, int32_t r0, int32_t r1) { vo_ss(_jit,ARM_VCVT_F64_S32,r0,r1); } static void -VCVT_F32_F64(jit_state_t *_jit, int32_t r0,r1) +VCVT_F32_F64(jit_state_t *_jit, int32_t r0, int32_t r1) { vo_ss(_jit,ARM_VCVT_F32_F64,r0,r1); } static void -VCVT_F64_F32(jit_state_t *_jit, int32_t r0,r1) +VCVT_F64_F32(jit_state_t *_jit, int32_t r0, int32_t r1) { vo_ss(_jit,ARM_VCVT_F64_F32,r0,r1); } static void -VMOV_A_S32(jit_state_t *_jit, int32_t r0,r1) +VMOV_A_S32(jit_state_t *_jit, int32_t r0, int32_t r1) { vori_(_jit,ARM_VMOV_A_D,r0,r1); } static void -VMOV_V_I32(jit_state_t *_jit, int32_t r0,r1) +VMOV_V_I32(jit_state_t *_jit, int32_t r0, int32_t r1) { vori_(_jit,ARM_VMOV_D_A,r1,r0); } /* "oi" should be the result of encode_vfp_double */ static void -VIMM(jit_state_t *_jit, int32_t oi,r0) +VIMM(jit_state_t *_jit, int32_t oi, int32_t r0) { vodi(_jit, oi,r0); } /* index is multipled by four */ static void -VLDRN_F32(jit_state_t *_jit, int32_t r0,r1,i0) +VLDRN_F32(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) { vldst(_jit,ARM_VLDR,r0,r1,i0); } static void -VLDR_F32(jit_state_t *_jit, int32_t r0,r1,i0) +VLDR_F32(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) { vldst(_jit,ARM_VLDR|ARM_P,r0,r1,i0); } static void -VLDRN_F64(jit_state_t *_jit, int32_t r0,r1,i0) +VLDRN_F64(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) { vldst(_jit,ARM_VLDR|ARM_V_F64,r0,r1,i0); } static void -VLDR_F64(jit_state_t *_jit, int32_t r0,r1,i0) +VLDR_F64(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) { vldst(_jit,ARM_VLDR|ARM_V_F64|ARM_P,r0,r1,i0); } static void -VSTRN_F32(jit_state_t *_jit, int32_t r0,r1,i0) +VSTRN_F32(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) { vldst(_jit,ARM_VSTR,r0,r1,i0); } static void -VSTR_F32(jit_state_t *_jit, int32_t r0,r1,i0) +VSTR_F32(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) { vldst(_jit,ARM_VSTR|ARM_P,r0,r1,i0); } static void -VSTRN_F64(jit_state_t *_jit, int32_t r0,r1,i0) +VSTRN_F64(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) { vldst(_jit,ARM_VSTR|ARM_V_F64,r0,r1,i0); } static void -VSTR_F64(jit_state_t *_jit, int32_t r0,r1,i0) +VSTR_F64(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) { vldst(_jit,ARM_VSTR|ARM_V_F64|ARM_P,r0,r1,i0); } static void -vfp_absr_f(jit_state_t *_jit, int32_t r0,r1) +absr_f(jit_state_t *_jit, int32_t r0, int32_t r1) { VABS_F32(_jit, r0,r1); } static void -vfp_absr_d(jit_state_t *_jit, int32_t r0,r1) +absr_d(jit_state_t *_jit, int32_t r0, int32_t r1) { VABS_F64(_jit, r0,r1); } static void -vfp_negr_f(jit_state_t *_jit, int32_t r0,r1) +negr_f(jit_state_t *_jit, int32_t r0, int32_t r1) { VNEG_F32(_jit, r0,r1); } static void -vfp_negr_d(jit_state_t *_jit, int32_t r0,r1) +negr_d(jit_state_t *_jit, int32_t r0, int32_t r1) { VNEG_F64(_jit, r0,r1); } static void -vfp_sqrtr_f(jit_state_t *_jit, int32_t r0,r1) +sqrtr_f(jit_state_t *_jit, int32_t r0, int32_t r1) { VSQRT_F32(_jit, r0,r1); } static void -vfp_sqrtr_d(jit_state_t *_jit, int32_t r0,r1) +sqrtr_d(jit_state_t *_jit, int32_t r0, int32_t r1) { VSQRT_F64(_jit, r0,r1); } static void -vfp_addr_f(jit_state_t *_jit, int32_t r0,r1,r2) +addr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { VADD_F32(_jit, r0,r1,r2); } static void -vfp_addr_d(jit_state_t *_jit, int32_t r0,r1,r2) +addr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { VADD_F64(_jit, r0,r1,r2); } static void -vfp_subr_f(jit_state_t *_jit, int32_t r0,r1,r2) +subr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { VSUB_F32(_jit, r0,r1,r2); } static void -vfp_subr_d(jit_state_t *_jit, int32_t r0,r1,r2) +subr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { VSUB_F64(_jit, r0,r1,r2); } static void -vfp_mulr_f(jit_state_t *_jit, int32_t r0,r1,r2) +mulr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { VMUL_F32(_jit, r0,r1,r2); } static void -vfp_mulr_d(jit_state_t *_jit, int32_t r0,r1,r2) +mulr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { VMUL_F64(_jit, r0,r1,r2); } static void -vfp_divr_f(jit_state_t *_jit, int32_t r0,r1,r2) +divr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { VDIV_F32(_jit, r0,r1,r2); } static void -vfp_divr_d(jit_state_t *_jit, int32_t r0,r1,r2) +divr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { VDIV_F64(_jit, r0,r1,r2); } +static void +cmp_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + VCMP_F32(_jit, r0, r1); +} + +static void +cmp_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + VCMP_F64(_jit, r0, r1); +} + static jit_reloc_t -vfp_bltr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +vbcmp_x(jit_state_t *_jit, int cc) +{ + VMRS(_jit); + return T2_CC_B(_jit, cc); +} + +static jit_reloc_t +vbcmp_f(jit_state_t *_jit, int cc, int32_t r0, int32_t r1) +{ + cmp_f(_jit, r0, r1); + return vbcmp_x(_jit, cc); +} + +static jit_reloc_t +vbcmp_d(jit_state_t *_jit, int cc, int32_t r0, int32_t r1) +{ + cmp_d(_jit, r0, r1); + return vbcmp_x(_jit, cc); +} + +static jit_reloc_t +vbncmp_x(jit_state_t *_jit, int cc) +{ + VMRS(_jit); + jit_reloc_t cont = T2_CC_B(_jit, cc); + jit_reloc_t ret = T2_B(_jit); + jit_patch_here(_jit, cont); + return ret; +} + +static jit_reloc_t +vbncmp_f(jit_state_t *_jit, int cc, int32_t r0, int32_t r1) +{ + cmp_f(_jit, r0, r1); + return vbncmp_x(_jit, cc); +} + +static jit_reloc_t +vbncmp_d(jit_state_t *_jit, int cc, int32_t r0, int32_t r1) +{ + cmp_d(_jit, r0, r1); + return vbncmp_x(_jit, cc); +} + +static jit_reloc_t +bltr_f(jit_state_t *_jit, int32_t r0, int32_t r1) { return vbcmp_f(_jit, ARM_CC_MI, r0, r1); } static jit_reloc_t -vfp_bltr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +bltr_d(jit_state_t *_jit, int32_t r0, int32_t r1) { return vbcmp_d(_jit, ARM_CC_MI, r0, r1); } static jit_reloc_t -vfp_bler_f(jit_state_t *_jit, int32_t r0, int32_t r1) +bler_f(jit_state_t *_jit, int32_t r0, int32_t r1) { return vbcmp_f(_jit, ARM_CC_LS, r0, r1); } static jit_reloc_t -vfp_bler_d(jit_state_t *_jit, int32_t r0, int32_t r1) +bler_d(jit_state_t *_jit, int32_t r0, int32_t r1) { return vbcmp_d(_jit, ARM_CC_LS, r0, r1); } static jit_reloc_t -vfp_beqr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +beqr_f(jit_state_t *_jit, int32_t r0, int32_t r1) { return vbcmp_f(_jit, ARM_CC_EQ, r0, r1); } static jit_reloc_t -vfp_beqr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +beqr_d(jit_state_t *_jit, int32_t r0, int32_t r1) { return vbcmp_d(_jit, ARM_CC_EQ, r0, r1); } static jit_reloc_t -vfp_bger_f(jit_state_t *_jit, int32_t r0, int32_t r1) +bger_f(jit_state_t *_jit, int32_t r0, int32_t r1) { return vbcmp_f(_jit, ARM_CC_GE, r0, r1); } static jit_reloc_t -vfp_bger_d(jit_state_t *_jit, int32_t r0, int32_t r1) +bger_d(jit_state_t *_jit, int32_t r0, int32_t r1) { return vbcmp_d(_jit, ARM_CC_GE, r0, r1); } static jit_reloc_t -vfp_bgtr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +bgtr_f(jit_state_t *_jit, int32_t r0, int32_t r1) { return vbcmp_f(_jit, ARM_CC_GT, r0, r1); } static jit_reloc_t -vfp_bgtr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +bgtr_d(jit_state_t *_jit, int32_t r0, int32_t r1) { return vbcmp_d(_jit, ARM_CC_GT, r0, r1); } static jit_reloc_t -vfp_bner_f(jit_state_t *_jit, int32_t r0, int32_t r1) +bner_f(jit_state_t *_jit, int32_t r0, int32_t r1) { return vbcmp_f(_jit, ARM_CC_NE, r0, r1); } static jit_reloc_t -vfp_bner_d(jit_state_t *_jit, int32_t r0, int32_t r1) +bner_d(jit_state_t *_jit, int32_t r0, int32_t r1) { return vbcmp_d(_jit, ARM_CC_NE, r0, r1); } static jit_reloc_t -vfp_bunltr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +bunltr_f(jit_state_t *_jit, int32_t r0, int32_t r1) { return vbncmp_f(_jit, ARM_CC_GE, r0, r1); } static jit_reloc_t -vfp_bunltr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +bunltr_d(jit_state_t *_jit, int32_t r0, int32_t r1) { return vbncmp_d(_jit, ARM_CC_GE, r0, r1); } static jit_reloc_t -vfp_bunler_f(jit_state_t *_jit, int32_t r0, int32_t r1) +bunler_f(jit_state_t *_jit, int32_t r0, int32_t r1) { return vbncmp_f(_jit, ARM_CC_GT, r0, r1); } static jit_reloc_t -vfp_bunler_d(jit_state_t *_jit, int32_t r0, int32_t r1) +bunler_d(jit_state_t *_jit, int32_t r0, int32_t r1) { return vbncmp_d(_jit, ARM_CC_GT, r0, r1); } static jit_reloc_t -vfp_bungtr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +bungtr_f(jit_state_t *_jit, int32_t r0, int32_t r1) { return vbcmp_f(_jit, ARM_CC_HI, r0, r1); } static jit_reloc_t -vfp_bungtr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +bungtr_d(jit_state_t *_jit, int32_t r0, int32_t r1) { return vbcmp_d(_jit, ARM_CC_HI, r0, r1); } static jit_reloc_t -vfp_bordr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +bordr_f(jit_state_t *_jit, int32_t r0, int32_t r1) { return vbcmp_f(_jit, ARM_CC_VC, r0, r1); } static jit_reloc_t -vfp_bordr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +bordr_d(jit_state_t *_jit, int32_t r0, int32_t r1) { return vbcmp_d(_jit, ARM_CC_VC, r0, r1); } static jit_reloc_t -vfp_bunordr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +bunordr_f(jit_state_t *_jit, int32_t r0, int32_t r1) { return vbcmp_f(_jit, ARM_CC_VS, r0, r1); } static jit_reloc_t -vfp_bunordr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +bunordr_d(jit_state_t *_jit, int32_t r0, int32_t r1) { return vbcmp_d(_jit, ARM_CC_VS, r0, r1); } +static jit_reloc_t +buneqr_x(jit_state_t *_jit) +{ + VMRS(_jit); + jit_reloc_t a = T2_CC_B(_jit, ARM_CC_VS); + jit_reloc_t b = T2_CC_B(_jit, ARM_CC_NE); + jit_patch_here(_jit, a); + jit_reloc_t ret = T2_B(_jit); + jit_patch_here(_jit, b); + return ret; +} + +static jit_reloc_t +buneqr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + cmp_f(_jit, r0, r1); + return buneqr_x(_jit); +} + +static jit_reloc_t +buneqr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + cmp_d(_jit, r0, r1); + return buneqr_x(_jit); +} + +static jit_reloc_t +bunger_x(jit_state_t *_jit) +{ + VMRS(_jit); + jit_reloc_t a = T2_CC_B(_jit, ARM_CC_MI); + jit_reloc_t ret = T2_CC_B(_jit, ARM_CC_HS); + jit_patch_here(_jit, a); + return ret; +} + +static jit_reloc_t +bunger_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + cmp_f(_jit, r0, r1); + return bunger_x(_jit); +} + +static jit_reloc_t +bunger_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + cmp_d(_jit, r0, r1); + return bunger_x(_jit); +} + +static jit_reloc_t +bltgtr_x(jit_state_t *_jit) +{ + VMRS(_jit); + jit_reloc_t a = T2_CC_B(_jit, ARM_CC_VS); + jit_reloc_t b = T2_CC_B(_jit, ARM_CC_EQ); + jit_reloc_t ret = T2_B(_jit); + jit_patch_here(_jit, a); + jit_patch_here(_jit, b); + return ret; +} + +static jit_reloc_t +bltgtr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + cmp_f(_jit, r0, r1); + return bltgtr_x(_jit); +} + +static jit_reloc_t +bltgtr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + cmp_d(_jit, r0, r1); + return bltgtr_x(_jit); +} + static void -vfp_ldr_f(jit_state_t *_jit, int32_t r0,r1) +ldr_f(jit_state_t *_jit, int32_t r0, int32_t r1) { VLDR_F32(_jit, r0,r1,0); } static void -vfp_ldr_d(jit_state_t *_jit, int32_t r0,r1) +ldr_d(jit_state_t *_jit, int32_t r0, int32_t r1) { VLDR_F64(_jit, r0,r1,0); } static void -vfp_str_f(jit_state_t *_jit, int32_t r0,r1) +str_f(jit_state_t *_jit, int32_t r0, int32_t r1) { VSTR_F32(_jit, r1,r0,0); } static void -vfp_str_d(jit_state_t *_jit, int32_t r0,r1) +str_d(jit_state_t *_jit, int32_t r0, int32_t r1) { VSTR_F64(_jit, r1,r0,0); } static void -vfp_movr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +movr_f(jit_state_t *_jit, int32_t r0, int32_t r1) { - if (r0 != r1) { - if (jit_fpr_p(r1)) { - if (jit_fpr_p(r0)) - VMOV_F32(r0, r1); - else - VMOV_A_S(r0, r1); - } - else if (jit_fpr_p(r0)) - VMOV_S_A(r0, r1); - else - movr(r0, r1); - } + if (r0 != r1) + VMOV_F32(_jit, r0, r1); } static void -vfp_movr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +movr_d(jit_state_t *_jit, int32_t r0, int32_t r1) { - if (r0 != r1) { - if (jit_fpr_p(r1)) { - if (jit_fpr_p(r0)) - VMOV_F64(r0, r1); - else - VMOV_AA_D(r0, r0 + 1, r1); - } - else if (jit_fpr_p(r0)) - VMOV_D_AA(r0, r1, r1 + 1); - else { - /* minor consistency check */ - assert(r0 + 1 != r1 && r0 -1 != r1); - movr(r0, r1); - movr(r0 + 1, r1 + 1); - } - } + if (r0 != r1) + VMOV_F64(_jit, r0, r1); } static int @@ -831,7 +846,7 @@ encode_vfp_double(int mov, int inv, unsigned lo, unsigned hi) fail: /* need another approach (load from memory, move from arm register, etc) */ - return (-1); + return -1; success: code = inv ? ARM_VMVNI : ARM_VMOVI; @@ -843,19 +858,19 @@ success: break; case 0x1: case 0x3: case 0x5: case 0x7: /* should actually not reach here */ - assert(!inv); + ASSERT(!inv); case 0x9: case 0xb: - assert(!mov); + ASSERT(!mov); break; case 0xc: case 0xd: /* should actually not reach here */ - assert(inv); + ASSERT(inv); case 0xe: - assert(mode & 0x20); - assert(mov && !inv); + ASSERT(mode & 0x20); + ASSERT(mov && !inv); break; default: - assert(!(mode & 0x20)); + ASSERT(!(mode & 0x20)); break; } imm = ((imm & 0x80) << 17) | ((imm & 0x70) << 12) | (imm & 0x0f); @@ -866,678 +881,288 @@ success: else code |= 0xef000000; - return (code); + return code; } static void -_vfp_movi_f(jit_state_t *_jit, int32_t r0, jit_float32_t i0) +movi_f(jit_state_t *_jit, int32_t r0, jit_float32_t i0) { - union { - int32_t i; - jit_float32_t f; - } u; - int32_t reg; - int32_t code; - u.f = i0; - if (jit_fpr_p(r0)) { - /* float arguments are packed, for others, - * lightning only address even registers */ - if (!(r0 & 1) && (r0 - 16) >= 0 && - ((code = encode_vfp_double(1, 0, u.i, u.i)) != -1 || - (code = encode_vfp_double(1, 1, ~u.i, ~u.i)) != -1)) - VIMM(code, r0); + union { int32_t i; jit_float32_t f; } u = { .f = i0 }; + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), u.i); + VMOV_S_A(_jit, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); +} + +static void +movi_d(jit_state_t *_jit, int32_t r0, jit_float64_t i0) +{ + union { int32_t i[2]; jit_float64_t d; } u = { .d = i0 }; + int32_t code; + if ((code = encode_vfp_double(1, 0, u.i[0], u.i[1])) != -1 || + (code = encode_vfp_double(1, 1, ~u.i[0], ~u.i[1])) != -1) + VIMM(_jit, code, r0); + else { + jit_gpr_t rg0 = get_temp_gpr(_jit); + jit_gpr_t rg1 = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(rg0), u.i[0]); + movi(_jit, jit_gpr_regno(rg1), u.i[1]); + VMOV_D_AA(_jit, r0, jit_gpr_regno(rg0), jit_gpr_regno(rg1)); + unget_temp_gpr(_jit); + unget_temp_gpr(_jit); + } +} + +static void +extr_d_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + VCVT_F64_F32(_jit, r0, r1); +} + +static void +extr_f_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + VCVT_F32_F64(_jit, r0, r1); +} + +static void +extr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + VMOV_V_I32(_jit, r0, r1); + VCVT_F32_S32(_jit, r0, r0); +} + +static void +extr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + VMOV_V_I32(_jit, r0, r1); + VCVT_F64_S32(_jit, r0, r0); +} + +static void +truncr_f_i(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + jit_fpr_t reg = get_temp_fpr(_jit); + VCVT_S32_F32(_jit, jit_fpr_regno(reg), r1); + VMOV_A_S32(_jit, r0, jit_fpr_regno(reg)); + unget_temp_fpr(_jit); +} + +static void +truncr_d_i(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + jit_fpr_t reg = get_temp_fpr(_jit); + VCVT_S32_F64(_jit, jit_fpr_regno(reg), r1); + VMOV_A_S32(_jit, r0, jit_fpr_regno(reg)); + unget_temp_fpr(_jit); +} + +static void +ldi_f(jit_state_t *_jit, int32_t r0, jit_word_t i0) +{ + jit_gpr_t gpr = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(gpr), i0); + VLDR_F32(_jit, r0, jit_gpr_regno(gpr), 0); + unget_temp_gpr(_jit); +} + +static void +ldi_d(jit_state_t *_jit, int32_t r0, jit_word_t i0) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + VLDR_F64(_jit, r0, jit_gpr_regno(reg), 0); + unget_temp_gpr(_jit); +} + +static void +ldxr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + addr(_jit, jit_gpr_regno(reg), r1, r2); + VLDR_F32(_jit, r0, jit_gpr_regno(reg), 0); + unget_temp_gpr(_jit); +} + +static void +ldxr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + jit_gpr_t reg = get_temp_gpr(_jit); + addr(_jit, jit_gpr_regno(reg), r1, r2); + VLDR_F64(_jit, r0, jit_gpr_regno(reg), 0); + unget_temp_gpr(_jit); +} + +static void +ldxi_f(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + if (i0 >= 0) { + ASSERT(!(i0 & 3)); + if (i0 < 1024) + VLDR_F32(_jit, r0, r1, i0 >> 2); else { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), u.i); - VMOV_S_A(r0, rn(reg)); - jit_unget_reg(reg); + jit_gpr_t reg = get_temp_gpr(_jit); + addi(_jit, jit_gpr_regno(reg), r1, i0); + VLDR_F32(_jit, r0, jit_gpr_regno(reg), 0); + unget_temp_gpr(_jit); } } - else - movi(r0, u.i); -} - -static void -_vfp_movi_d(jit_state_t *_jit, int32_t r0, jit_float64_t i0) -{ - union { - int32_t i[2]; - jit_float64_t d; - } u; - int32_t code; - int32_t rg0, rg1; - u.d = i0; - if (jit_fpr_p(r0)) { - if ((code = encode_vfp_double(1, 0, u.i[0], u.i[1])) != -1 || - (code = encode_vfp_double(1, 1, ~u.i[0], ~u.i[1])) != -1) - VIMM(code, r0); + else { + i0 = -i0; + ASSERT(!(i0 & 3)); + if (i0 < 1024) + VLDRN_F32(_jit, r0, r1, i0 >> 2); else { - rg0 = jit_get_reg(jit_class_gpr); - rg1 = jit_get_reg(jit_class_gpr); - movi(rn(rg0), u.i[0]); - movi(rn(rg1), u.i[1]); - VMOV_D_AA(r0, rn(rg0), rn(rg1)); - jit_unget_reg(rg1); - jit_unget_reg(rg0); + jit_gpr_t reg = get_temp_gpr(_jit); + subi(_jit, jit_gpr_regno(reg), r1, i0); + VLDR_F32(_jit, r0, jit_gpr_regno(reg), 0); + unget_temp_gpr(_jit); } } - else { - movi(r0, u.i[0]); - movi(r0 + 1, u.i[1]); - } } static void -_vfp_extr_d_f(jit_state_t *_jit, int32_t r0, int32_t r1) +ldxi_d(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - int32_t reg; - if (jit_fpr_p(r1)) { - if (jit_fpr_p(r0)) - VCVT_F64_F32(r0, r1); + if (i0 >= 0) { + ASSERT(!(i0 & 3)); + if (i0 < 1024) + VLDR_F64(_jit, r0, r1, i0 >> 2); else { - reg = jit_get_reg(jit_class_fpr); - VCVT_F64_F32(rn(reg), r1); - VMOV_A_S(r0, rn(reg)); - jit_unget_reg(reg); + jit_gpr_t reg = get_temp_gpr(_jit); + addi(_jit, jit_gpr_regno(reg), r1, i0); + VLDR_F64(_jit, r0, jit_gpr_regno(reg), 0); + unget_temp_gpr(_jit); } } else { - reg = jit_get_reg(jit_class_fpr); - VMOV_S_A(rn(reg), r1); - VCVT_F64_F32(rn(reg), rn(reg)); - if (jit_fpr_p(r0)) - VMOV_F32(r0, rn(reg)); - else - VMOV_A_S(r0, rn(reg)); - jit_unget_reg(reg); - } -} - -static void -_vfp_extr_f_d(jit_state_t *_jit, int32_t r0, int32_t r1) -{ - int32_t reg; - if (jit_fpr_p(r1)) { - if (jit_fpr_p(r0)) - VCVT_F32_F64(r0, r1); + i0 = -i0; + ASSERT(!(i0 & 3)); + if (i0 < 1024) + VLDRN_F64(_jit, r0, r1, i0 >> 2); else { - reg = jit_get_reg(jit_class_fpr); - VCVT_F32_F64(rn(reg), r1); - VMOV_AA_D(r0, r0 + 1, rn(reg)); - jit_unget_reg(reg); + jit_gpr_t reg = get_temp_gpr(_jit); + subi(_jit, jit_gpr_regno(reg), r1, i0); + VLDR_F64(_jit, r0, jit_gpr_regno(reg), 0); + unget_temp_gpr(_jit); } } - else { - reg = jit_get_reg(jit_class_fpr); - VMOV_D_AA(rn(reg), r1, r1 + 1); - VCVT_F32_F64(rn(reg), rn(reg)); - if (jit_fpr_p(r0)) - VMOV_F64(r0, rn(reg)); - else - VMOV_AA_D(r0, r0 + 1, rn(reg)); - jit_unget_reg(reg); - } } static void -_vfp_extr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +sti_f(jit_state_t *_jit, jit_word_t i0, int32_t r0) { - int32_t reg; - if (jit_fpr_p(r0)) { - VMOV_V_I32(r0, r1); - VCVT_F32_S32(r0, r0); - } - else { - reg = jit_get_reg(jit_class_fpr); - VMOV_V_I32(rn(reg), r1); - VCVT_F32_S32(rn(reg), rn(reg)); - VMOV_F32(r0, rn(reg)); - jit_unget_reg(reg); - } + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + VSTR_F32(_jit, r0, jit_gpr_regno(reg), 0); + unget_temp_gpr(_jit); } static void -_vfp_extr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +sti_d(jit_state_t *_jit, jit_word_t i0, int32_t r0) { - int32_t reg; - if (jit_fpr_p(r0)) { - VMOV_V_I32(r0, r1); - VCVT_F64_S32(r0, r0); - } - else { - reg = jit_get_reg(jit_class_fpr); - VMOV_V_I32(rn(reg), r1); - VCVT_F64_S32(rn(reg), rn(reg)); - VMOV_F64(r0, rn(reg)); - jit_unget_reg(reg); - } + jit_gpr_t reg = get_temp_gpr(_jit); + movi(_jit, jit_gpr_regno(reg), i0); + VSTR_F64(_jit, r0, jit_gpr_regno(reg), 0); + unget_temp_gpr(_jit); } static void -_vfp_truncr_f_i(jit_state_t *_jit, int32_t r0, int32_t r1) +stxr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - int32_t reg; - reg = jit_get_reg(jit_class_fpr); - if (jit_fpr_p(r1)) - VCVT_S32_F32(rn(reg), r1); - else { - VMOV_V_I32(rn(reg), r1); - VCVT_S32_F32(rn(reg), rn(reg)); - } - VMOV_A_S32(r0, rn(reg)); - jit_unget_reg(reg); + jit_gpr_t reg = get_temp_gpr(_jit); + addr(_jit, jit_gpr_regno(reg), r0, r1); + VSTR_F32(_jit, r2, jit_gpr_regno(reg), 0); + unget_temp_gpr(_jit); } static void -_vfp_truncr_d_i(jit_state_t *_jit, int32_t r0, int32_t r1) +stxr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - int32_t reg; - reg = jit_get_reg(jit_class_fpr); - if (jit_fpr_p(r1)) - VCVT_S32_F64(rn(reg), r1); - else { - VMOV_V_I32(rn(reg), r1); - VCVT_S32_F64(rn(reg), rn(reg)); - } - VMOV_A_S32(r0, rn(reg)); - jit_unget_reg(reg); + jit_gpr_t reg = get_temp_gpr(_jit); + addr(_jit, jit_gpr_regno(reg), r0, r1); + VSTR_F64(_jit, r2, jit_gpr_regno(reg), 0); + unget_temp_gpr(_jit); } static void -_vfp_cmp_f(jit_state_t *_jit, int32_t r0, int32_t r1) +stxi_f(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) { - int32_t rg0, rg1; - if (jit_fpr_p(r0)) { - if (jit_fpr_p(r1)) - VCMP_F32(r0, r1); + if (i0 >= 0) { + ASSERT(!(i0 & 3)); + if (i0 < 1024) + VSTR_F32(_jit, r1, r0, i0 >> 2); else { - rg1 = jit_get_reg(jit_class_fpr); - VMOV_S_A(rn(rg1), r1); - VCMP_F32(r0, rn(rg1)); - jit_unget_reg(rg1); + jit_gpr_t reg = get_temp_gpr(_jit); + addi(_jit, jit_gpr_regno(reg), r0, i0); + VSTR_F32(_jit, r1, jit_gpr_regno(reg), 0); + unget_temp_gpr(_jit); } } else { - rg0 = jit_get_reg(jit_class_fpr); - VMOV_S_A(rn(rg0), r0); - if (jit_fpr_p(r1)) - VCMP_F32(rn(rg0), r1); + i0 = -i0; + ASSERT(!(i0 & 3)); + if (i0 < 1024) + VSTRN_F32(_jit, r1, r0, i0 >> 2); else { - rg1 = jit_get_reg(jit_class_fpr); - VMOV_S_A(rn(rg1), r1); - VCMP_F32(rn(rg0), rn(rg1)); - jit_unget_reg(rg1); + jit_gpr_t reg = get_temp_gpr(_jit); + subi(_jit, jit_gpr_regno(reg), r0, i0); + VSTR_F32(_jit, r1, jit_gpr_regno(reg), 0); + unget_temp_gpr(_jit); } - jit_unget_reg(rg0); } } static void -_vfp_cmp_d(jit_state_t *_jit, int32_t r0, int32_t r1) +stxi_d(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) { - int32_t rg0, rg1; - if (jit_fpr_p(r0)) { - if (jit_fpr_p(r1)) - VCMP_F64(r0, r1); + if (i0 >= 0) { + ASSERT(!(i0 & 3)); + if (i0 < 0124) + VSTR_F64(_jit, r1, r0, i0 >> 2); else { - rg1 = jit_get_reg(jit_class_fpr); - VMOV_D_AA(rn(rg1), r1, r1 + 1); - VCMP_F64(r0, rn(rg1)); - jit_unget_reg(rg1); + jit_gpr_t reg = get_temp_gpr(_jit); + addi(_jit, jit_gpr_regno(reg), r0, i0); + VSTR_F64(_jit, r1, jit_gpr_regno(reg), 0); + unget_temp_gpr(_jit); } } else { - rg0 = jit_get_reg(jit_class_fpr); - VMOV_D_AA(rn(rg0), r0, r0 + 1); - if (jit_fpr_p(r1)) - VCMP_F64(rn(rg0), r1); + i0 = -i0; + ASSERT(!(i0 & 3)); + if (i0 < 1024) + VSTRN_F64(_jit, r1, r0, i0 >> 2); else { - rg1 = jit_get_reg(jit_class_fpr); - VMOV_D_AA(rn(rg1), r1, r1 + 1); - VCMP_F64(rn(rg0), rn(rg1)); - jit_unget_reg(rg1); - } - jit_unget_reg(rg0); - } -} - -static jit_word_t -_vbcmp_x(jit_state_t *_jit, int cc, jit_word_t i0) -{ - jit_word_t d, w; - VMRS(_R15_REGNO); - w = _jit->pc.w; - - d = ((i0 - w) >> 1) - 2; - assert(_s20P(d)); - T2_CC_B(cc, encode_thumb_cc_jump(d)); - - return (w); -} - - -static jit_word_t -_vbcmp_f(jit_state_t *_jit, int cc, - jit_word_t i0, int32_t r0, int32_t r1) -{ - vfp_cmp_f(r0, r1); - return (vbcmp_x(cc, i0)); -} - -static jit_word_t -_vbcmp_d(jit_state_t *_jit, int cc, - jit_word_t i0, int32_t r0, int32_t r1) -{ - vfp_cmp_d(r0, r1); - return (vbcmp_x(cc, i0)); -} - -static jit_word_t -_vbncmp_x(jit_state_t *_jit, int cc, jit_word_t i0) -{ - jit_word_t d, p, w; - VMRS(_R15_REGNO); - p = _jit->pc.w; - - T2_CC_B(cc, 0); - w = _jit->pc.w; - d = ((i0 - w) >> 1) - 2; - assert(_s20P(d)); - T2_B(encode_thumb_jump(d)); - - patch_at(arm_patch_jump, p, _jit->pc.w); - return (w); -} - -static jit_word_t -_vbncmp_f(jit_state_t *_jit, int cc, - jit_word_t i0, int32_t r0, int32_t r1) -{ - vfp_cmp_f(r0, r1); - return (vbncmp_x(cc, i0)); -} - -static jit_word_t -_vbncmp_d(jit_state_t *_jit, int cc, - jit_word_t i0, int32_t r0, int32_t r1) -{ - vfp_cmp_d(r0, r1); - return (vbncmp_x(cc, i0)); -} - -static jit_word_t -_vfp_buneqr_x(jit_state_t *_jit, jit_word_t i0) -{ - jit_word_t d, p, q, w; - VMRS(_R15_REGNO); - p = _jit->pc.w; - - T2_CC_B(ARM_CC_VS, 0); - q = _jit->pc.w; - T2_CC_B(ARM_CC_NE, 0); - patch_at(arm_patch_jump, p, _jit->pc.w); - w = _jit->pc.w; - d = ((i0 - w) >> 1) - 2; - assert(_s20P(d)); - T2_B(encode_thumb_jump(d)); - - patch_at(arm_patch_jump, q, _jit->pc.w); - return (w); -} - -static jit_word_t -_vfp_buneqr_f(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) -{ - vfp_cmp_f(r0, r1); - return (vfp_buneqr_x(i0)); -} - -static jit_word_t -_vfp_buneqr_d(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) -{ - vfp_cmp_d(r0, r1); - return (vfp_buneqr_x(i0)); -} - -static jit_word_t -_vfp_bunger_x(jit_state_t *_jit, jit_word_t i0) -{ - jit_word_t d, p, w; - VMRS(_R15_REGNO); - p = _jit->pc.w; - - T2_CC_B(ARM_CC_MI, 0); - w = _jit->pc.w; - d = ((i0 - w) >> 1) - 2; - assert(_s20P(d)); - T2_CC_B(ARM_CC_HS, encode_thumb_cc_jump(d)); - - patch_at(arm_patch_jump, p, _jit->pc.w); - return (w); -} - -static jit_word_t -_vfp_bunger_f(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) -{ - vfp_cmp_f(r0, r1); - return (vfp_bunger_x(i0)); -} - -static jit_word_t -_vfp_bunger_d(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) -{ - vfp_cmp_d(r0, r1); - return (vfp_bunger_x(i0)); -} - -static jit_word_t -_vfp_bltgtr_x(jit_state_t *_jit, jit_word_t i0) -{ - jit_word_t d, p, q, w; - VMRS(_R15_REGNO); - p = _jit->pc.w; - - T2_CC_B(ARM_CC_VS, 0); - q = _jit->pc.w; - T2_CC_B(ARM_CC_EQ, 0); - w = _jit->pc.w; - d = ((i0 - w) >> 1) - 2; - assert(_s20P(d)); - T2_B(encode_thumb_jump(d)); - - patch_at(arm_patch_jump, p, _jit->pc.w); - patch_at(arm_patch_jump, q, _jit->pc.w); - return (w); -} - -static jit_word_t -_vfp_bltgtr_f(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) -{ - vfp_cmp_f(r0, r1); - return (vfp_bltgtr_x(i0)); -} - -static jit_word_t -_vfp_bltgtr_d(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) -{ - vfp_cmp_d(r0, r1); - return (vfp_bltgtr_x(i0)); -} - -static void -_vfp_ldi_f(jit_state_t *_jit, int32_t r0, jit_word_t i0) -{ - int32_t gpr; - if (jit_fpr_p(r0)) { - gpr = jit_get_reg(jit_class_gpr); - movi(rn(gpr), i0); - VLDR_F32(r0, rn(gpr), 0); - jit_unget_reg(gpr); - } - else - ldi_i(r0, i0); -} - -static void -_vfp_ldi_d(jit_state_t *_jit, int32_t r0, jit_word_t i0) -{ - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - if (jit_fpr_p(r0)) - VLDR_F64(r0, rn(reg), 0); - else { - ldr_i(r0, rn(reg)); - ldxi_i(r0 + 1, rn(reg), 4); - } - jit_unget_reg(reg); -} - -static void -_vfp_ldxr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - int32_t reg; - if (jit_fpr_p(r0)) { - reg = jit_get_reg(jit_class_gpr); - addr(rn(reg), r1, r2); - VLDR_F32(r0, rn(reg), 0); - jit_unget_reg(reg); - } - else - ldxr_i(r0, r1, r2); -} - -static void -_vfp_ldxr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - addr(rn(reg), r1, r2); - if (jit_fpr_p(r0)) - VLDR_F64(r0, rn(reg), 0); - else { - ldr_i(r0, rn(reg)); - ldxi_i(r0 + 1, rn(reg), 4); - } - jit_unget_reg(reg); -} - -static void -_vfp_ldxi_f(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) -{ - int32_t reg; - if (jit_fpr_p(r0)) { - if (i0 >= 0) { - assert(!(i0 & 3)); - if (i0 < 1024) - VLDR_F32(r0, r1, i0 >> 2); - else { - reg = jit_get_reg(jit_class_gpr); - addi(rn(reg), r1, i0); - VLDR_F32(r0, rn(reg), 0); - jit_unget_reg(reg); - } - } - else { - i0 = -i0; - assert(!(i0 & 3)); - if (i0 < 1024) - VLDRN_F32(r0, r1, i0 >> 2); - else { - reg = jit_get_reg(jit_class_gpr); - subi(rn(reg), r1, i0); - VLDR_F32(r0, rn(reg), 0); - jit_unget_reg(reg); - } + jit_gpr_t reg = get_temp_gpr(_jit); + subi(_jit, jit_gpr_regno(reg), r0, i0); + VSTR_F64(_jit, r1, jit_gpr_regno(reg), 0); + unget_temp_gpr(_jit); } } - else - ldxi_i(r0, r1, i0); } static void -_vfp_ldxi_d(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +retr_d(jit_state_t *_jit, int32_t r) { - int32_t reg; - if (jit_fpr_p(r0)) { - if (i0 >= 0) { - assert(!(i0 & 3)); - if (i0 < 1024) - VLDR_F64(r0, r1, i0 >> 2); - else { - reg = jit_get_reg(jit_class_gpr); - addi(rn(reg), r1, i0); - VLDR_F64(r0, rn(reg), 0); - jit_unget_reg(reg); - } - } - else { - i0 = -i0; - assert(!(i0 & 3)); - if (i0 < 1024) - VLDRN_F64(r0, r1, i0 >> 2); - else { - reg = jit_get_reg(jit_class_gpr); - subi(rn(reg), r1, i0); - VLDR_F64(r0, rn(reg), 0); - jit_unget_reg(reg); - } - } - } - else { - reg = jit_get_reg(jit_class_gpr); - addi(rn(reg), r1, i0); - ldr_i(r0, rn(reg)); - ldxi_i(r0 + 1, rn(reg), 4); - jit_unget_reg(reg); - } + movr_d(_jit, jit_fpr_regno(_D0), r); + ret(_jit); } static void -_vfp_sti_f(jit_state_t *_jit, jit_word_t i0, int32_t r0) +retr_f(jit_state_t *_jit, int32_t r) { - int32_t reg; - if (jit_fpr_p(r0)) { - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - VSTR_F32(r0, rn(reg), 0); - jit_unget_reg(reg); - } - else - sti_i(i0, r0); + movr_f(_jit, jit_fpr_regno(_S0), r); + ret(_jit); } static void -_vfp_sti_d(jit_state_t *_jit, jit_word_t i0, int32_t r0) +retval_f(jit_state_t *_jit, int32_t r0) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - if (jit_fpr_p(r0)) - VSTR_F64(r0, rn(reg), 0); - else { - str_i(rn(reg), r0); - stxi_i(4, rn(reg), r0 + 1); - } - jit_unget_reg(reg); + movr_f(_jit, r0, jit_fpr_regno(_S0)); } static void -_vfp_stxr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +retval_d(jit_state_t *_jit, int32_t r0) { - int32_t reg; - if (jit_fpr_p(r2)) { - reg = jit_get_reg(jit_class_gpr); - addr(rn(reg), r0, r1); - VSTR_F32(r2, rn(reg), 0); - jit_unget_reg(reg); - } - else - stxr_i(r0, r1, r2); -} - -static void -_vfp_stxr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) -{ - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - addr(rn(reg), r0, r1); - if (jit_fpr_p(r2)) - VSTR_F64(r2, rn(reg), 0); - else { - str_i(rn(reg), r2); - stxi_i(4, rn(reg), r2 + 1); - } - jit_unget_reg(reg); -} - -static void -_vfp_stxi_f(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) -{ - int32_t reg; - if (jit_fpr_p(r1)) { - if (i0 >= 0) { - assert(!(i0 & 3)); - if (i0 < 1024) - VSTR_F32(r1, r0, i0 >> 2); - else { - reg = jit_get_reg(jit_class_gpr); - addi(rn(reg), r0, i0); - VSTR_F32(r1, rn(reg), 0); - jit_unget_reg(reg); - } - } - else { - i0 = -i0; - assert(!(i0 & 3)); - if (i0 < 1024) - VSTRN_F32(r1, r0, i0 >> 2); - else { - reg = jit_get_reg(jit_class_gpr); - subi(rn(reg), r0, i0); - VSTR_F32(r1, rn(reg), 0); - jit_unget_reg(reg); - } - } - } - else - stxi_i(i0, r0, r1); -} - -static void -_vfp_stxi_d(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) -{ - int32_t reg; - if (jit_fpr_p(r1)) { - if (i0 >= 0) { - assert(!(i0 & 3)); - if (i0 < 0124) - VSTR_F64(r1, r0, i0 >> 2); - else { - reg = jit_get_reg(jit_class_gpr); - addi(rn(reg), r0, i0); - VSTR_F64(r1, rn(reg), 0); - jit_unget_reg(reg); - } - } - else { - i0 = -i0; - assert(!(i0 & 3)); - if (i0 < 1024) - VSTRN_F64(r1, r0, i0 >> 2); - else { - reg = jit_get_reg(jit_class_gpr); - subi(rn(reg), r0, i0); - VSTR_F64(r1, rn(reg), 0); - jit_unget_reg(reg); - } - } - } - else { - reg = jit_get_reg(jit_class_gpr); - addi(rn(reg), r0, i0); - str_i(rn(reg), r1); - stxi_i(4, rn(reg), r1 + 1); - jit_unget_reg(reg); - } -} - -static void -_vfp_vaarg_d(jit_state_t *_jit, int32_t r0, int32_t r1) -{ - int32_t reg; - - assert(_jitc->function->self.call & jit_call_varargs); - - /* Adjust pointer. */ - reg = jit_get_reg(jit_class_gpr); - andi(rn(reg), r1, 7); - addr(r1, r1, rn(reg)); - jit_unget_reg(reg); - - /* Load argument. */ - vfp_ldr_d(r0, r1); - - /* Update stack pointer. */ - addi(r1, r1, sizeof(jit_float64_t)); + movr_d(_jit, r0, jit_fpr_regno(_D0)); } diff --git a/lightening/arm.h b/lightening/arm.h index b4f64667d..8db672ea0 100644 --- a/lightening/arm.h +++ b/lightening/arm.h @@ -99,13 +99,13 @@ #define JIT_V0 _R4 #define JIT_V1 _R5 #define JIT_V2 _R6 -#define JIT_V3 _R7 -#define JIT_V4 _R8 -#define JIT_V5 _R9 -#define JIT_V6 _R10 -#define JIT_V7 _R11 +#define JIT_TMP1 _R7 +#define JIT_V3 _R8 +#define JIT_V4 _R9 +#define JIT_V5 _R10 +#define JIT_V6 _R11 -#define _SP _R13 +#define JIT_SP _R13 #define _LR _R14 #define _PC _R15 @@ -127,7 +127,7 @@ #define JIT_VF6 _D14 #define JIT_VF7 _D15 -#define JIT_PLATFORM_CALLEE_SAVE_GPRS _LR +#define JIT_PLATFORM_CALLEE_SAVE_GPRS _LR, JIT_TMP1 #endif /* _jit_arm_h */ diff --git a/lightening/lightening.c b/lightening/lightening.c index e03dbda4c..2a1d282a6 100644 --- a/lightening/lightening.c +++ b/lightening/lightening.c @@ -1328,11 +1328,11 @@ emit_literal_pool(jit_state_t *_jit, enum guard_pool guard) switch (entry->reloc.kind) { case JIT_RELOC_JMP_WITH_VENEER: patch_jmp_offset((uint32_t*) loc, diff); - emit_veneer(_jit, (void*) entry->value); + emit_veneer(_jit, (void*) (uintptr_t) entry->value); break; case JIT_RELOC_JCC_WITH_VENEER: patch_jcc_offset((uint32_t*) loc, diff); - emit_veneer(_jit, (void*) entry->value); + emit_veneer(_jit, (void*) (uintptr_t) entry->value); break; case JIT_RELOC_LOAD_FROM_POOL: patch_load_from_pool_offset((uint32_t*) loc, diff); From 0b723c0401bc5f037199b75c14848121a987053a Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Mon, 20 May 2019 15:20:33 +0200 Subject: [PATCH 29/33] ARMv7 backend passing all tests! --- lightening/aarch64.c | 6 +++ lightening/arm-cpu.c | 104 ++++++++++++++++++++++++---------------- lightening/arm.c | 9 +++- lightening/arm.h | 4 +- lightening/lightening.c | 27 ++++++----- lightening/x86.c | 6 +++ 6 files changed, 100 insertions(+), 56 deletions(-) diff --git a/lightening/aarch64.c b/lightening/aarch64.c index 1964cb9bd..66fb27b61 100644 --- a/lightening/aarch64.c +++ b/lightening/aarch64.c @@ -223,3 +223,9 @@ static void jit_try_shorten(jit_state_t *_jit, jit_reloc_t reloc, jit_pointer_t addr) { } + +static void* +bless_function_pointer(void *ptr) +{ + return ptr; +} diff --git a/lightening/arm-cpu.c b/lightening/arm-cpu.c index 012b73ae8..e758bfd28 100644 --- a/lightening/arm-cpu.c +++ b/lightening/arm-cpu.c @@ -126,11 +126,14 @@ #define THUMB_TST 0x4200 #define THUMB2_TST 0xea100000 #define THUMB2_TSTI 0xf0100000 +#define THUMB_BLX 0x4780 +#define THUMB_BX 0x4700 #define THUMB_CC_B 0xd000 #define THUMB_B 0xe000 #define THUMB2_CC_B 0xf0008000 #define THUMB2_B 0xf0009000 #define THUMB2_BLI 0xf000d000 +#define THUMB2_BLXI 0xf000c000 #define THUMB2_P 0x00000400 #define THUMB2_U 0x00000200 #define THUMB_LDRSB 0x5600 @@ -245,8 +248,8 @@ encode_thumb_word_immediate(unsigned int v) static uint32_t read_wide_thumb(uint32_t *loc) { - uint16_t *sloc = (uint16_t*)sloc; - return (((uint32_t)sloc[0]) << 16) | sloc[1]; + uint16_t *sloc = (uint16_t*)loc; + return (sloc[0] << 16) | sloc[1]; } static void @@ -344,15 +347,13 @@ decode_thumb_cc_jump(uint32_t v) uint32_t s = (v >> 26) & 1; uint32_t j1 = (v >> 13) & 1; uint32_t j2 = (v >> 11) & 1; - uint32_t i1 = s ? j1 : !j1; - uint32_t i2 = s ? j2 : !j2; uint32_t hi = (v >> 16) & 0x3f; uint32_t lo = v & 0x7ff; int32_t ret = s << 31; ret >>= 12; - ret |= i1 << 18; - ret |= i2 << 17; + ret |= j2 << 18; + ret |= j1 << 17; ret |= hi << 11; ret |= lo; return ret; @@ -365,9 +366,11 @@ encode_thumb_cc_jump(int32_t v) { ASSERT(offset_in_jcc_range(v)); uint32_t s = !!(v & 0x80000); - uint32_t j1 = !!(v & 0x40000); - uint32_t j2 = !!(v & 0x20000); - uint32_t ret = (s<<26)|((v&0x1f800)<<5)|(j1<<13)|(j2<<11)|(v&0x7ff); + uint32_t j2 = !!(v & 0x40000); + uint32_t j1 = !!(v & 0x20000); + uint32_t hi = (v >> 11) & 0x3f; + uint32_t lo = v & 0x7ff; + uint32_t ret = (s<<26)|(hi << 16)|(j1<<13)|(j2<<11)|lo; ASSERT(decode_thumb_cc_jump(ret) == v); ASSERT((ret & thumb_cc_jump_mask) == 0); return ret; @@ -408,68 +411,68 @@ emit_thumb_cc_jump(jit_state_t *_jit, uint32_t inst) static void torrr(jit_state_t *_jit, int o, int rn, int rd, int rm) { - assert(!(o & 0xf0f0f)); + ASSERT(!(o & 0xf0f0f)); emit_wide_thumb(_jit, o|(_u4(rn)<<16)|(_u4(rd)<<8)|_u4(rm)); } static void torxr(jit_state_t *_jit, int o, int rn, int rt, int rm) { - assert(!(o & 0xf0f0f)); + ASSERT(!(o & 0xf0f0f)); emit_wide_thumb(_jit, o|(_u4(rn)<<16)|(_u4(rt)<<12)|_u4(rm)); } static void torrrr(jit_state_t *_jit, int o, int rn, int rl, int rh, int rm) { - assert(!(o & 0x000fff0f)); + ASSERT(!(o & 0x000fff0f)); emit_wide_thumb(_jit, o|(_u4(rn)<<16)|(_u4(rl)<<12)|(_u4(rh)<<8)|_u4(rm)); } static void torri(jit_state_t *_jit, int o, int rn, int rd, int im) { - assert(!(o & 0x0c0f7fff)); - assert(!(im & 0xfbff8f00)); + ASSERT(!(o & 0x0c0f7fff)); + ASSERT(!(im & 0xfbff8f00)); emit_wide_thumb(_jit, o|(_u4(rn)<<16)|(_u4(rd)<<8)|im); } static void torri8(jit_state_t *_jit, int o, int rn, int rt, int im) { - assert(!(o & 0x000ff0ff)); - assert(!(im & 0xffffff00)); + ASSERT(!(o & 0x000ff0ff)); + ASSERT(!(im & 0xffffff00)); emit_wide_thumb(_jit, o|(_u4(rn)<<16)|(_u4(rt)<<12)|im); } static void torri12(jit_state_t *_jit, int o, int rn, int rt, int im) { - assert(!(o & 0x000fffff)); - assert(!(im & 0xfffff000)); + ASSERT(!(o & 0x000fffff)); + ASSERT(!(im & 0xfffff000)); emit_wide_thumb(_jit, o|(_u4(rn)<<16)|(_u4(rt)<<12)|im); } static void tshift(jit_state_t *_jit, int o, int rd, int rm, int im) { - assert(!(o & 0x7fcf)); - assert(im >= 0 && im < 32); + ASSERT(!(o & 0x7fcf)); + ASSERT(im >= 0 && im < 32); emit_wide_thumb(_jit, o|((im&0x1c)<<10)|(_u4(rd)<<8)|((im&3)<<6)|_u4(rm)); } static void toriw(jit_state_t *_jit, int o, int rd, int im) { - assert(!(im & 0xffff0000)); + ASSERT(!(im & 0xffff0000)); emit_wide_thumb(_jit, o|((im&0xf000)<<4)|((im&0x800)<<15)|((im&0x700)<<4)|(_u4(rd)<<8)|(im&0xff)); } static jit_reloc_t tcb(jit_state_t *_jit, int cc) { - assert(!(cc & 0xfffffff)); - assert(cc != ARM_CC_AL && cc != ARM_CC_NV); + ASSERT(!(cc & 0xfffffff)); + ASSERT(cc != ARM_CC_AL && cc != ARM_CC_NV); cc = ((uint32_t)cc) >> 6; return emit_thumb_cc_jump(_jit, THUMB2_CC_B|cc); } @@ -477,7 +480,7 @@ tcb(jit_state_t *_jit, int cc) static jit_reloc_t tb(jit_state_t *_jit, int o) { - assert(!(o & 0x07ff2fff)); + ASSERT(!(o & 0x07ff2fff)); return emit_thumb_jump(_jit, o); } @@ -772,7 +775,7 @@ T2_UDIV(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t rm) static void T1_MLS(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t rm, int32_t ra) { - return torrrr(_jit, THUMB_MLS, ra, rn, rd, rm); + return torrrr(_jit, THUMB_MLS, rn, ra, rd, rm); } static void @@ -985,6 +988,18 @@ T2_TSTI(jit_state_t *_jit, int32_t rn, int32_t im) return torri(_jit, THUMB2_TSTI,rn,_NOREG,im); } +static void +T1_BLX(jit_state_t *_jit, int32_t r0) +{ + emit_u16(_jit, THUMB_BLX|(_u4(r0)<<3)); +} + +static void +T1_BX(jit_state_t *_jit, int32_t r0) +{ + emit_u16(_jit, THUMB_BX|(_u4(r0)<<3)); +} + static jit_reloc_t T2_CC_B(jit_state_t *_jit, uint32_t cc) { @@ -1003,6 +1018,12 @@ T2_BLI(jit_state_t *_jit) return tb(_jit, THUMB2_BLI); } +static jit_reloc_t +T2_BLXI(jit_state_t *_jit) +{ + return tb(_jit, THUMB2_BLXI); +} + static void T1_LDRSB(jit_state_t *_jit, int32_t rt, int32_t rn, int32_t rm) { @@ -1297,7 +1318,7 @@ nop(jit_state_t *_jit, int32_t i0) for (; i0 > 0; i0 -= 2) T1_NOP(_jit); - assert(i0 == 0); + ASSERT(i0 == 0); } static void @@ -1353,12 +1374,8 @@ static uint32_t encode_load_from_pool_offset(int32_t off) { ASSERT(offset_in_load_from_pool_range(off)); - uint32_t u; - if (off >= 0) - u = 1; - else - u = 0, off = -off; - uint32_t ret = (off & 0xfff) | (u << 23); + uint32_t u = off >= 0; + uint32_t ret = ((u ? off : -off) & 0xfff) | (u << 23); ASSERT(decode_load_from_pool_offset(ret) == off); return ret; } @@ -1766,7 +1783,7 @@ iqdivr(jit_state_t *_jit, int32_t r0, int32_t r1, divr(_jit, r0, r2, r3); else divr_u(_jit, r0, r2, r3); - T1_MLS(_jit, r1, r0, r3, r2); + T1_MLS(_jit, r1, r3, r0, r2); if (need_tmp) unget_temp_gpr(_jit); } @@ -1808,7 +1825,7 @@ qdivi_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, int32_t i0) static void iremr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, jit_bool_t sign) { - return iqdivr(_jit, r0, r0, r1, r2, 1); + return iqdivr(_jit, r0, r0, r1, r2, sign); } static void @@ -1936,7 +1953,7 @@ lshr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) static void lshi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - assert(i0 >= 0 && i0 <= 31); + ASSERT(i0 >= 0 && i0 <= 31); if (i0 == 0) movr(_jit, r0, r1); else { @@ -1959,7 +1976,7 @@ rshr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) static void rshi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - assert(i0 >= 0 && i0 <= 31); + ASSERT(i0 >= 0 && i0 <= 31); if (i0 == 0) movr(_jit, r0, r1); else { @@ -1982,7 +1999,7 @@ rshr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) static void rshi_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - assert(i0 >= 0 && i0 <= 31); + ASSERT(i0 >= 0 && i0 <= 31); if (i0 == 0) movr(_jit, r0, r1); else { @@ -2008,6 +2025,8 @@ jmp(jit_state_t *_jit) static void jmpi(jit_state_t *_jit, jit_word_t i0) { + /* Strip thumb bit, if any. */ + i0 &= ~1; return jit_patch_there(_jit, jmp(_jit), (void*)i0); } @@ -2841,21 +2860,22 @@ extr_us(jit_state_t *_jit, int32_t r0, int32_t r1) static void callr(jit_state_t *_jit, int32_t r0) { - T1_MOV(_jit, jit_gpr_regno(_LR), jit_gpr_regno(_PC)); - T1_MOV(_jit, jit_gpr_regno(_PC), r0); - // LR will point here: 4 bytes after the MOV LR,PC instruction. + T1_BLX(_jit, r0); } static void calli(jit_state_t *_jit, jit_word_t i0) { - jit_patch_there(_jit, T2_BLI(_jit), (void*)i0); + if (i0 & 1) + jit_patch_there(_jit, T2_BLI(_jit), (void*)(i0 & ~1)); + else + jit_patch_there(_jit, T2_BLXI(_jit), (void*)i0); } static void ret(jit_state_t *_jit) { - movr(_jit, jit_gpr_regno(_PC), jit_gpr_regno(_LR)); + T1_BX(_jit, jit_gpr_regno(_LR)); } static void diff --git a/lightening/arm.c b/lightening/arm.c index be0e629e8..d587e7158 100644 --- a/lightening/arm.c +++ b/lightening/arm.c @@ -109,7 +109,7 @@ next_abi_arg(struct abi_arg_iterator *iter, jit_operand_t *arg) } } *arg = jit_operand_mem (abi, JIT_SP, iter->stack_size); - iter->stack_size += 8; + iter->stack_size += 4; } static void @@ -130,3 +130,10 @@ static void jit_try_shorten(jit_state_t *_jit, jit_reloc_t reloc, jit_pointer_t addr) { } + +static void* +bless_function_pointer(void *ptr) +{ + // Set low bit to mark as thumb mode. + return (void*) (((uintptr_t)ptr) | 1); +} diff --git a/lightening/arm.h b/lightening/arm.h index 8db672ea0..47bd2c257 100644 --- a/lightening/arm.h +++ b/lightening/arm.h @@ -93,8 +93,8 @@ #define JIT_R0 _R0 #define JIT_R1 _R1 #define JIT_R2 _R2 -#define JIT_R3 _R12 -#define JIT_TMP0 _R3 +#define JIT_R3 _R3 +#define JIT_TMP0 _R12 #define JIT_V0 _R4 #define JIT_V1 _R5 diff --git a/lightening/lightening.c b/lightening/lightening.c index 2a1d282a6..572976f40 100644 --- a/lightening/lightening.c +++ b/lightening/lightening.c @@ -88,6 +88,7 @@ static jit_bool_t jit_init(jit_state_t *); static void jit_flush(void *fptr, void *tptr); static void jit_try_shorten(jit_state_t *_jit, jit_reloc_t reloc, jit_pointer_t addr); +static void* bless_function_pointer(void *ptr); struct abi_arg_iterator; @@ -239,7 +240,7 @@ jit_end(jit_state_t *_jit, size_t *length) clear_literal_pool(_jit->pool); #endif - return start; + return bless_function_pointer(start); } static int @@ -387,7 +388,8 @@ jit_patch_there(jit_state_t* _jit, jit_reloc_t reloc, jit_pointer_t addr) #ifdef JIT_NEEDS_LITERAL_POOL case JIT_RELOC_JMP_WITH_VENEER: { int32_t voff = read_jmp_offset(loc.ui); - if (voff == 0) { + uint8_t *target = pc_base + (voff << reloc.rsh); + if (target == loc.uc) { // PC still in range to reify direct branch. if (offset_in_jmp_range(diff)) { // Target also in range: reify direct branch. @@ -400,14 +402,14 @@ jit_patch_there(jit_state_t* _jit, jit_reloc_t reloc, jit_pointer_t addr) } else { // Already emitted a veneer. In this case, patch the veneer // directly. - uint8_t *target = pc_base + (voff << reloc.rsh); patch_veneer((uint32_t *) target, addr); } return; } case JIT_RELOC_JCC_WITH_VENEER: { - uint32_t voff = read_jcc_offset(loc.ui); - if (voff == 0) { + int32_t voff = read_jcc_offset(loc.ui); + uint8_t *target = pc_base + (voff << reloc.rsh); + if (target == loc.uc) { if (offset_in_jcc_range(diff)) { patch_jcc_offset(loc.ui, diff); remove_pending_literal(_jit, reloc); @@ -415,17 +417,16 @@ jit_patch_there(jit_state_t* _jit, jit_reloc_t reloc, jit_pointer_t addr) patch_pending_literal(_jit, reloc, (uintptr_t) addr); } } else { - uint8_t *target = pc_base + (voff << reloc.rsh); patch_veneer((uint32_t *) target, addr); } return; } case JIT_RELOC_LOAD_FROM_POOL: { - uint32_t voff = read_load_from_pool_offset(loc.ui); - if (voff == 0) { + int32_t voff = read_load_from_pool_offset(loc.ui); + uint8_t *target = pc_base + (voff << reloc.rsh); + if (target == loc.uc) { patch_pending_literal(_jit, reloc, (uintptr_t) addr); } else { - uint8_t *target = pc_base + (voff << reloc.rsh); *(uintptr_t *) target = (uintptr_t) addr; } return; @@ -782,7 +783,11 @@ move_operand(jit_state_t *_jit, jit_operand_t dst, jit_operand_t src) src.loc.mem.offset); case MOVE_FPR_TO_FPR: - return jit_movr_d(_jit, dst.loc.fpr, src.loc.fpr); + ASSERT(src.abi == dst.abi); + if (src.abi == JIT_OPERAND_ABI_DOUBLE) + return jit_movr_d(_jit, dst.loc.fpr, src.loc.fpr); + else + return jit_movr_f(_jit, dst.loc.fpr, src.loc.fpr); case MOVE_MEM_TO_FPR: return abi_mem_to_fpr(_jit, src.abi, dst.loc.fpr, src.loc.mem.base, @@ -1145,7 +1150,7 @@ prepare_call_args(jit_state_t *_jit, size_t argc, jit_operand_t args[]) for (size_t i = 0; i < argc; i++) { switch(args[i].kind) { case JIT_OPERAND_KIND_GPR: - if (jit_same_gprs (args[i].loc.mem.base, JIT_SP)) + if (jit_same_gprs (args[i].loc.gpr.gpr, JIT_SP)) args[i].loc.gpr.addend += stack_size; break; case JIT_OPERAND_KIND_MEM: diff --git a/lightening/x86.c b/lightening/x86.c index 4d0f7b9a2..965191a4c 100644 --- a/lightening/x86.c +++ b/lightening/x86.c @@ -399,3 +399,9 @@ jit_try_shorten(jit_state_t *_jit, jit_reloc_t reloc, jit_pointer_t addr) abort (); } } + +static void* +bless_function_pointer(void *ptr) +{ + return ptr; +} From 0b7c0367d4d39df895eb5990eab65285e7e39ea4 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Mon, 20 May 2019 15:25:03 +0200 Subject: [PATCH 30/33] Add ARMv7 testing to CI --- .gitlab-ci.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a445b678c..e4893a461 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -3,13 +3,14 @@ image: debian:testing before_script: - dpkg --add-architecture i386 - dpkg --add-architecture arm64 + - dpkg --add-architecture armhf - apt-get update -qq - apt-get install -y libc6-dev:amd64 gcc make qemu binfmt-support qemu-user-static gcc-i686-linux-gnu libc6-dev-i386-cross libc6:i386 gcc-aarch64-linux-gnu libc6-dev-arm64-cross libc6:arm64 - - update-binfmts --display + gcc-armhf-linux-gnu libc6-dev-armhf-cross libc6:armhf x86-64: stage: test @@ -25,3 +26,8 @@ aarch64: stage: test script: - make -C tests test-aarch64 CC_AARCH64=aarch64-linux-gnu-gcc + +armhf: + stage: test + script: + - make -C tests test-armhf CC_ARMv7=armhf-linux-gnu-gcc From 0b5f05a8a5c568021600f67f23f0ed360e357bca Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Mon, 20 May 2019 15:30:06 +0200 Subject: [PATCH 31/33] Attempt to get CI working on ARMv7 --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e4893a461..5237ea945 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -10,7 +10,7 @@ before_script: qemu binfmt-support qemu-user-static gcc-i686-linux-gnu libc6-dev-i386-cross libc6:i386 gcc-aarch64-linux-gnu libc6-dev-arm64-cross libc6:arm64 - gcc-armhf-linux-gnu libc6-dev-armhf-cross libc6:armhf + gcc-arm-linux-gnueabihf libc6-dev-armhf-cross libc6:armhf x86-64: stage: test @@ -30,4 +30,4 @@ aarch64: armhf: stage: test script: - - make -C tests test-armhf CC_ARMv7=armhf-linux-gnu-gcc + - make -C tests test-armhf CC_ARMv7=arm-linux-gnueabihf-gcc From c671c0868ea3da9e8c89b21b81badb463ea146a8 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Mon, 20 May 2019 15:38:37 +0200 Subject: [PATCH 32/33] Fix CI on ARMv7 --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5237ea945..43528960f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -30,4 +30,4 @@ aarch64: armhf: stage: test script: - - make -C tests test-armhf CC_ARMv7=arm-linux-gnueabihf-gcc + - make -C tests test-armv7 CC_ARMv7=arm-linux-gnueabihf-gcc From 2e53911c22a29af69f922e16aff1b4ad00254cd4 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Mon, 20 May 2019 15:45:51 +0200 Subject: [PATCH 33/33] Update README --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 14e33783b..515c3ee06 100644 --- a/README.md +++ b/README.md @@ -30,10 +30,14 @@ functionality, and Lightening wraps it all in a lightweight API. ## Supported targets -Lightening can generate code for the x86-64, i686, and AArch64 +Lightening can generate code for the x86-64, i686, ARMv7, and AArch64 architectures. It supports the calling conventions of MS Windows, GNU/Linux, and Mac OS. +On i686, Lightening requires SSE support. On ARMv7, we require hardware +floating-point support (the VFP instructions), as well as the UDIV/SDIV +instructions. + Lightening is automatically tested using GitLab's continuous integration for under the supported architectures, for GNU/Linux; for a list of recent jobs, see [the CI @@ -41,8 +45,6 @@ page](https://gitlab.com/wingo/lightening/-/jobs). ## Future targets -ARMv7 support will come soon. - Lightening has some inherited code from GNU Lightning for MIPS, PPC64, and s390. Patches to adapt this code to the Lightening code structure are quite welcome.