nawkで記述したSPARC V8の逆アセンブラです。gawkでも動作します。最初の行の#! /usr/bin/nawk -f を/usr/bin/awk -f や/usr/bin/gawk -f に書き換えてください。(きょうびawkとnawkの区別はなく、awkでいいみたい)
mbp13:~ takesita$ chmod +x craps.awk mbp13:~ takesita$ ./craps.awk 00000000 01000000 00000000 : 01000000 nop ^D mbp13:~ takesita$
#! /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 ;
}