|mspgcc: A port of the GNU tools to the Texas Instruments MSP430 microcontrollers|
|<<< Previous||An introduction to the TI MSP430 low-power microcontrollers||Next >>>|
All instructions are 16 bits long, and there are only three instruction formats:
|0||0||1||Condition||PC offset (10 bit)|
|Opcode||Source reg||Ad||B/W||As||Dest reg|
As and Ad are the source and destination addressing modes. B/W is a bit that is set to 1 for byte instructions. 2-operand opcodes begin at 0100 = 4.
As you can see, there are at most 8+8+12 = 28 instructions to keep track of, which is nice and simple.
|000||RRC(.B)||9-bit rotate right through carry. C->msbit->...->lsbit->C. Clear the carry bit beforehand to do a logical right shift.|
|001||SWPB||Swap 8-bit register halves. No byte form.|
|010||RRA(.B)||Badly named, this is an 8-bit arithmetic right shift.|
|011||SXT||Sign extend 8 bits to 16. No byte form.|
|100||PUSH(.B)||Push operand on stack. Push byte decrements SP by 2. CPU BUG: PUSH #4 and PUSH #8 do not work when the short encoding using @r2 and @r2+ is used. The workaround, to use a 16-bit immediate, is trivial, so TI do not plan to fix this bug.|
|101||CALL||Fetch operand, push PC, then assign operand value to PC. Note the immediate form is the most commonly used. There is no easy way to perform a PC-relative call; the PC-relative addressing mode fetches a word and uses it as an absolute address. This has no byte form.|
|110||RETI||Pop SP, then pop PC. Note that because flags like CPUOFF are in the stored status register, the CPU will normally return to the low-power mode it was previously in. This can be changed by adjusting the SR value stored on the stack before invoking RETI (see below). The operand field is unused.|
|111||Not used||The MSP430 actually only has 27 instructions.|
The status flags are set by RRA, RRC, SXT, and RETI.
The status flags are NOT set by PUSH, SWPB, and CALL.
Relative jumps. These are all PC-relative jumps, adding twice the sign-extended offset to the PC, for a jump range of -1024 to +1022.
|000||JNE/JNZ||Jump if Z==0 (if !=)|
|001||JEQ/Z||Jump if Z==1 (if ==)|
|010||JNC/JLO||Jump if C==0 (if unsigned <)|
|011||JC/JHS||Jump if C==1 (if unsigned >=)|
|100||JN||Jump if N==1 Note there is no "JP" if N==0!|
|101||JGE||Jump if N==V (if signed >=)|
|110||JL||Jump if N!=V (if signed <)|
Two-operand instructions. These basically perform dest = src op dest operations. However, MOV doesn't fetch the destination, and CMP and BIT do not write to the destination. All are valid in their 8 and 16 bit forms.
Operands are written in the order src,dest.
|0100||MOV src,dest||dest = src||The status flags are NOT set.|
|0101||ADD src,dest||dest += src|
|0110||ADDC src,dest||dest += src + C|
|0111||SUBC src,dest||dest += ~src + C|
|1001||SUB src,dest||dest -= src||Implemented as dest += ~src + 1.|
|1001||CMP src,dest||dest - src||Sets status only; the destination is not written.|
|1010||DADD src,dest||dest += src + C, BCD.|
|1011||BIT src,dest||dest & src||Sets status only; the destination is not written.|
|1100||BIC src,dest||dest &= ~src||The status flags are NOT set.|
|1101||BIS src,dest||dest |= src||The status flags are NOT set.|
|1110||XOR src,dest||dest ^= src|
|1111||AND src,dest||dest &=- src|
There are a number of zero- and one-operand pseudo-operations that can be built from these two-operand forms. These are usually referred to as "emulated" instructions:
Branch and return can be done by moving to PC (r0):
The constants were chosen to make status register (r2) twiddling efficient:
Shift and rotate left is done with add:
Some common one-operand instructions:
Increment and decrement (by one or two):
|DEC(.B) dst||SUB(.B) #1,dst|
|DECD(.B) dst||SUB(.B) #2,dst|
|INC(.B) dst||ADD(.B) #1,dst|
|INCD(.B) dst||ADD(.B) #2,dst|
Adding and subtracting only the carry bit: