mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-03 21:30:29 +02:00
* check/alu_rsb.ok, check/alu_rsb.tst: New files implementing tests for jit_rsb*. * check/Makefile.am, check/lightning.c, include/lightning.h, lib/jit_aarch64-cpu.c, lib/jit_aarch64-fpu.c, lib/jit_aarch64-sz.c, lib/jit_aarch64.c, lib/jit_alpha-cpu.c, lib/jit_alpha-fpu.c, lib/jit_alpha-sz.c, lib/jit_alpha.c, lib/jit_arm-cpu.c, lib/jit_arm-swf.c, lib/jit_arm-sz.c, lib/jit_arm-vfp.c, lib/jit_arm.c, lib/jit_hppa-cpu.c, lib/jit_hppa-fpu.c, lib/jit_hppa-sz.c, lib/jit_hppa.c, lib/jit_ia64-cpu.c, lib/jit_ia64-fpu.c, lib/jit_ia64-sz.c, lib/jit_ia64.c, lib/jit_mips-cpu.c, lib/jit_mips-fpu.c, lib/jit_mips-sz.c, lib/jit_mips.c, lib/jit_names.c, lib/jit_ppc-cpu.c, lib/jit_ppc-fpu.c, lib/jit_ppc-sz.c, lib/jit_ppc.c, lib/jit_s390x-cpu.c, lib/jit_s390x-fpu.c, lib/jit_s390x-sz.c, lib/jit_s390x.c, lib/jit_sparc-cpu.c, lib/jit_sparc-fpu.c, lib/jit_sparc-sz.c, lib/jit_sparc.c, lib/jit_x86-cpu.c, lib/jit_x86-sse.c, lib/jit_x86-sz.c, lib/jit_x86-x87.c, lib/jit_x86.c, lib/lightning.c: Implement jit_rsb*. This was a missing lightning 1.x interface, that on most backends is synthesized, but on a few backends (hppa and ia64), it can generate better code as on those there is, or the only instruction with an immediate is in "rsb" format (left operand).
2303 lines
67 KiB
C
2303 lines
67 KiB
C
/*
|
|
* Copyright (C) 2013 Free Software Foundation, Inc.
|
|
*
|
|
* This file is part of GNU lightning.
|
|
*
|
|
* GNU lightning is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU Lesser General Public License as published
|
|
* by the Free Software Foundation; either version 3, or (at your option)
|
|
* any later version.
|
|
*
|
|
* GNU lightning is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
|
* License for more details.
|
|
*
|
|
* Authors:
|
|
* Paulo Cesar Pereira de Andrade
|
|
*/
|
|
|
|
#if PROTO
|
|
typedef union {
|
|
/* aarch64-opc.c */
|
|
# define ui jit_uint32_t
|
|
# if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
/* cond2: condition in truly conditional-executed inst. */
|
|
struct { ui b: 4; } cond2;
|
|
/* nzcv: flag bit specifier, encoded in the "nzcv" field. */
|
|
struct { ui b: 4; } nzcv;
|
|
/* defgh: d:e:f:g:h bits in AdvSIMD modified immediate. */
|
|
struct { ui _: 5; ui b: 5; } defgh;
|
|
/* abc: a:b:c bits in AdvSIMD modified immediate. */
|
|
struct { ui _: 16; ui b: 3; } abc;
|
|
/* imm19: e.g. in CBZ. */
|
|
struct { ui _: 5; ui b: 19; } imm19;
|
|
/* immhi: e.g. in ADRP. */
|
|
struct { ui _: 5; ui b: 19; } immhi;
|
|
/* immlo: e.g. in ADRP. */
|
|
struct { ui _: 29; ui b: 2; } immlo;
|
|
/* size: in most AdvSIMD and floating-point instructions. */
|
|
struct { ui _: 22; ui b: 2; } size;
|
|
/* vldst_size: size field in the AdvSIMD load/store inst. */
|
|
struct { ui _: 10; ui b: 2; } vldst_size;
|
|
/* op: in AdvSIMD modified immediate instructions. */
|
|
struct { ui _: 29; ui b: 1; } op;
|
|
/* Q: in most AdvSIMD instructions. */
|
|
struct { ui _: 30; ui b: 1; } Q;
|
|
/* Rt: in load/store instructions. */
|
|
struct { ui b: 5; } Rt;
|
|
/* Rd: in many integer instructions. */
|
|
struct { ui b: 5; } Rd;
|
|
/* Rn: in many integer instructions. */
|
|
struct { ui _: 5; ui b: 5; } Rn;
|
|
/* Rt2: in load/store pair instructions. */
|
|
struct { ui _: 10; ui b: 5; } Rt2;
|
|
/* Ra: in fp instructions. */
|
|
struct { ui _: 10; ui b: 5; } Ra;
|
|
/* op2: in the system instructions. */
|
|
struct { ui _: 5; ui b: 3; } op2;
|
|
/* CRm: in the system instructions. */
|
|
struct { ui _: 8; ui b: 4; } CRm;
|
|
/* CRn: in the system instructions. */
|
|
struct { ui _: 12; ui b: 4; } CRn;
|
|
/* op1: in the system instructions. */
|
|
struct { ui _: 16; ui b: 3; } op1;
|
|
/* op0: in the system instructions. */
|
|
struct { ui _: 19; ui b: 2; } op0;
|
|
/* imm3: in add/sub extended reg instructions. */
|
|
struct { ui _: 10; ui b: 3; } imm3;
|
|
/* cond: condition flags as a source operand. */
|
|
struct { ui _: 12; ui b: 4; } cond;
|
|
/* opcode: in advsimd load/store instructions. */
|
|
struct { ui _: 12; ui b: 4; } opcode;
|
|
/* cmode: in advsimd modified immediate instructions. */
|
|
struct { ui _: 12; ui b: 4; } cmode;
|
|
/* asisdlso_opcode: opcode in advsimd ld/st single element. */
|
|
struct { ui _: 13; ui b: 3; } asisdlso_opcode;
|
|
/* len: in advsimd tbl/tbx instructions. */
|
|
struct { ui _: 13; ui b: 2; } len;
|
|
/* Rm: in ld/st reg offset and some integer inst. */
|
|
struct { ui _: 16; ui b: 5; } Rm;
|
|
/* Rs: in load/store exclusive instructions. */
|
|
struct { ui _: 16; ui b: 5; } Rs;
|
|
/* option: in ld/st reg offset + add/sub extended reg inst. */
|
|
struct { ui _: 13; ui b: 3; } option;
|
|
/* S: in load/store reg offset instructions. */
|
|
struct { ui _: 12; ui b: 1; } S;
|
|
/* hw: in move wide constant instructions. */
|
|
struct { ui _: 21; ui b: 2; } hw;
|
|
/* opc: in load/store reg offset instructions. */
|
|
struct { ui _: 22; ui b: 2; } opc;
|
|
/* opc1: in load/store reg offset instructions. */
|
|
struct { ui _: 23; ui b: 1; } opc1;
|
|
/* shift: in add/sub reg/imm shifted instructions. */
|
|
struct { ui _: 22; ui b: 2; } shift;
|
|
/* type: floating point type field in fp data inst. */
|
|
struct { ui _: 22; ui b: 2; } type;
|
|
/* ldst_size: size field in ld/st reg offset inst. */
|
|
struct { ui _: 30; ui b: 2; } ldst_size;
|
|
/* imm6: in add/sub reg shifted instructions. */
|
|
struct { ui _: 10; ui b: 6; } imm6;
|
|
/* imm4: in advsimd ext and advsimd ins instructions. */
|
|
struct { ui _: 11; ui b: 4; } imm4;
|
|
/* imm5: in conditional compare (immediate) instructions. */
|
|
struct { ui _: 16; ui b: 5; } imm5;
|
|
/* imm7: in load/store pair pre/post index instructions. */
|
|
struct { ui _: 15; ui b: 7; } imm7;
|
|
/* imm8: in floating-point scalar move immediate inst. */
|
|
struct { ui _: 13; ui b: 8; } imm8;
|
|
/* imm9: in load/store pre/post index instructions. */
|
|
struct { ui _: 12; ui b: 9; } imm9;
|
|
/* imm12: in ld/st unsigned imm or add/sub shifted inst. */
|
|
struct { ui _: 10; ui b: 12; } imm12;
|
|
/* imm14: in test bit and branch instructions. */
|
|
struct { ui _: 5; ui b: 14; } imm14;
|
|
/* imm16: in exception instructions. */
|
|
struct { ui _: 5; ui b: 16; } imm16;
|
|
/* imm26: in unconditional branch instructions. */
|
|
struct { ui b: 26; } imm26;
|
|
/* imms: in bitfield and logical immediate instructions. */
|
|
struct { ui _: 10; ui b: 6; } imms;
|
|
/* immr: in bitfield and logical immediate instructions. */
|
|
struct { ui _: 16; ui b: 6; } immr;
|
|
/* immb: in advsimd shift by immediate instructions. */
|
|
struct { ui _: 16; ui b: 3; } immb;
|
|
/* immh: in advsimd shift by immediate instructions. */
|
|
struct { ui _: 19; ui b: 4; } immh;
|
|
/* N: in logical (immediate) instructions. */
|
|
struct { ui _: 22; ui b: 1; } N;
|
|
/* index: in ld/st inst deciding the pre/post-index. */
|
|
struct { ui _: 11; ui b: 1; } index;
|
|
/* index2: in ld/st pair inst deciding the pre/post-index. */
|
|
struct { ui _: 24; ui b: 1; } index2;
|
|
/* sf: in integer data processing instructions. */
|
|
struct { ui _: 31; ui b: 1; } sf;
|
|
/* H: in advsimd scalar x indexed element instructions. */
|
|
struct { ui _: 11; ui b: 1; } H;
|
|
/* L: in advsimd scalar x indexed element instructions. */
|
|
struct { ui _: 21; ui b: 1; } L;
|
|
/* M: in advsimd scalar x indexed element instructions. */
|
|
struct { ui _: 20; ui b: 1; } M;
|
|
/* b5: in the test bit and branch instructions. */
|
|
struct { ui _: 31; ui b: 1; } b5;
|
|
/* b40: in the test bit and branch instructions. */
|
|
struct { ui _: 19; ui b: 5; } b40;
|
|
/* scale: in the fixed-point scalar to fp converting inst. */
|
|
struct { ui _: 10; ui b: 6; } scale;
|
|
# else
|
|
struct { ui _: 28; ui b: 4; } cond2;
|
|
struct { ui _: 28; ui b: 4; } nzcv;
|
|
struct { ui _: 22; ui b: 5; } defgh;
|
|
struct { ui _: 13; ui b: 3; } abc;
|
|
struct { ui _: 8; ui b: 19; } imm19;
|
|
struct { ui _: 8; ui b: 19; } immhi;
|
|
struct { ui _: 1; ui b: 29; } immlo;
|
|
struct { ui _: 8; ui b: 2; } size;
|
|
struct { ui _: 20; ui b: 2; } vldst_size;
|
|
struct { ui _: 2; ui b: 1; } op;
|
|
struct { ui _: 1; ui b: 1; } Q;
|
|
struct { ui _: 27; ui b: 1; } Rt;
|
|
struct { ui _: 27; ui b: 1; } Rd;
|
|
struct { ui _: 22; ui b: 5; } Rn;
|
|
struct { ui _: 17; ui b: 5; } Rt2;
|
|
struct { ui _: 17; ui b: 5; } Ra;
|
|
struct { ui _: 24; ui b: 3; } op2;
|
|
struct { ui _: 20; ui b: 4; } CRm;
|
|
struct { ui _: 16; ui b: 4; } CRn;
|
|
struct { ui _: 13; ui b: 3; } op1;
|
|
struct { ui _: 11; ui b: 2; } op0;
|
|
struct { ui _: 19; ui b: 3; } imm3;
|
|
struct { ui _: 16; ui b: 4; } cond;
|
|
struct { ui _: 16; ui b: 4; } opcode;
|
|
struct { ui _: 16; ui b: 4; } cmode;
|
|
struct { ui _: 16; ui b: 3; } asisdlso_opcode;
|
|
struct { ui _: 17; ui b: 2; } len;
|
|
struct { ui _: 11; ui b: 5; } Rm;
|
|
struct { ui _: 11; ui b: 5; } Rs;
|
|
struct { ui _: 16; ui b: 3; } option;
|
|
struct { ui _: 19; ui b: 1; } S;
|
|
struct { ui _: 9; ui b: 2; } hw;
|
|
struct { ui _: 8; ui b: 2; } opc;
|
|
struct { ui _: 8; ui b: 1; } opc1;
|
|
struct { ui _: 8; ui b: 2; } shift;
|
|
struct { ui _: 8; ui b: 2; } type;
|
|
struct { ui b: 2; } ldst_size;
|
|
struct { ui _: 16; ui b: 6; } imm6;
|
|
struct { ui _: 17; ui b: 4; } imm4;
|
|
struct { ui _: 11; ui b: 5; } imm5;
|
|
struct { ui _: 10; ui b: 7; } imm7;
|
|
struct { ui _: 11; ui b: 8; } imm8;
|
|
struct { ui _: 11; ui b: 9; } imm9;
|
|
struct { ui _: 10; ui b: 12; } imm12;
|
|
struct { ui _: 13; ui b: 14; } imm14;
|
|
struct { ui _: 11; ui b: 16; } imm16;
|
|
struct { ui _: 6; ui b: 26; } imm26;
|
|
struct { ui _: 16; ui b: 6; } imms;
|
|
struct { ui _: 10; ui b: 6; } immr;
|
|
struct { ui _: 13; ui b: 3; } immb;
|
|
struct { ui _: 9; ui b: 4; } immh;
|
|
struct { ui _: 9; ui b: 1; } N;
|
|
struct { ui _: 20; ui b: 1; } index;
|
|
struct { ui _: 7; ui b: 1; } index2;
|
|
struct { ui b: 1; } sf;
|
|
struct { ui _: 20; ui b: 1; } H;
|
|
struct { ui _: 10; ui b: 1; } L;
|
|
struct { ui _: 11; ui b: 1; } M;
|
|
struct { ui b: 1; } b5;
|
|
struct { ui _: 8; ui b: 5; } b40;
|
|
struct { ui _: 16; ui b: 6; } scale;
|
|
# endif
|
|
jit_int32_t w;
|
|
# undef ui
|
|
} instr_t;
|
|
# define stack_framesize 160
|
|
# define ii(i) *_jit->pc.ui++ = i
|
|
# define ldxi(r0,r1,i0) ldxi_l(r0,r1,i0)
|
|
# define stxi(i0,r0,r1) stxi_l(i0,r0,r1)
|
|
# define FP_REGNO 0x1d
|
|
# define LR_REGNO 0x1e
|
|
# define SP_REGNO 0x1f
|
|
# define XZR_REGNO 0x1f
|
|
# define WZR_REGNO XZR_REGNO
|
|
# define LSL_12 0x00400000
|
|
# define MOVI_LSL_16 0x00200000
|
|
# define MOVI_LSL_32 0x00400000
|
|
# define MOVI_LSL_48 0x00600000
|
|
# define XS 0x80000000 /* Wn -> Xn */
|
|
# define DS 0x00400000 /* Sn -> Dn */
|
|
# define CC_NE 0x0
|
|
# define CC_EQ 0x1
|
|
# define CC_CC 0x2
|
|
# define CC_LO CC_CC
|
|
# define CC_CS 0x3
|
|
# define CC_HS CC_CS
|
|
# define CC_PL 0x4
|
|
# define CC_MI 0x5
|
|
# define CC_VC 0x6
|
|
# define CC_VS 0x7
|
|
# define CC_LS 0x8
|
|
# define CC_HI 0x9
|
|
# define CC_LT 0xa
|
|
# define CC_GE 0xb
|
|
# define CC_LE 0xc
|
|
# define CC_GT 0xd
|
|
# define CC_NV 0xe
|
|
# define CC_AL 0xf
|
|
/* Branches need inverted condition */
|
|
# define BCC_EQ 0x0
|
|
# define BCC_NE 0x1
|
|
# define BCC_CS 0x2
|
|
# define BCC_HS BCC_CS
|
|
# define BCC_CC 0x3
|
|
# define BCC_LO BCC_CC
|
|
# define BCC_MI 0x4
|
|
# define BCC_PL 0x5
|
|
# define BCC_VS 0x6
|
|
# define BCC_VC 0x7
|
|
# define BCC_HI 0x8
|
|
# define BCC_LS 0x9
|
|
# define BCC_GE 0xa
|
|
# define BCC_LT 0xb
|
|
# define BCC_GT 0xc
|
|
# define BCC_LE 0xd
|
|
# define BCC_AL 0xe
|
|
# define BCC_NV 0xf
|
|
/* adapted and cut down to only tested and required by lightning,
|
|
* from data in binutils/aarch64-tbl.h */
|
|
# define A64_ADCS 0x3a000000
|
|
# define A64_SBCS 0x7a000000
|
|
# define A64_ADDI 0x11000000
|
|
# define A64_ADDSI 0xb1000000
|
|
# define A64_SUBI 0x51000000
|
|
# define A64_SUBSI 0x71000000
|
|
# define A64_ADD 0x0b000000
|
|
# define A64_ADDS 0x2b000000
|
|
# define A64_SUB 0x4b000000
|
|
# define A64_NEG 0x4b0003e0
|
|
# define A64_SUBS 0x6b000000
|
|
# define A64_CMP 0x6b00001f
|
|
# define A64_SBFM 0x93400000
|
|
# define A64_UBFM 0x53400000
|
|
# define A64_UBFX 0x53000000
|
|
# define A64_B 0x14000000
|
|
# define A64_BL 0x94000000
|
|
# define A64_BR 0xd61f0000
|
|
# define A64_BLR 0xd63f0000
|
|
# define A64_RET 0xd65f0000
|
|
# define A64_CBZ 0x34000000
|
|
# define A64_CBNZ 0x35000000
|
|
# define A64_B_C 0x54000000
|
|
# define A64_CSINC 0x1a800400
|
|
# define A64_REV 0xdac00c00
|
|
# define A64_UDIV 0x1ac00800
|
|
# define A64_SDIV 0x1ac00c00
|
|
# define A64_LSL 0x1ac02000
|
|
# define A64_LSR 0x1ac02400
|
|
# define A64_ASR 0x1ac02800
|
|
# define A64_MUL 0x1b007c00
|
|
# define A64_SMULL 0x9b207c00
|
|
# define A64_SMULH 0x9b407c00
|
|
# define A64_UMULL 0x9ba07c00
|
|
# define A64_UMULH 0x9bc07c00
|
|
# define A64_STRBI 0x39000000
|
|
# define A64_LDRBI 0x39400000
|
|
# define A64_LDRSBI 0x39800000
|
|
# define A64_STRI 0xf9000000
|
|
# define A64_LDRI 0xf9400000
|
|
# define A64_STRHI 0x79000000
|
|
# define A64_LDRHI 0x79400000
|
|
# define A64_LDRSHI 0x79800000
|
|
# define A64_STRWI 0xb9000000
|
|
# define A64_LDRWI 0xb9400000
|
|
# define A64_LDRSWI 0xb9800000
|
|
# define A64_STRB 0x38206800
|
|
# define A64_LDRB 0x38606800
|
|
# define A64_LDRSB 0x38e06800
|
|
# define A64_STR 0xf8206800
|
|
# define A64_LDR 0xf8606800
|
|
# define A64_STRH 0x78206800
|
|
# define A64_LDRH 0x78606800
|
|
# define A64_LDRSH 0x78a06800
|
|
# define A64_STRW 0xb8206800
|
|
# define A64_LDRW 0xb8606800
|
|
# define A64_LDRSW 0xb8a06800
|
|
# define A64_STURB 0x38000000
|
|
# define A64_LDURB 0x38400000
|
|
# define A64_LDURSB 0x38800000
|
|
# define A64_STUR 0xf8000000
|
|
# define A64_LDUR 0xf8400000
|
|
# define A64_STURH 0x78000000
|
|
# define A64_LDURH 0x78400000
|
|
# define A64_LDURSH 0x78800000
|
|
# define A64_STURW 0xb8000000
|
|
# define A64_LDURW 0xb8400000
|
|
# define A64_LDURSW 0xb8800000
|
|
# define A64_STP 0x29000000
|
|
# define A64_LDP 0x29400000
|
|
# define A64_STP_POS 0x29800000
|
|
# define A64_LDP_PRE 0x28c00000
|
|
# define A64_ANDI 0x12400000
|
|
# define A64_ORRI 0x32400000
|
|
# define A64_EORI 0x52400000
|
|
# define A64_ANDSI 0x72000000
|
|
# define A64_AND 0x0a000000
|
|
# define A64_ORR 0x2a000000
|
|
# define A64_MOV 0x2a0003e0 /* AKA orr Rd,xzr,Rm */
|
|
# define A64_MVN 0x2a2003e0
|
|
# define A64_UXTW 0x2a0003e0 /* AKA MOV */
|
|
# define A64_EOR 0x4a000000
|
|
# define A64_ANDS 0x6a000000
|
|
# define A64_MOVN 0x12800000
|
|
# define A64_MOVZ 0x52800000
|
|
# define A64_MOVK 0x72800000
|
|
# define SBFM(Rd,Rn,ImmR,ImmS) oxxrs(A64_SBFM|XS,Rd,Rn,ImmR,ImmS)
|
|
# define UBFM(Rd,Rn,ImmR,ImmS) oxxrs(A64_UBFM|XS,Rd,Rn,ImmR,ImmS)
|
|
# define UBFX(Rd,Rn,ImmR,ImmS) oxxrs(A64_UBFX,Rd,Rn,ImmR,ImmS)
|
|
# define CMP(Rn,Rm) oxx_(A64_CMP|XS,Rn,Rm)
|
|
# define CMPI(Rn,Imm12) oxxi(A64_SUBSI|XS,XZR_REGNO,Rn,Imm12)
|
|
# define CMPI_12(Rn,Imm12) oxxi(A64_SUBSI|XS|LSL_12,XZR_REGNO,Rn,Imm12)
|
|
# define CMNI(Rn,Imm12) oxxi(A64_ADDSI|XS,XZR_REGNO,Rn,Imm12)
|
|
# define CMNI_12(Rn,Imm12) oxxi(A64_ADDSI|XS|LSL_12,XZR_REGNO,Rn,Imm12)
|
|
# define CSINC(Rd,Rn,Rm,Cc) oxxxc(A64_CSINC|XS,Rd,Rn,Rm,Cc)
|
|
# define TST(Rn,Rm) oxxx(A64_ANDS|XS,XZR_REGNO,Rn,Rm)
|
|
/* actually should use oxxrs but logical_immediate returns proper encoding */
|
|
# define TSTI(Rn,Imm12) oxxi(A64_ANDSI,XZR_REGNO,Rn,Imm12)
|
|
# define MOV(Rd,Rm) ox_x(A64_MOV|XS,Rd,Rm)
|
|
# define MVN(Rd,Rm) ox_x(A64_MVN|XS,Rd,Rm)
|
|
# define NEG(Rd,Rm) ox_x(A64_NEG|XS,Rd,Rm)
|
|
# define MOVN(Rd,Imm16) ox_h(A64_MOVN|XS,Rd,Imm16)
|
|
# define MOVN_16(Rd,Imm16) ox_h(A64_MOVN|XS|MOVI_LSL_16,Rd,Imm16)
|
|
# define MOVN_32(Rd,Imm16) ox_h(A64_MOVN|XS|MOVI_LSL_32,Rd,Imm16)
|
|
# define MOVN_48(Rd,Imm16) ox_h(A64_MOVN|XS|MOVI_LSL_48,Rd,Imm16)
|
|
# define MOVZ(Rd,Imm16) ox_h(A64_MOVZ|XS,Rd,Imm16)
|
|
# define MOVZ_16(Rd,Imm16) ox_h(A64_MOVZ|XS|MOVI_LSL_16,Rd,Imm16)
|
|
# define MOVZ_32(Rd,Imm16) ox_h(A64_MOVZ|XS|MOVI_LSL_32,Rd,Imm16)
|
|
# define MOVZ_48(Rd,Imm16) ox_h(A64_MOVZ|XS|MOVI_LSL_48,Rd,Imm16)
|
|
# define MOVK(Rd,Imm16) ox_h(A64_MOVK|XS,Rd,Imm16)
|
|
# define MOVK_16(Rd,Imm16) ox_h(A64_MOVK|XS|MOVI_LSL_16,Rd,Imm16)
|
|
# define MOVK_32(Rd,Imm16) ox_h(A64_MOVK|XS|MOVI_LSL_32,Rd,Imm16)
|
|
# define MOVK_48(Rd,Imm16) ox_h(A64_MOVK|XS|MOVI_LSL_48,Rd,Imm16)
|
|
# define ADD(Rd,Rn,Rm) oxxx(A64_ADD|XS,Rd,Rn,Rm)
|
|
# define ADDI(Rd,Rn,Imm12) oxxi(A64_ADDI|XS,Rd,Rn,Imm12)
|
|
# define ADDI_12(Rd,Rn,Imm12) oxxi(A64_ADDI|XS|LSL_12,Rd,Rn,Imm12)
|
|
# define MOV_XSP(Rd,Rn) ADDI(Rd,Rn,0)
|
|
# define ADDS(Rd,Rn,Rm) oxxx(A64_ADDS|XS,Rd,Rn,Rm)
|
|
# define ADDSI(Rd,Rn,Imm12) oxxi(A64_ADDSI|XS,Rd,Rn,Imm12)
|
|
# define ADDSI_12(Rd,Rn,Imm12) oxxi(A64_ADDSI|XS|LSL_12,Rd,Rn,Imm12)
|
|
# define ADCS(Rd,Rn,Rm) oxxx(A64_ADCS|XS,Rd,Rn,Rm)
|
|
# define SUB(Rd,Rn,Rm) oxxx(A64_SUB|XS,Rd,Rn,Rm)
|
|
# define SUBI(Rd,Rn,Imm12) oxxi(A64_SUBI|XS,Rd,Rn,Imm12)
|
|
# define SUBI_12(Rd,Rn,Imm12) oxxi(A64_SUBI|XS|LSL_12,Rd,Rn,Imm12)
|
|
# define SUBS(Rd,Rn,Rm) oxxx(A64_SUBS|XS,Rd,Rn,Rm)
|
|
# define SUBSI(Rd,Rn,Imm12) oxxi(A64_SUBSI|XS,Rd,Rn,Imm12)
|
|
# define SUBSI_12(Rd,Rn,Imm12) oxxi(A64_SUBSI|XS|LSL_12,Rd,Rn,Imm12)
|
|
# define SBCS(Rd,Rn,Rm) oxxx(A64_SBCS|XS,Rd,Rn,Rm)
|
|
# define MUL(Rd,Rn,Rm) oxxx(A64_MUL|XS,Rd,Rn,Rm)
|
|
# define SMULL(Rd,Rn,Rm) oxxx(A64_SMULL,Rd,Rn,Rm)
|
|
# define SMULH(Rd,Rn,Rm) oxxx(A64_SMULH,Rd,Rn,Rm)
|
|
# define UMULL(Rd,Rn,Rm) oxxx(A64_UMULL,Rd,Rn,Rm)
|
|
# define UMULH(Rd,Rn,Rm) oxxx(A64_UMULH,Rd,Rn,Rm)
|
|
# define SDIV(Rd,Rn,Rm) oxxx(A64_SDIV|XS,Rd,Rn,Rm)
|
|
# define UDIV(Rd,Rn,Rm) oxxx(A64_UDIV|XS,Rd,Rn,Rm)
|
|
# define LSL(Rd,Rn,Rm) oxxx(A64_LSL|XS,Rd,Rn,Rm)
|
|
# define LSLI(r0,r1,i0) UBFM(r0,r1,(64-i0)&63,63-i0)
|
|
# define ASR(Rd,Rn,Rm) oxxx(A64_ASR|XS,Rd,Rn,Rm)
|
|
# define ASRI(r0,r1,i0) SBFM(r0,r1,i0,63)
|
|
# define LSR(Rd,Rn,Rm) oxxx(A64_LSR|XS,Rd,Rn,Rm)
|
|
# define LSRI(r0,r1,i0) UBFM(r0,r1,i0,63)
|
|
# define AND(Rd,Rn,Rm) oxxx(A64_AND|XS,Rd,Rn,Rm)
|
|
/* actually should use oxxrs but logical_immediate returns proper encoding */
|
|
# define ANDI(Rd,Rn,Imm12) oxxi(A64_ANDI|XS,Rd,Rn,Imm12)
|
|
# define ORR(Rd,Rn,Rm) oxxx(A64_ORR|XS,Rd,Rn,Rm)
|
|
/* actually should use oxxrs but logical_immediate returns proper encoding */
|
|
# define ORRI(Rd,Rn,Imm12) oxxi(A64_ORRI|XS,Rd,Rn,Imm12)
|
|
# define EOR(Rd,Rn,Rm) oxxx(A64_EOR|XS,Rd,Rn,Rm)
|
|
/* actually should use oxxrs but logical_immediate returns proper encoding */
|
|
# define EORI(Rd,Rn,Imm12) oxxi(A64_EORI|XS,Rd,Rn,Imm12)
|
|
# define SXTB(Rd,Rn) SBFM(Rd,Rn,0,7)
|
|
# define SXTH(Rd,Rn) SBFM(Rd,Rn,0,15)
|
|
# define SXTW(Rd,Rn) SBFM(Rd,Rn,0,31)
|
|
# define UXTB(Rd,Rn) UBFX(Rd,Rn,0,7)
|
|
# define UXTH(Rd,Rn) UBFX(Rd,Rn,0,15)
|
|
# define UXTW(Rd,Rm) ox_x(A64_UXTW,Rd,Rm)
|
|
# define REV(Rd,Rn) o_xx(A64_REV,Rd,Rn)
|
|
# define LDRSB(Rt,Rn,Rm) oxxx(A64_LDRSB,Rt,Rn,Rm)
|
|
# define LDRSBI(Rt,Rn,Imm12) oxxi(A64_LDRSBI,Rt,Rn,Imm12)
|
|
# define LDURSB(Rt,Rn,Imm9) oxx9(A64_LDURSB,Rt,Rn,Imm9)
|
|
# define LDRB(Rt,Rn,Rm) oxxx(A64_LDRB,Rt,Rn,Rm)
|
|
# define LDRBI(Rt,Rn,Imm12) oxxi(A64_LDRBI,Rt,Rn,Imm12)
|
|
# define LDURB(Rt,Rn,Imm9) oxx9(A64_LDURB,Rt,Rn,Imm9)
|
|
# define LDRSH(Rt,Rn,Rm) oxxx(A64_LDRSH,Rt,Rn,Rm)
|
|
# define LDRSHI(Rt,Rn,Imm12) oxxi(A64_LDRSHI,Rt,Rn,Imm12)
|
|
# define LDURSH(Rt,Rn,Imm9) oxx9(A64_LDURSH,Rt,Rn,Imm9)
|
|
# define LDRH(Rt,Rn,Rm) oxxx(A64_LDRH,Rt,Rn,Rm)
|
|
# define LDRHI(Rt,Rn,Imm12) oxxi(A64_LDRHI,Rt,Rn,Imm12)
|
|
# define LDURH(Rt,Rn,Imm9) oxx9(A64_LDURH,Rt,Rn,Imm9)
|
|
# define LDRSW(Rt,Rn,Rm) oxxx(A64_LDRSW,Rt,Rn,Rm)
|
|
# define LDRSWI(Rt,Rn,Imm12) oxxi(A64_LDRSWI,Rt,Rn,Imm12)
|
|
# define LDURSW(Rt,Rn,Imm9) oxx9(A64_LDURSW,Rt,Rn,Imm9)
|
|
# define LDRW(Rt,Rn,Rm) oxxx(A64_LDRW,Rt,Rn,Rm)
|
|
# define LDRWI(Rt,Rn,Imm12) oxxi(A64_LDRWI,Rt,Rn,Imm12)
|
|
# define LDURW(Rt,Rn,Imm9) oxx9(A64_LDURW,Rt,Rn,Imm9)
|
|
# define LDR(Rt,Rn,Rm) oxxx(A64_LDR,Rt,Rn,Rm)
|
|
# define LDRI(Rt,Rn,Imm12) oxxi(A64_LDRI,Rt,Rn,Imm12)
|
|
# define LDUR(Rt,Rn,Imm9) oxx9(A64_LDUR,Rt,Rn,Imm9)
|
|
# define STRB(Rt,Rn,Rm) oxxx(A64_STRB,Rt,Rn,Rm)
|
|
# define STRBI(Rt,Rn,Imm12) oxxi(A64_STRBI,Rt,Rn,Imm12)
|
|
# define STURB(Rt,Rn,Imm9) oxx9(A64_STURB,Rt,Rn,Imm9)
|
|
# define STRH(Rt,Rn,Rm) oxxx(A64_STRH,Rt,Rn,Rm)
|
|
# define STRHI(Rt,Rn,Imm12) oxxi(A64_STRHI,Rt,Rn,Imm12)
|
|
# define STURH(Rt,Rn,Imm9) oxx9(A64_STURH,Rt,Rn,Imm9)
|
|
# define STRW(Rt,Rn,Rm) oxxx(A64_STRW,Rt,Rn,Rm)
|
|
# define STRWI(Rt,Rn,Imm12) oxxi(A64_STRWI,Rt,Rn,Imm12)
|
|
# define STURW(Rt,Rn,Imm9) oxx9(A64_STURW,Rt,Rn,Imm9)
|
|
# define STR(Rt,Rn,Rm) oxxx(A64_STR,Rt,Rn,Rm)
|
|
# define STRI(Rt,Rn,Imm12) oxxi(A64_STRI,Rt,Rn,Imm12)
|
|
# define STUR(Rt,Rn,Imm9) oxx9(A64_STUR,Rt,Rn,Imm9)
|
|
# define LDPI(Rt,Rt2,Rn,Simm7) oxxx7(A64_LDP|XS,Rt,Rt2,Rn,Simm7)
|
|
# define STPI(Rt,Rt2,Rn,Simm7) oxxx7(A64_STP|XS,Rt,Rt2,Rn,Simm7)
|
|
# define LDPI_PRE(Rt,Rt2,Rn,Simm7) oxxx7(A64_LDP_PRE|XS,Rt,Rt2,Rn,Simm7)
|
|
# define STPI_POS(Rt,Rt2,Rn,Simm7) oxxx7(A64_STP_POS|XS,Rt,Rt2,Rn,Simm7)
|
|
# define CSET(Rd,Cc) CSINC(Rd,XZR_REGNO,XZR_REGNO,Cc)
|
|
# define B(Simm26) o26(A64_B,Simm26)
|
|
# define BL(Simm26) o26(A64_BL,Simm26)
|
|
# define BR(Rn) o_x_(A64_BR,Rn)
|
|
# define BLR(Rn) o_x_(A64_BLR,Rn)
|
|
# define RET() o_x_(A64_RET,LR_REGNO)
|
|
# define B_C(Cc,Simm19) oc19(A64_B_C,Cc,Simm19)
|
|
# define CBZ(Rd,Simm19) ox19(A64_CBZ|XS,Rd,Simm19)
|
|
# define CBNZ(Rd,Simm19) ox19(A64_CBNZ|XS,Rd,Simm19)
|
|
# define NOP() ii(0xd503201f)
|
|
static jit_int32_t logical_immediate(jit_word_t);
|
|
# define oxxx(Op,Rd,Rn,Rm) _oxxx(_jit,Op,Rd,Rn,Rm)
|
|
static void _oxxx(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t);
|
|
# define oxxi(Op,Rd,Rn,Imm12) _oxxi(_jit,Op,Rd,Rn,Imm12)
|
|
static void _oxxi(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t);
|
|
# define oxx9(Op,Rd,Rn,Imm9) _oxx9(_jit,Op,Rd,Rn,Imm9)
|
|
static void _oxx9(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t);
|
|
# define ox19(Op,Rd,Simm19) _ox19(_jit,Op,Rd,Simm19)
|
|
static void _ox19(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t);
|
|
# define oc19(Op,Cc,Simm19) _oc19(_jit,Op,Cc,Simm19)
|
|
static void _oc19(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t);
|
|
# define o26(Op,Simm26) _o26(_jit,Op,Simm26)
|
|
static void _oc26(jit_state_t*,jit_int32_t,jit_int32_t);
|
|
# define ox_x(Op,Rd,Rn) _ox_x(_jit,Op,Rd,Rn)
|
|
static void _ox_x(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t);
|
|
# define o_xx(Op,Rd,Rn) _o_xx(_jit,Op,Rd,Rn)
|
|
static void _o_xx(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t);
|
|
# define oxx_(Op,Rn,Rm) _oxx_(_jit,Op,Rn,Rm)
|
|
static void _oxx_(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t);
|
|
# define o_x_(Op,Rn) _o_x_(_jit,Op,Rn)
|
|
static void _o_x_(jit_state_t*,jit_int32_t,jit_int32_t);
|
|
# define ox_h(Op,Rd,Imm16) _ox_h(_jit,Op,Rd,Imm16)
|
|
static void _ox_h(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t);
|
|
# define oxxrs(Op,Rd,Rn,R,S) _oxxrs(_jit,Op,Rd,Rn,R,S)
|
|
static void _oxxrs(jit_state_t*,jit_int32_t,jit_int32_t,
|
|
jit_int32_t,jit_int32_t,jit_int32_t);
|
|
# define oxxxc(Op,Rd,Rn,Rm,Cc) _oxxxc(_jit,Op,Rd,Rn,Rm,Cc)
|
|
static void _oxxxc(jit_state_t*,jit_int32_t,jit_int32_t,
|
|
jit_int32_t,jit_int32_t,jit_int32_t);
|
|
# define oxxx7(Op,Rt,Rt2,Rn,Simm7) _oxxx7(_jit,Op,Rt,Rt2,Rn,Simm7)
|
|
static void _oxxx7(jit_state_t*,jit_int32_t,
|
|
jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t);
|
|
# define nop(i0) _nop(_jit,i0)
|
|
static void _nop(jit_state_t*,jit_int32_t);
|
|
# define addr(r0,r1,r2) ADD(r0,r1,r2)
|
|
# define addi(r0,r1,i0) _addi(_jit,r0,r1,i0)
|
|
static void _addi(jit_state_t*,jit_int32_t,jit_int32_t,jit_word_t);
|
|
# define addcr(r0,r1,r2) ADDS(r0,r1,r2)
|
|
# define addci(r0,r1,i0) _addci(_jit,r0,r1,i0)
|
|
static void _addci(jit_state_t*,jit_int32_t,jit_int32_t,jit_word_t);
|
|
# define addxr(r0,r1,r2) ADCS(r0,r1,r2)
|
|
# define addxi(r0,r1,i0) _addxi(_jit,r0,r1,i0)
|
|
static void _addxi(jit_state_t*,jit_int32_t,jit_int32_t,jit_word_t);
|
|
# define subr(r0,r1,r2) SUB(r0,r1,r2)
|
|
# define subi(r0,r1,i0) _subi(_jit,r0,r1,i0)
|
|
static void _subi(jit_state_t*,jit_int32_t,jit_int32_t,jit_word_t);
|
|
# define subcr(r0,r1,r2) SUBS(r0,r1,r2)
|
|
# define subci(r0,r1,i0) _subci(_jit,r0,r1,i0)
|
|
static void _subci(jit_state_t*,jit_int32_t,jit_int32_t,jit_word_t);
|
|
# define subxr(r0,r1,r2) SBCS(r0,r1,r2)
|
|
# define subxi(r0,r1,i0) _subxi(_jit,r0,r1,i0)
|
|
static void _subxi(jit_state_t*,jit_int32_t,jit_int32_t,jit_word_t);
|
|
# define rsbi(r0, r1, i0) _rsbi(_jit, r0, r1, i0)
|
|
static void _rsbi(jit_state_t*,jit_int32_t,jit_int32_t,jit_word_t);
|
|
# define mulr(r0,r1,r2) MUL(r0,r1,r2)
|
|
# define muli(r0,r1,i0) _muli(_jit,r0,r1,i0)
|
|
static void _muli(jit_state_t*,jit_int32_t,jit_int32_t,jit_word_t);
|
|
# define qmulr(r0,r1,r2,r3) _qmulr(_jit,r0,r1,r2,r3)
|
|
static void _qmulr(jit_state_t*,jit_int32_t,
|
|
jit_int32_t,jit_int32_t,jit_int32_t);
|
|
# define qmuli(r0,r1,r2,i0) _qmuli(_jit,r0,r1,r2,i0)
|
|
static void _qmuli(jit_state_t*,jit_int32_t,
|
|
jit_int32_t,jit_int32_t,jit_word_t);
|
|
# define qmulr_u(r0,r1,r2,r3) _qmulr_u(_jit,r0,r1,r2,r3)
|
|
static void _qmulr_u(jit_state_t*,jit_int32_t,
|
|
jit_int32_t,jit_int32_t,jit_int32_t);
|
|
# define qmuli_u(r0,r1,r2,i0) _qmuli_u(_jit,r0,r1,r2,i0)
|
|
static void _qmuli_u(jit_state_t*,jit_int32_t,
|
|
jit_int32_t,jit_int32_t,jit_word_t);
|
|
# define divr(r0,r1,r2) SDIV(r0,r1,r2)
|
|
# define divi(r0,r1,i0) _divi(_jit,r0,r1,i0)
|
|
static void _divi(jit_state_t*,jit_int32_t,jit_int32_t,jit_word_t);
|
|
# define divr_u(r0,r1,r2) UDIV(r0,r1,r2)
|
|
# define divi_u(r0,r1,i0) _divi_u(_jit,r0,r1,i0)
|
|
static void _divi_u(jit_state_t*,jit_int32_t,jit_int32_t,jit_word_t);
|
|
# define qdivr(r0,r1,r2,r3) _iqdivr(_jit,1,r0,r1,r2,r3)
|
|
# define qdivr_u(r0,r1,r2,r3) _iqdivr(_jit,0,r0,r1,r2,r3)
|
|
static void _iqdivr(jit_state_t*,jit_bool_t,
|
|
jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t);
|
|
# define qdivi(r0,r1,r2,i0) _qdivi(_jit,r0,r1,r2,i0)
|
|
static void _qdivi(jit_state_t*,jit_int32_t,
|
|
jit_int32_t,jit_int32_t,jit_word_t);
|
|
# define qdivi_u(r0,r1,r2,i0) _qdivi_u(_jit,r0,r1,r2,i0)
|
|
static void _qdivi_u(jit_state_t*,jit_int32_t,
|
|
jit_int32_t,jit_int32_t,jit_word_t);
|
|
# define remr(r0,r1,r2) _remr(_jit,r0,r1,r2)
|
|
static void _remr(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t);
|
|
# define remi(r0,r1,i0) _remi(_jit,r0,r1,i0)
|
|
static void _remi(jit_state_t*,jit_int32_t,jit_int32_t,jit_word_t);
|
|
# define remr_u(r0,r1,r2) _remr_u(_jit,r0,r1,r2)
|
|
static void _remr_u(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t);
|
|
# define remi_u(r0,r1,i0) _remi_u(_jit,r0,r1,i0)
|
|
static void _remi_u(jit_state_t*,jit_int32_t,jit_int32_t,jit_word_t);
|
|
# define lshr(r0,r1,r2) LSL(r0,r1,r2)
|
|
# define lshi(r0,r1,i0) _lshi(_jit,r0,r1,i0)
|
|
static void _lshi(jit_state_t*,jit_int32_t,jit_int32_t,jit_word_t);
|
|
# define rshr(r0,r1,r2) ASR(r0,r1,r2)
|
|
# define rshi(r0,r1,i0) _rshi(_jit,r0,r1,i0)
|
|
static void _rshi(jit_state_t*,jit_int32_t,jit_int32_t,jit_word_t);
|
|
# define rshr_u(r0,r1,r2) LSR(r0,r1,r2)
|
|
# define rshi_u(r0,r1,i0) _rshi_u(_jit,r0,r1,i0)
|
|
static void _rshi_u(jit_state_t*,jit_int32_t,jit_int32_t,jit_word_t);
|
|
# define negr(r0,r1) NEG(r0,r1)
|
|
# define comr(r0,r1) MVN(r0,r1)
|
|
# define andr(r0,r1,r2) AND(r0,r1,r2)
|
|
# define andi(r0,r1,i0) _andi(_jit,r0,r1,i0)
|
|
static void _andi(jit_state_t*,jit_int32_t,jit_int32_t,jit_word_t);
|
|
# define orr(r0,r1,r2) ORR(r0,r1,r2)
|
|
# define ori(r0,r1,i0) _ori(_jit,r0,r1,i0)
|
|
static void _ori(jit_state_t*,jit_int32_t,jit_int32_t,jit_word_t);
|
|
# define xorr(r0,r1,r2) EOR(r0,r1,r2)
|
|
# define xori(r0,r1,i0) _xori(_jit,r0,r1,i0)
|
|
static void _xori(jit_state_t*,jit_int32_t,jit_int32_t,jit_word_t);
|
|
# define ldr_c(r0,r1) LDRSBI(r0,r1,0)
|
|
# define ldi_c(r0,i0) _ldi_c(_jit,r0,i0)
|
|
static void _ldi_c(jit_state_t*,jit_int32_t,jit_word_t);
|
|
# define ldr_uc(r0,r1) _ldr_uc(_jit,r0,r1)
|
|
static void _ldr_uc(jit_state_t*,jit_int32_t,jit_int32_t);
|
|
# define ldi_uc(r0,i0) _ldi_uc(_jit,r0,i0)
|
|
static void _ldi_uc(jit_state_t*,jit_int32_t,jit_word_t);
|
|
# define ldr_s(r0,r1) LDRSHI(r0,r1,0)
|
|
# define ldi_s(r0,i0) _ldi_s(_jit,r0,i0)
|
|
static void _ldi_s(jit_state_t*,jit_int32_t,jit_word_t);
|
|
# define ldr_us(r0,r1) _ldr_us(_jit,r0,r1)
|
|
static void _ldr_us(jit_state_t*,jit_int32_t,jit_int32_t);
|
|
# define ldi_us(r0,i0) _ldi_us(_jit,r0,i0)
|
|
static void _ldi_us(jit_state_t*,jit_int32_t,jit_word_t);
|
|
# define ldr_i(r0,r1) LDRSWI(r0,r1,0)
|
|
# define ldi_i(r0,i0) _ldi_i(_jit,r0,i0)
|
|
static void _ldi_i(jit_state_t*,jit_int32_t,jit_word_t);
|
|
# define ldr_ui(r0,r1) _ldr_ui(_jit,r0,r1)
|
|
static void _ldr_ui(jit_state_t*,jit_int32_t,jit_int32_t);
|
|
# define ldi_ui(r0,i0) _ldi_ui(_jit,r0,i0)
|
|
static void _ldi_ui(jit_state_t*,jit_int32_t,jit_word_t);
|
|
# define ldr_l(r0,r1) LDRI(r0,r1,0)
|
|
static void _ldr_l(jit_state_t*,jit_int32_t,jit_int32_t);
|
|
# define ldi_l(r0,i0) _ldi_l(_jit,r0,i0)
|
|
static void _ldi_l(jit_state_t*,jit_int32_t,jit_word_t);
|
|
# define ldxr_c(r0,r1,r2) _ldxr_c(_jit,r0,r1,r2)
|
|
static void _ldxr_c(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t);
|
|
# define ldxi_c(r0,r1,i0) _ldxi_c(_jit,r0,r1,i0)
|
|
static void _ldxi_c(jit_state_t*,jit_int32_t,jit_int32_t,jit_word_t);
|
|
# define ldxr_uc(r0,r1,r2) _ldxr_uc(_jit,r0,r1,r2)
|
|
static void _ldxr_uc(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t);
|
|
# define ldxi_uc(r0,r1,i0) _ldxi_uc(_jit,r0,r1,i0)
|
|
static void _ldxi_uc(jit_state_t*,jit_int32_t,jit_int32_t,jit_word_t);
|
|
# define ldxr_s(r0,r1,r2) LDRSH(r0,r1,r2)
|
|
# define ldxi_s(r0,r1,i0) _ldxi_s(_jit,r0,r1,i0)
|
|
static void _ldxi_s(jit_state_t*,jit_int32_t,jit_int32_t,jit_word_t);
|
|
# define ldxr_us(r0,r1,r2) _ldxr_us(_jit,r0,r1,r2)
|
|
static void _ldxr_us(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t);
|
|
# define ldxi_us(r0,r1,i0) _ldxi_us(_jit,r0,r1,i0)
|
|
static void _ldxi_us(jit_state_t*,jit_int32_t,jit_int32_t,jit_word_t);
|
|
# define ldxr_i(r0,r1,r2) LDRSW(r0,r1,r2)
|
|
# define ldxi_i(r0,r1,i0) _ldxi_i(_jit,r0,r1,i0)
|
|
static void _ldxi_i(jit_state_t*,jit_int32_t,jit_int32_t,jit_word_t);
|
|
# define ldxr_ui(r0,r1,r2) _ldxr_ui(_jit,r0,r1,r2)
|
|
static void _ldxr_ui(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t);
|
|
# define ldxi_ui(r0,r1,i0) _ldxi_ui(_jit,r0,r1,i0)
|
|
static void _ldxi_ui(jit_state_t*,jit_int32_t,jit_int32_t,jit_word_t);
|
|
# define ldxr_l(r0,r1,r2) LDR(r0,r1,r2)
|
|
# define ldxi_l(r0,r1,i0) _ldxi_l(_jit,r0,r1,i0)
|
|
static void _ldxi_l(jit_state_t*,jit_int32_t,jit_int32_t,jit_word_t);
|
|
# define str_c(r0,r1) STRBI(r1,r0,0)
|
|
# define sti_c(i0,r0) _sti_c(_jit,i0,r0)
|
|
static void _sti_c(jit_state_t*,jit_word_t,jit_int32_t);
|
|
# define str_s(r0,r1) STRHI(r1,r0,0)
|
|
# define sti_s(i0,r0) _sti_s(_jit,i0,r0)
|
|
static void _sti_s(jit_state_t*,jit_word_t,jit_int32_t);
|
|
# define str_i(r0,r1) STRWI(r1,r0,0)
|
|
# define sti_i(i0,r0) _sti_i(_jit,i0,r0)
|
|
static void _sti_i(jit_state_t*,jit_word_t,jit_int32_t);
|
|
# define str_l(r0,r1) STRI(r1,r0,0)
|
|
# define sti_l(i0,r0) _sti_l(_jit,i0,r0)
|
|
static void _sti_l(jit_state_t*,jit_word_t,jit_int32_t);
|
|
# define stxr_c(r0,r1,r2) STRB(r2,r1,r0)
|
|
# define stxi_c(i0,r0,r1) _stxi_c(_jit,i0,r0,r1)
|
|
static void _stxi_c(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
|
|
# define stxr_s(r0,r1,r2) STRH(r2,r1,r0)
|
|
# define stxi_s(i0,r0,r1) _stxi_s(_jit,i0,r0,r1)
|
|
static void _stxi_s(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
|
|
# define stxr_i(r0,r1,r2) STRW(r2,r1,r0)
|
|
# define stxi_i(i0,r0,r1) _stxi_i(_jit,i0,r0,r1)
|
|
static void _stxi_i(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
|
|
# define stxr_l(r0,r1,r2) STR(r2,r1,r0)
|
|
# define stxi_l(i0,r0,r1) _stxi_l(_jit,i0,r0,r1)
|
|
static void _stxi_l(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
|
|
# if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
# define htonr(r0,r1) REV(r0,r1)
|
|
# else
|
|
# define htonr(r0,r1) movr(r0,r1)
|
|
# endif
|
|
# define extr_c(r0,r1) SXTB(r0,r1)
|
|
# define extr_uc(r0,r1) UXTB(r0,r1)
|
|
# define extr_s(r0,r1) SXTH(r0,r1)
|
|
# define extr_us(r0,r1) UXTH(r0,r1)
|
|
# define extr_i(r0,r1) SXTW(r0,r1)
|
|
# define extr_ui(r0,r1) UXTW(r0,r1)
|
|
# define movr(r0,r1) _movr(_jit,r0,r1)
|
|
static void _movr(jit_state_t*,jit_int32_t,jit_int32_t);
|
|
# define movi(r0,i0) _movi(_jit,r0,i0)
|
|
static void _movi(jit_state_t*,jit_int32_t,jit_word_t);
|
|
# define movi_p(r0,i0) _movi_p(_jit,r0,i0)
|
|
static jit_word_t _movi_p(jit_state_t*,jit_int32_t,jit_word_t);
|
|
# define ccr(cc,r0,r1,r2) _ccr(_jit,cc,r0,r1,r2)
|
|
static void _ccr(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t);
|
|
# define cci(cc,r0,r1,i0) _cci(_jit,cc,r0,r1,i0)
|
|
static void _cci(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t,jit_word_t);
|
|
# define ltr(r0,r1,r2) ccr(CC_LT,r0,r1,r2)
|
|
# define lti(r0,r1,i0) cci(CC_LT,r0,r1,i0)
|
|
# define ltr_u(r0,r1,r2) ccr(CC_CC,r0,r1,r2)
|
|
# define lti_u(r0,r1,i0) cci(CC_CC,r0,r1,i0)
|
|
# define ler(r0,r1,r2) ccr(CC_LE,r0,r1,r2)
|
|
# define lei(r0,r1,i0) cci(CC_LE,r0,r1,i0)
|
|
# define ler_u(r0,r1,r2) ccr(CC_LS,r0,r1,r2)
|
|
# define lei_u(r0,r1,i0) cci(CC_LS,r0,r1,i0)
|
|
# define eqr(r0,r1,r2) ccr(CC_EQ,r0,r1,r2)
|
|
# define eqi(r0,r1,i0) cci(CC_EQ,r0,r1,i0)
|
|
# define ger(r0,r1,r2) ccr(CC_GE,r0,r1,r2)
|
|
# define gei(r0,r1,i0) cci(CC_GE,r0,r1,i0)
|
|
# define ger_u(r0,r1,r2) ccr(CC_CS,r0,r1,r2)
|
|
# define gei_u(r0,r1,i0) cci(CC_CS,r0,r1,i0)
|
|
# define gtr(r0,r1,r2) ccr(CC_GT,r0,r1,r2)
|
|
# define gti(r0,r1,i0) cci(CC_GT,r0,r1,i0)
|
|
# define gtr_u(r0,r1,r2) ccr(CC_HI,r0,r1,r2)
|
|
# define gti_u(r0,r1,i0) cci(CC_HI,r0,r1,i0)
|
|
# define ner(r0,r1,r2) ccr(CC_NE,r0,r1,r2)
|
|
# define nei(r0,r1,i0) cci(CC_NE,r0,r1,i0)
|
|
# define bccr(cc,i0,r0,r1) _bccr(_jit,cc,i0,r0,r1)
|
|
static jit_word_t
|
|
_bccr(jit_state_t*,jit_int32_t,jit_word_t,jit_int32_t,jit_int32_t);
|
|
# define bcci(cc,i0,r0,i1) _bcci(_jit,cc,i0,r0,i1)
|
|
static jit_word_t
|
|
_bcci(jit_state_t*,jit_int32_t,jit_word_t,jit_int32_t,jit_word_t);
|
|
# define bltr(i0,r0,r1) bccr(BCC_LT,i0,r0,r1)
|
|
# define blti(i0,r0,i1) bcci(BCC_LT,i0,r0,i1)
|
|
# define bltr_u(i0,r0,r1) bccr(BCC_CC,i0,r0,r1)
|
|
# define blti_u(i0,r0,i1) bcci(BCC_CC,i0,r0,i1)
|
|
# define bler(i0,r0,r1) bccr(BCC_LE,i0,r0,r1)
|
|
# define blei(i0,r0,i1) bcci(BCC_LE,i0,r0,i1)
|
|
# define bler_u(i0,r0,r1) bccr(BCC_LS,i0,r0,r1)
|
|
# define blei_u(i0,r0,i1) bcci(BCC_LS,i0,r0,i1)
|
|
# define beqr(i0,r0,r1) bccr(BCC_EQ,i0,r0,r1)
|
|
# define beqi(i0,r0,i1) _beqi(_jit,i0,r0,i1)
|
|
static jit_word_t _beqi(jit_state_t*,jit_word_t,jit_int32_t,jit_word_t);
|
|
# define bger(i0,r0,r1) bccr(BCC_GE,i0,r0,r1)
|
|
# define bgei(i0,r0,i1) bcci(BCC_GE,i0,r0,i1)
|
|
# define bger_u(i0,r0,r1) bccr(BCC_CS,i0,r0,r1)
|
|
# define bgei_u(i0,r0,i1) bcci(BCC_CS,i0,r0,i1)
|
|
# define bgtr(i0,r0,r1) bccr(BCC_GT,i0,r0,r1)
|
|
# define bgti(i0,r0,i1) bcci(BCC_GT,i0,r0,i1)
|
|
# define bgtr_u(i0,r0,r1) bccr(BCC_HI,i0,r0,r1)
|
|
# define bgti_u(i0,r0,i1) bcci(BCC_HI,i0,r0,i1)
|
|
# define bner(i0,r0,r1) bccr(BCC_NE,i0,r0,r1)
|
|
# define bnei(i0,r0,i1) _bnei(_jit,i0,r0,i1)
|
|
static jit_word_t _bnei(jit_state_t*,jit_word_t,jit_int32_t,jit_word_t);
|
|
# define baddr(cc,i0,r0,r1) _baddr(_jit,cc,i0,r0,r1)
|
|
static jit_word_t
|
|
_baddr(jit_state_t*,jit_int32_t,jit_word_t,jit_int32_t,jit_int32_t);
|
|
# define baddi(cc,i0,r0,i1) _baddi(_jit,cc,i0,r0,i1)
|
|
static jit_word_t
|
|
_baddi(jit_state_t*,jit_int32_t,jit_word_t,jit_int32_t,jit_word_t);
|
|
# define boaddr(i0,r0,r1) baddr(BCC_VS,i0,r0,r1)
|
|
# define boaddi(i0,r0,i1) baddi(BCC_VS,i0,r0,i1)
|
|
# define boaddr_u(i0,r0,r1) baddr(BCC_HS,i0,r0,r1)
|
|
# define boaddi_u(i0,r0,i1) baddi(BCC_HS,i0,r0,i1)
|
|
# define bxaddr(i0,r0,r1) baddr(BCC_VC,i0,r0,r1)
|
|
# define bxaddi(i0,r0,i1) baddi(BCC_VC,i0,r0,i1)
|
|
# define bxaddr_u(i0,r0,r1) baddr(BCC_LO,i0,r0,r1)
|
|
# define bxaddi_u(i0,r0,i1) baddi(BCC_LO,i0,r0,i1)
|
|
# define bsubr(cc,i0,r0,r1) _bsubr(_jit,cc,i0,r0,r1)
|
|
static jit_word_t
|
|
_bsubr(jit_state_t*,jit_int32_t,jit_word_t,jit_int32_t,jit_int32_t);
|
|
# define bsubi(cc,i0,r0,i1) _bsubi(_jit,cc,i0,r0,i1)
|
|
static jit_word_t
|
|
_bsubi(jit_state_t*,jit_int32_t,jit_word_t,jit_int32_t,jit_word_t);
|
|
# define bosubr(i0,r0,r1) bsubr(BCC_VS,i0,r0,r1)
|
|
# define bosubi(i0,r0,i1) bsubi(BCC_VS,i0,r0,i1)
|
|
# define bosubr_u(i0,r0,r1) bsubr(BCC_LO,i0,r0,r1)
|
|
# define bosubi_u(i0,r0,i1) bsubi(BCC_LO,i0,r0,i1)
|
|
# define bxsubr(i0,r0,r1) bsubr(BCC_VC,i0,r0,r1)
|
|
# define bxsubi(i0,r0,i1) bsubi(BCC_VC,i0,r0,i1)
|
|
# define bxsubr_u(i0,r0,r1) bsubr(BCC_HS,i0,r0,r1)
|
|
# define bxsubi_u(i0,r0,i1) bsubi(BCC_HS,i0,r0,i1)
|
|
# define bmxr(cc,i0,r0,r1) _bmxr(_jit,cc,i0,r0,r1)
|
|
static jit_word_t
|
|
_bmxr(jit_state_t*,jit_int32_t,jit_word_t,jit_int32_t,jit_int32_t);
|
|
# define bmxi(cc,i0,r0,r1) _bmxi(_jit,cc,i0,r0,r1)
|
|
static jit_word_t
|
|
_bmxi(jit_state_t*,jit_int32_t,jit_word_t,jit_int32_t,jit_word_t);
|
|
# define bmsr(i0,r0,r1) bmxr(BCC_NE,i0,r0,r1)
|
|
# define bmsi(i0,r0,i1) bmxi(BCC_NE,i0,r0,i1)
|
|
# define bmcr(i0,r0,r1) bmxr(BCC_EQ,i0,r0,r1)
|
|
# define bmci(i0,r0,i1) bmxi(BCC_EQ,i0,r0,i1)
|
|
# define jmpr(r0) BR(r0)
|
|
# define jmpi(i0) _jmpi(_jit,i0)
|
|
static void _jmpi(jit_state_t*,jit_word_t);
|
|
# define jmpi_p(i0) _jmpi_p(_jit,i0)
|
|
static jit_word_t _jmpi_p(jit_state_t*,jit_word_t);
|
|
# define callr(r0) BLR(r0)
|
|
# define calli(i0) _calli(_jit,i0)
|
|
static void _calli(jit_state_t*,jit_word_t);
|
|
# define calli_p(i0) _calli_p(_jit,i0)
|
|
static jit_word_t _calli_p(jit_state_t*,jit_word_t);
|
|
# define prolog(i0) _prolog(_jit,i0)
|
|
static void _prolog(jit_state_t*,jit_node_t*);
|
|
# define epilog(i0) _epilog(_jit,i0)
|
|
static void _epilog(jit_state_t*,jit_node_t*);
|
|
# define patch_at(jump,label) _patch_at(_jit,jump,label)
|
|
static void _patch_at(jit_state_t*,jit_word_t,jit_word_t);
|
|
#endif
|
|
|
|
#if CODE
|
|
static jit_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, jit_int32_t Op,
|
|
jit_int32_t Rd, jit_int32_t Rn, jit_int32_t Rm)
|
|
{
|
|
instr_t i;
|
|
assert(!(Rd & ~0x1f));
|
|
assert(!(Rn & ~0x1f));
|
|
assert(!(Rm & ~0x1f));
|
|
assert(!(Op & ~0xffe0fc00));
|
|
i.w = Op;
|
|
i.Rd.b = Rd;
|
|
i.Rn.b = Rn;
|
|
i.Rm.b = Rm;
|
|
ii(i.w);
|
|
}
|
|
|
|
static void
|
|
_oxxi(jit_state_t *_jit, jit_int32_t Op,
|
|
jit_int32_t Rd, jit_int32_t Rn, jit_int32_t Imm12)
|
|
{
|
|
instr_t i;
|
|
assert(!(Rd & ~0x1f));
|
|
assert(!(Rn & ~0x1f));
|
|
assert(!(Imm12 & ~0xfff));
|
|
assert(!(Op & ~0xffe00000));
|
|
i.w = Op;
|
|
i.Rd.b = Rd;
|
|
i.Rn.b = Rn;
|
|
i.imm12.b = Imm12;
|
|
ii(i.w);
|
|
}
|
|
|
|
static void
|
|
_oxx9(jit_state_t *_jit, jit_int32_t Op,
|
|
jit_int32_t Rd, jit_int32_t Rn, jit_int32_t Imm9)
|
|
{
|
|
instr_t i;
|
|
assert(!(Rd & ~0x1f));
|
|
assert(!(Rn & ~0x1f));
|
|
assert(!(Imm9 & ~0x1ff));
|
|
assert(!(Op & ~0xffe00000));
|
|
i.w = Op;
|
|
i.Rd.b = Rd;
|
|
i.Rn.b = Rn;
|
|
i.imm9.b = Imm9;
|
|
ii(i.w);
|
|
}
|
|
|
|
static void
|
|
_ox19(jit_state_t *_jit, jit_int32_t Op, jit_int32_t Rd, jit_int32_t Simm19)
|
|
{
|
|
instr_t i;
|
|
assert(!(Rd & ~0x1f));
|
|
assert(Simm19 >= -262148 && Simm19 <= 262143);
|
|
assert(!(Op & ~0xff000000));
|
|
i.w = Op;
|
|
i.Rd.b = Rd;
|
|
i.imm19.b = Simm19;
|
|
ii(i.w);
|
|
}
|
|
|
|
static void
|
|
_oc19(jit_state_t *_jit, jit_int32_t Op, jit_int32_t Cc, jit_int32_t Simm19)
|
|
{
|
|
instr_t i;
|
|
assert(!(Cc & ~0xf));
|
|
assert(Simm19 >= -262148 && Simm19 <= 262143);
|
|
assert(!(Op & ~0xff000000));
|
|
i.w = Op;
|
|
i.cond2.b = Cc;
|
|
i.imm19.b = Simm19;
|
|
ii(i.w);
|
|
}
|
|
|
|
static void
|
|
_o26(jit_state_t *_jit, jit_int32_t Op, jit_int32_t Simm26)
|
|
{
|
|
instr_t i;
|
|
assert(Simm26 >= -33554432 && Simm26 <= 33554431);
|
|
assert(!(Op & ~0xfc000000));
|
|
i.w = Op;
|
|
i.imm26.b = Simm26;
|
|
ii(i.w);
|
|
}
|
|
|
|
static void
|
|
_ox_x(jit_state_t *_jit, jit_int32_t Op, jit_int32_t Rd, jit_int32_t Rm)
|
|
{
|
|
instr_t i;
|
|
assert(!(Rd & ~0x1f));
|
|
assert(!(Rm & ~0x1f));
|
|
assert(!(Op & ~0xffe0ffe0));
|
|
i.w = Op;
|
|
i.Rd.b = Rd;
|
|
i.Rm.b = Rm;
|
|
ii(i.w);
|
|
}
|
|
|
|
static void
|
|
_o_xx(jit_state_t *_jit, jit_int32_t Op, jit_int32_t Rd, jit_int32_t Rn)
|
|
{
|
|
instr_t i;
|
|
assert(!(Rd & ~0x1f));
|
|
assert(!(Rn & ~0x1f));
|
|
assert(!(Op & ~0xfffffc00));
|
|
i.w = Op;
|
|
i.Rd.b = Rd;
|
|
i.Rn.b = Rn;
|
|
ii(i.w);
|
|
}
|
|
|
|
static void
|
|
_oxx_(jit_state_t *_jit, jit_int32_t Op, jit_int32_t Rn, jit_int32_t Rm)
|
|
{
|
|
instr_t i;
|
|
assert(!(Rn & ~0x1f));
|
|
assert(!(Rm & ~0x1f));
|
|
assert(!(Op & ~0xffc0fc1f));
|
|
i.w = Op;
|
|
i.Rn.b = Rn;
|
|
i.Rm.b = Rm;
|
|
ii(i.w);
|
|
}
|
|
|
|
static void
|
|
_o_x_(jit_state_t *_jit, jit_int32_t Op, jit_int32_t Rn)
|
|
{
|
|
instr_t i;
|
|
assert(!(Rn & ~0x1f));
|
|
assert(!(Op & 0x3e0));
|
|
i.w = Op;
|
|
i.Rn.b = Rn;
|
|
ii(i.w);
|
|
}
|
|
|
|
static void
|
|
_ox_h(jit_state_t *_jit, jit_int32_t Op, jit_int32_t Rd, jit_int32_t Imm16)
|
|
{
|
|
instr_t i;
|
|
assert(!(Rd & ~0x1f));
|
|
assert(!(Imm16 & ~0xffff));
|
|
assert(!(Op & ~0xffe00000));
|
|
i.w = Op;
|
|
i.Rd.b = Rd;
|
|
i.imm16.b = Imm16;
|
|
ii(i.w);
|
|
}
|
|
|
|
static void
|
|
_oxxrs(jit_state_t *_jit, jit_int32_t Op,
|
|
jit_int32_t Rd, jit_int32_t Rn, jit_int32_t R, jit_int32_t S)
|
|
{
|
|
instr_t i;
|
|
assert(!(Rd & ~0x1f));
|
|
assert(!(Rn & ~0x1f));
|
|
assert(!(R & ~0x3f));
|
|
assert(!(S & ~0x3f));
|
|
assert(!(Op & ~0xffc00000));
|
|
i.w = Op;
|
|
i.Rd.b = Rd;
|
|
i.Rn.b = Rn;
|
|
i.immr.b = R;
|
|
i.imms.b = S;
|
|
ii(i.w);
|
|
}
|
|
|
|
static void
|
|
_oxxxc(jit_state_t *_jit, jit_int32_t Op,
|
|
jit_int32_t Rd, jit_int32_t Rn, jit_int32_t Rm, jit_int32_t Cc)
|
|
{
|
|
instr_t i;
|
|
assert(!(Rd & ~0x1f));
|
|
assert(!(Rn & ~0x1f));
|
|
assert(!(Rm & ~0x1f));
|
|
assert(!(Cc & ~0xf));
|
|
assert(!(Op & ~0xffc00c00));
|
|
i.w = Op;
|
|
i.Rd.b = Rd;
|
|
i.Rn.b = Rn;
|
|
i.Rm.b = Rm;
|
|
i.cond.b = Cc;
|
|
ii(i.w);
|
|
}
|
|
|
|
static void
|
|
_oxxx7(jit_state_t *_jit, jit_int32_t Op,
|
|
jit_int32_t Rt, jit_int32_t Rt2, jit_int32_t Rn, jit_int32_t Simm7)
|
|
{
|
|
instr_t i;
|
|
assert(!(Rt & ~0x1f));
|
|
assert(!(Rt2 & ~0x1f));
|
|
assert(!(Rn & ~0x1f));
|
|
assert(Simm7 >= -128 && Simm7 <= 127);
|
|
assert(!(Op & ~0xffc003e0));
|
|
i.w = Op;
|
|
i.Rt.b = Rt;
|
|
i.Rt2.b = Rt2;
|
|
i.Rn.b = Rn;
|
|
i.imm7.b = Simm7;
|
|
ii(i.w);
|
|
}
|
|
|
|
static void
|
|
_nop(jit_state_t *_jit, jit_int32_t i0)
|
|
{
|
|
for (; i0 > 0; i0 -= 4)
|
|
NOP();
|
|
assert(i0 == 0);
|
|
}
|
|
|
|
static void
|
|
_addi(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
jit_word_t is = i0 >> 12;
|
|
jit_word_t in = -i0;
|
|
jit_word_t iS = in >> 12;
|
|
if ( i0 >= 0 && i0 <= 0xfff)
|
|
ADDI (r0, r1, i0);
|
|
else if ((is << 12) == i0 && is >= 0 && is <= 0xfff)
|
|
ADDI_12(r0, r1, is);
|
|
else if ( in >= 0 && in <= 0xfff)
|
|
SUBI (r0, r1, in);
|
|
else if ((iS << 12) == is && iS >= 0 && iS <= 0xfff)
|
|
SUBI_12(r0, r1, iS);
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
addr(r0, r1, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_addci(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
jit_word_t is = i0 >> 12;
|
|
jit_word_t in = -i0;
|
|
jit_word_t iS = in >> 12;
|
|
if ( i0 >= 0 && i0 <= 0xfff)
|
|
ADDSI (r0, r1, i0);
|
|
else if ((is << 12) == i0 && is >= 0 && is <= 0xfff)
|
|
ADDSI_12(r0, r1, is);
|
|
else if ( in >= 0 && in <= 0xfff)
|
|
SUBSI (r0, r1, in);
|
|
else if ((iS << 12) == is && iS >= 0 && iS <= 0xfff)
|
|
SUBSI_12(r0, r1, iS);
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
addcr(r0, r1, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_addxi(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
addxr(r0, r1, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
|
|
static void
|
|
_subi(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
jit_word_t is = i0 >> 12;
|
|
if ( i0 >= 0 && i0 <= 0xfff)
|
|
SUBI (r0, r1, i0);
|
|
else if ((is << 12) == i0 && is >= 0 && is <= 0xfff)
|
|
SUBI_12(r0, r1, is);
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
subr(r0, r1, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_subci(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
jit_word_t is = i0 >> 12;
|
|
if ( i0 >= 0 && i0 <= 0xfff)
|
|
SUBSI (r0, r1, i0);
|
|
else if ((is << 12) == i0 && is >= 0 && is <= 0xfff)
|
|
SUBSI_12(r0, r1, is);
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
subcr(r0, r1, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_subxi(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
subxr(r0, r1, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
|
|
static void
|
|
_rsbi(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
subi(r0, r1, i0);
|
|
negr(r0, r0);
|
|
}
|
|
|
|
static void
|
|
_muli(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
mulr(r0, r1, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
|
|
static void
|
|
_qmulr(jit_state_t *_jit, jit_int32_t r0,
|
|
jit_int32_t r1, jit_int32_t r2, jit_int32_t r3)
|
|
{
|
|
jit_int32_t reg;
|
|
if (r0 == r2 || r0 == r3) {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
mulr(rn(reg), r2, r3);
|
|
}
|
|
else
|
|
mulr(r0, r2, r3);
|
|
SMULH(r1, r2, r3);
|
|
if (r0 == r2 || r0 == r3) {
|
|
movr(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_qmuli(jit_state_t *_jit, jit_int32_t r0,
|
|
jit_int32_t r1, jit_int32_t r2, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
qmulr(r0, r1, r2, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
|
|
static void
|
|
_qmulr_u(jit_state_t *_jit, jit_int32_t r0,
|
|
jit_int32_t r1, jit_int32_t r2, jit_int32_t r3)
|
|
{
|
|
jit_int32_t reg;
|
|
if (r0 == r2 || r0 == r3) {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
mulr(rn(reg), r2, r3);
|
|
}
|
|
else
|
|
mulr(r0, r2, r3);
|
|
UMULH(r1, r2, r3);
|
|
if (r0 == r2 || r0 == r3) {
|
|
movr(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_qmuli_u(jit_state_t *_jit, jit_int32_t r0,
|
|
jit_int32_t r1, jit_int32_t r2, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
qmulr_u(r0, r1, r2, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
|
|
static void
|
|
_divi(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
divr(r0, r1, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
|
|
static void
|
|
_divi_u(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
divr_u(r0, r1, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
|
|
static void
|
|
_iqdivr(jit_state_t *_jit, jit_bool_t sign,
|
|
jit_int32_t r0, jit_int32_t r1, jit_int32_t r2, jit_int32_t r3)
|
|
{
|
|
jit_int32_t sv0, rg0;
|
|
jit_int32_t sv1, rg1;
|
|
if (r0 == r2 || r0 == r3) {
|
|
sv0 = jit_get_reg(jit_class_gpr);
|
|
rg0 = rn(sv0);
|
|
}
|
|
else
|
|
rg0 = r0;
|
|
if (r1 == r2 || r1 == r3) {
|
|
sv1 = jit_get_reg(jit_class_gpr);
|
|
rg1 = rn(sv1);
|
|
}
|
|
else
|
|
rg1 = r1;
|
|
if (sign)
|
|
divr(rg0, r2, r3);
|
|
else
|
|
divr_u(rg0, r2, r3);
|
|
mulr(rg1, r3, rg0);
|
|
subr(rg1, r2, rg1);
|
|
if (rg0 != r0) {
|
|
movr(r0, rg0);
|
|
jit_unget_reg(sv0);
|
|
}
|
|
if (rg1 != r1) {
|
|
movr(r1, rg1);
|
|
jit_unget_reg(sv1);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_qdivi(jit_state_t *_jit, jit_int32_t r0,
|
|
jit_int32_t r1, jit_int32_t r2, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
qdivr(r0, r1, r2, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
|
|
static void
|
|
_qdivi_u(jit_state_t *_jit, jit_int32_t r0,
|
|
jit_int32_t r1, jit_int32_t r2, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
qdivr_u(r0, r1, r2, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
|
|
static void
|
|
_remr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
jit_int32_t reg;
|
|
if (r0 == r1 || r0 == r2) {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
divr(rn(reg), r1, r2);
|
|
mulr(rn(reg), r2, rn(reg));
|
|
subr(r0, r1, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
else {
|
|
divr(r0, r1, r2);
|
|
mulr(r0, r2, r0);
|
|
subr(r0, r1, r0);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_remi(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
remr(r0, r1, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
|
|
static void
|
|
_remr_u(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
jit_int32_t reg;
|
|
if (r0 == r1 || r0 == r2) {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
divr_u(rn(reg), r1, r2);
|
|
mulr(rn(reg), r2, rn(reg));
|
|
subr(r0, r1, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
else {
|
|
divr_u(r0, r1, r2);
|
|
mulr(r0, r2, r0);
|
|
subr(r0, r1, r0);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_remi_u(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
remr_u(r0, r1, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
|
|
static void
|
|
_lshi(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
if (i0 == 0)
|
|
movr(r0, r1);
|
|
else {
|
|
assert(i0 > 0 && i0 < 64);
|
|
LSLI(r0, r1, i0);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_rshi(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
if (i0 == 0)
|
|
movr(r0, r1);
|
|
else {
|
|
assert(i0 > 0 && i0 < 64);
|
|
ASRI(r0, r1, i0);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_rshi_u(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
if (i0 == 0)
|
|
movr(r0, r1);
|
|
else {
|
|
assert(i0 > 0 && i0 < 64);
|
|
LSRI(r0, r1, i0);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_andi(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
jit_int32_t imm;
|
|
if (i0 == 0)
|
|
movi(r0, 0);
|
|
else if (i0 == -1)
|
|
movr(r0, r1);
|
|
else {
|
|
imm = logical_immediate(i0);
|
|
if (imm != -1)
|
|
ANDI(r0, r1, imm);
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
andr(r0, r1, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
_ori(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
jit_int32_t imm;
|
|
if (i0 == 0)
|
|
movr(r0, r1);
|
|
else if (i0 == -1)
|
|
movi(r0, -1);
|
|
else {
|
|
imm = logical_immediate(i0);
|
|
if (imm != -1)
|
|
ORRI(r0, r1, imm);
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
orr(r0, r1, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
_xori(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
jit_int32_t imm;
|
|
if (i0 == 0)
|
|
movr(r0, r1);
|
|
else if (i0 == -1)
|
|
comr(r0, r1);
|
|
else {
|
|
imm = logical_immediate(i0);
|
|
if (imm != -1)
|
|
EORI(r0, r1, imm);
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
xorr(r0, r1, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
_ldi_c(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
ldr_c(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
|
|
static void
|
|
_ldr_uc(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
LDRBI(r0, r1, 0);
|
|
#if 0
|
|
extr_uc(r0, r0);
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
_ldi_uc(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
ldr_uc(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
|
|
static void
|
|
_ldi_s(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
ldr_s(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
|
|
static void
|
|
_ldr_us(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
LDRHI(r0, r1, 0);
|
|
#if 0
|
|
extr_us(r0, r0);
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
_ldi_us(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
ldr_us(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
|
|
static void
|
|
_ldi_i(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
ldr_i(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
|
|
static void
|
|
_ldr_ui(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
LDRWI(r0, r1, 0);
|
|
#if 0
|
|
extr_ui(r0, r0);
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
_ldi_ui(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
ldr_ui(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
|
|
static void
|
|
_ldi_l(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
ldr_l(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
|
|
static void
|
|
_ldxr_c(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
LDRSB(r0, r1, r2);
|
|
extr_c(r0, r0);
|
|
}
|
|
|
|
static void
|
|
_ldxi_c(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
if (i0 >= 0 && i0 <= 4095)
|
|
LDRSBI(r0, r1, i0);
|
|
else if (i0 > -256 && i0 < 0)
|
|
LDURSB(r0, r1, i0 & 0x1ff);
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
LDRSB(r0, r1, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
extr_c(r0, r0);
|
|
}
|
|
|
|
static void
|
|
_ldxr_uc(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
LDRB(r0, r1, r2);
|
|
#if 0
|
|
extr_uc(r0, r0);
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
_ldxi_uc(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
if (i0 >= 0 && i0 <= 4095)
|
|
LDRBI(r0, r1, i0);
|
|
else if (i0 > -256 && i0 < 0)
|
|
LDURB(r0, r1, i0 & 0x1ff);
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
addi(rn(reg), r1, i0);
|
|
ldr_uc(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
#if 0
|
|
extr_uc(r0, r0);
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
_ldxi_s(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
assert(!(i0 & 1));
|
|
if (i0 >= 0 && i0 <= 8191)
|
|
LDRSHI(r0, r1, i0 >> 1);
|
|
else if (i0 > -256 && i0 < 0)
|
|
LDURSH(r0, r1, i0 & 0x1ff);
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
LDRSH(r0, r1, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_ldxr_us(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
LDRH(r0, r1, r2);
|
|
#if 0
|
|
extr_us(r0, r0);
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
_ldxi_us(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
assert(!(i0 & 1));
|
|
if (i0 >= 0 && i0 <= 8191)
|
|
LDRHI(r0, r1, i0 >> 1);
|
|
else if (i0 > -256 && i0 < 0)
|
|
LDURH(r0, r1, i0 & 0x1ff);
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
LDRH(r0, r1, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
#if 0
|
|
extr_us(r0, r0);
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
_ldxi_i(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
assert(!(i0 & 3));
|
|
if (i0 >= 0 && i0 <= 16383)
|
|
LDRSWI(r0, r1, i0 >> 2);
|
|
else if (i0 > -256 && i0 < 0)
|
|
LDURSW(r0, r1, i0 & 0x1ff);
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
addi(rn(reg), r1, i0);
|
|
ldr_i(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_ldxr_ui(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
LDRW(r0, r1, r2);
|
|
#if 0
|
|
extr_ui(r0, r0);
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
_ldxi_ui(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
assert(!(i0 & 3));
|
|
if (i0 >= 0 && i0 <= 16383)
|
|
LDRWI(r0, r1, i0 >> 2);
|
|
else if (i0 > -256 && i0 < 0)
|
|
LDURW(r0, r1, i0 & 0x1ff);
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
LDRW(r0, r1, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
#if 0
|
|
extr_ui(r0, r0);
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
_ldxi_l(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
assert(!(i0 & 7));
|
|
if (i0 >= 0 && i0 <= 32767)
|
|
LDRI(r0, r1, i0 >> 3);
|
|
else if (i0 > -256 && i0 < 0)
|
|
LDUR(r0, r1, i0 & 0x1ff);
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
addi(rn(reg), r1, i0);
|
|
ldr_l(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_sti_c(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0)
|
|
{
|
|
jit_int32_t reg;
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
str_c(rn(reg), r0);
|
|
jit_unget_reg(reg);
|
|
}
|
|
|
|
static void
|
|
_sti_s(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0)
|
|
{
|
|
jit_int32_t reg;
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
str_s(rn(reg), r0);
|
|
jit_unget_reg(reg);
|
|
}
|
|
|
|
static void
|
|
_sti_i(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0)
|
|
{
|
|
jit_int32_t reg;
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
str_i(rn(reg), r0);
|
|
jit_unget_reg(reg);
|
|
}
|
|
|
|
static void
|
|
_sti_l(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0)
|
|
{
|
|
jit_int32_t reg;
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
str_l(rn(reg), r0);
|
|
jit_unget_reg(reg);
|
|
}
|
|
|
|
static void
|
|
_stxi_c(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
jit_int32_t reg;
|
|
if (i0 >= 0 && i0 <= 4095)
|
|
STRBI(r1, r0, i0);
|
|
else if (i0 > -256 && i0 < 0)
|
|
STURB(r1, r0, i0 & 0x1ff);
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
addi(rn(reg), r1, i0);
|
|
str_c(rn(reg), r1);
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_stxi_s(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
jit_int32_t reg;
|
|
assert(!(i0 & 1));
|
|
if (i0 >= 0 && i0 <= 8191)
|
|
STRHI(r1, r0, i0 >> 1);
|
|
else if (i0 > -256 && i0 < 0)
|
|
STURH(r1, r0, i0 & 0x1ff);
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
addi(rn(reg), r1, i0);
|
|
str_s(rn(reg), r1);
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_stxi_i(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
jit_int32_t reg;
|
|
assert(!(i0 & 3));
|
|
if (i0 >= 0 && i0 <= 16383)
|
|
STRWI(r1, r0, i0 >> 2);
|
|
else if (i0 > -256 && i0 < 0)
|
|
STURW(r1, r0, i0 & 0x1ff);
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
addi(rn(reg), r1, i0);
|
|
str_i(rn(reg), r1);
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_stxi_l(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
jit_int32_t reg;
|
|
assert(!(i0 & 7));
|
|
if (i0 >= 0 && i0 <= 32767)
|
|
STRI(r1, r0, i0 >> 3);
|
|
else if (i0 > -256 && i0 < 0)
|
|
STUR(r1, r0, i0 & 0x1ff);
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
addi(rn(reg), r1, i0);
|
|
str_l(rn(reg), r1);
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_movr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
if (r0 != r1)
|
|
MOV(r0, r1);
|
|
}
|
|
|
|
static void
|
|
_movi(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
|
|
{
|
|
jit_word_t n0, ibit, nbit;
|
|
n0 = ~i0;
|
|
ibit = nbit = 0;
|
|
if (i0 & 0x000000000000ffffL) ibit |= 1;
|
|
if (i0 & 0x00000000ffff0000L) ibit |= 2;
|
|
if (i0 & 0x0000ffff00000000L) ibit |= 4;
|
|
if (i0 & 0xffff000000000000L) ibit |= 8;
|
|
if (n0 & 0x000000000000ffffL) nbit |= 1;
|
|
if (n0 & 0x00000000ffff0000L) nbit |= 2;
|
|
if (n0 & 0x0000ffff00000000L) nbit |= 4;
|
|
if (n0 & 0xffff000000000000L) nbit |= 8;
|
|
switch (ibit) {
|
|
case 0:
|
|
MOVZ (r0, 0);
|
|
break;
|
|
case 1:
|
|
MOVZ (r0, i0 & 0xffff);
|
|
break;
|
|
case 2:
|
|
MOVZ_16(r0, (i0 >> 16) & 0xffff);
|
|
break;
|
|
case 3:
|
|
MOVZ (r0, i0 & 0xffff);
|
|
MOVK_16(r0, (i0 >> 16) & 0xffff);
|
|
break;
|
|
case 4:
|
|
MOVZ_32(r0, (i0 >> 32) & 0xffff);
|
|
break;
|
|
case 5:
|
|
MOVZ (r0, i0 & 0xffff);
|
|
MOVK_32(r0, (i0 >> 32) & 0xffff);
|
|
break;
|
|
case 6:
|
|
MOVZ_16(r0, (i0 >> 16) & 0xffff);
|
|
MOVK_32(r0, (i0 >> 32) & 0xffff);
|
|
break;
|
|
case 7:
|
|
if (nbit == 8)
|
|
MOVN_48(r0, (n0 >> 48) & 0xffff);
|
|
else {
|
|
MOVZ (r0, i0 & 0xffff);
|
|
MOVK_16(r0, (i0 >> 16) & 0xffff);
|
|
MOVK_32(r0, (i0 >> 32) & 0xffff);
|
|
}
|
|
break;
|
|
case 8:
|
|
MOVZ_48(r0, (i0 >> 48) & 0xffff);
|
|
break;
|
|
case 9:
|
|
MOVZ (r0, i0 & 0xffff);
|
|
MOVK_48(r0, (i0 >> 48) & 0xffff);
|
|
break;
|
|
case 10:
|
|
MOVZ_16(r0, (i0 >> 16) & 0xffff);
|
|
MOVK_48(r0, (i0 >> 48) & 0xffff);
|
|
break;
|
|
case 11:
|
|
if (nbit == 4)
|
|
MOVN_32(r0, (n0 >> 32) & 0xffff);
|
|
else {
|
|
MOVZ (r0, i0 & 0xffff);
|
|
MOVK_16(r0, (i0 >> 16) & 0xffff);
|
|
MOVK_48(r0, (i0 >> 48) & 0xffff);
|
|
}
|
|
break;
|
|
case 12:
|
|
MOVZ_32(r0, (i0 >> 32) & 0xffff);
|
|
MOVK_48(r0, (i0 >> 48) & 0xffff);
|
|
break;
|
|
case 13:
|
|
if (nbit == 2)
|
|
MOVN_16(r0, (n0 >> 16) & 0xffff);
|
|
else {
|
|
MOVZ (r0, i0 & 0xffff);
|
|
MOVK_32(r0, (i0 >> 32) & 0xffff);
|
|
MOVK_48(r0, (i0 >> 48) & 0xffff);
|
|
}
|
|
break;
|
|
case 14:
|
|
if (nbit == 1)
|
|
MOVN (r0, (n0) & 0xffff);
|
|
else {
|
|
MOVZ_16(r0, (i0 >> 16) & 0xffff);
|
|
MOVK_32(r0, (i0 >> 32) & 0xffff);
|
|
MOVK_48(r0, (i0 >> 48) & 0xffff);
|
|
}
|
|
break;
|
|
case 15:
|
|
if (nbit == 0)
|
|
MOVN (r0, 0);
|
|
else if (nbit == 1)
|
|
MOVN (r0, n0 & 0xffff);
|
|
else if (nbit == 8)
|
|
MOVN_48(r0, (n0 >> 48) & 0xffff);
|
|
else {
|
|
MOVZ (r0, i0 & 0xffff);
|
|
MOVK_16(r0, (i0 >> 16) & 0xffff);
|
|
MOVK_32(r0, (i0 >> 32) & 0xffff);
|
|
MOVK_48(r0, (i0 >> 48) & 0xffff);
|
|
}
|
|
break;
|
|
default:
|
|
abort();
|
|
}
|
|
}
|
|
|
|
static jit_word_t
|
|
_movi_p(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
|
|
{
|
|
jit_word_t w;
|
|
w = _jit->pc.w;
|
|
MOVZ (r0, i0 & 0xffff);
|
|
MOVK_16(r0, (i0 >> 16) & 0xffff);
|
|
MOVK_32(r0, (i0 >> 32) & 0xffff);
|
|
MOVK_48(r0, (i0 >> 48) & 0xffff);
|
|
return (w);
|
|
}
|
|
|
|
static void
|
|
_ccr(jit_state_t *_jit, jit_int32_t cc,
|
|
jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
CMP(r1, r2);
|
|
CSET(r0, cc);
|
|
}
|
|
|
|
static void
|
|
_cci(jit_state_t *_jit, jit_int32_t cc,
|
|
jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
jit_word_t is = i0 >> 12;
|
|
jit_word_t in = -i0;
|
|
jit_word_t iS = in >> 12;
|
|
if ( i0 >= 0 && i0 <= 0xfff)
|
|
CMPI (r1, i0);
|
|
else if ((is << 12) == i0 && is >= 0 && is <= 0xfff)
|
|
CMPI_12(r1, is);
|
|
else if ( in >= 0 && in <= 0xfff)
|
|
CMNI (r1, in);
|
|
else if ((iS << 12) == is && iS >= 0 && iS <= 0xfff)
|
|
CMNI_12(r1, iS);
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
CMP(r1, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
CSET(r0, cc);
|
|
}
|
|
|
|
static jit_word_t
|
|
_bccr(jit_state_t *_jit, jit_int32_t cc,
|
|
jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
jit_word_t w, d;
|
|
CMP(r0, r1);
|
|
w = _jit->pc.w;
|
|
d = (i0 - w) >> 2;
|
|
B_C(cc, d);
|
|
return (w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_bcci(jit_state_t *_jit, jit_int32_t cc,
|
|
jit_word_t i0, jit_int32_t r0, jit_word_t i1)
|
|
{
|
|
jit_int32_t reg;
|
|
jit_word_t w, d;
|
|
jit_word_t is = i1 >> 12;
|
|
jit_word_t in = -i1;
|
|
jit_word_t iS = in >> 12;
|
|
if ( i1 >= 0 && i1 <= 0xfff)
|
|
CMPI (r0, i1);
|
|
else if ((is << 12) == i0 && is >= 0 && is <= 0xfff)
|
|
CMPI_12(r0, is);
|
|
else if ( in >= 0 && in <= 0xfff)
|
|
CMNI (r0, in);
|
|
else if ((iS << 12) == is && iS >= 0 && iS <= 0xfff)
|
|
CMNI_12(r0, iS);
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i1);
|
|
CMP(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
w = _jit->pc.w;
|
|
d = (i0 - w) >> 2;
|
|
B_C(cc, d);
|
|
return (w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_beqi(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_word_t i1)
|
|
{
|
|
jit_word_t w;
|
|
if (i1 == 0) {
|
|
w = _jit->pc.w;
|
|
CBZ(r0, (i0 - w) >> 2);
|
|
}
|
|
else
|
|
w = bcci(BCC_EQ, i0, r0, i1);
|
|
return (w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_bnei(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_word_t i1)
|
|
{
|
|
jit_word_t w;
|
|
if (i1 == 0) {
|
|
w = _jit->pc.w;
|
|
CBNZ(r0, (i0 - w) >> 2);
|
|
}
|
|
else
|
|
w = bcci(BCC_NE, i0, r0, i1);
|
|
return (w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_baddr(jit_state_t *_jit, jit_int32_t cc,
|
|
jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
jit_word_t w;
|
|
addcr(r0, r0, r1);
|
|
w = _jit->pc.w;
|
|
B_C(cc, (i0 - w) >> 2);
|
|
return (w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_baddi(jit_state_t *_jit, jit_int32_t cc,
|
|
jit_word_t i0, jit_int32_t r0, jit_word_t i1)
|
|
{
|
|
jit_word_t w;
|
|
addci(r0, r0, i1);
|
|
w = _jit->pc.w;
|
|
B_C(cc, (i0 - w) >> 2);
|
|
return (w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_bsubr(jit_state_t *_jit, jit_int32_t cc,
|
|
jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
jit_word_t w;
|
|
subcr(r0, r0, r1);
|
|
w = _jit->pc.w;
|
|
B_C(cc, (i0 - w) >> 2);
|
|
return (w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_bsubi(jit_state_t *_jit, jit_int32_t cc,
|
|
jit_word_t i0, jit_int32_t r0, jit_word_t i1)
|
|
{
|
|
jit_word_t w;
|
|
subci(r0, r0, i1);
|
|
w = _jit->pc.w;
|
|
B_C(cc, (i0 - w) >> 2);
|
|
return (w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_bmxr(jit_state_t *_jit, jit_int32_t cc,
|
|
jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
jit_word_t w;
|
|
TST(r0, r1);
|
|
w = _jit->pc.w;
|
|
B_C(cc, (i0 - w) >> 2);
|
|
return (w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_bmxi(jit_state_t *_jit, jit_int32_t cc,
|
|
jit_word_t i0, jit_int32_t r0, jit_word_t i1)
|
|
{
|
|
jit_word_t w;
|
|
jit_int32_t reg;
|
|
jit_int32_t imm;
|
|
imm = logical_immediate(i1);
|
|
if (imm != -1)
|
|
TSTI(r0, imm);
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
TST(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
w = _jit->pc.w;
|
|
B_C(cc, (i0 - w) >> 2);
|
|
return (w);
|
|
}
|
|
|
|
static void
|
|
_jmpi(jit_state_t *_jit, jit_word_t i0)
|
|
{
|
|
jit_word_t w;
|
|
jit_int32_t reg;
|
|
w = (i0 - _jit->pc.w) >> 2;
|
|
if (w >= -33554432 && w <= 33554431)
|
|
B(w);
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr|jit_class_nospill);
|
|
movi(rn(reg), i0);
|
|
jmpr(rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static jit_word_t
|
|
_jmpi_p(jit_state_t *_jit, jit_word_t i0)
|
|
{
|
|
jit_word_t w;
|
|
jit_int32_t reg;
|
|
reg = jit_get_reg(jit_class_gpr|jit_class_nospill);
|
|
w = movi_p(rn(reg), i0);
|
|
jmpr(rn(reg));
|
|
jit_unget_reg(reg);
|
|
return (w);
|
|
}
|
|
|
|
static void
|
|
_calli(jit_state_t *_jit, jit_word_t i0)
|
|
{
|
|
jit_word_t w;
|
|
jit_int32_t reg;
|
|
w = (i0 - _jit->pc.w) >> 2;
|
|
if (w >= -33554432 && w <= 33554431)
|
|
BL(w);
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
callr(rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static jit_word_t
|
|
_calli_p(jit_state_t *_jit, jit_word_t i0)
|
|
{
|
|
jit_word_t w;
|
|
jit_int32_t reg;
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
w = movi_p(rn(reg), i0);
|
|
callr(rn(reg));
|
|
jit_unget_reg(reg);
|
|
return (w);
|
|
}
|
|
|
|
/*
|
|
* prolog and epilog not as "optimized" as one would like, but the
|
|
* problem of overallocating stack space to save callee save registers
|
|
* exists on all ports, and is still a todo to use a variable
|
|
* stack_framesize
|
|
* value, what would cause needing to patch some calls, most likely
|
|
* the offset of jit_arg* of stack arguments.
|
|
*/
|
|
static void
|
|
_prolog(jit_state_t *_jit, jit_node_t *node)
|
|
{
|
|
if (_jitc->function->define_frame || _jitc->function->assume_frame) {
|
|
jit_int32_t frame = -_jitc->function->frame;
|
|
assert(_jitc->function->self.aoff >= frame);
|
|
if (_jitc->function->assume_frame)
|
|
return;
|
|
_jitc->function->self.aoff = frame;
|
|
}
|
|
_jitc->function->stack = ((_jitc->function->self.alen -
|
|
/* align stack at 16 bytes */
|
|
_jitc->function->self.aoff) + 15) & -16;
|
|
STPI_POS(FP_REGNO, LR_REGNO, SP_REGNO, -(stack_framesize >> 3));
|
|
MOV_XSP(FP_REGNO, SP_REGNO);
|
|
#define SPILL(L, R, O) \
|
|
do { \
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _R##L)) { \
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _R##R)) \
|
|
STPI(L, R, SP_REGNO, O); \
|
|
else \
|
|
STRI(L, SP_REGNO, O); \
|
|
} \
|
|
else if (jit_regset_tstbit(&_jitc->function->regset, _R##R)) \
|
|
STRI(R, SP_REGNO, O + 1); \
|
|
} while (0)
|
|
SPILL(19, 20, 2);
|
|
SPILL(21, 22, 4);
|
|
SPILL(23, 24, 6);
|
|
SPILL(25, 26, 8);
|
|
SPILL(27, 28, 10);
|
|
#undef SPILL
|
|
#define SPILL(R, O) \
|
|
do { \
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _V##R)) \
|
|
stxi_d(O, SP_REGNO, R); \
|
|
} while (0)
|
|
SPILL( 8, 96);
|
|
SPILL( 9, 104);
|
|
SPILL(10, 112);
|
|
SPILL(11, 120);
|
|
SPILL(12, 128);
|
|
SPILL(13, 136);
|
|
SPILL(14, 144);
|
|
SPILL(15, 152);
|
|
#undef SPILL
|
|
if (_jitc->function->stack)
|
|
subi(SP_REGNO, SP_REGNO, _jitc->function->stack);
|
|
}
|
|
|
|
static void
|
|
_epilog(jit_state_t *_jit, jit_node_t *node)
|
|
{
|
|
if (_jitc->function->assume_frame)
|
|
return;
|
|
if (_jitc->function->stack)
|
|
MOV_XSP(SP_REGNO, FP_REGNO);
|
|
#define LOAD(L, R, O) \
|
|
do { \
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _R##L)) { \
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _R##R)) \
|
|
LDPI(L, R, SP_REGNO, O); \
|
|
else \
|
|
LDRI(L, SP_REGNO, O); \
|
|
} \
|
|
else if (jit_regset_tstbit(&_jitc->function->regset, _R##R)) \
|
|
LDRI(R, SP_REGNO, O + 1); \
|
|
} while (0)
|
|
LOAD(19, 20, 2);
|
|
LOAD(21, 22, 4);
|
|
LOAD(23, 24, 6);
|
|
LOAD(25, 26, 8);
|
|
LOAD(27, 28, 10);
|
|
#undef LOAD
|
|
#define LOAD(R, O) \
|
|
do { \
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _V##R)) \
|
|
ldxi_d(R, SP_REGNO, O); \
|
|
} while (0)
|
|
LOAD( 8, 96);
|
|
LOAD( 9, 104);
|
|
LOAD(10, 112);
|
|
LOAD(11, 120);
|
|
LOAD(12, 128);
|
|
LOAD(13, 136);
|
|
LOAD(14, 144);
|
|
LOAD(15, 152);
|
|
#undef LOAD
|
|
LDPI_PRE(FP_REGNO, LR_REGNO, SP_REGNO, stack_framesize >> 3);
|
|
RET();
|
|
}
|
|
|
|
static void
|
|
_patch_at(jit_state_t *_jit, jit_word_t instr, jit_word_t label)
|
|
{
|
|
instr_t i;
|
|
jit_word_t d;
|
|
jit_int32_t fc, ff, ffc;
|
|
union {
|
|
jit_int32_t *i;
|
|
jit_word_t w;
|
|
} u;
|
|
u.w = instr;
|
|
i.w = u.i[0];
|
|
fc = i.w & 0xfc000000;
|
|
ff = i.w & 0xff000000;
|
|
ffc = i.w & 0xffc00000;
|
|
if (fc == A64_B || fc == A64_BL) {
|
|
d = (label - instr) >> 2;
|
|
assert(d >= -33554432 && d <= 33554431);
|
|
i.imm26.b = d;
|
|
u.i[0] = i.w;
|
|
}
|
|
else if (ff == A64_B_C || ff == (A64_CBZ|XS) || ff == (A64_CBNZ|XS)) {
|
|
d = (label - instr) >> 2;
|
|
assert(d >= -262148 && d <= 262143);
|
|
i.imm19.b = d;
|
|
u.i[0] = i.w;
|
|
}
|
|
else if (ffc == (A64_MOVZ|XS)) {
|
|
i.imm16.b = label;
|
|
u.i[0] = i.w;
|
|
i.w = u.i[1];
|
|
assert((i.w & 0xffe00000) == (A64_MOVK|XS|MOVI_LSL_16));
|
|
i.imm16.b = label >> 16;
|
|
u.i[1] = i.w;
|
|
i.w = u.i[2];
|
|
assert((i.w & 0xffe00000) == (A64_MOVK|XS|MOVI_LSL_32));
|
|
i.imm16.b = label >> 32;
|
|
u.i[2] = i.w;
|
|
i.w = u.i[3];
|
|
assert((i.w & 0xffe00000) == (A64_MOVK|XS|MOVI_LSL_48));
|
|
i.imm16.b = label >> 48;
|
|
u.i[3] = i.w;
|
|
}
|
|
else
|
|
abort();
|
|
}
|
|
#endif
|