1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-05 11:40:20 +02:00
guile/lightening/aarch64-cpu.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));
}