diff --git a/Ghidra/Processors/8048/Module.manifest b/Ghidra/Processors/8048/Module.manifest new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Ghidra/Processors/8048/build.gradle b/Ghidra/Processors/8048/build.gradle new file mode 100644 index 0000000000..7820c04b5f --- /dev/null +++ b/Ghidra/Processors/8048/build.gradle @@ -0,0 +1,5 @@ +apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" +apply from: "$rootProject.projectDir/gradle/processorProject.gradle" +apply plugin: 'eclipse' + +eclipse.project.name = 'Processors 8048' diff --git a/Ghidra/Processors/8048/certification.manifest b/Ghidra/Processors/8048/certification.manifest new file mode 100644 index 0000000000..66aeeec38b --- /dev/null +++ b/Ghidra/Processors/8048/certification.manifest @@ -0,0 +1,8 @@ +##VERSION: 2.0 +Module.manifest||GHIDRA||||END| +build.gradle||GHIDRA||||END| +data/languages/8048.cspec||GHIDRA||||END| +data/languages/8048.ldefs||GHIDRA||||END| +data/languages/8048.pspec||GHIDRA||||END| +data/languages/8048.slaspec||GHIDRA||||END| +data/manuals/8048.idx||GHIDRA||||END| diff --git a/Ghidra/Processors/8048/data/languages/8048.cspec b/Ghidra/Processors/8048/data/languages/8048.cspec new file mode 100644 index 0000000000..531976acdb --- /dev/null +++ b/Ghidra/Processors/8048/data/languages/8048.cspec @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Ghidra/Processors/8048/data/languages/8048.ldefs b/Ghidra/Processors/8048/data/languages/8048.ldefs new file mode 100644 index 0000000000..6533853f05 --- /dev/null +++ b/Ghidra/Processors/8048/data/languages/8048.ldefs @@ -0,0 +1,18 @@ + + + + + + 8048 Microcontroller Family + + + + diff --git a/Ghidra/Processors/8048/data/languages/8048.pspec b/Ghidra/Processors/8048/data/languages/8048.pspec new file mode 100644 index 0000000000..edaef333cf --- /dev/null +++ b/Ghidra/Processors/8048/data/languages/8048.pspec @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Ghidra/Processors/8048/data/languages/8048.slaspec b/Ghidra/Processors/8048/data/languages/8048.slaspec new file mode 100644 index 0000000000..e75f207db2 --- /dev/null +++ b/Ghidra/Processors/8048/data/languages/8048.slaspec @@ -0,0 +1,349 @@ +# sleigh specification file for Intel 8048 + + +# Do not take BS into account when decompiling +@define SINGLE_REGISTER_BANK + +# Treat R0-R7 as not memory mapped (implies SINGLE_REGISTER_BANK) +@define INTERNAL_REGISTERS + + +@ifdef INTERNAL_REGISTERS +@define RegType variables +@define SINGLE_REGISTER_BANK +@else +@define RegType names +@endif + + +define endian=little; +define alignment=1; + +define space CODE type=ram_space size=2 default; +define space INTMEM type=ram_space size=1; +define space EXTMEM type=ram_space size=1; +define space PORT type=ram_space size=1; + +define space register type=register_space size=1; + +define register offset=0x00 size=1 [ A SP ]; +@ifdef INTERNAL_REGISTERS +define register offset=0x10 size=1 [ R0 R1 R2 R3 R4 R5 R6 R7 ]; +@endif +define register offset=0x20 size=2 [ PC ]; +define register offset=0x30 size=1 [ C AC F0 F1 BS DFB ]; # single bit + + +################################################################ +# Tokens +################################################################ + +define token opbyte (8) + opfull = (0,7) + oplo = (0,3) + ophi = (4,7) + rn = (0,2) dec + rnfill = (3,3) + ri = (0,0) dec + rifill = (1,3) + opaddr = (5,7) + addrfill = (4,4) + pp = (0,1) dec + xpp = (0,1) dec + ppfill = (2,3) + abit = (5,7) dec + abfill = (4,4) + dfb = (4,4) + bs = (4,4) +; + +define token aopword (16) + aoplo = (0,3) + aaddrfill = (4,4) + aopaddr = (5,7) + adata = (8,15) +; + +define token ImmedByte (8) data=(0,7); +define token AddrOne (8) addr8=(0,7); + +attach $(RegType) rn [ R0 R1 R2 R3 R4 R5 R6 R7 ]; +attach $(RegType) ri [ R0 R1 ]; +attach names dfb [ MB0 MB1 ]; +attach names bs [ RB0 RB1 ]; +attach names pp [ BUS P1 P2 _ ]; +attach names xpp [ P4 P5 P6 P7 ]; + + +################################################################ +# Psuedo Instructions +################################################################ + +define pcodeop nop; +define pcodeop enableExtInt; +define pcodeop enableTCntInt; +define pcodeop enableClockOutput; +define pcodeop disableExtInt; +define pcodeop disableTCntInt; +define pcodeop startTimer; +define pcodeop startEventCounter; +define pcodeop stopTimerAndEventCounter; +define pcodeop setTmr; +define pcodeop getTmr; +define pcodeop getT0; +define pcodeop getT1; +define pcodeop getTF; +define pcodeop getExtInt; +define pcodeop readPort; +define pcodeop writePort; +define pcodeop setBank; + + +################################################################ +# Macros +################################################################ + +macro getPSW(reg) { + local tmp:1 = 0; + tmp[7,1] = C; + tmp[6,1] = AC; + tmp[5,1] = F0; + tmp[4,1] = BS; + tmp[3,1] = 1; + tmp[0,3] = (SP>>1)&7; + reg = tmp; +} + +macro setPSW(reg) { + local tmp:1 = reg; + C = tmp[7,1]; + AC = tmp[6,1]; + F0 = tmp[5,1]; + BS = tmp[4,1]; + SP = 2*tmp[0,3] + 8; +} + +macro savePSWtoPC(pc) { + pc[15,1] = C; + pc[14,1] = AC; + pc[13,1] = F0; + pc[12,1] = BS; +} + +macro restorePSWfromPC(pc) { + C = pc[15,1]; + AC = pc[14,1]; + F0 = pc[13,1]; + BS = pc[12,1]; +} + +macro push(v) { + *[INTMEM]:2 SP = v; + SP = SP + 2; +} + +macro pop(v) { + SP = SP - 2; + v = *[INTMEM]:2 SP; +} + +macro popPC(pc) { + pop(pc); + pc = pc & 0xfff; +} + +macro popPCandPSW(pc) { + pop(pc); + restorePSWfromPC(pc); + pc = pc & 0xfff; +} + +macro funcall(target) { + ret:2 = inst_next; + savePSWtoPC(ret); + push(ret); + call target; +} + +macro add(dest, op1, op2, cy_in) { + local result:1 = op1 + op2 + cy_in; + local half_result:1 = (op1 & 0xf) + (op2 & 0xf) + cy_in; + C = carry(op1, op2) || carry(op1+op2, cy_in); + AC = (half_result > 0xf); + dest = result; +} + +macro da(reg) { + local tmp:1 = reg; + local low:1 = 6*(AC || (tmp&0xf) > 9); + local cy1:1 = C || carry(tmp, low); + tmp = tmp + low; + local high:1 = 0x60*(cy1 || tmp > 0x99); + C = C || carry(tmp, high); + tmp = tmp + high; + reg = tmp; +} + +macro rotc(cy, acc) { + local tmp:1 = cy; + A = acc; + C = tmp; +} + +macro xch(node1, node2) { + local tmp:1 = node1; + node1 = node2; + node2 = tmp; +} + +@ifdef SINGLE_REGISTER_BANK +macro regbank(r) { } +macro setbank(bs) { + BS = bs; + local tmp:1 = bs; + setBank(tmp); +} +@else +macro regbank(r) { + r = r + BS*0x18; +} +macro setbank(bs) { + BS = bs; +} +@endif + + +################################################################ + +Psw: "PSW" is epsilon { } +ExtInt: "I" is epsilon { } +TCntInt: "TCNTI" is epsilon { } +Clk: "CLK" is epsilon { } +Tmr: "T" is epsilon { } +Cnt: "CNT" is epsilon { } +TmrCnt: "TCNT" is epsilon { } + +Rn: rn is rn & rnfill=1 { +@ifdef INTERNAL_REGISTERS + export rn; +@else + local ptr:1 = rn; regbank(ptr); export *[INTMEM]:1 ptr; +@endif +} +Rind: @ri is ri & rifill=0 { +@ifdef INTERNAL_REGISTERS + export ri; +@else + local ptr:1 = ri; regbank(ptr); export *[INTMEM]:1 ptr; +@endif +} +Ri: Rind is Rind { export *[INTMEM]:1 Rind; } +RiX: Rind is Rind { export *[EXTMEM]:1 Rind; } +PData: @A is A { + local addr:2 = inst_next; addr[0,7] = A; export *[CODE]:1 addr; } +P3Data: @A is A { + local addr:2 = 0x300; addr[0,7] = A; export *[CODE]:1 addr; } +AddrInd: PData is PData { + local addr:2 = inst_next; addr[0,7] = PData; export *[CODE]:1 addr; } +Ab: abit is abit { local bit:1 = (A>>abit)&1; export bit; } +Data: #data is data { export *[const]:1 data; } +Imm: Data is oplo=3; Data { export Data; } +Addr8: addr is addr8 [ addr = (inst_next $and 0xf00)+addr8; ] { + export *[CODE]:1 addr; } +Addr12: addr is aopaddr & adata [ addr = (DFB*2048)+(aopaddr*256)+adata; ] { + export *[CODE]:1 addr; } +Bus: "BUS" is epsilon { local tmp:1 = 0; export *[PORT]:1 tmp; } +Pp: pp is pp & ppfill=2 { export *[PORT]:1 pp; } +Xpp: xpp is xpp & ppfill=3 { local tmp:1 = xpp+4; export *[PORT]:1 tmp; } + +Cc: "C" is ophi=15 { export C; } +Cc: "F0" is ophi=11 { export F0; } +Cc: "F1" is ophi=7 { export F1; } +Cc: "NC" is ophi=14 { tmp:1 = !C; export tmp; } +Cc: "NI" is ophi=8 { tmp:1 = getExtInt(); tmp = !tmp; export tmp; } +Cc: "NT0" is ophi=2 { tmp:1 = getT0(); tmp = !tmp; export tmp; } +Cc: "NT1" is ophi=4 { tmp:1 = getT1(); tmp = !tmp; export tmp; } +Cc: "NZ" is ophi=9 { tmp:1 = A!=0; export tmp; } +Cc: "TF" is ophi=1 { tmp:1 = getTF(); export tmp; } +Cc: "T0" is ophi=3 { tmp:1 = getT0(); export tmp; } +Cc: "T1" is ophi=5 { tmp:1 = getT1(); export tmp; } +Cc: "Z" is ophi=12 { tmp:1 = A==0; export tmp; } + + +# Conventience tables for opcodes taking both Rn and Ri (and Imm) +Rni: Rn is Rn { export Rn; } +Rni: Ri is Ri { export Ri; } +RniI: Rni is Rni { export Rni; } +RniI: Imm is Imm { export Imm; } + + +# These are not decoded correctly if placed alphabetically... +:JB^Ab Addr8 is oplo=2 & abfill=1 & Ab; Addr8 { if(Ab) goto Addr8; } +:J^Cc Addr8 is oplo=6 & Cc; Addr8 { if(Cc) goto Addr8; } +:CALL Addr12 is aaddrfill=1 & aoplo=4 & Addr12 { funcall(Addr12); } +:JMP Addr12 is aaddrfill=0 & aoplo=4 & Addr12 { goto Addr12; } +:DJNZ Rn,Addr8 is ophi=14 & Rn; Addr8 { Rn = Rn - 1; if(Rn != 0) goto Addr8; } + +:ADD A,Rni is ophi=6 & A & Rni { add(A,A,Rni,0); } +:ADD A,Imm is (ophi=0 & A)... & Imm { add(A,A,Imm,0); } +:ADDC A,Rni is ophi=7 & A & Rni { add(A,A,Rni,C); } +:ADDC A,Imm is (ophi=1 & A)... & Imm { add(A,A,Imm,C); } +:ANL A,RniI is (ophi=5 & A)... & RniI { A = A & RniI; } +:ANL Pp,Data is ophi=9 & Pp; Data { Pp = Pp & Data; } +:ANLD Xpp,A is ophi=9 & Xpp & A { Xpp = Xpp & (A & 0xf); } +:CLR A is ophi=2 & oplo=7 & A { A = 0; } +:CLR C is ophi=9 & oplo=7 & C { C = 0; } +:CLR F0 is ophi=8 & oplo=5 & F0 { F0 = 0; } +:CLR F1 is ophi=10 & oplo=5 & F1 { F1 = 0; } +:CPL A is ophi=3 & oplo=7 & A { A = ~A; } +:CPL C is ophi=10 & oplo=7 & C { C = !C; } +:CPL F0 is ophi=9 & oplo=5 & F0 { F0 = !F0; } +:CPL F1 is ophi=11 & oplo=5 & F1 { F1 = !F1; } +:DA A is ophi=5 & oplo=7 & A { da(A); } +:DEC A is ophi=0 & oplo=7 & A { A = A - 1; } +:DEC Rn is ophi=12 & Rn { Rn = Rn - 1; } +:DIS ExtInt is ophi=1 & oplo=5 & ExtInt { disableExtInt(); } +:DIS TCntInt is ophi=3 & oplo=5 & TCntInt { disableTCntInt(); } +:EN ExtInt is ophi=0 & oplo=5 & ExtInt { enableExtInt(); } +:EN TCntInt is ophi=2 & oplo=5 & TCntInt { enableTCntInt(); } +:ENT0 Clk is ophi=7 & oplo=5 & Clk { enableClockOutput(); } +:IN A,Pp is ophi=0 & pp!=0 & A & Pp { A = Pp; } +:INC A is ophi=1 & oplo=7 & A { A = A + 1; } +:INC Rni is ophi=1 & Rni { Rni = Rni + 1; } +:INS A,Bus is ophi=0 & oplo=8 & A & Bus { A = Bus; } +:JMPP AddrInd is ophi=11 & oplo=3 & AddrInd { goto AddrInd; } +:MOV A,Imm is (ophi=2 & A)... & Imm { A = Imm; } +:MOV A,Psw is ophi=12 & oplo=7 & A & Psw { getPSW(A); } +:MOV A,Rni is ophi=15 & A & Rni { A = Rni; } +:MOV A,Tmr is ophi=4 & oplo=2 & A & Tmr { A = getTmr(); } +:MOV Psw,A is ophi=13 & oplo=7 & Psw & A { setPSW(A); } +:MOV Rni,A is ophi=10 & Rni & A { Rni = A; } +:MOV Rni,Data is ophi=11 & Rni; Data { Rni = Data; } +:MOV Tmr,A is ophi=6 & oplo=2 & Tmr & A { setTmr(A); } +:MOVD A,Xpp is ophi=0 & Xpp & A { A = (Xpp & 0xf); } +:MOVD Xpp,A is ophi=3 & Xpp & A { Xpp = (A & 0xf); } +:MOVP A,PData is ophi=10 & oplo=3 & A & PData { A = PData; } +:MOVP3 A,P3Data is ophi=14 & oplo=3 & A & P3Data { A = P3Data; } +:MOVX A,RiX is ophi=8 & A & RiX { A = RiX; } +:MOVX RiX,A is ophi=9 & RiX & A { RiX = A; } +:NOP is ophi=0 & oplo=0 { nop(); } +:ORL A,RniI is (ophi=4 & A)... & RniI { A = A | RniI; } +:ORL Pp,Data is ophi=8 & Pp; Data { Pp = Pp | Data; } +:ORLD Xpp,A is ophi=8 & Xpp & A { Xpp = Xpp | (A & 0xf); } +:OUTL Bus,A is ophi=0 & oplo=2 & Bus & A { Bus = A; } +:OUTL Pp,A is ophi=3 & pp!=0 & Pp & A { Pp = A; } +:RET is ophi=8 & oplo=3 { pc:2 = 0; popPC(pc); return[pc]; } +:RETR is ophi=9 & oplo=3 { pc:2 = 0; popPCandPSW(pc); return[pc]; } +:RL A is ophi=14 & oplo=7 & A { A = (A<<1) | (A>>7); } +:RLC A is ophi=15 & oplo=7 & A { rotc((A&0x80)>>7, (A<<1)|C); } +:RR A is ophi=7 & oplo=7 & A { A = (A>>1) | (A<<7); } +:RRC A is ophi=6 & oplo=7 & A { rotc(A&1, (A>>1)|(C<<7)); } +:SEL dfb is (ophi=14 | ophi=15) & oplo=5 & dfb { DFB = dfb; } +:SEL bs is (ophi=12 | ophi=13) & oplo=5 & bs { setbank(bs); } +:STOP TmrCnt is ophi=6 & oplo=5 & TmrCnt { stopTimerAndEventCounter(); } +:STRT Cnt is ophi=4 & oplo=5 & Cnt { startEventCounter(); } +:STRT Tmr is ophi=5 & oplo=5 & Tmr { startTimer(); } +:SWAP A is ophi=4 & oplo=7 & A { A = (A<<4)|(A>>4); } +:XCH A,Rni is ophi=2 & A & Rni { xch(A, Rni); } +:XCHD A,Ri is ophi=3 & A & Ri { xch(A[0,4], Ri[0,4]); } +:XRL A,RniI is (ophi=13 & A)... & RniI { A = A ^ RniI; } diff --git a/Ghidra/Processors/8048/data/manuals/8048.idx b/Ghidra/Processors/8048/data/manuals/8048.idx new file mode 100644 index 0000000000..e2acc7d1e1 --- /dev/null +++ b/Ghidra/Processors/8048/data/manuals/8048.idx @@ -0,0 +1,54 @@ +@8048.pdf [MCS-48 Microcomputer User's Manual, February 1978] +ADD, 63 +ADDC, 63 +ANL, 64 +ANLD, 65 +CALL, 66 +CLR, 67 +CPL, 67 +DA, 68 +DEC, 68 +DIS, 69 +DJNZ, 69 +EN, 70 +ENT0, 70 +IN, 70 +INC, 71 +INS, 72 +JB, 72 +JC, 72 +JF0, 72 +JF1, 73 +JMP, 73 +JMPP, 73 +JNC, 73 +JNI, 74 +JNT0, 74 +JNT1, 74 +JNZ, 74 +JTF, 75 +JT0, 75 +JT1, 75 +JZ, 75 +MOV, 76 +MOVD, 79 +MOVP, 79 +MOVP3, 80 +MOVX, 80 +NOP, 81 +ORL, 81 +ORLD, 82 +OUTL, 82 +RET, 83 +RETR, 83 +RL, 83 +RLC, 84 +RR, 84 +RRC, 84 +SEL, 85 +STOP, 86 +STRT, 87 +SWAP, 87 +XCH, 88 +XCHD, 88 +XRL, 89