Como que tome que habia que invertir los 49 no los 48

.
Sabes lo que me rompi la cabeza intentando ver ese bit mas xD,, era un dolor de ....
Bueno, parece que ya lo solucionaste.
Lo que me parece raro son esos 37 ciclos. son demasiados.
Hay 6 instrucciones, de 32bits, no se si tomarlas como 12 ciclos o 6,
Supongamos 12, que luego por el pipeline se introduzca algunas bubbles por necesidad de los datos. eso lo aumentaria a cerca de 3 ciclos mas.
Sigiuiendo tenes el CALL y RETURN ( BL y BX ) eso va a depender exactamente del PC a donde se dirija, si es un salto a registro y no un literal, tomaria 3 ciclos, si es un literal 2 ciclos, si es un salto el cual no esta alineado a 32 bits tomaria 4 ciclos. entonces supongamos:
12 + 3 + 4 = 17 maximo.. incluso haciendo el doble en las instrucciones el cual NO deberia.
Esta bien que no contamos con, la asignacion de la variable a 0, la asignacion de los valores a R0 y R1 y finalmente el salto a la funcion pero no creo que en esto se vayan 20 ciclos

, Aunque todo depende del nivel de optimizacion, si no posee optimizacion lo creo BASTANTE posible xD, como ya demostre antes el cual sin optimizacion era malisimo, utilizaba de R0 a R3, y estaba continuamente cargando R3 con los datos.
Tenemos antes:, Poner a 0 el valor de DWT_CYCCNT es aun mas, son hasta 5 ciclos para acceder a la memoria flash y tomar el dato de la direccion ( supongo no alineado ) mover 0 a un registro , otro ciclo, almacenar el dato unos 3 ciclos mas. Mover del SP a R0/R1, 4 ciclos ( si es que no hay un double por ahi ). 13 ciclos ya aca , salto puede ser unos 4, 17ciclos y.... casi casi cerca de los 20

Podrias hacer un par de cambios y probar nuevamente con algo asi?
.align 4
Invertir:
RBIT R0, R0 ;@ R0 = Inv(R0)
RBIT R2, R1 ;@ R2 = Inv(R1)
RORS R0, R0, #16 ;@ R0 = Inv(R0) >> 16 Wrap
RORS R2, R2, #16 ;@ R0 = Inv(R0) >> 16 Wrap
BFI R1, R0, #0 ,#16 ;@ R1f = R0[16:0] = Alto invertido Final
BFI R0, R2, #0, #16 ;@ R0 = R0f[32:17] + R0f[16:0]
BX LR ;@ Volver
.end
Lo que hice fue alinearlo a 32bits asi lo que lo llama va mas rapido.
Intente eliminar las dependencias en las entradas de datos.
RBIT R0, R0 ;@ R0 = Inv(R0)
RORS R0, R0, #16 ;@ R0 = Inv(R0) >> 16 Wrap
Antes estaba asi, si en el pipeline entraba R0, para luego RORS usar R0 debia esperar que termine la primera instruccion. Por lo cual posiblemente se agregaba un "bubble" en el pipeline, es decir se retrasaba.
Creo que con el cambio de codigo no hay cambios en el funcionamiento y solo queda probarlo si efectivamente mejoro o no , tambien estaria bueno probar si el align cambia en algo o no la cantidad de ciclos.
PD: Todo esto sin contar si es que tu micro tiene un buffe de prefetch el cual un salto podria darle un miss a este buffer y dejar parado el CPU mientras se carga el buffer con el nuevo contenido. Especialmente en un salto. Lo cual te dejaria con el wait state de la flash + hasta que se cargue todo el pipeline xD
Si podes debuegearlo elgarbe, podes ir posicion por posicion. y podes medir exactamente cuanto mide los ciclos internos. Esa es otra
PD2: Esto de no poder probarlo me mata
PD3:
Ahora que son de 16 bits, te puede llegar a servir otra instruccion:
Pack halfword bottom + top
PKHBT Rd, Rn, Rm{, LSL #<sh>}
Rd[15:0] := Rn[15:0], Rd[31:16] := (Rm LSL sh)[31:16]. sh 0-31.
Pack halfword top + bottom
PKHTB Rd, Rn, Rm{, ASR #<sh>}
Rd[31:16] := Rn[31:16], Rd[15:0] := (Rm ASR sh)[15:0]. sh 1-32.
Especialmente si los pones en R2 y R3 a lo temporal y de ahi lo armas a tu gusto ( quedando creo que solo 4 instrucciones xD ), 2 RBIT y 2 Pack de esos, reduciendolo en 2 a lo que estaba.
Cuando vuelva intento ver si lo puedo escribir con esto.