ARMv6v7 Basic Assembler support (kind of...)
Pages: 1 2
Kuemmel (439) 384 posts |
Since a long time (Iyonix/Intel XScale) the Assembler integrated in BBC Basic wasn’t updated to support the new ARMv6, ARMv7 and ARMv7r opcodes. So I wrote a BASIC library that provides a work-around to finally support these. Your can find it here . At the moment there are 82 additional instructions included. Can’t really say ARM is RISC any more…feels more like heavy CISC ;-) There’s tons of parallel arithmetic, saturate, multiply, integer divide, move, reverse, bit field, packing and extending instructions that might be useful and of course faster for a lot of different purposes. Find some examples in the ‘Examples’ directory. There’s a list of all supported opcodes in .txt and .pdf within the archive also. One of the example is about comparing software and hardware signed/unsigned integer divide (Cortex A-15 only)…needed to be the year 2014 so that we finally got a hardware divide ;-) The hardware divide is roughly 10 times faster than the software divide I got from an old source from Peter Teichmann, of course depending on the input numbers. Then there’s an example playing with RGB manipulation using the parallel arithmetic saturation opcodes. That should run on all “new” machines (Pi,BB,PB,…). To use the new commands just include the following line in your Basic code …and when you want to use one of the new instructions insert the following code in your assembler section (before assembling !BasicASMv6v7 has to be seen by the filer): so for example You can also use EQUD instead of DCD. I’ve no clue if "FN_oc" is the best way to call the function, but that fits for me at the moment.
The parser is not as good as the normal assembler and also error checks are limited. See the !Help file for more information. As I didn’t test through all the variants of commands in total it’s recommended if you think there’s something wrong that you check the output of your desired opcode with my test application in the folder “Debug”. I hope I got it all right regarding the library function, as that’s the first time I ever did that. By now I didn’t included the opcodes CPSID, CPSIE, CPS, SETEND, SRS, RFE, SEV, WFE, WFI, YIELD, MRRC2, MCRR2 and the load and store exclusive instructions. If anybody is in need for them, I’ll do that as well. Feel free to send me any suggestions and error findings for improving future versions. Of course it would be better to provide the support of ARMv6/v7 directly within the standard Basic Assembler, but that will take a considerable amount of work and hassle I found when I looked at the sources. Nevertheless if I’ll find some time in the far future I’ll try to do so. |
Chris Evans (457) 1614 posts |
I’d private message this if the forum had that facility! |
Adrian Lees (1349) 122 posts |
Is anybody actively working on extending the BASIC assembler itself, rather than relying upon a library? This is something that I could take on, since I now have a permanent, stable v7 setup, and I am the original author of ExtBASICasm which originally added FPE/FPA support by patching the BASIC module….before source access was available ;) |
Steve Pampling (1551) 8170 posts |
I think that there is a shortage of people with the knowledge and time to do anything any time soon. So, I think you’re looking at a vacant position if you want to take it. |
Steve Drain (222) 1620 posts |
I have been using ExtBASICasm, in Darren Salt’s version, for a very long time, but find myself in a bind now because I can only run it with BASIC 1.20 and on 26-bit machines. I would be delighted to be able to transfer completely to RO 5. I recognise that the method of intercepting errors to implement the new features was ingenious, but it was tied to specific versions of the BASIC rom. With the source, things should be much simpler, so please go for it. My attempts to replicate those features with a library have not been easy. ;-) My commitment to ExtBASICasm went as far as producing a StrongHelp manual. |
Adrian Lees (1349) 122 posts |
Steve Drain: I think you misunderstand. What I am proposing is the implementation of native support for post-ARMv5 (ie. post-IYONIX pc machines, essentially) instructions within the BASIC assembler, not the additional features that Darren added when he took over the development of ExtBASICasm. Certainly not support for generating AOF files; this is already possible, including the latest instructions, using ObjAsm (or perhaps gccsdk?) but the BASIC assembler is certainly useful as a more accessible introduction to ARM code. Its immediacy also makes it far more suitable for assembling a few instructions as throwaway code, to check/test something behaves as expected. |
Sprow (202) 1158 posts |
I have for a while pondered abstracting the BASIC assembler a little, so that extension modules can be written for it without needing lots of code duplication/patching. The core BASIC assembler could then accept just the base ARM instruction set, then supporting module(s) could be added by 3rd parties as needed.
This is especially useful where using RISC OS as the development environment for some less capable system, for example there’s a 6809 assembler patch and 6502 one as well, developing big stuff on 8 bit systems is always a pain as you run out of RAM to hold the source code pretty quickly! I realise this isn’t really answering Adrian’s question, but it might be worth at least designing an API. Maybe a service call? Passing ARGP, the unknown opcode, P% and O% or something like that. If no one claims the service the built in assembler has a go, and if it fails you get a “Unknown opcode” default error. In ObjAsm there’s the CODE32 and THUMB keywords to select instruction set, if multiple assembler extensions could coexist they could be selected via some OPT keyword or something? Something like ‘MOV’ occurs in many instruction sets so you’d probably want some way that the extensions knew it was their MOV. |
David Feugey (2125) 2709 posts |
That’s a cool idea. Do you plan to work directly on the source code of Basic? if so, do you plan to apply a few AMRv7 optimizations on the Basic itself? For example hardware FPU for floating point operations? |
Adrian Lees (1349) 122 posts |
Since the ARMv6/7 extensions are currently ‘in my head’ – for other projects – I’ll at least make a start on extending the assembler. (There are a lot of additional instructions, and even if I don’t get them all added, committing the code would allow somebody to pick it up and continue). I’m not planning to implement BASIC’s internal FP using VFP, and you’d probably have a hard time measuring any performance increase given the overheads of the interpreter itself, unless you’re operating upon arrays of floats. You probably know that the default BASIC interpreter (as opposed to BASIC64) does not use the FPEmulator module anyway; it has its own internal FP implementation. |
Steve Drain (222) 1620 posts |
@Adrian I do not use the AOF features and I can see no reason to include them in the BASIC assembler. A lot of work has already gone into the VFP/NEON support and I have made some use of this, but without ExtBASICasm assistance. However, there are a number of directives and pseudo-instructions that I otherwise use all the time: ALIGN – padding with zeros ADRL, LDRL, STRL – very useful indeed As is: negative constants use the opposite instruction, eg: MOV r1,#-1 => MVN r1,#0 None of these is vital, perhaps, and I have most of a library to substitute for them, but they are very convenient. Really, I should move to ObjAss, but I am rather old for new tricks and I have rather a lot invested in using BASIC. ;-) |
Mike Freestone (2564) 131 posts |
You’re 13 years too late as basic already does that |
Kuemmel (439) 384 posts |
@Adrian: Would be very nice if you would modify the Assembler itself. At least I can say I’m not working on that by myself, as it would really take a lot of time. I can give you some help, that Jeffrey gave me back then as a start on it (Jeffrey, hope you don’t mind that I cite your e-mail here): “I think the best way to get started is to download one of the ROM source archives from ”https://www.riscosopen.org/content/downloads/risc-os-tarballs">https://www.riscosopen.org/content/downloads/risc-os-tarballs (preferably one for whatever machine you’ll be testing on) and make sure you’re able to build a ROM image. There’s a “getting started” guide here which will help you with that: https://www.riscosopen.org/wiki/documentation/show/Beginner’s%20guide%20to%20ROM%20builds Note that you don’t have to build a new ROM each time you make a change to BASIC, but doing it once first is a good way of getting yourself familiar with the build system and making sure everything is set up correctly. Next, you can start getting to grips with BASIC itself. The sources will be in castle.RiscOS.Sources.Programmer.BASIC, and the assembler sources are in s.Assembler. Note how there are very few comments, I did warn you that it wasn’t very nice :) There are a couple of tables of instruction prefixes at CASMTB and CASMTB2 which appear to be the main way the assembler identifies the instruction it’s trying to assemble. I’d guess the 4th byte in each table entry helps it to encode some extra information about the instruction (part of the opcode?) for use by the code that’s specific to each group of instructions. CASMTB looks like it deals with all of the original ARM instructions, which CASMTB2 looks like it deals with the ARMv5 instructions. Since CASMTB2 is a lot shorter than CASMTB, it would probably be easier to extend that to add the ARMv6/v7 instructions (or add a CASMTB3?). Once an instruction has been found in either table it looks like it will branch to either CASMGT or CASMGT2 (depending on the table) which then does some extra work to determine which instruction/group it was within the table. And that’s about as far as I’ve looked :) Once you’re ready to test your changes, you should be able to use the “!Mk” command file to build softloadable copies of BASIC and BASIC64. These will be output to the “rm” folder. Note that in order to do the build !Builder must be running and the build directory and environment must be selected. Also note that the VFP assembler sources are actually held in a different file, s.VFP, and are a lot nicer to work with – it’s just the original assembler that’s such a mess. Maybe you could add some comments as you go along? :)" |
Jeffrey Lee (213) 6048 posts |
Yeah, that’s fine. Good luck with deciphering Sophie’s code, Adrian! ;-) |
Adrian Lees (1349) 122 posts |
Meh, I find it perfectly legible :P And besides, in the past – for both ExtBASICasm and Aemulor (which takes a copy of the native 32-bit BASIC, and patches it to run 26-bit BASIC programs under Aemulor at almost full whack, whenever it starts up) I’ve worked purely from disassembly. It is striking how it belongs to ‘another time’ in that everything is written in capitals, fewer comments, no procedure call standard etc. Takes me right back to my teens ;) |
Jon Abbott (1421) 2651 posts |
I’m doing that for ADFFS as well. Is it worth registering a new Service call, get BASIC to issue it at CALL/USR and only do the code call itself if not claimed. It would make Aemultor/ADFFS future proof. |
Adrian Lees (1349) 122 posts |
That just wouldn’t work for Aemulor; I need to catch SWIs invoked by Aemulor’s copy of the BASIC module and modify their behaviour…so that’s any SWI that BASIC calls within its own code and anything called via SYS (the more complex case, obviously), and not just BASIC’s invocation of inline assembler (CALL/USR). I’ve never had to change the code in Aemulor, over 13 years of (admittedly quite small) changes to the BASIC module, because it scans the entire module and uses pattern-matching to locate the points where it needs to step in, and then appends suitable patch code to the end of the copy. |
Jon Abbott (1421) 2651 posts |
I’m doing something similar, although I capture them on the SWI vector. Essentially all I’m doing to BASIC is moving it to the RMA and changing the LDR PC,[R13],#4 in CALLARMROUT to an SWI. I don’t like it though as I’ve designed ADFFS to be fully OS legal. There’s only two areas I’ve had to break that rule, BASIC and OS_Memory because it corrupts the L2PT entries. |
Steve Drain (222) 1620 posts |
Ah! I started using ExtBASICasm more than 13 years ago and BASIC 1.20 is 16 years old and does not align with zeros. It is more complex than you assume, so I think we call that a tie. ;-) |
Steve Drain (222) 1620 posts |
In the original source I had there were no comments; I was quite new to assembler and completely lost. I think most of the existing ones were by Steve Revill, which I got somewhat later and to whom many thanks. ;-) |
Steve Drain (222) 1620 posts |
In a smaller way, it is a technique I have used with Basalt over a similar period to identify internal routines that are not exposed legally, such as EXP. I also have a couple of patches applied similarly, that I only use locally and experimentally. I hope this holds for the future. ;-) |
Steve Drain (222) 1620 posts |
I agree with Adrian: for BASIC V, I could see no advantage. For BASIC VI there could be some gain, but the problems1 involved make it less than worthwhile, maybe. I have explored some of these with my Float module , but that download is a bit rough around the edges and is not the most recent version. It is a distant plan to bring double precision floats to BASIC V with Basalt. 1 Here a couple of the biggies: |
Jeffrey Lee (213) 6048 posts |
Easy: Don’t context switch. Create & activate one context on interpreter startup, and then destroy it on exit. It then becomes the responsibility of the program to make sure the context is used sensibly, the same as with FPA. AFAIK the rules for FPA are:
Swap ‘FPA’ for ‘VFP’ in the above and you’ll get a sensible set of rules for VFP. E.g. VFP inline assembler can temporarily make use of vector mode, but it must remember to reset the vector length to 1 on exit in order to avoid breaking BASIC.
Yeah, you’d have to use some kind of software implementation of those. There’s also the issue of the differing word order for VFP doubles vs. FPA doubles, which may cause compatibility issues if we were hoping to replace BASIC64 with the VFP version. |
Steve Drain (222) 1620 posts |
Exactly what I have done when experimenting for Basalt, assuming you mean one context per program and not a global one as for FPA. Then you need to store values and there is just enough space in the BASIC arguments for now. I do not grasp the implications of a global interpreter context yet. To be backward compatible there is a need to discriminate between processsors and revert to FPE if necessary, but as you say, overall it should be easy, even if it requires a fair amount of rewriting. [Edit] On reflection, there might not be a need for reversion. It needs more thought.
That is one of the lesser problems, I think. If only for the sake of the file formats and exchange between BASIC V and VI you should stick to the FPA doubles and transpose as necessary for VFP.
My code is open for use if anyone wants it. Actually, there is perhaps enough in the Float module I have here1 that it would probably be possible to just use that to replace calls to FPA in BASIC64. Is anyone up for it? ;-) 1 not the online one |
Jeffrey Lee (213) 6048 posts |
Yes – one context per program/interpreter instance for VFP. To be backward compatible there is a need to discriminate between processsors and revert to FPE if necessary, but as you say, overall it should be easy, even if it requires a fair amount of rewriting. So far we don’t have any machines where VFP is optional. They either have it or they don’t. So with the exception of softload versions of the module, we don’t need to worry about it and can just make the choice of FPA or VFP fixed at build time. |
Steve Drain (222) 1620 posts |
It was those that prompted my original comment, and then I thought of your point. Since there is always the possibility of new versions of BASIC being installed on earlier machines I think that allowing for reversion might be wise. |
Pages: 1 2