Search code examples
cinline-assemblysdcc

sdcc inline asm() not working


I'm using GCC (correction) SDCC with the Eclipse IDE to compile C code for an 8051 architecture embedded target. I need to insert a few NOPs for timing, and I can't get the compiler to accept inline assembly code.

With __asm__ ("; This is a comment\nlabel:\n\tnop"); (as suggested below) or variations I get warning 112: function '__asm__' implicit declaration and then error 101: too many parameters, as if I'm trying to call an undeclared function. I've tried all other options in the SDCC manual section 3.14 also. __asm ... __endasm gives a syntax error on __asm, same with a single underbar, and combinations of whitespace, newlines, or the same line don't help.

If I'm piecing together the command line from the Makefile correctly (without the #include path), the CFLAGS on the SDCC command line are:

-Wp,-MD,$(@:%.rel=%.d),-MT,$@,-MP --disable-warning 110 -Wa,-p --model-medium


Solution

  • Moved from comment

    In the sources of SDCC 3.1.0's lexer, I see that both _asm/_endasm and __asm/__endasm are supported. I haven't noticed yet support for __asm("string") in the parser yet.

    Also in the lexer's code, the lexing type of the inline assembly token "blob" gets changed to CPP_ASM only if a property called preproc_asm is set to 0, as can be seen in sdcc/support/cpp/libcpp/lex.c:1900.

          result->type = CPP_NAME;
          {
            struct normalize_state nst = INITIAL_NORMALIZE_STATE;
            result->val.node.node = lex_identifier (pfile, buffer->cur - 1, false,
                                                    &nst);
            warn_about_normalization (pfile, result, &nst);
          }
    
          /* SDCC _asm specific */
          /* handle _asm ... _endasm ;  */
          if (result->val.node.node == pfile->spec_nodes.n__asm || result->val.node.node == pfile->spec_nodes.n__asm1)
            {
              if (CPP_OPTION (pfile, preproc_asm) == 0)
                {
                  comment_start = buffer->cur;
                  result->type = CPP_ASM;
                  _sdcpp_skip_asm_block (pfile);
                  /* Save the _asm block as a token in its own right.  */
                  _sdcpp_save_asm (pfile, result, comment_start, result->val.node.node == pfile->spec_nodes.n__asm);
                }
              result->flags |= ENTER_ASM;
            }
          else if (result->val.node.node == pfile->spec_nodes.n__endasm || result->val.node.node == pfile->spec_nodes.n__endasm1)
            {
              result->flags |= EXIT_ASM;
            }
          /* Convert named operators to their proper types.  */
          else if (result->val.node.node->flags & NODE_OPERATOR)
            {
              result->flags |= NAMED_OP;
              result->type = (enum cpp_ttype) result->val.node.node->directive_index;
            }
          break;
    

    The solution was to add #pragma preproc_asm - (or +) at the top of the file and to use the multiline __asm/__endasm blocks.