1
votes

I am doing some assembly programming in Linux ARM and FreeBSD ARM. I have some questions regarding ARM pipeline and assembly programming...

Q1. suppose there are ARM assembly instructions (ARM mode) such as

add r0, pc, #0
mov r1, #1
mov r1, #2
mov r1, #3
mov r1, #4

when these are executed, what is the value of r0? and why?

Q2. suppose there are arm assembly instructions such as

sub r0, r0, r0    
sub r1, r1, r1
svc #?(a system call which never returns such as execve)
mov r2, #1
mov r3, #1

assuming svc never returns, does mov r2, #1 executes or not? (executed because of pipelining...?)

Q3. is result of Q1, Q2 are same in Thumb mode? or not? why?

Q4, in FreeBSD, does Thumb mode svc numbering differ from ARM mode? svc $0x3b (execve) works fine in ARM mode, but it doesn't work in Thumb mode. e.g.:

mov r7, $0x3b
svc 1

this tells me 'bad system call'

2
I think question 4 belongs in a separate questiontangrs

2 Answers

4
votes

The pipeline effect has been exposed explicitly in the first ARM architecture versions. Since then the pipelines have changed, but the value of PC register has been retained for compatibility:

  1. In ARM mode, reading PC returns address of the current instruction plus 8 (i.e. two ARM instructions ahead). This allowed for the original call sequence which was used before introduction of the BL instruction:

      MOV LR, PC  ; LR gets loaded with address of "retaddr"
      MOV PC, R2  ; jump to adddress in R2
    retaddr:
      ; "MOV PC, LR" returns here
    
  2. In Thumb mode, reading PC return address of the current instruction plus 4 (i.e. two 16-bit Thumb instructions ahead). This behavior remains the same even in Thumb-2 which allows 32-bit instructions.

This can be confirmed by reading the ARM Architecture Manual:

(from B1.3 ARM processor modes and ARM core registers)

// R[] - non-assignment form
// =========================
bits(32) R[integer n]
  assert n >= 0 && n <= 15;
  if n == 15 then
    offset = if CurrentInstrSet() == InstrSet_ARM then 8 else 4;
    result = _R[RName_PC] + offset;
  else
    result = Rmode[n, CPSR.M];
  return result;

Now, to answer your questions:

Q1: r0 will get the address of the add instruction plus 8.
Q2: probably not, but even if does get executed (in processors with speculative execution), its results will be discarded when the execution goes into the svc handler. So from the programmer's point of view the mov r2, #1 is not executed.
Q3: in Q1, r0 will get the address of the add instruction plus 4. Q2 gets the same answer.
Q4: as mentioned, it's not related to pipeline so better asked as a separate question.

0
votes

Since pipe-lining occurs transparently, you do not need to worry about it most of the time unless you're optimizing code or using the r15/pc register.

  1. If I remember correctly, r0 should contain the address of the mov r1, #2 instruction (two instruction ahead).
  2. No, it does not execute if the system call doesn't return. Why should it?
  3. It should be similar.

You should be able to confirm most of my answers by simply running your sample code in a debugger.