/*
 * Copyright (C) 2013-2023  Free Software Foundation, Inc.
 *
 * This file is part of GNU lightning.
 *
 * GNU lightning is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation; either version 3, or (at your option)
 * any later version.
 *
 * GNU lightning is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 * License for more details.
 *
 * Authors:
 *	Paulo Cesar Pereira de Andrade
 */

#if PROTO
#  define _G2_REGNO				0x02
#  define _G3_REGNO				0x03
#  define _G4_REGNO				0x04
#  define _O0_REGNO				0x08
#  define _O1_REGNO				0x09
#  define _SP_REGNO				0x0e
#  define _FP_REGNO				0x1e
#  define _O7_REGNO				0x0f
#  define _L0_REGNO				0x10
#  define _L1_REGNO				0x11
#  define _L2_REGNO				0x12
#  define _L3_REGNO				0x13
#  define _L4_REGNO				0x14
#  define _L5_REGNO				0x15
#  define _L6_REGNO				0x16
#  define _L7_REGNO				0x17
#  define _I7_REGNO				0x1f
/*
 *					- previous stack frame
 * fp	----
 * fp-	local variables (in lightning, 8 bytes space for float conversion)
 * fp-	alloca
 * sp+	stack arguments
 * sp+	6 words to save register arguments
 * sp+	1 word for hidden address of aggregate return value (32 bits only)
 * sp+	16 words for in and local registers
 * sp	----
 *	decreasing memory address	- next stack frame (not yet allocated)
 */
#  define stack_framesize			((16 + (__WORDSIZE == 32) + 6) * sizeof(jit_word_t))
typedef union {
    struct {				jit_uint32_t b: 2;	} op;
    struct {	jit_uint32_t _: 2;	jit_uint32_t b: 1;	} a;
    struct {	jit_uint32_t _: 2;	jit_uint32_t b: 5;	} rd;
    struct {	jit_uint32_t _: 2;	jit_uint32_t b: 30;	} disp30;
    struct {	jit_uint32_t _: 3;	jit_uint32_t b: 4;	} cond;
    struct {	jit_uint32_t _: 7;	jit_uint32_t b: 3;	} op2;
    struct {	jit_uint32_t _: 7;	jit_uint32_t b: 6;	} op3;
    struct {	jit_uint32_t _: 10;	jit_uint32_t b: 1;	} cc1;
    struct {	jit_uint32_t _: 10;	jit_uint32_t b: 22;	} imm22;
    struct {	jit_uint32_t _: 10;	jit_uint32_t b: 22;	} disp22;
    struct {	jit_uint32_t _: 11;	jit_uint32_t b: 1;	} cc0;
    struct {	jit_uint32_t _: 12;	jit_uint32_t b: 1;	} p;
    struct {	jit_uint32_t _: 13;	jit_uint32_t b: 19;	} disp19;
    struct {	jit_uint32_t _: 13;	jit_uint32_t b: 5;	} rs1;
    struct {	jit_uint32_t _: 18;	jit_uint32_t b: 1;	} i;
    struct {	jit_uint32_t _: 18;	jit_uint32_t b: 9;	} opf;
    struct {	jit_uint32_t _: 19;	jit_uint32_t b: 1;	} x;
    struct {	jit_uint32_t _: 19;	jit_uint32_t b: 8;	} asi;
    struct {	jit_uint32_t _: 19;	jit_uint32_t b: 6;	} res;
    struct {	jit_uint32_t _: 19;	jit_uint32_t b: 13;	} simm13;
    struct {	jit_uint32_t _: 20;	jit_uint32_t b: 7;	} asix;
    struct {	jit_uint32_t _: 20;	jit_uint32_t b: 6;	} asis;
    struct {	jit_uint32_t _: 26;	jit_uint32_t b: 6;	} shim;
    struct {	jit_uint32_t _: 25;	jit_uint32_t b: 7;	} imm7;
    struct {	jit_uint32_t _: 27;	jit_uint32_t b: 5;	} rs2;
    jit_int32_t							  v;
} jit_instr_t;
#  define ii(i)				*_jit->pc.ui++ = i
#  define s7_p(imm)			((imm) <= 63 && (imm) >= -64)
#  define s13_p(imm)			((imm) <= 4095 && (imm) >= -4096)
#  define s19_p(imm)			((imm) <= 262143 && (imm) >= -262144)
#  define s22_p(imm)			((imm) <= 2097151 && (imm) >= -20971512)
#  define s30_p(imm)			((imm) <= 536870911 && (imm) >= -536870912)
#  define f1(op, disp30)		_f1(_jit, op, disp30)
static void _f1(jit_state_t*,jit_int32_t,jit_int32_t);
#  define f2r(op, rd, op2, imm22)	_f2r(_jit, op, rd, op2, imm22)
static void _f2r(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t);
#  define f2b(op, a, cond, op2, disp22)	_f2b(_jit, op, a, cond, op2, disp22)
static void
_f2b(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t);
#  if __WORDSIZE == 64
#    define f2bp(op,a,cond,op2,cc1,cc0,p,disp19)				\
	_f2bp(_jit,op,a,cond,op2,cc1,cc0,p,disp19)
static void
_f2bp(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t,
      jit_int32_t,jit_int32_t,jit_int32_t);
#  endif
#  define f3r(op, rd, op3, rs1, rs2)	_f3r(_jit, op, rd, op3, rs1, rs2)
static void _f3r(jit_state_t*,
		 jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t);
#  if __WORDSIZE == 64
#  define f3ri(op, rd, op3, rs1, rs2)	_f3ri(_jit, op, rd, op3, rs1, rs2)
static void _f3ri(jit_state_t*,
		  jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t);
#  define f3rx(op, rd, op3, rs1, rs2)	_f3rx(_jit, op, rd, op3, rs1, rs2)
static void _f3rx(jit_state_t*,
		  jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t);
#  endif
#  define f3i(op, rd, op3, rs1, simm13)	_f3i(_jit, op, rd, op3, rs1, simm13)
static void _f3i(jit_state_t*,
		 jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t);
#  define f3s(op, rd, op3, rs1, simm13)	_f3s(_jit, op, rd, op3, rs1, simm13)
static void _f3s(jit_state_t*,
		 jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t);
#  define f3t(cond, rs1, i, ri)		_f3t(_jit, cond, rs1, i, ri)
static void _f3t(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t)
    maybe_unused;
#  define f3a(op,rd,op3,rs1,asi,rs2)	_f3a(_jit, op, rd, op3, rs1, asi, rs2)
static void _f3a(jit_state_t*,jit_int32_t,
		 jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t)
    maybe_unused;
#  define f2c1(op,rd,op3,rs1,opf,rs2)	_f2c1(_jit,op,rd,op3,rs1,opf,rs2)
static void
_f2c1(jit_state_t*,jit_int32_t, jit_int32_t,
      jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t)
    maybe_unused;
#  define LDSB(rs1, rs2, rd)		f3r(3, rd, 9, rs1, rs2)
#  define LDSBI(rs1, imm, rd)		f3i(3, rd, 9, rs1, imm)
#  define LDSH(rs1, rs2, rd)		f3r(3, rd, 10, rs1, rs2)
#  define LDSHI(rs1, imm, rd)		f3i(3, rd, 10, rs1, imm)
#  define LDUB(rs1, rs2, rd)		f3r(3, rd, 1, rs1, rs2)
#  define LDUBI(rs1, imm, rd)		f3i(3, rd, 1, rs1, imm)
#  define LDUH(rs1, rs2, rd)		f3r(3, rd, 2, rs1, rs2)
#  define LDUHI(rs1, imm, rd)		f3i(3, rd, 2, rs1, imm)
#  if __WORDSIZE == 32
#    define LD(rs1, rs2, rd)		f3r(3, rd, 0, rs1, rs2)
#    define LDI(rs1, imm, rd)		f3i(3, rd, 0, rs1, imm)
#    define LDD(rs1, rs2, rd)		f3r(3, rd, 3, rs1, rs2)
#    define LDDI(rs1, imm, rd)		f3i(3, rd, 3, rs1, imm)
#  else
#    define LDSW(rs1, rs2, rd)		f3r(3, rd, 8, rs1, rs2)
#    define LDSWI(rs1, imm, rd)		f3i(3, rd, 8, rs1, imm)
#    define LDUW(rs1, rs2, rd)		f3r(3, rd, 0, rs1, rs2)
#    define LDUWI(rs1, imm, rd)		f3i(3, rd, 0, rs1, imm)
#    define LDX(rs1, rs2, rd)		f3r(3, rd, 11, rs1, rs2)
#    define LDXI(rs1, imm, rd)		f3i(3, rd, 11, rs1, imm)
#  endif
#  define LDSBA(rs1, rs2, asi, rd)	f3a(3, rd, 25, rs1, asi, rs2)
#  define LDSHA(rs1, rs2, asi, rd)	f3a(3, rd, 26, rs1, asi, rs2)
#  define LDUBA(rs1, rs2, asi, rd)	f3a(3, rd, 17, rs1, asi, rs2)
#  define LDUHA(rs1, rs2, asi, rd)	f3a(3, rd, 18, rs1, asi, rs2)
#  if __WORDSIZE == 32
#    define LDA(rs1, rs2, asi, rd)	f3a(3, rd, 16, rs1, asi, rs2)
#    define LDDA(rs1, rs2, asi, rd)	f3a(3, rd, 19, rs1, asi, rs2)
#  else
#    define LDSWA(rs1, rs2, asi, rd)	f3a(3, rd, 24, rs1, asi, rs2)
#    define LDUWA(rs1, rs2, asi, rd)	f3a(3, rd, 16, rs1, asi, rs2)
#    define LDXA(rs1, rs2, asi, rd)	f3a(3, rd, 27, rs1, asi, rs2)
#  endif
#  define LDC(rs1, rs2, rd)		f3r(3, rd, 48, rs1, rs2)
#  define LDCI(rs1, imm, rd)		f3i(3, rd, 48, rs1, imm)
#  define LDDC(rs1, rs2, rd)		f3r(3, rd, 51, rs1, rs2)
#  define LDDCI(rs1, imm, rd)		f3i(3, rd, 51, rs1, imm)
#  define LDCSR(rs1, rs2, rd)		f3r(3, rd, 49, rs1, rs2)
#  define LDCSRI(rs1, imm, rd)		f3i(3, rd, 49, rs1, imm)
#  define STB(rd, rs1, rs2)		f3r(3, rd, 5, rs1, rs2)
#  define STBI(rd, rs1, imm)		f3i(3, rd, 5, rs1, imm)
#  define STH(rd, rs1, rs2)		f3r(3, rd, 6, rs1, rs2)
#  define STHI(rd, rs1, imm)		f3i(3, rd, 6, rs1, imm)
#  if __WORDSIZE == 32
#    define ST(rd, rs1, rs2)		f3r(3, rd, 4, rs1, rs2)
#    define STI(rd, rs1, imm)		f3i(3, rd, 4, rs1, imm)
#    define STD(rrd, s1, rs2)		f3r(3, rd, 7, rs1, rs2)
#    define STDI(rd, rs1, imm)		f3i(3, rd, 7, rs1, imm)
#  else
#    define STW(rd, rs1, rs2)		f3r(3, rd, 4, rs1, rs2)
#    define STWI(rd, rs1, imm)		f3i(3, rd, 4, rs1, imm)
#    define STX(rd, rs1, rs2)		f3r(3, rd, 14, rs1, rs2)
#    define STXI(rd, rs1, imm)		f3i(3, rd, 14, rs1, imm)
#  endif
#  define STBA(rd, rs1, rs2)		f3a(3, rd, 21, rs1, asi, rs2)
#  define STHA(rd, rs1, rs2)		f3a(3, rd, 22, rs1, asi, rs2)
#  if __WORDSIZE == 32
#    define STA(rd, rs1, rs2)		f3a(3, rd, 20, rs1, asi, rs2)
#    define STDA(rd, rs1, rs2)		f3a(3, rd, 23, rs1, asi, rs2)
#  else
#    define STWA(rd, rs1, rs2)		f3a(3, rd, 20, rs1, asi, rs2)
#    define STXA(rd, rs1, rs2)		f3a(3, rd, 30, rs1, asi, rs2)
#  endif
#  define STC(rd, rs1, rs2)		f3r(3, rd, 52, rs1, rs2)
#  define STCI(rd, rs1, imm)		f3i(3, rd, 52, rs1, imm)
#  define STDC(rd, rs1, rs2)		f3r(3, rd, 55, rs1, rs2)
#  define STDCI(rd, rs1, imm)		f3i(3, rd, 55, rs1, imm)
#  define STCSR(rd, rs1, rs2)		f3r(3, rd, 53, rs1, rs2)
#  define STCSRI(rd, rs1, imm)		f3i(3, rd, 53, rs1, imm)
#  define STDCQ(rd, rs1, rs2)		f3r(3, rd, 54, rs1, rs2)
#  define STDCQI(rd, rs1, imm)		f3i(3, rd, 54, rs1, imm)
#  define LDSTUB(rs1, rs2, rd)		f3r(3, rd, 13, rs1, rs2)
#  define LDSTUBI(rs1, imm, rd)		f3r(3, rd, 13, rs1, imm)
#  define LDSTUBA(rs1, rs2, asi, rd)	f3a(3, rd, 21, rs1, asi, rs2)
#  define SWAP(rs1, rs2, rd)		f3r(3, rd, 15, rs1, rs2)
#  define SWAPI(rs1, imm, rd)		f3r(3, rd, 15, rs1, imm)
#  define SWAPA(rs1, rs2, asi, rd)	f3a(3, rd, 23, rs1, asi, rs2)
/* Sparc v9 deprecates SWAP* in favor of CAS*A */
#  define CASA(rs1, rs2, rd)		f3a(3, rd, 60, rs1, 128, rs2)
#  if __WORDSIZE == 64
#    define CASXA(rs1, rs2, rd)		f3a(3, rd, 62, rs1, 128, rs2)
#  endif
#  define NOP()				SETHI(0, 0)
#  define HI(im)			((im) >> 10)
#  define LO(im)			((im) & 0x3ff)
#  define SETHI(im, rd)			f2r(0, rd, 4, im)
#  define AND(rs1, rs2, rd)		f3r(2, rd, 1, rs1, rs2)
#  define ANDI(rs1, imm, rd)		f3i(2, rd, 1, rs1, imm)
#  define ANDcc(rs1, rs2, rd)		f3r(2, rd, 17, rs1, rs2)
#  define ANDIcc(rs1, imm, rd)		f3i(2, rd, 17, rs1, imm)
#  define BTST(rs1, rs2)		ANDcc(rs1, rs2, 0)
#  define BTSTI(rs1, imm)		ANDIcc(rs1, imm, 0)
#  define ANDN(rs1, rs2, rd)		f3r(2, rd, 5, rs1, rs2)
#  define ANDNI(rs1, imm, rd)		f3i(2, rd, 5, rs1, imm)
#  define ANDNcc(rs1, rs2, rd)		f3r(2, rd, 21, rs1, rs2)
#  define ANDNIcc(rs1, imm, rd)		f3i(2, rd, 21, rs1, imm)
#  define OR(rs1, rs2, rd)		f3r(2, rd, 2, rs1, rs2)
#  define ORI(rs1, imm, rd)		f3i(2, rd, 2, rs1, imm)
#  define ORcc(rs1, rs2, rd)		f3r(2, rd, 18, rs1, rs2)
#  define ORIcc(rs1, imm, rd)		f3i(2, rd, 18, rs1, imm)
#  define ORN(rs1, rs2, rd)		f3r(2, rd, 6, rs1, rs2)
#  define ORNI(rs1, imm, rd)		f3i(2, rd, 6, rs1, imm)
#  define ORNcc(rs1, rs2, rd)		f3r(2, rd, 22, rs1, rs2)
#  define ORNIcc(rs1, imm, rd)		f3i(2, rd, 22, rs1, imm)
#  define XOR(rs1, rs2, rd)		f3r(2, rd, 3, rs1, rs2)
#  define XORI(rs1, imm, rd)		f3i(2, rd, 3, rs1, imm)
#  define XORcc(rs1, rs2, rd)		f3r(2, rd, 19, rs1, rs2)
#  define XORIcc(rs1, imm, rd)		f3i(2, rd, 19, rs1, imm)
#  define XNOR(rs1, rs2, rd)		f3r(2, rd, 7, rs1, rs2)
#  define XNORI(rs1, imm, rd)		f3i(2, rd, 7, rs1, imm)
#  define XNORcc(rs1, rs2, rd)		f3r(2, rd, 23, rs1, rs2)
#  define XNORIcc(rs1, imm, rd)		f3i(2, rd, 23, rs1, imm)
#  define SLL(rs1, rs2, rd)		f3r(2, rd, 37, rs1, rs2)
#  define SLLI(rs1, imm, rd)		f3i(2, rd, 37, rs1, imm)
#  define SRL(rs1, rs2, rd)		f3r(2, rd, 38, rs1, rs2)
#  define SRLI(rs1, imm, rd)		f3i(2, rd, 38, rs1, imm)
#  define SRA(rs1, rs2, rd)		f3r(2, rd, 39, rs1, rs2)
#  define SRAI(rs1, imm, rd)		f3i(2, rd, 39, rs1, imm)
#  if __WORDSIZE == 64
#    define SLLX(rs1, rs2, rd)		f3rx(2, rd, 37, rs1, rs2)
#    define SLLXI(rs1, imm, rd)		f3s(2, rd, 37, rs1, imm)
#    define SRLX(rs1, rs2, rd)		f3rx(2, rd, 38, rs1, rs2)
#    define SRLXI(rs1, imm, rd)		f3s(2, rd, 38, rs1, imm)
#    define SRAX(rs1, rs2, rd)		f3rx(2, rd, 39, rs1, rs2)
#    define SRAXI(rs1, imm, rd)		f3s(2, rd, 39, rs1, imm)
#  endif
#  define ADD(rs1, rs2, rd)		f3r(2, rd, 0, rs1, rs2)
#  define ADDI(rs1, imm, rd)		f3i(2, rd, 0, rs1, imm)
#  define ADDcc(rs1, rs2, rd)		f3r(2, rd, 16, rs1, rs2)
#  define ADDIcc(rs1, imm, rd)		f3i(2, rd, 16, rs1, imm)
#  define ADDX(rs1, rs2, rd)		f3r(2, rd, 8, rs1, rs2)
#  define ADDXI(rs1, imm, rd)		f3i(2, rd, 8, rs1, imm)
#  define ADDXcc(rs1, rs2, rd)		f3r(2, rd, 24, rs1, rs2)
#  define ADDXIcc(rs1, imm, rd)		f3i(2, rd, 24, rs1, imm)
#  define TADDcc(rs1, rs2, rd)		f3r(2, rd, 32, rs1, rs2)
#  define TADDIcc(rs1, imm, rd)		f3i(2, rd, 32, rs1, imm)
#  define TADDccTV(rs1, rs2, rd)	f3r(2, rd, 34, rs1, rs2)
#  define TADDIccTV(rs1, imm, rd)	f3i(2, rd, 34, rs1, imm)
#  define SUB(rs1, rs2, rd)		f3r(2, rd, 4, rs1, rs2)
#  define NEG(rs1, rd)			SUB(0, rs1, rd)
#  define SUBI(rs1, imm, rd)		f3i(2, rd, 4, rs1, imm)
#  define SUBcc(rs1, rs2, rd)		f3r(2, rd, 20, rs1, rs2)
#  define SUBIcc(rs1, imm, rd)		f3i(2, rd, 20, rs1, imm)
#  define CMP(rs1, rs2)			SUBcc(rs1, rs2, 0)
#  define CMPI(rs1, imm)		SUBIcc(rs1, imm, 0)
#  define SUBX(rs1, rs2, rd)		f3r(2, rd, 12, rs1, rs2)
#  define SUBXI(rs1, imm, rd)		f3i(2, rd, 12, rs1, imm)
#  define SUBXcc(rs1, rs2, rd)		f3r(2, rd, 28, rs1, rs2)
#  define SUBXIcc(rs1, imm, rd)		f3i(2, rd, 28, rs1, imm)
#  define TSUBcc(rs1, rs2, rd)		f3r(2, rd, 33, rs1, rs2)
#  define TDADDIcc(rs1, imm, rd)	f3i(2, rd, 33, rs1, imm)
#  define TSUBccTV(rs1, rs2, rd)	f3r(2, rd, 35, rs1, rs2)
#  define TSUBIccTV(rs1, imm, rd)	f3i(2, rd, 35, rs1, imm)
#  define MULScc(rs1, rs2, rd)		f3r(2, rd, 36, rs1, rs2)
#  define MULSIcc(rs1, imm, rd)		f3i(2, rd, 36, rs1, imm)
#  define UMUL(rs1, rs2, rd)		f3r(2, rd, 10, rs1, rs2)
#  define UMULI(rs1, imm, rd)		f3i(2, rd, 10, rs1, imm)
#  define SMUL(rs1, rs2, rd)		f3r(2, rd, 11, rs1, rs2)
#  define SMULI(rs1, imm, rd)		f3i(2, rd, 11, rs1, imm)
#  define UMULcc(rs1, rs2, rd)		f3r(2, rd, 26, rs1, rs2)
#  define UMULIcc(rs1, imm, rd)		f3i(2, rd, 26, rs1, imm)
#  define SMULcc(rs1, rs2, rd)		f3r(2, rd, 27, rs1, rs2)
#  define SMULIcc(rs1, imm, rd)		f3i(2, rd, 27, rs1, imm)
#  define UDIV(rs1, rs2, rd)		f3r(2, rd, 14, rs1, rs2)
#  define UDIVI(rs1, imm, rd)		f3i(2, rd, 14, rs1, imm)
#  define SDIV(rs1, rs2, rd)		f3r(2, rd, 15, rs1, rs2)
#  define SDIVI(rs1, imm, rd)		f3i(2, rd, 15, rs1, imm)
#  define UDIVcc(rs1, rs2, rd)		f3r(2, rd, 30, rs1, rs2)
#  define UDIVIcc(rs1, imm, rd)		f3i(2, rd, 30, rs1, imm)
#  define SDIVcc(rs1, rs2, rd)		f3r(2, rd, 31, rs1, rs2)
#  define SDIVIcc(rs1, imm, rd)		f3i(2, rd, 31, rs1, imm)
#  if __WORDSIZE == 64
#    define MULX(rs1, rs2, rd)		f3r(2, rd, 9, rs1, rs2)
#    define MULXI(rs1, imm, rd)		f3i(2, rd, 9, rs1, imm)
#    define SDIVX(rs1, rs2, rd)		f3r(2, rd, 45, rs1, rs2)
#    define SDIVXI(rs1, imm, rd)	f3i(2, rd, 45, rs1, imm)
#    define UDIVX(rs1, rs2, rd)		f3r(2, rd, 13, rs1, rs2)
#    define UDIVXI(rs1, imm, rd)	f3i(2, rd, 13, rs1, imm)
#  endif
#  define SAVE(rs1, rs2, rd)		f3r(2, rd, 60, rs1, rs2)
#  define SAVEI(rs1, imm, rd)		f3i(2, rd, 60, rs1, imm)
#  define RESTORE(rs1, rs2, rd)		f3r(2, rd, 61, rs1, rs2)
#  define RESTOREI(rs1, imm, rd)	f3i(2, rd, 61, rs1, imm)
#  define SPARC_BA			8	/* always */
#  define SPARC_BN			0	/* never */
#  define SPARC_BNE			9	/* not equal - not Z */
#  define SPARC_BNZ			SPARC_BNE
#  define SPARC_BE			1	/* equal - Z */
#  define SPARC_BZ			SPARC_BE
#  define SPARC_BG			10	/* greater - not (Z or (N xor V)) */
#  define SPARC_BLE			2	/* less or equal - Z or (N xor V) */
#  define SPARC_BGE			11	/* greater or equal - not (N xor V) */
#  define SPARC_BL			3	/* less - N xor V */
#  define SPARC_BGU			12	/* greater unsigned - not (C or Z) */
#  define SPARC_BLEU			4	/* less or equal unsigned - C or Z */
#  define SPARC_BCC			13	/* carry clear - not C */
#  define SPARC_BGEU			SPARC_BCC
#  define SPARC_BCS			5	/* carry set - C */
#  define SPARC_BLU			SPARC_BCS
#  define SPARC_BPOS			14	/* positive - not N */
#  define SPARC_BNEG			6	/* negative - N */
#  define SPARC_BVC			15	/* overflow clear - not V */
#  define SPARC_BVS			7	/* overflow set - V */
/* Preferred BPcc integer branch opcodes */
#  if __WORDSIZE == 64
#    define SPARC_BPA			8	/* always - 1 */
#    define SPARC_BPN			0	/* never - 0 */
#    define SPARC_BPNE			9	/* not equal - not Z */
#    define SPARC_BPE			1	/* equal - Z */
#    define SPARC_BPG			10	/* greater - not (Z or (N xor V)) */
#    define SPARC_BPLE			2	/* less or equal - Z or (N xor V) */
#    define SPARC_BPGE			11	/* greater or equal - not (N xor V) */
#    define SPARC_BPL			3	/* less - N xor V */
#    define SPARC_BPGU			12	/* greater unsigned - not (C or V) */
#    define SPARC_BPLEU			4	/* less or equal unsigned  - C or Z */
#    define SPARC_BPCC			13	/* carry clear (greater than or equal, unsigned) - not C */
#    define SPARC_BPCS			5	/* carry set (less than, unsigned) - C */
#    define SPARC_BPPOS			14	/* positive - not N */
#    define SPARC_BPNEG			6	/* negative - N */
#    define SPARC_BPVC			15	/* overflow clear - not V */
#    define SPARC_BPVS			7	/* overflow set - V */
#  endif
#  define B(cc, imm)			f2b(0, 0, cc, 2, imm)
#  define Ba(cc, imm)			f2b(0, 1, cc, 2, imm)
#  define BA(imm)			B(SPARC_BA, imm)
#  define BAa(imm)			Ba(SPARC_BA, imm)
#  define BN(imm)			B(SPARC_BN, imm)
#  define BNa(imm)			Ba(SPARC_BN, imm)
#  define BNE(imm)			B(SPARC_BNE, imm)
#  define BNEa(imm)			Ba(SPARC_BNE, imm)
#  define BNZ(imm)			BNE(imm)
#  define BNZa(imm)			BNEa(imm)
#  define BE(imm)			B(SPARC_BE, imm)
#  define BEa(imm)			Ba(SPARC_BE, imm)
#  define BZ(imm)			BE(imm)
#  define BZa(imm)			BEa(imm)
#  define BG(imm)			B(SPARC_BG, imm)
#  define BGa(imm)			Ba(SPARC_BG, imm)
#  define BLE(imm)			B(SPARC_BLE, imm)
#  define BLEa(imm)			Ba(SPARC_BLE, imm)
#  define BGE(imm)			B(SPARC_BGE, imm)
#  define BGEa(imm)			Ba(SPARC_BGE, imm)
#  define BL(imm)			B(SPARC_BL, imm)
#  define BLa(imm)			Ba(SPARC_BL, imm)
#  define BGU(imm)			B(SPARC_BGU, imm)
#  define BGUa(imm)			Ba(SPARC_BGU, imm)
#  define BLEU(imm)			B(SPARC_BLEU, imm)
#  define BLEUa(imm)			Ba(SPARC_BLEU, imm)
#  define BCC(imm)			B(SPARC_BCC, imm)
#  define BCCa(imm)			Ba(SPARC_BCC, imm)
#  define BGEU(imm)			BCC(imm)
#  define BGEUa(imm)			BCCa(imm)
#  define BCS(imm)			B(SPARC_BCS, imm)
#  define BCSa(imm)			Ba(SPARC_BCS, imm)
#  define BLU(imm)			BCS(imm)
#  define BLUa(imm)			BCSa(imm)
#  define BPOS(imm)			B(SPARC_BPOS, imm)
#  define BPOSa(imm)			Ba(SPARC_BPOS, imm)
#  define BNEG(imm)			B(SPARC_BNEG, imm)
#  define BNEGa(imm)			Ba(SPARC_BNEG, imm)
#  define BVC(imm)			B(SPARC_BVC, imm)
#  define BVCa(imm)			Ba(SPARC_BVC, imm)
#  define BVS(imm)			B(SPARC_BVS, imm)
#  define BVSa(imm)			Ba(SPARC_BVS, imm)
#  if __WORDSIZE == 64
#    define BPccap(cc,a,cc1, cc2,p,imm)	f2bp(0, a, cc, 1, cc1, cc0, p, imm)
#    define BPap(cc, imm)		f2bp(0, 1, cc, 1, 1, 0, p, imm)
#    define BPa(cc, imm)		f2bp(0, 1, cc, 1, 1, 0, 1, imm)
#    define BP(cc, imm)			f2bp(0, 0, cc, 1, 1, 0, 1, imm)
#    define BPA(imm)			BP(SPARC_BPA, imm)
#    define BPN(imm)			BP(SPARC_BPN, imm)
#    define BNPE(imm)			BP(SPARC_BPNE, imm)
#    define BPE(imm)			BP(SPARC_BPE, imm)
#    define BPG(imm)			BP(SPARC_BPG, imm)
#    define BPLE(imm)			BP(SPARC_BPLE, imm)
#    define BPGE(imm)			BP(SPARC_BPGE, imm)
#    define BPL(imm)			BP(SPARC_BPL, imm)
#    define BPGU(imm)			BP(SPARC_BPGU, imm)
#    define BPLEU(imm)			BP(SPARC_BPLEU, imm)
#    define BPCC(imm)			BP(SPARC_BPCC, imm)
#    define BPCS(imm)			BP(SPARC_BPCS, imm)
#    define BPPOS(imm)			BP(SPARC_BPPOS, imm)
#    define BPNEG(imm)			BP(SPARC_BPNEG, imm)
#    define BPVC(imm)			BP(SPARC_BPVC, imm)
#    define BPVS(imm)			BP(SPARC_BPVS, imm)
#  endif
#  define SPARC_CBA			8	/* always */
#  define SPARC_CBN			0	/* never */
#  define SPARC_CB3			7	/* 3 */
#  define SPARC_CB2			6	/* 2 */
#  define SPARC_CB23			5	/* 2 or 3 */
#  define SPARC_CB1			4	/* 1 */
#  define SPARC_CB13			3	/* 1 or 3 */
#  define SPARC_CB12			2	/* 1 or 2 */
#  define SPARC_CB123			1	/* 1 or 2 or 3 */
#  define SPARC_CB0			9	/* 0 */
#  define SPARC_CB03			10	/* 0 or 3 */
#  define SPARC_CB02			11	/* 0 or 2 */
#  define SPARC_CB023			12	/* 0 or 2 or 3 */
#  define SPARC_CB01			13	/* 0 or 1 */
#  define SPARC_CB013			14	/* 0 or 1 or 3 */
#  define SPARC_CB012			15	/* 0 or 1 or 2 */
#  define CB(cc, imm)			f2b(0, 0, cc, 7, imm)
#  define CBa(cc, imm)			f2b(0, 1, cc, 7, imm)
#  define CBA(imm)			CB(SPARC_CBA, imm)
#  define CBAa(imm)			CBa(SPARC_CBA, imm)
#  define CBN(imm)			CB(SPARC_CBN, imm)
#  define CBNa(imm)			CBa(SPARC_CBN, imm)
#  define CB3(imm)			CB(SPARC_CB3, imm)
#  define CB3a(imm)			CBa(SPARC_CB3, imm)
#  define CB2(imm)			CB(SPARC_CB2, imm)
#  define CB2a(imm)			CBa(SPARC_CB2, imm)
#  define CB23(imm)			CB(SPARC_CB23, imm)
#  define CB23a(imm)			CBa(SPARC_CB23, imm)
#  define CB1(imm)			CB(SPARC_CB1, imm)
#  define CB1a(imm)			CBa(SPARC_CB1, imm)
#  define CB13(imm)			CB(SPARC_CB13, imm)
#  define CB13a(imm)			CBa(SPARC_CB13, imm)
#  define CB12(imm)			CB(SPARC_CB12, imm)
#  define CB12a(imm)			CBa(SPARC_CB12, imm)
#  define CB123(imm)			CB(SPARC_CB123, imm)
#  define CB123a(imm)			CBa(SPARC_CB123, imm)
#  define CB0(imm)			CB(SPARC_CB0, imm)
#  define CB0a(imm)			CBa(SPARC_CB0, imm)
#  define CB03(imm)			CB(SPARC_CB03, imm)
#  define CB03a(imm)			CBa(SPARC_CB03, imm)
#  define CB02(imm)			CB(SPARC_CB02, imm)
#  define CB02a(imm)			CBa(SPARC_CB02, imm)
#  define CB023(imm)			CB(SPARC_CB103, imm)
#  define CB023a(imm)			CBa(SPARC_CB023, imm)
#  define CB01(imm)			CB(SPARC_CB01, imm)
#  define CB01a(imm)			CBa(SPARC_CB01, imm)
#  define CB013(imm)			CB(SPARC_CB013, imm)
#  define CB013a(imm)			CBa(SPARC_CB013, imm)
#  define CB012(imm)			CB(SPARC_CB012, imm)
#  define CB012a(imm)			CBa(SPARC_CB012, imm)
#  define CALLI(imm)			f1(1, imm)
#  define CALL(r0)			JMPL(_O7_REGNO, r0, 0)
#  define RETL()			JMPLI(0, _O7_REGNO, 8)
#  define RET()				JMPLI(0, _I7_REGNO, 8)
#  define JMPL(rd, rs1, rs2)		f3r(2, rd, 56, rs1, rs2)
#  define JMPLI(rd, rs1, imm)		f3i(2, rd, 56, rs1, imm)
#  define RETT(rs1, rs2)		f3r(2, 0, 57, rs1, rs2)
#  define RETTI(rs1, imm)		f3i(2, 0, 57, rs1, imm)
#  define SPARC_TA			8	/* always */
#  define SPARC_TN			0	/* never */
#  define SPARC_TNE			9	/* not equal - not Z */
#  define SPARC_TNZ			SPARC_BNE
#  define SPARC_TE			1	/* equal - Z */
#  define SPARC_TZ			SPARC_BE
#  define SPARC_TG			10	/* greater - not (Z or (N xor V)) */
#  define SPARC_TLE			2	/* less or equal - Z or (N xor V) */
#  define SPARC_TGE			11	/* greater or equal - not (N xor V) */
#  define SPARC_TL			3	/* less - N xor V */
#  define SPARC_TGU			12	/* greater unsigned - not (C or Z) */
#  define SPARC_TLEU			4	/* less or equal unsigned - C or Z */
#  define SPARC_TCC			13	/* carry clear - not C */
#  define SPARC_TGEU			SPARC_BCC
#  define SPARC_TCS			5	/* carry set - C */
#  define SPARC_TLU			SPARC_BCS
#  define SPARC_TPOS			14	/* positive - not N */
#  define SPARC_TNEG			6	/* negative - N */
#  define SPARC_TVC			15	/* overflow clear - not V */
#  define SPARC_TVS			7	/* overflow set - V */
#  define T(cc, rs1, rs2)		f3t(cc, rs1, 0, rs2)
#  define TI(cc, rs1, imm)		f3t(cc, rs1, 1, imm)
#  define TA(rs1, rs2)			T(SPARC_TA, rs1, rs2)
#  define TAI(rs1, imm)			TI(SPARC_TA, rs1, imm)
#  define TN(rs1, rs2)			T(SPARC_TN, rs1, rs2)
#  define TNI(rs1, imm)			TI(SPARC_TN, rs1, imm)
#  define TNE(rs1, rs2)			T(SPARC_TNE, rs1, rs2)
#  define TNEI(rs1, imm)		TI(SPARC_TNE, rs1, imm)
#  define TNZ(rs1, rs2)			TNE(rs1, rs2)
#  define TNZI(rs1, imm)		TNEI(rs1, imm)
#  define TE(rs1, rs2)			T(SPARC_TE, rs1, rs2)
#  define TEI(rs1, imm)			TI(SPARC_TE, rs1, imm)
#  define TZ(rs1, rs2)			TE(rs1, rs2)
#  define TZI(rs1, imm)			TEI(rs1, imm)
#  define TG(rs1, rs2)			T(SPARC_TG, rs1, rs2)
#  define TGI(rs1, imm)			TI(SPARC_TG, rs1, imm)
#  define TLE(rs1, rs2)			T(SPARC_TLE, rs1, rs2)
#  define TLEI(rs1, imm)		TI(SPARC_TLE, rs1, imm)
#  define TGE(rs1, rs2)			T(SPARC_TGE, rs1, rs2)
#  define TGEI(rs1, imm)		TI(SPARC_TGE, rs1, imm)
#  define TL(rs1, rs2)			T(SPARC_TL, rs1, rs2)
#  define TLI(rs1, imm)			TI(SPARC_TL, rs1, imm)
#  define TGU(rs1, rs2)			T(SPARC_TGU, rs1, rs2)
#  define TGUI(rs1, imm)		TI(SPARC_TGU, rs1, imm)
#  define TLEU(rs1, rs2)		T(SPARC_TLEU, rs1, rs2)
#  define TLEUI(rs1, imm)		TI(SPARC_TLEU, rs1, imm)
#  define TCC(rs1, rs2)			T(SPARC_TCC, rs1, rs2)
#  define TCCI(rs1, imm)		TI(SPARC_TCC, rs1, imm)
#  define TGEU(rs1, rs2)		TCC(rs1, rs2)
#  define TGEUI(rs1, imm)		TCCI(rs1, imm)
#  define TCS(rs1, rs2)			T(SPARC_TCC, rs1, rs2)
#  define TCSI(rs1, imm)		TI(SPARC_TCC, rs1, imm)
#  define TLU(rs1, rs2)			TCS(rs1, rs2)
#  define TLUI(rs1, imm)		TCSI(rs1, imm)
#  define TPOS(rs1, rs2)		T(SPARC_TPOS, rs1, rs2)
#  define TPOSI(rs1, imm)		TI(SPARC_TPOS, rs1, imm)
#  define TNEG(rs1, rs2)		T(SPARC_TNEG, rs1, rs2)
#  define TNEGI(rs1, imm)		TI(SPARC_TNEG, rs1, imm)
#  define TVC(rs1, rs2)			T(SPARC_TVC, rs1, rs2)
#  define TVCI(rs1, imm)		TI(SPARC_TVC, rs1, imm)
#  define TVS(rs1, rs2)			T(SPARC_TVS, rs1, rs2)
#  define TVSI(rs1, imm)		TI(SPARC_TVS, rs1, imm)
#  define RDY(rd)			f3r(2, rd, 40, 0, 0)
#  define RDASR(rs1, rd)		f3r(2, rd, 40, rs1, 0)
#  define RDPSR(rd)			f3r(2, rd, 41, 0, 0)
#  define RDWIM(rd)			f3r(2, rd, 42, 0, 0)
#  define RDTBR(rd)			f3r(2, rd, 43, 0, 0)
#  define WRY(rs1, rs2)			f3r(2, 0, 48, rs1, rs2)
#  define WRYI(rs1, imm)		f3i(2, 0, 48, rs1, imm)
#  define WRASR(rs1, rs2, rd)		f3r(2, rd, 48, rs1, rs2)
#  define WRASRI(rs1, imm, rd)		f3i(2, rd, 48, rs1, imm)
#  define WRPSR(rs1, rs2, rd)		f3r(2, rd, 49, rs1, rs2)
#  define WRPSRI(rs1, imm, rd)		f3i(2, rd, 49, rs1, imm)
#  define WRWIM(rs1, rs2, rd)		f3r(2, rd, 50, rs1, rs2)
#  define WRWIMI(rs1, imm, rd)		f3i(2, rd, 50, rs1, imm)
#  define WRTBR(rs1, rs2, rd)		f3r(2, rd, 51, rs1, rs2)
#  define WRTBRI(rs1, imm, rd)		f3i(2, rd, 51, rs1, imm)
#  define STBAR()			f3i(2, 0, 40, 15, 0)
#  define UNIMP(imm)			f2r(0, 0, 0, imm)
#  define FLUSH(rs1, rs2)		f3r(2, 0, 59, rs1, rs2)
#  define FLUSHI(rs1, im)		f3i(2, 0, 59, rs1, imm)
#  define LZCNT(rs2, rd)		f2c1(2, rd, 54, 0, 23, rs2)
#  define nop(i0)			_nop(_jit, i0)
static void _nop(jit_state_t*, jit_int32_t);
#  define movr(r0, r1)			_movr(_jit, r0, r1)
static void _movr(jit_state_t*, jit_int32_t, jit_int32_t);
#  define movi(r0, i0)			_movi(_jit, r0, i0)
static void _movi(jit_state_t*, jit_int32_t, jit_word_t);
#  define movi_p(r0, i0)		_movi_p(_jit, r0, i0)
static jit_word_t _movi_p(jit_state_t*, jit_int32_t, jit_word_t);
#  define bswapr_us(r0, r1)		generic_bswapr_us(_jit, r0, r1)
#  define bswapr_ui(r0, r1)		generic_bswapr_ui(_jit, r0, r1)
#  define bswapr_ul(r0, r1)		generic_bswapr_ul(_jit, r0, r1)
#  define movnr(r0,r1,r2)		_movnr(_jit,r0,r1,r2)
static void _movnr(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t);
#  define movzr(r0,r1,r2)		_movzr(_jit,r0,r1,r2)
static void _movzr(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t);
#  define casx(r0, r1, r2, r3, i0)	_casx(_jit, r0, r1, r2, r3, i0)
static void _casx(jit_state_t *_jit,jit_int32_t,jit_int32_t,
		  jit_int32_t,jit_int32_t,jit_word_t);
#define casr(r0, r1, r2, r3)		casx(r0, r1, r2, r3, 0)
#define casi(r0, i0, r1, r2)		casx(r0, _NOREG, r1, r2, i0)
#  define comr(r0, r1)			XNOR(r1, 0, r0)
#  define negr(r0, r1)			NEG(r1, r0)
#  define bitswap(r0, r1)		_bitswap(_jit, r0, r1)
static void _bitswap(jit_state_t*, jit_int32_t, jit_int32_t);
#  define clor(r0, r1)			_clor(_jit, r0, r1)
static void _clor(jit_state_t*, jit_int32_t, jit_int32_t);
#  define clzr(r0, r1)			_clzr(_jit, r0, r1)
static void _clzr(jit_state_t*, jit_int32_t, jit_int32_t);
#  define ctor(r0, r1)			_ctor(_jit, r0, r1)
static void _ctor(jit_state_t*, jit_int32_t, jit_int32_t);
#  define ctzr(r0, r1)			_ctzr(_jit, r0, r1)
static void _ctzr(jit_state_t*, jit_int32_t, jit_int32_t);
#  define addr(r0, r1, r2)		ADD(r1, r2, r0)
#  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);
#  if __WORDSIZE == 32
#    define addcr(r0, r1, r2)		ADDcc(r1, r2, r0)
#  else
#    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);
#  endif
#  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);
#  if __WORDSIZE == 32
#    define addxr(r0, r1, r2)		ADDXcc(r1, r2, r0)
#  else
#    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);
#  endif
#  define addxi(r0, r1, i0)		_addxi(_jit, r0, r1, i0)
static void _addxi(jit_state_t*, jit_int32_t, jit_int32_t, jit_word_t);
#  define subr(r0, r1, r2)		SUB(r1, r2, r0)
#  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);
#  if __WORDSIZE == 32
#    define subcr(r0, r1, r2)		SUBcc(r1, r2, r0)
#  else
#    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);
#  endif
#  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);
#  if __WORDSIZE == 32
#    define subxr(r0, r1, r2)		SUBXcc(r1, r2, r0)
#  else
#    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);
#  endif
#  define subxi(r0, r1, i0)		_subxi(_jit, r0, r1, i0)
static void _subxi(jit_state_t*, jit_int32_t, jit_int32_t, jit_word_t);
#  define rsbi(r0, r1, i0)		_rsbi(_jit, r0, r1, i0)
static void _rsbi(jit_state_t*,jit_int32_t,jit_int32_t,jit_word_t);
#  if __WORDSIZE == 32
#    define mulr(r0, r1, r2)		UMUL(r1, r2, r0)
#  else
#    define mulr(r0, r1, r2)		MULX(r1, r2, r0)
#  endif
#  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);
#  if __WORDSIZE == 32
#    define qmulr(r0,r1,r2,r3)		iqmulr(r0,r1,r2,r3,1)
#    define qmulr_u(r0,r1,r2,r3)	iqmulr(r0,r1,r2,r3,0)
#    define iqmulr(r0,r1,r2,r3,cc)	_iqmulr(_jit,r0,r1,r2,r3,cc)
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(r0,r1,r2,i0,1)
#  define qmuli_u(r0,r1,r2,i0)		iqmuli(r0,r1,r2,i0,0)
#  define iqmuli(r0,r1,r2,i0,cc)	_iqmuli(_jit,r0,r1,r2,i0,cc)
static void _iqmuli(jit_state_t*,jit_int32_t,jit_int32_t,
		    jit_int32_t,jit_word_t,jit_bool_t);
#  else
#    define qmulr(r0,r1,r2,r3)		_qmulr(_jit,r0,r1,r2,r3)
static void _qmulr(jit_state_t*,jit_int32_t,jit_int32_t,
		   jit_int32_t,jit_int32_t);
#  define qmuli(r0,r1,r2,i0)		_qmuli(_jit,r0,r1,r2,i0)
static void _qmuli(jit_state_t*,jit_int32_t,jit_int32_t,
		   jit_int32_t,jit_word_t);
#    define qmulr_u(r0,r1,r2,r3)	_qmulr_u(_jit,r0,r1,r2,r3)
static void _qmulr_u(jit_state_t*,jit_int32_t,jit_int32_t,
		     jit_int32_t,jit_int32_t);
#  define qmuli_u(r0,r1,r2,i0)		_qmuli_u(_jit,r0,r1,r2,i0)
static void _qmuli_u(jit_state_t*,jit_int32_t,jit_int32_t,
		     jit_int32_t,jit_word_t);
#  endif
#  define divr(r0, r1, r2)		_divr(_jit, r0, r1, r2)
static void _divr(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
#  define divi(r0, r1, i0)		_divi(_jit, r0, r1, i0)
static void _divi(jit_state_t*, jit_int32_t, jit_int32_t, jit_word_t);
#  define divr_u(r0, r1, r2)		_divr_u(_jit, r0, r1, r2)
static void _divr_u(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
#  define divi_u(r0, r1, i0)		_divi_u(_jit, r0, r1, i0)
static void _divi_u(jit_state_t*, jit_int32_t, jit_int32_t, jit_word_t);
#  define qdivr(r0,r1,r2,r3)		iqdivr(r0,r1,r2,r3,1)
#  define qdivr_u(r0,r1,r2,r3)		iqdivr(r0,r1,r2,r3,0)
#  define iqdivr(r0,r1,r2,r3,cc)	_iqdivr(_jit,r0,r1,r2,r3,cc)
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(r0,r1,r2,i0,1)
#  define qdivi_u(r0,r1,r2,i0)		iqdivi(r0,r1,r2,i0,0)
#  define iqdivi(r0,r1,r2,i0,cc)	_iqdivi(_jit,r0,r1,r2,i0,cc)
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)		_remr(_jit, r0, r1, r2)
static void _remr(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
#  define remi(r0, r1, i0)		_remi(_jit, r0, r1, i0)
static void _remi(jit_state_t*, jit_int32_t, jit_int32_t, jit_word_t);
#  define remr_u(r0, r1, r2)		_remr_u(_jit, r0, r1, r2)
static void _remr_u(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
#  define remi_u(r0, r1, i0)		_remi_u(_jit, r0, r1, i0)
static void _remi_u(jit_state_t*, jit_int32_t, jit_int32_t, jit_word_t);
#  define andr(r0, r1, r2)		AND(r1, r2, r0)
#  define andi(r0, r1, i0)		_andi(_jit, r0, r1, i0)
static void _andi(jit_state_t*, jit_int32_t, jit_int32_t, jit_word_t);
#  define orr(r0, r1, r2)		OR(r1, r2, r0)
#  define ori(r0, r1, i0)		_ori(_jit, r0, r1, i0)
static void _ori(jit_state_t*, jit_int32_t, jit_int32_t, jit_word_t);
#  define xorr(r0, r1, r2)		XOR(r1, r2, r0)
#  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);
#  if __WORDSIZE == 32
#    define lshr(r0, r1, r2)		SLL(r1, r2, r0)
#    define lshi(r0, r1, i0)		SLLI(r1, i0, r0)
#    define rshr(r0, r1, r2)		SRA(r1, r2, r0)
#    define rshi(r0, r1, i0)		SRAI(r1, i0, r0)
#    define rshr_u(r0, r1, r2)		SRL(r1, r2, r0)
#    define rshi_u(r0, r1, i0)		SRLI(r1, i0, r0)
#  else
#    define lshr(r0, r1, r2)		SLLX(r1, r2, r0)
#    define lshi(r0, r1, i0)		SLLXI(r1, i0, r0)
#    define rshr(r0, r1, r2)		SRAX(r1, r2, r0)
#    define rshi(r0, r1, i0)		SRAXI(r1, i0, r0)
#    define rshr_u(r0, r1, r2)		SRLX(r1, r2, r0)
#    define rshi_u(r0, r1, i0)		SRLXI(r1, i0, r0)
#  endif
#  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)		andi(r0, r1, 0xff)
#  define extr_s(r0,r1)			_extr_s(_jit,r0,r1)
static void _extr_s(jit_state_t*,jit_int32_t,jit_int32_t);
#  define extr_us(r0,r1)		_extr_us(_jit,r0,r1)
static void _extr_us(jit_state_t*,jit_int32_t,jit_int32_t);
#  if __WORDSIZE == 64
#    define extr_i(r0,r1)		_extr_i(_jit,r0,r1)
static void _extr_i(jit_state_t*,jit_int32_t,jit_int32_t);
#    define extr_ui(r0,r1)		_extr_ui(_jit,r0,r1)
static void _extr_ui(jit_state_t*,jit_int32_t,jit_int32_t);
#  endif
#  define cr(cc, r0, r1, r2)		_cr(_jit, cc, r0, r1, r2)
static void _cr(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t);
#  define cw(cc, r0, r1, i0)		_cw(_jit, cc, r0, r1, i0)
static void _cw(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t,jit_word_t);
#  if __WORDSIZE == 32
#    define ltr(r0, r1, r2)		cr(SPARC_BL, r0, r1, r2)
#    define lti(r0, r1, i0)		cw(SPARC_BL, r0, r1, i0)
#    define ltr_u(r0, r1, r2)		cr(SPARC_BLU, r0, r1, r2)
#    define lti_u(r0, r1, i0)		cw(SPARC_BLU, r0, r1, i0)
#    define ler(r0, r1, r2)		cr(SPARC_BLE, r0, r1, r2)
#    define lei(r0, r1, i0)		cw(SPARC_BLE, r0, r1, i0)
#    define ler_u(r0, r1, r2)		cr(SPARC_BLEU, r0, r1, r2)
#    define lei_u(r0, r1, i0)		cw(SPARC_BLEU, r0, r1, i0)
#    define eqr(r0, r1, r2)		cr(SPARC_BE, r0, r1, r2)
#    define eqi(r0, r1, i0)		cw(SPARC_BE, r0, r1, i0)
#    define ger(r0, r1, r2)		cr(SPARC_BGE, r0, r1, r2)
#    define gei(r0, r1, i0)		cw(SPARC_BGE, r0, r1, i0)
#    define ger_u(r0, r1, r2)		cr(SPARC_BGEU, r0, r1, r2)
#    define gei_u(r0, r1, i0)		cw(SPARC_BGEU, r0, r1, i0)
#    define gtr(r0, r1, r2)		cr(SPARC_BG, r0, r1, r2)
#    define gti(r0, r1, i0)		cw(SPARC_BG, r0, r1, i0)
#    define gtr_u(r0, r1, r2)		cr(SPARC_BGU, r0, r1, r2)
#    define gti_u(r0, r1, i0)		cw(SPARC_BGU, r0, r1, i0)
#    define ner(r0, r1, r2)		cr(SPARC_BNE, r0, r1, r2)
#    define nei(r0, r1, i0)		cw(SPARC_BNE, r0, r1, i0)
#  else
#  define ltr(r0, r1, r2)		cr(SPARC_BPL, r0, r1, r2)
#  define lti(r0, r1, i0)		cw(SPARC_BPL, r0, r1, i0)
#  define ltr_u(r0, r1, r2)		cr(SPARC_BPCS, r0, r1, r2)
#  define lti_u(r0, r1, i0)		cw(SPARC_BPCS, r0, r1, i0)
#  define ler(r0, r1, r2)		cr(SPARC_BPLE, r0, r1, r2)
#  define lei(r0, r1, i0)		cw(SPARC_BPLE, r0, r1, i0)
#  define ler_u(r0, r1, r2)		cr(SPARC_BPLEU, r0, r1, r2)
#  define lei_u(r0, r1, i0)		cw(SPARC_BPLEU, r0, r1, i0)
#  define eqr(r0, r1, r2)		cr(SPARC_BPE, r0, r1, r2)
#  define eqi(r0, r1, i0)		cw(SPARC_BPE, r0, r1, i0)
#  define ger(r0, r1, r2)		cr(SPARC_BPGE, r0, r1, r2)
#  define gei(r0, r1, i0)		cw(SPARC_BPGE, r0, r1, i0)
#  define ger_u(r0, r1, r2)		cr(SPARC_BPCC, r0, r1, r2)
#  define gei_u(r0, r1, i0)		cw(SPARC_BPCC, r0, r1, i0)
#  define gtr(r0, r1, r2)		cr(SPARC_BPG, r0, r1, r2)
#  define gti(r0, r1, i0)		cw(SPARC_BPG, r0, r1, i0)
#  define gtr_u(r0, r1, r2)		cr(SPARC_BPGU, r0, r1, r2)
#  define gti_u(r0, r1, i0)		cw(SPARC_BPGU, r0, r1, i0)
#  define ner(r0, r1, r2)		cr(SPARC_BPNE, r0, r1, r2)
#  define nei(r0, r1, i0)		cw(SPARC_BPNE, r0, r1, i0)
#  endif
#  define ldr_c(r0, r1)			LDSB(r1, 0, r0)
#  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)		LDUB(r1, 0, r0)
#  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)			LDSH(r1, 0, r0)
#  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)		LDUH(r1, 0, r0)
#  define ldi_us(r0, i0)		_ldi_us(_jit, r0, i0)
static void _ldi_us(jit_state_t*,jit_int32_t,jit_word_t);
#  if __WORDSIZE == 32
#    define ldr_i(r0, r1)		LD(r1, 0, r0)
#    define ldr(u, v)			ldr_i(u, v)
#    define ldi(u, v)			ldi_i(u, v)
#  else
#    define ldr_i(r0, r1)		LDSW(r1, 0, r0)
#    define ldr_ui(r0, r1)		LDUW(r1, 0, r0)
#    define ldr_l(r0, r1)		LDX(r1, 0, r0)
#    define ldr(u, v)			ldr_l(u, v)
#    define ldi(u, v)			ldi_l(u, v)
#  endif
#  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 ldi_ui(r0, i0)		_ldi_ui(_jit, r0, i0)
static void _ldi_ui(jit_state_t*,jit_int32_t,jit_word_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)		LDSB(r1, r2, r0)
#  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)		LDUB(r1, r2, r0)
#  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)		LDSH(r1, r2, r0)
#  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)		LDUH(r1, r2, r0)
#  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);
#  if __WORDSIZE == 32
#    define ldxr(u, v, w)		ldxr_i(u, v, w)
#    define ldxr_i(r0, r1, r2)		LD(r1, r2, r0)
#    define ldxi(u, v, w)		ldxi_i(u, v, w)
#  else
#    define ldxr(u, v, w)		ldxr_l(u, v, w)
#    define ldxr_i(r0, r1, r2)		LDSW(r1, r2, r0)
#    define ldxr_ui(r0, r1, r2)		LDUW(r1, r2, r0)
#    define ldxr_l(r0, r1, r2)		LDX(r1, r2, r0)
#    define ldxi(u, v, w)		ldxi_l(u, v, w)
#  endif
#  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 ldxi_ui(r0, r1, i0)		_ldxi_ui(_jit, r0, r1, i0)
static void _ldxi_ui(jit_state_t*,jit_int32_t,jit_int32_t,jit_word_t);
#    define 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)			STB(r1, r0, 0)
#  define sti_c(i0, r0)			_sti_c(_jit, i0, r0)
static void _sti_c(jit_state_t*,jit_word_t,jit_int32_t);
#  define str_s(r0, r1)			STH(r1, r0, 0)
#  define sti_s(i0, r0)			_sti_s(_jit, i0, r0)
static void _sti_s(jit_state_t*,jit_word_t,jit_int32_t);
#  if __WORDSIZE == 32
#    define str(u, v)			str_i(u, v)
#    define str_i(r0, r1)		STI(r1, r0, 0)
#    define sti(u, v)			sti_i(u, v)
#  else
#    define str(u, v)			str_l(u, v)
#    define str_i(r0, r1)		STW(r1, r0, 0)
#    define str_l(r0, r1)		STX(r1, r0, 0)
#    define sti(u, v)			sti_l(u, v)
#  endif
#  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 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)		STB(r2, r1, r0)
#  define stxi_c(i0, r0, r1)		_stxi_c(_jit, i0, r0, r1)
static void _stxi_c(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
#  define stxr_s(r0, r1, r2)		STH(r2, r1, r0)
#  define stxi_s(i0, r0, r1)		_stxi_s(_jit, i0, r0, r1)
static void _stxi_s(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
#  if __WORDSIZE == 32
#    define stxr(u, v, w)		stxr_i(u, v, w)
#    define stxr_i(r0, r1, r2)		ST(r2, r1, r0)
#    define stxi(u, v, w)		stxi_i(u, v, w)
#  else
#    define stxr(u, v, w)		stxr_l(u, v, w)
#    define stxr_i(r0, r1, r2)		STW(r2, r1, r0)
#    define stxi(u, v, w)		stxi_l(u, v, w)
#    define stxr_l(r0, r1, r2)		STX(r2, r1, r0)
#  endif
#  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 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 br(cc, i0, r0, r1)		_br(_jit, cc, i0, r0, r1)
static jit_word_t
_br(jit_state_t*,jit_int32_t,jit_word_t,jit_int32_t,jit_int32_t);
#  define bw(cc, i0, r0, i1)		_bw(_jit, cc, i0, r0, i1)
static jit_word_t
_bw(jit_state_t*,jit_int32_t,jit_word_t,jit_int32_t,jit_word_t);
#  if __WORDSIZE == 32
#    define bltr(i0, r0, r1)		br(SPARC_BL, i0, r0, r1)
#    define blti(i0, r0, i1)		bw(SPARC_BL, i0, r0, i1)
#    define bltr_u(i0, r0, r1)		br(SPARC_BLU, i0, r0, r1)
#    define blti_u(i0, r0, i1)		bw(SPARC_BLU, i0, r0, i1)
#    define bler(i0, r0, r1)		br(SPARC_BLE, i0, r0, r1)
#    define blei(i0, r0, i1)		bw(SPARC_BLE, i0, r0, i1)
#    define bler_u(i0, r0, r1)		br(SPARC_BLEU, i0, r0, r1)
#    define blei_u(i0, r0, i1)		bw(SPARC_BLEU, i0, r0, i1)
#    define beqr(i0, r0, r1)		br(SPARC_BE, i0, r0, r1)
#    define beqi(i0, r0, i1)		bw(SPARC_BE, i0, r0, i1)
#    define bger(i0, r0, r1)		br(SPARC_BGE, i0, r0, r1)
#    define bgei(i0, r0, i1)		bw(SPARC_BGE, i0, r0, i1)
#    define bger_u(i0, r0, r1)		br(SPARC_BGEU, i0, r0, r1)
#    define bgei_u(i0, r0, i1)		bw(SPARC_BGEU, i0, r0, i1)
#    define bgtr(i0, r0, r1)		br(SPARC_BG, i0, r0, r1)
#    define bgti(i0, r0, i1)		bw(SPARC_BG, i0, r0, i1)
#    define bgtr_u(i0, r0, r1)		br(SPARC_BGU, i0, r0, r1)
#    define bgti_u(i0, r0, i1)		bw(SPARC_BGU, i0, r0, i1)
#    define bner(i0, r0, r1)		br(SPARC_BNE, i0, r0, r1)
#    define bnei(i0, r0, i1)		bw(SPARC_BNE, i0, r0, i1)
#  else
#    define bltr(i0, r0, r1)		br(SPARC_BPL, i0, r0, r1)
#    define blti(i0, r0, i1)		bw(SPARC_BPL, i0, r0, i1)
#    define bltr_u(i0, r0, r1)		br(SPARC_BPCS, i0, r0, r1)
#    define blti_u(i0, r0, i1)		bw(SPARC_BPCS, i0, r0, i1)
#    define bler(i0, r0, r1)		br(SPARC_BPLE, i0, r0, r1)
#    define blei(i0, r0, i1)		bw(SPARC_BPLE, i0, r0, i1)
#    define bler_u(i0, r0, r1)		br(SPARC_BPLEU, i0, r0, r1)
#    define blei_u(i0, r0, i1)		bw(SPARC_BPLEU, i0, r0, i1)
#    define beqr(i0, r0, r1)		br(SPARC_BPE, i0, r0, r1)
#    define beqi(i0, r0, i1)		bw(SPARC_BPE, i0, r0, i1)
#    define bger(i0, r0, r1)		br(SPARC_BPGE, i0, r0, r1)
#    define bgei(i0, r0, i1)		bw(SPARC_BPGE, i0, r0, i1)
#    define bger_u(i0, r0, r1)		br(SPARC_BPCC, i0, r0, r1)
#    define bgei_u(i0, r0, i1)		bw(SPARC_BPCC, i0, r0, i1)
#    define bgtr(i0, r0, r1)		br(SPARC_BPG, i0, r0, r1)
#    define bgti(i0, r0, i1)		bw(SPARC_BPG, i0, r0, i1)
#    define bgtr_u(i0, r0, r1)		br(SPARC_BPGU, i0, r0, r1)
#    define bgti_u(i0, r0, i1)		bw(SPARC_BPGU, i0, r0, i1)
#    define bner(i0, r0, r1)		br(SPARC_BPNE, i0, r0, r1)
#    define bnei(i0, r0, i1)		bw(SPARC_BPNE, i0, r0, i1)
#  endif
#  define b_asr(jif,add,sgn,i0,r0,r1)	_b_asr(_jit,jif,add,sgn,i0,r0,r1)
static jit_word_t
_b_asr(jit_state_t*,jit_bool_t,jit_bool_t,jit_bool_t,
       jit_word_t,jit_int32_t,jit_int32_t);
#  define b_asw(jif,add,sgn,i0,r0,i1)	_b_asw(_jit,jif,add,sgn,i0,r0,i1)
static jit_word_t
_b_asw(jit_state_t*,jit_bool_t,jit_bool_t,jit_bool_t,
       jit_word_t,jit_int32_t,jit_word_t);
#  define boaddr(i0, r0, r1)		b_asr(1, 1, 1, i0, r0, r1)
#  define boaddi(i0, r0, i1)		b_asw(1, 1, 1, i0, r0, i1)
#  define boaddr_u(i0, r0, r1)		b_asr(1, 1, 0, i0, r0, r1)
#  define boaddi_u(i0, r0, i1)		b_asw(1, 1, 0, i0, r0, i1)
#  define bxaddr(i0, r0, r1)		b_asr(0, 1, 1, i0, r0, r1)
#  define bxaddi(i0, r0, i1)		b_asw(0, 1, 1, i0, r0, i1)
#  define bxaddr_u(i0, r0, r1)		b_asr(0, 1, 0, i0, r0, r1)
#  define bxaddi_u(i0, r0, i1)		b_asw(0, 1, 0, i0, r0, i1)
#  define bosubr(i0, r0, r1)		b_asr(1, 0, 1, i0, r0, r1)
#  define bosubi(i0, r0, i1)		b_asw(1, 0, 1, i0, r0, i1)
#  define bosubr_u(i0, r0, r1)		b_asr(1, 0, 0, i0, r0, r1)
#  define bosubi_u(i0, r0, i1)		b_asw(1, 0, 0, i0, r0, i1)
#  define bxsubr(i0, r0, r1)		b_asr(0, 0, 1, i0, r0, r1)
#  define bxsubi(i0, r0, i1)		b_asw(0, 0, 1, i0, r0, i1)
#  define bxsubr_u(i0, r0, r1)		b_asr(0, 0, 0, i0, r0, r1)
#  define bxsubi_u(i0, r0, i1)		b_asw(0, 0, 0, i0, r0, i1)
#  define bm_r(set, i0, r0, r1)		_bm_r(_jit,set,i0,r0,r1)
static jit_word_t
_bm_r(jit_state_t*,jit_bool_t,jit_word_t,jit_int32_t,jit_int32_t);
#  define bm_w(set,i0,r0,i1)		_bm_w(_jit,set,i0,r0,i1)
static jit_word_t
_bm_w(jit_state_t*,jit_bool_t,jit_word_t,jit_int32_t,jit_word_t);
#  define bmsr(i0, r0, r1)		bm_r(1, i0, r0, r1)
#  define bmsi(i0, r0, i1)		bm_w(1, i0, r0, i1)
#  define bmcr(i0, r0, r1)		bm_r(0, i0, r0, r1)
#  define bmci(i0, r0, i1)		bm_w(0, i0, r0, i1)
#  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 jmpi_p(i0)			_jmpi_p(_jit, i0)
static jit_word_t _jmpi_p(jit_state_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 calli_p(i0)			_calli_p(_jit, i0)
static jit_word_t _calli_p(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 vastart(r0)			_vastart(_jit, r0)
static void _vastart(jit_state_t*, jit_int32_t);
#define vaarg(r0, r1)			_vaarg(_jit, r0, r1)
static void _vaarg(jit_state_t*, jit_int32_t, jit_int32_t);
#define patch_at(jump, label)		_patch_at(_jit, jump, label)
static void _patch_at(jit_state_t*,jit_word_t,jit_word_t);
#endif

#if CODE
static void
_f2r(jit_state_t *_jit,
     jit_int32_t op, jit_int32_t rd, jit_int32_t op2, jit_int32_t imm22)
{
    jit_instr_t		v;
    assert(!(op  & 0xfffffffc));
    assert(!(rd  & 0xffffffe0));
    assert(!(op2 & 0xfffffff8));
    assert(s22_p(imm22));
    v.op.b    = op;
    v.rd.b    = rd;
    v.op2.b   = op2;
    v.imm22.b = imm22;
    ii(v.v);
}

static void
_f2b(jit_state_t *_jit,
     jit_int32_t op, jit_int32_t a, jit_int32_t cond, jit_int32_t op2,
     jit_int32_t disp22)
{
    jit_instr_t		v;
    assert(!(op   & 0xfffffffc));
    assert(!(a    & 0xfffffffe));
    assert(!(cond & 0xfffffff0));
    assert(!(op2  & 0xfffffff8));
    assert(s22_p(disp22));
    v.op.b     = op;
    v.a.b      = a;
    v.cond.b   = cond;
    v.op2.b    = op2;
    v.disp22.b = disp22;
    ii(v.v);
}

#  if __WORDSIZE == 64
static void
_f2bp(jit_state_t *_jit,
      jit_int32_t op, jit_int32_t a, jit_int32_t cond, jit_int32_t op2,
      jit_int32_t cc1, jit_int32_t cc0, jit_int32_t p, jit_int32_t disp19)
{
    jit_instr_t		v;
    assert(!(op   & 0xfffffffc));
    assert(!(a    & 0xfffffffe));
    assert(!(cond & 0xfffffff0));
    assert(!(op2  & 0xfffffff8));
    assert(s19_p(disp19));
    v.op.b     = op;
    v.a.b      = a;
    v.cond.b   = cond;
    v.op2.b    = op2;
    v.cc1.b    = cc1;
    v.cc0.b    = cc0;
    v.p.b      = p;
    v.disp19.b = disp19;
    ii(v.v);
}
#  endif

static void
_f3r(jit_state_t *_jit, jit_int32_t op, jit_int32_t rd,
     jit_int32_t op3, jit_int32_t rs1, jit_int32_t rs2)
{
    jit_instr_t		v;
    assert(!(op  & 0xfffffffc));
    assert(!(rd  & 0xffffffe0));
    assert(!(op3 & 0xffffffc0));
    assert(!(rs1 & 0xffffffe0));
    assert(!(rs2 & 0xffffffe0));
    v.op.b  = op;
    v.rd.b  = rd;
    v.op3.b = op3;
    v.rs1.b = rs1;
    v.i.b   = 0;
    v.asi.b = 0;
    v.rs2.b = rs2;
    ii(v.v);
}

#  if __WORDSIZE == 64
static void
_f3ri(jit_state_t *_jit, jit_int32_t op, jit_int32_t rd,
      jit_int32_t op3, jit_int32_t rs1, jit_int32_t rs2)
{
    jit_instr_t		v;
    assert(!(op  & 0xfffffffc));
    assert(!(rd  & 0xffffffe0));
    assert(!(op3 & 0xffffffc0));
    assert(!(rs1 & 0xffffffe0));
    assert(!(rs2 & 0xffffffe0));
    v.op.b  = op;
    v.rd.b  = rd;
    v.op3.b = op3;
    v.rs1.b = rs1;
    v.i.b   = 1;
    v.asi.b = 0;
    v.rs2.b = rs2;
    ii(v.v);
}

static void
_f3rx(jit_state_t *_jit, jit_int32_t op, jit_int32_t rd,
      jit_int32_t op3, jit_int32_t rs1, jit_int32_t rs2)
{
    jit_instr_t		v;
    assert(!(op  & 0xfffffffc));
    assert(!(rd  & 0xffffffe0));
    assert(!(op3 & 0xffffffc0));
    assert(!(rs1 & 0xffffffe0));
    assert(!(rs2 & 0xffffffe0));
    v.op.b   = op;
    v.rd.b   = rd;
    v.op3.b  = op3;
    v.rs1.b  = rs1;
    v.i.b    = 0;
    v.x.b    = 1;
    v.asix.b = 0;
    v.rs2.b  = rs2;
    ii(v.v);
}

static void
_f3s(jit_state_t *_jit, jit_int32_t op, jit_int32_t rd,
      jit_int32_t op3, jit_int32_t rs1, jit_int32_t shim)
{
    jit_instr_t		v;
    assert(!(op   & 0xfffffffc));
    assert(!(rd   & 0xffffffe0));
    assert(!(op3  & 0xffffffc0));
    assert(!(rs1  & 0xffffffe0));
    assert(!(shim & 0xffffffc0));
    v.op.b   = op;
    v.rd.b   = rd;
    v.op3.b  = op3;
    v.rs1.b  = rs1;
    v.i.b    = 1;
    v.x.b    = 1;
    v.asis.b = 0;
    v.shim.b = shim;
    ii(v.v);
}
#  endif

static void
_f3i(jit_state_t *_jit, jit_int32_t op, jit_int32_t rd,
     jit_int32_t op3, jit_int32_t rs1, jit_int32_t simm13)
{
    jit_instr_t		v;
    assert(!(op  & 0xfffffffc));
    assert(!(rd  & 0xffffffe0));
    assert(!(op3 & 0xffffffc0));
    assert(!(rs1 & 0xffffffe0));
    assert(s13_p(simm13));
    v.op.b     = op;
    v.rd.b     = rd;
    v.op3.b    = op3;
    v.rs1.b    = rs1;
    v.i.b      = 1;
    v.simm13.b = simm13;
    ii(v.v);
}

static void
_f3t(jit_state_t *_jit, jit_int32_t cond,
     jit_int32_t rs1, jit_int32_t i, jit_int32_t rs2_imm7)
{
    jit_instr_t		v;
    assert(!(cond & 0xfffffff0));
    assert(!(i    & 0xfffffffe));
    assert(!(rs1 & 0xffffffe0));
    v.op.b     = 2;
    v.rd.b     = cond;
    v.op3.b    = 58;
    v.i.b      = i;
    if (i) {
	assert(s7_p(rs2_imm7));
	v.res.b  = 0;
	v.imm7.b = rs2_imm7;
    }
    else {
	assert(!(rs2_imm7 & 0xffffffe0));
	v.asi.b = 0;
	v.rs2.b = rs2_imm7;
    }
    ii(v.v);
}

static void
_f3a(jit_state_t *_jit, jit_int32_t op, jit_int32_t rd,
     jit_int32_t op3, jit_int32_t rs1, jit_int32_t asi, jit_int32_t rs2)
{
    jit_instr_t		v;
    assert(!(op  & 0xfffffffc));
    assert(!(rd  & 0xffffffe0));
    assert(!(op3 & 0xffffffc0));
    assert(!(rs1 & 0xffffffe0));
    assert(!(asi & 0xffffff00));
    assert(!(rs2 & 0xffffffe0));
    v.op.b    = op;
    v.rd.b    = rd;
    v.op3.b   = op3;
    v.rs1.b   = rs1;
    v.i.b     = 0;
    v.asi.b   = asi;
    v.rs2.b   = rs2;
    ii(v.v);
}

static void
_f1(jit_state_t *_jit, jit_int32_t op, jit_int32_t disp30)
{
    jit_instr_t		v;
    assert(!(op  & 0xfffffffc));
    assert(s30_p(disp30));
    v.op.b     = op;
    v.disp30.b = disp30;
    ii(v.v);
}

static void
_f2c1(jit_state_t *_jit, jit_int32_t op, jit_int32_t rd,
      jit_int32_t op3, jit_int32_t rs1, jit_int32_t opf, jit_int32_t rs2)
{
    jit_instr_t		v;
    assert(!(op  & 0xfffffffc));
    assert(!(rd  & 0xffffffe0));
    assert(!(res & 0xffffffc0));
    assert(!(rs1 & 0xffffffe0));
    assert(!(opf & 0xfffffe00));
    assert(!(rs2 & 0xfffffe00));
    v.op.b = op;
    v.rd.b = rd;
    v.op3.b = op3;
    v.rs1.b = rs1;
    v.opf.b = opf;
    v.rs2.b = rs2;
    ii(v.v);
}

static void
_nop(jit_state_t *_jit, jit_int32_t i0)
{
    for (; i0 > 0; i0 -= 4)
	NOP();
    assert(i0 == 0);
}

static void
_movr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
{
    if (r0 != r1)
	ORI(r1, 0, r0);
}

static void
_movi(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
{
    if (s13_p(i0))
	ORI(0, i0, r0);
    else {
#  if __WORDSIZE == 64
	if (i0 & 0xffffffff00000000) {
	    jit_int32_t	reg = jit_get_reg(jit_class_gpr);
	    movi(rn(reg), (i0 >> 32) & 0xffffffff);
	    movi(r0, i0 & 0xffffffff);
	    lshi(rn(reg), rn(reg), 32);
	    OR(rn(reg), r0, r0);
	    jit_unget_reg(reg);
	}
	else {
#  endif
	    SETHI(HI((int)i0), r0);
	    if (LO(i0))
		ORI(r0, LO(i0), r0);
#  if __WORDSIZE == 64
	}
#  endif
    }
}

static jit_word_t
_movi_p(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
{
    jit_word_t		w;
#  if __WORDSIZE == 64
    jit_int32_t		reg;
#  endif
    w = _jit->pc.w;
#  if __WORDSIZE == 64
    reg = jit_get_reg(jit_class_gpr);
    SETHI(HI((int)i0), r0);
    ORI(r0, LO(i0), r0);
    i0 = (int)(i0 >> 32);
    SETHI(HI(i0), rn(reg));
    ORI(rn(reg), LO(i0), rn(reg));
    SLLXI(rn(reg), 32, rn(reg));
    OR(rn(reg), r0, r0);
    jit_unget_reg(reg);
#  else
    SETHI(HI(i0), r0);
    ORI(r0, LO(i0), r0);
#  endif
    return (w);
}

static void
_movnr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
{
    jit_word_t	w;
    w = beqi(_jit->pc.w, r2, 0);
    ORI(r1, 0, r0);
    patch_at(w, _jit->pc.w);
}

static void
_movzr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
{
    jit_word_t	w;
    w = bnei(_jit->pc.w, r2, 0);
    ORI(r1, 0, r0);
    patch_at(w, _jit->pc.w);
}

static void
_casx(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1,
      jit_int32_t r2, jit_int32_t r3, jit_word_t i0)
{
    jit_int32_t         iscasi, r1_reg;
    if ((iscasi = (r1 == _NOREG))) {
        r1_reg = jit_get_reg(jit_class_gpr);
        r1 = rn(r1_reg);
        movi(r1, i0);
    }
    /* Do not clobber r2 */
    movr(r0, r3);
    /* The CASXA instruction compares the value in register r[rs2] with
     * the doubleword in memory pointed to by the doubleword address in
     *  r[rs1]. If the values are equal, the value in r[rd] is swapped
     * with the doubleword pointed to by the doubleword address in r[rs1].
     *  If the values are not equal, the contents of the doubleword pointed
     *  to by r[rs1] replaces the value in r[rd], but the memory location
     * remains unchanged.
     */
#  if __WORDSIZE == 32
    CASA(r1, r2, r0);
#  else
    CASXA(r1, r2, r0);
#  endif
    eqr(r0, r0, r2);
    if (iscasi)
        jit_unget_reg(r1_reg);
}

static void
_bitswap(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
{
    jit_int32_t		t0, t1, t2, t3, t4;
    movr(r0, r1);
    t0 = jit_get_reg(jit_class_gpr);
    t1 = jit_get_reg(jit_class_gpr);
    t2 = jit_get_reg(jit_class_gpr);
    movi(rn(t0), __WORDSIZE == 32 ? 0x55555555L : 0x5555555555555555L);
    rshi_u(rn(t1), r0, 1);		/* t1 = v >> 1 */
    andr(rn(t1), rn(t1), rn(t0));	/* t1 &= t0 */
    andr(rn(t2), r0, rn(t0));		/* t2 = v & t0*/
    lshi(rn(t2), rn(t2), 1);		/* t2 <<= 1 */
    orr(r0, rn(t1), rn(t2));		/* v = t1 | t2 */
    movi(rn(t0), __WORDSIZE == 32 ? 0x33333333L : 0x3333333333333333L);
    rshi_u(rn(t1), r0, 2);		/* t1 = v >> 2 */
    andr(rn(t1), rn(t1), rn(t0));	/* t1 &= t0 */
    andr(rn(t2), r0, rn(t0));		/* t2 = v & t0*/
    lshi(rn(t2), rn(t2), 2);		/* t2 <<= 2 */
    orr(r0, rn(t1), rn(t2));		/* v = t1 | t2 */
    movi(rn(t0), __WORDSIZE == 32 ? 0x0f0f0f0fL : 0x0f0f0f0f0f0f0f0fL);
    rshi_u(rn(t1), r0, 4);		/* t1 = v >> 4 */
    andr(rn(t1), rn(t1), rn(t0));	/* t1 &= t0 */
    andr(rn(t2), r0, rn(t0));		/* t2 = v & t0*/
    lshi(rn(t2), rn(t2), 4);		/* t2 <<= 4 */
    orr(r0, rn(t1), rn(t2));		/* v = t1 | t2 */
    movi(rn(t0), __WORDSIZE == 32 ?  0x00ff00ffL : 0x00ff00ff00ff00ffL);
    rshi_u(rn(t1), r0, 8);		/* t1 = v >> 8 */
    andr(rn(t1), rn(t1), rn(t0));	/* t1 &= t0 */
    andr(rn(t2), r0, rn(t0));		/* t2 = v & t0*/
    lshi(rn(t2), rn(t2), 8);		/* t2 <<= 8 */
    orr(r0, rn(t1), rn(t2));		/* v = t1 | t2 */
#  if __WORDSIZE == 32
    rshi_u(rn(t1), r0, 16);		/* t1 = v >> 16 */
    lshi(rn(t2), r0, 16);		/* t2 = v << 16 */
    orr(r0, rn(t1), rn(t2));		/* v = t1 | t2 */
#  else
    movi(rn(t0), 0x0000ffff0000ffffL);
    rshi_u(rn(t1), r0, 16);		/* t1 = v >> 16 */
    andr(rn(t1), rn(t1), rn(t0));	/* t1 &= t0 */
    andr(rn(t2), r0, rn(t0));		/* t2 = v & t0*/
    lshi(rn(t2), rn(t2), 16);		/* t2 <<= 16 */
    orr(r0, rn(t1), rn(t2));		/* v = t1 | t2 */
    rshi_u(rn(t1), r0, 32);		/* t1 = v >> 32 */
    lshi(rn(t2), r0, 32);		/* t2 = v << 32 */
    orr(r0, rn(t1), rn(t2));		/* v = t1 | t2 */
#  endif
    jit_unget_reg(t2);
    jit_unget_reg(t1);
    jit_unget_reg(t0);
}

static void
_clor(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
{
    if (jit_cpu.lzcnt) {
	comr(r0, r1);
	clzr(r0, r0);
    }
    else
	fallback_clo(r0, r1);
}

static void
_clzr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
{
    if (jit_cpu.lzcnt) {
#if __WORDSIZE == 32
	jit_word_t		w;
	SLLXI(r1, 32, r0);
	LZCNT(r0, r0);
#if __WORDSIZE == 32
	w = blei(_jit->pc.w, r0, 31);
	rshi(r0, r0, 1);	/* r0 is 64 */
	patch_at(w, _jit->pc.w);
#endif
#else
	LZCNT(r1, r0);
    }
    else
	fallback_clz(r0, r1);
}

static void
_ctor(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
{
    if (jit_cpu.lzcnt) {
	bitswap(r0, r1);
	clor(r0, r0);
    }
    else
	fallback_cto(r0, r1);
}

static void
_ctzr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
{
    if (jit_cpu.lzcnt) {
	bitswap(r0, r1);
	clzr(r0, r0);
    }
    else
	fallback_ctz(r0, r1);
}

static void
_addi(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
{
    jit_int32_t		reg;
    if (s13_p(i0))
	ADDI(r1, i0, r0);
    else {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	addr(r0, r1, rn(reg));
	jit_unget_reg(reg);
    }
}

#  if __WORDSIZE == 64
static void
_addcr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
{
    jit_int32_t		reg;
    if (jit_carry == _NOREG)
	jit_carry = jit_get_reg(jit_class_gpr);
    if (r0 == r1) {
	reg = jit_get_reg(jit_class_gpr);
	addr(rn(reg), r1, r2);
	ltr_u(rn(jit_carry), rn(reg), r1);
	movr(r0, rn(reg));
	jit_unget_reg(reg);
    }
    else {
	addr(r0, r1, r2);
	ltr_u(rn(jit_carry), r0, r1);
    }
}
#  endif

static void
_addci(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
{
#  if __WORDSIZE == 32
    jit_int32_t		reg;
    if (s13_p(i0))
	ADDIcc(r1, i0, r0);
    else {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	addcr(r0, r1, rn(reg));
	jit_unget_reg(reg);
    }
#  else
    jit_int32_t		reg;
    if (jit_carry == _NOREG)
	jit_carry = jit_get_reg(jit_class_gpr);
    if (r0 == r1) {
	reg = jit_get_reg(jit_class_gpr);
	addi(rn(reg), r1, i0);
	ltr_u(rn(jit_carry), rn(reg), r1);
	movr(r0, rn(reg));
	jit_unget_reg(reg);
    }
    else {
	addi(r0, r1, i0);
	ltr_u(rn(jit_carry), r0, r1);
    }
#  endif
}

#  if __WORDSIZE == 64
static void
_addxr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
{
    jit_int32_t		reg;
    assert(jit_carry != _NOREG);
    reg = jit_get_reg(jit_class_gpr);
    movr(rn(reg), rn(jit_carry));
    addcr(r0, r1, r2);
    addcr(r0, r0, rn(reg));
    jit_unget_reg(reg);
}
#  endif

static void
_addxi(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
{
#  if __WORDSIZE == 32
    jit_int32_t		reg;
    if (s13_p(i0))
	ADDXIcc(r1, i0, r0);
    else {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	addxr(r0, r1, rn(reg));
	jit_unget_reg(reg);
    }
#  else
    jit_int32_t		reg;
    assert(jit_carry != _NOREG);
    reg = jit_get_reg(jit_class_gpr);
    movr(rn(reg), rn(jit_carry));
    addci(r0, r1, i0);
    addcr(r0, r0, rn(reg));
    jit_unget_reg(reg);
#  endif
}

static void
_subi(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
{
    jit_int32_t		reg;
    if (s13_p(i0))
	SUBI(r1, i0, r0);
    else {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	subr(r0, r1, rn(reg));
	jit_unget_reg(reg);
    }
}

#  if __WORDSIZE == 64
static void
_subcr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
{
    jit_int32_t		reg;
    if (jit_carry == _NOREG)
	jit_carry = jit_get_reg(jit_class_gpr);
    if (r0 == r1) {
	reg = jit_get_reg(jit_class_gpr);
	subr(rn(reg), r1, r2);
	ltr_u(rn(jit_carry), r1, rn(reg));
	movr(r0, rn(reg));
	jit_unget_reg(reg);
    }
    else {
	subr(r0, r1, r2);
	ltr_u(rn(jit_carry), r1, r0);
    }
}
#  endif

static void
_subci(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
{
#  if __WORDSIZE == 32
    jit_int32_t		reg;
    if (s13_p(i0))
	SUBIcc(r1, i0, r0);
    else {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	subcr(r0, r1, rn(reg));
	jit_unget_reg(reg);
    }
#  else
    jit_int32_t		reg;
    if (jit_carry == _NOREG)
	jit_carry = jit_get_reg(jit_class_gpr);
    if (r0 == r1) {
	reg = jit_get_reg(jit_class_gpr);
	addi(rn(reg), r1, -i0);
	ltr_u(rn(jit_carry), r1, rn(reg));
	movr(r0, rn(reg));
	jit_unget_reg(reg);
    }
    else {
	addi(r0, r1, -i0);
	ltr_u(rn(jit_carry), r1, r0);
    }
#  endif
}

#  if __WORDSIZE == 64
static void
_subxr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
{
    jit_int32_t		reg;
    assert(jit_carry != _NOREG);
    reg = jit_get_reg(jit_class_gpr);
    movr(rn(reg), rn(jit_carry));
    subcr(r0, r1, r2);
    subcr(r0, r0, rn(reg));
    jit_unget_reg(reg);
}
#endif

static void
_subxi(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
{
#  if __WORDSIZE == 32
    jit_int32_t		reg;
    if (s13_p(i0))
	SUBXIcc(r1, i0, r0);
    else {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	subxr(r0, r1, rn(reg));
	jit_unget_reg(reg);
    }
#  else
    jit_int32_t		reg;
    assert(jit_carry != _NOREG);
    reg = jit_get_reg(jit_class_gpr);
    movr(rn(reg), rn(jit_carry));
    subci(r0, r1, i0);
    subcr(r0, r0, rn(reg));
    jit_unget_reg(reg);
#  endif
}

static void
_rsbi(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
{
    subi(r0, r1, i0);
    negr(r0, r0);
}

static void
_muli(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
{
    jit_int32_t		reg;
    if (s13_p(i0)) {
#  if __WORDSIZE == 32
	UMULI(r1, i0, r0);
#  else
	MULXI(r1, i0, r0);
#  endif
    }
    else {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	mulr(r0, r1, rn(reg));
	jit_unget_reg(reg);
    }
}

#  if __WORDSIZE == 32
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)
{
    if (sign)
	SMUL(r2, r3, r0);
    else
	UMUL(r2, r3, r0);
    RDY(r1);
}

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 (s13_p(i0)) {
	if (sign)
	    SMULI(r2, i0, r0);
	else
	    UMULI(r2, i0, r0);
	RDY(r1);
    }
    else {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	iqmulr(r0, r1, r2, rn(reg), sign);
	jit_unget_reg(reg);
    }
}

#  else
static __int128_t __llmul(jit_word_t a, jit_word_t b)
{
    return (__int128_t)a * (__int128_t)b;
}

#  define QMUL_PROLOG()						\
    do {							\
	(void)jit_get_reg(_O0|jit_class_gpr|jit_class_named);	\
	(void)jit_get_reg(_O1|jit_class_gpr|jit_class_named);	\
	if (r0 != _G2_REGNO && r1 != _G2_REGNO)			\
	    stxi(BIAS(-8), _FP_REGNO, _G2_REGNO);		\
	if (r0 != _G3_REGNO && r1 != _G3_REGNO)			\
	    stxi(BIAS(-16), _FP_REGNO, _G3_REGNO);		\
	if (r0 != _G4_REGNO && r1 != _G4_REGNO)			\
	    stxi(BIAS(-24), _FP_REGNO, _G4_REGNO);		\
    } while (0)

#  define QMUL_EPILOG()						\
    do {							\
	if (r0 != _G2_REGNO && r1 != _G2_REGNO)			\
	    ldxi(_G2_REGNO, _FP_REGNO, BIAS(-8));		\
	if (r0 != _G3_REGNO && r1 != _G3_REGNO)			\
	    ldxi(_G3_REGNO, _FP_REGNO, BIAS(-16));		\
	if (r0 != _G4_REGNO && r1 != _G4_REGNO)			\
	    ldxi(_G4_REGNO, _FP_REGNO, BIAS(-24));		\
	(void)jit_unget_reg(_O0);				\
	(void)jit_unget_reg(_O1);				\
    } while (0)

static void
_qmulr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1,
       jit_int32_t r2, jit_int32_t r3)
{
    QMUL_PROLOG();
    movr(_O0_REGNO, r3);
    movr(_O1_REGNO, r2);
    calli((jit_word_t)__llmul);
    movr(r0, _O1_REGNO);
    movr(r1, _O0_REGNO);
    QMUL_EPILOG();
}

static void
_qmuli(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1,
       jit_int32_t r2, jit_word_t i0)
{
    QMUL_PROLOG();
    movi(_O0_REGNO, i0);
    movr(_O1_REGNO, r2);
    calli((jit_word_t)__llmul);
    movr(r0, _O1_REGNO);
    movr(r1, _O0_REGNO);
    QMUL_EPILOG();
}

static __uint128_t __ullmul(jit_uword_t a, jit_uword_t b)
{
    return (__uint128_t)a * (__uint128_t)b;
}

static void
_qmulr_u(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1,
	 jit_int32_t r2, jit_int32_t r3)
{
    QMUL_PROLOG();
    movr(_O0_REGNO, r3);
    movr(_O1_REGNO, r2);
    calli((jit_word_t)__ullmul);
    movr(r0, _O1_REGNO);
    movr(r1, _O0_REGNO);
    QMUL_EPILOG();
}

static void
_qmuli_u(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1,
	 jit_int32_t r2, jit_word_t i0)
{
    QMUL_PROLOG();
    movi(_O0_REGNO, i0);
    movr(_O1_REGNO, r2);
    calli((jit_word_t)__ullmul);
    movr(r0, _O1_REGNO);
    movr(r1, _O0_REGNO);
    QMUL_EPILOG();
}
#  endif

static void
_divr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
{
#  if __WORDSIZE == 32
    jit_int32_t		reg;
    reg = jit_get_reg(jit_class_gpr);
    rshi(rn(reg), r1, 31);
    WRY(rn(reg), 0);
    SDIV(r1, r2, r0);
    jit_unget_reg(reg);
#  else
    SDIVX(r1, r2, r0);
#  endif
}

static void
_divi(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
{
    jit_int32_t		reg;
#  if __WORDSIZE == 32
    reg = jit_get_reg(jit_class_gpr);
#  endif
    if (s13_p(i0)) {
#  if __WORDSIZE == 32
	rshi(rn(reg), r1, 31);
	WRY(rn(reg), 0);
	SDIVI(r1, i0, r0);
#  else
	SDIVXI(r1, i0, r0);
#  endif
    }
    else {
#  if __WORDSIZE == 64
	reg = jit_get_reg(jit_class_gpr);
#  endif
	movi(rn(reg), i0);
	divr(r0, r1, rn(reg));
#  if __WORDSIZE == 64
	jit_unget_reg(reg);
#  endif
    }
#  if __WORDSIZE == 32
    jit_unget_reg(reg);
#  endif
}

static void
_divr_u(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
{
#  if __WORDSIZE == 32
    WRYI(0, 0);
    UDIV(r1, r2, r0);
#  else
    UDIVX(r1, r2, r0);
#  endif
}

static void
_divi_u(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
{
    jit_int32_t		reg;
    if (s13_p(i0)) {
#  if __WORDSIZE == 32
	WRYI(0, 0);
	UDIVI(r1, i0, r0);
#  else
	UDIVXI(r1, i0, r0);
#  endif
    }
    else {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	divr_u(r0, r1, rn(reg));
	jit_unget_reg(reg);
    }
}

static void
_iqdivr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1,
	jit_int32_t r2, jit_int32_t r3, jit_bool_t sign)
{
    jit_int32_t		sv0, rg0;
    jit_int32_t		sv1, rg1;

    if (r0 == r2 || r0 == r3) {
	sv0 = jit_get_reg(jit_class_gpr);
	rg0 = rn(sv0);
    }
    else
	rg0 = r0;
    if (r1 == r2 || r1 == r3) {
	sv1 = jit_get_reg(jit_class_gpr);
	rg1 = rn(sv1);
    }
    else
	rg1 = r1;

    if (sign)
	divr(rg0, r2, r3);
    else
	divr_u(rg0, r2, r3);
    mulr(rg1, r3, rg0);
    subr(rg1, r2, rg1);
    if (rg0 != r0) {
	movr(r0, rg0);
	jit_unget_reg(sv0);
    }
    if (rg1 != r1) {
	movr(r1, rg1);
	jit_unget_reg(sv1);
    }
}

static void
_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);
    iqdivr(r0, r1, r2, rn(reg), sign);
    jit_unget_reg(reg);
}

static void
_remr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
{
    jit_int32_t		reg;
    if (r0 == r1 || r0 == r2) {
	reg = jit_get_reg(jit_class_gpr);
	divr(rn(reg), r1, r2);
	mulr(rn(reg), r2, rn(reg));
	subr(r0, r1, rn(reg));
	jit_unget_reg(reg);
    }
    else {
	divr(r0, r1, r2);
	mulr(r0, r2, r0);
	subr(r0, r1, r0);
    }
}

static void
_remi(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
{
    jit_int32_t		reg;
    reg = jit_get_reg(jit_class_gpr);
    movi(rn(reg), i0);
    remr(r0, r1, rn(reg));
    jit_unget_reg(reg);
}

static void
_remr_u(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
{
    jit_int32_t		reg;
    if (r0 == r1 || r0 == r2) {
	reg = jit_get_reg(jit_class_gpr);
	divr_u(rn(reg), r1, r2);
	mulr(rn(reg), r2, rn(reg));
	subr(r0, r1, rn(reg));
	jit_unget_reg(reg);
    }
    else {
	divr_u(r0, r1, r2);
	mulr(r0, r2, r0);
	subr(r0, r1, r0);
    }
}

static void
_remi_u(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
{
    jit_int32_t		reg;
    reg = jit_get_reg(jit_class_gpr);
    movi(rn(reg), i0);
    remr_u(r0, r1, rn(reg));
    jit_unget_reg(reg);
}

static void
_andi(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
{
    jit_int32_t		reg;
    if (s13_p(i0))
	ANDI(r1, i0, r0);
    else {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	andr(r0, r1, rn(reg));
	jit_unget_reg(reg);
    }
}

static void
_ori(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
{
    jit_int32_t		reg;
    if (s13_p(i0))
	ORI(r1, i0, r0);
    else {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	orr(r0, r1, rn(reg));
	jit_unget_reg(reg);
    }
}

static void
_xori(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
{
    jit_int32_t		reg;
    if (s13_p(i0))
	XORI(r1, i0, r0);
    else {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	xorr(r0, r1, rn(reg));
	jit_unget_reg(reg);
    }
}

static void
_extr_c(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
{
    lshi(r0, r1, __WORDSIZE - 8);
    rshi(r0, r0, __WORDSIZE - 8);
}

static void
_extr_s(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
{
    lshi(r0, r1, __WORDSIZE - 16);
    rshi(r0, r0, __WORDSIZE - 16);
}

static void
_extr_us(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
{
    lshi(r0, r1, __WORDSIZE - 16);
    rshi_u(r0, r0, __WORDSIZE - 16);
}

#if __WORDSIZE == 64
static void
_extr_i(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
{
    lshi(r0, r1, __WORDSIZE - 32);
    rshi(r0, r0, __WORDSIZE - 32);
}

static void
_extr_ui(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
{
    lshi(r0, r1, __WORDSIZE - 32);
    rshi_u(r0, r0, __WORDSIZE - 32);
}
#endif

static void
_cr(jit_state_t *_jit, jit_int32_t cc,
    jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
{
    CMP(r1, r2);
#  if __WORDSIZE == 32
    Ba(cc, 3);
#  else
    BPa(cc, 3);
#  endif
    movi(r0, 1);
    movi(r0, 0);
}

static void
_cw(jit_state_t *_jit, jit_int32_t cc,
    jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
{
    jit_int32_t		reg;
    if (s13_p(i0)) {
	CMPI(r1, i0);
#  if __WORDSIZE == 32
	Ba(cc, 3);
#  else
	BPa(cc, 3);
#  endif
	movi(r0, 1);
	movi(r0, 0);
    }
    else {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	cr(cc, r0, r1, rn(reg));
	jit_unget_reg(reg);
    }
}

static void
_ldi_c(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
{
    jit_int32_t		reg;
    if (s13_p(i0))
	LDSBI(0, i0, r0);
    else {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	ldr_c(r0, rn(reg));
	jit_unget_reg(reg);
    }
}

static void
_ldi_uc(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
{
    jit_int32_t		reg;
    if (s13_p(i0))
	LDUBI(0, i0, r0);
    else {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	ldr_uc(r0, rn(reg));
	jit_unget_reg(reg);
    }
}

static void
_ldi_s(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
{
    jit_int32_t		reg;
    if (s13_p(i0))
	LDSHI(0, i0, r0);
    else {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	ldr_s(r0, rn(reg));
	jit_unget_reg(reg);
    }
}

static void
_ldi_us(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
{
    jit_int32_t		reg;
    if (s13_p(i0))
	LDUHI(0, i0, r0);
    else {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	ldr_us(r0, rn(reg));
	jit_unget_reg(reg);
    }
}

static void
_ldi_i(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
{
    jit_int32_t		reg;
    if (s13_p(i0)) {
#  if __WORDSIZE == 32
	LDI(0, i0, r0);
#  else
	LDSWI(0, i0, r0);
#  endif
    }
    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
_ldi_ui(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
{
    jit_int32_t		reg;
    if (s13_p(i0))
	LDUWI(0, i0, r0);
    else {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	ldr_ui(r0, rn(reg));
	jit_unget_reg(reg);
    }
}

static void
_ldi_l(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
{
    jit_int32_t		reg;
    if (s13_p(i0))
	LDXI(0, i0, r0);
    else {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	ldr_l(r0, rn(reg));
	jit_unget_reg(reg);
    }
}
#  endif

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 (s13_p(i0))
	LDSBI(r1, i0, r0);
    else {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	ldxr_c(r0, r1, rn(reg));
	jit_unget_reg(reg);
    }
}

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 (s13_p(i0))
	LDUBI(r1, i0, r0);
    else {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	ldxr_uc(r0, r1, rn(reg));
	jit_unget_reg(reg);
    }
}

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 (s13_p(i0))
	LDSHI(r1, i0, r0);
    else {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	ldxr_s(r0, r1, rn(reg));
	jit_unget_reg(reg);
    }
}

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 (s13_p(i0))
	LDUHI(r1, i0, r0);
    else {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	ldxr_us(r0, r1, rn(reg));
	jit_unget_reg(reg);
    }
}

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 (s13_p(i0)) {
#  if __WORDSIZE == 32
	LDI(r1, i0, r0);
#  else
	LDSWI(r1, i0, r0);
#  endif
    }
    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
_ldxi_ui(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
{
    jit_int32_t		reg;
    if (s13_p(i0))
	LDUWI(r1, i0, r0);
    else {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	ldxr_ui(r0, r1, rn(reg));
	jit_unget_reg(reg);
    }
}

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 (s13_p(i0))
	LDXI(r1, i0, r0);
    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
_sti_c(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0)
{
    jit_int32_t		reg;
    if (s13_p(i0))
	STBI(r0, 0, i0);
    else {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	str_c(rn(reg), r0);
	jit_unget_reg(reg);
    }
}

static void
_sti_s(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0)
{
    jit_int32_t		reg;
    if (s13_p(i0))
	STHI(r0, 0, i0);
    else {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	str_s(rn(reg), r0);
	jit_unget_reg(reg);
    }
}

static void
_sti_i(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0)
{
    jit_int32_t		reg;
    if (s13_p(i0)) {
#  if __WORDSIZE == 32
	STI(r0, 0, i0);
#  else
	STWI(r0, 0, i0);
#  endif
    }
    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
_sti_l(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0)
{
    jit_int32_t		reg;
    if (s13_p(i0))
	STXI(r0, 0, i0);
    else {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	str_l(rn(reg), r0);
	jit_unget_reg(reg);
    }
}
#  endif

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 (s13_p(i0))
	STBI(r1, r0, i0);
    else {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	stxr_c(r0, rn(reg), r1);
	jit_unget_reg(reg);
    }
}

static void
_stxi_s(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
{
    jit_int32_t		reg;
    if (s13_p(i0))
	STHI(r1, r0, i0);
    else {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	stxr_s(r0, rn(reg), r1);
	jit_unget_reg(reg);
    }
}

static void
_stxi_i(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
{
    jit_int32_t		reg;
    if (s13_p(i0)) {
#  if __WORDSIZE == 32
	STI(r1, r0, i0);
#  else
	STWI(r1, r0, i0);
#  endif
    }
    else {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	stxr_i(r0, rn(reg), r1);
	jit_unget_reg(reg);
    }
}

#  if __WORDSIZE == 64
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 (s13_p(i0))
	STXI(r1, r0, i0);
    else {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	stxr_l(r0, rn(reg), r1);
	jit_unget_reg(reg);
    }
}
#  endif

static jit_word_t
_br(jit_state_t *_jit, jit_int32_t cc,
    jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
{
    jit_word_t		w;
    CMP(r0, r1);
    w = _jit->pc.w;
#  if __WORDSIZE == 32
    B(cc, (i0 - w) >> 2);
#  else
    BP(cc, (i0 - w) >> 2);
#  endif
    NOP();
    return (w);
}

static jit_word_t
_bw(jit_state_t *_jit, jit_int32_t cc,
    jit_word_t i0, jit_int32_t r0, jit_word_t i1)
{
    jit_word_t		w;
    jit_int32_t		reg;
    if (s13_p(i1)) {
	CMPI(r0, i1);
	w = _jit->pc.w;
#  if __WORDSIZE == 32
	B(cc, (i0 - w) >> 2);
#  else
	BP(cc, (i0 - w) >> 2);
#  endif
	NOP();
    }
    else {
	reg = jit_get_reg(jit_class_gpr|jit_class_nospill);
	movi(rn(reg), i1);
	w = br(cc, i0, r0, rn(reg));
	jit_unget_reg(reg);
    }
    return (w);
}

static jit_word_t
_b_asr(jit_state_t *_jit, jit_bool_t jif, jit_bool_t add, jit_bool_t sgn,
       jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
{
    jit_word_t		w;
    if (add)
	ADDcc(r0, r1, r0);
    else
	SUBcc(r0, r1, r0);
    w = _jit->pc.w;
#  if __WORDSIZE == 32
    B(sgn ?
      (jif ? SPARC_BVS : SPARC_BVC) :
      (jif ? SPARC_BCS : SPARC_BCC),
      (i0 - w) >> 2);
#  else
    BP(sgn ?
       (jif ? SPARC_BPVS : SPARC_BPVC) :
       (jif ? SPARC_BPCS : SPARC_BPCC),
       (i0 - w) >> 2);
#  endif
    NOP();
    return (w);
}

static jit_word_t
_b_asw(jit_state_t *_jit, jit_bool_t jif, jit_bool_t add, jit_bool_t sgn,
       jit_word_t i0, jit_int32_t r0, jit_word_t i1)
{
    jit_word_t		w;
    jit_int32_t		reg;
    if (s13_p(i1)) {
	if (add)
	    ADDIcc(r0, i1, r0);
	else
	    SUBIcc(r0, i1, r0);
	w = _jit->pc.w;
#  if __WORDSIZE == 32
	B(sgn ?
	  (jif ? SPARC_BVS : SPARC_BVC) :
	  (jif ? SPARC_BCS : SPARC_BCC),
	  (i0 - w) >> 2);
#  else
	BP(sgn ?
	   (jif ? SPARC_BPVS : SPARC_BPVC) :
	   (jif ? SPARC_BPCS : SPARC_BPCC),
	   (i0 - w) >> 2);
#  endif
	NOP();
    }
    else {
	reg = jit_get_reg(jit_class_gpr|jit_class_nospill);
	movi(rn(reg), i1);
	w = b_asr(jif, add, sgn, i0, r0, rn(reg));
	jit_unget_reg(reg);
    }
    return (w);
}

static jit_word_t
_bm_r(jit_state_t *_jit, jit_bool_t set,
      jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
{
    jit_word_t		w;
    BTST(r0, r1);
    w = _jit->pc.w;
#  if __WORDSIZE == 32
    B(set ? SPARC_BNZ : SPARC_BZ, (i0 - w) >> 2);
#  else
    BP(set ? SPARC_BPNE : SPARC_BPE, (i0 - w) >> 2);
#  endif
    NOP();
    return (w);
}

static jit_word_t
_bm_w(jit_state_t *_jit, jit_bool_t set,
      jit_word_t i0, jit_int32_t r0, jit_word_t i1)
{
    jit_word_t		w;
    jit_int32_t		reg;
    if (s13_p(i1)) {
	BTSTI(r0, i1);
	w = _jit->pc.w;
#  if __WORDSIZE == 32
	B(set ? SPARC_BNZ : SPARC_BZ, (i0 - w) >> 2);
#  else
	BP(set ? SPARC_BPNE : SPARC_BPE, (i0 - w) >> 2);
#  endif
	NOP();
    }
    else {
	reg = jit_get_reg(jit_class_gpr|jit_class_nospill);
	movi(rn(reg), i1);
	w = bm_r(set, i0, r0, rn(reg));
	jit_unget_reg(reg);
    }
    return (w);
}

static void
_jmpr(jit_state_t *_jit, jit_int32_t r0)
{
    JMPL(0, r0, 0);
    NOP();
}

static jit_word_t
_jmpi(jit_state_t *_jit, jit_word_t i0)
{
    jit_int32_t		reg;
    jit_word_t		d, w;
    w = _jit->pc.w;
    d = (i0 - w) >> 2;
    if (s22_p(d)) {
	BA(d);
	NOP();
    }
    else {
	reg = jit_get_reg(jit_class_gpr|jit_class_nospill);
	movi(rn(reg), i0);
	jmpr(rn(reg));
	jit_unget_reg(reg);
    }
    return (w);
}

static jit_word_t
_jmpi_p(jit_state_t *_jit, jit_word_t i0)
{
    jit_word_t		w;
    jit_int32_t		reg;
    reg = jit_get_reg(jit_class_gpr|jit_class_nospill);
    w = movi_p(rn(reg), i0);
    jmpr(rn(reg));
    jit_unget_reg(reg);
    return (w);
}

static void
_callr(jit_state_t *_jit, jit_int32_t r0)
{
    CALL(r0);
    NOP();
}

static jit_word_t
_calli(jit_state_t *_jit, jit_word_t i0)
{
    jit_word_t		d, w;
    w = _jit->pc.w;
    d = (i0 - w) >> 2;
    if (s30_p(d)) {
	CALLI(d);
	NOP();
    }
    else
	w = calli_p(i0);
    return (w);
}

static jit_word_t
_calli_p(jit_state_t *_jit, jit_word_t i0)
{
    jit_word_t		w;
    jit_int32_t		reg;
    reg = jit_get_reg(jit_class_gpr);
    w = movi_p(rn(reg), i0);
    callr(rn(reg));
    jit_unget_reg(reg);
    return (w);
}

#define OFF(n)		BIAS(((n) * sizeof(jit_word_t)))
static void
_prolog(jit_state_t *_jit, jit_node_t *node)
{
    jit_int32_t		reg;
    if (_jitc->function->define_frame || _jitc->function->assume_frame) {
	jit_int32_t	frame = -_jitc->function->frame;
	assert(_jitc->function->self.aoff >= frame);
	if (_jitc->function->assume_frame)
	    return;
	_jitc->function->self.aoff = frame;
    }
    if (_jitc->function->allocar)
	_jitc->function->self.aoff &= -16;
    /* align at 16 bytes boundary */
    _jitc->function->stack = ((stack_framesize +
			      _jitc->function->self.alen -
			      _jitc->function->self.aoff) + 15) & -16;
    SAVEI(_SP_REGNO, -_jitc->function->stack, _SP_REGNO);

    /* (most) other backends do not save incoming arguments, so,
     * only save locals here */
    if (jit_regset_tstbit(&_jitc->function->regset, _L0))
	stxi(OFF(0), _SP_REGNO, _L0_REGNO);
    if (jit_regset_tstbit(&_jitc->function->regset, _L1))
	stxi(OFF(1), _SP_REGNO, _L1_REGNO);
    if (jit_regset_tstbit(&_jitc->function->regset, _L2))
	stxi(OFF(2), _SP_REGNO, _L2_REGNO);
    if (jit_regset_tstbit(&_jitc->function->regset, _L3))
	stxi(OFF(3), _SP_REGNO, _L3_REGNO);
    if (jit_regset_tstbit(&_jitc->function->regset, _L4))
	stxi(OFF(4), _SP_REGNO, _L4_REGNO);
    if (jit_regset_tstbit(&_jitc->function->regset, _L5))
	stxi(OFF(5), _SP_REGNO, _L5_REGNO);
    if (jit_regset_tstbit(&_jitc->function->regset, _L6))
	stxi(OFF(6), _SP_REGNO, _L6_REGNO);
    if (jit_regset_tstbit(&_jitc->function->regset, _L7))
	stxi(OFF(7), _SP_REGNO, _L7_REGNO);

    if (_jitc->function->allocar) {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), BIAS(_jitc->function->self.aoff));
	/* Already "biased" by allocai */
	stxi_i(_jitc->function->aoffoff, _FP_REGNO, rn(reg));
	jit_unget_reg(reg);
    }

    if (_jitc->function->self.call & jit_call_varargs) {
	for (reg = _jitc->function->vagp; jit_arg_reg_p(reg); ++reg)
	    stxi(BIAS((16 + (__WORDSIZE == 32)) * sizeof(jit_word_t) +
		      reg * sizeof(jit_word_t)), _FP_REGNO, rn(_I0 + reg));
    }
}

static void
_epilog(jit_state_t *_jit, jit_node_t *node)
{
    if (_jitc->function->assume_frame)
	return;
    if (_jitc->function->allocar)
	subi(_SP_REGNO, _FP_REGNO, _jitc->function->stack);
    if (jit_regset_tstbit(&_jitc->function->regset, _L0))
	ldxi(_L0_REGNO, _SP_REGNO, _jitc->function->stack + OFF(0));
    if (jit_regset_tstbit(&_jitc->function->regset, _L1))
	ldxi(_L1_REGNO, _SP_REGNO, _jitc->function->stack + OFF(1));
    if (jit_regset_tstbit(&_jitc->function->regset, _L2))
	ldxi(_L2_REGNO, _SP_REGNO, _jitc->function->stack + OFF(2));
    if (jit_regset_tstbit(&_jitc->function->regset, _L3))
	ldxi(_L3_REGNO, _SP_REGNO, _jitc->function->stack + OFF(3));
    if (jit_regset_tstbit(&_jitc->function->regset, _L4))
	ldxi(_L4_REGNO, _SP_REGNO, _jitc->function->stack + OFF(4));
    if (jit_regset_tstbit(&_jitc->function->regset, _L5))
	ldxi(_L5_REGNO, _SP_REGNO, _jitc->function->stack + OFF(5));
    if (jit_regset_tstbit(&_jitc->function->regset, _L6))
	ldxi(_L6_REGNO, _SP_REGNO, _jitc->function->stack + OFF(6));
    if (jit_regset_tstbit(&_jitc->function->regset, _L7))
	ldxi(_L7_REGNO, _SP_REGNO, _jitc->function->stack + OFF(7));
    RESTOREI(0, 0, 0);
    RETL();
    NOP();
}

static void
_vastart(jit_state_t *_jit, jit_int32_t r0)
{
    /* Initialize stack pointer to the first stack argument. */
    if (jit_arg_reg_p(_jitc->function->vagp))
	addi(r0, _FP_REGNO, BIAS((16 + (__WORDSIZE == 32) +
				  _jitc->function->vagp) *
				 sizeof(jit_word_t)));
    else
	addi(r0, _FP_REGNO, BIAS(_jitc->function->self.size));
}

static void
_vaarg(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
{
    assert(_jitc->function->self.call & jit_call_varargs);

    /* Load argument. */
    ldr(r0, r1);

    /* Update vararg stack pointer. */
    addi(r1, r1, sizeof(jit_word_t));
}

static void
_patch_at(jit_state_t *_jit, jit_word_t instr, jit_word_t label)
{
    jit_instr_t		 i;
    union {
	jit_int32_t	*i;
	jit_word_t	 w;
    } u;

    u.w = instr;
    i.v = u.i[0];

    if (i.op.b == 0) {				/* conditional branch */
	if (i.op2.b == 2 || i.op2.b == 6) {	/* int or float condition */
	    i.disp22.b = (label - instr) >> 2;
	    u.i[0] = i.v;
	}
#  if __WORDSIZE == 64
	else if (i.op2.b == 1) {
	    i.disp19.b = (label - instr) >> 2;
	    u.i[0] = i.v;
	}
#  endif
	else if (i.op2.b == 4) {	/* movi_p */
	    /* SETHI */
	    i.imm22.b = HI((int)label);
	    u.i[0] = i.v;
	    i.v = u.i[1];
	    if (i.op.b == 2 && i.op3.b == 2) {
		/* ORI */
		i.simm13.b = LO(label);
		u.i[1] = i.v;
#  if __WORDSIZE == 64
		i.v = u.i[2];
		assert(i.op2.b == 4);
		label = (label >> 32) & 0xffffffff;
		i.imm22.b = HI((int)label);
		u.i[2] = i.v;
		i.v = u.i[3];
		assert(i.op.b == 2 && i.op3.b == 2);
		/* ORI */
		i.simm13.b = LO(label);
		u.i[3] = i.v;
#  endif
	    }
	    else
		abort();
	}
	else
	    abort();
    }
    else if (i.op.b == 1) {
	assert(s30_p((label - instr) >> 2));
	i.disp30.b = (label - instr) >> 2;
	u.i[0] = i.v;
    }
    else
	abort();
}
#endif
