新千葉 ガーベージ・コレクション

FPGA マガジンやインターフェースで書けなかったこと等をちょぼちょぼ書いてます。@ryos36

おれおれ tiny scheme もついに VM コード生成まで来た

この2か月の成果。なんとか fib をコンパイルして VM のコードに落とすことに成功。

(:JUMP |:MAIN|)

MAIN
(:LABEL |:MAIN|)

EXIT
(:LABEL |:EXIT|)

|:EXIT|
(:HALT :R0)

|:MAIN|
(:LABEL |:MAIN|)
(:JUMP |:label0|)
(:LIVE-REG 0 (1 1 1 1 1 0 0 0 0 0))

|:FIBO-2|
(:JUMP-COND := (:R2 0) |:label1|)
(:- (:R2 1) (:R2))
(:+ (:R3 :R4) (:R9))
(:RECORD-REF (:R0 0) (:R8))
(:SWAP :R9 :R3)
(:MOVE :R9 :R4)
(:JUMP :R8)

|:label1|
(:RECORD-REF (:R1 0) (:R9))
(:MOVE :R1 :R0)
(:MOVE :R3 :R1)
(:JUMP :R9)
(:LIVE-REG 0 (1 1 1 0 0 0 0 0 0 0))

|:FIBO|
(:RECORD-OFFS (:R0 1) (:R0))
(:RECORD-REF (:R0 0) (:R9))
(:MOVEI 1 :R3)
(:MOVEI 0 :R4)
(:JUMP :R9)

|:label0|
(:HEAP ((:LABEL |:FIBO|) (:LABEL |:FIBO-2|)) (:R9))
(:RECORD-REF (:R9 0) (:R8))
(:MOVE :R9 :R0)
(:MOVEI (:ADDRESS EXIT) :R1)
(:MOVEI 8 :R2)
(:JUMP :R8)

JUMP 命令が多い気もするが、気にしないで行こう。:R9 とかも気にせずいこう。
さて、これをさらにバイナリに落とすと行きたいところだが、できてないので C のソースに落ちる。

#define __codes_MAIN__ 0x00000003
#define __codes_EXIT__ 0x00000004
#define __codes__EXIT__ 0x00000005
#define __codes__MAIN__ 0x00000007
#define __codes__FIBO_2__ 0x0000000A
#define __codes__label1__ 0x00000019
#define __codes__FIBO__ 0x00000021
#define __codes__label0__ 0x0000002B
(Inst *)INST_ADDR(jumpi32),
0x20000000,
__codes__MAIN__,
__codes__MAIN__,
__codes__EXIT__,
(Inst *)INST_ADDR(halt),
0x00000000,
(Inst *)INST_ADDR(jumpi32),
0x20000000,
__codes__label0__,
(Inst *)INST_ADDR(eqi8),
0x04020000,
__codes__label1__,
(Inst *)INST_ADDR(subi8),
0x04020102,
(Inst *)INST_ADDR(add),
0x00030409,
(Inst *)INST_ADDR(record_refi8),
0x04000008,
(Inst *)INST_ADDR(move),
0x00030400,
(Inst *)INST_ADDR(swap),
0x00090300,
(Inst *)INST_ADDR(jump),
0x00080000,
(Inst *)INST_ADDR(record_refi8),
0x04010009,
(Inst *)INST_ADDR(move),
0x00010000,
(Inst *)INST_ADDR(move),
0x00030100,
(Inst *)INST_ADDR(halt),
0x00010000,
(Inst *)INST_ADDR(record_offsi8),
0x04000100,
(Inst *)INST_ADDR(record_refi8),
0x04000009,
(Inst *)INST_ADDR(movei8),
0x04000103,
(Inst *)INST_ADDR(movei8),
0x04000004,
(Inst *)INST_ADDR(jump),
0x00090000,
(Inst *)INST_ADDR(heap),
0x04000209,
0x0000000A,
__codes__FIBO__,
__codes__FIBO_2__,
(Inst *)INST_ADDR(record_refi8),
0x04090008,
(Inst *)INST_ADDR(move),
0x00090000,
(Inst *)INST_ADDR(movei32),
0x20000001,
&pre_inst[__codes__EXIT__],
(Inst *)INST_ADDR(movei8),
0x04005b02,
(Inst *)INST_ADDR(jump),
0x00080000,

で一部改ざんして(orz) 0x5b を入力にする。実行。

> ./hvm
いろいろデバッグ用の出力があるので省略
move result regs[1] =  68a3dd8e61eccfbd
halt 7540113804746346429

こたえがでる。movei32 とかいうコードなのに、long が 64bit のために答えも 64bit。
こたえは 7540113804746346429 で 92(0x5c) のフィボナッチを計算した答えに一致!!

http://www.maths.surrey.ac.uk/hosted-sites/R.Knott/Fibonacci/fibtable.html

ん?0x5b をいれると 0x5c の答えが返ってくるという、、、仕様です。はい。