Skip to content

Commit 8308495

Browse files
committed
CPU32
1 parent 881282d commit 8308495

File tree

3 files changed

+169
-1
lines changed

3 files changed

+169
-1
lines changed

Ghidra/Processors/68000/data/languages/68000.ldefs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,17 @@
6464
<external_name tool="IDA-PRO" name="colfire"/>
6565
<external_name tool="DWARF.register.mapping.file" name="68000.dwarf"/>
6666
</language>
67+
<language processor="68000"
68+
endian="big"
69+
size="32"
70+
variant="CPU32"
71+
version="1.1"
72+
slafile="CPU32.sla"
73+
processorspec="68000.pspec"
74+
manualindexfile="../manuals/68000.idx"
75+
id="68000:BE:32:CPU32">
76+
<description>Motorola 32-bit CPU32</description>
77+
<compiler name="default" spec="68000.cspec" id="default"/>
78+
<external_name tool="IDA-PRO" name="CPU32"/>
79+
</language>
6780
</language_definitions>

Ghidra/Processors/68000/data/languages/68000.sinc

Lines changed: 150 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ define register offset=0x600 size=4 [ EMACSR ACC0 ACC1 ACC2 ACC3 ACCext01 ACCext
5252
@define DAT_DIR_CTL_ADDR_MODES2 "(mode2=0 | mode2=2 | mode2=5 | mode2=6 | mode=7)" # Data direct and control addressing modes
5353
@define CTL_ADDR_MODES2 "(mode2=2 | mode2=5 | mode2=6 | mode2=7)" # Control addressing modes
5454

55+
@ifdef CPU32
56+
@define TBL_ADDR_MODES "(tbl_mode=2 | tbl_mode=4 | tbl_mode=5 | tbl_mode=6 | tbl_mode=7)" # Addressing modes for tblxx instructions
57+
@endif
58+
5559
# Floating-point condition code bits within FPSR
5660
@define N_FP "FPSR[27,1]"
5761
@define Z_FP "FPSR[26,1]"
@@ -149,8 +153,32 @@ define token extword (16)
149153
sfact = (9,10)
150154
accmsb = (4,4)
151155
@endif
156+
@ifdef CPU32 # Data register interpolation fields for TBL instructions.
157+
tbl_dr_size = (6,7)
158+
tbl_dr_round = (10,10)
159+
tbl_dr_sign = (11,11)
160+
tbl_dr_reg = (0,2)
161+
@endif
152162
;
153163

164+
@ifdef CPU32
165+
# The TBLxx instructions are two 16-bit tokens optionally followed by a disp16 token.
166+
# The presence of the disp16 token is governed by bits in the first token.
167+
# Sleigh's ... operator follows the second token, but needs the bits from the first.
168+
# To work around that, a single 32-bit token is used in place of the standard tokens.
169+
define token tbl_instrA(32)
170+
tbl_regan=(16,18)
171+
tbl_mode=(19,21)
172+
tbl_op37=(19,23)
173+
tbl_op67=(22,23)
174+
tbl_opbig=(24,31)
175+
tbl_size=(6,7)
176+
tbl_round=(10,10)
177+
tbl_sign=(11,11)
178+
tbl_regxdn=(12,14)
179+
;
180+
@endif
181+
154182
define token extword2 (16)
155183
regda2 = (12,15)
156184
ext2_911 = (9,11)
@@ -281,7 +309,12 @@ define context contextreg
281309
extGUARD = (14,14) # guard for saving off modes before starting instructions
282310
;
283311

312+
@ifdef CPU32
313+
attach variables [ regdn regxdn reg9dn regdr regdq regsdn regdu regdc regdu2 regdc2 tbl_regxdn tbl_dr_reg ] [ D0 D1 D2 D3 D4 D5 D6 D7 ];
314+
@else
284315
attach variables [ regdn regxdn reg9dn regdr regdq regsdn regdu regdc regdu2 regdc2 ] [ D0 D1 D2 D3 D4 D5 D6 D7 ];
316+
@endif
317+
285318
attach variables [ fldoffreg fldwdreg f_reg fcnt fkfacreg fldynreg ] [ D0 D1 D2 D3 D4 D5 D6 D7 ];
286319
attach variables [ regdnw regxdnw reg9dnw regsdnw regduw regdcw regdu2w regdc2w ] [ D0w D1w D2w D3w D4w D5w D6w D7w ];
287320
attach variables [ regdnb reg9dnb regsdnb regdub regdcb ] [ D0b D1b D2b D3b D4b D5b D6b D7b ];
@@ -526,11 +559,13 @@ Tyb: regdnb is rmbit=0 & regdnb { export regdnb; }
526559
Txb: -(reg9an) is rmbit=1 & reg9an { reg9an = reg9an-1; export *:1 reg9an; }
527560
Txb: reg9dnb is rmbit=0 & reg9dnb { export reg9dnb; }
528561

562+
@ifndef CPU32
529563
# Bit field parameters
530564
f_off: fldoffdat is flddo=0 & fldoffdat { export *[const]:4 fldoffdat; }
531565
f_off: fldoffreg is flddo=1 & fldoffreg { export fldoffreg; }
532566
f_wd: fldwddat is flddw=0 & fldwddat { export *[const]:4 fldwddat; }
533567
f_wd: fldwdreg is flddw=1 & fldwdreg { export fldwdreg; }
568+
@endif # CPU32
534569

535570
rreg: regxdn is da=0 & regxdn { export regxdn; }
536571
rreg: regxan is da=1 & regxan { export regxan; }
@@ -772,6 +807,7 @@ with : extGUARD=1 {
772807
:bclr.l reg9dn,regdn is op=0 & reg9dn & op68=6 & mode=0 & regdn { mask:4 = 1<<(reg9dn&31); ZF=(regdn&mask)==0; regdn=regdn&(~mask); }
773808
:bclr.l d8,regdn is opbig=8 & op67=2 & mode=0 & regdn; d8 { mask:4 = 1<<d8; ZF=(regdn&mask)==0; regdn=regdn&(~mask); }
774809

810+
@ifndef CPU32
775811
:bfchg e2l{f_off:f_wd} is opbig=0xea & op67=3 & $(DAT_DIR_CTL_ADDR_MODES); f_off & f_wd; e2l [ savmod2=savmod1; regtsan=regtfan; ] {
776812
logflags(); tmp:4 = e2l; getbitfield(tmp, f_off, f_wd); resbitflags(tmp, f_wd-1); mask:4 = 0; bfmask(mask, f_off, f_wd); e2l = (e2l & ~mask) | (~(e2l & mask) & mask);
777813
}
@@ -826,6 +862,7 @@ define pcodeop countLeadingZeros;
826862
:bftst e2l{f_off:f_wd} is opbig=0xe8 & op67=3 & $(DAT_DIR_CTL_ADDR_MODES); f_off & f_wd; e2l [ savmod2=savmod1; regtsan=regtfan; ] {
827863
logflags(); tmp:4 = e2l; getbitfield(tmp, f_off, f_wd); resbitflags(tmp, f_wd-1);
828864
}
865+
@endif # CPU32
829866

830867
:bkpt "#"op02 is opbig=0x48 & op67=1 & op5=0 & op34=1 & op02 unimpl
831868

@@ -847,6 +884,7 @@ define pcodeop countLeadingZeros;
847884
:btst.l reg9dn,regdn is op=0 & reg9dn & op68=4 & mode=0 & regdn { mask:4 = 1<<(reg9dn&31); ZF=(regdn&mask)==0; }
848885
:btst.l d8,regdn is opbig=8 & op67=0 & mode=0 & regdn; d8 { mask:4 = 1<<d8; ZF=(regdn&mask)==0; }
849886

887+
@ifndef CPU32
850888
:callm "#"^d8,e2l is opbig=6 & op67=3 & $(CTL_ADDR_MODES); d8; e2l [ savmod2=savmod1; regtsan=regtfan; ] unimpl
851889

852890
#TODO: should constrain CAS to ignore mode=7 & regan=4 (place CAS2 before CAS to avoid problem)
@@ -914,6 +952,7 @@ define pcodeop countLeadingZeros;
914952
ZF = 1;
915953
NF = 0;
916954
}
955+
@endif # CPU32
917956

918957
:chk.w eaw,reg9dnw is (op=4 & reg9dnw & op68=6 & $(DAT_ALTER_ADDR_MODES))... & eaw unimpl
919958
:chk.l eal,reg9dn is (op=4 & reg9dn & op68=4 & $(DAT_ALTER_ADDR_MODES))... & eal unimpl
@@ -969,11 +1008,16 @@ cachetype: "both" is op67=3 { export 3:4; }
9691008
subflags(tmp2,tmp1); local tmp =tmp2-tmp1; resflags(tmp); }
9701009
:cmpm.l (regan)+,(reg9an)+ is op=11 & reg9an & op8=1 & op67=2 & op5=0 & op34=1 & regan { local tmp1=*:4 regan; regan=regan+4; local tmp2=*:4 reg9an; reg9an=reg9an+4;
9711010
subflags(tmp2,tmp1); local tmp =tmp2-tmp1; resflags(tmp); }
1011+
1012+
@ifndef CPU32
9721013
# cpBcc # need to know specific copressors use copcc1
9731014
# cpDBcc # use copcc2
9741015
# cpGEN
1016+
# cpRESTORE
1017+
# cpSAVE
9751018
# cpScc # use copcc2
9761019
# cpTRAPcc # use copcc2
1020+
@endif # CPU32
9771021

9781022
:db^cc regdnw,addr16 is op=5 & cc & op67=3 & op5=0 & op34=1 & regdnw; addr16 { if (cc) goto inst_next; regdnw=regdnw-1; if (regdnw!=-1) goto addr16; }
9791023

@@ -1467,7 +1511,9 @@ macro negResFlags(result) {
14671511
:ori "#"^d8,"CCR" is opbig=0 & op37=7 & op02=4; d8 { packflags(SR); SR=SR|d8; unpackflags(SR); }
14681512
:ori "#"^d16,SR is SR; opbig=0x00 & d8base=0x7c; d16 { packflags(SR); SR=SR|d16; unpackflags(SR); }
14691513

1514+
@ifndef CPU32
14701515
:pack Tyb,Txb,"#"d16 is op=8 & op48=20 & Txb & Tyb; d16 unimpl
1516+
@endif # CPU32
14711517

14721518
:pea eaptr is (opbig=0x48 & op67=1 & $(CTL_ADDR_MODES))... & eaptr { SP = SP-4; *SP = eaptr; }
14731519

@@ -1605,8 +1651,10 @@ ptestLevel: "#"^mregn is mregn { export *[const]:1 mregn; }
16051651
:rtd "#"^d16 is opbig=0x4e & op37=14 & op02=4; d16 { PC = *SP; SP = SP + 4 + d16; return [PC]; }
16061652
:rte is d16=0x4e73 { tmp:4 = 0; return [tmp]; }
16071653

1654+
@ifndef CPU32
16081655
:rtm regdn is opbig=0x06 & op37=24 & regdn unimpl
16091656
:rtm regan is opbig=0x06 & op37=25 & regan unimpl
1657+
@endif # CPU32
16101658

16111659
:rtr is opbig=0x4e & op37=14 & op02=7 { SR = *SP; SP = SP+2; PC = *SP; SP = SP+4; unpackflags(SR); return [PC]; }
16121660

@@ -1617,7 +1665,16 @@ ptestLevel: "#"^mregn is mregn { export *[const]:1 mregn; }
16171665

16181666
:s^cc eab is (op=5 & cc & op67=3 & $(DAT_ALTER_ADDR_MODES))... & eab { eab = -cc; }
16191667

1620-
:stop "#"^d16 is opbig=0x4e & d8base=0x72; d16 unimpl
1668+
#TODO: implement STOP
1669+
:stop "#"^d16 is opbig=0x4e & d8base=0x72; d16 { SR = d16; }
1670+
1671+
@ifdef CPU32
1672+
#TODO: implement interrupt mask → EBI; STOP
1673+
:lpstop "#"^d16 is opbig=0xf8 & d8base=0x00; opbig=0x01 & d8base=0xC0; d16 { SR = d16; }
1674+
1675+
#TODO: implement: if (background mode enabled) then enter Background Mode else Format/Vector offset → –(SSP); PC → –(SSP); SR → –(SSP); (Vector) → PC
1676+
:bgnd is opbig=0x4A & d8base=0xFA { }
1677+
@endif # CPU32
16211678

16221679
:sub.b eab,reg9dnb is (op=9 & reg9dnb & op68=0)... & eab
16231680
{ subflags(reg9dnb, eab); reg9dnb = reg9dnb - eab; resflags(reg9dnb); }
@@ -1680,6 +1737,96 @@ ptestLevel: "#"^mregn is mregn { export *[const]:1 mregn; }
16801737
:tas eab is (opbig=0x4a & op67=3 & $(DAT_ALTER_ADDR_MODES))... & eab { logflags(); resflags(eab); eab = eab | 0x80; }
16811738
@endif # COLDFIRE
16821739

1740+
@ifdef CPU32
1741+
1742+
# TODO: tbl_mode=4 and tbl_mode=5 constructors
1743+
1744+
tbl_eal: (tbl_regan) is tbl_mode=2 & tbl_regan { export *:4 tbl_regan; }
1745+
# tbl_eal: -(tbl_regan) is tbl_mode=4 & tbl_regan { tbl_regan = tbl_regan - 4; export *:4 tbl_regan; }
1746+
# tbl_eal: (d16,tbl_regan) is tbl_mode=5 & tbl_regan; d16 { local tmp = tbl_regan + d16; export *:4 tmp; }
1747+
tbl_eal: (extw) is tbl_mode=6 & tbl_regan; extw [ regtfan = tbl_regan; pcmode = 0; ] { build extw; export *:4 extw; }
1748+
tbl_eal: (d16,PC) is PC & tbl_mode=7 & tbl_regan=2; d16 { tmp:4 = inst_start + 2 + d16; export *:4 tmp; }
1749+
tbl_eal: (extw) is tbl_mode=7 & tbl_regan=3; extw [ pcmode=1; ] { build extw; export *:4 extw; }
1750+
tbl_eal: (d16)".w" is tbl_mode=7 & tbl_regan=0; d16 { export *:4 d16; }
1751+
tbl_eal: (d32)".l" is tbl_mode=7 & tbl_regan=1; d32 { export *:4 d32; }
1752+
tbl_eal: "#"^d32 is tbl_mode=7 & tbl_regan=4; d32 { export *[const]:4 d32; }
1753+
1754+
tbl_eaw: (tbl_regan) is tbl_mode=2 & tbl_regan { export *:2 tbl_regan; }
1755+
# tbl_eaw: -(tbl_regan) is tbl_mode=4 & tbl_regan { tbl_regan = tbl_regan - 2; export *:2 tbl_regan; }
1756+
# tbl_eaw: (d16,tbl_regan) is tbl_mode=5 & tbl_regan; d16 { local tmp = tbl_regan + d16; export *:2 tmp; }
1757+
tbl_eaw: (extw) is tbl_mode=6 & tbl_regan; extw [ pcmode=0; regtfan=tbl_regan; ] { build extw; export *:2 extw; }
1758+
tbl_eaw: (d16,PC) is PC & tbl_mode=7 & tbl_regan=2; d16 { tmp:4 = inst_start + 2 + d16; export *:2 tmp; }
1759+
tbl_eaw: (extw) is tbl_mode=7 & tbl_regan=3; extw [ pcmode=1; ] { build extw; export *:2 extw; }
1760+
tbl_eaw: (d16)".w" is tbl_mode=7 & tbl_regan=0; d16 { export *:2 d16; }
1761+
tbl_eaw: (d32)".l" is tbl_mode=7 & tbl_regan=1; d32 { export *:2 d32; }
1762+
tbl_eaw: "#"^d16 is tbl_mode=7 & tbl_regan=4; d16 { export *[const]:2 d16; }
1763+
1764+
tbl_eab: (tbl_regan) is tbl_mode=2 & tbl_regan { export *:1 tbl_regan; }
1765+
# tbl_eab: -(tbl_regan) is tbl_mode=4 & tbl_regan { tbl_regan = tbl_regan - 1; export *:1 tbl_regan; }
1766+
# tbl_eab: (d16,tbl_regan) is tbl_mode=5 & tbl_regan; d16 { local tmp = tbl_regan + d16; export *:1 tmp; }
1767+
tbl_eab: (extw) is tbl_mode=6 & tbl_regan; extw [ pcmode=0; regtfan=tbl_regan; ] { build extw; export *:1 extw; }
1768+
tbl_eab: (d16,PC) is PC & tbl_mode=7 & tbl_regan=2; d16 { tmp:4 = inst_start + 2 + d16; export *:1 tmp; }
1769+
tbl_eab: (extw) is tbl_mode=7 & tbl_regan=3; extw [ pcmode=1; ] { build extw; export *:1 extw; }
1770+
tbl_eab: (d16)".w" is tbl_mode=7 & tbl_regan=0; d16 { export *:1 d16; }
1771+
tbl_eab: (d32)".l" is tbl_mode=7 & tbl_regan=1; d32 { export *:1 d32; }
1772+
tbl_eab: "#"^d8 is tbl_mode=7 & tbl_regan=4; d8 { export *[const]:1 d8; }
1773+
1774+
tblsign: "u" is tbl_sign=0 { }
1775+
tblsign: "s" is tbl_sign=1 { }
1776+
1777+
tbldrsign: "u" is tbl_dr_sign=0 { }
1778+
tbldrsign: "s" is tbl_dr_sign=1 { }
1779+
1780+
define pcodeop tableLookup;
1781+
1782+
# Rounded Table Lookup and Interpolate
1783+
1784+
:tbl^tblsign^".b" tbl_eab,tbl_regxdn is (tbl_opbig=0xF8 & tbl_op67=0 & $(TBL_ADDR_MODES) & tbl_size=0 & tblsign & tbl_round=0 & tbl_regxdn) ... & tbl_eab
1785+
{ tbl_regxdn = tableLookup(tbl_regxdn, tbl_eab); }
1786+
1787+
:tbl^tblsign^".w" tbl_eaw,tbl_regxdn is (tbl_opbig=0xF8 & tbl_op67=0 & $(TBL_ADDR_MODES) & tbl_size=1 & tblsign & tbl_round=0 & tbl_regxdn) ... & tbl_eaw
1788+
{ tbl_regxdn = tableLookup(tbl_regxdn, tbl_eaw); }
1789+
1790+
:tbl^tblsign^".l" tbl_eal,tbl_regxdn is (tbl_opbig=0xF8 & tbl_op67=0 & $(TBL_ADDR_MODES) & tbl_size=2 & tblsign & tbl_round=0 & tbl_regxdn) ... & tbl_eal
1791+
{ tbl_regxdn = tableLookup(tbl_regxdn, tbl_eal); }
1792+
1793+
# Unrounded Table Lookup and Interpolate
1794+
1795+
:tbl^tblsign^"n.b" tbl_eab,tbl_regxdn is (tbl_opbig=0xF8 & tbl_op67=0 & $(TBL_ADDR_MODES) & tbl_size=0 & tblsign & tbl_round=1 & tbl_regxdn) ... & tbl_eab
1796+
{ tbl_regxdn = tableLookup(tbl_regxdn, tbl_eab); }
1797+
1798+
:tbl^tblsign^"n.w" tbl_eaw,tbl_regxdn is (tbl_opbig=0xF8 & tbl_op67=0 & $(TBL_ADDR_MODES) & tbl_size=1 & tblsign & tbl_round=1 & tbl_regxdn) ... & tbl_eaw
1799+
{ tbl_regxdn = tableLookup(tbl_regxdn, tbl_eaw); }
1800+
1801+
:tbl^tblsign^"n.l" tbl_eal,tbl_regxdn is (tbl_opbig=0xF8 & tbl_op67=0 & $(TBL_ADDR_MODES) & tbl_size=2 & tblsign & tbl_round=1 & tbl_regxdn) ... & tbl_eal
1802+
{ tbl_regxdn = tableLookup(tbl_regxdn, tbl_eal); }
1803+
1804+
define pcodeop interpolate;
1805+
1806+
# Rounded Data Register Interpolate
1807+
1808+
:tbl^tbldrsign^".b" regdn:tbl_dr_reg,regxdn is opbig=0xF8 & op37=0 & mode=0 & regdn ; tbl_dr_size=0 & tbldrsign & tbl_dr_round=0 & tbl_dr_reg & regxdn
1809+
{ regxdn = interpolate(regdn, tbl_dr_reg); }
1810+
1811+
:tbl^tbldrsign^".w" regdn:tbl_dr_reg,regxdn is opbig=0xF8 & op37=0 & mode=0 & regdn ; tbl_dr_size=1 & tbldrsign & tbl_dr_round=0 & tbl_dr_reg & regxdn
1812+
{ regxdn = interpolate(regdn, tbl_dr_reg); }
1813+
1814+
:tbl^tbldrsign^".l" regdn:tbl_dr_reg,regxdn is opbig=0xF8 & op37=0 & mode=0 & regdn ; tbl_dr_size=2 & tbldrsign & tbl_dr_round=0 & tbl_dr_reg & regxdn
1815+
{ regxdn = interpolate(regdn, tbl_dr_reg); }
1816+
1817+
# Unrounded Data Register Interpolate
1818+
1819+
:tbl^tbldrsign^"n.b" regdn:tbl_dr_reg,regxdn is opbig=0xF8 & op37=0 & mode=0 & regdn ; tbl_dr_size=0 & tbldrsign & tbl_dr_round=1 & tbl_dr_reg & regxdn
1820+
{ regxdn = interpolate(regdn, tbl_dr_reg); }
1821+
1822+
:tbl^tbldrsign^"n.w" regdn:tbl_dr_reg,regxdn is opbig=0xF8 & op37=0 & mode=0 & regdn ; tbl_dr_size=1 & tbldrsign & tbl_dr_round=1 & tbl_dr_reg & regxdn
1823+
{ regxdn = interpolate(regdn, tbl_dr_reg); }
1824+
1825+
:tbl^tbldrsign^"n.l" regdn:tbl_dr_reg,regxdn is opbig=0xF8 & op37=0 & mode=0 & regdn ; tbl_dr_size=2 & tbldrsign & tbl_dr_round=1 & tbl_dr_reg & regxdn
1826+
{ regxdn = interpolate(regdn, tbl_dr_reg); }
1827+
1828+
@endif # CPU32
1829+
16831830
:trap "#"^op03 is opbig=0x4e & op67=1 & op45=0 & op03 { vector:1 = op03; __m68k_trap(vector); }
16841831
:trap^cc is op=5 & cc & op37=31 & op02=4 { if (!cc) goto inst_next; SP = SP - 4; *:4 SP = PC; vector:1 = 7; __m68k_trap(vector); }
16851832
:trap^cc^".w" "#"^d16 is op=5 & cc & op37=31 & op02=2; d16 { if (!cc) goto inst_next; SP = SP - 4; *:4 SP = PC; __m68k_trapv(); }
@@ -1696,7 +1843,9 @@ ptestLevel: "#"^mregn is mregn { export *[const]:1 mregn; }
16961843

16971844
:unlk regan is opbig=0x4e & op37=11 & regan { SP = regan; regan = *SP; SP = SP+4; }
16981845

1846+
@ifndef CPU32
16991847
:unpk Tyb,Txb,"#"^d16 is op=8 & Txb & op48=24 & Tyb; d16 unimpl
1848+
@endif # CPU32
17001849

17011850
# Floating Point Instructions
17021851

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Motorola's CPU32 processor
2+
3+
@define CPU32 ""
4+
@define MC68332 ""
5+
6+
@include "68000.sinc"

0 commit comments

Comments
 (0)