diff options
Diffstat (limited to 'libguile')
20 files changed, 7180 insertions, 15192 deletions
diff --git a/libguile/lightening/.gitlab-ci.yml b/libguile/lightening/.gitlab-ci.yml index 891112e87..43528960f 100644 --- a/libguile/lightening/.gitlab-ci.yml +++ b/libguile/lightening/.gitlab-ci.yml @@ -1,12 +1,16 @@ -# 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 +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 libc6-dev:i386 gcc gcc-multilib make + - 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 + gcc-arm-linux-gnueabihf libc6-dev-armhf-cross libc6:armhf x86-64: stage: test @@ -16,4 +20,14 @@ x86-64: i686: stage: test script: - - make -C tests test-ia32 + - make -C tests test-ia32 CC_IA32=i686-linux-gnu-gcc + +aarch64: + stage: test + script: + - make -C tests test-aarch64 CC_AARCH64=aarch64-linux-gnu-gcc + +armhf: + stage: test + script: + - make -C tests test-armv7 CC_ARMv7=arm-linux-gnueabihf-gcc diff --git a/libguile/lightening/README.md b/libguile/lightening/README.md index 7eb499435..515c3ee06 100644 --- a/libguile/lightening/README.md +++ b/libguile/lightening/README.md @@ -28,10 +28,30 @@ 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, 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 +page](https://gitlab.com/wingo/lightening/-/jobs). + +## Future targets + +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/libguile/lightening/lightening.h b/libguile/lightening/lightening.h index c3163486e..23635a01d 100644 --- a/libguile/lightening/lightening.h +++ b/libguile/lightening/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, @@ -72,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; @@ -87,20 +108,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 @@ -567,17 +574,10 @@ 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) \ \ - 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/libguile/lightening/lightening/aarch64-cpu.c b/libguile/lightening/lightening/aarch64-cpu.c index 98f2dabde..b9aea687c 100644 --- a/libguile/lightening/lightening/aarch64-cpu.c +++ b/libguile/lightening/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,2525 @@ * 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, +#if __BYTE_ORDER != __LITTLE_ENDIAN +#error AArch64 requires little-endian host +#endif + +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; + } +} + +static void +oxxx(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Rn, int32_t Rm) +{ + 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) +{ + 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 Simm9) +{ + 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) +{ + 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) +{ + uint32_t inst = Op; + inst = write_cond2_bitfield(inst, Cc); + return inst; +} + +static uint32_t +encode_o26(jit_state_t *_jit, int32_t Op) +{ + uint32_t inst = Op; + return inst; +} + +static void +ox_x(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Rm) +{ + 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) +{ + 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) +{ + 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) +{ + 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) +{ + 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) +{ + 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) +{ + 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) +{ + 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 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 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 lightening, * 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) +#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_POS 0x29800000 +#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 +#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 */ -# define ANDI(Rd,Rn,Imm12) oxxi(A64_ANDI|XS,Rd,Rn,Imm12) -# define ORR(Rd,Rn,Rm) oxxx(A64_ORR|XS,Rd,Rn,Rm) +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 */ -# define ORRI(Rd,Rn,Imm12) oxxi(A64_ORRI|XS,Rd,Rn,Imm12) -# define EOR(Rd,Rn,Rm) oxxx(A64_EOR|XS,Rd,Rn,Rm) +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 */ -# 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); -#endif +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); +} -#if CODE -static int32_t -logical_immediate(jit_word_t imm) +static void +SXTB(jit_state_t *_jit, int32_t Rd, int32_t Rn) { - /* 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); - } + return SBFM(_jit, Rd,Rn,0,7); } static void -_oxxx(jit_state_t *_jit, int32_t Op, - int32_t Rd, int32_t Rn, int32_t Rm) +SXTH(jit_state_t *_jit, int32_t Rd, int32_t Rn) { - 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); + return SBFM(_jit, Rd,Rn,0,15); } static void -_oxxi(jit_state_t *_jit, int32_t Op, - int32_t Rd, int32_t Rn, int32_t Imm12) +SXTW(jit_state_t *_jit, int32_t Rd, int32_t Rn) { - 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); + return SBFM(_jit, Rd,Rn,0,31); } static void -_oxx9(jit_state_t *_jit, int32_t Op, - int32_t Rd, int32_t Rn, int32_t Imm9) +UXTB(jit_state_t *_jit, int32_t Rd, int32_t Rn) { - 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); + return UBFX(_jit, Rd,Rn,0,7); } static void -_ox19(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Simm19) +UXTH(jit_state_t *_jit, int32_t Rd, int32_t Rn) { - 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); + return UBFX(_jit, Rd,Rn,0,15); } static void -_oc19(jit_state_t *_jit, int32_t Op, int32_t Cc, int32_t Simm19) +UXTW(jit_state_t *_jit, int32_t Rd, int32_t Rm) { - 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); + return ox_x(_jit, A64_UXTW,Rd,Rm); } static void -_o26(jit_state_t *_jit, int32_t Op, int32_t Simm26) +REV(jit_state_t *_jit, int32_t Rd, int32_t Rn) { - instr_t i; - assert(Simm26 >= -33554432 && Simm26 <= 33554431); - assert(!(Op & ~0xfc000000)); - i.w = Op; - i.imm26.b = Simm26; - ii(i.w); + return o_xx(_jit, A64_REV,Rd,Rn); } static void -_ox_x(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Rm) +LDRSB(jit_state_t *_jit, int32_t Rt, int32_t Rn, 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); + return oxxx(_jit, A64_LDRSB,Rt,Rn,Rm); } static void -_o_xx(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Rn) +LDRSBI(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm12) { - 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); + return oxxi(_jit, A64_LDRSBI,Rt,Rn,Imm12); } static void -_oxx_(jit_state_t *_jit, int32_t Op, int32_t Rn, int32_t Rm) +LDURSB(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm9) { - 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); + return oxx9(_jit, A64_LDURSB,Rt,Rn,Imm9); } static void -_o_x_(jit_state_t *_jit, int32_t Op, int32_t Rn) +LDRB(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Rm) { - instr_t i; - assert(!(Rn & ~0x1f)); - assert(!(Op & 0x3e0)); - i.w = Op; - i.Rn.b = Rn; - ii(i.w); + return oxxx(_jit, A64_LDRB,Rt,Rn,Rm); } static void -_ox_h(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Imm16) +LDRBI(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm12) { - 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); + return oxxi(_jit, A64_LDRBI,Rt,Rn,Imm12); } static void -_oxxrs(jit_state_t *_jit, int32_t Op, - int32_t Rd, int32_t Rn, int32_t R, int32_t S) +LDURB(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm9) { - 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); + return oxx9(_jit, A64_LDURB,Rt,Rn,Imm9); } static void -_oxxxc(jit_state_t *_jit, int32_t Op, - int32_t Rd, int32_t Rn, int32_t Rm, int32_t Cc) +LDRSH(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Rm) { - 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); + return oxxx(_jit, A64_LDRSH,Rt,Rn,Rm); } static void -_oxxx7(jit_state_t *_jit, int32_t Op, - int32_t Rt, int32_t Rt2, int32_t Rn, int32_t Simm7) +LDRSHI(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm12) { - 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); + return oxxi(_jit, A64_LDRSHI,Rt,Rn,Imm12); } static void -_nop(jit_state_t *_jit, int32_t i0) +LDURSH(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm9) { - for (; i0 > 0; i0 -= 4) - NOP(); - assert(i0 == 0); + return oxx9(_jit, A64_LDURSH,Rt,Rn,Imm9); } static void -_addi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +LDRH(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Rm) { - 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); - } + return oxxx(_jit, A64_LDRH,Rt,Rn,Rm); } 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); - } +LDRHI(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm12) +{ + return oxxi(_jit, A64_LDRHI,Rt,Rn,Imm12); } static void -_addxi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +LDURH(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm9) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - addxr(r0, r1, rn(reg)); - jit_unget_reg(reg); + return oxx9(_jit, A64_LDURH,Rt,Rn,Imm9); } static void -_subi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +LDRSW(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Rm) { - 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); - } + return oxxx(_jit, A64_LDRSW,Rt,Rn,Rm); } static void -_subci(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +LDRSWI(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm12) { - 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); - } + return oxxi(_jit, A64_LDRSWI,Rt,Rn,Imm12); } static void -_subxi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +LDURSW(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm9) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - subxr(r0, r1, rn(reg)); - jit_unget_reg(reg); + return oxx9(_jit, A64_LDURSW,Rt,Rn,Imm9); } static void -_rsbi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +LDRW(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Rm) { - subi(r0, r1, i0); - negr(r0, r0); + return oxxx(_jit, A64_LDRW,Rt,Rn,Rm); } static void -_muli(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +LDRWI(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm12) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - mulr(r0, r1, rn(reg)); - jit_unget_reg(reg); + return oxxi(_jit, A64_LDRWI,Rt,Rn,Imm12); } static void -_qmulr(jit_state_t *_jit, int32_t r0, - int32_t r1, int32_t r2, int32_t r3) +LDURW(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm9) { - 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); - SMULH(r1, r2, r3); - if (r0 == r2 || r0 == r3) { - movr(r0, rn(reg)); - jit_unget_reg(reg); - } + return oxx9(_jit, A64_LDURW,Rt,Rn,Imm9); } static void -_qmuli(jit_state_t *_jit, int32_t r0, - int32_t r1, int32_t r2, jit_word_t i0) +LDR(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Rm) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - qmulr(r0, r1, r2, rn(reg)); - jit_unget_reg(reg); + return oxxx(_jit, A64_LDR,Rt,Rn,Rm); } static void -_qmulr_u(jit_state_t *_jit, int32_t r0, - int32_t r1, int32_t r2, int32_t r3) +LDRI(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm12) { - 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); - } + return oxxi(_jit, A64_LDRI,Rt,Rn,Imm12); } static void -_qmuli_u(jit_state_t *_jit, int32_t r0, - int32_t r1, int32_t r2, jit_word_t i0) +LDUR(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm9) { - 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); + return oxx9(_jit, A64_LDUR,Rt,Rn,Imm9); } static void -_divi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +STRB(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Rm) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - divr(r0, r1, rn(reg)); - jit_unget_reg(reg); + return oxxx(_jit, A64_STRB,Rt,Rn,Rm); } static void -_divi_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +STRBI(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm12) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - divr_u(r0, r1, rn(reg)); - jit_unget_reg(reg); + return oxxi(_jit, A64_STRBI,Rt,Rn,Imm12); } static void -_iqdivr(jit_state_t *_jit, jit_bool_t sign, - int32_t r0, int32_t r1, int32_t r2, int32_t r3) +STURB(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm9) { - 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); - } + return oxx9(_jit, A64_STURB,Rt,Rn,Imm9); } static void -_qdivi(jit_state_t *_jit, int32_t r0, - int32_t r1, int32_t r2, jit_word_t i0) +STRH(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Rm) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - qdivr(r0, r1, r2, rn(reg)); - jit_unget_reg(reg); + return oxxx(_jit, A64_STRH,Rt,Rn,Rm); } static void -_qdivi_u(jit_state_t *_jit, int32_t r0, - int32_t r1, int32_t r2, jit_word_t i0) +STRHI(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm12) { - 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); + return oxxi(_jit, A64_STRHI,Rt,Rn,Imm12); } static void -_remr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +STURH(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm9) { - 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); - } + return oxx9(_jit, A64_STURH,Rt,Rn,Imm9); } static void -_remi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +STRW(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Rm) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - remr(r0, r1, rn(reg)); - jit_unget_reg(reg); + return oxxx(_jit, A64_STRW,Rt,Rn,Rm); } static void -_remr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +STRWI(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm12) { - 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); - } + return oxxi(_jit, A64_STRWI,Rt,Rn,Imm12); } static void -_remi_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +STURW(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm9) { - 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 oxx9(_jit, A64_STURW,Rt,Rn,Imm9); } static void -_lshi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +STR(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Rm) { - if (i0 == 0) - movr(r0, r1); - else { - assert(i0 > 0 && i0 < 64); - LSLI(r0, r1, i0); - } + return oxxx(_jit, A64_STR,Rt,Rn,Rm); } static void -_rshi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +STRI(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm12) { - if (i0 == 0) - movr(r0, r1); - else { - assert(i0 > 0 && i0 < 64); - ASRI(r0, r1, i0); - } + return oxxi(_jit, A64_STRI,Rt,Rn,Imm12); } static void -_rshi_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +STUR(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm9) { - if (i0 == 0) - movr(r0, r1); - else { - assert(i0 > 0 && i0 < 64); - LSRI(r0, r1, i0); - } + return oxx9(_jit, A64_STUR,Rt,Rn,Imm9); } 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); - } - } +STR_PRE(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Simm9) +{ + return oxx9(_jit, A64_STR_PRE,Rt,Rn,Simm9); } 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); - } - } +LDR_POS(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Simm9) +{ + return oxx9(_jit, A64_LDR_POS,Rt,Rn,Simm9); } 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); - } - } +STP_PRE(jit_state_t *_jit, int32_t Rt, int32_t Rt2, int32_t Rn, int32_t Simm7) +{ + return oxxx7(_jit, A64_STP_PRE|XS,Rt,Rt2,Rn,Simm7); } -#if __BYTE_ORDER == __LITTLE_ENDIAN static void -_bswapr_us(jit_state_t *_jit, int32_t r0, int32_t r1) +LDP_POS(jit_state_t *_jit, int32_t Rt, int32_t Rt2, int32_t Rn, int32_t Simm7) { - bswapr_ul(r0, r1); - rshi_u(r0, r0, 48); + return oxxx7(_jit, A64_LDP_POS|XS,Rt,Rt2,Rn,Simm7); +} + +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 -_bswapr_ui(jit_state_t *_jit, int32_t r0, int32_t r1) +BR(jit_state_t *_jit, int32_t Rn) { - bswapr, 2019_ul(r0, r1); - rshi_u(r0, r0, 32); + return o_x_(_jit, A64_BR,Rn); } -#endif static void -_ldi_c(jit_state_t *_jit, int32_t r0, jit_word_t i0) +BLR(jit_state_t *_jit, int32_t Rn) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - ldr_c(r0, rn(reg)); - jit_unget_reg(reg); + return o_x_(_jit, A64_BLR,Rn); } static void -_ldr_uc(jit_state_t *_jit, int32_t r0, int32_t r1) +RET(jit_state_t *_jit) { - LDRBI(r0, r1, 0); -#if 0 - extr_uc(r0, r0); -#endif + return o_x_(_jit, A64_RET,jit_gpr_regno(_LR)); +} + +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 -_ldi_uc(jit_state_t *_jit, int32_t r0, jit_word_t i0) +NOP(jit_state_t *_jit) +{ + return emit_u32(_jit, 0xd503201f); +} + +static jit_reloc_t +movi_from_pool(jit_state_t *_jit, int32_t Rt) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - ldr_uc(r0, rn(reg)); - jit_unget_reg(reg); + return emit_load_from_pool(_jit, encode_ox19(_jit, A64_LDRI_LITERAL, Rt)); } static void -_ldi_s(jit_state_t *_jit, int32_t r0, jit_word_t i0) +emit_veneer(jit_state_t *_jit, jit_pointer_t target) { - 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 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 -_ldr_us(jit_state_t *_jit, int32_t r0, int32_t r1) +movr(jit_state_t *_jit, int32_t r0, int32_t r1) { - LDRHI(r0, r1, 0); -#if 0 - extr_us(r0, r0); -#endif + if (r0 != r1) + MOV(_jit, r0, r1); } static void -_ldi_us(jit_state_t *_jit, int32_t r0, jit_word_t i0) +addr(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); - ldr_us(r0, rn(reg)); - jit_unget_reg(reg); + return ADD(_jit,r0,r1,r2); } static void -_ldi_i(jit_state_t *_jit, int32_t r0, jit_word_t i0) +addcr(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); - ldr_i(r0, rn(reg)); - jit_unget_reg(reg); + return ADDS(_jit,r0,r1,r2); } static void -_ldr_ui(jit_state_t *_jit, int32_t r0, int32_t r1) +addxr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - LDRWI(r0, r1, 0); -#if 0 - extr_ui(r0, r0); -#endif + return ADCS(_jit,r0,r1,r2); } static void -_ldi_ui(jit_state_t *_jit, int32_t r0, jit_word_t i0) +subr(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); - ldr_ui(r0, rn(reg)); - jit_unget_reg(reg); + return SUB(_jit,r0,r1,r2); } static void -_ldi_l(jit_state_t *_jit, int32_t r0, jit_word_t i0) +subcr(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); - ldr_l(r0, rn(reg)); - jit_unget_reg(reg); + return SUBS(_jit,r0,r1,r2); } static void -_ldxr_c(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +subxr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - LDRSB(r0, r1, r2); - extr_c(r0, r0); + return SBCS(_jit,r0,r1,r2); } static void -_ldxi_c(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +mulr(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); + return MUL(_jit,r0,r1,r2); } static void -_ldxr_uc(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +divr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - LDRB(r0, r1, r2); -#if 0 - extr_uc(r0, r0); -#endif + return SDIV(_jit,r0,r1,r2); } static void -_ldxi_uc(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +divr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - 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 0 - extr_uc(r0, r0); -#endif + return UDIV(_jit,r0,r1,r2); } static void -_ldxi_s(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +iqdivr(jit_state_t *_jit, jit_bool_t sign, + int32_t r0, int32_t r1, int32_t r2, int32_t r3) { - 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); - } + 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 -_ldxr_us(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) { - LDRH(r0, r1, r2); -#if 0 - extr_us(r0, r0); -#endif + return iqdivr(_jit,1,r0,r1,r2,r3); } static void -_ldxi_us(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; - 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); - } -#if 0 - extr_us(r0, r0); -#endif + return iqdivr(_jit,0,r0,r1,r2,r3); } static void -_ldxi_i(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +lshr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - 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); - } + return LSL(_jit,r0,r1,r2); } static void -_ldxr_ui(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +rshr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - LDRW(r0, r1, r2); -#if 0 - extr_ui(r0, r0); -#endif + return ASR(_jit,r0,r1,r2); } static void -_ldxi_ui(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) { - 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); - } -#if 0 - extr_ui(r0, r0); -#endif + return LSR(_jit,r0,r1,r2); } static void -_ldxi_l(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +negr(jit_state_t *_jit, int32_t r0, int32_t r1) { - 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); - } + return NEG(_jit,r0,r1); } static void -_sti_c(jit_state_t *_jit, jit_word_t i0, int32_t r0) +comr(jit_state_t *_jit, int32_t r0, int32_t r1) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - str_c(rn(reg), r0); - jit_unget_reg(reg); + return MVN(_jit,r0,r1); } static void -_sti_s(jit_state_t *_jit, jit_word_t i0, int32_t r0) +andr(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); - str_s(rn(reg), r0); - jit_unget_reg(reg); + return AND(_jit,r0,r1,r2); } static void -_sti_i(jit_state_t *_jit, jit_word_t i0, int32_t r0) +orr(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); - str_i(rn(reg), r0); - jit_unget_reg(reg); + return ORR(_jit,r0,r1,r2); } static void -_sti_l(jit_state_t *_jit, jit_word_t i0, int32_t r0) +xorr(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); - str_l(rn(reg), r0); - jit_unget_reg(reg); + return EOR(_jit,r0,r1,r2); } static void -_stxi_c(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) +ldr_c(jit_state_t *_jit, 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); - } + return LDRSBI(_jit,r0,r1,0); } static void -_stxi_s(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) +ldr_s(jit_state_t *_jit, 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); - } + return LDRSHI(_jit,r0,r1,0); } static void -_stxi_i(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) +ldr_i(jit_state_t *_jit, 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); - } + return LDRSWI(_jit,r0,r1,0); } static void -_stxi_l(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) +ldxr_s(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - 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); - } + return LDRSH(_jit,r0,r1,r2); } static void -_movr(jit_state_t *_jit, int32_t r0, int32_t r1) -{ - if (r0 != r1) - MOV(r0, r1); -} - -static void -_movi(jit_state_t *_jit, int32_t r0, 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(); - } +ldxr_i(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + return LDRSW(_jit,r0,r1,r2); } -static jit_word_t -_movi_p(jit_state_t *_jit, int32_t r0, jit_word_t i0) +static void +ldxr_l(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - 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 LDR(_jit,r0,r1,r2); } static void -_ccr(jit_state_t *_jit, int32_t cc, - int32_t r0, int32_t r1, int32_t r2) +str_c(jit_state_t *_jit, int32_t r0, int32_t r1) { - CMP(r1, r2); - CSET(r0, cc); + return STRBI(_jit,r1,r0,0); } static void -_cci(jit_state_t *_jit, int32_t cc, - int32_t r0, int32_t r1, jit_word_t i0) +str_s(jit_state_t *_jit, int32_t r0, int32_t r1) { - 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); + return STRHI(_jit,r1,r0,0); } -static jit_word_t -_beqi(jit_state_t *_jit, jit_word_t i0, int32_t r0, jit_word_t i1) +static void +str_i(jit_state_t *_jit, int32_t r0, int32_t r1) { - 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); + return STRWI(_jit,r1,r0,0); } -static jit_word_t -_bnei(jit_state_t *_jit, jit_word_t i0, int32_t r0, jit_word_t i1) +static void +str_l(jit_state_t *_jit, int32_t r0, int32_t r1) { - 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); + return STRI(_jit,r1,r0,0); } -static jit_word_t -_baddr(jit_state_t *_jit, int32_t cc, - jit_word_t i0, int32_t r0, int32_t r1) +static void +stxr_c(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - jit_word_t w; - addcr(r0, r0, r1); - w = _jit->pc.w; - B_C(cc, (i0 - w) >> 2); - return (w); + return STRB(_jit,r2,r1,r0); } -static jit_word_t -_baddi(jit_state_t *_jit, int32_t cc, - jit_word_t i0, int32_t r0, jit_word_t i1) +static void +stxr_s(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - jit_word_t w; - addci(r0, r0, i1); - w = _jit->pc.w; - B_C(cc, (i0 - w) >> 2); - return (w); + return STRH(_jit,r2,r1,r0); } -static jit_word_t -_bsubr(jit_state_t *_jit, int32_t cc, - jit_word_t i0, int32_t r0, int32_t r1) +static void +stxr_i(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - jit_word_t w; - subcr(r0, r0, r1); - w = _jit->pc.w; - B_C(cc, (i0 - w) >> 2); - return (w); + return STRW(_jit,r2,r1,r0); } -static jit_word_t -_bsubi(jit_state_t *_jit, int32_t cc, - jit_word_t i0, int32_t r0, jit_word_t i1) +static void +stxr_l(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - jit_word_t w; - subci(r0, r0, i1); - w = _jit->pc.w; - B_C(cc, (i0 - w) >> 2); - return (w); + return STR(_jit,r2,r1,r0); } -static jit_word_t -_bmxr(jit_state_t *_jit, int32_t cc, - jit_word_t i0, int32_t r0, int32_t r1) +static void +bswapr_ul(jit_state_t *_jit, 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); + return REV(_jit,r0,r1); } -static jit_word_t -_bmxi(jit_state_t *_jit, int32_t cc, - jit_word_t i0, int32_t r0, jit_word_t i1) +static void +extr_c(jit_state_t *_jit, int32_t r0, int32_t r1) { - 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); + return SXTB(_jit,r0,r1); } static void -_jmpi(jit_state_t *_jit, jit_word_t i0) +extr_uc(jit_state_t *_jit, int32_t r0, int32_t r1) { - 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); - } + return UXTB(_jit,r0,r1); } -static jit_word_t -_jmpi_p(jit_state_t *_jit, jit_word_t i0) +static void +extr_s(jit_state_t *_jit, int32_t r0, int32_t r1) { - 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); + return SXTH(_jit,r0,r1); } static void -_calli(jit_state_t *_jit, jit_word_t i0) +extr_us(jit_state_t *_jit, int32_t r0, int32_t r1) { - 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); - } + return UXTH(_jit,r0,r1); } -static jit_word_t -_calli_p(jit_state_t *_jit, jit_word_t i0) +static void +extr_i(jit_state_t *_jit, int32_t r0, int32_t r1) { - 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); + return SXTW(_jit,r0,r1); +} + +static void +extr_ui(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return UXTW(_jit,r0,r1); } -/* - * 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) +movi(jit_state_t *_jit, int32_t r0, 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) - return; - _jitc->function->self.aoff = frame; + 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); } - 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); + 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); } - - 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)); + 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); } + 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); + } + 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 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 -_epilog(jit_state_t *_jit, jit_node_t *node) +addi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - 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(); + 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 { + 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); + } } static void -_vastart(jit_state_t *_jit, int32_t r0) +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 (_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 { + 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); + } +} - assert(_jitc->function->self.call & jit_call_varargs); +static void +addxi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + 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); +} - /* Return jit_va_list_t in the register argument */ - addi(r0, FP_REGNO, _jitc->function->vaoff); +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 { + 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); + } +} - reg = jit_get_reg(jit_class_gpr); +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 { + 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); + } +} - /* 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)); +static void +subxi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + 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); +} - /* 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)); +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); +} - /* 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)); +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); +} - /* Initialize gp offset in the save area. */ - movi(rn(reg), _jitc->function->vagp); - stxi_i(offsetof(jit_va_list_t, gpoff), r0, rn(reg)); +static jit_reloc_t +boaddr(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return baddr(_jit,BCC_VS,r0,r1); +} - /* Initialize fp offset in the save area. */ - movi(rn(reg), _jitc->function->vafp); - stxi_i(offsetof(jit_va_list_t, fpoff), r0, rn(reg)); +static jit_reloc_t +boaddi(jit_state_t *_jit, int32_t r0, int32_t i1) +{ + return baddi(_jit,BCC_VS,r0,i1); +} - jit_unget_reg(reg); +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 -_vaarg(jit_state_t *_jit, int32_t r0, int32_t r1) +muli(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - jit_word_t ge_code; - jit_word_t lt_code; - int32_t rg0, rg1; + 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); +} - assert(_jitc->function->self.call & jit_call_varargs); +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); + } +} - rg0 = jit_get_reg(jit_class_gpr); - rg1 = jit_get_reg(jit_class_gpr); +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); +} - /* Load the gp offset in save area in the first temporary. */ - ldxi_i(rn(rg0), r1, offsetof(jit_va_list_t, gpoff)); +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); + } +} - /* Jump over if there are no remaining arguments in the save area. */ - ge_code = bgei(_jit->pc.w, rn(rg0), 0); +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); +} - /* Load the gp save pointer in the second temporary. */ - ldxi(rn(rg1), r1, offsetof(jit_va_list_t, gptop)); +static void +divi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + 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); +} - /* Load the vararg argument in the first argument. */ - ldxr(r0, rn(rg1), rn(rg0)); +static void +divi_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + 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); +} - /* Update the gp offset. */ - addi(rn(rg0), rn(rg0), 8); - stxi_i(offsetof(jit_va_list_t, gpoff), r1, rn(rg0)); +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); +} - /* Will only need one temporary register below. */ - jit_unget_reg(rg1); +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); +} - /* Jump over overflow code. */ - lt_code = jmpi_p(_jit->pc.w); +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); + } +} - /* Where to land if argument is in overflow area. */ - patch_at(ge_code, _jit->pc.w); +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); +} - /* Load stack pointer. */ - ldxi(rn(rg0), r1, offsetof(jit_va_list_t, stack)); +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); + } +} - /* Load argument. */ - ldr(r0, rn(rg0)); +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); +} - /* Update stack pointer. */ - addi(rn(rg0), rn(rg0), 8); - stxi(offsetof(jit_va_list_t, stack), r1, rn(rg0)); +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); + } +} - /* Where to land if argument is in gp save area. */ - patch_at(lt_code, _jit->pc.w); +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); + } +} - jit_unget_reg(rg0); +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 -_patch_at(jit_state_t *_jit, jit_word_t instr, jit_word_t label) +andi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - 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; + 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 { + 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); } - 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; + } +} + +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 { + 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); } - 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; + } +} + +static void +xori(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) { + comr(_jit, r0, r1); + } else { + imm = logical_immediate(i0); + if (imm != -1) { + EORI(_jit, r0, r1, imm); + } else { + 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); } - else - abort(); + } +} + +static void +bswapr_us(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + bswapr_ul(_jit, r0, r1); + rshi_u(_jit, r0, r0, 48); } + +static void +bswapr_ui(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + bswapr_ul(_jit, r0, r1); + rshi_u(_jit, r0, r0, 32); +} + +static void +ldi_c(jit_state_t *_jit, int32_t r0, jit_word_t i0) +{ + movi(_jit, r0, i0); + ldr_c(_jit, r0, r0); +} + +static void +ldr_uc(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + LDRBI(_jit, r0, r1, 0); +#if 0 + extr_uc(_jit, r0, r0); +#endif +} + +static void +ldi_uc(jit_state_t *_jit, int32_t r0, jit_word_t i0) +{ + movi(_jit, r0, i0); + ldr_uc(_jit, r0, r0); +} + +static void +ldi_s(jit_state_t *_jit, int32_t r0, jit_word_t i0) +{ + movi(_jit, r0, i0); + ldr_s(_jit, r0, r0); +} + +static void +ldr_us(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + LDRHI(_jit, r0, r1, 0); +#if 0 + extr_us(_jit, r0, r0); +#endif +} + +static void +ldi_us(jit_state_t *_jit, int32_t r0, jit_word_t i0) +{ + movi(_jit, r0, i0); + ldr_us(_jit, r0, r0); +} + +static void +ldi_i(jit_state_t *_jit, int32_t r0, jit_word_t i0) +{ + movi(_jit, r0, i0); + ldr_i(_jit, r0, r0); +} + +static void +ldr_ui(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + LDRWI(_jit, r0, r1, 0); +#if 0 + extr_ui(_jit, r0, r0); +#endif +} + +static void +ldi_ui(jit_state_t *_jit, int32_t r0, jit_word_t i0) +{ + movi(_jit, r0, i0); + ldr_ui(_jit, r0, r0); +} + +static void +ldr_l(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + LDRI(_jit, r0, r1, 0); +} + +static void +ldi_l(jit_state_t *_jit, int32_t r0, jit_word_t i0) +{ + movi(_jit, r0, i0); + ldr_l(_jit, r0, r0); +} + +static void +ldxr_c(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + LDRSB(_jit, r0, r1, r2); + extr_c(_jit, r0, r0); +} + +static void +ldxi_c(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + if (i0 >= 0 && i0 <= 4095) { + LDRSBI(_jit, r0, r1, i0); + } else if (i0 > -256 && i0 < 0) { + LDURSB(_jit, r0, r1, i0 & 0x1ff); + } else { + 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); +} + +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(_jit, r0, r0); +#endif +} + +static void +ldxi_uc(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + if (i0 >= 0 && i0 <= 4095) { + LDRBI(_jit, r0, r1, i0); + } else if (i0 > -256 && i0 < 0) { + LDURB(_jit, r0, r1, i0 & 0x1ff); + } else { + 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); +#endif +} + +static void +ldxi_s(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + 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 { + 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); + } +} + +static void +ldxr_us(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + LDRH(_jit, r0, r1, r2); +#if 0 + extr_us(_jit, r0, r0); +#endif +} + +static void +ldxi_us(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + 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 { + 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); +#endif +} + +static void +ldxi_i(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + 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 { + 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); + } +} + +static void +ldxr_ui(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + LDRW(_jit, r0, r1, r2); +#if 0 + extr_ui(_jit, r0, r0); +#endif +} + +static void +ldxi_ui(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + 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 { + 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); #endif +} + +static void +ldxi_l(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + 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 { + 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); + } +} + +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); + 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) +{ + 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) +{ + 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) +{ + 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) +{ + 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) +{ + 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) +{ + 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) +{ + 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 +jmpi(jit_state_t *_jit, jit_word_t i0) +{ + return jit_patch_there(_jit, jmp(_jit), (void*)i0); +} + +static jit_reloc_t +call(jit_state_t *_jit) +{ + return BL(_jit); +} + +static void +calli(jit_state_t *_jit, jit_word_t i0) +{ + return jit_patch_there(_jit, call(_jit), (void*)i0); +} + +static void +ret(jit_state_t *_jit) +{ + RET(_jit); +} + +static void +retr(jit_state_t *_jit, int32_t r) +{ + movr(_jit, jit_gpr_regno(_X0), r); + ret(_jit); +} + +static void +reti(jit_state_t *_jit, int32_t i) +{ + movi(_jit, jit_gpr_regno(_X0), i); + ret(_jit); +} + +static void +retval_c(jit_state_t *_jit, int32_t r0) +{ + extr_c(_jit, r0, jit_gpr_regno(_X0)); +} + +static void +retval_uc(jit_state_t *_jit, int32_t r0) +{ + extr_uc(_jit, r0, jit_gpr_regno(_X0)); +} + +static void +retval_s(jit_state_t *_jit, int32_t r0) +{ + extr_s(_jit, r0, jit_gpr_regno(_X0)); +} + +static void +retval_us(jit_state_t *_jit, int32_t r0) +{ + extr_us(_jit, r0, jit_gpr_regno(_X0)); +} + +static void +retval_i(jit_state_t *_jit, int32_t r0) +{ + 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)); +} diff --git a/libguile/lightening/lightening/aarch64-fpu.c b/libguile/lightening/lightening/aarch64-fpu.c index e1ccde65c..44f1eb0df 100644 --- a/libguile/lightening/lightening/aarch64-fpu.c +++ b/libguile/lightening/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,797 @@ * 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) -{ - 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); -} - -static void -_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); -} - -static void -_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); -} - -#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); \ +static void +osvvv(jit_state_t *_jit, int32_t Op, int32_t Sz, int32_t Rd, int32_t Rn, + int32_t Rm) +{ + 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) +{ + 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) +{ + 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 +#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 +FCMPED(jit_state_t *_jit, int32_t Rn, int32_t Rm) +{ + os_vv(_jit, A64_FCMPE, 1, Rn, Rm); +} + +static void +FMOVS(jit_state_t *_jit, int32_t Rd, int32_t Rn) +{ + osvv_(_jit, A64_FMOV, 0, Rd, Rn); +} + +static void +FMOVD(jit_state_t *_jit, int32_t Rd, int32_t Rn) +{ + osvv_(_jit, A64_FMOV, 1, Rd, Rn); +} + +static void +FMOVWS(jit_state_t *_jit, int32_t Rd, int32_t Rn) +{ + osvv_(_jit, A64_FMOVWV, 0, Rd, Rn); +} + +static void +FMOVSW(jit_state_t *_jit, int32_t Rd, int32_t Rn) +{ + osvv_(_jit, A64_FMOVVW, 0, Rd, Rn); +} + +static void +FMOVXD(jit_state_t *_jit, int32_t Rd, int32_t Rn) +{ + osvv_(_jit, A64_FMOVXV, 1, Rd, Rn); +} + +static void +FMOVDX(jit_state_t *_jit, int32_t Rd, int32_t Rn) +{ + osvv_(_jit, A64_FMOVVX, 1, Rd, Rn); +} + +static void +FCVT_SD(jit_state_t *_jit, int32_t Rd, int32_t Rn) +{ + osvv_(_jit, A64_FCVTS, 1, Rd, Rn); +} + +static void +FCVT_DS(jit_state_t *_jit, int32_t Rd, int32_t Rn) +{ + osvv_(_jit, A64_FCVTD, 0, Rd, Rn); +} + +static void +SCVTFS(jit_state_t *_jit, int32_t Rd, int32_t Rn) +{ + osvv_(_jit, A64_SCVTF|XS, 0, Rd, Rn); +} + +static void +SCVTFD(jit_state_t *_jit, int32_t Rd, int32_t Rn) +{ + osvv_(_jit, A64_SCVTF|XS, 1, Rd, Rn); +} + +static void +FCVTSZ_WS(jit_state_t *_jit, int32_t Rd, int32_t Rn) +{ + osvv_(_jit, A64_FCVTZS, 0, Rd, Rn); +} + +static void +FCVTSZ_WD(jit_state_t *_jit, int32_t Rd, int32_t Rn) +{ + osvv_(_jit, A64_FCVTZS, 1, Rd, Rn); +} + +static void +FCVTSZ_XS(jit_state_t *_jit, int32_t Rd, int32_t Rn) +{ + osvv_(_jit, A64_FCVTZS|XS, 0, Rd, Rn); +} + +static void +FCVTSZ_XD(jit_state_t *_jit, int32_t Rd, int32_t Rn) +{ + osvv_(_jit, A64_FCVTZS|XS, 1, Rd, Rn); +} + +static void +FABSS(jit_state_t *_jit, int32_t Rd, int32_t Rn) +{ + osvv_(_jit, A64_FABS, 0, Rd, Rn); +} + +static void +FABSD(jit_state_t *_jit, int32_t Rd, int32_t Rn) +{ + osvv_(_jit, A64_FABS, 1, Rd, Rn); +} + +static void +FNEGS(jit_state_t *_jit, int32_t Rd, int32_t Rn) +{ + osvv_(_jit, A64_FNEG, 0, Rd, Rn); +} + +static void +FNEGD(jit_state_t *_jit, int32_t Rd, int32_t Rn) +{ + osvv_(_jit, A64_FNEG, 1, Rd, Rn); +} + +static void +FSQRTS(jit_state_t *_jit, int32_t Rd, int32_t Rn) +{ + osvv_(_jit, A64_FSQRT, 0, Rd, Rn); } -#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); \ + +static void +FSQRTD(jit_state_t *_jit, int32_t Rd, int32_t Rn) +{ + osvv_(_jit, A64_FSQRT, 1, Rd, Rn); +} + +static void +FADDS(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) +{ + osvvv(_jit, A64_FADD, 0, Rd, Rn, Rm); +} + +static void +FADDD(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) +{ + osvvv(_jit, A64_FADD, 1, Rd, Rn, Rm); } static void -_truncr_f_i(jit_state_t *_jit, int32_t r0, int32_t r1) +FSUBS(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) { - FCVTSZ_WS(r0, r1); - extr_i(r0, r0); + osvvv(_jit, A64_FSUB, 0, Rd, Rn, Rm); } static void -_truncr_d_i(jit_state_t *_jit, int32_t r0, int32_t r1) +FSUBD(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) { - FCVTSZ_WD(r0, r1); - extr_i(r0, r0); + osvvv(_jit, A64_FSUB, 1, Rd, Rn, Rm); } -fopi(add) -fopi(sub) -fopi(rsb) -fopi(mul) -fopi(div) +static void +FMULS(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) +{ + osvvv(_jit, A64_FMUL, 0, Rd, Rn, Rm); +} static void -_ldr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +FMULD(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - ldr_i(rn(reg), r1); - FMOVSW(r0, rn(reg)); - jit_unget_reg(reg); + osvvv(_jit, A64_FMUL, 1, Rd, Rn, Rm); } static void -_ldi_f(jit_state_t *_jit, int32_t r0, jit_word_t i0) +FDIVS(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - ldi_i(rn(reg), i0); - FMOVSW(r0, rn(reg)); - jit_unget_reg(reg); + osvvv(_jit, A64_FDIV, 0, Rd, Rn, Rm); } static void -_ldxr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +FDIVD(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - ldxr_i(rn(reg), r1, r2); - FMOVSW(r0, rn(reg)); - jit_unget_reg(reg); + osvvv(_jit, A64_FDIV, 1, Rd, Rn, Rm); } static void -_ldxi_f(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +truncr_f_l(jit_state_t *_jit, int32_t r0, int32_t r1) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - ldxi_i(rn(reg), r1, i0); - FMOVSW(r0, rn(reg)); - jit_unget_reg(reg); + FCVTSZ_XS(_jit, r0, r1); } static void -_str_f(jit_state_t *_jit, int32_t r0, int32_t r1) +truncr_d_l(jit_state_t *_jit, int32_t r0, int32_t r1) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - FMOVWS(rn(reg), r1); - str_i(r0, rn(reg)); - jit_unget_reg(reg); + FCVTSZ_XD(_jit, r0, r1); } static void -_sti_f(jit_state_t *_jit, jit_word_t i0, int32_t r0) +addr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - FMOVWS(rn(reg), r0); - sti_i(i0, rn(reg)); - jit_unget_reg(reg); + FADDS(_jit, r0, r1, r2); } static void -_stxr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +subr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - FMOVWS(rn(reg), r2); - stxr_i(r0, r1, rn(reg)); - jit_unget_reg(reg); + FSUBS(_jit, r0, r1, r2); } static void -_stxi_f(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) +mulr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - FMOVWS(rn(reg), r1); - stxi_i(i0, r0, rn(reg)); - jit_unget_reg(reg); + FMULS(_jit, r0, r1, r2); } static void -_movr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +divr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - if (r0 != r1) - FMOVS(r0, r1); + FDIVS(_jit, r0, r1, r2); } static void -_movi_f(jit_state_t *_jit, int32_t r0, jit_float32_t i0) +absr_f(jit_state_t *_jit, int32_t r0, int32_t r1) { - 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); - } + FABSS(_jit, r0, r1); } static void -_fccr(jit_state_t *_jit, int32_t cc, - int32_t r0, int32_t r1, int32_t r2) +negr_f(jit_state_t *_jit, int32_t r0, int32_t r1) { - FCMPES(r1, r2); - CSET(r0, cc); + FNEGS(_jit, r0, r1); } static void -_fcci(jit_state_t *_jit, int32_t cc, - int32_t r0, int32_t r1, jit_float32_t i0) +sqrtr_f(jit_state_t *_jit, int32_t r0, int32_t r1) { - 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); + FSQRTS(_jit, r0, r1); } static void -_uneqr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +extr_f(jit_state_t *_jit, int32_t r0, int32_t r1) { - 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); + SCVTFS(_jit, r0, r1); } -fopi(uneq) static void -_ltgtr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +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) { - 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); + return fbccr(_jit, BCC_PL,r0, r1); } -fopi(ltgt) -static jit_word_t -_fbccr(jit_state_t *_jit, int32_t cc, - jit_word_t i0, int32_t r0, int32_t r1) +static jit_reloc_t +bungtr_f(jit_state_t *_jit, 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); + return fbccr(_jit, BCC_HI,r0, r1); } -static jit_word_t -_fbcci(jit_state_t *_jit, int32_t cc, - jit_word_t i0, int32_t r0, jit_float32_t i1) +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) { - 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); + FSUBD(_jit, r0, r1, r2); } -static jit_word_t -_buneqr_f(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) +static void +mulr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - 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); + FMULD(_jit, r0, r1, r2); } -fbopi(uneq) -static jit_word_t -_bltgtr_f(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) +static void +divr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - 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); + FDIVD(_jit, r0, r1, r2); } -fbopi(ltgt) -dopi(add) -dopi(sub) -dopi(rsb) -dopi(mul) -dopi(div) +static void +absr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + FABSD(_jit, r0, r1); +} static void -_ldr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +negr_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); + FNEGD(_jit, r0, r1); } static void -_ldi_d(jit_state_t *_jit, int32_t r0, jit_word_t i0) +sqrtr_d(jit_state_t *_jit, int32_t r0, int32_t r1) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - ldi_l(rn(reg), i0); - FMOVDX(r0, rn(reg)); - jit_unget_reg(reg); + FSQRTD(_jit, r0, r1); } static void -_ldxr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +extr_d(jit_state_t *_jit, int32_t r0, int32_t r1) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - ldxr_l(rn(reg), r1, r2); - FMOVDX(r0, rn(reg)); - jit_unget_reg(reg); + SCVTFD(_jit, r0, r1); } static void -_ldxi_d(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +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) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - ldxi_l(rn(reg), r1, i0); - FMOVDX(r0, rn(reg)); - jit_unget_reg(reg); + 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 -_str_d(jit_state_t *_jit, int32_t r0, int32_t r1) +truncr_f_i(jit_state_t *_jit, int32_t r0, int32_t r1) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - FMOVXD(rn(reg), r1); - str_l(r0, rn(reg)); - jit_unget_reg(reg); + FCVTSZ_WS(_jit, r0, r1); + extr_i(_jit, r0, r0); } static void -_sti_d(jit_state_t *_jit, jit_word_t i0, int32_t r0) +truncr_d_i(jit_state_t *_jit, int32_t r0, int32_t r1) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - FMOVXD(rn(reg), r0); - sti_l(i0, rn(reg)); - jit_unget_reg(reg); + FCVTSZ_WD(_jit, r0, r1); + extr_i(_jit, r0, r0); } static void -_stxr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +ldr_f(jit_state_t *_jit, int32_t r0, int32_t r1) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - FMOVXD(rn(reg), r2); - stxr_l(r0, r1, rn(reg)); - jit_unget_reg(reg); + 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 -_stxi_d(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) +ldi_f(jit_state_t *_jit, int32_t r0, jit_word_t i0) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - FMOVXD(rn(reg), r1); - stxi_l(i0, r0, rn(reg)); - jit_unget_reg(reg); + 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 -_movr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +ldxr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - if (r0 != r1) - FMOVD(r0, r1); + 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 -_movi_d(jit_state_t *_jit, int32_t r0, jit_float64_t i0) +ldxi_f(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) { - 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); - } + 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 -_dccr(jit_state_t *_jit, int32_t cc, - int32_t r0, int32_t r1, int32_t r2) +str_f(jit_state_t *_jit, int32_t r0, int32_t r1) { - FCMPED(r1, r2); - CSET(r0, cc); + 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 -_dcci(jit_state_t *_jit, int32_t cc, - int32_t r0, int32_t r1, jit_float64_t i0) +sti_f(jit_state_t *_jit, jit_word_t i0, int32_t r0) { - 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); + 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 -_uneqr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +stxr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - 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); + 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); } -dopi(uneq) static void -_ltgtr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +stxi_f(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) { - 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); + 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); } -dopi(ltgt) -static jit_word_t -_dbccr(jit_state_t *_jit, int32_t cc, - jit_word_t i0, int32_t r0, int32_t r1) +static void +movr_f(jit_state_t *_jit, 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); + if (r0 != r1) + FMOVS(_jit, r0, r1); } -static jit_word_t -_dbcci(jit_state_t *_jit, int32_t cc, - jit_word_t i0, int32_t r0, jit_float64_t i1) +static void +movi_f(jit_state_t *_jit, int32_t r0, float i0) { - 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); + 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_word_t -_buneqr_d(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) +static jit_reloc_t +buneqr_f(jit_state_t *_jit, 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); + 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; } -dbopi(uneq) -static jit_word_t -_bltgtr_d(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) +static jit_reloc_t +bltgtr_f(jit_state_t *_jit, 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); + 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; } -dbopi(ltgt) static void -_vaarg_d(jit_state_t *_jit, int32_t r0, int32_t r1) +ldr_d(jit_state_t *_jit, int32_t r0, int32_t r1) { - jit_word_t ge_code; - jit_word_t lt_code; - int32_t rg0, rg1; + 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); +} - assert(_jitc->function->self.call & jit_call_varargs); +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); +} - rg0 = jit_get_reg(jit_class_gpr); - rg1 = jit_get_reg(jit_class_gpr); +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); +} - /* Load the fp offset in save area in the first temporary. */ - ldxi_i(rn(rg0), r1, offsetof(jit_va_list_t, fpoff)); +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); +} - /* Jump over if there are no remaining arguments in the save area. */ - ge_code = bgei(_jit->pc.w, rn(rg0), 0); +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); +} - /* Load the gp save pointer in the second temporary. */ - ldxi(rn(rg1), r1, offsetof(jit_va_list_t, fptop)); +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); +} - /* Load the vararg argument in the first argument. */ - ldxr_d(r0, rn(rg1), rn(rg0)); +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); +} - /* Update the fp offset. */ - addi(rn(rg0), rn(rg0), 16); - stxi_i(offsetof(jit_va_list_t, fpoff), r1, rn(rg0)); +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); +} - /* Will only need one temporary register below. */ - jit_unget_reg(rg1); +static void +movr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + if (r0 != r1) + FMOVD(_jit, r0, r1); +} - /* Jump over overflow code. */ - lt_code = jmpi_p(_jit->pc.w); +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); + } +} - /* Where to land if argument is in overflow area. */ - patch_at(ge_code, _jit->pc.w); +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; +} - /* Load stack pointer. */ - ldxi(rn(rg0), r1, offsetof(jit_va_list_t, stack)); +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; +} - /* Load argument. */ - ldr_d(r0, rn(rg0)); +static void +retr_d(jit_state_t *_jit, int32_t r) +{ + movr_d(_jit, jit_fpr_regno(_D0), r); + ret(_jit); +} - /* Update stack pointer. */ - addi(rn(rg0), rn(rg0), 8); - stxi(offsetof(jit_va_list_t, stack), r1, rn(rg0)); +static void +retr_f(jit_state_t *_jit, int32_t r) +{ + movr_f(_jit, jit_fpr_regno(_D0), r); + ret(_jit); +} - /* Where to land if argument is in gp save area. */ - patch_at(lt_code, _jit->pc.w); +static void +retval_f(jit_state_t *_jit, int32_t r0) +{ + movr_f(_jit, r0, jit_fpr_regno(_D0)); +} - jit_unget_reg(rg0); +static void +retval_d(jit_state_t *_jit, int32_t r0) +{ + movr_d(_jit, r0, jit_fpr_regno(_D0)); } -#endif diff --git a/libguile/lightening/lightening/aarch64.c b/libguile/lightening/lightening/aarch64.c index 65efb74c3..66fb27b61 100644 --- a/libguile/lightening/lightening/aarch64.c +++ b/libguile/lightening/lightening/aarch64.c @@ -17,1572 +17,215 @@ * 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, "<none>" }, +static inline int32_t +read_signed_bitfield(uint32_t word, uint8_t width, uint8_t shift) +{ + 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 +in_signed_range(ptrdiff_t diff, uint8_t bits) +{ + return (-1 << (bits - 1)) <= diff && diff < (1 << (bits - 1)); +} + +static inline int +in_unsigned_range(uint32_t val, uint8_t bits) +{ + ASSERT(bits < __WORDSIZE); + return val < (1 << bits); +} + +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_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) \ + { \ + return in_signed_range(diff, kind##_width); \ + } \ + static void \ + patch_##name##_offset(uint32_t *loc, ptrdiff_t 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, kind##_width - 1); \ + emit_u32(_jit, inst); \ + return ret; \ + } + +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 +{ + uint32_t ldr; + uint32_t br; + uint64_t addr; }; -/* - * Implementation - */ -void -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) +static void +patch_veneer(uint32_t *loc, jit_pointer_t addr) { - 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(); + struct veneer *v = (struct veneer*) v; + v->addr = (uint64_t) addr; } -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(); -} +#include "aarch64-cpu.c" +#include "aarch64-fpu.c" -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(); -} +static const jit_gpr_t abi_gpr_args[] = { + _X0, _X1, _X2, _X3, _X4, _X5, _X6, _X7 +}; -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(); -} +static const jit_fpr_t abi_fpr_args[] = { + _D0, _D1, _D2, _D3, _D4, _D5, _D6, _D7 +}; -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(); -} +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]); -void -_jit_retr_d(jit_state_t *_jit, int32_t u) +struct abi_arg_iterator { - 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(); -} + const jit_operand_t *args; + size_t argc; -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(); -} + size_t arg_idx; + size_t gpr_idx; + size_t fpr_idx; + size_t stack_size; + size_t stack_padding; +}; -void -_jit_epilog(jit_state_t *_jit) -{ - assert(_jitc->function); - assert(_jitc->function->epilog->next == NULL); - jit_link(_jitc->function->epilog); - _jitc->function = NULL; -} +static size_t page_size; jit_bool_t -_jit_arg_register_p(jit_state_t *_jit, jit_node_t *u) -{ - 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)); -} - -void -_jit_ellipsis(jit_state_t *_jit) -{ - 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(); -} - -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) -{ - 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); -} - -jit_node_t * -_jit_arg_f(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_f, offset, - ++_jitc->function->self.argn); - jit_link_prolog(); - return (node); -} - -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) +jit_get_cpu(void) { - 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(); + page_size = sysconf(_SC_PAGE_SIZE); + return 1; } 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_init(jit_state_t *_jit) { - 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(); + return 1; } -jit_node_t * -_jit_finishi(jit_state_t *_jit, jit_pointer_t i0) +static size_t +jit_initial_frame_size (void) { - 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); + return 0; } -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) +static void +reset_abi_arg_iterator(struct abi_arg_iterator *iter, size_t argc, + const jit_operand_t *args) { - jit_inc_synth_w(retval_d, r0); - if (r0 != JIT_FRET) - jit_movr_d(r0, JIT_FRET); - jit_dec_synth(); + memset(iter, 0, sizeof *iter); + iter->argc = argc; + iter->args = args; } -jit_pointer_t -_emit_code(jit_state_t *_jit) +static void +next_abi_arg(struct abi_arg_iterator *iter, jit_operand_t *arg) { - 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); + 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++; } -#define CODE 1 -# include "aarch64-cpu.c" -# include ", 2018aarch64-fpu.c" -#undef CODE - -void +static 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 -} - -void -_emit_ldxi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) -{ - ldxi(rn(r0), rn(r1), i0); + 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_stxi(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) +static inline size_t +jit_stack_alignment(void) { - stxi(i0, rn(r0), rn(r1)); + return 16; } -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) +static void +jit_try_shorten(jit_state_t *_jit, jit_reloc_t reloc, jit_pointer_t addr) { - stxi_d(i0, rn(r0), rn(r1)); } -static void -_patch(jit_state_t *_jit, jit_word_t instr, jit_node_t *node) +static void* +bless_function_pointer(void *ptr) { - 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 ptr; } diff --git a/libguile/lightening/lightening/aarch64.h b/libguile/lightening/lightening/aarch64.h index 65723a6d2..0e675a9ee 100644 --- a/libguile/lightening/lightening/aarch64.h +++ b/libguile/lightening/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,148 @@ #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) + +#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_TMP0 _X17 +#define JIT_TMP1 _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. +#define JIT_PLATFORM_CALLEE_SAVE_GPRS _X29, _X30 + +// 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 */ diff --git a/libguile/lightening/lightening/arm-cpu.c b/libguile/lightening/lightening/arm-cpu.c index 9d44699b9..e758bfd28 100644 --- a/libguile/lightening/lightening/arm-cpu.c +++ b/libguile/lightening/lightening/arm-cpu.c @@ -14,3942 +14,2937 @@ * 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 -/* >> 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 _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 ARM_CC_EQ 0x00000000 /* Z=1 */ +#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 */ +#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 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 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 THUMB_RSBI 0x4240 +#define THUMB2_RSBI 0xf1c00000 +#define THUMB_MUL 0x4340 +#define THUMB2_MUL 0xfb00f000 +#define THUMB2_UMULL 0xfba00000 +#define THUMB2_SMULL 0xfb800000 +#define THUMB_MLS 0xfb000010 +#define THUMB2_SDIV 0xfb90f0f0 +#define THUMB2_UDIV 0xfbb0f0f0 +#define THUMB_AND 0x4000 +#define THUMB2_AND 0xea000000 +#define THUMB2_ANDI 0xf0000000 +#define THUMB2_BIC 0xea200000 +#define THUMB2_BICI 0xf0200000 +#define THUMB_ORR 0x4300 +#define THUMB2_ORR 0xea400000 +#define THUMB2_ORRI 0xf0400000 +#define THUMB_EOR 0x4040 +#define THUMB2_EOR 0xea800000 +#define THUMB2_EORI 0xf0800000 +#define THUMB_REV 0xba00 +#define THUMB2_REV 0xfa90f080 +#define THUMB_SXTB 0xb240 +#define THUMB2_SXTB 0xfa40f080 +#define THUMB_UXTB 0xb2c0 +#define THUMB2_UXTB 0xfa50f080 +#define THUMB_SXTH 0xb200 +#define THUMB2_SXTH 0xfa00f080 +#define THUMB_UXTH 0xb280 +#define THUMB2_UXTH 0xfa10f080 +#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 THUMB_CMP 0x4280 +#define THUMB_CMPX 0x4500 +#define THUMB2_CMP 0xebb00000 +#define THUMB_CMPI 0x2800 +#define THUMB2_CMPI 0xf1b00000 +#define THUMB2_CMN 0xeb100000 +#define THUMB2_CMNI 0xf1100000 +#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 +#define THUMB2_LDRSB 0xf9100000 +#define THUMB2_LDRSBI 0xf9100c00 +#define THUMB2_LDRSBWI 0xf9900000 +#define THUMB_LDRB 0x5c00 +#define THUMB2_LDRB 0xf8100000 +#define THUMB_LDRBI 0x7800 +#define THUMB2_LDRBI 0xf8100c00 +#define THUMB2_LDRBWI 0xf8900000 +#define THUMB_LDRSH 0x5e00 +#define THUMB2_LDRSH 0xf9300000 +#define THUMB2_LDRSHI 0xf9300c00 +#define THUMB2_LDRSHWI 0xf9b00000 +#define THUMB_LDRH 0x5a00 +#define THUMB2_LDRH 0xf8300000 +#define THUMB_LDRHI 0x8800 +#define THUMB2_LDRHI 0xf8300c00 +#define THUMB2_LDRHWI 0xf8b00000 +#define THUMB_LDR 0x5800 +#define THUMB2_LDR 0xf8500000 +#define THUMB2_LDRP 0xf85f0000 +#define THUMB_LDRI 0x6800 +#define THUMB_LDRISP 0x9800 +#define THUMB2_LDRI 0xf8500c00 +#define THUMB2_LDRWI 0xf8d00000 +#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_LDM_W 0x00200000 +#define THUMB2_PUSH 0xe92d0000 + +#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)) +# 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); - } - } - return (-1); + 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); } 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) -{ - 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); +static uint32_t +read_wide_thumb(uint32_t *loc) +{ + uint16_t *sloc = (uint16_t*)loc; + return (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 -encode_thumb_cc_jump(int 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); +offset_in_jmp_range(int32_t offset) +{ + 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_jmp_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 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) +{ + 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_shift(int v, int type) +offset_in_jcc_range(int32_t v) { - 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) -{ - 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); + 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 hi = (v >> 16) & 0x3f; + uint32_t lo = v & 0x7ff; + + int32_t ret = s << 31; + ret >>= 12; + ret |= j2 << 18; + ret |= j1 << 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_jcc_range(v)); + uint32_t s = !!(v & 0x80000); + 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; +} + +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 int32_t +read_jcc_offset(uint32_t *loc) +{ + return decode_thumb_cc_jump(read_wide_thumb(loc)); } static void -_corrr(jit_state_t *_jit, int cc, int o, int rn, int rd, int rm) +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) { - assert(!(cc & 0x0fffffff)); - assert(!(o & 0xf00fff0f)); - ii(cc|o|(_u4(rn)<<16)|(_u4(rd)<<12)|_u4(rm)); + 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 void -_corri(jit_state_t *_jit, int cc, int o, int rn, int rd, int im) +torrr(jit_state_t *_jit, int o, int rn, int rd, 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(rd)<<8)|_u4(rm)); } static void -_corri8(jit_state_t *_jit, int cc, int o, int rn, int rt, int im) +torxr(jit_state_t *_jit, int o, int rn, int rt, 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 & 0xf0f0f)); + emit_wide_thumb(_jit, o|(_u4(rn)<<16)|(_u4(rt)<<12)|_u4(rm)); } static void -_coriw(jit_state_t *_jit, int cc, int o, int rd, int im) +torrrr(jit_state_t *_jit, int o, int rn, int rl, int rh, int rm) { - assert(!(cc & 0x0fffffff)); - assert(!(o & 0xf00fffff)); - assert(!(im & 0xffff0000)); - ii(cc|o|((im&0xf000)<<4)|(_u4(rd)<<12)|(im&0xfff)); + ASSERT(!(o & 0x000fff0f)); + emit_wide_thumb(_jit, o|(_u4(rn)<<16)|(_u4(rl)<<12)|(_u4(rh)<<8)|_u4(rm)); } 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 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 -_torri(jit_state_t *_jit, int o, int rn, int rd, int im) +T1_ORR(jit_state_t *_jit, int32_t rdn, int32_t rm) { - 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]); + return emit_u16(_jit, THUMB_ORR|(_u3(rm)<<3)|_u3(rdn)); } static void -_torri8(jit_state_t *_jit, int o, int rn, int rt, int im) +T2_ORR(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t rm) { - 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]); + return torrr(_jit, THUMB2_ORR,rn,rd,rm); } static void -_torri12(jit_state_t *_jit, int o, int rn, int rt, int im) +T2_ORRI(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t 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]); + return torri(_jit, THUMB2_ORRI,rn,rd,im); } static void -_tshift(jit_state_t *_jit, int o, int rd, int rm, int im) +T1_EOR(jit_state_t *_jit, int32_t rdn, int32_t rm) { - 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]); + return emit_u16(_jit, THUMB_EOR|(_u3(rm)<<3)|_u3(rdn)); } static void -_toriw(jit_state_t *_jit, int o, int rd, int im) +T2_EOR(jit_state_t *_jit, int32_t rd, int32_t rn, 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 torrr(_jit, THUMB2_EOR,rn,rd,rm); } static void -_tc8(jit_state_t *_jit, int cc, int im) +T2_EORI(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t im) { - 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 torri(_jit, THUMB2_EORI,rn,rd,im); } static void -_t11(jit_state_t *_jit, int im) +T1_MOV(jit_state_t *_jit, int32_t rd, int32_t rm) { - assert(!(im & 0xfffff800)); - is(THUMB_B|im); + return emit_u16(_jit, THUMB_MOV|((_u4(rd)&8)<<4)|(_u4(rm)<<3)|(rd&7)); } static void -_tcb(jit_state_t *_jit, int cc, int im) +T1_MOVI(jit_state_t *_jit, int32_t rd, int32_t im) { - 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_MOVI|(_u3(rd)<<8)|_u8(im)); } static void -_blxi(jit_state_t *_jit, int im) +T2_MOVI(jit_state_t *_jit, int32_t rd, int32_t im) { - assert(!(im & 0xfe000000)); - ii(ARM_BLXI|im); + return torri(_jit, THUMB2_MOVI,_NOREG,rd,im); } static void -_tb(jit_state_t *_jit, int o, int im) +T2_MOVWI(jit_state_t *_jit, int32_t rd, 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 toriw(_jit, THUMB2_MOVWI,rd,im); } static void -_corrrr(jit_state_t *_jit, int cc, int o, int rh, int rl, int rm, int rn) +T2_MOVTI(jit_state_t *_jit, int32_t rd, int32_t im) { - assert(!(cc & 0x0fffffff)); - assert(!(o & 0xf00fff0f)); - ii(cc|o|(_u4(rh)<<16)|(_u4(rl)<<12)|(_u4(rm)<<8)|_u4(rn)); + return toriw(_jit, THUMB2_MOVTI,rd,im); } static void -_corrrs(jit_state_t *_jit, int cc, int o, int rn, int rd, int rm, int im) +T1_MVN(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 emit_u16(_jit, THUMB_MVN|(_u3(rm)<<3)|_u3(rd)); } static void -_cshift(jit_state_t *_jit, int cc, int o, int rd, int rm, int rn, int im) +T2_MVN(jit_state_t *_jit, int32_t rd, int32_t rm) { - 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 torrr(_jit, THUMB2_MVN,_NOREG,rd,rm); } static void -_cb(jit_state_t *_jit, int cc, int o, int im) +T2_MVNI(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_MVNI,_NOREG,rd,im); } static void -_cbx(jit_state_t *_jit, int cc, int o, int rm) +T1_NOT(jit_state_t *_jit, int32_t rd, int32_t rm) { - assert(!(cc & 0x0fffffff)); - assert(!(o & 0xf000000f)); - ii(cc|o|_u4(rm)); + return T1_MVN(_jit, rd,rm); } static void -_corl(jit_state_t *_jit, int cc, int o, int r0, int i0) +T2_NOT(jit_state_t *_jit, int32_t rd, int32_t rm) { - assert(!(cc & 0x0fffffff)); - assert(!(o & 0xf00fffff)); - ii(cc|o|(_u4(r0)<<16)|_u16(i0)); + return T2_MVN(_jit, rd,rm); } static void -_c6orr(jit_state_t *_jit, int cc, int o, int rd, int rm) +T1_NOP(jit_state_t *_jit) { - assert(!(cc & 0x0fffffff)); - assert(!(o & 0xf000f00f)); - ii(cc|o|(_u4(rd)<<12)|_u4(rm)); + return emit_u16(_jit, 0xbf00); } static void -_tpp(jit_state_t *_jit, int o, int im) +T1_ADD(jit_state_t *_jit, int32_t rd, int32_t rn, 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 emit_u16(_jit, THUMB_ADD|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rd)); } static void -_torl(jit_state_t *_jit, int o, int rn, int im) +T1_ADDX(jit_state_t *_jit, int32_t rdn, int32_t rm) { - 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 emit_u16(_jit, THUMB_ADDX|((_u4(rdn)&8)<<4)|(_u4(rm)<<3)|(rdn&7)); } static void -_nop(jit_state_t *_jit, int32_t i0) +T2_ADD(jit_state_t *_jit, int32_t rd, int32_t rn, 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 torrr(_jit, THUMB2_ADD,rn,rd,rm); } static void -_movr(jit_state_t *_jit, int32_t r0, int32_t r1) +T1_ADDI3(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t im) { - if (r0 != r1) { - if (jit_thumb_p()) - T1_MOV(r0, r1); - else - MOV(r0, r1); - } + return emit_u16(_jit, THUMB_ADDI3|(_u3(im)<<6)|(_u3(rn)<<3)|_u3(rd)); } static void -_movi(jit_state_t *_jit, int32_t r0, jit_word_t i0) +T1_ADDI8(jit_state_t *_jit, int32_t rdn, int32_t im) { - 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); - } + return emit_u16(_jit, THUMB_ADDI8|(_u3(rdn)<<8)|_u8(im)); } -static jit_word_t -_movi_p(jit_state_t *_jit, int32_t r0, jit_word_t i0) +static void +T2_ADDI(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t im) { - 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 torri(_jit, THUMB2_ADDI,rn,rd,im); } static void -_comr(jit_state_t *_jit, int32_t r0, int32_t r1) +T2_ADDWI(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t im) { - 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 torri(_jit, THUMB2_ADDWI,rn,rd,im); } static void -_negr(jit_state_t *_jit, int32_t r0, int32_t r1) +T2_ADDS(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_RSBI(r0, r1); - else - T2_RSBI(r0, r1, 0); - } - else - RSBI(r0, r1, 0); + return torrr(_jit, THUMB2_ADD|ARM_S,rn,rd,rm); } static void -_addr(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_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); -} - -static void -_addi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) -{ - 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 torri(_jit, THUMB2_ADDI|ARM_S,rn,rd,im); } static void -_addcr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +T1_ADC(jit_state_t *_jit, int32_t rdn, int32_t rm) { - 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); -} - -static void -_addci(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) -{ - 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 emit_u16(_jit, THUMB_ADC|(_u3(rm)<<3)|_u3(rdn)); } static void -_addxr(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) { - /* 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); -} - -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; - 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_ADC|ARM_S,rn,rd,rm); } static void -_subr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +T2_ADCSI(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); -} - -static void -_subi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) -{ - 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 torri(_jit, THUMB2_ADCI|ARM_S,rn,rd,im); } static void -_subcr(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) { - 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); -} - -static void -_subci(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) -{ - 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 emit_u16(_jit, THUMB_SUB|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rd)); } static void -_subxr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +T2_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); -} - -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; - 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) -{ - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - mulr(r0, r1, rn(reg)); - jit_unget_reg(reg); -} - -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); - } - } +T2_SUBI(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t im) +{ + return torri(_jit, THUMB2_SUBI,rn,rd,im); } static void -_iqmuli(jit_state_t *_jit, int32_t r0, int32_t r1, - int32_t r2, jit_word_t i0, jit_bool_t sign) +T2_SUBWI(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); - iqmulr(r0, r1, r2, rn(reg), sign); - jit_unget_reg(reg); + return torri(_jit, THUMB2_SUBWI,rn,rd,im); } static void -_divrem(jit_state_t *_jit, int div, int sign, - int32_t r0, int32_t r1, int32_t r2) +T2_SUBS(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t rm) { - 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 torrr(_jit, THUMB2_SUB|ARM_S,rn,rd,rm); } static void -_divr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +T2_SUBSI(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t im) { - if (jit_armv7r_p() && jit_thumb_p()) - T2_SDIV(r0, r1, r2); - else - divrem(1, 1, r0, r1, r2); + return torri(_jit, THUMB2_SUBI|ARM_S,rn,rd,im); } static void -_divi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +T1_SBC(jit_state_t *_jit, int32_t rdn, int32_t rm) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - divr(r0, r1, rn(reg)); - jit_unget_reg(reg); + return emit_u16(_jit, THUMB_SBC|(_u3(rm)<<3)|_u3(rdn)); } static void -_divr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +T2_SBCS(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t rm) { - if (jit_armv7r_p() && jit_thumb_p()) - T2_UDIV(r0, r1, r2); - else - divrem(1, 0, r0, r1, r2); + return torrr(_jit, THUMB2_SBC|ARM_S,rn,rd,rm); } static void -_divi_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +T2_SBCSI(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); - divr_u(r0, r1, rn(reg)); - jit_unget_reg(reg); + return torri(_jit, THUMB2_SBCI|ARM_S,rn,rd,im); } static void -_iqdivr(jit_state_t *_jit, int32_t r0, int32_t r1, - int32_t r2, int32_t r3, jit_bool_t sign) +T1_RSBI(jit_state_t *_jit, int32_t rd, int32_t rn) { - 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; - } - else { - fallback: - movi(_R2_REGNO, w); - if (jit_thumb_p()) T1_BLX(_R2_REGNO); - else BLX(_R2_REGNO); - } - movr(r0, _R0_REGNO); - movr(r1, _R1_REGNO); - jit_unget_reg_args(); + return emit_u16(_jit, THUMB_RSBI|(_u3(rn)<<3)|_u3(rd)); } static void -_iqdivi(jit_state_t *_jit, int32_t r0, int32_t r1, - int32_t r2, jit_word_t i0, jit_bool_t sign) +T2_RSBI(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); - iqdivr(r0, r1, r2, rn(reg), sign); - jit_unget_reg(reg); + return torri(_jit, THUMB2_RSBI,rn,rd,im); } static void -_remr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +T1_MUL(jit_state_t *_jit, int32_t rdm, int32_t rn) { - divrem(0, 1, r0, r1, r2); + return emit_u16(_jit, THUMB_MUL|(_u3(rn)<<3)|_u3(rdm)); } static void -_remi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +T2_MUL(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t rm) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - remr(r0, r1, rn(reg)); - jit_unget_reg(reg); + return torrr(_jit, THUMB2_MUL,rn,rd,rm); } static void -_remr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +T2_SMULL(jit_state_t *_jit, int32_t rl, int32_t rh, int32_t rn, int32_t rm) { - divrem(0, 0, r0, r1, r2); + return torrrr(_jit, THUMB2_SMULL,rn,rl,rh,rm); } static void -_remi_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +T2_UMULL(jit_state_t *_jit, int32_t rl, int32_t rh, int32_t rn, int32_t rm) { - 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 torrrr(_jit, THUMB2_UMULL,rn,rl,rh,rm); } static void -_andr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +T2_SDIV(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 && (r0 == r1 || r0 == r2)) - T1_AND(r0, r0 == r1 ? r2 : r1); - else - T2_AND(r0, r1, r2); - } - else - 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; - 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); - } - } + return torrr(_jit, THUMB2_SDIV,rn,rd,rm); } static void -_orr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +T2_UDIV(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 && (r0 == r1 || r0 == r2)) - T1_ORR(r0, r0 == r1 ? r2 : r1); - else - T2_ORR(r0, r1, r2); - } - else - 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; - 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); - } - } + return torrr(_jit, THUMB2_UDIV,rn,rd,rm); } static void -_xorr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +T1_MLS(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t rm, int32_t ra) { - 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); - } - else - 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; - 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); - } - } + return torrrr(_jit, THUMB_MLS, rn, ra, rd, rm); } static void -_lshr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +T1_AND(jit_state_t *_jit, int32_t rdn, int32_t rm) { - 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 emit_u16(_jit, THUMB_AND|(_u3(rm)<<3)|_u3(rdn)); } static void -_lshi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +T2_AND(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t rm) { - 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); + return torrr(_jit, THUMB2_AND,rn,rd,rm); } static void -_rshr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +T2_ANDI(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 && r0 == r1) - T1_ASR(r0, r2); - else - T2_ASR(r0, r1, r2); - } - else - ASR(r0, r1, r2); + return torri(_jit, THUMB2_ANDI,rn,rd,im); } static void -_rshi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +T2_BICI(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t im) { - 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); + return torri(_jit, THUMB2_BICI,rn,rd,im); } static void -_rshr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +T1_REV(jit_state_t *_jit, int32_t rd, int32_t rm) { - 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); + return emit_u16(_jit, THUMB_REV|(_u3(rm)<<3)|_u3(rd)); } static void -_rshi_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +T2_REV(jit_state_t *_jit, int32_t rd, int32_t rm) { - 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); - } + return torrr(_jit, THUMB2_REV,rm,rd,rm); } 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); - } +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 -_ner(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +T2_SXTB(jit_state_t *_jit, int32_t rd, int32_t rm) { - 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); - } + return torrr(_jit, THUMB2_SXTB,_NOREG,rd,rm); } 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); - } +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 -_jmpr(jit_state_t *_jit, int32_t r0) +T2_UXTB(jit_state_t *_jit, int32_t rd, int32_t rm) { - 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); - } - } + return torrr(_jit, THUMB2_UXTB,_NOREG,rd,rm); } -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 +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 -_ldr_c(jit_state_t *_jit, int32_t r0, int32_t r1) +T2_SXTH(jit_state_t *_jit, int32_t rd, int32_t rm) { - if (jit_thumb_p()) - T2_LDRSBI(r0, r1, 0); - else - LDRSBI(r0, r1, 0); + return torrr(_jit, THUMB2_SXTH,_NOREG,rd,rm); } static void -_ldi_c(jit_state_t *_jit, int32_t r0, jit_word_t i0) +T1_UXTH(jit_state_t *_jit, int32_t rd, int32_t rm) { - 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); + return emit_u16(_jit, THUMB_UXTH|(_u3(rm)<<3)|_u3(rd)); } static void -_ldxr_c(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +T2_UXTH(jit_state_t *_jit, int32_t rd, int32_t rm) { - 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); -} - -static void -_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); - } - } + return torrr(_jit, THUMB2_UXTH,_NOREG,rd,rm); } static void -_ldr_uc(jit_state_t *_jit, int32_t r0, int32_t r1) +T1_LSL(jit_state_t *_jit, int32_t rdn, int32_t rm) { - if (jit_thumb_p()) - T2_LDRBI(r0, r1, 0); - else - LDRBI(r0, r1, 0); + return emit_u16(_jit, THUMB_LSL|(_u3(rm)<<3)|_u3(rdn)); } static void -_ldi_uc(jit_state_t *_jit, int32_t r0, jit_word_t i0) +T2_LSL(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t rm) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - if (jit_thumb_p()) - T2_LDRBI(r0, rn(reg), 0); - else - LDRBI(r0, rn(reg), 0); - jit_unget_reg(reg); + return torrr(_jit, THUMB2_LSL,rn,rd,rm); } static void -_ldxr_uc(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +T1_LSLI(jit_state_t *_jit, int32_t rd, int32_t rm, int32_t im) { - if (jit_thumb_p()) { - if ((r0|r1|r2) < 8) - T1_LDRB(r0, r1, r2); - else - T2_LDRB(r0, r1, r2); - } - 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); - } - } + return emit_u16(_jit, THUMB_LSLI|(_u5(im)<<6)|(_u3(rm)<<3)|_u3(rd)); } static void -_ldr_s(jit_state_t *_jit, int32_t r0, int32_t r1) +T2_LSLI(jit_state_t *_jit, int32_t rd, int32_t rm, int32_t im) { - if (jit_thumb_p()) - T2_LDRSHI(r0, r1, 0); - else - LDRSHI(r0, r1, 0); + return tshift(_jit, THUMB2_LSLI,rd,rm,im); } static void -_ldi_s(jit_state_t *_jit, int32_t r0, jit_word_t i0) +T1_LSR(jit_state_t *_jit, int32_t rdn, int32_t rm) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - if (jit_thumb_p()) - T2_LDRSHI(r0, rn(reg), 0); - else - LDRSHI(r0, rn(reg), 0); - jit_unget_reg(reg); + return emit_u16(_jit, THUMB_LSR|(_u3(rm)<<3)|_u3(rdn)); } static void -_ldxr_s(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +T2_LSR(jit_state_t *_jit, int32_t rd, int32_t rn, int32_t rm) { - if (jit_thumb_p()) { - if ((r0|r1|r2) < 8) - T1_LDRSH(r0, r1, r2); - else - T2_LDRSH(r0, r1, r2); - } - else - 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; - 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); - } - } + return torrr(_jit, THUMB2_LSR,rn,rd,rm); } static void -_ldr_us(jit_state_t *_jit, int32_t r0, int32_t r1) +T1_LSRI(jit_state_t *_jit, int32_t rd, int32_t rm, int32_t im) { - if (jit_thumb_p()) - T2_LDRHI(r0, r1, 0); - else - LDRHI(r0, r1, 0); + return emit_u16(_jit, THUMB_LSRI|(_u5(im)<<6)|(_u3(rm)<<3)|_u3(rd)); } static void -_ldi_us(jit_state_t *_jit, int32_t r0, jit_word_t i0) +T2_LSRI(jit_state_t *_jit, int32_t rd, int32_t rm, int32_t im) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - if (jit_thumb_p()) - T2_LDRHI(r0, rn(reg), 0); - else - LDRHI(r0, rn(reg), 0); - jit_unget_reg(reg); + return tshift(_jit, THUMB2_LSRI,rd,rm,im); } static void -_ldxr_us(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +T1_ASR(jit_state_t *_jit, int32_t rdn, int32_t rm) { - if (jit_thumb_p()) { - if ((r0|r1|r2) < 8) - T1_LDRH(r0, r1, r2); - else - T2_LDRH(r0, r1, r2); - } + 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_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) +{ + 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 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) +{ + 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 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) +{ + int32_t ret = inst & 0xfff; + return ((inst >> 23) & 1) ? ret : -ret; +} + +static uint32_t +encode_load_from_pool_offset(int32_t off) +{ + ASSERT(offset_in_load_from_pool_range(off)); + uint32_t u = off >= 0; + uint32_t ret = ((u ? off : -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 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) +{ + 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) +{ + 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 - 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); - } + 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, + int32_t r2, jit_word_t i0, jit_bool_t sign) +{ + 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 +qmulr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, int32_t r3) +{ + return iqmulr(_jit, r0,r1,r2,r3,1); +} + +static void +qmulr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, int32_t r3) +{ + return iqmulr(_jit, r0,r1,r2,r3,0); +} + +static void +qmuli(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, int32_t i0) +{ + return iqmuli(_jit, r0,r1,r2,i0,1); +} + +static void +qmuli_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, int32_t i0) +{ + return iqmuli(_jit, r0,r1,r2,i0,0); +} + +static void +divr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + T2_SDIV(_jit, r0, r1, r2); +} + +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 +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) +{ + 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 { - 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 (r0 == r3) { + if (r2 != r3) + movr(_jit, tmp, r3); + r3 = tmp; } + } + if (sign) + divr(_jit, r0, r2, r3); + else + divr_u(_jit, r0, r2, r3); + T1_MLS(_jit, r1, r3, r0, r2); + if (need_tmp) + unget_temp_gpr(_jit); } static void -_ldr_i(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) { - if (jit_thumb_p()) - T2_LDRI(r0, r1, 0); - else - LDRI(r0, r1, 0); + 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 -_ldi_i(jit_state_t *_jit, int32_t r0, jit_word_t i0) +qdivr(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); - if (jit_thumb_p()) - T2_LDRI(r0, rn(reg), 0); + return iqdivr(_jit, r0,r1,r2,r3,1); +} + +static void +qdivr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, int32_t r3) +{ + return iqdivr(_jit, r0,r1,r2,r3,0); +} + +static void +qdivi(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, int32_t i0) +{ + return iqdivi(_jit, r0,r1,r2,i0,1); +} + +static void +qdivi_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, int32_t i0) +{ + return iqdivi(_jit, r0,r1,r2,i0,0); +} + +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, sign); +} + +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 - LDRI(r0, rn(reg), 0); - jit_unget_reg(reg); + T2_LSLI(_jit, r0, r1, i0); + } } static void -_ldxr_i(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +rshr(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 && r0 == r1) + T1_ASR(_jit, r0, r2); + else + T2_ASR(_jit, r0, r1, r2); +} + +static void +rshi(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_ASRI(_jit, r0, r1, i0); else - 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; - 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_ASRI(_jit, r0, r1, i0); + } } static void -_str_c(jit_state_t *_jit, int32_t r0, int32_t r1) +rshr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - if (jit_thumb_p()) - T2_STRBI(r1, r0, 0); + if ((r0|r1|r2) < 8 && r0 == r1) + T1_LSR(_jit, r0, r2); + else + T2_LSR(_jit, 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(_jit, r0, r1); + else { + if ((r0|r1) < 8) + T1_LSRI(_jit, r0, r1, i0); else - STRBI(r1, r0, 0); + T2_LSRI(_jit, r0, r1, i0); + } +} + +static void +jmpr(jit_state_t *_jit, int32_t r0) +{ + T1_MOV(_jit, jit_gpr_regno(_PC), r0); +} + +static jit_reloc_t +jmp(jit_state_t *_jit) +{ + return T2_B(_jit); } static void -_sti_c(jit_state_t *_jit, jit_word_t i0, int32_t r0) +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); +} + +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) { - int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - if (jit_thumb_p()) - T2_STRBI(r0, rn(reg), 0); + 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 +ldr_c(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + T2_LDRSBI(_jit, r0, r1, 0); +} + +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); + T2_LDRSBI(_jit, r0, jit_gpr_regno(reg), 0); + unget_temp_gpr(_jit); +} + +static void +ldxr_c(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t 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) +{ + + 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 + 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 - STRBI(r0, rn(reg), 0); - jit_unget_reg(reg); + T2_LDRSB(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } } static void -_stxr_c(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_STRB(r2, r1, r0); - else - T2_STRB(r2, r1, r0); - } + 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 - 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); - } - } + 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 + T2_LDRB(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } } static void -_str_s(jit_state_t *_jit, int32_t r0, int32_t r1) +ldr_s(jit_state_t *_jit, int32_t r0, int32_t r1) { - if (jit_thumb_p()) - T2_STRHI(r1, r0, 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 - STRHI(r1, r0, 0); + 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 + T2_LDRSH(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } +} + +static void +ldr_us(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + T2_LDRHI(_jit, r0, r1, 0); +} + +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); + 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 -_sti_s(jit_state_t *_jit, jit_word_t i0, int32_t r0) +ldxi_us(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); - if (jit_thumb_p()) - T2_STRHI(r0, rn(reg), 0); + 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 - STRHI(r0, rn(reg), 0); - jit_unget_reg(reg); + 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 + T2_LDRH(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } } static void -_stxr_s(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_STRH(r2, r1, r0); - else - T2_STRH(r2, r1, r0); - } + 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(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) + 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 - 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); - } - } + 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 + T2_LDR(_jit, r0, r1, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } +} + +static void +str_c(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + T2_STRBI(_jit, r1, r0, 0); } static void -_str_i(jit_state_t *_jit, int32_t r0, int32_t r1) +sti_c(jit_state_t *_jit, jit_word_t i0, int32_t r0) { - if (jit_thumb_p()) - T2_STRI(r1, r0, 0); + 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 - STRI(r1, r0, 0); + T2_STRB(_jit, r1, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } +} + +static void +str_s(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + 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 -_sti_i(jit_state_t *_jit, jit_word_t i0, int32_t r0) +stxi_s(jit_state_t *_jit, jit_word_t i0, 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_STRI(r0, rn(reg), 0); + 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 - STRI(r0, rn(reg), 0); - jit_unget_reg(reg); + T2_STRH(_jit, r1, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } } static void -_stxr_i(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +str_i(jit_state_t *_jit, int32_t r0, int32_t r1) { - if (jit_thumb_p()) { - if ((r0|r1|r2) < 8) - T1_STR(r2, r1, r0); - else - T2_STR(r2, r1, r0); - } + T2_STRI(_jit, r1, r0, 0); +} + +static void +sti_i(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_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(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) + 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 - 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); - } - } + T2_STR(_jit, r1, r0, jit_gpr_regno(reg)); + unget_temp_gpr(_jit); + } } -# if __BYTE_ORDER == __LITTLE_ENDIAN static void -_bswapr_us(jit_state_t *_jit, int32_t r0, int32_t r1) +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); - } - } + if ((r0|r1) < 8) + T1_REV(_jit, r0, r1); + else + T2_REV(_jit, r0, r1); } -#endif static void -_extr_c(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_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_SXTB(_jit, r0, r1); + else + T2_SXTB(_jit, r0, r1); } static void -_extr_uc(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_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_UXTB(_jit, r0, r1); + else + T2_UXTB(_jit, r0, r1); } static void -_extr_s(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_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_SXTH(_jit, r0, r1); + else + T2_SXTH(_jit, r0, r1); } static void -_extr_us(jit_state_t *_jit, int32_t r0, int32_t r1) +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); - } - else { - if (jit_armv6_p()) - UXTH(r0, r1); - else { - LSLI(r0, r1, 16); - LSRI(r0, r0, 16); - } - } + if ((r0|r1) < 8) + T1_UXTH(_jit, r0, r1); + else + T2_UXTH(_jit, r0, r1); } static void -_callr(jit_state_t *_jit, int32_t r0) +callr(jit_state_t *_jit, int32_t r0) { - if (jit_thumb_p()) - T1_BLX(r0); - else - BLX(r0); + T1_BLX(_jit, r0); } static void -_calli(jit_state_t *_jit, jit_word_t i0) +calli(jit_state_t *_jit, jit_word_t i0) { - 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); - } + if (i0 & 1) + jit_patch_there(_jit, T2_BLI(_jit), (void*)(i0 & ~1)); + else + jit_patch_there(_jit, T2_BLXI(_jit), (void*)i0); } -static jit_word_t -_calli_p(jit_state_t *_jit, jit_word_t i0) +static void +ret(jit_state_t *_jit) { - 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_BX(_jit, jit_gpr_regno(_LR)); } static void -_prolog(jit_state_t *_jit, jit_node_t *node) +reti(jit_state_t *_jit, int32_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); - } + movi(_jit, jit_gpr_regno(_R0), i0); + ret(_jit); } static void -_epilog(jit_state_t *_jit, jit_node_t *node) +retr(jit_state_t *_jit, int32_t r0) { - if (_jitc->function->assume_frame) - return; + movr(_jit, jit_gpr_regno(_R0), r0); + ret(_jit); +} - 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(); -} - -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"); +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) +{ + 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); } -#endif diff --git a/libguile/lightening/lightening/arm-swf.c b/libguile/lightening/lightening/arm-swf.c deleted file mode 100644 index 2b8bfa139..000000000 --- a/libguile/lightening/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/libguile/lightening/lightening/arm-vfp.c b/libguile/lightening/lightening/arm-vfp.c index d17a77844..208edc316 100644 --- a/libguile/lightening/lightening/arm-vfp.c +++ b/libguile/lightening/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. * @@ -14,2317 +14,1155 @@ * License for more details. * * Authors: - * Paulo Cesar Pereira de Andrade + * 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 -# 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 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 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) -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); -#endif - -#if CODE -# define vfp_regno(rn) (((rn) - 16) >> 1) +#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_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_P 0x00800000 /* positive offset */ +#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 vfp_regno(rn) ((rn) >> 1) -static int -encode_vfp_double(int mov, int inv, unsigned lo, unsigned hi) +static void +vodi(jit_state_t *_jit, int oi, int r0) { - 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; - } - } - } + ASSERT(!(oi & 0x0000f000)); + ASSERT(!(r0 & 1)); + r0 >>= 1; + emit_wide_thumb(_jit, oi|(_u4(r0)<<12)); +} -fail: - /* need another approach (load from memory, move from arm register, etc) */ - return (-1); +static void +vo_ss(jit_state_t *_jit, int o, int r0, int 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)); +} -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); +static void +vo_dd(jit_state_t *_jit, int o, int r0, int 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 -_vodi(jit_state_t *_jit, int oi, int r0) +vors_(jit_state_t *_jit, int o, int r0, int r1) { - 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); + 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 -_voqi(jit_state_t *_jit, int oi, int r0) +vori_(jit_state_t *_jit, int o, int r0, int r1) { - 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); + ASSERT(!(o & 0xf000f00f)); + /* use same bit pattern, to set opc1... */ + 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 -_cc_vo_ss(jit_state_t *_jit, int cc, int o, int r0, int r1) +vorrd(jit_state_t *_jit, int o, int r0, int r1, int r2) { - 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 & 0xf00ff00f)); + ASSERT(!(r2 & 1)); + r2 >>= 1; + emit_wide_thumb(_jit, ARM_CC_AL|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u4(r2)); } static void -_cc_vo_dd(jit_state_t *_jit, int cc, int o, int r0, int r1) +vosss(jit_state_t *_jit, int o, int r0, int r1, int r2) { - 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 & 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 -_cc_vo_qd(jit_state_t *_jit, int cc, int o, int r0, int r1) +voddd(jit_state_t *_jit, int o, int r0, int r1, int r2) { - 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 & 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)); } static void -_cc_vo_qq(jit_state_t *_jit, int cc, int o, int r0, int r1) +vldst(jit_state_t *_jit, int o, int r0, int r1, int i0) { - 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); + /* i0 << 2 is byte offset */ + ASSERT(!(o & 0xf00ff0ff)); + if (r0 & 1) { + ASSERT(!(o & ARM_V_F64)); + o |= ARM_V_D; + } + r0 >>= 1; + emit_wide_thumb(_jit, ARM_CC_AL|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u8(i0)); } static void -_cc_vorr_(jit_state_t *_jit, int cc, int o, int r0, int r1) +VADD_F32(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - 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); + vosss(_jit,ARM_VADD_F,r0,r1,r2); } static void -_cc_vors_(jit_state_t *_jit, int cc, int o, int r0, int r1) +VADD_F64(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - 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); + voddd(_jit,ARM_VADD_F|ARM_V_F64,r0,r1,r2); } static void -_cc_vorv_(jit_state_t *_jit, int cc, int o, int r0, int r1) +VSUB_F32(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - 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); + vosss(_jit,ARM_VSUB_F,r0,r1,r2); } static void -_cc_vori_(jit_state_t *_jit, int cc, int o, int r0, int r1) +VSUB_F64(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - 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); + voddd(_jit,ARM_VSUB_F|ARM_V_F64,r0,r1,r2); } static void -_cc_vorrd(jit_state_t *_jit, int cc, int o, int r0, int r1, int r2) +VMUL_F32(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t 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); + vosss(_jit,ARM_VMUL_F,r0,r1,r2); } static void -_cc_vosss(jit_state_t *_jit, int cc, int o, int r0, int r1, int r2) +VMUL_F64(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t 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); + voddd(_jit,ARM_VMUL_F|ARM_V_F64,r0,r1,r2); } static void -_cc_voddd(jit_state_t *_jit, int cc, int o, int r0, int r1, int r2) +VDIV_F32(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t 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); + vosss(_jit,ARM_VDIV_F,r0,r1,r2); } static void -_cc_voqdd(jit_state_t *_jit, int cc, int o, int r0, int r1, int r2) +VDIV_F64(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t 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); + voddd(_jit,ARM_VDIV_F|ARM_V_F64,r0,r1,r2); } static void -_cc_voqqd(jit_state_t *_jit, int cc, int o, int r0, int r1, int r2) +VABS_F32(jit_state_t *_jit, int32_t r0, int32_t r1) { - 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); + vo_ss(_jit,ARM_VABS_F,r0,r1); } static void -_cc_voqqq(jit_state_t *_jit, int cc, int o, int r0, int r1, int r2) +VABS_F64(jit_state_t *_jit, int32_t r0, int32_t r1) { - 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); + vo_dd(_jit,ARM_VABS_F|ARM_V_F64,r0,r1); } static void -_cc_vldst(jit_state_t *_jit, int cc, int o, int r0, int r1, int i0) +VNEG_F32(jit_state_t *_jit, int32_t r0, int32_t r1) { - 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; - } - 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 - ii(thumb.i); -} - -static void -_cc_vorsl(jit_state_t *_jit, int cc, int o, int r0, int r1, int i0) -{ - 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); - } + vo_ss(_jit,ARM_VNEG_F,r0,r1); } static void -_vfp_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); - } - } +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 -_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); - } - } - 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); - } - } - else { - movi(r0, u.i[0]); - movi(r0 + 1, u.i[1]); - } +VSQRT_F32(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + vo_ss(_jit,ARM_VSQRT_F,r0,r1); } static void -_vfp_extr_d_f(jit_state_t *_jit, int32_t r0, int32_t r1) +VSQRT_F64(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); - } - } - 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); - } + vo_dd(_jit,ARM_VSQRT_F|ARM_V_F64,r0,r1); } static void -_vfp_extr_f_d(jit_state_t *_jit, int32_t r0, int32_t r1) +VMOV_F32(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); - } - } - 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); - } + vo_ss(_jit,ARM_VMOV_F,r0,r1); } static void -_vfp_extr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +VMOV_F64(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); - } + vo_dd(_jit,ARM_VMOV_F|ARM_V_F64,r0,r1); } static void -_vfp_extr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +VMOV_D_AA(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - 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); - } + vorrd(_jit,ARM_VMOV_D_AA,r1,r2,r0); } static void -_vfp_truncr_f_i(jit_state_t *_jit, int32_t r0, int32_t r1) +VMOV_S_A(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); + vors_(_jit,ARM_VMOV_S_A,r1,r0); } static void -_vfp_truncr_d_i(jit_state_t *_jit, int32_t r0, int32_t r1) +VCMP_F32(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); -} - -# 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) -{ - 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); - } - } - 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); - } + vo_ss(_jit,ARM_VCMP,r0,r1); } static void -_vfp_cmp_d(jit_state_t *_jit, int32_t r0, int32_t r1) +VCMP_F64(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); - } - } - 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); - } + vo_dd(_jit,ARM_VCMP|ARM_V_F64,r0,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); - } +VMRS(jit_state_t *_jit) +{ + emit_wide_thumb(_jit, ARM_CC_AL|ARM_VMRS|(0xf<<12)); } static void -_vcmp01_f(jit_state_t *_jit, int c0, int c1, - int32_t r0, int32_t r1, int32_t r2) +VCVT_S32_F32(jit_state_t *_jit, int32_t r0, int32_t r1) { - vfp_cmp_f(r1, r2); - vcmp01_x(c0, c1, r0); + vo_ss(_jit,ARM_VCVT_S32_F32,r0,r1); } static void -_vcmp01_d(jit_state_t *_jit, int c0, int c1, - int32_t r0, int32_t r1, int32_t r2) +VCVT_S32_F64(jit_state_t *_jit, int32_t r0, int32_t r1) { - vfp_cmp_d(r1, r2); - vcmp01_x(c0, c1, r0); + vo_ss(_jit,ARM_VCVT_S32_F64,r0,r1); } static void -_vcmp10_x(jit_state_t *_jit, int cc, int32_t r0) +VCVT_F32_S32(jit_state_t *_jit, int32_t r0, int32_t r1) { - 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); - } + vo_ss(_jit,ARM_VCVT_F32_S32,r0,r1); } + 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); - } +VCVT_F64_S32(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + vo_ss(_jit,ARM_VCVT_F64_S32,r0,r1); } static void -_vfp_uneqr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +VCVT_F32_F64(jit_state_t *_jit, int32_t r0, int32_t r1) { - vfp_cmp_f(r1, r2); - vfp_uneqr_x(r0); + vo_ss(_jit,ARM_VCVT_F32_F64,r0,r1); } -fopi(uneq) +static void +VCVT_F64_F32(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + vo_ss(_jit,ARM_VCVT_F64_F32,r0,r1); +} static void -_vfp_uneqr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +VMOV_A_S32(jit_state_t *_jit, int32_t r0, int32_t r1) { - vfp_cmp_d(r1, r2); - vfp_uneqr_x(r0); + vori_(_jit,ARM_VMOV_A_D,r0,r1); } -dopi(uneq) +static void +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 -_vcmp_01_x(jit_state_t *_jit, int cc, int32_t r0) +VIMM(jit_state_t *_jit, int32_t oi, 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); - } + vodi(_jit, oi,r0); } +/* index is multipled by four */ static void -_vcmp_01_f(jit_state_t *_jit, int cc, - int32_t r0, int32_t r1, int32_t r2) +VLDRN_F32(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) { - vfp_cmp_f(r1, r2); - vcmp_01_x(cc, r0); + vldst(_jit,ARM_VLDR,r0,r1,i0); } static void -_vcmp_01_d(jit_state_t *_jit, int cc, - int32_t r0, int32_t r1, int32_t r2) +VLDR_F32(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) { - vfp_cmp_d(r1, r2); - vcmp_01_x(cc, r0); + vldst(_jit,ARM_VLDR|ARM_P,r0,r1,i0); } -fopi(unge) -dopi(unge) -fopi(ungt) -dopi(ungt) +static void +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 -_vfp_ltgtr_x(jit_state_t *_jit, int32_t r0) +VLDR_F64(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) { - 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); - } + vldst(_jit,ARM_VLDR|ARM_V_F64|ARM_P,r0,r1,i0); } static void -_vfp_ltgtr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +VSTRN_F32(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) { - vfp_cmp_f(r1, r2); - vfp_ltgtr_x(r0); + vldst(_jit,ARM_VSTR,r0,r1,i0); } -fopi(ltgt) +static void +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 -_vfp_ltgtr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +VSTRN_F64(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0) { - vfp_cmp_d(r1, r2); - vfp_ltgtr_x(r0); + vldst(_jit,ARM_VSTR|ARM_V_F64,r0,r1,i0); } -dopi(ltgt) +static void +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_ordr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +absr_f(jit_state_t *_jit, int32_t r0, int32_t r1) { - vfp_cmp_f(r1, r2); - vcmp10_x(ARM_CC_VS, r0); + VABS_F32(_jit, r0,r1); } -fopi(ord) +static void +absr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + VABS_F64(_jit, r0,r1); +} static void -_vfp_ordr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +negr_f(jit_state_t *_jit, int32_t r0, int32_t r1) { - vfp_cmp_d(r1, r2); - vcmp10_x(ARM_CC_VS, r0); + VNEG_F32(_jit, r0,r1); } -dopi(ord) +static void +negr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + VNEG_F64(_jit, r0,r1); +} static void -_vfp_unordr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +sqrtr_f(jit_state_t *_jit, int32_t r0, int32_t r1) { - vfp_cmp_f(r1, r2); - vcmp_01_x(ARM_CC_VS, r0); + VSQRT_F32(_jit, r0,r1); } -fopi(unord) +static void +sqrtr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + VSQRT_F64(_jit, r0,r1); +} static void -_vfp_unordr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +addr_f(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); + VADD_F32(_jit, r0,r1,r2); } -dopi(unord) +static void +addr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + VADD_F64(_jit, r0,r1,r2); +} -static jit_word_t -_vbcmp_x(jit_state_t *_jit, int cc, jit_word_t i0) +static void +subr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - 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); + VSUB_F32(_jit, r0,r1,r2); } +static void +subr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +{ + VSUB_F64(_jit, r0,r1,r2); +} -static jit_word_t -_vbcmp_f(jit_state_t *_jit, int cc, - jit_word_t i0, int32_t r0, int32_t r1) +static void +mulr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - vfp_cmp_f(r0, r1); - return (vbcmp_x(cc, i0)); + VMUL_F32(_jit, r0,r1,r2); } -static jit_word_t -_vbcmp_d(jit_state_t *_jit, int cc, - jit_word_t i0, int32_t r0, int32_t r1) +static void +mulr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - vfp_cmp_d(r0, r1); - return (vbcmp_x(cc, i0)); + VMUL_F64(_jit, r0,r1,r2); } -static jit_word_t -_vbncmp_x(jit_state_t *_jit, int cc, jit_word_t i0) +static void +divr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - 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); -} - -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)); -} - -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) -{ - 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); + VDIV_F32(_jit, r0,r1,r2); } -static jit_word_t -_vfp_buneqr_f(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) +static void +divr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) { - vfp_cmp_f(r0, r1); - return (vfp_buneqr_x(i0)); + VDIV_F64(_jit, r0,r1,r2); } -fbopi(uneq) +static void +cmp_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + VCMP_F32(_jit, r0, r1); +} -static jit_word_t -_vfp_buneqr_d(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) +static void +cmp_d(jit_state_t *_jit, int32_t r0, int32_t r1) { - vfp_cmp_d(r0, r1); - return (vfp_buneqr_x(i0)); + VCMP_F64(_jit, r0, r1); } -dbopi(uneq) +static jit_reloc_t +vbcmp_x(jit_state_t *_jit, int cc) +{ + VMRS(_jit); + return T2_CC_B(_jit, cc); +} -static jit_word_t -_vfp_bunger_x(jit_state_t *_jit, jit_word_t i0) +static jit_reloc_t +vbcmp_f(jit_state_t *_jit, int cc, int32_t r0, int32_t r1) { - 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); + 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_word_t -_vfp_bunger_f(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) +static jit_reloc_t +vbncmp_f(jit_state_t *_jit, int cc, int32_t r0, int32_t r1) { - vfp_cmp_f(r0, r1); - return (vfp_bunger_x(i0)); + cmp_f(_jit, r0, r1); + return vbncmp_x(_jit, cc); } -fbopi(unge) +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_word_t -_vfp_bunger_d(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) +static jit_reloc_t +bltr_d(jit_state_t *_jit, int32_t r0, int32_t r1) { - vfp_cmp_d(r0, r1); - return (vfp_bunger_x(i0)); + return vbcmp_d(_jit, ARM_CC_MI, r0, r1); } -dbopi(unge) +static jit_reloc_t +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 +bler_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + return vbcmp_d(_jit, ARM_CC_LS, r0, r1); +} -static jit_word_t -_vfp_bltgtr_x(jit_state_t *_jit, jit_word_t i0) +static jit_reloc_t +beqr_f(jit_state_t *_jit, int32_t r0, int32_t r1) { - 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)); + return vbcmp_f(_jit, ARM_CC_EQ, r0, r1); +} + +static jit_reloc_t +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +ldr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + VLDR_F32(_jit, r0,r1,0); +} + +static void +ldr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + VLDR_F64(_jit, r0,r1,0); +} + +static void +str_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + VSTR_F32(_jit, r1,r0,0); +} + +static void +str_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + VSTR_F64(_jit, r1,r0,0); +} + +static void +movr_f(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + if (r0 != r1) + VMOV_F32(_jit, r0, r1); +} + +static void +movr_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + if (r0 != r1) + VMOV_F64(_jit, r0, r1); +} + +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; } - 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); + 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; } - patch_at(arm_patch_jump, p, _jit->pc.w); - patch_at(arm_patch_jump, q, _jit->pc.w); - return (w); + } + /* (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 +movi_f(jit_state_t *_jit, int32_t r0, jit_float32_t i0) +{ + 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 jit_word_t -_vfp_bltgtr_f(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) +static void +extr_d_f(jit_state_t *_jit, int32_t r0, int32_t r1) { - vfp_cmp_f(r0, r1); - return (vfp_bltgtr_x(i0)); + VCVT_F64_F32(_jit, r0, r1); } -fbopi(ungt) -dbopi(ungt) -fbopi(ltgt) +static void +extr_f_d(jit_state_t *_jit, int32_t r0, int32_t r1) +{ + VCVT_F32_F64(_jit, r0, r1); +} -static jit_word_t -_vfp_bltgtr_d(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) +static void +extr_f(jit_state_t *_jit, int32_t r0, int32_t r1) { - vfp_cmp_d(r0, r1); - return (vfp_bltgtr_x(i0)); + VMOV_V_I32(_jit, r0, r1); + VCVT_F32_S32(_jit, r0, r0); } -dbopi(ltgt) -fbopi(ord) -dbopi(ord) -fbopi(unord) -dbopi(unord) +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 -_vfp_ldi_f(jit_state_t *_jit, int32_t r0, jit_word_t i0) +truncr_f_i(jit_state_t *_jit, int32_t r0, int32_t r1) { - 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); + 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 -_vfp_ldi_d(jit_state_t *_jit, int32_t r0, jit_word_t i0) +truncr_d_i(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_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); + 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 -_vfp_ldxr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +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); - addr(rn(reg), r1, r2); - VLDR_F32(r0, rn(reg), 0); - jit_unget_reg(reg); - } - else - ldxr_i(r0, r1, r2); + 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 -_vfp_ldxr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +ldi_d(jit_state_t *_jit, int32_t r0, jit_word_t i0) { - 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); + 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 { - ldr_i(r0, rn(reg)); - ldxi_i(r0 + 1, rn(reg), 4); + 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); } - 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); - } - } + } + else { + i0 = -i0; + ASSERT(!(i0 & 3)); + if (i0 < 1024) + VLDRN_F32(_jit, r0, r1, i0 >> 2); + else { + 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 - 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); - } - } + } +} + +static void +ldxi_d(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) +{ + if (i0 >= 0) { + ASSERT(!(i0 & 3)); + if (i0 < 1024) + VLDR_F64(_jit, r0, r1, i0 >> 2); + else { + 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 { + i0 = -i0; + ASSERT(!(i0 & 3)); + if (i0 < 1024) + VLDRN_F64(_jit, r0, r1, i0 >> 2); 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); + 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); } + } } static void -_vfp_sti_f(jit_state_t *_jit, jit_word_t i0, int32_t r0) +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); + 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_sti_d(jit_state_t *_jit, jit_word_t i0, int32_t r0) +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); + 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_stxr_f(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +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); + 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_stxr_d(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2) +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); + 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 +stxi_f(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) +{ + if (i0 >= 0) { + ASSERT(!(i0 & 3)); + if (i0 < 1024) + VSTR_F32(_jit, r1, r0, i0 >> 2); else { - str_i(rn(reg), r2); - stxi_i(4, rn(reg), r2 + 1); + 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); } - 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 { + i0 = -i0; + ASSERT(!(i0 & 3)); + if (i0 < 1024) + VSTRN_F32(_jit, r1, r0, i0 >> 2); + else { + 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); } - 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); - } - } + } +} + +static void +stxi_d(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1) +{ + if (i0 >= 0) { + ASSERT(!(i0 & 3)); + if (i0 < 0124) + VSTR_F64(_jit, r1, r0, i0 >> 2); + else { + 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 { + i0 = -i0; + ASSERT(!(i0 & 3)); + if (i0 < 1024) + VSTRN_F64(_jit, r1, r0, i0 >> 2); 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); + 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); } + } } static void -_vfp_vaarg_d(jit_state_t *_jit, int32_t r0, int32_t r1) +retr_d(jit_state_t *_jit, int32_t r) { - int32_t reg; - - assert(_jitc->function->self.call & jit_call_varargs); + movr_d(_jit, jit_fpr_regno(_D0), r); + ret(_jit); +} - /* Adjust pointer. */ - reg = jit_get_reg(jit_class_gpr); - andi(rn(reg), r1, 7); - addr(r1, r1, rn(reg)); - jit_unget_reg(reg); +static void +retr_f(jit_state_t *_jit, int32_t r) +{ + movr_f(_jit, jit_fpr_regno(_S0), r); + ret(_jit); +} - /* Load argument. */ - vfp_ldr_d(r0, r1); +static void +retval_f(jit_state_t *_jit, int32_t r0) +{ + movr_f(_jit, r0, jit_fpr_regno(_S0)); +} - /* Update stack pointer. */ - addi(r1, r1, sizeof(jit_float64_t)); +static void +retval_d(jit_state_t *_jit, int32_t r0) +{ + movr_d(_jit, r0, jit_fpr_regno(_D0)); } -# undef dbopi -# undef fbopi -# undef dopi -# undef fopi -#endif diff --git a/libguile/lightening/lightening/arm.c b/libguile/lightening/lightening/arm.c index 0df47814e..d587e7158 100644 --- a/libguile/lightening/lightening/arm.c +++ b/libguile/lightening/lightening/arm.c @@ -14,2271 +14,126 @@ * License for more details. * * Authors: - * Paulo Cesar Pereira de Andrade + * Paulo Cesar Pereira de Andrade */ -#if defined(__linux__) -# include <stdio.h> -#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-swf.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, "<none>" }, +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]); -/* - * Implementation - */ -void -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) +struct abi_arg_iterator { - 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(); -} + const jit_operand_t *args; + size_t argc; -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(); -} + size_t arg_idx; + size_t gpr_idx; + uint32_t vfp_used_registers; + size_t stack_size; + size_t stack_padding; +}; -void -_jit_epilog(jit_state_t *_jit) -{ - assert(_jitc->function); - assert(_jitc->function->epilog->next == NULL); - jit_link(_jitc->function->epilog); - _jitc->function = NULL; -} +static size_t page_size; jit_bool_t -_jit_arg_register_p(jit_state_t *_jit, jit_node_t *u) -{ - 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)); -} - -static jit_node_t * -_jit_make_arg(jit_state_t *_jit, jit_node_t *node) -{ - 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); -} - -jit_node_t * -_jit_make_arg_f(jit_state_t *_jit, jit_node_t *node) -{ - 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); -} - -jit_node_t * -_jit_make_arg_d(jit_state_t *_jit, jit_node_t *node) -{ - 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; - } - } - 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); -} - -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) +jit_get_cpu(void) { - 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(); + page_size = sysconf(_SC_PAGE_SIZE); + // FIXME check version, thumb, hardware fp support + return 1; } jit_bool_t -_jit_regarg_p(jit_state_t *_jit, jit_node_t *node, int32_t regno) +jit_init(jit_state_t *_jit) { - 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); + return 1; } -void -_jit_finishr(jit_state_t *_jit, int32_t r0) +static size_t +jit_initial_frame_size (void) { - 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-swf.c" -# include ", 2018arm-vfp.c" -#undef CODE - -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 -} - -void -_emit_ldxi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) -{ - 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 0; } static void -_jit_unget_reg_pair(jit_state_t *_jit, int32_t reg) +reset_abi_arg_iterator(struct abi_arg_iterator *iter, size_t argc, + const jit_operand_t *args) { - 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(); - } + memset(iter, 0, sizeof *iter); + iter->argc = argc; + iter->args = args; } -/* 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 +next_abi_arg(struct abi_arg_iterator *iter, jit_operand_t *arg) +{ + 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; + } + } + } + *arg = jit_operand_mem (abi, JIT_SP, iter->stack_size); + iter->stack_size += 4; } static void -_load_const(jit_state_t *_jit, jit_bool_t uniq, int32_t r0, jit_word_t i0) +jit_flush(void *fptr, void *tptr) { - 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; + 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); } -static void -_flush_consts(jit_state_t *_jit) +static inline size_t +jit_stack_alignment(void) { - 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; + return 8; } -/* to be called if needing to start over a function */ static void -_invalidate_consts(jit_state_t *_jit) +jit_try_shorten(jit_state_t *_jit, jit_reloc_t reloc, jit_pointer_t addr) { - /* 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) +static void* +bless_function_pointer(void *ptr) { - 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; + // Set low bit to mark as thumb mode. + return (void*) (((uintptr_t)ptr) | 1); } diff --git a/libguile/lightening/lightening/arm.h b/libguile/lightening/lightening/arm.h index 9177f1354..47bd2c257 100644 --- a/libguile/lightening/lightening/arm.h +++ b/libguile/lightening/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,114 @@ #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 JIT_R0 _R0 +#define JIT_R1 _R1 +#define JIT_R2 _R2 +#define JIT_R3 _R3 +#define JIT_TMP0 _R12 + +#define JIT_V0 _R4 +#define JIT_V1 _R5 +#define JIT_V2 _R6 +#define JIT_TMP1 _R7 +#define JIT_V3 _R8 +#define JIT_V4 _R9 +#define JIT_V5 _R10 +#define JIT_V6 _R11 + +#define JIT_SP _R13 +#define _LR _R14 +#define _PC _R15 + +#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_FTMP _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, JIT_TMP1 -/* - * Initialization - */ -JIT_API jit_cpu_t jit_cpu; #endif /* _jit_arm_h */ diff --git a/libguile/lightening/lightening/lightening.c b/libguile/lightening/lightening/lightening.c index 0973d8a69..572976f40 100644 --- a/libguile/lightening/lightening/lightening.c +++ b/libguile/lightening/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,23 @@ 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 byte_size; + uint32_t capacity; + struct jit_literal_pool_entry entries[]; +}; +#endif // JIT_NEEDS_LITERAL_POOL + struct jit_state { union jit_pc pc; @@ -57,25 +76,50 @@ 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); 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; +#ifdef JIT_NEEDS_LITERAL_POOL +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); +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, const jit_operand_t *args); static void next_abi_arg(struct abi_arg_iterator *iter, @@ -102,16 +146,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, 0); +#endif + return _jit; } void jit_destroy_state(jit_state_t *_jit) { +#ifdef JIT_NEEDS_LITERAL_POOL + _jit->free (_jit->pool); +#endif _jit->free (_jit); } @@ -131,6 +185,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 @@ -147,30 +204,43 @@ 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* 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; _jit->overflow = 0; _jit->frame_size = 0; +#ifdef JIT_NEEDS_LITERAL_POOL + clear_literal_pool(_jit->pool); +#endif - return code; + return bless_function_pointer(start); } static int @@ -179,14 +249,46 @@ is_power_of_two (unsigned x) return x && !(x & (x-1)); } -void -jit_align(jit_state_t *_jit, unsigned align) +static jit_gpr_t +get_temp_gpr(jit_state_t *_jit) { - 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); + 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) +{ + switch(_jit->temp_fpr_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--; +} + +static void +unget_temp_gpr(jit_state_t *_jit) +{ + ASSERT(_jit->temp_gpr_saved); + _jit->temp_gpr_saved--; } static inline void emit_u8(jit_state_t *_jit, uint8_t u8) { @@ -210,6 +312,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 } } @@ -223,38 +329,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; } @@ -272,7 +361,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) { @@ -284,25 +376,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); + 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. + patch_jmp_offset(loc.ui, diff); + remove_pending_literal(_jit, reloc); + } else { + // Target out of range; branch to veneer. + patch_pending_literal(_jit, reloc, (uintptr_t) addr); + } + } else { + // Already emitted a veneer. In this case, patch the veneer + // directly. + patch_veneer((uint32_t *) target, addr); + } + return; + } + case JIT_RELOC_JCC_WITH_VENEER: { + 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); + } else { + patch_pending_literal(_jit, reloc, (uintptr_t) addr); + } + } else { + patch_veneer((uint32_t *) target, addr); + } + return; + } + case JIT_RELOC_LOAD_FROM_POOL: { + 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 { + *(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; @@ -403,6 +538,45 @@ 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) +{ + 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) @@ -570,10 +744,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); } } @@ -609,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, @@ -704,7 +882,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 +907,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 @@ -849,10 +1027,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 @@ -869,12 +1048,15 @@ static const jit_gpr_t V[] = { #ifdef JIT_V7 , JIT_V7 #endif +#ifdef JIT_V8 + , JIT_V8 +#endif +#ifdef JIT_V9 + , JIT_V9 +#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 @@ -901,55 +1083,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); + + size_t offset = 0; + 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]); + 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 jit_align_stack(_jit, frame_size); + 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 - - jit_shrink_stack(_jit, frame_size); + ASSERT(v <= v_count); + ASSERT(vf <= vf_count); + ASSERT((pv_count + v) * (__WORDSIZE / 8) + vf * 8 <= frame_size); - /* Restore callee-save registers. */ - for (size_t i = 0; i < vf; i++) - jit_popr_d (_jit, VF[vf - i - 1]); + size_t offset = 0; + 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); + 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); - for (size_t i = 0; i < v; i++) - jit_popr (_jit, V[v - i - 1]); + jit_shrink_stack(_jit, frame_size); } - // Precondition: stack is already aligned. static size_t prepare_call_args(jit_state_t *_jit, size_t argc, jit_operand_t args[]) @@ -969,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: @@ -1029,3 +1210,147 @@ 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*) (uintptr_t) entry->value); + break; + case JIT_RELOC_JCC_WITH_VENEER: + patch_jcc_offset((uint32_t*) loc, diff); + emit_veneer(_jit, (void*) (uintptr_t) 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/libguile/lightening/lightening/x86-cpu.c b/libguile/lightening/lightening/x86-cpu.c index 041c54906..ab0da684e 100644 --- a/libguile/lightening/lightening/x86-cpu.c +++ b/libguile/lightening/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) { @@ -397,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 @@ -2128,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 @@ -2136,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 @@ -2583,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/libguile/lightening/lightening/x86-sse.c b/libguile/lightening/lightening/x86-sse.c index 9f4084c85..15db27bca 100644 --- a/libguile/lightening/lightening/x86-sse.c +++ b/libguile/lightening/lightening/x86-sse.c @@ -170,39 +170,6 @@ movr_d(jit_state_t *_jit, int32_t r0, int32_t 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 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) { ssexr(_jit, 0xf3, X86_SSE_ADD, r0, r1); @@ -409,14 +376,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 +510,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 +528,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 +572,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 +590,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 +606,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 +623,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 +642,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 +659,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/libguile/lightening/lightening/x86.c b/libguile/lightening/lightening/x86.c index a79d602aa..965191a4c 100644 --- a/libguile/lightening/lightening/x86.c +++ b/libguile/lightening/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" @@ -216,35 +245,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. */ @@ -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) { } @@ -387,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 @@ -397,10 +394,14 @@ 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 (); } } + +static void* +bless_function_pointer(void *ptr) +{ + return ptr; +} diff --git a/libguile/lightening/lightening/x86.h b/libguile/lightening/lightening/x86.h index 6e029d631..64ee00637 100644 --- a/libguile/lightening/lightening/x86.h +++ b/libguile/lightening/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 @@ -76,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 @@ -132,7 +81,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_TMP0 _RBX # define JIT_F0 _XMM0 # define JIT_F1 _XMM1 # define JIT_F2 _XMM2 @@ -141,6 +90,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_TMP0 #elif __CYGWIN__ # define JIT_R0 _RAX # define JIT_R1 _RCX @@ -148,7 +98,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 @@ -172,6 +122,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 @@ -181,7 +132,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 @@ -203,6 +154,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/libguile/lightening/tests/Makefile b/libguile/lightening/tests/Makefile index 7b6bbd49d..2a048501d 100644 --- a/libguile/lightening/tests/Makefile +++ b/libguile/lightening/tests/Makefile @@ -1,8 +1,26 @@ TESTS=$(sort $(basename $(wildcard *.c))) -TARGETS=native - +TARGETS=native ia32 aarch64 +ALL_TARGETS=$(TARGETS) armv7 + +# Suitable values of cross-compiler variables for Debian: +# +# make test CC_IA32=i668-linux-gnu-gcc CC_AARCH64=aarch64-linux-gnu-gcc +# +# The relevant packages that you need to run this: +# +# dpkg --add-architecture i386 +# dpkg --add-architecture arm64 +# 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 +# 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 +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))) @@ -29,9 +47,17 @@ test-ia32-%: CC = $(CC_IA32) test-ia32-%: %.c lightening-ia32.o test.h $(CC) $(CFLAGS) $(CPPFLAGS) -I.. -o $@ lightening-ia32.o $< -.PRECIOUS: $(foreach TARGET,$(TARGETS),$(addprefix test-$(TARGET)-,$(TESTS))) -.PRECIOUS: $(foreach TARGET,$(TARGETS),lightening-$(TARGET).o) +test-aarch64-%: CC = $(CC_AARCH64) +test-aarch64-%: %.c lightening-aarch64.o test.h + $(CC) $(CFLAGS) $(CPPFLAGS) -I.. -o $@ lightening-aarch64.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) diff --git a/libguile/lightening/tests/nop.c b/libguile/lightening/tests/nop.c deleted file mode 100644 index c029954d2..000000000 --- a/libguile/lightening/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); -} diff --git a/libguile/lightening/tests/pushpop.c b/libguile/lightening/tests/pushpop.c deleted file mode 100644 index cd2420bdd..000000000 --- a/libguile/lightening/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); -} |