普通に計算すりゃいいじゃねーか!って内容なわけだけど、脳みそのリハビリを兼ねてZ80用のバイナリコードをニーモニックに変換してたついでに加算回路を記述してみた。
Perlなのは、使用環境がVSCode+WSL2:Ubuntuだったので、インストール作業なし、バージョン差異なし、コンパイル作業なし、文字列の取り扱いが楽って理由で変換コード書く際に使っていたから。
で、コードについてもメモしとくと、Z80のALUは、4bitで演算してるので半加算器、全加算器、それらを組みわあせた4bit加算器となっている。
#
# HALF ADDER
sub half_adder {
return hex($_[0])^hex($_[1]), hex($_[0])&hex($_[1]);
}
#
# FULL ADDER
sub full_adder {
my($BIT, $CARRY1 ) = half_adder($_[0],$_[1]);
my($BIT, $CARRY2 ) = half_adder($BIT,$_[2]);
return $BIT, ($CARRY1|$CARRY2);
}
#
# 4bit ADDER
sub ADD_4bit {
my @BIT; my $CARRY = 0;
my @BIT1 = sprintf("%04b",hex($_[0])) =~ /.{1}/g;
my @BIT2 = sprintf("%04b",hex($_[1])) =~ /.{1}/g;
if ( $_[2] ) { $CARRY = $_[2] }
for ( my $i = 3; $i >= 0; $i-- ) {
($BIT[$i], $CARRY) = full_adder($BIT1[$i],$BIT2[$i],$CARRY);
}
return join('',@BIT), $CARRY;
}
$C、$Hは、元コードで宣言済みのフラグレジスタのキャリーフラグとハーフキャリーフラグを指す変数。ここでは何も宣言してないので意味ないんだけど。
実際のコードでは、まとめて一つの関数にしてあるのだけど、コメントアウトしても場所とって邪魔なので、こちらに保管。
sub ADD_8bit {
my @BITS;
if ( !$_[2] ) { $C = 0; }
($BITS[1], $H) = ADD_4bit(substr($_[0],1,1),substr($_[1],1,1),$C);
($BITS[0], $C) = ADD_4bit(substr($_[0],0,1),substr($_[1],0,1),$H);
return sprintf("%02X",oct("0b".join("",@BITS)));
}
sub ADD_16bit {
my @BITS;
if ( !$_[2] ) { $C = 0; }
($BITS[3], $H) = ADD_4bit(substr($_[0],3,1),substr($_[1],3,1),$C);
($BITS[2], $C) = ADD_4bit(substr($_[0],2,1),substr($_[1],2,1),$H);
($BITS[1], $H) = ADD_4bit(substr($_[0],1,1),substr($_[1],1,1),$C);
($BITS[0], $C) = ADD_4bit(substr($_[0],0,1),substr($_[1],0,1),$H);
return sprintf("%04X",oct("0b".join("",@BITS)));
}
sub SUB_8bit {
$C = 1;
my @BITS;
my $NOT_BIT = sprintf("%02X",oct("0b".substr(sprintf("%b",~hex($_[1])),-8,8)));
($BITS[1], $H) = ADD_4bit(substr($_[0],1,1),substr($NOT_BIT,1,1),$C);
($BITS[0], $C) = ADD_4bit(substr($_[0],0,1),substr($NOT_BIT,0,1),$H);
return sprintf("%02X",oct("0b".join("",@BITS)));
}
sub SUB_16bit {
$C = 1;
my @BITS;
my $NOT_BIT = sprintf("%04X",oct("0b".substr(sprintf("%016b",~hex($_[1])),-16,16)));
($BITS[3], $H) = ADD_4bit(substr($_[0],3,1),substr($NOT_BIT,3,1),$C);
($BITS[2], $C) = ADD_4bit(substr($_[0],2,1),substr($NOT_BIT,2,1),$H);
($BITS[1], $H) = ADD_4bit(substr($_[0],1,1),substr($NOT_BIT,1,1),$C);
($BITS[0], $C) = ADD_4bit(substr($_[0],0,1),substr($NOT_BIT,0,1),$H);
return sprintf("%04X",oct("0b".join("",@BITS)));
}
0 件のコメント:
コメントを投稿