mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-05 03:30:24 +02:00
2538 lines
56 KiB
C
2538 lines
56 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
|
|
|
|
static int32_t
|
|
logical_immediate(jit_word_t imm)
|
|
{
|
|
/* There are 5334 possible immediate values, but to avoid the
|
|
* need of either too complex code or large lookup tables,
|
|
* only check for (simply) encodable common/small values */
|
|
switch (imm) {
|
|
case -16: return 0xf3b;
|
|
case -15: return 0xf3c;
|
|
case -13: return 0xf3d;
|
|
case -9: return 0xf3e;
|
|
case -8: return 0xf7c;
|
|
case -7: return 0xf7d;
|
|
case -5: return 0xf7e;
|
|
case -4: return 0xfbd;
|
|
case -3: return 0xfbe;
|
|
case -2: return 0xffe;
|
|
case 1: return 0x000;
|
|
case 2: return 0xfc0;
|
|
case 3: return 0x001;
|
|
case 4: return 0xf80;
|
|
case 6: return 0xfc1;
|
|
case 7: return 0x002;
|
|
case 8: return 0xf40;
|
|
case 12: return 0xf81;
|
|
case 14: return 0xfc2;
|
|
case 15: return 0x003;
|
|
case 16: return 0xf00;
|
|
default: return -1;
|
|
}
|
|
}
|
|
|
|
static void
|
|
oxxx(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Rn, int32_t Rm)
|
|
{
|
|
uint32_t inst = Op;
|
|
inst = write_Rd_bitfield(inst, Rd);
|
|
inst = write_Rn_bitfield(inst, Rn);
|
|
inst = write_Rm_bitfield(inst, Rm);
|
|
emit_u32(_jit, inst);
|
|
}
|
|
|
|
static void
|
|
oxxi(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Rn, int32_t Imm12)
|
|
{
|
|
uint32_t inst = Op;
|
|
inst = write_Rd_bitfield(inst, Rd);
|
|
inst = write_Rn_bitfield(inst, Rn);
|
|
inst = write_imm12_bitfield(inst, Imm12);
|
|
emit_u32(_jit, inst);
|
|
}
|
|
|
|
static void
|
|
oxx9(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Rn, int32_t Simm9)
|
|
{
|
|
uint32_t inst = Op;
|
|
inst = write_Rd_bitfield(inst, Rd);
|
|
inst = write_Rn_bitfield(inst, Rn);
|
|
inst = write_simm9_bitfield(inst, Simm9);
|
|
emit_u32(_jit, inst);
|
|
}
|
|
|
|
static uint32_t
|
|
encode_ox19(jit_state_t *_jit, int32_t Op, int32_t Rd)
|
|
{
|
|
uint32_t inst = Op;
|
|
inst = write_Rd_bitfield(inst, Rd);
|
|
return inst;
|
|
}
|
|
|
|
static uint32_t
|
|
encode_oc19(jit_state_t *_jit, int32_t Op, int32_t Cc)
|
|
{
|
|
uint32_t inst = Op;
|
|
inst = write_cond2_bitfield(inst, Cc);
|
|
return inst;
|
|
}
|
|
|
|
static uint32_t
|
|
encode_o26(jit_state_t *_jit, int32_t Op)
|
|
{
|
|
uint32_t inst = Op;
|
|
return inst;
|
|
}
|
|
|
|
static void
|
|
ox_x(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Rm)
|
|
{
|
|
uint32_t inst = Op;
|
|
inst = write_Rd_bitfield(inst, Rd);
|
|
inst = write_Rm_bitfield(inst, Rm);
|
|
emit_u32(_jit, inst);
|
|
}
|
|
|
|
static void
|
|
o_xx(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Rn)
|
|
{
|
|
uint32_t inst = Op;
|
|
inst = write_Rd_bitfield(inst, Rd);
|
|
inst = write_Rn_bitfield(inst, Rn);
|
|
emit_u32(_jit, inst);
|
|
}
|
|
|
|
static void
|
|
oxx_(jit_state_t *_jit, int32_t Op, int32_t Rn, int32_t Rm)
|
|
{
|
|
uint32_t inst = Op;
|
|
inst = write_Rn_bitfield(inst, Rn);
|
|
inst = write_Rm_bitfield(inst, Rm);
|
|
emit_u32(_jit, inst);
|
|
}
|
|
|
|
static void
|
|
o_x_(jit_state_t *_jit, int32_t Op, int32_t Rn)
|
|
{
|
|
uint32_t inst = Op;
|
|
inst = write_Rn_bitfield(inst, Rn);
|
|
emit_u32(_jit, inst);
|
|
}
|
|
|
|
static void
|
|
ox_h(jit_state_t *_jit, int32_t Op, int32_t Rd, int32_t Imm16)
|
|
{
|
|
uint32_t inst = Op;
|
|
inst = write_Rd_bitfield(inst, Rd);
|
|
inst = write_imm16_bitfield(inst, Imm16);
|
|
emit_u32(_jit, inst);
|
|
}
|
|
|
|
static void
|
|
oxxrs(jit_state_t *_jit, int32_t Op,
|
|
int32_t Rd, int32_t Rn, int32_t R, int32_t S)
|
|
{
|
|
uint32_t inst = Op;
|
|
inst = write_Rd_bitfield(inst, Rd);
|
|
inst = write_Rn_bitfield(inst, Rn);
|
|
inst = write_immr_bitfield(inst, R);
|
|
inst = write_imms_bitfield(inst, S);
|
|
emit_u32(_jit, inst);
|
|
}
|
|
|
|
static void
|
|
oxxxc(jit_state_t *_jit, int32_t Op,
|
|
int32_t Rd, int32_t Rn, int32_t Rm, int32_t Cc)
|
|
{
|
|
uint32_t inst = Op;
|
|
inst = write_Rd_bitfield(inst, Rd);
|
|
inst = write_Rn_bitfield(inst, Rn);
|
|
inst = write_Rm_bitfield(inst, Rm);
|
|
inst = write_cond_bitfield(inst, Cc);
|
|
emit_u32(_jit, inst);
|
|
}
|
|
|
|
static void
|
|
oxxx7(jit_state_t *_jit, int32_t Op,
|
|
int32_t Rt, int32_t Rt2, int32_t Rn, int32_t Simm7)
|
|
{
|
|
uint32_t inst = Op;
|
|
inst = write_Rt_bitfield(inst, Rt);
|
|
inst = write_Rt2_bitfield(inst, Rt2);
|
|
inst = write_Rn_bitfield(inst, Rn);
|
|
inst = write_simm7_bitfield(inst, Simm7);
|
|
emit_u32(_jit, inst);
|
|
}
|
|
|
|
#define XZR_REGNO 0x1f
|
|
#define WZR_REGNO XZR_REGNO
|
|
#define LSL_12 0x00400000
|
|
#define MOVI_LSL_16 0x00200000
|
|
#define MOVI_LSL_32 0x00400000
|
|
#define MOVI_LSL_48 0x00600000
|
|
#define XS 0x80000000 /* Wn -> Xn */
|
|
#define BCC_EQ 0x0
|
|
#define BCC_NE 0x1
|
|
#define BCC_CS 0x2
|
|
#define BCC_HS BCC_CS
|
|
#define BCC_CC 0x3
|
|
#define BCC_LO BCC_CC
|
|
#define BCC_MI 0x4
|
|
#define BCC_PL 0x5
|
|
#define BCC_VS 0x6
|
|
#define BCC_VC 0x7
|
|
#define BCC_HI 0x8
|
|
#define BCC_LS 0x9
|
|
#define BCC_GE 0xa
|
|
#define BCC_LT 0xb
|
|
#define BCC_GT 0xc
|
|
#define BCC_LE 0xd
|
|
#define BCC_AL 0xe
|
|
#define BCC_NV 0xf
|
|
/* adapted and cut down to only tested and required by lightening,
|
|
* from data in binutils/aarch64-tbl.h */
|
|
#define A64_ADCS 0x3a000000
|
|
#define A64_SBCS 0x7a000000
|
|
#define A64_ADDI 0x11000000
|
|
#define A64_ADDSI 0xb1000000
|
|
#define A64_SUBI 0x51000000
|
|
#define A64_SUBSI 0x71000000
|
|
#define A64_ADD 0x0b000000
|
|
#define A64_ADDS 0x2b000000
|
|
#define A64_SUB 0x4b000000
|
|
#define A64_NEG 0x4b0003e0
|
|
#define A64_SUBS 0x6b000000
|
|
#define A64_CMP 0x6b00001f
|
|
#define A64_SBFM 0x93400000
|
|
#define A64_UBFM 0x53400000
|
|
#define A64_UBFX 0x53000000
|
|
#define A64_B 0x14000000
|
|
#define A64_BL 0x94000000
|
|
#define A64_BR 0xd61f0000
|
|
#define A64_BLR 0xd63f0000
|
|
#define A64_RET 0xd65f0000
|
|
#define A64_CBZ 0x34000000
|
|
#define A64_CBNZ 0x35000000
|
|
#define A64_B_C 0x54000000
|
|
#define A64_CSINC 0x1a800400
|
|
#define A64_REV 0xdac00c00
|
|
#define A64_UDIV 0x1ac00800
|
|
#define A64_SDIV 0x1ac00c00
|
|
#define A64_LSL 0x1ac02000
|
|
#define A64_LSR 0x1ac02400
|
|
#define A64_ASR 0x1ac02800
|
|
#define A64_MUL 0x1b007c00
|
|
#define A64_SMULL 0x9b207c00
|
|
#define A64_SMULH 0x9b407c00
|
|
#define A64_UMULL 0x9ba07c00
|
|
#define A64_UMULH 0x9bc07c00
|
|
#define A64_STRBI 0x39000000
|
|
#define A64_LDRBI 0x39400000
|
|
#define A64_LDRSBI 0x39800000
|
|
#define A64_STRI 0xf9000000
|
|
#define A64_LDRI 0xf9400000
|
|
#define A64_LDRI_LITERAL 0x58000000
|
|
#define A64_STRHI 0x79000000
|
|
#define A64_LDRHI 0x79400000
|
|
#define A64_LDRSHI 0x79800000
|
|
#define A64_STRWI 0xb9000000
|
|
#define A64_LDRWI 0xb9400000
|
|
#define A64_LDRSWI 0xb9800000
|
|
#define A64_STRB 0x38206800
|
|
#define A64_LDRB 0x38606800
|
|
#define A64_LDRSB 0x38e06800
|
|
#define A64_STR 0xf8206800
|
|
#define A64_LDR 0xf8606800
|
|
#define A64_STRH 0x78206800
|
|
#define A64_LDRH 0x78606800
|
|
#define A64_LDRSH 0x78a06800
|
|
#define A64_STRW 0xb8206800
|
|
#define A64_LDRW 0xb8606800
|
|
#define A64_LDRSW 0xb8a06800
|
|
#define A64_STURB 0x38000000
|
|
#define A64_LDURB 0x38400000
|
|
#define A64_LDURSB 0x38800000
|
|
#define A64_STUR 0xf8000000
|
|
#define A64_LDUR 0xf8400000
|
|
#define A64_STURH 0x78000000
|
|
#define A64_LDURH 0x78400000
|
|
#define A64_LDURSH 0x78800000
|
|
#define A64_STURW 0xb8000000
|
|
#define A64_LDURW 0xb8400000
|
|
#define A64_LDURSW 0xb8800000
|
|
#define A64_STP_POS 0x29800000
|
|
#define A64_LDP_POS 0x28c00000
|
|
#define A64_STP_PRE 0x29800000
|
|
#define A64_STR_PRE 0xf8000c00
|
|
#define A64_LDR_POS 0xf8400c00
|
|
#define A64_ANDI 0x12400000
|
|
#define A64_ORRI 0x32400000
|
|
#define A64_EORI 0x52400000
|
|
#define A64_ANDSI 0x72000000
|
|
#define A64_AND 0x0a000000
|
|
#define A64_ORR 0x2a000000
|
|
#define A64_MOV 0x2a0003e0 /* AKA orr Rd,xzr,Rm */
|
|
#define A64_MVN 0x2a2003e0
|
|
#define A64_UXTW 0x2a0003e0 /* AKA MOV */
|
|
#define A64_EOR 0x4a000000
|
|
#define A64_ANDS 0x6a000000
|
|
#define A64_MOVN 0x12800000
|
|
#define A64_MOVZ 0x52800000
|
|
#define A64_MOVK 0x72800000
|
|
|
|
static void
|
|
SBFM(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t ImmR, int32_t ImmS)
|
|
{
|
|
return oxxrs(_jit, A64_SBFM|XS,Rd,Rn,ImmR,ImmS);
|
|
}
|
|
|
|
static void
|
|
UBFM(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t ImmR, int32_t ImmS)
|
|
{
|
|
return oxxrs(_jit, A64_UBFM|XS,Rd,Rn,ImmR,ImmS);
|
|
}
|
|
|
|
static void
|
|
UBFX(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t ImmR, int32_t ImmS)
|
|
{
|
|
return oxxrs(_jit, A64_UBFX,Rd,Rn,ImmR,ImmS);
|
|
}
|
|
|
|
static void
|
|
CMP(jit_state_t *_jit, int32_t Rn, int32_t Rm)
|
|
{
|
|
return oxx_(_jit, A64_CMP|XS,Rn,Rm);
|
|
}
|
|
|
|
static void
|
|
CMPI(jit_state_t *_jit, int32_t Rn, int32_t Imm12)
|
|
{
|
|
return oxxi(_jit, A64_SUBSI|XS,XZR_REGNO,Rn,Imm12);
|
|
}
|
|
|
|
static void
|
|
CMPI_12(jit_state_t *_jit, int32_t Rn, int32_t Imm12)
|
|
{
|
|
return oxxi(_jit, A64_SUBSI|XS|LSL_12,XZR_REGNO,Rn,Imm12);
|
|
}
|
|
|
|
static void
|
|
CMNI(jit_state_t *_jit, int32_t Rn, int32_t Imm12)
|
|
{
|
|
return oxxi(_jit, A64_ADDSI|XS,XZR_REGNO,Rn,Imm12);
|
|
}
|
|
|
|
static void
|
|
CMNI_12(jit_state_t *_jit, int32_t Rn, int32_t Imm12)
|
|
{
|
|
return oxxi(_jit, A64_ADDSI|XS|LSL_12,XZR_REGNO,Rn,Imm12);
|
|
}
|
|
|
|
static void
|
|
CSINC(jit_state_t *_jit, int32_t Rd, int32_t Rn, int32_t Rm, int32_t Cc)
|
|
{
|
|
return oxxxc(_jit, A64_CSINC|XS,Rd,Rn,Rm,Cc);
|
|
}
|
|
|
|
static void
|
|
TST(jit_state_t *_jit, int32_t Rn, int32_t Rm)
|
|
{
|
|
return oxxx(_jit, A64_ANDS|XS,XZR_REGNO,Rn,Rm);
|
|
}
|
|
|
|
/* actually should use oxxrs but logical_immediate returns proper encoding */
|
|
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
|
|
STR_PRE(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Simm9)
|
|
{
|
|
return oxx9(_jit, A64_STR_PRE,Rt,Rn,Simm9);
|
|
}
|
|
|
|
static void
|
|
LDR_POS(jit_state_t *_jit, int32_t Rt, int32_t Rn, int32_t Simm9)
|
|
{
|
|
return oxx9(_jit, A64_LDR_POS,Rt,Rn,Simm9);
|
|
}
|
|
|
|
static void
|
|
STP_PRE(jit_state_t *_jit, int32_t Rt, int32_t Rt2, int32_t Rn, int32_t Simm7)
|
|
{
|
|
return oxxx7(_jit, A64_STP_PRE|XS,Rt,Rt2,Rn,Simm7);
|
|
}
|
|
|
|
static void
|
|
LDP_POS(jit_state_t *_jit, int32_t Rt, int32_t Rt2, int32_t Rn, int32_t Simm7)
|
|
{
|
|
return oxxx7(_jit, A64_LDP_POS|XS,Rt,Rt2,Rn,Simm7);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
B(jit_state_t *_jit)
|
|
{
|
|
return emit_jmp(_jit, encode_o26(_jit, A64_B));
|
|
}
|
|
|
|
static jit_reloc_t
|
|
BL(jit_state_t *_jit)
|
|
{
|
|
return emit_jmp(_jit, encode_o26(_jit, A64_BL));
|
|
}
|
|
|
|
static void
|
|
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,jit_gpr_regno(_LR));
|
|
}
|
|
|
|
static jit_reloc_t
|
|
B_C(jit_state_t *_jit, int32_t Cc)
|
|
{
|
|
return emit_jcc(_jit, encode_oc19(_jit, A64_B_C, Cc));
|
|
}
|
|
|
|
static jit_reloc_t
|
|
CBZ(jit_state_t *_jit, int32_t Rd)
|
|
{
|
|
return emit_jcc(_jit, encode_ox19(_jit, A64_CBZ|XS,Rd));
|
|
}
|
|
|
|
static jit_reloc_t
|
|
CBNZ(jit_state_t *_jit, int32_t Rd)
|
|
{
|
|
return emit_jcc(_jit, encode_ox19(_jit, A64_CBNZ|XS,Rd));
|
|
}
|
|
|
|
static void
|
|
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
|
|
emit_veneer(jit_state_t *_jit, jit_pointer_t target)
|
|
{
|
|
jit_gpr_t tmp = get_temp_gpr(_jit);
|
|
uint32_t inst = encode_ox19(_jit, A64_LDRI_LITERAL, jit_gpr_regno(tmp));
|
|
uint32_t *loc = _jit->pc.ui;
|
|
emit_u32(_jit, inst);
|
|
BR(_jit, jit_gpr_regno(tmp));
|
|
unget_temp_gpr(_jit);
|
|
if (_jit->overflow)
|
|
return;
|
|
// Patch load to here, divided by 4.
|
|
patch_load_from_pool_offset(loc, _jit->pc.ui - loc);
|
|
emit_u64(_jit, (uint64_t) target);
|
|
}
|
|
|
|
static void
|
|
movr(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
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 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 {
|
|
int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0;
|
|
movi(_jit, r2, i0);
|
|
addr(_jit, r0, r1, r2);
|
|
if (r0 == r1)
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
}
|
|
|
|
static void
|
|
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 {
|
|
int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0;
|
|
movi(_jit, r2, i0);
|
|
addcr(_jit, r0, r1, r2);
|
|
if (r0 == r1)
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
}
|
|
|
|
static void
|
|
addxi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
|
{
|
|
int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0;
|
|
movi(_jit, r2, i0);
|
|
addxr(_jit, r0, r1, r2);
|
|
if (r0 == r1)
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
|
|
static void
|
|
subi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_word_t is = i0 >> 12;
|
|
if ( i0 >= 0 && i0 <= 0xfff) {
|
|
SUBI (_jit, r0, r1, i0);
|
|
} else if ((is << 12) == i0 && is >= 0 && is <= 0xfff) {
|
|
SUBI_12(_jit, r0, r1, is);
|
|
} else {
|
|
int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0;
|
|
movi(_jit, r2, i0);
|
|
subr(_jit, r0, r1, r2);
|
|
if (r0 == r1)
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
}
|
|
|
|
static void
|
|
subci(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_word_t is = i0 >> 12;
|
|
if ( i0 >= 0 && i0 <= 0xfff) {
|
|
SUBSI (_jit, r0, r1, i0);
|
|
} else if ((is << 12) == i0 && is >= 0 && is <= 0xfff) {
|
|
SUBSI_12(_jit, r0, r1, is);
|
|
} else {
|
|
int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0;
|
|
movi(_jit, r2, i0);
|
|
subcr(_jit, r0, r1, r2);
|
|
if (r0 == r1)
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
}
|
|
|
|
static void
|
|
subxi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
|
{
|
|
int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0;
|
|
movi(_jit, r2, i0);
|
|
subxr(_jit, r0, r1, r2);
|
|
if (r0 == r1)
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
|
|
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
|
|
muli(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
|
{
|
|
int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0;
|
|
movi(_jit, r2, i0);
|
|
mulr(_jit, r0, r1, r2);
|
|
if (r0 == r1)
|
|
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)
|
|
{
|
|
int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0;
|
|
movi(_jit, r2, i0);
|
|
divr(_jit, r0, r1, r2);
|
|
if (r0 == r1)
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
|
|
static void
|
|
divi_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
|
{
|
|
int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0;
|
|
movi(_jit, r2, i0);
|
|
divr_u(_jit, r0, r1, r2);
|
|
if (r0 == r1)
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
|
|
static void
|
|
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 {
|
|
int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0;
|
|
movi(_jit, r2, i0);
|
|
andr(_jit, r0, r1, r2);
|
|
if (r0 == r1)
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
ori(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
|
{
|
|
int32_t imm;
|
|
if (i0 == 0) {
|
|
movr(_jit, r0, r1);
|
|
} else if (i0 == -1) {
|
|
movi(_jit, r0, -1);
|
|
} else {
|
|
imm = logical_immediate(i0);
|
|
if (imm != -1) {
|
|
ORRI(_jit, r0, r1, imm);
|
|
} else {
|
|
int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0;
|
|
movi(_jit, r2, i0);
|
|
orr(_jit, r0, r1, r2);
|
|
if (r0 == r1)
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
xori(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
|
{
|
|
int32_t imm;
|
|
if (i0 == 0) {
|
|
movr(_jit, r0, r1);
|
|
} else if (i0 == -1) {
|
|
comr(_jit, r0, r1);
|
|
} else {
|
|
imm = logical_immediate(i0);
|
|
if (imm != -1) {
|
|
EORI(_jit, r0, r1, imm);
|
|
} else {
|
|
int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0;
|
|
movi(_jit, r2, i0);
|
|
xorr(_jit, r0, r1, r2);
|
|
if (r0 == r1)
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
bswapr_us(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
bswapr_ul(_jit, r0, r1);
|
|
rshi_u(_jit, r0, r0, 48);
|
|
}
|
|
|
|
static void
|
|
bswapr_ui(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
bswapr_ul(_jit, r0, r1);
|
|
rshi_u(_jit, r0, r0, 32);
|
|
}
|
|
|
|
static void
|
|
ldi_c(jit_state_t *_jit, int32_t r0, jit_word_t i0)
|
|
{
|
|
movi(_jit, r0, i0);
|
|
ldr_c(_jit, r0, r0);
|
|
}
|
|
|
|
static void
|
|
ldr_uc(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
LDRBI(_jit, r0, r1, 0);
|
|
#if 0
|
|
extr_uc(_jit, r0, r0);
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
ldi_uc(jit_state_t *_jit, int32_t r0, jit_word_t i0)
|
|
{
|
|
movi(_jit, r0, i0);
|
|
ldr_uc(_jit, r0, r0);
|
|
}
|
|
|
|
static void
|
|
ldi_s(jit_state_t *_jit, int32_t r0, jit_word_t i0)
|
|
{
|
|
movi(_jit, r0, i0);
|
|
ldr_s(_jit, r0, r0);
|
|
}
|
|
|
|
static void
|
|
ldr_us(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
LDRHI(_jit, r0, r1, 0);
|
|
#if 0
|
|
extr_us(_jit, r0, r0);
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
ldi_us(jit_state_t *_jit, int32_t r0, jit_word_t i0)
|
|
{
|
|
movi(_jit, r0, i0);
|
|
ldr_us(_jit, r0, r0);
|
|
}
|
|
|
|
static void
|
|
ldi_i(jit_state_t *_jit, int32_t r0, jit_word_t i0)
|
|
{
|
|
movi(_jit, r0, i0);
|
|
ldr_i(_jit, r0, r0);
|
|
}
|
|
|
|
static void
|
|
ldr_ui(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
LDRWI(_jit, r0, r1, 0);
|
|
#if 0
|
|
extr_ui(_jit, r0, r0);
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
ldi_ui(jit_state_t *_jit, int32_t r0, jit_word_t i0)
|
|
{
|
|
movi(_jit, r0, i0);
|
|
ldr_ui(_jit, r0, r0);
|
|
}
|
|
|
|
static void
|
|
ldr_l(jit_state_t *_jit, int32_t r0, int32_t r1)
|
|
{
|
|
LDRI(_jit, r0, r1, 0);
|
|
}
|
|
|
|
static void
|
|
ldi_l(jit_state_t *_jit, int32_t r0, jit_word_t i0)
|
|
{
|
|
movi(_jit, r0, i0);
|
|
ldr_l(_jit, r0, r0);
|
|
}
|
|
|
|
static void
|
|
ldxr_c(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
LDRSB(_jit, r0, r1, r2);
|
|
extr_c(_jit, r0, r0);
|
|
}
|
|
|
|
static void
|
|
ldxi_c(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
|
{
|
|
if (i0 >= 0 && i0 <= 4095) {
|
|
LDRSBI(_jit, r0, r1, i0);
|
|
} else if (i0 > -256 && i0 < 0) {
|
|
LDURSB(_jit, r0, r1, i0 & 0x1ff);
|
|
} else {
|
|
int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0;
|
|
movi(_jit, r2, i0);
|
|
LDRSB(_jit, r0, r1, r2);
|
|
if (r0 == r1)
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
extr_c(_jit, r0, r0);
|
|
}
|
|
|
|
static void
|
|
ldxr_uc(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
LDRB(_jit, r0, r1, r2);
|
|
#if 0
|
|
extr_uc(_jit, r0, r0);
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
ldxi_uc(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
|
{
|
|
if (i0 >= 0 && i0 <= 4095) {
|
|
LDRBI(_jit, r0, r1, i0);
|
|
} else if (i0 > -256 && i0 < 0) {
|
|
LDURB(_jit, r0, r1, i0 & 0x1ff);
|
|
} else {
|
|
int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0;
|
|
addi(_jit, r2, r1, i0);
|
|
ldr_uc(_jit, r0, r2);
|
|
if (r0 == r1)
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
#if 0
|
|
extr_uc(_jit, r0, r0);
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
ldxi_s(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
|
{
|
|
ASSERT(!(i0 & 1));
|
|
if (i0 >= 0 && i0 <= 8191) {
|
|
LDRSHI(_jit, r0, r1, i0 >> 1);
|
|
} else if (i0 > -256 && i0 < 0) {
|
|
LDURSH(_jit, r0, r1, i0 & 0x1ff);
|
|
} else {
|
|
int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0;
|
|
movi(_jit, r2, i0);
|
|
LDRSH(_jit, r0, r1, r2);
|
|
if (r0 == r1)
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
}
|
|
|
|
static void
|
|
ldxr_us(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
LDRH(_jit, r0, r1, r2);
|
|
#if 0
|
|
extr_us(_jit, r0, r0);
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
ldxi_us(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
|
{
|
|
ASSERT(!(i0 & 1));
|
|
if (i0 >= 0 && i0 <= 8191) {
|
|
LDRHI(_jit, r0, r1, i0 >> 1);
|
|
} else if (i0 > -256 && i0 < 0) {
|
|
LDURH(_jit, r0, r1, i0 & 0x1ff);
|
|
} else {
|
|
int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0;
|
|
movi(_jit, r2, i0);
|
|
LDRH(_jit, r0, r1, r2);
|
|
if (r0 == r1)
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
#if 0
|
|
extr_us(_jit, r0, r0);
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
ldxi_i(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
|
{
|
|
ASSERT(!(i0 & 3));
|
|
if (i0 >= 0 && i0 <= 16383) {
|
|
LDRSWI(_jit, r0, r1, i0 >> 2);
|
|
} else if (i0 > -256 && i0 < 0) {
|
|
LDURSW(_jit, r0, r1, i0 & 0x1ff);
|
|
} else {
|
|
int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0;
|
|
addi(_jit, r2, r1, i0);
|
|
ldr_i(_jit, r0, r2);
|
|
if (r0 == r1)
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
}
|
|
|
|
static void
|
|
ldxr_ui(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
|
|
{
|
|
LDRW(_jit, r0, r1, r2);
|
|
#if 0
|
|
extr_ui(_jit, r0, r0);
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
ldxi_ui(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
|
{
|
|
ASSERT(!(i0 & 3));
|
|
if (i0 >= 0 && i0 <= 16383) {
|
|
LDRWI(_jit, r0, r1, i0 >> 2);
|
|
} else if (i0 > -256 && i0 < 0) {
|
|
LDURW(_jit, r0, r1, i0 & 0x1ff);
|
|
} else {
|
|
int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0;
|
|
movi(_jit, r2, i0);
|
|
LDRW(_jit, r0, r1, r2);
|
|
if (r0 == r1)
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
#if 0
|
|
extr_ui(_jit, r0, r0);
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
ldxi_l(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
|
{
|
|
ASSERT(!(i0 & 7));
|
|
if (i0 >= 0 && i0 <= 32767) {
|
|
LDRI(_jit, r0, r1, i0 >> 3);
|
|
} else if (i0 > -256 && i0 < 0) {
|
|
LDUR(_jit, r0, r1, i0 & 0x1ff);
|
|
} else {
|
|
int32_t r2 = (r0 == r1) ? jit_gpr_regno(get_temp_gpr(_jit)) : r0;
|
|
addi(_jit, r2, r1, i0);
|
|
ldr_l(_jit, r0, r2);
|
|
if (r0 == r1)
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
}
|
|
|
|
static void
|
|
sti_c(jit_state_t *_jit, jit_word_t i0, int32_t r0)
|
|
{
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i0);
|
|
str_c(_jit, jit_gpr_regno(reg), r0);
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
|
|
static void
|
|
sti_s(jit_state_t *_jit, jit_word_t i0, int32_t r0)
|
|
{
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i0);
|
|
str_s(_jit, jit_gpr_regno(reg), r0);
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
|
|
static void
|
|
sti_i(jit_state_t *_jit, jit_word_t i0, int32_t r0)
|
|
{
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i0);
|
|
str_i(_jit, jit_gpr_regno(reg), r0);
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
|
|
static void
|
|
sti_l(jit_state_t *_jit, jit_word_t i0, int32_t r0)
|
|
{
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
movi(_jit, jit_gpr_regno(reg), i0);
|
|
str_l(_jit, jit_gpr_regno(reg), r0);
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
|
|
static void
|
|
stxi_c(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1)
|
|
{
|
|
if (i0 >= 0 && i0 <= 4095) {
|
|
STRBI(_jit, r1, r0, i0);
|
|
} else if (i0 > -256 && i0 < 0) {
|
|
STURB(_jit, r1, r0, i0 & 0x1ff);
|
|
} else {
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
addi(_jit, jit_gpr_regno(reg), r0, i0);
|
|
str_c(_jit, jit_gpr_regno(reg), r1);
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
}
|
|
|
|
static void
|
|
stxi_s(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1)
|
|
{
|
|
ASSERT(!(i0 & 1));
|
|
if (i0 >= 0 && i0 <= 8191) {
|
|
STRHI(_jit, r1, r0, i0 >> 1);
|
|
} else if (i0 > -256 && i0 < 0) {
|
|
STURH(_jit, r1, r0, i0 & 0x1ff);
|
|
} else {
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
addi(_jit, jit_gpr_regno(reg), r0, i0);
|
|
str_s(_jit, jit_gpr_regno(reg), r1);
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
}
|
|
|
|
static void
|
|
stxi_i(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1)
|
|
{
|
|
ASSERT(!(i0 & 3));
|
|
if (i0 >= 0 && i0 <= 16383) {
|
|
STRWI(_jit, r1, r0, i0 >> 2);
|
|
} else if (i0 > -256 && i0 < 0) {
|
|
STURW(_jit, r1, r0, i0 & 0x1ff);
|
|
} else {
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
addi(_jit, jit_gpr_regno(reg), r0, i0);
|
|
str_i(_jit, jit_gpr_regno(reg), r1);
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
}
|
|
|
|
static void
|
|
stxi_l(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1)
|
|
{
|
|
ASSERT(!(i0 & 7));
|
|
if (i0 >= 0 && i0 <= 32767) {
|
|
STRI(_jit, r1, r0, i0 >> 3);
|
|
} else if (i0 > -256 && i0 < 0) {
|
|
STUR(_jit, r1, r0, i0 & 0x1ff);
|
|
} else {
|
|
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
addi(_jit, jit_gpr_regno(reg), r0, i0);
|
|
str_l(_jit, jit_gpr_regno(reg), r1);
|
|
unget_temp_gpr(_jit);
|
|
}
|
|
}
|
|
|
|
static jit_reloc_t
|
|
mov_addr(jit_state_t *_jit, int32_t r0)
|
|
{
|
|
return movi_from_pool(_jit, r0);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
beqi(jit_state_t *_jit, int32_t r0, jit_word_t i1)
|
|
{
|
|
if (i1 == 0) {
|
|
return CBZ(_jit, r0);
|
|
} else {
|
|
return bcci(_jit, BCC_EQ, r0, i1);
|
|
}
|
|
}
|
|
|
|
static jit_reloc_t
|
|
bnei(jit_state_t *_jit, int32_t r0, jit_word_t i1)
|
|
{
|
|
if (i1 == 0) {
|
|
return CBNZ(_jit, r0);
|
|
} else {
|
|
return bcci(_jit, BCC_NE, r0, i1);
|
|
}
|
|
}
|
|
|
|
static jit_reloc_t
|
|
jmp(jit_state_t *_jit)
|
|
{
|
|
return B(_jit);
|
|
}
|
|
|
|
static void
|
|
jmpi(jit_state_t *_jit, jit_word_t i0)
|
|
{
|
|
return jit_patch_there(_jit, jmp(_jit), (void*)i0);
|
|
}
|
|
|
|
static jit_reloc_t
|
|
call(jit_state_t *_jit)
|
|
{
|
|
return BL(_jit);
|
|
}
|
|
|
|
static void
|
|
calli(jit_state_t *_jit, jit_word_t i0)
|
|
{
|
|
return jit_patch_there(_jit, call(_jit), (void*)i0);
|
|
}
|
|
|
|
static void
|
|
ret(jit_state_t *_jit)
|
|
{
|
|
RET(_jit);
|
|
}
|
|
|
|
static void
|
|
retr(jit_state_t *_jit, int32_t r)
|
|
{
|
|
movr(_jit, jit_gpr_regno(_X0), r);
|
|
ret(_jit);
|
|
}
|
|
|
|
static void
|
|
reti(jit_state_t *_jit, int32_t i)
|
|
{
|
|
movi(_jit, jit_gpr_regno(_X0), i);
|
|
ret(_jit);
|
|
}
|
|
|
|
static void
|
|
retval_c(jit_state_t *_jit, int32_t r0)
|
|
{
|
|
extr_c(_jit, r0, jit_gpr_regno(_X0));
|
|
}
|
|
|
|
static void
|
|
retval_uc(jit_state_t *_jit, int32_t r0)
|
|
{
|
|
extr_uc(_jit, r0, jit_gpr_regno(_X0));
|
|
}
|
|
|
|
static void
|
|
retval_s(jit_state_t *_jit, int32_t r0)
|
|
{
|
|
extr_s(_jit, r0, jit_gpr_regno(_X0));
|
|
}
|
|
|
|
static void
|
|
retval_us(jit_state_t *_jit, int32_t r0)
|
|
{
|
|
extr_us(_jit, r0, jit_gpr_regno(_X0));
|
|
}
|
|
|
|
static void
|
|
retval_i(jit_state_t *_jit, int32_t r0)
|
|
{
|
|
extr_i(_jit, r0, jit_gpr_regno(_X0));
|
|
}
|
|
|
|
static void
|
|
retval_ui(jit_state_t *_jit, int32_t r0)
|
|
{
|
|
extr_ui(_jit, r0, jit_gpr_regno(_X0));
|
|
}
|
|
|
|
static void
|
|
retval_l(jit_state_t *_jit, int32_t r0)
|
|
{
|
|
movr(_jit, r0, jit_gpr_regno(_X0));
|
|
}
|