mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-06 04:00:26 +02:00
2901 lines
67 KiB
C
2901 lines
67 KiB
C
/*
|
|
* Copyright (C) 2013-2017, 2019 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 __BYTE_ORDER != __LITTLE_ENDIAN
|
|
#error AArch64 requires little-endian host
|
|
#endif
|
|
|
|
typedef union {
|
|
/* cond2: condition in truly conditional-executed inst. */
|
|
struct { uint32_t b: 4; } cond2;
|
|
/* nzcv: flag bit specifier, encoded in the "nzcv" field. */
|
|
struct { uint32_t b: 4; } nzcv;
|
|
/* defgh: d:e:f:g:h bits in AdvSIMD modified immediate. */
|
|
struct { uint32_t _: 5; uint32_t b: 5; } defgh;
|
|
/* abc: a:b:c bits in AdvSIMD modified immediate. */
|
|
struct { uint32_t _: 16; uint32_t b: 3; } abc;
|
|
/* imm19: e.g. in CBZ. */
|
|
struct { uint32_t _: 5; uint32_t b: 19; } imm19;
|
|
/* immhi: e.g. in ADRP. */
|
|
struct { uint32_t _: 5; uint32_t b: 19; } immhi;
|
|
/* immlo: e.g. in ADRP. */
|
|
struct { uint32_t _: 29; uint32_t b: 2; } immlo;
|
|
/* size: in most AdvSIMD and floating-point instructions. */
|
|
struct { uint32_t _: 22; uint32_t b: 2; } size;
|
|
/* vldst_size: size field in the AdvSIMD load/store inst. */
|
|
struct { uint32_t _: 10; uint32_t b: 2; } vldst_size;
|
|
/* op: in AdvSIMD modified immediate instructions. */
|
|
struct { uint32_t _: 29; uint32_t b: 1; } op;
|
|
/* Q: in most AdvSIMD instructions. */
|
|
struct { uint32_t _: 30; uint32_t b: 1; } Q;
|
|
/* Rt: in load/store instructions. */
|
|
struct { uint32_t b: 5; } Rt;
|
|
/* Rd: in many integer instructions. */
|
|
struct { uint32_t b: 5; } Rd;
|
|
/* Rn: in many integer instructions. */
|
|
struct { uint32_t _: 5; uint32_t b: 5; } Rn;
|
|
/* Rt2: in load/store pair instructions. */
|
|
struct { uint32_t _: 10; uint32_t b: 5; } Rt2;
|
|
/* Ra: in fp instructions. */
|
|
struct { uint32_t _: 10; uint32_t b: 5; } Ra;
|
|
/* op2: in the system instructions. */
|
|
struct { uint32_t _: 5; uint32_t b: 3; } op2;
|
|
/* CRm: in the system instructions. */
|
|
struct { uint32_t _: 8; uint32_t b: 4; } CRm;
|
|
/* CRn: in the system instructions. */
|
|
struct { uint32_t _: 12; uint32_t b: 4; } CRn;
|
|
/* op1: in the system instructions. */
|
|
struct { uint32_t _: 16; uint32_t b: 3; } op1;
|
|
/* op0: in the system instructions. */
|
|
struct { uint32_t _: 19; uint32_t b: 2; } op0;
|
|
/* imm3: in add/sub extended reg instructions. */
|
|
struct { uint32_t _: 10; uint32_t b: 3; } imm3;
|
|
/* cond: condition flags as a source operand. */
|
|
struct { uint32_t _: 12; uint32_t b: 4; } cond;
|
|
/* opcode: in advsimd load/store instructions. */
|
|
struct { uint32_t _: 12; uint32_t b: 4; } opcode;
|
|
/* cmode: in advsimd modified immediate instructions. */
|
|
struct { uint32_t _: 12; uint32_t b: 4; } cmode;
|
|
/* asisdlso_opcode: opcode in advsimd ld/st single element. */
|
|
struct { uint32_t _: 13; uint32_t b: 3; } asisdlso_opcode;
|
|
/* len: in advsimd tbl/tbx instructions. */
|
|
struct { uint32_t _: 13; uint32_t b: 2; } len;
|
|
/* Rm: in ld/st reg offset and some integer inst. */
|
|
struct { uint32_t _: 16; uint32_t b: 5; } Rm;
|
|
/* Rs: in load/store exclusive instructions. */
|
|
struct { uint32_t _: 16; uint32_t b: 5; } Rs;
|
|
/* option: in ld/st reg offset + add/sub extended reg inst. */
|
|
struct { uint32_t _: 13; uint32_t b: 3; } option;
|
|
/* S: in load/store reg offset instructions. */
|
|
struct { uint32_t _: 12; uint32_t b: 1; } S;
|
|
/* hw: in move wide constant instructions. */
|
|
struct { uint32_t _: 21; uint32_t b: 2; } hw;
|
|
/* opc: in load/store reg offset instructions. */
|
|
struct { uint32_t _: 22; uint32_t b: 2; } opc;
|
|
/* opc1: in load/store reg offset instructions. */
|
|
struct { uint32_t _: 23; uint32_t b: 1; } opc1;
|
|
/* shift: in add/sub reg/imm shifted instructions. */
|
|
struct { uint32_t _: 22; uint32_t b: 2; } shift;
|
|
/* type: floating point type field in fp data inst. */
|
|
struct { uint32_t _: 22; uint32_t b: 2; } type;
|
|
/* ldst_size: size field in ld/st reg offset inst. */
|
|
struct { uint32_t _: 30; uint32_t b: 2; } ldst_size;
|
|
/* imm6: in add/sub reg shifted instructions. */
|
|
struct { uint32_t _: 10; uint32_t b: 6; } imm6;
|
|
/* imm4: in advsimd ext and advsimd ins instructions. */
|
|
struct { uint32_t _: 11; uint32_t b: 4; } imm4;
|
|
/* imm5: in conditional compare (immediate) instructions. */
|
|
struct { uint32_t _: 16; uint32_t b: 5; } imm5;
|
|
/* imm7: in load/store pair pre/post index instructions. */
|
|
struct { uint32_t _: 15; uint32_t b: 7; } imm7;
|
|
/* imm8: in floating-point scalar move immediate inst. */
|
|
struct { uint32_t _: 13; uint32_t b: 8; } imm8;
|
|
/* imm9: in load/store pre/post index instructions. */
|
|
struct { uint32_t _: 12; uint32_t b: 9; } imm9;
|
|
/* imm12: in ld/st unsigned imm or add/sub shifted inst. */
|
|
struct { uint32_t _: 10; uint32_t b: 12; } imm12;
|
|
/* imm14: in test bit and branch instructions. */
|
|
struct { uint32_t _: 5; uint32_t b: 14; } imm14;
|
|
/* imm16: in exception instructions. */
|
|
struct { uint32_t _: 5; uint32_t b: 16; } imm16;
|
|
/* imm26: in unconditional branch instructions. */
|
|
struct { uint32_t b: 26; } imm26;
|
|
/* imms: in bitfield and logical immediate instructions. */
|
|
struct { uint32_t _: 10; uint32_t b: 6; } imms;
|
|
/* immr: in bitfield and logical immediate instructions. */
|
|
struct { uint32_t _: 16; uint32_t b: 6; } immr;
|
|
/* immb: in advsimd shift by immediate instructions. */
|
|
struct { uint32_t _: 16; uint32_t b: 3; } immb;
|
|
/* immh: in advsimd shift by immediate instructions. */
|
|
struct { uint32_t _: 19; uint32_t b: 4; } immh;
|
|
/* N: in logical (immediate) instructions. */
|
|
struct { uint32_t _: 22; uint32_t b: 1; } N;
|
|
/* index: in ld/st inst deciding the pre/post-index. */
|
|
struct { uint32_t _: 11; uint32_t b: 1; } index;
|
|
/* index2: in ld/st pair inst deciding the pre/post-index. */
|
|
struct { uint32_t _: 24; uint32_t b: 1; } index2;
|
|
/* sf: in integer data processing instructions. */
|
|
struct { uint32_t _: 31; uint32_t b: 1; } sf;
|
|
/* H: in advsimd scalar x indexed element instructions. */
|
|
struct { uint32_t _: 11; uint32_t b: 1; } H;
|
|
/* L: in advsimd scalar x indexed element instructions. */
|
|
struct { uint32_t _: 21; uint32_t b: 1; } L;
|
|
/* M: in advsimd scalar x indexed element instructions. */
|
|
struct { uint32_t _: 20; uint32_t b: 1; } M;
|
|
/* b5: in the test bit and branch instructions. */
|
|
struct { uint32_t _: 31; uint32_t b: 1; } b5;
|
|
/* b40: in the test bit and branch instructions. */
|
|
struct { uint32_t _: 19; uint32_t b: 5; } b40;
|
|
/* scale: in the fixed-point scalar to fp converting inst. */
|
|
struct { uint32_t _: 10; uint32_t b: 6; } scale;
|
|
int32_t w;
|
|
} instr_t;
|
|
|
|
static int32_t
|
|
logical_immediate(jit_word_t imm)
|
|
{
|
|
/* There are 5334 possible immediate values, but to avoid the
|
|
* need of either too complex code or large lookup tables,
|
|
* only check for (simply) encodable common/small values */
|
|
switch (imm) {
|
|
case -16: return 0xf3b;
|
|
case -15: return 0xf3c;
|
|
case -13: return 0xf3d;
|
|
case -9: return 0xf3e;
|
|
case -8: return 0xf7c;
|
|
case -7: return 0xf7d;
|
|
case -5: return 0xf7e;
|
|
case -4: return 0xfbd;
|
|
case -3: return 0xfbe;
|
|
case -2: return 0xffe;
|
|
case 1: return 0x000;
|
|
case 2: return 0xfc0;
|
|
case 3: return 0x001;
|
|
case 4: return 0xf80;
|
|
case 6: return 0xfc1;
|
|
case 7: return 0x002;
|
|
case 8: return 0xf40;
|
|
case 12: return 0xf81;
|
|
case 14: return 0xfc2;
|
|
case 15: return 0x003;
|
|
case 16: return 0xf00;
|
|
default: return -1;
|
|
}
|
|
}
|
|
|
|
static void
|
|
oxxx(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Rn, int32_t Rm)
|
|
{
|
|
instr_t i;
|
|
ASSERT(!(Rd & ~0x1f));
|
|
ASSERT(!(Rn & ~0x1f));
|
|
ASSERT(!(Rm & ~0x1f));
|
|
ASSERT(!(Op & ~0xffe0fc00));
|
|
i.w = Op;
|
|
i.Rd.b = Rd;
|
|
i.Rn.b = Rn;
|
|
i.Rm.b = Rm;
|
|
emit_u32(_jit, i.w);
|
|
}
|
|
|
|
static void
|
|
oxxi(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Rn, int32_t Imm12)
|
|
{
|
|
instr_t i;
|
|
ASSERT(!(Rd & ~0x1f));
|
|
ASSERT(!(Rn & ~0x1f));
|
|
ASSERT(!(Imm12 & ~0xfff));
|
|
ASSERT(!(Op & ~0xffe00000));
|
|
i.w = Op;
|
|
i.Rd.b = Rd;
|
|
i.Rn.b = Rn;
|
|
i.imm12.b = Imm12;
|
|
emit_u32(_jit, i.w);
|
|
}
|
|
|
|
static void
|
|
oxx9(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Rn, int32_t Imm9)
|
|
{
|
|
instr_t i;
|
|
ASSERT(!(Rd & ~0x1f));
|
|
ASSERT(!(Rn & ~0x1f));
|
|
ASSERT(!(Imm9 & ~0x1ff));
|
|
ASSERT(!(Op & ~0xffe00000));
|
|
i.w = Op;
|
|
i.Rd.b = Rd;
|
|
i.Rn.b = Rn;
|
|
i.imm9.b = Imm9;
|
|
emit_u32(_jit, i.w);
|
|
}
|
|
|
|
static uint32_t
|
|
encode_ox19(jit_state_t *_jit, int32_t Op, int32_t Rd)
|
|
{
|
|
instr_t i;
|
|
ASSERT(!(Rd & ~0x1f));
|
|
ASSERT(!(Op & ~0xff000000));
|
|
i.w = Op;
|
|
i.Rd.b = Rd;
|
|
return i.w;
|
|
}
|
|
|
|
static uint32_t
|
|
encode_oc19(jit_state_t *_jit, int32_t Op, int32_t Cc)
|
|
{
|
|
instr_t i;
|
|
ASSERT(!(Cc & ~0xf));
|
|
ASSERT(!(Op & ~0xff000000));
|
|
i.w = Op;
|
|
i.cond2.b = Cc;
|
|
return i.w;
|
|
}
|
|
|
|
static uint32_t
|
|
encode_o26(jit_state_t *_jit, int32_t Op)
|
|
{
|
|
instr_t i;
|
|
ASSERT(!(Op & ~0xfc000000));
|
|
i.w = Op;
|
|
return i.w;
|
|
}
|
|
|
|
static void
|
|
ox_x(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Rm)
|
|
{
|
|
instr_t i;
|
|
ASSERT(!(Rd & ~0x1f));
|
|
ASSERT(!(Rm & ~0x1f));
|
|
ASSERT(!(Op & ~0xffe0ffe0));
|
|
i.w = Op;
|
|
i.Rd.b = Rd;
|
|
i.Rm.b = Rm;
|
|
emit_u32(_jit, i.w);
|
|
}
|
|
|
|
static void
|
|
o_xx(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Rn)
|
|
{
|
|
instr_t i;
|
|
ASSERT(!(Rd & ~0x1f));
|
|
ASSERT(!(Rn & ~0x1f));
|
|
ASSERT(!(Op & ~0xfffffc00));
|
|
i.w = Op;
|
|
i.Rd.b = Rd;
|
|
i.Rn.b = Rn;
|
|
emit_u32(_jit, i.w);
|
|
}
|
|
|
|
static void
|
|
oxx_(jit_state_t *_jit, int32_t Op, int32_t Rn, int32_t Rm)
|
|
{
|
|
instr_t i;
|
|
ASSERT(!(Rn & ~0x1f));
|
|
ASSERT(!(Rm & ~0x1f));
|
|
ASSERT(!(Op & ~0xffc0fc1f));
|
|
i.w = Op;
|
|
i.Rn.b = Rn;
|
|
i.Rm.b = Rm;
|
|
emit_u32(_jit, i.w);
|
|
}
|
|
|
|
static void
|
|
o_x_(jit_state_t *_jit, int32_t Op, int32_t Rn)
|
|
{
|
|
instr_t i;
|
|
ASSERT(!(Rn & ~0x1f));
|
|
ASSERT(!(Op & 0x3e0));
|
|
i.w = Op;
|
|
i.Rn.b = Rn;
|
|
emit_u32(_jit, i.w);
|
|
}
|
|
|
|
static void
|
|
ox_h(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Imm16)
|
|
{
|
|
instr_t i;
|
|
ASSERT(!(Rd & ~0x1f));
|
|
ASSERT(!(Imm16 & ~0xffff));
|
|
ASSERT(!(Op & ~0xffe00000));
|
|
i.w = Op;
|
|
i.Rd.b = Rd;
|
|
i.imm16.b = Imm16;
|
|
emit_u32(_jit, i.w);
|
|
}
|
|
|
|
static void
|
|
oxxrs(jit_state_t *_jit, int32_t Op,
|
|
int32_t Rd, int32_t Rn, int32_t R, int32_t S)
|
|
{
|
|
instr_t i;
|
|
ASSERT(!(Rd & ~0x1f));
|
|
ASSERT(!(Rn & ~0x1f));
|
|
ASSERT(!(R & ~0x3f));
|
|
ASSERT(!(S & ~0x3f));
|
|
ASSERT(!(Op & ~0xffc00000));
|
|
i.w = Op;
|
|
i.Rd.b = Rd;
|
|
i.Rn.b = Rn;
|
|
i.immr.b = R;
|
|
i.imms.b = S;
|
|
emit_u32(_jit, i.w);
|
|
}
|
|
|
|
static void
|
|
oxxxc(jit_state_t *_jit, int32_t Op,
|
|
int32_t Rd, int32_t Rn, int32_t Rm, int32_t Cc)
|
|
{
|
|
instr_t i;
|
|
ASSERT(!(Rd & ~0x1f));
|
|
ASSERT(!(Rn & ~0x1f));
|
|
ASSERT(!(Rm & ~0x1f));
|
|
ASSERT(!(Cc & ~0xf));
|
|
ASSERT(!(Op & ~0xffc00c00));
|
|
i.w = Op;
|
|
i.Rd.b = Rd;
|
|
i.Rn.b = Rn;
|
|
i.Rm.b = Rm;
|
|
i.cond.b = Cc;
|
|
emit_u32(_jit, i.w);
|
|
}
|
|
|
|
static void
|
|
oxxx7(jit_state_t *_jit, int32_t Op,
|
|
int32_t Rt, int32_t Rt2, int32_t Rn, int32_t Simm7)
|
|
{
|
|
instr_t i;
|
|
ASSERT(!(Rt & ~0x1f));
|
|
ASSERT(!(Rt2 & ~0x1f));
|
|
ASSERT(!(Rn & ~0x1f));
|
|
ASSERT(Simm7 >= -128 && Simm7 <= 127);
|
|
ASSERT(!(Op & ~0xffc003e0));
|
|
i.w = Op;
|
|
i.Rt.b = Rt;
|
|
i.Rt2.b = Rt2;
|
|
i.Rn.b = Rn;
|
|
i.imm7.b = Simm7;
|
|
emit_u32(_jit, i.w);
|
|
}
|
|
|
|
#define stack_framesize 160
|
|
#define FP_REGNO 0x1d
|
|
#define LR_REGNO 0x1e
|
|
#define SP_REGNO 0x1f
|
|
#define XZR_REGNO 0x1f
|
|
#define WZR_REGNO XZR_REGNO
|
|
#define LSL_12 0x00400000
|
|
#define MOVI_LSL_16 0x00200000
|
|
#define MOVI_LSL_32 0x00400000
|
|
#define MOVI_LSL_48 0x00600000
|
|
#define XS 0x80000000 /* Wn -> Xn */
|
|
#define DS 0x00400000 /* Sn -> Dn */
|
|
#define CC_NE 0x0
|
|
#define CC_EQ 0x1
|
|
#define CC_CC 0x2
|
|
#define CC_LO CC_CC
|
|
#define CC_CS 0x3
|
|
#define CC_HS CC_CS
|
|
#define CC_PL 0x4
|
|
#define CC_MI 0x5
|
|
#define CC_VC 0x6
|
|
#define CC_VS 0x7
|
|
#define CC_LS 0x8
|
|
#define CC_HI 0x9
|
|
#define CC_LT 0xa
|
|
#define CC_GE 0xb
|
|
#define CC_LE 0xc
|
|
#define CC_GT 0xd
|
|
#define CC_NV 0xe
|
|
#define CC_AL 0xf
|
|
/* Branches need inverted condition */
|
|
#define BCC_EQ 0x0
|
|
#define BCC_NE 0x1
|
|
#define BCC_CS 0x2
|
|
#define BCC_HS BCC_CS
|
|
#define BCC_CC 0x3
|
|
#define BCC_LO BCC_CC
|
|
#define BCC_MI 0x4
|
|
#define BCC_PL 0x5
|
|
#define BCC_VS 0x6
|
|
#define BCC_VC 0x7
|
|
#define BCC_HI 0x8
|
|
#define BCC_LS 0x9
|
|
#define BCC_GE 0xa
|
|
#define BCC_LT 0xb
|
|
#define BCC_GT 0xc
|
|
#define BCC_LE 0xd
|
|
#define BCC_AL 0xe
|
|
#define BCC_NV 0xf
|
|
/* adapted and cut down to only tested and required by lightning,
|
|
* from data in binutils/aarch64-tbl.h */
|
|
#define A64_ADCS 0x3a000000
|
|
#define A64_SBCS 0x7a000000
|
|
#define A64_ADDI 0x11000000
|
|
#define A64_ADDSI 0xb1000000
|
|
#define A64_SUBI 0x51000000
|
|
#define A64_SUBSI 0x71000000
|
|
#define A64_ADD 0x0b000000
|
|
#define A64_ADDS 0x2b000000
|
|
#define A64_SUB 0x4b000000
|
|
#define A64_NEG 0x4b0003e0
|
|
#define A64_SUBS 0x6b000000
|
|
#define A64_CMP 0x6b00001f
|
|
#define A64_SBFM 0x93400000
|
|
#define A64_UBFM 0x53400000
|
|
#define A64_UBFX 0x53000000
|
|
#define A64_B 0x14000000
|
|
#define A64_BL 0x94000000
|
|
#define A64_BR 0xd61f0000
|
|
#define A64_BLR 0xd63f0000
|
|
#define A64_RET 0xd65f0000
|
|
#define A64_CBZ 0x34000000
|
|
#define A64_CBNZ 0x35000000
|
|
#define A64_B_C 0x54000000
|
|
#define A64_CSINC 0x1a800400
|
|
#define A64_REV 0xdac00c00
|
|
#define A64_UDIV 0x1ac00800
|
|
#define A64_SDIV 0x1ac00c00
|
|
#define A64_LSL 0x1ac02000
|
|
#define A64_LSR 0x1ac02400
|
|
#define A64_ASR 0x1ac02800
|
|
#define A64_MUL 0x1b007c00
|
|
#define A64_SMULL 0x9b207c00
|
|
#define A64_SMULH 0x9b407c00
|
|
#define A64_UMULL 0x9ba07c00
|
|
#define A64_UMULH 0x9bc07c00
|
|
#define A64_STRBI 0x39000000
|
|
#define A64_LDRBI 0x39400000
|
|
#define A64_LDRSBI 0x39800000
|
|
#define A64_STRI 0xf9000000
|
|
#define A64_LDRI 0xf9400000
|
|
#define A64_LDRI_LITERAL 0x58000000
|
|
#define A64_STRHI 0x79000000
|
|
#define A64_LDRHI 0x79400000
|
|
#define A64_LDRSHI 0x79800000
|
|
#define A64_STRWI 0xb9000000
|
|
#define A64_LDRWI 0xb9400000
|
|
#define A64_LDRSWI 0xb9800000
|
|
#define A64_STRB 0x38206800
|
|
#define A64_LDRB 0x38606800
|
|
#define A64_LDRSB 0x38e06800
|
|
#define A64_STR 0xf8206800
|
|
#define A64_LDR 0xf8606800
|
|
#define A64_STRH 0x78206800
|
|
#define A64_LDRH 0x78606800
|
|
#define A64_LDRSH 0x78a06800
|
|
#define A64_STRW 0xb8206800
|
|
#define A64_LDRW 0xb8606800
|
|
#define A64_LDRSW 0xb8a06800
|
|
#define A64_STURB 0x38000000
|
|
#define A64_LDURB 0x38400000
|
|
#define A64_LDURSB 0x38800000
|
|
#define A64_STUR 0xf8000000
|
|
#define A64_LDUR 0xf8400000
|
|
#define A64_STURH 0x78000000
|
|
#define A64_LDURH 0x78400000
|
|
#define A64_LDURSH 0x78800000
|
|
#define A64_STURW 0xb8000000
|
|
#define A64_LDURW 0xb8400000
|
|
#define A64_LDURSW 0xb8800000
|
|
#define A64_STP 0x29000000
|
|
#define A64_LDP 0x29400000
|
|
#define A64_STP_POS 0x29800000
|
|
#define A64_LDP_PRE 0x28c00000
|
|
#define A64_ANDI 0x12400000
|
|
#define A64_ORRI 0x32400000
|
|
#define A64_EORI 0x52400000
|
|
#define A64_ANDSI 0x72000000
|
|
#define A64_AND 0x0a000000
|
|
#define A64_ORR 0x2a000000
|
|
#define A64_MOV 0x2a0003e0 /* AKA orr Rd,xzr,Rm */
|
|
#define A64_MVN 0x2a2003e0
|
|
#define A64_UXTW 0x2a0003e0 /* AKA MOV */
|
|
#define A64_EOR 0x4a000000
|
|
#define A64_ANDS 0x6a000000
|
|
#define A64_MOVN 0x12800000
|
|
#define A64_MOVZ 0x52800000
|
|
#define A64_MOVK 0x72800000
|
|
|
|
static void
|
|
SBFM(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t ImmR, int32_t ImmS)
|
|
{
|
|
return oxxrs(_jit, A64_SBFM|XS,Rd,Rn,ImmR,ImmS);
|
|
}
|
|
|
|
static void
|
|
UBFM(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t ImmR, int32_t ImmS)
|
|
{
|
|
return oxxrs(_jit, A64_UBFM|XS,Rd,Rn,ImmR,ImmS);
|
|
}
|
|
|
|
static void
|
|
UBFX(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t ImmR, int32_t ImmS)
|
|
{
|
|
return oxxrs(_jit, A64_UBFX,Rd,Rn,ImmR,ImmS);
|
|
}
|
|
|
|
static void
|
|
CMP(jit_state_t *_jit, int32_t Rn, int32_t Rm)
|
|
{
|
|
return oxx_(_jit, A64_CMP|XS,Rn,Rm);
|
|
}
|
|
|
|
static void
|
|
CMPI(jit_state_t *_jit, int32_t Rn, int32_t Imm12)
|
|
{
|
|
return oxxi(_jit, A64_SUBSI|XS,XZR_REGNO,Rn,Imm12);
|
|
}
|
|
|
|
static void
|
|
CMPI_12(jit_state_t *_jit, int32_t Rn, int32_t Imm12)
|
|
{
|
|
return oxxi(_jit, A64_SUBSI|XS|LSL_12,XZR_REGNO,Rn,Imm12);
|
|
}
|
|
|
|
static void
|
|
CMNI(jit_state_t *_jit, int32_t Rn, int32_t Imm12)
|
|
{
|
|
return oxxi(_jit, A64_ADDSI|XS,XZR_REGNO,Rn,Imm12);
|
|
}
|
|
|
|
static void
|
|
CMNI_12(jit_state_t *_jit, int32_t Rn, int32_t Imm12)
|
|
{
|
|
return oxxi(_jit, A64_ADDSI|XS|LSL_12,XZR_REGNO,Rn,Imm12);
|
|
}
|
|
|
|
static void
|
|
CSINC(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm, int32_t Cc)
|
|
{
|
|
return oxxxc(_jit, A64_CSINC|XS,Rd,Rn,Rm,Cc);
|
|
}
|
|
|
|
static void
|
|
TST(jit_state_t *_jit, int32_t Rn, int32_t Rm)
|
|
{
|
|
return oxxx(_jit, A64_ANDS|XS,XZR_REGNO,Rn,Rm);
|
|
}
|
|
|
|
/* actually should use oxxrs but logical_immediate returns proper encoding */
|
|
static void
|
|
TSTI(jit_state_t *_jit, int32_t Rn, int32_t Imm12)
|
|
{
|
|
return oxxi(_jit, A64_ANDSI,XZR_REGNO,Rn,Imm12);
|
|
}
|
|
|
|
static void
|
|
MOV(jit_state_t *_jit, int32_t Rd, int32_t Rm)
|
|
{
|
|
return ox_x(_jit, A64_MOV|XS,Rd,Rm);
|
|
}
|
|
|
|
static void
|
|
MVN(jit_state_t *_jit, int32_t Rd, int32_t Rm)
|
|
{
|
|
return ox_x(_jit, A64_MVN|XS,Rd,Rm);
|
|
}
|
|
|
|
static void
|
|
NEG(jit_state_t *_jit, int32_t Rd, int32_t Rm)
|
|
{
|
|
return ox_x(_jit, A64_NEG|XS,Rd,Rm);
|
|
}
|
|
|
|
static void
|
|
MOVN(jit_state_t *_jit, int32_t Rd, int32_t Imm16)
|
|
{
|
|
return ox_h(_jit, A64_MOVN|XS,Rd,Imm16);
|
|
}
|
|
|
|
static void
|
|
MOVN_16(jit_state_t *_jit, int32_t Rd, int32_t Imm16)
|
|
{
|
|
return ox_h(_jit, A64_MOVN|XS|MOVI_LSL_16,Rd,Imm16);
|
|
}
|
|
|
|
static void
|
|
MOVN_32(jit_state_t *_jit, int32_t Rd, int32_t Imm16)
|
|
{
|
|
return ox_h(_jit, A64_MOVN|XS|MOVI_LSL_32,Rd,Imm16);
|
|
}
|
|
|
|
static void
|
|
MOVN_48(jit_state_t *_jit, int32_t Rd, int32_t Imm16)
|
|
{
|
|
return ox_h(_jit, A64_MOVN|XS|MOVI_LSL_48,Rd,Imm16);
|
|
}
|
|
|
|
static void
|
|
MOVZ(jit_state_t *_jit, int32_t Rd, int32_t Imm16)
|
|
{
|
|
return ox_h(_jit, A64_MOVZ|XS,Rd,Imm16);
|
|
}
|
|
|
|
static void
|
|
MOVZ_16(jit_state_t *_jit, int32_t Rd, int32_t Imm16)
|
|
{
|
|
return ox_h(_jit, A64_MOVZ|XS|MOVI_LSL_16,Rd,Imm16);
|
|
}
|
|
|
|
static void
|
|
MOVZ_32(jit_state_t *_jit, int32_t Rd, int32_t Imm16)
|
|
{
|
|
return ox_h(_jit, A64_MOVZ|XS|MOVI_LSL_32,Rd,Imm16);
|
|
}
|
|
|
|
static void
|
|
MOVZ_48(jit_state_t *_jit, int32_t Rd, int32_t Imm16)
|
|
{
|
|
return ox_h(_jit, A64_MOVZ|XS|MOVI_LSL_48,Rd,Imm16);
|
|
}
|
|
|
|
static void
|
|
MOVK(jit_state_t *_jit, int32_t Rd, int32_t Imm16)
|
|
{
|
|
return ox_h(_jit, A64_MOVK|XS,Rd,Imm16);
|
|
}
|
|
|
|
static void
|
|
MOVK_16(jit_state_t *_jit, int32_t Rd, int32_t Imm16)
|
|
{
|
|
return ox_h(_jit, A64_MOVK|XS|MOVI_LSL_16,Rd,Imm16);
|
|
}
|
|
|
|
static void
|
|
MOVK_32(jit_state_t *_jit, int32_t Rd, int32_t Imm16)
|
|
{
|
|
return ox_h(_jit, A64_MOVK|XS|MOVI_LSL_32,Rd,Imm16);
|
|
}
|
|
|
|
static void
|
|
MOVK_48(jit_state_t *_jit, int32_t Rd, int32_t Imm16)
|
|
{
|
|
return ox_h(_jit, A64_MOVK|XS|MOVI_LSL_48,Rd,Imm16);
|
|
}
|
|
|
|
static void
|
|
ADD(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm)
|
|
{
|
|
return oxxx(_jit, A64_ADD|XS,Rd,Rn,Rm);
|
|
}
|
|
|
|
static void
|
|
ADDI(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Imm12)
|
|
{
|
|
return oxxi(_jit, A64_ADDI|XS,Rd,Rn,Imm12);
|
|
}
|
|
|
|
static void
|
|
ADDI_12(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Imm12)
|
|
{
|
|
return oxxi(_jit, A64_ADDI|XS|LSL_12,Rd,Rn,Imm12);
|
|
}
|
|
|
|
static void
|
|
MOV_XSP(jit_state_t *_jit, int32_t Rd, int32_t Rn)
|
|
{
|
|
return ADDI(_jit, Rd,Rn,0);
|
|
}
|
|
|
|
static void
|
|
ADDS(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm)
|
|
{
|
|
return oxxx(_jit, A64_ADDS|XS,Rd,Rn,Rm);
|
|
}
|
|
|
|
static void
|
|
ADDSI(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Imm12)
|
|
{
|
|
return oxxi(_jit, A64_ADDSI|XS,Rd,Rn,Imm12);
|
|
}
|
|
|
|
static void
|
|
ADDSI_12(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Imm12)
|
|
{
|
|
return oxxi(_jit, A64_ADDSI|XS|LSL_12,Rd,Rn,Imm12);
|
|
}
|
|
|
|
static void
|
|
ADCS(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm)
|
|
{
|
|
return oxxx(_jit, A64_ADCS|XS,Rd,Rn,Rm);
|
|
}
|
|
|
|
static void
|
|
SUB(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm)
|
|
{
|
|
return oxxx(_jit, A64_SUB|XS,Rd,Rn,Rm);
|
|
}
|
|
|
|
static void
|
|
SUBI(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Imm12)
|
|
{
|
|
return oxxi(_jit, A64_SUBI|XS,Rd,Rn,Imm12);
|
|
}
|
|
|
|
static void
|
|
SUBI_12(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Imm12)
|
|
{
|
|
return oxxi(_jit, A64_SUBI|XS|LSL_12,Rd,Rn,Imm12);
|
|
}
|
|
|
|
static void
|
|
SUBS(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm)
|
|
{
|
|
return oxxx(_jit, A64_SUBS|XS,Rd,Rn,Rm);
|
|
}
|
|
|
|
static void
|
|
SUBSI(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Imm12)
|
|
{
|
|
return oxxi(_jit, A64_SUBSI|XS,Rd,Rn,Imm12);
|
|
}
|
|
|
|
static void
|
|
SUBSI_12(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Imm12)
|
|
{
|
|
return oxxi(_jit, A64_SUBSI|XS|LSL_12,Rd,Rn,Imm12);
|
|
}
|
|
|
|
static void
|
|
SBCS(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm)
|
|
{
|
|
return oxxx(_jit, A64_SBCS|XS,Rd,Rn,Rm);
|
|
}
|
|
|
|
static void
|
|
MUL(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm)
|
|
{
|
|
return oxxx(_jit, A64_MUL|XS,Rd,Rn,Rm);
|
|
}
|
|
|
|
static void
|
|
SMULL(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm)
|
|
{
|
|
return oxxx(_jit, A64_SMULL,Rd,Rn,Rm);
|
|
}
|
|
|
|
static void
|
|
SMULH(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm)
|
|
{
|
|
return oxxx(_jit, A64_SMULH,Rd,Rn,Rm);
|
|
}
|
|
|
|
static void
|
|
UMULL(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm)
|
|
{
|
|
return oxxx(_jit, A64_UMULL,Rd,Rn,Rm);
|
|
}
|
|
|
|
static void
|
|
UMULH(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm)
|
|
{
|
|
return oxxx(_jit, A64_UMULH,Rd,Rn,Rm);
|
|
}
|
|
|
|
static void
|
|
SDIV(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm)
|
|
{
|
|
return oxxx(_jit, A64_SDIV|XS,Rd,Rn,Rm);
|
|
}
|
|
|
|
static void
|
|
UDIV(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm)
|
|
{
|
|
return oxxx(_jit, A64_UDIV|XS,Rd,Rn,Rm);
|
|
}
|
|
|
|
static void
|
|
LSL(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm)
|
|
{
|
|
return oxxx(_jit, A64_LSL|XS,Rd,Rn,Rm);
|
|
}
|
|
|
|
static void
|
|
LSLI(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0)
|
|
{
|
|
return UBFM(_jit, r0,r1,(64-i0)&63,63-i0);
|
|
}
|
|
|
|
static void
|
|
ASR(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm)
|
|
{
|
|
return oxxx(_jit, A64_ASR|XS,Rd,Rn,Rm);
|
|
}
|
|
|
|
static void
|
|
ASRI(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0)
|
|
{
|
|
return SBFM(_jit, r0,r1,i0,63);
|
|
}
|
|
|
|
static void
|
|
LSR(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm)
|
|
{
|
|
return oxxx(_jit, A64_LSR|XS,Rd,Rn,Rm);
|
|
}
|
|
|
|
static void
|
|
LSRI(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0)
|
|
{
|
|
return UBFM(_jit, r0,r1,i0,63);
|
|
}
|
|
|
|
static void
|
|
AND(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm)
|
|
{
|
|
return oxxx(_jit, A64_AND|XS,Rd,Rn,Rm);
|
|
}
|
|
|
|
/* actually should use oxxrs but logical_immediate returns proper encoding */;
|
|
static void
|
|
ANDI(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Imm12)
|
|
{
|
|
return oxxi(_jit, A64_ANDI|XS,Rd,Rn,Imm12);
|
|
}
|
|
|
|
static void
|
|
ORR(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm)
|
|
{
|
|
return oxxx(_jit, A64_ORR|XS,Rd,Rn,Rm);
|
|
}
|
|
|
|
/* actually should use oxxrs but logical_immediate returns proper encoding */
|
|
static void
|
|
ORRI(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Imm12)
|
|
{
|
|
return oxxi(_jit, A64_ORRI|XS,Rd,Rn,Imm12);
|
|
}
|
|
|
|
static void
|
|
EOR(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm)
|
|
{
|
|
return oxxx(_jit, A64_EOR|XS,Rd,Rn,Rm);
|
|
}
|
|
|
|
/* actually should use oxxrs but logical_immediate returns proper encoding */
|
|
static void
|
|
EORI(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Imm12)
|
|
{
|
|
return oxxi(_jit, A64_EORI|XS,Rd,Rn,Imm12);
|
|
}
|
|
|
|
static void
|
|
SXTB(jit_state_t *_jit, int32_t Rd, int32_t Rn)
|
|
{
|
|
return SBFM(_jit, Rd,Rn,0,7);
|
|
}
|
|
|
|
static void
|
|
SXTH(jit_state_t *_jit, int32_t Rd, int32_t Rn)
|
|
{
|
|
return SBFM(_jit, Rd,Rn,0,15);
|
|
}
|
|
|
|
static void
|
|
SXTW(jit_state_t *_jit, int32_t Rd, int32_t Rn)
|
|
{
|
|
return SBFM(_jit, Rd,Rn,0,31);
|
|
}
|
|
|
|
static void
|
|
UXTB(jit_state_t *_jit, int32_t Rd, int32_t Rn)
|
|
{
|
|
return UBFX(_jit, Rd,Rn,0,7);
|
|
}
|
|
|
|
static void
|
|
UXTH(jit_state_t *_jit, int32_t Rd, int32_t Rn)
|
|
{
|
|
return UBFX(_jit, Rd,Rn,0,15);
|
|
}
|
|
|
|
static void
|
|
UXTW(jit_state_t *_jit, int32_t Rd, int32_t Rm)
|
|
{
|
|
return ox_x(_jit, A64_UXTW,Rd,Rm);
|
|
}
|
|
|
|
static void
|
|
REV(jit_state_t *_jit, int32_t Rd, int32_t Rn)
|
|
{
|
|
return o_xx(_jit, A64_REV,Rd,Rn);
|
|
}
|
|
|
|
static void
|
|
LDRSB(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Rm)
|
|
{
|
|
return oxxx(_jit, A64_LDRSB,Rt,Rn,Rm);
|
|
}
|
|
|
|
static void
|
|
LDRSBI(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm12)
|
|
{
|
|
return oxxi(_jit, A64_LDRSBI,Rt,Rn,Imm12);
|
|
}
|
|
|
|
static void
|
|
LDURSB(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm9)
|
|
{
|
|
return oxx9(_jit, A64_LDURSB,Rt,Rn,Imm9);
|
|
}
|
|
|
|
static void
|
|
LDRB(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Rm)
|
|
{
|
|
return oxxx(_jit, A64_LDRB,Rt,Rn,Rm);
|
|
}
|
|
|
|
static void
|
|
LDRBI(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm12)
|
|
{
|
|
return oxxi(_jit, A64_LDRBI,Rt,Rn,Imm12);
|
|
}
|
|
|
|
static void
|
|
LDURB(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm9)
|
|
{
|
|
return oxx9(_jit, A64_LDURB,Rt,Rn,Imm9);
|
|
}
|
|
|
|
static void
|
|
LDRSH(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Rm)
|
|
{
|
|
return oxxx(_jit, A64_LDRSH,Rt,Rn,Rm);
|
|
}
|
|
|
|
static void
|
|
LDRSHI(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm12)
|
|
{
|
|
return oxxi(_jit, A64_LDRSHI,Rt,Rn,Imm12);
|
|
}
|
|
|
|
static void
|
|
LDURSH(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm9)
|
|
{
|
|
return oxx9(_jit, A64_LDURSH,Rt,Rn,Imm9);
|
|
}
|
|
|
|
static void
|
|
LDRH(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Rm)
|
|
{
|
|
return oxxx(_jit, A64_LDRH,Rt,Rn,Rm);
|
|
}
|
|
|
|
static void
|
|
LDRHI(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm12)
|
|
{
|
|
return oxxi(_jit, A64_LDRHI,Rt,Rn,Imm12);
|
|
}
|
|
|
|
static void
|
|
LDURH(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm9)
|
|
{
|
|
return oxx9(_jit, A64_LDURH,Rt,Rn,Imm9);
|
|
}
|
|
|
|
static void
|
|
LDRSW(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Rm)
|
|
{
|
|
return oxxx(_jit, A64_LDRSW,Rt,Rn,Rm);
|
|
}
|
|
|
|
static void
|
|
LDRSWI(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm12)
|
|
{
|
|
return oxxi(_jit, A64_LDRSWI,Rt,Rn,Imm12);
|
|
}
|
|
|
|
static void
|
|
LDURSW(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm9)
|
|
{
|
|
return oxx9(_jit, A64_LDURSW,Rt,Rn,Imm9);
|
|
}
|
|
|
|
static void
|
|
LDRW(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Rm)
|
|
{
|
|
return oxxx(_jit, A64_LDRW,Rt,Rn,Rm);
|
|
}
|
|
|
|
static void
|
|
LDRWI(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm12)
|
|
{
|
|
return oxxi(_jit, A64_LDRWI,Rt,Rn,Imm12);
|
|
}
|
|
|
|
static void
|
|
LDURW(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm9)
|
|
{
|
|
return oxx9(_jit, A64_LDURW,Rt,Rn,Imm9);
|
|
}
|
|
|
|
static void
|
|
LDR(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Rm)
|
|
{
|
|
return oxxx(_jit, A64_LDR,Rt,Rn,Rm);
|
|
}
|
|
|
|
static void
|
|
LDRI(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm12)
|
|
{
|
|
return oxxi(_jit, A64_LDRI,Rt,Rn,Imm12);
|
|
}
|
|
|
|
static void
|
|
LDUR(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm9)
|
|
{
|
|
return oxx9(_jit, A64_LDUR,Rt,Rn,Imm9);
|
|
}
|
|
|
|
static void
|
|
STRB(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Rm)
|
|
{
|
|
return oxxx(_jit, A64_STRB,Rt,Rn,Rm);
|
|
}
|
|
|
|
static void
|
|
STRBI(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm12)
|
|
{
|
|
return oxxi(_jit, A64_STRBI,Rt,Rn,Imm12);
|
|
}
|
|
|
|
static void
|
|
STURB(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm9)
|
|
{
|
|
return oxx9(_jit, A64_STURB,Rt,Rn,Imm9);
|
|
}
|
|
|
|
static void
|
|
STRH(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Rm)
|
|
{
|
|
return oxxx(_jit, A64_STRH,Rt,Rn,Rm);
|
|
}
|
|
|
|
static void
|
|
STRHI(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm12)
|
|
{
|
|
return oxxi(_jit, A64_STRHI,Rt,Rn,Imm12);
|
|
}
|
|
|
|
static void
|
|
STURH(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm9)
|
|
{
|
|
return oxx9(_jit, A64_STURH,Rt,Rn,Imm9);
|
|
}
|
|
|
|
static void
|
|
STRW(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Rm)
|
|
{
|
|
return oxxx(_jit, A64_STRW,Rt,Rn,Rm);
|
|
}
|
|
|
|
static void
|
|
STRWI(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm12)
|
|
{
|
|
return oxxi(_jit, A64_STRWI,Rt,Rn,Imm12);
|
|
}
|
|
|
|
static void
|
|
STURW(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm9)
|
|
{
|
|
return oxx9(_jit, A64_STURW,Rt,Rn,Imm9);
|
|
}
|
|
|
|
static void
|
|
STR(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Rm)
|
|
{
|
|
return oxxx(_jit, A64_STR,Rt,Rn,Rm);
|
|
}
|
|
|
|
static void
|
|
STRI(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm12)
|
|
{
|
|
return oxxi(_jit, A64_STRI,Rt,Rn,Imm12);
|
|
}
|
|
|
|
static void
|
|
STUR(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Imm9)
|
|
{
|
|
return oxx9(_jit, A64_STUR,Rt,Rn,Imm9);
|
|
}
|
|
|
|
static void
|
|
LDPI(jit_state_t *_jit, int32_t Rt, int32_t Rt2, int32_t Rn, int32_t Simm7)
|
|
{
|
|
return oxxx7(_jit, A64_LDP|XS,Rt,Rt2,Rn,Simm7);
|
|
}
|
|
|
|
static void
|
|
STPI(jit_state_t *_jit, int32_t Rt, int32_t Rt2, int32_t Rn, int32_t Simm7)
|
|
{
|
|
return oxxx7(_jit, A64_STP|XS,Rt,Rt2,Rn,Simm7);
|
|
}
|
|
|
|
static void
|
|
LDPI_PRE(jit_state_t *_jit, int32_t Rt, int32_t Rt2, int32_t Rn, int32_t Simm7)
|
|
{
|
|
return oxxx7(_jit, A64_LDP_PRE|XS,Rt,Rt2,Rn,Simm7);
|
|
}
|
|
|
|
static void
|
|
STPI_POS(jit_state_t *_jit, int32_t Rt, int32_t Rt2, int32_t Rn, int32_t Simm7)
|
|
{
|
|
return oxxx7(_jit, A64_STP_POS|XS,Rt,Rt2,Rn,Simm7);
|
|
}
|
|
|
|
static void
|
|
CSET(jit_state_t *_jit, int32_t Rd, int32_t Cc)
|
|
{
|
|
return CSINC(_jit, Rd,XZR_REGNO,XZR_REGNO,Cc);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
B(jit_state_t *_jit)
|
|
{
|
|
return emit_jmp(_jit, encode_o26(_jit, A64_B));
|
|
}
|
|
|
|
static jit_reloc_t
|
|
BL(jit_state_t *_jit)
|
|
{
|
|
return emit_jmp(_jit, encode_o26(_jit, A64_BL));
|
|
}
|
|
|
|
static void
|
|
BR(jit_state_t *_jit, int32_t Rn)
|
|
{
|
|
return o_x_(_jit, A64_BR,Rn);
|
|
}
|
|
|
|
static void
|
|
BLR(jit_state_t *_jit, int32_t Rn)
|
|
{
|
|
return o_x_(_jit, A64_BLR,Rn);
|
|
}
|
|
|
|
static void
|
|
RET(jit_state_t *_jit)
|
|
{
|
|
return o_x_(_jit, A64_RET,LR_REGNO);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
B_C(jit_state_t *_jit, int32_t Cc)
|
|
{
|
|
return emit_jcc(_jit, encode_oc19(_jit, A64_B_C, Cc));
|
|
}
|
|
|
|
static jit_reloc_t
|
|
CBZ(jit_state_t *_jit, int32_t Rd)
|
|
{
|
|
return emit_jcc(_jit, encode_ox19(_jit, A64_CBZ|XS,Rd));
|
|
}
|
|
|
|
static jit_reloc_t
|
|
CBNZ(jit_state_t *_jit, int32_t Rd)
|
|
{
|
|
return emit_jcc(_jit, encode_ox19(_jit, A64_CBNZ|XS,Rd));
|
|
}
|
|
|
|
static void
|
|
NOP(jit_state_t *_jit)
|
|
{
|
|
return emit_u32(_jit, 0xd503201f);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
movi_from_pool(jit_state_t *_jit, int32_t Rt)
|
|
{
|
|
return emit_load_from_pool(_jit, encode_ox19(_jit, A64_LDRI_LITERAL, Rt));
|
|
}
|
|
|
|
static void
|
|
movr(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
if (r0 != r1)
|
|
MOV(_jit, r0, r1);
|
|
}
|
|
|
|
static void
|
|
addr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
return ADD(_jit,r0,r1,r2);
|
|
}
|
|
|
|
static void
|
|
addcr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
return ADDS(_jit,r0,r1,r2);
|
|
}
|
|
|
|
static void
|
|
addxr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
return ADCS(_jit,r0,r1,r2);
|
|
}
|
|
|
|
static void
|
|
subr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
return SUB(_jit,r0,r1,r2);
|
|
}
|
|
|
|
static void
|
|
subcr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
return SUBS(_jit,r0,r1,r2);
|
|
}
|
|
|
|
static void
|
|
subxr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
return SBCS(_jit,r0,r1,r2);
|
|
}
|
|
|
|
static void
|
|
mulr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
return MUL(_jit,r0,r1,r2);
|
|
}
|
|
|
|
static void
|
|
divr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
return SDIV(_jit,r0,r1,r2);
|
|
}
|
|
|
|
static void
|
|
divr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
return UDIV(_jit,r0,r1,r2);
|
|
}
|
|
|
|
static void
|
|
iqdivr(jit_state_t *_jit, jit_bool_t sign,
|
|
int32_t r0, int32_t r1, int32_t r2, int32_t r3)
|
|
{
|
|
int32_t rg0, rg1;
|
|
if (r0 == r2 || r0 == r3) {
|
|
rg0 = jit_gpr_regno(get_temp_gpr(_jit));
|
|
} else {
|
|
rg0 = r0;
|
|
}
|
|
if (r1 == r2 || r1 == r3) {
|
|
rg1 = jit_gpr_regno(get_temp_gpr(_jit));
|
|
} else {
|
|
rg1 = r1;
|
|
}
|
|
if (sign)
|
|
divr(_jit, rg0, r2, r3);
|
|
else
|
|
divr_u(_jit, rg0, r2, r3);
|
|
mulr(_jit, rg1, r3, rg0);
|
|
subr(_jit, rg1, r2, rg1);
|
|
if (rg0 != r0) {
|
|
movr(_jit, r0, rg0);
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
if (rg1 != r1) {
|
|
movr(_jit, r1, rg1);
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
}
|
|
|
|
static void
|
|
qdivr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, int32_t r3)
|
|
{
|
|
return iqdivr(_jit,1,r0,r1,r2,r3);
|
|
}
|
|
|
|
static void
|
|
qdivr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, int32_t r3)
|
|
{
|
|
return iqdivr(_jit,0,r0,r1,r2,r3);
|
|
}
|
|
|
|
static void
|
|
lshr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
return LSL(_jit,r0,r1,r2);
|
|
}
|
|
|
|
static void
|
|
rshr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
return ASR(_jit,r0,r1,r2);
|
|
}
|
|
|
|
static void
|
|
rshr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
return LSR(_jit,r0,r1,r2);
|
|
}
|
|
|
|
static void
|
|
negr(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return NEG(_jit,r0,r1);
|
|
}
|
|
|
|
static void
|
|
comr(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return MVN(_jit,r0,r1);
|
|
}
|
|
|
|
static void
|
|
andr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
return AND(_jit,r0,r1,r2);
|
|
}
|
|
|
|
static void
|
|
orr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
return ORR(_jit,r0,r1,r2);
|
|
}
|
|
|
|
static void
|
|
xorr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
return EOR(_jit,r0,r1,r2);
|
|
}
|
|
|
|
static void
|
|
ldr_c(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return LDRSBI(_jit,r0,r1,0);
|
|
}
|
|
|
|
static void
|
|
ldr_s(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return LDRSHI(_jit,r0,r1,0);
|
|
}
|
|
|
|
static void
|
|
ldr_i(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return LDRSWI(_jit,r0,r1,0);
|
|
}
|
|
|
|
static void
|
|
ldxr_s(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
return LDRSH(_jit,r0,r1,r2);
|
|
}
|
|
|
|
static void
|
|
ldxr_i(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
return LDRSW(_jit,r0,r1,r2);
|
|
}
|
|
|
|
static void
|
|
ldxr_l(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
return LDR(_jit,r0,r1,r2);
|
|
}
|
|
|
|
static void
|
|
str_c(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return STRBI(_jit,r1,r0,0);
|
|
}
|
|
|
|
static void
|
|
str_s(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return STRHI(_jit,r1,r0,0);
|
|
}
|
|
|
|
static void
|
|
str_i(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return STRWI(_jit,r1,r0,0);
|
|
}
|
|
|
|
static void
|
|
str_l(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return STRI(_jit,r1,r0,0);
|
|
}
|
|
|
|
static void
|
|
stxr_c(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
return STRB(_jit,r2,r1,r0);
|
|
}
|
|
|
|
static void
|
|
stxr_s(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
return STRH(_jit,r2,r1,r0);
|
|
}
|
|
|
|
static void
|
|
stxr_i(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
return STRW(_jit,r2,r1,r0);
|
|
}
|
|
|
|
static void
|
|
stxr_l(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
return STR(_jit,r2,r1,r0);
|
|
}
|
|
|
|
static void
|
|
bswapr_ul(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return REV(_jit,r0,r1);
|
|
}
|
|
|
|
static void
|
|
extr_c(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return SXTB(_jit,r0,r1);
|
|
}
|
|
|
|
static void
|
|
extr_uc(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return UXTB(_jit,r0,r1);
|
|
}
|
|
|
|
static void
|
|
extr_s(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return SXTH(_jit,r0,r1);
|
|
}
|
|
|
|
static void
|
|
extr_us(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return UXTH(_jit,r0,r1);
|
|
}
|
|
|
|
static void
|
|
extr_i(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return SXTW(_jit,r0,r1);
|
|
}
|
|
|
|
static void
|
|
extr_ui(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return UXTW(_jit,r0,r1);
|
|
}
|
|
|
|
static void
|
|
movi(jit_state_t *_jit, int32_t r0, jit_word_t i0)
|
|
{
|
|
jit_word_t n0 = ~i0, ibit = 0, nbit = 0;
|
|
if (i0 & 0x000000000000ffffL) ibit |= 1;
|
|
if (i0 & 0x00000000ffff0000L) ibit |= 2;
|
|
if (i0 & 0x0000ffff00000000L) ibit |= 4;
|
|
if (i0 & 0xffff000000000000L) ibit |= 8;
|
|
if (n0 & 0x000000000000ffffL) nbit |= 1;
|
|
if (n0 & 0x00000000ffff0000L) nbit |= 2;
|
|
if (n0 & 0x0000ffff00000000L) nbit |= 4;
|
|
if (n0 & 0xffff000000000000L) nbit |= 8;
|
|
switch (ibit) {
|
|
case 0:
|
|
MOVZ (_jit, r0, 0);
|
|
break;
|
|
case 1:
|
|
MOVZ (_jit, r0, i0 & 0xffff);
|
|
break;
|
|
case 2:
|
|
MOVZ_16(_jit, r0, (i0 >> 16) & 0xffff);
|
|
break;
|
|
case 3:
|
|
MOVZ (_jit, r0, i0 & 0xffff);
|
|
MOVK_16(_jit, r0, (i0 >> 16) & 0xffff);
|
|
break;
|
|
case 4:
|
|
MOVZ_32(_jit, r0, (i0 >> 32) & 0xffff);
|
|
break;
|
|
case 5:
|
|
MOVZ (_jit, r0, i0 & 0xffff);
|
|
MOVK_32(_jit, r0, (i0 >> 32) & 0xffff);
|
|
break;
|
|
case 6:
|
|
MOVZ_16(_jit, r0, (i0 >> 16) & 0xffff);
|
|
MOVK_32(_jit, r0, (i0 >> 32) & 0xffff);
|
|
break;
|
|
case 7:
|
|
if (nbit == 8) {
|
|
MOVN_48(_jit, r0, (n0 >> 48) & 0xffff);
|
|
} else {
|
|
MOVZ (_jit, r0, i0 & 0xffff);
|
|
MOVK_16(_jit, r0, (i0 >> 16) & 0xffff);
|
|
MOVK_32(_jit, r0, (i0 >> 32) & 0xffff);
|
|
}
|
|
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);
|
|
}
|
|
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 void
|
|
ccr(jit_state_t *_jit, int32_t cc, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
CMP(_jit, r1, r2);
|
|
CSET(_jit, r0, cc);
|
|
}
|
|
|
|
static void
|
|
cci(jit_state_t *_jit, int32_t cc, int32_t r0, int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_word_t is = i0 >> 12;
|
|
jit_word_t in = -i0;
|
|
jit_word_t iS = in >> 12;
|
|
if ( i0 >= 0 && i0 <= 0xfff) {
|
|
CMPI (_jit, r1, i0);
|
|
} else if ((is << 12) == i0 && is >= 0 && is <= 0xfff) {
|
|
CMPI_12(_jit, r1, is);
|
|
} else if ( in >= 0 && in <= 0xfff) {
|
|
CMNI (_jit, r1, in);
|
|
} else if ((iS << 12) == is && iS >= 0 && iS <= 0xfff) {
|
|
CMNI_12(_jit, r1, iS);
|
|
} else {
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i0);
|
|
CMP(_jit, r1, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
CSET(_jit, r0, cc);
|
|
}
|
|
|
|
static void
|
|
ltr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
return ccr(_jit,CC_LT,r0,r1,r2);
|
|
}
|
|
|
|
static void
|
|
lti(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0)
|
|
{
|
|
return cci(_jit,CC_LT,r0,r1,i0);
|
|
}
|
|
|
|
static void
|
|
ltr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
return ccr(_jit,CC_CC,r0,r1,r2);
|
|
}
|
|
|
|
static void
|
|
lti_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0)
|
|
{
|
|
return cci(_jit,CC_CC,r0,r1,i0);
|
|
}
|
|
|
|
static void
|
|
ler(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
return ccr(_jit,CC_LE,r0,r1,r2);
|
|
}
|
|
|
|
static void
|
|
lei(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0)
|
|
{
|
|
return cci(_jit,CC_LE,r0,r1,i0);
|
|
}
|
|
|
|
static void
|
|
ler_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
return ccr(_jit,CC_LS,r0,r1,r2);
|
|
}
|
|
|
|
static void
|
|
lei_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0)
|
|
{
|
|
return cci(_jit,CC_LS,r0,r1,i0);
|
|
}
|
|
|
|
static void
|
|
eqr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
return ccr(_jit,CC_EQ,r0,r1,r2);
|
|
}
|
|
|
|
static void
|
|
eqi(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0)
|
|
{
|
|
return cci(_jit,CC_EQ,r0,r1,i0);
|
|
}
|
|
|
|
static void
|
|
ger(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
return ccr(_jit,CC_GE,r0,r1,r2);
|
|
}
|
|
|
|
static void
|
|
gei(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0)
|
|
{
|
|
return cci(_jit,CC_GE,r0,r1,i0);
|
|
}
|
|
|
|
static void
|
|
ger_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
return ccr(_jit,CC_CS,r0,r1,r2);
|
|
}
|
|
|
|
static void
|
|
gei_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0)
|
|
{
|
|
return cci(_jit,CC_CS,r0,r1,i0);
|
|
}
|
|
|
|
static void
|
|
gtr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
return ccr(_jit,CC_GT,r0,r1,r2);
|
|
}
|
|
|
|
static void
|
|
gti(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0)
|
|
{
|
|
return cci(_jit,CC_GT,r0,r1,i0);
|
|
}
|
|
|
|
static void
|
|
gtr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
return ccr(_jit,CC_HI,r0,r1,r2);
|
|
}
|
|
|
|
static void
|
|
gti_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0)
|
|
{
|
|
return cci(_jit,CC_HI,r0,r1,i0);
|
|
}
|
|
|
|
static void
|
|
ner(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
return ccr(_jit,CC_NE,r0,r1,r2);
|
|
}
|
|
|
|
static void
|
|
nei(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t i0)
|
|
{
|
|
return cci(_jit,CC_NE,r0,r1,i0);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bccr(jit_state_t *_jit, int32_t cc, int32_t r0, int32_t r1)
|
|
{
|
|
CMP(_jit, r0, r1);
|
|
return B_C(_jit, cc);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bcci(jit_state_t *_jit, int32_t cc, int32_t r0, jit_word_t i1)
|
|
{
|
|
jit_word_t is = i1 >> 12;
|
|
jit_word_t in = -i1;
|
|
jit_word_t iS = in >> 12;
|
|
if ( i1 >= 0 && i1 <= 0xfff) {
|
|
CMPI (_jit, r0, i1);
|
|
} else if ((is << 12) == i1 && is >= 0 && is <= 0xfff) {
|
|
CMPI_12(_jit, r0, is);
|
|
} else if ( in >= 0 && in <= 0xfff) {
|
|
CMNI (_jit, r0, in);
|
|
} else if ((iS << 12) == is && iS >= 0 && iS <= 0xfff) {
|
|
CMNI_12(_jit, r0, iS);
|
|
} else {
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i1);
|
|
CMP(_jit, r0, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
return B_C(_jit, cc);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bltr(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return bccr(_jit,BCC_LT,r0,r1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
blti(jit_state_t *_jit, int32_t r0, int32_t i1)
|
|
{
|
|
return bcci(_jit,BCC_LT,r0,i1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bltr_u(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return bccr(_jit,BCC_CC,r0,r1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
blti_u(jit_state_t *_jit, int32_t r0, int32_t i1)
|
|
{
|
|
return bcci(_jit,BCC_CC,r0,i1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bler(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return bccr(_jit,BCC_LE,r0,r1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
blei(jit_state_t *_jit, int32_t r0, int32_t i1)
|
|
{
|
|
return bcci(_jit,BCC_LE,r0,i1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bler_u(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return bccr(_jit,BCC_LS,r0,r1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
blei_u(jit_state_t *_jit, int32_t r0, int32_t i1)
|
|
{
|
|
return bcci(_jit,BCC_LS,r0,i1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
beqr(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return bccr(_jit,BCC_EQ,r0,r1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bger(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return bccr(_jit,BCC_GE,r0,r1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bgei(jit_state_t *_jit, int32_t r0, int32_t i1)
|
|
{
|
|
return bcci(_jit,BCC_GE,r0,i1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bger_u(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return bccr(_jit,BCC_CS,r0,r1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bgei_u(jit_state_t *_jit, int32_t r0, int32_t i1)
|
|
{
|
|
return bcci(_jit,BCC_CS,r0,i1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bgtr(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return bccr(_jit,BCC_GT,r0,r1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bgti(jit_state_t *_jit, int32_t r0, int32_t i1)
|
|
{
|
|
return bcci(_jit,BCC_GT,r0,i1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bgtr_u(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return bccr(_jit,BCC_HI,r0,r1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bgti_u(jit_state_t *_jit, int32_t r0, int32_t i1)
|
|
{
|
|
return bcci(_jit,BCC_HI,r0,i1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bner(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return bccr(_jit,BCC_NE,r0,r1);
|
|
}
|
|
|
|
static void
|
|
addi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_word_t is = i0 >> 12;
|
|
jit_word_t in = -i0;
|
|
jit_word_t iS = in >> 12;
|
|
if ( i0 >= 0 && i0 <= 0xfff) {
|
|
ADDI (_jit, r0, r1, i0);
|
|
} else if ((is << 12) == i0 && is >= 0 && is <= 0xfff) {
|
|
ADDI_12(_jit, r0, r1, is);
|
|
} else if ( in >= 0 && in <= 0xfff) {
|
|
SUBI (_jit, r0, r1, in);
|
|
} else if ((iS << 12) == is && iS >= 0 && iS <= 0xfff) {
|
|
SUBI_12(_jit, r0, r1, iS);
|
|
} else {
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i0);
|
|
addr(_jit, r0, r1, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
}
|
|
|
|
static void
|
|
addci(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_word_t is = i0 >> 12;
|
|
jit_word_t in = -i0;
|
|
jit_word_t iS = in >> 12;
|
|
if ( i0 >= 0 && i0 <= 0xfff) {
|
|
ADDSI (_jit, r0, r1, i0);
|
|
} else if ((is << 12) == i0 && is >= 0 && is <= 0xfff) {
|
|
ADDSI_12(_jit, r0, r1, is);
|
|
} else if ( in >= 0 && in <= 0xfff) {
|
|
SUBSI (_jit, r0, r1, in);
|
|
} else if ((iS << 12) == is && iS >= 0 && iS <= 0xfff) {
|
|
SUBSI_12(_jit, r0, r1, iS);
|
|
} else {
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i0);
|
|
addcr(_jit, r0, r1, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
}
|
|
|
|
static void
|
|
addxi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i0);
|
|
addxr(_jit, r0, r1, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
|
|
static void
|
|
subi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_word_t is = i0 >> 12;
|
|
if ( i0 >= 0 && i0 <= 0xfff) {
|
|
SUBI (_jit, r0, r1, i0);
|
|
} else if ((is << 12) == i0 && is >= 0 && is <= 0xfff) {
|
|
SUBI_12(_jit, r0, r1, is);
|
|
} else {
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i0);
|
|
subr(_jit, r0, r1, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
}
|
|
|
|
static void
|
|
subci(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_word_t is = i0 >> 12;
|
|
if ( i0 >= 0 && i0 <= 0xfff) {
|
|
SUBSI (_jit, r0, r1, i0);
|
|
} else if ((is << 12) == i0 && is >= 0 && is <= 0xfff) {
|
|
SUBSI_12(_jit, r0, r1, is);
|
|
} else {
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i0);
|
|
subcr(_jit, r0, r1, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
}
|
|
|
|
static void
|
|
subxi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i0);
|
|
subxr(_jit, r0, r1, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
baddr(jit_state_t *_jit, int32_t cc, int32_t r0, int32_t r1)
|
|
{
|
|
addcr(_jit, r0, r0, r1);
|
|
return B_C(_jit, cc);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
baddi(jit_state_t *_jit, int32_t cc, int32_t r0, jit_word_t i1)
|
|
{
|
|
addci(_jit, r0, r0, i1);
|
|
return B_C(_jit, cc);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
boaddr(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return baddr(_jit,BCC_VS,r0,r1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
boaddi(jit_state_t *_jit, int32_t r0, int32_t i1)
|
|
{
|
|
return baddi(_jit,BCC_VS,r0,i1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
boaddr_u(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return baddr(_jit,BCC_HS,r0,r1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
boaddi_u(jit_state_t *_jit, int32_t r0, int32_t i1)
|
|
{
|
|
return baddi(_jit,BCC_HS,r0,i1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bxaddr(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return baddr(_jit,BCC_VC,r0,r1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bxaddi(jit_state_t *_jit, int32_t r0, int32_t i1)
|
|
{
|
|
return baddi(_jit,BCC_VC,r0,i1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bxaddr_u(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return baddr(_jit,BCC_LO,r0,r1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bxaddi_u(jit_state_t *_jit, int32_t r0, int32_t i1)
|
|
{
|
|
return baddi(_jit,BCC_LO,r0,i1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bsubr(jit_state_t *_jit, int32_t cc, int32_t r0, int32_t r1)
|
|
{
|
|
subcr(_jit, r0, r0, r1);
|
|
return B_C(_jit, cc);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bsubi(jit_state_t *_jit, int32_t cc, int32_t r0, jit_word_t i1)
|
|
{
|
|
subci(_jit, r0, r0, i1);
|
|
return B_C(_jit, cc);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bosubr(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return bsubr(_jit,BCC_VS,r0,r1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bosubi(jit_state_t *_jit, int32_t r0, int32_t i1)
|
|
{
|
|
return bsubi(_jit,BCC_VS,r0,i1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bosubr_u(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return bsubr(_jit,BCC_LO,r0,r1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bosubi_u(jit_state_t *_jit, int32_t r0, int32_t i1)
|
|
{
|
|
return bsubi(_jit,BCC_LO,r0,i1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bxsubr(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return bsubr(_jit,BCC_VC,r0,r1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bxsubi(jit_state_t *_jit, int32_t r0, int32_t i1)
|
|
{
|
|
return bsubi(_jit,BCC_VC,r0,i1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bxsubr_u(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return bsubr(_jit,BCC_HS,r0,r1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bxsubi_u(jit_state_t *_jit, int32_t r0, int32_t i1)
|
|
{
|
|
return bsubi(_jit,BCC_HS,r0,i1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bmxr(jit_state_t *_jit, int32_t cc, int32_t r0, int32_t r1)
|
|
{
|
|
TST(_jit, r0, r1);
|
|
return B_C(_jit, cc);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bmxi(jit_state_t *_jit, int32_t cc, int32_t r0, jit_word_t i1)
|
|
{
|
|
int32_t imm;
|
|
imm = logical_immediate(i1);
|
|
if (imm != -1) {
|
|
TSTI(_jit, r0, imm);
|
|
} else {
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i1);
|
|
TST(_jit, r0, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
return B_C(_jit, cc);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bmsr(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return bmxr(_jit,BCC_NE,r0,r1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bmsi(jit_state_t *_jit, int32_t r0, int32_t i1)
|
|
{
|
|
return bmxi(_jit,BCC_NE,r0,i1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bmcr(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
return bmxr(_jit,BCC_EQ,r0,r1);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bmci(jit_state_t *_jit, int32_t r0, int32_t i1)
|
|
{
|
|
return bmxi(_jit,BCC_EQ,r0,i1);
|
|
}
|
|
|
|
static void
|
|
jmpr(jit_state_t *_jit, int32_t r0)
|
|
{
|
|
return BR(_jit, r0);
|
|
}
|
|
|
|
static void
|
|
callr(jit_state_t *_jit, int32_t r0)
|
|
{
|
|
return BLR(_jit,r0);
|
|
}
|
|
|
|
static void
|
|
nop(jit_state_t *_jit, int32_t i0)
|
|
{
|
|
for (; i0 > 0; i0 -= 4)
|
|
NOP(_jit);
|
|
ASSERT(i0 == 0);
|
|
}
|
|
|
|
static void
|
|
rsbi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
|
{
|
|
subi(_jit, r0, r1, i0);
|
|
negr(_jit, r0, r0);
|
|
}
|
|
|
|
static void
|
|
muli(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i0);
|
|
mulr(_jit, r0, r1, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
|
|
static void
|
|
qmulr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, int32_t r3)
|
|
{
|
|
jit_gpr_t reg;
|
|
if (r0 == r2 || r0 == r3) {
|
|
reg = get_temp_gpr(_jit);
|
|
mulr(_jit, jit_gpr_regno(reg), r2, r3);
|
|
} else {
|
|
mulr(_jit, r0, r2, r3);
|
|
}
|
|
SMULH(_jit, r1, r2, r3);
|
|
if (r0 == r2 || r0 == r3) {
|
|
movr(_jit, r0, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
}
|
|
|
|
static void
|
|
qmuli(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, jit_word_t i0)
|
|
{
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i0);
|
|
qmulr(_jit, r0, r1, r2, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
|
|
static void
|
|
qmulr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, int32_t r3)
|
|
{
|
|
jit_gpr_t reg;
|
|
if (r0 == r2 || r0 == r3) {
|
|
reg = get_temp_gpr(_jit);
|
|
mulr(_jit, jit_gpr_regno(reg), r2, r3);
|
|
} else {
|
|
mulr(_jit, r0, r2, r3);
|
|
}
|
|
UMULH(_jit, r1, r2, r3);
|
|
if (r0 == r2 || r0 == r3) {
|
|
movr(_jit, r0, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
}
|
|
|
|
static void
|
|
qmuli_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, jit_word_t i0)
|
|
{
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i0);
|
|
qmulr_u(_jit, r0, r1, r2, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
|
|
static void
|
|
divi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i0);
|
|
divr(_jit, r0, r1, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
|
|
static void
|
|
divi_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i0);
|
|
divr_u(_jit, r0, r1, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
|
|
static void
|
|
qdivi(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, jit_word_t i0)
|
|
{
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i0);
|
|
qdivr(_jit, r0, r1, r2, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
|
|
static void
|
|
qdivi_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2, jit_word_t i0)
|
|
{
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i0);
|
|
qdivr_u(_jit, r0, r1, r2, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
|
|
static void
|
|
remr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
if (r0 == r1 || r0 == r2) {
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
divr(_jit, jit_gpr_regno(reg), r1, r2);
|
|
mulr(_jit, jit_gpr_regno(reg), r2, jit_gpr_regno(reg));
|
|
subr(_jit, r0, r1, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
} else {
|
|
divr(_jit, r0, r1, r2);
|
|
mulr(_jit, r0, r2, r0);
|
|
subr(_jit, r0, r1, r0);
|
|
}
|
|
}
|
|
|
|
static void
|
|
remi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i0);
|
|
remr(_jit, r0, r1, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
|
|
static void
|
|
remr_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
if (r0 == r1 || r0 == r2) {
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
divr_u(_jit, jit_gpr_regno(reg), r1, r2);
|
|
mulr(_jit, jit_gpr_regno(reg), r2, jit_gpr_regno(reg));
|
|
subr(_jit, r0, r1, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
} else {
|
|
divr_u(_jit, r0, r1, r2);
|
|
mulr(_jit, r0, r2, r0);
|
|
subr(_jit, r0, r1, r0);
|
|
}
|
|
}
|
|
|
|
static void
|
|
remi_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i0);
|
|
remr_u(_jit, r0, r1, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
|
|
static void
|
|
lshi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
|
{
|
|
if (i0 == 0) {
|
|
movr(_jit, r0, r1);
|
|
} else {
|
|
ASSERT(i0 > 0 && i0 < 64);
|
|
LSLI(_jit, r0, r1, i0);
|
|
}
|
|
}
|
|
|
|
static void
|
|
rshi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
|
{
|
|
if (i0 == 0) {
|
|
movr(_jit, r0, r1);
|
|
} else {
|
|
ASSERT(i0 > 0 && i0 < 64);
|
|
ASRI(_jit, r0, r1, i0);
|
|
}
|
|
}
|
|
|
|
static void
|
|
rshi_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
|
{
|
|
if (i0 == 0) {
|
|
movr(_jit, r0, r1);
|
|
} else {
|
|
ASSERT(i0 > 0 && i0 < 64);
|
|
LSRI(_jit, r0, r1, i0);
|
|
}
|
|
}
|
|
|
|
static void
|
|
andi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
|
{
|
|
int32_t imm;
|
|
if (i0 == 0) {
|
|
movi(_jit, r0, 0);
|
|
} else if (i0 == -1){
|
|
movr(_jit, r0, r1);
|
|
} else {
|
|
imm = logical_immediate(i0);
|
|
if (imm != -1) {
|
|
ANDI(_jit, r0, r1, imm);
|
|
} else {
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i0);
|
|
andr(_jit, r0, r1, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
ori(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
|
{
|
|
int32_t imm;
|
|
if (i0 == 0) {
|
|
movr(_jit, r0, r1);
|
|
} else if (i0 == -1) {
|
|
movi(_jit, r0, -1);
|
|
} else {
|
|
imm = logical_immediate(i0);
|
|
if (imm != -1) {
|
|
ORRI(_jit, r0, r1, imm);
|
|
} else {
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i0);
|
|
orr(_jit, r0, r1, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
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 {
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i0);
|
|
xorr(_jit, r0, r1, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
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)
|
|
{
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i0);
|
|
ldr_c(_jit, r0, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
|
|
static void
|
|
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)
|
|
{
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i0);
|
|
ldr_uc(_jit, r0, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
|
|
static void
|
|
ldi_s(jit_state_t *_jit, int32_t r0, jit_word_t i0)
|
|
{
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i0);
|
|
ldr_s(_jit, r0, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
|
|
static void
|
|
ldr_us(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
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)
|
|
{
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i0);
|
|
ldr_us(_jit, r0, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
|
|
static void
|
|
ldi_i(jit_state_t *_jit, int32_t r0, jit_word_t i0)
|
|
{
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i0);
|
|
ldr_i(_jit, r0, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
|
|
static void
|
|
ldr_ui(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
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)
|
|
{
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i0);
|
|
ldr_ui(_jit, r0, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
|
|
static void
|
|
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)
|
|
{
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i0);
|
|
ldr_l(_jit, r0, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
|
|
static void
|
|
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 {
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i0);
|
|
LDRSB(_jit, r0, r1, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
extr_c(_jit, r0, r0);
|
|
}
|
|
|
|
static void
|
|
ldxr_uc(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
LDRB(_jit, r0, r1, r2);
|
|
#if 0
|
|
extr_uc(_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 {
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
addi(_jit, jit_gpr_regno(reg), r1, i0);
|
|
ldr_uc(_jit, r0, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
#if 0
|
|
extr_uc(_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 {
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i0);
|
|
LDRSH(_jit, r0, r1, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
}
|
|
|
|
static void
|
|
ldxr_us(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
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 {
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i0);
|
|
LDRH(_jit, r0, r1, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
#if 0
|
|
extr_us(_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 {
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
addi(_jit, jit_gpr_regno(reg), r1, i0);
|
|
ldr_i(_jit, r0, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
}
|
|
|
|
static void
|
|
ldxr_ui(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
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 {
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i0);
|
|
LDRW(_jit, r0, r1, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
#if 0
|
|
extr_ui(_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 {
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
addi(_jit, jit_gpr_regno(reg), r1, i0);
|
|
ldr_l(_jit, r0, jit_gpr_regno(reg));
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
}
|
|
|
|
static void
|
|
sti_c(jit_state_t *_jit, jit_word_t i0, int32_t r0)
|
|
{
|
|
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));
|
|
}
|
|
|
|
static void
|
|
pushr(jit_state_t *_jit, int32_t r0)
|
|
{
|
|
abort();
|
|
}
|
|
|
|
static void
|
|
popr(jit_state_t *_jit, int32_t r0)
|
|
{
|
|
abort();
|
|
}
|