Skip to content

Latest commit

 

History

History
170 lines (140 loc) · 14.9 KB

thumb.md

File metadata and controls

170 lines (140 loc) · 14.9 KB

Thumb instructions

Thumb instructions generally use the first 5 bits to decide which operation to use, though sometimes the next 2 or 5 bits are used to add more instructions that only use 3 or 2 registers (RegOp3b, RegOp0b).

The following notation is used for instructions; Rd = Destination register (r0-r7) Rs = Source register (r0-r7) Rn = Intermediate register Hd = Destination register (r8-r15) Hs = Source register (r8-r15) #x = a x-bit constant (i) #xs = a x-bit signed constant (i)

opCode Instruction Name Layout Condtion code
0 0000 LSL Rd, Rs, #5 Logical Shift Left (<<) RegOp5b +
0 0001 LSR Rd, Rs, #5 Logical Shift Right (>>) +
0 0010 ASR Rd, Rs, #5 Arithmetic Shift Right +
0 0011 00 ADD Rd, Rs, Rn Addition (+) RegOp3b +
0 0011 01 SUB Rd, Rs, Rn Subtraction (-) +
0 0011 10 ADD Rd, Rs, #3 Addition (+) +
0 0011 11 SUB Rd, Rs, #3 Subtraction (-) +
0 0100 MOV Rd, #8 Move (=) RegOp8b +
0 0101 CMP Rd, #8 Compare +
0 0110 ADD Rd, #8 Add assign (+=) +
0 0111 SUB Rd, #8 Subtract assign (-=) +
0 1000 0 0000 AND Rd, Rs Bitwise and assign (&=) RegOp0b +
0 1000 0 0001 EOR Rd, Rs Bitwise xor assign (^=) +
0 1000 0 0010 LSL Rd, Rs Logical shift left assign (<<=) +
0 1000 0 0011 LSR Rd, Rs Logical shift right assign (>>=) +
0 1000 0 0100 ASR Rd, Rs Arithmetic shift right assign (maintains sign) +
0 1000 0 0101 ADC Rd, Rs Assign add with carry (+=) +
0 1000 0 0110 SBC Rd, Rs Subtract with carry (-=) +
0 1000 0 0111 ROR Rd, Rs ROtate Right (>>>= in Java) +
0 1000 0 1000 TST Rd, Rs Rd & Rs (set condition flags) +
0 1000 0 1001 NEG Rd, Rs Negate (= -x) +
0 1000 0 1010 CMP Rd, Rs Rd - Rs (set condition flags) +
0 1000 0 1011 CMN Rd, Rs Rd + Rs (set condition flags) +
0 1000 0 1100 ORR Rd, Rs Bitwise or (|=) +
0 1000 0 1101 MUL Rd, Rs Multiply (*=) +
0 1000 0 1110 BIC Rd, Rs Bitwise nand (&= ~Rs) +
0 1000 0 1111 MVN Rd, Rs Bitwise not (= ~Rs) +
0 1000 1 0000 undefined
0 1000 1 0001 ADD Rd, Hs ADD r8-r15 to r0-r7 (+=) +
0 1000 1 0010 ADD Hd, Rs ADD r0-r7 to r8-r15 (+=) +
0 1000 1 0011 ADD Hd, Hs ADD r8-r15 to r8-15 (+=) +
0 1000 1 0100 undefined
0 1000 1 0101 CMP Rd, Hs CMP r8-r15 to r0-r7 +
0 1000 1 0110 CMP Hd, Rs CMP r0-r7 to r8-r15 +
0 1000 1 0111 CMP Hd, Hs CMP r8-r15 to r8-15 +
0 1000 1 1000 undefined
0 1000 1 1001 MOV Rd, Hs MOV r8-r15 to r0-r7 +
0 1000 1 1010 MOV Hd, Rs MOV r0-r7 to r8-r15 +
0 1000 1 1011 MOV Hd, Hs MOV r8-r15 to r8-15 +
0 1000 1 1100 BX Rs MOV pc, Rs -
0 1000 1 1101 BX Hs MOV pc, Hs -
0 1000 1 1110 undefined
0 1000 1 1111 undefined
0 1001 LDR Rd, [PC, #8] Rd =data[pc NAND 3 + 4 + i << 2]
Load u32 relative to the next instruction. Specify i in u32s.
RegOp8b -
0 1010 00 STR Rd, [Rs, Rn] u32[Rs + Rn] = Rd RegOp3b -
0 1010 01 STRH Rd, [Rs, Rn] u16[Rs + Rn] = Rd -
0 1010 10 STRB Rd, [Rs, Rn] u8[Rs + Rn] = Rd -
0 1010 11 LDSB Rd, [Rs, Rn] Rd = i8[Rs + Rn] -
0 1011 00 LDR Rd, [Rs, Rn] Rd = u32[Rs + Rn] -
0 1011 01 LDRH Rd, [Rs, Rn] Rd = u16[Rs + Rn] -
0 1011 10 LDRB Rd, [Rs, Rn] Rd = u8[Rs + Rn] -
0 1011 11 LDSH Rd, [Rs, Rn] Rd = i16[Rs + Rn] -
0 1100 STR Rd, [Rs, #5] u32[Rs + i << 2] = Rd RegOp5b -
0 1101 LDR Rd, [Rs, #5] Rd = u32[Rs + i << 2] -
0 1110 STRB Rd, [Rs, #5] u8[Rs + i] = Rd -
0 1111 LDRB Rd, [Rs, #5] Rd = u8[Rs + i] -
1 0000 STRH Rd, [Rs, #5] u16[Rs + i << 1] = Rd -
1 0001 LDRH Rd, [Rs, #5] Rd = u16[Rs + i << 1] -
1 0010 STR Rd, [SP, #8] u32[SP + i << 2] = Rd RegOp8b -
1 0011 LDR Rd, [SP, #8] Rd = u32[SP + i << 2] -
1 0100 ADD Rd, PC, #8 Rd = PC + i << 2 +
1 0101 ADD Rd, SP, #8 Rd = SP + i << 2 +
1 0110 000 ADD SP, #8s b ? SP -= i << 2 : SP += i << 2 RegOp7b +
1 0110 001 undefined
1 0110 010 undefined
1 0110 011 undefined
1 0110 100 PUSH { Rs..., Rs... } Push the specified registers onto the stack and update the SP. i is a bitflag for x << regId. -
1 0110 101 PUSH { Rs..., Rs..., LR } Push the registers and the LR onto the stack and update the SP. i is a bitflag for x << regId -
1 0110 110 undefined
1 0110 111 undefined
1 0111 000 undefined
1 0111 001 undefined
1 0111 010 undefined
1 0111 011 undefined
1 0111 100 POP { Rs..., Rs... } Pop the stack and put the values into the specified registers. i is a bitflag for x << regId -
1 0111 101 POP { Rs..., Rs..., PC } Pop the stack and put the values into the specified registers and PC. i is a bitflag for x << regId -
1 0111 110 undefined
1 0111 111 undefined
1 1000 STMIA Rb!, { Rs..., Rs... } "Push" the specified registers onto the memory range specified and update the register. i is a bitflag for x << regId. RegOp8b -
1 1001 LDMIA Rb!,{ Rs..., Rs... } "Pop" the specified registers onto the memory range specified and update the register. i is a bitflag for x << regId. -
1 1010, 1 1011 B{cond} #8s Increments PC by i << 1. cond = 1110 is undefined RegOp12b -
1 1011 111 SWI #8 Causes a software interrupt. LR = next pc. CPSR into SPSR_SVC. SWI vector address 0x8 into the PC. Switch to arm mode, mode to SVC. SWI handler uses i to determine what the interrupt should do (depending on the system) -
1 1100 B #11 Unconditional branch RegOp11b -
1 1101 undefined
1 1110, 1 1111 BL #23
BLH #11
BLL #11
Long branch; 23-bit jump.
Long branch high: LR = i << 12
Long branch low: LR |= i << 1
LR is relative to the next pc. PC is set to LR and the previous next pc | 1 is placed into LR.
-

r15 (pc register)

A mov to the pc (r15) via a branch will cause the thumb mode to switch if bit 0 is set (1). This means branches can jump to ARM code.

If the pc is touched through an instruction it is set to the address of the next ARM instruction. pc NAND 2 + 4 where pc is the pc before the instruction. If pc is non WORD aligned this will result in unpredictable execution (pc AND 2).

RegOp

"RegOp" stands for regular operation, there are 3 variants; RegOp0b, RegOp3b, RegOp5b, RegOp8b. The xb stands for how many bits are used for data used besides the destination registers and the op code. The layout is as follows:

struct RegOp0b {
  
    u16 Rd : 3;		//Destination register
    u16 Rs : 3;		//Source register
    u16 op : 10;	//Opcode
    
};

struct RegOp3b {
  
    u16 Rd : 3;		//Destination register
    u16 Rs : 3;		//Source register
    u16 Rni : 3;	//Rn or intermediate
    u16 op : 7;		//Opcode
    
};

struct RegOp5b {
  
    u16 Rd : 3;		//Destination register
    u16 Rs : 3;		//Source register
    u16 i : 5;		//Intermediate
    u16 op : 5;		//Opcode
    
};

struct RegOp7b {
  
    u16 i : 7;		//Intermediate
    u16 b : 1;		//Additional opcode bit
    u16 op : 8;		//Opcode
    
};

struct RegOp8b {
  
    u16 i : 8;		//Intermediate
    u16 Rd : 3;		//Destination register
    u16 op : 5;		//Opcode
    
};

struct RegOp11b {
    
    u16 i : 11;		//Intermediate signed integer
    u16 op : 5;		//Opcode
    
};

struct RegOp12b {
    
    u16 i : 8;		//Intermediate
    u16 cond : 4;	//Execute condition
    u16 op : 4;		//Opcode
    
};