Lesson 08 Machine code and Compare & Test 1. Overview In this lesson, machine code is discussed and the compare & test instructions supported by the Cortex-M3 processor are introduced. Again, only a subset of these instructions will be discussed. The concept and syntax will generally extend to other instructions as you explore them in the Cortex-M3 instruction set. 2. Machine Code Before going any further, let s take a look at how our instructions are actually encoded As mentioned in the previous lessons, the instruction names (mnemonic) are created for users to develop assembly programs, these names are not what the processor can understand. The instructions must be translated into strings of binary machine (or object) code by an assembler such as the Keil assembler. All machine code is half-word (16 bits) aligned. It means that each instruction is either a single 16-bit half-word in that stream, or a 32-bit instruction consisting of two consecutive half-words. In the Keil IDE, the machine code is included in the listing file that is displayed in the disassembly window. In addition to the machine code, the listing also shows the memory locations where the instructions are stored and the original source code. A screenshot of the disassembly window is shown below. Memory Address Machine Code Source Code 1
The instruction encoding is explained in chapter A5 in the ARMv7-M Architecture Reference Manual document. For example, the machine code for the MOVW instruction with 16-bit constant is encoded with From ARMv7-M Architecture Reference Manual, ARM Limited, 2010. As we can see from the screenshot above, instruction movw r6, #0xC038 is encoded as 0xF24C0638. Let s look closely at how the encoding method was applied for this instruction. The constant to be loaded is 0xC038, so we can extract imm4, i, imm3, and imm8 fields as 0xC038 = 1 1 0 0 0 0 0 0 0 0 1 1 1 0 0 0 Since the destination register (Rd) is R6, the RD field in the machine code is 0110. Now, we can encode the instruction movw r6, #0xC038 as 1 1 1 1 0 0 1 0 0 1 0 0 1 1 0 0 0 0 0 0 0 1 1 0 0 0 1 1 1 0 0 0 The hex value for the machine code is: 0xF24C0638 (same as in example screenshot) Example: Find the machine code for movw r9, #0xA9C8. 0xA9C8 = 0b 1 0 1 0 1 0 0 1 1 1 0 0 1 0 0 0 imm4 = 1010 i = 1 imm3 = 001 imm8 = 11001000 Rd = 1001 So, the machine code for movw r9, #0xA9C8 is 11110110010010100001100111001000 The hex value for the machine code is: 0xF64A19C8 2
Example: Find the machine code for movs r4, #0x003D. Since the constant is an 8-bit number and the destination register is a lower register, we can use 16-bit version of the movs instruction. From the ARMv7-M Architecture Reference Manual document, we have Machine code: 0010010000111000 = 0x243D 3. Compare and Test The compare and test instructions are used to update the status flags in the APSR (N, Z, C, and V). From The Definitive Guide to ARM Cortex-M3 and Cortex-M4 Processors, Joseph Yiu, Elsevier, 3 nd ed, 2014. 3
It is important to note that these instructions do not alter the contents of the registers they utilize. Essentially, these instructions perform the specified operation and set the flags based on the result, but do not store the result. For example: CMP R0, R1 CMN R0, R1 TST R0, R1 TEQ R0, R1 ; Subtraction (compare) ; Calculates R0 R1 and sets the flags based on the result ; Addition (compare negative) ; Calculates R0 + R1 and sets the flags based on the result ; Bitwise AND ; Calculates R0 & R1 and sets the flags based on the result ; Bitwise XOR ; Calculates R0 ^ R1 and sets the flags based on the result Another form of these instructions can be used to operate between one register and an immediate constant value. For example: CMP R0, #0x12 TST R0, #0x12 TEQ R0, #0x12 ; Calculates R0 #0x12 and sets the flags based on the result ; Calculates R0 & #0x12 and sets the flags based on the result ; Calculates R0 ^ #0x12 and sets the flags based on the result Example: Given the initial values for R0 through R7 in the table below, complete the table on the right to show the values of the flags after the execution of the following instructions. Before Code After Register Content R0 0x12345678 R1 0x87650321 R2 0x0000f000 R3 0x12345678 R4 R5 R6 R7 CMP R0, R1 CMP R1, R0 TST R1, R2 TEQ R0, R3 TEQ R2, #0xf000 N Z C V: 0b1001 N Z C V: 0b0011 N Z C V: 0b0111 (NZ only) N Z C V: 0b0111 (NZ only) N Z C V: 0b0101 C bit is impacted because barrel shifter is used. Notes: CMP is used to compare the relative magnitude of two operands using the N bit. TST is used to see if a given bits or bit(s) are cleared. If they are, then the result is zero (Z = 1). TEQ is used to check if two operands are equal. If they are, then the result is zero (Z = 1). 4
We often combine these compare and test instructions with conditional branches, as we shall see in the next lesson. Exercise: Write an assembly program to verify the examples above. 4. References [1]. Joseph Yiu, The Definitive Guide to ARM Cortex-M3 and Cortex-M4 Processors, Elsevier, 3 rd ed, 2014. [2]. [3]. Jonathan Valvano, Introduction to ARM Cortex-M Microcontroller, 4 nd ed, 2013. ARMv7-M Architecture Reference Manual, ARM Limited, 2010. [4]. LPC17xx User manual, NXP Semiconductors, 2010. 5