Cibyl is a programming environment and binary translator that allows compiled C programs to execute on Blackberry and 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 Blackberry and J2ME phones 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.
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
- Guidelines when programming for Cibyl: What to do and what not to do when programming for Cibyl
- 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
- Waze: Social navigation software ported to Blackberry using Cibyl by Ehud Shabtai.
- 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
Short example program
``` #include
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:
<TT>
-mno-check-zero-division
</TT>
,
<TT>
-fno-pic
</TT>
,
<TT>
-mno-abicalls
</TT>
. 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 *
<TT>
crt0.S
</TT>
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
<TT>
nop
</TT>
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
<TT>
0x16
</TT>
(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, much of J2ME is missing
- Use MIPS32 instead of MIPS1 (R3000) as the target of compilation
- MIPS32 has some useful extra instructions:
<TT>
movn
</TT>
(conditional move) and
<TT>
mul
</TT>
(32-bit multiply) * Nicer build-environment and less GNU/Linux dependencies. * Integration with e.g., Eclipse * 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
- Git repository: http://github.com/SimonKagstrom/cibyl
- Releases: http://code.google.com/p/cibyl/downloads/list
Contact
Simon Kågstö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.