The ARM Cortex M3 is a 32-bit processor, which means it primarily operates on 32-bit data. However, it does have some limited support for 64-bit data types and operations. In this article, we’ll look at the 64-bit capabilities of the Cortex M3 and how to use them.
64-bit integer types
The Cortex M3 supports two 64-bit integer types: int64_t and uint64_t. These types allow you to store 64-bit signed and unsigned integer values respectively. They take up 8 bytes (64 bits) of memory.
You can declare variables of these types like:
int64_t i64;
uint64_t u64;
And assign values to them:
i64 = -9223372036854775808; // min 64-bit signed int
u64 = 18446744073709551615; // max 64-bit unsigned int
Integer literals can also be suffixed with LL or ULL to make them 64-bit:
int64_t i64 = -9223372036854775808LL;
uint64_t u64 = 18446744073709551615ULL;
64-bit Operations
The Cortex M3 supports most arithmetic and bitwise operations on 64-bit integer types including:
- Addition, subtraction
- Multiplication, division
- Bitwise AND, OR, XOR, NOT
- Left and right shifts
For example:
int64_t a = 1234, b = 5678;
int64_t c = a + b; // c = 6912
uint64_t d = 0xFF00FF00, e = 0x00FF00FF;
uint64_t f = d & e; // f = 0xFF0000FF
However, some limitations apply when using 64-bit operations on Cortex M3:
- There is no hardware division support for 64-bit values. Division is implemented in software and is very slow.
- Multiplication of two 64-bit values requires multiple 32-bit multiplications and additions. It is slower than 32-bit multiplication.
- Bitwise shifts by more than 31 places are undefined.
- Bitfields cannot be larger than 32 bits.
So for performance critical code, it is better to use 32-bit arithmetic where possible.
Accessing 64-bit data
Since the Cortex M3 is a 32-bit processor, it cannot access 64-bit data types natively. Instead, 64-bit values need to be accessed in two 32-bit chunks.
For example, to read a 64-bit integer:
uint64_t val;
uint32_t low = *(uint32_t*)&val; //get lower 32 bits
uint32_t high = *((uint32_t*)&val + 1); //get upper 32 bits
And to write:
uint64_t val;
uint32_t low = 0x1234ABCD;
uint32_t high = 0x7890EF01;
*(uint32_t*)&val = low; //set lower 32 bits
*((uint32_t*)&val + 1) = high; //set upper 32 bits
This dual access method works for both int64_t and uint64_t types. Keep in mind that the endianness also matters here – the lower 32 bits come first in memory on little endian systems.
64-bit Loads and Stores
The Cortex M3 instruction set includes LDM, STM and LDRD instructions that can load and store 64-bit data between memory and registers.
For example:
uint64_t val;
// Load val from memory into R0,R1
LDM (R8), {R0-R1};
// Store R0,R1 into val in memory
STM (R8), {R0-R1};
// Load 64-bit value from [R2] into R0,R1
LDRD R0, R1, [R2];
This allows efficiently transferring 64-bit data between memory and the register file. Individual 32-bit loads/stores can also be used, but are less efficient.
Comparisons
The Cortex M3 instruction set has CMP and CMn instructions that allow comparing 64-bit registers or a register with a value in memory. For example:
CMP R0, R1 // compare R0,R1 register pair
CMN R0, #1 // compare R0,R1 with value 1
This sets the status flags like N, Z, C, V based on the 64-bit comparison result. The flags can then be tested to see the relation between the values.
In addition, software methods can be used to compare 64-bit values by comparing the individual 32-bit halves.
Hardware Multiply and Accumulate
The Cortex M3 has a 32×32 bit multiplier that can be used to efficiently multiply 32-bit operands and 64-bit accumulators. This is provided by the SMMLA and SMMLS instructions.
For example:
SMMLA R0,R1,R6,R7 // R0,R1 = R0,R1 + (R6 * R7)
This allows implementing 64-bit multiply-accumulate operations very efficiently in hardware.
Summary
In summary:
- The Cortex M3 supports 64-bit integer types int64_t and uint64_t
- Most arithmetic and bitwise operations are supported on 64-bit types
- Hardware multiplication, division and shifting is limited for 64-bit values
- LDM, STM and LDRD instructions can load/store 64-bit data efficiently
- Status flags from CMP and CMN allow 64-bit comparisons
- SMMLA instruction provides efficient 64-bit multiply-accumulate
While the Cortex M3 is 32-bit, utilizing these 64-bit features can be useful for applications like cryptography, large integer math, wide memory addressing, etc. But care must be taken to understand the limitations and performance impacts.