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.

Assembly syntax conversion from GCC to TI compiler



Hi all,
I'm doing some improvements to an old firmware developed with gcc tools for ARM7 device TMS470R1VF338. I've to work now with TI toolchain and unfortunately I've to rewrite some assembly lines, the code is inside this asm calls and it's below:

asm ("poll_rx:\n\tmrc p14,0,r1,c0,c0\n\ttst r1,#1\n\tbeq poll_rx\n\tmrc p14,0,%0,c1,c0\n\t"
  :"=r" (read));

asm("poll_tx:\n\tmrc p14,0,r1,c0,c0\n\ttst r1,#2\n\tbne poll_tx\n\tmcr p14,0,%0,c1,c0\n\t"
  :
  :"r" (write_data));

the compiler answer is: "../src/FlashPrg.c", line 399: error: expected a ")", which make me think about a syntax problem. What more worries me is that if I try to symplify the call above as:

asm("MRC p2,5,R3,c5,c6");

the compiler answer is: 

[E0002]
Illegal mnemonic specified
MRC p2,5,R3,c5,c6

Why doesn't it understand this mnemonic? Shouldn't it be specified in ARM architecture? To my knowledge if a mnemonic is specified by ARM, whatever compiler must understand it.

Thank you,
Samuele 

  • Searching in the forum i found that could be related to the fact that mnemonics start from column 1, which is reserved for labels. I also tried

    asm(" mrc p14, 0, r0, c0, c0");

    whithout success (same compiler output)

    Thanks

  • Try:

     MRC             P14, #0, R0, C0, C0, #0

  • Hi Archaeologist,

    unfortunately your suggestion didn't work. 
    If the architecture is the same, only changing compiler could cause differences in instruction syntax?
    Thank you, 

     

  • Hi all,
    I've been able to compile this instruction, the main problem was related to the fact that I was compiling in 16 bit mode and this istruction is available only in 32 bit mode (see DUI0204  chapter 4.9.3). Combining also the information of Archaeologist and the tab spacing I've finally compiled.

    Now I've to rewrite the complete phrase which bring the output to the "read" variable. Can somehow give me some indication on how this can be translated on TI assembler?

    Thank you

  • The TI compiler does not support GNU-style inline assembly, and does not provide any way to refer to local variables from inline assembly.

  • Ok, is there any workaround I could use to achieve the same result?
    Thank you 

  • Ok, probably the only workaround is to rewrite the complete function in assembly...here's the code:

    int DCC_Read(UINT32 *read_data)
    {
    //assembler instructions to read data from coprocessor 14
    //poll_rx:
    // MRC p14,0,r0,c0,c0 @ read DCC control register
    // TST r0,#1 @ read R bit
    // BEQ poll_rx @ if R=0 branch to poll_rx
    // MRC p14,0,r1,c1,c0 @ save data into r1
    UINT32 read;

    asm ("poll_rx:\n\tmrc p14,0,r1,c0,c0\n\ttst r1,#1\n\tbeq poll_rx\n\tmrc p14,0,%0,c1,c0\n\t"
    :"=r" (read));
    *read_data=read;
    return (ANSW_OK);
    }

    Can I please have some help on how to rewrite this in assembly language?
    Thank you, 

  • So that you can call the assembly function from C, make sure it adheres to the register conventions used by the compiler.  Please see the section titled Register Conventions in the ARM compiler manual.

    Thanks and regards,

    -George

  • Hi George,
    thank you for this suggestion. I read the chapter and found some usefull information on how to do this rework. Here's how I modified my functions:

    int DCC_Read(UINT32 *read_data)
    {

    //assembler instructions to read data from coprocessor 14
    //poll_rx:
    // MRC p14,0,r0,c0,c0 @ read DCC control register
    // TST r0,#1 @ read R bit
    // BEQ poll_rx @ if R=0 branch to poll_rx
    // MRC p14,0,r1,c1,c0 @ save data into r1
    UINT32 read;

    read = poll_rx();

    *read_data=read;
    return (ANSW_OK);

    }


    int DCC_Write(UINT32 write_data)
    {

    /*assembler instructions to write data into coprocessor 14
    poll_tx:
    MRC p14,0,r0,c0,c0 @ read DCC control register
    TST r0,#2 @ read W bit
    BNE poll_tx @ if W=1 branch to poll_tx
    MCR p14,0,r1,c1,c0 @ send data via DCC
    */

    poll_tx(write_data);

    return (ANSW_OK);

    }

    I added the two function definitions:

    int poll_rx(void);
    int poll_tx(unsigned long write_data);

    I created a poll_rx.asm with the code below:

    .global _poll_rx

    _poll_rx:

    MRC p14,#0,r1,c0,c0
    TST r1,#1
    BEQ _poll_rx
    MRC p14,#0,r0,c1,c0

    I changed the register assignment because return value must be on r0 register. I also created poll_tx.asm with the code below:

    .global _poll_tx

    _poll_tx:

    MRC p14,#0,r1,c0,c0
    TST r1,#2
    BNE _poll_tx
    MCR p14,#0,r0,c1,c0

    I changed the register assignment because arguments are received starting from r0 on.

    Can you please give me a review of this code and suggest me if can it work as expected?
    Thank you very much,

  • You need some sort of return statement in each function to return to the caller

  • Hi Archaeologist,
    you are right, in fact poll_tx works (being called last it doesn't matter the return statement), poll_rx instead has still some trouble. 
    Reading example 6-1 of  ARM Optimizing C/C++ Compiler i found suggestion on how to create return statement. I tried to append:

    MOV pc, lr

    instruction at the bottom line of the two functions but it doesn't work. Should it be enough to return to the caller?
    Thank you,

  • I'm not an ARM expert, but that doesn't seem quite right.  Try writing a similar function in C and examining the compiler's output assembly code to see what it does.  You can keep this file with the --keep_asm compiler option.

  • You should use BX LR to return. IIRC MOV PC, LR is not a state changing return so will not work if the function is in a different state (ARM/Thumb) from the caller.

  • Thank you Cody,
    this last tip did the work. Thank you all for your precious support,
    Samuele