JVM for Prop (ICCv7 version)
I started with converting the jvm spin files to C.
Attached is the lowest level include file jvmEeprom.c
It compiles but I do have some questions:
All local variables in spin functions are longs, so I declared longs
in jvmEeprom.c as well (also for parameters and return values).
Does this generates the least code (16bit locals would suffice)?
I set and clear I/O pins using constructs like
OUTA |= 1<<SDA;
OUTA &= ~(1<<SDA);
Is this the fastest way to set I/O pins or should I use the propeller
specific library functions CLR(), SET() and FLIP() ?
For spin code
· ·byte[noparse][[/noparse]addr] = value
I used
· ·*addr = value;
with addr declared as
char *addr;
Are there standard eeprom functions supplied by ICC?
The jvmEeprom functions are used to store and retrieve values in the eeprom.
Using spin, that means·the array holding jem bytes is filled after reset.
For ICC, how can I set aside a block of eeprom to hold the jembytes?
(and fill the array char jemData[noparse][[/noparse]16384] after reset?
(the 16384 is an optimistic value, it probably will be less).
regards peter
Attached is the lowest level include file jvmEeprom.c
It compiles but I do have some questions:
All local variables in spin functions are longs, so I declared longs
in jvmEeprom.c as well (also for parameters and return values).
Does this generates the least code (16bit locals would suffice)?
I set and clear I/O pins using constructs like
OUTA |= 1<<SDA;
OUTA &= ~(1<<SDA);
Is this the fastest way to set I/O pins or should I use the propeller
specific library functions CLR(), SET() and FLIP() ?
For spin code
· ·byte[noparse][[/noparse]addr] = value
I used
· ·*addr = value;
with addr declared as
char *addr;
Are there standard eeprom functions supplied by ICC?
The jvmEeprom functions are used to store and retrieve values in the eeprom.
Using spin, that means·the array holding jem bytes is filled after reset.
For ICC, how can I set aside a block of eeprom to hold the jembytes?
(and fill the array char jemData[noparse][[/noparse]16384] after reset?
(the 16384 is an optimistic value, it probably will be less).
regards peter
c
![](/plugins/FileUpload/images/file.png)
6K
Comments
The CLR()/SET()/etc. macros just turn into the bit operations, and it's the fastest way to do them.
I am not familiar with the eeprom issues, I will have to look into it.
For now I will just use long until all files are converted and compile.
Attached is file jvmData.c converted from jvmData.spin
regards peter
Hippy's smaller footprint C may help with memory issues (not sure of the readiness though). Eventually when the mythical PropII arrives, the JVM would be easily ported there. Surely there would be enough resources there for a full Java6 compliant JVM to be possible on PropII.
The ASIO serial library provides getchar and putchar, is limited on baud rate to about 57k6, is processor speed dependent, and is fairly small 3K object vs 6K object for FdSerial. Use the FdSerial module instead of ASIO for non-blocking function and faster access with trade off in bigger code. FdSerial uses the original FullDuplexSerial.spin asm code for a driver.
SET/CLR/FLIP are macros so significant use will eat memory quickly. You could write function versions of these to reduce memory requirement but sacrifice speed.
Your eeprom driver should work assuming you translated it correctly from spin. A global "char JemBytes[noparse][[/noparse]0x4000];" should be fine for the byte array; accessing a global in a function is relatively slow because of the "lmm load" time though.
I would be inclined to use a cache block in combination with Jem bytes stored on EEPROM rather than trying to keep it all in propeller memory. A cache manager could be successfully implemented in a cog as C-code and launched in the cache cog ... this would cause some delay for management and cache misses of course but should not be too much of a performance burden relatively speaking. Such a module could also double as the EEPROM interface core API.
One performance observation on non-cached ICCV7 is that function calls are very expensive in time about a micro-second (more locals mean more overhead for saving and restoring stack context ... you probably guessed this though). Using macros instead of functions where possible will save time but eat memory of course so functions that have lots of references should remain functions, but functions that have only one or two references might be converted into macros.
Cheers.
--Steve
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Converting spin to C is not so much work so I decided to take that up.
I already have most files done.
Now converting jvmSerial.spin (I know there is the asyncio lib but would
like jvmSerial.c to compile).
The problem is with the assembly code.
I have put all assembly statements in asm("<string>"); statements.
@ImageCraft:
Why is #asm/#endasm not supported? Would save alot of typing and
gives better readability.
The attached file generates 1 error: Invalid instruction in jvmSerial.s
Any help here is appreciated.
regards peter
You're right about the simple conversion. I think Tom Rockiki (sp?) wrote a C->Spin converter in perl. The biggest problem I've had in conversion is differences in arithmetic operator precedence regarding <<, >>, and logic operators; grouping solves that of course.
You can't use straigt PASM like in your jvmSerial.c. C uses the LMM interpreter which requires special manipulation for JMP and other instructions. Math instructions and others can be used with asm(). Examples of using asm() are in <ICC path> \include \propeller.h . Different workable approaches for using full asm code are: 1) write asm in ICC ASM format using LMM and load (not sure if ICC supports Spin PASM), 2) convert a Spin PASM binary to a C array and load that. FdSerial and other device drivers in the OBEX use the second approach.
--Steve
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Attached are the C files (and spin files from which they are converted).
Just place all files in a folder amd open project jvm in ICC.
Compiling jvmMain.c to output shows alot of warnings about duplicates,
which I don't understand because all C files have a block
#ifndef filename
#define filename
// C source
#endif
so all sources should be included only once, right?
There is only 1·error: not enough memory to load .text area
Another problem is how to start 2 identical objects in seperate cogs
and then accessing routines from that object (we cannot use obj.routine() )
See jvmVirtualPeripheral.c
regards peter
This builds except for some strange things in jvmNative.c commented with #ifdef INTERNAL_ERROR
--Steve
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Thanks for creating the header files.
I fixed jvmNative.c - the error was using PSHA which should be PHSA
The fixed version is attached.
However, when I build I still get the error
C:\PROGRA~1\ICCV7P~1\bin\imakew -f JVM.mak
iccprop -o JVM -g -ucrtprop.o -lmm:kernel.o -fhexbin -cf:JVM.cmd @JVM.lk -lcprop -lasyncio
!E Unable to fit text section into memory
C:\PROGRA~1\ICCV7P~1\bin\imakew.exe: Error code 1
Done: there are error(s). Exit code: 1. Thu Nov 06 20:04:23 2008
regards peter
Code size without optimizations and keeping 16KB jemcode array is about 160KB. As expected this is about 4X-5X spin JVM size. Until we have a way to execute from some external memory, find a compiler as compact as spin, or have a bigger Propeller, all one can hope to achieve is emulating the JVM on windows or linux or running the JVM on another CPU ... I thought about building it for ARM but not too much ....
--Steve
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔