1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-06 04:00:26 +02:00
guile/lightening/aarch64-cpu.c
2019-05-14 15:46:19 +02:00

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();
}