MOSpeed

From C64-Wiki
Jump to: navigation, search
MOSPeed
Console output
Developer EgonOlsen71
Company
Publisher
Release 2018
Licence Open Source / The Unlicense
Platform PC, C64
Genre BASIC Cross Compiler
Operation C64-icon.png
Media Download
Language(s) Language:english
Information

MOSPeed is an optimizing BASIC Cross Compiler by EgonOlsen71. It's Open Source/Public Domain. Being a cross compiler, it runs on a PC but generates 6502-Machine language for the Commodore 64.

Description[edit]

MOSPeed is an optimizing BASIC Cross Compiler that's controlled on a PC via the command line/shell. It expects a BASIC V2 program in text file format, just like C64 Studio or CBM prg Studio are using it. It supports the usual placeholders like {clear}. MOSpeed is written in Java. It requires a Java runtime environment version 8 or higher.

MOSpeed can be configured via command line parameters. It doesn't make use of compiler directives directly in the source code like some other compilers for the C64 do.

MOSpeed in an optimizing compiler. It's able to detect constants (even if those are declared as Variables) and replaces them accordingly. Unused variables or the calculations used to set them will be detected and removed as well.

The performance on average is between 10 and 20 % higher than the performance of a BASIC-BOSS compiled program without any special variable declarations, but can be much higher in some special cases as well. On average, MOSpeed increases the performance of BASIC V2 programs by a factor of 3 to 5.

Loading, startup, controls[edit]

MOSPeed is a command line application for the PC. Because MOSPeed is written in Java, the compiler is distributed as a JAR-file. This distribution contains two script file - one for Windows (mospeed.cmd) and one for Linux (mospeed.sh) - which can be used to start the compiler.

The compiler needs at least the name/path of the source file to run or /? to display the integrated help text. Started with just the source file name, the compiler will create (assuming that the compile process went fine) a prg-file named like the source file but with two plus signs as prefix. For example: example.bas becomes ++example.prg

The compilation process can be configured by using various commaanf line parameters.

The source code can use line numbers (as usual) but also labels, which the interpreter doesn't support. MOSpeed translates these label to line numbers at compile time.

Command line parameters[edit]

These command line parameter can be appended directly to the call to start the compiler. Order doesn't matter.
All parameters start with a /, alternatively a -sign can be used.
In the following, true|false means that the feature can be enabled (true) or disables (false).

  • /target=<target file>: Sets the name of the target file. If nothing is given, the name will be generated from the source file's name (as described above). It's possible to use a complete path name.
  • /platform=xxxx: Sets the target platform. Supported are c64 for C64-compatible machine language and js for Javascript. Default is c64.
  • /generatesrc=true|false: If true, the generated source codes for the assembly like intermediate language as well as for the 6502-Assembly will be written to disk as well. Default is false.
  • /constfolding=true|false: If true, constants will be detected and replaced by their actual values. Examples are the often used addresses for VIC or SID. Default is true.
  • /constprop=true|false: If true, constant propagation will be used. I.e. constants won't only just detected directly, but also if calculations result in constant values. Default is true.
  • /ilangopt=true|false: If true, the generated intermediate code will be optimized. This increases the speed and usually reduces the size. Default is true.
  • /nlangopt=true|false: If true, the generated 6502-Assembly code will be optimized. This increases the speed and usually reduces the size. This optimization can take some time, depending on the size of the program. Default is true.
  • /smartlinker=true|false: If true, only used parts of the runtime will be linked to the actual program. If false, the complete runtime will be linked. Default is true.
  • /deadstoreopt=true|false: If true, dead, i.e. unused variable assigments will be detected and removed. In most cases, this is just fine but in some cases (for example when calling but not using the result of RND) it can cause the results of the compiled program to differ from the interpreted ones. This parameter affects integer and floating point variables only. Default is true.
  • /deadstoreoptstr=true|false: Just like /deadstoreopt, but for string variables. Default is true.
  • /loopopt=true|false: Detects and removes empty loops. These loops don't have to be empty in the source code, but if the values that are calculated inside them aren't actually used, they might get removed anyway. Default is true.
  • /floatopt=true|false: If true, various optimizations for floating point calculations will be used. In some case, caused by inaccuracies in the calculations, this can lead to small differences but in most cases, this shouldn't be a problem if it's even noticable. Default is true.
  • /intopt=true|false: If true, certain integer operations will be optimized. In general MOSpeed treats integer variables like the interpreter does for compatibility reasons. By using this parameter, this restriction can me loosened somewhat. Default is true.
  • /compactlevel=[0|3...]: If >= 3, the generated code will be optimized for size. This has an impact on performance, but not in the same proportion as the size reduction. The higher the value, the less of a performance impact there will be, but the size reduction might be smaller as well. 4 or 5 are usually a good compromise, which often leads to a size reduction of 10 to 15 % with a performance impact of 0.5- to 1 %. Default is 0, which disables this optimization.
  • /progstart=xxxxx|$yyyy: Sets the start address of the compiled program. This value can be either decimal or hexadecimal. If it's < 2100, a BASIC header to run the program will be added automatically, otherwise it won't. Default is 2072.
  • /varstart=xxxxx|$yyyy: Sets the start address of the variable/constants memory. This value can be either decimal or hexadecimal. If nothing is given, this memory will follow the memory used for the runtime. This is also the default.
  • /varend=xxxxx|$yyyy: Sets the end of the variable memory. This value can be either decimal or hexadecimal. Because the actual variable memory doesn't change at runtime, this actually sets the end of the string's heap memory. Make sure that the memory is readable, i.e. that it isn't shadowed by the ROM. Default is 40960.
  • /runtimestart=xxxxx|$yyyy: Sets the start address of the runtime code. This value can be either decimal or hexadecimal. If nothing is given, it will follow the actual program's memory. This is also the default.
  • /alloff=true|false: If true, all optimizations which are enabled by default will be turned off. Default is false.
  • /vice=<path>: This sets the path to an instance of the VICE-Emulator (or some other with similar behaviour). After a successful compilation, the compiled program will be started in that emulator. By default this doesn't happen.


Changes compared to BASIC 2.0[edit]

MOSpeed tries to stay compatible with the BASIC V2 interpreter when possible. However, there are some deviations.

  • LIST, CONT: Will be ignored.
  • NEW, STOP: Will be treated like END.
  • DIM with variables: While this actually isn't supported, it might work to a degree if MOSpeed can detect these variables as constants.
  • Limited support for USR: This function is supported, but only a single floating point value is allowed as input. Strings or multiple parameters are not allowed.
  • SYS with parameters: This option isn't supported. Even in the interpreter, it's more of a hack than anything else.
  • INPUT with double quotes: When using INPUT MOSpeed is a little more forgiving with double quotes.
  • Unified rounding: The interpreter chooses different approaches to rounding in different contexts. The rounding differs inside of functions, for example. An example: A=145/3*3 assigns 145 to A, but PEEK(145/3*3) reads from 144, not 145. MOSpeed unifies this behaviour, so that in this example, the outcome will always be 145 (just like in the BASIC 7.0 of the C128).
  • floating point accuracy: The results of floating point operations may show slight differences between the interpreter and MOSpeed, depending on the applied optimizations. In almost all cases, this shouldn't be a problem at all. In addition, MOSpeed tries to workaround a bug in the interpreter ROM, so that the results might turn out to be more precise.


Runtime errors[edit]

Runtime errors in the program (for example divisions by zero so similar) will be catched and printed out in most cases, but the Line number will always be 0.


Integration with CBM prg Studio[edit]

MOSpeed can be integrated with CBM prg Studio, so that the compiler runs on every build and the result will be executed in the emulator. This integration isn't perfect, but quite helpful anyway. To make this a little clearer, here's an example.

In this example, I'm using a project named "compilertest" and a source file named "fractal.bas"

project structure.png


Now select the menu option "Build" -> "Build Events...":

build events.png



Check the "Post-Build Commands" box and enter the following into the now active text area:

[DOSCMD]cd <Path to MOSpeed> && <Drive, on which MOSspeed is located>: && mospeed.cmd [ProjectDir]<Name of the source file> -vice=<path to VICE>\x64.exe

in this particular example, it would look like this:

[DOSCMD]cd e:\src\myprojects\workspace\BasicV2\dist && e: && mospeed.cmd [ProjectDir]fractal.bas -vice=e:\vice\WinVICE-2.2-x64\x64.exe

events dialog.png


The command is a concatenated list of DOS commands. According to the documention, this shouldn't actually be needed, but I couldn't get it to work otherwise. This command will be executed after each build (for example when pressing F6 in CBM prg Studio). Please note that it doesn't use the .prg-file that CBM prg Studio creates when building, but the actual file. Sadly, CBM prg Studio offers no option so far to access the generated code right before the creation of the PRG. Because of this, this solution isn't ideal. The name of the source file has to be given directly in the command (fractal.bas in this example). CBM prg Studio offers a [prg]-placeholder, but that references the built PRG-file, which is of no use for MOSPeed. Another problem is, that CBM prg Studio only shows the compiler's output in case of a problem. So you don't see what's going on and have to wait for the compiler to complete its job, especially on larger programs.

A bug in CBM prg Studio causes the &&-characters in the command to be converted into &amp;&amp; on restart. You have to correct them, each time you are starting the IDE.

Links[edit]

Program