mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-01 20:30:28 +02:00
* check/alu_rsb.ok, check/alu_rsb.tst: New files implementing tests for jit_rsb*. * check/Makefile.am, check/lightning.c, include/lightning.h, lib/jit_aarch64-cpu.c, lib/jit_aarch64-fpu.c, lib/jit_aarch64-sz.c, lib/jit_aarch64.c, lib/jit_alpha-cpu.c, lib/jit_alpha-fpu.c, lib/jit_alpha-sz.c, lib/jit_alpha.c, lib/jit_arm-cpu.c, lib/jit_arm-swf.c, lib/jit_arm-sz.c, lib/jit_arm-vfp.c, lib/jit_arm.c, lib/jit_hppa-cpu.c, lib/jit_hppa-fpu.c, lib/jit_hppa-sz.c, lib/jit_hppa.c, lib/jit_ia64-cpu.c, lib/jit_ia64-fpu.c, lib/jit_ia64-sz.c, lib/jit_ia64.c, lib/jit_mips-cpu.c, lib/jit_mips-fpu.c, lib/jit_mips-sz.c, lib/jit_mips.c, lib/jit_names.c, lib/jit_ppc-cpu.c, lib/jit_ppc-fpu.c, lib/jit_ppc-sz.c, lib/jit_ppc.c, lib/jit_s390x-cpu.c, lib/jit_s390x-fpu.c, lib/jit_s390x-sz.c, lib/jit_s390x.c, lib/jit_sparc-cpu.c, lib/jit_sparc-fpu.c, lib/jit_sparc-sz.c, lib/jit_sparc.c, lib/jit_x86-cpu.c, lib/jit_x86-sse.c, lib/jit_x86-sz.c, lib/jit_x86-x87.c, lib/jit_x86.c, lib/lightning.c: Implement jit_rsb*. This was a missing lightning 1.x interface, that on most backends is synthesized, but on a few backends (hppa and ia64), it can generate better code as on those there is, or the only instruction with an immediate is in "rsb" format (left operand).
3526 lines
89 KiB
C
3526 lines
89 KiB
C
/*
|
|
* Copyright (C) 2012, 2013 Free Software Foundation, Inc.
|
|
*
|
|
* This file is part of GNU lightning.
|
|
*
|
|
* GNU lightning is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU Lesser General Public License as published
|
|
* by the Free Software Foundation; either version 3, or (at your option)
|
|
* any later version.
|
|
*
|
|
* GNU lightning is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
|
* License for more details.
|
|
*
|
|
* Authors:
|
|
* Paulo Cesar Pereira de Andrade
|
|
*/
|
|
|
|
/* avoid using it due to partial stalls */
|
|
#define USE_INC_DEC 0
|
|
|
|
#if PROTO
|
|
# if __WORDSIZE == 32
|
|
# define ldi(u, v) ldi_i(u, v)
|
|
# define ldxi(u, v, w) ldxi_i(u, v, w)
|
|
# define sti(u, v) sti_i(u, v)
|
|
# define stxi(u, v, w) stxi_i(u, v, w)
|
|
# define can_sign_extend_int_p(im) 1
|
|
# define can_zero_extend_int_p(im) 1
|
|
# define fits_uint32_p(im) 1
|
|
# define reg8_p(rn) \
|
|
((rn) >= _RAX_REGNO && (rn) <= _RBX_REGNO)
|
|
# else
|
|
# define ldi(u, v) ldi_l(u, v)
|
|
# define ldxi(u, v, w) ldxi_l(u, v, w)
|
|
# define sti(u, v) sti_l(u, v)
|
|
# define stxi(u, v, w) stxi_l(u, v, w)
|
|
# define can_sign_extend_int_p(im) \
|
|
(((im) >= 0 && (long)(im) <= 0x7fffffffL) || \
|
|
((im) < 0 && (long)(im) > -0x80000000L))
|
|
# define can_zero_extend_int_p(im) \
|
|
((im) >= 0 && (im) < 0x80000000L)
|
|
# define fits_uint32_p(im) (((im) & 0xffffffff00000000L) == 0)
|
|
# if __CYGWIN__
|
|
# define reg8_p(rn) \
|
|
(r7(rn) >= _RAX_REGNO && r7(rn) <= _RBX_REGNO)
|
|
# else
|
|
# define reg8_p(rn) 1
|
|
# endif
|
|
# endif
|
|
# define _RAX_REGNO 0
|
|
# define _RCX_REGNO 1
|
|
# define _RDX_REGNO 2
|
|
# define _RBX_REGNO 3
|
|
# define _RSP_REGNO 4
|
|
# define _RBP_REGNO 5
|
|
# define _RSI_REGNO 6
|
|
# define _RDI_REGNO 7
|
|
# define _R8_REGNO 8
|
|
# define _R9_REGNO 9
|
|
# define _R10_REGNO 10
|
|
# define _R11_REGNO 11
|
|
# define _R12_REGNO 12
|
|
# define _R13_REGNO 13
|
|
# define _R14_REGNO 14
|
|
# define _R15_REGNO 15
|
|
# define r7(reg) ((reg) & 7)
|
|
# define r8(reg) ((reg) & 15)
|
|
# define _SCL1 0x00
|
|
# define _SCL2 0x01
|
|
# define _SCL4 0x02
|
|
# define _SCL8 0x03
|
|
# define X86_ADD 0
|
|
# define X86_OR 1 << 3
|
|
# define X86_ADC 2 << 3
|
|
# define X86_SBB 3 << 3
|
|
# define X86_AND 4 << 3
|
|
# define X86_SUB 5 << 3
|
|
# define X86_XOR 6 << 3
|
|
# define X86_CMP 7 << 3
|
|
# define X86_ROL 0
|
|
# define X86_ROR 1
|
|
# define X86_RCL 2
|
|
# define X86_RCR 3
|
|
# define X86_SHL 4
|
|
# define X86_SHR 5
|
|
# define X86_SAR 7
|
|
# define X86_NOT 2
|
|
# define X86_NEG 3
|
|
# define X86_MUL 4
|
|
# define X86_IMUL 5
|
|
# define X86_DIV 6
|
|
# define X86_IDIV 7
|
|
# define X86_CC_O 0x0
|
|
# define X86_CC_NO 0x1
|
|
# define X86_CC_NAE 0x2
|
|
# define X86_CC_B 0x2
|
|
# define X86_CC_C 0x2
|
|
# define X86_CC_AE 0x3
|
|
# define X86_CC_NB 0x3
|
|
# define X86_CC_NC 0x3
|
|
# define X86_CC_E 0x4
|
|
# define X86_CC_Z 0x4
|
|
# define X86_CC_NE 0x5
|
|
# define X86_CC_NZ 0x5
|
|
# define X86_CC_BE 0x6
|
|
# define X86_CC_NA 0x6
|
|
# define X86_CC_A 0x7
|
|
# define X86_CC_NBE 0x7
|
|
# define X86_CC_S 0x8
|
|
# define X86_CC_NS 0x9
|
|
# define X86_CC_P 0xa
|
|
# define X86_CC_PE 0xa
|
|
# define X86_CC_NP 0xb
|
|
# define X86_CC_PO 0xb
|
|
# define X86_CC_L 0xc
|
|
# define X86_CC_NGE 0xc
|
|
# define X86_CC_GE 0xd
|
|
# define X86_CC_NL 0xd
|
|
# define X86_CC_LE 0xe
|
|
# define X86_CC_NG 0xe
|
|
# define X86_CC_G 0xf
|
|
# define X86_CC_NLE 0xf
|
|
# define mrm(md, r, m) *_jit->pc.uc++ = (md<<6) | (r<<3) | m
|
|
# define sib(sc, i, b) *_jit->pc.uc++ = (sc<<6) | (i<<3) | b
|
|
# define ic(c) *_jit->pc.uc++ = c
|
|
# define is(s) *_jit->pc.us++ = s
|
|
# define ii(i) *_jit->pc.ui++ = i
|
|
# if __WORDSIZE == 64
|
|
# define il(l) *_jit->pc.ul++ = l
|
|
# endif
|
|
# define patch_abs(instr, label) \
|
|
*(jit_word_t *)(instr - sizeof(jit_word_t)) = label
|
|
# define patch_rel(instr, label) \
|
|
*(jit_int32_t *)(instr - 4) = label - instr
|
|
# define patch_rel_char(instr, label) \
|
|
*(jit_int8_t *)(instr - 1) = label - instr
|
|
# define rex(l, w, r, x, b) _rex(_jit, l, w, r, x, b)
|
|
static void
|
|
_rex(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t);
|
|
# define rx(rd, md, rb, ri, ms) _rx(_jit, rd, md, rb, ri, ms)
|
|
static void
|
|
_rx(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t);
|
|
# define nop(n) _nop(_jit, n)
|
|
static void _nop(jit_state_t*, jit_int32_t);
|
|
# define emms() is(0x770f)
|
|
# define lea(md, rb, ri, ms, rd) _lea(_jit, md, rb, ri, ms, rd)
|
|
static void
|
|
_lea(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t);
|
|
# define pushr(r0) _pushr(_jit, r0)
|
|
static void _pushr(jit_state_t*, jit_int32_t) maybe_unused;
|
|
# define popr(r0) _popr(_jit, r0)
|
|
static void _popr(jit_state_t*, jit_int32_t) maybe_unused;
|
|
# define xchgr(r0, r1) _xchgr(_jit, r0, r1)
|
|
static void _xchgr(jit_state_t*, jit_int32_t, jit_int32_t);
|
|
# define testr(r0, r1) _testr(_jit, r0, r1)
|
|
static void _testr(jit_state_t*, jit_int32_t, jit_int32_t);
|
|
# define testi(r0, i0) _testi(_jit, r0, i0)
|
|
static void _testi(jit_state_t*, jit_int32_t, jit_word_t);
|
|
# define cc(code, r0) _cc(_jit, code, r0)
|
|
static void _cc(jit_state_t*, jit_int32_t, jit_int32_t);
|
|
# define icmpr(r0, r1) alur(X86_CMP, r0, r1)
|
|
# define alur(code, r0, r1) _alur(_jit, code, r0, r1)
|
|
static void _alur(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
|
|
# define icmpi(r0, i0) alui(X86_CMP, r0, i0)
|
|
# define alui(code, r0, i0) _alui(_jit, code, r0, i0)
|
|
static void _alui(jit_state_t*, jit_int32_t, jit_int32_t, jit_word_t);
|
|
# define iaddr(r0, r1) alur(X86_ADD, r0, r1)
|
|
# define save(r0) _save(_jit, r0)
|
|
static void _save(jit_state_t*, jit_int32_t);
|
|
# define load(r0) _load(_jit, r0)
|
|
static void _load(jit_state_t*, jit_int32_t);
|
|
# define addr(r0, r1, r2) _addr(_jit, r0, r1, r2)
|
|
static void _addr(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
|
|
# define iaddi(r0, i0) alui(X86_ADD, r0, i0)
|
|
# 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) _addcr(_jit, r0, r1, r2)
|
|
static void _addcr(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
|
|
#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 iaddxr(r0, r1) alur(X86_ADC, r0, r1)
|
|
# define addxr(r0, r1, r2) _addxr(_jit, r0, r1, r2)
|
|
static void _addxr(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
|
|
# define iaddxi(r0, i0) alui(X86_ADC, r0, i0)
|
|
# 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 isubr(r0, r1) alur(X86_SUB, r0, r1)
|
|
# define subr(r0, r1, r2) _subr(_jit, r0, r1, r2)
|
|
static void _subr(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
|
|
# define isubi(r0, i0) alui(X86_SUB, r0, i0)
|
|
# 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) _subcr(_jit, r0, r1, r2)
|
|
static void _subcr(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t);
|
|
# 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 isubxr(r0, r1) alur(X86_SBB, r0, r1)
|
|
# define subxr(r0, r1, r2) _subxr(_jit, r0, r1, r2)
|
|
static void _subxr(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t);
|
|
# define isubxi(r0, i0) alui(X86_SBB, r0, i0)
|
|
# 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 imulr(r0, r1) _imulr(_jit, r0, r1)
|
|
static void _imulr(jit_state_t*, jit_int32_t, jit_int32_t);
|
|
# define imuli(r0, r1, i0) _imuli(_jit, r0, r1, i0)
|
|
static void _imuli(jit_state_t*, jit_int32_t, jit_int32_t, jit_word_t);
|
|
# define mulr(r0, r1, r2) _mulr(_jit, r0, r1, r2)
|
|
static void _mulr(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
|
|
# 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 umulr(r0) unr(X86_IMUL, r0)
|
|
# define umulr_u(r0) unr(X86_MUL, r0)
|
|
# define qmulr(r0, r1, r2, r3) _iqmulr(_jit, r0, r1, r2, r3, 1)
|
|
# define qmulr_u(r0, r1, r2, r3) _iqmulr(_jit, r0, r1, r2, r3, 0)
|
|
# define iqmulr(r0, r1, r2, r3, sign) _iqmulr(_jit, r0, r1, r2, r3, sign)
|
|
static void _iqmulr(jit_state_t*, jit_int32_t, jit_int32_t,
|
|
jit_int32_t,jit_int32_t, jit_bool_t);
|
|
# define qmuli(r0, r1, r2, i0) _iqmuli(_jit, r0, r1, r2, i0, 1)
|
|
# define qmuli_u(r0, r1, r2, i0) _iqmuli(_jit, r0, r1, r2, i0, 0)
|
|
# define iqmuli(r0, r1, r2, i0, sign) _iqmuli(_jit, r0, r1, r2, i0, sign)
|
|
static void _iqmuli(jit_state_t*, jit_int32_t, jit_int32_t,
|
|
jit_int32_t,jit_word_t, jit_bool_t);
|
|
# define sign_extend_rdx_rax() _sign_extend_rdx_rax(_jit)
|
|
static void _sign_extend_rdx_rax(jit_state_t*);
|
|
# define idivr(r0) unr(X86_IDIV, r0)
|
|
# define idivr_u(r0) unr(X86_DIV, r0)
|
|
# define divremr(r0, r1, r2, i0, i1) _divremr(_jit, r0, r1, r2, i0, i1)
|
|
static void
|
|
_divremr(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t,
|
|
jit_bool_t,jit_bool_t);
|
|
# define divremi(r0, r1, i0, i1, i2) _divremi(_jit, r0, r1, i0, i1, i2)
|
|
static void
|
|
_divremi(jit_state_t*,jit_int32_t,jit_int32_t,jit_word_t,jit_bool_t,jit_bool_t);
|
|
# define divr(r0, r1, r2) divremr(r0, r1, r2, 1, 1)
|
|
# define divi(r0, r1, i0) divremi(r0, r1, i0, 1, 1)
|
|
# define divr_u(r0, r1, r2) divremr(r0, r1, r2, 0, 1)
|
|
# define divi_u(r0, r1, i0) divremi(r0, r1, i0, 0, 1)
|
|
# define qdivr(r0, r1, r2, r3) _iqdivr(_jit, r0, r1, r2, r3, 1)
|
|
# define qdivr_u(r0, r1, r2, r3) _iqdivr(_jit, r0, r1, r2, r3, 0)
|
|
# define iqdivr(r0, r1, r2, r3, sign) _iqdivr(_jit, r0, r1, r2, r3, sign)
|
|
static void _iqdivr(jit_state_t*, jit_int32_t, jit_int32_t,
|
|
jit_int32_t,jit_int32_t, jit_bool_t);
|
|
# define qdivi(r0, r1, r2, i0) _iqdivi(_jit, r0, r1, r2, i0, 1)
|
|
# define qdivi_u(r0, r1, r2, i0) _iqdivi(_jit, r0, r1, r2, i0, 0)
|
|
# define iqdivi(r0, r1, r2, i0, sign) _iqdivi(_jit, r0, r1, r2, i0, sign)
|
|
static void _iqdivi(jit_state_t*, jit_int32_t, jit_int32_t,
|
|
jit_int32_t,jit_word_t, jit_bool_t);
|
|
# define remr(r0, r1, r2) divremr(r0, r1, r2, 1, 0)
|
|
# define remi(r0, r1, i0) divremi(r0, r1, i0, 1, 0)
|
|
# define remr_u(r0, r1, r2) divremr(r0, r1, r2, 0, 0)
|
|
# define remi_u(r0, r1, i0) divremi(r0, r1, i0, 0, 0)
|
|
# define iandr(r0, r1) alur(X86_AND, r0, r1)
|
|
# define andr(r0, r1, r2) _andr(_jit, r0, r1, r2)
|
|
static void _andr(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t);
|
|
# define iandi(r0, i0) alui(X86_AND, r0, i0)
|
|
# 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 iorr(r0, r1) alur(X86_OR, r0, r1)
|
|
# define orr(r0, r1, r2) _orr(_jit, r0, r1, r2)
|
|
static void _orr(jit_state_t*, jit_int32_t,jit_int32_t,jit_int32_t);
|
|
# define iori(r0, i0) alui(X86_OR, r0, i0)
|
|
# 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 ixorr(r0, r1) alur(X86_XOR, r0, r1)
|
|
# define xorr(r0, r1, r2) _xorr(_jit, r0, r1, r2)
|
|
static void _xorr(jit_state_t*, jit_int32_t,jit_int32_t,jit_int32_t);
|
|
# define ixori(r0, i0) alui(X86_XOR, r0, i0)
|
|
# 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 irotshr(code, r0) _irotshr(_jit, code, r0)
|
|
static void _irotshr(jit_state_t*, jit_int32_t, jit_int32_t);
|
|
# define rotshr(code, r0, r1, r2) _rotshr(_jit, code, r0, r1, r2)
|
|
static void
|
|
_rotshr(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t);
|
|
# define irotshi(code, r0, i0) _irotshi(_jit, code, r0, i0)
|
|
static void _irotshi(jit_state_t*, jit_int32_t, jit_int32_t, jit_word_t);
|
|
# define rotshi(code, r0, r1, i0) _rotshi(_jit, code, r0, r1, i0)
|
|
static void
|
|
_rotshi(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t,jit_word_t);
|
|
# define lshr(r0, r1, r2) rotshr(X86_SHL, 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) rotshr(X86_SAR, r0, r1, r2)
|
|
# define rshi(r0, r1, i0) rotshi(X86_SAR, r0, r1, i0)
|
|
# define rshr_u(r0, r1, r2) rotshr(X86_SHR, r0, r1, r2)
|
|
# define rshi_u(r0, r1, i0) rotshi(X86_SHR, r0, r1, i0)
|
|
# define unr(code, r0) _unr(_jit, code, r0)
|
|
static void _unr(jit_state_t*, jit_int32_t, jit_int32_t);
|
|
# define inegr(r0) unr(X86_NEG, r0)
|
|
# define negr(r0, r1) _negr(_jit, r0, r1)
|
|
static void _negr(jit_state_t*, jit_int32_t, jit_int32_t);
|
|
# define icomr(r0) unr(X86_NOT, r0)
|
|
# define comr(r0, r1) _comr(_jit, r0, r1)
|
|
static void _comr(jit_state_t*, jit_int32_t, jit_int32_t);
|
|
# if USE_INC_DEC
|
|
# define incr(r0, r1) _incr(_jit, r0, r1)
|
|
static void _incr(jit_state_t*, jit_int32_t, jit_int32_t);
|
|
# define decr(r0, r1) _decr(_jit, r0, r1)
|
|
static void _decr(jit_state_t*, jit_int32_t, jit_int32_t);
|
|
# endif
|
|
# define cr(code, r0, r1, r2) _cr(_jit, code, r0, r1, r2)
|
|
static void
|
|
_cr(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t, jit_int32_t);
|
|
# define ci(code, r0, r1, i0) _ci(_jit, code, r0, r1, i0)
|
|
static void
|
|
_ci(jit_state_t *_jit, jit_int32_t, jit_int32_t, jit_int32_t, jit_word_t);
|
|
# define ci0(code, r0, r1) _ci0(_jit, code, r0, r1)
|
|
static void _ci0(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
|
|
# define ltr(r0, r1, r2) _ltr(_jit, r0, r1, r2)
|
|
static void _ltr(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
|
|
# define lti(r0, r1, i0) _lti(_jit, r0, r1, i0)
|
|
static void _lti(jit_state_t*, jit_int32_t, jit_int32_t, jit_word_t);
|
|
# define ltr_u(r0, r1, r2) _ltr_u(_jit, r0, r1, r2)
|
|
static void _ltr_u(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
|
|
# define lti_u(r0, r1, i0) ci(X86_CC_B, r0, r1, i0)
|
|
# define ler(r0, r1, r2) _ler(_jit, r0, r1, r2)
|
|
static void _ler(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
|
|
# define lei(r0, r1, i0) ci(X86_CC_LE, r0, r1, i0)
|
|
# define ler_u(r0, r1, r2) _ler_u(_jit, r0, r1, r2)
|
|
static void _ler_u(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
|
|
# define lei_u(r0, r1, i0) _lei_u(_jit, r0, r1, i0)
|
|
static void _lei_u(jit_state_t*, jit_int32_t, jit_int32_t, jit_word_t);
|
|
# define eqr(r0, r1, r2) _eqr(_jit, r0, r1, r2)
|
|
static void _eqr(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
|
|
# define eqi(r0, r1, i0) _eqi(_jit, r0, r1, i0)
|
|
static void _eqi(jit_state_t*, jit_int32_t, jit_int32_t, jit_word_t);
|
|
# define ger(r0, r1, r2) _ger(_jit, r0, r1, r2)
|
|
static void _ger(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
|
|
# define gei(r0, r1, i0) _gei(_jit, r0, r1, i0)
|
|
static void _gei(jit_state_t*, jit_int32_t, jit_int32_t, jit_word_t);
|
|
# define ger_u(r0, r1, r2) _ger_u(_jit, r0, r1, r2)
|
|
static void _ger_u(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
|
|
# define gei_u(r0, r1, i0) _gei_u(_jit, r0, r1, i0)
|
|
static void _gei_u(jit_state_t*, jit_int32_t, jit_int32_t, jit_word_t);
|
|
# define gtr(r0, r1, r2) _gtr(_jit, r0, r1, r2)
|
|
static void _gtr(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
|
|
# define gti(r0, r1, i0) _ci(_jit, X86_CC_G, r0, r1, i0)
|
|
# define gtr_u(r0, r1, r2) _gtr_u(_jit, r0, r1, r2)
|
|
static void _gtr_u(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
|
|
# define gti_u(r0, r1, i0) _gti_u(_jit, r0, r1, i0)
|
|
static void _gti_u(jit_state_t*, jit_int32_t, jit_int32_t, jit_word_t);
|
|
# define ner(r0, r1, r2) _ner(_jit, r0, r1, r2)
|
|
static void _ner(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
|
|
# define nei(r0, r1, i0) _nei(_jit, r0, r1, i0)
|
|
static void _nei(jit_state_t*, jit_int32_t, jit_int32_t, jit_word_t);
|
|
# define movr(r0, r1) _movr(_jit, r0, r1)
|
|
static void _movr(jit_state_t*, jit_int32_t, jit_int32_t);
|
|
# define imovi(r0, i0) _imovi(_jit, r0, i0)
|
|
static void _imovi(jit_state_t*, jit_int32_t, jit_word_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 movcr(r0, r1) _movcr(_jit, r0, r1)
|
|
static void _movcr(jit_state_t*,jit_int32_t,jit_int32_t);
|
|
# define movcr_u(r0, r1) _movcr_u(_jit, r0, r1)
|
|
static void _movcr_u(jit_state_t*,jit_int32_t,jit_int32_t);
|
|
# define movsr(r0, r1) _movsr(_jit, r0, r1)
|
|
static void _movsr(jit_state_t*,jit_int32_t,jit_int32_t);
|
|
# define movsr_u(r0, r1) _movsr_u(_jit, r0, r1)
|
|
static void _movsr_u(jit_state_t*,jit_int32_t,jit_int32_t);
|
|
# if __WORDSIZE == 64
|
|
# define movir(r0, r1) _movir(_jit, r0, r1)
|
|
static void _movir(jit_state_t*,jit_int32_t,jit_int32_t);
|
|
# define movir_u(r0, r1) _movir_u(_jit, r0, r1)
|
|
static void _movir_u(jit_state_t*,jit_int32_t,jit_int32_t);
|
|
# endif
|
|
#define htonr(r0, r1) _htonr(_jit, r0, r1)
|
|
static void _htonr(jit_state_t*,jit_int32_t,jit_int32_t);
|
|
# define extr_c(r0, r1) _extr_c(_jit, r0, r1)
|
|
static void _extr_c(jit_state_t*,jit_int32_t,jit_int32_t);
|
|
# define extr_uc(r0, r1) _extr_uc(_jit, r0, r1)
|
|
static void _extr_uc(jit_state_t*,jit_int32_t,jit_int32_t);
|
|
# define extr_s(r0, r1) movsr(r0, r1)
|
|
# define extr_us(r0, r1) movsr_u(r0, r1)
|
|
# if __WORDSIZE == 64
|
|
# define extr_i(r0, r1) movir(r0, r1)
|
|
# define extr_ui(r0, r1) movir_u(r0, r1)
|
|
# endif
|
|
# define ldr_c(r0, r1) _ldr_c(_jit, r0, r1)
|
|
static void _ldr_c(jit_state_t*, jit_int32_t, jit_int32_t);
|
|
# 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) _ldr_s(_jit, r0, r1)
|
|
static void _ldr_s(jit_state_t*, jit_int32_t, jit_int32_t);
|
|
# 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) _ldr_i(_jit, r0, r1)
|
|
static void _ldr_i(jit_state_t*, jit_int32_t, jit_int32_t);
|
|
# define ldi_i(r0, i0) _ldi_i(_jit, r0, i0)
|
|
static void _ldi_i(jit_state_t*, jit_int32_t, jit_word_t);
|
|
# if __WORDSIZE == 64
|
|
# 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) _ldr_l(_jit, r0, r1)
|
|
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);
|
|
# endif
|
|
# 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) _ldxr_s(_jit, r0, r1, r2)
|
|
static void _ldxr_s(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
|
|
# 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) _ldxr_i(_jit, r0, r1, r2)
|
|
static void _ldxr_i(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
|
|
# 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);
|
|
# if __WORDSIZE == 64
|
|
# 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) _ldxr_l(_jit, r0, r1, r2)
|
|
static void _ldxr_l(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
|
|
# 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);
|
|
# endif
|
|
# define str_c(r0, r1) _str_c(_jit, r0, r1)
|
|
static void _str_c(jit_state_t*, jit_int32_t, jit_int32_t);
|
|
# 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) _str_s(_jit, r0, r1)
|
|
static void _str_s(jit_state_t*, jit_int32_t, jit_int32_t);
|
|
# 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) _str_i(_jit, r0, r1)
|
|
static void _str_i(jit_state_t*, jit_int32_t, jit_int32_t);
|
|
# define sti_i(i0, r0) _sti_i(_jit, i0, r0)
|
|
static void _sti_i(jit_state_t*, jit_word_t, jit_int32_t);
|
|
# if __WORDSIZE == 64
|
|
# define str_l(r0, r1) _str_l(_jit, r0, r1)
|
|
static void _str_l(jit_state_t*, jit_int32_t, jit_int32_t);
|
|
# define sti_l(i0, r0) _sti_l(_jit, i0, r0)
|
|
static void _sti_l(jit_state_t*, jit_word_t, jit_int32_t);
|
|
# endif
|
|
# define stxr_c(r0, r1, r2) _stxr_c(_jit, r0, r1, r2)
|
|
static void _stxr_c(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
|
|
# 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) _stxr_s(_jit, r0, r1, r2)
|
|
static void _stxr_s(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
|
|
# 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) _stxr_i(_jit, r0, r1, r2)
|
|
static void _stxr_i(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
|
|
# 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);
|
|
# if __WORDSIZE == 64
|
|
# define stxr_l(r0, r1, r2) _stxr_l(_jit, r0, r1, r2)
|
|
static void _stxr_l(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
|
|
# 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);
|
|
# endif
|
|
# define jcc(code, i0) _jcc(_jit, code, i0)
|
|
# define jo(i0) jcc(X86_CC_O, i0)
|
|
# define jno(i0) jcc(X86_CC_NO, i0)
|
|
# define jnae(i0) jcc(X86_CC_NAE, i0)
|
|
# define jb(i0) jcc(X86_CC_B, i0)
|
|
# define jc(i0) jcc(X86_CC_C, i0)
|
|
# define jae(i0) jcc(X86_CC_AE, i0)
|
|
# define jnb(i0) jcc(X86_CC_NB, i0)
|
|
# define jnc(i0) jcc(X86_CC_NC, i0)
|
|
# define je(i0) jcc(X86_CC_E, i0)
|
|
# define jz(i0) jcc(X86_CC_Z, i0)
|
|
# define jne(i0) jcc(X86_CC_NE, i0)
|
|
# define jnz(i0) jcc(X86_CC_NZ, i0)
|
|
# define jbe(i0) jcc(X86_CC_BE, i0)
|
|
# define jna(i0) jcc(X86_CC_NA, i0)
|
|
# define ja(i0) jcc(X86_CC_A, i0)
|
|
# define jnbe(i0) jcc(X86_CC_NBE, i0)
|
|
# define js(i0) jcc(X86_CC_S, i0)
|
|
# define jns(i0) jcc(X86_CC_NS, i0)
|
|
# define jp(i0) jcc(X86_CC_P, i0)
|
|
# define jpe(i0) jcc(X86_CC_PE, i0)
|
|
# define jnp(i0) jcc(X86_CC_NP, i0)
|
|
# define jpo(i0) jcc(X86_CC_PO, i0)
|
|
# define jl(i0) jcc(X86_CC_L, i0)
|
|
# define jnge(i0) jcc(X86_CC_NGE, i0)
|
|
# define jge(i0) jcc(X86_CC_GE, i0)
|
|
# define jnl(i0) jcc(X86_CC_NL, i0)
|
|
# define jle(i0) jcc(X86_CC_LE, i0)
|
|
# define jng(i0) jcc(X86_CC_NG, i0)
|
|
# define jg(i0) jcc(X86_CC_G, i0)
|
|
# define jnle(i0) jcc(X86_CC_NLE, i0)
|
|
static void _jcc(jit_state_t*, jit_int32_t, jit_word_t);
|
|
# define jccs(code, i0) _jccs(_jit, code, i0)
|
|
# define jos(i0) jccs(X86_CC_O, i0)
|
|
# define jnos(i0) jccs(X86_CC_NO, i0)
|
|
# define jnaes(i0) jccs(X86_CC_NAE, i0)
|
|
# define jbs(i0) jccs(X86_CC_B, i0)
|
|
# define jcs(i0) jccs(X86_CC_C, i0)
|
|
# define jaes(i0) jccs(X86_CC_AE, i0)
|
|
# define jnbs(i0) jccs(X86_CC_NB, i0)
|
|
# define jncs(i0) jccs(X86_CC_NC, i0)
|
|
# define jes(i0) jccs(X86_CC_E, i0)
|
|
# define jzs(i0) jccs(X86_CC_Z, i0)
|
|
# define jnes(i0) jccs(X86_CC_NE, i0)
|
|
# define jnzs(i0) jccs(X86_CC_NZ, i0)
|
|
# define jbes(i0) jccs(X86_CC_BE, i0)
|
|
# define jnas(i0) jccs(X86_CC_NA, i0)
|
|
# define jas(i0) jccs(X86_CC_A, i0)
|
|
# define jnbes(i0) jccs(X86_CC_NBE, i0)
|
|
# define jss(i0) jccs(X86_CC_S, i0)
|
|
# define jnss(i0) jccs(X86_CC_NS, i0)
|
|
# define jps(i0) jccs(X86_CC_P, i0)
|
|
# define jpes(i0) jccs(X86_CC_PE, i0)
|
|
# define jnps(i0) jccs(X86_CC_NP, i0)
|
|
# define jpos(i0) jccs(X86_CC_PO, i0)
|
|
# define jls(i0) jccs(X86_CC_L, i0)
|
|
# define jnges(i0) jccs(X86_CC_NGE, i0)
|
|
# define jges(i0) jccs(X86_CC_GE, i0)
|
|
# define jnls(i0) jccs(X86_CC_NL, i0)
|
|
# define jles(i0) jccs(X86_CC_LE, i0)
|
|
# define jngs(i0) jccs(X86_CC_NG, i0)
|
|
# define jgs(i0) jccs(X86_CC_G, i0)
|
|
# define jnles(i0) jccs(X86_CC_NLE, i0)
|
|
static void _jccs(jit_state_t*, jit_int32_t, jit_word_t);
|
|
# define jcr(code, i0, r0, r1) _jcr(_jit, code, i0, r0, r1)
|
|
static void _jcr(jit_state_t*,jit_int32_t,jit_word_t,jit_int32_t,jit_int32_t);
|
|
# define jci(code, i0, r0, i1) _jci(_jit, code, i0, r0, i1)
|
|
static void _jci(jit_state_t*,jit_int32_t,jit_word_t,jit_int32_t,jit_word_t);
|
|
# define jci0(code, i0, r0) _jci0(_jit, code, i0, r0)
|
|
static void _jci0(jit_state_t*, jit_int32_t, jit_word_t, jit_int32_t);
|
|
# define bltr(i0, r0, r1) _bltr(_jit, i0, r0, r1)
|
|
static jit_word_t _bltr(jit_state_t*, jit_word_t, jit_int32_t, jit_int32_t);
|
|
# define blti(i0, r0, i1) _blti(_jit, i0, r0, i1)
|
|
static jit_word_t _blti(jit_state_t*, jit_word_t, jit_int32_t, jit_word_t);
|
|
# define bltr_u(i0, r0, r1) _bltr_u(_jit, i0, r0, r1)
|
|
static jit_word_t _bltr_u(jit_state_t*, jit_word_t, jit_int32_t, jit_int32_t);
|
|
# define blti_u(i0, r0, i1) _blti_u(_jit, i0, r0, i1)
|
|
static jit_word_t _blti_u(jit_state_t*, jit_word_t, jit_int32_t, jit_word_t);
|
|
# define bler(i0, r0, r1) _bler(_jit, i0, r0, r1)
|
|
static jit_word_t _bler(jit_state_t*, jit_word_t, jit_int32_t, jit_int32_t);
|
|
# define blei(i0, r0, i1) _blei(_jit, i0, r0, i1)
|
|
static jit_word_t _blei(jit_state_t*, jit_word_t, jit_int32_t, jit_word_t);
|
|
# define bler_u(i0, r0, r1) _bler_u(_jit, i0, r0, r1)
|
|
static jit_word_t _bler_u(jit_state_t*, jit_word_t, jit_int32_t, jit_int32_t);
|
|
# define blei_u(i0, r0, i1) _blei_u(_jit, i0, r0, i1)
|
|
static jit_word_t _blei_u(jit_state_t*, jit_word_t, jit_int32_t, jit_word_t);
|
|
# define beqr(i0, r0, r1) _beqr(_jit, i0, r0, r1)
|
|
static jit_word_t _beqr(jit_state_t*, jit_word_t, jit_int32_t, jit_int32_t);
|
|
# 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) _bger(_jit, i0, r0, r1)
|
|
static jit_word_t _bger(jit_state_t*, jit_word_t, jit_int32_t, jit_int32_t);
|
|
# define bgei(i0, r0, i1) _bgei(_jit, i0, r0, i1)
|
|
static jit_word_t _bgei(jit_state_t*, jit_word_t, jit_int32_t, jit_word_t);
|
|
# define bger_u(i0, r0, r1) _bger_u(_jit, i0, r0, r1)
|
|
static jit_word_t _bger_u(jit_state_t*, jit_word_t, jit_int32_t, jit_int32_t);
|
|
# define bgei_u(i0, r0, i1) _bgei_u(_jit, i0, r0, i1)
|
|
static jit_word_t _bgei_u(jit_state_t*, jit_word_t, jit_int32_t, jit_word_t);
|
|
# define bgtr(i0, r0, r1) _bgtr(_jit, i0, r0, r1)
|
|
static jit_word_t _bgtr(jit_state_t*, jit_word_t, jit_int32_t, jit_int32_t);
|
|
# define bgti(i0, r0, i1) _bgti(_jit, i0, r0, i1)
|
|
static jit_word_t _bgti(jit_state_t*, jit_word_t, jit_int32_t, jit_word_t);
|
|
# define bgtr_u(i0, r0, r1) _bgtr_u(_jit, i0, r0, r1)
|
|
static jit_word_t _bgtr_u(jit_state_t*, jit_word_t, jit_int32_t, jit_int32_t);
|
|
# define bgti_u(i0, r0, i1) _bgti_u(_jit, i0, r0, i1)
|
|
static jit_word_t _bgti_u(jit_state_t*, jit_word_t, jit_int32_t, jit_word_t);
|
|
# define bner(i0, r0, r1) _bner(_jit, i0, r0, r1)
|
|
static jit_word_t _bner(jit_state_t*, jit_word_t, jit_int32_t, jit_int32_t);
|
|
# 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 bmsr(i0, r0, r1) _bmsr(_jit, i0, r0, r1)
|
|
static jit_word_t _bmsr(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
|
|
# define bmsi(i0, r0, i1) _bmsi(_jit, i0, r0, i1)
|
|
static jit_word_t _bmsi(jit_state_t*,jit_word_t,jit_int32_t,jit_word_t);
|
|
# define bmcr(i0, r0, r1) _bmcr(_jit, i0, r0, r1)
|
|
static jit_word_t _bmcr(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
|
|
# define bmci(i0, r0, i1) _bmci(_jit, i0, r0, i1)
|
|
static jit_word_t _bmci(jit_state_t*,jit_word_t,jit_int32_t,jit_word_t);
|
|
# define boaddr(i0, r0, r1) _boaddr(_jit, i0, r0, r1)
|
|
static jit_word_t _boaddr(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
|
|
# define boaddi(i0, r0, i1) _boaddi(_jit, i0, r0, i1)
|
|
static jit_word_t _boaddi(jit_state_t*,jit_word_t,jit_int32_t,jit_word_t);
|
|
# define boaddr_u(i0, r0, r1) _boaddr_u(_jit, i0, r0, r1)
|
|
static jit_word_t _boaddr_u(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
|
|
# define boaddi_u(i0, r0, i1) _boaddi_u(_jit, i0, r0, i1)
|
|
static jit_word_t _boaddi_u(jit_state_t*,jit_word_t,jit_int32_t,jit_word_t);
|
|
# define bxaddr(i0, r0, r1) _bxaddr(_jit, i0, r0, r1)
|
|
static jit_word_t _bxaddr(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
|
|
# define bxaddi(i0, r0, i1) _bxaddi(_jit, i0, r0, i1)
|
|
static jit_word_t _bxaddi(jit_state_t*,jit_word_t,jit_int32_t,jit_word_t);
|
|
# define bxaddr_u(i0, r0, r1) _bxaddr_u(_jit, i0, r0, r1)
|
|
static jit_word_t _bxaddr_u(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
|
|
# define bxaddi_u(i0, r0, i1) _bxaddi_u(_jit, i0, r0, i1)
|
|
static jit_word_t _bxaddi_u(jit_state_t*,jit_word_t,jit_int32_t,jit_word_t);
|
|
# define bosubr(i0, r0, r1) _bosubr(_jit, i0, r0, r1)
|
|
static jit_word_t _bosubr(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
|
|
# define bosubi(i0, r0, i1) _bosubi(_jit, i0, r0, i1)
|
|
static jit_word_t _bosubi(jit_state_t*,jit_word_t,jit_int32_t,jit_word_t);
|
|
# define bosubr_u(i0, r0, r1) _bosubr_u(_jit, i0, r0, r1)
|
|
static jit_word_t _bosubr_u(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
|
|
# define bosubi_u(i0, r0, i1) _bosubi_u(_jit, i0, r0, i1)
|
|
static jit_word_t _bosubi_u(jit_state_t*,jit_word_t,jit_int32_t,jit_word_t);
|
|
# define bxsubr(i0, r0, r1) _bxsubr(_jit, i0, r0, r1)
|
|
static jit_word_t _bxsubr(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
|
|
# define bxsubi(i0, r0, i1) _bxsubi(_jit, i0, r0, i1)
|
|
static jit_word_t _bxsubi(jit_state_t*,jit_word_t,jit_int32_t,jit_word_t);
|
|
# define bxsubr_u(i0, r0, r1) _bxsubr_u(_jit, i0, r0, r1)
|
|
static jit_word_t _bxsubr_u(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
|
|
# define bxsubi_u(i0, r0, i1) _bxsubi_u(_jit, i0, r0, i1)
|
|
static jit_word_t _bxsubi_u(jit_state_t*,jit_word_t,jit_int32_t,jit_word_t);
|
|
# define callr(r0) _callr(_jit, r0)
|
|
static void _callr(jit_state_t*, jit_int32_t);
|
|
# define calli(i0) _calli(_jit, i0)
|
|
static jit_word_t _calli(jit_state_t*, jit_word_t);
|
|
# define jmpr(r0) _jmpr(_jit, r0)
|
|
static void _jmpr(jit_state_t*, jit_int32_t);
|
|
# define jmpi(i0) _jmpi(_jit, i0)
|
|
static jit_word_t _jmpi(jit_state_t*, jit_word_t);
|
|
# define prolog(node) _prolog(_jit, node)
|
|
static void _prolog(jit_state_t*, jit_node_t*);
|
|
# define epilog(node) _epilog(_jit, node)
|
|
static void _epilog(jit_state_t*, jit_node_t*);
|
|
# define patch_at(node, instr, label) _patch_at(_jit, node, instr, label)
|
|
static void _patch_at(jit_state_t*, jit_node_t*, jit_word_t, jit_word_t);
|
|
# if !defined(HAVE_FFSL)
|
|
# if __WORDSIZE == 32
|
|
# define ffsl(i) ffs(i)
|
|
# else
|
|
static int ffsl(long);
|
|
# endif
|
|
# endif
|
|
#endif
|
|
|
|
#if CODE
|
|
static void
|
|
_rex(jit_state_t *_jit, jit_int32_t l, jit_int32_t w,
|
|
jit_int32_t r, jit_int32_t x, jit_int32_t b)
|
|
{
|
|
#if __WORDSIZE == 64
|
|
jit_int32_t v = 0x40 | (w << 3);
|
|
|
|
if (r != _NOREG)
|
|
v |= (r & 8) >> 1;
|
|
if (x != _NOREG)
|
|
v |= (x & 8) >> 2;
|
|
if (b != _NOREG)
|
|
v |= (b & 8) >> 3;
|
|
if (l || v != 0x40)
|
|
ic(v);
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
_rx(jit_state_t *_jit, jit_int32_t rd, jit_int32_t md,
|
|
jit_int32_t rb, jit_int32_t ri, jit_int32_t ms)
|
|
{
|
|
if (ri == _NOREG) {
|
|
if (rb == _NOREG) {
|
|
#if __WORDSIZE == 32
|
|
mrm(0x00, r7(rd), 0x05);
|
|
#else
|
|
mrm(0x00, r7(rd), 0x04);
|
|
sib(_SCL1, 0x04, 0x05);
|
|
#endif
|
|
ii(md);
|
|
}
|
|
else if (r7(rb) == _RSP_REGNO) {
|
|
if (md == 0) {
|
|
mrm(0x00, r7(rd), 0x04);
|
|
sib(ms, 0x04, 0x04);
|
|
}
|
|
else if ((jit_int8_t)md == md) {
|
|
mrm(0x01, r7(rd), 0x04);
|
|
sib(ms, 0x04, 0x04);
|
|
ic(md);
|
|
}
|
|
else {
|
|
mrm(0x02, r7(rd), 0x04);
|
|
sib(ms, 0x04, 0x04);
|
|
ii(md);
|
|
}
|
|
}
|
|
else {
|
|
if (md == 0 && r7(rb) != _RBP_REGNO)
|
|
mrm(0x00, r7(rd), r7(rb));
|
|
else if ((jit_int8_t)md == md) {
|
|
mrm(0x01, r7(rd), r7(rb));
|
|
ic(md);
|
|
}
|
|
else {
|
|
mrm(0x02, r7(rd), r7(rb));
|
|
ii(md);
|
|
}
|
|
}
|
|
}
|
|
else if (rb == _NOREG) {
|
|
mrm(0x00, r7(rd), 0x04);
|
|
sib(ms, r7(ri), 0x05);
|
|
ii(md);
|
|
}
|
|
else if (r8(ri) != _RSP_REGNO) {
|
|
if (md == 0 && r7(rb) != _RBP_REGNO) {
|
|
mrm(0x00, r7(rd), 0x04);
|
|
sib(ms, r7(ri), r7(rb));
|
|
}
|
|
else if ((jit_int8_t)md == md) {
|
|
mrm(0x01, r7(rd), 0x04);
|
|
sib(ms, r7(ri), r7(rb));
|
|
ic(md);
|
|
}
|
|
else {
|
|
mrm(0x02, r7(rd), 0x04);
|
|
sib(ms, r7(ri), r7(rb));
|
|
ic(md);
|
|
}
|
|
}
|
|
else {
|
|
fprintf(stderr, "illegal index register");
|
|
abort();
|
|
}
|
|
}
|
|
|
|
static void
|
|
_nop(jit_state_t *_jit, jit_int32_t count)
|
|
{
|
|
switch (count) {
|
|
case 0:
|
|
break;
|
|
case 1: /* NOP */
|
|
ic(0x90); break;
|
|
case 2: /* 66 NOP */
|
|
ic(0x66); ic(0x90);
|
|
break;
|
|
case 3: /* NOP DWORD ptr [EAX] */
|
|
ic(0x0f); ic(0x1f); ic(0x00);
|
|
break;
|
|
case 4: /* NOP DWORD ptr [EAX + 00H] */
|
|
ic(0x0f); ic(0x1f); ic(0x40); ic(0x00);
|
|
break;
|
|
case 5: /* NOP DWORD ptr [EAX + EAX*1 + 00H] */
|
|
ic(0x0f); ic(0x1f); ic(0x44); ic(0x00);
|
|
ic(0x00);
|
|
break;
|
|
case 6: /* 66 NOP DWORD ptr [EAX + EAX*1 + 00H] */
|
|
ic(0x66); ic(0x0f); ic(0x1f); ic(0x44);
|
|
ic(0x00); ic(0x00);
|
|
break;
|
|
case 7: /* NOP DWORD ptr [EAX + 00000000H] */
|
|
ic(0x0f); ic(0x1f); ic(0x80); ii(0x0000);
|
|
break;
|
|
case 8: /* NOP DWORD ptr [EAX + EAX*1 + 00000000H] */
|
|
ic(0x0f); ic(0x1f); ic(0x84); ic(0x00);
|
|
ii(0x0000);
|
|
break;
|
|
case 9: /* 66 NOP DWORD ptr [EAX + EAX*1 + 00000000H] */
|
|
ic(0x66); ic(0x0f); ic(0x1f); ic(0x84);
|
|
ic(0x00); ii(0x0000);
|
|
break;
|
|
default:
|
|
abort();
|
|
}
|
|
}
|
|
|
|
static void
|
|
_lea(jit_state_t *_jit, jit_int32_t md, jit_int32_t rb,
|
|
jit_int32_t ri, jit_int32_t ms, jit_int32_t rd)
|
|
{
|
|
rex(0, 1, rd, ri, rb);
|
|
ic(0x8d);
|
|
rx(rd, md, rb, ri, ms);
|
|
}
|
|
|
|
static void
|
|
_pushr(jit_state_t *_jit, jit_int32_t r0)
|
|
{
|
|
rex(0, 0, 0, 0, r0);
|
|
ic(0x50 | r7(r0));
|
|
}
|
|
|
|
static void
|
|
_popr(jit_state_t *_jit, jit_int32_t r0)
|
|
{
|
|
rex(0, 0, 0, 0, r0);
|
|
ic(0x58 | r7(r0));
|
|
}
|
|
|
|
static void
|
|
_xchgr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
rex(0, 1, r1, _NOREG, r0);
|
|
ic(0x87);
|
|
mrm(0x03, r7(r1), r7(r0));
|
|
}
|
|
|
|
static void
|
|
_testr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
rex(0, 1, r1, _NOREG, r0);
|
|
ic(0x85);
|
|
mrm(0x03, r7(r1), r7(r0));
|
|
}
|
|
|
|
static void
|
|
_testi(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
|
|
{
|
|
rex(0, 1, _NOREG, _NOREG, r0);
|
|
if (r0 == _RAX_REGNO)
|
|
ic(0xa9);
|
|
else {
|
|
ic(0xf7);
|
|
mrm(0x03, 0x00, r7(r0));
|
|
}
|
|
ii(i0);
|
|
}
|
|
|
|
static void
|
|
_cc(jit_state_t *_jit, jit_int32_t code, jit_int32_t r0)
|
|
{
|
|
rex(0, 0, _NOREG, _NOREG, r0);
|
|
ic(0x0f);
|
|
ic(0x90 | code);
|
|
mrm(0x03, 0x00, r7(r0));
|
|
}
|
|
|
|
static void
|
|
_alur(jit_state_t *_jit, jit_int32_t code, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
rex(0, 1, r1, _NOREG, r0);
|
|
ic(code | 0x01);
|
|
mrm(0x03, r7(r1), r7(r0));
|
|
}
|
|
|
|
static void
|
|
_alui(jit_state_t *_jit, jit_int32_t code, jit_int32_t r0, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
if (can_sign_extend_int_p(i0)) {
|
|
rex(0, 1, _NOREG, _NOREG, r0);
|
|
if ((jit_int8_t)i0 == i0) {
|
|
ic(0x83);
|
|
ic(0xc0 | code | r7(r0));
|
|
ic(i0);
|
|
}
|
|
else {
|
|
if (r0 == _RAX_REGNO)
|
|
ic(code | 0x05);
|
|
else {
|
|
ic(0x81);
|
|
ic(0xc0 | code | r7(r0));
|
|
}
|
|
ii(i0);
|
|
}
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
alur(code, r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_save(jit_state_t *_jit, jit_int32_t r0)
|
|
{
|
|
if (!_jitc->function->regoff[r0]) {
|
|
_jitc->function->regoff[r0] = jit_allocai(sizeof(jit_word_t));
|
|
_jitc->again = 1;
|
|
}
|
|
assert(!jit_regset_tstbit(&_jitc->regsav, r0));
|
|
jit_regset_setbit(&_jitc->regsav, r0);
|
|
stxi(_jitc->function->regoff[r0], _RBP_REGNO, r0);
|
|
}
|
|
|
|
static void
|
|
_load(jit_state_t *_jit, jit_int32_t r0)
|
|
{
|
|
assert(_jitc->function->regoff[r0]);
|
|
assert(jit_regset_tstbit(&_jitc->regsav, r0));
|
|
jit_regset_clrbit(&_jitc->regsav, r0);
|
|
ldxi(r0, _RBP_REGNO, _jitc->function->regoff[r0]);
|
|
}
|
|
|
|
static void
|
|
_addr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
if (r0 == r1)
|
|
iaddr(r0, r2);
|
|
else if (r0 == r2)
|
|
iaddr(r0, r1);
|
|
else
|
|
lea(0, r1, r2, _SCL1, r0);
|
|
}
|
|
|
|
static void
|
|
_addi(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
if (i0 == 0)
|
|
movr(r0, r1);
|
|
#if USE_INC_DEC
|
|
else if (i0 == 1)
|
|
incr(r0, r1);
|
|
else if (i0 == -1)
|
|
decr(r0, r1);
|
|
#endif
|
|
else if (can_sign_extend_int_p(i0)) {
|
|
if (r0 == r1)
|
|
iaddi(r0, i0);
|
|
else
|
|
lea(i0, r1, _NOREG, _SCL1, r0);
|
|
}
|
|
else if (r0 != r1) {
|
|
movi(r0, i0);
|
|
iaddr(r0, r1);
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
iaddr(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_addcr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
if (r0 == r2)
|
|
iaddr(r0, r1);
|
|
else {
|
|
movr(r0, r1);
|
|
iaddr(r0, r2);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_addci(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
if (can_sign_extend_int_p(i0)) {
|
|
movr(r0, r1);
|
|
iaddi(r0, i0);
|
|
}
|
|
else if (r0 == r1) {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
iaddr(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
else {
|
|
movi(r0, i0);
|
|
iaddr(r0, r1);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_addxr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
if (r0 == r2)
|
|
iaddxr(r0, r1);
|
|
else {
|
|
movr(r0, r1);
|
|
iaddxr(r0, r2);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_addxi(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
if (can_sign_extend_int_p(i0)) {
|
|
movr(r0, r1);
|
|
iaddxi(r0, i0);
|
|
}
|
|
else if (r0 == r1) {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
iaddxr(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
else {
|
|
movi(r0, i0);
|
|
iaddxr(r0, r1);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_subr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
if (r1 == r2)
|
|
ixorr(r0, r0);
|
|
else if (r0 == r2) {
|
|
isubr(r0, r1);
|
|
inegr(r0);
|
|
}
|
|
else {
|
|
movr(r0, r1);
|
|
isubr(r0, r2);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_subi(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
if (i0 == 0)
|
|
movr(r0, r1);
|
|
#if USE_INC_DEC
|
|
else if (i0 == 1)
|
|
decr(r0, r1);
|
|
else if (i0 == -1)
|
|
incr(r0, r1);
|
|
#endif
|
|
else if (can_sign_extend_int_p(i0)) {
|
|
if (r0 == r1)
|
|
isubi(r0, i0);
|
|
else
|
|
lea(-i0, r1, _NOREG, _SCL1, r0);
|
|
}
|
|
else if (r0 != r1) {
|
|
movi(r0, -i0);
|
|
iaddr(r0, r1);
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
isubr(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_subcr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
jit_int32_t reg;
|
|
if (r0 == r2 && r0 != r1) {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movr(rn(reg), r0);
|
|
movr(r0, r1);
|
|
isubr(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
else {
|
|
movr(r0, r1);
|
|
isubr(r0, r2);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_subci(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
movr(r0, r1);
|
|
if (can_sign_extend_int_p(i0))
|
|
isubi(r0, i0);
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
isubr(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_subxr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
jit_int32_t reg;
|
|
if (r0 == r2 && r0 != r1) {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movr(rn(reg), r0);
|
|
movr(r0, r1);
|
|
isubxr(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
else {
|
|
movr(r0, r1);
|
|
isubxr(r0, r2);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_subxi(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
movr(r0, r1);
|
|
if (can_sign_extend_int_p(i0))
|
|
isubxi(r0, i0);
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
imovi(rn(reg), i0);
|
|
isubxr(r0, 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
|
|
_imulr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
rex(0, 1, r0, _NOREG, r1);
|
|
ic(0x0f);
|
|
ic(0xaf);
|
|
mrm(0x03, r7(r0), r7(r1));
|
|
}
|
|
|
|
static void
|
|
_imuli(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
if (can_sign_extend_int_p(i0)) {
|
|
rex(0, 1, r0, _NOREG, r1);
|
|
if ((jit_int8_t)i0 == i0) {
|
|
ic(0x6b);
|
|
mrm(0x03, r7(r0), r7(r1));
|
|
ic(i0);
|
|
}
|
|
else {
|
|
ic(0x69);
|
|
mrm(0x03, r7(r0), r7(r1));
|
|
ii(i0);
|
|
}
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
imulr(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_mulr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
if (r0 == r1)
|
|
imulr(r0, r2);
|
|
else if (r0 == r2)
|
|
imulr(r0, r1);
|
|
else {
|
|
movr(r0, r1);
|
|
imulr(r0, r2);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_muli(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
switch (i0) {
|
|
case 0:
|
|
ixorr(r0, r0);
|
|
break;
|
|
case 1:
|
|
movr(r0, r1);
|
|
break;
|
|
case -1:
|
|
negr(r0, r1);
|
|
break;
|
|
case 2:
|
|
lea(0, _NOREG, r1, _SCL2, r0);
|
|
break;
|
|
case 4:
|
|
lea(0, _NOREG, r1, _SCL4, r0);
|
|
break;
|
|
case 8:
|
|
lea(0, _NOREG, r1, _SCL8, r0);
|
|
break;
|
|
default:
|
|
if (i0 > 0 && !(i0 & (i0 - 1)))
|
|
lshi(r0, r1, ffsl(i0) - 1);
|
|
else if (can_sign_extend_int_p(i0))
|
|
imuli(r0, r1, i0);
|
|
else if (r0 != r1) {
|
|
movi(r0, i0);
|
|
imulr(r0, r1);
|
|
}
|
|
else
|
|
imuli(r0, r0, i0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
#define savset(rn) \
|
|
if (r0 != rn) { \
|
|
sav |= 1 << rn; \
|
|
if (r1 != rn && r2 != rn) \
|
|
set |= 1 << rn; \
|
|
}
|
|
#define isavset(rn) \
|
|
if (r0 != rn) { \
|
|
sav |= 1 << rn; \
|
|
if (r1 != rn) \
|
|
set |= 1 << rn; \
|
|
}
|
|
#define qsavset(rn) \
|
|
if (r0 != rn && r1 != rn) { \
|
|
sav |= 1 << rn; \
|
|
if (r2 != rn && r3 != rn) \
|
|
set |= 1 << rn; \
|
|
}
|
|
#define allocr(rn, rv) \
|
|
if (set & (1 << rn)) \
|
|
(void)jit_get_reg(rv|jit_class_gpr|jit_class_named); \
|
|
if (sav & (1 << rn)) { \
|
|
if ( jit_regset_tstbit(&_jitc->regsav, rv) || \
|
|
!jit_regset_tstbit(&_jitc->reglive, rv)) \
|
|
sav &= ~(1 << rn); \
|
|
else \
|
|
save(rv); \
|
|
}
|
|
#define clear(rn, rv) \
|
|
if (set & (1 << rn)) \
|
|
jit_unget_reg(rv); \
|
|
if (sav & (1 << rn)) \
|
|
load(rv);
|
|
static void
|
|
_iqmulr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1,
|
|
jit_int32_t r2, jit_int32_t r3, jit_bool_t sign)
|
|
{
|
|
jit_int32_t mul;
|
|
jit_int32_t sav;
|
|
jit_int32_t set;
|
|
|
|
sav = set = 0;
|
|
qsavset(_RDX_REGNO);
|
|
qsavset(_RAX_REGNO);
|
|
allocr(_RDX_REGNO, _RDX);
|
|
allocr(_RAX_REGNO, _RAX);
|
|
|
|
if (r3 == _RAX_REGNO)
|
|
mul = r2;
|
|
else {
|
|
mul = r3;
|
|
movr(_RAX_REGNO, r2);
|
|
}
|
|
if (sign)
|
|
umulr(mul);
|
|
else
|
|
umulr_u(mul);
|
|
|
|
if (r0 == _RDX_REGNO && r1 == _RAX_REGNO)
|
|
xchgr(_RAX_REGNO, _RDX_REGNO);
|
|
else {
|
|
if (r0 != _RDX_REGNO)
|
|
movr(r0, _RAX_REGNO);
|
|
movr(r1, _RDX_REGNO);
|
|
if (r0 == _RDX_REGNO)
|
|
movr(r0, _RAX_REGNO);
|
|
}
|
|
|
|
clear(_RDX_REGNO, _RDX);
|
|
clear(_RAX_REGNO, _RAX);
|
|
}
|
|
|
|
static void
|
|
_iqmuli(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1,
|
|
jit_int32_t r2, jit_word_t i0, jit_bool_t sign)
|
|
{
|
|
jit_int32_t reg;
|
|
|
|
if (i0 == 0) {
|
|
ixorr(r0, r0);
|
|
ixorr(r1, r1);
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
if (sign)
|
|
qmulr(r0, r1, r2, rn(reg));
|
|
else
|
|
qmulr_u(r0, r1, r2, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_sign_extend_rdx_rax(jit_state_t *_jit)
|
|
{
|
|
rex(0, 1, 0, 0, 0);
|
|
ic(0x99);
|
|
}
|
|
|
|
static void
|
|
_divremr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2,
|
|
jit_bool_t sign, jit_bool_t divide)
|
|
{
|
|
jit_int32_t div;
|
|
jit_int32_t reg;
|
|
jit_int32_t set;
|
|
jit_int32_t sav;
|
|
jit_int32_t use;
|
|
|
|
sav = set = use = 0;
|
|
savset(_RDX_REGNO);
|
|
savset(_RAX_REGNO);
|
|
allocr(_RDX_REGNO, _RDX);
|
|
allocr(_RAX_REGNO, _RAX);
|
|
|
|
if (r2 == _RAX_REGNO) {
|
|
if (r0 == _RAX_REGNO || r0 == _RDX_REGNO) {
|
|
if ((reg = jit_get_reg(jit_class_gpr|jit_class_chk)) == JIT_NOREG)
|
|
reg = jit_get_reg((r1 == _RCX_REGNO ? _RBX : _RCX) |
|
|
jit_class_gpr|jit_class_named);
|
|
use = 1;
|
|
div = rn(reg);
|
|
movr(div, _RAX_REGNO);
|
|
if (r1 != _RAX_REGNO)
|
|
movr(_RAX_REGNO, r1);
|
|
}
|
|
else {
|
|
if (r0 == r1)
|
|
xchgr(r0, _RAX_REGNO);
|
|
else {
|
|
if (r0 != _RAX_REGNO)
|
|
movr(r0, _RAX_REGNO);
|
|
if (r1 != _RAX_REGNO)
|
|
movr(_RAX_REGNO, r1);
|
|
}
|
|
div = r0;
|
|
}
|
|
}
|
|
else if (r2 == _RDX_REGNO) {
|
|
if (r0 == _RAX_REGNO || r0 == _RDX_REGNO) {
|
|
if ((reg = jit_get_reg(jit_class_gpr|jit_class_chk)) == JIT_NOREG)
|
|
reg = jit_get_reg((r1 == _RCX_REGNO ? _RBX : _RCX) |
|
|
jit_class_gpr|jit_class_named);
|
|
use = 1;
|
|
div = rn(reg);
|
|
movr(div, _RDX_REGNO);
|
|
if (r1 != _RAX_REGNO)
|
|
movr(_RAX_REGNO, r1);
|
|
}
|
|
else {
|
|
if (r1 != _RAX_REGNO)
|
|
movr(_RAX_REGNO, r1);
|
|
movr(r0, _RDX_REGNO);
|
|
div = r0;
|
|
}
|
|
}
|
|
else {
|
|
if (r1 != _RAX_REGNO)
|
|
movr(_RAX_REGNO, r1);
|
|
div = r2;
|
|
}
|
|
|
|
if (sign) {
|
|
sign_extend_rdx_rax();
|
|
idivr(div);
|
|
}
|
|
else {
|
|
ixorr(_RDX_REGNO, _RDX_REGNO);
|
|
idivr_u(div);
|
|
}
|
|
|
|
if (use)
|
|
jit_unget_reg(reg);
|
|
|
|
if (divide)
|
|
movr(r0, _RAX_REGNO);
|
|
else
|
|
movr(r0, _RDX_REGNO);
|
|
|
|
clear(_RDX_REGNO, _RDX);
|
|
clear(_RAX_REGNO, _RAX);
|
|
}
|
|
|
|
static void
|
|
_divremi(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0,
|
|
jit_bool_t sign, jit_bool_t divide)
|
|
{
|
|
jit_int32_t reg;
|
|
jit_int32_t div;
|
|
jit_int32_t sav;
|
|
jit_int32_t set;
|
|
jit_int32_t use;
|
|
|
|
if (divide) {
|
|
switch (i0) {
|
|
case 1:
|
|
movr(r0, r1);
|
|
return;
|
|
case -1:
|
|
if (sign) {
|
|
negr(r0, r1);
|
|
return;
|
|
}
|
|
break;
|
|
default:
|
|
if (i0 > 0 && !(i0 & (i0 - 1))) {
|
|
movr(r0, r1);
|
|
if (sign)
|
|
rshi(r0, r0, ffsl(i0) - 1);
|
|
else
|
|
rshi_u(r0, r0, ffsl(i0) - 1);
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else if (i0 == 1 || (sign && i0 == -1)) {
|
|
ixorr(r0, r0);
|
|
return;
|
|
}
|
|
else if (!sign && i0 > 0 && !(i0 & (i0 - 1))) {
|
|
if (can_sign_extend_int_p(i0)) {
|
|
movr(r0, r1);
|
|
iandi(r0, i0 - 1);
|
|
}
|
|
else if (r0 != r1) {
|
|
movi(r0, i0 - 1);
|
|
iandr(r0, r1);
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0 - 1);
|
|
iandr(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
return;
|
|
}
|
|
|
|
sav = set = use = 0;
|
|
isavset(_RDX_REGNO);
|
|
isavset(_RAX_REGNO);
|
|
allocr(_RDX_REGNO, _RDX);
|
|
allocr(_RAX_REGNO, _RAX);
|
|
|
|
if (r0 == _RAX_REGNO || r0 == _RDX_REGNO || r0 == r1) {
|
|
if ((reg = jit_get_reg(jit_class_gpr|jit_class_chk)) == JIT_NOREG)
|
|
reg = jit_get_reg((r1 == _RCX_REGNO ? _RBX : _RCX) |
|
|
jit_class_gpr|jit_class_named);
|
|
use = 1;
|
|
div = rn(reg);
|
|
}
|
|
else
|
|
div = r0;
|
|
|
|
movi(div, i0);
|
|
movr(_RAX_REGNO, r1);
|
|
|
|
if (sign) {
|
|
sign_extend_rdx_rax();
|
|
idivr(div);
|
|
}
|
|
else {
|
|
ixorr(_RDX_REGNO, _RDX_REGNO);
|
|
idivr_u(div);
|
|
}
|
|
|
|
if (use)
|
|
jit_unget_reg(reg);
|
|
|
|
if (divide)
|
|
movr(r0, _RAX_REGNO);
|
|
else
|
|
movr(r0, _RDX_REGNO);
|
|
|
|
clear(_RDX_REGNO, _RDX);
|
|
clear(_RAX_REGNO, _RAX);
|
|
}
|
|
|
|
static void
|
|
_iqdivr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1,
|
|
jit_int32_t r2, jit_int32_t r3, jit_bool_t sign)
|
|
{
|
|
jit_int32_t div;
|
|
jit_int32_t reg;
|
|
jit_int32_t sav;
|
|
jit_int32_t set;
|
|
jit_int32_t use;
|
|
|
|
sav = set = use = 0;
|
|
qsavset(_RDX_REGNO);
|
|
qsavset(_RAX_REGNO);
|
|
allocr(_RDX_REGNO, _RDX);
|
|
allocr(_RAX_REGNO, _RAX);
|
|
if (r3 == _RAX_REGNO) {
|
|
if (r0 == _RAX_REGNO || r0 == _RDX_REGNO) {
|
|
if ((reg = jit_get_reg(jit_class_gpr|jit_class_chk)) == JIT_NOREG)
|
|
reg = jit_get_reg((r1 == _RCX_REGNO ? _RBX : _RCX) |
|
|
jit_class_gpr|jit_class_named);
|
|
use = 1;
|
|
div = rn(reg);
|
|
movr(div, _RAX_REGNO);
|
|
if (r2 != _RAX_REGNO)
|
|
movr(_RAX_REGNO, r2);
|
|
}
|
|
else {
|
|
if (r0 == r2)
|
|
xchgr(r0, _RAX_REGNO);
|
|
else {
|
|
if (r0 != _RAX_REGNO)
|
|
movr(r0, _RAX_REGNO);
|
|
if (r2 != _RAX_REGNO)
|
|
movr(_RAX_REGNO, r2);
|
|
}
|
|
div = r0;
|
|
}
|
|
}
|
|
else if (r3 == _RDX_REGNO) {
|
|
if (r0 == _RAX_REGNO || r0 == _RDX_REGNO) {
|
|
if ((reg = jit_get_reg(jit_class_gpr|jit_class_chk)) == JIT_NOREG)
|
|
reg = jit_get_reg((r1 == _RCX_REGNO ? _RBX : _RCX) |
|
|
jit_class_gpr|jit_class_named);
|
|
use = 1;
|
|
div = rn(reg);
|
|
movr(div, _RDX_REGNO);
|
|
if (r2 != _RAX_REGNO)
|
|
movr(_RAX_REGNO, r2);
|
|
}
|
|
else {
|
|
if (r2 != _RAX_REGNO)
|
|
movr(_RAX_REGNO, r2);
|
|
movr(r0, _RDX_REGNO);
|
|
div = r0;
|
|
}
|
|
}
|
|
else {
|
|
if (r2 != _RAX_REGNO)
|
|
movr(_RAX_REGNO, r2);
|
|
div = r3;
|
|
}
|
|
if (sign) {
|
|
sign_extend_rdx_rax();
|
|
idivr(div);
|
|
}
|
|
else {
|
|
ixorr(_RDX_REGNO, _RDX_REGNO);
|
|
idivr_u(div);
|
|
}
|
|
if (use)
|
|
jit_unget_reg(reg);
|
|
|
|
if (r0 == _RDX_REGNO && r1 == _RAX_REGNO)
|
|
xchgr(_RAX_REGNO, _RDX_REGNO);
|
|
else {
|
|
if (r0 != _RDX_REGNO)
|
|
movr(r0, _RAX_REGNO);
|
|
movr(r1, _RDX_REGNO);
|
|
if (r0 == _RDX_REGNO)
|
|
movr(r0, _RAX_REGNO);
|
|
}
|
|
|
|
clear(_RDX_REGNO, _RDX);
|
|
clear(_RAX_REGNO, _RAX);
|
|
}
|
|
|
|
static void
|
|
_iqdivi(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1,
|
|
jit_int32_t r2, jit_word_t i0, jit_bool_t sign)
|
|
{
|
|
jit_int32_t reg;
|
|
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
if (sign)
|
|
qdivr(r0, r1, r2, rn(reg));
|
|
else
|
|
qdivr_u(r0, r1, r2, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
#undef clear
|
|
#undef allocr
|
|
#undef savset
|
|
|
|
static void
|
|
_andr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
if (r1 == r2)
|
|
movr(r0, r1);
|
|
else if (r0 == r1)
|
|
iandr(r0, r2);
|
|
else if (r0 == r2)
|
|
iandr(r0, r1);
|
|
else {
|
|
movr(r0, r1);
|
|
iandr(r0, r2);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_andi(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
|
|
if (i0 == 0)
|
|
ixorr(r0, r0);
|
|
else if (i0 == -1)
|
|
movr(r0, r1);
|
|
else if (r0 == r1) {
|
|
if (can_sign_extend_int_p(i0))
|
|
iandi(r0, i0);
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
iandr(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
else {
|
|
movi(r0, i0);
|
|
iandr(r0, r1);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_orr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
if (r1 == r2)
|
|
movr(r0, r1);
|
|
else if (r0 == r1)
|
|
iorr(r0, r2);
|
|
else if (r0 == r2)
|
|
iorr(r0, r1);
|
|
else {
|
|
movr(r0, r1);
|
|
iorr(r0, r2);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_ori(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
if (i0 == 0)
|
|
movr(r0, r1);
|
|
else if (i0 == -1)
|
|
movi(r0, -1);
|
|
else if (can_sign_extend_int_p(i0)) {
|
|
movr(r0, r1);
|
|
iori(r0, i0);
|
|
}
|
|
else if (r0 != r1) {
|
|
movi(r0, i0);
|
|
iorr(r0, r1);
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
iorr(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_xorr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
if (r1 == r2)
|
|
ixorr(r0, r0);
|
|
else if (r0 == r1)
|
|
ixorr(r0, r2);
|
|
else if (r0 == r2)
|
|
ixorr(r0, r1);
|
|
else {
|
|
movr(r0, r1);
|
|
ixorr(r0, r2);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_xori(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
if (i0 == 0)
|
|
movr(r0, r1);
|
|
else if (i0 == -1)
|
|
comr(r0, r1);
|
|
else if (can_sign_extend_int_p(i0)) {
|
|
movr(r0, r1);
|
|
ixori(r0, i0);
|
|
}
|
|
else if (r0 != r1) {
|
|
movi(r0, i0);
|
|
ixorr(r0, r1);
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
ixorr(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_irotshr(jit_state_t *_jit, jit_int32_t code, jit_int32_t r0)
|
|
{
|
|
rex(0, 1, _RCX_REGNO, _NOREG, r0);
|
|
ic(0xd3);
|
|
mrm(0x03, code, r7(r0));
|
|
}
|
|
|
|
static void
|
|
_rotshr(jit_state_t *_jit, jit_int32_t code,
|
|
jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
jit_int32_t reg;
|
|
jit_int32_t use;
|
|
|
|
if (r0 == _RCX_REGNO) {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movr(rn(reg), r1);
|
|
if (r2 != _RCX_REGNO)
|
|
movr(_RCX_REGNO, r2);
|
|
irotshr(code, rn(reg));
|
|
movr(_RCX_REGNO, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
else if (r2 != _RCX_REGNO) {
|
|
use = !jit_reg_free_p(_RCX);
|
|
if (use) {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movr(rn(reg), _RCX_REGNO);
|
|
}
|
|
else
|
|
reg = 0;
|
|
if (r1 == _RCX_REGNO) {
|
|
if (r0 == r2)
|
|
xchgr(r0, _RCX_REGNO);
|
|
else {
|
|
movr(r0, r1);
|
|
movr(_RCX_REGNO, r2);
|
|
}
|
|
}
|
|
else {
|
|
movr(_RCX_REGNO, r2);
|
|
movr(r0, r1);
|
|
}
|
|
irotshr(code, r0);
|
|
if (use) {
|
|
movr(_RCX_REGNO, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
else {
|
|
movr(r0, r1);
|
|
irotshr(code, r0);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_irotshi(jit_state_t *_jit, jit_int32_t code, jit_int32_t r0, jit_word_t i0)
|
|
{
|
|
rex(0, 1, _NOREG, _NOREG, r0);
|
|
if (i0 == 1) {
|
|
ic(0xd1);
|
|
mrm(0x03, code, r7(r0));
|
|
}
|
|
else {
|
|
ic(0xc1);
|
|
mrm(0x03, code, r7(r0));
|
|
ic(i0);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_rotshi(jit_state_t *_jit, jit_int32_t code,
|
|
jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
movr(r0, r1);
|
|
if (i0)
|
|
irotshi(code, r0, i0);
|
|
}
|
|
|
|
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 if (i0 <= 3)
|
|
lea(0, _NOREG, r1, i0 == 1 ? _SCL2 : i0 == 2 ? _SCL4 : _SCL8, r0);
|
|
else
|
|
rotshi(X86_SHL, r0, r1, i0);
|
|
}
|
|
|
|
static void
|
|
_unr(jit_state_t *_jit, jit_int32_t code, jit_int32_t r0)
|
|
{
|
|
rex(0, 1, _NOREG, _NOREG, r0);
|
|
ic(0xf7);
|
|
mrm(0x03, code, r7(r0));
|
|
}
|
|
|
|
static void
|
|
_negr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
if (r0 == r1)
|
|
inegr(r0);
|
|
else {
|
|
ixorr(r0, r0);
|
|
isubr(r0, r1);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_comr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
movr(r0, r1);
|
|
icomr(r0);
|
|
}
|
|
|
|
#if USE_INC_DEC
|
|
static void
|
|
_incr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
movr(r0, r1);
|
|
# if __WORDSIZE == 64
|
|
rex(0, 1, _NOREG, _NOREG, r0);
|
|
ic(0xff);
|
|
ic(0xc0 | r7(r0));
|
|
# else
|
|
ic(0x40 | r7(r0));
|
|
# endif
|
|
}
|
|
|
|
static void
|
|
_decr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
movr(r0, r1);
|
|
# if __WORDSIZE == 64
|
|
rex(0, 1, _NOREG, _NOREG, r0);
|
|
ic(0xff);
|
|
ic(0xc8 | r7(r0));
|
|
# else
|
|
ic(0x48 | r7(r0));
|
|
# endif
|
|
}
|
|
#endif
|
|
|
|
static void
|
|
_cr(jit_state_t *_jit,
|
|
jit_int32_t code, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
jit_int32_t reg;
|
|
jit_bool_t same;
|
|
if (reg8_p(r0)) {
|
|
same = r0 == r1 || r0 == r2;
|
|
if (!same)
|
|
ixorr(r0, r0);
|
|
icmpr(r1, r2);
|
|
if (same)
|
|
imovi(r0, 0);
|
|
cc(code, r0);
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr|jit_class_rg8);
|
|
ixorr(rn(reg), rn(reg));
|
|
icmpr(r1, r2);
|
|
cc(code, rn(reg));
|
|
movr(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_ci(jit_state_t *_jit,
|
|
jit_int32_t code, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
jit_bool_t same;
|
|
if (reg8_p(r0)) {
|
|
same = r0 == r1;
|
|
if (!same)
|
|
ixorr(r0, r0);
|
|
icmpi(r1, i0);
|
|
if (same)
|
|
imovi(r0, 0);
|
|
cc(code, r0);
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr|jit_class_rg8);
|
|
ixorr(rn(reg), rn(reg));
|
|
icmpi(r1, i0);
|
|
cc(code, rn(reg));
|
|
movr(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_ci0(jit_state_t *_jit, jit_int32_t code, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
jit_int32_t reg;
|
|
jit_bool_t same;
|
|
if (reg8_p(r0)) {
|
|
same = r0 == r1;
|
|
if (!same)
|
|
ixorr(r0, r0);
|
|
testr(r1, r1);
|
|
if (same)
|
|
imovi(r0, 0);
|
|
cc(code, r0);
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr|jit_class_rg8);
|
|
ixorr(rn(reg), rn(reg));
|
|
testr(r1, r1);
|
|
cc(code, rn(reg));
|
|
movr(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_ltr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
if (r1 == r2)
|
|
movi(r0, 0);
|
|
else
|
|
cr(X86_CC_L, r0, r1, r2);
|
|
}
|
|
|
|
static void
|
|
_lti(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
if (i0)
|
|
ci(X86_CC_L, r0, r1, i0);
|
|
else
|
|
ci0(X86_CC_S, r0, r1);
|
|
}
|
|
|
|
static void
|
|
_ltr_u(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
if (r1 == r2)
|
|
movi(r0, 0);
|
|
else
|
|
cr(X86_CC_B, r0, r1, r2);
|
|
}
|
|
|
|
static void
|
|
_ler(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
if (r1 == r2)
|
|
movi(r0, 1);
|
|
else
|
|
cr(X86_CC_LE, r0, r1, r2);
|
|
}
|
|
|
|
static void
|
|
_ler_u(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
if (r1 == r2)
|
|
movi(r0, 1);
|
|
else
|
|
cr(X86_CC_BE, r0, r1, r2);
|
|
}
|
|
|
|
static void
|
|
_lei_u(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
if (i0)
|
|
ci(X86_CC_BE, r0, r1, i0);
|
|
else
|
|
ci0(X86_CC_E, r0, r1);
|
|
}
|
|
|
|
static void
|
|
_eqr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
if (r1 == r2)
|
|
movi(r0, 1);
|
|
else
|
|
cr(X86_CC_E, r0, r1, r2);
|
|
}
|
|
|
|
static void
|
|
_eqi(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
if (i0)
|
|
ci(X86_CC_E, r0, r1, i0);
|
|
else
|
|
ci0(X86_CC_E, r0, r1);
|
|
}
|
|
|
|
static void
|
|
_ger(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
if (r1 == r2)
|
|
movi(r0, 1);
|
|
else
|
|
cr(X86_CC_GE, r0, r1, r2);
|
|
}
|
|
|
|
static void
|
|
_gei(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
if (i0)
|
|
ci(X86_CC_GE, r0, r1, i0);
|
|
else
|
|
ci0(X86_CC_NS, r0, r1);
|
|
}
|
|
|
|
static void
|
|
_ger_u(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
if (r1 == r2)
|
|
movi(r0, 1);
|
|
else
|
|
cr(X86_CC_AE, r0, r1, r2);
|
|
}
|
|
|
|
static void
|
|
_gei_u(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
if (i0)
|
|
ci(X86_CC_AE, r0, r1, i0);
|
|
else
|
|
ci0(X86_CC_NB, r0, r1);
|
|
}
|
|
|
|
static void
|
|
_gtr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
if (r1 == r2)
|
|
movi(r0, 0);
|
|
else
|
|
cr(X86_CC_G, r0, r1, r2);
|
|
}
|
|
|
|
static void
|
|
_gtr_u(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
if (r1 == r2)
|
|
movi(r0, 0);
|
|
else
|
|
cr(X86_CC_A, r0, r1, r2);
|
|
}
|
|
|
|
static void
|
|
_gti_u(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
if (i0)
|
|
ci(X86_CC_A, r0, r1, i0);
|
|
else
|
|
ci0(X86_CC_NE, r0, r1);
|
|
}
|
|
|
|
static void
|
|
_ner(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
if (r1 == r2)
|
|
movi(r0, 0);
|
|
else
|
|
cr(X86_CC_NE, r0, r1, r2);
|
|
}
|
|
|
|
static void
|
|
_nei(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
if (i0)
|
|
ci(X86_CC_NE, r0, r1, i0);
|
|
else
|
|
ci0(X86_CC_NE, r0, r1);
|
|
}
|
|
|
|
static void
|
|
_movr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
if (r0 != r1) {
|
|
rex(0, 1, r1, _NOREG, r0);
|
|
ic(0x89);
|
|
ic(0xc0 | (r1 << 3) | r7(r0));
|
|
}
|
|
}
|
|
|
|
static void
|
|
_imovi(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
|
|
{
|
|
#if __WORDSIZE == 64
|
|
if (fits_uint32_p(i0)) {
|
|
rex(0, 0, _NOREG, _NOREG, r0);
|
|
ic(0xb8 | r7(r0));
|
|
ii(i0);
|
|
}
|
|
else {
|
|
rex(0, 1, _NOREG, _NOREG, r0);
|
|
ic(0xb8 | r7(r0));
|
|
il(i0);
|
|
}
|
|
#else
|
|
ic(0xb8 | r7(r0));
|
|
ii(i0);
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
_movi(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
|
|
{
|
|
if (i0)
|
|
imovi(r0, i0);
|
|
else
|
|
ixorr(r0, r0);
|
|
}
|
|
|
|
static jit_word_t
|
|
_movi_p(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
|
|
{
|
|
#if __WORDSIZE == 64
|
|
rex(0, 1, _NOREG, _NOREG, r0);
|
|
ic(0xb8 | r7(r0));
|
|
il(i0);
|
|
#else
|
|
ic(0xb8 | r7(r0));
|
|
ii(i0);
|
|
#endif
|
|
return (_jit->pc.w);
|
|
}
|
|
|
|
static void
|
|
_movcr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
rex(0, 1, r0, _NOREG, r1);
|
|
ic(0x0f);
|
|
ic(0xbe);
|
|
mrm(0x03, r7(r0), r7(r1));
|
|
}
|
|
|
|
static void
|
|
_movcr_u(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
rex(0, 1, r0, _NOREG, r1);
|
|
ic(0x0f);
|
|
ic(0xb6);
|
|
mrm(0x03, r7(r0), r7(r1));
|
|
}
|
|
|
|
static void
|
|
_movsr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
rex(0, 1, r0, _NOREG, r1);
|
|
ic(0x0f);
|
|
ic(0xbf);
|
|
mrm(0x03, r7(r0), r7(r1));
|
|
}
|
|
|
|
static void
|
|
_movsr_u(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
rex(0, 1, r0, _NOREG, r1);
|
|
ic(0x0f);
|
|
ic(0xb7);
|
|
mrm(0x03, r7(r0), r7(r1));
|
|
}
|
|
|
|
#if __WORDSIZE == 64
|
|
static void
|
|
_movir(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
rex(0, 1, r0, _NOREG, r1);
|
|
ic(0x63);
|
|
mrm(0x03, r7(r0), r7(r1));
|
|
}
|
|
|
|
static void
|
|
_movir_u(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
rex(0, 0, r1, _NOREG, r0);
|
|
ic(0x89);
|
|
ic(0xc0 | (r1 << 3) | r7(r0));
|
|
}
|
|
#endif
|
|
|
|
static void
|
|
_htonr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
movr(r0, r1);
|
|
rex(0, 1, _NOREG, _NOREG, r0);
|
|
ic(0x0f);
|
|
ic(0xc8 | r7(r0));
|
|
}
|
|
|
|
static void
|
|
_extr_c(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
jit_int32_t reg;
|
|
if (reg8_p(r1))
|
|
movcr(r0, r1);
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr|jit_class_rg8);
|
|
movr(rn(reg), r1);
|
|
movcr(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_extr_uc(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
jit_int32_t reg;
|
|
if (reg8_p(r1))
|
|
movcr_u(r0, r1);
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr|jit_class_rg8);
|
|
movr(rn(reg), r1);
|
|
movcr_u(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_ldr_c(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
rex(0, 1, r0, _NOREG, r1);
|
|
ic(0x0f);
|
|
ic(0xbe);
|
|
rx(r0, 0, r1, _NOREG, _SCL1);
|
|
}
|
|
|
|
static void
|
|
_ldi_c(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
if (can_sign_extend_int_p(i0)) {
|
|
rex(0, 1, r0, _NOREG, _NOREG);
|
|
ic(0x0f);
|
|
ic(0xbe);
|
|
rx(r0, i0, _NOREG, _NOREG, _SCL1);
|
|
}
|
|
else {
|
|
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)
|
|
{
|
|
rex(0, 1, r0, _NOREG, r1);
|
|
ic(0x0f);
|
|
ic(0xb6);
|
|
rx(r0, 0, r1, _NOREG, _SCL1);
|
|
}
|
|
|
|
static void
|
|
_ldi_uc(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
if (can_sign_extend_int_p(i0)) {
|
|
rex(0, 1, r0, _NOREG, _NOREG);
|
|
ic(0x0f);
|
|
ic(0xb6);
|
|
rx(r0, i0, _NOREG, _NOREG, _SCL1);
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
ldr_uc(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_ldr_s(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
rex(0, 1, r0, _NOREG, r1);
|
|
ic(0x0f);
|
|
ic(0xbf);
|
|
rx(r0, 0, r1, _NOREG, _SCL1);
|
|
}
|
|
|
|
static void
|
|
_ldi_s(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
if (can_sign_extend_int_p(i0)) {
|
|
rex(0, 1, r0, _NOREG, _NOREG);
|
|
ic(0x0f);
|
|
ic(0xbf);
|
|
rx(r0, i0, _NOREG, _NOREG, _SCL1);
|
|
}
|
|
else {
|
|
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)
|
|
{
|
|
rex(0, 1, r0, _NOREG, r1);
|
|
ic(0x0f);
|
|
ic(0xb7);
|
|
rx(r0, 0, r1, _NOREG, _SCL1);
|
|
}
|
|
|
|
static void
|
|
_ldi_us(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
if (can_sign_extend_int_p(i0)) {
|
|
rex(0, 1, r0, _NOREG, _NOREG);
|
|
ic(0x0f);
|
|
ic(0xb7);
|
|
rx(r0, i0, _NOREG, _NOREG, _SCL1);
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
ldr_us(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_ldr_i(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
#if __WORDSIZE == 64
|
|
rex(0, 1, r0, _NOREG, r1);
|
|
ic(0x63);
|
|
#else
|
|
ic(0x8b);
|
|
#endif
|
|
rx(r0, 0, r1, _NOREG, _SCL1);
|
|
}
|
|
|
|
static void
|
|
_ldi_i(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
if (can_sign_extend_int_p(i0)) {
|
|
#if __WORDSIZE == 64
|
|
rex(0, 1, r0, _NOREG, _NOREG);
|
|
ic(0x63);
|
|
#else
|
|
ic(0x8b);
|
|
#endif
|
|
rx(r0, i0, _NOREG, _NOREG, _SCL1);
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
ldr_i(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
#if __WORDSIZE == 64
|
|
static void
|
|
_ldr_ui(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
rex(0, 0, r0, _NOREG, r1);
|
|
ic(0x63);
|
|
rx(r0, 0, r1, _NOREG, _SCL1);
|
|
}
|
|
|
|
static void
|
|
_ldi_ui(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
if (can_sign_extend_int_p(i0)) {
|
|
rex(0, 0, r0, _NOREG, _NOREG);
|
|
ic(0x63);
|
|
rx(r0, i0, _NOREG, _NOREG, _SCL1);
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
ldr_ui(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_ldr_l(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
rex(0, 1, r0, _NOREG, r1);
|
|
ic(0x8b);
|
|
rx(r0, 0, r1, _NOREG, _SCL1);
|
|
}
|
|
|
|
static void
|
|
_ldi_l(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
if (can_sign_extend_int_p(i0)) {
|
|
rex(0, 1, r0, _NOREG, _NOREG);
|
|
ic(0x8b);
|
|
rx(r0, i0, _NOREG, _NOREG, _SCL1);
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
ldr_l(r0, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
static void
|
|
_ldxr_c(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
rex(0, 1, r0, r1, r2);
|
|
ic(0x0f);
|
|
ic(0xbe);
|
|
rx(r0, 0, r2, r1, _SCL1);
|
|
}
|
|
|
|
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 (can_sign_extend_int_p(i0)) {
|
|
rex(0, 1, r0, _NOREG, r1);
|
|
ic(0x0f);
|
|
ic(0xbe);
|
|
rx(r0, i0, r1, _NOREG, _SCL1);
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
ldxr_c(r0, r1, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_ldxr_uc(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
rex(0, 1, r0, r1, r2);
|
|
ic(0x0f);
|
|
ic(0xb6);
|
|
rx(r0, 0, r2, r1, _SCL1);
|
|
}
|
|
|
|
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 (can_sign_extend_int_p(i0)) {
|
|
rex(0, 1, r0, _NOREG, r1);
|
|
ic(0x0f);
|
|
ic(0xb6);
|
|
rx(r0, i0, r1, _NOREG, _SCL1);
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
ldxr_uc(r0, r1, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_ldxr_s(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
rex(0, 1, r0, r1, r2);
|
|
ic(0x0f);
|
|
ic(0xbf);
|
|
rx(r0, 0, r2, r1, _SCL1);
|
|
}
|
|
|
|
static void
|
|
_ldxi_s(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
if (can_sign_extend_int_p(i0)) {
|
|
rex(0, 1, r0, _NOREG, r1);
|
|
ic(0x0f);
|
|
ic(0xbf);
|
|
rx(r0, i0, r1, _NOREG, _SCL1);
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
ldxr_s(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)
|
|
{
|
|
rex(0, 1, r0, r1, r2);
|
|
ic(0x0f);
|
|
ic(0xb7);
|
|
rx(r0, 0, r2, r1, _SCL1);
|
|
}
|
|
|
|
static void
|
|
_ldxi_us(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
if (can_sign_extend_int_p(i0)) {
|
|
rex(0, 1, r0, _NOREG, r1);
|
|
ic(0x0f);
|
|
ic(0xb7);
|
|
rx(r0, i0, r1, _NOREG, _SCL1);
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
ldxr_us(r0, r1, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_ldxr_i(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
#if __WORDSIZE == 64
|
|
rex(0, 1, r0, r1, r2);
|
|
ic(0x63);
|
|
#else
|
|
ic(0x8b);
|
|
#endif
|
|
rx(r0, 0, r2, r1, _SCL1);
|
|
}
|
|
|
|
static void
|
|
_ldxi_i(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
if (can_sign_extend_int_p(i0)) {
|
|
#if __WORDSIZE == 64
|
|
rex(0, 1, r0, _NOREG, r1);
|
|
ic(0x63);
|
|
#else
|
|
ic(0x8b);
|
|
#endif
|
|
rx(r0, i0, r1, _NOREG, _SCL1);
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
ldxr_i(r0, r1, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
#if __WORDSIZE == 64
|
|
static void
|
|
_ldxr_ui(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
rex(0, 0, r0, r1, r2);
|
|
ic(0x8b);
|
|
rx(r0, 0, r2, r1, _SCL1);
|
|
}
|
|
|
|
static void
|
|
_ldxi_ui(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
if (can_sign_extend_int_p(i0)) {
|
|
rex(0, 0, r0, _NOREG, r1);
|
|
ic(0x8b);
|
|
rx(r0, i0, r1, _NOREG, _SCL1);
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
ldxr_ui(r0, r1, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_ldxr_l(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
rex(0, 1, r0, r1, r2);
|
|
ic(0x8b);
|
|
rx(r0, 0, r2, r1, _SCL1);
|
|
}
|
|
|
|
static void
|
|
_ldxi_l(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
|
|
{
|
|
jit_int32_t reg;
|
|
if (can_sign_extend_int_p(i0)) {
|
|
rex(0, 1, r0, _NOREG, r1);
|
|
ic(0x8b);
|
|
rx(r0, i0, r1, _NOREG, _SCL1);
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
ldxr_l(r0, r1, rn(reg));
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
static void
|
|
_str_c(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
jit_int32_t reg;
|
|
if (reg8_p(r1)) {
|
|
rex(0, 0, r1, _NOREG, r0);
|
|
ic(0x88);
|
|
rx(r1, 0, r0, _NOREG, _SCL1);
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr|jit_class_rg8);
|
|
movr(rn(reg), r1);
|
|
rex(0, 0, rn(reg), _NOREG, r0);
|
|
ic(0x88);
|
|
rx(rn(reg), 0, r0, _NOREG, _SCL1);
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_sti_c(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0)
|
|
{
|
|
jit_int32_t reg;
|
|
if (can_sign_extend_int_p(i0)) {
|
|
if (reg8_p(r0)) {
|
|
rex(0, 0, r0, _NOREG, _NOREG);
|
|
ic(0x88);
|
|
rx(r0, i0, _NOREG, _NOREG, _SCL1);
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr|jit_class_rg8);
|
|
movr(rn(reg), r0);
|
|
rex(0, 0, rn(reg), _NOREG, _NOREG);
|
|
ic(0x88);
|
|
rx(rn(reg), i0, _NOREG, _NOREG, _SCL1);
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
str_c(rn(reg), r0);
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_str_s(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
ic(0x66);
|
|
rex(0, 0, r1, _NOREG, r0);
|
|
ic(0x89);
|
|
rx(r1, 0, r0, _NOREG, _SCL1);
|
|
}
|
|
|
|
static void
|
|
_sti_s(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0)
|
|
{
|
|
jit_int32_t reg;
|
|
if (can_sign_extend_int_p(i0)) {
|
|
ic(0x66);
|
|
rex(0, 0, r0, _NOREG, _NOREG);
|
|
ic(0x89);
|
|
rx(r0, i0, _NOREG, _NOREG, _SCL1);
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
str_s(rn(reg), r0);
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_str_i(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
rex(0, 0, r1, _NOREG, r0);
|
|
ic(0x89);
|
|
rx(r1, 0, r0, _NOREG, _SCL1);
|
|
}
|
|
|
|
static void
|
|
_sti_i(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0)
|
|
{
|
|
jit_int32_t reg;
|
|
if (can_sign_extend_int_p(i0)) {
|
|
rex(0, 0, r0, _NOREG, _NOREG);
|
|
ic(0x89);
|
|
rx(r0, i0, _NOREG, _NOREG, _SCL1);
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
str_i(rn(reg), r0);
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
#if __WORDSIZE == 64
|
|
static void
|
|
_str_l(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
rex(0, 1, r1, _NOREG, r0);
|
|
ic(0x89);
|
|
rx(r1, 0, r0, _NOREG, _SCL1);
|
|
}
|
|
|
|
static void
|
|
_sti_l(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0)
|
|
{
|
|
jit_int32_t reg;
|
|
if (can_sign_extend_int_p(i0)) {
|
|
rex(0, 1, r0, _NOREG, _NOREG);
|
|
ic(0x89);
|
|
rx(r0, i0, _NOREG, _NOREG, _SCL1);
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
str_l(rn(reg), r0);
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
static void
|
|
_stxr_c(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
jit_int32_t reg;
|
|
if (reg8_p(r2)) {
|
|
rex(0, 0, r2, r1, r0);
|
|
ic(0x88);
|
|
rx(r2, 0, r0, r1, _SCL1);
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr|jit_class_rg8);
|
|
movr(rn(reg), r2);
|
|
rex(0, 0, rn(reg), r1, r0);
|
|
ic(0x88);
|
|
rx(rn(reg), 0, r0, r1, _SCL1);
|
|
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 (can_sign_extend_int_p(i0)) {
|
|
if (reg8_p(r1)) {
|
|
rex(0, 0, r1, _NOREG, r0);
|
|
ic(0x88);
|
|
rx(r1, i0, r0, _NOREG, _SCL1);
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr|jit_class_rg8);
|
|
movr(rn(reg), r1);
|
|
rex(0, 0, rn(reg), _NOREG, r0);
|
|
ic(0x88);
|
|
rx(rn(reg), i0, r0, _NOREG, _SCL1);
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
stxr_c(rn(reg), r0, r1);
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_stxr_s(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
ic(0x66);
|
|
rex(0, 0, r2, r1, r0);
|
|
ic(0x89);
|
|
rx(r2, 0, r0, r1, _SCL1);
|
|
}
|
|
|
|
static void
|
|
_stxi_s(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
jit_int32_t reg;
|
|
if (can_sign_extend_int_p(i0)) {
|
|
ic(0x66);
|
|
rex(0, 0, r1, _NOREG, r0);
|
|
ic(0x89);
|
|
rx(r1, i0, r0, _NOREG, _SCL1);
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
stxr_s(rn(reg), r0, r1);
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_stxr_i(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
rex(0, 0, r2, r1, r0);
|
|
ic(0x89);
|
|
rx(r2, 0, r0, r1, _SCL1);
|
|
}
|
|
|
|
static void
|
|
_stxi_i(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
jit_int32_t reg;
|
|
if (can_sign_extend_int_p(i0)) {
|
|
rex(0, 0, r1, _NOREG, r0);
|
|
ic(0x89);
|
|
rx(r1, i0, r0, _NOREG, _SCL1);
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
stxr_i(rn(reg), r0, r1);
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
|
|
#if __WORDSIZE == 64
|
|
static void
|
|
_stxr_l(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
|
|
{
|
|
rex(0, 1, r2, r1, r0);
|
|
ic(0x89);
|
|
rx(r2, 0, r0, r1, _SCL1);
|
|
}
|
|
|
|
static void
|
|
_stxi_l(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
jit_int32_t reg;
|
|
if (can_sign_extend_int_p(i0)) {
|
|
rex(0, 1, r1, _NOREG, r0);
|
|
ic(0x89);
|
|
rx(r1, i0, r0, _NOREG, _SCL1);
|
|
}
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i0);
|
|
stxr_l(rn(reg), r0, r1);
|
|
jit_unget_reg(reg);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
static void
|
|
_jccs(jit_state_t *_jit, jit_int32_t code, jit_word_t i0)
|
|
{
|
|
jit_word_t w;
|
|
ic(0x70 | code);
|
|
w = i0 - (_jit->pc.w + 1);
|
|
ic(w);
|
|
}
|
|
|
|
static void
|
|
_jcc(jit_state_t *_jit, jit_int32_t code, jit_word_t i0)
|
|
{
|
|
jit_word_t w;
|
|
ic(0x0f);
|
|
ic(0x80 | code);
|
|
w = i0 - (_jit->pc.w + 4);
|
|
ii(w);
|
|
}
|
|
|
|
static void
|
|
_jcr(jit_state_t *_jit,
|
|
jit_int32_t code, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
alur(X86_CMP, r0, r1);
|
|
jcc(code, i0);
|
|
}
|
|
|
|
static void
|
|
_jci(jit_state_t *_jit,
|
|
jit_int32_t code, jit_word_t i0, jit_int32_t r0, jit_word_t i1)
|
|
{
|
|
alui(X86_CMP, r0, i1);
|
|
jcc(code, i0);
|
|
}
|
|
|
|
static void
|
|
_jci0(jit_state_t *_jit, jit_int32_t code, jit_word_t i0, jit_int32_t r0)
|
|
{
|
|
testr(r0, r0);
|
|
jcc(code, i0);
|
|
}
|
|
|
|
static jit_word_t
|
|
_bltr(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
jcr(X86_CC_L, i0, r0, r1);
|
|
return (_jit->pc.w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_blti(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_word_t i1)
|
|
{
|
|
if (i1) jci (X86_CC_L, i0, r0, i1);
|
|
else jci0(X86_CC_S, i0, r0);
|
|
return (_jit->pc.w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_bltr_u(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
jcr(X86_CC_B, i0, r0, r1);
|
|
return (_jit->pc.w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_blti_u(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_word_t i1)
|
|
{
|
|
if (i1) jci (X86_CC_B, i0, r0, i1);
|
|
else jci0(X86_CC_B, i0, r0);
|
|
return (_jit->pc.w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_bler(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
if (r0 == r1) jmpi(i0);
|
|
else jcr (X86_CC_LE, i0, r0, r1);
|
|
return (_jit->pc.w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_blei(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_word_t i1)
|
|
{
|
|
if (i1) jci (X86_CC_LE, i0, r0, i1);
|
|
else jci0(X86_CC_LE, i0, r0);
|
|
return (_jit->pc.w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_bler_u(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
if (r0 == r1) jmpi(i0);
|
|
else jcr (X86_CC_BE, i0, r0, r1);
|
|
return (_jit->pc.w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_blei_u(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_word_t i1)
|
|
{
|
|
if (i1) jci (X86_CC_BE, i0, r0, i1);
|
|
else jci0(X86_CC_BE, i0, r0);
|
|
return (_jit->pc.w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_beqr(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
if (r0 == r1) jmpi(i0);
|
|
else jcr (X86_CC_E, i0, r0, r1);
|
|
return (_jit->pc.w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_beqi(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_word_t i1)
|
|
{
|
|
if (i1) jci (X86_CC_E, i0, r0, i1);
|
|
else jci0(X86_CC_E, i0, r0);
|
|
return (_jit->pc.w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_bger(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
if (r0 == r1) jmpi(i0);
|
|
else jcr (X86_CC_GE, i0, r0, r1);
|
|
return (_jit->pc.w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_bgei(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_word_t i1)
|
|
{
|
|
if (i1) jci (X86_CC_GE, i0, r0, i1);
|
|
else jci0(X86_CC_NS, i0, r0);
|
|
return (_jit->pc.w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_bger_u(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
if (r0 == r1) jmpi(i0);
|
|
else jcr (X86_CC_AE, i0, r0, r1);
|
|
return (_jit->pc.w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_bgei_u(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_word_t i1)
|
|
{
|
|
if (i1) jci (X86_CC_AE, i0, r0, i1);
|
|
else jmpi(i0);
|
|
return (_jit->pc.w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_bgtr(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
jcr(X86_CC_G, i0, r0, r1);
|
|
return (_jit->pc.w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_bgti(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_word_t i1)
|
|
{
|
|
jci(X86_CC_G, i0, r0, i1);
|
|
return (_jit->pc.w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_bgtr_u(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
jcr(X86_CC_A, i0, r0, r1);
|
|
return (_jit->pc.w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_bgti_u(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_word_t i1)
|
|
{
|
|
if (i1) jci (X86_CC_A, i0, r0, i1);
|
|
else jci0(X86_CC_NE, i0, r0);
|
|
return (_jit->pc.w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_bner(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
jcr(X86_CC_NE, i0, r0, r1);
|
|
return (_jit->pc.w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_bnei(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_word_t i1)
|
|
{
|
|
if (i1) jci (X86_CC_NE, i0, r0, i1);
|
|
else jci0(X86_CC_NE, i0, r0);
|
|
return (_jit->pc.w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_bmsr(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
testr(r0, r1);
|
|
jnz(i0);
|
|
return (_jit->pc.w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_bmsi(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_word_t i1)
|
|
{
|
|
jit_int32_t reg;
|
|
if (can_zero_extend_int_p(i1))
|
|
testi(r0, i1);
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i1);
|
|
testr(r0, rn(reg));
|
|
}
|
|
jnz(i0);
|
|
return (_jit->pc.w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_bmcr(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
testr(r0, r1);
|
|
jz(i0);
|
|
return (_jit->pc.w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_bmci(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_word_t i1)
|
|
{
|
|
jit_int32_t reg;
|
|
if (can_zero_extend_int_p(i1))
|
|
testi(r0, i1);
|
|
else {
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
movi(rn(reg), i1);
|
|
testr(r0, rn(reg));
|
|
}
|
|
jz(i0);
|
|
return (_jit->pc.w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_boaddr(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
iaddr(r0, r1);
|
|
jo(i0);
|
|
return (_jit->pc.w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_boaddi(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_word_t i1)
|
|
{
|
|
jit_int32_t reg;
|
|
if (can_sign_extend_int_p(i1)) {
|
|
iaddi(r0, i1);
|
|
jo(i0);
|
|
return (_jit->pc.w);
|
|
}
|
|
reg = jit_get_reg(jit_class_gpr|jit_class_nospill);
|
|
movi(rn(reg), i1);
|
|
jit_unget_reg(reg);
|
|
return (boaddr(i0, r0, rn(reg)));
|
|
}
|
|
|
|
static jit_word_t
|
|
_boaddr_u(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
iaddr(r0, r1);
|
|
jc(i0);
|
|
return (_jit->pc.w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_boaddi_u(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_word_t i1)
|
|
{
|
|
jit_int32_t reg;
|
|
if (can_sign_extend_int_p(i1)) {
|
|
iaddi(r0, i1);
|
|
jc(i0);
|
|
return (_jit->pc.w);
|
|
}
|
|
reg = jit_get_reg(jit_class_gpr|jit_class_nospill);
|
|
movi(rn(reg), i1);
|
|
jit_unget_reg(reg);
|
|
return (boaddr_u(i0, r0, rn(reg)));
|
|
}
|
|
|
|
static jit_word_t
|
|
_bxaddr(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
iaddr(r0, r1);
|
|
jno(i0);
|
|
return (_jit->pc.w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_bxaddi(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_word_t i1)
|
|
{
|
|
jit_int32_t reg;
|
|
if (can_sign_extend_int_p(i1)) {
|
|
iaddi(r0, i1);
|
|
jno(i0);
|
|
return (_jit->pc.w);
|
|
}
|
|
reg = jit_get_reg(jit_class_gpr|jit_class_nospill);
|
|
movi(rn(reg), i1);
|
|
jit_unget_reg(reg);
|
|
return (bxaddr(i0, r0, rn(reg)));
|
|
}
|
|
|
|
static jit_word_t
|
|
_bxaddr_u(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
iaddr(r0, r1);
|
|
jnc(i0);
|
|
return (_jit->pc.w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_bxaddi_u(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_word_t i1)
|
|
{
|
|
jit_int32_t reg;
|
|
if (can_sign_extend_int_p(i1)) {
|
|
iaddi(r0, i1);
|
|
jnc(i0);
|
|
return (_jit->pc.w);
|
|
}
|
|
reg = jit_get_reg(jit_class_gpr|jit_class_nospill);
|
|
movi(rn(reg), i1);
|
|
jit_unget_reg(reg);
|
|
return (bxaddr_u(i0, r0, rn(reg)));
|
|
}
|
|
|
|
static jit_word_t
|
|
_bosubr(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
isubr(r0, r1);
|
|
jo(i0);
|
|
return (_jit->pc.w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_bosubi(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_word_t i1)
|
|
{
|
|
jit_int32_t reg;
|
|
if (can_sign_extend_int_p(i1)) {
|
|
isubi(r0, i1);
|
|
jo(i0);
|
|
return (_jit->pc.w);
|
|
}
|
|
reg = jit_get_reg(jit_class_gpr|jit_class_nospill);
|
|
movi(rn(reg), i1);
|
|
jit_unget_reg(reg);
|
|
return (bosubr(i0, r0, rn(reg)));
|
|
}
|
|
|
|
static jit_word_t
|
|
_bosubr_u(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
isubr(r0, r1);
|
|
jc(i0);
|
|
return (_jit->pc.w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_bosubi_u(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_word_t i1)
|
|
{
|
|
jit_int32_t reg;
|
|
if (can_sign_extend_int_p(i1)) {
|
|
isubi(r0, i1);
|
|
jc(i0);
|
|
return (_jit->pc.w);
|
|
}
|
|
reg = jit_get_reg(jit_class_gpr|jit_class_nospill);
|
|
movi(rn(reg), i1);
|
|
jit_unget_reg(reg);
|
|
return (bosubr_u(i0, r0, rn(reg)));
|
|
}
|
|
|
|
static jit_word_t
|
|
_bxsubr(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
isubr(r0, r1);
|
|
jno(i0);
|
|
return (_jit->pc.w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_bxsubi(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_word_t i1)
|
|
{
|
|
jit_int32_t reg;
|
|
if (can_sign_extend_int_p(i1)) {
|
|
isubi(r0, i1);
|
|
jno(i0);
|
|
return (_jit->pc.w);
|
|
}
|
|
reg = jit_get_reg(jit_class_gpr|jit_class_nospill);
|
|
movi(rn(reg), i1);
|
|
jit_unget_reg(reg);
|
|
return (bxsubr(i0, r0, rn(reg)));
|
|
}
|
|
|
|
static jit_word_t
|
|
_bxsubr_u(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
|
|
{
|
|
isubr(r0, r1);
|
|
jnc(i0);
|
|
return (_jit->pc.w);
|
|
}
|
|
|
|
static jit_word_t
|
|
_bxsubi_u(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_word_t i1)
|
|
{
|
|
jit_int32_t reg;
|
|
if (can_sign_extend_int_p(i1)) {
|
|
isubi(r0, i1);
|
|
jnc(i0);
|
|
return (_jit->pc.w);
|
|
}
|
|
reg = jit_get_reg(jit_class_gpr|jit_class_nospill);
|
|
movi(rn(reg), i1);
|
|
jit_unget_reg(reg);
|
|
return (bxsubr_u(i0, r0, rn(reg)));
|
|
}
|
|
|
|
static void
|
|
_callr(jit_state_t *_jit, jit_int32_t r0)
|
|
{
|
|
#if __WORDSIZE == 32
|
|
emms();
|
|
#endif
|
|
rex(0, 0, _NOREG, _NOREG, r0);
|
|
ic(0xff);
|
|
mrm(0x03, 0x02, r7(r0));
|
|
}
|
|
|
|
static jit_word_t
|
|
_calli(jit_state_t *_jit, jit_word_t i0)
|
|
{
|
|
jit_word_t word;
|
|
#if __WORDSIZE == 64
|
|
jit_int32_t reg;
|
|
|
|
reg = jit_get_reg(jit_class_gpr);
|
|
word = movi_p(rn(reg), i0);
|
|
callr(rn(reg));
|
|
jit_unget_reg(reg);
|
|
#else
|
|
jit_word_t w;
|
|
emms();
|
|
ic(0xe8);
|
|
w = i0 - (_jit->pc.w + 4);
|
|
ii(w);
|
|
word = _jit->pc.w;
|
|
#endif
|
|
return (word);
|
|
}
|
|
|
|
static void
|
|
_jmpr(jit_state_t *_jit, jit_int32_t r0)
|
|
{
|
|
rex(0, 1, _NOREG, _NOREG, r0);
|
|
ic(0xff);
|
|
mrm(0x03, 0x04, r7(r0));
|
|
}
|
|
|
|
static jit_word_t
|
|
_jmpi(jit_state_t *_jit, jit_word_t i0)
|
|
{
|
|
jit_word_t w;
|
|
ic(0xe9);
|
|
w = i0 - (_jit->pc.w + 4);
|
|
ii(w);
|
|
return (_jit->pc.w);
|
|
}
|
|
|
|
static void
|
|
_prolog(jit_state_t *_jit, jit_node_t *node)
|
|
{
|
|
if (_jitc->function->define_frame || _jitc->function->assume_frame) {
|
|
jit_int32_t frame = -_jitc->function->frame;
|
|
assert(_jitc->function->self.aoff >= frame);
|
|
if (_jitc->function->assume_frame)
|
|
return;
|
|
_jitc->function->self.aoff = frame;
|
|
}
|
|
#if __WORDSIZE == 64 && __CYGWIN__
|
|
_jitc->function->stack = (((/* first 32 bytes must be allocated */
|
|
(_jitc->function->self.alen > 32 ?
|
|
_jitc->function->self.alen : 32) -
|
|
/* align stack at 16 bytes */
|
|
_jitc->function->self.aoff) + 15) & -16) +
|
|
stack_adjust;
|
|
#else
|
|
_jitc->function->stack = (((_jitc->function->self.alen -
|
|
_jitc->function->self.aoff) + 15) & -16) +
|
|
stack_adjust;
|
|
#endif
|
|
/* callee save registers */
|
|
subi(_RSP_REGNO, _RSP_REGNO, stack_framesize - sizeof(jit_word_t));
|
|
#if __WORDSIZE == 32
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _RDI))
|
|
stxi(12, _RSP_REGNO, _RDI_REGNO);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _RSI))
|
|
stxi( 8, _RSP_REGNO, _RSI_REGNO);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _RBX))
|
|
stxi( 4, _RSP_REGNO, _RBX_REGNO);
|
|
#else
|
|
# if __CYGWIN__
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _XMM15))
|
|
sse_stxi_d(136, _RSP_REGNO, _XMM15_REGNO);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _XMM14))
|
|
sse_stxi_d(128, _RSP_REGNO, _XMM14_REGNO);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _XMM13))
|
|
sse_stxi_d(120, _RSP_REGNO, _XMM13_REGNO);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _XMM12))
|
|
sse_stxi_d(112, _RSP_REGNO, _XMM12_REGNO);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _XMM11))
|
|
sse_stxi_d(104, _RSP_REGNO, _XMM11_REGNO);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _XMM10))
|
|
sse_stxi_d(96, _RSP_REGNO, _XMM10_REGNO);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _XMM9))
|
|
sse_stxi_d(88, _RSP_REGNO, _XMM9_REGNO);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _XMM8))
|
|
sse_stxi_d(80, _RSP_REGNO, _XMM8_REGNO);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _XMM7))
|
|
sse_stxi_d(72, _RSP_REGNO, _XMM7_REGNO);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _XMM6))
|
|
sse_stxi_d(64, _RSP_REGNO, _XMM6_REGNO);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _R15))
|
|
stxi(56, _RSP_REGNO, _R15_REGNO);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _R14))
|
|
stxi(48, _RSP_REGNO, _R14_REGNO);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _R13))
|
|
stxi(40, _RSP_REGNO, _R13_REGNO);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _R12))
|
|
stxi(32, _RSP_REGNO, _R12_REGNO);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _RSI))
|
|
stxi(24, _RSP_REGNO, _RSI_REGNO);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _RDI))
|
|
stxi(16, _RSP_REGNO, _RDI_REGNO);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _RBX))
|
|
stxi( 8, _RSP_REGNO, _RBX_REGNO);
|
|
# else
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _RBX))
|
|
stxi(40, _RSP_REGNO, _RBX_REGNO);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _R12))
|
|
stxi(32, _RSP_REGNO, _R12_REGNO);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _R13))
|
|
stxi(24, _RSP_REGNO, _R13_REGNO);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _R14))
|
|
stxi(16, _RSP_REGNO, _R14_REGNO);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _R15))
|
|
stxi( 8, _RSP_REGNO, _R15_REGNO);
|
|
# endif
|
|
#endif
|
|
stxi(0, _RSP_REGNO, _RBP_REGNO);
|
|
movr(_RBP_REGNO, _RSP_REGNO);
|
|
|
|
/* alloca */
|
|
subi(_RSP_REGNO, _RSP_REGNO, _jitc->function->stack);
|
|
}
|
|
|
|
static void
|
|
_epilog(jit_state_t *_jit, jit_node_t *node)
|
|
{
|
|
if (_jitc->function->assume_frame)
|
|
return;
|
|
/* callee save registers */
|
|
movr(_RSP_REGNO, _RBP_REGNO);
|
|
#if __WORDSIZE == 32
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _RDI))
|
|
ldxi(_RDI_REGNO, _RSP_REGNO, 12);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _RSI))
|
|
ldxi(_RSI_REGNO, _RSP_REGNO, 8);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _RBX))
|
|
ldxi(_RBX_REGNO, _RSP_REGNO, 4);
|
|
#else
|
|
# if __CYGWIN__
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _XMM15))
|
|
sse_ldxi_d(_XMM15_REGNO, _RSP_REGNO, 136);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _XMM14))
|
|
sse_ldxi_d(_XMM14_REGNO, _RSP_REGNO, 128);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _XMM13))
|
|
sse_ldxi_d(_XMM13_REGNO, _RSP_REGNO, 120);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _XMM12))
|
|
sse_ldxi_d(_XMM12_REGNO, _RSP_REGNO, 112);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _XMM11))
|
|
sse_ldxi_d(_XMM11_REGNO, _RSP_REGNO, 104);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _XMM10))
|
|
sse_ldxi_d(_XMM10_REGNO, _RSP_REGNO, 96);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _XMM9))
|
|
sse_ldxi_d(_XMM9_REGNO, _RSP_REGNO, 88);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _XMM8))
|
|
sse_ldxi_d(_XMM8_REGNO, _RSP_REGNO, 80);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _XMM7))
|
|
sse_ldxi_d(_XMM7_REGNO, _RSP_REGNO, 72);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _XMM6))
|
|
sse_ldxi_d(_XMM6_REGNO, _RSP_REGNO, 64);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _R15))
|
|
ldxi(_R15_REGNO, _RSP_REGNO, 56);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _R14))
|
|
ldxi(_R14_REGNO, _RSP_REGNO, 48);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _R13))
|
|
ldxi(_R13_REGNO, _RSP_REGNO, 40);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _R12))
|
|
ldxi(_R12_REGNO, _RSP_REGNO, 32);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _RSI))
|
|
ldxi(_RSI_REGNO, _RSP_REGNO, 24);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _RDI))
|
|
ldxi(_RDI_REGNO, _RSP_REGNO, 16);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _RBX))
|
|
ldxi(_RBX_REGNO, _RSP_REGNO, 8);
|
|
# else
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _RBX))
|
|
ldxi(_RBX_REGNO, _RSP_REGNO, 40);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _R12))
|
|
ldxi(_R12_REGNO, _RSP_REGNO, 32);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _R13))
|
|
ldxi(_R13_REGNO, _RSP_REGNO, 24);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _R14))
|
|
ldxi(_R14_REGNO, _RSP_REGNO, 16);
|
|
if (jit_regset_tstbit(&_jitc->function->regset, _R15))
|
|
ldxi(_R15_REGNO, _RSP_REGNO, 8);
|
|
# endif
|
|
#endif
|
|
ldxi(_RBP_REGNO, _RSP_REGNO, 0);
|
|
addi(_RSP_REGNO, _RSP_REGNO, stack_framesize - sizeof(jit_word_t));
|
|
|
|
ic(0xc3);
|
|
}
|
|
|
|
static void
|
|
_patch_at(jit_state_t *_jit, jit_node_t *node,
|
|
jit_word_t instr, jit_word_t label)
|
|
{
|
|
switch (node->code) {
|
|
#if __WORDSIZE == 64
|
|
case jit_code_calli:
|
|
#endif
|
|
case jit_code_movi:
|
|
patch_abs(instr, label);
|
|
break;
|
|
default:
|
|
patch_rel(instr, label);
|
|
break;
|
|
}
|
|
}
|
|
|
|
# if __WORDSIZE == 64 && !defined(HAVE_FFSL)
|
|
static int
|
|
ffsl(long i)
|
|
{
|
|
int bit;
|
|
# if __CYGWIN__
|
|
/* Bug workaround */
|
|
if ((int)i == (int)0x80000000)
|
|
bit = 32;
|
|
else
|
|
# endif
|
|
if ((bit = ffs((int)i)) == 0) {
|
|
if ((bit = ffs((int)((unsigned long)i >> 32))))
|
|
bit += 32;
|
|
}
|
|
return (bit);
|
|
}
|
|
# endif
|
|
#endif
|