Moved HCS12 files for release.

This commit is contained in:
ghidorahrex 2019-08-26 10:44:28 -04:00
parent f5a366fa5c
commit a744c01b6d
11 changed files with 7304 additions and 0 deletions

View File

View File

@ -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 HCS12'

View File

@ -0,0 +1,13 @@
##VERSION: 2.0
.project||NONE||||END|
Module.manifest||GHIDRA||||END|
build.gradle||GHIDRA||||END|
data/build.xml||GHIDRA||||END|
data/languages/HCS12.cspec||GHIDRA||||END|
data/languages/HCS12.ldefs||GHIDRA||||END|
data/languages/HCS12.opinion||GHIDRA||||END|
data/languages/HCS12.pspec||GHIDRA||||END|
data/languages/HCS12.slaspec||GHIDRA||||END|
data/languages/HCS_HC12.sinc||GHIDRA||||END|
data/languages/XGATE.sinc||GHIDRA||||END|
data/manuals/HCS12.idx||GHIDRA||||END|

View File

@ -0,0 +1,143 @@
<?xml version="1.0" encoding="UTF-8"?>
<compiler_spec>
<data_organization> <!-- These tags need to be verified -->
<absolute_max_alignment value="0" />
<machine_alignment value="1" />
<default_alignment value="1" />
<default_pointer_alignment value="3" />
<pointer_size value="2" />
<wchar_size value="4" />
<short_size value="2" />
<integer_size value="4" />
<long_size value="4" />
<long_long_size value="8" />
<float_size value="4" />
<double_size value="8" />
<long_double_size value="8" />
<size_alignment_map>
<entry size="1" alignment="1" />
<entry size="2" alignment="2" />
<entry size="4" alignment="4" />
<entry size="8" alignment="8" />
</size_alignment_map>
</data_organization>
<global>
<range space="RAM" first="0x00" last="0x0f"/>
<range space="RAM" first="0x11" last="0x15"/>
<range space="RAM" first="0x18" last="0x2f"/>
<range space="RAM" first="0x31" last="0xffff"/>
</global>
<stackpointer register="SP" space="RAM" growth="negative"/>
<segmentop space="RAM" userop="segment" baseinsize="1" innerinsize="2" farpointer="no">
<baseop code="INT_ZEXT"/>
<baseop code="INT_LEFT" value="16"/>
<innerop code="INT_ZEXT"/>
<constresolve>
<register name="PPAGE"/>
</constresolve>
</segmentop>
<returnaddress>
<varnode space="stack" offset="0" size="3"/>
</returnaddress>
<default_proto>
<prototype name="__asmA" extrapop="2" stackshift="2" strategy="register">
<input>
<pentry minsize="1" maxsize="1">
<register name="A"/>
</pentry>
<pentry minsize="1" maxsize="1">
<register name="B"/>
</pentry>
<pentry minsize="1" maxsize="2">
<register name="D"/>
</pentry>
<pentry minsize="1" maxsize="2">
<register name="IY"/>
</pentry>
<pentry minsize="1" maxsize="2">
<register name="IX"/>
</pentry>
<pentry minsize="1" maxsize="500" align="2">
<addr offset="2" space="stack"/>
</pentry>
</input>
<output>
<pentry minsize="1" maxsize="2">
<register name="D"/>
</pentry>
</output>
<unaffected>
<register name="SP"/>
<register name="PPAGE"/>
<register name="RPAGE"/>
<register name="GPAGE"/>
</unaffected>
</prototype>
</default_proto>
<prototype name="__asmA_longcall" extrapop="3" stackshift="3" strategy="register">
<input>
<pentry minsize="1" maxsize="1">
<register name="A"/>
</pentry>
<pentry minsize="1" maxsize="1">
<register name="B"/>
</pentry>
<pentry minsize="1" maxsize="2">
<register name="D"/>
</pentry>
<pentry minsize="1" maxsize="2">
<register name="IY"/>
</pentry>
<pentry minsize="1" maxsize="2">
<register name="IX"/>
</pentry>
<pentry minsize="1" maxsize="500" align="2">
<addr offset="2" space="stack"/>
</pentry>
</input>
<output>
<pentry minsize="1" maxsize="2">
<register name="D"/>
</pentry>
</output>
<unaffected>
<register name="SP"/>
<register name="PPAGE"/>
<register name="RPAGE"/>
<register name="GPAGE"/>
</unaffected>
</prototype>
<prototype name="__asmA_xgate" extrapop="3" stackshift="3" strategy="register">
<input>
<pentry minsize="1" maxsize="2">
<register name="R2"/>
</pentry>
<pentry minsize="1" maxsize="2">
<register name="R3"/>
</pentry>
<pentry minsize="3" maxsize="4">
<addr space="join" piece1="R2" piece2="R3"/>
</pentry>
<pentry minsize="1" maxsize="2">
<register name="R4"/>
</pentry>
<pentry minsize="3" maxsize="4">
<addr space="join" piece1="R3" piece2="R4"/>
</pentry>
<pentry minsize="1" maxsize="500" align="2">
<addr offset="2" space="stack"/>
</pentry>
</input>
<output>
<pentry minsize="1" maxsize="2">
<register name="R2"/>
</pentry>
<pentry minsize="4" maxsize="4">
<addr space="join" piece1="R2" piece2="R3"/>
</pentry>
</output>
</prototype>
</compiler_spec>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<language_definitions>
<language processor="HCS12"
endian="big"
size="24"
variant="default"
version="1.0"
slafile="HCS12.sla"
processorspec="HCS12.pspec"
manualindexfile="../manuals/HCS12.idx"
id="HCS12:BE:24:default">
<description>HCS12X Microcontroller Family</description>
<compiler name="default" spec="HCS12.cspec" id="default"/>
<external_name tool="gnu" name="m9s12x"/>
</language>
</language_definitions>

View File

@ -0,0 +1,6 @@
<opinions>
<constraint loader="Executable and Linking Format (ELF)" compilerSpecID="default">
<constraint primary="53" processor="HCS12" endian="big" size="24" variant="default"/>
</constraint>
</opinions>

View File

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
This is the processor specification for the MC9S12C and MC9S12GC processor families.
It is based upon the MC9S12C128 and MC9S12GC128 variants.
-->
<processor_spec>
<programcounter register="PC"/>
<!-- TODO
<volatile outputop="write_volatile" inputop="read_volatile">
<range space="RAM" first="0x0" last="0x03FF"/>
</volatile>
-->
<context_data>
<tracked_set space="RAM">
<set name="PPAGE" val="0xfe"/>
<set name="RPAGE" val="0xfd"/>
<set name="EPAGE" val="0xfe"/>
<set name="XG_BASE" val="0xfe800"/>
</tracked_set>
</context_data>
<default_symbols>
<symbol name="VECTOR_Reset" address="FFFE" entry="true" type="code_ptr"/>
<symbol name="VECTOR_ClockMonitorFailReset" address="FFFC" entry="true" type="code_ptr"/>
<symbol name="VECTOR_COPFailureReset" address="FFFA" entry="true" type="code_ptr"/>
<symbol name="VECTOR_UnimplementedInstructionTrap" address="FFF8" entry="true" type="code_ptr"/>
<symbol name="VECTOR_SWI" address="FFF6" entry="true" type="code_ptr"/>
<symbol name="VECTOR_XIRQ" address="FFF4" entry="true" type="code_ptr"/>
<symbol name="VECTOR_IRQ" address="FFF2" entry="true" type="code_ptr"/>
<symbol name="VECTOR_RealTimeInterrupt" address="FFF0" entry="true" type="code_ptr"/>
<symbol name="VECTOR_StandardTimerChannel0" address="FFEE" entry="true" type="code_ptr"/>
<symbol name="VECTOR_StandardTimerChannel1" address="FFEC" entry="true" type="code_ptr"/>
<symbol name="VECTOR_StandardTimerChannel2" address="FFEA" entry="true" type="code_ptr"/>
<symbol name="VECTOR_StandardTimerChannel3" address="FFE8" entry="true" type="code_ptr"/>
<symbol name="VECTOR_StandardTimerChannel4" address="FFE6" entry="true" type="code_ptr"/>
<symbol name="VECTOR_StandardTimerChannel5" address="FFE4" entry="true" type="code_ptr"/>
<symbol name="VECTOR_StandardTimerChannel6" address="FFE2" entry="true" type="code_ptr"/>
<symbol name="VECTOR_StandardTimerChannel7" address="FFE0" entry="true" type="code_ptr"/>
<symbol name="VECTOR_StandardTimerOverflow" address="FFDE" entry="true" type="code_ptr"/>
<symbol name="VECTOR_PulseAccumulatorAOverflow" address="FFDC" entry="true" type="code_ptr"/>
<symbol name="VECTOR_PulseAccumulatorInputEdge" address="FFDA" entry="true" type="code_ptr"/>
<symbol name="VECTOR_SPI" address="FFD8" entry="true" type="code_ptr"/>
<symbol name="VECTOR_SCI" address="FFD6" entry="true" type="code_ptr"/>
<symbol name="VECTOR_Reserved_FFD4" address="FFD4" entry="true" type="code_ptr"/>
<symbol name="VECTOR_ATD" address="FFD2" entry="true" type="code_ptr"/>
<symbol name="VECTOR_Reserved_FFD0" address="FFD0" entry="true" type="code_ptr"/>
<symbol name="VECTOR_PortJ" address="FFCE" entry="true" type="code_ptr"/>
<symbol name="VECTOR_Reserved_FFCC" address="FFCC" entry="true" type="code_ptr"/>
<symbol name="VECTOR_Reserved_FFCA" address="FFCA" entry="true" type="code_ptr"/>
<symbol name="VECTOR_Reserved_FFC8" address="FFC8" entry="true" type="code_ptr"/>
<symbol name="VECTOR_CRG_PLL_Lock" address="FFC6" entry="true" type="code_ptr"/>
<symbol name="VECTOR_CRGSelfClockMode" address="FFC4" entry="true" type="code_ptr"/>
<symbol name="VECTOR_Reserved_FFC2" address="FFC2" entry="true" type="code_ptr"/>
<symbol name="VECTOR_Reserved_FFC0" address="FFC0" entry="true" type="code_ptr"/>
<symbol name="VECTOR_Reserved_FFBE" address="FFBE" entry="true" type="code_ptr"/>
<symbol name="VECTOR_Reserved_FFBC" address="FFBC" entry="true" type="code_ptr"/>
<symbol name="VECTOR_Reserved_FFBA" address="FFBA" entry="true" type="code_ptr"/>
<symbol name="VECTOR_FLASH" address="FFB8" entry="true" type="code_ptr"/>
<symbol name="VECTOR_CANwake-up" address="FFB6" entry="true" type="code_ptr"/>
<symbol name="VECTOR_CANerrors" address="FFB4" entry="true" type="code_ptr"/>
<symbol name="VECTOR_CANreceive" address="FFB2" entry="true" type="code_ptr"/>
<symbol name="VECTOR_CANtransmit" address="FFB0" entry="true" type="code_ptr"/>
<symbol name="VECTOR_Reserved_FFAE" address="FFAE" entry="true" type="code_ptr"/>
<symbol name="VECTOR_Reserved_FFAC" address="FFAC" entry="true" type="code_ptr"/>
<symbol name="VECTOR_Reserved_FFAA" address="FFAA" entry="true" type="code_ptr"/>
<symbol name="VECTOR_Reserved_FFA8" address="FFA8" entry="true" type="code_ptr"/>
<symbol name="VECTOR_Reserved_FFA6" address="FFA6" entry="true" type="code_ptr"/>
<symbol name="VECTOR_Reserved_FFA4" address="FFA4" entry="true" type="code_ptr"/>
<symbol name="VECTOR_Reserved_FFA2" address="FFA2" entry="true" type="code_ptr"/>
<symbol name="VECTOR_Reserved_FFA0" address="FFA0" entry="true" type="code_ptr"/>
<symbol name="VECTOR_Reserved_FF9E" address="FF9E" entry="true" type="code_ptr"/>
<symbol name="VECTOR_Reserved_FF9C" address="FF9C" entry="true" type="code_ptr"/>
<symbol name="VECTOR_Reserved_FF9A" address="FF9A" entry="true" type="code_ptr"/>
<symbol name="VECTOR_Reserved_FF98" address="FF98" entry="true" type="code_ptr"/>
<symbol name="VECTOR_Reserved_FF96" address="FF96" entry="true" type="code_ptr"/>
<symbol name="VECTOR_Reserved_FF94" address="FF94" entry="true" type="code_ptr"/>
<symbol name="VECTOR_Reserved_FF92" address="FF92" entry="true" type="code_ptr"/>
<symbol name="VECTOR_Reserved_FF90" address="FF90" entry="true" type="code_ptr"/>
<symbol name="VECTOR_PortP" address="FF8E" entry="true" type="code_ptr"/>
<symbol name="VECTOR_PWM_EmergencyShutdown" address="FF8C" entry="true" type="code_ptr"/>
<symbol name="VECTOR_VREG_LVI" address="FF8A" entry="true" type="code_ptr"/>
<symbol name="VECTOR_Reserved_FF88" address="FF88" entry="true" type="code_ptr"/>
<symbol name="VECTOR_Reserved_FF86" address="FF86" entry="true" type="code_ptr"/>
<symbol name="VECTOR_Reserved_FF84" address="FF84" entry="true" type="code_ptr"/>
<symbol name="VECTOR_Reserved_FF82" address="FF82" entry="true" type="code_ptr"/>
<symbol name="VECTOR_Reserved_FF80" address="FF80" entry="true" type="code_ptr"/>
</default_symbols>
</processor_spec>

View File

@ -0,0 +1,9 @@
# sleigh specification file for Freescale HCS12 (68HCS12)
@define HCS12 "1"
@define HCS12X "1"
@define MAXFLASHPage "0xFF"
@include "HCS_HC12.sinc"
@include "XGATE.sinc"

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,960 @@
# sleigh specification file for XGATE MCU peripheral co-processor
################################################################
# Registers
################################################################
# register R0 always contains the value 0
define register offset=0x100 size=2 [R0 R1 R2 R3 R4 R5 R6 R7];
define register offset=0x110 size=2 [XPC XCCR];
define register offset=0x120 size=1 [XC XV XZ XN];
define register offset=0x130 size=3 [XG_BASE];
# Individual status bits within the XCCR
@define XN "XN" # XCCR[3,1] # Negative Flag
@define XZ "XZ" # XCCR[2,1] # Zero Flag
@define XV "XV" # XCCR[1,1] # Overflow Flag
@define XC "XC" # XCCR[0,1] # Carry Flag
################################################################
# Tokens
################################################################
define token XOpWord16 (16)
xop16 = (0,15)
opcode = (11,15)
reg8 = (8,10)
reg8_lo = (8,10)
reg8_hi = (8,10)
imm3 = (8,10)
op9_10 = (9,10)
bit_10 = (10,10)
immrel9 = (0,9) signed
immrel8 = (0,8) signed
xop8 = (0,7)
reg5 = (5,7)
ximm4 = (4,7)
ximm8 = (0,7)
op4 = (0,4)
op3 = (0,3)
offs5 = (0,5)
reg2 = (2,4)
op2 = (0,1)
;
################################################################
# Attach variables
################################################################
attach variables [reg8 reg5 reg2] [R0 R1 R2 R3 R4 R5 R6 R7];
################################################################
# Pseudo Instructions
################################################################
define pcodeop bfins;
define pcodeop bfinsi;
define pcodeop findFirstOne;
define pcodeop leftShiftCarry;
define pcodeop rightShiftCarry;
define pcodeop parity;
define pcodeop clearSemaphore;
define pcodeop setSemaphore;
define pcodeop setInterruptFlag;
################################################################
# Macros Instructions
################################################################
macro default_flags(result)
{
$(XZ) = (result == 0);
$(XN) = (result s< 0);
$(XV) = 0;
#$(XC) not affected
}
macro default_flagsH(result)
{
$(XN) = (result s< 0);
$(XZ) = ((result & 0xff00) == 0);
$(XV) = 0;
#$(XC) not affected
}
macro default_flagsL(result)
{
$(XN) = ((result & 0x0080) != 0);
$(XZ) = ((result & 0xff) == 0);
$(XV) = 0;
#$(XC) not affected
}
macro addition_flags(operand1, operand2, result)
{
$(XN) = (result s< 0);
$(XZ) = ((result == 0) & ($(XZ)==1));
$(XV) = (((operand1 & operand2 & ~result) | (~operand1 & ~operand2 & result)) & 0x8000) != 0;
$(XC) = (((operand1 & operand2) | (operand2 & ~result) | (~result & operand1)) & 0x8000) != 0;
}
macro subtraction_flags(register, operand, result) {
$(XN) = (result s< 0);
$(XZ) = (result == 0);
$(XV) = ( ((register & ~operand & ~result) | (~register & operand & result)) & 0x8000 ) != 0;
$(XC) = ( ((~register & operand) | (operand & result) | (~register & result)) & 0x8000 ) != 0;
}
macro subtraction_flagsB(register, operand, result) {
$(XN) = (result s< 0);
$(XZ) = (result == 0);
$(XV) = ( ((register & ~operand & ~result) | (~register & operand & result)) & 0x80 ) != 0;
$(XC) = ( ((~register & operand) | (operand & result) | (result & ~register)) & 0x80 ) != 0;
}
macro subtraction_flagsC(register, operand, result) {
$(XN) = (result s< 0);
$(XZ) = ( (result == 0) & ($(XZ) == 1));
$(XV) = ( ((register & ~operand & ~result) | (~register & operand & result)) & 0x8000 ) != 0;
$(XC) = ( ((~register & operand) | (operand & result) | (~register & result)) & 0x8000 ) != 0;
}
macro shiftFlags(result,old)
{
$(XN) = (result s< 0);
$(XZ) = (result == 0);
tmp:2 = (old >> 15) ^ (result >> 15);
$(XV) = tmp(1);
}
macro getbit(res,in,bitnum) {
res = ((in >> bitnum) & 1) != 0;
}
################################################################
# Constructors
################################################################
#rel9 defined in HCS_HC12.sinc
# range -256 through +255
with : XGATE=1 {
rel9: reloc is immrel8 [ reloc = XG_BASE + inst_next + (immrel8 * 2); ] { export * reloc; }
# range -512 through +512
rel10: reloc is immrel9 [ reloc = XG_BASE + inst_next + (immrel9 * 2); ] { export * reloc; }
rd : reg8 is reg8 { export reg8; }
rs1: reg5 is reg5 & reg5=0 { export 0:2; }
rs1: reg5 is reg5 { export reg5; }
rs2: reg2 is reg2 & reg2=0 { export 0:2; }
rs2: reg2 is reg2 { export reg2; }
# Add with carry
:ADC rd, rs1, rs2 is opcode=0x3 & rd & rs1 & rs2 & op2=0x3
{
local result:2 = rs1 + rs2 + zext($(XC));
rd = result;
addition_flags(rs1, rs2, result);
}
# Add without carry
:ADD rd, rs1, rs2 is opcode=0x3 & rd & rs1 & rs2 & op2=0x2
{
local result:2 = rs1 + rs2;
rd = result;
addition_flags(rs1, rs2, result);
}
# Add immediate 8-bit constant (high byte)
:ADDH rd, ximm8 is opcode=0x1d & rd & ximm8
{
local val:2 = ximm8 << 8;
local result:2 = rd + val;
addition_flags(rd, val, result);
rd = result;
}
# Add immediate 8-bit constant (low byte)
:ADDL rd, ximm8 is opcode=0x1c & rd & ximm8
{
local result:2 = rd + ximm8;
$(XN) = (result s< 0);
$(XZ) = ((result == 0) & ($(XZ)==1));
$(XV) = ((~rd & result) & 0x8000) != 0;
$(XC) = ((rd & ~result) & 0x8000) != 0;
rd = result;
}
# Logical AND
:AND rd, rs1, rs2 is opcode=0x2 & rd & rs1 & rs2 & op2=0x0
{
local result:2 = rs1 & rs2;
rd = result;
default_flags(result);
}
# Logical AND immediate 8-bit constant (high byte)
:ANDH rd, ximm8 is opcode=0x11 & rd & ximm8
{
local result:2 = (ximm8 << 8) | 0xff;
result = rd & result;
rd = result;
default_flagsH(result);
}
# Logical AND immediate 8-bit constant (low byte)
:ANDL rd, ximm8 is opcode=0x10 & rd & ximm8
{
local result:2 = 0xff00 | ximm8;
result = rd & result;
rd = result;
default_flagsL(result);
}
# Arithmetic Shift Right
:ASR rd, ximm4 is opcode=0x1 & rd & ximm4 & op3=0x9
{
getbit($(XC), rd, ximm4-1);
rd = rd s>> ximm4;
default_flags(rd);
}
:ASR rd, rs1 is opcode=0x1 & rd & rs1 & op4=0x11
{
getbit($(XC), rd, rs1-1);
rd = rd s>> rs1;
default_flags(rd);
}
# Branch if Carry Cleared
:BCC rel9 is opcode=0x4 & op9_10=0x0 & rel9
{
if ($(XC) == 0) goto rel9;
}
# Branch if Carry Set
:BCS rel9 is opcode=0x4 & op9_10=0x1 & rel9
{
if ($(XC) == 1) goto rel9;
}
# Branch of Equal
:BEQ rel9 is opcode=0x4 & op9_10=0x3 & rel9
{
if ($(XZ) == 1) goto rel9;
}
# Bit Field Extract
:BFEXT rd, rs1, rs2 is opcode=0xc & rd & rs1 & rs2 & op2=0x3
{
local origin:2 = rs2 & 0xf;
local width:2 = (rs2 >> 4) & 0xf;
local mask:2 = (0xffff >> (16-(width + 1))) << origin;
local result:2 = (rs1 & mask) >> origin;
rd = result;
default_flags(rd);
}
# Bit Field Find First One
:BFFO rd, rs1 is opcode=0x1 & rd & rs1 & op4=0x10
{
# 15 - count leading zeros
tmp:2 = rs1;
$(XC) = (rd == 0);
#TODO: implement findFirstOne behavior
rd = findFirstOne(tmp);
default_flags(rd);
}
# Bit Field Insert
:BFINS rd, rs1, rs2 is opcode=0xd & rd & rs1 & rs2 & op2=0x3
{
local origin:2 = rs2 & 0xf;
local width:2 = (rs2 >> 4) & 0xf;
local mask:2 = (0xffff >> (16-(width + 1))) << origin;
local result:2 = (rs1 & mask);
rd = (rd & ~mask) | result;
default_flags(rd);
}
# Bit Field Insert and Invert
:BFINSI rd, rs1, rs2 is opcode=0xe & rd & rs1 & rs2 & op2=0x3
{
local origin:2 = rs2 & 0xf;
local width:2 = (rs2 >> 4) & 0xf;
local mask:2 = (0xffff >> (16-(width + 1))) << origin;
local result:2 = (~rs1 & mask);
rd = (rd & ~mask) | result;
default_flags(rd);
}
# Bit Field Insert and XNOR
:BFINSX rd, rs1, rs2 is opcode=0xf & rd & rs1 & rs2 & op2=0x3
{
local origin:2 = rs2 & 0xf;
local width:2 = (rs2 >> 4) & 0xf;
local mask:2 = (0xffff >> (16-(width + 1))) << origin;
local result:2 = (~(rs1 ^ rd) & mask);
rd = (rd & ~mask) | result;
default_flags(rd);
}
# Branch if Greater than or Equal to Zero
:BGE rel9 is opcode=0x6 & op9_10=0x2 & rel9
{
if (($(XN) ^ $(XV)) == 0) goto rel9;
}
# Branch if Greater than Zero
:BGT rel9 is opcode=0x7 & op9_10=0x0 & rel9
{
if (($(XZ) | ($(XN) ^ $(XV))) == 0) goto rel9;
}
# Branch if Higher
:BHI rel9 is opcode=0x6 & op9_10=0x0 & rel9
{
if (($(XC) | $(XZ)) == 0) goto rel9;
}
#:BHS rel9 is opcode=0x4 & op9_10=0x0 & rel9 see BCC
# Bit Test immediate 8-bit constant (high byte)
:BITH rd, ximm8 is opcode=0x13 & rd & ximm8
{
local val:2 = rd >> 8;
val = val & ximm8;
default_flags(val);
}
# Bit Test immediate 8-bit constant (low byte)
:BITL reg8, ximm8 is opcode=0x12 & reg8 & ximm8
{
local val:2 = reg8 & 0xff;
val = val & ximm8;
default_flags(val);
}
# Branch if Less or Equal to Zero
:BLE rel9 is opcode=0x7 & op9_10=0x1 & rel9
{
if ($(XZ) | ($(XN) ^ $(XV))) goto rel9;
}
#:BLO rel9 is opcode=0x4 & op9_10=0x1 & rel9 See BCS
# Branch if Lower or Same
:BLS rel9 is opcode=0x6 & op9_10=0x1 & rel9
{
if (($(XC) | $(XZ)) == 1) goto rel9;
}
# Branch of Lower than Zero
:BLT rel9 is opcode=0x6 & op9_10=0x3 & rel9
{
if (($(XN) ^ $(XV)) == 1) goto rel9;
}
# Branch if Minus
:BMI rel9 is opcode=0x5 & op9_10=0x1 & rel9
{
if ($(XN) == 1) goto rel9;
}
# Branch if Not Equal
:BNE rel9 is opcode=0x4 & op9_10=0x2 & rel9
{
if ($(XZ) == 0) goto rel9;
}
# Branch if Plus
:BPL rel9 is opcode=0x5 & op9_10=0x0 & rel9
{
if ($(XN) == 0) goto rel9;
}
# Branch Always
:BRA rel10 is opcode=0x7 & bit_10=0x1 & rel10
{
goto rel10;
}
# Break
:BRK is xop16=0x0
{
# put xgate into debug mode and set breakpoint
goto inst_next;
}
# Branch if Overflow Cleared
:BVC rel9 is opcode=0x5 & op9_10=0x2 & rel9
{
if ($(XV) == 0) goto rel9;
}
# Branch if Overflow Set
:BVS rel9 is opcode=0x5 & op9_10=0x3 & rel9
{
if ($(XV) == 2) goto rel9;
}
# Compare
# synonym for SUB R0, RS1, RS2
:CMP rs1, rs2 is opcode=0x3 & reg8=0x0 & rs1 & rs2 & op2=0x0
{
tmp:2 = rs1 - rs2;
subtraction_flags(rs1, rs2, tmp);
}
# Compare Immediate 8-bit constant (low byte)
:CMPL rd, ximm8 is opcode=0x1a & rd & ximm8
{
local val:1 = rd:1;
local tmp:1 = val - ximm8;
local xtmp:1 = ximm8;
subtraction_flagsB(val, xtmp, tmp);
}
# One's Complement
:COM rd, rs2 is opcode=0x2 & rd & reg5=0x0 & rs2 & op2=0x3
{
local val:2 = ~rs2;
rd = val;
default_flags(rd);
}
:COM rd is opcode=0x2 & rd & reg5=0x0 & rs2 & reg8=reg2 & op2=0x3
{
local val:2 = ~rs2;
rd = val;
default_flags(rd);
}
# Compare with Carry
:CPC rs1, rs2 is opcode=0x3 & reg8=0x0 & rs1 & rs2 & op2=0x1
{
local tmp:2 = rs1 - rs2 - zext($(XC));
subtraction_flags(rs1, rs2, tmp);
}
# Compare Immediate 8-bit constant with carry (high byte)
:CPCH rd, ximm8 is opcode=0x1b & rd & ximm8
{
local val:2 = rd >> 8;
local tmp:1 = val(1) - ximm8 - $(XC);
local xtmp:1 = ximm8;
subtraction_flagsB(val(1), xtmp, tmp);
}
# Clear Semaphore
:CSEM rd is opcode=0x0 & rd & xop8=0xf0
{
# treat as NOP
clearSemaphore();
}
:CSEM imm3 is opcode=0x0 & imm3 & xop8=0xf1
{
clearSemaphore();
}
# Logical Shift Left with Carry
:CSL rd, ximm4 is opcode=0x1 & rd & ximm4 & op3=0xa
{
local Ctmp:2 = zext($(XC));
local shift:2 = ((ximm4-1)%16+1);
local oldRd:2 = rd >> 15;
getbit($(XC), rd, 16-shift);
leftShiftCarry(rd,Ctmp,shift,rd);
shiftFlags(rd,oldRd);
}
:CSL rd, rs1 is opcode=0x1 & rd & rs1 & op4=0x12
{
local Ctmp:2 = zext($(XC));
#if rs1 > 16, then rs1 = 16
local rsgt:2 = zext(rs1>16);
local rslt:2 = zext(rs1<16);
local shift:2 = rs1*rsgt + 16*rslt;
local oldRd:2 = rd >> 15;
getbit($(XC), rd, 16-shift);
leftShiftCarry(rd,Ctmp,shift,rd);
shiftFlags(rd,oldRd);
}
# Logical Shift Right with Carry
:CSR rd, ximm4 is opcode=0x1 & rd & ximm4 & op3=0xb
{
local Ctmp:2 = zext($(XC));
local shift:2 = ((ximm4-1)%16+1);
local oldRd:2 = rd >> 15;
getbit($(XC), rd, shift-1);
rightShiftCarry(rd,Ctmp,shift,rd);
shiftFlags(rd,oldRd);
}
:CSR rd, rs1 is opcode=0x1 & rd & rs1 & op4=0x13
{
local Ctmp:2 = zext($(XC));
#if rs1 > 16, then rs1 = 16
local rsgt:2 = zext(rs1>16);
local rslt:2 = zext(rs1<16);
local shift:2 = rs1*rsgt + 16*rslt;
local oldRd:2 = rd >> 15;
getbit($(XC), rd, shift-1);
rightShiftCarry(rd,Ctmp,shift,rd);
shiftFlags(rd,oldRd);
}
:CSR rd, rs1 is opcode=0x1 & rd & rs1 & reg5=0 & op4=0x13
{
$(XN) = (rd s< 0);
$(XZ) = (rd == 0);
$(XV) = 0;
# $(XC) is unaffected
}
# Jump and Link
:JAL rd is opcode=0x0 & rd & xop8=0xf6
{
local dest:2 = rd;
rd = XPC;
call [dest];
}
# Load byte from memory (low byte)
:LDB rd, (rs1, offs5) is opcode=0x8 & rd & rs1 & offs5
{
dst:3 = XG_BASE + zext(rs1) + offs5;
local val:1 = *:1 (dst);
rd = (rd & 0xff00) | zext(val);
}
:LDB rd, (rs1, rs2) is opcode=0xc & rd & rs1 & rs2 & op2=0x0
{
dst:3 = XG_BASE + zext(rs1) + zext(rs2);
local val:1 = *:1 (dst);
rd = (rd & 0xff00) | zext(val);
}
:LDB rd, (rs1, rs2+) is opcode=0xc & rd & rs1 & rs2 & op2=0x1
{
dst:3 = XG_BASE + zext(rs1) + zext(rs2);
local val:1 = *:1 (dst);
rd = (rd & 0xff00) | zext(val);
rs1 = rs1 + 1;
}
:LDB rd, (rs1, -rs2) is opcode=0xc & rd & rs1 & rs2 & op2=0x2
{
rs2 = rs2 - 1;
dst:3 = XG_BASE + zext(rs1) + zext(rs2);
local val:1 = *:1 (dst);
rd = (rd & 0xff00) | zext(val);
}
# Load Immediate 8-bit constant (high byte)
:LDH rd, ximm8 is opcode=0x1f & rd & ximm8
{
rd = (rd & 0x00ff) | (ximm8 << 8);
}
# Load Immediate 8-bit constant (low byte)
:LDL rd, ximm8 is opcode=0x1e & rd & ximm8
{
rd = (rd & 0xff00) | ximm8;
}
# Load Word from Memory
:LDW rd, (rs1, offs5) is opcode=0x9 & rd & rs1 & offs5
{
dst:3 = XG_BASE + zext(rs1) + offs5;
local val:2 = *:2 (dst);
rd = val;
}
:LDW rd, (rs1, rs2) is opcode=0xd & rd & rs1 & rs2 & op2=0x0
{
dst:3 = XG_BASE + zext(rs1) + zext(rs2);
local val:2 = *:2 (dst);
rd = val;
}
:LDW rd, (rs1, rs2+) is opcode=0xd & rd & rs1 & rs2 & op2=0x1
{
dst:3 = XG_BASE + zext(rs1) + zext(rs2);
local val:2 = *:2 (dst);
rd = val;
rs1 = rs1 + 2;
}
:LDW rd, (rs1, -rs2) is opcode=0xd & rd & rs1 & rs2 & op2=0x2
{
rs2 = rs2 - 2;
dst:3 = XG_BASE + zext(rs1) + zext(rs2);
local val:2 = *:2 (dst);
rd = val;
}
# Logical Shift Left
:LSL rd, ximm4 is opcode=0x1 & rd & ximm4 & op3=0xc
{
local shift:2 = ((ximm4-1)%16+1);
getbit($(XC), rd, 16-shift);
local oldRd:2 = rd >> 15;
rd = rd << shift;
shiftFlags(rd,oldRd);
}
:LSL rd, rs1 is opcode=0x1 & rd & rs1 & op4=0x14
{
getbit($(XC), rd, 16-rs1);
local oldRd:2 = rd >> 15;
rd = rd << rs1;
shiftFlags(rd,oldRd);
}
# Logical Shift Right
:LSR rd, ximm4 is opcode=0x1 & rd & ximm4 & op3=0xd
{
getbit($(XC), rd, ximm4-1);
local oldRd:2 = rd >> 15;
rd = rd << ximm4;
shiftFlags(rd,oldRd);
}
:LSR rd, rs1 is opcode=0x1 & rd & rs1 & op4=0x15
{
getbit($(XC), rd, rs1-1);
local oldRd:2 = (rd >> 15);
rd = rd << rs1;
shiftFlags(rd,oldRd);
}
# Move Register Content
# Synonym for OR RD, R0, RS
:MOV rd, rs2 is opcode=0x2 & rd & reg5=0 & rs2 & op2=0x2
{
rd = rs2;
default_flags(rd);
}
# Two's Complement
:NEG rd, rs2 is opcode=0x3 & rd & reg5=0x0 & rs2 & op2=0x0
{
local tmp:2 = -rs2;
rd = tmp;
$(XN) = (rd s< 0);
$(XZ) = (rd == 0);
$(XV) = (((rs2 & rd) & 0x8000) != 0);
$(XC) = (((rs2 | rd) & 0x8000) != 0);
}
:NEG rd is opcode=0x3 & rd & reg5=0x0 & rs2 & reg2=reg8 & op2=0x0
{
local tmp:2 = -rs2;
rd = tmp;
$(XN) = (rd s< 0);
$(XZ) = (rd == 0);
$(XV) = (((rs2 & rd) & 0x8000) != 0);
$(XC) = (((rs2 | rd) & 0x8000) != 0);
}
# No Op
:NOP is xop16=0x100 {}
# Logical OR
:OR rd, rs1, rs2 is opcode=0x2 & rd & rs1 & rs2 & op2=0x2
{
local result:2 = rs1 | rs2;
rd = result;
default_flags(result);
}
# Logical OR Immediate 8-bit Constant (high byte)
:ORH rd, ximm8 is opcode=0x15 & rd & ximm8
{
local result:2 = (ximm8 << 8);
result = rd | result;
rd = result;
default_flagsH(result);
}
# Logical OR Immediate 8-bit Constant (low byte)
:ORL rd, ximm8 is opcode=0x14 & rd & ximm8
{
local result:2 = ximm8;
result = rd | result;
default_flagsL(result);
}
# Calculate Parity
:PAR rd is opcode=0x0 & rd & xop8=0xf5
{
parity(rd, $(XC));
default_flags(rd);
}
# Rotate Left
:ROL rd, ximm4 is opcode=0x1 & rd & ximm4 & op3=0xe
{
local cnt:2 = ximm4;
rd = (rd << cnt) | (rd >> (16 - cnt));
default_flags(rd);
}
:ROL rd, rs1 is opcode=0x1 & rd & rs1 & op4=0x16
{
local cnt:2 = rs1 & 0xf;
rd = (rd << cnt) | (rd >> (16 - cnt));
default_flags(rd);
}
# Rotate Right
:ROR rd, ximm4 is opcode=0x1 & rd & ximm4 & op3=0xf
{
local cnt:2 = ximm4;
rd = (rd >> cnt) | (rd << (16 - rd));
default_flags(rd);
}
:ROR rd, rs1 is opcode=0x1 & rd & rs1 & op4=0x17
{
local cnt:2 = rs1 & 0xf;
rd = (rd >> cnt) | (rd << (16 - rd));
default_flags(rd);
}
# Return to Scheduler
# Implement as NOP for now
:RTS is xop16=0x0200 {}
# Subtract with Carry
:SBC rd, rs1, rs2 is opcode=0x3 & rd & rs1 & rs2 & op2=0x1
{
local result:2 = rs1 - rs2 - zext($(XC));
rd = result;
subtraction_flagsC(rs1, rs2, result);
}
# Sign Extent Byte to Word
:SEX rd is opcode=0x0 & rd & xop8=0xf4
{
local result:1 = rd:1 & 0xff;
rd = sext(result);
default_flags(rd);
}
# Set Interrupt Flag
# TODO: implement interrupt flags
:SIF is xop16=0x0300
{
setInterruptFlag();
}
:SIF rd is opcode=0x0 & rd & xop8=0xf7
{
setInterruptFlag();
}
# Set Semaphore
# TODO: implement semaphores
:SSEM imm3 is opcode=0x0 & imm3 & xop8=0xf2
{
setSemaphore();
}
:SSEM rd is opcode=0x0 & rd & xop8=0xf3
{
setSemaphore();
}
# Store Byte to Memory (low byte)
:STB rd, (rs1, offs5) is opcode=0xa & rd & rs1 & offs5
{
dst:3 = XG_BASE + zext(rs1) + offs5;
local val:1 = rd:1;
*dst = val;
}
:STB rd, (rs1, rs2) is opcode=0xe & rd & rs1 & rs2 & op2=0x0
{
dst:3 = XG_BASE + zext(rs1) + zext(rs2);
local val:1 = rd:1;
*dst = val;
}
:STB rd, (rs1, rs2+) is opcode=0xe & rd & rs1 & rs2 & op2=0x1
{
dst:3 = XG_BASE + zext(rs1) + zext(rs2);
local val:1 = rd:1;
*dst = val;
rs2 = rs2 + 1;
}
:STB rd, (rs1, -rs2) is opcode=0xe & rd & rs1 & rs2 & op2=0x2
{
rs2 = rs2 - 1;
dst:3 = XG_BASE + zext(rs1) + zext(rs2);
local val:1 = rd:1;
*dst = val;
}
# Store Word to Memory
:STW rd, (rs1, offs5) is opcode=0xb & rd & rs1 & offs5
{
dst:3 = XG_BASE + zext(rs1) + offs5;
local val:2 = rd;
*dst = val;
}
:STW rd, (rs1, rs2) is opcode=0xf & rd & rs1 & rs2 & op2=0x0
{
dst:3 = XG_BASE + zext(rs1) + zext(rs2);
local val:2 = rd;
*dst = val;
rs2 = rs2 + 1;
}
:STW rd, (rs1, rs2+) is opcode=0xf & rd & rs1 & rs2 & op2=0x1
{
dst:3 = XG_BASE + zext(rs1) + zext(rs2);
local val:2 = rd;
*dst = val;
rs2 = rs2 + 2;
}
:STW rd, (rs1, -rs2) is opcode=0xf & rd & rs1 & rs2 & op2=0x2
{
rs2 = rs2 - 2;
dst:3 = XG_BASE + zext(rs1) + zext(rs2);
local val:2 = rd;
*dst = val;
}
# Subtract without Carry
:SUB rd, rs1, rs2 is opcode=0x3 & rd & rs1 & rs2 & op2=0x0
{
local result:2 = rs1 - rs2;
rd = result;
subtraction_flags(rs1, rs2, result);
}
# Subtract Immediate 8-bit constant (high byte)
:SUBH rd, ximm8 is opcode=0x19 & rd & ximm8
{
local val:2 = ximm8 << 8;
local result:2 = rd - val;
subtraction_flags(rd, val, result);
rd = result;
}
# Subtract Immediate 8-bit constant (low byte)
:SUBL rd, ximm8 is opcode=0x18 & rd & ximm8
{
local val:2 = ximm8;
local result:2 = rd - val;
$(XN) = (result s< 0);
$(XZ) = ((result == 0) & ($(XZ)==1));
$(XV) = ((~rd & result) & 0x8000) != 0;
$(XC) = ((rd & ~result) & 0x8000) != 0;
rd = result;
}
# Transfer from and to Special Registers
:TFR rd, XCCR is opcode=0x0 & rd & xop8=0xf8 & XCCR
{
local val:1 = ((($(XN) << 1) | $(XZ) << 1) | $(XV) << 1) | $(XC);
rd = zext(val);
}
:TFR XCCR, rd is opcode=0x0 & rd & xop8=0xf9 & XCCR
{
XCCR = rd & 0xf;
$(XN) = rd[3,1];
$(XZ) = rd[2,1];
$(XV) = rd[1,1];
$(XC) = rd[0,1];
}
:TFR rd, XPC is opcode=0x0 & rd & xop8=0xfa & XPC
{
rd = XPC + 2;
}
# Test Register
# Synonym for SUB R0, RS, R0
:TST rs1 is opcode=0x3 & reg8=0x0 & rs1 & reg2=0x0 & op2=0x0
{
local result:2 = rs1;
subtraction_flags(rs1,0,result);
}
# Logical Exclusive NOR
:XNOR rd, rs1, rs2 is opcode=0x2 & rd & rs1 & rs2 & op2=0x3
{
local result:2 = ~(rs1 ^ rs2);
rd = result;
default_flags(result);
}
# Logical Exclusive NOR Immediate 8-bit constant (high byte)
:XNORH rd, ximm8 is opcode=0x17 & rd & ximm8
{
local result:2 = ximm8 << 0xff;
rd = ~(rd ^ result);
default_flagsH(result);
}
# Logical Exclusive NOR Immediate 8-bit constant (low byte)
:XNORL rd, ximm8 is opcode=0x16 & rd & ximm8
{
local result:2 = ximm8 | 0xff00;
rd = ~(rd ^ result);
default_flagsL(result);
}
}

View File

@ -0,0 +1,356 @@
@S12XCPUV2.pdf[ CPU12/CPU12X Reference Manual, Rev. v01.04 21 Apr. 2016, nxp.com ]
ABA, 84
ABX, 85
ABY, 86
ADCA, 87
ADCB, 88
ADDA, 89
ADDB, 90
ADDD, 91
ADDX, 92
ADDY, 93
ADED, 94
ADEX, 95
ADEY, 96
ANDA, 97
ANDB, 98
ANDCC, 99
ANDX, 100
ANDY, 101
ASL, 102
ASLA, 103
ASLB, 104
ASLD, 105
ASLW, 106
ASLX, 107
ASLY, 108
ASR, 109
ASRA, 110
ASRB, 111
ASRW, 112
ASRX, 113
ASRY, 114
BCC, 115
BCLR, 116
BCS, 117
BEQ, 118
BGE, 119
BGND, 120
BGT, 121
BHI, 122
BHS, 123
BITA, 124
BITB, 125
BITX, 126
BITY, 127
BLE, 128
BLO, 129
BLS, 130
BLT, 131
BMI, 132
BNE, 133
BPL, 134
BRA, 135
BRCLR, 136
BRN, 137
BRSET, 138
BSET, 139
BSR, 140
BTAS, 141
BVC, 142
BVS, 143
CALL, 144
CBA, 145
CLC, 146
CLI, 147
CLR, 148
CLRA, 149
CLRB, 150
CLRW, 151
CLRX, 152
CLRY, 153
CLV, 154
CMPA, 155
CMPB, 156
COM, 157
COMA, 158
COMB, 159
COMW, 160
COMX, 161
COMY, 162
CPD, 163
CPED, 164
CPES, 165
CPEX, 166
CPEY, 167
CPS, 168
CPX, 169
CPY, 170
DAA, 171
DBEQ, 172
DBNE, 173
DEC, 174
DECA, 175
DECB, 176
DECW, 177
DECX, 178
DECY, 179
DES, 180
DEX, 181
DEY, 182
EDIV, 183
EDIVS, 184
EMACS, 185
EMAXD, 186
EMAXM, 187
EMIND, 188
EMINM, 189
EMUL, 190
EMULS, 191
EORA, 192
EORB, 193
EORX, 194
EORY, 195
ETBL, 196
EXG, 197
FDIV, 199
GLDAA, 200
GLDAB, 201
GLDD, 202
GLDS, 203
GLDX, 204
GLDY, 205
GSTAA, 206
GSTAB, 207
GSTD, 208
GSTS, 209
GSTX, 210
GSTY, 211
IBEQ, 212
IBNE, 213
IDIV, 214
IDIVS, 215
INC, 216
INCA, 217
INCB, 218
INCW, 219
INCX, 220
INCY, 221
INS, 222
INX, 223
INY, 224
JMP, 225
JSR, 226
LBCC, 227
LBCS, 228
LBEQ, 229
LBGE, 230
LBGT, 231
LBHI, 232
LBHS, 233
LBLE, 234
LBLO, 235
LBLS, 236
LBLT, 237
LBMI, 238
LBNE, 239
LBPL, 240
LBRA, 241
LBRN, 242
LBVC, 243
LBVS, 244
LDAA, 245
LDAB, 246
LDD, 247
LDS, 248
LDX, 249
LDY, 250
LEAS, 251
LEAX, 252
LEAY, 253
LSL, 254
LSLA, 255
LSLB, 256
LSLD, 257
LSLW, 258
LSLX, 259
LSLY, 260
LSR, 261
LSRA, 262
LSRB, 263
LSRD, 264
LSRW, 265
LSRX, 266
LSRY, 267
MAXA, 268
MAXM, 269
MEM, 270
MINA, 271
MINM, 272
MOVB, 273
MOVW, 280
MUL, 287
NEG, 288
NEGA, 289
NEGB, 290
NEGW, 291
NEGX, 292
NEGY, 293
NOP, 294
ORAA, 295
ORAB, 296
ORCC, 297
ORX, 298
ORY, 299
PSHA, 300
PSHB, 301
PSHC, 302
PSHCW, 303
PSHD, 304
PSHX, 305
PSHY, 306
PULA, 307
PULB, 308
PULC, 309
PULCW, 310
PULD, 311
PULX, 312
PULY, 313
REV, 314
REVW, 316
ROL, 318
ROLA, 319
ROLB, 320
ROLW, 321
ROLX, 322
ROLY, 323
ROR, 324
RORA, 325
RORB, 326
RORW, 327
RORX, 328
RORY, 329
RTC, 330
RTI, 331
RTS, 332
SBA, 333
SBCA, 334
SBCB, 335
SBED, 336
SBEX, 337
SBEY, 338
SEC, 339
SEI, 340
SEV, 341
SEX, 342
STAA, 343
STAB, 344
STD, 345
STOP, 346
STS, 348
STX, 349
STY, 350
SUBA, 351
SUBB, 352
SUBD, 353
SUBX, 354
SUBY, 355
SWI, 356
SYS, 357
TAB, 358
TAP, 359
TBA, 360
TBEQ, 361
TBL, 362
TBNE, 363
TFR, 364
TPA, 366
TRAP, 367
TST, 368
TSTA, 369
TSTB, 370
TSTW, 371
TSTX, 372
TSTY, 373
TSX, 374
TSY, 375
TXS, 376
TYS, 377
WAI, 378
WAV, 379
XGDX, 380
XGDY, 381
@MC9S12XEP100RMV1.pdf[ MC9S12XEP100 Reference Manual, Rev. 1.25 02/2013, nxp.com ]
ADC, 389
ADD, 390
ADDH, 391
ADDL, 392
AND, 393
ANDH, 394
ANDL, 395
ASR, 396
BCC, 397
BCS, 398
BEQ, 399
BFEXT, 400
BFFO, 401
BFINS, 402
BFINSI, 403
BFINSX, 404
BGE, 405
BGT, 406
BHI, 407
BHS, 408
BITH, 409
BITL, 410
BLE, 411
BLO, 412
BLS, 413
BLT, 414
BMI, 415
BNE, 416
BPL, 417
BRA, 418
BRK, 419
BVC, 420
BVS, 421
CMP, 422
CMPL, 423
COM, 424
CPC, 425
CPCH, 426
CSEM, 427
CSL, 428
CSR, 429
JAL, 430
LDB, 431
LDH, 432
LDL, 433
LDW, 434
LSL, 435
LSR, 436
MOV, 437
NEG, 438
NOP, 439
OR, 440
ORH, 441
ORL, 442
PAR, 443
ROL, 444
ROR, 445
RTS, 446
SBC, 447
SEX, 448
SIF, 449
SSEM, 450
STB, 451
STW, 452
SUB, 453
SUBH, 454
SUBL, 455
TFR, 456
TST, 457
XNOR, 458
XNORH, 459
XNORL, 460