Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions Ghidra/Extensions/SleighDevTools/pcodetest/pcode_defs.py
Original file line number Diff line number Diff line change
Expand Up @@ -842,3 +842,19 @@
'language_id': 'Xtensa:BE:32:default',
'ccflags': '-L %(toolchain_dir)s/lib/gcc/xtensa-elf/%(gcc_version)s',
})


PCodeTest({
'name': 'CPU32',
'build_all': 1,
'build_exe': 0,
'has_float': 0,
'has_double': 0,
'toolchain': 'm68k/m68k-linux-gnu',
'exec_prefix': 'm68k-linux-gnu-',
'gcc_version': '14',
'ccflags': '-mcpu=cpu32 -nostdlib -static',
'cclibs': '-lgcc',
'gcc_libdir': '/usr/lib/gcc-cross/m68k-linux-gnu/14',
'language_id': '68000:BE:32:CPU32',
})
1 change: 1 addition & 0 deletions Ghidra/Processors/68000/certification.manifest
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ data/languages/68020.slaspec||GHIDRA||reviewed||END|
data/languages/68030.slaspec||GHIDRA||||END|
data/languages/68040.slaspec||GHIDRA||||END|
data/languages/coldfire.slaspec||GHIDRA||||END|
data/languages/CPU32.slaspec||GHIDRA||||END|
data/manuals/68000.idx||GHIDRA||||END|
data/patterns/68000_patterns.xml||GHIDRA||||END|
data/patterns/patternconstraints.xml||GHIDRA||||END|
13 changes: 13 additions & 0 deletions Ghidra/Processors/68000/data/languages/68000.ldefs
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,17 @@
<external_name tool="qemu" name="qemu-m68k"/>
<external_name tool="qemu_system" name="qemu-system-m68k"/>
</language>
<language processor="68000"
endian="big"
size="32"
variant="CPU32"
version="1.1"
slafile="CPU32.sla"
processorspec="68000.pspec"
manualindexfile="../manuals/68000.idx"
id="68000:BE:32:CPU32">
<description>Motorola 32-bit CPU32 (MC68340)</description>
<compiler name="default" spec="68000.cspec" id="default"/>
<external_name tool="DWARF.register.mapping.file" name="68000.dwarf"/>
</language>
</language_definitions>
141 changes: 139 additions & 2 deletions Ghidra/Processors/68000/data/languages/68000.sinc
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ define register offset=0x746 size=10 [ FP7 ];
@define DAT_DIR_CTL_ADDR_MODES2 "(mode2=0 | mode2=2 | mode2=5 | mode2=6 | mode=7)" # Data direct and control addressing modes
@define CTL_ADDR_MODES2 "(mode2=2 | mode2=5 | mode2=6 | mode2=7)" # Control addressing modes

@ifdef CPU32
@define TBL_ADDR_MODES "(tbl_mode=2 | tbl_mode=4 | tbl_mode=5 | tbl_mode=6 | tbl_mode=7)"
@endif

# Floating-point condition code bits within FPSR
@define N_FP "FPSR[27,1]"
@define Z_FP "FPSR[26,1]"
Expand Down Expand Up @@ -173,9 +177,29 @@ define token extword (16)
reg12x = (12,15)
reg12xwu = (12,15)
reg12xwl = (12,15)
@endif
@endif
@ifdef CPU32
tbl_dr_size = (6,7)
tbl_dr_round = (10,10)
tbl_dr_sign = (11,11)
tbl_dr_reg = (0,2)
@endif
;

@ifdef CPU32
define token tbl_instrA(32)
tbl_regan=(16,18)
tbl_mode=(19,21)
tbl_op37=(19,23)
tbl_op67=(22,23)
tbl_opbig=(24,31)
tbl_size=(6,7)
tbl_round=(10,10)
tbl_sign=(11,11)
tbl_regxdn=(12,14)
;
@endif

define token extword2 (16)
regda2 = (12,15)
ext2_911 = (9,11)
Expand Down Expand Up @@ -307,12 +331,20 @@ define context contextreg
extGUARD = (14,14) # guard for saving off modes before starting instructions
;

@ifdef CPU32
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 ];
@else
attach variables [ regdn regxdn reg9dn regdr regdq regsdn regdu regdc regdu2 regdc2 ] [ D0 D1 D2 D3 D4 D5 D6 D7 ];
@endif
attach variables [ fldoffreg fldwdreg f_reg fcnt fkfacreg fldynreg ] [ D0 D1 D2 D3 D4 D5 D6 D7 ];
attach variables [ regdnw regxdnw reg9dnw regsdnw regduw regdcw regdu2w regdc2w ] [ D0w D1w D2w D3w D4w D5w D6w D7w ];
attach variables [ regdnb reg9dnb regsdnb regdub regdcb ] [ D0b D1b D2b D3b D4b D5b D6b D7b ];
attach variables [ regda regda2 ] [ D0 D1 D2 D3 D4 D5 D6 D7 A0 A1 A2 A3 A4 A5 A6 SP ];
@ifdef CPU32
attach variables [ regan regxan reg9an regfan regsan aregx tbl_regan ] [ A0 A1 A2 A3 A4 A5 A6 SP ];
@else
attach variables [ regan regxan reg9an regfan regsan aregx ] [ A0 A1 A2 A3 A4 A5 A6 SP ];
@endif
attach variables [ reganw regxanw regsanw ] [ A0w A1w A2w A3w A4w A5w A6w A7w ];
attach variables [ reganb regsanb ] [ A0b A1b A2b A3b A4b A5b A6b A7b ];

Expand Down Expand Up @@ -1051,6 +1083,7 @@ with : extGUARD=1 {
local source = regdn; mask:4 = 1 << (const8 & 31); ZF = (source & mask) == 0; regdn = source & (~mask);
}

@ifndef CPU32
bfOffWd: {f_off:f_wd} is f_off & f_wd { }
:bfchg e2l^bfOffWd is opbig=0xea & op67=3 & $(DAT_DIR_CTL_ADDR_MODES); bfOffWd & f_off & f_wd; e2l [ savmod2=savmod1; regtsan=regtfan; ] {
logflags();
Expand Down Expand Up @@ -1144,6 +1177,7 @@ bfOffWd: {f_off:f_wd} is f_off & f_wd { }
getbitfield(tmp, f_off, f_wd);
resbitflags(tmp, f_wd-1);
}
@endif # CPU32 - no bitfield instructions

define pcodeop breakpoint;
:bkpt "#"op02 is opbig=0x48 & op67=1 & op5=0 & op34=1 & op02 { breakpoint(); }
Expand Down Expand Up @@ -1205,7 +1239,8 @@ define pcodeop breakpoint;
}

@endif # COLDFIRE
# TODO: Determine layout of a module descriptor
@ifndef CPU32
# TODO: Determine layout of a module descriptor
define pcodeop callm;
:callm const8,e2l is opbig=6 & op67=3 & $(CTL_ADDR_MODES); const8; e2l [ savmod2=savmod1; regtsan=regtfan; ] {
PC = callm(const8, e2l);
Expand Down Expand Up @@ -1283,6 +1318,7 @@ define pcodeop callm;
ZF = 1;
NF = 0;
}
@endif # CPU32 - no CALLM, CAS, CAS2

:chk.w eaw,reg9dnw is (op=4 & reg9dnw & op68=6 & $(DAT_ALTER_ADDR_MODES))... & eaw {
build eaw;
Expand Down Expand Up @@ -2060,6 +2096,7 @@ macro negResFlags(result) {
:ori const8,"CCR" is opbig=0 & op37=7 & op02=4; const8 { packflags(SR); SR=SR|zext(const8); unpackflags(SR); }
:ori const16,SR is SR; opbig=0x00 & d8base=0x7c; const16 { packflags(SR); SR=SR|const16; unpackflags(SR); }

@ifndef CPU32
:pack Tyw,Txw,const16 is op=8 & op48=20 & Txw & Tyw & rmbit=0; const16 {
local value = (Tyw & 0x0F0F) + const16;
Txw = (Txw & 0xFF00) | ((value & 0x0F00) >> 4) | (value & 0x000F);
Expand All @@ -2070,6 +2107,7 @@ macro negResFlags(result) {
local result:2 = ((value & 0x0F00) >> 4) | (value & 0x000F);
Txb = result:1;
}
@endif # CPU32 - no PACK

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

Expand Down Expand Up @@ -2227,9 +2265,11 @@ ptestLevel: "#"^mregn is mregn { export *[const]:1 mregn; }
:rtd const16 is opbig=0x4e & op37=14 & op02=4; const16 { PC = *SP; SP = SP + 4 + zext(const16); return [PC]; }
:rte is d16=0x4e73 { tmp:4 = 0; return [tmp]; }

@ifndef CPU32
define pcodeop rtm;
:rtm regdn is opbig=0x06 & op37=24 & regdn { PC = rtm(regdn); return [PC]; }
:rtm regan is opbig=0x06 & op37=25 & regan { PC = rtm(regan); return [PC];}
@endif # CPU32 - no RTM

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

Expand Down Expand Up @@ -2306,6 +2346,7 @@ define pcodeop stop;

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

@ifndef CPU32
:unpk Tyw,Txw,const16 is op=8 & Txw & op48=24 & Tyw & rmbit=0; const16 {
Txw = (Txw & 0xF0F0) | ((((Tyw & 0x00F0) << 4) | (Tyw & 0x000F)) + const16);
}
Expand All @@ -2315,7 +2356,9 @@ define pcodeop stop;
source = (((source & 0x00F0) << 4) | (source & 0x000F)) + const16;
Txw = (Txw & 0xF0F0) | source;
}
@endif # CPU32 - no UNPK

@ifndef CPU32
# Floating Point Instructions

# 68040 directly implements Floating Point instructions but requires Coprocessor ID be 001
Expand Down Expand Up @@ -2883,6 +2926,7 @@ fsubrnd: "d" is fdst & fopmode=0x6c { tmp:4 = float2float(fdst); fdst = float2f
:ftwotox.x fsrc, fdst is op=15 & $(FP_COP) & op68=0 & mode=0 & regan=0; frm=0 & f1515=0 & f1313=0 & fsrc & fdst & fopmode=0x11
{ fdst = ftwotox(fsrc); }

@endif # CPU32 - no FPU instructions

@ifdef COLDFIRE

Expand Down Expand Up @@ -3151,4 +3195,97 @@ moveaccreg2: ACC3 is ACC3 & op01=3 { export ACC3; }

@endif

@ifdef CPU32

tbl_eal: (tbl_regan) is tbl_mode=2 & tbl_regan { export *:4 tbl_regan; }
tbl_eal: -(tbl_regan) is tbl_mode=4 & tbl_regan { tbl_regan = tbl_regan - 4; export *:4 tbl_regan; }
tbl_eal: (d16,tbl_regan) is tbl_mode=5 & tbl_regan; d16 { local tmp = tbl_regan + d16; export *:4 tmp; }
tbl_eal: (extw) is tbl_mode=6 & tbl_regan; extw [ regtfan = tbl_regan; pcmode = 0; ] { build extw; export *:4 extw; }
tbl_eal: (d16,PC) is PC & tbl_mode=7 & tbl_regan=2; d16 { tmp:4 = inst_start + 2 + d16; export *:4 tmp; }
tbl_eal: (extw) is tbl_mode=7 & tbl_regan=3; extw [ pcmode=1; ] { build extw; export *:4 extw; }
tbl_eal: (d16)".w" is tbl_mode=7 & tbl_regan=0; d16 { export *:4 d16; }
tbl_eal: (d32)".l" is tbl_mode=7 & tbl_regan=1; d32 { export *:4 d32; }
tbl_eal: "#"^d32 is tbl_mode=7 & tbl_regan=4; d32 { export *[const]:4 d32; }

tbl_eaw: (tbl_regan) is tbl_mode=2 & tbl_regan { export *:2 tbl_regan; }
tbl_eaw: -(tbl_regan) is tbl_mode=4 & tbl_regan { tbl_regan = tbl_regan - 2; export *:2 tbl_regan; }
tbl_eaw: (d16,tbl_regan) is tbl_mode=5 & tbl_regan; d16 { local tmp = tbl_regan + d16; export *:2 tmp; }
tbl_eaw: (extw) is tbl_mode=6 & tbl_regan; extw [ pcmode=0; regtfan=tbl_regan; ] { build extw; export *:2 extw; }
tbl_eaw: (d16,PC) is PC & tbl_mode=7 & tbl_regan=2; d16 { tmp:4 = inst_start + 2 + d16; export *:2 tmp; }
tbl_eaw: (extw) is tbl_mode=7 & tbl_regan=3; extw [ pcmode=1; ] { build extw; export *:2 extw; }
tbl_eaw: (d16)".w" is tbl_mode=7 & tbl_regan=0; d16 { export *:2 d16; }
tbl_eaw: (d32)".l" is tbl_mode=7 & tbl_regan=1; d32 { export *:2 d32; }
tbl_eaw: "#"^d16 is tbl_mode=7 & tbl_regan=4; d16 { export *[const]:2 d16; }

tbl_eab: (tbl_regan) is tbl_mode=2 & tbl_regan { export *:1 tbl_regan; }
tbl_eab: -(tbl_regan) is tbl_mode=4 & tbl_regan { tbl_regan = tbl_regan - 1; export *:1 tbl_regan; }
tbl_eab: (d16,tbl_regan) is tbl_mode=5 & tbl_regan; d16 { local tmp = tbl_regan + d16; export *:1 tmp; }
tbl_eab: (extw) is tbl_mode=6 & tbl_regan; extw [ pcmode=0; regtfan=tbl_regan; ] { build extw; export *:1 extw; }
tbl_eab: (d16,PC) is PC & tbl_mode=7 & tbl_regan=2; d16 { tmp:4 = inst_start + 2 + d16; export *:1 tmp; }
tbl_eab: (extw) is tbl_mode=7 & tbl_regan=3; extw [ pcmode=1; ] { build extw; export *:1 extw; }
tbl_eab: (d16)".w" is tbl_mode=7 & tbl_regan=0; d16 { export *:1 d16; }
tbl_eab: (d32)".l" is tbl_mode=7 & tbl_regan=1; d32 { export *:1 d32; }
tbl_eab: "#"^d8 is tbl_mode=7 & tbl_regan=4; d8 { export *[const]:1 d8; }

tblsign: "u" is tbl_sign=0 { }
tblsign: "s" is tbl_sign=1 { }

tbldrsign: "u" is tbl_dr_sign=0 { }
tbldrsign: "s" is tbl_dr_sign=1 { }

define pcodeop tableLookup;

# Rounded Table Lookup and Interpolate

: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
{ tbl_regxdn = tableLookup(tbl_regxdn, tbl_eab); }

: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
{ tbl_regxdn = tableLookup(tbl_regxdn, tbl_eaw); }

: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
{ tbl_regxdn = tableLookup(tbl_regxdn, tbl_eal); }

# Unrounded Table Lookup and Interpolate

: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
{ tbl_regxdn = tableLookup(tbl_regxdn, tbl_eab); }

: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
{ tbl_regxdn = tableLookup(tbl_regxdn, tbl_eaw); }

: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
{ tbl_regxdn = tableLookup(tbl_regxdn, tbl_eal); }

define pcodeop interpolate;

# Rounded Data Register Interpolate

: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
{ regxdn = interpolate(regdn, tbl_dr_reg); }

: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
{ regxdn = interpolate(regdn, tbl_dr_reg); }

: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
{ regxdn = interpolate(regdn, tbl_dr_reg); }

# Unrounded Data Register Interpolate

: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
{ regxdn = interpolate(regdn, tbl_dr_reg); }

: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
{ regxdn = interpolate(regdn, tbl_dr_reg); }

: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
{ regxdn = interpolate(regdn, tbl_dr_reg); }

define pcodeop low_power_stop;
:lpstop "#"^d16 is opbig=0xf8 & d8base=0x00; opbig=0x01 & d8base=0xC0; d16 { SR = d16; low_power_stop(); }

define pcodeop background_mode;
:bgnd is opbig=0x4A & d8base=0xFA { background_mode(); }

@endif # CPU32
} # end with : extGUARD=1
6 changes: 6 additions & 0 deletions Ghidra/Processors/68000/data/languages/CPU32.slaspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Motorola's CPU32 processor

@define CPU32 ""
@define MC68332 ""

@include "68000.sinc"
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.test.processors;

import ghidra.test.processors.support.ProcessorEmulatorTestAdapter;
import junit.framework.Test;

public class CPU32_O0_EmulatorTest extends ProcessorEmulatorTestAdapter {

private static final String LANGUAGE_ID = "68000:BE:32:CPU32";
private static final String COMPILER_SPEC_ID = "default";

private static final String[] REG_DUMP_SET = new String[] {};

public CPU32_O0_EmulatorTest(String name) throws Exception {
super(name, LANGUAGE_ID, COMPILER_SPEC_ID, REG_DUMP_SET);
}

@Override
protected String getProcessorDesignator() {
return "CPU32_GCC_O0";
}

public static Test suite() {
return ProcessorEmulatorTestAdapter.buildEmulatorTestSuite(CPU32_O0_EmulatorTest.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.test.processors;

import ghidra.test.processors.support.ProcessorEmulatorTestAdapter;
import junit.framework.Test;

public class CPU32_O3_EmulatorTest extends ProcessorEmulatorTestAdapter {

private static final String LANGUAGE_ID = "68000:BE:32:CPU32";
private static final String COMPILER_SPEC_ID = "default";

private static final String[] REG_DUMP_SET = new String[] {};

public CPU32_O3_EmulatorTest(String name) throws Exception {
super(name, LANGUAGE_ID, COMPILER_SPEC_ID, REG_DUMP_SET);
}

@Override
protected String getProcessorDesignator() {
return "CPU32_GCC_O3";
}

public static Test suite() {
return ProcessorEmulatorTestAdapter.buildEmulatorTestSuite(CPU32_O3_EmulatorTest.class);
}
}