Rewrite pseudo ops, relocation, and relaxation

This commit is contained in:
John Winans 2021-02-11 14:16:41 -06:00
parent 67ea29c8d9
commit cda9d96127

View File

@ -170,9 +170,7 @@ For example, to set \reg{t3} to zero:
\DrawInsnTypeIPicture{addi x1, x7, 4}{00000000010000111000000010010011} \DrawInsnTypeIPicture{addi x1, x7, 4}{00000000010000111000000010010011}
{\small
\begin{verbatim} \begin{verbatim}
addi t0, zero, 4 # t0 = 4 addi t0, zero, 4 # t0 = 4
addi t1, t1, 100 # t1 = 104 addi t1, t1, 100 # t1 = 104
@ -186,7 +184,7 @@ For example, to set \reg{t3} to zero:
addi x0, x0, 0 # no operation (pseudo: nop) addi x0, x0, 0 # no operation (pseudo: nop)
addi rd, rs, 0 # copy reg rs to rd (pseudo: mv rd, rs) addi rd, rs, 0 # copy reg rs to rd (pseudo: mv rd, rs)
\end{verbatim} \end{verbatim}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -206,6 +204,7 @@ Ideas for the order of introducing instructions.
\label{uguide:srai} \label{uguide:srai}
\label{uguide:slli} \label{uguide:slli}
\label{uguide:srli} \label{uguide:srli}
{\small
\begin{verbatim} \begin{verbatim}
andi andi
ori ori
@ -217,7 +216,7 @@ Ideas for the order of introducing instructions.
slli slli
srli srli
\end{verbatim} \end{verbatim}
}
\section{Transferring Data Between Registers and Memory} \section{Transferring Data Between Registers and Memory}
@ -232,6 +231,7 @@ Copying values from memory to a register (first examples using regs set with add
\label{uguide:lw} \label{uguide:lw}
\label{uguide:lbu} \label{uguide:lbu}
\label{uguide:lhu} \label{uguide:lhu}
{\small
\begin{verbatim} \begin{verbatim}
lb lb
lh lh
@ -239,16 +239,19 @@ Copying values from memory to a register (first examples using regs set with add
lbu lbu
lhu lhu
\end{verbatim} \end{verbatim}
}
Copying values from a register to memory: Copying values from a register to memory:
\label{uguide:sb} \label{uguide:sb}
\label{uguide:sh} \label{uguide:sh}
\label{uguide:sw} \label{uguide:sw}
{\small
\begin{verbatim} \begin{verbatim}
sb sb
sh sh
sw sw
\end{verbatim} \end{verbatim}
}
\section{RR operations} \section{RR operations}
\label{uguide:add} \label{uguide:add}
@ -261,6 +264,7 @@ Copying values from a register to memory:
\label{uguide:xor} \label{uguide:xor}
\label{uguide:sltu} \label{uguide:sltu}
\label{uguide:slt} \label{uguide:slt}
{\small
\begin{verbatim} \begin{verbatim}
add add
sub sub
@ -273,12 +277,14 @@ Copying values from a register to memory:
sltu sltu
slt slt
\end{verbatim} \end{verbatim}
}
\section{Setting registers to large values using lui with addi} \section{Setting registers to large values using lui with addi}
\label{uguide:lui} \label{uguide:lui}
\label{uguide:auipc} \label{uguide:auipc}
{\small
\begin{verbatim} \begin{verbatim}
addi // useful for values from -2048 to 2047 addi // useful for values from -2048 to 2047
lui // useful for loading any multiple of 0x1000 lui // useful for loading any multiple of 0x1000
@ -288,11 +294,11 @@ Copying values from a register to memory:
auipc // Load an address relative the the current PC (see la pseudo) auipc // Load an address relative the the current PC (see la pseudo)
addi addi
lui // Load constant into into bits 31:12 (see li pseudo) lui // Load constant into into bits 31:12 (see li pseudo)
addi // add a constant to fill in bits 11:0 addi // add a constant to fill in bits 11:0
if bit 11 is set then need to +1 the lui value to compensate if bit 11 is set then need to +1 the lui value to compensate
\end{verbatim} \end{verbatim}
}
\section{Labels and Branching} \section{Labels and Branching}
@ -314,6 +320,7 @@ Start to introduce addressing here?
\label{uguide:bgez} \label{uguide:bgez}
\label{uguide:bltz} \label{uguide:bltz}
\label{uguide:bgtz} \label{uguide:bgtz}
{\small
\begin{verbatim} \begin{verbatim}
beq beq
bne bne
@ -334,40 +341,9 @@ Start to introduce addressing here?
bltz rs, offset # pseudo for: blt rs, x0, offset bltz rs, offset # pseudo for: blt rs, x0, offset
bgtz rs, offset # pseudo for: blt x0, rs, offset bgtz rs, offset # pseudo for: blt x0, rs, offset
\end{verbatim} \end{verbatim}
}
\section{Relocation}
Absolute:
\begin{verbatim}
%hi(symbol)
%lo(symbol)
\end{verbatim}
PC-relative:
\begin{verbatim}
%pcrel_hi(symbol)
%pcrel_lo(label)
\end{verbatim}
Using \verb@auipc@ \& \verb@addi@ together with label references:
The \verb@%pcrel_lo()@ uses the label to find the associated \verb@%pcrel_hi()@.
The label MUST be on a line that used a \verb@%pcrel_hi()@ or get an error.
This is needed to calculate the proper offset.
Things like this are legal:
\begin{verbatim}
label: auipc t1, %pcrel_hi(symbol)
addi t2, t1, %pcrel_lo(label)
addi t3, t1, %pcrel_lo(label)
lw t4, %pcrel_lo(label)(t1)
sw t5, %pcrel_lo(label)(t1)
\end{verbatim}
Discuss how relaxation works.
see: \url{https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md}
\section{Jumps} \section{Jumps}
@ -375,87 +351,276 @@ Introduce and present subroutines but not nesting until introduce stack operatio
\label{uguide:jal} \label{uguide:jal}
\label{uguide:jalr} \label{uguide:jalr}
{\small
\begin{verbatim} \begin{verbatim}
jal jal
jalr jalr
\end{verbatim} \end{verbatim}
}
\section{Pseudo Operations} \section{Pseudo Operations}
\enote{Explain why we have pseudo ops. Most of these mappings are lifted from the ISM, Vol 1, V2.2}% {\small
\begin{verbatim} \begin{verbatim}
la rd, symbol li rd,constant lui rd,(constant >>U 12)+(constant & 0x00000800 ? 1 : 0)
auipc rd, symbol[31:12] addi rd,rd,(constant & 0xfff)
addi rd, rd, symbol[11:0]
l{b|h|w|d} rd, symbol la rd,label
auipc rd, symbol[31:12] auipc rd,((label-.) >>U 12) + ((label-.) & 0x00000800 ? 1 : 0)
l{b|h|w|d} rd, symbol[11:0](rd) addi rd,rd,((label-(.-4)) & 0xfff)
s{b|h|w|d} rd, symbol, rt # rt is the temp reg to use for the operation l{b|h|w} rd,label
auipc rt, symbol[31:12] auipc rd,((label-.) >>U 12) + ((label-.) & 0x00000800 ? 1 : 0)
s{b|h|w|d} rd, symbol[11:0](rt) l{b|h|w} rd,((label-(.-4)) & 0xfff)(rd)
s{b|h|w} rd,label,rt # rt used as a temp reg for the operation (default=x6)
auipc rt,((label-.) >>U 12) + ((label-.) & 0x00000800 ? 1 : 0)
s{b|h|w} rd,((label-(.-4)) & 0xfff)(rt)
j offset jal x0, offset call label auipc x1,((label-.) >>U 12) + ((label-.) & 0x00000800 ? 1 : 0)
jal offset jal x1, offset jalr x1,((label-(.-4)) & 0xfff)(x1)
jr rs jalr x0, rs, 0
jalr rs jalr x1, rs, 0
ret jalr x0, x1, 0
call offset auipc x6, offset[31:12] tail label,rt # rt used as a temp reg for the operation (default=x6)
jalr x1, x6, offset[11:0] auipc rt,((label-.) >>U 12) + ((label-.) & 0x00000800 ? 1 : 0)
jalr x0,((label-(.-4)) & 0xfff)(rt)
tail offset auipc x6, offset[31:12] # same as call but no x1 mv rd,rs addi rd,rs,0
jalr x0, x6, offset[11:0]
j label jal x0,label
mv rd,rs addi rd,rs,0 jal label jal x1,label
jr rs jalr x0,0(rs)
li rd,number lui rd,(number >>U 12)+(number&0x00000800 ? 1 : 0) jalr rs jalr x1,0(rs)
addi rd,rd,(number&0xfff) ret jalr x0,0(x1)
\end{verbatim} \end{verbatim}
}
\subsection{The {\tt li} Pseudo Instruction} \subsection{The {\tt li} Pseudo Instruction}
Note that the {\tt li} pseudo instruction includes a conditional addition of 1 to the operand Note that the {\tt li} pseudo instruction includes a conditional addition of 1 to the operand
in the {\tt lui} instruction. This is because the immediate operand in the in the {\tt lui} instruction. This is because the immediate operand in the
{\tt addi} instruction is sign-extended before it is added to rd. {\tt addi} instruction is sign-extended before it is added to \verb@rd@.
If the immediate operand to the {\tt addi} has its most-significant-bit set to 1 then If the immediate operand to the {\tt addi} has its most-significant-bit set to 1 then
it will have the effect of subtracting 1 from the most significant 20-bits in {\tt rd}. it will have the effect of subtracting 1 from the operand in the \verb@lui@ instruction.
Consider putting the value {\tt 0x12345800} into register {\tt x5} using the following Consider the case of putting the value {\tt 0x12345800} into register {\tt x5}:
naive example code:
{\small
\begin{verbatim}
li x5,0x12345800
\end{verbatim}
}
{\color{red}
A naive (incorrect) solution might be:
{\small
\begin{verbatim} \begin{verbatim}
lui x5,0x12345 // x5 = 0x12345000 lui x5,0x12345 // x5 = 0x12345000
addi x5,x5,0x800 // x5 = 0x12345000 + sx(0x800) = 0x12345000 + 0xfffff800 = 0x12344800 addi x5,x5,0x800 // x5 = 0x12345000 + sx(0x800) = 0x12345000 + 0xfffff800 = 0x12344800
\end{verbatim} \end{verbatim}
}
The result of the above code is that an incorrect value has been placed into x5.
}
Therefore, in order to put the value {\tt 0x12345800} into register {\tt x5}, the value To remedy this problem, the value used in the {\tt lui} instruction can altered
used in the {\tt lui} instruction will altered to compensate for the sign-extention (by adding 1 to its operand) to compensate for the sign-extention in the {\tt addi}
in the {\tt addi} instruction: instruction:
{\small
\begin{verbatim} \begin{verbatim}
lui x5,0x12346 // x5 = 0x12346000 lui x5,0x12346 // x5 = 0x12346000 (note this is 0x12345 + 1)
addi x5,x5,0x800 // x5 = 0x12346000 + sx(0x800) = 0x12346000 + 0xfffff800 = 0x12345800 addi x5,x5,0x800 // x5 = 0x12346000 + sx(0x800) = 0x12346000 + 0xfffff800 = 0x12345800
\end{verbatim} \end{verbatim}
}
Keep in mind that the {\em only} time that this altering of the operand in the {\tt lui} Keep in mind that the {\em only} time that this altering of the operand in the {\tt lui}
instruction will take place is when the most-significant-bit of the operand in the instruction should take place is when the most-significant-bit of the operand in the
{\tt addi} is set to one. {\tt addi} is set to one.
Consider the case where we wish to put the value {\tt 0x12345700} into register {\tt x5}: Consider the case where we wish to put the value {\tt 0x12345700} into register {\tt x5}:
{\small
\begin{verbatim} \begin{verbatim}
lui x5,0x12345 // x5 = 0x12345000 lui x5,0x12345 // x5 = 0x12345000 (note this is 0x12345 + 0)
addi x5,x5,0x700 // x5 = 0x12345000 + sx(0x700) = 0x12345000 + 0x00000700 = 0x12345700 addi x5,x5,0x700 // x5 = 0x12345000 + sx(0x700) = 0x12345000 + 0x00000700 = 0x12345700
\end{verbatim} \end{verbatim}
}
This time, the sign-extension performed by the {\tt addi} instruction will sign-extend the The sign-extension in this example performed by the {\tt addi} instruction will convert the
{\tt 0x700} to {\tt 0x00000700} before the addition. {\tt 0x700} to {\tt 0x00000700} before the addition.
Therefore, the {\tt li} pseudo-instruction will {\em only} increment the operand of the Therefore, the {\tt li} pseudo-instruction must {\em only} increment the operand of the
{\tt lui} instruction when it is known that the operand of the {\tt addi} instruction {\tt lui} instruction when it is known that the operand of the subsequent {\tt addi}
will end up being treated as a negative number. instruction will be a negative number.
\subsection{The {\tt la} Pseudo Instruction}
The \verb@la@ (and others that use \verb@auipc@ such as
the \verb@l{b|h|w}@, \verb@s{b|h|w}@, \verb@call@, and \verb@tail@) pseudo instructions
also compensate for a sign-ended negative number when adding a 12-bit immediate
operand. The only difference is that these use a \verb@pc@-relative addressing mode.
For example, consider the task of putting an address represented by the label \verb@var1@
into register x10:
{\small
\begin{verbatim}
00010040 la x10,var1
00010048 ... # note that the la pseudo instruction expands into 8 bytes
...
var1:
00010900 .word 999 # a 32-bit integer constant stored in memory at address var1
\end{verbatim}
}
The \verb@la@ instruction here will expand into:
{\small
\begin{verbatim}
00010040 auipc x10,((var1-.) >>U 12) + ((var1-.) & 0x00000800 ? 1 : 0)
00010044 addi x10,x10,((var1-(.-4)) & 0xfff)
\end{verbatim}
}
Note that \verb@auipc@ will shift the immediate operand to the left 12 bits and then
add that to the \verb@pc@ register (see \autoref{insn:auipc}.)
The assembler will calculate the value of \verb@(var1-.)@ by subtracting the address
represented by the label \verb@var1@ from the address of the current instruction
(which is expressed as '.') resulting in the number of bytes from the current instruction
to the target label\ldots{} which is \verb@0x000008c0@.
Therefore the expanded pseudo instruction example will become:
{\small
\begin{verbatim}
00010040 auipc x10,((0x00010900-0x00010040) >>U 12) + ((0x00010900-0x00010040) & 0x00000800 ? 1 : 0)
00010044 addi x10,x10,((0x00010900-(0x00010044-4)) & 0xfff) # note the extra -4 here!
\end{verbatim}
}
After performing the subtractions, it will reduce to this:
{\small
\begin{verbatim}
00010040 auipc x10,(0x000008c0 >>U 12) + ((0x000008c0) & 0x00000800 ? 1 : 0)
00010044 addi x10,x10,(0x000008c0 & 0xfff)
\end{verbatim}
}
Continuing to reduce the math operations we get:
{\small
\begin{verbatim}
00010040 auipc x10,0x00000 + 1 # add 1 here because 0x8c0 below has MSB = 1
00010044 addi x10,x10,0x8c0
\end{verbatim}
}
\ldots and\ldots
{\small
\begin{verbatim}
00010040 auipc x10,0x00001
00010044 addi x10,x10,0x8c0
\end{verbatim}
}
Note that the the \verb@la@ exhibits the same sort of technique as the \verb@li@ in that
if/when the immediate operand of the \verb@addi@ instruction has its most significant
bit set then the operand in the \verb@auipc@ has to be incremented by 1 to compensate.
\section{Relocation}
Because expressions that refer to constants and address labels are common in
assembly language programs, a shorthand notation is available for calculating
the pairs of values that are used in the implementation of things like the
\verb@li@ and \verb@la@ pseudo instructions (that have to be written to
compensate for the sign-extension that will take place in the immediate operand
that appears in instructions like \verb@addi@ and \verb@jalr@.)
\subsection{Absolute Addresses}
To refer to an absolute value, the following operators can be used:
{\small
\begin{verbatim}
%hi(constant) // becomes: (constant >>U 12)+(constant & 0x00000800 ? 1 : 0)
%lo(constant) // becomes: (constant & 0xfff)
\end{verbatim}
}
Thus, the \verb@li@ pseudo operation can be expressed like this:
{\small
\begin{verbatim}
li rd,constant lui rd,%hi(constant)
addi rd,rd,%lo(constant)
\end{verbatim}
}
\subsection{PC-Relative Addresses}
The following can be used for PC-relative addresses:
{\small
\begin{verbatim}
%pcrel_hi(symbol) // becomes: ((symbol-.) >>U 12) + ((symbol-.) & 0x00000800 ? 1 : 0)
%pcrel_lo(lab) // becomes: ((symbol-lab) & 0xfff)
\end{verbatim}
}
Note the subtlety involved with the \verb@lab@ on \verb@%pcrel_lo@. It is needed to
determine the address of the instruction that contains the corresponding \verb@%pcrel_hi@.
(The label \verb@lab@ MUST be on a line that used a \verb@%pcrel_hi()@ or get an
error from the assembler.)
Thus, the \verb@la rd,label@ pseudo operation can be expressed like this:
{\small
\begin{verbatim}
xxx: auipc rd,%pcrel_hi(label)
addi rd,rd,%pcrel_lo(xxx) // the xxx tells pcrel_lo where to find the matching pcrel_hi
\end{verbatim}
}
Examples of using the \verb@auipc@ \& \verb@addi@ together with \verb@%pcrel_hi()@ and
\verb@%pcrel_lo()@:
{\small
\begin{verbatim}
xxx: auipc t1,%pcrel_hi(yyy) // (yyy-xxx) >>U 12) + ((yyy-xxx) & 0x00000800 ? 1 : 0)
addi t1,t1,%pcrel_lo(xxx) // ((yyy-xxx) & 0xfff)
...
yyy: // the address: yyy is saved into t1 above
...
\end{verbatim}
}
Things like this are legal:
{\small
\begin{verbatim}
label: auipc t1,%pcrel_hi(symbol)
addi t2,t1,%pcrel_lo(label)
addi t3,t1,%pcrel_lo(label)
lw t4,%pcrel_lo(label)(t1)
sw t5,%pcrel_lo(label)(t1)
\end{verbatim}
}
\section{Relaxation}
\enote{I'm not sure I want to get into the details of how this is done. Just assume it works.}%
In the simplest of terms, {\em Relaxation} refers to the ability of the
linker (not the compiler!) to determine if/when the instructions that
were generated with the \verb@xxx_hi@ and \verb@xxx_lo@ operators are
unneeded (and thus waste execution time and memory) and can therefore
be removed.
However, doing so is not trivial as it will result in moving things around
in memory, possibly changing the values of address labels in the
already-assembled program! Therefore, while the motivation for
rexation is obvious, the process of implementing it is non-trivial.
See: \url{https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md}