使い方

プログラムの最初に

1 1 1

と書いておけば、以降変数1は定数1として使える

0 0 1 0 1 0 0 0

これで、「H」が出力できる。頑張って並べれば「Hello, world!」が書ける

基本的な計算

### X <- !Y
X Y Y

### X <- Y
X Y Y
X X X

### X <- Y & Z
X Y Z
X X X

### X <- Y | Z
s Y Y
t Z Z
X s t

### X <- Y ^ Z
s Y Y
t Z Z
s s Z
t t Y
X s t

こんだけだとどう書いたらQuineができるのかよく分からない。もっと複雑なのを書くためにマクロを作る

フラグによって動作を変える命令が重要で、これを使わないと頭がおかしくなる。

## copy_flag_if(d, s, f)  # d = f ? s : d = (s & f) | (d & ~f)
x f f
y d x
x s f
d x y
## copy_reg_if(d, s, f)
copy_flag_if(d[0], s[0], f)
copy_flag_if(d[1], s[1], f)
...
copy_flag_if(d[7], s[7], f)

条件付インクリメントとかは

## inc_if(d, f)
copy_reg(tmp, d)
inc(tmp)
copy_reg_if(d, tmp, f)

インクリメントってどうやるの?

## inc(r)
set_flag(c)    # c 0 0  # キャリー
clear_flag(d)  # d 1 1  # not キャリー

## 半加算器
s r0 r0
s s c
t r0 d
d r0 c
c d d
r0 s t

## 半加算器
s r1 r1
s s c
t r1 d
d r1 c
c d d
r1 s t

...

s r7 r7
s s c
t r7 d
d r7 c
c d d
r7 s t

ROM の構成

ROMっていうのは16bitから8bitへのデコーダとかそんなもんですから、入力と出力を決めてやれば頑張ってNANDだけで書けるわけです。

でも、Quineで使うROMはそのROMのプログラム自体を出力できなければいけません。ようするに規則的に作らないといけないというわけです。

インターフェースはこんな感じにします

## ROM
##
## ADDR_BUS 16bit in
## DATA_BUS 8bit  out

# ここでADDR_BUSに適当な値を設定する
copy_reg(ADDR_BUS, PC)
# ROMのコードを記述する
...
# ここまで実行が終わると DATA_BUS に結果が入ってる
copy_reg(VALUE, DATA_BUS)

ROMの各セルは次のように作ります

##
## if (ADDR_BUS-- == 0) {
##   DATA_BUS = ROM[addr]
## }
##
dec(ADDR_BUS, carry)
copy_reg_if(DATA_BUS, 'H', carry)

これで、値'H'の入ったROMができました。これをたくさん並べれば好きなだけ大きなROMが作れます。

つづく