Hopefully today I can get to work on the emulator.
For the emulator, I thought about having it where I just load the binary and just start executing bytes in a specific region (perhaps the end). This would for the most part be how the real system is handled and such. So then this way I can have binary initialization be written in Java and be generic as possible. Compiler magic would handle most of the things.
I really just need components and that is it.
To support recording and replays, components have to be added and initialized
via factories. However the classes could be used. So the system would have an
addComponent which takes a
String (id of component), and
Object... for the component properties.
So component creation can be stored in replays. Currently the class type is stored, so they cannot be changed at all.
The interpreter runs at 8MHz internally (at least the one created by the interpreter target builder). 58122500000ps (0.0581225s) was done in about a minute of just mass printing text.
Currently my emulator is cycle accurate and extremely slow. It takes 13 seconds for a 8MHz cycle to complete.
DEBUG -- 1s at 2888363125743347 DEBUG -- 1s at 2888376866173501 (13740430154 or ) DEBUG -- 1s at 2888389859357080
This means that is is really slow, too slow for the emulator to truly be viable for testing. Although cycle accurate is nice, it is far too undesirable.
So what I really need is a kind of deterministic emulator that does not run extremely slow. So I suppose what I need instead of running a single cycle for each method, I need a run to amount to occur instead or similar.
Also, each call essentially is done in a single method, every cycle has its
own method call so there is much overhead. So bulk execution is definitely
needed. There has to be a central loop somewhere which calls all the
associated methods as required and does not cause a method to be called for
each cycle. I suppose what I can do is instead change the emulator code to
not use picotime and instead just have a generic run time amount. Real time
on the system can be virtualized instead. Code to be ran by the CPU could be
read into a buffer and bytes could be interpreted in a giant loop until the
PC leaves the block or a given number of instructions were executed. Then
something I can do is just implement JIT compiling for MIPS instead of the
interpreter. So there would still be an interpreter, but it would just run
MIPS code in my own faux
squirreljme.interpreter operating system. This would
be a bit more realistic than writing my own instruction format.
So I suppose this means that the
jit-mips for the
most part. Perhaps not. I would need to initialize a code generator.
jit-mips would be difficult if it is not OS dependent. I would need
a way to adjust the generated machine code because some platforms may change
how some registers are used or have a different syscall mechanism. So the JITs
will remain the same as targets. So really the interpreter JIT code will be
the same, except that once I get to actual byte code recompilation it will just
generate MIPS code instead.
So I definitely need a simplification of the emulator, so despite moving to MIPS I really do not need to do anything much except change the emulator code. Then at least I would have a single target. So if the interpreter works out and gets code implemented, I could target Linux MIPS next.
Thinking about it, although having an emulator which can support TAS would be nice, it would complicate things a bit. It would also potentially cause some slow down. So I would suppose that I should drop the very complex emulator which I plan to have and just go with something far simpler. Setup a basic machine, load a binary into memory, and just start executing it. Do not worry about being cycle accurate, just make sure the code runs.
So I suppose what I need in this case is a traditional JIT that outputs blobs to be used on standard modern systems with code and memory in a single address space, which means pretty much every CPU from classic 8-bits to modern 64-bits. Then I only need to write the JIT once. When the need come to have slightly different code generators (for architectures) they can just be created over the base class. So basically a traditional output system. The blobs would be the same for every architecture. The byte ordering can be determined by using the triplet easily. So this means that the initial MIPS could instead of being ELF will just be a proprietary format that is directly the blob format. Then this way, I really only need to write that code once since all of the architectures will end up creating the same format anyway. This simplifies things greatly.
Then the interpreter target could just support any CPU and not just MIPS. Then the interpreter will just have some special memory areas or system calls that do specific things.
I would suppose for some increased processing speed that strings could be sort of written inline or at least after the last output has been placed.