I need to fix the simulator so that instead it is a service based interface
which provides operating system support based on architectures and such
instead of not as concrete sets of data. Get rid of all the providers and just
SimulationProvider which can create simulations as such.
Today is just rain.
The simulation such as architecture variants can be linked to the JIT for simplicity.
When it comes to simulating a root filesystem, the basic filesystem layout
could be described in resources associated with JAR resources. This way when
it comes to the binary, no other details have to actually exist. There could
be a special filesystem specifier of sorts which describes the files which
are available on the root. It would not be a simulation of a whole system,
however it should be good enough to allow a basic system to operate
properly. So essentially stuff such as
/bin/sh for Linux at least would
appear a resource which could use an internal special commands to execute a
command which should be provided by the system (in the event of
being called). This would also allow specific programs to be ran on the host
without worrying about the host operating system at all. Certain details of
the filesystem, such as block devices and character devices, can be implemented
by classes. The current user directory could be mounted as a certain directory
in the simulated system when applicable. Then this way, I do not have to
worry about forwarding calls to the host system (if in the event the code is
running on Linux). However, this would essentially permit a specific set of
programs to run from any operating system.
Simulation starting details would best be placed into a single object, this way I can add more potentially in the future without requiring massive simulator changes.
I likely do not need
EmulatedCPU at all, it could really just fit within
SimulationThread which is initialized and emulates a given CPU such as for
However, I really need a single emulation core, otherwise I will end up writing many PowerPC CPU implementations. One thing I could use however is a generic CPU emulation framework. Not part of the simulator but completely different. The simualtor itself could use this emulation layer however. I could also have native emulators available so I can run other operating systems within them, for example Linux. I could use the emulators in a way where I could support specific systems in them. I could also just have a much stronger simulation core also.
However, the emulation sub-system could be used potentially with the actual run-time running as a kind of co-process potentially. Although, I could just have a much simpler simulation system which is not complex at all. I could sacrifice some things such as multiple processes in a way (although I should not do that, since some processes may rely on it).
A problem is that with the CPU manager, I will need to wrap the TLBs and MMUs for some CPUs. This depends on the number of TLBs which are available to a CPU, although ones such as x86 use an address in memory to contain page information. So I suppose what I can do instead is have a high level emulator that can emulate hardware. I will write an actual emulator which could run operating systems and uses BIOSes. When it comes to the simulator, they will just be based on the emulator except that it would provide some high level wrapping.
Actually being a bit higher than userspace would be handy. So I suppose I should go for a high level system emulator. This way I can run Linux itself while I can drop down to lower levels and run Linux programs itself. So I suppose my initial goal should be running a Linux kernel or perhaps even the Mac OS X kernel.
unsafe there is a way where I can get away with not having any
binary stubs and assembly bits.
Well, when it comes to the binary format, the loading of classes, with linking when it comes to fields and methods is system dependent. For example when it comes to ELFs the classes and such can be linked in the binary. Alternatively I can just have a bootstrap which sets up an executable region and then jumps into it. Some systems, say a hypothetical POSIX shell target will not use a binary representation of classes at all. Each class would essentially just be a field and allocated objects would be files on the disk for the most part.
Ok, so having the JIT output to an output stream with some kind of binary
writer does not make sense at all for certain targets. These targets would
be an interpreter which runs on an existing JVM, and perhaps esoteric targets
which do not target binary formats but some other strange format. So basically
the output to the JIT would be similar to before except that when it comes to
output it might output to a binary format, or it might not. I really should
support a kind of JITted interpreter, so that way I can test the JIT and then
the class library with minimal effort. Basically the JIT would output a
CompatibleExecutable as a kind of interface. However there may be a case
where the JIT would want to store the result to the disk (say with AOT) while
in other cases it would want it directly in memory ready to be used. So what
I propose when it comes to a JIT that it can output a ready to execute format
or it can use an
OutputStream to a cached form of the data. These forms
would be very system specific.
So, I would say it would be best kept to an interface. The interface can then
declare if it wants to output a cached form directly, or also a
CompatibleExecutable. Basically the handles for all methods would need to
handle output to be cached or a compatible executable for direct execution.
This means that the JIT output again becomes non-abstract.
So actually, I suppose that this instead removes
JITFactory which then turns
JITOutputFactory which creates
JITOutputs which are associated with
JIT. The output factory is then given an architecture and a variant. When
it comes to JIT generation fully handled triplet would be used in the factory.
JITOutput created will handle stuff such as writing to binary
formats and such. So the factory creation method would then handle cases where
output is to a cached form or directly executable form. Then when it comes to
actual assembly code generation, there will just be a basic output for
an architecture which uses a compatible interface.
Then when it comes to the output factory, the variant could be supported or it might not be. The system specific output handler can see if a given variant and endianess is supported.
When it comes to the word size of the CPU, perhaps instead of
is instead part of the variant, say
powerpc-32+g4,big. Then stuff such as
x86 would be
x86-16+286,little. This way I do not have to have quite a number
of variants which target similar things.
Probably something to simplify output would be a state that can be changed accordingly. It can be made immutable when work needs to be performed. So it would essentially be a configuration of sorts.
I would suppose when it comes to an interpreter JVM, that instead of creating a
JVM it would just setup a JIT and start executing the JVM as it would in the
instance. Any special calls would then just modify the state. This would
provide a close execution environment. It would also allow me to design the
JVM so that it is closer to how real environments would run.