How to determine the endian mode the processor is running in? - arm

How do I determine the endian mode the ARM processor is running in using only assembly language.
I can easily see the Thumb/ARM state reading bit 5 of the CPSR, but I don't know if there a corresponding bit in the CPSR or elsewhere for endianness.
;silly example trying to execute ARM code when I may be in Thumb mode....
MRS R0,CPSR
ANDS R0,#0x20
BNE ThumbModeIsActive
B ARMModeIsActive
I've got access to the ARM7TDMI data sheet, but this document does not tell me how to read the current state.
What assembly code do I use to determine the endianness?
Let's assume I'm using an ARM9 processor.

There is no CPSR bit for endianness in ARMv4 (ARM7TDMI) or ARMv5 (ARM9), so you need to use other means.
If your core implements system coprocessor 15, then you can check the bit 7 of the register 1:
MRC p15, 0, r0, c1, c0 ; CP15 register 1
TST r0, #0x80 ; check bit 7 (B)
BNE big_endian
B little_endian
However, the doc (ARM DDI 0100E) seems to hint that this bit is only valid for systems where the endianness is configurable at runtime. If it's set by the pin, the bit may be wrong. And, of course, on most(all?) ARM7 cores, the CP15 is not present.
There is a platform-independent way of checking the endianness which does not require any hardware bits. It goes something like this:
LDR R0, checkbytes
CMP R0, 0x12345678
BE big_endian
BNE little_endian
checkbytes
DB 0x12, 0x34, 0x56, 0x78
Depending on the current endianness, the load will produce either 0x12345678 or 0x78563412.

ARMv6 and later versions let you check CPSR bit E (9) for endianness.
Before ARMv6 co-processor 15 register c1 bit 7 should tell which endianness core is using.
In both cases 1 is big-endian while 0 is little-endian.

Related

How to set carry flag on ARM to 0 or 1?

I couldn't find any tutorial on how to set the flags for the Carry on ARM to 1 or to 0. Can anybody help me out with that?
As in put ARM CPU in different modes and linux's irqflags.h, setting the mode, IRQ and carry flags can all be done in the same way.
Generally the macros is like,
.macro set_cflag, temp_reg
mrs \temp_reg, cpsr
bic \temp_reg, \temp_reg, #(1<<29)
msr cpsr_f, \temp_reg
.endm
.macro clear_cflag, temp_reg
mrs \temp_reg, cpsr
orr \temp_reg, \temp_reg, #(1<<29)
msr cpsr_f, \temp_reg
.endm
It is three steps,
Read the old value.
Update the flag in a working register.
Write the value back.
Some additional details are 'atomic' behaviour. Ie, you might need to disable interrupts and memory faults, etc. For some user code or a simple 'polling mode' bare metal, the above is fine.
If you really want to be 'efficient'; looking at your surrounding context and known registers you can execute some instruction that you know will set/clear the carry flag. For instance, if R0 is '0' then adds r0,r0,r0 will clear the carry flag. An instruction like eors R0,R0,R0 will not touch the carry bit. It may depend on whether you also need to know about other NZV bits. The notation 'cpsr_f' will only alter the NZCV bits. You can use msr cpsr_f, #NZCV_bits if you want to set/clear all of these. Ie, you don't care about the old value of all of them arch restrictions . The other flags, like mode, IRQ, etc will remain untouched.
See also:
Heyrick on status register.
ARM Q bit

decode ARM BL instruction

I'm just getting started with the ARM architecture on my Nucleo STM32F303RE, and I'm trying to understand how the instructions are encoded.
I have running a simple LED-blinking program, and the first few disassembled application instructions are:
08000188: push {lr}
0800018a: sub sp, #12
235 __initialize_hardware_early ();
0800018c: bl 0x80005b8 <__initialize_hardware_early>
These instructions resolve to the following in the hex file (displayed weird in Eclipse -- each 32-bit word is in MSB order, but Eclipse doesn't seem to know it... but that's for another topic):
address 0x08000188: B083B500 FA14F000
Using the ARM Architecture Ref Manual, I've confirmed the first 2 instructions, push (0xB500) and sub (0xB083). But I can't make any sense out of the "bl" instruction.
The hex instruction is 0xFA14F000. The Ref Manual says it breaks down like this:
31.28 27 26 25 24 23............0
cond 1 0 1 L signed_immed_24
The first "F" (0xF......) makes sense: all conditions are set (ALways).
The "A" doesn't make sense though, since the L bit should be set (1011). Shouldn't it be 0xFB......?
And the signed_immed_24 doesn't make sense, either. The ref manual says:
- start with 0x14F000
- sign extend to 30 bits (signed 2's-complement), giving 0x0014F000
- shift left to form 32-bit value, giving 0x0053C000
- add to the PC, which is the current instruction + 8, giving 0x0800018c + 8 + 0x0053C000, or 0x0853C194.
So I get a branch address of 0x0853C194, but the disassembly shows 0x080005B8.
What am I missing?
Thanks!
-Eric
bl is two, separate, 16 bit instructions. The armv5 (and older) ARM ARM does a better job of documenting them.
111HHoffset11
From the ARM ARM
The first Thumb instruction has H == 10 and supplies the high part of
the branch offset. This instruction sets up for the subroutine call
and is shared between the BL and BLX forms.
The second Thumb instruction has H == 11 (for BL) or H == 01 (for
BLX). It supplies the low part of the branch offset and causes the
subroutine call to take place.
0xFA14 0xF000
0xF000 is the first instruction upper offset is zeros
0xFA14 is the second instruction offset is 0x214
If starting at 0x0800018c then it is 0x0800018C + 4 + (0x0000214<<1) = 0x080005B8. The 4 is the two instructions head for the current PC. And the offset is units of (16 bit) instructions.
I guess the armv7-m ARM ARM covers it as well, but is harder to read, and apparently features were added. But they do not affect you with this branch link.
The ARMv5 ARM ARM does a better job of describing what happens as well. you can certaily take these two separate instructions and move them apart
.byte 0x00,0xF0
nop
nop
nop
nop
nop
.byte 0x14,0xFA
and it will branch to the same offset (relative to the second instruction). Maybe the broke that in some cores, but I know in some (after armv5) it works.

Encoding and decoding ARM instructions to/ from binary

Task 1: Write the corresponding ARM assembly representation for the following instructions:
11101001_000111000001000000010000
11100100_110100111000000000011001
10010010_111110100100000011111101
11100001_000000010010000011111010
00010001_101011101011011111001100
Task 2: Write the instruction code for the following instructions:
STMFA R13!, {R1, R3, R5-R11}
LDR R11, [R3, R5, LSL #2]
MOVMI R6, #1536
LDR R1, [R0, #4]!
EORS R3, R5, R10, RRX
I have zero experience with this material and the professor has left us students out to dry. Basically I've found the various methods for decoding these instructions but I have three major doubts still.
I don't have any idea on how to get started on decoding binary to ARM Instructions which is the first part of the homework.
I can't find some of these suffixes for example on EORS what is the S? Is it the set condition bit? Is it set to 1 when there is an S in front of the instruction?
I don't what to make of having multiple registers in one instruction line. Example:
EORS R3,R5,R10,RRx
I don't understand what's going on there with so many registers.
Any nudge in the right direction is greatly appreciated. Also I have searched the ARM manual, they're not very helpful for someone with no understanding of what they're looking for. They do have the majority of instructions for coding and decoding but have little explanation for the things I asked above.
If you have the ARM v7 A+R architecture manual (DDI0406C) there is a good table-based decode/disassembly description in chapter A5. You start at table A5.1 and and depending on the value of different bits in the instruction word it refers to more and more specific tables leading to the instruction.
As an example, consider the following instruction:
0001 0101 1001 1111 0000 0000 0000 1000
According to the first table it is an unsigned load/store instruction since the condition is not 1111 and op1 is 010. The encoding of this is further expanded in A5.3
From this section we see that A=0, op1=11001, Rn=1111 (PC), and B=0. This implies that the instruction is LDR(literal). Checking the page describing this instruction and remembering that cond=0001 we see that the instruction isLDRNE R0, [PC, #4].
To do the reverse procedure you look up the instruction in the alphabetical list of instructions and follow the pattern.
Looking at a different part of (one of) the ARM architectural reference manuals (not the cortex-m (armv6m armv7m) you want the ARMv5 one or the ARMv7-AR one) going to look at a thumb instruction, but the ARM instructions work the same way and are a couple chapters prior.
it says thumb instruction set as the section/chapter, then shortly into that is a table that shows thumb instruction set encoding or you can just search for that. one if them is called Add/subtract register, there are a lot of hardcoded ones and zeros up front then bit 9 is opc, then rm, rn and rd bits.
arm toolchains are easy to come by for windows mac and linux or can easily build from sources (just need binutils). assembling this
.thumb
add r1,r2,r3
add r1,r2,r4
add r1,r2,r5
add r1,r2,r6
add r1,r2,r7
then disassembling gives
00000000 <.text>:
0: 18d1 adds r1, r2, r3
2: 1911 adds r1, r2, r4
4: 1951 adds r1, r2, r5
6: 1991 adds r1, r2, r6
8: 19d1 adds r1, r2, r7
from that chart in the ARM ARM the add register starts with hardcoded bits 000110 the instructions above start with 0x18 or 0x19 which both start with the 6 bits 000110 (00011000 or 00011001). In the alphabetical list of thumb instructions we look for the add instructions. find the three register one and in this case it has 7 bits which happen to match the bits we are decoding 0001100 so we are on the right track. the the last 9 bits are three sets of three
0x1951 is 0001100101010001 or 0001100 101 010 001, the last nine represent r5, r2, and r1. Looking at the syntax part of the instruction it shows add rd, rn, rm but the machine code has rm, rn, rd so we take the machine code and rearrange per the syntax and get add r1,r2,r5. Not bad it matches, now unfortunately the s here is confusing, this thumb instruction doesnt have an s bit there wasnt room so this one always updates the flags, so the nature of this instruction and toolchain and how I used it requires the add without the s on the assembly end and disassembles with the s. confusing, sorry. when using arm instructions the letter s works as expected.
Just repeat this with the ARM instructions in either direction. The immediate values are going to be the most challenging part of this. Or not depends on the specific instruction and immediate encoding.

ARM mode, load 32bits constant. General case

I'm looking for a generic way to load a 32 bits constant in ARM mode.
Unfortunately I can't use neither "ldr rX, =const" (due to external problems) nor movw/movt (my target is a armv6k)
This is my attempt:
mov rX, 0
orr rX, (const&0x000000FF)
orr rX, (const&0x0000FF00)
orr rX, (const&0x00FF0000)
orr rX, (const&0xFF000000)
Is my code correct? Can you suggest me a better way? Thank you.
arm and gnu assemblers both allow the syntax:
ldr rX,=0x12345678
Which results in a location within pc relative addressing range (if possible) being allocated with the data word 0x12345678 and the instruction encoded as a pc-relative load, basically:
ldr r0,my_data
...
my_data: .word 0x12345678
Your other alternative is one instruction less than what you outlined:
mov rX,0x0000078
orr rX,rX,0x00005600
orr rX,rX,0x00340000
orr rX,rX,0x12000000
Now at least with gcc, dont know about arm, if you use the ldr rX,=number feature and the number can be encoded with a single move, it will encode that single mov...

What is the ARM Thumb Instruction set?

under "The Thumb instruction set" in section 1-34 of "ARM11TechnicalRefManual" it said that:
"The Thumb instruction set is a subset of the most commonly used 32-bit ARM instructions.Thumb instructions are 16 bits long,and have a corresponding 32-bit ARM instruction that has the same effect on processor model."
can any one explain more about this especially second sentence and say how does processor perform it?
The ARM processor has 2 instruction sets, the traditional ARM set, where the instructions are all 32-bit long, and the more condensed Thumb set, where most common instructions are 16-bit long (and some are 32-bit long). Which instruction set to run can be chosen by the developer, and only one set can be active (i.e. once the processor is switched to Thumb mode, all instructions will be decoded as using the Thumb instead of ARM).
Although they are different instruction sets, they share similar functionality, and can be represented using the same assembly language. For example, the instruction
ADDS R0, R1, R2
can be compiled to ARM (E0910002 / 11100000 10010001 00000000 00000010) or Thumb (1888 / 00011000 10001000). Of course, they perform the same function (add r1 and r2 and store the result to r0), even if they have different encodings. This is the meaning of Thumb instructions are 16 bits long,and have a corresponding 32-bit ARM instruction that has the same effect on processor model.
Every* instruction in Thumb encoding also has a corresponding encoding in ARM, which is meant by the "subset" sentence.
*: Not strictly true, there is not "IT" instruction in ARM, although ARM doesn't need "IT" anyway (it will be ignored by the assembler).

Resources