m68 runs 68000 elf, Motorola hex, and CP/M 68K binaries on Windows, macOS, and Linux.
m68 loads binaries into memory then emulates the Motorola 68000 and required system calls to execute them.
C and C++ programs in the c_tests folder can be built with a 68000 cross compiler on most platforms. I've run buildgcc-8.2.0.sh on both Windows 11 running on AMD64 and Ubuntu running on Arm64 to build the GNU gcc 8.2.0 cross compiler. See Building GCC for 68000 for details.
I've been unable to build the gcc 68000 cross compiler on macOS and Raspberry PI 5.
The build scripts m.bat and m.sh in the c_tests folder can be used to build samples on Windows, macOS, and Linux. mm68.bat and mm68.sh build the m68 emulator targeting the 68000 so the emulator can run itself recursively. mall.bat and mall.sh build all of the sample apps.
The sample apps in the c_tests folder build with newlib and have the required stubs for newlib to call into Linux-like system calls emulated by m68. m68start.s has the assembly code that initializes newlib then calls main(). newlib68.c has the small wrappers that are called by newlib then make Linux-style system calls into the m68 emulator via the Trap insruction. It's required to link these two object files with yor C apps for them to link and run.
m68 can also load and run CP/M 68K .68k binary files. The cpm folder has the Digital Research C compiler, assembler, and linker along with some sample .c and .s apps that can be built and run. Those tools all run in m68 along with the binaries they produce. Same for the Pascal and BASIC compilers in the mtpascal and CB68 folders. The DDT debugger works in the emulator including instruction tracing and breakpoints.
Trap 0 is used for linux-style syscalls, Trap 2 and trap 3 are used for CP/M 68K, and Trap 15 is used to mimic the 68k emulator
I've built and tested m68 on Amd64 on Windows and Ubuntu as well as Arm64 on Raspberry PI OS, Ubuntu, and macOS. It also builds with GCC targeting 68000 (mm68.bat/mm68.sh in c_tests) and that runs in any other build of m68 recursively. I've also tested for RISC-V 64 on hardware running Debian and in the RVOS emulator.
M68 can run the NTVAO 6502 + Apple 1 emulator built for 68000 targeting Linux.
All test cases can run with plain m68, m68 nested in itself, or m68 running in ARMOS or RVOS for versions built for Arm64 or RISC-V 64.
usage: M68
arguments: -e just show information about the elf executable; don't actually run it
-h:X # of meg for the heap (brk space). 0..1024 are valid. default is 40
-i if -t is set, also enables instruction tracing with symbols.
-l when a LF (10) is output, allow Windows to add a CR (13) beforehand
-m:X # of meg for mmap space. 0..1024 are valid. default is 40. 0 for CP/M.
-p shows performance information at app exit
-t enable debug tracing to m68.log
-v used with -e shows verbose information (e.g. symbols)
files:
* m68.cxx: Loads programs and OS services (Linux-style syscall() or CP/M 68K BDOS) from apps
* linuxem.h: Defines syscall IDs. Same values as for RISC-V 64 and Arm64.
* m68000.cxx: Emulates a 68000
* m68000.hxx: Header for the 68000
* djl_con.hxx: Console / terminal related functionality
* djl_mmap.hxx: Support for mmap syscalls. Newlib doesn't use it so currently unused.
* djl_os.hxx: Abstracts various OS, CPU, and compiler-specific concepts
* djltrace.hxx: Used for tracing status and instructions
* m.bat/mmac.sh/m.sh: Builds debug versions of m68 on Windows/macOS/Linux
* mr.bat/mrmac.sh/mr.sh: Builds release versions of m6 on Windows/macOS/Linux
* runall.bat/runall.sh: Runs test apps in c_tests to validate m68. Use argument "nested" to run the 68000 c_tests\m68.elf in the native m68.
* baseline_test_m68.txt: Expected results of runall.bat/runall.sh test scripts
* mgr.bat/mclr.bat: Builds m68 on Windows using gcc and clang. clang and gcc versions of m68 are about 14% faster than msft C++.
* words.txt: Dictionary file for the AN test app
Test files in the hexapps folder are Motorolla hex files generated by Peter J. Fondse's 68000 IDE + emulator. More information is here: m68k
c_tests folder (test apps + newlib stubs with Linux syscall support)
* m68start.s: _start and syscall() for C/C++ apps built with newlib
* newlib68.c: stubs called by newlib() for primitives including exit, open, close, etc. Also, printf/sprintf/fprintf overrides of newlib that support floating point (%f, %lf), 8-byte integers (%lld), and size_t integers (%zd).
* m.bat/m.sh: builds C++ apps on Windows and Linux
* mm68.bat/mm68.sh: builds the m68 emulator for the 68000 to run nested as another test case.
* mall.bat/mall.sh: builds all test apps on Windows/Linux
* ma.bat/ma.sh: builds .s 68000 assembly file apps
* *.c: various test apps in C and C++. All are built as C++.
* tbcd.s: validates the 3 68000 BCD instructions
cpm folder:
* standard distribution of the Digital Research C compiler, assembler, and linker with support files
* e.c, sieve.c, tm.c, ttt.c: apps that can be built with the C compiler running in m68
* ttt68u.s: a 68000 assembly version of ttt with loops unrolled for performance.
* e68.s and sieve68.s: 68000 assembly versions of these benchmarks
* tchk.s: validates the chk instruction since I can't get the compilers to generate code using it
* m.bat/m.sh: builds C apps
* ma.bat/ma.sh: builds .s assembly apps
* mall.bat/mall.sh and runall.bat/runall.sh: builds and runs all test cases
cpmcv11 and cpmcv12 folders:
* older versions of the C compiler. v11 can't build and/or run some of the tests. The C runtime has a stack corruption when using printf.
* these compilers generate slower code than the one in the cpm folder. None of the compilers work with floating point.
mtpascal folder:
* standard distribution of the Digital Research MT Pascal compiler
* e.pas, sieve.pas, ttt.pas: apps that can be built with the Pascal compiler running in m68
* m.bat/m.sh: builds Pascal apps
* mall.bat/mall.sh and runall.bat/runall.sh: builds and runs all test cases
cb68 folder:
* standard distribution of the Digital Research BASIC compiler
* DDT.68K and DDT68000.68K: debugger
* e.bas, sieve.bas, ttt.bas: apps that can be built with the BASIC compiler running in m68
* m.bat/m.sh: builds BASIC apps
* mall.bat/mall.sh and runall.bat/runall.sh: builds and runs all test cases
com folder:
* COM.68K: CP/M v2.2 + 8080 emulator for CP/M 68K. I don't know its origins. I've tested it running in m68 using a variety of CP/M v2.2 tools in my cpm_compilers repo.
* MBASIC.COM: Microsoft BASIC interpreter
* TTT.BAS/E.BAS/ASCIIART.BAS/SIEVE.BAS/HELLO.BAS: various test programs for mbasic.
* TTTCPM.COM: cp/m 2.2 app to prove you can't win at tic-tac-toe
* com.68k running in m68 was tested with Wordstar as well.
ntvcm folder:
* mntvcm.bat: Windows build script for my ntvcm repo. ntvcm gives full Z80 + CP/M 2.2 emulation running inside of m68.
* tested with a Z80 validation app and a variety of cp/m 2.2 apps including Wordstar. Plus 77 CP/M compilers and interpreters.
ntvao folder:
* mntvao.bat: Windows build script for my ntvao repo. ntvao is an Apple 1 emulator with WozMon and WozBasic
* validated with assembly, C, and BASIC apps along with a 6502 instruction validation app.
rvos folder:
* mrvos.bat: Windows build script for my rvos repo. rvos is a RISC-V 64 + Linux emulator.
* validated running the rvos test suite in that repo with rvos running in m68.
sysfor and syspas folders:
* Silicon Valley Software FORTRAN and Pascal compilers
* *.sh and *.bat: scripts to build and run test apps
* e.pas, ttt.pas, sieve.pas, mm.pas, e.for, ttt.for, sieve.for, mm.for: test apps
forth83 folder:
* 68000 Forth 83 version 2.1.0
* m.bat/m.sh: invokes the interpreter for a Forth file
* e.f, sieve.f, ttt.f: sample Forth apps
* runall.bat/runall.sh: runs all of the sample Forth apps
* this does not run on physical CP/M 68K machines that don't make address 0x500 available. F83.68K is non-relocatable and must load there.
relocatable f86 describes how to hack f83.68k to run on such hardware, but this impacts performance of the interpreter.
notes/bugs:
* C++ exceptions don't work due to _start not initializing them for newlib
* Unlike the 68000, addresses aren't limited to 24 bits. Data in the high bits will be used as part of the address.
compiler and assembler benchmark performance:
* source code, tools, and build scripts for all benchmarks are in this repo
* DR = Digital Research
* SVS = Silicon Valley Software
* g++ = GNU C++ cross compiler m68k-elf-gcc (GCC) 8.2.0
* ms = milliseconds
* DR C v1.3 has text in cp68.68k that indicates v1.2, but it ships with CP/M 68K v1.3
* times on the 68008 are with CP/M 68K and include significant relocatable binary load times
* I haven't figured out how to use the modern g++ compiler to produce CP/M 68K binaries
* much of the g++ e instruction count is consumed by division calculations
* Forth is interpreted, not compiled.
* f83.68k won't load on my CP/M 68K device. The start address is 0x500, which is reserved on that machine. There is a documented hack available, but it changes performance.
* the BA compiler only supports 4-byte integers, which dramatically slows 68008 performance
* assembly code always wins