* riscv files for lightening
@ 2021-01-29 19:13 Matt Wette
2021-01-30 15:14 ` Matt Wette
0 siblings, 1 reply; 2+ messages in thread
From: Matt Wette @ 2021-01-29 19:13 UTC (permalink / raw)
To: guile-devel
[-- Attachment #1: Type: text/plain, Size: 499 bytes --]
Andy,
I took a stab at porting RISC-V from lightning to lightening.
I have no riscv toolset or computer yet so these are untested.
I copied files from sv/lightning for riscv to wingo/lightening. Patch
attached.
The changes are:
1) copy lightning/jit_riscv{.c,-cpu.c-fpu.c,-sz.c,.h} to lightening
2) s/include "jit_riscv/include "riscv/
3) s/git_int/int/ and s/git_uint/uint/
4) copied the JIT_RA0, etc defines from jit_private.h to riscv.c
5) updated lightening.am
6) updated lightening.h
Matt
[-- Attachment #2: 0001-merge-riscv-files-from-lightning.patch --]
[-- Type: text/x-patch, Size: 173550 bytes --]
From d5ee171e902a3a38dd667518ff215aa3fe825185 Mon Sep 17 00:00:00 2001
From: Matt Wette <mwette@alumni.caltech.edu>
Date: Fri, 29 Jan 2021 11:07:17 -0800
Subject: [PATCH] merge riscv files from lightning
---
lightening.am | 4 +
lightening.h | 2 +
lightening/riscv-cpu.c | 2378 ++++++++++++++++++++++++++++++++++++++++
lightening/riscv-fpu.c | 1271 +++++++++++++++++++++
lightening/riscv-sz.c | 401 +++++++
lightening/riscv.c | 1621 +++++++++++++++++++++++++++
lightening/riscv.h | 147 +++
7 files changed, 5824 insertions(+)
create mode 100644 lightening/riscv-cpu.c
create mode 100644 lightening/riscv-fpu.c
create mode 100644 lightening/riscv-sz.c
create mode 100644 lightening/riscv.c
create mode 100644 lightening/riscv.h
diff --git a/lightening.am b/lightening.am
index 2c9089e..be22c31 100644
--- a/lightening.am
+++ b/lightening.am
@@ -53,6 +53,10 @@ lightening_extra_files = \
$(lightening)/lightening/ppc.c \
$(lightening)/lightening/ppc-cpu.c \
$(lightening)/lightening/ppc-fpu.c \
+ $(lightening)/lightening/riscv.c \
+ $(lightening)/lightening/riscv-cpu.c \
+ $(lightening)/lightening/riscv-fpu.c \
+ $(lightening)/lightening/riscv-sz.c \
$(lightening)/lightening/x86.c \
$(lightening)/lightening/x86-cpu.c \
$(lightening)/lightening/x86-sse.c
diff --git a/lightening.h b/lightening.h
index efa5dfd..5c02fa9 100644
--- a/lightening.h
+++ b/lightening.h
@@ -77,6 +77,8 @@ jit_same_fprs (jit_fpr_t a, jit_fpr_t b)
# include "lightening/aarch64.h"
#elif defined(__s390__) || defined(__s390x__)
# include "lightening/s390.h"
+#elif defined(__riscv__)
+# include "lightening/riscv.h"
#endif
enum jit_reloc_kind
diff --git a/lightening/riscv-cpu.c b/lightening/riscv-cpu.c
new file mode 100644
index 0000000..dbe1249
--- /dev/null
+++ b/lightening/riscv-cpu.c
@@ -0,0 +1,2378 @@
+/*
+ * Copyright (C) 2019,2021 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 _ZERO_REGNO 0
+#define _RA_REGNO 1
+#define _SP_REGNO 2
+#define _FP_REGNO 8
+typedef union {
+# define ui uint32_t
+ struct {
+ ui opcode : 7;
+ ui rd : 5;
+ ui funct3 : 3;
+ ui rs1 : 5;
+ ui rs2 : 5;
+ ui funct7 : 7;
+ } R;
+ struct {
+ ui opcode : 7;
+ ui rd : 5;
+ ui funct3 : 3;
+ ui rs1 : 5;
+ ui rs2 : 5;
+ ui funct2 : 2;
+ ui rs3 : 5;
+ } R4;
+ struct {
+ ui opcode : 7;
+ ui rd : 5;
+ ui funct3 : 3;
+ ui rs1 : 5;
+ ui imm11_0 : 12;
+ } I;
+# if __WORDSIZE == 64
+ struct {
+ ui opcode : 7;
+ ui rd : 5;
+ ui funct3 : 3;
+ ui rs1 : 5;
+ ui shamt : 6;
+ ui imm6_0 : 6;
+ } IS;
+# endif
+ struct {
+ ui opcode : 7;
+ ui imm4_0 : 5;
+ ui funct3 : 3;
+ ui rs1 : 5;
+ ui rs2 : 5;
+ ui imm11_5 : 7;
+ } S;
+ struct {
+ ui opcode : 7;
+ ui imm11 : 1;
+ ui imm4_1 : 4;
+ ui funct3 : 3;
+ ui rs1 : 5;
+ ui rs2 : 5;
+ ui imm10_5 : 6;
+ ui imm12 : 1;
+ } B;
+ struct {
+ ui opcode : 7;
+ ui rd : 5;
+ ui imm12_31 : 20;
+ } U;
+ struct {
+ ui opcode : 7;
+ ui rd : 5;
+ ui imm19_12 : 8;
+ ui imm11 : 1;
+ ui imm10_1 : 10;
+ ui imm20 : 1;
+ } J;
+ int32_t w;
+# undef ui
+} instr_t;
+# define ii(i) *_jit->pc.ui++ = i
+/* FIXME could jit_rewind_prolog() to only use extra 64 bytes
+ * if a variadic jit function that have variadic arguments in
+ * registers */
+# define stack_framesize (200 + 64)
+# define ldr(r0, r1) ldr_l(r0, r1)
+# define ldi(r0, im) ldi_l(r0, im)
+# define ldxr(r0, r1, r2) ldxr_l(r0, r1, r2)
+# define ldxi(r0, r1, im) ldxi_l(r0, r1, im)
+# define str(r0, r1) str_l(r0, r1)
+# define sti(im, r0) sti_l(im, r0)
+# define stxr(r0, r1, r2) stxr_l(r0, r1, r2)
+# define stxi(im, r0, r1) stxi_l(im, r0, r1)
+# define simm6_p(im) ((im) <= 31 && (im) >= -32)
+# define simm12_p(im) ((im) <= 2047 && (im) >= -2048)
+# define simm20_p(im) ((im) <= 524287 && (im) >= -524288)
+# define simm32_p(im) ((im) <= 2147483647LL && (im) >= -2147483648LL)
+
+/*
+ * RV32I Base Instruction Set
+ */
+# define LUI(rd, imm) Utype(55, rd, imm)
+# define AUIPC(rd, imm) Utype(23, rd, imm)
+# define JAL(rd, imm) Jtype(111, rd, imm)
+# define JALR(rd, rs1, imm) Itype(103, rd, 0, rs1, imm)
+# define BEQ(rs1, rs2, imm) Btype(99, 0, rs1, rs2, imm)
+# define BNE(rs1, rs2, imm) Btype(99, 1, rs1, rs2, imm)
+# define BLT(rs1, rs2, imm) Btype(99, 4, rs1, rs2, imm)
+# define BGE(rs1, rs2, imm) Btype(99, 5, rs1, rs2, imm)
+# define BLTU(rs1, rs2, imm) Btype(99, 6, rs1, rs2, imm)
+# define BGEU(rs1, rs2, imm) Btype(99, 7, rs1, rs2, imm)
+# define LB(rd, rs1, imm) Itype(3, rd, 0, rs1, imm)
+# define LH(rd, rs1, imm) Itype(3, rd, 1, rs1, imm)
+# define LW(rd, rs1, imm) Itype(3, rd, 2, rs1, imm)
+# define LBU(rd, rs1, imm) Itype(3, rd, 4, rs1, imm)
+# define LHU(rd, rs1, imm) Itype(3, rd, 5, rs1, imm)
+# define SB(rs1, rs2, imm) Stype(35, 0, rs1, rs2, imm)
+# define SH(rs1, rs2, imm) Stype(35, 1, rs1, rs2, imm)
+# define SW(rs1, rs2, imm) Stype(35, 2, rs1, rs2, imm)
+# define ADDI(rd, rs1, imm) Itype(19, rd, 0, rs1, imm)
+# define SLTI(rd, rs1, imm) Itype(19, rd, 2, rs1, imm)
+# define SLTIU(rd, rs1, imm) Itype(19, rd, 3, rs1, imm)
+# define XORI(rd, rs1, imm) Itype(19, rd, 4, rs1, imm)
+# define ORI(rd, rs1, imm) Itype(19, rd, 6, rs1, imm)
+# define ANDI(rd, rs1, imm) Itype(19, rd, 7, rs1, imm)
+# if __WORDSIZE == 32
+# define SLLI(rd, rs1, imm) Rtype(19, rd, 1, rs1, imm, 0)
+# define SRLI(rd, rs1, imm) Rtype(19, rd, 5, rs1, imm, 0)
+# define SRAI(rd, rs1, imm) Rtype(19, rd, 5, rs1, imm, 32)
+# endif
+# define ADD(rd, rs1, rs2) Rtype(51, rd, 0, rs1, rs2, 0)
+# define SUB(rd, rs1, rs2) Rtype(51, rd, 0, rs1, rs2, 32)
+# define SLL(rd, rs1, rs2) Rtype(51, rd, 1, rs1, rs2, 0)
+# define SLT(rd, rs1, rs2) Rtype(51, rd, 2, rs1, rs2, 0)
+# define SLTU(rd, rs1, rs2) Rtype(51, rd, 3, rs1, rs2, 0)
+# define XOR(rd, rs1, rs2) Rtype(51, rd, 4, rs1, rs2, 0)
+# define SRL(rd, rs1, rs2) Rtype(51, rd, 5, rs1, rs2, 0)
+# define SRA(rd, rs1, rs2) Rtype(51, rd, 5, rs1, rs2, 32)
+# define OR(rd, rs1, rs2) Rtype(51, rd, 6, rs1, rs2, 0)
+# define AND(rd, rs1, rs2) Rtype(51, rd, 7, rs1, rs2, 0)
+# define FENCE(imm) Itype(15, 0, 0, 0, im)
+# define FENCE_I(imm) Itype(15, 0, 1, 0, im)
+# define ECALL() Itype(115, 0, 0, 0, 0)
+# define EBREAK() Itype(115, 0, 0, 0, 1)
+# define CSRRW(rd, rs1, csr) Itype(115, rd, 1, rs1, csr)
+# define CSRRS(rd, rs1, csr) Itype(115, rd, 2, rs1, csr)
+# define CSRRC(rd, rs1, csr) Itype(115, rd, 3, rs1, csr)
+# define CSRRWI(rd, zimm, csr) Itype(115, rd, 5, zimm, csr)
+# define CSRRSI(rd, zimm, csr) Itype(115, rd, 6, zimm, csr)
+# define CSRRCI(rd, zimm, csr) Itype(115, rd, 7, zimm, csr)
+/*
+ * RV64I Base Instruction Set (in addition to RV32I)
+ */
+# define LWU(rd, rs1, imm) Itype(3, rd, 6, rs1, imm)
+# define LD(rd, rs1, imm) Itype(3, rd, 3, rs1, imm)
+# define SD(rs1, rs2, imm) Stype(35, 3, rs1, rs2, imm)
+# if __WORDSIZE == 64
+# define SLLI(rd, rs1, sh) IStype(19, rd, 1, rs1, sh, 0)
+# define SRLI(rd, rs1, sh) IStype(19, rd, 5, rs1, sh, 0)
+# define SRAI(rd, rs1, sh) IStype(19, rd, 5, rs1, sh, 16)
+# endif
+# define ADDIW(rd, rs1, imm) Itype(27, rd, 0, rs1, imm)
+# define SLLIW(rd, rs1, imm) Rtype(27, rd, 1, rs1, imm, 0)
+# define SRLIW(rd, rs1, imm) Rtype(27, rd, 3, rs1, imm, 0)
+# define SRAIW(rd, rs1, imm) Rtype(27, rd, 3, rs1, imm, 32)
+# define ADDW(rd, rs1, imm) Rtype(59, rd, 0, rs1, imm, 0)
+# define SUBW(rd, rs1, imm) Rtype(59, rd, 0, rs1, imm, 32)
+# define SLLW(rd, rs1, imm) Rtype(59, rd, 1, rs1, imm, 0)
+# define SRLW(rd, rs1, imm) Rtype(59, rd, 5, rs1, imm, 0)
+# define SRAW(rd, rs1, imm) Rtype(59, rd, 5, rs1, imm, 32)
+/*
+ * RV32M Standard Extension
+ */
+# define MUL(rd, rs1, rs2) Rtype(51, rd, 0, rs1, rs2, 1)
+# define MULH(rd, rs1, rs2) Rtype(51, rd, 1, rs1, rs2, 1)
+# define MULHSU(rd, rs1, rs2) Rtype(51, rd, 2, rs1, rs2, 1)
+# define MULHU(rd, rs1, rs2) Rtype(51, rd, 3, rs1, rs2, 1)
+# define DIV(rd, rs1, rs2) Rtype(51, rd, 4, rs1, rs2, 1)
+# define DIVU(rd, rs1, rs2) Rtype(51, rd, 5, rs1, rs2, 1)
+# define REM(rd, rs1, rs2) Rtype(51, rd, 6, rs1, rs2, 1)
+# define REMU(rd, rs1, rs2) Rtype(51, rd, 7, rs1, rs2, 1)
+/*
+ * RV64M Standard Extension (in addition to RV32M)
+ */
+# define MULW(rd, rs1, rs2) Rtype(59, rd, 0, rs1, rs2, 1)
+# define DIVW(rd, rs1, rs2) Rtype(59, rd, 4, rs1, rs2, 1)
+# define DIVUW(rd, rs1, rs2) Rtype(59, rd, 5, rs1, rs2, 1)
+# define REMW(rd, rs1, rs2) Rtype(59, rd, 6, rs1, rs2, 1)
+# define REMUW(rd, rs1, rs2) Rtype(59, rd, 7, rs1, rs2, 1)
+/*
+ * RV32A Standard Extension
+ */
+# define LR_W(rd, rs1) R4type(47, rd, 2, rs1, 0, 0, 2)
+# define SC_W(rd, rs1, rs2) R4type(47, rd, 2, rs1, rs2, 0, 3)
+# define AMOSWAP_W(rd, rs1, rs2) R4type(47, rd, 2, rs1, rs2, 0, 1)
+# define AMOADD_W(rd, rs1, rs2) R4type(47, rd, 2, rs1, rs2, 0, 0)
+# define AMOXOR_W(rd, rs1, rs2) R4type(47, rd, 2, rs1, rs2, 0, 4)
+# define AMOAND_W(rd, rs1, rs2) R4type(47, rd, 2, rs1, rs2, 0, 12)
+# define AMOOR_W(rd, rs1, rs2) R4type(47, rd, 2, rs1, rs2, 0, 8)
+# define AMOMIN_W(rd, rs1, rs2) R4type(47, rd, 2, rs1, rs2, 0, 16)
+# define AMOMAX_W(rd, rs1, rs2) R4type(47, rd, 2, rs1, rs2, 0, 20)
+# define AMOMINU_W(rd, rs1, rs2) R4type(47, rd, 2, rs1, rs2, 0, 24)
+# define AMOMAXU_W(rd, rs1, rs2) R4type(47, rd, 2, rs1, rs2, 0, 28)
+/*
+ * RV64A Standard Extension (in addition to RV32A)
+ */
+# define LR_D(rd, rs1) R4type(47, rd, 3, rs1, 0, 0, 2)
+# define SC_D(rd, rs1, rs2) R4type(47, rd, 3, rs1, rs2, 0, 3)
+# define AMOSWAP_D(rd, rs1, rs2) R4type(47, rd, 3, rs1, rs2, 0, 1)
+# define AMOADD_D(rd, rs1, rs2) R4type(47, rd, 3, rs1, rs2, 0, 0)
+# define AMOXOR_D(rd, rs1, rs2) R4type(47, rd, 3, rs1, rs2, 0, 4)
+# define AMOAND_D(rd, rs1, rs2) R4type(47, rd, 3, rs1, rs2, 0, 12)
+# define AMOOR_D(rd, rs1, rs2) R4type(47, rd, 3, rs1, rs2, 0, 8)
+# define AMOMIN_D(rd, rs1, rs2) R4type(47, rd, 3, rs1, rs2, 0, 16)
+# define AMOMAX_D(rd, rs1, rs2) R4type(47, rd, 3, rs1, rs2, 0, 20)
+# define AMOMINU_D(rd, rs1, rs2) R4type(47, rd, 3, rs1, rs2, 0, 24)
+# define AMOMAXU_D(rd, rs1, rs2) R4type(47, rd, 3, rs1, rs2, 0, 28)
+/*
+ * Pseudo Instructions
+ */
+# define NOP() ADDI(_ZERO_REGNO, _ZERO_REGNO, 0)
+# define MV(r0, r1) ADDI(r0, r1, 0)
+# define NOT(r0, r1) XORI(r0, r1, -1)
+# define NEG(r0, r1) SUB(r0, _ZERO_REGNO, r1)
+# define NEGW(r0, r1) SUBW(r0, _ZERO_REGNO, r1)
+# define SEXT_W(r0, r1) ADDIW(r0, r1, 0)
+# define RET() JALR(0, 1, 0)
+
+/*
+ * Enconding functions
+ */
+# define Rtype(op, rd, fct, rs1, rs2, fct2) \
+ _Rtype(_jit, op, rd, fct, rs1, rs2, fct2)
+static void _Rtype(jit_state_t*, int32_t, int32_t,
+ int32_t, int32_t, int32_t, int32_t);
+# define R4type(op, rd, fct, rs1,rs2,fct2,rs3) \
+ _R4type(_jit, op, rd, fct, rs1, rs2, fct2, rs3)
+static void _R4type(jit_state_t*, int32_t, int32_t, int32_t,
+ int32_t, int32_t, int32_t, int32_t);
+# define Itype(op, rd, fct, rs1, imm) \
+ _Itype(_jit, op, rd, fct, rs1, imm)
+static void _Itype(jit_state_t*, int32_t, int32_t,
+ int32_t, int32_t, int32_t);
+# if __WORDSIZE == 64
+# define IStype(op, rd, fct, rs1, sh, imm) \
+ _IStype(_jit, op, rd, fct, rs1, sh, imm)
+static void _IStype(jit_state_t*, int32_t, int32_t,
+ int32_t, int32_t, int32_t,int32_t);
+# endif
+# define Stype(op, fct, rs1, rs2, imm) \
+ _Stype(_jit, op, fct, rs1, rs2, imm)
+static void _Stype(jit_state_t*, int32_t, int32_t,
+ int32_t, int32_t, int32_t);
+# define Btype(op, fct, rs1, rs2, imm) \
+ _Btype(_jit, op, fct, rs1, rs2, imm)
+static void _Btype(jit_state_t*, int32_t, int32_t,
+ int32_t, int32_t, int32_t);
+# define Utype(op, rd, imm) _Utype(_jit, op, rd, imm)
+static void _Utype(jit_state_t*, int32_t, int32_t, int32_t);
+# define Jtype(op, rd, imm) _Jtype(_jit, op, rd, imm)
+static void _Jtype(jit_state_t*, int32_t, int32_t, int32_t);
+/*
+ * Lightning instructions
+ */
+# define nop(im) _nop(_jit, im)
+static void _nop(jit_state_t*, int32_t);
+# define addr(r0, r1, r2) ADD(r0, r1, r2)
+# define addi(r0, r1, im) _addi(_jit, r0, r1, im)
+static void _addi(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define addcr(r0, r1, r2) _addcr(_jit, r0, r1, r2)
+static void _addcr(jit_state_t*,int32_t,int32_t,int32_t);
+# define addci(r0, r1, im) _addci(_jit, r0, r1, im)
+static void _addci(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define addxr(r0, r1, r2) _addxr(_jit, r0, r1, r2)
+static void _addxr(jit_state_t*,int32_t,int32_t,int32_t);
+# define addxi(r0, r1, im) _addxi(_jit, r0, r1, im)
+static void _addxi(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define subr(r0, r1, r2) SUB(r0, r1, r2)
+# define subi(r0, r1, im) _subi(_jit, r0, r1, im)
+static void _subi(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define subcr(r0, r1, r2) _subcr(_jit, r0, r1, r2)
+static void _subcr(jit_state_t*,int32_t,int32_t,int32_t);
+# define subci(r0, r1, im) _subci(_jit, r0, r1, im)
+static void _subci(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define subxr(r0, r1, r2) _subxr(_jit, r0, r1, r2)
+static void _subxr(jit_state_t*,int32_t,int32_t,int32_t);
+# define subxi(r0, r1, im) _subxi(_jit, r0, r1, im)
+static void _subxi(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define rsbi(r0, r1, im) _rsbi(_jit, r0, r1, im)
+static void _rsbi(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define mulr(r0, r1, r2) MUL(r0, r1, r2)
+# define muli(r0, r1, im) _muli(_jit, r0, r1, im)
+static void _muli(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define divr(r0, r1, r2) DIV(r0, r1, r2)
+# define divi(r0, r1, im) _divi(_jit, r0, r1, im)
+static void _divi(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define divr_u(r0, r1, r2) DIVU(r0, r1, r2)
+# define divi_u(r0, r1, im) _divi_u(_jit, r0, r1, im)
+static void _divi_u(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define remr(r0, r1, r2) REM(r0, r1, r2)
+# define remi(r0, r1, im) _remi(_jit, r0, r1, im)
+static void _remi(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define remr_u(r0, r1, r2) REMU(r0, r1, r2)
+# define remi_u(r0, r1, im) _remi_u(_jit, r0, r1, im)
+static void _remi_u(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define qmulr(r0, r1, r2, r3) _qmulr(_jit,r0,r1,r2,r3)
+static void _qmulr(jit_state_t*,int32_t,int32_t,int32_t,int32_t);
+# define qmuli(r0, r1, r2, i0) _qmuli(_jit,r0,r1,r2,i0)
+static void _qmuli(jit_state_t*,int32_t,int32_t,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*,int32_t,int32_t,int32_t,int32_t);
+# define qmuli_u(r0, r1, r2, i0) _qmuli_u(_jit,r0,r1,r2,i0)
+static void _qmuli_u(jit_state_t*,int32_t,int32_t,int32_t,jit_word_t);
+static void _iqdivr(jit_state_t*,jit_bool_t,
+ int32_t,int32_t,int32_t,int32_t);
+# define qdivr(r0,r1,r2,r3) _iqdivr(_jit,1,r0,r1,r2,r3)
+# define qdivr_u(r0,r1,r2,r3) _iqdivr(_jit,0,r0,r1,r2,r3)
+static void _iqdivr(jit_state_t*,jit_bool_t,
+ int32_t,int32_t,int32_t,int32_t);
+# define qdivi(r0,r1,r2,i0) _qdivi(_jit,r0,r1,r2,i0)
+static void _qdivi(jit_state_t*,int32_t,
+ int32_t,int32_t,jit_word_t);
+# define qdivi_u(r0,r1,r2,i0) _qdivi_u(_jit,r0,r1,r2,i0)
+static void _qdivi_u(jit_state_t*,int32_t,
+ int32_t,int32_t,jit_word_t);
+# define lshr(r0, r1, r2) SLL(r0, r1, r2)
+# define lshi(r0, r1, im) _lshi(_jit, r0, r1, im)
+static void _lshi(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define rshr(r0, r1, r2) SRA(r0, r1, r2)
+# define rshi(r0, r1, im) _rshi(_jit, r0, r1, im)
+static void _rshi(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define rshr_u(r0, r1, r2) SRL(r0, r1, r2)
+# define rshi_u(r0, r1, im) _rshi_u(_jit, r0, r1, im)
+static void _rshi_u(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define negr(r0, r1) NEG(r0, r1)
+# define comr(r0, r1) NOT(r0, r1)
+# define andr(r0, r1, r2) AND(r0, r1, r2)
+# define andi(r0, r1, im) _andi(_jit, r0, r1, im)
+static void _andi(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define orr(r0, r1, r2) OR(r0, r1, r2)
+# define ori(r0, r1, im) _ori(_jit, r0, r1, im)
+static void _ori(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define xorr(r0, r1, r2) XOR(r0, r1, r2)
+# define xori(r0, r1, im) _xori(_jit, r0, r1, im)
+static void _xori(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define ldr_c(r0, r1) LB(r0, r1, 0)
+# define ldi_c(r0, im) _ldi_c(_jit, r0, im)
+static void _ldi_c(jit_state_t*,int32_t,jit_word_t);
+# define ldr_uc(r0, r1) LBU(r0, r1, 0)
+# define ldi_uc(r0, im) _ldi_uc(_jit, r0, im)
+static void _ldi_uc(jit_state_t*,int32_t,jit_word_t);
+# define ldr_s(r0, r1) LH(r0, r1, 0)
+# define ldi_s(r0, im) _ldi_s(_jit, r0, im)
+static void _ldi_s(jit_state_t*,int32_t,jit_word_t);
+# define ldr_us(r0, r1) LHU(r0, r1, 0)
+# define ldi_us(r0, im) _ldi_us(_jit, r0, im)
+static void _ldi_us(jit_state_t*,int32_t,jit_word_t);
+# define ldr_i(r0, r1) LW(r0, r1, 0)
+# define ldi_i(r0, im) _ldi_i(_jit, r0, im)
+static void _ldi_i(jit_state_t*,int32_t,jit_word_t);
+# define ldr_ui(r0, r1) LWU(r0, r1, 0)
+# define ldi_ui(r0, im) _ldi_ui(_jit, r0, im)
+static void _ldi_ui(jit_state_t*,int32_t,jit_word_t);
+# define ldr_l(r0, r1) LD(r0, r1, 0)
+# define ldi_l(r0, im) _ldi_l(_jit, r0, im)
+static void _ldi_l(jit_state_t*,int32_t,jit_word_t);
+# define ldxr_c(r0, r1, r2) _ldxr_c(_jit, r0, r1, r2)
+static void _ldxr_c(jit_state_t*,int32_t,int32_t,int32_t);
+# define ldxi_c(r0, r1, im) _ldxi_c(_jit, r0, r1, im)
+static void _ldxi_c(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define ldxr_uc(r0, r1, r2) _ldxr_uc(_jit, r0, r1, r2)
+static void _ldxr_uc(jit_state_t*,int32_t,int32_t,int32_t);
+# define ldxi_uc(r0, r1, im) _ldxi_uc(_jit, r0, r1, im)
+static void _ldxi_uc(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define ldxr_s(r0, r1, r2) _ldxr_s(_jit, r0, r1, r2)
+static void _ldxr_s(jit_state_t*,int32_t,int32_t,int32_t);
+# define ldxi_s(r0, r1, im) _ldxi_s(_jit, r0, r1, im)
+static void _ldxi_s(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define ldxr_us(r0, r1, r2) _ldxr_us(_jit, r0, r1, r2)
+static void _ldxr_us(jit_state_t*,int32_t,int32_t,int32_t);
+# define ldxi_us(r0, r1, im) _ldxi_us(_jit, r0, r1, im)
+static void _ldxi_us(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define ldxr_i(r0, r1, r2) _ldxr_i(_jit, r0, r1, r2)
+static void _ldxr_i(jit_state_t*,int32_t,int32_t,int32_t);
+# define ldxi_i(r0, r1, im) _ldxi_i(_jit, r0, r1, im)
+static void _ldxi_i(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define ldxr_ui(r0, r1, r2) _ldxr_ui(_jit, r0, r1, r2)
+static void _ldxr_ui(jit_state_t*,int32_t,int32_t,int32_t);
+# define ldxi_ui(r0, r1, im) _ldxi_ui(_jit, r0, r1, im)
+static void _ldxi_ui(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define ldxr_l(r0, r1, r2) _ldxr_l(_jit, r0, r1, r2)
+static void _ldxr_l(jit_state_t*,int32_t,int32_t,int32_t);
+# define ldxi_l(r0, r1, im) _ldxi_l(_jit, r0, r1, im)
+static void _ldxi_l(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define str_c(r0, r1) SB(r0, r1, 0)
+# define sti_c(im, r0) _sti_c(_jit, im, r0)
+static void _sti_c(jit_state_t*,jit_word_t,int32_t);
+# define str_s(r0, r1) SH(r0, r1, 0)
+# define sti_s(im, r0) _sti_s(_jit, im, r0)
+static void _sti_s(jit_state_t*,jit_word_t,int32_t);
+# define str_i(r0, r1) SW(r0, r1, 0)
+# define sti_i(im, r0) _sti_i(_jit, im, r0)
+static void _sti_i(jit_state_t*,jit_word_t,int32_t);
+# define str_l(r0, r1) SD(r0, r1, 0)
+# define sti_l(im, r0) _sti_l(_jit, im, r0)
+static void _sti_l(jit_state_t*,jit_word_t,int32_t);
+# define stxr_c(r0, r1, r2) _stxr_c(_jit, r0, r1, r2)
+static void _stxr_c(jit_state_t*,int32_t,int32_t,int32_t);
+# define stxi_c(i0, r0, r1) _stxi_c(_jit, i0, r0, r1)
+static void _stxi_c(jit_state_t*,jit_word_t,int32_t,int32_t);
+# define stxr_s(r0, r1, r2) _stxr_s(_jit, r0, r1, r2)
+static void _stxr_s(jit_state_t*,int32_t,int32_t,int32_t);
+# define stxi_s(i0, r0, r1) _stxi_s(_jit, i0, r0, r1)
+static void _stxi_s(jit_state_t*,jit_word_t,int32_t,int32_t);
+# define stxr_i(r0, r1, r2) _stxr_i(_jit, r0, r1, r2)
+static void _stxr_i(jit_state_t*,int32_t,int32_t,int32_t);
+# define stxi_i(i0, r0, r1) _stxi_i(_jit, i0, r0, r1)
+static void _stxi_i(jit_state_t*,jit_word_t,int32_t,int32_t);
+# define stxr_l(r0, r1, r2) _stxr_l(_jit, r0, r1, r2)
+static void _stxr_l(jit_state_t*,int32_t,int32_t,int32_t);
+# define stxi_l(i0, r0, r1) _stxi_l(_jit, i0, r0, r1)
+static void _stxi_l(jit_state_t*,jit_word_t,int32_t,int32_t);
+# define htonr_us(r0, r1) _htonr_us(_jit, r0, r1)
+static void _htonr_us(jit_state_t*,int32_t,int32_t);
+# define htonr_ui(r0, r1) _htonr_ui(_jit, r0, r1)
+static void _htonr_ui(jit_state_t*,int32_t,int32_t);
+# define htonr_ul(r0, r1) _htonr_ul(_jit, r0, r1)
+static void _htonr_ul(jit_state_t*,int32_t,int32_t);
+# define extr_c(r0, r1) _extr_c(_jit, r0, r1)
+static void _extr_c(jit_state_t*,int32_t,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*,int32_t,int32_t);
+# define extr_us(r0, r1) _extr_us(_jit, r0, r1)
+static void _extr_us(jit_state_t*,int32_t,int32_t);
+# define extr_i(r0, r1) SEXT_W(r0, r1)
+# define extr_ui(r0, r1) _extr_ui(_jit, r0, r1)
+static void _extr_ui(jit_state_t*,int32_t,int32_t);
+# define movr(r0, r1) MV(r0, r1)
+# define movi(r0, im) _movi(_jit, r0, im)
+static void _movi(jit_state_t*,int32_t,jit_word_t);
+# define movi_p(r0, im) _movi_p(_jit, r0, im)
+static jit_word_t _movi_p(jit_state_t*,int32_t,jit_word_t);
+# define ltr(r0, r1, r2) SLT(r0, r1, r2)
+# define lti(r0, r1, im) _lti(_jit, r0, r1, im)
+static void _lti(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define ltr_u(r0, r1, r2) SLTU(r0, r1, r2)
+# define lti_u(r0, r1, im) _lti_u(_jit, r0, r1, im)
+static void _lti_u(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define ler(r0, r1, r2) _ler(_jit, r0, r1, r2)
+static void _ler(jit_state_t*,int32_t,int32_t,int32_t);
+# define lei(r0, r1, im) _lei(_jit, r0, r1, im)
+static void _lei(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define ler_u(r0, r1, r2) _ler_u(_jit, r0, r1, r2)
+static void _ler_u(jit_state_t*,int32_t,int32_t,int32_t);
+# define lei_u(r0, r1, im) _lei_u(_jit, r0, r1, im)
+static void _lei_u(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define eqr(r0, r1, r2) _eqr(_jit, r0, r1, r2)
+static void _eqr(jit_state_t*,int32_t,int32_t,int32_t);
+# define eqi(r0, r1, im) _eqi(_jit, r0, r1, im)
+static void _eqi(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define ger(r0, r1, r2) _ger(_jit, r0, r1, r2)
+static void _ger(jit_state_t*,int32_t,int32_t,int32_t);
+# define gei(r0, r1, r2) _gei(_jit, r0, r1, r2)
+static void _gei(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define ger_u(r0, r1, r2) _ger_u(_jit, r0, r1, r2)
+static void _ger_u(jit_state_t*,int32_t,int32_t,int32_t);
+# define gei_u(r0, r1, im) _gei_u(_jit, r0, r1, im)
+static void _gei_u(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define gtr(r0, r1, r2) SLT(r0, r2, r1)
+# define gti(r0, r1, im) _gti(_jit, r0, r1, im)
+static void _gti(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define gtr_u(r0, r1, r2) SLTU(r0, r2, r1)
+# define gti_u(r0, r1, im) _gti_u(_jit, r0, r1, im)
+static void _gti_u(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define ner(r0, r1, r2) _ner(_jit, r0, r1, r2)
+static void _ner(jit_state_t*,int32_t,int32_t,int32_t);
+# define nei(r0, r1, im) _nei(_jit, r0, r1, im)
+static void _nei(jit_state_t*,int32_t,int32_t,jit_word_t);
+# define bltr(br, r0, r1) _bltr(_jit, br, r0, r1)
+static jit_word_t _bltr(jit_state_t*,jit_word_t,int32_t,int32_t);
+# define blti(br, r0, im) _blti(_jit, br, r0, im)
+static jit_word_t _blti(jit_state_t*,jit_word_t,int32_t,jit_word_t);
+# define bltr_u(br, r0, r1) _bltr_u(_jit, br, r0, r1)
+static jit_word_t _bltr_u(jit_state_t*,jit_word_t,int32_t,int32_t);
+# define blti_u(br, r0, im) _blti_u(_jit, br, r0, im)
+static jit_word_t _blti_u(jit_state_t*,jit_word_t,int32_t,jit_word_t);
+# define bler(br, r0, r1) _bler(_jit, br, r0, r1)
+static jit_word_t _bler(jit_state_t*,jit_word_t,int32_t,int32_t);
+# define blei(br, r0, im) _blei(_jit, br, r0, im)
+static jit_word_t _blei(jit_state_t*,jit_word_t,int32_t,jit_word_t);
+# define bler_u(br, r0, r1) _bler_u(_jit, br, r0, r1)
+static jit_word_t _bler_u(jit_state_t*,jit_word_t,int32_t,int32_t);
+# define blei_u(br, r0, im) _blei_u(_jit, br, r0, im)
+static jit_word_t _blei_u(jit_state_t*,jit_word_t,int32_t,jit_word_t);
+# define beqr(br, r0, r1) _beqr(_jit, br, r0, r1)
+static jit_word_t _beqr(jit_state_t*,jit_word_t,int32_t,int32_t);
+# define beqi(br, r0, im) _beqi(_jit, br, r0, im)
+static jit_word_t _beqi(jit_state_t*,jit_word_t,int32_t,jit_word_t);
+# define bger(br, r0, r1) _bger(_jit, br, r0, r1)
+static jit_word_t _bger(jit_state_t*,jit_word_t,int32_t,int32_t);
+# define bgei(br, r0, im) _bgei(_jit, br, r0, im)
+static jit_word_t _bgei(jit_state_t*,jit_word_t,int32_t,jit_word_t);
+# define bger_u(br, r0, r1) _bger_u(_jit, br, r0, r1)
+static jit_word_t _bger_u(jit_state_t*,jit_word_t,int32_t,int32_t);
+# define bgei_u(br, r0, im) _bgei_u(_jit, br, r0, im)
+static jit_word_t _bgei_u(jit_state_t*,jit_word_t,int32_t,jit_word_t);
+# define bgtr(br, r0, r1) _bgtr(_jit, br, r0, r1)
+static jit_word_t _bgtr(jit_state_t*,jit_word_t,int32_t,int32_t);
+# define bgti(br, r0, im) _bgti(_jit, br, r0, im)
+static jit_word_t _bgti(jit_state_t*,jit_word_t,int32_t,jit_word_t);
+# define bgtr_u(br, r0, r1) _bgtr_u(_jit, br, r0, r1)
+static jit_word_t _bgtr_u(jit_state_t*,jit_word_t,int32_t,int32_t);
+# define bgti_u(br, r0, im) _bgti_u(_jit, br, r0, im)
+static jit_word_t _bgti_u(jit_state_t*,jit_word_t,int32_t,jit_word_t);
+# define bner(br, r0, r1) _bner(_jit, br, r0, r1)
+static jit_word_t _bner(jit_state_t*,jit_word_t,int32_t,int32_t);
+# define bnei(br, r0, im) _bnei(_jit, br, r0, im)
+static jit_word_t _bnei(jit_state_t*,jit_word_t,int32_t,jit_word_t);
+# define boaddr(br, r0, r1) _boaddr(_jit, br, r0, r1)
+# define boaddi(br, r0, im) _boaddi(_jit, br, r0, im)
+static jit_word_t _boaddr(jit_state_t*,jit_word_t,int32_t,int32_t);
+static jit_word_t _boaddi(jit_state_t*,jit_word_t,int32_t,jit_word_t);
+# define boaddr_u(br, r0, r1) _boaddr_u(_jit, br, r0, r1)
+# define boaddi_u(br, r0, im) _boaddi_u(_jit, br, r0, im)
+static jit_word_t _boaddr_u(jit_state_t*,jit_word_t,int32_t,int32_t);
+static jit_word_t _boaddi_u(jit_state_t*,jit_word_t,int32_t,jit_word_t);
+# define bxaddr(br, r0, r1) _bxaddr(_jit, br, r0, r1)
+# define bxaddi(br, r0, im) _bxaddi(_jit, br, r0, im)
+static jit_word_t _bxaddr(jit_state_t*,jit_word_t,int32_t,int32_t);
+static jit_word_t _bxaddi(jit_state_t*,jit_word_t,int32_t,jit_word_t);
+# define bxaddr_u(br, r0, r1) _bxaddr_u(_jit, br, r0, r1)
+# define bxaddi_u(br, r0, im) _bxaddi_u(_jit, br, r0, im)
+static jit_word_t _bxaddr_u(jit_state_t*,jit_word_t,int32_t,int32_t);
+static jit_word_t _bxaddi_u(jit_state_t*,jit_word_t,int32_t,jit_word_t);
+# define bosubr(br, r0, r1) _bosubr(_jit, br, r0, r1)
+# define bosubi(br, r0, im) _bosubi(_jit, br, r0, im)
+static jit_word_t _bosubr(jit_state_t*,jit_word_t,int32_t,int32_t);
+static jit_word_t _bosubi(jit_state_t*,jit_word_t,int32_t,jit_word_t);
+# define bosubr_u(br, r0, r1) _bosubr_u(_jit, br, r0, r1)
+# define bosubi_u(br, r0, im) _bosubi_u(_jit, br, r0, im)
+static jit_word_t _bosubr_u(jit_state_t*,jit_word_t,int32_t,int32_t);
+static jit_word_t _bosubi_u(jit_state_t*,jit_word_t,int32_t,jit_word_t);
+# define bxsubr(br, r0, r1) _bxsubr(_jit, br, r0, r1)
+# define bxsubi(br, r0, im) _bxsubi(_jit, br, r0, im)
+static jit_word_t _bxsubr(jit_state_t*,jit_word_t,int32_t,int32_t);
+static jit_word_t _bxsubi(jit_state_t*,jit_word_t,int32_t,jit_word_t);
+# define bxsubr_u(br, r0, r1) _bxsubr_u(_jit, br, r0, r1)
+# define bxsubi_u(br, r0, im) _bxsubi_u(_jit, br, r0, im)
+static jit_word_t _bxsubr_u(jit_state_t*,jit_word_t,int32_t,int32_t);
+static jit_word_t _bxsubi_u(jit_state_t*,jit_word_t,int32_t,jit_word_t);
+# define bmsr(br, r0, r1) _bmsr(_jit, br, r0, r1)
+# define bmsi(br, r0, im) _bmsi(_jit, br, r0, im)
+static jit_word_t _bmsr(jit_state_t*,jit_word_t,int32_t,int32_t);
+static jit_word_t _bmsi(jit_state_t*,jit_word_t,int32_t,jit_word_t);
+# define bmcr(br, r0, r1) _bmcr(_jit, br, r0, r1)
+# define bmci(br, r0, im) _bmci(_jit, br, r0, im)
+static jit_word_t _bmcr(jit_state_t*,jit_word_t,int32_t,int32_t);
+static jit_word_t _bmci(jit_state_t*,jit_word_t,int32_t,jit_word_t);
+# define jmpr(r0) JALR(_ZERO_REGNO, r0, 0)
+# define jmpi(im) _jmpi(_jit, im)
+static void _jmpi(jit_state_t*,jit_word_t);
+# define jmpi_p(im) _jmpi_p(_jit, im)
+static jit_word_t _jmpi_p(jit_state_t*,jit_word_t);
+# define callr(r0) JALR(_RA_REGNO, r0, 0)
+# define calli(im) _calli(_jit, im)
+static void _calli(jit_state_t*,jit_word_t);
+# define calli_p(im) _calli_p(_jit, im)
+static jit_word_t _calli_p(jit_state_t*,jit_word_t);
+# define prolog(i0) _prolog(_jit,i0)
+static void _prolog(jit_state_t*,jit_node_t*);
+# define epilog(i0) _epilog(_jit,i0)
+static void _epilog(jit_state_t*,jit_node_t*);
+# define vastart(r0) _vastart(_jit, r0)
+static void _vastart(jit_state_t*, int32_t);
+# define vaarg(r0, r1) _vaarg(_jit, r0, r1)
+static void _vaarg(jit_state_t*, int32_t, int32_t);
+#define patch_abs(instr,label) _patch_at(_jit,instr,label)
+#define patch_at(instr,label) _patch_at(_jit,instr,label)
+static void _patch_at(jit_state_t*,jit_word_t,jit_word_t);
+#endif /* PROTO */
+
+#if CODE
+static void
+_Rtype(jit_state_t *_jit, int32_t op, int32_t rd,
+ int32_t fct, int32_t rs1, int32_t rs2, int32_t fct2)
+{
+ instr_t i;
+ assert(!(op & ~0x7f));
+ assert(!(rd & ~0x1f));
+ assert(!(fct & ~0x07));
+ assert(!(rs1 & ~0x1f));
+ assert(!(rs2 & ~0x1f));
+ assert(!(fct2 & ~0x7f));
+ i.R.opcode = op;
+ i.R.rd = rd;
+ i.R.funct3 = fct;
+ i.R.rs1 = rs1;
+ i.R.rs2 = rs2;
+ i.R.funct7 = fct2;
+ ii(i.w);
+}
+
+static void
+_R4type(jit_state_t *_jit, int32_t op, int32_t rd, int32_t fct,
+ int32_t rs1, int32_t rs2, int32_t fct2, int32_t rs3)
+{
+ instr_t i;
+ assert(!(op & ~0x7f));
+ assert(!(rd & ~0x1f));
+ assert(!(fct & ~0x07));
+ assert(!(rs1 & ~0x1f));
+ assert(!(rs2 & ~0x1f));
+ assert(!(fct2 & ~0x03));
+ assert(!(rs3 & ~0x1f));
+ i.R4.opcode = op;
+ i.R4.rd = rd;
+ i.R4.funct3 = fct;
+ i.R4.rs1 = rs1;
+ i.R4.rs2 = rs2;
+ i.R4.funct2 = fct2;
+ i.R4.rs3 = rs3;
+ ii(i.w);
+}
+
+static void
+_Itype(jit_state_t *_jit, int32_t op, int32_t rd,
+ int32_t fct, int32_t rs1, int32_t imm)
+{
+ instr_t i;
+ assert(!(op & ~0x7f));
+ assert(!(rd & ~0x1f));
+ assert(!(fct & ~0x07));
+ assert(!(rs1 & ~0x1f));
+ assert(simm12_p(imm));
+ i.I.opcode = op;
+ i.I.rd = rd;
+ i.I.funct3 = fct;
+ i.I.rs1 = rs1;
+ i.I.imm11_0 = imm;
+ ii(i.w);
+}
+
+# if __WORDSIZE == 64
+static void
+_IStype(jit_state_t *_jit, int32_t op, int32_t rd,
+ int32_t fct, int32_t rs1, int32_t sh, int32_t imm)
+{
+ instr_t i;
+ assert(!(op & ~0x7f));
+ assert(!(rd & ~0x1f));
+ assert(!(fct & ~0x07));
+ assert(!(rs1 & ~0x1f));
+ assert(!(sh & ~0x3f));
+ assert(simm6_p(imm));
+ i.IS.opcode = op;
+ i.IS.rd = rd;
+ i.IS.funct3 = fct;
+ i.IS.rs1 = rs1;
+ i.IS.shamt = sh;
+ i.IS.imm6_0 = imm;
+ ii(i.w);
+}
+# endif
+
+static void
+_Stype(jit_state_t *_jit, int32_t op, int32_t fct,
+ int32_t rs1, int32_t rs2, int32_t imm)
+{
+ instr_t i;
+ assert(!(op & ~0x7f));
+ assert(!(fct & ~0x07));
+ assert(!(rs1 & ~0x1f));
+ assert(!(rs2 & ~0x1f));
+ assert(simm12_p(imm));
+ i.S.opcode = op;
+ i.S.imm4_0 = imm & 0x1f;
+ i.S.funct3 = fct;
+ i.S.rs1 = rs1;
+ i.S.rs2 = rs2;
+ i.S.imm11_5 = (imm >> 5) & 0x7f;
+ ii(i.w);
+}
+
+static void
+_Btype(jit_state_t *_jit, int32_t op, int32_t fct,
+ int32_t rs1, int32_t rs2, int32_t imm)
+{
+ instr_t i;
+ assert(!(op & ~0x7f));
+ assert(!(fct & ~0x07));
+ assert(!(rs1 & ~0x1f));
+ assert(!(rs2 & ~0x1f));
+ assert(!(imm & 1) && simm12_p(imm));
+ i.B.opcode = op;
+ i.B.imm11 = (imm >> 11) & 0x1;
+ i.B.imm4_1 = (imm >> 1) & 0xf;
+ i.B.funct3 = fct;
+ i.B.rs1 = rs1;
+ i.B.rs2 = rs2;
+ i.B.imm10_5 = (imm >> 5) & 0x3f;
+ i.B.imm12 = (imm >> 12) & 0x1;
+ ii(i.w);
+}
+
+static void
+_Utype(jit_state_t *_jit, int32_t op, int32_t rd, int32_t imm)
+{
+ instr_t i;
+ assert(!(op & ~0x7f));
+ assert(!(rd & ~0x1f));
+ assert(simm20_p(imm));
+ i.U.opcode = op;
+ i.U.rd = rd;
+ i.U.imm12_31= imm;
+ ii(i.w);
+}
+
+static void
+_Jtype(jit_state_t *_jit, int32_t op, int32_t rd, int32_t imm)
+{
+ instr_t i;
+ assert(!(op & ~0x7f));
+ assert(!(rd & ~0x1f));
+ assert(!(imm & 1) && imm <= 1048575 && imm >= -1048576);
+ i.J.opcode = op;
+ i.J.rd = rd;
+ i.J.imm19_12= (imm >> 12) & 0xff;
+ i.J.imm11 = (imm >> 11) & 0x1;
+ i.J.imm10_1 = (imm >> 1) & 0x3ff;
+ i.J.imm20 = (imm >> 20) & 0x1;
+ ii(i.w);
+}
+
+static void
+_nop(jit_state_t *_jit, int32_t im)
+{
+ for (; im > 0; im -= 4)
+ NOP();
+ assert(im == 0);
+}
+
+static void
+_addi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
+{
+ if (simm12_p(i0))
+ ADDI(r0, r1, i0);
+ else {
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr);
+ movi(rn(t0), i0);
+ addr(r0, r1, rn(t0));
+ jit_unget_reg(t0);
+ }
+}
+
+static void
+_addcr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
+{
+ int32_t t0;
+ if (jit_carry == _NOREG)
+ jit_carry = jit_get_reg(jit_class_gpr);
+ if (r0 == r1) {
+ t0 = jit_get_reg(jit_class_gpr);
+ addr(rn(t0), r1, r2);
+ SLTU(rn(jit_carry), rn(t0), r1);
+ movr(r0, rn(t0));
+ jit_unget_reg(t0);
+ }
+ else {
+ addr(r0, r1, r2);
+ SLTU(rn(jit_carry), r0, r1);
+ }
+}
+
+static void
+_addci(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
+{
+ int32_t t0;
+ if (jit_carry == _NOREG)
+ jit_carry = jit_get_reg(jit_class_gpr);
+ if (r0 == r1) {
+ t0 = jit_get_reg(jit_class_gpr);
+ addi(rn(t0), r1, i0);
+ SLTU(rn(jit_carry), rn(t0), r1);
+ movr(r0, rn(t0));
+ jit_unget_reg(t0);
+ }
+ else {
+ addi(r0, r1, i0);
+ SLTU(rn(jit_carry), r0, r1);
+ }
+}
+
+static void
+_addxr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
+{
+ int32_t t0;
+ assert(jit_carry != _NOREG);
+ t0 = jit_get_reg(jit_class_gpr);
+ movr(rn(t0), rn(jit_carry));
+ addcr(r0, r1, r2);
+ addcr(r0, r0, rn(t0));
+ jit_unget_reg(t0);
+}
+
+static void
+_addxi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
+{
+ int32_t t0;
+ assert(jit_carry != _NOREG);
+ t0 = jit_get_reg(jit_class_gpr);
+ movr(rn(t0), rn(jit_carry));
+ addci(r0, r1, i0);
+ addcr(r0, r0, rn(t0));
+ jit_unget_reg(t0);
+}
+
+static void
+_subi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
+{
+ if (simm12_p(-i0))
+ ADDI(r0, r1, -i0);
+ else {
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr);
+ movi(rn(t0), i0);
+ subr(r0, r1, rn(t0));
+ jit_unget_reg(t0);
+ }
+}
+
+static void
+_subcr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
+{
+ int32_t t0;
+ if (jit_carry == _NOREG)
+ jit_carry = jit_get_reg(jit_class_gpr);
+ if (r0 == r1) {
+ t0 = jit_get_reg(jit_class_gpr);
+ subr(rn(t0), r1, r2);
+ SLTU(rn(jit_carry), r1, rn(t0));
+ movr(r0, rn(t0));
+ jit_unget_reg(t0);
+ }
+ else {
+ subr(r0, r1, r2);
+ SLTU(rn(jit_carry), r1, r0);
+ }
+}
+
+static void
+_subci(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
+{
+ int32_t t0;
+ if (jit_carry == _NOREG)
+ jit_carry = jit_get_reg(jit_class_gpr);
+ if (r0 == r1) {
+ t0 = jit_get_reg(jit_class_gpr);
+ subi(rn(t0), r1, i0);
+ SLTU(rn(jit_carry), r1, rn(t0));
+ movr(r0, rn(t0));
+ jit_unget_reg(t0);
+ }
+ else {
+ subi(r0, r1, i0);
+ SLTU(rn(jit_carry), r1, r0);
+ }
+}
+
+static void
+_subxr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
+{
+ int32_t t0;
+ assert(jit_carry != _NOREG);
+ t0 = jit_get_reg(jit_class_gpr);
+ movr(rn(t0), rn(jit_carry));
+ subcr(r0, r1, r2);
+ subcr(r0, r0, rn(t0));
+ jit_unget_reg(t0);
+}
+
+static void
+_subxi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
+{
+ int32_t t0;
+ assert(jit_carry != _NOREG);
+ t0 = jit_get_reg(jit_class_gpr);
+ movr(rn(t0), rn(jit_carry));
+ subci(r0, r1, i0);
+ subcr(r0, r0, rn(t0));
+ jit_unget_reg(t0);
+}
+
+static void
+_rsbi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
+{
+ subi(r0, r1, i0);
+ negr(r0, r0);
+}
+
+static void
+_muli(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
+{
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr);
+ movi(rn(t0), i0);
+ mulr(r0, r1, rn(t0));
+ jit_unget_reg(t0);
+}
+
+static void
+_divi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
+{
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr);
+ movi(rn(t0), i0);
+ divr(r0, r1, rn(t0));
+ jit_unget_reg(t0);
+}
+
+static void
+_divi_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
+{
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr);
+ movi(rn(t0), i0);
+ divr_u(r0, r1, rn(t0));
+ jit_unget_reg(t0);
+}
+
+static void
+_remi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
+{
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr);
+ movi(rn(t0), i0);
+ remr(r0, r1, rn(t0));
+ jit_unget_reg(t0);
+}
+
+static void
+_remi_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
+{
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr);
+ movi(rn(t0), i0);
+ remr_u(r0, r1, rn(t0));
+ jit_unget_reg(t0);
+}
+
+static void
+_qmulr(jit_state_t *_jit, int32_t r0,
+ int32_t r1, int32_t r2, int32_t r3)
+{
+ int32_t t0;
+ if (r0 == r2 || r0 == r3) {
+ t0 = jit_get_reg(jit_class_gpr);
+ mulr(rn(t0), r2, r3);
+ }
+ else
+ mulr(r0, r2, r3);
+ MULH(r1, r2, r3);
+ if (r0 == r2 || r0 == r3) {
+ movr(r0, rn(t0));
+ jit_unget_reg(t0);
+ }
+}
+
+static void
+_qmuli(jit_state_t *_jit, int32_t r0,
+ int32_t r1, int32_t r2, jit_word_t i0)
+{
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr);
+ movi(rn(t0), i0);
+ qmulr(r0, r1, r2, rn(t0));
+ jit_unget_reg(t0);
+}
+
+static void
+_qmulr_u(jit_state_t *_jit, int32_t r0,
+ int32_t r1, int32_t r2, int32_t r3)
+{
+ int32_t t0;
+ if (r0 == r2 || r0 == r3) {
+ t0 = jit_get_reg(jit_class_gpr);
+ mulr(rn(t0), r2, r3);
+ }
+ else
+ mulr(r0, r2, r3);
+ MULHU(r1, r2, r3);
+ if (r0 == r2 || r0 == r3) {
+ movr(r0, rn(t0));
+ jit_unget_reg(t0);
+ }
+}
+
+static void
+_qmuli_u(jit_state_t *_jit, int32_t r0,
+ int32_t r1, int32_t r2, jit_word_t i0)
+{
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr);
+ movi(rn(t0), i0);
+ qmulr_u(r0, r1, r2, rn(t0));
+ jit_unget_reg(t0);
+}
+
+static void
+_iqdivr(jit_state_t *_jit, jit_bool_t sign,
+ int32_t r0, int32_t r1, int32_t r2, int32_t r3)
+{
+ int32_t sv0, rg0;
+ int32_t sv1, rg1;
+ if (r0 == r2 || r0 == r3) {
+ sv0 = jit_get_reg(jit_class_gpr);
+ rg0 = rn(sv0);
+ }
+ else
+ rg0 = r0;
+ if (r1 == r2 || r1 == r3) {
+ sv1 = jit_get_reg(jit_class_gpr);
+ rg1 = rn(sv1);
+ }
+ else
+ rg1 = r1;
+ if (sign)
+ divr(rg0, r2, r3);
+ else
+ divr_u(rg0, r2, r3);
+ mulr(rg1, r3, rg0);
+ subr(rg1, r2, rg1);
+ if (rg0 != r0) {
+ movr(r0, rg0);
+ jit_unget_reg(sv0);
+ }
+ if (rg1 != r1) {
+ movr(r1, rg1);
+ jit_unget_reg(sv1);
+ }
+}
+
+static void
+_qdivi(jit_state_t *_jit, int32_t r0,
+ int32_t r1, int32_t r2, jit_word_t i0)
+{
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr);
+ movi(rn(t0), i0);
+ qdivr(r0, r1, r2, rn(t0));
+ jit_unget_reg(t0);
+}
+
+static void
+_qdivi_u(jit_state_t *_jit, int32_t r0,
+ int32_t r1, int32_t r2, jit_word_t i0)
+{
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr);
+ movi(rn(t0), i0);
+ qdivr_u(r0, r1, r2, rn(t0));
+ jit_unget_reg(t0);
+}
+
+static void
+_lshi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
+{
+ if (i0 == 0)
+ movr(r0, r1);
+ else {
+ assert(i0 > 0 && i0 < 64);
+ SLLI(r0, r1, i0);
+ }
+}
+
+static void
+_rshi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
+{
+ if (i0 == 0)
+ movr(r0, r1);
+ else {
+ assert(i0 > 0 && i0 < 64);
+ SRAI(r0, r1, i0);
+ }
+}
+
+static void
+_rshi_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
+{
+ if (i0 == 0)
+ movr(r0, r1);
+ else {
+ assert(i0 > 0 && i0 < 64);
+ SRLI(r0, r1, i0);
+ }
+}
+
+static void
+_andi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
+{
+ if (simm12_p(i0))
+ ANDI(r0, r1, i0);
+ else {
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr);
+ movi(rn(t0), i0);
+ andr(r0, r1, rn(t0));
+ jit_unget_reg(t0);
+ }
+}
+
+static void
+_ori(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
+{
+ if (simm12_p(i0))
+ ORI(r0, r1, i0);
+ else {
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr);
+ movi(rn(t0), i0);
+ orr(r0, r1, rn(t0));
+ jit_unget_reg(t0);
+ }
+}
+
+static void
+_xori(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
+{
+ if (simm12_p(i0))
+ XORI(r0, r1, i0);
+ else {
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr);
+ movi(rn(t0), i0);
+ xorr(r0, r1, rn(t0));
+ jit_unget_reg(t0);
+ }
+}
+
+# define DEFLD(T,O) \
+static void \
+_ldi_##T(jit_state_t *_jit, int32_t r0, jit_word_t i0) \
+{ \
+ if (simm12_p(i0)) \
+ L##O(r0, _ZERO_REGNO, i0); \
+ else { \
+ int32_t t0; \
+ t0 = jit_get_reg(jit_class_gpr); \
+ movi(rn(t0), i0); \
+ ldr_##T(r0, rn(t0)); \
+ jit_unget_reg(t0); \
+ } \
+} \
+ \
+static void \
+_ldxr_##T(jit_state_t *_jit,int32_t r0,int32_t r1,int32_t r2)\
+{ \
+ int32_t t0; \
+ t0 = jit_get_reg(jit_class_gpr); \
+ addr(rn(t0), r1, r2); \
+ ldr_##T(r0, rn(t0)); \
+ jit_unget_reg(t0); \
+} \
+ \
+static void \
+_ldxi_##T(jit_state_t *_jit,int32_t r0,int32_t r1,jit_word_t i0)\
+{ \
+ if (simm12_p(i0)) \
+ L##O(r0, r1, i0); \
+ else { \
+ int32_t t0; \
+ t0 = jit_get_reg(jit_class_gpr); \
+ addi(rn(t0), r1, i0); \
+ ldr_##T(r0, rn(t0)); \
+ jit_unget_reg(t0); \
+ } \
+}
+
+DEFLD(c,B)
+DEFLD(uc,BU)
+DEFLD(s,H)
+DEFLD(us,HU)
+DEFLD(i,W)
+DEFLD(ui,WU)
+DEFLD(l,D)
+
+# define DEFST(T, O) \
+static void \
+_sti_##T(jit_state_t *_jit, jit_word_t i0, int32_t r0) \
+{ \
+ if (simm12_p(i0)) \
+ S##O(_ZERO_REGNO, r0, i0); \
+ else { \
+ int32_t t0; \
+ t0 = jit_get_reg(jit_class_gpr); \
+ movi(rn(t0), i0); \
+ str_##T(rn(t0), r0); \
+ jit_unget_reg(t0); \
+ } \
+} \
+ \
+static void \
+_stxr_##T(jit_state_t *_jit,int32_t r0,int32_t r1,int32_t r2)\
+{ \
+ int32_t t0; \
+ t0 = jit_get_reg(jit_class_gpr); \
+ addr(rn(t0), r0, r1); \
+ str_##T(rn(t0), r2); \
+ jit_unget_reg(t0); \
+} \
+ \
+static void \
+_stxi_##T(jit_state_t *_jit,jit_word_t i0,int32_t r0,int32_t r1)\
+{ \
+ if (simm12_p(i0)) \
+ S##O(r0, r1, i0); \
+ else { \
+ int32_t t0; \
+ t0 = jit_get_reg(jit_class_gpr); \
+ addi(rn(t0), r0, i0); \
+ str_##T(rn(t0), r1); \
+ jit_unget_reg(t0); \
+ } \
+}
+
+DEFST(c, B)
+DEFST(s, H)
+DEFST(i, W)
+DEFST(l, D)
+
+static void
+_htonr_us(jit_state_t *_jit, int32_t r0, int32_t r1)
+{
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr);
+ rshi(rn(t0), r1, 8);
+ andi(r0, r1, 0xff);
+ andi(rn(t0), rn(t0), 0xff);
+ lshi(r0, r0, 8);
+ orr(r0, r0, rn(t0));
+ jit_unget_reg(t0);
+}
+
+static void
+_htonr_ui(jit_state_t *_jit, int32_t r0, int32_t r1)
+{
+ int32_t t0;
+ int32_t t1;
+ int32_t t2;
+ t0 = jit_get_reg(jit_class_gpr);
+ t1 = jit_get_reg(jit_class_gpr);
+ t2 = jit_get_reg(jit_class_gpr);
+ rshi(rn(t0), r1, 24);
+ rshi(rn(t1), r1, 16);
+ rshi(rn(t2), r1, 8);
+ andi(rn(t0), rn(t0), 0xff);
+ andi(rn(t1), rn(t1), 0xff);
+ andi(rn(t2), rn(t2), 0xff);
+ andi(r0, r1, 0xff);
+ lshi(r0, r0, 24);
+ lshi(rn(t1), rn(t1), 8);
+ orr(r0, r0, rn(t0));
+ lshi(rn(t2), rn(t2), 16);
+ orr(r0, r0, rn(t1));
+ orr(r0, r0, rn(t2));
+ jit_unget_reg(t2);
+ jit_unget_reg(t1);
+ jit_unget_reg(t0);
+}
+
+static void
+_htonr_ul(jit_state_t *_jit, int32_t r0, int32_t r1)
+{
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr);
+ rshi_u(rn(t0), r1, 32);
+ htonr_ui(r0, r1);
+ htonr_ui(rn(t0), rn(t0));
+ lshi(r0, r0, 32);
+ orr(r0, r0, rn(t0));
+ jit_unget_reg(t0);
+}
+
+static void
+_extr_c(jit_state_t *_jit, int32_t r0, int32_t r1)
+{
+ lshi(r0, r1, 56);
+ rshi(r0, r0, 56);
+}
+
+static void
+_extr_s(jit_state_t *_jit, int32_t r0, int32_t r1)
+{
+ lshi(r0, r1, 48);
+ rshi(r0, r0, 48);
+}
+
+static void
+_extr_us(jit_state_t *_jit, int32_t r0, int32_t r1)
+{
+ lshi(r0, r1, 48);
+ rshi_u(r0, r0, 48);
+}
+
+static void
+_extr_ui(jit_state_t *_jit, int32_t r0, int32_t r1)
+{
+ lshi(r0, r1, 32);
+ rshi_u(r0, r0, 32);
+}
+
+static void
+_movi(jit_state_t *_jit, int32_t r0, jit_word_t i0)
+{
+ if (simm32_p(i0)) {
+ int32_t lo = (int32_t)i0 << 20 >> 20;
+ int32_t hi = i0 - lo;
+ if (hi) {
+ LUI(r0, hi >> 12);
+ if (lo)
+ ADDIW(r0, r0, lo);
+ }
+ else
+ ADDIW(r0, _ZERO_REGNO, lo);
+ }
+ else {
+ int32_t lo = i0 << 32 >> 32;
+ jit_word_t hi = i0 - lo;
+ int32_t t0 = jit_get_reg(jit_class_gpr);
+ movi(rn(t0), (int32_t)(hi >> 32));
+ movi(r0, lo);
+ lshi(rn(t0), rn(t0), 32);
+ addr(r0, r0, rn(t0));
+ jit_unget_reg(t0);
+ }
+}
+
+static jit_word_t
+_movi_p(jit_state_t *_jit, int32_t r0, jit_word_t i0)
+{
+ jit_word_t w;
+ int32_t t0;
+ int32_t ww = i0 << 32 >> 32;
+ int32_t lo = ww << 20 >> 20;
+ int32_t hi = ww - lo;
+ w = _jit->pc.w;
+ t0 = jit_get_reg(jit_class_gpr);
+ LUI(r0, hi >> 12);
+ ADDIW(r0, r0, lo);
+ ww = i0 >> 32;
+ lo = ww << 20 >> 20;
+ hi = ww - lo;
+ LUI(rn(t0), hi >> 12);
+ ADDIW(rn(t0), rn(t0), lo);
+ SLLI(rn(t0), rn(t0), 32);
+ ADD(r0, r0, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+
+static void
+_lti(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
+{
+ if (simm12_p(i0))
+ SLTI(r0, r1, i0);
+ else {
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr);
+ movi(r0, i0);
+ ltr(r0, r1, rn(t0));
+ jit_unget_reg(t0);
+ }
+}
+
+static void
+_lti_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
+{
+ if (simm12_p(i0))
+ SLTIU(r0, r1, i0);
+ else {
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr);
+ movi(r0, i0);
+ ltr_u(r0, r1, rn(t0));
+ jit_unget_reg(t0);
+ }
+}
+
+static void
+_ler(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
+{
+ SLT(r0, r2, r1);
+ XORI(r0, r0, 1);
+}
+
+static void
+_lei(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
+{
+ int32_t t0;
+ if (i0 == 0) {
+ SLT(r0, _ZERO_REGNO, r1);
+ XORI(r0, r0, 1);
+ }
+ else {
+ t0 = jit_get_reg(jit_class_gpr);
+ movi(rn(t0), i0);
+ ler(r0, r1, rn(t0));
+ jit_unget_reg(t0);
+ }
+}
+
+static void
+_ler_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
+{
+ SLTU(r0, r2, r1);
+ XORI(r0, r0, 1);
+}
+
+static void
+_lei_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
+{
+ int32_t t0;
+ if (i0 == 0) {
+ SLTU(r0, _ZERO_REGNO, r1);
+ XORI(r0, r0, 1);
+ }
+ else {
+ t0 = jit_get_reg(jit_class_gpr);
+ movi(rn(t0), i0);
+ ler_u(r0, r1, rn(t0));
+ jit_unget_reg(t0);
+ }
+}
+
+static void
+_eqr(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
+{
+ subr(r0, r1, r2);
+ SLTU(r0, _ZERO_REGNO, r0);
+ XORI(r0, r0, 1);
+}
+
+static void
+_eqi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
+{
+ if (i0) {
+ subi(r0, r1, i0);
+ SLTU(r0, _ZERO_REGNO, r0);
+ }
+ else
+ SLTU(r0, _ZERO_REGNO, r1);
+ XORI(r0, r0, 1);
+}
+
+static void
+_ger(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
+{
+ SLT(r0, r1, r2);
+ XORI(r0, r0, 1);
+}
+
+static void
+_gei(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
+{
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr);
+ movi(rn(t0), i0);
+ ger(r0, r1, rn(t0));
+ jit_unget_reg(t0);
+}
+
+static void
+_ger_u(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
+{
+ SLTU(r0, r1, r2);
+ XORI(r0, r0, 1);
+}
+
+static void
+_gei_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
+{
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr);
+ movi(rn(t0), i0);
+ ger_u(r0, r1, rn(t0));
+ jit_unget_reg(t0);
+}
+
+static void
+_gti(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
+{
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr);
+ movi(r0, i0);
+ ltr(r0, rn(t0), r1);
+ jit_unget_reg(t0);
+}
+
+static void
+_gti_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
+{
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr);
+ movi(r0, i0);
+ ltr_u(r0, rn(t0), r1);
+ jit_unget_reg(t0);
+}
+
+static void
+_ner(jit_state_t *_jit, int32_t r0, int32_t r1, int32_t r2)
+{
+ subr(r0, r1, r2);
+ SLTU(r0, _ZERO_REGNO, r0);
+}
+
+static void
+_nei(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
+{
+ if (i0) {
+ subi(r0, r1, i0);
+ SLTU(r0, _ZERO_REGNO, r0);
+ }
+ else
+ SLTU(r0, _ZERO_REGNO, r1);
+}
+
+static jit_word_t
+_bltr(jit_state_t *_jit, jit_word_t br, int32_t r0, int32_t r1)
+{
+ jit_word_t w;
+ w = _jit->pc.w;
+ BLT(r0, r1, br - w);
+ return (w);
+}
+
+static jit_word_t
+_blti(jit_state_t *_jit, jit_word_t br, int32_t r0, jit_word_t i0)
+{
+ jit_word_t w;
+ jit_reg_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ movi(rn(t0), i0);
+ w = bltr(br, r0, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+
+static jit_word_t
+_bltr_u(jit_state_t *_jit, jit_word_t br, int32_t r0, int32_t r1)
+{
+ jit_word_t w;
+ w = _jit->pc.w;
+ BLTU(r0, r1, br - w);
+ return (w);
+}
+
+static jit_word_t
+_blti_u(jit_state_t *_jit, jit_word_t br, int32_t r0, jit_word_t i0)
+{
+ jit_word_t w;
+ jit_reg_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ movi(rn(t0), i0);
+ w = bltr_u(br, r0, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+
+static jit_word_t
+_bler(jit_state_t *_jit, jit_word_t br, int32_t r0, int32_t r1)
+{
+ jit_word_t w;
+ w = _jit->pc.w;
+ BGE(r1, r0, br - w);
+ return (w);
+}
+
+static jit_word_t
+_blei(jit_state_t *_jit, jit_word_t br, int32_t r0, jit_word_t i0)
+{
+ jit_word_t w;
+ jit_reg_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ movi(rn(t0), i0);
+ w = bler(br, r0, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+
+static jit_word_t
+_bler_u(jit_state_t *_jit, jit_word_t br, int32_t r0, int32_t r1)
+{
+ jit_word_t w;
+ w = _jit->pc.w;
+ BGEU(r1, r0, br - w);
+ return (w);
+}
+
+static jit_word_t
+_blei_u(jit_state_t *_jit, jit_word_t br, int32_t r0, jit_word_t i0)
+{
+ jit_word_t w;
+ jit_reg_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ movi(rn(t0), i0);
+ w = bler_u(br, r0, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+
+static jit_word_t
+_beqr(jit_state_t *_jit, jit_word_t br, int32_t r0, int32_t r1)
+{
+ jit_word_t w;
+ w = _jit->pc.w;
+ BEQ(r1, r0, br - w);
+ return (w);
+}
+
+static jit_word_t
+_beqi(jit_state_t *_jit, jit_word_t br, int32_t r0, jit_word_t i0)
+{
+ jit_word_t w;
+ jit_reg_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ movi(rn(t0), i0);
+ w = beqr(br, r0, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+
+static jit_word_t
+_bger(jit_state_t *_jit, jit_word_t br, int32_t r0, int32_t r1)
+{
+ jit_word_t w;
+ w = _jit->pc.w;
+ BGE(r0, r1, br - w);
+ return (w);
+}
+
+static jit_word_t
+_bgei(jit_state_t *_jit, jit_word_t br, int32_t r0, jit_word_t i0)
+{
+ jit_word_t w;
+ jit_reg_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ movi(rn(t0), i0);
+ w = bger(br, r0, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+
+static jit_word_t
+_bger_u(jit_state_t *_jit, jit_word_t br, int32_t r0, int32_t r1)
+{
+ jit_word_t w;
+ w = _jit->pc.w;
+ BGEU(r0, r1, br - w);
+ return (w);
+}
+
+static jit_word_t
+_bgei_u(jit_state_t *_jit, jit_word_t br, int32_t r0, jit_word_t i0)
+{
+ jit_word_t w;
+ jit_reg_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ movi(rn(t0), i0);
+ w = bger_u(br, r0, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+
+static jit_word_t
+_bgtr(jit_state_t *_jit, jit_word_t br, int32_t r0, int32_t r1)
+{
+ jit_word_t w;
+ w = _jit->pc.w;
+ BLT(r1, r0, br - w);
+ return (w);
+}
+
+static jit_word_t
+_bgti(jit_state_t *_jit, jit_word_t br, int32_t r0, jit_word_t i0)
+{
+ jit_word_t w;
+ jit_reg_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ movi(rn(t0), i0);
+ w = bgtr(br, r0, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+
+static jit_word_t
+_bgtr_u(jit_state_t *_jit, jit_word_t br, int32_t r0, int32_t r1)
+{
+ jit_word_t w;
+ w = _jit->pc.w;
+ BLTU(r1, r0, br - w);
+ return (w);
+}
+
+static jit_word_t
+_bgti_u(jit_state_t *_jit, jit_word_t br, int32_t r0, jit_word_t i0)
+{
+ jit_word_t w;
+ jit_reg_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ movi(rn(t0), i0);
+ w = bgtr_u(br, r0, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+
+static jit_word_t
+_bner(jit_state_t *_jit, jit_word_t br, int32_t r0, int32_t r1)
+{
+ jit_word_t w;
+ w = _jit->pc.w;
+ BNE(r1, r0, br - w);
+ return (w);
+}
+
+static jit_word_t
+_bnei(jit_state_t *_jit, jit_word_t br, int32_t r0, jit_word_t i0)
+{
+ jit_word_t w;
+ jit_reg_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ movi(rn(t0), i0);
+ w = bner(br, r0, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+
+static jit_word_t
+_boaddr(jit_state_t *_jit, jit_word_t br, int32_t r0, int32_t r1)
+{
+ jit_word_t w, jal;
+ int32_t t0, t1;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ t1 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ /* t0 = r1 < 0; */
+ SLT(rn(t0), r1, _ZERO_REGNO);
+ /* t1 = r0 */
+ movr(rn(t1), r0);
+ /* r0 = r0 + r1 */
+ addr(r0, r0, r1);
+ /* overflow = r1 < 0 ? t1 < r0 : r0 < t1 */
+ w = _jit->pc.w;
+ BNE(rn(t0), _ZERO_REGNO, 0);
+ /* r1 >= 0 */
+ SLT(rn(t1), r0, rn(t1));
+ jal = _jit->pc.w;
+ JAL(_ZERO_REGNO, 0);
+ /* r1 < 0 */
+ patch_at(w, _jit->pc.w);
+ SLT(rn(t1), rn(t1), r0);
+ /**/
+ patch_at(jal, _jit->pc.w);
+ w = _jit->pc.w;
+ BNE(rn(t1), _ZERO_REGNO, br - w);
+ jit_unget_reg(t1);
+ jit_unget_reg(t0);
+ return (w);
+}
+
+static jit_word_t
+_boaddi(jit_state_t *_jit, jit_word_t br, int32_t r0, jit_word_t i0)
+{
+ jit_word_t w;
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ movi(rn(t0), i0);
+ w = boaddr(br, r0, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+
+static jit_word_t
+_boaddr_u(jit_state_t *_jit, jit_word_t br, int32_t r0, int32_t r1)
+{
+ jit_word_t w;
+ int32_t t0, t1;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ t1 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ addr(rn(t0), r0, r1);
+ SLTU(rn(t1), rn(t0), r0);
+ movr(r0, rn(t0));
+ w = _jit->pc.w;
+ BNE(_ZERO_REGNO, rn(t1), br - w);
+ jit_unget_reg(t1);
+ jit_unget_reg(t0);
+ return (w);
+}
+
+static jit_word_t
+_boaddi_u(jit_state_t *_jit, jit_word_t br, int32_t r0, jit_word_t i0)
+{
+ jit_word_t w;
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ movi(rn(t0), i0);
+ w = boaddr_u(br, r0, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+
+static jit_word_t
+_bxaddr(jit_state_t *_jit, jit_word_t br, int32_t r0, int32_t r1)
+{
+ jit_word_t w, jal;
+ int32_t t0, t1;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ t1 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ /* t0 = r1 < 0; */
+ SLT(rn(t0), r1, _ZERO_REGNO);
+ /* t1 = r0 */
+ movr(rn(t1), r0);
+ /* r0 = r0 + r1 */
+ addr(r0, r0, r1);
+ /* overflow = r1 < 0 ? t1 < r0 : r0 < t1 */
+ w = _jit->pc.w;
+ BNE(rn(t0), _ZERO_REGNO, 0);
+ /* r1 >= 0 */
+ SLT(rn(t1), r0, rn(t1));
+ jal = _jit->pc.w;
+ JAL(_ZERO_REGNO, 0);
+ /* r1 < 0 */
+ patch_at(w, _jit->pc.w);
+ SLT(rn(t1), rn(t1), r0);
+ /**/
+ patch_at(jal, _jit->pc.w);
+ w = _jit->pc.w;
+ BEQ(rn(t1), _ZERO_REGNO, br - w);
+ jit_unget_reg(t1);
+ jit_unget_reg(t0);
+ return (w);
+}
+
+static jit_word_t
+_bxaddi(jit_state_t *_jit, jit_word_t br, int32_t r0, jit_word_t i0)
+{
+ jit_word_t w;
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ movi(rn(t0), i0);
+ w = bxaddr(br, r0, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+
+static jit_word_t
+_bxaddr_u(jit_state_t *_jit, jit_word_t br, int32_t r0, int32_t r1)
+{
+ jit_word_t w;
+ int32_t t0, t1;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ t1 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ addr(rn(t0), r0, r1);
+ SLTU(rn(t1), rn(t0), r0);
+ movr(r0, rn(t0));
+ w = _jit->pc.w;
+ BEQ(_ZERO_REGNO, rn(t1), br - w);
+ jit_unget_reg(t1);
+ jit_unget_reg(t0);
+ return (w);
+}
+
+static jit_word_t
+_bxaddi_u(jit_state_t *_jit, jit_word_t br, int32_t r0, jit_word_t i0)
+{
+ jit_word_t w;
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ movi(rn(t0), i0);
+ w = bxaddr_u(br, r0, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+
+static jit_word_t
+_bosubr(jit_state_t *_jit, jit_word_t br, int32_t r0, int32_t r1)
+{
+ jit_word_t w, jal;
+ int32_t t0, t1;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ t1 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ /* t0 = 0 < r1; */
+ SLT(rn(t0), _ZERO_REGNO, r1);
+ /* t1 = r0 */
+ movr(rn(t1), r0);
+ /* r0 = r0 - r1 */
+ subr(r0, r0, r1);
+ /* overflow = r1 < 0 ? t1 < r0 : r0 < t1 */
+ w = _jit->pc.w;
+ BNE(rn(t0), _ZERO_REGNO, 0);
+ /* r1 >= 0 */
+ SLT(rn(t1), r0, rn(t1));
+ jal = _jit->pc.w;
+ JAL(_ZERO_REGNO, 0);
+ /* r1 < 0 */
+ patch_at(w, _jit->pc.w);
+ SLT(rn(t1), rn(t1), r0);
+ /**/
+ patch_at(jal, _jit->pc.w);
+ w = _jit->pc.w;
+ BNE(rn(t1), _ZERO_REGNO, br - w);
+ jit_unget_reg(t1);
+ jit_unget_reg(t0);
+ return (w);
+}
+
+static jit_word_t
+_bosubi(jit_state_t *_jit, jit_word_t br, int32_t r0, jit_word_t i0)
+{
+ jit_word_t w;
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ movi(rn(t0), i0);
+ w = bosubr(br, r0, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+
+static jit_word_t
+_bosubr_u(jit_state_t *_jit, jit_word_t br, int32_t r0, int32_t r1)
+{
+ jit_word_t w;
+ int32_t t0, t1;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ t1 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ subr(rn(t0), r0, r1);
+ SLTU(rn(t1), r0, rn(t0));
+ movr(r0, rn(t0));
+ w = _jit->pc.w;
+ BNE(_ZERO_REGNO, rn(t1), br - w);
+ jit_unget_reg(t1);
+ jit_unget_reg(t0);
+ return (w);
+}
+
+static jit_word_t
+_bosubi_u(jit_state_t *_jit, jit_word_t br, int32_t r0, jit_word_t i0)
+{
+ jit_word_t w;
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ movi(rn(t0), i0);
+ w = bosubr_u(br, r0, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+
+static jit_word_t
+_bxsubr(jit_state_t *_jit, jit_word_t br, int32_t r0, int32_t r1)
+{
+ jit_word_t w, jal;
+ int32_t t0, t1;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ t1 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ /* t0 = r1 < 0; */
+ SLT(rn(t0), _ZERO_REGNO, r1);
+ /* t1 = r0 */
+ movr(rn(t1), r0);
+ /* r0 = r0 - r1 */
+ subr(r0, r0, r1);
+ /* overflow = r1 < 0 ? t1 < r0 : r0 < t1 */
+ w = _jit->pc.w;
+ BNE(rn(t0), _ZERO_REGNO, 0);
+ /* r1 >= 0 */
+ SLT(rn(t1), r0, rn(t1));
+ jal = _jit->pc.w;
+ JAL(_ZERO_REGNO, 0);
+ /* r1 < 0 */
+ patch_at(w, _jit->pc.w);
+ SLT(rn(t1), rn(t1), r0);
+ /**/
+ patch_at(jal, _jit->pc.w);
+ w = _jit->pc.w;
+ BEQ(rn(t1), _ZERO_REGNO, br - w);
+ jit_unget_reg(t1);
+ jit_unget_reg(t0);
+ return (w);
+}
+
+static jit_word_t
+_bxsubi(jit_state_t *_jit, jit_word_t br, int32_t r0, jit_word_t i0)
+{
+ jit_word_t w;
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ movi(rn(t0), i0);
+ w = bxsubr(br, r0, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+
+static jit_word_t
+_bxsubr_u(jit_state_t *_jit, jit_word_t br, int32_t r0, int32_t r1)
+{
+ jit_word_t w;
+ int32_t t0, t1;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ t1 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ subr(rn(t0), r0, r1);
+ SLTU(rn(t1), r0, rn(t0));
+ movr(r0, rn(t0));
+ w = _jit->pc.w;
+ BEQ(_ZERO_REGNO, rn(t1), br - w);
+ jit_unget_reg(t1);
+ jit_unget_reg(t0);
+ return (w);
+}
+
+static jit_word_t
+_bxsubi_u(jit_state_t *_jit, jit_word_t br, int32_t r0, jit_word_t i0)
+{
+ jit_word_t w;
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ movi(rn(t0), i0);
+ w = bxsubr_u(br, r0, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+
+static jit_word_t
+_bmsr(jit_state_t *_jit, jit_word_t br, int32_t r0, int32_t r1)
+{
+ jit_word_t w;
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ AND(rn(t0), r0, r1);
+ w = _jit->pc.w;
+ BNE(_ZERO_REGNO, rn(t0), br - w);
+ jit_unget_reg(t0);
+ return (w);
+}
+
+static jit_word_t
+_bmsi(jit_state_t *_jit, jit_word_t br, int32_t r0, jit_word_t i0)
+{
+ jit_word_t w;
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ movi(rn(t0), i0);
+ w = bmsr(br, r0, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+
+static jit_word_t
+_bmcr(jit_state_t *_jit, jit_word_t br, int32_t r0, int32_t r1)
+{
+ jit_word_t w;
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ AND(rn(t0), r0, r1);
+ w = _jit->pc.w;
+ BEQ(_ZERO_REGNO, rn(t0), br - w);
+ jit_unget_reg(t0);
+ return (w);
+}
+
+static jit_word_t
+_bmci(jit_state_t *_jit, jit_word_t br, int32_t r0, jit_word_t i0)
+{
+ jit_word_t w;
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ movi(rn(t0), i0);
+ w = bmcr(br, r0, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+
+static void
+_jmpi(jit_state_t *_jit, jit_word_t i0)
+{
+ int32_t t0;
+ jit_word_t dsp;
+ dsp = i0 - _jit->pc.w;
+ if (simm20_p(dsp))
+ JAL(_ZERO_REGNO, dsp);
+ else {
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ movi(rn(t0), i0);
+ jmpr(rn(t0));
+ jit_unget_reg(t0);
+ }
+}
+
+static jit_word_t
+_jmpi_p(jit_state_t *_jit, jit_word_t i0)
+{
+ jit_word_t w;
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ w = movi_p(rn(t0), i0);
+ jmpr(rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+
+static void
+_calli(jit_state_t *_jit, jit_word_t i0)
+{
+ int32_t t0;
+ jit_word_t dsp;
+ dsp = i0 - _jit->pc.w;
+ if (simm20_p(dsp))
+ JAL(_RA_REGNO, dsp);
+ else {
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ movi(rn(t0), i0);
+ callr(rn(t0));
+ jit_unget_reg(t0);
+ }
+}
+
+static jit_word_t
+_calli_p(jit_state_t *_jit, jit_word_t i0)
+{
+ jit_word_t w;
+ int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ w = movi_p(rn(t0), i0);
+ callr(rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+
+static void
+_prolog(jit_state_t *_jit, jit_node_t *node)
+{
+ int32_t reg;
+ if (_jitc->function->define_frame || _jitc->function->assume_frame) {
+ int32_t frame = -_jitc->function->frame;
+ assert(_jitc->function->self.aoff >= frame);
+ if (_jitc->function->assume_frame)
+ return;
+ _jitc->function->self.aoff = frame;
+ }
+ if (_jitc->function->allocar)
+ _jitc->function->self.aoff &= -16;
+ _jitc->function->stack = ((_jitc->function->self.alen -
+ /* align stack at 16 bytes */
+ _jitc->function->self.aoff) + 15) & -16;
+ subi(_SP_REGNO, _SP_REGNO, stack_framesize);
+ stxi(0, _SP_REGNO, _RA_REGNO);
+ stxi(8, _SP_REGNO, _FP_REGNO);
+ if (jit_regset_tstbit(&_jitc->function->regset, _S1))
+ stxi(16, _SP_REGNO, 9);
+ if (jit_regset_tstbit(&_jitc->function->regset, _S2))
+ stxi(24, _SP_REGNO, 18);
+ if (jit_regset_tstbit(&_jitc->function->regset, _S3))
+ stxi(32, _SP_REGNO, 19);
+ if (jit_regset_tstbit(&_jitc->function->regset, _S4))
+ stxi(40, _SP_REGNO, 20);
+ if (jit_regset_tstbit(&_jitc->function->regset, _S5))
+ stxi(48, _SP_REGNO, 21);
+ if (jit_regset_tstbit(&_jitc->function->regset, _S6))
+ stxi(56, _SP_REGNO, 22);
+ if (jit_regset_tstbit(&_jitc->function->regset, _S7))
+ stxi(64, _SP_REGNO, 23);
+ if (jit_regset_tstbit(&_jitc->function->regset, _S8))
+ stxi(72, _SP_REGNO, 24);
+ if (jit_regset_tstbit(&_jitc->function->regset, _S9))
+ stxi(80, _SP_REGNO, 25);
+ if (jit_regset_tstbit(&_jitc->function->regset, _S10))
+ stxi(88, _SP_REGNO, 26);
+ if (jit_regset_tstbit(&_jitc->function->regset, _S11))
+ stxi(96, _SP_REGNO, 27);
+ if (jit_regset_tstbit(&_jitc->function->regset, _FS0))
+ stxi_d(104, _SP_REGNO, 8);
+ if (jit_regset_tstbit(&_jitc->function->regset, _FS1))
+ stxi_d(112, _SP_REGNO, 9);
+ if (jit_regset_tstbit(&_jitc->function->regset, _FS2))
+ stxi_d(120, _SP_REGNO, 18);
+ if (jit_regset_tstbit(&_jitc->function->regset, _FS3))
+ stxi_d(128, _SP_REGNO, 19);
+ if (jit_regset_tstbit(&_jitc->function->regset, _FS4))
+ stxi_d(136, _SP_REGNO, 20);
+ if (jit_regset_tstbit(&_jitc->function->regset, _FS5))
+ stxi_d(144, _SP_REGNO, 21);
+ if (jit_regset_tstbit(&_jitc->function->regset, _FS6))
+ stxi_d(152, _SP_REGNO, 22);
+ if (jit_regset_tstbit(&_jitc->function->regset, _FS7))
+ stxi_d(160, _SP_REGNO, 23);
+ if (jit_regset_tstbit(&_jitc->function->regset, _FS8))
+ stxi_d(168, _SP_REGNO, 24);
+ if (jit_regset_tstbit(&_jitc->function->regset, _FS9))
+ stxi_d(176, _SP_REGNO, 25);
+ if (jit_regset_tstbit(&_jitc->function->regset, _FS10))
+ stxi_d(184, _SP_REGNO, 26);
+ if (jit_regset_tstbit(&_jitc->function->regset, _FS11))
+ stxi_d(192, _SP_REGNO, 27);
+ movr(_FP_REGNO, _SP_REGNO);
+ if (_jitc->function->stack)
+ subi(_SP_REGNO, _SP_REGNO, _jitc->function->stack);
+ if (_jitc->function->allocar) {
+ reg = jit_get_reg(jit_class_gpr);
+ movi(rn(reg), _jitc->function->self.aoff);
+ stxi_i(_jitc->function->aoffoff, _FP_REGNO, rn(reg));
+ jit_unget_reg(reg);
+ }
+ if (_jitc->function->self.call & jit_call_varargs) {
+ for (reg = _jitc->function->vagp; jit_arg_reg_p(reg); ++reg)
+ stxi(stack_framesize - ((8 - reg) * 8),
+ _FP_REGNO, rn(JIT_RA0 - reg));
+ }
+}
+
+static void
+_epilog(jit_state_t *_jit, jit_node_t *node)
+{
+ if (_jitc->function->assume_frame)
+ return;
+ movr(_SP_REGNO, _FP_REGNO);
+ ldxi(_RA_REGNO, _SP_REGNO, 0);
+ ldxi(_FP_REGNO, _SP_REGNO, 8);
+ if (jit_regset_tstbit(&_jitc->function->regset, _S1))
+ ldxi(9, _SP_REGNO, 16);
+ if (jit_regset_tstbit(&_jitc->function->regset, _S2))
+ ldxi(18, _SP_REGNO, 24);
+ if (jit_regset_tstbit(&_jitc->function->regset, _S3))
+ ldxi(19, _SP_REGNO, 32);
+ if (jit_regset_tstbit(&_jitc->function->regset, _S4))
+ ldxi(20, _SP_REGNO, 40);
+ if (jit_regset_tstbit(&_jitc->function->regset, _S5))
+ ldxi(21, _SP_REGNO, 48);
+ if (jit_regset_tstbit(&_jitc->function->regset, _S6))
+ ldxi(22, _SP_REGNO, 56);
+ if (jit_regset_tstbit(&_jitc->function->regset, _S7))
+ ldxi(23, _SP_REGNO, 64);
+ if (jit_regset_tstbit(&_jitc->function->regset, _S8))
+ ldxi(24, _SP_REGNO, 72);
+ if (jit_regset_tstbit(&_jitc->function->regset, _S9))
+ ldxi(25, _SP_REGNO, 80);
+ if (jit_regset_tstbit(&_jitc->function->regset, _S10))
+ ldxi(26, _SP_REGNO, 88);
+ if (jit_regset_tstbit(&_jitc->function->regset, _S11))
+ ldxi(27, _SP_REGNO, 96);
+ if (jit_regset_tstbit(&_jitc->function->regset, _FS0))
+ ldxi_d(8, _SP_REGNO, 104);
+ if (jit_regset_tstbit(&_jitc->function->regset, _FS1))
+ ldxi_d(9, _SP_REGNO, 112);
+ if (jit_regset_tstbit(&_jitc->function->regset, _FS2))
+ ldxi_d(18, _SP_REGNO, 120);
+ if (jit_regset_tstbit(&_jitc->function->regset, _FS3))
+ ldxi_d(19, _SP_REGNO, 128);
+ if (jit_regset_tstbit(&_jitc->function->regset, _FS4))
+ ldxi_d(20, _SP_REGNO, 136);
+ if (jit_regset_tstbit(&_jitc->function->regset, _FS5))
+ ldxi_d(21, _SP_REGNO, 144);
+ if (jit_regset_tstbit(&_jitc->function->regset, _FS6))
+ ldxi_d(22, _SP_REGNO, 152);
+ if (jit_regset_tstbit(&_jitc->function->regset, _FS7))
+ ldxi_d(23, _SP_REGNO, 160);
+ if (jit_regset_tstbit(&_jitc->function->regset, _FS8))
+ ldxi_d(24, _SP_REGNO, 168);
+ if (jit_regset_tstbit(&_jitc->function->regset, _FS9))
+ ldxi_d(25, _SP_REGNO, 176);
+ if (jit_regset_tstbit(&_jitc->function->regset, _FS10))
+ ldxi_d(26, _SP_REGNO, 184);
+ if (jit_regset_tstbit(&_jitc->function->regset, _FS11))
+ ldxi_d(27, _SP_REGNO, 192);
+ addi(_SP_REGNO, _SP_REGNO, stack_framesize);
+ RET();
+}
+
+static void
+_vastart(jit_state_t *_jit, int32_t r0)
+{
+ assert(_jitc->function->self.call & jit_call_varargs);
+ /* Initialize va_list to the first stack argument. */
+ if (jit_arg_reg_p(_jitc->function->vagp))
+ addi(r0, _FP_REGNO, stack_framesize - ((8 - _jitc->function->vagp) * 8));
+ else
+ addi(r0, _FP_REGNO, _jitc->function->self.size);
+}
+
+static void
+_vaarg(jit_state_t *_jit, int32_t r0, int32_t r1)
+{
+ assert(_jitc->function->self.call & jit_call_varargs);
+ /* Load argument. */
+ ldr(r0, r1);
+ /* Update va_list. */
+ addi(r1, r1, sizeof(jit_word_t));
+}
+
+static void
+_patch_at(jit_state_t *_jit, jit_word_t instr, jit_word_t label)
+{
+ instr_t i;
+ union {
+ int32_t *i;
+ jit_word_t w;
+ } u;
+ u.w = instr;
+ i.w = u.i[0];
+ /* movi_p? */
+ if (i.U.opcode == 55) { /* LUI */
+ int32_t ww = label << 32 >> 32;
+ int32_t lo = ww << 20 >> 20;
+ int32_t hi = ww - lo;
+ i.U.imm12_31 = hi >> 12;
+ u.i[0] = i.w;
+ i.w = u.i[1];
+ if (i.I.opcode == 27 && i.I.funct3 == 0) { /* ADDIW */
+ i.I.imm11_0 = lo & 0xfff;
+ u.i[1] = i.w;
+ i.w = u.i[2];
+ if (i.U.opcode == 55) { /* LUI */
+ ww = label >> 32;
+ lo = ww << 20 >> 20;
+ hi = ww - lo;
+ i.U.imm12_31 = hi >> 12;
+ u.i[2] = i.w;
+ i.w = u.i[3];
+ if (i.I.opcode == 27 && i.I.funct3 == 0) { /* ADDIW */
+ i.I.imm11_0 = lo & 0xfff;
+ u.i[3] = i.w;
+ i.w = u.i[4];
+ assert(i.IS.opcode == 19); /* SLLI */
+ assert(i.IS.shamt == 32);
+ i.w = u.i[5];
+ assert(i.R.opcode == 51); /* ADD */
+ }
+ else
+ abort();
+ }
+ else
+ abort();
+ }
+ else
+ abort();
+ }
+ /* b{lt,le,eq,ge,gt,ne}{,_u}? */
+ else if (i.B.opcode == 99) { /* B{EQ,NE,LT,GE,LTU,GEU} */
+ jit_word_t jmp = label - instr;
+ assert(simm12_p(jmp));
+ i.B.imm11 = (jmp >> 11) & 0x1;
+ i.B.imm4_1 = (jmp >> 1) & 0xf;
+ i.B.imm10_5 = (jmp >> 5) & 0x3f;
+ i.B.imm12 = (jmp >> 12) & 0x1;
+ u.i[0] = i.w;
+ }
+ else if (i.J.opcode == 111) { /* JAL */
+ jit_word_t jmp = label - instr;
+ i.J.imm19_12 = (jmp >> 12) & 0xff;
+ i.J.imm11 = (jmp >> 11) & 0x1;
+ i.J.imm10_1 = (jmp >> 1) & 0x3ff;
+ i.J.imm20 = (jmp >> 20) & 0x1;
+ u.i[0] = i.w;
+ }
+ else
+ abort();
+}
+#endif /* CODE */
diff --git a/lightening/riscv-fpu.c b/lightening/riscv-fpu.c
new file mode 100644
index 0000000..367975e
--- /dev/null
+++ b/lightening/riscv-fpu.c
@@ -0,0 +1,1271 @@
+/*
+ * Copyright (C) 2019 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
+/*
+ * RV32F Standard Extension
+ */
+# define FLW(rd, rs1, im) Itype(7, rd, 2, rs1, im)
+# define FSW(rs1, rs2, imm) Stype(39, 2, rs1, rs2, imm)
+# define FMADD_S(rd, rs1, rs2, rs3) R4type(67, rd, 0, rs1, rs2, 0, rs3)
+# define FMSUB_S(rd, rs1, rs2, rs3) R4type(71, rd, 0, rs1, rs2, 0, rs3)
+# define FNMSUB_S(rd, rs1, rs2, rs3) R4type(75, rd, 0, rs1, rs2, 0, rs3)
+# define FNMADD_S(rd, rs1, rs2, rs3) R4type(79, rd, 0, rs1, rs2, 0, rs3)
+# define FADD_S(rd, rs1, rs2) Rtype(83, rd, 0, rs1, rs2, 0)
+# define FSUB_S(rd, rs1, rs2) Rtype(83, rd, 0, rs1, rs2, 4)
+# define FMUL_S(rd, rs1, rs2) Rtype(83, rd, 0, rs1, rs2, 8)
+# define FDIV_S(rd, rs1, rs2) Rtype(83, rd, 0, rs1, rs2, 12)
+# define FSQRT_S(rd, rs1) Rtype(83, rd, 0, rs1, 0, 44)
+# define FSGNJ_S(rd, rs1, rs2) Rtype(83, rd, 0, rs1, rs2, 16)
+# define FSGNJN_S(rd, rs1, rs2) Rtype(83, rd, 1, rs1, rs2, 16)
+# define FSGNJX_S(rd, rs1, rs2) Rtype(83, rd, 2, rs1, rs2, 16)
+# define FMIN_S(rd, rs1, rs2) Rtype(83, rd, 0, rs1, rs2, 20)
+# define FMAX_S(rd, rs1, rs2) Rtype(83, rd, 1, rs1, rs2, 20)
+# define FCVT_W_S(rd, rs1) Rtype(83, rd, 0, rs1, 0, 96)
+# define FCVT_WU_S(rd, rs1) Rtype(83, rd, 1, rs1, 1, 96)
+# define FMV_X_W(rd, rs1) Rtype(83, rd, 0, rs1, 0, 112)
+# define FEQ_S(rd, rs1, rs2) Rtype(83, rd, 2, rs1, rs2, 80)
+# define FLT_S(rd, rs1, rs2) Rtype(83, rd, 1, rs1, rs2, 80)
+# define FLE_S(rd, rs1, rs2) Rtype(83, rd, 0, rs1, rs2, 80)
+# define FCLASS_S(rd, rs1) Rtype(83, rd, 1, rs1, 0, 112)
+# define FCVT_S_W(rd, rs1) Rtype(83, rd, 0, rs1, 0, 104)
+# define FCVT_S_WU(rd, rs1) Rtype(83, rd, 0, rs1, 1, 104)
+# define FMV_W_X(rd, rs1) Rtype(83, rd, 0, rs1, 0, 120)
+/*
+ * RV64F Standard Extension (in addition to RV32F)
+ */
+# define FCVT_L_S(rd, rs1) Rtype(83, rd, 0, rs1, 2, 96)
+# define FCVT_LU_S(rd, rs1) Rtype(83, rd, 0, rs1, 3, 96)
+# define FCVT_S_L(rd, rs1) Rtype(83, rd, 0, rs1, 2, 104)
+# define FCVT_S_LU(rd, rs1) Rtype(83, rd, 0, rs1, 3, 104)
+/*
+ * RV32D Standard Extension
+ */
+# define FLD(rd, rs1, im) Itype(7, rd, 3, rs1, im)
+# define FSD(rs1, rs2, imm) Stype(39, 3, rs1, rs2, imm)
+# define FMADD_D(rd, rs1, rs2, rs3) R4type(67, rd, 0, rs1, rs2, 1, rs3)
+# define FMSUB_D(rd, rs1, rs2, rs3) R4type(71, rd, 0, rs1, rs2, 1, rs3)
+# define FNMSUB_D(rd, rs1, rs2, rs3) R4type(75, rd, 0, rs1, rs2, 1, rs3)
+# define FNMADD_D(rd, rs1, rs2, rs3) R4type(79, rd, 0, rs1, rs2, 1, rs3)
+# define FADD_D(rd, rs1, rs2) Rtype(83, rd, 0, rs1, rs2, 1)
+# define FSUB_D(rd, rs1, rs2) Rtype(83, rd, 0, rs1, rs2, 5)
+# define FMUL_D(rd, rs1, rs2) Rtype(83, rd, 0, rs1, rs2, 9)
+# define FDIV_D(rd, rs1, rs2) Rtype(83, rd, 0, rs1, rs2, 13)
+# define FSQRT_D(rd, rs1) Rtype(83, rd, 0, rs1, 0, 45)
+# define FSGNJ_D(rd, rs1, rs2) Rtype(83, rd, 0, rs1, rs2, 17)
+# define FSGNJN_D(rd, rs1, rs2) Rtype(83, rd, 1, rs1, rs2, 17)
+# define FSGNJX_D(rd, rs1, rs2) Rtype(83, rd, 2, rs1, rs2, 17)
+# define FMIN_D(rd, rs1, rs2) Rtype(83, rd, 0, rs1, rs2, 21)
+# define FMAX_D(rd, rs1, rs2) Rtype(83, rd, 1, rs1, rs2, 21)
+# define FCVT_S_D(rd, rs1) Rtype(83, rd, 0, rs1, 1, 32)
+# define FCVT_D_S(rd, rs1) Rtype(83, rd, 0, rs1, 0, 33)
+# define FEQ_D(rd, rs1, rs2) Rtype(83, rd, 2, rs1, rs2, 81)
+# define FLT_D(rd, rs1, rs2) Rtype(83, rd, 1, rs1, rs2, 81)
+# define FLE_D(rd, rs1, rs2) Rtype(83, rd, 0, rs1, rs2, 81)
+# define FCLASS_D(rd, rs1) Rtype(83, rd, 1, rs1, 0, 113)
+# define FCVT_W_D(rd, rs1) Rtype(83, rd, 0, rs1, 0, 97)
+# define FCVT_WU_D(rd, rs1) Rtype(83, rd, 0, rs1, 1, 97)
+# define FCVT_D_W(rd, rs1) Rtype(83, rd, 0, rs1, 0, 105)
+# define FCVT_D_WU(rd, rs1) Rtype(83, rd, 0, rs1, 1, 105)
+/*
+ * RV64D Standard Extension (in addition to RV32D)
+ */
+# define FCVT_L_D(rd, rs1) Rtype(83, rd, 0, rs1, 2, 97)
+# define FCVT_LU_D(rd, rs1) Rtype(83, rd, 0, rs1, 3, 97)
+# define FMV_X_D(rd, rs1) Rtype(83, rd, 0, rs1, 0, 113)
+# define FCVT_D_L(rd, rs1) Rtype(83, rd, 0, rs1, 2, 105)
+# define FCVT_D_LU(rd, rs1) Rtype(83, rd, 0, rs1, 3, 105)
+# define FMV_D_X(rd, rs1) Rtype(83, rd, 0, rs1, 0, 121)
+/*
+ * Pseudo instructions
+ */
+# define FMV_S(r0, r1) FSGNJ_S(r0, r1, r1)
+# define FABS_S(r0, r1) FSGNJX_S(r0, r1, r1)
+# define FNEG_S(r0, r1) FSGNJN_S(r0, r1, r1)
+# define FMV_D(r0, r1) FSGNJ_D(r0, r1, r1)
+# define FABS_D(r0, r1) FSGNJX_D(r0, r1, r1)
+# define FNEG_D(r0, r1) FSGNJN_D(r0, r1, r1)
+
+/*
+ * Lightning instructions
+ */
+# define truncr_f_i(r0, r1) FCVT_W_S(r0, r1)
+# define truncr_d_i(r0, r1) FCVT_W_D(r0, r1)
+# define truncr_f_l(r0, r1) FCVT_L_S(r0, r1)
+# define truncr_d_l(r0, r1) FCVT_L_D(r0, r1)
+# define addr_f(r0, r1, r2) FADD_S(r0, r1, r2)
+# define addi_f(r0, r1, im) _addi_f(_jit, r0, r1, im)
+static void _addi_f(jit_state_t *_jit,jit_int32_t,jit_int32_t,jit_float32_t);
+# define subr_f(r0, r1, r2) FSUB_S(r0, r1, r2)
+# define subi_f(r0, r1, im) _subi_f(_jit, r0, r1, im)
+static void _subi_f(jit_state_t *_jit,jit_int32_t,jit_int32_t,jit_float32_t);
+# define rsbr_f(r0, r1, r2) FSUB_S(r0, r2, r1)
+# define rsbi_f(r0, r1, im) _rsbi_f(_jit, r0, r1, im)
+static void _rsbi_f(jit_state_t *_jit,jit_int32_t,jit_int32_t,jit_float32_t);
+# define mulr_f(r0, r1, r2) FMUL_S(r0, r1, r2)
+# define muli_f(r0, r1, im) _muli_f(_jit, r0, r1, im)
+static void _muli_f(jit_state_t *_jit,jit_int32_t,jit_int32_t,jit_float32_t);
+# define divr_f(r0, r1, r2) FDIV_S(r0, r1, r2)
+# define divi_f(r0, r1, im) _divi_f(_jit, r0, r1, im)
+static void _divi_f(jit_state_t *_jit,jit_int32_t,jit_int32_t,jit_float32_t);
+# define absr_f(r0, r1) FABS_S(r0, r1)
+# define negr_f(r0, r1) FNEG_S(r0, r1)
+# define sqrtr_f(r0, r1) FSQRT_S(r0, r1)
+# define extr_f(r0, r1) FCVT_S_L(r0, r1)
+# define ldr_f(r0, r1) FLW(r0, r1, 0)
+# define ldi_f(r0, im) _ldi_f(_jit, r0, im)
+static void _ldi_f(jit_state_t*, jit_int32_t, jit_word_t);
+# define ldxr_f(r0, r1, r2) _ldxr_f(_jit, r0, r1, r2)
+static void _ldxr_f(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
+# define ldxi_f(r0, r1, i0) _ldxi_f(_jit, r0, r1, i0)
+static void _ldxi_f(jit_state_t*, jit_int32_t, jit_int32_t, jit_word_t);
+# define str_f(r0, r1) FSW(r0, r1, 0)
+# define sti_f(im, r0) _sti_f(_jit, im, r0)
+static void _sti_f(jit_state_t*, jit_word_t, jit_int32_t);
+# define stxr_f(r0, r1, r2) _stxr_f(_jit, r0, r1, r2)
+static void _stxr_f(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
+# define stxi_f(im, r0, r1) _stxi_f(_jit, im, r0, r1)
+static void _stxi_f(jit_state_t*, jit_word_t, jit_int32_t, jit_int32_t);
+# define movr_f(r0, r1) FMV_S(r0, r1)
+# define movi_f(r0, im) _movi_f(_jit, r0, im)
+static void _movi_f(jit_state_t*, jit_int32_t, jit_float32_t);
+# define movr_f_w(r0, r1) FMV_X_W(r0, r1)
+# define movi_f_w(r0, im) _movi_f_w(_jit, r0, im)
+static void _movi_f_w(jit_state_t*, jit_int32_t, jit_float32_t);
+# define movr_w_f(r0, r1) FMV_W_X(r0, r1)
+# define extr_d_f(r0, r1) FCVT_S_D(r0, r1)
+# define ltr_f(r0, r1, r2) FLT_S(r0, r1, r2)
+# define lti_f(r0, r1, im) _lti_f(_jit, r0, r1, im)
+static void _lti_f(jit_state_t*, jit_int32_t, jit_int32_t, jit_float32_t);
+# define ler_f(r0, r1, r2) FLE_S(r0, r1, r2)
+# define lei_f(r0, r1, im) _lei_f(_jit, r0, r1, im)
+static void _lei_f(jit_state_t*, jit_int32_t, jit_int32_t, jit_float32_t);
+# define eqr_f(r0, r1, r2) FEQ_S(r0, r1, r2)
+# define eqi_f(r0, r1, im) _eqi_f(_jit, r0, r1, im)
+static void _eqi_f(jit_state_t*, jit_int32_t, jit_int32_t, jit_float32_t);
+# define ger_f(r0, r1, r2) FLE_S(r0, r2, r1)
+# define gei_f(r0, r1, im) _gei_f(_jit, r0, r1, im)
+static void _gei_f(jit_state_t*, jit_int32_t, jit_int32_t, jit_float32_t);
+# define gtr_f(r0, r1, r2) FLT_S(r0, r2, r1)
+# define gti_f(r0, r1, im) _gti_f(_jit, r0, r1, im)
+static void _gti_f(jit_state_t*, jit_int32_t, jit_int32_t, jit_float32_t);
+# define ner_f(r0, r1, r2) _ner_f(_jit, r0, r1, r2)
+static void _ner_f(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
+# define nei_f(r0, r1, im) _nei_f(_jit, r0, r1, im)
+static void _nei_f(jit_state_t*, jit_int32_t, jit_int32_t, jit_float32_t);
+# define unltr_f(r0, r1, r2) _unltr_f(_jit, r0, r1, r2)
+static void _unltr_f(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
+# define unlti_f(r0, r1, im) _unlti_f(_jit, r0, r1, im)
+static void _unlti_f(jit_state_t*, jit_int32_t, jit_int32_t, jit_float32_t);
+# define unler_f(r0, r1, r2) _unler_f(_jit, r0, r1, r2)
+static void _unler_f(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
+# define unlei_f(r0, r1, im) _unlei_f(_jit, r0, r1, im)
+static void _unlei_f(jit_state_t*, jit_int32_t, jit_int32_t, jit_float32_t);
+# define uneqr_f(r0, r1, r2) _uneqr_f(_jit, r0, r1, r2)
+static void _uneqr_f(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
+# define uneqi_f(r0, r1, im) _uneqi_f(_jit, r0, r1, im)
+static void _uneqi_f(jit_state_t*, jit_int32_t, jit_int32_t, jit_float32_t);
+# define unger_f(r0, r1, r2) _unger_f(_jit, r0, r1, r2)
+static void _unger_f(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
+# define ungei_f(r0, r1, im) _ungei_f(_jit, r0, r1, im)
+static void _ungei_f(jit_state_t*, jit_int32_t, jit_int32_t, jit_float32_t);
+# define ungtr_f(r0, r1, r2) _ungtr_f(_jit, r0, r1, r2)
+static void _ungtr_f(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
+# define ungti_f(r0, r1, im) _ungti_f(_jit, r0, r1, im)
+static void _ungti_f(jit_state_t*, jit_int32_t, jit_int32_t, jit_float32_t);
+# define ltgtr_f(r0, r1, r2) _ltgtr_f(_jit, r0, r1, r2)
+static void _ltgtr_f(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
+# define ltgti_f(r0, r1, im) _ltgti_f(_jit, r0, r1, im)
+static void _ltgti_f(jit_state_t*, jit_int32_t, jit_int32_t, jit_float32_t);
+# define ordr_f(r0, r1, r2) _ordr_f(_jit, r0, r1, r2)
+static void _ordr_f(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
+# define ordi_f(r0, r1, im) _ordi_f(_jit, r0, r1, im)
+static void _ordi_f(jit_state_t*, jit_int32_t, jit_int32_t, jit_float32_t);
+# define unordr_f(r0, r1, r2) _unordr_f(_jit, r0, r1, r2)
+static void _unordr_f(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
+# define unordi_f(r0, r1, im) _unordi_f(_jit, r0, r1, im)
+static void _unordi_f(jit_state_t*, jit_int32_t, jit_int32_t, jit_float32_t);
+# define bltr_f(br, r0, r1) _bltr_f(_jit,br,r0,r1)
+static jit_word_t _bltr_f(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
+# define blti_f(br, r0, im) _blti_f(_jit,br,r0,im)
+static jit_word_t _blti_f(jit_state_t*,jit_word_t,jit_int32_t,jit_float32_t);
+# define bler_f(br, r0, r1) _bler_f(_jit,br,r0,r1)
+static jit_word_t _bler_f(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
+# define blei_f(br, r0, im) _blei_f(_jit,br,r0,im)
+static jit_word_t _blei_f(jit_state_t*,jit_word_t,jit_int32_t,jit_float32_t);
+# define beqr_f(br, r0, r1) _beqr_f(_jit,br,r0,r1)
+static jit_word_t _beqr_f(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
+# define beqi_f(br, r0, im) _beqi_f(_jit,br,r0,im)
+static jit_word_t _beqi_f(jit_state_t*,jit_word_t,jit_int32_t,jit_float32_t);
+# define bger_f(br, r0, r1) _bger_f(_jit,br,r0,r1)
+static jit_word_t _bger_f(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
+# define bgei_f(br, r0, im) _bgei_f(_jit,br,r0,im)
+static jit_word_t _bgei_f(jit_state_t*,jit_word_t,jit_int32_t,jit_float32_t);
+# define bgtr_f(br, r0, r1) _bgtr_f(_jit,br,r0,r1)
+static jit_word_t _bgtr_f(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
+# define bgti_f(br, r0, im) _bgti_f(_jit,br,r0,im)
+static jit_word_t _bgti_f(jit_state_t*,jit_word_t,jit_int32_t,jit_float32_t);
+# define bner_f(br, r0, r1) _bner_f(_jit,br,r0,r1)
+static jit_word_t _bner_f(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
+# define bnei_f(br, r0, im) _bnei_f(_jit,br,r0,im)
+static jit_word_t _bnei_f(jit_state_t*,jit_word_t,jit_int32_t,jit_float32_t);
+# define bunltr_f(br, r0, r1) _bunltr_f(_jit,br,r0,r1)
+static jit_word_t _bunltr_f(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
+# define bunlti_f(br, r0, im) _bunlti_f(_jit,br,r0,im)
+static jit_word_t _bunlti_f(jit_state_t*,jit_word_t,jit_int32_t,jit_float32_t);
+# define bunler_f(br, r0, r1) _bunler_f(_jit,br,r0,r1)
+static jit_word_t _bunler_f(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
+# define bunlei_f(br, r0, im) _bunlei_f(_jit,br,r0,im)
+static jit_word_t _bunlei_f(jit_state_t*,jit_word_t,jit_int32_t,jit_float32_t);
+# define buneqr_f(br, r0, r1) _buneqr_f(_jit,br,r0,r1)
+static jit_word_t _buneqr_f(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
+# define buneqi_f(br, r0, im) _buneqi_f(_jit,br,r0,im)
+static jit_word_t _buneqi_f(jit_state_t*,jit_word_t,jit_int32_t,jit_float32_t);
+# define bunger_f(br, r0, r1) _bunger_f(_jit,br,r0,r1)
+static jit_word_t _bunger_f(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
+# define bungei_f(br, r0, im) _bungei_f(_jit,br,r0,im)
+static jit_word_t _bungei_f(jit_state_t*,jit_word_t,jit_int32_t,jit_float32_t);
+# define bungtr_f(br, r0, r1) _bungtr_f(_jit,br,r0,r1)
+static jit_word_t _bungtr_f(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
+# define bungti_f(br, r0, im) _bungti_f(_jit,br,r0,im)
+static jit_word_t _bungti_f(jit_state_t*,jit_word_t,jit_int32_t,jit_float32_t);
+# define bltgtr_f(br, r0, r1) _bltgtr_f(_jit,br,r0,r1)
+static jit_word_t _bltgtr_f(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
+# define bltgti_f(br, r0, im) _bltgti_f(_jit,br,r0,im)
+static jit_word_t _bltgti_f(jit_state_t*,jit_word_t,jit_int32_t,jit_float32_t);
+# define bordr_f(br, r0, r1) _bordr_f(_jit,br,r0,r1)
+static jit_word_t _bordr_f(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
+# define bordi_f(br, r0, im) _bordi_f(_jit,br,r0,im)
+static jit_word_t _bordi_f(jit_state_t*,jit_word_t,jit_int32_t,jit_float32_t);
+# define bunordr_f(br, r0, r1) _bunordr_f(_jit,br,r0,r1)
+static jit_word_t _bunordr_f(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
+# define bunordi_f(br, r0, im) _bunordi_f(_jit,br,r0,im)
+static jit_word_t _bunordi_f(jit_state_t*,jit_word_t,jit_int32_t,jit_float32_t);
+# define addr_d(r0, r1, r2) FADD_D(r0, r1, r2)
+# define addi_d(r0, r1, im) _addi_d(_jit, r0, r1, im)
+static void _addi_d(jit_state_t *_jit,jit_int32_t,jit_int32_t,jit_float64_t);
+# define subr_d(r0, r1, r2) FSUB_D(r0, r1, r2)
+# define subi_d(r0, r1, im) _subi_d(_jit, r0, r1, im)
+static void _subi_d(jit_state_t *_jit,jit_int32_t,jit_int32_t,jit_float64_t);
+# define rsbr_d(r0, r1, r2) FSUB_D(r0, r2, r1)
+# define rsbi_d(r0, r1, im) _rsbi_d(_jit, r0, r1, im)
+static void _rsbi_d(jit_state_t *_jit,jit_int32_t,jit_int32_t,jit_float64_t);
+# define mulr_d(r0, r1, r2) FMUL_D(r0, r1, r2)
+# define muli_d(r0, r1, im) _muli_d(_jit, r0, r1, im)
+static void _muli_d(jit_state_t *_jit,jit_int32_t,jit_int32_t,jit_float64_t);
+# define divr_d(r0, r1, r2) FDIV_D(r0, r1, r2)
+# define divi_d(r0, r1, im) _divi_d(_jit, r0, r1, im)
+static void _divi_d(jit_state_t *_jit,jit_int32_t,jit_int32_t,jit_float64_t);
+# define absr_d(r0, r1) FABS_D(r0, r1)
+# define negr_d(r0, r1) FNEG_D(r0, r1)
+# define sqrtr_d(r0, r1) FSQRT_D(r0, r1)
+# define extr_d(r0, r1) FCVT_D_L(r0, r1)
+# define ldr_d(r0, r1) FLD(r0, r1, 0)
+# define ldi_d(r0, im) _ldi_d(_jit, r0, im)
+static void _ldi_d(jit_state_t*, jit_int32_t, jit_word_t);
+# define ldxr_d(r0, r1, r2) _ldxr_d(_jit, r0, r1, r2)
+static void _ldxr_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
+# define ldxi_d(r0, r1, i0) _ldxi_d(_jit, r0, r1, i0)
+static void _ldxi_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_word_t);
+# define str_d(r0, r1) FSD(r0, r1, 0)
+# define sti_d(im, r0) _sti_d(_jit, im, r0)
+static void _sti_d(jit_state_t*, jit_word_t, jit_int32_t);
+# define stxr_d(r0, r1, r2) _stxr_d(_jit, r0, r1, r2)
+static void _stxr_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
+# define stxi_d(im, r0, r1) _stxi_d(_jit, im, r0, r1)
+static void _stxi_d(jit_state_t*, jit_word_t, jit_int32_t, jit_int32_t);
+# define movr_d(r0, r1) FMV_D(r0, r1)
+# define movi_d(r0, im) _movi_d(_jit, r0, im)
+static void _movi_d(jit_state_t*, jit_int32_t, jit_float64_t);
+# define movr_d_w(r0, r1) FMV_X_D(r0, r1)
+# define movi_d_w(r0, im) _movi_d_w(_jit, r0, im)
+static void _movi_d_w(jit_state_t*, jit_int32_t, jit_float64_t);
+# define movr_w_d(r0, r1) FMV_D_X(r0, r1)
+# define extr_f_d(r0, r1) FCVT_D_S(r0, r1)
+# define ltr_d(r0, r1, r2) FLT_D(r0, r1, r2)
+# define lti_d(r0, r1, r2) _lti_d(_jit, r0, r1, r2)
+static void _lti_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_float64_t);
+# define ler_d(r0, r1, r2) FLE_D(r0, r1, r2)
+# define lei_d(r0, r1, r2) _lei_d(_jit, r0, r1, r2)
+static void _lei_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_float64_t);
+# define eqr_d(r0, r1, r2) FEQ_D(r0, r1, r2)
+# define eqi_d(r0, r1, r2) _eqi_d(_jit, r0, r1, r2)
+static void _eqi_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_float64_t);
+# define ger_d(r0, r1, r2) FLE_D(r0, r2, r1)
+# define gei_d(r0, r1, r2) _gei_d(_jit, r0, r1, r2)
+static void _gei_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_float64_t);
+# define gtr_d(r0, r1, r2) FLT_D(r0, r2, r1)
+# define gti_d(r0, r1, r2) _gti_d(_jit, r0, r1, r2)
+static void _gti_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_float64_t);
+# define ner_d(r0, r1, r2) _ner_d(_jit, r0, r1, r2)
+static void _ner_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
+# define nei_d(r0, r1, r2) _nei_d(_jit, r0, r1, r2)
+static void _nei_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_float64_t);
+# define unltr_d(r0, r1, r2) _unltr_d(_jit, r0, r1, r2)
+static void _unltr_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
+# define unlti_d(r0, r1, im) _unlti_d(_jit, r0, r1, im)
+static void _unlti_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_float64_t);
+# define unler_d(r0, r1, r2) _unler_d(_jit, r0, r1, r2)
+static void _unler_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
+# define unlei_d(r0, r1, im) _unlei_d(_jit, r0, r1, im)
+static void _unlei_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_float64_t);
+# define uneqr_d(r0, r1, r2) _uneqr_d(_jit, r0, r1, r2)
+static void _uneqr_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
+# define uneqi_d(r0, r1, im) _uneqi_d(_jit, r0, r1, im)
+static void _uneqi_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_float64_t);
+# define unger_d(r0, r1, r2) _unger_d(_jit, r0, r1, r2)
+static void _unger_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
+# define ungei_d(r0, r1, im) _ungei_d(_jit, r0, r1, im)
+static void _ungei_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_float64_t);
+# define ungtr_d(r0, r1, r2) _ungtr_d(_jit, r0, r1, r2)
+static void _ungtr_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
+# define ungti_d(r0, r1, im) _ungti_d(_jit, r0, r1, im)
+static void _ungti_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_float64_t);
+# define ltgtr_d(r0, r1, r2) _ltgtr_d(_jit, r0, r1, r2)
+static void _ltgtr_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
+# define ltgti_d(r0, r1, im) _ltgti_d(_jit, r0, r1, im)
+static void _ltgti_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_float64_t);
+# define ordr_d(r0, r1, r2) _ordr_d(_jit, r0, r1, r2)
+static void _ordr_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
+# define ordi_d(r0, r1, im) _ordi_d(_jit, r0, r1, im)
+static void _ordi_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_float64_t);
+# define unordr_d(r0, r1, r2) _unordr_d(_jit, r0, r1, r2)
+static void _unordr_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
+# define unordi_d(r0, r1, im) _unordi_d(_jit, r0, r1, im)
+static void _unordi_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_float64_t);
+# define bltr_d(br, r0, r1) _bltr_d(_jit,br,r0,r1)
+static jit_word_t _bltr_d(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
+# define blti_d(br, r0, im) _blti_d(_jit,br,r0,im)
+static jit_word_t _blti_d(jit_state_t*,jit_word_t,jit_int32_t,jit_float64_t);
+# define bler_d(br, r0, r1) _bler_d(_jit,br,r0,r1)
+static jit_word_t _bler_d(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
+# define blei_d(br, r0, im) _blei_d(_jit,br,r0,im)
+static jit_word_t _blei_d(jit_state_t*,jit_word_t,jit_int32_t,jit_float64_t);
+# define beqr_d(br, r0, r1) _beqr_d(_jit,br,r0,r1)
+static jit_word_t _beqr_d(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
+# define beqi_d(br, r0, im) _beqi_d(_jit,br,r0,im)
+static jit_word_t _beqi_d(jit_state_t*,jit_word_t,jit_int32_t,jit_float64_t);
+# define bger_d(br, r0, r1) _bger_d(_jit,br,r0,r1)
+static jit_word_t _bger_d(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
+# define bgei_d(br, r0, im) _bgei_d(_jit,br,r0,im)
+static jit_word_t _bgei_d(jit_state_t*,jit_word_t,jit_int32_t,jit_float64_t);
+# define bgtr_d(br, r0, r1) _bgtr_d(_jit,br,r0,r1)
+static jit_word_t _bgtr_d(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
+# define bgti_d(br, r0, im) _bgti_d(_jit,br,r0,im)
+static jit_word_t _bgti_d(jit_state_t*,jit_word_t,jit_int32_t,jit_float64_t);
+# define bner_d(br, r0, r1) _bner_d(_jit,br,r0,r1)
+static jit_word_t _bner_d(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
+# define bnei_d(br, r0, im) _bnei_d(_jit,br,r0,im)
+static jit_word_t _bnei_d(jit_state_t*,jit_word_t,jit_int32_t,jit_float64_t);
+# define bunltr_d(br, r0, r1) _bunltr_d(_jit,br,r0,r1)
+static jit_word_t _bunltr_d(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
+# define bunlti_d(br, r0, im) _bunlti_d(_jit,br,r0,im)
+static jit_word_t _bunlti_d(jit_state_t*,jit_word_t,jit_int32_t,jit_float64_t);
+# define bunler_d(br, r0, r1) _bunler_d(_jit,br,r0,r1)
+static jit_word_t _bunler_d(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
+# define bunlei_d(br, r0, im) _bunlei_d(_jit,br,r0,im)
+static jit_word_t _bunlei_d(jit_state_t*,jit_word_t,jit_int32_t,jit_float64_t);
+# define buneqr_d(br, r0, r1) _buneqr_d(_jit,br,r0,r1)
+static jit_word_t _buneqr_d(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
+# define buneqi_d(br, r0, im) _buneqi_d(_jit,br,r0,im)
+static jit_word_t _buneqi_d(jit_state_t*,jit_word_t,jit_int32_t,jit_float64_t);
+# define bunger_d(br, r0, r1) _bunger_d(_jit,br,r0,r1)
+static jit_word_t _bunger_d(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
+# define bungei_d(br, r0, im) _bungei_d(_jit,br,r0,im)
+static jit_word_t _bungei_d(jit_state_t*,jit_word_t,jit_int32_t,jit_float64_t);
+# define bungtr_d(br, r0, r1) _bungtr_d(_jit,br,r0,r1)
+static jit_word_t _bungtr_d(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
+# define bungti_d(br, r0, im) _bungti_d(_jit,br,r0,im)
+static jit_word_t _bungti_d(jit_state_t*,jit_word_t,jit_int32_t,jit_float64_t);
+# define bltgtr_d(br, r0, r1) _bltgtr_d(_jit,br,r0,r1)
+static jit_word_t _bltgtr_d(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
+# define bltgti_d(br, r0, im) _bltgti_d(_jit,br,r0,im)
+static jit_word_t _bltgti_d(jit_state_t*,jit_word_t,jit_int32_t,jit_float64_t);
+# define bordr_d(br, r0, r1) _bordr_d(_jit,br,r0,r1)
+static jit_word_t _bordr_d(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
+# define bordi_d(br, r0, im) _bordi_d(_jit,br,r0,im)
+static jit_word_t _bordi_d(jit_state_t*,jit_word_t,jit_int32_t,jit_float64_t);
+# define bunordr_d(br, r0, r1) _bunordr_d(_jit,br,r0,r1)
+static jit_word_t _bunordr_d(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
+# define bunordi_d(br, r0, im) _bunordi_d(_jit,br,r0,im)
+static jit_word_t _bunordi_d(jit_state_t*,jit_word_t,jit_int32_t,jit_float64_t);
+# define vaarg_d(r0, r1) _vaarg_d(_jit, r0, r1)
+static void _vaarg_d(jit_state_t*, jit_int32_t, jit_int32_t);
+#endif /* PROTO */
+
+#if CODE
+# define fpr_opi(name, type, size) \
+static void \
+_##name##i_##type(jit_state_t *_jit, \
+ jit_int32_t r0, jit_int32_t r1, \
+ jit_float##size##_t i0) \
+{ \
+ jit_int32_t reg = jit_get_reg(jit_class_fpr); \
+ movi_##type(rn(reg), i0); \
+ name##r_##type(r0, r1, rn(reg)); \
+ jit_unget_reg(reg); \
+}
+# define fopi(name) fpr_opi(name, f, 32)
+# define dopi(name) fpr_opi(name, d, 64)
+
+fopi(add)
+fopi(sub)
+fopi(rsb)
+fopi(mul)
+fopi(div)
+
+static void
+_ldi_f(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
+{
+ jit_int32_t t0;
+ if (simm12_p(i0))
+ FLW(r0, _ZERO_REGNO, i0);
+ else {
+ t0 = jit_get_reg(jit_class_gpr);
+ movi(rn(t0), i0);
+ ldr_f(r0, rn(t0));
+ jit_unget_reg(t0);
+ }
+}
+
+static void
+_ldxr_f(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr);
+ addr(rn(t0), r1, r2);
+ ldr_f(r0, rn(t0));
+ jit_unget_reg(t0);
+}
+
+static void
+_ldxi_f(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
+{
+ jit_int32_t t0;
+ if (simm12_p(i0))
+ FLW(r0, r1, i0);
+ else {
+ t0 = jit_get_reg(jit_class_gpr);
+ addi(rn(t0), r1, i0);
+ ldr_f(r0, rn(t0));
+ jit_unget_reg(t0);
+ }
+}
+
+static void
+_sti_f(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0)
+{
+ jit_int32_t t0;
+ if (simm12_p(i0))
+ FSW(r0, _ZERO_REGNO, i0);
+ else {
+ t0 = jit_get_reg(jit_class_gpr);
+ movi(rn(t0), i0);
+ str_f(rn(t0), r0);
+ jit_unget_reg(t0);
+ }
+}
+
+static void
+_stxr_f(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr);
+ addr(rn(t0), r0, r1);
+ str_f(rn(t0), r2);
+ jit_unget_reg(t0);
+}
+
+static void
+_stxi_f(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
+{
+ jit_int32_t t0;
+ if (simm12_p(i0))
+ FSW(r0, r1, i0);
+ else {
+ t0 = jit_get_reg(jit_class_gpr);
+ addi(rn(t0), r0, i0);
+ str_f(rn(t0), r1);
+ jit_unget_reg(t0);
+ }
+}
+
+static void
+_movi_f(jit_state_t *_jit, jit_int32_t r0, jit_float32_t i0)
+{
+ union {
+ jit_int32_t i;
+ jit_float32_t f;
+ } data;
+ jit_int32_t reg;
+ data.f = i0;
+ if (data.i == 0)
+ movr_w_f(r0, _ZERO_REGNO);
+ else {
+ reg = jit_get_reg(jit_class_gpr);
+ movi(rn(reg), data.i);
+ movr_w_f(r0, rn(reg));
+ jit_unget_reg(reg);
+ }
+}
+
+static void
+_movi_f_w(jit_state_t *_jit, jit_int32_t r0, jit_float32_t i0)
+{
+ union {
+ jit_int32_t i;
+ jit_float32_t f;
+ } data;
+ data.f = i0;
+ movi(r0, data.i);
+}
+
+fopi(lt)
+fopi(le)
+fopi(eq)
+fopi(ge)
+fopi(gt)
+
+static void
+_ner_f(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
+{
+ eqr_f(r0, r1, r2);
+ xori(r0, r0, 1);
+}
+fopi(ne)
+
+# define fpr_bopi(name, type, size) \
+static jit_word_t \
+_b##name##i_##type(jit_state_t *_jit, \
+ jit_word_t i0, jit_int32_t r0, \
+ jit_float##size##_t i1) \
+{ \
+ jit_word_t word; \
+ jit_int32_t reg = jit_get_reg(jit_class_fpr| \
+ jit_class_nospill); \
+ movi_##type(rn(reg), i1); \
+ word = b##name##r_##type(i0, r0, rn(reg)); \
+ jit_unget_reg(reg); \
+ return (word); \
+}
+# define fbopi(name) fpr_bopi(name, f, 32)
+# define dbopi(name) fpr_bopi(name, d, 64)
+
+# define unop(CLASS, OP) \
+ jit_word_t w; \
+ jit_int32_t t0, t1; \
+ t0 = jit_get_reg(jit_class_gpr); \
+ FCLASS_##CLASS(rn(t0), r1); \
+ t1 = jit_get_reg(jit_class_gpr); \
+ FCLASS_##CLASS(rn(t1), r2); \
+ orr(rn(t0), rn(t0), rn(t1)); \
+ jit_unget_reg(t1); \
+ rshi(rn(t0), rn(t0), 8); \
+ ltr(r0, _ZERO_REGNO, rn(t0)); \
+ jit_unget_reg(t0); \
+ w = _jit->pc.w; \
+ BLT(_ZERO_REGNO, r0, 0); \
+ OP(r0, r1, r2); \
+ patch_at(w, _jit->pc.w)
+
+static void
+_unltr_f(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
+{
+ unop(S, ltr_f);
+}
+fopi(unlt)
+
+static void
+_unler_f(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
+{
+ unop(S, ler_f);
+}
+fopi(unle)
+
+static void
+_uneqr_f(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
+{
+ unop(S, eqr_f);
+}
+fopi(uneq)
+
+static void
+_unger_f(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
+{
+ unop(S, ger_f);
+}
+fopi(unge)
+
+static void
+_ungtr_f(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
+{
+ unop(S, gtr_f);
+}
+fopi(ungt)
+
+static void
+_ltgtr_f(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_word_t w0, w1;
+ jit_int32_t t0, t1;
+ t0 = jit_get_reg(jit_class_gpr);
+ FCLASS_S(rn(t0), r1);
+ t1 = jit_get_reg(jit_class_gpr);
+ FCLASS_S(rn(t1), r2);
+ orr(rn(t0), rn(t0), rn(t1));
+ jit_unget_reg(t1);
+ rshi(rn(t0), rn(t0), 8);
+ ltr(r0, _ZERO_REGNO, rn(t0));
+ jit_unget_reg(t0);
+ w0 = _jit->pc.w;
+ BEQ(_ZERO_REGNO, r0, 0);
+ movr(r0, _ZERO_REGNO);
+ w1 = _jit->pc.w;
+ JAL(_ZERO_REGNO, 0);
+ patch_at(w0, _jit->pc.w);
+ ner_f(r0, r1, r2);
+ patch_at(w1, _jit->pc.w);
+}
+fopi(ltgt)
+
+static void
+_ordr_f(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_int32_t t0, t1;
+ t0 = jit_get_reg(jit_class_gpr);
+ FCLASS_S(rn(t0), r1);
+ t1 = jit_get_reg(jit_class_gpr);
+ FCLASS_S(rn(t1), r2);
+ orr(rn(t0), rn(t0), rn(t1));
+ jit_unget_reg(t1);
+ rshi(rn(t0), rn(t0), 8);
+ eqr(r0, _ZERO_REGNO, rn(t0));
+ jit_unget_reg(t0);
+}
+fopi(ord)
+
+static void
+_unordr_f(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_int32_t t0, t1;
+ t0 = jit_get_reg(jit_class_gpr);
+ FCLASS_S(rn(t0), r1);
+ t1 = jit_get_reg(jit_class_gpr);
+ FCLASS_S(rn(t1), r2);
+ orr(rn(t0), rn(t0), rn(t1));
+ jit_unget_reg(t1);
+ rshi(rn(t0), rn(t0), 8);
+ ltr(r0, _ZERO_REGNO, rn(t0));
+ jit_unget_reg(t0);
+}
+fopi(unord)
+
+static jit_word_t
+_bltr_f(jit_state_t *_jit, jit_word_t i0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_word_t w;
+ jit_int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ ltr_f(rn(t0), r1, r2);
+ w = bner(i0, _ZERO_REGNO, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+fbopi(lt)
+
+static jit_word_t
+_bler_f(jit_state_t *_jit, jit_word_t i0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_word_t w;
+ jit_int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ ler_f(rn(t0), r1, r2);
+ w = bner(i0, _ZERO_REGNO, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+fbopi(le)
+
+static jit_word_t
+_beqr_f(jit_state_t *_jit, jit_word_t i0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_word_t w;
+ jit_int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ eqr_f(rn(t0), r1, r2);
+ w = bner(i0, _ZERO_REGNO, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+fbopi(eq)
+
+static jit_word_t
+_bger_f(jit_state_t *_jit, jit_word_t i0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_word_t w;
+ jit_int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ ger_f(rn(t0), r1, r2);
+ w = bner(i0, _ZERO_REGNO, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+fbopi(ge)
+
+static jit_word_t
+_bgtr_f(jit_state_t *_jit, jit_word_t i0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_word_t w;
+ jit_int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ gtr_f(rn(t0), r1, r2);
+ w = bner(i0, _ZERO_REGNO, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+fbopi(gt)
+
+static jit_word_t
+_bner_f(jit_state_t *_jit, jit_word_t i0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_word_t w;
+ jit_int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ eqr_f(rn(t0), r1, r2);
+ w = beqr(i0, _ZERO_REGNO, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+fbopi(ne)
+
+static jit_word_t
+_bunltr_f(jit_state_t *_jit, jit_word_t i0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_word_t w;
+ jit_int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ unltr_f(rn(t0), r1, r2);
+ w = bner(i0, _ZERO_REGNO, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+fbopi(unlt)
+
+static jit_word_t
+_bunler_f(jit_state_t *_jit, jit_word_t i0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_word_t w;
+ jit_int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ unler_f(rn(t0), r1, r2);
+ w = bner(i0, _ZERO_REGNO, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+fbopi(unle)
+
+static jit_word_t
+_buneqr_f(jit_state_t *_jit, jit_word_t i0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_word_t w;
+ jit_int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ uneqr_f(rn(t0), r1, r2);
+ w = bner(i0, _ZERO_REGNO, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+fbopi(uneq)
+
+static jit_word_t
+_bunger_f(jit_state_t *_jit, jit_word_t i0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_word_t w;
+ jit_int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ unger_f(rn(t0), r1, r2);
+ w = bner(i0, _ZERO_REGNO, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+fbopi(unge)
+
+static jit_word_t
+_bungtr_f(jit_state_t *_jit, jit_word_t i0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_word_t w;
+ jit_int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ ungtr_f(rn(t0), r1, r2);
+ w = bner(i0, _ZERO_REGNO, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+fbopi(ungt)
+
+static jit_word_t
+_bltgtr_f(jit_state_t *_jit, jit_word_t i0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_word_t w;
+ jit_int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ ltgtr_f(rn(t0), r1, r2);
+ w = bner(i0, _ZERO_REGNO, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+fbopi(ltgt)
+
+static jit_word_t
+_bordr_f(jit_state_t *_jit, jit_word_t i0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_word_t w;
+ jit_int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ ordr_f(rn(t0), r1, r2);
+ w = bner(i0, _ZERO_REGNO, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+fbopi(ord)
+
+static jit_word_t
+_bunordr_f(jit_state_t *_jit, jit_word_t i0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_word_t w;
+ jit_int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ unordr_f(rn(t0), r1, r2);
+ w = bner(i0, _ZERO_REGNO, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+fbopi(unord)
+
+dopi(add)
+dopi(sub)
+dopi(rsb)
+dopi(mul)
+dopi(div)
+
+static void
+_ldi_d(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
+{
+ jit_int32_t t0;
+ if (simm12_p(i0))
+ FLD(r0, _ZERO_REGNO, i0);
+ else {
+ t0 = jit_get_reg(jit_class_gpr);
+ movi(rn(t0), i0);
+ ldr_d(r0, rn(t0));
+ jit_unget_reg(t0);
+ }
+}
+
+static void
+_ldxr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr);
+ addr(rn(t0), r1, r2);
+ ldr_d(r0, rn(t0));
+ jit_unget_reg(t0);
+}
+
+static void
+_ldxi_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
+{
+ jit_int32_t t0;
+ if (simm12_p(i0))
+ FLD(r0, r1, i0);
+ else {
+ t0 = jit_get_reg(jit_class_gpr);
+ addi(rn(t0), r1, i0);
+ ldr_d(r0, rn(t0));
+ jit_unget_reg(t0);
+ }
+}
+
+static void
+_sti_d(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0)
+{
+ jit_int32_t t0;
+ if (simm12_p(i0))
+ FSD(r0, _ZERO_REGNO, i0);
+ else {
+ t0 = jit_get_reg(jit_class_gpr);
+ movi(rn(t0), i0);
+ str_d(rn(t0), r0);
+ jit_unget_reg(t0);
+ }
+}
+
+static void
+_stxr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr);
+ addr(rn(t0), r0, r1);
+ str_d(rn(t0), r2);
+ jit_unget_reg(t0);
+}
+
+static void
+_stxi_d(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
+{
+ jit_int32_t t0;
+ if (simm12_p(i0))
+ FSD(r0, r1, i0);
+ else {
+ t0 = jit_get_reg(jit_class_gpr);
+ addi(rn(t0), r0, i0);
+ str_d(rn(t0), r1);
+ jit_unget_reg(t0);
+ }
+}
+
+static void
+_movi_d(jit_state_t *_jit, jit_int32_t r0, jit_float64_t i0)
+{
+ union {
+ jit_word_t w;
+ jit_float64_t d;
+ } data;
+ jit_int32_t reg;
+ data.d = i0;
+ if (data.w == 0)
+ movr_w_d(r0, _ZERO_REGNO);
+ else {
+ reg = jit_get_reg(jit_class_gpr);
+ movi(rn(reg), data.w);
+ movr_w_d(r0, rn(reg));
+ jit_unget_reg(reg);
+ }
+}
+
+static void
+_movi_d_w(jit_state_t *_jit, jit_int32_t r0, jit_float64_t i0)
+{
+ union {
+ jit_int64_t l;
+ jit_float64_t d;
+ } data;
+ data.d = i0;
+ movi(r0, data.l);
+}
+
+dopi(lt)
+dopi(le)
+dopi(eq)
+dopi(ge)
+dopi(gt)
+
+static void
+_ner_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
+{
+ eqr_d(r0, r1, r2);
+ xori(r0, r0, 1);
+}
+dopi(ne)
+
+static void
+_unltr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
+{
+ unop(D, ltr_d);
+}
+dopi(unlt)
+
+static void
+_unler_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
+{
+ unop(D, ler_d);
+}
+dopi(unle)
+
+static void
+_uneqr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
+{
+ unop(D, eqr_d);
+}
+dopi(uneq)
+
+static void
+_unger_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
+{
+ unop(D, ger_d);
+}
+dopi(unge)
+
+static void
+_ungtr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
+{
+ unop(D, gtr_d);
+}
+dopi(ungt)
+
+static void
+_ltgtr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_word_t w0, w1;
+ jit_int32_t t0, t1;
+ t0 = jit_get_reg(jit_class_gpr);
+ FCLASS_D(rn(t0), r1);
+ t1 = jit_get_reg(jit_class_gpr);
+ FCLASS_D(rn(t1), r2);
+ orr(rn(t0), rn(t0), rn(t1));
+ jit_unget_reg(t1);
+ rshi(rn(t0), rn(t0), 8);
+ ltr(r0, _ZERO_REGNO, rn(t0));
+ jit_unget_reg(t0);
+ w0 = _jit->pc.w;
+ BEQ(_ZERO_REGNO, r0, 0);
+ movr(r0, _ZERO_REGNO);
+ w1 = _jit->pc.w;
+ JAL(_ZERO_REGNO, 0);
+ patch_at(w0, _jit->pc.w);
+ ner_d(r0, r1, r2);
+ patch_at(w1, _jit->pc.w);
+}
+dopi(ltgt)
+
+static void
+_ordr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_int32_t t0, t1;
+ t0 = jit_get_reg(jit_class_gpr);
+ FCLASS_D(rn(t0), r1);
+ t1 = jit_get_reg(jit_class_gpr);
+ FCLASS_D(rn(t1), r2);
+ orr(rn(t0), rn(t0), rn(t1));
+ jit_unget_reg(t1);
+ rshi(rn(t0), rn(t0), 8);
+ eqr(r0, _ZERO_REGNO, rn(t0));
+ jit_unget_reg(t0);
+}
+dopi(ord)
+
+static void
+_unordr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_int32_t t0, t1;
+ t0 = jit_get_reg(jit_class_gpr);
+ FCLASS_D(rn(t0), r1);
+ t1 = jit_get_reg(jit_class_gpr);
+ FCLASS_D(rn(t1), r2);
+ orr(rn(t0), rn(t0), rn(t1));
+ jit_unget_reg(t1);
+ rshi(rn(t0), rn(t0), 8);
+ ltr(r0, _ZERO_REGNO, rn(t0));
+ jit_unget_reg(t0);
+}
+dopi(unord)
+
+static jit_word_t
+_bltr_d(jit_state_t *_jit, jit_word_t i0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_word_t w;
+ jit_int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ ltr_d(rn(t0), r1, r2);
+ w = bner(i0, _ZERO_REGNO, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+dbopi(lt)
+
+static jit_word_t
+_bler_d(jit_state_t *_jit, jit_word_t i0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_word_t w;
+ jit_int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ ler_d(rn(t0), r1, r2);
+ w = bner(i0, _ZERO_REGNO, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+dbopi(le)
+
+static jit_word_t
+_beqr_d(jit_state_t *_jit, jit_word_t i0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_word_t w;
+ jit_int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ eqr_d(rn(t0), r1, r2);
+ w = bner(i0, _ZERO_REGNO, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+dbopi(eq)
+
+static jit_word_t
+_bger_d(jit_state_t *_jit, jit_word_t i0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_word_t w;
+ jit_int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ ger_d(rn(t0), r1, r2);
+ w = bner(i0, _ZERO_REGNO, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+dbopi(ge)
+
+static jit_word_t
+_bgtr_d(jit_state_t *_jit, jit_word_t i0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_word_t w;
+ jit_int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ gtr_d(rn(t0), r1, r2);
+ w = bner(i0, _ZERO_REGNO, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+dbopi(gt)
+
+static jit_word_t
+_bner_d(jit_state_t *_jit, jit_word_t i0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_word_t w;
+ jit_int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ eqr_d(rn(t0), r1, r2);
+ w = beqr(i0, _ZERO_REGNO, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+dbopi(ne)
+
+static jit_word_t
+_bunltr_d(jit_state_t *_jit, jit_word_t i0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_word_t w;
+ jit_int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ unltr_d(rn(t0), r1, r2);
+ w = bner(i0, _ZERO_REGNO, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+dbopi(unlt)
+
+static jit_word_t
+_bunler_d(jit_state_t *_jit, jit_word_t i0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_word_t w;
+ jit_int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ unler_d(rn(t0), r1, r2);
+ w = bner(i0, _ZERO_REGNO, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+dbopi(unle)
+
+static jit_word_t
+_buneqr_d(jit_state_t *_jit, jit_word_t i0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_word_t w;
+ jit_int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ uneqr_d(rn(t0), r1, r2);
+ w = bner(i0, _ZERO_REGNO, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+dbopi(uneq)
+
+static jit_word_t
+_bunger_d(jit_state_t *_jit, jit_word_t i0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_word_t w;
+ jit_int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ unger_d(rn(t0), r1, r2);
+ w = bner(i0, _ZERO_REGNO, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+dbopi(unge)
+
+static jit_word_t
+_bungtr_d(jit_state_t *_jit, jit_word_t i0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_word_t w;
+ jit_int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ ungtr_d(rn(t0), r1, r2);
+ w = bner(i0, _ZERO_REGNO, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+dbopi(ungt)
+
+static jit_word_t
+_bltgtr_d(jit_state_t *_jit, jit_word_t i0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_word_t w;
+ jit_int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ ltgtr_d(rn(t0), r1, r2);
+ w = bner(i0, _ZERO_REGNO, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+dbopi(ltgt)
+
+static jit_word_t
+_bordr_d(jit_state_t *_jit, jit_word_t i0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_word_t w;
+ jit_int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ ordr_d(rn(t0), r1, r2);
+ w = bner(i0, _ZERO_REGNO, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+dbopi(ord)
+
+static jit_word_t
+_bunordr_d(jit_state_t *_jit, jit_word_t i0, jit_int32_t r1, jit_int32_t r2)
+{
+ jit_word_t w;
+ jit_int32_t t0;
+ t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
+ unordr_d(rn(t0), r1, r2);
+ w = bner(i0, _ZERO_REGNO, rn(t0));
+ jit_unget_reg(t0);
+ return (w);
+}
+dbopi(unord)
+
+static void
+_vaarg_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
+{
+ assert(_jitc->function->self.call & jit_call_varargs);
+ /* Load argument. */
+ ldr_d(r0, r1);
+ /* Update va_list. */
+ addi(r1, r1, sizeof(jit_float64_t));
+}
+
+#endif /* CODE */
diff --git a/lightening/riscv-sz.c b/lightening/riscv-sz.c
new file mode 100644
index 0000000..2f1d725
--- /dev/null
+++ b/lightening/riscv-sz.c
@@ -0,0 +1,401 @@
+#if __WORDSIZE == 64
+#define JIT_INSTR_MAX 116
+ 0, /* data */
+ 0, /* live */
+ 4, /* align */
+ 0, /* save */
+ 0, /* load */
+ 0, /* #name */
+ 0, /* #note */
+ 0, /* label */
+ 112, /* prolog */
+ 0, /* ellipsis */
+ 0, /* va_push */
+ 0, /* allocai */
+ 0, /* allocar */
+ 0, /* arg */
+ 0, /* getarg_c */
+ 0, /* getarg_uc */
+ 0, /* getarg_s */
+ 0, /* getarg_us */
+ 0, /* getarg_i */
+ 0, /* getarg_ui */
+ 0, /* getarg_l */
+ 0, /* putargr */
+ 0, /* putargi */
+ 4, /* va_start */
+ 8, /* va_arg */
+ 8, /* va_arg_d */
+ 0, /* va_end */
+ 4, /* addr */
+ 20, /* addi */
+ 12, /* addcr */
+ 28, /* addci */
+ 28, /* addxr */
+ 28, /* addxi */
+ 4, /* subr */
+ 20, /* subi */
+ 12, /* subcr */
+ 28, /* subci */
+ 28, /* subxr */
+ 28, /* subxi */
+ 28, /* rsbi */
+ 4, /* mulr */
+ 20, /* muli */
+ 12, /* qmulr */
+ 24, /* qmuli */
+ 12, /* qmulr_u */
+ 24, /* qmuli_u */
+ 4, /* divr */
+ 20, /* divi */
+ 4, /* divr_u */
+ 20, /* divi_u */
+ 20, /* qdivr */
+ 16, /* qdivi */
+ 20, /* qdivr_u */
+ 16, /* qdivi_u */
+ 4, /* remr */
+ 20, /* remi */
+ 4, /* remr_u */
+ 20, /* remi_u */
+ 4, /* andr */
+ 20, /* andi */
+ 4, /* orr */
+ 20, /* ori */
+ 4, /* xorr */
+ 20, /* xori */
+ 4, /* lshr */
+ 4, /* lshi */
+ 4, /* rshr */
+ 4, /* rshi */
+ 4, /* rshr_u */
+ 4, /* rshi_u */
+ 4, /* negr */
+ 4, /* comr */
+ 4, /* ltr */
+ 4, /* lti */
+ 4, /* ltr_u */
+ 4, /* lti_u */
+ 8, /* ler */
+ 12, /* lei */
+ 8, /* ler_u */
+ 12, /* lei_u */
+ 12, /* eqr */
+ 12, /* eqi */
+ 8, /* ger */
+ 12, /* gei */
+ 8, /* ger_u */
+ 12, /* gei_u */
+ 4, /* gtr */
+ 8, /* gti */
+ 4, /* gtr_u */
+ 8, /* gti_u */
+ 8, /* ner */
+ 8, /* nei */
+ 4, /* movr */
+ 24, /* movi */
+ 8, /* extr_c */
+ 4, /* extr_uc */
+ 8, /* extr_s */
+ 8, /* extr_us */
+ 4, /* extr_i */
+ 8, /* extr_ui */
+ 20, /* htonr_us */
+ 52, /* htonr_ui */
+ 116, /* htonr_ul */
+ 4, /* ldr_c */
+ 12, /* ldi_c */
+ 4, /* ldr_uc */
+ 12, /* ldi_uc */
+ 4, /* ldr_s */
+ 12, /* ldi_s */
+ 4, /* ldr_us */
+ 12, /* ldi_us */
+ 4, /* ldr_i */
+ 12, /* ldi_i */
+ 4, /* ldr_ui */
+ 12, /* ldi_ui */
+ 4, /* ldr_l */
+ 12, /* ldi_l */
+ 8, /* ldxr_c */
+ 16, /* ldxi_c */
+ 8, /* ldxr_uc */
+ 16, /* ldxi_uc */
+ 8, /* ldxr_s */
+ 16, /* ldxi_s */
+ 8, /* ldxr_us */
+ 16, /* ldxi_us */
+ 8, /* ldxr_i */
+ 16, /* ldxi_i */
+ 8, /* ldxr_ui */
+ 16, /* ldxi_ui */
+ 8, /* ldxr_l */
+ 16, /* ldxi_l */
+ 4, /* str_c */
+ 12, /* sti_c */
+ 4, /* str_s */
+ 12, /* sti_s */
+ 4, /* str_i */
+ 12, /* sti_i */
+ 4, /* str_l */
+ 12, /* sti_l */
+ 8, /* stxr_c */
+ 16, /* stxi_c */
+ 8, /* stxr_s */
+ 16, /* stxi_s */
+ 8, /* stxr_i */
+ 16, /* stxi_i */
+ 8, /* stxr_l */
+ 16, /* stxi_l */
+ 4, /* bltr */
+ 8, /* blti */
+ 4, /* bltr_u */
+ 8, /* blti_u */
+ 4, /* bler */
+ 8, /* blei */
+ 4, /* bler_u */
+ 8, /* blei_u */
+ 4, /* beqr */
+ 28, /* beqi */
+ 4, /* bger */
+ 8, /* bgei */
+ 4, /* bger_u */
+ 8, /* bgei_u */
+ 4, /* bgtr */
+ 8, /* bgti */
+ 4, /* bgtr_u */
+ 8, /* bgti_u */
+ 4, /* bner */
+ 20, /* bnei */
+ 8, /* bmsr */
+ 12, /* bmsi */
+ 8, /* bmcr */
+ 12, /* bmci */
+ 32, /* boaddr */
+ 36, /* boaddi */
+ 16, /* boaddr_u */
+ 20, /* boaddi_u */
+ 32, /* bxaddr */
+ 36, /* bxaddi */
+ 16, /* bxaddr_u */
+ 20, /* bxaddi_u */
+ 32, /* bosubr */
+ 36, /* bosubi */
+ 16, /* bosubr_u */
+ 20, /* bosubi_u */
+ 32, /* bxsubr */
+ 36, /* bxsubi */
+ 16, /* bxsubr_u */
+ 20, /* bxsubi_u */
+ 4, /* jmpr */
+ 28, /* jmpi */
+ 4, /* callr */
+ 28, /* calli */
+ 0, /* prepare */
+ 0, /* pushargr */
+ 0, /* pushargi */
+ 0, /* finishr */
+ 0, /* finishi */
+ 0, /* ret */
+ 0, /* retr */
+ 0, /* reti */
+ 0, /* retval_c */
+ 0, /* retval_uc */
+ 0, /* retval_s */
+ 0, /* retval_us */
+ 0, /* retval_i */
+ 0, /* retval_ui */
+ 0, /* retval_l */
+ 112, /* epilog */
+ 0, /* arg_f */
+ 0, /* getarg_f */
+ 0, /* putargr_f */
+ 0, /* putargi_f */
+ 4, /* addr_f */
+ 12, /* addi_f */
+ 4, /* subr_f */
+ 12, /* subi_f */
+ 12, /* rsbi_f */
+ 4, /* mulr_f */
+ 12, /* muli_f */
+ 4, /* divr_f */
+ 12, /* divi_f */
+ 4, /* negr_f */
+ 4, /* absr_f */
+ 4, /* sqrtr_f */
+ 4, /* ltr_f */
+ 12, /* lti_f */
+ 4, /* ler_f */
+ 12, /* lei_f */
+ 4, /* eqr_f */
+ 12, /* eqi_f */
+ 4, /* ger_f */
+ 12, /* gei_f */
+ 4, /* gtr_f */
+ 12, /* gti_f */
+ 8, /* ner_f */
+ 16, /* nei_f */
+ 28, /* unltr_f */
+ 36, /* unlti_f */
+ 28, /* unler_f */
+ 36, /* unlei_f */
+ 28, /* uneqr_f */
+ 36, /* uneqi_f */
+ 28, /* unger_f */
+ 36, /* ungei_f */
+ 28, /* ungtr_f */
+ 36, /* ungti_f */
+ 40, /* ltgtr_f */
+ 48, /* ltgti_f */
+ 28, /* ordr_f */
+ 36, /* ordi_f */
+ 20, /* unordr_f */
+ 28, /* unordi_f */
+ 4, /* truncr_f_i */
+ 4, /* truncr_f_l */
+ 4, /* extr_f */
+ 4, /* extr_d_f */
+ 4, /* movr_f */
+ 8, /* movi_f */
+ 4, /* ldr_f */
+ 12, /* ldi_f */
+ 8, /* ldxr_f */
+ 16, /* ldxi_f */
+ 4, /* str_f */
+ 12, /* sti_f */
+ 8, /* stxr_f */
+ 16, /* stxi_f */
+ 8, /* bltr_f */
+ 16, /* blti_f */
+ 8, /* bler_f */
+ 16, /* blei_f */
+ 8, /* beqr_f */
+ 16, /* beqi_f */
+ 8, /* bger_f */
+ 16, /* bgei_f */
+ 8, /* bgtr_f */
+ 16, /* bgti_f */
+ 8, /* bner_f */
+ 16, /* bnei_f */
+ 32, /* bunltr_f */
+ 40, /* bunlti_f */
+ 32, /* bunler_f */
+ 40, /* bunlei_f */
+ 32, /* buneqr_f */
+ 40, /* buneqi_f */
+ 32, /* bunger_f */
+ 40, /* bungei_f */
+ 32, /* bungtr_f */
+ 40, /* bungti_f */
+ 44, /* bltgtr_f */
+ 52, /* bltgti_f */
+ 32, /* bordr_f */
+ 40, /* bordi_f */
+ 24, /* bunordr_f */
+ 32, /* bunordi_f */
+ 0, /* pushargr_f */
+ 0, /* pushargi_f */
+ 0, /* retr_f */
+ 0, /* reti_f */
+ 0, /* retval_f */
+ 0, /* arg_d */
+ 0, /* getarg_d */
+ 0, /* putargr_d */
+ 0, /* putargi_d */
+ 4, /* addr_d */
+ 24, /* addi_d */
+ 4, /* subr_d */
+ 24, /* subi_d */
+ 24, /* rsbi_d */
+ 4, /* mulr_d */
+ 24, /* muli_d */
+ 4, /* divr_d */
+ 24, /* divi_d */
+ 4, /* negr_d */
+ 4, /* absr_d */
+ 4, /* sqrtr_d */
+ 4, /* ltr_d */
+ 24, /* lti_d */
+ 4, /* ler_d */
+ 24, /* lei_d */
+ 4, /* eqr_d */
+ 24, /* eqi_d */
+ 4, /* ger_d */
+ 24, /* gei_d */
+ 4, /* gtr_d */
+ 24, /* gti_d */
+ 8, /* ner_d */
+ 28, /* nei_d */
+ 28, /* unltr_d */
+ 48, /* unlti_d */
+ 28, /* unler_d */
+ 48, /* unlei_d */
+ 28, /* uneqr_d */
+ 48, /* uneqi_d */
+ 28, /* unger_d */
+ 48, /* ungei_d */
+ 28, /* ungtr_d */
+ 48, /* ungti_d */
+ 40, /* ltgtr_d */
+ 60, /* ltgti_d */
+ 28, /* ordr_d */
+ 48, /* ordi_d */
+ 20, /* unordr_d */
+ 40, /* unordi_d */
+ 4, /* truncr_d_i */
+ 4, /* truncr_d_l */
+ 4, /* extr_d */
+ 4, /* extr_f_d */
+ 4, /* movr_d */
+ 20, /* movi_d */
+ 4, /* ldr_d */
+ 12, /* ldi_d */
+ 8, /* ldxr_d */
+ 16, /* ldxi_d */
+ 4, /* str_d */
+ 12, /* sti_d */
+ 8, /* stxr_d */
+ 16, /* stxi_d */
+ 8, /* bltr_d */
+ 28, /* blti_d */
+ 8, /* bler_d */
+ 28, /* blei_d */
+ 8, /* beqr_d */
+ 28, /* beqi_d */
+ 8, /* bger_d */
+ 28, /* bgei_d */
+ 8, /* bgtr_d */
+ 28, /* bgti_d */
+ 8, /* bner_d */
+ 28, /* bnei_d */
+ 32, /* bunltr_d */
+ 52, /* bunlti_d */
+ 32, /* bunler_d */
+ 52, /* bunlei_d */
+ 32, /* buneqr_d */
+ 52, /* buneqi_d */
+ 32, /* bunger_d */
+ 52, /* bungei_d */
+ 32, /* bungtr_d */
+ 52, /* bungti_d */
+ 44, /* bltgtr_d */
+ 64, /* bltgti_d */
+ 32, /* bordr_d */
+ 52, /* bordi_d */
+ 24, /* bunordr_d */
+ 44, /* bunordi_d */
+ 0, /* pushargr_d */
+ 0, /* pushargi_d */
+ 0, /* retr_d */
+ 0, /* reti_d */
+ 0, /* retval_d */
+ 4, /* movr_w_f */
+ 0, /* movr_ww_d */
+ 4, /* movr_w_d */
+ 0, /* movr_f_w */
+ 4, /* movi_f_w */
+ 0, /* movr_d_ww */
+ 0, /* movi_d_ww */
+ 4, /* movr_d_w */
+ 16, /* movi_d_w */
+#endif /* __WORDSIZE */
diff --git a/lightening/riscv.c b/lightening/riscv.c
new file mode 100644
index 0000000..0efca1e
--- /dev/null
+++ b/lightening/riscv.c
@@ -0,0 +1,1621 @@
+/*
+ * Copyright (C) 2019,2021 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
+ */
+
+#define JIT_RA0 _A0
+#define JIT_FA0 _FA0
+#define JIT_SP _SP
+#define JIT_RET _A0
+#define JIT_FRET _FA0
+
+#define jit_arg_reg_p(i) ((i) >= 0 && (i) < 8)
+#define jit_arg_f_reg_p(i) ((i) >= 0 && (i) < 8)
+
+/*
+ * Types
+ */
+typedef jit_pointer_t jit_va_list_t;
+
+/*
+ * Prototypes
+ */
+#define patch(instr, node) _patch(_jit, instr, node)
+static void _patch(jit_state_t*,jit_word_t,jit_node_t*);
+
+#define PROTO 1
+# include "riscv-cpu.c"
+# include "riscv-fpu.c"
+#undef PROTO
+
+/*
+ * Initialization
+ */
+static const jit_register_t _rvs[] = {
+ { 0x00, "zero" },
+ { 0x01, "ra" },
+ { 0x02, "sp" },
+ { 0x03, "gp" },
+#if 0 /* Pretend it does not exist, so _NOREG can be used in
+ * a 64 bit bitmask */
+ { 0x04, "tp" },
+#endif
+ { rc(gpr) | 0x05, "t0" },
+ { rc(gpr) | 0x06, "t1" },
+ { rc(gpr) | 0x07, "t2" },
+ { rc(gpr) | 0x1c, "t3" },
+ { rc(gpr) | 0x1d, "t4" },
+ { rc(gpr) | 0x1e, "t5" },
+ { rc(gpr) | 0x1f, "t6" },
+ { 0x08, "fp" },
+ { rc(sav) | rc(gpr) | 0x09, "s1" },
+ { rc(sav) | rc(gpr) | 0x12, "s2" },
+ { rc(sav) | rc(gpr) | 0x13, "s3" },
+ { rc(sav) | rc(gpr) | 0x14, "s4" },
+ { rc(sav) | rc(gpr) | 0x15, "s5" },
+ { rc(sav) | rc(gpr) | 0x16, "s6" },
+ { rc(sav) | rc(gpr) | 0x17, "s7" },
+ { rc(sav) | rc(gpr) | 0x18, "s8" },
+ { rc(sav) | rc(gpr) | 0x19, "s9" },
+ { rc(sav) | rc(gpr) | 0x1a, "s10" },
+ { rc(sav) | rc(gpr) | 0x1b, "s11" },
+ { rc(arg) | rc(gpr) | 0x11, "a7" },
+ { rc(arg) | rc(gpr) | 0x10, "a6" },
+ { rc(arg) | rc(gpr) | 0x0f, "a5" },
+ { rc(arg) | rc(gpr) | 0x0e, "a4" },
+ { rc(arg) | rc(gpr) | 0x0d, "a3" },
+ { rc(arg) | rc(gpr) | 0x0c, "a2" },
+ { rc(arg) | rc(gpr) | 0x0b, "a1" },
+ { rc(arg) | rc(gpr) | 0x0a, "a0" },
+ { rc(fpr) | 0x00, "ft0" },
+ { rc(fpr) | 0x01, "ft1" },
+ { rc(fpr) | 0x02, "ft2" },
+ { rc(fpr) | 0x03, "ft3" },
+ { rc(fpr) | 0x04, "ft4" },
+ { rc(fpr) | 0x05, "ft5" },
+ { rc(fpr) | 0x06, "ft6" },
+ { rc(fpr) | 0x07, "ft7" },
+ { rc(fpr) | 0x1c, "ft8" },
+ { rc(fpr) | 0x1d, "ft9" },
+ { rc(fpr) | 0x1e, "ft10" },
+ { rc(fpr) | 0x1f, "ft11" },
+ { rc(sav) | rc(fpr) | 0x08, "fs0" },
+ { rc(sav) | rc(fpr) | 0x09, "fs1" },
+ { rc(sav) | rc(fpr) | 0x12, "fs2" },
+ { rc(sav) | rc(fpr) | 0x13, "fs3" },
+ { rc(sav) | rc(fpr) | 0x14, "fs4" },
+ { rc(sav) | rc(fpr) | 0x15, "fs5" },
+ { rc(sav) | rc(fpr) | 0x16, "fs6" },
+ { rc(sav) | rc(fpr) | 0x17, "fs7" },
+ { rc(sav) | rc(fpr) | 0x18, "fs8" },
+ { rc(sav) | rc(fpr) | 0x19, "fs9" },
+ { rc(sav) | rc(fpr) | 0x1a, "fs10" },
+ { rc(sav) | rc(fpr) | 0x1b, "fs11" },
+ { rc(arg) | rc(fpr) | 0x11, "fa7" },
+ { rc(arg) | rc(fpr) | 0x10, "fa6" },
+ { rc(arg) | rc(fpr) | 0x0f, "fa5" },
+ { rc(arg) | rc(fpr) | 0x0e, "fa4" },
+ { rc(arg) | rc(fpr) | 0x0d, "fa3" },
+ { rc(arg) | rc(fpr) | 0x0c, "fa2" },
+ { rc(arg) | rc(fpr) | 0x0b, "fa1" },
+ { rc(arg) | rc(fpr) | 0x0a, "fa0" },
+ { _NOREG, "<none>" },
+};
+
+/*
+ * Implementation
+ */
+void
+jit_get_cpu(void)
+{
+}
+
+void
+_jit_init(jit_state_t *_jit)
+{
+ _jitc->reglen = jit_size(_rvs) - 1;
+ jit_carry = _NOREG;
+}
+
+void
+_jit_prolog(jit_state_t *_jit)
+{
+ int32_t offset;
+
+ if (_jitc->function)
+ jit_epilog();
+ assert(jit_regset_cmp_ui(&_jitc->regarg, 0) == 0);
+ jit_regset_set_ui(&_jitc->regsav, 0);
+ offset = _jitc->functions.offset;
+ if (offset >= _jitc->functions.length) {
+ jit_realloc((jit_pointer_t *)&_jitc->functions.ptr,
+ _jitc->functions.length * sizeof(jit_function_t),
+ (_jitc->functions.length + 16) * sizeof(jit_function_t));
+ _jitc->functions.length += 16;
+ }
+ _jitc->function = _jitc->functions.ptr + _jitc->functions.offset++;
+ _jitc->function->self.size = stack_framesize;
+ _jitc->function->self.argi = _jitc->function->self.argf =
+ _jitc->function->self.alen = 0;
+ _jitc->function->self.aoff = 0;
+ _jitc->function->self.call = jit_call_default;
+ jit_alloc((jit_pointer_t *)&_jitc->function->regoff,
+ _jitc->reglen * sizeof(int32_t));
+
+ /* _no_link here does not mean the jit_link() call can be removed
+ * by rewriting as:
+ * _jitc->function->prolog = jit_new_node(jit_code_prolog);
+ */
+ _jitc->function->prolog = jit_new_node_no_link(jit_code_prolog);
+ jit_link(_jitc->function->prolog);
+ _jitc->function->prolog->w.w = offset;
+ _jitc->function->epilog = jit_new_node_no_link(jit_code_epilog);
+ /* u: label value
+ * v: offset in blocks vector
+ * w: offset in functions vector
+ */
+ _jitc->function->epilog->w.w = offset;
+
+ jit_regset_new(&_jitc->function->regset);
+}
+
+int32_t
+_jit_allocai(jit_state_t *_jit, int32_t length)
+{
+ assert(_jitc->function);
+ switch (length) {
+ case 0: case 1: break;
+ case 2: _jitc->function->self.aoff &= -2; break;
+ case 3: case 4: _jitc->function->self.aoff &= -4; break;
+ default: _jitc->function->self.aoff &= -8; break;
+ }
+ _jitc->function->self.aoff -= length;
+ if (!_jitc->realize) {
+ jit_inc_synth_ww(allocai, _jitc->function->self.aoff, length);
+ jit_dec_synth();
+ }
+ return (_jitc->function->self.aoff);
+}
+
+void
+_jit_allocar(jit_state_t *_jit, int32_t u, int32_t v)
+{
+ int32_t r0;
+ assert(_jitc->function);
+ jit_inc_synth_ww(allocar, u, v);
+ if (!_jitc->function->allocar) {
+ _jitc->function->aoffoff = jit_allocai(sizeof(int32_t));
+ _jitc->function->allocar = 1;
+ }
+ r0 = jit_get_reg(jit_class_gpr);
+ jit_negr(r0, v);
+ jit_andi(r0, r0, -16);
+ jit_ldxi_i(u, JIT_FP, _jitc->function->aoffoff);
+ jit_addr(u, u, r0);
+ jit_addr(JIT_SP, JIT_SP, r0);
+ jit_stxi_i(_jitc->function->aoffoff, JIT_FP, u);
+ jit_unget_reg(r0);
+ jit_dec_synth();
+}
+
+void
+_jit_ret(jit_state_t *_jit)
+{
+ jit_node_t *instr;
+ assert(_jitc->function);
+ jit_inc_synth(ret);
+ /* jump to epilog */
+ instr = jit_jmpi();
+ jit_patch_at(instr, _jitc->function->epilog);
+ jit_dec_synth();
+}
+
+void
+_jit_retr(jit_state_t *_jit, int32_t u)
+{
+ jit_inc_synth_w(retr, u);
+ if (JIT_RET != u)
+ jit_movr(JIT_RET, u);
+ jit_live(JIT_RET);
+ jit_ret();
+ jit_dec_synth();
+}
+
+void
+_jit_reti(jit_state_t *_jit, jit_word_t u)
+{
+ jit_inc_synth_w(reti, u);
+ jit_movi(JIT_RET, u);
+ jit_ret();
+ jit_dec_synth();
+}
+
+void
+_jit_retr_f(jit_state_t *_jit, int32_t u)
+{
+ jit_inc_synth_w(retr_f, u);
+ if (u != JIT_FRET)
+ jit_movr_f(JIT_FRET, u);
+ else
+ jit_live(JIT_FRET);
+ jit_ret();
+ jit_dec_synth();
+}
+
+void
+_jit_reti_f(jit_state_t *_jit, jit_float32_t u)
+{
+ jit_inc_synth_f(reti_f, u);
+ jit_movi_f(JIT_FRET, u);
+ jit_ret();
+ jit_dec_synth();
+}
+
+void
+_jit_retr_d(jit_state_t *_jit, int32_t u)
+{
+ jit_inc_synth_w(retr_d, u);
+ if (u != JIT_FRET)
+ jit_movr_d(JIT_FRET, u);
+ else
+ jit_live(JIT_FRET);
+ jit_ret();
+ jit_dec_synth();
+}
+
+void
+_jit_reti_d(jit_state_t *_jit, jit_float64_t u)
+{
+ jit_inc_synth_d(reti_d, u);
+ jit_movi_d(JIT_FRET, u);
+ jit_ret();
+ jit_dec_synth();
+}
+
+void
+_jit_epilog(jit_state_t *_jit)
+{
+ assert(_jitc->function);
+ assert(_jitc->function->epilog->next == NULL);
+ jit_link(_jitc->function->epilog);
+ _jitc->function = NULL;
+}
+
+jit_bool_t
+_jit_arg_register_p(jit_state_t *_jit, jit_node_t *u)
+{
+ if (u->code == jit_code_arg)
+ return (jit_arg_reg_p(u->u.w));
+ assert(u->code == jit_code_arg_f || u->code == jit_code_arg_d);
+ return (jit_arg_f_reg_p(u->u.w));
+}
+
+void
+_jit_ellipsis(jit_state_t *_jit)
+{
+ jit_inc_synth(ellipsis);
+ if (_jitc->prepare) {
+ jit_link_prepare();
+ assert(!(_jitc->function->call.call & jit_call_varargs));
+ _jitc->function->call.call |= jit_call_varargs;
+ }
+ else {
+ jit_link_prolog();
+ assert(!(_jitc->function->self.call & jit_call_varargs));
+ _jitc->function->self.call |= jit_call_varargs;
+ _jitc->function->vagp = _jitc->function->self.argi;
+ }
+ jit_dec_synth();
+}
+
+void
+_jit_va_push(jit_state_t *_jit, int32_t u)
+{
+ jit_inc_synth_w(va_push, u);
+ jit_pushargr(u);
+ jit_dec_synth();
+}
+
+jit_node_t *
+_jit_arg(jit_state_t *_jit)
+{
+ jit_node_t *node;
+ int32_t offset;
+ assert(_jitc->function);
+ assert(!(_jitc->function->self.call & jit_call_varargs));
+ if (jit_arg_reg_p(_jitc->function->self.argi))
+ offset = _jitc->function->self.argi++;
+ else {
+ offset = _jitc->function->self.size;
+ _jitc->function->self.size += sizeof(jit_word_t);
+ }
+ node = jit_new_node_ww(jit_code_arg, offset,
+ ++_jitc->function->self.argn);
+ jit_link_prolog();
+ return (node);
+}
+
+jit_node_t *
+_jit_arg_f(jit_state_t *_jit)
+{
+ jit_node_t *node;
+ int32_t offset;
+ assert(_jitc->function);
+ assert(!(_jitc->function->self.call & jit_call_varargs));
+ if (jit_arg_f_reg_p(_jitc->function->self.argf))
+ offset = _jitc->function->self.argf++;
+ else if (jit_arg_reg_p(_jitc->function->self.argi)) {
+ offset = _jitc->function->self.argi++;
+ offset += 8;
+ }
+ else {
+ offset = _jitc->function->self.size;
+ _jitc->function->self.size += sizeof(jit_word_t);
+ }
+ node = jit_new_node_ww(jit_code_arg_f, offset,
+ ++_jitc->function->self.argn);
+ jit_link_prolog();
+ return (node);
+}
+
+jit_node_t *
+_jit_arg_d(jit_state_t *_jit)
+{
+ jit_node_t *node;
+ int32_t offset;
+ assert(_jitc->function);
+ assert(!(_jitc->function->self.call & jit_call_varargs));
+ if (jit_arg_f_reg_p(_jitc->function->self.argf))
+ offset = _jitc->function->self.argf++;
+ else if (jit_arg_reg_p(_jitc->function->self.argi)) {
+ offset = _jitc->function->self.argi++;
+ offset += 8;
+ }
+ else {
+ offset = _jitc->function->self.size;
+ _jitc->function->self.size += sizeof(jit_word_t);
+ }
+ node = jit_new_node_ww(jit_code_arg_d, offset,
+ ++_jitc->function->self.argn);
+ jit_link_prolog();
+ return (node);
+}
+
+void
+_jit_getarg_c(jit_state_t *_jit, int32_t u, jit_node_t *v)
+{
+ assert(v->code == jit_code_arg);
+ jit_inc_synth_wp(getarg_c, u, v);
+ if (jit_arg_reg_p(v->u.w))
+ jit_extr_c(u, JIT_RA0 - v->u.w);
+ else
+ jit_ldxi_c(u, JIT_FP, v->u.w);
+ jit_dec_synth();
+}
+
+void
+_jit_getarg_uc(jit_state_t *_jit, int32_t u, jit_node_t *v)
+{
+ assert(v->code == jit_code_arg);
+ jit_inc_synth_wp(getarg_uc, u, v);
+ if (jit_arg_reg_p(v->u.w))
+ jit_extr_uc(u, JIT_RA0 - v->u.w);
+ else
+ jit_ldxi_uc(u, JIT_FP, v->u.w);
+ jit_dec_synth();
+}
+
+void
+_jit_getarg_s(jit_state_t *_jit, int32_t u, jit_node_t *v)
+{
+ assert(v->code == jit_code_arg);
+ jit_inc_synth_wp(getarg_s, u, v);
+ if (jit_arg_reg_p(v->u.w))
+ jit_extr_s(u, JIT_RA0 - v->u.w);
+ else
+ jit_ldxi_s(u, JIT_FP, v->u.w);
+ jit_dec_synth();
+}
+
+void
+_jit_getarg_us(jit_state_t *_jit, int32_t u, jit_node_t *v)
+{
+ assert(v->code == jit_code_arg);
+ jit_inc_synth_wp(getarg_us, u, v);
+ if (jit_arg_reg_p(v->u.w))
+ jit_extr_us(u, JIT_RA0 - v->u.w);
+ else
+ jit_ldxi_us(u, JIT_FP, v->u.w);
+ jit_dec_synth();
+}
+
+void
+_jit_getarg_i(jit_state_t *_jit, int32_t u, jit_node_t *v)
+{
+ assert(v->code == jit_code_arg);
+ jit_inc_synth_wp(getarg_i, u, v);
+ if (jit_arg_reg_p(v->u.w))
+ jit_extr_i(u, JIT_RA0 - v->u.w);
+ else
+ jit_ldxi_i(u, JIT_FP, v->u.w);
+ jit_dec_synth();
+}
+
+void
+_jit_getarg_ui(jit_state_t *_jit, int32_t u, jit_node_t *v)
+{
+ assert(v->code == jit_code_arg);
+ jit_inc_synth_wp(getarg_ui, u, v);
+ if (jit_arg_reg_p(v->u.w))
+ jit_extr_ui(u, JIT_RA0 - v->u.w);
+ else
+ jit_ldxi_ui(u, JIT_FP, v->u.w);
+ jit_dec_synth();
+}
+
+void
+_jit_getarg_l(jit_state_t *_jit, int32_t u, jit_node_t *v)
+{
+ assert(v->code == jit_code_arg);
+ jit_inc_synth_wp(getarg_l, u, v);
+ if (jit_arg_reg_p(v->u.w))
+ jit_movr(u, JIT_RA0 - v->u.w);
+ else
+ jit_ldxi_l(u, JIT_FP, v->u.w);
+ jit_dec_synth();
+}
+
+void
+_jit_putargr(jit_state_t *_jit, int32_t u, jit_node_t *v)
+{
+ assert(v->code == jit_code_arg);
+ jit_inc_synth_wp(putargr, u, v);
+ if (jit_arg_reg_p(v->u.w))
+ jit_movr(JIT_RA0 - v->u.w, u);
+ else
+ jit_stxi(v->u.w, JIT_FP, u);
+ jit_dec_synth();
+}
+
+void
+_jit_putargi(jit_state_t *_jit, jit_word_t u, jit_node_t *v)
+{
+ int32_t regno;
+ assert(v->code == jit_code_arg);
+ jit_inc_synth_wp(putargi, u, v);
+ if (jit_arg_reg_p(v->u.w))
+ jit_movi(JIT_RA0 - v->u.w, u);
+ else {
+ regno = jit_get_reg(jit_class_gpr);
+ jit_movi(regno, u);
+ jit_stxi(v->u.w, JIT_FP, regno);
+ jit_unget_reg(regno);
+ }
+ jit_dec_synth();
+}
+
+void
+_jit_getarg_f(jit_state_t *_jit, int32_t u, jit_node_t *v)
+{
+ assert(v->code == jit_code_arg_f);
+ jit_inc_synth_wp(getarg_f, u, v);
+ if (jit_arg_f_reg_p(v->u.w))
+ jit_movr_f(u, JIT_FA0 - v->u.w);
+ else if (jit_arg_reg_p(v->u.w - 8))
+ jit_movr_w_f(u, JIT_RA0 - (v->u.w - 8));
+ else
+ jit_ldxi_f(u, JIT_FP, v->u.w);
+ jit_dec_synth();
+}
+
+void
+_jit_putargr_f(jit_state_t *_jit, int32_t u, jit_node_t *v)
+{
+ assert(v->code == jit_code_arg_f);
+ jit_inc_synth_wp(putargr_f, u, v);
+ if (jit_arg_f_reg_p(v->u.w))
+ jit_movr_f(JIT_FA0 - v->u.w, u);
+ else if (jit_arg_reg_p(v->u.w - 8))
+ jit_movr_f_w(JIT_RA0 - (v->u.w - 8), u);
+ else
+ jit_stxi_f(v->u.w, JIT_FP, u);
+ jit_dec_synth();
+}
+
+void
+_jit_putargi_f(jit_state_t *_jit, jit_float32_t u, jit_node_t *v)
+{
+ int32_t regno;
+ assert(v->code == jit_code_arg_f);
+ jit_inc_synth_fp(putargi_f, u, v);
+ if (jit_arg_f_reg_p(v->u.w))
+ jit_movi_f(JIT_FA0 - v->u.w, u);
+ else if (jit_arg_reg_p(v->u.w - 8)) {
+ union {
+ jit_float32_t f;
+ int32_t i;
+ } uu;
+ uu.f = u;
+ jit_movi(JIT_RA0 - (v->u.w - 8), uu.i);
+ }
+ else {
+ regno = jit_get_reg(jit_class_fpr);
+ jit_movi_f(regno, u);
+ jit_stxi_f(v->u.w, JIT_FP, regno);
+ jit_unget_reg(regno);
+ }
+ jit_dec_synth();
+}
+
+void
+_jit_getarg_d(jit_state_t *_jit, int32_t u, jit_node_t *v)
+{
+ assert(v->code == jit_code_arg_d);
+ jit_inc_synth_wp(getarg_d, u, v);
+ if (jit_arg_f_reg_p(v->u.w))
+ jit_movr_d(u, JIT_FA0 - v->u.w);
+ else if (jit_arg_reg_p(v->u.w - 8))
+ jit_movr_w_d(u, JIT_RA0 - (v->u.w - 8));
+ else
+ jit_ldxi_d(u, JIT_FP, v->u.w);
+ jit_dec_synth();
+}
+
+void
+_jit_putargr_d(jit_state_t *_jit, int32_t u, jit_node_t *v)
+{
+ assert(v->code == jit_code_arg_d);
+ jit_inc_synth_wp(putargr_d, u, v);
+ if (jit_arg_reg_p(v->u.w))
+ jit_movr_d(JIT_FA0 - v->u.w, u);
+ else if (jit_arg_reg_p(v->u.w - 8))
+ jit_movr_d_w(JIT_RA0 - (v->u.w - 8), u);
+ else
+ jit_stxi_d(v->u.w, JIT_FP, u);
+ jit_dec_synth();
+}
+
+void
+_jit_putargi_d(jit_state_t *_jit, jit_float64_t u, jit_node_t *v)
+{
+ int32_t regno;
+ assert(v->code == jit_code_arg_d);
+ jit_inc_synth_dp(putargi_d, u, v);
+ if (jit_arg_reg_p(v->u.w))
+ jit_movi_d(JIT_FA0 - v->u.w, u);
+ else if (jit_arg_reg_p(v->u.w - 8)) {
+ union {
+ jit_float64_t d;
+ int64_t w;
+ } uu;
+ uu.d = u;
+ jit_movi(JIT_RA0 - (v->u.w - 8), uu.w);
+ }
+ else {
+ regno = jit_get_reg(jit_class_fpr);
+ jit_movi_d(regno, u);
+ jit_stxi_d(v->u.w, JIT_FP, regno);
+ jit_unget_reg(regno);
+ }
+ jit_dec_synth();
+}
+
+void
+_jit_pushargr(jit_state_t *_jit, int32_t u)
+{
+ assert(_jitc->function);
+ jit_inc_synth_w(pushargr, u);
+ jit_link_prepare();
+ if (jit_arg_reg_p(_jitc->function->call.argi)) {
+ jit_movr(JIT_RA0 - _jitc->function->call.argi, u);
+ ++_jitc->function->call.argi;
+ }
+ else {
+ jit_stxi(_jitc->function->call.size, JIT_SP, u);
+ _jitc->function->call.size += sizeof(jit_word_t);
+ }
+ jit_dec_synth();
+}
+
+void
+_jit_pushargi(jit_state_t *_jit, jit_word_t u)
+{
+ int32_t regno;
+ assert(_jitc->function);
+ jit_inc_synth_w(pushargi, u);
+ jit_link_prepare();
+ if (jit_arg_reg_p(_jitc->function->call.argi)) {
+ jit_movi(JIT_RA0 - _jitc->function->call.argi, u);
+ ++_jitc->function->call.argi;
+ }
+ else {
+ regno = jit_get_reg(jit_class_gpr);
+ jit_movi(regno, u);
+ jit_stxi(_jitc->function->call.size, JIT_SP, regno);
+ jit_unget_reg(regno);
+ _jitc->function->call.size += sizeof(jit_word_t);
+ }
+ jit_dec_synth();
+}
+
+void
+_jit_pushargr_f(jit_state_t *_jit, int32_t u)
+{
+ assert(_jitc->function);
+ jit_inc_synth_w(pushargr_f, u);
+ jit_link_prepare();
+ if (jit_arg_f_reg_p(_jitc->function->call.argf) &&
+ !(_jitc->function->call.call & jit_call_varargs)) {
+ jit_movr_f(JIT_FA0 - _jitc->function->call.argf, u);
+ ++_jitc->function->call.argf;
+ }
+ else if (jit_arg_reg_p(_jitc->function->call.argi)) {
+ jit_movr_f_w(JIT_RA0 - _jitc->function->call.argi, u);
+ ++_jitc->function->call.argi;
+ }
+ else {
+ jit_stxi_f(_jitc->function->call.size, JIT_SP, u);
+ _jitc->function->call.size += sizeof(jit_word_t);
+ }
+ jit_dec_synth();
+}
+
+void
+_jit_pushargi_f(jit_state_t *_jit, jit_float32_t u)
+{
+ int32_t regno;
+ assert(_jitc->function);
+ jit_inc_synth_f(pushargi_f, u);
+ jit_link_prepare();
+ if (jit_arg_f_reg_p(_jitc->function->call.argf) &&
+ !(_jitc->function->call.call & jit_call_varargs)) {
+ jit_movi_f(JIT_FA0 - _jitc->function->call.argf, u);
+ ++_jitc->function->call.argf;
+ }
+ else if (jit_arg_reg_p(_jitc->function->call.argi)) {
+ jit_movi_f_w(JIT_RA0 - _jitc->function->call.argi, u);
+ ++_jitc->function->call.argi;
+ }
+ else {
+ regno = jit_get_reg(jit_class_fpr);
+ jit_movi_f(regno, u);
+ jit_stxi_f(_jitc->function->call.size, JIT_SP, regno);
+ jit_unget_reg(regno);
+ _jitc->function->call.size += sizeof(jit_word_t);
+ }
+ jit_dec_synth();
+}
+
+void
+_jit_pushargr_d(jit_state_t *_jit, int32_t u)
+{
+ assert(_jitc->function);
+ jit_inc_synth_w(pushargr_d, u);
+ jit_link_prepare();
+ if (jit_arg_f_reg_p(_jitc->function->call.argf) &&
+ !(_jitc->function->call.call & jit_call_varargs)) {
+ jit_movr_d(JIT_FA0 - _jitc->function->call.argf, u);
+ ++_jitc->function->call.argf;
+ }
+ else if (jit_arg_reg_p(_jitc->function->call.argi)) {
+ jit_movr_d_w(JIT_RA0 - _jitc->function->call.argi, u);
+ ++_jitc->function->call.argi;
+ }
+ else {
+ jit_stxi_d(_jitc->function->call.size, JIT_SP, u);
+ _jitc->function->call.size += sizeof(jit_word_t);
+ }
+ jit_dec_synth();
+}
+
+void
+_jit_pushargi_d(jit_state_t *_jit, jit_float64_t u)
+{
+ int32_t regno;
+ assert(_jitc->function);
+ jit_inc_synth_d(pushargi_d, u);
+ jit_link_prepare();
+ if (jit_arg_f_reg_p(_jitc->function->call.argf) &&
+ !(_jitc->function->call.call & jit_call_varargs)) {
+ jit_movi_d(JIT_FA0 - _jitc->function->call.argf, u);
+ ++_jitc->function->call.argf;
+ }
+ else if (jit_arg_reg_p(_jitc->function->call.argi)) {
+ jit_movi_d_w(JIT_RA0 - _jitc->function->call.argi, u);
+ ++_jitc->function->call.argi;
+ }
+ else {
+ regno = jit_get_reg(jit_class_fpr);
+ jit_movi_d(regno, u);
+ jit_stxi_d(_jitc->function->call.size, JIT_SP, regno);
+ jit_unget_reg(regno);
+ _jitc->function->call.size += sizeof(jit_word_t);
+ }
+ jit_dec_synth();
+}
+
+jit_bool_t
+_jit_regarg_p(jit_state_t *_jit, jit_node_t *node, int32_t regno)
+{
+ int32_t spec;
+ spec = jit_class(_rvs[regno].spec);
+ if (spec & jit_class_arg) {
+ regno = JIT_RA0 - regno;
+ if (regno >= 0 && regno < node->v.w)
+ return (1);
+ if (spec & jit_class_fpr) {
+ regno = JIT_FA0 - regno;
+ if (regno >= 0 && regno < node->w.w)
+ return (1);
+ }
+ }
+
+ return (0);
+}
+
+void
+_jit_finishr(jit_state_t *_jit, int32_t r0)
+{
+ jit_node_t *node;
+ assert(_jitc->function);
+ jit_inc_synth_w(finishr, r0);
+ if (_jitc->function->self.alen < _jitc->function->call.size)
+ _jitc->function->self.alen = _jitc->function->call.size;
+ node = jit_callr(r0);
+ node->v.w = _jitc->function->self.argi;
+ node->w.w = _jitc->function->call.argf;
+ _jitc->function->call.argi = _jitc->function->call.argf =
+ _jitc->function->call.size = 0;
+ _jitc->prepare = 0;
+ jit_dec_synth();
+}
+
+jit_node_t *
+_jit_finishi(jit_state_t *_jit, jit_pointer_t i0)
+{
+ jit_node_t *node;
+ assert(_jitc->function);
+ jit_inc_synth_w(finishi, (jit_word_t)i0);
+ if (_jitc->function->self.alen < _jitc->function->call.size)
+ _jitc->function->self.alen = _jitc->function->call.size;
+ node = jit_calli(i0);
+ node->v.w = _jitc->function->call.argi;
+ node->w.w = _jitc->function->call.argf;
+ _jitc->function->call.argi = _jitc->function->call.argf =
+ _jitc->function->call.size = 0;
+ _jitc->prepare = 0;
+ jit_dec_synth();
+ return (node);
+}
+
+void
+_jit_retval_c(jit_state_t *_jit, int32_t r0)
+{
+ jit_inc_synth_w(retval_c, r0);
+ jit_extr_c(r0, JIT_RET);
+ jit_dec_synth();
+}
+
+void
+_jit_retval_uc(jit_state_t *_jit, int32_t r0)
+{
+ jit_inc_synth_w(retval_uc, r0);
+ jit_extr_uc(r0, JIT_RET);
+ jit_dec_synth();
+}
+
+void
+_jit_retval_s(jit_state_t *_jit, int32_t r0)
+{
+ jit_inc_synth_w(retval_s, r0);
+ jit_extr_s(r0, JIT_RET);
+ jit_dec_synth();
+}
+
+void
+_jit_retval_us(jit_state_t *_jit, int32_t r0)
+{
+ jit_inc_synth_w(retval_us, r0);
+ jit_extr_us(r0, JIT_RET);
+ jit_dec_synth();
+}
+
+void
+_jit_retval_i(jit_state_t *_jit, int32_t r0)
+{
+ jit_inc_synth_w(retval_i, r0);
+ jit_extr_i(r0, JIT_RET);
+ jit_dec_synth();
+}
+
+void
+_jit_retval_ui(jit_state_t *_jit, int32_t r0)
+{
+ jit_inc_synth_w(retval_ui, r0);
+ jit_extr_ui(r0, JIT_RET);
+ jit_dec_synth();
+}
+
+void
+_jit_retval_l(jit_state_t *_jit, int32_t r0)
+{
+ jit_inc_synth_w(retval_l, r0);
+ if (r0 != JIT_RET)
+ jit_movr(r0, JIT_RET);
+ jit_dec_synth();
+}
+
+void
+_jit_retval_f(jit_state_t *_jit, int32_t r0)
+{
+ jit_inc_synth_w(retval_f, r0);
+ if (r0 != JIT_FRET)
+ jit_movr_f(r0, JIT_FRET);
+ jit_dec_synth();
+}
+
+void
+_jit_retval_d(jit_state_t *_jit, int32_t r0)
+{
+ jit_inc_synth_w(retval_d, r0);
+ if (r0 != JIT_FRET)
+ jit_movr_d(r0, JIT_FRET);
+ jit_dec_synth();
+}
+
+jit_pointer_t
+_emit_code(jit_state_t *_jit)
+{
+ jit_node_t *node;
+ jit_node_t *temp;
+ jit_word_t word;
+ jit_word_t value;
+ int32_t offset;
+ struct {
+ jit_node_t *node;
+ uint8_t *data;
+ jit_word_t word;
+#if DEVEL_DISASSEMBLER
+ jit_word_t prevw;
+#endif
+ int32_t const_offset;
+ int32_t patch_offset;
+ } undo;
+#if DEVEL_DISASSEMBLER
+ jit_word_t prevw;
+#endif
+
+ _jitc->function = NULL;
+
+ jit_reglive_setup();
+
+ undo.word = 0;
+ undo.node = NULL;
+ undo.const_offset = undo.patch_offset = 0;
+# define assert_data(node) /**/
+#define case_rr(name, type) \
+ case jit_code_##name##r##type: \
+ name##r##type(rn(node->u.w), rn(node->v.w)); \
+ break
+#define case_rw(name, type) \
+ case jit_code_##name##i##type: \
+ name##i##type(rn(node->u.w), node->v.w); \
+ break
+#define case_wr(name, type) \
+ case jit_code_##name##i##type: \
+ name##i##type(node->u.w, rn(node->v.w)); \
+ break
+#define case_rrr(name, type) \
+ case jit_code_##name##r##type: \
+ name##r##type(rn(node->u.w), \
+ rn(node->v.w), rn(node->w.w)); \
+ break
+#define case_rrrr(name, type) \
+ case jit_code_##name##r##type: \
+ name##r##type(rn(node->u.q.l), rn(node->u.q.h), \
+ rn(node->v.w), rn(node->w.w)); \
+ break
+#define case_rrw(name, type) \
+ case jit_code_##name##i##type: \
+ name##i##type(rn(node->u.w), rn(node->v.w), node->w.w); \
+ break
+#define case_rrrw(name, type) \
+ case jit_code_##name##i##type: \
+ name##i##type(rn(node->u.q.l), rn(node->u.q.h), \
+ rn(node->v.w), node->w.w); \
+ break
+#define case_rrf(name) \
+ case jit_code_##name##i_f: \
+ assert_data(node); \
+ name##i_f(rn(node->u.w), rn(node->v.w), node->w.f); \
+ break
+#define case_rrd(name) \
+ case jit_code_##name##i_d: \
+ assert_data(node); \
+ name##i_d(rn(node->u.w), rn(node->v.w), node->w.d); \
+ break
+#define case_wrr(name, type) \
+ case jit_code_##name##i##type: \
+ name##i##type(node->u.w, rn(node->v.w), rn(node->w.w)); \
+ break
+#define case_brr(name, type) \
+ case jit_code_##name##r##type: \
+ temp = node->u.n; \
+ assert(temp->code == jit_code_label || \
+ temp->code == jit_code_epilog); \
+ if (temp->flag & jit_flag_patch) \
+ name##r##type(temp->u.w, rn(node->v.w), \
+ rn(node->w.w)); \
+ else { \
+ word = name##r##type(_jit->pc.w, \
+ rn(node->v.w), rn(node->w.w)); \
+ patch(word, node); \
+ } \
+ break
+#define case_brw(name, type) \
+ case jit_code_##name##i##type: \
+ temp = node->u.n; \
+ assert(temp->code == jit_code_label || \
+ temp->code == jit_code_epilog); \
+ if (temp->flag & jit_flag_patch) \
+ name##i##type(temp->u.w, \
+ rn(node->v.w), node->w.w); \
+ else { \
+ word = name##i##type(_jit->pc.w, \
+ rn(node->v.w), node->w.w); \
+ patch(word, node); \
+ } \
+ break;
+#define case_brf(name) \
+ case jit_code_##name##i_f: \
+ temp = node->u.n; \
+ assert(temp->code == jit_code_label || \
+ temp->code == jit_code_epilog); \
+ if (temp->flag & jit_flag_patch) \
+ name##i_f(temp->u.w, rn(node->v.w), node->w.f); \
+ else { \
+ word = name##i_f(_jit->pc.w, rn(node->v.w), \
+ node->w.f); \
+ patch(word, node); \
+ } \
+ break
+#define case_brd(name) \
+ case jit_code_##name##i_d: \
+ temp = node->u.n; \
+ assert(temp->code == jit_code_label || \
+ temp->code == jit_code_epilog); \
+ if (temp->flag & jit_flag_patch) \
+ name##i_d(temp->u.w, rn(node->v.w), node->w.d); \
+ else { \
+ word = name##i_d(_jit->pc.w, rn(node->v.w), \
+ node->w.d); \
+ patch(word, node); \
+ } \
+ break
+#if DEVEL_DISASSEMBLER
+ prevw = _jit->pc.w;
+#endif
+ for (node = _jitc->head; node; node = node->next) {
+ if (_jit->pc.uc >= _jitc->code.end)
+ return (NULL);
+
+#if DEVEL_DISASSEMBLER
+ node->offset = (jit_uword_t)_jit->pc.w - (jit_uword_t)prevw;
+ prevw = _jit->pc.w;
+#endif
+ value = jit_classify(node->code);
+ jit_regarg_set(node, value);
+ switch (node->code) {
+ case jit_code_align:
+ assert(!(node->u.w & (node->u.w - 1)) &&
+ node->u.w <= sizeof(jit_word_t));
+ if (node->u.w == sizeof(jit_word_t) &&
+ (word = _jit->pc.w & (sizeof(jit_word_t) - 1)))
+ nop(sizeof(jit_word_t) - word);
+ break;
+ case jit_code_note: case jit_code_name:
+ node->u.w = _jit->pc.w;
+ break;
+ case jit_code_label:
+ /* remember label is defined */
+ node->flag |= jit_flag_patch;
+ node->u.w = _jit->pc.w;
+ break;
+ case_rrr(add,);
+ case_rrw(add,);
+ case_rrr(addc,);
+ case_rrw(addc,);
+ case_rrr(addx,);
+ case_rrw(addx,);
+ case_rrr(sub,);
+ case_rrw(sub,);
+ case_rrr(subc,);
+ case_rrw(subc,);
+ case_rrr(subx,);
+ case_rrw(subx,);
+ case_rrw(rsb,);
+ case_rrr(mul,);
+ case_rrw(mul,);
+ case_rrrr(qmul,);
+ case_rrrw(qmul,);
+ case_rrrr(qmul, _u);
+ case_rrrw(qmul, _u);
+ case_rrr(div,);
+ case_rrw(div,);
+ case_rrr(div, _u);
+ case_rrw(div, _u);
+ case_rrrr(qdiv,);
+ case_rrrw(qdiv,);
+ case_rrrr(qdiv, _u);
+ case_rrrw(qdiv, _u);
+ case_rrr(rem,);
+ case_rrw(rem,);
+ case_rrr(rem, _u);
+ case_rrw(rem, _u);
+ case_rrr(lsh,);
+ case_rrw(lsh,);
+ case_rrr(rsh,);
+ case_rrw(rsh,);
+ case_rrr(rsh, _u);
+ case_rrw(rsh, _u);
+ case_rr(neg,);
+ case_rr(com,);
+ case_rrr(and,);
+ case_rrw(and,);
+ case_rrr(or,);
+ case_rrw(or,);
+ case_rrr(xor,);
+ case_rrw(xor,);
+ case_rr(trunc, _f_i);
+ case_rr(trunc, _d_i);
+ case_rr(trunc, _f_l);
+ case_rr(trunc, _d_l);
+ case_rr(ld, _c);
+ case_rw(ld, _c);
+ case_rr(ld, _uc);
+ case_rw(ld, _uc);
+ case_rr(ld, _s);
+ case_rw(ld, _s);
+ case_rr(ld, _us);
+ case_rw(ld, _us);
+ case_rr(ld, _i);
+ case_rw(ld, _i);
+ case_rr(ld, _ui);
+ case_rw(ld, _ui);
+ case_rr(ld, _l);
+ case_rw(ld, _l);
+ case_rrr(ldx, _c);
+ case_rrw(ldx, _c);
+ case_rrr(ldx, _uc);
+ case_rrw(ldx, _uc);
+ case_rrr(ldx, _s);
+ case_rrw(ldx, _s);
+ case_rrr(ldx, _us);
+ case_rrw(ldx, _us);
+ case_rrr(ldx, _i);
+ case_rrw(ldx, _i);
+ case_rrr(ldx, _ui);
+ case_rrw(ldx, _ui);
+ case_rrr(ldx, _l);
+ case_rrw(ldx, _l);
+ case_rr(st, _c);
+ case_wr(st, _c);
+ case_rr(st, _s);
+ case_wr(st, _s);
+ case_rr(st, _i);
+ case_wr(st, _i);
+ case_rr(st, _l);
+ case_wr(st, _l);
+ case_rrr(stx, _c);
+ case_wrr(stx, _c);
+ case_rrr(stx, _s);
+ case_wrr(stx, _s);
+ case_rrr(stx, _i);
+ case_wrr(stx, _i);
+ case_rrr(stx, _l);
+ case_wrr(stx, _l);
+ case_rr(hton, _us);
+ case_rr(hton, _ui);
+ case_rr(hton, _ul);
+ case_rr(ext, _c);
+ case_rr(ext, _uc);
+ case_rr(ext, _s);
+ case_rr(ext, _us);
+ case_rr(ext, _i);
+ case_rr(ext, _ui);
+ case_rr(mov,);
+ case jit_code_movi:
+ if (node->flag & jit_flag_node) {
+ temp = node->v.n;
+ if (temp->code == jit_code_data ||
+ (temp->code == jit_code_label &&
+ (temp->flag & jit_flag_patch)))
+ movi(rn(node->u.w), temp->u.w);
+ else {
+ assert(temp->code == jit_code_label ||
+ temp->code == jit_code_epilog);
+ word = movi_p(rn(node->u.w), temp->u.w);
+ patch(word, node);
+ }
+ }
+ else
+ movi(rn(node->u.w), node->v.w);
+ break;
+ case_rrr(lt,);
+ case_rrw(lt,);
+ case_rrr(lt, _u);
+ case_rrw(lt, _u);
+ case_rrr(le,);
+ case_rrw(le,);
+ case_rrr(le, _u);
+ case_rrw(le, _u);
+ case_rrr(eq,);
+ case_rrw(eq,);
+ case_rrr(ge,);
+ case_rrw(ge,);
+ case_rrr(ge, _u);
+ case_rrw(ge, _u);
+ case_rrr(gt,);
+ case_rrw(gt,);
+ case_rrr(gt, _u);
+ case_rrw(gt, _u);
+ case_rrr(ne,);
+ case_rrw(ne,);
+ case_brr(blt,);
+ case_brw(blt,);
+ case_brr(blt, _u);
+ case_brw(blt, _u);
+ case_brr(ble,);
+ case_brw(ble,);
+ case_brr(ble, _u);
+ case_brw(ble, _u);
+ case_brr(beq,);
+ case_brw(beq,);
+ case_brr(bge,);
+ case_brw(bge,);
+ case_brr(bge, _u);
+ case_brw(bge, _u);
+ case_brr(bgt,);
+ case_brw(bgt,);
+ case_brr(bgt, _u);
+ case_brw(bgt, _u);
+ case_brr(bne,);
+ case_brw(bne,);
+ case_brr(boadd,);
+ case_brw(boadd,);
+ case_brr(boadd, _u);
+ case_brw(boadd, _u);
+ case_brr(bxadd,);
+ case_brw(bxadd,);
+ case_brr(bxadd, _u);
+ case_brw(bxadd, _u);
+ case_brr(bosub,);
+ case_brw(bosub,);
+ case_brr(bosub, _u);
+ case_brw(bosub, _u);
+ case_brr(bxsub,);
+ case_brw(bxsub,);
+ case_brr(bxsub, _u);
+ case_brw(bxsub, _u);
+ case_brr(bms,);
+ case_brw(bms,);
+ case_brr(bmc,);
+ case_brw(bmc,);
+ case_rrr(add, _f);
+ case_rrf(add);
+ case_rrr(sub, _f);
+ case_rrf(sub);
+ case_rrf(rsb);
+ case_rrr(mul, _f);
+ case_rrf(mul);
+ case_rrr(div, _f);
+ case_rrf(div);
+ case_rr(abs, _f);
+ case_rr(neg, _f);
+ case_rr(sqrt, _f);
+ case_rr(ext, _f);
+ case_rr(ld, _f);
+ case_rw(ld, _f);
+ case_rrr(ldx, _f);
+ case_rrw(ldx, _f);
+ case_rr(st, _f);
+ case_wr(st, _f);
+ case_rrr(stx, _f);
+ case_wrr(stx, _f);
+ case_rr(mov, _f);
+ case jit_code_movi_f:
+ assert_data(node);
+ movi_f(rn(node->u.w), node->v.f);
+ break;
+ case_rr(ext, _d_f);
+ case_rrr(lt, _f);
+ case_rrf(lt);
+ case_rrr(le, _f);
+ case_rrf(le);
+ case_rrr(eq, _f);
+ case_rrf(eq);
+ case_rrr(ge, _f);
+ case_rrf(ge);
+ case_rrr(gt, _f);
+ case_rrf(gt);
+ case_rrr(ne, _f);
+ case_rrf(ne);
+ case_rrr(unlt, _f);
+ case_rrf(unlt);
+ case_rrr(unle, _f);
+ case_rrf(unle);
+ case_rrr(uneq, _f);
+ case_rrf(uneq);
+ case_rrr(unge, _f);
+ case_rrf(unge);
+ case_rrr(ungt, _f);
+ case_rrf(ungt);
+ case_rrr(ltgt, _f);
+ case_rrf(ltgt);
+ case_rrr(ord, _f);
+ case_rrf(ord);
+ case_rrr(unord, _f);
+ case_rrf(unord);
+ case_brr(blt, _f);
+ case_brf(blt);
+ case_brr(ble, _f);
+ case_brf(ble);
+ case_brr(beq, _f);
+ case_brf(beq);
+ case_brr(bge, _f);
+ case_brf(bge);
+ case_brr(bgt, _f);
+ case_brf(bgt);
+ case_brr(bne, _f);
+ case_brf(bne);
+ case_brr(bunlt, _f);
+ case_brf(bunlt);
+ case_brr(bunle, _f);
+ case_brf(bunle);
+ case_brr(buneq, _f);
+ case_brf(buneq);
+ case_brr(bunge, _f);
+ case_brf(bunge);
+ case_brr(bungt, _f);
+ case_brf(bungt);
+ case_brr(bltgt, _f);
+ case_brf(bltgt);
+ case_brr(bord, _f);
+ case_brf(bord);
+ case_brr(bunord, _f);
+ case_brf(bunord);
+ case_rrr(add, _d);
+ case_rrd(add);
+ case_rrr(sub, _d);
+ case_rrd(sub);
+ case_rrd(rsb);
+ case_rrr(mul, _d);
+ case_rrd(mul);
+ case_rrr(div, _d);
+ case_rrd(div);
+ case_rr(abs, _d);
+ case_rr(neg, _d);
+ case_rr(sqrt, _d);
+ case_rr(ext, _d);
+ case_rr(ld, _d);
+ case_rw(ld, _d);
+ case_rrr(ldx, _d);
+ case_rrw(ldx, _d);
+ case_rr(st, _d);
+ case_wr(st, _d);
+ case_rrr(stx, _d);
+ case_wrr(stx, _d);
+ case_rr(mov, _d);
+ case jit_code_movi_d:
+ assert_data(node);
+ movi_d(rn(node->u.w), node->v.d);
+ break;
+ case_rr(ext, _f_d);
+ case_rrr(lt, _d);
+ case_rrd(lt);
+ case_rrr(le, _d);
+ case_rrd(le);
+ case_rrr(eq, _d);
+ case_rrd(eq);
+ case_rrr(ge, _d);
+ case_rrd(ge);
+ case_rrr(gt, _d);
+ case_rrd(gt);
+ case_rrr(ne, _d);
+ case_rrd(ne);
+ case_rrr(unlt, _d);
+ case_rrd(unlt);
+ case_rrr(unle, _d);
+ case_rrd(unle);
+ case_rrr(uneq, _d);
+ case_rrd(uneq);
+ case_rrr(unge, _d);
+ case_rrd(unge);
+ case_rrr(ungt, _d);
+ case_rrd(ungt);
+ case_rrr(ltgt, _d);
+ case_rrd(ltgt);
+ case_rrr(ord, _d);
+ case_rrd(ord);
+ case_rrr(unord, _d);
+ case_rrd(unord);
+ case_brr(blt, _d);
+ case_brd(blt);
+ case_brr(ble, _d);
+ case_brd(ble);
+ case_brr(beq, _d);
+ case_brd(beq);
+ case_brr(bge, _d);
+ case_brd(bge);
+ case_brr(bgt, _d);
+ case_brd(bgt);
+ case_brr(bne, _d);
+ case_brd(bne);
+ case_brr(bunlt, _d);
+ case_brd(bunlt);
+ case_brr(bunle, _d);
+ case_brd(bunle);
+ case_brr(buneq, _d);
+ case_brd(buneq);
+ case_brr(bunge, _d);
+ case_brd(bunge);
+ case_brr(bungt, _d);
+ case_brd(bungt);
+ case_brr(bltgt, _d);
+ case_brd(bltgt);
+ case_brr(bord, _d);
+ case_brd(bord);
+ case_brr(bunord, _d);
+ case_brd(bunord);
+ case jit_code_jmpr:
+ jmpr(rn(node->u.w));
+ break;
+ case jit_code_jmpi:
+ if (node->flag & jit_flag_node) {
+ temp = node->u.n;
+ assert(temp->code == jit_code_label ||
+ temp->code == jit_code_epilog);
+ if (temp->flag & jit_flag_patch)
+ jmpi(temp->u.w);
+ else {
+ word = jmpi_p(_jit->pc.w);
+ patch(word, node);
+ }
+ }
+ else
+ jmpi(node->u.w);
+ break;
+ case jit_code_callr:
+ callr(rn(node->u.w));
+ break;
+ case jit_code_calli:
+ if (node->flag & jit_flag_node) {
+ temp = node->u.n;
+ assert(temp->code == jit_code_label ||
+ temp->code == jit_code_epilog);
+ if (temp->flag & jit_flag_patch)
+ calli(temp->u.w);
+ else {
+ word = calli_p(_jit->pc.w);
+ patch(word, node);
+ }
+ }
+ else
+ calli(node->u.w);
+ break;
+ case jit_code_prolog:
+ _jitc->function = _jitc->functions.ptr + node->w.w;
+ undo.node = node;
+ undo.word = _jit->pc.w;
+#if DEVEL_DISASSEMBLER
+ undo.prevw = prevw;
+#endif
+ undo.patch_offset = _jitc->patches.offset;
+ restart_function:
+ _jitc->again = 0;
+ prolog(node);
+ break;
+ case jit_code_epilog:
+ assert(_jitc->function == _jitc->functions.ptr + node->w.w);
+ if (_jitc->again) {
+ for (temp = undo.node->next;
+ temp != node; temp = temp->next) {
+ if (temp->code == jit_code_label ||
+ temp->code == jit_code_epilog)
+ temp->flag &= ~jit_flag_patch;
+ }
+ temp->flag &= ~jit_flag_patch;
+ node = undo.node;
+ _jit->pc.w = undo.word;
+#if DEVEL_DISASSEMBLER
+ prevw = undo.prevw;
+#endif
+ _jitc->patches.offset = undo.patch_offset;
+ goto restart_function;
+ }
+ /* remember label is defined */
+ node->flag |= jit_flag_patch;
+ node->u.w = _jit->pc.w;
+ epilog(node);
+ _jitc->function = NULL;
+ break;
+ case jit_code_movr_w_f:
+ movr_w_f(rn(node->u.w), rn(node->v.w));
+ break;
+ case jit_code_movr_f_w:
+ movr_f_w(rn(node->u.w), rn(node->v.w));
+ break;
+ case jit_code_movi_f_w:
+ assert_data(node);
+ movi_f_w(rn(node->u.w), node->v.f);
+ break;
+ case jit_code_movr_w_d:
+ movr_w_d(rn(node->u.w), rn(node->v.w));
+ break;
+ case jit_code_movr_d_w:
+ movr_d_w(rn(node->u.w), rn(node->v.w));
+ break;
+ case jit_code_movi_d_w:
+ assert_data(node);
+ movi_d_w(rn(node->u.w), node->v.d);
+ break;
+ case jit_code_va_start:
+ vastart(rn(node->u.w));
+ break;
+ case jit_code_va_arg:
+ vaarg(rn(node->u.w), rn(node->v.w));
+ break;
+ case jit_code_va_arg_d:
+ vaarg_d(rn(node->u.w), rn(node->v.w));
+ break;
+ case jit_code_live: case jit_code_ellipsis:
+ case jit_code_va_push:
+ case jit_code_allocai: case jit_code_allocar:
+ case jit_code_arg:
+ case jit_code_arg_f: case jit_code_arg_d:
+ case jit_code_va_end:
+ case jit_code_ret:
+ case jit_code_retr: case jit_code_reti:
+ case jit_code_retr_f: case jit_code_reti_f:
+ case jit_code_retr_d: case jit_code_reti_d:
+ case jit_code_getarg_c: case jit_code_getarg_uc:
+ case jit_code_getarg_s: case jit_code_getarg_us:
+ case jit_code_getarg_i: case jit_code_getarg_ui:
+ case jit_code_getarg_l:
+ case jit_code_getarg_f: case jit_code_getarg_d:
+ case jit_code_putargr: case jit_code_putargi:
+ case jit_code_putargr_f: case jit_code_putargi_f:
+ case jit_code_putargr_d: case jit_code_putargi_d:
+ case jit_code_pushargr: case jit_code_pushargi:
+ case jit_code_pushargr_f: case jit_code_pushargi_f:
+ case jit_code_pushargr_d: case jit_code_pushargi_d:
+ case jit_code_retval_c: case jit_code_retval_uc:
+ case jit_code_retval_s: case jit_code_retval_us:
+ case jit_code_retval_i:
+ case jit_code_retval_ui: case jit_code_retval_l:
+ case jit_code_retval_f: case jit_code_retval_d:
+ case jit_code_prepare:
+ case jit_code_finishr: case jit_code_finishi:
+ break;
+ default:
+ abort();
+ }
+ if (jit_carry != _NOREG) {
+ switch (node->code) {
+ case jit_code_note:
+ case jit_code_addcr: case jit_code_addci:
+ case jit_code_addxr: case jit_code_addxi:
+ case jit_code_subcr: case jit_code_subci:
+ case jit_code_subxr: case jit_code_subxi:
+ break;
+ default:
+ jit_unget_reg(jit_carry);
+ jit_carry = _NOREG;
+ break;
+ }
+ }
+ jit_regarg_clr(node, value);
+ assert(_jitc->regarg == 0 ||
+ (jit_carry != _NOREG && _jitc->regarg == (1 << jit_carry)));
+ assert(_jitc->synth == 0);
+ /* update register live state */
+ jit_reglive(node);
+ }
+#undef case_brw
+#undef case_brr
+#undef case_wrr
+#undef case_rrw
+#undef case_rrr
+#undef case_wr
+#undef case_rw
+#undef case_rr
+
+ for (offset = 0; offset < _jitc->patches.offset; offset++) {
+ node = _jitc->patches.ptr[offset].node;
+ word = _jitc->patches.ptr[offset].inst;
+ value = node->code == jit_code_movi ? node->v.n->u.w : node->u.n->u.w;
+ patch_at(word, value);
+ }
+
+ jit_flush(_jit->code.ptr, _jit->pc.uc);
+
+ return (_jit->code.ptr);
+}
+
+#define CODE 1
+# include "riscv-cpu.c"
+# include "riscv-fpu.c"
+#undef CODE
+
+void
+jit_flush(void *fptr, void *tptr)
+{
+#if defined(__GNUC__)
+ jit_word_t f, t, s;
+
+ s = sysconf(_SC_PAGE_SIZE);
+ f = (jit_word_t)fptr & -s;
+ t = (((jit_word_t)tptr) + s - 1) & -s;
+ __clear_cache((void *)f, (void *)t);
+#endif
+}
+
+void
+_emit_ldxi(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
+{
+ ldxi(rn(r0), rn(r1), i0);
+}
+
+void
+_emit_stxi(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1)
+{
+ stxi(i0, rn(r0), rn(r1));
+}
+
+void
+_emit_ldxi_d(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
+{
+ ldxi_d(rn(r0), rn(r1), i0);
+}
+
+void
+_emit_stxi_d(jit_state_t *_jit, jit_word_t i0, int32_t r0, int32_t r1)
+{
+ stxi_d(i0, rn(r0), rn(r1));
+}
+
+static void
+_patch(jit_state_t *_jit, jit_word_t instr, jit_node_t *node)
+{
+ int32_t flag;
+
+ assert(node->flag & jit_flag_node);
+ if (node->code == jit_code_movi)
+ flag = node->v.n->flag;
+ else
+ flag = node->u.n->flag;
+ assert(!(flag & jit_flag_patch));
+ if (_jitc->patches.offset >= _jitc->patches.length) {
+ jit_realloc((jit_pointer_t *)&_jitc->patches.ptr,
+ _jitc->patches.length * sizeof(jit_patch_t),
+ (_jitc->patches.length + 1024) * sizeof(jit_patch_t));
+ _jitc->patches.length += 1024;
+ }
+ _jitc->patches.ptr[_jitc->patches.offset].inst = instr;
+ _jitc->patches.ptr[_jitc->patches.offset].node = node;
+ ++_jitc->patches.offset;
+}
diff --git a/lightening/riscv.h b/lightening/riscv.h
new file mode 100644
index 0000000..1b4f93d
--- /dev/null
+++ b/lightening/riscv.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2019 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
+ */
+
+#ifndef _jit_riscv_h
+#define _jit_riscv_h
+
+#define JIT_HASH_CONSTS 0
+#define JIT_NUM_OPERANDS 3
+
+/*
+ * Types
+ */
+#define JIT_FP _FP
+typedef enum {
+#define jit_r(i) (JIT_R0 + (i))
+#define jit_r_num() 7
+#define jit_v(i) (JIT_V0 + (i))
+#define jit_v_num() 11
+#define jit_f(i) (JIT_F0 + (i))
+#define jit_f_num() 12
+ _ZERO, /* x0 - Hard-wired zero --- */
+ _RA, /* x1 - Return address (CalleR save) */
+ _SP, /* x2 - Stack pointer (CalleE save) */
+ _GP, /* x3 - Global pointer --- */
+
+#if 0 /* Pretend it does not exist, so _NOREG can be used in
+ * a 64 bit bitmask */
+ _TP, /* x4 - Thread pointer --- */
+#endif
+
+#define JIT_R0 _T0
+#define JIT_R1 _T1
+#define JIT_R2 _T2
+#define JIT_R3 _T3
+#define JIT_R4 _T4
+#define JIT_R5 _T5
+#define JIT_R6 _T6
+ _T0, /* x5 - Temporary/alternate
+ link register (CalleR save) */
+ _T1, /* x6 - Temporary (CalleR save) */
+ _T2, /* x7 - Temporary (CalleR save) */
+ _T3, /* x28 - Temporary (CalleR save) */
+ _T4, /* x28 - Temporary (CalleR save) */
+ _T5, /* x30 - Temporary (CalleR save) */
+ _T6, /* x31 - Temporary (CalleR save) */
+ _FP, /* x8 - Saved register/frame
+ pointer (CalleE save) */
+ _S0 = _FP,
+#define JIT_V0 _S1
+#define JIT_V1 _S2
+#define JIT_V2 _S3
+#define JIT_V3 _S4
+#define JIT_V4 _S5
+#define JIT_V5 _S6
+#define JIT_V6 _S7
+#define JIT_V7 _S8
+#define JIT_V8 _S9
+#define JIT_V9 _S10
+#define JIT_V10 _S11
+ _S1, /* x9 - Saved register (CalleE save) */
+ _S2, /* x18 - Saved register (CalleE save) */
+ _S3, /* x19 - Saved register (CalleE save) */
+ _S4, /* x20 - Saved register (CalleE save) */
+ _S5, /* x21 - Saved register (CalleE save) */
+ _S6, /* x22 - Saved register (CalleE save) */
+ _S7, /* x23 - Saved register (CalleE save) */
+ _S8, /* x24 - Saved register (CalleE save) */
+ _S9, /* x25 - Saved register (CalleE save) */
+ _S10, /* x26 - Saved register (CalleE save) */
+ _S11, /* x27 - Saved register (CalleE save) */
+ _A7, /* x17 - Function argument (CalleR save) */
+ _A6, /* x16 - Function argument (CalleR save) */
+ _A5, /* x15 - Function argument (CalleR save) */
+ _A4, /* x14 - Function argument (CalleR save) */
+ _A3, /* x13 - Function argument (CalleR save) */
+ _A2, /* x12 - Function argument (CalleR save) */
+ _A1, /* x11 - Function argument/
+ return value (CalleR save) */
+ _A0, /* x10 - Function argument/
+ return value (CalleR save) */
+ _FT0, /* f0 - FP temporary (CalleR save) */
+ _FT1, /* f1 - FP temporary (CalleR save) */
+ _FT2, /* f2 - FP temporary (CalleR save) */
+ _FT3, /* f3 - FP temporary (CalleR save) */
+ _FT4, /* f4 - FP temporary (CalleR save) */
+ _FT5, /* f5 - FP temporary (CalleR save) */
+ _FT6, /* f6 - FP temporary (CalleR save) */
+ _FT7, /* f7 - FP temporary (CalleR save) */
+ _FT8, /* f28 - FP temporary (CalleR save) */
+ _FT9, /* f29 - FP temporary (CalleR save) */
+ _FT10, /* f30 - FP temporary (CalleR save) */
+ _FT11, /* f31 - FP temporary (CalleR save) */
+#define JIT_F0 _FS0
+#define JIT_F1 _FS1
+#define JIT_F2 _FS2
+#define JIT_F3 _FS3
+#define JIT_F4 _FS4
+#define JIT_F5 _FS5
+#define JIT_F6 _FS6
+#define JIT_F7 _FS7
+#define JIT_F8 _FS8
+#define JIT_F9 _FS9
+#define JIT_F10 _FS10
+#define JIT_F11 _FS11
+ _FS0, /* f8 - FP saved register (CalleE save) */
+ _FS1, /* f9 - FP saved register (CalleE save) */
+ _FS2, /* f18 - FP saved register (CalleE save) */
+ _FS3, /* f19 - FP saved register (CalleE save) */
+ _FS4, /* f20 - FP saved register (CalleE save) */
+ _FS5, /* f21 - FP saved register (CalleE save) */
+ _FS6, /* f22 - FP saved register (CalleE save) */
+ _FS7, /* f23 - FP saved register (CalleE save) */
+ _FS8, /* f24 - FP saved register (CalleE save) */
+ _FS9, /* f25 - FP saved register (CalleE save) */
+ _FS10, /* f26 - FP saved register (CalleE save) */
+ _FS11, /* f27 - FP saved register (CalleE save) */
+ _FA7, /* f17 - FP Function argument (CalleR save) */
+ _FA6, /* f16 - FP Function argument (CalleR save) */
+ _FA5, /* f15 - FP Function argument (CalleR save) */
+ _FA4, /* f14 - FP Function argument (CalleR save) */
+ _FA3, /* f13 - FP Function argument (CalleR save) */
+ _FA2, /* f12 - FP Function argument (CalleR save) */
+ _FA1, /* f11 - FP function argument/
+ return value (CalleR save) */
+ _FA0, /* f10 - FP function argument/
+ return value (CalleR save) */
+ _NOREG,
+#define JIT_NOREG _NOREG
+} jit_reg_t;
+
+#endif /* _jit_riscv_h */
--
2.27.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: riscv files for lightening
2021-01-29 19:13 riscv files for lightening Matt Wette
@ 2021-01-30 15:14 ` Matt Wette
0 siblings, 0 replies; 2+ messages in thread
From: Matt Wette @ 2021-01-30 15:14 UTC (permalink / raw)
To: guile-devel
On 1/29/21 11:13 AM, Matt Wette wrote:
> Andy,
>
> I took a stab at porting RISC-V from lightning to lightening.
> I have no riscv toolset or computer yet so these are untested.
>
> I copied files from sv/lightning for riscv to wingo/lightening. Patch
> attached.
> The changes are:
> 1) copy lightning/jit_riscv{.c,-cpu.c-fpu.c,-sz.c,.h} to lightening
> 2) s/include "jit_riscv/include "riscv/
> 3) s/git_int/int/ and s/git_uint/uint/
> 4) copied the JIT_RA0, etc defines from jit_private.h to riscv.c
> 5) updated lightening.am
> 6) updated lightening.h
>
> Matt
>
I did find github.com/riscv/riscv/riscv-gnu-toolchain.
I'm going to see where that goes wrt testing.
Matt
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2021-01-30 15:14 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-29 19:13 riscv files for lightening Matt Wette
2021-01-30 15:14 ` Matt Wette
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).