GCC not allowing SWI calls
Pages: 1 2
Graeme (8815) 106 posts |
Has anyone had this issue before? I have GCC making a module in C and CMHG. Using _kernel_swi does not work. It creates a branch and link instruction right into the middle of a long block of code that is a long list of repeated MOV PC,#0. What am I doing wrong? This fails: Then in the module initialise: That should print a newline but creates a branch through zero error instead. I can call SWIs from making an assembler file and calling from there but that defeats the purpose of having a library that should just work. |
Paolo Fabio Zaino (28) 1882 posts |
@ Graeme
Not me.
I am trying to reconstruct what you may have been doing, so here is my test code (I wrote it in the hope I can follow your steps, based on what you’ve shared (not much) I had to improvise, hope this will be helpful to you and for others in future requests too). The problem could be in multiple places. So, first off, C source code (stored in c subdirectory):
Next, CMHG file (stored in a file called module in cmhg subdirectory):
Last, Makefile it’s a standard one from GCC (I think) I use it since ever, so not sure:
TaskObey to start the build (called MkGCC and stored in the directory that contains the subdirectories above):
This builds and yes your way to call _kernel_swi works fine. Hope the sources above will help you to find what is wrong in your own code. Please remember to post more significant sources, I know some people may wish to keep things kinda secret (I respect that), but it makes things hard to figure out what you did wrong. Hope my English makes sense. Good luck! [edit] |
Graeme (8815) 106 posts |
Well, I’ve had to mix a chunk of C with assembler to get things working. Can’t work out how to return a pointer to a function which has an array of integers to another function that wants to access these array integers. Address exception. Over and over again. Hours of it. I can see you used stdio.h which I did not. Maybe something in there I need? I certainly could not use NULL until some libraries were included. The joys of C. Using some three/four line assembly routines, I have VLDR and VSTR successfully emulating now for 64-bit only but with no offsets! However, this is a start. Once I get going with one instruction, the others will follow much more quickly. |
Rick Murray (539) 13851 posts |
Why a pointer to a function, rather than just a pointer to the array?
Completely normal. Plain C is a very rudimentary language. It’s the various included things that make it work, and the power of being able to create functions that behave in a similar manner to the “built in” ones. |
Paolo Fabio Zaino (28) 1882 posts |
Weird, I did not need that at all.
I included stdio, just to have access to puts (and now printf) function for debugging purposes.
NULL is defined in stddef.h, which is included by stdio, so I had no need to include it directly. Without including stdio.h, you probably want to include stddef.h and (eventually) stdarg.h (not sure how you’re handling your function parameters).
Ok, trying to “decipher” what you meant (sorry, my English is not good enough, a code snippet would help)… You want to return a function pointer to Func A (from Func B) that points at Func C which returns a pointer to an array? If that’s so, then the following code does exactly that. Func A is get_array(), Func B is istr_decode (’cause you seems to have mentioned instructions you are trying to implement), arr is the instruction implementation that returns a pointer to an array of integers. Replace previous C code with this one (leave untouched all other files, to reduce warning, add -std=c99 in CCFLAGS in the MakeFile):
This produce the following output:
I quickly designed the base for an instruction set that is 2 operands, the ARR isntruction ignores the 2nd operand and uses only the first (which is used to create the seed for each element in the returned array just as a test). The instruction decoder is made on purpose super simple for this specific test, but, of course can be easly improved adding instruction groups etc, it’s just that that would be out of scope for the specific issue you’re having. Few take away: 1) I declared the array I return the pointer of as static, this is an important detail, because that means that even if the array a10 is defined as local, it will be allocated in the .BSS (or .DATA) section, not on the stack. This makes returning a pointer to that local array a safer activity, the array is not deleted after we leave the function arr(). For more details on this please have a look at my video on usign GNU ASM on RISC OS, which shows the same technique used in ASM. 2) make sure that the istr_decode is defined exactly how I did and, if yours, for whatever reason, doesn’t accept parameters, then declare them as (void), don’t use the () syntax for its parameters. 3) arr and nop are just two instructions implementations, so you can see that all the dependent functions must return values in the exact same way and accept arguments in the exact same way (however, you have an ISA that has variable arguments, aka each instruction can be decoded with a different number and type of parameters). Hope this helps, |
Simon Willcocks (1499) 521 posts |
If you’d like to have a play, I’ve got a system to build modules just using an arm gcc cross-compiler (no stdlib or anything like that). It should work with plain RISC OS, as long as you avoid using any strange SWIs like OS_ThreadOp or OS_PipeOp. It’s not intended as a tutorial or anything, nor is it my current focus of attention, so while I’ll be happy to help, don’t expect too much! Oh, and even if the (very incomplete) module builds DO NOT try running it on RISC OS, it will probably crash. wget <a href="https://raw.githubusercontent.com/Simon-Willcocks/RISC-OS-Kernel-in-C/main/include/kernel_swis.h">https://raw.githubusercontent.com/Simon-Willcocks/RISC-OS-Kernel-in-C/main/include/kernel_swis.h</a> && wget <a href="https://raw.githubusercontent.com/Simon-Willcocks/RISC-OS-Kernel-in-C/main/include/module.h">https://raw.githubusercontent.com/Simon-Willcocks/RISC-OS-Kernel-in-C/main/include/module.h</a> && wget <a href="https://raw.githubusercontent.com/Simon-Willcocks/RISC-OS-Kernel-in-C/main/module.script">https://raw.githubusercontent.com/Simon-Willcocks/RISC-OS-Kernel-in-C/main/module.script</a> && wget <a href="https://raw.githubusercontent.com/Simon-Willcocks/RISC-OS-Kernel-in-C/main/GCC_Modules/MTWimp/MTWimp.c">https://raw.githubusercontent.com/Simon-Willcocks/RISC-OS-Kernel-in-C/main/GCC_Modules/MTWimp/MTWimp.c</a> && mkdir include && mv kernel_swis.h include && arm-linux-gnueabi-gcc-8 *.c -Wall -o /tmp/module$$.elf -fpic -nostartfiles -nostdlib -fno-zero-initialized-in-bss -static -O4 -g -march=armv8-a+nofp -T module.script -fno-toplevel-reorder && arm-linux-gnueabi-objcopy -R .ignoring -O binary MTWimp.elf MTWimp,ffa (The optimisation seems to be essential, but I’m not sure why!) |
André Timmermans (100) 655 posts |
I have always used to typedef my function pointers with Norcroft C, so I had several surprises:
|
Paolo Fabio Zaino (28) 1882 posts |
@ Simon
Is that question for Graeme? If so, then:
I think Graeme is trying to build at least to run on RISC OS… |
Paolo Fabio Zaino (28) 1882 posts |
@ André
You can do that if you want, but the point here is I was trying to interpret what Graeme is doing
Yes Graeme is doing something that sounds very cumbersome, no idea why. The point of my code is to represent the expressed thoughts and test if that works in GCC straight out of the box (and in a RO module) and it does.
The & is good coding practice (makes code more obvious), but you don’t need to specify it (as long as you avoid the function parameters, the compiler should understand your intents)
With that particoular form YES you can use functions with different parameters set, but note, the function is being called directly by get_array. Here is an example that adds nop with no parameters at all:
To test, you can add a printf in nop definition and you’ll see it gets executed without specifying the (int, int), but that is because you’ve defined your pointer to nop accordingly. In real world the instructions would be called directly by istr_decode() and would probably be defined in a different way (to be faster). Hope this makes sense. |
David J. Ruck (33) 1636 posts |
The SharedCLibrary stubs will initialise that block when the module is loaded, assuming you are linking against it? |
Rick Murray (539) 13851 posts |
You can’t call a SWI (SVC mode) from module initialisation code (also SVC mode) or your return address (R14) is going to get trashed. The way around this is to tell the compiler that you are building module code (in the DDE, the command option is -zM maybe GCC has something similar?) and you may need to link to module specific versions of libraries. In this way, R14 can be preserved, stuff will work, nothing “go bang”. ;) |
Paolo Fabio Zaino (28) 1882 posts |
@ Rick
Did you check my attached Makefile, link options? -mmodule is what works “the magic” for GCC on RISC OS, basically the GCC team has set RISC OS modules as a target, the target has the receipt for to work all the required bits. I hope Graeme had a look at it. By the way Graeme described the problem, it seems that the compiler/linker flags are a bit “custom” in his case (maybe?), but who knows, I mean very little was shared. The code, if done correctly, works fine and there is no need to use ASM, proven above, so there are probably more problems here and there, hope Graeme will catch them all using the examples that are working totally fine. |
Graeme (8815) 106 posts |
Thanks everyone.
I did start with the example from GCC which has no SharedCLibrary. When trying to use SWI calls, I removed the -nostdlib and -lgcc and it compiled. The link flags still had -znoscl and that may be the issue. The module loaded into memory has a list of MOV PC,#0 when -znoscl is present and these are changed to LDR PC,address without it. That looks much better. There have been a lot of issues. The compiler has frozen multiple times and after a reset will just freeze when trying to compile my code. Restoring a backup of my code from a working copy and resetting will get it to work again but that is lost work and I’m unsure why it is doing it. Manually entering commands to compile show it is gcc freezing and asasm continues to work. That could be tested because Alt-Break allows you to continue but only if you are in the command line. The desktop freezes completely. I’ll try Paolo’s code this evening and see if I can get that to work. My ideal set up would be able to get a module to compile, allow SWIs and (hopefully) allow me to code in C++. The first two should be possible as other people have done it. There are no module examples using C++ with GCC so that will have to be tested to check if it can work at all. The reason I started without the SharedCLibrary was because I am compiling some code that will be called by the undefined instruction vector (a VFP emulator). Whatever is in there wants to be simple instructions but quite complicated maths. So far I’ve forced it to get VLDR and VSTR working fully for 32 and 64-bit numbers. Again, I am having to call some assembler code because I haven’t quite worked out how to do the LDR x,[y,#0] instruction in C. It was something like int x=y[ 0 ] where y is int* but I haven’t used C/C++ for over 20 years and it is taking a while to get used to some of the things again. Funny how I jumped back into assembler without much issue but struggling to get back into C which I thought would have been easier to remember! |
Rick Murray (539) 13851 posts |
Ummm……. are you sure your machine isn’t shagged somehow? Because a compiler really shouldn’t be doing anything like that. |
Simon Willcocks (1499) 521 posts |
I don’t have experience with this setup, but I wonder if the standard library is compatible with module code (it might assume it can allocate memory from the running application, for example). |
Graeme (8815) 106 posts |
I’ve decided not to continue with C/C++ on Risc OS. The tools available are not good enough. |
Simon Willcocks (1499) 521 posts |
What is it you’re trying to achieve? |
David J. Ruck (33) 1636 posts |
Can’t say I’ve tried modules in C or C++ using GCC, but plain C using Norcroft is straight forward and works. |
Rick Murray (539) 13851 posts |
Ditto. The only times I have issues with C or the compiler is when I’ve screwed up, even if it can take a while to track down the source of the problem. Certainly this is, um….
|
Graeme (8815) 106 posts |
The LDR thing was to find out if the concept of a VFP emulator would actually be possible in C at all. The concept works. I know exactly how LDR/STR work so knew those would not be an issue while testing, something to fix later. C pointers are definitely something I need to brush up on if I am to continue this. I may try a simpler module first and come back to this one at a later date. |
Simon Willcocks (1499) 521 posts |
Can’t you just do: static inline unsigned ldr( unsigned *y ) { return *y; } |
Graeme (8815) 106 posts |
I have it working but I am so confused why.
It is no wonder I had to resort to assembler. What is going on here? This code copies two 32-bit words (int) that are next to each other. I set up a pointer to |
Simon Willcocks (1499) 521 posts |
Oh, so you’re decoding an instruction? I misunderstood. (You might like to use html’s pre /pre tags rather than textile’s bq) Are you sure you want load[ 4 ]? That would be 16 bytes on from load (4 * sizeof(int)). |
Graeme (8815) 106 posts |
That is what I would expect but it is not what it is doing, it is doing 4 bytes and not 4 * the size. |
Simon Willcocks (1499) 521 posts |
I mean, if load is 0×1000, load[ 0 ] is the 4 bytes at 0×1000, load[ 4 ] is the four bytes at 0×1010. Have you tried the -S option to gcc? (I hate Textile!) x.c: int r( int *p ) { return p[ 4 ]; }
(You need -O4 or similar to get a reasonable sized function.) /tmp$ tail x.s .type r, %function r: @ args = 0, pretend = 0, frame = 0 @ frame_needed = 0, uses_anonymous_args = 0 @ link register save eliminated. ldr r0, [r0, #16] bx lr .size r, .-r .ident "GCC: (Ubuntu/Linaro 8.4.0-3ubuntu1) 8.4.0" .section .note.GNU-stack,"",%progbits
|
Pages: 1 2