December 2013

jvmBasic 2.0

I’ve always had a fascination with compilers.  As a Java geek, I’m also quite interested in the JVM.  In order to learn a little more about both, and as a way to contribute to the open source world, I decided to implement a compiler for BASIC.   So, jvmBasic consumes BASIC code and emits .class files. The first step was to build a parser and lexer for BASIC.  I decided to define an ANTLR4 grammar and use it to generate the lexer and parser.  BASIC is a fairly simple language, so the grammar was not difficult to define.  However, there are numerous BASIC dialects, so I had to pick a simple dialect.  jvmBASIC syntax looks much like Integer BASIC, but could easily be extended to parse GW-Basic, or maybe VB.  The resulting grammar is here. Once ANTLR has generated a parser and lexer, it’s possible to generate a parse tree for any BASIC input and then walk the tree emitting bytecode.  I used ASM to emit the bytecode.  An example BAS input file looks like this: 100 PRINT “Hello world” The generated parse tree from jvmBASIC debug output looks like – [1 line] –  [3 linenumber] –   [120 NUMBER] 100 –  [4 amprstmt] –   [5 statement] –    [7 printstmt1] –     [4 ‘PRINT’] PRINT –     [8 printlist] –      [66 expression] –       [60 func] –        [118 STRINGLITERAL] “Hello world” –  [122 CR] Because there is no concept of functions, methods or classes in BASIC, I chose to enclose the generated code in a single method, of a single class.  The classname is the name of the BASIC input file, and the single method is: public static void main(String[] args) The class has two fields: public InputStream inputStream; public OutputStream outputStream; The default values of inputStream and outputStream are System.in and System.out respectively.  However, in the case of jvmbasicwww, I replace them with HTTP input and output streams. BASIC doesn’t have new, delete, malloc, or free, or really any analogue of those.  Additionally, methods such as MID$ or perhaps VAL have certain semantics and behaviour.  In order to as closely as possible emulate BASIC, I implement jvmbasicrt.  Inside jvmbasicrt are implementation of each BASIC function, as well as a class called ExecutionContext. ExecutionContext includes the “guts” of a BASIC runtime: A stack.  Similar to many programming languages, BASIC needs a stack. All variables.  This is simple a hashtable of Values, keyed on the Variable name. Additionally there is Value which implements a variable with BASIC semantics. There is a maven mojo which wraps jvmbasicc.  The mojo jvmbasicmojo, compiles all BASIC files in “/src/main/bas” and produces a .class file for each one.  This mojo can be used to incorporate BASIC files into any normal maven project and then link them into a .jar file. An additional example BASIC file is: 10 REM this is a comment 20 PRINT “13” 30 PRINT “hi” 40 PRINT 10 50 PRINT 15.55 60 LET x = 12 70 PRINT “hihi” 80 PRINT x 90 LET y = 1+2 100 LET z = 3*6 110 LET d= y+z 120 PRINT d The maven pom file that uses jvmbasicmojo is here. The javap output for the generated .class file is: public class EXAMPLE1 { public com.khubla.jvmbasic.jvmbasicrt.ExecutionContext executionContext; public java.io.InputStream inputStream; public java.io.PrintStream outputStream; public EXAMPLE1(); public static void main(java.lang.String[]); public void program() throws java.lang.Exception; } There isn’t a big demand, that I’m aware of, for bytecode compilers for BASIC.  Two potential applications that come to mind are: Running VB code on the JVM.  Theoretically it would be possible to extend the grammar to include VB, and then to emit bytecode for VB programs.  This would form the foundation of technology to run .asp applications on the JVM.  The VB standard library would have to be implemented too. Cross-compilation.  Again, theoretically, it should be possible to use the grammar file to implement a cross compiler which consumes VB code and emits JSP code, or even PHP code.  

Building the Wandboard boot loader

I’ve bee hacking away trying to set up Crochet-BSD to build boot images for Wandboard.  Wandboard uses Cortex A9 processor, so it’s ARM.  The linux distros for it use U-Boot, so that seemed like a likely place to start for FreeBSD. Looking at the Wandboard Wiki, there is an article on U-Boot which explains how to build U-Boot for Wandboard.   Firstly, download the October 2013 release of U-Boot here.  If you are building on FreeBSD, you’ll need this patch to the Makefile to include libc. Then, build U-Boot for wandboard: make wandboard_quad_config make and copy the imx file to the sd card sudo dd if=u-boot.imx of=/dev/mmcblk0 bs=1 seek=1024 This writes the imx file 1K into the disk; which is where the i.mx6 processor expects to find the U-boot image.  The processor manual is here.  It specifies offset 0x400 as the Program Image start on the SD card.  The U-boot startup looks like this: CPU: Freescale i.MX6Q rev1.2 at 792 MHz Reset cause: POR Board: Wandboard DRAM: 2 GiB MMC: FSL_SDHC: 0, FSL_SDHC: 1 *** Warning – bad CRC, using default environment In: serial Out: serial Err: serial Net: FEC [PRIME] Hit any key to stop autoboot: 1 0 mmc0 is current device SD/MMC found on device 0 Keep in mind that the default serial protocol for Wandboard is 8n1 and 115200. Once U-boot is started, you will need to boot the FreeBSD kernel.  My disk image is partitioned with a FAT partition on which I have kernel.bin, and a UFS partition which is the FreeBSD root file system.  kernel.bin is the raw kernel.  The partition table looks like this: Disk: /dev/rdisk1 geometry: 3880/255/63 [62333952 sectors] Signature: 0xAA55 Starting       Ending #: id  cyl  hd sec –  cyl  hd sec [     start –       size] ———————————————————————— *1: 0C    8   5   1 –   58  29  63 [     16443 –     102375] Win95 FAT32L 2: A5   58  30   1 –  992   1  63 [    118818 –    1881180] FreeBSD 3: 00    0   0   0 –    0   0   0 [         0 –          0] unused 4: 00    0   0   0 –    0   0   0 [         0 –          0] unused You should notice that the FAT partition starts at 16443.  I’ve moved the start of the FAT partition further into the disk to accomodate u-boot at disk offset 0x400. Once you’ve got an SD card with u-boot and kernel.bin on it, and you’ve booted to u-boot, you’ll want to start the kernel.  At the u-boot console, load the kernel.bin into memory at address 0x12000000. fatload mmc 0:1 12000000 kernel.bin The address 0x1200000 is specified in the FreeBSD ARM configuration for Freescale.  Check here. Once the kernel is loaded, go ahead and start it: go 12000000 This will start FreeBSD: KDB: debugger backends: ddb KDB: current backend: ddb Copyright (c) 1992-2013 The FreeBSD Project. Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994 The Regents of the University of California. All rights reserved. FreeBSD is a registered trademark of The FreeBSD Foundation. FreeBSD 11.0-CURRENT #0 r259276: Thu Dec 12 17:20:23 MST 2013 tom@bernice:/storage/home/tom/crochet/crochet-wandboard/crochet-freebsd/work/obj/arm.arm/storage/home/tom/crochet/src/FreeBSDHead/head/sys/WANDBOARD-QUAD arm FreeBSD clang version 3.3 (tags/RELEASE_33/final 183502) 20130610 Preloaded elf kernel “kernel” at 0xc24afdac. CPU: Cortex A9-r2 rev 10 (Cortex-A core) Supported features: ARM_ISA THUMB2 JAZELLE THUMBEE ARMv4 Security_Ext WB disabled EABT branch prediction enabled In my case, I’ve run into a kernel crash starting the kernel, so I don’t have a fully working system yet, but I do have a working boot loader.  The Crochet-BSD code to build an image file containing USB, a partitioned disk image, kernel.bin and the userland is here: