竹下世界塔の計算機よもやま話

アクセスカウンタ

zoom RSS AWKによるSPARC V8逆アセンブラ

<<   作成日時 : 2010/01/07 10:09   >>

ブログ気持玉 0 / トラックバック 0 / コメント 0

 Aho、Weinberger、Kernighan著の「プログラミング言語AWK」復刊(/.J)
 トッパンから初版が出た時には大学生協でA君と奪い合ったなあ。スラッシュドットジャパンでも活発に議論されてるみたいだが、自分がオッサンだと自白するようなものか?
 ハード設計でも役に立って、CADのデータ加工などに活躍しました。それまではみな印刷して手作業でチェックしていたので布教してまわったものです。しかし新人の私に結局は仕事が振られるという。
 昔作った、AWKで書いたSPARC V8用の逆アセンブラを公開します。これは事務所引っ越しの時、計算機環境もまっさらにしたため無くしてしまったと思っていたのですが、年末の掃除でフロッピーの中にあったものを発見しました。入力は16進ダンプです。バイナリは読めません。
 逆アセンブラを作るということは、命令デコーダを作ることと似ている。その点固定長命令のSPARCは作るのが楽だった。

craps.awk (nawkで動作) 以下はソースなので不要な方は読み流してください
※インデントが失われました。ごめんなさい。

20101221 ウェブリブログではソースコードをそのまま貼り付けるとインデントが消えるようです。別のページに整形したものを公開しましたのでご参照ください。→awkで書いたSPARC V8逆アセンブラ


<PRE>

#! /usr/bin/nawk -f
#
# craps.awk - sparc disassembler
#
# 95/04/07 ver 1.0 by Katsunori Takeshita
# 95/04/10 ver 1.1 alu implement
# 95/05/24 ver 1.2 rd operand decode miss
#

BEGIN {
H2B["0"]="0000" ;
H2B["1"]="0001" ;
H2B["2"]="0010" ;
H2B["3"]="0011" ;
H2B["4"]="0100" ;
H2B["5"]="0101" ;
H2B["6"]="0110" ;
H2B["7"]="0111" ;
H2B["8"]="1000" ;
H2B["9"]="1001" ;
H2B["A"]="1010" ;
H2B["B"]="1011" ;
H2B["C"]="1100" ;
H2B["D"]="1101" ;
H2B["E"]="1110" ;
H2B["F"]="1111" ;
H2B["a"]="1010" ;
H2B["b"]="1011" ;
H2B["c"]="1100" ;
H2B["d"]="1101" ;
H2B["e"]="1110" ;
H2B["f"]="1111" ;
#
B2H["0000"]="0" ;
B2H["0001"]="1" ;
B2H["0010"]="2" ;
B2H["0011"]="3" ;
B2H["0100"]="4" ;
B2H["0101"]="5" ;
B2H["0110"]="6" ;
B2H["0111"]="7" ;
B2H["1000"]="8" ;
B2H["1001"]="9" ;
B2H["1010"]="A" ;
B2H["1011"]="B" ;
B2H["1100"]="C" ;
B2H["1101"]="D" ;
B2H["1110"]="E" ;
B2H["1111"]="F" ;
#
REG["00000"]="%g0" ;
REG["00001"]="%g1" ;
REG["00010"]="%g2" ;
REG["00011"]="%g3" ;
REG["00100"]="%g4" ;
REG["00101"]="%g5" ;
REG["00110"]="%g6" ;
REG["00111"]="%g7" ;
REG["01000"]="%o0" ;
REG["01001"]="%o1" ;
REG["01010"]="%o2" ;
REG["01011"]="%o3" ;
REG["01100"]="%o4" ;
REG["01101"]="%o5" ;
REG["01110"]="%o6" ;
REG["01111"]="%o7" ;
REG["10000"]="%l0" ;
REG["10001"]="%l1" ;
REG["10010"]="%l2" ;
REG["10011"]="%l3" ;
REG["10100"]="%l4" ;
REG["10101"]="%l5" ;
REG["10110"]="%l6" ;
REG["10111"]="%l7" ;
REG["11000"]="%i0" ;
REG["11001"]="%i1" ;
REG["11010"]="%i2" ;
REG["11011"]="%i3" ;
REG["11100"]="%i4" ;
REG["11101"]="%i5" ;
REG["11110"]="%i6" ;
REG["11111"]="%i7" ;
#
Bicc["0000"]="bn" ;
Bicc["0001"]="be" ;
Bicc["0010"]="ble" ;
Bicc["0011"]="bl" ;
Bicc["0100"]="bleu" ;
Bicc["0101"]="bcs" ;
Bicc["0110"]="bneg" ;
Bicc["0111"]="bvs" ;
Bicc["1000"]="ba" ;
Bicc["1001"]="bne" ;
Bicc["1010"]="bg" ;
Bicc["1011"]="bge" ;
Bicc["1100"]="bgu" ;
Bicc["1101"]="bcc" ;
Bicc["1110"]="bpos" ;
Bicc["1111"]="bvc" ;
#
CBccc["0000"]="cbn" ;
CBccc["0001"]="cb123" ;
CBccc["0010"]="cb12" ;
CBccc["0011"]="cb13" ;
CBccc["0100"]="cb1" ;
CBccc["0101"]="cb23" ;
CBccc["0110"]="cb2" ;
CBccc["0111"]="cb3" ;
CBccc["1000"]="cba" ;
CBccc["1001"]="cb0" ;
CBccc["1010"]="cb03" ;
CBccc["1011"]="cb02" ;
CBccc["1100"]="cb023" ;
CBccc["1101"]="cb01" ;
CBccc["1110"]="cb013" ;
CBccc["1111"]="cb012" ;
#
FBfcc["0000"]="fbn" ;
FBfcc["0001"]="fbne" ;
FBfcc["0010"]="fblg" ;
FBfcc["0011"]="fbul" ;
FBfcc["0100"]="fbl" ;
FBfcc["0101"]="fbug" ;
FBfcc["0110"]="fbg" ;
FBfcc["0111"]="fbu" ;
FBfcc["1000"]="fba" ;
FBfcc["1001"]="fbe" ;
FBfcc["1010"]="fbue" ;
FBfcc["1011"]="fbge" ;
FBfcc["1100"]="fbuge" ;
FBfcc["1101"]="fble" ;
FBfcc["1110"]="fbule" ;
FBfcc["1111"]="fbo" ;
#
Ticc["0000"]="tn" ;
Ticc["0001"]="te" ;
Ticc["0010"]="tle" ;
Ticc["0011"]="tl" ;
Ticc["0100"]="tleu" ;
Ticc["0101"]="tcs" ;
Ticc["0110"]="tneg" ;
Ticc["0111"]="tvs" ;
Ticc["1000"]="ta" ;
Ticc["1001"]="tne" ;
Ticc["1010"]="tg" ;
Ticc["1011"]="tge" ;
Ticc["1100"]="tgu" ;
Ticc["1101"]="tcc" ;
Ticc["1110"]="tpos" ;
Ticc["1111"]="tvc" ;
#
ALU01["0000"]="add" ;
ALU01["0001"]="and" ;
ALU01["0010"]="or" ;
ALU01["0011"]="xor" ;
ALU01["0100"]="sub" ;
ALU01["0101"]="andn" ;
ALU01["0110"]="orn" ;
ALU01["0111"]="xnor" ;
ALU01["1000"]="addx" ;
ALU01["1001"]="XXX" ;
ALU01["1010"]="umul" ;
ALU01["1011"]="smul" ;
ALU01["1100"]="subx" ;
ALU01["1101"]="XXX" ;
ALU01["1110"]="udiv" ;
ALU01["1111"]="sdiv" ;
#
ALU2["0000"]="taddcc" ;
ALU2["0001"]="tsubcc" ;
ALU2["0010"]="taddcctv" ;
ALU2["0011"]="tsubcctv" ;
ALU2["0100"]="mulscc" ;
ALU2["0101"]="sll" ;
ALU2["0110"]="srl" ;
ALU2["0111"]="sra" ;
ALU2["1000"]="rd" ; # stbar,rdasr,rdy
ALU2["1001"]="rd" ; # rdpsr
ALU2["1010"]="rd" ; # rdwim
ALU2["1011"]="rd" ; # rdtbr
ALU2["1100"]="XXX" ;
ALU2["1101"]="XXX" ;
ALU2["1110"]="XXX" ;
ALU2["1111"]="XXX" ;
#
ALU3["0000"]="wr" ; # wrasr,wry
ALU3["0001"]="wr" ; # wrpsr
ALU3["0010"]="wr" ; # wrwim
ALU3["0011"]="wr" ; # wrtbr
ALU3["0100"]="FPop1" ;
ALU3["0101"]="FPop2" ;
ALU3["0110"]="CPop1" ;
ALU3["0111"]="CPop2" ;
ALU3["1000"]="jmpl" ;
ALU3["1001"]="rett" ;
ALU3["1010"]="ticc" ; # Ticc
ALU3["1011"]="flush" ;
ALU3["1100"]="save" ;
ALU3["1101"]="restore" ;
ALU3["1110"]="XXX" ;
ALU3["1111"]="XXX" ;
#
LD01["0000"]="ld" ;
LD01["0001"]="ldub" ;
LD01["0010"]="lduh" ;
LD01["0011"]="ldd" ;
LD01["0100"]="st" ;
LD01["0101"]="stb" ;
LD01["0110"]="sth" ;
LD01["0111"]="std" ;
LD01["1000"]="XXX" ;
LD01["1001"]="ldsb" ;
LD01["1010"]="ldsh" ;
LD01["1011"]="XXX" ;
LD01["1100"]="XXX" ;
LD01["1101"]="ldstub" ;
LD01["1110"]="XXX" ;
LD01["1111"]="swap" ;
#
LD2["0000"]="ldf" ;
LD2["0001"]="ldfsr" ;
LD2["0010"]="XXX" ;
LD2["0011"]="lddf" ;
LD2["0100"]="stf" ;
LD2["0101"]="stfsr" ;
LD2["0110"]="stdfq" ;
LD2["0111"]="stdf" ;
LD2["1000"]="XXX" ;
LD2["1001"]="XXX" ;
LD2["1010"]="XXX" ;
LD2["1011"]="XXX" ;
LD2["1100"]="XXX" ;
LD2["1101"]="XXX" ;
LD2["1110"]="XXX" ;
LD2["1111"]="XXX" ;
#
LD3["0000"]="ldc" ;
LD3["0001"]="ldcsr" ;
LD3["0010"]="XXX" ;
LD3["0011"]="lddc" ;
LD3["0100"]="stc" ;
LD3["0101"]="stcsr" ;
LD3["0110"]="stdcq" ;
LD3["0111"]="stdc" ;
LD3["1000"]="XXX" ;
LD3["1001"]="XXX" ;
LD3["1010"]="XXX" ;
LD3["1011"]="XXX" ;
LD3["1100"]="XXX" ;
LD3["1101"]="XXX" ;
LD3["1110"]="XXX" ;
LD3["1111"]="XXX" ;
#
ASR["00000"]="%y" ;
ASR["00001"]="%asr_1" ;
ASR["00010"]="%asr_2" ;
ASR["00011"]="%asr_3" ;
ASR["00100"]="%asr_4" ;
ASR["00101"]="%asr_5" ;
ASR["00110"]="%asr_6" ;
ASR["00111"]="%asr_7" ;
ASR["01000"]="%asr_8" ;
ASR["01001"]="%asr_9" ;
ASR["01010"]="%asr_10" ;
ASR["01011"]="%asr_11" ;
ASR["01100"]="%asr_12" ;
ASR["01101"]="%asr_13" ;
ASR["01110"]="%asr_14" ;
ASR["01111"]="%asr_15" ;
}

{
ADDR = $1 ;
DATA = $2 ; INST = h2b( $2 );
OPCODE = "" ; OPRAND = "" ;

# 1st decode
op = substr( INST,1,2 ) ;

if ( op=="01" ) { # call
dist = substr(INST,3) "00" ;
OPCODE = "call" ;
OPRAND = "0x" b2h(dist);
writeln( ADDR,DATA,OPCODE,OPRAND );
next ;
}

if ( op=="00" ) { # F2 - branch,sethi,nop
# 2nd decode
op2 = substr(INST,8,3) ;
if ( op2=="000" ) { # unimplement
OPCODE = "unimp" ;
OPRAND = DATA ;
}
if ( op2=="100" ) { # sethi | nop
rd = substr(INST,3,5);
disp22 = substr(INST,11);
if ( rd+0 + disp22+0 == 0 ) {
OPCODE = "nop" ;
} else {
OPCODE = "sethi" ;
rd = REG[rd];
t = disp22 "0000000000" ;
OPRAND = "%hi(0x" b2h(t) ")," rd;
}
}
if ( op2=="010" || op2=="110" ||op2=="111" ) { # branch
cond = substr(INST,4,4) ;
if ( op2=="010" ) OPCODE = Bicc[cond] ;
if ( op2=="110" ) OPCODE = FBfcc[cond] ;
if ( op2=="111" ) OPCODE = CBccc[cond] ;
a = substr(INST,3,1);
if ( a=="1" ) OPCODE = OPCODE ",a" ;
disp22 = substr(INST,11,22) ;
OPRAND = "+" getsimm22(disp22) ;
}
writeln( ADDR,DATA,OPCODE,OPRAND );
next ;
}

if ( op=="10" ) { # F3 - ALU
op3_30 = substr(INST,10,4) ;
op3_54 = substr(INST,8,2) ;
rd = REG[substr(INST,3,5)] ;
rs1 = REG[substr(INST,14,5)] ;
if ( substr(INST,19,1) == "1" ) {
rs2 = substr(INST,20,13) ;
rs2 = "0x" b2h( rs2 ) ;
} else {
rs2 = REG[substr(INST,28,5)] ;
}

if ( op3_54 == "00" || op3_54=="01" ) {
OPCODE = ALU01[op3_30] ;
if ( op3_54=="01" ) OPCODE = OPCODE "cc" ;
OPRAND = rs1 "," rs2 "," rd ;
}
if ( op3_54 == "10" ) {
OPCODE = ALU2[op3_30] ;
if ( OPCODE == "rd" ) {
if ( op3_30=="1001" ) rs1 = "%psr" ;
if ( op3_30=="1010" ) rs1 = "%wim" ;
if ( op3_30=="1011" ) rs1 = "%tbr" ;
if ( op3_30=="1000" ) {
if ( rd=="%g0" && rs1=="%o7" ) {
OPCODE = "stbar" ;
OPRAND = "" ;
}
rs1 = ASR[substr(INST,14,5)];
}
if ( OPCODE == "rd" ) {
OPRAND = rs1 "," rd ;
}
} else {
OPRAND = rs1 "," rs2 "," rd ;
}
}
if ( op3_54 == "11" ) {
OPCODE = ALU3[op3_30] ;
if ( OPCODE == "wr" ) {
if ( op3_30=="0001" ) rd = "%psr" ;
if ( op3_30=="0010" ) rd = "%wim" ;
if ( op3_30=="0011" ) rd = "%tbr" ;
if ( op3_30=="0000" ) {
rd = ASR[substr(INST,3,5)];
}
OPRAND = rs1 "," rs2 "," rd ;
}
if ( op3_30 == "1100" || op3_30 == "1101" ) {
OPRAND = rs1 "," rs2 "," rd ;
}
if ( op3_30 == "1000" ) { # jmpl
OPRAND = getaddr(INST) "," rd ;
}
if ( op3_30 == "1001" || op3_30 == "1011" ) {
OPRAND = getaddr(INST) ;
}
if ( op3_30 == "1010" ) { #Ticc
cond = substr(INST,4,4) ;
OPCODE = Ticc[cond] ;
OPRAND = geteaddr(INST) ;
}
# CP/FP
}
writeln( ADDR,DATA,OPCODE,OPRAND );
next ;
}

if ( op=="11" ) { # F3 - LD/ST
op3_30 = substr(INST,10,4) ;
op3_54 = substr(INST,8,2) ;
rd = REG[substr(INST,3,5)] ;

if ( op3_54=="00" || op3_54=="01" ) {
OPCODE = LD01[op3_30] ;
if ( op3_54=="01" ) {
OPCODE = OPCODE "a" ;
OPRAND = getaddrasi(INST) ;
} else {
OPRAND = getaddr(INST);
}
}
if ( substr(OPCODE,1,2)=="st" ) {
OPRAND = rd "," OPRAND ;
} else {
OPRAND = OPRAND "," rd ;
}

writeln( ADDR,DATA,OPCODE,OPRAND );
next ;
}
}
#
function writeln( ADDR,DATA,OPCODE,OPRAND ) {
if ( OPCODE =="" ) {
printf( "%8s : %8s\n",ADDR,DATA );
return ;
}
if ( OPRAND != "" ) {
printf( "%8s : %8s %-8s\t%s\n",ADDR,DATA,OPCODE,OPRAND );
} else {
printf( "%8s : %8s %-8s\n",ADDR,DATA,OPCODE );
}
}
#
function h2b( indata ,ans,l,i) {
ans = "" ;
l = length(indata);
for ( i=1 ; i<=l ; i++ ) {
ans = ans H2B[substr(indata,i,1)] ;
}
return ans ;
}
#
function b2h( indata ,ans,len,i) {
ans = "" ;
len = length(indata);
if ( len%4!=0 ) {
indata = substr("0000",1,4-(len%4)) indata ;
}
len = length(indata)/4 ;
for ( i=0; i<len; i++ ) {
ans = ans B2H[ substr(indata,1+i*4,4) ] ;
}
return ans ;
}
#
function geteaddr( inst, ans,rs1,rs2) {
rs1 = REG[substr(inst,14,5)] ;
if ( substr(inst,19,1)=="1" ) {
ans = rs1 "+" getsimm13(inst) ;
} else {
rs2 = REG[substr(inst,28,5)] ;
ans = rs1 "+" rs2 ;
}
return ans ;
}
#
function getaddr( inst ,a) {
a = "[" geteaddr(inst) "]" ;
return a ;
}
#
function getaddrasi( inst, ans,rs1,rs2,asi) {
rs1 = REG[substr(inst,14,5)] ;
rs2 = REG[substr(inst,28,5)] ;
asi = b2h(substr(inst,20,8)) ;
ans = "[" rs1 "+" rs2 "]0x" asi ;
return ans ;
}
#
function getsimm13( inst, simm13) {
simm13 = substr(inst,20,13);
if ( substr(simm13,1,1)=="1" ) {
simm13 = "1111111111111111111" simm13 ;
}
simm13 = "0x" b2h(simm13) ;
return simm13 ;
}
#
function getsimm22( simm22 ) {
if ( substr(simm22,1,1)=="1" ) {
simm22 = "11111111" simm22 "00" ;
} else {
simm22 = "00000000" simm22 "00" ;
}
simm22 = "0x" b2h(simm22) ;
return simm22 ;
}

</PRE>

テーマ

注目テーマ 一覧


月別リンク

ブログ気持玉

クリックして気持ちを伝えよう!
ログインしてクリックすれば、自分のブログへのリンクが付きます。
→ログインへ

トラックバック(0件)

タイトル (本文) ブログ名/日時

トラックバック用URL help


自分のブログにトラックバック記事作成(会員用) help

タイトル
本 文

コメント(0件)

内 容 ニックネーム/日時

コメントする help

ニックネーム
本 文




AWKによるSPARC V8逆アセンブラ 竹下世界塔の計算機よもやま話/BIGLOBEウェブリブログ
文字サイズ:       閉じる