Mapping extern C calls to ASM - parameter passing and the linker

technosf
Posts: 16
Joined: Fri Dec 28, 2018 9:55 pm

Mapping extern C calls to ASM - parameter passing and the linker

Postby technosf » Sat Dec 29, 2018 2:17 am

Hit there,

I've decided to learn ASM again after a long hiatus, and I'm using Arduino Core C to call a basic test .S file I'm linking in. The call passes some parameters in and expects one back. I can see the in bound params hit A10 and A11, and sometime I can ASM to complete a call and return something to C: How do I define the external inputs and access them within ASM, and how do I return a value and change the values of the input C variables? I've tried doing psuedo define ops in the ASM, but no joy.

Any help, pointers, or sources of documentation would be much appreciated.

Heres the code - the loop:
  1.   Serial.println("Fire");
  2.   uint8_t out = test( 0x2F, 0x1F );
  3.   Serial.println("Done");
  4.   Serial.printf("Out: %#010x",out);
The external .h:
  1. extern "C"
  2. {
  3.   uint32_t test( uint8_t vone, uint8_t vtwo );
  4. }
And the .S that just does anything I can without crashing:
  1. #include <xtensa/config/specreg.h>
  2. #include <xtensa/config/core-isa.h>
  3. #include <xtensa/corebits.h>
  4.  
  5.   .data
  6.  
  7.   .global vone
  8. vone:
  9.   .int  0xAA
  10.      
  11. .set voneaddr, vone
  12.  
  13.   .text  
  14.   .align
  15.    .global test
  16. test:
  17.     movi  a14,  vone
  18.     l8ui  a4,   a14,  0
  19.     nop

ESP_Sprite
Posts: 8921
Joined: Thu Nov 26, 2015 4:08 am

Re: Mapping extern C calls to ASM - parameter passing and the linker

Postby ESP_Sprite » Sat Dec 29, 2018 8:10 am

You can do this in two ways: either you use the gcc ability to do inline assembly, or you put your functions in an external file.

In case of inline assembly, you can specify the parameters in the asm block. See for instance here for an example. The parameters to specify exactly how gcc interacts with the bit of assembly can, however, get a bit complicated, but in theory everything you need is there. You can use this to sprinkle inline assembly into a function; the assembly can be tightly integrated with C code and isn't necessarily a separate function on its own.

The other option is to put your functions in an external file. This way, you can call it like you call a C function. In this case, to pass parameters and in general interact nicely with the C code, you need to obey the Xtensa ABI, specifically the windowed ABI. I think the xtensa isa pdf that floats around on the Internet describes it. It comes down to you needing to start the function with 'entry' and ending it with 'retw'; your arguments are passed in a2-a5 and your return value should be in a2, and apart from a0/a1 you can clobber all registers you want. An example is e.g. [url=https://github.com/espressif/esp-idf/bl ... _arb_asm.S]here[/]. Apart from that file, you'd need to declare the function somewhere so you can use it in C:

Code: Select all

void test_s32c1i_lock(volatile int *lockvar, int lockval, int unlockval, volatile int *ctr);
and after that you can call it as a standard C function.

technosf
Posts: 16
Joined: Fri Dec 28, 2018 9:55 pm

Re: Mapping extern C calls to ASM - parameter passing and the linker

Postby technosf » Mon Dec 31, 2018 11:14 pm

Thanks for the pointers, Sprite: I do not want to use inline asm - I did find the Xtensa ISA guide and am working my way through it. It's a little dry - but elsewhere I have not found much information from the point of view of basic Xtensa ASM routine setup and housecleaning. But it's been fun experimenting to the point where I've got input, output. I'm putting my experiment on github.

Experimented with windowing and got stable results, but I'm finding the input C vars are getting clobbered on return from the ASM. Calling with one var, one pointer, copying the var to the pointer and returning 0xff, the var is wiped on return:

Code: Select all

Calling the ASM C header with values In1: 0x00000011 In2: 0x00000022 Out: 0000000000

Call Complete. In1: 0000000000 In2: 0x00000011 Out: 0x000000ff
I also have found the Cadence Xtensa programming guide, which has some good examples but seams to be more this-is-what-dissembled-C-looks-like.

Cheers

T

ESP_Sprite
Posts: 8921
Joined: Thu Nov 26, 2015 4:08 am

Re: Mapping extern C calls to ASM - parameter passing and the linker

Postby ESP_Sprite » Wed Jan 02, 2019 9:18 am

That might be because you declare your variables as uint8_t (which is 8 bit) but overwrite in2 using s32i, which writes 32 bits. My guess would be that the zeroes written in the 24 MSBs end up in the address of in1, zeroing out that variable.

technosf
Posts: 16
Joined: Fri Dec 28, 2018 9:55 pm

Re: Mapping extern C calls to ASM - parameter passing and the linker

Postby technosf » Wed Jan 02, 2019 6:03 pm

Exactly right, Sprite.

Thank you so much for your help and encouragement - I feel the week I've spend digging into this has been very productive and, weirdly given this is assembler, fun :lol: Learning a lot!

Who is online

Users browsing this forum: No registered users and 104 guests