1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-02 13:00:26 +02:00
guile/libguile/lightning/lib/jit_aarch64-cpu.c
Andy Wingo 40aafa5279 Merge GNU lightning to libguile/lightning
* 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
2018-06-30 10:54:39 +02:00

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