// // // Java Virutal Machine // // for ACEX 1K30 use less than 1024 instructions // no internal ram possible // use serial interface to download byte code // // Author: Martin Schoeberl martin@good-ear.com // // revision: // 2001-01-14 first 'real' Java program runs (prime) // 2001-01-27 byte code in extern ram // 2001-01-27 byte code in extern ram // 2001-05-26 ir to cache (pc) for xxx_n // // iobase = 2097152 ext_ram = 3145728 ext_rom = 3670016 // // system wide pointers // mbase = ? const = ? stack = ? heap = ? // // function local pointers // pc = ? vars = ? frame = ? sp = ? ir = ? // store instruction for xxx_n tmp = ? a = ? b = ? c = ? d = ? // // vars for utility functions // tmpb = ? tmpc = ? retadr = ? retadr2 = ? cr = 13 lf = 10 ok = 27503 noim = 1835626350 crlf = 2573 blank = 32 ld (ext_ram) // for timing diagram in max+ ld (ext_ram) ld 12345678 //st (ext_ram) //st (ext_ram+1) ld (ext_rom) ld (ext_rom) ld 12345678 //st (ext_rom) //st (ext_rom+1) init ld 6000000 init_loop sub 1 bnz init_loop ld (ext_ram) st mbase ld (ext_ram+1) st const ld (ext_ram+2) st stack ld (ext_ram+3) st heap // // simulate invokestatic for function main // index 1 in method table // write bytecodes in first 4 stack positions // ld stack st pc // use stack ld 184 st (pc) // dummy ld 202 // breakpoint after return from main st (pc+1) ld stack add 2 st sp ld ok st a jp short_strg ld crlf st a jp short_strg ld 65537 // 0x00010001 main st a jp invoke_main // jp monitor fetch ld (pc+1) // to optimize: fetchcode zu den bytecodes st ir add jmp_tbl // => somtimes less pc inc st tmp // one jump less !!! ld pc add 1 st pc // st a // jp hex_out // ld ir // st a // jp hex_out // ld crlf // st a // jp short_strg jp (tmp) // // begin of bytecodes // notimp ld crlf st a jp short_strg ld pc st a jp hex_out ld ir st a jp hex_out ld noim st a jp short_strg ld crlf st a jp short_strg notimp_end jp notimp_end iconst_n ld sp add 1 st sp ld ir sub 3 st (sp) jp fetch bipush ld sp add 1 st sp ld (pc+1) st (sp) and 128 bz bipush_pos ld (pc+1) add -256 // 0xffffff00 st (sp) bipush_pos ld pc add 1 st pc jp fetch sipush ld sp add 1 st sp ld (pc+1) sbr st a ld (pc+2) add a st (sp) and 32768 // 0x00008000 bz sipush_pos ld (sp) add -65536 // 0xffff0000 st (sp) sipush_pos ld pc add 2 st pc jp fetch ldc // !!!! derweilen fix!!! ld sp add 1 st sp ld (pc+1) add const st a st a ld (a) st (sp) ld pc add 1 st pc jp fetch iload aload ld sp add 1 st sp ld (pc+1) add vars st tmp st tmp ld (tmp) st (sp) ld pc add 1 st pc jp fetch iload_n ld sp add 1 st sp ld ir sub 26 add vars st tmp st tmp ld (tmp) st (sp) jp fetch aload_n ld sp add 1 st sp ld ir sub 42 add vars st tmp st tmp ld (tmp) st (sp) jp fetch iaload ld sp sub 1 st sp st sp ld (sp) st a ld (sp+1) add a st a st a ld (a) st (sp) jp fetch istore astore ld (pc+1) add vars st tmp ld (sp) st (tmp) ld sp sub 1 st sp ld pc add 1 st pc jp fetch istore_n ld ir sub 59 add vars st tmp ld (sp) st (tmp) ld sp sub 1 st sp jp fetch breakpoint ld 0 stop bz stop iastore ld sp sub 3 st sp st sp ld (sp+1) st a ld (sp+2) add a st a ld (sp+3) st (a) jp fetch pop ld sp sub 1 st sp jp fetch pop2 ld sp sub 2 st sp jp fetch dup ld (sp) st (sp+1) ld sp add 1 st sp jp fetch iadd ld (sp) st tmp ld sp sub 1 st sp st sp ld (sp) add tmp st (sp) jp fetch isub ld (sp) st tmp ld sp sub 1 st sp st sp ld (sp) sub tmp st (sp) jp fetch ishl ld (sp) and 31 st tmp ld sp sub 1 st sp st sp ld (sp) st a ld tmp bz ishl_end ishl_loop ld a shl st a ld tmp sub 1 st tmp bnz ishl_loop ishl_end ld a st (sp) jp fetch ishr ld (sp) and 31 st tmp ld sp sub 1 st sp st sp ld (sp) st a and -2147483648 // 0x80000000 (sign) st b ld tmp bz ishr_end ishr_loop ld a shr or b st a ld tmp sub 1 st tmp bnz ishr_loop ishr_end ld a st (sp) jp fetch iushr ld (sp) and 31 st tmp ld sp sub 1 st sp st sp ld (sp) st a ld tmp bz iushr_end iushr_loop ld a shr st a ld tmp sub 1 st tmp bnz iushr_loop iushr_end ld a st (sp) jp fetch iand ld (sp) st tmp ld sp sub 1 st sp st sp ld (sp) and tmp st (sp) jp fetch ior ld (sp) st tmp ld sp sub 1 st sp st sp ld (sp) or tmp st (sp) jp fetch ixor ld (sp) st tmp ld sp sub 1 st sp st sp ld (sp) xor tmp st (sp) jp fetch iinc ld (pc+1) add vars st a ld (pc+2) st tmp and 128 bz iinc_pos ld -256 // 0xffffff00 add tmp st tmp iinc_pos ld (a) add tmp st (a) ld pc add 2 st pc jp fetch ifeq ld sp sub 1 st sp st sp ld (sp+1) bz goto ld pc add 2 st pc jp fetch ifne ld sp sub 1 st sp st sp ld (sp+1) bnz goto ld pc add 2 st pc jp fetch ifgt ld sp sub 1 st sp st sp ld (sp+1) bz ifgt_nobr and -2147483648 // 0x80000000 bz goto ifgt_nobr ld pc add 2 st pc jp fetch if_icmpne ld sp sub 2 st sp st sp ld (sp+1) st tmp ld (sp+2) sub tmp bnz goto ld pc add 2 st pc jp fetch if_icmplt ld sp sub 2 st sp st sp ld (sp+1) st tmp ld (sp+2) add 0 // clr c ??? // sign ??? see ifgt sub tmp bz if_icmplt_nobr bc goto if_icmplt_nobr ld pc add 2 st pc jp fetch if_icmpge ld sp sub 2 st sp st sp ld (sp+2) st tmp ld (sp+1) add 0 // clr c ??? // sign ??? see ifgt sub tmp bc goto bz goto ld pc add 2 st pc jp fetch if_icmpgt ld sp sub 2 st sp st sp ld (sp+2) st tmp ld (sp+1) add 0 // clr c ??? // sign ??? see ifgt sub tmp bz if_icmpgt_nobr bc goto if_icmpgt_nobr ld pc add 2 st pc jp fetch goto ld (pc+2) st tmp ld (pc+1) and 128 bz goto_add ld -65536 // 0xffff0000 add tmp st tmp goto_add ld (pc+1) sbl add tmp add pc sub 1 st pc jp fetch return ld (frame) st pc ld (frame+1) st vars ld (frame+3) st sp ld (frame+2) st frame jp fetch invokestatic // derweilen fixe sys funktionen (const 1, 2, 3) ld (pc+2) // only low index byte add const st b ld pc // increment pc add 2 st pc ld (b) st a st a invoke_main ld a and -65536 // 0xffff0000 bz invokestatic_sys ld a and 65535 // 0x0000ffff add mbase // start of method table st b st b ld (b) // address of method struct st b st b // // jetzt geht's los mit frame Aufbau,..... // ld (b+2) // varcnt st c ld sp add c add 1 // sp points to last arg st c // new frame ld pc st (c) // save old pc ld vars st (c+1) // save old vars ld frame st (c+2) // save old frame ld c st frame // new frame ld (b+1) // args st c ld sp sub c st (frame+3) // save old sp-args add 1 st vars // vars points to first arg ld frame add 3 // pc, vars, frame, sp st sp ld (b) // startpc sub 1 // pc = pc-1 at start !!! st pc // und weiter mit neuem pc jp fetch invokestatic_sys ld a sub 1 bz invoke_rd ld a sub 2 bz invoke_wr ld a sub 3 bz invoke_print invoke_rd // int rd(int adr) ld (sp) st a st a ld (a) st (sp) jp fetch invoke_wr // void wr(int adr, int val) ld (sp) // val st a ld sp sub 2 st sp st sp ld (sp+1) // adr st b ld a st (b) jp fetch invoke_print // void print(int i) ld (sp) st a jp hex_out ld sp sub 1 st sp jp fetch newarray // quick and VERY dirty ld (sp) // every element is 32 bit, no type check, no init st a ld heap st (sp) add a st heap ld pc add 1 st pc jp fetch jmp_tbl bnz notimp // 0x00 bnz notimp bnz iconst_n bnz iconst_n bnz iconst_n bnz iconst_n bnz iconst_n bnz iconst_n bnz iconst_n bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz bipush // 0x10 bnz sipush bnz ldc bnz notimp bnz notimp bnz iload bnz notimp bnz notimp bnz notimp bnz aload bnz iload_n bnz iload_n bnz iload_n bnz iload_n bnz notimp bnz notimp bnz notimp // 0x20 bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz aload_n bnz aload_n bnz aload_n bnz aload_n bnz iaload bnz notimp bnz notimp // 0x30 bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz istore bnz notimp bnz notimp bnz notimp bnz astore bnz istore_n bnz istore_n bnz istore_n bnz istore_n bnz notimp bnz notimp // 0x40 bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz iastore bnz notimp // 0x50 bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz pop bnz pop2 bnz dup bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz iadd // 0x60 bnz notimp bnz notimp bnz notimp bnz isub bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp // 0x70 bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz ishl bnz notimp bnz ishr bnz notimp bnz iushr bnz notimp bnz iand bnz notimp bnz ior // 0x80 bnz notimp bnz ixor bnz notimp bnz iinc bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp // 0x90 bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz ifeq bnz ifne bnz notimp bnz notimp bnz ifgt bnz notimp bnz notimp bnz if_icmpne // 0xa0 bnz if_icmplt bnz if_icmpge bnz if_icmpgt bnz notimp bnz notimp bnz notimp bnz goto bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp // 0xb0 bnz return bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz invokestatic bnz notimp bnz notimp bnz notimp bnz newarray bnz notimp bnz notimp bnz notimp bnz notimp // 0xc0 bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz breakpoint bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp // 0xd0 bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp // 0xe0 bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp // 0xf0 bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp bnz notimp // // write short string (a, max. 4 characters) // short_strg st retadr2 ld a st tmpb short_strg_loop and 255 st a jp ser_out ld tmpb sbr st tmpb bnz short_strg_loop jp (retadr2) // // write val of a in hex + blank // hex_out st retadr2 ld a st tmpb ld 8 st tmpc hex_out_loop ld tmpb sbr sbr sbr shr shr shr shr st a jp hex2ascii jp ser_out ld tmpb shl shl shl shl st tmpb ld tmpc sub 1 st tmpc bnz hex_out_loop ld blank st a jp ser_out jp (retadr2) // // low nib of a to ascii value // hex2ascii st retadr ld 9 sub a and 16 bnz hex2ascii_gt9 ld a add 48 st a jp (retadr) hex2ascii_gt9 ld a add 55 st a jp (retadr) // // low byte of a from (hex-)ascii value to bin-nib // bit 4 set if no hex char ascii2hex st retadr ld a sub 58 // sub '9'+1 and 256 bz ascii2hex_gt9 ld a sub 48 // sub '0' st a and 256 bnz ascii2hex_nothex jp (retadr) ascii2hex_gt9 ld a sub 97 // sub 'a' st a and 256 bnz ascii2hex_nothex ld a sub 6 and 256 bz ascii2hex_nothex ld a add 10 st a jp (retadr) ascii2hex_nothex ld 16 st a jp (retadr) // // write one character to uart // ser_out st retadr wait ld (iobase+2) and 1 bz wait ld a st (iobase+1) jp (retadr)