This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Query on MSP430 Constant Generator

Hi All,

I have an interesting query on the MSP430 constant generators. So the registers R2 and R3 can be used as constant generators if used in a particular addressing mode and the assembler/compiler automatically replaces the source operand with the constant generator register. Lets say I'm writing an assembly code and I encounter this:

MOV #0x25,R3      ;Move the immediate value 0x25 to register R3
MOV 0(R3),0(R5)   ;Move the contents pointed by (0+R3) to address (0+R5). Basically moves 0x25 to R5.

So I'm pushing 0x25 to R3 and then using R3 in indexed mode to transfer this value to R5. So the question is, will R3 be used as a constant generator and will generate the constant 01h(01h if R3 used in indexed mode) which will mess up the operation(move contents pointed by 0+1h to R5)! Or is the assembler/compiler clever enough and will not use R3 as a constant generator. 

I know this is not a recommended coding but just curious to know what happens if a programmer encounters this situation. While writing assembly code, we use the CPU registers extensively and what happens if I use R2 and R3 in an addressing mode which would result a constant generator.

Regards,

Sud

  • I think you misunderstood it or was misled by TI's description. Try it with a MSP430 or the simulator.

  • Hi OCY,

    Can you let me know the possible output of the above assembly code? I don't have a board currently and I don't think TI Simulator supports MSP430.

    Thanks,

    Sudarshan

  • MOV 0(R3),0(R5) does not copy the contents of R3 to R5. Instead, this syntax means that the contents of the memory address 0+R3 is moved to the memory location at address 0+R5. The constant generator is only used for immediate mode source operands, e.g. MOV #1,R5.

  • Hi Nuno,

    My bad. I din say it right. Maybe I should use MOV R3,R5. What would happen now?
    The instruction MOV #1,R5 will be automatically replaced by the assembler to MOV 0(R3),0(R5) with R3 as the constant generator. Or to support my example, the instruction MOV #0,R5 will be replaced by MOV R3,R5 by the assembler. So, if I write as

    MOV #0x25,R3      ;Move the immediate value 0x25 to register R3
    MOV R3,R5      ;Move content of R3 to R5
    Then, 0x25 will be moved or constant value 0h will be moved to R5? 

    Thanks,

    Sud

  • MOV R3,R5 will set R5 to zero since this uses source addressing mode 00 with R3 and that causes the value 0 to be used instead. R3 can't be read at all because all source addressing modes using R3 are used for constant generation.

  • When reading the MSP430 manuals, it's easy to get the impression that R2 andR3 is something that a user could use to generate tighter code. Unfortunately, this is not the case. The processor only supports registers SP, R4 to R15, and the status registers. The other "registers" are used when encoding an instruction to make it behave differently.

    Concretely, the constant generator makes it possible to encode instructions containing some constants like 0, 1, and 8 into a more efficient form. For example:

    0F43             MOV.W   #0, R15
    3F400700         MOV.W   #7, R15
    3F42             MOV.W   #8, R15
    3F403412         MOV.W   #0x1234, R15

    In the code above, it's clear that moving 0 or 8 into R15 could be done using small instructions, whereas 7 and 0x1234 requires a large. Internally, this is done by using the same encoding as a register to register move, but use 2 or 3 as the source register number (plus some extra bits, to control which constant should be generated).

    From a pedagogical point of view, it would be better if the manual would have present this as s special encoding for constants rather than talking about the non-existing registers R2 and R3.

        -- Anders Lindgren, IAR Systems, Author of the IAR compiler for MSP430

  • Hi Anders,

    I think I totally agree with your point! I got my hands on the MSP430 board and tried to move an immediate value to the register R3. This assembly instruction (MOV #0xB0,R3) was not getting executed at all. When the processor tries to execute this instruction, it jumps directly to the _main of the program. I guess the microcontroller generated a fault exception and the control jumps to the _main. Might be since we are trying to execute a illegal instruction. 

    And yes, the datasheet does give the impression that R2 and R3 can be used by the user for programming and it misleads us. At the end of section 6.3.4 of the MSP430 User Guide, it says that R2 and R3 can only be used as source operands when used in constant mode, but says nothing about programming usage restriction. I guess TI missed to mention this explicitly.

    I have attached a screenshot showing the code along with the CPU register contents. I could observe that when the control reaches the instruction mov #0xB0,r3 and tries to execute it, the control jumps to _main of the program. Also could observe that the Stack Pointer (SP) is decremented by 2, so a PUSH operation was executed. Do you have any possible explanation for this?

    And thanks for the valuable info about the registers.

    Regards,

    Sud

  • Sudarshan R said:

    I could observe that when the control reaches the instruction mov #0xB0,r3 and tries to execute it, the control jumps to _main of the program. Also could observe that the Stack Pointer (SP) is decremented by 2, so a PUSH operation was executed. Do you have any possible explanation for this?

    When you execute an illegal instruction, anything can happen. Some parts of the instruction encoding could treat this as a PUSH or CALL, thus adjusting the SP, before the reset happens. Also, it might act differently on different devices. Anyway, the question is more of academic value, as you should never write an application that depend on the effect of illegal instructions.

        -- Anders

  • Was just studying about the constant generators and guess I have gone more deep into it. But well, thanks to this I now have a deeper understanding of how the constant generators are used. Thanks a lot for the help.

    Thanks and Regards,

    Sud

  • Sudarshan R said:
    ... I got my hands on the MSP430 board ...

    Are you using a G2 LaunchPad board?

    Sudarshan R said:
    ...

    And yes, the datasheet does give the impression that R2 and R3 can be used by the user for programming and it misleads us. At the end of section 6.3.4 of the MSP430 User Guide, it says that R2 and R3 can only be used as source operands when used in constant mode, but says nothing about programming usage restriction. I guess TI missed to mention this explicitly.

    ...

    What you said is correct. In addition, someone (not you) made two more mistakes

    #1. The assembler you use mistakenly took your "mov #0xB0,r3" without complain and generated a senseless machine instruction -- probably "4033 00B0".

    #2 That senseless machine instruction probably takes 2 MCLKs to execute (on a MSP430G2xx chip) and does nothing. But the debugger you use mistakenly showed you that the control jumps to _main of the program.

  • Anders, for the instruction set, all 16 registers are exchangeable.
    Except for R0, if destination, the CPU will make no difference between the different registers in micro code. (writing to R0 will cause an additional clock cycle/disable the instruction prefetch)
    However, some of them act differently than the others (R2/R3) or have a special meaning (R1/R2) regarding othe rinstructions. So while you (in theory) can use any register as a stack pointer for the POP instruction (which is nothing more than a MOV @R1+, x), PUSH will only work with R1. Same for CALL and RETI (while RET too is just a MOV @R1+,R0)
    Also, writing to R0 will silently discard the LSB. And you can use R2 as storage register (in register mode), but since its bits have side-effects, this won’t be of much use.

    So yes, for the user, only R4 to R15 are usable. But would be PC, SP, SR and CG0/CG1 (where CG0 is an alias for SR) together with R0 to R11 a better naming? After all, the binary construction of the opcodes uses #0 to #15 as direct binary parts in the opcode for source/destination register.

    Normal C users won’t ever need to deal with the registers at all, and those who do (in assembler) will have to learn about their usage. Their choice. We can’t make the world more complex (and therefore less efficient) to save users from reading the documentation. (well, we could, but for what purpose?)
    After all, it's not really different from memory. If a user accesses a hardware registers with special effects, you too can't say 'this is unexpected, one would assume that memory is memory and won't expect that flash is read only and PxIN is changing and writing to it has no efect'

    BTW, the ATMega compilers use R0 as ‘1-constant generator’ - by assigning #0 to it at program start and assuming this will never change. I really prefer the two-register-7-constants solution, as #0 is not the only often-used constant.

    Sud: MOV #x,R3 likely is executed. However, R3 is a WOR (write-only-register) ;) Depending on silicon implementation, it is possible that te value you wrote to it is really stored in R3, but there is no way to read it back.

    I agree to OCY that the assembler could issue at a warning on a write to R3. I guess, nobody made the effort because it is difficult to impossible to analyze the sense (or not) of any operation regarding R2 and R3. And a warning for a register write on R3 could lead to the false assumption that other senseless usage of R2 or R3 would trigger a warning too.
    An ‘always or never’ decision.

  • Jens-Michael Gross said:

    So yes, for the user, only R4 to R15 are usable. But would be PC, SP, SR and CG0/CG1 (where CG0 is an alias for SR) together with R0 to R11 a better naming? After all, the binary construction of the opcodes uses #0 to #15 as direct binary parts in the opcode for source/destination register.

    The naming of the register is basically fine. I think a user can accept that there are special register like PC, SP, and SR that are aliases to numbered registers. Also, there is no problem with starting the general purpose registers with R4. The ONLY thing I object to is referring to the R2 and R3 (as CG0/CG1) as constant generator *registers*, as this give the impression that you as an assembler programmer could use them in your code. I've seen tons of beginners who spend a lot of time and energy trying to use them directly, like the creator of this thread, when clearly this is a minor encoding issue handled by the assembler.

    As I said earlier, I would have preferred if the constant generator only would have been discussed as a short way to encode an instruction, which happen to use an encoding pattern normally used to encode registers.

    Jens-Michael Gross said:

    I agree to OCY that the assembler could issue at a warning on a write to R3. I guess, nobody made the effort because it is difficult to impossible to analyze the sense (or not) of any operation regarding R2 and R3. And a warning for a register write on R3 could lead to the false assumption that other senseless usage of R2 or R3 would trigger a warning too.

    The IAR tools warn writing to R3:

            MOV.W   #0x280, R3
    -------------------------^
    "E:\src\test\430\cgasm.s43",10  Warning[407]: Using R3 as destination is undefined.

    Also, we issue an error if you use R2 as the base register in an indexed operand:

            MOV.W   0x1234(R2), R4          ; Same as 0x1234, R4
    -----------------------------^
    "E:\src\test\430\cgasm.s43",14  Error[449]: R2 can not be a source register in this mode.

    Unfortunately, we do not warn when using R3 as a source register -- maybe we should?

        -- Anders Lindgren, IAR Systems, Author of the IAR compiler for MSP430

  • Well, if I read that R2/R3 are used as constant generator, I wonder why one could think of using them as normal registers. Is there some magic crystal ball that tells the processor when I mean them to use as constant generator and when as normal registers? Or is there a switch (if so, I’d look for it and discover that there is none and that they are always used as constant generator).
    Also, If I go and write in assembly (or write a compiler, the only situations where I need to know about it at all), and I don’t read the register descriptions, then I’m the only one responsible for my failure. The users guide leaves no doubt about the use of R2 and R3. But I agree, one could mark more clearly that R2 and R3 cannot be used for anything else (well, except for R2 in register mode, as status register)
    But this won’t help if the chapters are skipped by the impatient users.

    Well, by re-reading the chapter, I wonder whether I could write to R3 in register mode, and then use R3 as index register for a destination, as the constant generator feature only applies for source addressing. But I guess, the R3 result will still be based on As. Well, even if so, this could be lead to a valid and purposeful instruction when used as destination index register :)

    Anders Lindgren said:
            MOV.W   0x1234(R2), R4          ; Same as 0x1234, R4
    -----------------------------^
    "E:\src\test\430\cgasm.s43",14  Error[449]: R2 can not be a source register in this mode.

    Why can’t be R2 used as source register? This is exactly how absolute mode works. So it definitely is no error (even though it might not give the expected result, if someone really wants to use the content of the status register as base address for an indexed read). Sorry, if one gets down to assembly level, he should know what he’s doing. Or go back to a high-level language.

**Attention** This is a public forum