[[rv64]]
== RV64I Base Integer Instruction Set, Version 2.1

This chapter describes the RV64I base integer instruction set, which
builds upon the RV32I variant described in <<rv32>>.
This chapter presents only the differences with RV32I, so should be read
in conjunction with the earlier chapter.

=== Register State

RV64I widens the integer registers and supported user address space to
64 bits (XLEN=64 in <<gprs>>).

=== Integer Computational Instructions

Most integer computational instructions operate on XLEN-bit values.
Additional instruction variants are provided to manipulate 32-bit values
in RV64I, indicated by a 'W' suffix to the opcode. These "*W"
instructions ignore the upper 32 bits of their inputs and always produce
32-bit signed values, sign-extending them to 64 bits, i.e. bits XLEN-1
through 31 are equal.

[NOTE]
====
The compiler and calling convention maintain an invariant that all
32-bit values are held in a sign-extended format in 64-bit registers.
Even 32-bit unsigned integers extend bit 31 into bits 63 through 32.
Consequently, conversion between unsigned and signed 32-bit integers is
a no-op, as is conversion from a signed 32-bit integer to a signed
64-bit integer. Existing 64-bit wide SLTU and unsigned branch compares
still operate correctly on unsigned 32-bit integers under this
invariant. Similarly, existing 64-bit wide logical operations on 32-bit
sign-extended integers preserve the sign-extension property. A few new
instructions (ADD[I]W/SUBW/SxxW) are required for addition and shifts to
ensure reasonable performance for 32-bit values.
====
(((RV64I, shifts)))
(((RV64I, compares)))

==== Integer Register-Immediate Instructions

include::images/wavedrom/rv64i-base-int.edn[]
[[rv64i-base-int]]
//.RV64I register-immediate instructions

ADDIW is an RV64I instruction that adds the sign-extended 12-bit
immediate to register _rs1_ and produces the proper sign extension of a
32-bit result in _rd_. Overflows are ignored and the result is the low
32 bits of the result sign-extended to 64 bits. Note, ADDIW _rd, rs1, 0_
writes the sign extension of the lower 32 bits of register _rs1_ into
register _rd_ (assembler pseudoinstruction SEXT.W).

include::images/wavedrom/rv64i-slli.edn[]
[[rv64i-slli]]
//.RV64I register-immediate (descr ADDIW) instructions

Shifts by a constant are encoded as a specialization of the I-type
format using the same instruction opcode as RV32I. The operand to be
shifted is in _rs1_, and the shift amount is encoded in the lower 6 bits
of the I-immediate field for RV64I. The right shift type is encoded in
bit 30. SLLI is a logical left shift (zeros are shifted into the lower
bits); SRLI is a logical right shift (zeros are shifted into the upper
bits); and SRAI is an arithmetic right shift (the original sign bit is
copied into the vacated upper bits).
(((RV64I, SLLI)))
(((RV64I, SRKIW)))
(((RV64I, SRLIW)))
(((RV64I, RV64I-only)))

include::images/wavedrom/rv64i-slliw.edn[]
[[rv64i-slliw]]

SLLIW, SRLIW, and SRAIW are RV64I-only instructions that are analogously
defined but operate on 32-bit values and sign-extend their 32-bit
results to 64 bits. SLLIW, SRLIW, and SRAIW encodings with
_imm[5] &#8800; 0_ are reserved.

[NOTE]
====
Previously, SLLIW, SRLIW, and SRAIW with _imm[5] &#8800; 0_
were defined to cause illegal-instruction exceptions, whereas now they
are marked as reserved. This is a backwards-compatible change.
====

include::images/wavedrom/rv64-lui-auipc.edn[]
[[rv64_lui-auipc]]
//.RV64I register-immediate (descr) instructions

LUI (load upper immediate) uses the same opcode as RV32I. LUI places the
32-bit U-immediate into register _rd_, filling in the lowest 12 bits
with zeros. The 32-bit result is sign-extended to 64 bits.
(((RV64I, LUI)))

AUIPC (add upper immediate to `pc`) uses the same opcode as RV32I. AUIPC
is used to build `pc`-relative addresses and uses the U-type format.
AUIPC forms a 32-bit offset from the U-immediate, filling in the lowest
12 bits with zeros, sign-extends the result to 64 bits, adds it to the
address of the AUIPC instruction, then places the result in register
_rd_.

[NOTE]
====
Note that the set of address offsets that can be formed by pairing LUI
with LD, AUIPC with JALR, etc. in RV64I is
[latexmath:[${-}2^{31}{-}2^{11}$], latexmath:[$2^{31}{-}2^{11}{-}1$]].
====

==== Integer Register-Register Operations

//this diagramdoesn't match the tex specification
include::images/wavedrom/rv64i-int-reg-reg.edn[]
[[int_reg-reg]]
//.RV64I integer register-register instructions

ADDW and SUBW are RV64I-only instructions that are defined analogously
to ADD and SUB but operate on 32-bit values and produce signed 32-bit
results. Overflows are ignored, and the low 32-bits of the result is
sign-extended to 64-bits and written to the destination register.
(((RV64I-only, ADDW)))
(((RV64I-only, SUBW)))

SLL, SRL, and SRA perform logical left, logical right, and arithmetic
right shifts on the value in register _rs1_ by the shift amount held in
register _rs2_. In RV64I, only the low 6 bits of _rs2_ are considered
for the shift amount.

SLLW, SRLW, and SRAW are RV64I-only instructions that are analogously
defined but operate on 32-bit values and sign-extend their 32-bit
results to 64 bits. The shift amount is given by _rs2[4:0]_.
(((RV64I-only, SLLW)))
(((RV64I-only, SRLW)))
(((RV64I-only, SRAW)))

=== Load and Store Instructions

RV64I extends the address space to 64 bits. The execution environment
will define what portions of the address space are legal to access.

include::images/wavedrom/load-store.edn[]
[[load_store]]
//.Load and store instructions

The LD instruction loads a 64-bit value from memory into register _rd_
for RV64I.
(((RV64I, LD)))

The LW instruction loads a 32-bit value from memory and sign-extends
this to 64 bits before storing it in register _rd_ for RV64I. The LWU
instruction, on the other hand, zero-extends the 32-bit value from
memory for RV64I. LH and LHU are defined analogously for 16-bit values,
as are LB and LBU for 8-bit values. The SD, SW, SH, and SB instructions
store 64-bit, 32-bit, 16-bit, and 8-bit values from the low bits of
register _rs2_ to memory respectively.

[[rv64i-hints]]
=== HINT Instructions

All instructions that are microarchitectural HINTs in RV32I (see
<<rv32>>) are also HINTs in RV64I.
The additional computational instructions in RV64I expand both the
standard and custom HINT encoding spaces.
(((RV64I, HINT)))

<<rv64i-h>> lists all RV64I HINT code points. 91% of the
HINT space is reserved for standard HINTs, but none are presently
defined. The remainder of the HINT space is designated for custom HINTs;
no standard HINTs will ever be defined in this subspace.

[[rv64i-h]]
.RV64I HINT instructions.
[float="center",align="center",cols="<,<,^,<", options="header", grid="all"]
|===
|Instruction |Constraints |Code Points |Purpose
|LUI |_rd_=_x0_ |latexmath:[$2^{20}$] .9+.^|_Designated for future standard use_

|AUIPC |_rd_=_x0_ |latexmath:[$2^{20}$]

|ADDI |_rd_=_x0_, and either _rs1_≠_x0_ or _imm_≠0  |latexmath:[$2^{17}-1$]

|ANDI |_rd_=_x0_ |latexmath:[$2^{17}$]

|ORI |_rd_=_x0_ |latexmath:[$2^{17}$]

|XORI |_rd_=_x0_ |latexmath:[$2^{17}$]

|ADDIW |_rd_=_x0_ |latexmath:[$2^{17}$]

|ADD |_rd_=_x0_, _rs1_≠_x0_ |latexmath:[$2^{10}-32$]

|ADD |_rd_=_x0_, _rs1_=_x0_, _rs2_≠_x2_-_x5_| 28

|ADD |_rd_=_x0_, _rs1_=_x0_, _rs2_=_x2_-_x5_| 4 | (_rs2_=_x2_) NTL.P1 +
 (_rs2_=_x3_) NTL.PALL +
 (_rs2_=_x4_) NTL.S1 +
 (_rs2_=_x5_) NTL.ALL

|SLLI |_rd_=`x0`, _rs1_=`x0`, _shamt_=31 |1|Semihosting entry marker

|SRAI |_rd_=`x0`, _rs1_=`x0`, _shamt_=7 |1|Semihosting exit marker

|SUB |_rd_=_x0_ |latexmath:[$2^{10}$] .16+.^| _Designated for future standard use_

|AND |_rd_=_x0_ |latexmath:[$2^{10}$]

|OR |_rd_=_x0_ |latexmath:[$2^{10}$]

|XOR |_rd_=_x0_ |latexmath:[$2^{10}$]

|SLL |_rd_=_x0_ |latexmath:[$2^{10}$]

|SRL |_rd_=_x0_ |latexmath:[$2^{10}$]

|SRA |_rd_=_x0_ |latexmath:[$2^{10}$]

|ADDW |_rd_=_x0_ |latexmath:[$2^{10}$]

|SUBW |_rd_=_x0_ |latexmath:[$2^{10}$]

|SLLW |_rd_=_x0_ |latexmath:[$2^{10}$]

|SRLW |_rd_=_x0_ |latexmath:[$2^{10}$]

|SRAW |_rd_=_x0_ |latexmath:[$2^{10}$]

|FENCE |_rd_=_x0_, _rs1_≠_x0_,_fm_=0, and either _pred_=0 or _succ_=0 |latexmath:[$2^{10}-63$]

|FENCE |_rd_≠_x0_, _rs1_=_x0_, _fm_=0, and either _pred_=0 or _succ_=0  |latexmath:[$2^{10}-63$]

|FENCE |_rd_=_rs1_=_x0_, _fm_=0, _pred_=0, _succ_≠0 |15

|FENCE |_pred_=0 or _succ_=0, _pred_≠W, _succ_ =0  | 15

|FENCE |_rd_=_rs1_=_x0_, _fm_=0, _pred_=W, _succ_=0 |1 | PAUSE

|SLTI |_rd_=_x0_ |latexmath:[$2^{17}$] .10+.^|_Designated for custom use_

|SLTIU |_rd_=_x0_ |latexmath:[$2^{17}$]

|SLLI |_rd_=`x0`, and either _rs1_&#8800;``x0`` or _shamt_&#8800;31 |latexmath:[$2^{11}-1$]

|SRLI |_rd_=`x0` |latexmath:[$2^{11}$]

|SRAI |_rd_=`x0`, and either _rs1_&#8800;``x0`` or _shamt_&#8800;7 |latexmath:[$2^{11}-1$]

|SLLIW |_rd_=_x0_ |latexmath:[$2^{10}$]

|SRLIW |_rd_=_x0_ |latexmath:[$2^{10}$]

|SRAIW |_rd_=_x0_ |latexmath:[$2^{10}$]

|SLT |_rd_=_x0_ |latexmath:[$2^{10}$]

|SLTU |_rd_=_x0_ |latexmath:[$2^{10}$]
|===

NOTE: `slli x0, x0, 0x1f` and `srai x0, x0, 7` were previously designated as
custom HINTs, but they have been appropriated for use in semihosting calls, as
described in <<ecall-ebreak>>.
To reflect their usage in practice, the base ISA spec has been changed to
designate them as standard HINTs.
