mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-30 03:40:34 +02:00
3387 lines
84 KiB
C
3387 lines
84 KiB
C
/*
|
|
* Copyright (C) 2012, 2013 Free Software Foundation, Inc.
|
|
*
|
|
* This is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This software 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 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)
|
|
# define reg8_p(rn) 1
|
|
# 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 _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 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 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_int32_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);
|
|
#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 (r7(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
|
|
_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, 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_int32_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);
|
|
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);
|
|
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);
|
|
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);
|
|
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);
|
|
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);
|
|
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);
|
|
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);
|
|
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);
|
|
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);
|
|
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);
|
|
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);
|
|
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)
|
|
{
|
|
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;
|
|
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 __WORDSIZE == 32
|
|
_jitc->function->stack = (((_jitc->function->self.alen -
|
|
_jitc->function->self.aoff) + 15) & -16) + 12;
|
|
#else
|
|
_jitc->function->stack = (((_jitc->function->self.alen -
|
|
_jitc->function->self.aoff) + 15) & -16) + 8;
|
|
#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 (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
|
|
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)
|
|
{
|
|
/* 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 (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
|
|
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;
|
|
}
|
|
}
|
|
#endif
|