pdp11のディスアセンブラ
日曜日に池袋バイナリ勉強会に行ってきました。
で、pdp11のエミュレータのようなものの手順書を貰ったのだけど、
Mountain LionにしたばっかりでMacPorts動かないんですけど、、、。
makeとか出来ないんですけど、、、。
って感じだったので、コマンド表みたいなものを元に
ディスアセンブラを作ってみてました。
せっかくなので、Scalaのパターンマッチで書けば奇麗に書けるんじゃないか?
ってことで、書いてみたのが以下のソースです。
テストを途中まで書いていて、時間切れになったので、途中までしかテスト出来てませんが、結構奇麗に書けたんじゃないかと思います。
実行方法は、scalac pdp11.scalaでコンパイルして、 scala pdp11.disasmでテストが動きます。
package pdp11 object disasm { // 4 6 6 = 16 bit case class C(h:Int, m:Int, l:Int) def apply(o:Any):String = { o match { case C(0, 000, 000) => "HALT" case C(0, 000, 001) => "WAIT" case C(0, 000, 002) => "RTI" case C(0, 000, 003) => "BPT" case C(0, 000, 004) => "IOT" case C(0, 000, 005) => "RESET" case C(0, 000, 006) => "RTT" case C(0, 000, 007) => "(unused)" case C(0, 001, dd) => "JMP " + dd case C(0, 002, r) if (r < 010) => "RTS r" + r case C(0, 002, r) if (010 <= r && r <= 027) => "(unused)" case C(0, 002, n) if (030 <= n && n <= 037) => "SPL " + (7 & n) case C(0, 002, 040) => "NOP" case C(0, 002, _) => "cond codes" case C(0, 003, dd) => "SWAB " + dd case C(0, 004, xxx) => "BR " + xxx case C(0, 010, xxx) => "BNE " + xxx case C(0, 014, xxx) => "BEQ " + xxx case C(0, 020, xxx) => "BGE " + xxx case C(0, 024, xxx) => "BLT " + xxx case C(0, 030, xxx) => "BGT " + xxx case C(0, 034, xxx) => "BLE " + xxx case C(0, r, dd) if ((070 & r) == 040) => "JSR " + (r & 7) + ", " + dd case C(0, 050, dd) => "CLR " + dd case C(0, 051, dd) => "COM " + dd case C(0, 052, dd) => "INC " + dd case C(0, 053, dd) => "DEC " + dd case C(0, 054, dd) => "NEG " + dd case C(0, 055, dd) => "ADC " + dd case C(0, 056, dd) => "SBC " + dd case C(0, 057, dd) => "TST " + dd case C(0, 060, dd) => "ROR " + dd case C(0, 061, dd) => "ROL " + dd case C(0, 062, dd) => "ASR " + dd case C(0, 063, dd) => "ASL " + dd case C(0, 064, nn) => "MARK " + nn case C(0, 065, ss) => "MFPI " + ss case C(0, 066, dd) => "MTPI " + dd case C(0, 067, dd) => "SXT " + dd case C(0, d1, d2) => "(unused)" case C(1, ss, dd) => "MOV " + ss + ", " + dd case C(2, ss, dd) => "CMP " + ss + ", " + dd case C(3, ss, dd) => "BIT " + ss + ", " + dd case C(4, ss, dd) => "BIC " + ss + ", " + dd case C(5, ss, dd) => "BIS " + ss + ", " + dd case C(6, ss, dd) => "ADD " + ss + ", " + dd case C(7, r, ss) if ((r & 070) == 000) => "MUL " + r + ", " + ss case C(7, r, ss) if ((r & 070) == 010) => "DIV " + (r & 7) + ", " + ss case C(7, r, ss) if ((r & 070) == 020) => "ASH " + (r & 7) + ", " + ss case C(7, r, ss) if ((r & 070) == 030) => "ASHC " + (r & 7) + ", " + ss case C(7, r, dd) if ((r & 070) == 040) => "XOR " + (r & 7) + ", " + dd case C(7, 050, r) if ((r & 070) == 000) => "FADD " + (r & 7) case C(7, 050, r) if ((r & 070) == 010) => "FSUB " + (r & 7) case C(7, 050, r) if ((r & 070) == 020) => "FMUL " + (r & 7) case C(7, 050, r) if ((r & 070) == 030) => "FDIV " + (r & 7) case C(7, r, nn) if ((r & 070) == 070) => "SOB " + r + "," + nn case C(7, r1, r2) => "(unused)" case C(8, 000, xxx) => "BPL " + xxx case C(8, 004, xxx) => "BMI " + xxx case C(8, 010, xxx) => "BHI " + xxx case C(8, 014, xxx) => "BLOS " + xxx case C(8, 020, xxx) => "BVC " + xxx case C(8, 024, xxx) => "BVS " + xxx case C(8, 030, xxx) => "BCC " + xxx case C(8, 034, xxx) => "BCS " + xxx case C(8, v1, v2) if(040 <= v1 && v1 <= 043) => "EMT" case C(8, v1, v2) if(044 <= v1 && v1 <= 047) => "TRAP" case C(8, 050, dd) => "CLRB " + dd case C(8, 051, dd) => "COMB " + dd case C(8, 052, dd) => "INCB " + dd case C(8, 053, dd) => "DECB " + dd case C(8, 054, dd) => "NEGB " + dd case C(8, 055, dd) => "ADCB " + dd case C(8, 056, dd) => "SBCB " + dd case C(8, 057, dd) => "TSTB " + dd case C(8, 060, dd) => "RORB " + dd case C(8, 061, dd) => "ROLB " + dd case C(8, 062, dd) => "ASRB " + dd case C(8, 063, dd) => "ASLB " + dd case C(8, 064, dd) => "(unused)" case C(8, 065, ss) => "MFPD " + ss case C(8, 066, dd) => "MTPD " + dd case C(8, d1, d2) => "(unused)" case C(9, ss, dd) => "MOVB " + ss + ", " + dd case C(10, ss, dd) => "CMPB " + ss + ", " + dd case C(11, ss, dd) => "BITB " + ss + ", " + dd case C(12, ss, dd) => "BICB " + ss + ", " + dd case C(13, ss, dd) => "BISB " + ss + ", " + dd case C(14, ss, dd) => "SUB " + ss + ", " + dd case C(15, d1, d2) => "floating point " + d1 + ", " + d2 } } var count = 0 var ok = 0 var ng = 0 def test(o:C, expected:String) { val v = disasm(o) if (v != expected) { println("error " + o + " expected is " + expected + " but found '" + v + "'.") ng += 1 } else { ok += 1 } count += 1 } def main(argv:Array[String]) { test(C(0,0,0),"HALT") test(C(0,0,1),"WAIT") test(C(0,0,2),"RTI") test(C(0,0,3),"BPT") test(C(0,0,4),"IOT") test(C(0,0,5),"RESET") test(C(0,0,6),"RTT") test(C(0,0,7),"(unused)") test(C(0,1,7),"JMP 7") test(C(0,2,1),"RTS r1") test(C(0,2,2),"RTS r2") test(C(0,2,3),"RTS r3") test(C(0,2,4),"RTS r4") test(C(0,2,8),"(unused)") test(C(0,2,010),"(unused)") test(C(0,2,027),"(unused)") test(C(0,2,030),"SPL 0") test(C(0,2,031),"SPL 1") test(C(0,2,037),"SPL 7") test(C(0,2,040),"NOP") test(C(0,2,041),"cond codes") test(C(0,2,077),"cond codes") test(C(0,3,000),"SWAB 0") test(C(0,3,077),"SWAB "+077) test(C(0,4,000),"BR 0") test(C(0,4,077),"BR "+077) test(C(0,010,000),"BNE 0") test(C(0,010,077),"BNE "+077) test(C(0,014,000),"BEQ 0") test(C(0,014,077),"BEQ "+077) test(C(0,020,000),"BGE 0") test(C(0,020,077),"BGE "+077) test(C(0,024,000),"BLT 0") test(C(0,024,077),"BLT "+077) test(C(0,030,000),"BGT 0") test(C(0,030,077),"BGT "+077) test(C(0,034,000),"BLE 0") test(C(0,034,077),"BLE "+077) test(C(0,040,000),"JSR 0, 0") test(C(0,047,077),"JSR 7, "+077) test(C(0,050,000),"CLR 0") test(C(0,050,077),"CLR "+077) test(C(0,051,000),"COM 0") test(C(0,051,077),"COM "+077) test(C(0,052,000),"INC 0") test(C(0,052,077),"INC "+077) test(C(0,053,000),"DEC 0") test(C(0,053,077),"DEC "+077) test(C(0,054,000),"NEG 0") test(C(0,054,077),"NEG "+077) test(C(0,055,000),"ADC 0") test(C(0,055,077),"ADC "+077) test(C(0,056,000),"SBC 0") test(C(0,056,077),"SBC "+077) test(C(0,057,000),"TST 0") test(C(0,057,077),"TST "+077) test(C(0,060,000),"ROR 0") test(C(0,060,077),"ROR "+077) test(C(0,061,000),"ROL 0") test(C(0,061,077),"ROL "+077) test(C(0,062,000),"ASR 0") test(C(0,062,077),"ASR "+077) test(C(0,063,000),"ASL 0") test(C(0,063,077),"ASL "+077) test(C(0,064,000),"MARK 0") test(C(0,064,077),"MARK "+077) test(C(0,065,000),"MFPI 0") test(C(0,065,077),"MFPI "+077) test(C(0,066,000),"MTPI 0") test(C(0,066,077),"MTPI "+077) test(C(0,067,000),"SXT 0") test(C(0,067,077),"SXT "+077) test(C(0,070,000),"(unused)") test(C(0,070,077),"(unused)") test(C(0,077,000),"(unused)") test(C(0,077,077),"(unused)") test(C(1,000,000),"MOV 0, 0") test(C(1,077,077),"MOV "+077+", "+077) test(C(2,000,000),"CMP 0, 0") test(C(2,077,077),"CMP "+077+", "+077) test(C(3,000,000),"BIT 0, 0") test(C(3,077,077),"BIT "+077+", "+077) test(C(4,000,000),"BIC 0, 0") test(C(4,077,077),"BIC "+077+", "+077) test(C(5,000,000),"BIS 0, 0") test(C(5,077,077),"BIS "+077+", "+077) test(C(6,000,000),"ADD 0, 0") test(C(6,077,077),"ADD "+077+", "+077) test(C(7,000,000),"MUL 0, 0") test(C(7,007,077),"MUL 7, "+077) test(C(7,010,000),"DIV 0, 0") test(C(7,017,077),"DIV 7, "+077) test(C(7,020,000),"ASH 0, 0") test(C(7,027,077),"ASH 7, "+077) test(C(7,030,000),"ASHC 0, 0") test(C(7,037,077),"ASHC 7, "+077) test(C(7,040,000),"XOR 0, 0") test(C(7,047,077),"XOR 7, "+077) test(C(7,050,000),"FADD 0") test(C(7,050,007),"FADD 7") test(C(7,050,010),"FSUB 0") test(C(7,050,017),"FSUB 7") test(C(7,050,020),"FMUL 0") test(C(7,050,027),"FMUL 7") test(C(7,050,030),"FDIV 0") test(C(7,050,037),"FDIV 7") test(C(7,050,040),"(unused)") test(C(7,050,077),"(unused)") test(C(7,067,000),"(unused)") test(C(7,067,077),"(unused)") test(C(010,000,000),"BPL 0") test(C(010,000,077),"BPL "+077) test(C(010,004,000),"BMI 0") test(C(010,004,077),"BMI "+077) test(C(010,010,000),"BHI 0") test(C(010,010,077),"BHI "+077) test(C(010,014,000),"BLOS 0") test(C(010,014,077),"BLOS "+077) test(C(010,020,000),"BVC 0") test(C(010,020,077),"BVC "+077) test(C(010,024,000),"BVS 0") test(C(010,024,077),"BVS "+077) test(C(010,030,000),"BCC 0") test(C(010,030,077),"BCC "+077) test(C(010,034,000),"BCS 0") test(C(010,034,077),"BCS "+077) test(C(010,040,000),"EMT") test(C(010,043,077),"EMT") test(C(010,044,000),"TRAP") test(C(010,047,077),"TRAP") test(C(010,050,000),"CLRB "+0) test(C(010,050,077),"CLRB "+077) test(C(010,051,000),"COMB "+0) test(C(010,051,077),"COMB "+077) test(C(010,052,000),"INCB "+0) test(C(010,052,077),"INCB "+077) test(C(010,053,000),"DECB "+0) test(C(010,053,077),"DECB "+077) test(C(010,054,000),"NEGB "+0) test(C(010,054,077),"NEGB "+077) test(C(010,055,000),"ADCB "+0) test(C(010,055,077),"ADCB "+077) test(C(010,056,000),"SBCB "+0) test(C(010,056,077),"SBCB "+077) test(C(010,057,000),"TSTB "+0) test(C(010,057,077),"TSTB "+077) test(C(010,060,000),"RORB "+0) test(C(010,060,077),"RORB "+077) test(C(010,061,000),"ROLB "+0) test(C(010,061,077),"ROLB "+077) test(C(010,062,000),"ASRB "+0) test(C(010,062,077),"ASRB "+077) test(C(010,063,000),"ASLB "+0) test(C(010,063,077),"ASLB "+077) // test(C(010,064,000),"MTPS "+0) // test(C(010,064,077),"MTPS "+077) test(C(010,064,000),"(unused)") test(C(010,064,077),"(unused)") test(C(010,065,000),"MFPD "+0) test(C(010,065,077),"MFPD "+077) test(C(010,066,000),"MTPD "+0) test(C(010,066,077),"MTPD "+077) // test(C(010,067,000),"MFPS "+0) // test(C(010,067,077),"MFPS "+077) test(C(010,067,000),"(unused)") test(C(010,067,077),"(unused)") test(C(011,000,000),"MOVB "+0+", "+0) test(C(011,077,077),"MOVB "+077+", "+077) test(C(012,000,000),"CMPB "+0+", "+0) test(C(012,077,077),"CMPB "+077+", "+077) test(C(013,000,000),"BITB "+0+", "+0) test(C(013,077,077),"BITB "+077+", "+077) test(C(014,000,000),"BICB "+0+", "+0) test(C(014,077,077),"BICB "+077+", "+077) test(C(015,000,000),"BISB "+0+", "+0) test(C(015,077,077),"BISB "+077+", "+077) test(C(016,000,000),"SUB "+0+", "+0) test(C(016,077,077),"SUB "+077+", "+077) /* test(C(017,000,000),"CFCC") test(C(017,000,001),"SETF") test(C(017,000,002),"SETI") test(C(017,000,011),"SETD") test(C(017,000,012),"SETL") test(C(017,001,000),"LDFPS "+0) test(C(017,001,077),"LDFPS "+077) test(C(017,002,000),"STFPS "+0) test(C(017,002,077),"STFPS "+077) test(C(017,003,000),"STST "+0) test(C(017,003,077),"STST "+077) test(C(017,004,000),"CLRF "+0) test(C(017,004,077),"CLRF "+077) test(C(017,005,000),"TSTF "+0) test(C(017,005,077),"TSTF "+077) test(C(017,006,000),"ABSF "+0) test(C(017,006,077),"ABSF "+077) test(C(017,007,000),"NEGF "+0) test(C(017,007,077),"NEGF "+077) test(C(017,010,000),"MULF "+0+", "+000) test(C(017,013,077),"MULF "+3+", "+077) test(C(017,014,000),"MODF "+0+", "+000) test(C(017,017,077),"MODF "+3+", "+077) test(C(017,020,000),"ADDF "+0+", "+000) test(C(017,023,077),"ADDF "+3+", "+077) test(C(017,024,000),"LDF "+0+", "+000) test(C(017,027,077),"LDF "+3+", "+077) test(C(017,030,000),"SUBF "+0+", "+000) test(C(017,033,077),"SUBF "+3+", "+077) test(C(017,034,000),"CMPF "+0+", "+000) test(C(017,037,077),"CMPF "+3+", "+077) test(C(017,040,000),"STF "+0+", "+000) test(C(017,043,077),"STF "+3+", "+077) test(C(017,044,000),"DIF "+0+", "+000) test(C(017,047,077),"DIF "+3+", "+077) test(C(017,050,000),"STEXP "+0+", "+000) test(C(017,053,077),"STEXP "+3+", "+077) test(C(017,054,000),"STCFI "+0+", "+000) test(C(017,057,077),"STCFI "+3+", "+077) test(C(017,060,000),"STCFD "+0+", "+000) test(C(017,063,077),"STCFD "+3+", "+077) test(C(017,064,000),"LDEXP "+0+", "+000) test(C(017,067,077),"LDEXP "+3+", "+077) test(C(017,070,000),"LDCIF "+0+", "+000) test(C(017,073,077),"LDCIF "+3+", "+077) test(C(017,074,000),"LDCDF "+0+", "+000) test(C(017,077,077),"LDCDF "+3+", "+077) */ test(C(017,000,000),"floating point "+0+", " + 000) test(C(017,000,001),"floating point "+0+", " + 001) test(C(017,000,002),"floating point "+0+", " + 002) test(C(017,000,011),"floating point "+0+", " + 011) test(C(017,000,012),"floating point "+0+", " + 012) test(C(017,001,000),"floating point "+1+", "+0) test(C(017,001,077),"floating point "+1+", "+077) test(C(017,002,000),"floating point "+2+", "+0) test(C(017,002,077),"floating point "+2+", "+077) test(C(017,003,000),"floating point "+3+", "+0) test(C(017,003,077),"floating point "+3+", "+077) test(C(017,004,000),"floating point "+4+", "+0) test(C(017,004,077),"floating point "+4+", "+077) test(C(017,005,000),"floating point "+5+", "+0) test(C(017,005,077),"floating point "+5+", "+077) test(C(017,006,000),"floating point "+6+", "+0) test(C(017,006,077),"floating point "+6+", "+077) test(C(017,007,000),"floating point "+7+", "+0) test(C(017,007,077),"floating point "+7+", "+077) test(C(017,077,077),"floating point "+077+", "+077) println("test " + count + " ok " + ok + " ng " + ng) } }