Cibyl
From SpelWiki
Cibyl is a programming environment and binary translator that allows compiled C programs to execute on J2ME-capable phones. Cibyl uses GCC to compile the C programs to MIPS binaries, and these are then recompiled into Java bytecode. Cibyl programs are regular compiled Java programs, and Cibyl therefore performs relatively well. Cibyl is an abbreviation of something, but only the C, meaning C has been fixed so far.
With Cibyl, C programs can be ported to J2ME without switching language. It also allows C and Java code to be integrated in an easy and efficient way. The environment uses the GNU compiler tools (GCC and binutils) and should work in all environments which provide a GNU toolchain.
There are three reasons why I want Cibyl. First, C is in my opinion a much better suited language for writing games than Java. Also, since I have a couple of old games written in C, I would like to port them to the J2ME environment without rewriting the entire games (which I have also done with Lessphun). The goal is to be able to get by without porting the game to another language. Finally, I find it a nice intellectual past time which combines my favorite areas compilers, low-level programming and performance.
Contents |
Topics
These pages contain information about how Cibyl works, how to build and run programs and reference usage of the tools. Simon's blog also contains journal entries about Cibyl internals.
- Writing, compiling and running programs with Cibyl
- Building Cibyl: How to build Cibyl
- Writing games for Cibyl: Describes how to structure a game with Cibyl (J2ME-dependent)
- Guidelines when programming for Cibyl: What to do and what not to do when programming for Cibyl
- Hello World: How an hello world application is written and compiled (not dependent on J2ME)
- Cibyl performance: Some performance measurements
- Cibyl test cases: Results from the test cases on different phones
- Debugging Cibyl applications: Cibyl applications can be debugged with GDB
- General information and technical details
- http://spel.bth.se/~ska/vee-pres.pdf: Presentation about Cibyl on the VEE conference
- http://spel.bth.se/~ska/vee008-kagstrom.pdf: Paper about Cibyl that appeared on the Virtual Execution Environments conference in June 2007
- Cibyl binary translator: What the binary translator does
- Cibyl directory structure: Describes the directory structure in the Cibyl release
- API and syscalls: Describes the C API for Cibyl
- Calling convention: The calling convention (MIPS assembly) for syscalls
- Cibyl limitations: Some limitations to what can be done with Cibyl and a few current bugs
- Tool usage:
- cibyl-generate-java-wrappers: Describes how to use the cibyl-generate-java-wrappers tool that generates Java system call wrappers
- cibyl-generate-c-header: Describes how to use the cibyl-generate-c-header tool that generates C system call headers
- cibyl-mips2java: Describes how to use the cibyl-mips2java tool that recompiles MIPS binaries
- cibyl-peephole-optimize: Describes how to use the cibyl-peephole-optimize tool which optimizes the Java bytecode assembly output
- cibyl-gdbserver: Describes how to use the cibyl-gdbserver tool which starts a GDB server for Cibyl programs
- cibyl-generate-cibar: Describes how to use the cibyl-generate-cibar tool which generates a cibar file from a directory
Showcases
- RoadMap: Navigation software ported to J2ME using Cibyl by Ehud Shabtai with quite advanced features
- Sarien for Cibyl: A port of the Sarien AGI interpreter for old Sierra games (Kings Quest, Space Quest etc)
- Frodo for Cibyl: A port of the Frodo C64 emulator written in C++ (ongoing)
- Lessphun: An implementation of the Mophun API for Cibyl
- Lorminator Dash (Lessphun): A port of the Mophun Lorminator dash game to Lessphun and Cibyl.
- REX Arkanoid for Cibyl: Arkanoid game recompiled from a REX 6000 implementation
Some quotes and links about Cibyl found on the net:
- "Verdens mest kompliserte tilnærming for å lage J2ME applikasjoner" (www.java.no). If you don't read norwegian, it means basically "The world's most complex way of making J2ME applications".
- "La forma mas complicada del mundo de programar en Java" (http://www.xatakamovil.com/2007/12/28-10-programas-asombrosos). A spanish article quite simiar to the Norwegian above. Well, at least the title is :-)
- "Utterly bizarre cool idea: a translator from MIPS binaries to Java bytecode, so that you can compile C to the JVM using GCC" (http://del.icio.us/azz)
- "This is the single most interesting thing I've seen in quite a long time" (Thygrr, www.j2meforums.com)
- "Zajímavost pro programátory je prostředí Cibyl 9, které je určeno těm, kteří chtějí tvořit aplikace, či hry pro mobilní telefony zvládající J2ME, ale nechtějí se učit Javu." (Linuxsoft.cz) I don't understand a word of it, I hope it's not overly negative! ;-)
- www.penguin.cz: Cibyl in the program news on another Czech site
Short example program
#include <javax/microedition/lcdui.h>
int main(int argc, char *argv[])
{
NOPH_GameCanvas_t canvas = NOPH_GameCanvas_get();
NOPH_Graphics_t graphics = NOPH_GameCanvas_getGraphics(canvas);
/* Select red pen, then draw a line */
NOPH_Graphics_setColor(graphics, 255,0,0);
NOPH_Graphics_drawLine(graphics, 10, 10, 50, 50);
NOPH_GameCanvas_flushGraphics(canvas);
return 0;
}
Technology overview
Cibyl is based on the beautiful MIPS1 instruction set and uses GCC for compiling C source. The MIPS instructions are not decoded and parsed during runtime, but instead recompiled into Java bytecode at build-time. The overhead should therefore be small and the goal is to achieve similar performance of code written in C to a native Java implementation.
The API is called through special instruction encodings to get good efficiency. Cibyl also allows for semi-automatic generation of calls to native Java functionality.
The technology used in Cibyl is very similar to that in NestedVM, which also recompiles MIPS binaries into Java .class-files although they are completely unrelated code-wise. Note: I've seen somewhere on the web the statement that Cibyl predates NestedVM. This is not true, NestedVM came before Cibyl, but I was unaware of it until I had implemented quite a bit of Cibyl. The two projects are quite different, but I've tried to use good ideas from NestedVM whenever possible, and hope the same can be true in the other direction as well.
Compiler technology
The cibyl-mips2java compiler generates Java assembly for compilation with jasmin from the binary MIPS executable. Parts of the MIPS binary parser has been rewritten (into C++) from the Java MIPS emulator written for the topsy operating system. Some notes about the compilation:
- Extra arguments need to be supplied: -mno-check-zero-division, -fno-pic, -mno-abicalls. These simplify certain things (i.e., no trap on div-by-zero, no position-independent code etc.)
- A simple linker script that places the sections for easy parsing is used
- The cibyl-mips2java tool recompiles the binary output into Java assembly
- crt0.S initializes the C runtime and needs to be linked against by the C application.
Architectural model
There are some simplifications of the MIPS instruction set employed in Cibyl. Only instructions accessible in userspace (i.e., no coprocessor updates etc) are allowed, and nop instructions generate no code. Cibyl stores the memory contents in an integer-vector and registers as local variables. The instructions are recompiled into Java bytecode which update the registers and memory contents directly.
- The file containing the data (resource in J2ME) starts with some setup information (stack size, bss size etc.) at address 0
- The data segment is mapped to address 0x16 (to keep NULL == 0 and alignment)
- syscalls translate into calls of Java functions. Arguments are passed via special instruction encodings
- Java objects are stored in a table and passed via integer handles to C. When a Java object is created, an integer handle for it is registered and a mapping between the handle and the object is stored in the table.
System calls
Cibyl supports easy adaptation to different Cibyl APIs. Currently, subsets of the MIDP 2.0 and ANSI C APIs have been implemented. I will add functionality to the APIs as I go. The MIDP C API looks like
typedef int NOPH_Sprite_t; ... NOPH_Sprite_t NOPH_Sprite_new_image(NOPH_Image_t image); NOPH_Sprite_t NOPH_Sprite_new_imageSize(NOPH_Image_t image, int width, int height); NOPH_Sprite_t NOPH_Sprite_new_sprite(NOPH_Sprite_t sprite); ...
Integer handles are used to pass Java objects along. The cibyl-generate-c-header and cibyl-generate-java-wrappers tools goes through the syscall files and generates a C header and a Java class which defines the system calls and generates wrapper calls for the MIDP API.
Help needed!
- Run the Cibyl test cases on your mobile phone: This is the easiest way of helping out - you don't even have to install Cibyl to do the tests!
A partial list of things to be done in the development can be found below. Feel free to contribute these!
- Extend the API, most of J2ME is missing
- Replace the ANSI C environment with uClibc or newlib (where possible)
- Use MIPS32 instead of MIPS1 (R3000) as the target of compilation
- MIPS32 has some useful extra instructions: movn (conditional move) and mul (32-bit multiply)
- Nicer build-environment and less GNU/Linux dependencies. SCons?
- Make Cibyl installable in /usr/local or similar
- Integration with e.g., Eclipse
- Other languages (ObjC/Fortran/?)
- Runtime libraries needed
- PyPy?
- Optimization:
- Better implementation of library routines, especially memcpy (though it can often be inlined efficiently)
Download
Cibyl is released under the GNU GPL and LGPL licenses. The tools (e.g., cibyl-mips2java) are released under GPL while the Java libraries are LGPL. Cibyl is managed on googlecode at http://cibyl.googlecode.com
- Subversion repository: http://cibyl.googlecode.com/svn/
- Releases: http://code.google.com/p/cibyl/downloads/list
Contact
Simon Kågström is the author of Cibyl. Contact him at simon.kagstrom@gmail.com. He has a blog at http://simonkagstrom.livejournal.com, where he sometimes will post Cibyl stuff.
