SDK-80のシリアルポートにASR-33が接続された環境を想定している東大版Palo Alto Tiny BASICをWSL2Ubuntu環境に移植しています。Geminiと相談しながら作業しています。BASICというものは、編集環境と実行環境が統合されているところに真髄があるのですが、まず編集環境の方から移植を進めています。数字文字列を2進数に変換するために「GETI」というルーチンがあります。これをamd64にしてみます。
オリジナルは次のようになっています。
GINT: LXI H,0000H ;GET INTEGER
MOV B,H
CALL SKPBL
GETI1: CPI '0'
RC ;RETURN INTEGER IN HL
CPI '9'+1
RNC
MVI A,0F0H
ANA H ;IF INTEGER>#0FFF ERHOW
JNZ ERHOW
INR B
PUSH B
MOV B,H ;HL HL+10
MOV C,L
DAD H
DAD H
DAD B
DAD H
LDAX D ;HL HL+(DE)�F
INX D
ANI 0FH
ADD L
MOV L,A
MVI A,00H
ADC H
MOV H,A
POP B
LDAX D
JM ERHOW
JMP GETI1
Geminiの指導を受けながらamd64に移植したら、次のようになりました。
.equ GINT_DIGIT_MAX, (NINE-ZERO)
.equ GINT_MAX_BEFORE_X10, 0x0FFF
gint: xor eax,eax
xor ecx,ecx
call skpbl
geti1: movzx edx,byte ptr [rdi]
sub edx,ZERO
cmp edx,GINT_DIGIT_MAX
ja geti9
cmp ax,GINT_MAX_BEFORE_X10
ja erhow
inc cx
# amd64の真骨頂: LEA命令による AX = (AX * 10) + DX
lea eax,[rax + rax*4]
lea eax,[rdx + rax*2]
inc rdi
test ax,ax
js erhow
jmp geti1
geti9: ret
amd64と比べるのは卑怯かもしれませんが、i8080は命令が貧弱です。レジスタの内容を10倍するのも、簡単にはできません。一方amd64は、IMUL命令で簡単に10倍できるはずですが、Geminiが提示してきたのはLEA命令を使う方法でした。なぜIMUL命令を使わないでLEA命令なのかとGeminiに問うと、内部処理の都合上この方が速いのだそうです。ここがボトルネックという訳ではないので、微妙に速くなっても全体としては速さを意識できないと思います。しかし、いかにもamd64チューニングされているという感じにはなりました。
0 件のコメント:
コメントを投稿