mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-02 21:10:27 +02:00
* libguile/lightning/: New directory, made by the following commands: git remote add lightning https://git.savannah.gnu.org/git/lightning.git git merge -s ours --no-commit --allow-unrelated-histories lightning/master git read-tree --prefix=libguile/lightning/ -u lightning/master In theory we will be able to update via: git merge -s subtree lightning/master
2446 lines
72 KiB
C
2446 lines
72 KiB
C
/*
|
|
* Copyright (C) 2013-2017 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 ldr(r0,r1) ldr_l(r0,r1)
|
|
# define ldxr(r0,r1,r2) ldxr_l(r0,r1,r2)
|
|
# 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_us(r0,r1) _htonr_us(_jit,r0,r1)
|
|
static void _htonr_us(jit_state_t*,jit_int32_t,jit_int32_t);
|
|
# define htonr_ui(r0,r1) _htonr_ui(_jit,r0,r1)
|
|
static void _htonr_ui(jit_state_t*,jit_int32_t,jit_int32_t);
|
|
# define htonr_ul(r0,r1) REV(r0,r1)
|
|
# else
|
|
# define htonr_us(r0,r1) extr_us(r0,r1)
|
|
# define htonr_ui(r0,r1) extr_ui(r0,r1)
|
|
# define htonr_ul(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 vastart(r0) _vastart(_jit, r0)
|
|
static void _vastart(jit_state_t*, jit_int32_t);
|
|
# define vaarg(r0, r1) _vaarg(_jit, r0, r1)
|
|
static void _vaarg(jit_state_t*, jit_int32_t, jit_int32_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);
|
|
}
|
|
}
|
|
}
|
|
|
|
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
static void
|
|
_htonr_us(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
htonr_ul(r0, r1);
|
|
rshi_u(r0, r0, 48);
|
|
}
|
|
|
|
static void
|
|
_htonr_ui(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
htonr_ul(r0, r1);
|
|
rshi_u(r0, r0, 32);
|
|
}
|
|
#endif
|
|
|
|
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), r0, 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), r0, 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), r0, 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), r0, 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)
|
|
{
|
|
jit_int32_t reg;
|
|
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;
|
|
}
|
|
if (_jitc->function->allocar)
|
|
_jitc->function->self.aoff &= -16;
|
|
_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);
|
|
if (_jitc->function->allocar) {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), _jitc->function->self.aoff);
|
|
stxi_i(_jitc->function->aoffoff, FP_REGNO, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
|
|
if (_jitc->function->self.call & jit_call_varargs) {
|
|
/* Save gp registers in the save area, if any is a vararg */
|
|
for (reg = 8 - _jitc->function->vagp / -8;
|
|
jit_arg_reg_p(reg); ++reg)
|
|
stxi(_jitc->function->vaoff + offsetof(jit_va_list_t, x0) +
|
|
reg * 8, FP_REGNO, rn(JIT_RA0 - reg));
|
|
|
|
for (reg = 8 - _jitc->function->vafp / -16;
|
|
jit_arg_f_reg_p(reg); ++reg)
|
|
/* Save fp registers in the save area, if any is a vararg */
|
|
/* Note that the full 16 byte register is not saved, because
|
|
* lightning only handles float and double, and, while
|
|
* attempting to provide a va_list compatible pointer as
|
|
* jit_va_start return, does not guarantee it (on all ports). */
|
|
stxi_d(_jitc->function->vaoff + offsetof(jit_va_list_t, q0) +
|
|
reg * 16 + offsetof(jit_qreg_t, l), FP_REGNO, rn(_V0 - reg));
|
|
}
|
|
}
|
|
|
|
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
|
|
_vastart(jit_state_t *_jit, jit_int32_t r0)
|
|
{
|
|
jit_int32_t reg;
|
|
|
|
assert(_jitc->function->self.call & jit_call_varargs);
|
|
|
|
/* Return jit_va_list_t in the register argument */
|
|
addi(r0, FP_REGNO, _jitc->function->vaoff);
|
|
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
|
|
/* Initialize stack pointer to the first stack argument. */
|
|
addi(rn(reg), FP_REGNO, _jitc->function->self.size);
|
|
stxi(offsetof(jit_va_list_t, stack), r0, rn(reg));
|
|
|
|
/* Initialize gp top pointer to the first stack argument. */
|
|
addi(rn(reg), r0, va_gp_top_offset);
|
|
stxi(offsetof(jit_va_list_t, gptop), r0, rn(reg));
|
|
|
|
/* Initialize fp top pointer to the first stack argument. */
|
|
addi(rn(reg), r0, va_fp_top_offset);
|
|
stxi(offsetof(jit_va_list_t, fptop), r0, rn(reg));
|
|
|
|
/* Initialize gp offset in the save area. */
|
|
movi(rn(reg), _jitc->function->vagp);
|
|
stxi_i(offsetof(jit_va_list_t, gpoff), r0, rn(reg));
|
|
|
|
/* Initialize fp offset in the save area. */
|
|
movi(rn(reg), _jitc->function->vafp);
|
|
stxi_i(offsetof(jit_va_list_t, fpoff), r0, rn(reg));
|
|
|
|
jit_unget_reg(reg);
|
|
}
|
|
|
|
static void
|
|
_vaarg(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
jit_word_t ge_code;
|
|
jit_word_t lt_code;
|
|
jit_int32_t rg0, rg1;
|
|
|
|
assert(_jitc->function->self.call & jit_call_varargs);
|
|
|
|
rg0 = jit_get_reg(jit_class_gpr);
|
|
rg1 = jit_get_reg(jit_class_gpr);
|
|
|
|
/* Load the gp offset in save area in the first temporary. */
|
|
ldxi_i(rn(rg0), r1, offsetof(jit_va_list_t, gpoff));
|
|
|
|
/* Jump over if there are no remaining arguments in the save area. */
|
|
ge_code = bgei(_jit->pc.w, rn(rg0), 0);
|
|
|
|
/* Load the gp save pointer in the second temporary. */
|
|
ldxi(rn(rg1), r1, offsetof(jit_va_list_t, gptop));
|
|
|
|
/* Load the vararg argument in the first argument. */
|
|
ldxr(r0, rn(rg1), rn(rg0));
|
|
|
|
/* Update the gp offset. */
|
|
addi(rn(rg0), rn(rg0), 8);
|
|
stxi_i(offsetof(jit_va_list_t, gpoff), r1, rn(rg0));
|
|
|
|
/* Will only need one temporary register below. */
|
|
jit_unget_reg(rg1);
|
|
|
|
/* Jump over overflow code. */
|
|
lt_code = jmpi_p(_jit->pc.w);
|
|
|
|
/* Where to land if argument is in overflow area. */
|
|
patch_at(ge_code, _jit->pc.w);
|
|
|
|
/* Load stack pointer. */
|
|
ldxi(rn(rg0), r1, offsetof(jit_va_list_t, stack));
|
|
|
|
/* Load argument. */
|
|
ldr(r0, rn(rg0));
|
|
|
|
/* Update stack pointer. */
|
|
addi(rn(rg0), rn(rg0), 8);
|
|
stxi(offsetof(jit_va_list_t, stack), r1, rn(rg0));
|
|
|
|
/* Where to land if argument is in gp save area. */
|
|
patch_at(lt_code, _jit->pc.w);
|
|
|
|
jit_unget_reg(rg0);
|
|
}
|
|
|
|
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
|