summaryrefslogtreecommitdiff
path: root/thesis/fix-storing-pc.tex
diff options
context:
space:
mode:
Diffstat (limited to 'thesis/fix-storing-pc.tex')
-rw-r--r--thesis/fix-storing-pc.tex65
1 files changed, 65 insertions, 0 deletions
diff --git a/thesis/fix-storing-pc.tex b/thesis/fix-storing-pc.tex
new file mode 100644
index 0000000..3b96314
--- /dev/null
+++ b/thesis/fix-storing-pc.tex
@@ -0,0 +1,65 @@
+\subsection{Storing the program counter}
+\label{sec:fix-storing-pc}
+The first issue I ran into is that of storing the program counter.
+Storing the program counter on the stack is something done commonly in many languages during a function call.
+
+\subsubsection{ARM code example}
+Usually, an offset to the actual program counter at the moment of the store instruction is stored,
+to allow for a branch after that instruction, and have the callee return to the address after that branch.
+The ARM architecture accommodates for this: an instruction that reads the program counter, actually reads
+ \enquote{the address of the current instruction plus 8}~\cite[A2.3]{armv7ar}.
+The following ARM assembly example illustrates this (\texttt{armstartup.s:540-2}):
+
+\begin{minted}{ual}
+ str pc,[sp,#-4]! @ 0x20 Store PC on the stack
+ bl init_clean @ 0x24 Branch to init_clean
+ tst r4,r4 @ 0x28
+\end{minted}
+
+Dummy addresses have been indicated in comments.
+When execution arrives at \ual{0x20}, the program counter is set to \ual{0x20}.
+Per the above documentation, \ual{str} stores \ual{0x20+8} on the stack%
+ \footnote{\ual{[sp,#-4]!}
+ indicates that the stack pointer should be decreased by four before storing the program counter on the stack.
+ It has nothing to do with the 8 offset that is added to the program counter itself.}.
+The processor branches to \ual{init_clean},
+ which loads the value from the stack back into the program counter to return to the caller.
+The program counter is then \ual{0x28}.
+For the next instruction cycle, the \ual{tst} command is executed.
+
+\subsubsection{Problems in Thumb-2}
+There are two reasons why the above cannot be used in Thumb-2 code.
+
+First, \ual{pc} is not allowed as the first operand to a \ual{str} instruction.
+Hence, we need to first move \ual{pc} to an auxiliary register, and then push that on the stack.
+We then get:
+
+\begin{minted}{ual}
+ add lr,pc,#9 @ 0x20 Save PC+4+9 to LR
+ str lr,[sp,#-4]! @ 0x24 Store LR on the stack
+ bl init_clean @ 0x28 Branch to init_clean
+ tst r4,r4 @ 0x2c
+\end{minted}
+
+We store the value \ual{0x2d}.
+This address points to the \ual{tst} instruction as before, with the LSB set to 1 to indicate Thumb mode.
+
+The second problem we meet is that the instruction to store the program counter may be halfword-aligned rather than word-aligned.
+We saw above that a read of the program counter in ARM mode reads as PC+8.
+In Thumb mode this is more complicated.
+In this case, we
+ \enquote{[r]ead the word-aligned PC value, that is,
+ the address of the current instruction + 4,
+ with bits [1:0] forced to zero}~\cite[A5.1.2]{armv7m}.
+This means that when the \ual{add} instruction above is at \ual{0x22},
+ we will still store \ual{0x2d} on the stack,
+ since the word-aligned program counter is \ual{0x20} as before.
+However, in this case \ual{bl} is located at \ual{0x2a}, and since this is a 32 bits instruction we point to the middle of that instruction.
+
+In hand-written code, we can solve this by adding labels for the addresses we want to store on the stack.
+In generated code, we need to keep track of the current alignment and add either \ual{9} or \ual{11} to the read program counter.
+
+\subsubsection{Complexity analysis}
+To be done. For every occurrence:
+
+Code size: +1 word; instructions: +1