D on lm32-CPU: string argument on stack instead of register
Michael Reese
michaelate at gmail.com
Sat Aug 1 08:58:03 UTC 2020
On Friday, 31 July 2020 at 15:13:29 UTC, Chad Joan wrote:
> THAT SAID, I think there are things to try and I hope we can
> get you what you want.
>
> If you're willing to entertain more experimentation, here are
> my thoughts:
Thanks a lot for the suggestions and explanations. I tried them
all but the only time I got different assembly code was your
suggestion (3) which produced the following.
> (3) Try a different type of while-loop in the D-style version:
>
> // ideomatic D version
> void write_to_host(in string msg) {
> // a fixed address to get bytes to the host via usb
> char *usb_slave = cast(char*)BaseAdr.ft232_slave;
> size_t i = 0;
> while(i < msg.length) {
> *usb_slave = msg[i++];
> }
> }
_D10firmware_d13write_to_hostFAyaZv:
addi sp, sp, -8
addi r4, r0, 4096
sw (sp+8), r2
sw (sp+4), r1
addi r2, r0, 0
.L3:
or r5, r2, r0
be r2,r1,.L1
lw r3, (sp+8)
addi r2, r2, 1
add r3, r3, r5
lbu r3, (r3+0)
sb (r4+0), r3
bi .L3
.L1:
addi sp, sp, 8
b ra
> At any rate, I don't think your code is larger or less
> efficient due to utf-8 decoding, because I don't see the utf-8
> decoding.
Agreed, I think there's no code for autodecoding being generated.
I did some more experiments:
Trying to put pointer and length into a struct and pass that to
the function. Same result, the argument ended up on the stack.
Then, I wrote the function in C and compiled it with the
C-compiler of lm32-elf-gcc. It also puts the 64-bit POD structure
on the stack. It seems the only arguments passed in registers are
primitive data types. However, if I pass a uint64_t argument, it
is registered using registers r1 and r2. So the compiler knows
how to use r1 and r2 for arguments. I checked again in the lm32
manual
(https://www.latticesemi.com/view_document?document_id=52077),
and it says:
"As illustrated in Table 3 on page 8, the first eight function
arguments are
passed in registers. Any remaining arguments are passed on the
stack, as
illustrated in Figure 12."
So strings and structs should be passed on the stack and this
seems to be more an issue of the gcc lm32 backend than a D issue.
But I just found a workaround using a wrapper function.
void write_to_host(in string msg) {
write_to_hostC(msg.ptr, msg.length);
}
I checked the assembly code on the caller side, and the call
write_to host("Hello, World!\n") is inlined. There is only one
call to write_to_hostC. This is still not nice, but I think I can
live with that for now. Now I have to figure out how make the
cast back from from pointer-length pair into a string. I'm sure I
read that somewhere before, but forgot it and was unable to find
it now on a quick google search...
And since this is D: is there maybe some CTFE magic that allows
to create these wrappers automatically? Somthing like
fix_stack!write_to_host("Hello, World!\n");
> Good luck with your lm32/FPGA coding. That sounds like cool
> stuff!
I'm doing this mainly to improve my understanding of how embedded
processors work, and how to write linker scripts for a given
environment. Although I do have actual hardware where I can see
if everything runs in the real world, I mainly use simulations.
The coolest thing in my opinion is, nowadays it can be done using
only open source tools (mainly ghdl and verilator, the lm32
source code is open source, too). The complete system is
simulated and you can look at every logic signal in the cpu or in
the ram while the program executes.
More information about the Digitalmars-d-learn
mailing list