diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/disassemble/Hcs12DisassembleCommand.java b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/disassemble/Hcs12DisassembleCommand.java new file mode 100644 index 0000000000..62a91bf02d --- /dev/null +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/disassemble/Hcs12DisassembleCommand.java @@ -0,0 +1,142 @@ +/* ### + * IP: GHIDRA + * REVIEWED: YES + * + * 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.app.cmd.disassemble; + +import ghidra.framework.model.DomainObject; +import ghidra.program.disassemble.DisassemblerContextImpl; +import ghidra.program.model.address.*; +import ghidra.program.model.lang.Register; +import ghidra.program.model.lang.RegisterValue; +import ghidra.program.model.listing.Program; +import ghidra.util.exception.CancelledException; +import ghidra.util.task.TaskMonitor; + +import java.math.BigInteger; + +/** + * Command object for performing HCS12/XGate disassembly + */ +public class Hcs12DisassembleCommand extends DisassembleCommand { + + private boolean xgMode; + + /** + * Constructor for Hcs12DisassembleCommand. + * @param startSet set of addresses to be the start of a disassembly. The + * Command object will attempt to start a disassembly at each address in this set. + * @param restrictedSet addresses that can be disassembled. + * a null set implies no restrictions + * @param xgMode pass true if the disassembling in XGATE Mode + */ + public Hcs12DisassembleCommand(AddressSetView startSet, AddressSetView restrictedSet, + boolean xgMode) { + super("Disassemble " + (xgMode ? "XGate" : "HCS12"), startSet, restrictedSet, true); + this.xgMode = xgMode; + } + + /** + * Constructor for DisassembleCommand. + * @param startSet set of addresses to be the start of a disassembly. The + * Command object will attempt to start a disassembly at each address in this set. + * @param restrictedSet addresses that can be disassembled. + * a null set implies no restrictions + * @param xgMode pass true if the disassembling in XGATE Mode + */ + public Hcs12DisassembleCommand(Address start, AddressSetView restrictedSet, boolean xgMode) { + this(new AddressSet(start, start), restrictedSet, xgMode); + useDefaultRepeatPatternBehavior = true; + } + + @Override + public void setSeedContext(DisassemblerContextImpl seedContext) { + throw new UnsupportedOperationException(); + } + + @Override + public void setInitialContext(RegisterValue initialContextValue) { + throw new UnsupportedOperationException(); + } + + /** + * + * @see ghidra.framework.cmd.BackgroundCommand#applyTo(ghidra.framework.model.DomainObject, ghidra.util.task.TaskMonitor) + */ + @Override + synchronized public boolean applyTo(DomainObject obj, TaskMonitor monitor) { + Program program = (Program) obj; + + disassemblyPerformed = false; + unalignedStart = false; + + // get the XGATE mode register and set accordingly + Register xgmodeReg = program.getProgramContext().getRegister("XGATE"); + RegisterValue xgmodeValue = null; + + // if doing xgate, and have no XGmode reg, no way to do disassemble in xgate + if (xgmodeReg == null) { + if (xgMode) { + return false; + } + } + else { + xgmodeValue = new RegisterValue(xgmodeReg, BigInteger.valueOf(xgMode ? 0x1 : 0x0)); + super.setInitialContext(xgmodeValue); + } + + int alignment = 1; + + // Set XGate Mode context on undefined code units only + try { + if (startSet != null) { + + // Align startSet so that context only affected at possible instruction starts + + AddressSet alignedSet = new AddressSet(); + for (AddressRange range : startSet) { + Address min = range.getMinAddress(); + long minOfffset = min.getOffset(); + if (minOfffset != min.getOffset()) { + min = min.getNewAddress(minOfffset); + } + Address max = range.getMaxAddress(); + long maxOffset = max.getOffset(); + if (maxOffset < minOfffset) { + // skip short unaligned range + continue; + } + if (maxOffset != max.getOffset()) { + max = max.getNewAddress(maxOffset); + } + alignedSet.addRange(min, max); + } + if (alignedSet.isEmpty()) { + unalignedStart = true; + return false; // alignedSet does not contain any aligned starts + } + startSet = program.getListing().getUndefinedRanges(alignedSet, true, monitor); + if (startSet.isEmpty()) { + return true; // startSet does not contain any aligned undefined starts + } + } + } + catch (CancelledException e) { + return true; + } + + return doDisassembly(monitor, program, alignment); + } +} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/disassembler/DisassemblerPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/disassembler/DisassemblerPlugin.java index 9f4fac5d3e..2a22ca800f 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/disassembler/DisassemblerPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/disassembler/DisassemblerPlugin.java @@ -83,6 +83,8 @@ public class DisassemblerPlugin extends Plugin { private DockingAction contextAction; private DockingAction armDisassembleAction; private DockingAction armThumbDisassembleAction; + private DockingAction hcs12DisassembleAction; + private DockingAction xgateDisassembleAction; private DockingAction mipsDisassembleAction; private DockingAction mips16DisassembleAction; private DockingAction ppcDisassembleAction; @@ -172,6 +174,8 @@ public class DisassemblerPlugin extends Plugin { contextAction = new ContextAction(this, GROUP_NAME); armDisassembleAction = new ArmDisassembleAction(this, GROUP_NAME, false); armThumbDisassembleAction = new ArmDisassembleAction(this, GROUP_NAME, true); + hcs12DisassembleAction = new Hcs12DisassembleAction(this, GROUP_NAME, false); + xgateDisassembleAction = new Hcs12DisassembleAction(this, GROUP_NAME, true); mipsDisassembleAction = new MipsDisassembleAction(this, GROUP_NAME, false); mips16DisassembleAction = new MipsDisassembleAction(this, GROUP_NAME, true); ppcDisassembleAction = new PowerPCDisassembleAction(this, GROUP_NAME, false); @@ -183,6 +187,8 @@ public class DisassemblerPlugin extends Plugin { tool.addAction(disassembleStaticAction); tool.addAction(armDisassembleAction); tool.addAction(armThumbDisassembleAction); + tool.addAction(hcs12DisassembleAction); + tool.addAction(xgateDisassembleAction); tool.addAction(mipsDisassembleAction); tool.addAction(mips16DisassembleAction); tool.addAction(ppcDisassembleAction); @@ -350,6 +356,30 @@ public class DisassemblerPlugin extends Plugin { } } + public void disassembleHcs12Callback(ListingActionContext context, boolean xgMode) { + ProgramSelection currentSelection = context.getSelection(); + ProgramLocation currentLocation = context.getLocation(); + Program currentProgram = context.getProgram(); + Hcs12DisassembleCommand cmd = null; + + if ((currentSelection != null) && (!currentSelection.isEmpty())) { + cmd = new Hcs12DisassembleCommand(currentSelection, null, xgMode); + } + else { + Address addr = currentLocation.getAddress(); + try { + currentProgram.getMemory().getByte(addr); + cmd = new Hcs12DisassembleCommand(addr, null, xgMode); + } + catch (MemoryAccessException e) { + tool.setStatusInfo("Can't disassemble unitialized memory!", true); + } + } + if (cmd != null) { + tool.executeBackgroundCommand(cmd, currentProgram); + } + } + public void disassembleMipsCallback(ListingActionContext context, boolean mips16) { ProgramSelection currentSelection = context.getSelection(); ProgramLocation currentLocation = context.getLocation(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/disassembler/Hcs12DisassembleAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/disassembler/Hcs12DisassembleAction.java new file mode 100644 index 0000000000..23f6c893aa --- /dev/null +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/disassembler/Hcs12DisassembleAction.java @@ -0,0 +1,84 @@ +/* ### + * 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.app.plugin.core.disassembler; + +import java.awt.event.KeyEvent; + +import docking.action.KeyBindingData; +import docking.action.MenuData; +import ghidra.app.context.ListingActionContext; +import ghidra.app.context.ListingContextAction; +import ghidra.program.model.address.Address; +import ghidra.program.model.lang.*; +import ghidra.program.model.listing.Program; + + +/** + * Action for HCS12 mode disassembly + */ + +class Hcs12DisassembleAction extends ListingContextAction { + private DisassemblerPlugin plugin; + private boolean disassembleXgate = false; + + public Hcs12DisassembleAction(DisassemblerPlugin plugin, String groupName, boolean disassembleXgate) { + super("Disassemble " + (disassembleXgate ? "HCS12" : "XGate"), plugin.getName()); + + this.plugin = plugin; + this.disassembleXgate = disassembleXgate; + + setPopupMenuData( new MenuData( + new String[]{"Disassemble - "+ (disassembleXgate ? "XGate" : "HCS12") }, + null, + groupName ) ); + + int keyEvent = (disassembleXgate ? KeyEvent.VK_F12 : KeyEvent.VK_F11); + setKeyBindingData( new KeyBindingData( keyEvent, 0 ) ); + } + + @Override + public void actionPerformed(ListingActionContext context) { + plugin.disassembleHcs12Callback(context, disassembleXgate); + } + + @Override + public boolean isEnabledForContext(ListingActionContext context) { + + // Action only intended for use where Xgate instructions are available. + // The presence of the XGATE context register can be used for this + // determination. + + Address address = context.getAddress(); + if ( address == null ) { + return false; + } + + Program program = context.getProgram(); + Language lang = program.getLanguage(); + Processor proc = lang.getProcessor(); + + if (!"HCS12".equals(proc.toString())) { + return false; + } + + Register register = context.getProgram().getProgramContext().getRegister("XGATE"); + if (register == null) { + return false; + } + + return plugin.checkDisassemblyEnabled(context, address, true); + } +} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/extend/ElfLoadAdapter.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/extend/ElfLoadAdapter.java index 3da7000d45..0a7959ada9 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/extend/ElfLoadAdapter.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/extend/ElfLoadAdapter.java @@ -143,6 +143,29 @@ public class ElfLoadAdapter { // segment is not marked execute, use the data space by default return program.getLanguage().getDefaultDataSpace(); } + + + /** + * Get the preferred load address for a program segment + * @param elfLoadHelper load helper object + * @param elfProgramHeader elf program segment header + * @return preferred load address + */ + public Address getPreferredSegmentAddress(ElfLoadHelper elfLoadHelper, ElfProgramHeader elfProgramHeader) { + + Program program = elfLoadHelper.getProgram(); + + AddressSpace space = + getPreferredSegmentAddressSpace(elfLoadHelper, elfProgramHeader); + + long addrWordOffset = elfProgramHeader.getVirtualAddress(); + + if (space == program.getAddressFactory().getDefaultAddressSpace()) { + addrWordOffset += elfLoadHelper.getImageBaseWordAdjustmentOffset(); + } + + return space.getTruncatedAddress(addrWordOffset, true); + } /** * Get the default alignment within the default address space. @@ -174,6 +197,27 @@ public class ElfLoadAdapter { // segment is not marked execute, use the data space by default return program.getLanguage().getDefaultDataSpace(); } + + /** + * Get the preferred load address for a program section + * @param elfLoadHelper load helper object + * @param elfSectionHeader elf program section header + * @return preferred load address + */ + public Address getPreferredSectionAddress(ElfLoadHelper elfLoadHelper, + ElfSectionHeader elfSectionHeader) { + Program program = elfLoadHelper.getProgram(); + + AddressSpace space = getPreferredSectionAddressSpace(elfLoadHelper, elfSectionHeader); + + long addrWordOffset = elfSectionHeader.getAddress(); + + if (space == program.getAddressFactory().getDefaultAddressSpace()) { + addrWordOffset += elfLoadHelper.getImageBaseWordAdjustmentOffset(); + } + + return space.getTruncatedAddress(addrWordOffset, true); + } /** * Check if this extension can handle the specified elf header. If this method returns @@ -429,5 +473,4 @@ public class ElfLoadAdapter { public Class getRelocationClass(ElfHeader elfHeader) { return null; } - } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java index 7dffceadb3..9928e3b71c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java @@ -2170,16 +2170,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { private Address getPreferredSegmentLoadAddress(ElfProgramHeader elfProgramHeader) throws AddressOutOfBoundsException { - AddressSpace space = - elf.getLoadAdapter().getPreferredSegmentAddressSpace(this, elfProgramHeader); - - long addrWordOffset = elfProgramHeader.getVirtualAddress(); - - if (space == getDefaultAddressSpace()) { - addrWordOffset += getImageBaseWordAdjustmentOffset(); - } - - return space.getTruncatedAddress(addrWordOffset, true); + return elf.getLoadAdapter().getPreferredSegmentAddress(this, elfProgramHeader); } /** @@ -2216,15 +2207,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { private Address getPreferredSectionLoadAddress(ElfSectionHeader elfSectionHeader) throws AddressOutOfBoundsException { - AddressSpace space = getPreferredSectionAddressSpace(elfSectionHeader); - - long addrWordOffset = elfSectionHeader.getAddress(); - - if (space == getDefaultAddressSpace()) { - addrWordOffset += getImageBaseWordAdjustmentOffset(); - } - - return space.getTruncatedAddress(addrWordOffset, true); + return elf.getLoadAdapter().getPreferredSectionAddress(this, elfSectionHeader); } @Override diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/CommitParamsAction.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/CommitParamsAction.java index 5bb5d6e7b1..b00fd7ed94 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/CommitParamsAction.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/CommitParamsAction.java @@ -83,8 +83,9 @@ public class CommitParamsAction extends AbstractDecompilerAction { if (hfunc.getFunction().getSignatureSource() == SourceType.USER_DEFINED) { source = SourceType.USER_DEFINED; } - HighFunctionDBUtil.commitParamsToDatabase(hfunc, true, source); + HighFunctionDBUtil.commitReturnToDatabase(hfunc, source); + HighFunctionDBUtil.commitParamsToDatabase(hfunc, true, source); } catch (DuplicateNameException e) { throw new AssertException("Unexpected exception", e); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/listing/VariableUtilities.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/listing/VariableUtilities.java index f6a9e0295e..a88c2c80a5 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/listing/VariableUtilities.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/listing/VariableUtilities.java @@ -415,6 +415,8 @@ public class VariableUtilities { " bytes: " + curStorage.toString()); } } + + vnAddr = newReg.getAddress(); if (bigEndian) { vnAddr = vnAddr.add(newReg.getMinimumByteSize() - size); return new Varnode(vnAddr, size); diff --git a/Ghidra/Processors/HCS12/Module.manifest b/Ghidra/Processors/HCS12/Module.manifest new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Ghidra/Processors/HCS12/build.gradle b/Ghidra/Processors/HCS12/build.gradle new file mode 100644 index 0000000000..2cfe0295d5 --- /dev/null +++ b/Ghidra/Processors/HCS12/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 HCS12' + diff --git a/Ghidra/Processors/HCS12/certification.manifest b/Ghidra/Processors/HCS12/certification.manifest new file mode 100644 index 0000000000..929bc8b859 --- /dev/null +++ b/Ghidra/Processors/HCS12/certification.manifest @@ -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| diff --git a/Ghidra/Processors/HCS12/data/languages/HCS12.cspec b/Ghidra/Processors/HCS12/data/languages/HCS12.cspec new file mode 100644 index 0000000000..17a93d7bc5 --- /dev/null +++ b/Ghidra/Processors/HCS12/data/languages/HCS12.cspec @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + R7 = SP; + + + + diff --git a/Ghidra/Processors/HCS12/data/languages/HCS12.ldefs b/Ghidra/Processors/HCS12/data/languages/HCS12.ldefs new file mode 100644 index 0000000000..dc9cc2f7c2 --- /dev/null +++ b/Ghidra/Processors/HCS12/data/languages/HCS12.ldefs @@ -0,0 +1,17 @@ + + + + + HCS12X Microcontroller Family + + + + diff --git a/Ghidra/Processors/HCS12/data/languages/HCS12.opinion b/Ghidra/Processors/HCS12/data/languages/HCS12.opinion new file mode 100644 index 0000000000..97dcaa03b5 --- /dev/null +++ b/Ghidra/Processors/HCS12/data/languages/HCS12.opinion @@ -0,0 +1,6 @@ + + + + + + diff --git a/Ghidra/Processors/HCS12/data/languages/HCS12.pspec b/Ghidra/Processors/HCS12/data/languages/HCS12.pspec new file mode 100644 index 0000000000..90fb9f51c1 --- /dev/null +++ b/Ghidra/Processors/HCS12/data/languages/HCS12.pspec @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Ghidra/Processors/HCS12/data/languages/HCS12.slaspec b/Ghidra/Processors/HCS12/data/languages/HCS12.slaspec new file mode 100644 index 0000000000..5421a5d192 --- /dev/null +++ b/Ghidra/Processors/HCS12/data/languages/HCS12.slaspec @@ -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" \ No newline at end of file diff --git a/Ghidra/Processors/HCS12/data/languages/HCS_HC12.sinc b/Ghidra/Processors/HCS12/data/languages/HCS_HC12.sinc new file mode 100644 index 0000000000..451bfb0a2a --- /dev/null +++ b/Ghidra/Processors/HCS12/data/languages/HCS_HC12.sinc @@ -0,0 +1,5791 @@ +# common include file for HCS12, and HC12 constructors + +define endian=big; +define alignment=1; + +define space RAM type=ram_space size=3 default; +define space register type=register_space size=2; + +@define VECTOR_SWI "0xFFF6" +@define VECTOR_TRAP "0xFFF8" + +################################################################ +# Registers +################################################################ + +define register offset=0x00 size=1 [ A B ]; +define register offset=0x00 size=2 [ D ]; + +# IX also referred to as X or x; but must be distinct from X bit in CCR +# IY also referred to as Y or y; made IY to be consistent with IX +define register offset=0x10 size=2 [ IX IY TMP2 TMP3 TMP1 ]; +define register offset=0x10 size=1 [ IXH IXL IYH IYL TMP2H TMP2L TMP3H TMP3L TMP1H TMP1L ]; + +#define register offset=0x20 size=3 [ _ PCE _ SPE ]; +define register offset=0x20 size=3 [ _ PCE ]; +define register offset=0x20 size=2 [ _ _ PC _ _ SP ]; +define register offset=0x20 size=1 [ _ _ _ _ PCH PCL _ _ _ _ SPH SPL ]; + +define register offset=0x30 size=2 [ CCRW ]; +define register offset=0x30 size=1 [ CCRH ]; + +define register offset=0x31 size=1 [ CCR ]; + +define register offset = 0x32 size=3 [physPage]; + + +define RAM offset=0x10 size=1 [GPAGE]; +define RAM offset=0x11 size=1 [DIRECT]; +define RAM offset=0x16 size=1 [RPAGE]; +define RAM offset=0x17 size=1 [EPAGE]; +define RAM offset=0x30 size=1 [PPAGE]; + + +# Define context bits +# WARNING: when adjusting context keep compiler packing in mind +# and make sure fields do not span a 32-bit boundary before or +# after context packing +define register offset=0x40 size=4 contextreg; +define context contextreg + Prefix18 = (0,0) # 1 if 0x18 is the first byte + PrefixHCS12X = (0,0) # 1 if first byte is 0x18 so that HCS12X to use GPAGE for memory access + UseGPAGE = (1,1) # 1 if should use GPAGE concatenated to lower 16-bit EA + XGATE = (2,2) # 1 if in xgate instruction decode mode +; + + +# individual status bits within CCRH + +@define IPL_2 "CCRH[2,1]" +@define IPL_1 "CCRH[1,1]" +@define IPL_0 "CCRH[0,1]" + +@define IPL "CCRH[0,3]" # entire IPL + +# individual status bits within CCR + +@define S "CCR[7,1]" # STOP Enable +@define X "CCR[6,1]" # Non-maskable interrupt control bit +@define H "CCR[5,1]" # Half Carry Flag +@define I "CCR[4,1]" # Maskable interrupt control bit +@define N "CCR[3,1]" # Negative Flag +@define Z "CCR[2,1]" # Zero Flag +@define V "CCR[1,1]" # Two's complement overflow Flag +@define C "CCR[0,1]" # Carry/Borrow Flag + +################################################################ +# Tokens +################################################################ + +define token opbyte8 (8) + op8 = (0,7) + op7_4 = (4,7) + op6_4 = (4,6) + nIndex = (1,3) + op0_0 = (0,0) + trapnum = (0,7) +; + +define token xb8 (8) + rr7_6 = (6,7) + rr7_6a = (6,7) + xb5_5 = (5,5) + nn4_0 = (0,4) signed + + xb7_5 = (5,7) + rr4_3 = (3,4) + xb2_2 = (2,2) + xb2_1 = (1,2) # actually needed this instead of xb2_2 + z1_1 = (1,1) + s0_0 = (0,0) + + xb2_0 = (0,2) + + p4_4 = (4,4) + decrement3_3 = (3,3) + nn3_0 = (0,3) + + aa1_0 = (0,1) + aa0_0 = (0,0) # actually needed this instead of aa1_0 +; + +define token eb8 (8) + notUsed7_7 = (7,7) + abcdxys6_4 = (4,6) + abc5_4 = (4,5) + dxys2_0 = (0,2) + abcdxys2_0 = (0,2) + columns7_4 = (4,7) + rows2_0 = (0,2) + rows3_0 = (0,3) + bytes_ABCl_6_4 = (4,6) + bytes_ABClT3lBXlYlSl_6_4 = (4,6) + bytes_ABChT3hBXhYhSh_6_4 = (4,6) + words_CT3DXYS_6_4 = (4,6) + words_T3DXYS_6_4 = (4,6) + bytes_ABCl_2_0 = (0,2) + bytes_T3lDlXlYlSl_6_4 = (4,6) + words_T2DXYS_2_0 = (0,2) + bytes_T2h_XhYhSh_2_0 = (0,2) + bytes_T2l_XlYlSl_2_0 = (0,2) + bytes_T3l_XlYlSl_6_4 = (4,6) + bytes_T3h_XhYhSh_6_4 = (4,6) + words_T3_XYS_6_4 = (4,6) + bytes_T2hDhXhYhSh_2_0 = (0,2) + bytes_T2lDlXlYlSl_2_0 = (0,2) +; + +define token opbyte16 (16) + op16 = (0,15) + op15_13 = (13,15) + sign12_12 = (12,12) signed + not_used11 = (11,11) + size10_10 = (10,10) + byte9_8 = (8,9) + word9_8 = (8,9) + rr7_0 = (0,7) +; + +define token data8 (8) + imm8 = (0,7) + simm8 = (0,7) signed + rel = (0,7) signed +; + +define token data16 (16) + imm16 = (0,15) + imm16p = (12,15) + imm16e = (8,15) + imm16ev = (0,9) + imm16rv = (0,11) + imm16pv = (0,13) + simm16 = (0,15) signed +; + +attach variables [ rr7_6 rr4_3 ] [ IX IY SP PC ]; +attach variables [ rr7_6a ] [ IX IY SP _ ]; # PC not valid choice in this case + +# TODO would be great if this worked +# attach names [ rr7_6 rr4_3 ] [ "X" "Y" "SP" "PC" ]; + + +# TODO do the negative values work? +attach values [ nn3_0 ] [ 1 2 3 4 5 6 7 8 -8 -7 -6 -5 -4 -3 -2 -1 ]; + +attach variables [ aa0_0 ] [ A B ]; + +attach variables [ byte9_8 ] [ A B _ _ ]; + +attach variables [ word9_8 ] [ D IX IY SP ]; + +attach variables [ abc5_4 ] [ A B CCR _ ]; + +attach variables [ dxys2_0 ] [ _ _ _ TMP2 D IX IY SP ]; + +attach variables [ bytes_ABCl_2_0 ] [ A B CCR _ _ _ _ _ ]; + +attach variables [ bytes_ABClT3lBXlYlSl_6_4 ] [ A B CCR TMP3L B IXL IYL SPL ]; + +attach variables [ bytes_ABChT3hBXhYhSh_6_4 ] [ A B CCRH TMP3H B IXH IYH SPH ]; + +attach variables [ words_T2DXYS_2_0 ] [ _ _ _ TMP2 D IX IY SP ]; + +attach variables [ bytes_T3lDlXlYlSl_6_4 ] [ _ _ _ TMP3L B IXL IYL SPL ]; + +attach variables [ words_T3DXYS_6_4 ] [ _ _ _ TMP3 D IX IY SP ]; + +attach variables [ words_CT3DXYS_6_4 ] [ _ _ CCRW TMP3 D IX IY SP ]; + +attach variables [ bytes_T2l_XlYlSl_2_0 ] [ _ _ _ TMP2L _ IXL IYL SPL ]; + +attach variables [ bytes_T2h_XhYhSh_2_0 ] [ _ _ _ TMP2H _ IXH IYH SPH ]; + +attach variables [ bytes_T3l_XlYlSl_6_4 ] [ _ _ _ TMP3L _ IXL IYL SPL ]; + +attach variables [ bytes_T3h_XhYhSh_6_4 ] [ _ _ _ TMP3H _ IXH IYH SPH ]; + +attach variables [ words_T3_XYS_6_4 ] [ _ _ _ TMP3 _ IX IY SP ]; + +attach variables [ bytes_ABCl_6_4 ] [ A B CCR _ _ _ _ _ ]; + +attach variables [ bytes_T2hDhXhYhSh_2_0 ] [ _ _ _ TMP2H A IXH IYH SPH ]; + +attach variables [ bytes_T2lDlXlYlSl_2_0 ] [ _ _ _ TMP2L B IXL IYL SPL ]; + +################################################################ +# Pseudo Instructions +################################################################ +define pcodeop segment; # Define special pcodeop that calculates the RAM address +# given the segment selector and offset as input + +define pcodeop readIRQ; +define pcodeop stop; +define pcodeop WaitForInterrupt; + +define pcodeop decimalAdjustAccumulator; +define pcodeop decimalAdjustCarry; +define pcodeop EMACS; +define pcodeop ETBL; +define pcodeop ETBL_Cflag; +define pcodeop GradeOfMembership; +define pcodeop TableLookupAndInterpolate; +define pcodeop TableLookupAndInterpolateRoundable; +define pcodeop WeightedAverageSOPHigh; +define pcodeop WeightedAverageSOPLow; +define pcodeop WeightedAverageSOW; +define pcodeop WeightedAverageResume; +define pcodeop MinMaxRuleEvaluation; +define pcodeop MinMaxRuleEvaluationCorrect; +define pcodeop MinMaxRuleEvaluationWeighted; +define pcodeop MinMaxRuleEvaluationWeightedCorrect; + +define pcodeop backgroundDebugMode; + +macro setHCSphysPage(addr) { + local a3:3 = zext(addr); + + local isReg:1 = (a3 & 0xfC00) == 0x0; + local isEpage:1 = (a3 & 0xfc00) ==0x800; + local isEpage_FF:1 = (a3 & 0xfc00) ==0xC00; + local isRpage:1 = (a3 & 0xf000) ==0x1000; + local isRpage_FE:1 = (a3 & 0xf000) ==0x2000; + local isRpage_FF:1 = (a3 & 0xf000) ==0x3000; + local isPpage_FD:1 = (a3 & 0xc000) ==0x4000; + local isPpage:1 = (a3 & 0xc000) ==0x8000; + local isPpage_FF:1 = (a3 & 0xc000) ==0xC000; + + physPage = (zext(isReg) * 0x0) + + (zext(isEpage) * (0x100000 | ((zext(EPAGE) << 10) ^ 0x800))) + + (zext(isEpage_FF) * ((0x4FF << 10) ^ 0xC00)) + + (zext(isRpage) * (((zext(RPAGE) << 12) ^ 0x1000))) + + (zext(isRpage_FE) * (((0xFE << 12) ^ 0x2000))) + + (zext(isRpage_FF) * (((0xFF << 12) ^ 0x3000))) + + (zext(isPpage_FD) * (0x400000 | ((0x3F4000) ^ 0x4000))) + + (zext(isPpage) * (0x400000 | ((zext(PPAGE) << 14 ) ^ 0x8000))) + + (zext(isPpage_FF) * (0x400000 | ((0x3FC000) ^ 0xC000))) ; +} + +macro Load1(value, addr) { + setHCSphysPage(addr); + + local paddr:3 = segment(physPage, addr); + value = *:1 paddr; +} +macro Load2(value, addr) { + setHCSphysPage(addr); + + local paddr:3 = segment(physPage, addr); + value = *:2 paddr; +} + +macro GetPagedAddr(addr,paddr) { + setHCSphysPage(addr); + + paddr = segment(physPage, addr); +} + +macro Store(addr, value) { + setHCSphysPage(addr); + + local paddr:3 = segment(physPage, addr); + + *paddr = value; +} + +################################################################ +# Addressing tables +################################################################ + +# +# TODO: Paging could be added here as these are constant addresses +# could factor the overlapping addresses here, unless the +# page register is always added in then will have to export as a constant +# since don't know the real address +# + +# known EPAGE offsets +opr16a: imm16 is imm16e=0x8 & imm16 & imm16ev { local addr:3 = 0x100000 | (zext(EPAGE) << 10) | imm16ev; export addr; } +opr16a: imm16 is imm16e=0x9 & imm16 & imm16ev { local addr:3 = 0x100000 | (zext(EPAGE) << 10) | imm16ev; export addr; } +opr16a: imm16 is imm16e=0xa & imm16 & imm16ev { local addr:3 = 0x100000 | (zext(EPAGE) << 10) | imm16ev; export addr; } +opr16a: imm16 is imm16e=0xb & imm16 & imm16ev { local addr:3 = 0x100000 | (zext(EPAGE) << 10) | imm16ev; export addr; } + +opr16a: imm16 is imm16e=0xc & imm16 & imm16ev { local addr:3 = (0xFF << 10) | imm16ev; export addr; } +opr16a: imm16 is imm16e=0xd & imm16 & imm16ev { local addr:3 = (0xFF << 10) | imm16ev; export addr; } +opr16a: imm16 is imm16e=0xe & imm16 & imm16ev { local addr:3 = (0xFF << 10) | imm16ev; export addr; } +opr16a: imm16 is imm16e=0xf & imm16 & imm16ev { local addr:3 = (0xFF << 10) | imm16ev; export addr; } + +# known RPAGE offsets +opr16a: imm16 is imm16p=0x1 & imm16 & imm16rv { local addr:3 = (zext(RPAGE) << 12) | imm16rv; export addr; } +opr16a: imm16 is imm16p=0x2 & imm16 & imm16rv { local addr:3 = (0xFE << 12) | imm16rv; export addr; } +opr16a: imm16 is imm16p=0x3 & imm16 & imm16rv { local addr:3 = (0xFF << 12) | imm16rv; export addr; } + +# known PPAGE offsets +opr16a: imm16 is imm16p=0x4 & imm16 & imm16pv { local addr:3 = 0x400000 | (0xFD << 14) | imm16pv; export addr; } +opr16a: imm16 is imm16p=0x5 & imm16 & imm16pv { local addr:3 = 0x400000 | (0xFD << 14) | imm16pv; export addr; } +opr16a: imm16 is imm16p=0x6 & imm16 & imm16pv { local addr:3 = 0x400000 | (0xFD << 14) | imm16pv; export addr; } +opr16a: imm16 is imm16p=0x7 & imm16 & imm16pv { local addr:3 = 0x400000 | (0xFD << 14) | imm16pv; export addr; } + +opr16a: imm16 is imm16p=0x8 & imm16 & imm16pv { local addr:3 = 0x400000 | (zext(PPAGE) << 14) | (imm16pv & 0x3fff); export addr; } +opr16a: imm16 is imm16p=0x9 & imm16 & imm16pv { local addr:3 = 0x400000 | (zext(PPAGE) << 14) | (imm16pv & 0x3fff); export addr; } +opr16a: imm16 is imm16p=0xa & imm16 & imm16pv { local addr:3 = 0x400000 | (zext(PPAGE) << 14) | (imm16pv & 0x3fff); export addr; } +opr16a: imm16 is imm16p=0xb & imm16 & imm16pv { local addr:3 = 0x400000 | (zext(PPAGE) << 14) | (imm16pv & 0x3fff); export addr; } + +opr16a: imm16 is imm16p=0xC & imm16 & imm16pv { local addr:3 = 0x400000 | (0xFF << 14) | imm16pv; export addr; } +opr16a: imm16 is imm16p=0xD & imm16 & imm16pv { local addr:3 = 0x400000 | (0xFF << 14) | imm16pv; export addr; } +opr16a: imm16 is imm16p=0xE & imm16 & imm16pv { local addr:3 = 0x400000 | (0xFF << 14) | imm16pv; export addr; } +opr16a: imm16 is imm16p=0xF & imm16 & imm16pv { local addr:3 = 0x400000 | (0xFF << 14) | imm16pv; export addr; } + +opr16a: imm16 is imm16e & imm16 { local addr:3 = imm16; export addr; } + +opr8a: imm8 is imm8 { export *[const]:3 imm8; } + +opr8a_8: imm8 is UseGPAGE=0 & imm8 { export *:1 imm8; } +opr8a_8: imm8 is UseGPAGE=1 & imm8 { local addr:3 = (zext(GPAGE) << 16) | imm8; export *:1 addr; } +opr8a_16: imm8 is UseGPAGE=0 & imm8 { export *:2 imm8; } +opr8a_16: imm8 is UseGPAGE=1 & imm8 { local addr:3 = (zext(GPAGE) << 16) | imm8; export *:2 addr; } + +opr16a_8: opr16a is UseGPAGE=0 & opr16a { export *:1 opr16a; } +opr16a_8: imm16 is UseGPAGE=1 & imm16 { local addr:3 = (zext(GPAGE) << 16) | imm16; export *:1 addr; } +opr16a_16: opr16a is UseGPAGE=0 & opr16a { export *:2 opr16a; } +opr16a_16: imm16 is UseGPAGE=1 & imm16 { local addr:3 = (zext(GPAGE) << 16) | imm16; export *:2 addr; } + +iopr8i: "#"imm8 is imm8 { export *[const]:1 imm8; } +iopr16i: "#"imm16 is imm16 { export *[const]:2 imm16; } +msk8: imm8 is imm8 { export *[const]:1 imm8; } +page: imm8 is imm8 { export *[const]:1 imm8; } + +#PageDest: dest is imm16p=0x8 & imm16 & imm16pv ; imm8 [ dest = (imm8 << 16) | imm16; ] { export *:1 dest; } +#PageDest: dest is imm16p=0x9 & imm16 & imm16pv ; imm8 [ dest = (imm8 << 16) | imm16; ] { export *:1 dest; } +#PageDest: dest is imm16p=0xa & imm16 & imm16pv ; imm8 [ dest = (imm8 << 16) | imm16; ] { export *:1 dest; } +#PageDest: dest is imm16p=0xb & imm16 & imm16pv ; imm8 [ dest = (imm8 << 16) | imm16; ] { export *:1 dest; } +#PageDest: dest is imm16p=0xc & imm16 & imm16pv ; imm8 [ dest = ($(MAXFLASHPage) << 16) | imm16; ] { export *:1 dest; } +#PageDest: dest is imm16p=0xd & imm16 & imm16pv ; imm8 [ dest = ($(MAXFLASHPage) << 16) | imm16; ] { export *:1 dest; } +#PageDest: dest is imm16p=0xe & imm16 & imm16pv ; imm8 [ dest = ($(MAXFLASHPage) << 16) | imm16; ] { export *:1 dest; } +#PageDest: dest is imm16p=0xf & imm16 & imm16pv ; imm8 [ dest = ($(MAXFLASHPage) << 16) | imm16; ] { export *:1 dest; } +PageDest: opr16a is opr16a; page { export opr16a; } + +# +# Postbyte Code (xb) address decoding +# for indexed addressing modes: IDX, IDX1, IDX2, [D,IDX] and [IDX2] +# +# +# per page 29, 30, and 33 +# + +#********** +# IDX +#********** +# +# rr0nnnnn +# +# 5-bit constant offset n = -16 to +15 +IDX_a: 0,rr7_6 is rr7_6 & xb5_5=0 & nn4_0=0 + { export rr7_6; } + +# TODO make sure that nn4_0 is a signed extension +IDX_b: nn4_0, rr7_6 is rr7_6 & xb5_5=0 & nn4_0 + { address:2 = rr7_6 + nn4_0; export address; } + +# rr1pnnnn +# +# used xb7_5 in all of these to prevent rr7_6a from ever being 0b11, and overlapping the 111rr0zs decodes +# +# Auto pre-decrement +IDX_c: nn3_0, -rr7_6a is (xb7_5=0b001 | xb7_5=0b011 | xb7_5=0b101) & rr7_6a & p4_4=0 & decrement3_3=1 & nn3_0 + { rr7_6a = rr7_6a + nn3_0; address:2 = rr7_6a; export address; } + +# Auto pre-increment +IDX_d: nn3_0, +rr7_6a is (xb7_5=0b001 | xb7_5=0b011 | xb7_5=0b101) & rr7_6a & p4_4=0 & decrement3_3=0 & nn3_0 + { rr7_6a = rr7_6a + nn3_0; address:2 = rr7_6a; export address; } + +# Auto post-decrement +IDX_e: nn3_0, rr7_6a- is (xb7_5=0b001 | xb7_5=0b011 | xb7_5=0b101) & rr7_6a & p4_4=1 & decrement3_3=1 & nn3_0 + { address:2 = rr7_6a; rr7_6a = rr7_6a + nn3_0; export address; } + +# Auto post-increment +IDX_f: nn3_0, rr7_6a+ is (xb7_5=0b001 | xb7_5=0b011 | xb7_5=0b101) & rr7_6a & p4_4=1 & decrement3_3=0 & nn3_0 + { address:2 = rr7_6a; rr7_6a = rr7_6a + nn3_0; export address; } + +# 111rr1aa +# +# Accumulator unsigned 8-bit offset indexed +IDX_g: aa0_0, rr4_3 is xb7_5=0b111 & rr4_3 & xb2_1=0b10 & aa0_0 + { address:2 = rr4_3 + zext(aa0_0); export address; } + +# Accumulator 16-bit offset indexed +IDX_h: D, rr4_3 is xb7_5=0b111 & rr4_3 & xb2_0=0b110 & D + { address:2 = rr4_3 + D; export address; } + + +#********** +# IDX1 +#********** +# +# 111rr0zs imm8 +# +# Constant offset (9-bit signed, positive) +IDX_i: imm8, rr4_3 is xb7_5=0b111 & rr4_3 & xb2_2=0 & z1_1=0 & s0_0=0; imm8 + { address:2 = rr4_3 + imm8; export address; } + +# Constant offset (9-bit signed, negative) +# TODO make sure that the -256 case works +IDX_j: -neg, rr4_3 is xb7_5=0b111 & rr4_3 & xb2_2=0 & z1_1=0 & s0_0=1; imm8 [ neg = -imm8; ] + { address:2 = rr4_3 - neg; export address; } + + +#********** +# IDX2 +#********** +# +# 111rr0zs simm16 +# +# Constant offset (16-bit signed) +IDX_k: simm16, rr4_3 is xb7_5=0b111 & rr4_3 & xb2_2=0 & z1_1=1 & s0_0=0; simm16 + { address:2 = rr4_3 + simm16; export address; } + +#********** +# [IDX2] +#********** +# +# 111rr011 simm16 +# +# 16-bit offset indexed-indirect + +IDX_l: [simm16, rr4_3] is xb7_5=0b111 & rr4_3 & xb2_2=0 & z1_1=1 & s0_0=1; simm16 + { address:2 = rr4_3 + simm16; Load2(address,address); export address; } + +IDX_l: [simm16, PC] is xb7_5=0b111 & rr4_3=3 & xb2_2=0 & z1_1=1 & s0_0=1; simm16 & PC + { address:2 = inst_next + simm16; Load2(address,address); export address; } + +#********** +# [D,IDX] +#********** +# +# 111rr111 +# +# Accumulator D offset indexed-indirect +IDX_m: [D, rr4_3] is xb7_5=0b111 & rr4_3 & xb2_0=0b111 & D + { address:2 = rr4_3 + D; Load2(address,address); export address; } + + +###################################################################### +###################################################################### +# +# effective address of IDX, IDX1, IDX2 +# +indexed3: IDX_a is IDX_a { export IDX_a; } +indexed3: IDX_b is IDX_b { export IDX_b; } +indexed3: IDX_c is IDX_c { export IDX_c; } +indexed3: IDX_d is IDX_d { export IDX_d; } +indexed3: IDX_e is IDX_e { export IDX_e; } +indexed3: IDX_f is IDX_f { export IDX_f; } +indexed3: IDX_g is IDX_g { export IDX_g; } +indexed3: IDX_h is IDX_h { export IDX_h; } +indexed3: IDX_i is IDX_i { export IDX_i; } +indexed3: IDX_j is IDX_j { export IDX_j; } +indexed3: IDX_k is IDX_k { export IDX_k; } +# not indexed3: IDX_l is IDX_l { export IDX_l; } +# not indexed3: IDX_m is IDX_m { export IDX_m; } + +# +# effective address of [IDX2], [D,IDX] +# +# not indexedindexed3: IDX_a is IDX_a { export IDX_a; } +# not indexedindexed3: IDX_b is IDX_b { export IDX_b; } +# not indexedindexed3: IDX_c is IDX_c { export IDX_c; } +# not indexedindexed3: IDX_d is IDX_d { export IDX_d; } +# not indexedindexed3: IDX_e is IDX_e { export IDX_e; } +# not indexedindexed3: IDX_f is IDX_f { export IDX_f; } +# not indexedindexed3: IDX_g is IDX_g { export IDX_g; } +# not indexedindexed3: IDX_h is IDX_h { export IDX_h; } +# not indexedindexed3: IDX_i is IDX_i { export IDX_i; } +# not indexedindexed3: IDX_j is IDX_j { export IDX_j; } +# not indexedindexed3: IDX_k is IDX_k { export IDX_k; } +indexed2: IDX_l is IDX_l { export IDX_l; } +indexed2: IDX_m is IDX_m { export IDX_m; } + +# +# effective address of IDX, IDX1, IDX2, [IDX2], [D,IDX] +# +indexed5: IDX_a is IDX_a { export IDX_a; } +indexed5: IDX_b is IDX_b { export IDX_b; } +indexed5: IDX_c is IDX_c { export IDX_c; } +indexed5: IDX_d is IDX_d { export IDX_d; } +indexed5: IDX_e is IDX_e { export IDX_e; } +indexed5: IDX_f is IDX_f { export IDX_f; } +indexed5: IDX_g is IDX_g { export IDX_g; } +indexed5: IDX_h is IDX_h { export IDX_h; } +indexed5: IDX_i is IDX_i { export IDX_i; } +indexed5: IDX_j is IDX_j { export IDX_j; } +indexed5: IDX_k is IDX_k { export IDX_k; } +indexed5: IDX_l is IDX_l { export IDX_l; } +indexed5: IDX_m is IDX_m { export IDX_m; } + +# +# effective address of IDX +# +indexed1: IDX_a is IDX_a { export IDX_a; } +indexed1: IDX_b is IDX_b { export IDX_b; } +indexed1: IDX_c is IDX_c { export IDX_c; } +indexed1: IDX_d is IDX_d { export IDX_d; } +indexed1: IDX_e is IDX_e { export IDX_e; } +indexed1: IDX_f is IDX_f { export IDX_f; } +indexed1: IDX_g is IDX_g { export IDX_g; } +indexed1: IDX_h is IDX_h { export IDX_h; } +# not indexed1: IDX_i is IDX_i { export IDX_i; } +# not indexed1: IDX_j is IDX_j { export IDX_j; } +# not indexed1: IDX_k is IDX_k { export IDX_k; } +# not indexed1: iIDX_l is iIDX_l { export iIDX_l; } +# not indexed1: IDX_m is IDX_m { export IDX_m; } + + +# +# indexed0_x - exports the effective address (EA) +# indexed1_x - exports a single byte at the effective address +# indexed2_x - exports a double byte at the effective address +# + +indexed1_1: indexed1 is indexed1 { + local paddr:3 = 0; + GetPagedAddr(indexed1,paddr); + export *:1 paddr; +} +indexed2_1: indexed1 is indexed1 { + local paddr:3 = 0; + GetPagedAddr(indexed1,paddr); + export *:2 paddr; +} + +indexed0_2: indexed2 is indexed2 { + local val = indexed2; export val; +} + +indexed0_3: indexed3 is indexed3 { + local val = indexed3; export val; +} +indexed1_3: indexed3 is indexed3 { + local paddr:3 = 0; + GetPagedAddr(indexed3,paddr); + export *:1 paddr; +} +indexed2_3: indexed3 is indexed3 { + local paddr:3 = 0; + GetPagedAddr(indexed3,paddr); + export *:2 paddr; +} + +indexedA_5: indexed5 is UseGPAGE=0 & indexed5 { + local paddr:3 = 0; + GetPagedAddr(indexed5,paddr); + export paddr; +} +indexedA_5: indexed5 is UseGPAGE=1 & indexed5 { + local addr:3 = (zext(GPAGE) << 16) | zext(indexed5); + export addr; +} +indexed1_5: indexed5 is UseGPAGE=0 & indexed5 { + local paddr:3 = 0; + GetPagedAddr(indexed5,paddr); + export *:1 paddr; +} +indexed1_5: indexed5 is UseGPAGE=1 & indexed5 { + local addr:3 = (zext(GPAGE) << 16) | zext(indexed5); + export *:1 addr; +} +indexed2_5: indexed5 is UseGPAGE=0 & indexed5 { + local paddr:3 = 0; + GetPagedAddr(indexed5,paddr); + export *:2 paddr; +} +indexed2_5: indexed5 is UseGPAGE=1 & indexed5 { + local addr:3 = (zext(GPAGE) << 16) | zext(indexed5); + export *:2 addr; +} + +# range -128 through +127 +rel8: reloc is rel [ reloc = inst_next + rel; ] { export *:1 reloc; } + +# range -256 through +255 +rel9: reloc is XGATE=0 & sign12_12 & rr7_0 [ reloc = inst_next + ((sign12_12 << 8) | rr7_0); ] { export *:1 reloc; } + +# positive range 0 through +65535 +rel16: reloc is simm16 [ reloc = inst_next + simm16; ] { export *:1 reloc; } + + +op2_opr16a_8: opr16a_8 is opr16a_8 { export opr16a_8; } +op2_opr16a_16: opr16a_16 is opr16a_16 { export opr16a_16; } + +@if defined(HCS12X) +op2_indexed1_5: indexed1_5 is indexed1_5 { export indexed1_5; } +@else +op2_indexed1_1: indexed1_1 is indexed1_1 { export indexed1_1; } +@endif + +@if defined(HCS12X) +op2_indexed2_5: indexed2_5 is indexed2_5 { export indexed2_5; } +@else +op2_indexed2_1: indexed2_1 is indexed2_1 { export indexed2_1; } +@endif + +################################################################ +# Macros +################################################################ + + + +macro additionWithCarry(operand1, operand2, result) { + local Ccopy = zext($(C)); + local AFmask = -1 >> 4; + $(H) = (((operand1 & AFmask) + (operand2 & AFmask) + Ccopy) & (AFmask + 1)) != 0; + $(C) = carry(operand1, operand2); + local tempResult = operand1 + operand2; + $(C) = $(C) || carry(tempResult, Ccopy); + $(V) = $(V) ^^ scarry(tempResult, Ccopy); + result = tempResult + Ccopy; + $(N) = (result s< 0); + $(Z) = (result == 0); +} + + + +macro addition_flags1(operand1, operand2,result) { + local AFmask = -1 >> 4; + $(H) = (((operand1 & AFmask) + (operand2 & AFmask)) & (AFmask + 1)) != 0; + + $(N) = (result s< 0); + $(Z) = (result == 0); + $(V) = scarry(operand1,operand2); + $(C) = carry(operand1,operand2); +} + +macro addition_flags2(operand1, operand2, result) { + $(N) = (result s< 0); + $(Z) = (result == 0); + $(V) = scarry(operand1,operand2); + $(C) = carry(operand1,operand2); +} + +macro subtraction_flags1(register, operand, result) { + $(V) = sborrow(register,operand); + $(N) = (result s< 0); + $(Z) = (result == 0); + $(C) = register < operand; +} + +macro subtraction_flags2(register, operand, result) { + $(V) = sborrow(register,operand); + $(N) = (result s< 0); + $(Z) = (result == 0); + $(C) = register < operand; +} + +macro V_equals_0() { + $(V) = 0; +} + +macro V_equals_C() { + $(V) = $(C); +} + +macro V_equals_N_xor_C() { + $(V) = $(N) ^ $(C); +} + +macro V_CMP_flag(register, operand) { + $(V) = sborrow(register,operand); +} + +macro V_DEC_flag(operand) { + $(V) = sborrow(operand,1); +} + +macro V_DEC_flag2(operand) { + $(V) = sborrow(operand,1); +} + +macro V_INC_flag(operand) { + $(V) = scarry(operand,1); +} + +macro V_INC_flag2(operand) { + $(V) = scarry(operand,1); +} + +macro V_NEG_flag(operand) { + $(V) = sborrow(0,operand); +} + +macro V_NEG_flag2(operand) { + $(V) = sborrow(0,operand); +} + +macro Pull1(operand) { + setHCSphysPage(SP); + + paddr:3 = segment(physPage,SP); + operand = *paddr; + SP = SP + 1; +} + +macro Pull2(operand) { + setHCSphysPage(SP); + + paddr:3 = segment(physPage,SP); + operand = *paddr; + SP = SP + 2; +} + +macro Push1(operand) { + SP = SP - 1; + + setHCSphysPage(SP); + paddr:3 = segment(physPage,SP); + *paddr = operand; +} + +macro Push2(operand) { + SP = SP - 2; + + setHCSphysPage(SP); + + paddr:3 = segment(physPage,SP); + *paddr = operand; +} + +macro setCCR( operand ) { + # when CCR is the destination, cannot set the X bit unless it is already set in CCR + CCR = operand & (CCR | 0b10111111); +} + +macro setCCRW( operand ) { + # when CCRW is the destination, cannot set the X bit unless it is already set in CCRW + CCRW = operand & (CCRW | 0b1111111110111111); +} + +:^instruction is XGATE=0 & op8=0x18; instruction [ Prefix18=1; ] {} + +################################################################ +# Constructors +################################################################ + +:ABA is XGATE=0 & (Prefix18=1 & op8=0x06) +{ + result:1 = A + B; + addition_flags1(A, B, result); + A = result; +} + +:ABX is XGATE=0 & Prefix18=0 & (op16=0x1AE5) +{ + IX = zext(B) + IX; +} + +:ABY is XGATE=0 & Prefix18=0 & (op16=0x19ED) +{ + IY = zext(B) + IY; +} + +:ADCA iopr8i is XGATE=0 & Prefix18=0 & (op8=0x89); iopr8i +{ + op1:1 = iopr8i; + + local result:1; + additionWithCarry(A, op1, result); + + A = result; +} + +:ADCA opr8a_8 is XGATE=0 & Prefix18=0 & (op8=0x99); opr8a_8 +{ + op1:1 = opr8a_8; + + local result:1; + additionWithCarry(A, op1, result); + + A = result; +} + +:ADCA opr16a_8 is XGATE=0 & Prefix18=0 & (op8=0xB9); opr16a_8 +{ + op1:1 = opr16a_8; + + local result:1; + additionWithCarry(A, op1, result); + + A = result; +} + +:ADCA indexed1_5 is XGATE=0 & Prefix18=0 & (op8=0xA9); indexed1_5 +{ + op1:1 = indexed1_5; + + result:1 = A + op1 + $(C); + addition_flags1(A, op1, result); + A = result; +} + +:ADCB iopr8i is XGATE=0 & Prefix18=0 & (op8=0xC9); iopr8i +{ + op1:1 = iopr8i; + + local result:1; + additionWithCarry(A, op1, result); + + B = result; +} + +:ADCB opr8a_8 is XGATE=0 & Prefix18=0 & (op8=0xD9); opr8a_8 +{ + op1:1 = opr8a_8; + + result:1 = B + op1 + $(C); + addition_flags1(B, op1, result); + B = result; +} + +:ADCB opr16a_8 is XGATE=0 & Prefix18=0 & (op8=0xF9); opr16a_8 +{ + op1:1 = opr16a_8; + + local result:1; + additionWithCarry(B, op1, result); + + B = result; +} + +:ADCB indexed1_5 is XGATE=0 & Prefix18=0 & (op8=0xE9); indexed1_5 +{ + op1:1 = indexed1_5; + + local result:1; + additionWithCarry(B, op1, result); + + B = result; +} + +:ADDA iopr8i is XGATE=0 & Prefix18=0 & (op8=0x8B); iopr8i +{ + op1:1 = iopr8i; + + result:1 = A + op1; + addition_flags1(A, op1, result); + + A = result; +} + +:ADDA opr8a_8 is XGATE=0 & Prefix18=0 & (op8=0x9B); opr8a_8 +{ + op1:1 = opr8a_8; + + result:1 = A + op1; + addition_flags1(A, op1, result); + A = result; +} + +:ADDA opr16a_8 is XGATE=0 & Prefix18=0 & (op8=0xBB); opr16a_8 +{ + op1:1 = opr16a_8; + + result:1 = A + op1; + addition_flags1(A, op1, result); + A = result; +} + +:ADDA indexed1_5 is XGATE=0 & Prefix18=0 & (op8=0xAB); indexed1_5 +{ + op1:1 = indexed1_5; + + result:1 = A + op1; + addition_flags1(A, op1, result); + A = result; +} + +:ADDB iopr8i is XGATE=0 & Prefix18=0 & (op8=0xCB); iopr8i +{ + op1:1 = iopr8i; + + result:1 = B + op1; + addition_flags1(B, op1, result); + B = result; +} + +:ADDB opr8a_8 is XGATE=0 & Prefix18=0 & (op8=0xDB); opr8a_8 +{ + op1:1 = opr8a_8; + + result:1 = B + op1; + addition_flags1(B, op1, result); + B = result; +} + +:ADDB opr16a_8 is XGATE=0 & Prefix18=0 & (op8=0xFB); opr16a_8 +{ + op1:1 = opr16a_8; + + result:1 = B + op1; + addition_flags1(B, op1, result); + B = result; +} + +:ADDB indexed1_5 is XGATE=0 & Prefix18=0 & (op8=0xEB); indexed1_5 +{ + op1:1 = indexed1_5; + + result:1 = B + op1; + addition_flags1(B, op1, result); + B = result; +} + +:ADDD iopr16i is XGATE=0 & Prefix18=0 & (op8=0xC3); iopr16i +{ + op1:2 = iopr16i; + + result:2 = D + op1; + addition_flags2(D, op1, result); + D = result; +} + +:ADDD opr8a_16 is XGATE=0 & Prefix18=0 & (op8=0xD3); opr8a_16 +{ + op1:2 = opr8a_16; + + result:2 = D + op1; + addition_flags2(D, op1, result); + D = result; +} + +:ADDD opr16a_16 is XGATE=0 & Prefix18=0 & (op8=0xF3); opr16a_16 +{ + op1:2 = opr16a_16; + + result:2 = D + op1; + addition_flags2(D, op1, result); + D = result; +} + +:ADDD indexed2_5 is XGATE=0 & Prefix18=0 & (op8=0xE3); indexed2_5 +{ + op1:2 = indexed2_5; + + result:2 = D + op1; + addition_flags2(D, op1, result); + D = result; +} + +@if defined(HCS12X) +:ADDX iopr16i is XGATE=0 & Prefix18=1 & (op8=0x8B); iopr16i +{ + op1:2 = iopr16i; + + result:2 = IX + op1; + addition_flags2(IX, op1, result); + IX = result; +} +@endif + +@if defined(HCS12X) +:ADDX opr8a_16 is XGATE=0 & Prefix18=1 & (op8=0x9B); opr8a_16 +{ + op1:2 = opr8a_16; + + result:2 = IX + op1; + addition_flags2(IX, op1, result); + IX = result; +} +@endif + +@if defined(HCS12X) +:ADDX opr16a_16 is XGATE=0 & Prefix18=1 & (op8=0xBB); opr16a_16 +{ + op1:2 = opr16a_16; + + result:2 = IX + op1; + addition_flags2(IX, op1, result); + IX = result; +} +@endif + +@if defined(HCS12X) +:ADDX indexed2_5 is XGATE=0 & Prefix18=1 & (op8=0xAB); indexed2_5 +{ + op1:2 = indexed2_5; + + result:2 = IX + op1; + addition_flags2(IX, op1, result); + IX = result; +} +@endif + +@if defined(HCS12X) +:ADDY iopr16i is XGATE=0 & Prefix18=1 & (op8=0xCB); iopr16i +{ + op1:2 = iopr16i; + + result:2 = IY + op1; + addition_flags2(IY, op1, result); + IY = result; +} +@endif + +@if defined(HCS12X) +:ADDY opr8a_16 is XGATE=0 & Prefix18=1 & (op8=0xDB); opr8a_16 +{ + op1:2 = opr8a_16; + + result:2 = IY + op1; + addition_flags2(IY, op1, result); + IY = result; +} +@endif + +@if defined(HCS12X) +:ADDY opr16a_16 is XGATE=0 & Prefix18=1 & (op8=0xFB); opr16a_16 +{ + op1:2 = opr16a_16; + + result:2 = IY + op1; + addition_flags2(IY, op1, result); + IY = result; +} +@endif + +@if defined(HCS12X) +:ADDY indexed2_5 is XGATE=0 & Prefix18=1 & (op8=0xEB); indexed2_5 +{ + op1:2 = indexed2_5; + + result:2 = IY + op1; + addition_flags2(IY, op1, result); + IY = result; +} +@endif + +@if defined(HCS12X) +:ADED iopr16i is XGATE=0 & Prefix18=1 & (op8=0xC3); iopr16i +{ + op1:2 = iopr16i; + + result:2 = D + op1 + zext($(C)); + addition_flags2(D, op1, result); + D = result; +} +@endif + +@if defined(HCS12X) +:ADED opr8a_16 is XGATE=0 & Prefix18=1 & (op8=0xD3); opr8a_16 +{ + op1:2 = opr8a_16; + + result:2 = D + op1 + zext($(C)); + addition_flags2(D, op1, result); + D = result; +} +@endif + +@if defined(HCS12X) +:ADED opr16a_16 is XGATE=0 & Prefix18=1 & (op8=0xF3); opr16a_16 +{ + op1:2 = opr16a_16; + + result:2 = D + op1 + zext($(C)); + addition_flags2(D, op1, result); + D = result; +} +@endif + +@if defined(HCS12X) +:ADED indexed2_5 is XGATE=0 & Prefix18=1 & (op8=0xE3); indexed2_5 +{ + op1:2 = indexed2_5; + + result:2 = D + op1 + zext($(C)); + addition_flags2(D, op1, result); + D = result; +} +@endif + +@if defined(HCS12X) +:ADEX iopr16i is XGATE=0 & Prefix18=1 & (op8=0x89); iopr16i +{ + op1:2 = iopr16i; + + result:2 = IX + op1 + zext($(C)); + addition_flags2(IX, op1, result); + IX = result; +} +@endif + +@if defined(HCS12X) +:ADEX opr8a_16 is XGATE=0 & Prefix18=1 & (op8=0x99); opr8a_16 +{ + op1:2 = opr8a_16; + + result:2 = IX + op1 + zext($(C)); + addition_flags2(IX, op1, result); + IX = result; +} +@endif + +@if defined(HCS12X) +:ADEX opr16a_16 is XGATE=0 & Prefix18=1 & (op8=0xb9); opr16a_16 +{ + op1:2 = opr16a_16; + + result:2 = IX + op1 + zext($(C)); + addition_flags2(IX, op1, result); + IX = result; +} +@endif + +@if defined(HCS12X) +:ADEX indexed2_5 is XGATE=0 & Prefix18=1 & (op8=0xa9); indexed2_5 +{ + op1:2 = indexed2_5; + + result:2 = IX + op1 + zext($(C)); + addition_flags2(IX, op1, result); + IX = result; +} +@endif + +@if defined(HCS12X) +:ADEY iopr16i is XGATE=0 & Prefix18=1 & (op8=0xC9); iopr16i +{ + op1:2 = iopr16i; + + result:2 = IY + op1 + zext($(C)); + addition_flags2(IY, op1, result); + IY = result; +} +@endif + +@if defined(HCS12X) +:ADEY opr8a_16 is XGATE=0 & Prefix18=1 & (op8=0xD9); opr8a_16 +{ + op1:2 = opr8a_16; + + result:2 = IY + op1 + zext($(C)); + addition_flags2(IY, op1, result); + IY = result; +} +@endif + +@if defined(HCS12X) +:ADEY opr16a_16 is XGATE=0 & Prefix18=1 & (op8=0xF9); opr16a_16 +{ + op1:2 = opr16a_16; + + result:2 = IY + op1 + zext($(C)); + addition_flags2(IY, op1, result); + IY = result; +} +@endif + +@if defined(HCS12X) +:ADEY indexed2_5 is XGATE=0 & Prefix18=1 & (op8=0xE9); indexed2_5 +{ + op1:2 = indexed2_5; + + result:2 = IY + op1 + zext($(C)); + addition_flags2(IY, op1, result); + IY = result; +} +@endif + +:ANDA iopr8i is XGATE=0 & Prefix18=0 & (op8=0x84); iopr8i +{ + A = A & iopr8i; + V_equals_0(); + $(Z) = (A == 0); + $(N) = (A s< 0); +} + +:ANDA opr8a_8 is XGATE=0 & Prefix18=0 & (op8=0x94); opr8a_8 +{ + A = A & opr8a_8; + V_equals_0(); + $(Z) = (A == 0); + $(N) = (A s< 0); +} + +:ANDA opr16a_8 is XGATE=0 & Prefix18=0 & (op8=0xB4); opr16a_8 +{ + A = A & opr16a_8; + V_equals_0(); + $(Z) = (A == 0); + $(N) = (A s< 0); +} + +:ANDA indexed1_5 is XGATE=0 & Prefix18=0 & (op8=0xA4); indexed1_5 +{ + A = A & indexed1_5; + V_equals_0(); + $(Z) = (A == 0); + $(N) = (A s< 0); +} + +:ANDB iopr8i is XGATE=0 & Prefix18=0 & (op8=0xC4); iopr8i +{ + B = B & iopr8i; + V_equals_0(); + $(Z) = (B == 0); + $(N) = (B s< 0); +} + +:ANDB opr8a_8 is XGATE=0 & Prefix18=0 & (op8=0xD4); opr8a_8 +{ + B = B & opr8a_8; + V_equals_0(); + $(Z) = (B == 0); + $(N) = (B s< 0); +} + +:ANDB opr16a_8 is XGATE=0 & Prefix18=0 & (op8=0xF4); opr16a_8 +{ + B = B & opr16a_8; + V_equals_0(); + $(Z) = (B == 0); + $(N) = (B s< 0); +} + +:ANDB indexed1_5 is XGATE=0 & Prefix18=0 & (op8=0xE4); indexed1_5 +{ + B = B & indexed1_5; + V_equals_0(); + $(Z) = (B == 0); + $(N) = (B s< 0); +} + +:ANDCC iopr8i is XGATE=0 & Prefix18=0 & (op8=0x10); iopr8i +{ + CCR = CCR & iopr8i; +} + +@if defined(HCS12X) +:ANDX iopr16i is XGATE=0 & Prefix18=1 & (op8=0x84); iopr16i +{ + IX = IX & iopr16i; + V_equals_0(); + $(Z) = (IX == 0); + $(N) = (IX s< 0); +} +@endif + +@if defined(HCS12X) +:ANDX opr8a_16 is XGATE=0 & Prefix18=1 & (op8=0x94); opr8a_16 +{ + IX = IX & opr8a_16; + V_equals_0(); + $(Z) = (IX == 0); + $(N) = (IX s< 0); +} +@endif + +@if defined(HCS12X) +:ANDX opr16a_16 is XGATE=0 & Prefix18=1 & (op8=0xB4); opr16a_16 +{ + IX = IX & opr16a_16; + V_equals_0(); + $(Z) = (IX == 0); + $(N) = (IX s< 0); +} +@endif + +@if defined(HCS12X) +:ANDX indexed2_5 is XGATE=0 & Prefix18=1 & (op8=0xA4); indexed2_5 +{ + IX = IX & indexed2_5; + V_equals_0(); + $(Z) = (IX == 0); + $(N) = (IX s< 0); +} +@endif + +@if defined(HCS12X) +:ANDY iopr16i is XGATE=0 & Prefix18=1 & (op8=0xC4); iopr16i +{ + IY = IY & iopr16i; + V_equals_0(); + $(Z) = (IY == 0); + $(N) = (IY s< 0); +} +@endif + +@if defined(HCS12X) +:ANDY opr8a_16 is XGATE=0 & Prefix18=1 & (op8=0xD4); opr8a_16 +{ + IY = IY & opr8a_16; + V_equals_0(); + $(Z) = (IY == 0); + $(N) = (IY s< 0); +} +@endif + +@if defined(HCS12X) +:ANDY opr16a_16 is XGATE=0 & Prefix18=1 & (op8=0xF4); opr16a_16 +{ + IY = IY & opr16a_16; + V_equals_0(); + $(Z) = (IY == 0); + $(N) = (IY s< 0); +} +@endif + +@if defined(HCS12X) +:ANDY indexed2_5 is XGATE=0 & Prefix18=1 & (op8=0xE4); indexed2_5 +{ + IY = IY & indexed2_5; + V_equals_0(); + $(Z) = (IY == 0); + $(N) = (IY s< 0); +} +@endif + +:ASL opr16a_8 is XGATE=0 & Prefix18=0 & (op8=0x78); opr16a_8 +{ + tmp:1 = opr16a_8; + $(C) = tmp[7,1]; + tmp = tmp << 1; + opr16a_8 = tmp; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + V_equals_N_xor_C(); +} + +:ASL indexed1_5 is XGATE=0 & Prefix18=0 & (op8=0x68); indexed1_5 +{ + tmp:1 = indexed1_5; + $(C) = tmp[7,1]; + tmp = tmp << 1; + indexed1_5 = tmp; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + V_equals_N_xor_C(); +} + +:ASLA is XGATE=0 & Prefix18=0 & op8=0x48 +{ + $(C) = A[7,1]; + A = A << 1; + $(Z) = (A == 0); + $(N) = (A s< 0); + V_equals_N_xor_C(); +} + +:ASLB is XGATE=0 & Prefix18=0 & op8=0x58 +{ + $(C) = B[7,1]; + B = B << 1; + $(Z) = (B == 0); + $(N) = (B s< 0); + V_equals_N_xor_C(); +} + +:ASLD is XGATE=0 & Prefix18=0 & op8=0x59 +{ + $(C) = D[15,1]; + D = D << 1; + $(Z) = (D == 0); + $(N) = (D s< 0); + V_equals_N_xor_C(); +} + +@if defined(HCS12X) +:ASLW opr16a_16 is XGATE=0 & Prefix18=1 & (op8=0x78); opr16a_16 +{ + local tmp = opr16a_16; + $(C) = tmp[15,1]; + tmp = tmp << 1; + opr16a_16 = tmp; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + V_equals_N_xor_C(); +} +@endif + +@if defined(HCS12X) +:ASLW indexed2_5 is XGATE=0 & Prefix18=1 & (op8=0x68); indexed2_5 +{ + local tmp = indexed2_5; + $(C) = tmp[15,1]; + tmp = tmp << 1; + indexed2_5 = tmp; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + V_equals_N_xor_C(); +} +@endif + +@if defined(HCS12X) +:ASLX is XGATE=0 & Prefix18=1 & op8=0x48 +{ + $(C) = IX[15,1]; + IX = IX << 1; + $(Z) = (IX == 0); + $(N) = (IX s< 0); + V_equals_N_xor_C(); +} +@endif + +@if defined(HCS12X) +:ASLY is XGATE=0 & Prefix18=1 & op8=0x58 +{ + $(C) = IY[15,1]; + IY = IY << 1; + $(Z) = (IY == 0); + $(N) = (IY s< 0); + V_equals_N_xor_C(); +} +@endif + +:ASR opr16a_8 is XGATE=0 & Prefix18=0 & (op8=0x77); opr16a_8 +{ + tmp:1 = opr16a_8; + $(C) = tmp[0,1]; + tmp = tmp s>> 1; + opr16a_8 = tmp; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + V_equals_N_xor_C(); +} + +:ASR indexed1_5 is XGATE=0 & Prefix18=0 & (op8=0x67); indexed1_5 +{ + tmp:1 = indexed1_5; + $(C) = tmp[0,1]; + tmp = tmp s>> 1; + indexed1_5 = tmp; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + V_equals_N_xor_C(); +} + +:ASRA is XGATE=0 & Prefix18=0 & op8=0x47 +{ + $(C) = A[0,1]; + A = A s>> 1; + $(Z) = (A == 0); + $(N) = (A s< 0); + V_equals_N_xor_C(); +} + +:ASRB is XGATE=0 & Prefix18=0 & op8=0x57 +{ + $(C) = B[0,1]; + B = B s>> 1; + $(Z) = (B == 0); + $(N) = (B s< 0); + V_equals_N_xor_C(); +} + +@if defined(HCS12X) +:ASRW opr16a_16 is XGATE=0 & Prefix18=1 & (op8=0x77); opr16a_16 +{ + local tmp = opr16a_16; + $(C) = tmp[0,1]; + tmp = tmp s>> 1; + opr16a_16 = tmp; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + V_equals_N_xor_C(); +} +@endif + +@if defined(HCS12X) +:ASRW indexed2_5 is XGATE=0 & Prefix18=1 & (op8=0x67); indexed2_5 +{ + local tmp = indexed2_5; + $(C) = tmp[0,1]; + tmp = tmp s>> 1; + indexed2_5 = tmp; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + V_equals_N_xor_C(); +} +@endif + +@if defined(HCS12X) +:ASRX is XGATE=0 & Prefix18=1 & op8=0x47 +{ + $(C) = IX[0,1]; + IX = IX s>> 1; + $(Z) = (IX == 0); + $(N) = (IX s< 0); + V_equals_N_xor_C(); +} +@endif + +@if defined(HCS12X) +:ASRY is XGATE=0 & Prefix18=1 & op8=0x57 +{ + $(C) = IY[0,1]; + IY = IY s>> 1; + $(Z) = (IY == 0); + $(N) = (IY s< 0); + V_equals_N_xor_C(); +} +@endif + +:BCC rel8 is XGATE=0 & Prefix18=0 & op8=0x24; rel8 +{ + if ($(C) == 0) goto rel8; +} + +:BCLR opr8a_8, msk8 is XGATE=0 & Prefix18=0 & (op8=0x4D); opr8a_8; msk8 +{ + op1:1 = opr8a_8; + op1 = op1 & ~msk8; + opr8a_8 = op1; + $(N) = (op1 s< 0); + $(Z) = (op1 == 0); + V_equals_0(); +} + +:BCLR opr16a_8, msk8 is XGATE=0 & Prefix18=0 & (op8=0x1D); opr16a_8; msk8 +{ + op1:1 = opr16a_8; + op1 = op1 & ~msk8; + opr16a_8 = op1; + $(N) = (op1 s< 0); + $(Z) = (op1 == 0); + V_equals_0(); +} + +:BCLR indexed1_3, msk8 is XGATE=0 & Prefix18=0 & (op8=0x0D); indexed1_3; msk8 +{ + op1:1 = indexed1_3; + op1 = op1 & ~msk8; + indexed1_3 = op1; + $(N) = (op1 s< 0); + $(Z) = (op1 == 0); + V_equals_0(); +} + +:BCS rel8 is XGATE=0 & Prefix18=0 & op8=0x25; rel8 +{ + if ($(C) == 1) goto rel8; +} + +:BEQ rel8 is XGATE=0 & Prefix18=0 & op8=0x27; rel8 +{ + if ($(Z) == 1) goto rel8; +} + +:BGE rel8 is XGATE=0 & Prefix18=0 & op8=0x2C; rel8 +{ + if (($(N) ^ $(V)) == 1) goto rel8; +} + +@if defined(HCS12) +:BGND is XGATE=0 & Prefix18=0 & op8=0x00 +{ + BDM_return:3 = inst_next; + # this could return BDM location, or BDM_return + PCE = backgroundDebugMode(BDM_return); + goto [PCE]; +} +@endif + +:BGT rel8 is XGATE=0 & Prefix18=0 & op8=0x2E; rel8 +{ + if (($(Z) | ($(N) ^ $(V))) == 0) goto rel8; +} + +:BHI rel8 is XGATE=0 & Prefix18=0 & op8=0x22; rel8 +{ + if (($(C) | $(Z)) == 0) goto rel8; +} + +#:BHS rel8 is op8=0x24; rel8 See BCC + +:BITA iopr8i is XGATE=0 & Prefix18=0 & (op8=0x85); iopr8i +{ + result:1 = A & iopr8i; + $(Z) = (result == 0); + $(N) = (result s< 0); + V_equals_0(); +} + +:BITA opr8a_8 is XGATE=0 & Prefix18=0 & (op8=0x95); opr8a_8 +{ + result:1 = A & opr8a_8; + $(Z) = (result == 0); + $(N) = (result s< 0); + V_equals_0(); +} + +:BITA opr16a_8 is XGATE=0 & Prefix18=0 & (op8=0xB5); opr16a_8 +{ + result:1 = A & opr16a_8; + $(Z) = (result == 0); + $(N) = (result s< 0); + V_equals_0(); +} + +:BITA indexed1_5 is XGATE=0 & Prefix18=0 & (op8=0xA5); indexed1_5 +{ + result:1 = A & indexed1_5; + $(Z) = (result == 0); + $(N) = (result s< 0); + V_equals_0(); +} + +:BITB iopr8i is XGATE=0 & Prefix18=0 & (op8=0xC5); iopr8i +{ + result:1 = B & iopr8i; + $(Z) = (result == 0); + $(N) = (result s< 0); + V_equals_0(); +} + +:BITB opr8a_8 is XGATE=0 & Prefix18=0 & (op8=0xD5); opr8a_8 +{ + result:1 = B & opr8a_8; + $(Z) = (result == 0); + $(N) = (result s< 0); + V_equals_0(); +} + +:BITB opr16a_8 is XGATE=0 & Prefix18=0 & (op8=0xF5); opr16a_8 +{ + result:1 = B & opr16a_8; + $(Z) = (result == 0); + $(N) = (result s< 0); + V_equals_0(); +} + +:BITB indexed1_5 is XGATE=0 & Prefix18=0 & (op8=0xE5); indexed1_5 +{ + result:1 = B & indexed1_5; + $(Z) = (result == 0); + $(N) = (result s< 0); + V_equals_0(); +} + +@if defined(HCS12X) +:BITX iopr16i is XGATE=0 & Prefix18=1 & (op8=0x85); iopr16i +{ + local result = IX & iopr16i; + $(Z) = (result == 0); + $(N) = (result s< 0); + V_equals_0(); +} +@endif + +@if defined(HCS12X) +:BITX opr8a_16 is XGATE=0 & Prefix18=1 & (op8=0x95); opr8a_16 +{ + local result = IX & opr8a_16; + $(Z) = (result == 0); + $(N) = (result s< 0); + V_equals_0(); +} +@endif + +@if defined(HCS12X) +:BITX opr16a_16 is XGATE=0 & Prefix18=1 & (op8=0xB5); opr16a_16 +{ + local result = IX & opr16a_16; + $(Z) = (result == 0); + $(N) = (result s< 0); + V_equals_0(); +} +@endif + +@if defined(HCS12X) +:BITX indexed2_5 is XGATE=0 & Prefix18=1 & (op8=0xA5); indexed2_5 +{ + local result = IX & indexed2_5; + $(Z) = (result == 0); + $(N) = (result s< 0); + V_equals_0(); +} +@endif + +@if defined(HCS12X) +:BITY iopr16i is XGATE=0 & Prefix18=1 & (op8=0xC5); iopr16i +{ + local result = IY & iopr16i; + $(Z) = (result == 0); + $(N) = (result s< 0); + V_equals_0(); +} +@endif + +@if defined(HCS12X) +:BITY opr8a_16 is XGATE=0 & Prefix18=1 & (op8=0xD5); opr8a_16 +{ + local result = IY & opr8a_16; + $(Z) = (result == 0); + $(N) = (result s< 0); + V_equals_0(); +} +@endif + +@if defined(HCS12X) +:BITY opr16a_16 is XGATE=0 & Prefix18=1 & (op8=0xF5); opr16a_16 +{ + local result = IY & opr16a_16; + $(Z) = (result == 0); + $(N) = (result s< 0); + V_equals_0(); +} +@endif + +@if defined(HCS12X) +:BITY indexed2_5 is XGATE=0 & Prefix18=1 & (op8=0xE5); indexed2_5 +{ + local result = IY & indexed2_5; + $(Z) = (result == 0); + $(N) = (result s< 0); + V_equals_0(); +} +@endif + + +:BLE rel8 is XGATE=0 & Prefix18=0 & op8=0x2F; rel8 +{ + if ($(Z) | ($(N) ^ $(V))) goto rel8; +} + +#:BLO rel8 is op8=0x25; rel8 see BCS + +:BLS rel8 is XGATE=0 & Prefix18=0 & op8=0x23; rel8 +{ + if (($(C) | $(Z)) == 1) goto rel8; +} + +:BLT rel8 is XGATE=0 & Prefix18=0 & op8=0x2D; rel8 +{ + if (($(N) ^ $(V)) ==1) goto rel8; +} + +:BMI rel8 is XGATE=0 & Prefix18=0 & op8=0x2B; rel8 +{ + if ($(N) == 1) goto rel8; +} + +:BNE rel8 is XGATE=0 & Prefix18=0 & op8=0x26; rel8 +{ + if ($(Z) == 0) goto rel8; +} + +:BPL rel8 is XGATE=0 & Prefix18=0 & op8=0x2A; rel8 +{ + if ($(N) == 0) goto rel8; +} + +:BRA rel8 is XGATE=0 & Prefix18=0 & op8=0x20; rel8 +{ + goto rel8; +} + +:BRCLR opr8a_8, msk8, rel8 is XGATE=0 & Prefix18=0 & op8=0x4F; opr8a_8; msk8; rel8 +{ + result:1 = opr8a_8 & msk8; + if (result == 0) goto rel8; +} + +:BRCLR opr16a_8, msk8, rel8 is XGATE=0 & Prefix18=0 & op8=0x1F; opr16a_8; msk8; rel8 +{ + result:1 = opr16a_8 & msk8; + if (result == 0) goto rel8; +} + +:BRCLR indexed1_3, msk8, rel8 is XGATE=0 & Prefix18=0 & op8=0x0F; indexed1_3; msk8; rel8 +{ + result:1 = indexed1_3 & msk8; + if (result == 0) goto rel8; +} + +# branch never is a two-byte nop +SkipNextInstr: dest is epsilon [ dest = inst_next + 1; ] { export *[RAM]:1 dest; } + +:BRN SkipNextInstr is XGATE=0 & Prefix18=0 & op8=0x21 & SkipNextInstr +{ + goto SkipNextInstr; +} + +:BRSET opr8a_8, msk8, rel8 is XGATE=0 & Prefix18=0 & op8=0x4E; opr8a_8; msk8; rel8 +{ + result:1 = ~opr8a_8 & msk8; + if (result != 0) goto rel8; +} + +:BRSET opr16a_8, msk8, rel8 is XGATE=0 & Prefix18=0 & op8=0x1E; opr16a_8; msk8; rel8 +{ + result:1 = ~opr16a_8 & msk8; + if (result != 0) goto rel8; +} + +:BRSET indexed1_3, msk8, rel8 is XGATE=0 & Prefix18=0 & op8=0x0E; indexed1_3; msk8; rel8 +{ + result:1 = ~indexed1_3 & msk8; + if (result != 0) goto rel8; +} + +:BSET opr8a_8, msk8 is XGATE=0 & Prefix18=0 & op8=0x4C; opr8a_8; msk8 +{ + result:1 = opr8a_8 | msk8; + opr8a_8 = result; + $(N) = (result s< 0); + $(Z) = (result == 0); + V_equals_0(); +} + +:BSET opr16a_8, msk8 is XGATE=0 & Prefix18=0 & op8=0x1C; opr16a_8; msk8 +{ + result:1 = opr16a_8 | msk8; + opr16a_8 = result; + $(N) = (result s< 0); + $(Z) = (result == 0); + V_equals_0(); +} + +:BSET indexed1_3, msk8 is XGATE=0 & Prefix18=0 & op8=0x0C; indexed1_3; msk8 +{ + result:1 = indexed1_3 | msk8; + indexed1_3 = result; + $(N) = (result s< 0); + $(Z) = (result == 0); + V_equals_0(); +} + +:BSR rel8 is XGATE=0 & Prefix18=0 & op8=0x07; rel8 +{ + tmp:2 = inst_next; + Push2( tmp ); + + call rel8; +} + +@if defined(HCS12X) +:BTAS opr8a_8, msk8 is XGATE=0 & Prefix18=1 & (op8=0x35); opr8a_8; msk8 +{ + op1:1 = opr8a_8; + tmp:1 = op1 & msk8; + $(N) = tmp[7,1]; + $(Z) = (tmp == 0); + $(V) = 0; + opr8a_8 = op1 | msk8; +} +@endif + +@if defined(HCS12X) +:BTAS opr16a_8, msk8 is XGATE=0 & Prefix18=1 & (op8=0x36); opr16a_8; msk8 +{ + op1:1 = opr16a_8; + tmp:1 = op1 & msk8; + $(N) = tmp[7,1]; + $(Z) = (tmp == 0); + $(V) = 0; + opr16a_8 = op1 | msk8; +} +@endif + +@if defined(HCS12X) +:BTAS indexed1_3, msk8 is XGATE=0 & Prefix18=1 & (op8=0x37); indexed1_3; msk8 +{ + op1:1 = indexed1_3; + tmp:1 = op1 & msk8; + $(N) = tmp[7,1]; + $(Z) = (tmp == 0); + $(V) = 0; + indexed1_3 = op1 | msk8; +} +@endif + + +:BVC rel8 is XGATE=0 & Prefix18=0 & op8=0x28; rel8 +{ + if ($(V) == 0) goto rel8; +} + +:BVS rel8 is XGATE=0 & Prefix18=0 & op8=0x29; rel8 +{ + if ($(V) == 1) goto rel8; +} + +CallDest: PageDest, imm8 is (imm16; imm8) & PageDest { + PPAGE = imm8; + + build PageDest; + + export PageDest; +} + +:CALL CallDest is XGATE=0 & Prefix18=0 & op8=0x4A; CallDest +{ + tmp:2 = inst_next; + Push2( tmp ); + + Push1( PPAGE ); + + build CallDest; + + local dest:3 = CallDest; + call [dest]; +} + +:CALL indexed2_3, page is XGATE=0 & Prefix18=0 & (op8=0x4B); indexed2_3; page +{ + tmp:2 = inst_next; + Push2( tmp ); + + Push1( PPAGE ); + PPAGE = page; + + build indexed2_3; + + local dest:3; + GetPagedAddr(indexed2_3,dest); + call [dest]; +} + +:CALL indexed0_2 is XGATE=0 & Prefix18=0 & (op8=0x4B); indexed0_2 +{ + tmp:2 = inst_next; + Push2( tmp ); + + Push1( PPAGE ); + Load1(PPAGE, indexed0_2 + 2); + + local addr:2; + Load2(addr,indexed0_2); + + local dest:3; + GetPagedAddr(addr,dest); + call [dest]; +} + +:CBA is XGATE=0 & (Prefix18=1 & op8=0x17) +{ + tmp:1 = A - B; + $(N) = (tmp s< 0); + $(Z) = (tmp == 0); + V_CMP_flag(A, B); + $(C) = (B > A); +} + +:CLC is XGATE=0 & Prefix18=0 & op16=0x10FE +{ + $(C) = 0; +} + +:CLI is XGATE=0 & Prefix18=0 & op16=0x10EF +{ + $(I) = 0; +} + +:CLR opr16a_8 is XGATE=0 & Prefix18=0 & (op8=0x79); opr16a_8 +{ + opr16a_8 = 0; + $(N) = 0; + $(Z) = 1; + V_equals_0(); + $(C) = 0; +} + +:CLR indexed1_5 is XGATE=0 & Prefix18=0 & (op8=0x69); indexed1_5 +{ + indexed1_5 = 0; + $(N) = 0; + $(Z) = 1; + V_equals_0(); + $(C) = 0; +} + +:CLRA is XGATE=0 & Prefix18=0 & op8=0x87 +{ + A = 0; + $(N) = 0; + $(Z) = 1; + V_equals_0(); + $(C) = 0; +} + +:CLRB is XGATE=0 & Prefix18=0 & op8=0xC7 +{ + B = 0; + $(N) = 0; + $(Z) = 1; + V_equals_0(); + $(C) = 0; +} + +@if defined(HCS12X) +:CLRW opr16a_16 is XGATE=0 & Prefix18=1 & (op8=0x79); opr16a_16 +{ + opr16a_16 = 0; + $(N) = 0; + $(Z) = 1; + V_equals_0(); + $(C) = 0; +} +@endif + +@if defined(HCS12X) +:CLRW indexed2_5 is XGATE=0 & Prefix18=1 & (op8=0x69); indexed2_5 +{ + indexed2_5 = 0; + $(N) = 0; + $(Z) = 1; + V_equals_0(); + $(C) = 0; +} +@endif + +@if defined(HCS12X) +:CLRX is XGATE=0 & Prefix18=1 & op8=0x87 +{ + IX = 0; + $(N) = 0; + $(Z) = 1; + V_equals_0(); + $(C) = 0; +} +@endif + +@if defined(HCS12X) +:CLRY is XGATE=0 & Prefix18=1 & op8=0xC7 +{ + IY = 0; + $(N) = 0; + $(Z) = 1; + V_equals_0(); + $(C) = 0; +} +@endif + +:CLV is XGATE=0 & Prefix18=0 & op16=0x10FD +{ + $(V) = 0; +} + +:CMPA iopr8i is XGATE=0 & Prefix18=0 & (op8=0x81); iopr8i +{ + op1:1 = iopr8i; + tmp:1 = A - op1; + $(N) = (tmp s< 0); + $(Z) = (tmp == 0); + V_CMP_flag(A, op1); + $(C) = (op1 > A); +} + +:CMPA opr8a_8 is XGATE=0 & Prefix18=0 & (op8=0x91); opr8a_8 +{ + op1:1 = opr8a_8; + tmp:1 = A - op1; + $(N) = (tmp s< 0); + $(Z) = (tmp == 0); + V_CMP_flag(A, op1); + $(C) = (op1 > A); +} + +:CMPA opr16a_8 is XGATE=0 & Prefix18=0 & (op8=0xB1); opr16a_8 +{ + op1:1 = opr16a_8; + tmp:1 = A - op1; + $(N) = (tmp s< 0); + $(Z) = (tmp == 0); + V_CMP_flag(A, op1); + $(C) = (op1 > A); +} + +:CMPA indexed1_5 is XGATE=0 & Prefix18=0 & (op8=0xA1); indexed1_5 +{ + op1:1 = indexed1_5; + tmp:1 = A - op1; + $(N) = (tmp s< 0); + $(Z) = (tmp == 0); + V_CMP_flag(A, op1); + $(C) = (op1 > A); +} + +:CMPB iopr8i is XGATE=0 & Prefix18=0 & (op8=0xC1); iopr8i +{ + op1:1 = iopr8i; + tmp:1 = B - op1; + $(N) = (tmp s< 0); + $(Z) = (tmp == 0); + V_CMP_flag(B, op1); + $(C) = (op1 > B); +} + +:CMPB opr8a_8 is XGATE=0 & Prefix18=0 & (op8=0xD1); opr8a_8 +{ + op1:1 = opr8a_8; + tmp:1 = B - op1; + $(N) = (tmp s< 0); + $(Z) = (tmp == 0); + V_CMP_flag(B, op1); + $(C) = (op1 > B); +} + +:CMPB opr16a_8 is XGATE=0 & Prefix18=0 & (op8=0xF1); opr16a_8 +{ + op1:1 = opr16a_8; + tmp:1 = B - op1; + $(N) = (tmp s< 0); + $(Z) = (tmp == 0); + V_CMP_flag(B, op1); + $(C) = (op1 > B); +} + +:CMPB indexed1_5 is XGATE=0 & Prefix18=0 & (op8=0xE1); indexed1_5 +{ + op1:1 = indexed1_5; + tmp:1 = B - op1; + $(N) = (tmp s< 0); + $(Z) = (tmp == 0); + V_CMP_flag(B, op1); + $(C) = (op1 > B); +} + +:COM opr16a_8 is XGATE=0 & Prefix18=0 & (op8=0x71); opr16a_8 +{ + tmp:1 = ~opr16a_8; + opr16a_8 = tmp; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = 1; + V_equals_0(); +} + +:COM indexed1_5 is XGATE=0 & Prefix18=0 & (op8=0x61); indexed1_5 +{ + tmp:1 = ~indexed1_5; + indexed1_5 = tmp; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = 1; + V_equals_0(); +} + +:COMA is XGATE=0 & Prefix18=0 & op8=0x41 +{ + A = ~A; + $(Z) = (A == 0); + $(N) = (A s< 0); + $(C) = 1; + V_equals_0(); +} + +:COMB is XGATE=0 & Prefix18=0 & op8=0x51 +{ + B = ~B; + $(Z) = (B == 0); + $(N) = (B s< 0); + $(C) = 1; + V_equals_0(); +} + +@if defined(HCS12X) +:COMW opr16a_16 is XGATE=0 & Prefix18=1 & (op8=0x71); opr16a_16 +{ + local tmp = ~opr16a_16; + opr16a_16 = tmp; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = 1; + V_equals_0(); +} +@endif + +@if defined(HCS12X) +:COMW indexed2_5 is XGATE=0 & Prefix18=1 & (op8=0x61); indexed2_5 +{ + local tmp = ~indexed2_5; + indexed2_5 = tmp; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = 1; + V_equals_0(); +} +@endif + +@if defined(HCS12X) +:COMX is XGATE=0 & Prefix18=1 & op8=0x41 +{ + IX = ~IX; + $(Z) = (IX == 0); + $(N) = (IX s< 0); + $(C) = 1; + V_equals_0(); +} +@endif + +@if defined(HCS12X) +:COMY is XGATE=0 & Prefix18=1 & op8=0x51 +{ + IY = ~IY; + $(Z) = (IY == 0); + $(N) = (IY s< 0); + $(C) = 1; + V_equals_0(); +} +@endif + +:CPD iopr16i is XGATE=0 & Prefix18=0 & (op8=0x8C); iopr16i +{ + op1:2 = iopr16i; + tmp:2 = D - op1; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = (op1 > D); + V_CMP_flag(D, op1); +} + +:CPD opr8a_16 is XGATE=0 & Prefix18=0 & (op8=0x9C); opr8a_16 +{ + op1:2 = opr8a_16; + tmp:2 = D - op1; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = (op1 > D); + V_CMP_flag(D, op1); +} + +:CPD opr16a_16 is XGATE=0 & Prefix18=0 & (op8=0xBC); opr16a_16 +{ + op1:2 = opr16a_16; + tmp:2 = D - op1; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = (op1 > D); + V_CMP_flag(D, op1); +} + +:CPD indexed2_5 is XGATE=0 & Prefix18=0 & (op8=0xAC); indexed2_5 +{ + op1:2 = indexed2_5; + tmp:2 = D - op1; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = (op1 > D); + V_CMP_flag(D, op1); +} + +@if defined(HCS12X) +:CPED iopr16i is XGATE=0 & Prefix18=1 & (op8=0x8C); iopr16i +{ + op1:2 = iopr16i; + tmp:2 = D - (op1 + zext($(C))); + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = (op1 > D); + V_CMP_flag(D, op1); +} +@endif + +@if defined(HCS12X) +:CPED opr8a_16 is XGATE=0 & Prefix18=1 & (op8=0x9C); opr8a_16 +{ + op1:2 = opr8a_16; + tmp:2 = D - (op1 + zext($(C))); + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = (op1 > D); + V_CMP_flag(D, op1); +} +@endif + +@if defined(HCS12X) +:CPED opr16a_16 is XGATE=0 & Prefix18=1 & (op8=0xBC); opr16a_16 +{ + op1:2 = opr16a_16; + tmp:2 = D - (op1 + zext($(C))); + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = (op1 > D); + V_CMP_flag(D, op1); +} +@endif + +@if defined(HCS12X) +:CPED indexed2_5 is XGATE=0 & Prefix18=1 & (op8=0xAC); indexed2_5 +{ + op1:2 = indexed2_5; + tmp:2 = D - (op1 + zext($(C))); + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = (op1 > D); + V_CMP_flag(D, op1); +} +@endif + +@if defined(HCS12X) +:CPES iopr16i is XGATE=0 & Prefix18=1 & (op8=0x8F); iopr16i +{ + op1:2 = iopr16i; + tmp:2 = SP - (op1 + zext($(C))); + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = (op1 > SP); + V_CMP_flag(SP, op1); +} +@endif + +@if defined(HCS12X) +:CPES opr8a_16 is XGATE=0 & Prefix18=1 & (op8=0x9F); opr8a_16 +{ + op1:2 = opr8a_16; + tmp:2 = SP - (op1 + zext($(C))); + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = (op1 > SP); + V_CMP_flag(SP, op1); +} +@endif + +@if defined(HCS12X) +:CPES opr16a_16 is XGATE=0 & Prefix18=1 & (op8=0xBF); opr16a_16 +{ + op1:2 = opr16a_16; + tmp:2 = SP - (op1 + zext($(C))); + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = (op1 > SP); + V_CMP_flag(SP, op1); +} +@endif + +@if defined(HCS12X) +:CPES indexed2_5 is XGATE=0 & Prefix18=1 & (op8=0xAF); indexed2_5 +{ + op1:2 = indexed2_5; + tmp:2 = SP - (op1 + zext($(C))); + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = (op1 > SP); + V_CMP_flag(SP, op1); +} +@endif + +@if defined(HCS12X) +:CPEX iopr16i is XGATE=0 & Prefix18=1 & (op8=0x8E); iopr16i +{ + op1:2 = iopr16i; + tmp:2 = IX - (op1 + zext($(C))); + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = (op1 > IX); + V_CMP_flag(IX, op1); +} +@endif + +@if defined(HCS12X) +:CPEX opr8a_16 is XGATE=0 & Prefix18=1 & (op8=0x9E); opr8a_16 +{ + op1:2 = opr8a_16; + tmp:2 = IX - (op1 + zext($(C))); + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = (op1 > IX); + V_CMP_flag(IX, op1); +} +@endif + +@if defined(HCS12X) +:CPEX opr16a_16 is XGATE=0 & Prefix18=1 & (op8=0xBE); opr16a_16 +{ + op1:2 = opr16a_16; + tmp:2 = IX - (op1 + zext($(C))); + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = (op1 > IX); + V_CMP_flag(IX, op1); +} +@endif + +@if defined(HCS12X) +:CPEX indexed2_5 is XGATE=0 & Prefix18=1 & (op8=0xAE); indexed2_5 +{ + op1:2 = indexed2_5; + tmp:2 = IX - (op1 + zext($(C))); + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = (op1 > IX); + V_CMP_flag(IX, op1); +} +@endif + +@if defined(HCS12X) +:CPEY iopr16i is XGATE=0 & Prefix18=1 & (op8=0x8D); iopr16i +{ + op1:2 = iopr16i; + tmp:2 = IY - (op1 + zext($(C))); + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = (op1 > IY); + V_CMP_flag(IY, op1); +} +@endif + +@if defined(HCS12X) +:CPEY opr8a_16 is XGATE=0 & Prefix18=1 & (op8=0x9D); opr8a_16 +{ + op1:2 = opr8a_16; + tmp:2 = IY - (op1 + zext($(C))); + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = (op1 > IY); + V_CMP_flag(IY, op1); +} +@endif + +@if defined(HCS12X) +:CPEY opr16a_16 is XGATE=0 & Prefix18=1 & (op8=0xBD); opr16a_16 +{ + op1:2 = opr16a_16; + tmp:2 = IY - (op1 + zext($(C))); + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = (op1 > IY); + V_CMP_flag(IY, op1); +} +@endif + +@if defined(HCS12X) +:CPEY indexed2_5 is XGATE=0 & Prefix18=1 & (op8=0xAD); indexed2_5 +{ + op1:2 = indexed2_5; + tmp:2 = IY - (op1 + zext($(C))); + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = (op1 > IY); + V_CMP_flag(IY, op1); +} +@endif + +SkipNext2Bytes: dest is epsilon [ dest = inst_next + 2; ] { export *[RAM]:1 dest; } + +:CPS loc is XGATE=0 & Prefix18=0 & (op8=0x8F) & SkipNext2Bytes [ loc = (inst_next & 0xffffff); ] +{ + local addr:3 = inst_next; + local op1:2 = *[RAM]:2 addr; + tmp:2 = SP - op1; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = (op1 > SP); + V_CMP_flag(SP, op1); + goto SkipNext2Bytes; +} + +:CPS opr8a_16 is XGATE=0 & Prefix18=0 & (op8=0x9F); opr8a_16 +{ + op1:2 = opr8a_16; + tmp:2 = SP - op1; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = (op1 > SP); + V_CMP_flag(SP, op1); +} + +:CPS loc is XGATE=0 & Prefix18=0 & (op8=0xBF) & SkipNext2Bytes [ loc = (inst_next & 0xffffff); ] +{ + local addr:3 = inst_next; + local op1:2 = *[RAM]:2 addr; + Load2(op1, op1); + tmp:2 = SP - op1; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = (op1 > SP); + V_CMP_flag(SP, op1); + goto SkipNext2Bytes; +} + +:CPS indexed2_5 is XGATE=0 & Prefix18=0 & (op8=0xAF); indexed2_5 +{ + op1:2 = indexed2_5; + tmp:2 = SP - op1; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = (op1 > SP); + V_CMP_flag(SP, op1); +} + +:CPX iopr16i is XGATE=0 & Prefix18=0 & (op8=0x8E); iopr16i +{ + op1:2 = iopr16i; + tmp:2 = IX - op1; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = (op1 > IX); + V_CMP_flag(IX, op1); +} + +:CPX opr8a_16 is XGATE=0 & Prefix18=0 & (op8=0x9E); opr8a_16 +{ + op1:2 = opr8a_16; + tmp:2 = IX - op1; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = (op1 > IX); + V_CMP_flag(IX, op1); +} + +:CPX opr16a_16 is XGATE=0 & Prefix18=0 & (op8=0xBE); opr16a_16 +{ + op1:2 = opr16a_16; + tmp:2 = IX - op1; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = (op1 > IX); + V_CMP_flag(IX, op1); +} + +:CPX indexed2_5 is XGATE=0 & Prefix18=0 & (op8=0xAE); indexed2_5 +{ + op1:2 = indexed2_5; + tmp:2 = IX - op1; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = (op1 > IX); + V_CMP_flag(IX, op1); +} + +:CPY iopr16i is XGATE=0 & Prefix18=0 & (op8=0x8D); iopr16i +{ + op1:2 = iopr16i; + tmp:2 = IY - op1; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = (op1 > IY); + V_CMP_flag(IY, op1); +} + +:CPY opr8a_16 is XGATE=0 & Prefix18=0 & (op8=0x9D); opr8a_16 +{ + op1:2 = opr8a_16; + tmp:2 = IY - op1; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = (op1 > IY); + V_CMP_flag(IY, op1); +} + +:CPY opr16a_16 is XGATE=0 & Prefix18=0 & (op8=0xBD); opr16a_16 +{ + op1:2 = opr16a_16; + tmp:2 = IY - op1; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = (op1 > IY); + V_CMP_flag(IY, op1); +} + +:CPY indexed2_5 is XGATE=0 & Prefix18=0 & (op8=0xAD); indexed2_5 +{ + op1:2 = indexed2_5; + tmp:2 = IY - op1; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + $(C) = (op1 > IY); + V_CMP_flag(IY, op1); +} + +:DAA is XGATE=0 & Prefix18=1 & op8=0x07 +{ + A = decimalAdjustAccumulator(A, $(C), $(H)); + $(C) = decimalAdjustCarry(A, $(C), $(H)); + $(Z) = (A == 0); + $(N) = (A s< 0); + #V is undefined +} + +:DBEQ byte9_8, rel9 is XGATE=0 & Prefix18=0 & op8=0x04; op15_13=0x0 & size10_10=0 & byte9_8 & rel9 +{ + byte9_8 = byte9_8 - 1; + if (byte9_8 == 0) goto rel9; +} + +:DBEQ word9_8, rel9 is XGATE=0 & Prefix18=0 & op8=0x04; op15_13=0x0 & size10_10=1 & word9_8 & rel9 +{ + word9_8 = word9_8 - 1; + if (word9_8 == 0) goto rel9; +} + +:DBNE byte9_8, rel9 is XGATE=0 & Prefix18=0 & op8=0x04; op15_13=0x1 & size10_10=0 & byte9_8 & rel9 +{ + byte9_8 = byte9_8 - 1; + if (byte9_8 != 0) goto rel9; +} + +:DBNE word9_8, rel9 is XGATE=0 & Prefix18=0 & op8=0x04; op15_13=0x1 & size10_10=1 & word9_8 & rel9 +{ + word9_8 = word9_8 - 1; + if (word9_8 != 0) goto rel9; +} + +:DEC opr16a_8 is XGATE=0 & Prefix18=0 & (op8=0x73); opr16a_8 +{ + tmp:1 = opr16a_8; + result:1 = tmp - 1; + opr16a_8 = result; + $(Z) = (result == 0); + $(N) = (result s< 0); + V_DEC_flag(tmp); +} + +:DEC indexed1_5 is XGATE=0 & Prefix18=0 & (op8=0x63); indexed1_5 +{ + tmp:1 = indexed1_5; + result:1 = tmp - 1; + indexed1_5 = result; + $(Z) = (result == 0); + $(N) = (result s< 0); + V_DEC_flag(tmp); +} + +:DECA is XGATE=0 & Prefix18=0 & op8=0x43 +{ + tmp:1 = A; + A = tmp - 1; + $(Z) = (A == 0); + $(N) = (A s< 0); + V_DEC_flag(tmp); +} + +:DECB is XGATE=0 & Prefix18=0 & op8=0x53 +{ + tmp:1 = B; + B = tmp - 1; + $(Z) = (B == 0); + $(N) = (B s< 0); + V_DEC_flag(tmp); +} + +@if defined(HCS12X) +:DECW opr16a_16 is XGATE=0 & Prefix18=1 & (op8=0x73); opr16a_16 +{ + local tmp = opr16a_16; + local result = tmp - 1; + opr16a_16 = result; + $(Z) = (result == 0); + $(N) = (result s< 0); + V_DEC_flag2(tmp); +} +@endif + +@if defined(HCS12X) +:DECW indexed2_5 is XGATE=0 & Prefix18=1 & (op8=0x63); indexed2_5 +{ + local tmp = indexed2_5; + local result = tmp - 1; + indexed2_5 = result; + $(Z) = (result == 0); + $(N) = (result s< 0); + V_DEC_flag2(tmp); +} +@endif + +@if defined(HCS12X) +:DECX is XGATE=0 & Prefix18=1 & op8=0x43 +{ + local tmp = IX; + IX = tmp - 1; + $(Z) = (IX == 0); + $(N) = (IX s< 0); + V_DEC_flag2(tmp); +} +@endif + +@if defined(HCS12X) +:DECY is XGATE=0 & Prefix18=1 & op8=0x53 +{ + local tmp = IY; + IY = tmp - 1; + $(Z) = (IY == 0); + $(N) = (IY s< 0); + V_DEC_flag2(tmp); +} +@endif + +:DES is XGATE=0 & Prefix18=0 & op16=0x1B9F +{ + SP = SP - 1; +} + +:DEX is XGATE=0 & Prefix18=0 & op8=0x09 +{ + IX = IX - 1; + $(Z) = (IX == 0); +} + +:DEY is XGATE=0 & Prefix18=0 & op8=0x03 +{ + IY = IY - 1; + $(Z) = (IY == 0); +} + +:EDIV is XGATE=0 & Prefix18=0 & op8=0x11 +{ + tmp:4 = (zext(IY) << 16) | (zext(D)); + resultQ:4 = tmp / zext(IX); + resultR:4 = tmp % zext(IX); + IY = resultQ:2; + D = resultR:2; + $(N) = (IY s< 0); + $(Z) = (IY == 0); + $(V) = (resultQ > 0x0000FFFF); + $(C) = (IX == 0); +} + +:EDIVS is XGATE=0 & Prefix18=1 & op8=0x14 +{ + tmp:4 = (zext(IY) << 16) | (zext(D)); + resultQ:4 = tmp s/ sext(IX); + resultR:4 = tmp s% sext(IX); + IY = resultQ:2; + D = resultR:2; + $(N) = (IY s< 0); + $(Z) = (IY == 0); + $(V) = (resultQ s> 0x00007FFF) | (resultQ s< 0x00008000); + $(C) = (IX == 0); +} + +:EMACS opr16a is XGATE=0 & Prefix18=1 & op8=0x12; opr16a +{ + local valx:2 = 0; + local valy:2 = 0; + Load2(valx,IX); + Load2(valy,IY); + result:4 = sext(valx) * sext(valy); + Store(opr16a, result); + $(N) = (result s< 0); + $(Z) = (result == 0); + $(V) = (result s> 0x000000007FFFFFFF) | (result s< 0x0000000080000000); + $(C) = (result > 0x00000000FFFFFFFF); +} + +:EMAXD indexed2_5 is XGATE=0 & Prefix18=1 & op8=0x1A; indexed2_5 +{ + result:4 = zext(D) - zext(indexed2_5); + if (D > indexed2_5) goto ; + D = indexed2_5; + + + $(N) = (result:2 s< 0); + $(Z) = (result:2 == 0); + $(V) = (result s> 0x00007FFF) | (result s< 0x00008000); + $(C) = (result > 0x0000FFFF); +} + +:EMAXM indexed2_5 is XGATE=0 & Prefix18=1 & op8=0x1E; indexed2_5 +{ + result:4 = zext(D) - zext(indexed2_5); + if (D > indexed2_5) goto ; + indexed2_5 = D; + + + $(N) = (result:2 s< 0); + $(Z) = (result:2 == 0); + $(V) = (result s> 0x00007FFF) | (result s< 0x00008000); + $(C) = (result > 0x0000FFFF); +} + +:EMIND indexed2_5 is XGATE=0 & Prefix18=1 & op8=0x1B; indexed2_5 +{ + result:4 = zext(D) - zext(indexed2_5); + if (D < indexed2_5) goto ; + D = indexed2_5; + + + $(N) = (result:2 s< 0); + $(Z) = (result:2 == 0); + $(V) = (result s> 0x00007FFF) | (result s< 0x00008000); + $(C) = (result > 0x0000FFFF); +} + +:EMINM indexed2_5 is XGATE=0 & Prefix18=1 & op8=0x1F; indexed2_5 +{ + result:4 = zext(D) - zext(indexed2_5); + if (D < indexed2_5) goto ; + indexed2_5 = D; + + + $(N) = (result:2 s< 0); + $(Z) = (result:2 == 0); + $(V) = (result s> 0x00007FFF) | (result s< 0x00008000); + $(C) = (result > 0x0000FFFF); +} + +:EMUL is XGATE=0 & Prefix18=0 & op8=0x13 +{ + result:4 = zext(D) * zext(IY); + IY = result(2); + D = result:2; + $(N) = result[31,1]; + $(Z) = (result == 0); + $(C) = result[15,1]; +} + +:EMULS is XGATE=0 & Prefix18=1 & op8=0x13 +{ + result:4 = sext(D) * sext(IY); + IY = result(2); + D = result:2; + $(N) = result[31,1]; + $(Z) = (result == 0); + $(C) = result[15,1]; +} + +:EORA iopr8i is XGATE=0 & Prefix18=0 & (op8=0x88); iopr8i +{ + op1:1 = iopr8i; + A = A ^ op1; + $(Z) = (A == 0); + $(N) = (A s< 0); + V_equals_0(); +} + +:EORA opr8a_8 is XGATE=0 & Prefix18=0 & (op8=0x98); opr8a_8 +{ + op1:1 = opr8a_8; + A = A ^ op1; + $(Z) = (A == 0); + $(N) = (A s< 0); + V_equals_0(); +} + +:EORA opr16a_8 is XGATE=0 & Prefix18=0 & (op8=0xB8); opr16a_8 +{ + op1:1 = opr16a_8; + A = A ^ op1; + $(Z) = (A == 0); + $(N) = (A s< 0); + V_equals_0(); +} + +:EORA indexed1_5 is XGATE=0 & Prefix18=0 & (op8=0xA8); indexed1_5 +{ + op1:1 = indexed1_5; + A = A ^ op1; + $(Z) = (A == 0); + $(N) = (A s< 0); + V_equals_0(); +} + +:EORB iopr8i is XGATE=0 & Prefix18=0 & (op8=0xC8); iopr8i +{ + op1:1 = iopr8i; + B = B ^ op1; + $(Z) = (B == 0); + $(N) = (B s< 0); + V_equals_0(); +} + +:EORB opr8a_8 is XGATE=0 & Prefix18=0 & (op8=0xD8); opr8a_8 +{ + op1:1 = opr8a_8; + B = B ^ op1; + $(Z) = (B == 0); + $(N) = (B s< 0); + V_equals_0(); +} + +:EORB opr16a_8 is XGATE=0 & Prefix18=0 & (op8=0xF8); opr16a_8 +{ + op1:1 = opr16a_8; + B = B ^ op1; + $(Z) = (B == 0); + $(N) = (B s< 0); + V_equals_0(); +} + +:EORB indexed1_5 is XGATE=0 & Prefix18=0 & (op8=0xE8); indexed1_5 +{ + op1:1 = indexed1_5; + B = B ^ op1; + $(Z) = (B == 0); + $(N) = (B s< 0); + V_equals_0(); +} + +@if defined(HCS12X) +:EORX iopr16i is XGATE=0 & Prefix18=1 & (op8=0x88); iopr16i +{ + local op1 = iopr16i; + IX = IX ^ op1; + $(Z) = (IX == 0); + $(N) = (IX s< 0); + V_equals_0(); +} +@endif + +@if defined(HCS12X) +:EORX opr8a_16 is XGATE=0 & Prefix18=1 & (op8=0x98); opr8a_16 +{ + local op1 = opr8a_16; + IX = IX ^ op1; + $(Z) = (IX == 0); + $(N) = (IX s< 0); + V_equals_0(); +} +@endif + +@if defined(HCS12X) +:EORX opr16a_16 is XGATE=0 & Prefix18=1 & (op8=0xB8); opr16a_16 +{ + local op1 = opr16a_16; + IX = IX ^ op1; + $(Z) = (IX == 0); + $(N) = (IX s< 0); + V_equals_0(); +} +@endif + +@if defined(HCS12X) +:EORX indexed2_5 is XGATE=0 & Prefix18=1 & (op8=0xA8); indexed2_5 +{ + local op1 = indexed2_5; + IX = IX ^ op1; + $(Z) = (IX == 0); + $(N) = (IX s< 0); + V_equals_0(); +} +@endif + +@if defined(HCS12X) +:EORY iopr16i is XGATE=0 & Prefix18=1 & (op8=0xC8); iopr16i +{ + local op1 = iopr16i; + IY = IY ^ op1; + $(Z) = (IY == 0); + $(N) = (IY s< 0); + V_equals_0(); +} +@endif + +@if defined(HCS12X) +:EORY opr8a_16 is XGATE=0 & Prefix18=1 & (op8=0xD8); opr8a_16 +{ + local op1 = opr8a_16; + IY = IY ^ op1; + $(Z) = (IY == 0); + $(N) = (IY s< 0); + V_equals_0(); +} + +@if defined(HCS12X) +:EORY opr16a_16 is XGATE=0 & Prefix18=1 & (op8=0xF8); opr16a_16 +{ + local op1 = opr16a_16; + IY = IY ^ op1; + $(Z) = (IY == 0); + $(N) = (IY s< 0); + V_equals_0(); +} +@endif + +@if defined(HCS12X) +:EORY indexed2_5 is XGATE=0 & Prefix18=1 & (op8=0xE8); indexed2_5 +{ + local op1 = indexed2_5; + IY = IY ^ op1; + $(Z) = (IY == 0); + $(N) = (IY s< 0); + V_equals_0(); +} +@endif + +:ETBL indexed2_1 is XGATE=0 & Prefix18=1 & op8=0x3F; indexed2_1 +{ + D = ETBL( indexed2_1, B ); + $(N) = (D s< 0); + $(Z) = (D == 0); + $(C) = ETBL_Cflag( indexed2_1, B ); +} + +# this case 'C0' or 'C8', does not display similarly to other members of either its row or column +:EXG D, A is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( + ( rows3_0=0x0 & ( columns7_4=0xC ) ) | + + ( rows3_0=0x8 & ( columns7_4=0xC ) ) + ) & + D & A +{ + tmp:1 = B; + B = A; + A = tmp; +} + +# this case 'C1' or 'C9', does not work similarly to other members of either its row or column +:EXG D, B is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( + ( rows3_0=0x1 & ( columns7_4=0xC ) ) | + + ( rows3_0=0x9 & ( columns7_4=0xC ) ) + ) & + D & B +{ + B = B; + A = 0xFF; +} + +# this case '84' or '8C', does not work similarly to other members of either its row or column +:EXG A, D is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( + ( rows3_0=0x4 & ( columns7_4=0x8 ) ) | + + ( rows3_0=0xC & ( columns7_4=0x8 ) ) + ) & + A & D +{ + D = zext(A); +} + +# this case '94' or '9C', does not work similarly to other members of either its row or column +:EXG B, D is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( + ( rows3_0=0x4 & ( columns7_4=0x9 ) ) | + + ( rows3_0=0xC & ( columns7_4=0x9 ) ) + ) & + B & D +{ + D = zext(B); +} + +# this case 'A8', does not work the same as 'A0' +:EXG CCRH, A is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( + ( rows3_0=0x8 & ( columns7_4=0xA ) ) + ) & + CCRH & A +{ + tmp:1 = CCRH; + CCRH = A; + A = tmp; +} + +# this case '8A', does not work the same as '82' +:EXG A, CCRH is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( + ( rows3_0=0xA & ( columns7_4=0x8 ) ) + ) & + A & CCRH +{ + tmp:1 = A; + A = CCRH; + CCRH = tmp; +} + +# this case 'AA', does not display the same as 'A2' +:EXG CCRW, "CCRW" is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( + ( rows3_0=0xA & ( columns7_4=0xA ) ) + ) & + CCRW +{ + CCRW = CCRW; +} + +:EXG bytes_ABCl_6_4, bytes_ABCl_2_0 is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( + ( rows3_0=0x0 & ( columns7_4=0x8 | columns7_4=0x9 ) ) | + ( rows3_0=0x1 & ( columns7_4=0x8 | columns7_4=0x9 ) ) | + + ( rows3_0=0x8 & ( columns7_4=0x8 | columns7_4=0x9 ) ) | + ( rows3_0=0x9 & ( columns7_4=0x8 | columns7_4=0x9 ) ) + ) & + bytes_ABCl_6_4 & bytes_ABCl_2_0 +{ + tmp:1 = bytes_ABCl_2_0; + bytes_ABCl_2_0 = bytes_ABCl_6_4; + bytes_ABCl_6_4 = tmp; +} + +:EXG bytes_ABCl_6_4, CCR is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( + ( rows3_0=0x2 & ( columns7_4=0x8 | columns7_4=0x9 ) ) | + + ( rows3_0=0xA & ( columns7_4=0x9 ) ) + ) & + bytes_ABCl_6_4 & CCR +{ + tmp:1 = bytes_ABCl_6_4; + bytes_ABCl_6_4 = CCR; + setCCR( tmp ); +} + +:EXG CCR, bytes_ABCl_2_0 is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( + ( rows3_0=0x0 & ( columns7_4=0xA ) ) | + ( rows3_0=0x1 & ( columns7_4=0xA ) ) | + ( rows3_0=0x2 & ( columns7_4=0xA ) ) | + + ( rows3_0=0x9 & ( columns7_4=0xA ) ) + ) & + CCR & bytes_ABCl_2_0 +{ + tmp:1 = bytes_ABCl_2_0; + bytes_ABCl_2_0 = CCR; + setCCR( tmp ); +} + +:EXG bytes_T3l_XlYlSl_6_4, A is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( + ( rows3_0=0x0 & ( columns7_4=0xB | columns7_4=0xD | columns7_4=0xE | columns7_4=0xF ) ) + ) & + bytes_T3l_XlYlSl_6_4 & words_T3_XYS_6_4 & A +{ + tmp:2 = zext(A); + A = bytes_T3l_XlYlSl_6_4; + words_T3_XYS_6_4 = tmp; +} + +:EXG bytes_T3h_XhYhSh_6_4, A is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( + ( rows3_0=0x8 & ( columns7_4=0xB | columns7_4=0xD | columns7_4=0xE | columns7_4=0xF ) ) + ) & + bytes_T3h_XhYhSh_6_4 & words_T3_XYS_6_4 & A +{ + tmp:2 = zext(A); + A = bytes_T3h_XhYhSh_6_4; + words_T3_XYS_6_4 = tmp; +} + +:EXG bytes_T3l_XlYlSl_6_4, B is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( + ( rows3_0=0x1 & ( columns7_4=0xB | columns7_4=0xD | columns7_4=0xE | columns7_4=0xF ) ) + ) & + bytes_T3l_XlYlSl_6_4 & words_T3_XYS_6_4 & B +{ + tmp:2 = 0xFF00 | zext(B); + B = bytes_T3l_XlYlSl_6_4; + words_T3_XYS_6_4 = tmp; +} + +:EXG bytes_T3l_XlYlSl_6_4, B is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( + ( rows3_0=0x9 & ( columns7_4=0xB | columns7_4=0xD | columns7_4=0xE | columns7_4=0xF ) ) + ) & + bytes_T3l_XlYlSl_6_4 & B +{ + tmp:1 = B; + B = bytes_T3l_XlYlSl_6_4; + bytes_T3l_XlYlSl_6_4 = tmp; +} + +:EXG bytes_T3lDlXlYlSl_6_4, CCR is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( + ( rows3_0=0x2 & ( columns7_4=0xB | columns7_4=0xC | columns7_4=0xD | columns7_4=0xE | columns7_4=0xF ) ) + ) & + bytes_T3lDlXlYlSl_6_4 & words_T3DXYS_6_4 & CCR +{ + tmp:2 = 0xFF00 | zext(CCR); + # when CCR is the destination, cannot set the X bit unless it is already set in CCR + setCCR( bytes_T3lDlXlYlSl_6_4 ); + words_T3DXYS_6_4 = tmp; +} + +:EXG words_T3DXYS_6_4, CCRW is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( + ( rows3_0=0xA & ( columns7_4=0xB | columns7_4=0xC | columns7_4=0xD | columns7_4=0xE | columns7_4=0xF ) ) + ) & + words_T3DXYS_6_4 & CCRW +{ + tmp:2 = CCRW; + setCCRW( words_T3DXYS_6_4 ); + words_T3DXYS_6_4 = tmp; +} + +# this case 'CB', does not work similarly to other members of either its row or column +:EXG D, TMP1 is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( + ( rows3_0=0xB & ( columns7_4=0xC ) ) + ) & + D & TMP1 +{ + tmp:2 = D; + D = TMP1; + TMP1 = tmp; +} + +# this case 'BC', does not work similarly to other members of either its row or column +:EXG TMP1, D is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( + ( rows3_0=0xC & ( columns7_4=0xB ) ) + ) & + TMP1 & D +{ + tmp:2 = TMP1; + TMP1 = D; + D = tmp; +} + +:EXG words_T3DXYS_6_4, words_T2DXYS_2_0 is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( +# Case "C5" is handled by XGDX +# Case "C6" is handled by XGDY + ( rows3_0=0x3 & ( columns7_4=0xB | columns7_4=0xC | columns7_4=0xD | columns7_4=0xE | columns7_4=0xF ) ) | + ( rows3_0=0x4 & ( columns7_4=0xB | columns7_4=0xC | columns7_4=0xD | columns7_4=0xE | columns7_4=0xF ) ) | + ( rows3_0=0x5 & ( columns7_4=0xB | columns7_4=0xD | columns7_4=0xE | columns7_4=0xF ) ) | + ( rows3_0=0x6 & ( columns7_4=0xB | columns7_4=0xD | columns7_4=0xE | columns7_4=0xF ) ) | + ( rows3_0=0x7 & ( columns7_4=0xB | columns7_4=0xC | columns7_4=0xD | columns7_4=0xE | columns7_4=0xF ) ) | + + ( rows3_0=0xB & ( columns7_4=0xB | columns7_4=0xD | columns7_4=0xE | columns7_4=0xF ) ) | + ( rows3_0=0xC & ( columns7_4=0xC | columns7_4=0xD | columns7_4=0xE | columns7_4=0xF ) ) | + ( rows3_0=0xD & ( columns7_4=0xB | columns7_4=0xC | columns7_4=0xD | columns7_4=0xE | columns7_4=0xF ) ) | + ( rows3_0=0xE & ( columns7_4=0xB | columns7_4=0xC | columns7_4=0xD | columns7_4=0xE | columns7_4=0xF ) ) | + ( rows3_0=0xF & ( columns7_4=0xB | columns7_4=0xC | columns7_4=0xD | columns7_4=0xE | columns7_4=0xF ) ) + ) & + words_T3DXYS_6_4 & words_T2DXYS_2_0 +{ + tmp:2 = words_T3DXYS_6_4; + words_T3DXYS_6_4 = words_T2DXYS_2_0; + words_T2DXYS_2_0 = tmp; +} + +:EXG bytes_ABCl_6_4, words_T2DXYS_2_0 is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( + ( rows3_0=0x3 & ( columns7_4=0x8 | columns7_4=0x9 ) ) | + + ( rows3_0=0x5 & ( columns7_4=0x8 | columns7_4=0x9 ) ) | + ( rows3_0=0x6 & ( columns7_4=0x8 | columns7_4=0x9 ) ) | + ( rows3_0=0x7 & ( columns7_4=0x8 | columns7_4=0x9 ) ) + ) & + bytes_ABCl_6_4 & words_T2DXYS_2_0 & bytes_T2lDlXlYlSl_2_0 +{ + tmp:2 = zext(bytes_ABCl_6_4); + bytes_ABCl_6_4 = bytes_T2lDlXlYlSl_2_0; + words_T2DXYS_2_0 = tmp; +} + +:EXG bytes_ABCl_6_4, bytes_T2hDhXhYhSh_2_0 is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( + ( rows3_0=0xB & ( columns7_4=0x8 ) ) | + + ( rows3_0=0xD & ( columns7_4=0x8 ) ) | + ( rows3_0=0xE & ( columns7_4=0x8 ) ) | + ( rows3_0=0xF & ( columns7_4=0x8 ) ) + ) & + bytes_ABCl_6_4 & bytes_T2hDhXhYhSh_2_0 +{ + tmp:1 = bytes_ABCl_6_4; + bytes_ABCl_6_4 = bytes_T2hDhXhYhSh_2_0; + bytes_T2hDhXhYhSh_2_0 = tmp; +} + +# only column 9 with rows B, (skip C), D, E, and F +:EXG bytes_ABCl_6_4, bytes_T2lDlXlYlSl_2_0 is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( + ( rows3_0=0xB & ( columns7_4=0x9 ) ) | + + ( rows3_0=0xD & ( columns7_4=0x9 ) ) | + ( rows3_0=0xE & ( columns7_4=0x9 ) ) | + ( rows3_0=0xF & ( columns7_4=0x9 ) ) + ) & + bytes_ABCl_6_4 & bytes_T2lDlXlYlSl_2_0 +{ + tmp:1 = bytes_ABCl_6_4; + bytes_ABCl_6_4 = bytes_T2lDlXlYlSl_2_0; + bytes_T2lDlXlYlSl_2_0 = tmp; +} + +:EXG CCR, words_T2DXYS_2_0 is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( + ( rows3_0=0x3 & ( columns7_4=0xA ) ) | + ( rows3_0=0x4 & ( columns7_4=0xA ) ) | + ( rows3_0=0x5 & ( columns7_4=0xA ) ) | + ( rows3_0=0x6 & ( columns7_4=0xA ) ) | + ( rows3_0=0x7 & ( columns7_4=0xA ) ) + ) & + CCR & words_T2DXYS_2_0 & bytes_T2lDlXlYlSl_2_0 +{ + tmp:2 = zext(CCR); + setCCR( bytes_T2lDlXlYlSl_2_0 ); + words_T2DXYS_2_0 = tmp; +} + +:EXG CCRW, words_T2DXYS_2_0 is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( + ( rows3_0=0xB & ( columns7_4=0xA ) ) | + ( rows3_0=0xC & ( columns7_4=0xA ) ) | + ( rows3_0=0xD & ( columns7_4=0xA ) ) | + ( rows3_0=0xE & ( columns7_4=0xA ) ) | + ( rows3_0=0xF & ( columns7_4=0xA ) ) + ) & + CCRW & words_T2DXYS_2_0 +{ + tmp:2 = CCRW; + setCCRW( words_T2DXYS_2_0 ); + words_T2DXYS_2_0 = tmp; +} + +:FDIV is XGATE=0 & Prefix18=1 & op8=0x11 +{ + $(V) = (IX <= D); + $(C) = (IX == 0); + tmp:4 = (zext(D) << 16); + resultQ:4 = tmp / zext(IX); + resultR:4 = tmp % zext(IX); + IX = resultQ:2; + D = resultR:2; + $(Z) = (IX == 0); +} + +#:GLDAA is op16=0x1896 See GPAGE extended LDAA +#:GLDAA is op16=0x18B6 See GPAGE extended LDAA +#:GLDAA is op16=0x18A6 See GPAGE extended LDAA + +#:GLDAB is op16=0x18D6 See GPAGE extended LDAB +#:GLDAB is op16=0x18F6 See GPAGE extended LDAB +#:GLDAB is op16=0x18E6 See GPAGE extended LDAB + +#:GLDD is op16=0x18DC See GPAGE extended LDD +#:GLDD is op16=0x18FC See GPAGE extended LDD +#:GLDD is op16=0x18EC See GPAGE extended LDD + +#:GLDS is op16=0x18DF See GPAGE extended LDS +#:GLDS is op16=0x18FF See GPAGE extended LDS +#:GLDS is op16=0x18EF See GPAGE extended LDS + +#:GLDX is op16=0x18DE See GPAGE extended LDX +#:GLDX is op16=0x18FE See GPAGE extended LDX +#:GLDX is op16=0x18EE See GPAGE extended LDX + +#:GLDY is op16=0x18DD See GPAGE extended LDY +#:GLDY is op16=0x18FD See GPAGE extended LDY +#:GLDY is op16=0x18ED See GPAGE extended LDY + +#:GSTAA is op16=0x185A See GPAGE extended STAA +#:GSTAA is op16=0x187A See GPAGE extended STAA +#:GSTAA is op16=0x186A See GPAGE extended STAA + +#:GSTAB is op16=0x185B See GPAGE extended STAB +#:GSTAB is op16=0x187B See GPAGE extended STAB +#:GSTAB is op16=0x186B See GPAGE extended STAB + +#:GSTD is op16=0x185C See GPAGE extended STD +#:GSTD is op16=0x187C See GPAGE extended STD +#:GSTD is op16=0x186C See GPAGE extended STD + +#:GSTS is op16=0x185F See GPAGE extended STS +#:GSTS is op16=0x187F See GPAGE extended STS +#:GSTS is op16=0x186F See GPAGE extended STS + +#:GSTX is op16=0x185E See GPAGE extended STX +#:GSTX is op16=0x187E See GPAGE extended STX +#:GSTX is op16=0x186E See GPAGE extended STX + +#:GSTY is op16=0x185D See GPAGE extended STY +#:GSTY is op16=0x187D See GPAGE extended STY +#:GSTY is op16=0x186D See GPAGE extended STY + + +:IBEQ byte9_8, rel9 is XGATE=0 & Prefix18=0 & op8=0x04; op15_13=0x4 & size10_10=0 & byte9_8 & rel9 +{ + byte9_8 = byte9_8 + 1; + if (byte9_8 == 0) goto rel9; +} + +:IBEQ word9_8, rel9 is XGATE=0 & Prefix18=0 & op8=0x04; op15_13=0x4 & size10_10=1 & word9_8 & rel9 +{ + word9_8 = word9_8 + 1; + if (word9_8 == 0) goto rel9; +} + +:IBNE byte9_8, rel9 is XGATE=0 & Prefix18=0 & op8=0x04; op15_13=0x5 & size10_10=0 & byte9_8 & rel9 +{ + byte9_8 = byte9_8 + 1; + if (byte9_8 != 0) goto rel9; +} + +:IBNE word9_8, rel9 is XGATE=0 & Prefix18=0 & op8=0x04; op15_13=0x5 & size10_10=1 & word9_8 & rel9 +{ + word9_8 = word9_8 + 1; + if (word9_8 != 0) goto rel9; +} + +:IDIV is XGATE=0 & Prefix18=1 & op8=0x10 +{ + $(C) = (IX == 0); + resultQ:2 = D / IX; + resultR:2 = D % IX; + IX = resultQ; + D = resultR; + $(Z) = (IX == 0); + $(V) = 0; +} + +:IDIVS is XGATE=0 & Prefix18=1 & op8=0x15 +{ + $(C) = (IX == 0); + resultQ:4 = sext(D) s/ sext(IX); + resultR:4 = sext(D) s% sext(IX); + IX = resultQ:2; + D = resultR:2; + $(N) = (IX s< 0); + $(Z) = (IX == 0); + $(V) = (resultQ s> 0x00007FFF) | (resultQ s< 0x00008000); +} + +:INC opr16a_8 is XGATE=0 & Prefix18=0 & (op8=0x72); opr16a_8 +{ + tmp:1 = opr16a_8; + result:1 = tmp + 1; + opr16a_8 = result; + $(Z) = (result == 0); + $(N) = (result s< 0); + V_INC_flag(tmp); +} + +:INC indexed1_5 is XGATE=0 & Prefix18=0 & (op8=0x62); indexed1_5 +{ + tmp:1 = indexed1_5; + result:1 = tmp + 1; + indexed1_5 = result; + $(Z) = (result == 0); + $(N) = (result s< 0); + V_INC_flag(tmp); +} + +:INCA is XGATE=0 & Prefix18=0 & op8=0x42 +{ + tmp:1 = A; + A = tmp + 1; + $(Z) = (A == 0); + $(N) = (A s< 0); + V_INC_flag(tmp); +} + +:INCB is XGATE=0 & Prefix18=0 & op8=0x52 +{ + tmp:1 = B; + B = tmp + 1; + $(Z) = (B == 0); + $(N) = (B s< 0); + V_INC_flag(tmp); +} + +@if defined(HCS12X) +:INCW opr16a_16 is XGATE=0 & Prefix18=1 & (op8=0x72); opr16a_16 +{ + tmp:2 = opr16a_16; + result:2 = tmp + 1; + opr16a_16 = result; + $(Z) = (result == 0); + $(N) = (result s< 0); + V_INC_flag2(tmp); +} +@endif + +@if defined(HCS12X) +:INCW indexed2_5 is XGATE=0 & Prefix18=1 & (op8=0x62); indexed2_5 +{ + tmp:2 = indexed2_5; + result:2 = tmp + 1; + indexed2_5 = result; + $(Z) = (result == 0); + $(N) = (result s< 0); + V_INC_flag2(tmp); +} +@endif + +@if defined(HCS12X) +:INCX is XGATE=0 & Prefix18=1 & op8=0x42 +{ + local tmp = IX; + IX = tmp + 1; + $(Z) = (IX == 0); + $(N) = (IX s< 0); + V_INC_flag2(tmp); +} +@endif + +@if defined(HCS12X) +:INCY is XGATE=0 & Prefix18=1 & op8=0x52 +{ + local tmp = IY; + IY = tmp + 1; + $(Z) = (IY == 0); + $(N) = (IY s< 0); + V_INC_flag2(tmp); +} +@endif + +:INS is XGATE=0 & Prefix18=0 & op16=0x1B81 +{ + SP = SP + 1; +} + +:INX is XGATE=0 & Prefix18=0 & op8=0x08 +{ + IX = IX + 1; + $(Z) = (IX == 0); +} + +:INY is XGATE=0 & Prefix18=0 & op8=0x02 +{ + IY = IY + 1; + $(Z) = (IY == 0); +} + +:JMP opr16a is XGATE=0 & Prefix18=0 & (op8=0x06); opr16a +{ + local target = opr16a; + goto [target]; +} + +:JMP indexed2_5 is XGATE=0 & Prefix18=0 & (op8=0x05); indexed2_5 +{ + goto [indexed2_5]; +} + +:JSR opr8a is XGATE=0 & Prefix18=0 & (op8=0x17); opr8a +{ + tmp:2 = inst_next; + Push2( tmp ); + + local target = opr8a; + call [target]; +} + +:JSR opr16a is XGATE=0 & Prefix18=0 & (op8=0x16); opr16a +{ + tmp:2 = inst_next; + Push2( tmp ); + + local target = opr16a; + call [target]; +} + +:JSR indexed2_5 is XGATE=0 & Prefix18=0 & (op8=0x15); indexed2_5 +{ + tmp:2 = inst_next; + Push2( tmp ); + + call [indexed2_5]; +} + +:LBCC rel16 is XGATE=0 & Prefix18=1 & op8=0x24; rel16 +{ + if ($(C) == 0) goto rel16; +} + +:LBCS rel16 is XGATE=0 & Prefix18=1 & op8=0x25; rel16 +{ + if ($(C) == 1) goto rel16; +} + +:LBEQ rel16 is XGATE=0 & Prefix18=1 & op8=0x27; rel16 +{ + if ($(Z) == 1) goto rel16; +} + +:LBGE rel16 is XGATE=0 & Prefix18=1 & op8=0x2C; rel16 +{ + if (($(N) ^ $(V)) == 1) goto rel16; +} + +:LBGT rel16 is XGATE=0 & Prefix18=1 & op8=0x2E; rel16 +{ + if (($(Z) | ($(N) ^ $(V))) == 0) goto rel16; +} + +:LBHI rel16 is XGATE=0 & Prefix18=1 & op8=0x22; rel16 +{ + if (($(C) | $(Z)) == 0) goto rel16; +} + +#:LBHS rel16 is XGATE=0 & Prefix18=1 & op8=0x24; rel16 See LBCC + +:LBLE rel16 is XGATE=0 & Prefix18=1 & op8=0x2F; rel16 +{ + if ($(Z) | ($(N) ^ $(V))) goto rel16; +} + +#:LBLO rel16 is XGATE=0 & Prefix18=1 & op8=0x25; rel16 see LBCS + +:LBLS rel16 is XGATE=0 & Prefix18=1 & op8=0x23; rel16 +{ + if (($(C) | $(Z)) == 1) goto rel16; +} + +:LBLT rel16 is XGATE=0 & Prefix18=1 & op8=0x2D; rel16 +{ + if (($(N) ^ $(V)) == 1) goto rel16; +} + +:LBMI rel16 is XGATE=0 & Prefix18=1 & op8=0x2B; rel16 +{ + if ($(N) == 1) goto rel16; +} + +:LBNE rel16 is XGATE=0 & Prefix18=1 & op8=0x26; rel16 +{ + if ($(Z) == 0) goto rel16; +} + +:LBPL rel16 is XGATE=0 & Prefix18=1 & op8=0x2A; rel16 +{ + if ($(N) == 0) goto rel16; +} + +:LBRA rel16 is XGATE=0 & Prefix18=1 & op8=0x20; rel16 +{ + goto rel16; +} + +# branch never is a four-byte nop +:LBRN rel16 is XGATE=0 & Prefix18=1 & op8=0x21; rel16 +{ +} + +:LBVC rel16 is XGATE=0 & Prefix18=1 & op8=0x28; rel16 +{ + if ($(V) == 0) goto rel16; +} + +:LBVS rel16 is XGATE=0 & Prefix18=1 & op8=0x29; rel16 +{ + if ($(V) == 1) goto rel16; +} + +:LDAA iopr8i is XGATE=0 & Prefix18=0 & (op8=0x86); iopr8i +{ + A = iopr8i; + $(Z) = (A == 0); + $(N) = (A s< 0); + V_equals_0(); +} + +GPaged: "G" is XGATE=0 & Prefix18=1 [ UseGPAGE=1; ] {} +GPaged: is XGATE=0 & Prefix18=0 [ UseGPAGE=0; ] {} + +:^GPaged^"LDAA" opr8a_8 is XGATE=0 & GPaged & (op8=0x96); opr8a_8 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + A = opr8a_8; + $(Z) = (A == 0); + $(N) = (A s< 0); + V_equals_0(); +} + +:^GPaged^"LDAA" opr16a_8 is XGATE=0 & GPaged & (op8=0xB6); opr16a_8 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + A = opr16a_8; + $(Z) = (A == 0); + $(N) = (A s< 0); + V_equals_0(); +} + +:^GPaged^"LDAA" indexed1_5 is XGATE=0 & GPaged & (op8=0xA6); indexed1_5 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + A = indexed1_5; + $(Z) = (A == 0); + $(N) = (A s< 0); + V_equals_0(); +} + +:LDAB iopr8i is XGATE=0 & Prefix18=0 & (op8=0xC6); iopr8i +{ + B = iopr8i; + $(Z) = (B == 0); + $(N) = (B s< 0); + V_equals_0(); +} + +:^GPaged^"LDAB" opr8a_8 is XGATE=0 & GPaged & (op8=0xD6); opr8a_8 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + B = opr8a_8; + $(Z) = (B == 0); + $(N) = (B s< 0); + V_equals_0(); +} + +:^GPaged^"LDAB" opr16a_8 is XGATE=0 & GPaged & (op8=0xF6); opr16a_8 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + B = opr16a_8; + $(Z) = (B == 0); + $(N) = (B s< 0); + V_equals_0(); +} + +:^GPaged^"LDAB" indexed1_5 is XGATE=0 & GPaged & (op8=0xE6); indexed1_5 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + B = indexed1_5; + $(Z) = (B == 0); + $(N) = (B s< 0); + V_equals_0(); +} + +:LDD iopr16i is XGATE=0 & Prefix18=0 & (op8=0xCC); iopr16i +{ + D = iopr16i; + $(Z) = (D == 0); + $(N) = (D s< 0); + V_equals_0(); +} + +:^GPaged^"LDD" opr8a_16 is XGATE=0 & GPaged & (op8=0xDC); opr8a_16 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + D = opr8a_16; + $(Z) = (D == 0); + $(N) = (D s< 0); + V_equals_0(); +} + +:^GPaged^"LDD" opr16a_16 is XGATE=0 & GPaged & (op8=0xFC); opr16a_16 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + D = opr16a_16; + $(Z) = (D == 0); + $(N) = (D s< 0); + V_equals_0(); +} + +:^GPaged^"LDD" indexed2_5 is XGATE=0 & GPaged & (op8=0xEC); indexed2_5 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + D = indexed2_5; + $(Z) = (D == 0); + $(N) = (D s< 0); + V_equals_0(); +} + + +define pcodeop LoadStack; + +:LDS iopr16i is XGATE=0 & Prefix18=0 & (op8=0xCF); iopr16i +{ + SP = LoadStack(iopr16i); + $(Z) = (SP == 0); + $(N) = (SP s< 0); + V_equals_0(); +} + +:^GPaged^"LDS" opr8a_16 is XGATE=0 & GPaged & (op8=0xDF); opr8a_16 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + SP = LoadStack(opr8a_16); + $(Z) = (SP == 0); + $(N) = (SP s< 0); + V_equals_0(); +} + +:^GPaged^"LDS" opr16a_16 is XGATE=0 & GPaged & (op8=0xFF); opr16a_16 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + SP = LoadStack(opr16a_16); + $(Z) = (SP == 0); + $(N) = (SP s< 0); + V_equals_0(); +} + +:^GPaged^"LDS" indexed2_5 is XGATE=0 & GPaged & (op8=0xEF); indexed2_5 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + SP = LoadStack(indexed2_5); + $(Z) = (SP == 0); + $(N) = (SP s< 0); + V_equals_0(); +} + +:LDX iopr16i is XGATE=0 & Prefix18=0 & (op8=0xCE); iopr16i +{ + IX = iopr16i; + $(Z) = (IX == 0); + $(N) = (IX s< 0); + V_equals_0(); +} + +:^GPaged^"LDX" opr8a_16 is XGATE=0 & GPaged & (op8=0xDE); opr8a_16 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + IX = opr8a_16; + $(Z) = (IX == 0); + $(N) = (IX s< 0); + V_equals_0(); +} + +:^GPaged^"LDX" opr16a_16 is XGATE=0 & GPaged & (op8=0xFE); opr16a_16 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + IX = opr16a_16; + $(Z) = (IX == 0); + $(N) = (IX s< 0); + V_equals_0(); +} + +:^GPaged^"LDX" indexed2_5 is XGATE=0 & GPaged & (op8=0xEE); indexed2_5 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + IX = indexed2_5; + $(Z) = (IX == 0); + $(N) = (IX s< 0); + V_equals_0(); +} + +:LDY iopr16i is XGATE=0 & Prefix18=0 & (op8=0xCD); iopr16i +{ + IY = iopr16i; + $(Z) = (IY == 0); + $(N) = (IY s< 0); + V_equals_0(); +} + +:^GPaged^"LDY" opr8a_16 is XGATE=0 & GPaged & (op8=0xDD); opr8a_16 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + IY = opr8a_16; + $(Z) = (IY == 0); + $(N) = (IY s< 0); + V_equals_0(); +} + +:^GPaged^"LDY" opr16a_16 is XGATE=0 & GPaged & (op8=0xFD); opr16a_16 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + IY = opr16a_16; + $(Z) = (IY == 0); + $(N) = (IY s< 0); + V_equals_0(); +} + +:^GPaged^"LDY" indexed2_5 is XGATE=0 & GPaged & (op8=0xED); indexed2_5 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + IY = indexed2_5; + $(Z) = (IY == 0); + $(N) = (IY s< 0); + V_equals_0(); +} + +:LEAS indexed0_3 is XGATE=0 & Prefix18=0 & (op8=0x1B); indexed0_3 +{ + SP = indexed0_3; +} + +:LEAX indexed0_3 is XGATE=0 & Prefix18=0 & (op8=0x1A); indexed0_3 +{ + IX = indexed0_3; +} + +:LEAY indexed0_3 is XGATE=0 & Prefix18=0 & (op8=0x19); indexed0_3 +{ + IY = indexed0_3; +} + +## Logical Shift left is same as arithmetic shift left +#:LSL is (op8=0x68 | op8=0x78) +#:LSLA is op8=0x48 +#:LSLB is op8=0x58 +#:LSLD is op8=0x59 + +#:LSLW is op16=0x1878 | op16=0x1868 see ASLW +#:LSLX is op16=0x1848 see ASLX +#:LSLY is op16=0x1858 see ASLY + +:LSR opr16a_8 is XGATE=0 & Prefix18=0 & (op8=0x74); opr16a_8 +{ + tmp:1 = opr16a_8; + $(C) = tmp & 1; + tmp = tmp >> 1; + opr16a_8 = tmp; + $(Z) = (tmp == 0); + $(N) = 0; + V_equals_C(); +} + +:LSR indexed1_5 is XGATE=0 & Prefix18=0 & (op8=0x64); indexed1_5 +{ + tmp:1 = indexed1_5; + $(C) = tmp & 1; + tmp = tmp >> 1; + indexed1_5 = tmp; + $(Z) = (tmp == 0); + $(N) = 0; + V_equals_C(); +} + +:LSRA is XGATE=0 & Prefix18=0 & op8=0x44 +{ + $(C) = A[0,1]; + A = (A >> 1); + $(Z) = (A == 0); + $(N) = 0; + V_equals_C(); +} + +:LSRB is XGATE=0 & Prefix18=0 & op8=0x54 +{ + $(C) = B[0,1]; + B = (B >> 1); + $(Z) = (B == 0); + $(N) = 0; + V_equals_C(); +} + +:LSRD is XGATE=0 & Prefix18=0 & op8=0x49 +{ + $(C) = D[0,1]; + D = (D >> 1); + $(Z) = (D == 0); + $(N) = 0; + V_equals_C(); +} + +@if defined(HCS12X) +:LSRW opr16a_16 is XGATE=0 & Prefix18=1 & (op8=0x74); opr16a_16 +{ + local tmp = opr16a_16; + $(C) = tmp[0,1]; + tmp = tmp >> 1; + opr16a_16 = tmp; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + V_equals_N_xor_C(); +} +@endif + +@if defined(HCS12X) +:LSRW indexed2_5 is XGATE=0 & Prefix18=1 & (op8=0x64); indexed2_5 +{ + local tmp = indexed2_5; + $(C) = tmp[0,1]; + tmp = tmp >> 1; + indexed2_5 = tmp; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + V_equals_N_xor_C(); +} +@endif + +@if defined(HCS12X) +:LSRX is XGATE=0 & Prefix18=1 & op8=0x44 +{ + $(C) = IX[0,1]; + IX = IX >> 1; + $(Z) = (IX == 0); + $(N) = (IX s< 0); + V_equals_N_xor_C(); +} +@endif + +@if defined(HCS12X) +:LSRY is XGATE=0 & Prefix18=1 & op8=0x54 +{ + $(C) = IY[0,1]; + IY = IY >> 1; + $(Z) = (IY == 0); + $(N) = (IY s< 0); + V_equals_N_xor_C(); +} +@endif + +:MAXA indexed1_5 is XGATE=0 & Prefix18=1 & op8=0x18; indexed1_5 +{ + tmp:1 = indexed1_5; + result:2 = zext(A) - zext(tmp); + if (A > tmp) goto ; + A = tmp; + + + $(N) = (result:1 s< 0); + $(Z) = (result:1 == 0); + $(V) = (result s> 0x007F) | (result s< 0x0080); + $(C) = (result > 0x00FF); +} + +:MAXM indexed1_5 is XGATE=0 & Prefix18=1 & op8=0x1C; indexed1_5 +{ + tmp:1 = indexed1_5; + result:4 = zext(A) - zext(tmp); + if (tmp > A) goto ; + indexed1_5 = A; + + + $(N) = (result:2 s< 0); + $(Z) = (result:2 == 0); + $(V) = (result s> 0x007F) | (result s< 0x0080); + $(C) = (result > 0x00FF); +} + +:MEM is XGATE=0 & Prefix18=0 & op8=0x01 +{ + local val:1 = GradeOfMembership(A, IX, IY); + Store(IY, val); + IY = IY + 1; + IX = IX + 4; +} + +:MINA indexed1_5 is XGATE=0 & Prefix18=1 & op8=0x19; indexed1_5 +{ + tmp:1 = indexed1_5; + result:2 = zext(A) - zext(tmp); + if (A < tmp) goto ; + A = tmp; + + + $(N) = (result:1 s< 0); + $(Z) = (result:1 == 0); + $(V) = (result s> 0x007F) | (result s< 0x0080); + $(C) = (result > 0x00FF); +} + +:MINM indexed1_5 is XGATE=0 & Prefix18=1 & op8=0x1D; indexed1_5 +{ + tmp:1 = indexed1_5; + result:4 = zext(A) - zext(tmp); + if (tmp < A) goto ; + indexed1_5 = A; + + + $(N) = (result:2 s< 0); + $(Z) = (result:2 == 0); + $(V) = (result s> 0x007F) | (result s< 0x0080); + $(C) = (result > 0x00FF); +} + +:MOVB iopr8i, opr16a_8 is XGATE=0 & Prefix18=1 & op8=0x0B; iopr8i; opr16a_8 +{ + opr16a_8 = iopr8i; +} + +@if defined(HCS12X) +:MOVB iopr8i, indexed1_5 is XGATE=0 & Prefix18=1 & op8=0x08; indexed1_5; iopr8i +{ + indexed1_5 = iopr8i; +} +@else +:MOVB iopr8i, indexed1_1 is XGATE=0 & Prefix18=1 & op8=0x08; indexed1_1; iopr8i +{ + indexed1_1 = iopr8i; +} +@endif + +:MOVB opr16a_8, op2_opr16a_8 is XGATE=0 & Prefix18=1 & op8=0x0C; opr16a_8; op2_opr16a_8 +{ + build opr16a_8; + local tmp = opr16a_8; + build op2_opr16a_8; + op2_opr16a_8 = tmp; +} + +@if defined(HCS12X) +:MOVB opr16a_8, indexed1_5 is XGATE=0 & Prefix18=1 & op8=0x09; indexed1_5; opr16a_8 +{ + indexed1_5 = opr16a_8; +} +@else +:MOVB opr16a_8, indexed1_1 is XGATE=0 & Prefix18=1 & op8=0x09; indexed1_1; opr16a_8 +{ + indexed1_1 = opr16a_8; +} +@endif + +@if defined(HCS12X) +:MOVB indexed1_5, opr16a_8 is XGATE=0 & Prefix18=1 & op8=0x0D; indexed1_5; opr16a_8 +{ + opr16a_8 = indexed1_5; +} +@else +:MOVB indexed1_1, opr16a_8 is XGATE=0 & Prefix18=1 & op8=0x0D; indexed1_1; opr16a_8 +{ + opr16a_8 = indexed1_1; +} +@endif + +@if defined(HCS12X) +:MOVB indexed1_5, op2_indexed1_5 is XGATE=0 & Prefix18=1 & op8=0x0A; indexed1_5; op2_indexed1_5 +{ + # two operands share a lower level subconstructor + # MUST do the builds and store the value, or the first operands results will be overwritten + build indexed1_5; + local tmp = indexed1_5; + build op2_indexed1_5; + op2_indexed1_5 = tmp; +} +@else +:MOVB indexed1_1, op2_indexed1_1 is XGATE=0 & Prefix18=1 & op8=0x0A; indexed1_1; op2_indexed1_1 +{ + # two operands share a lower level subconstructor + # MUST do the builds and store the value, or the first operands results will be overwritten + build indexed1_1; + local tmp = indexed1_1; + build op2_indexed1_1; + op2_indexed1_1 = tmp; +} +@endif + +:MOVW iopr16i, opr16a_16 is XGATE=0 & Prefix18=1 & op8=0x03; iopr16i; opr16a_16 +{ + opr16a_16 = iopr16i; +} + +@if defined(HCS12X) +:MOVW iopr16i, indexed2_5 is XGATE=0 & Prefix18=1 & op8=0x00; indexed2_5; iopr16i +{ + indexed2_5 = iopr16i; +} +@else +:MOVW iopr16i, indexed2_1 is XGATE=0 & Prefix18=1 & op8=0x00; indexed2_1; iopr16i +{ + indexed2_1 = iopr16i; +} +@endif + +:MOVW opr16a_16, op2_opr16a_16 is XGATE=0 & Prefix18=1 & op8=0x04; opr16a_16; op2_opr16a_16 +{ + # two operands share a lower level subconstructor + # MUST do the builds and store the value, or the first operands results will be overwritten + build opr16a_16; + local tmp = opr16a_16; + build op2_opr16a_16; + op2_opr16a_16 = tmp; +} + +@if defined(HCS12X) +:MOVW opr16a_16, indexed2_5 is XGATE=0 & Prefix18=1 & op8=0x01; indexed2_5; opr16a_16 +{ + indexed2_5 = opr16a_16; +} +@else +:MOVW opr16a_16, indexed2_1 is XGATE=0 & Prefix18=1 & op8=0x01; indexed2_1; opr16a_16 +{ + indexed2_1 = opr16a_16; +} +@endif + +@if defined(HCS12X) +:MOVW indexed2_5, opr16a_16 is XGATE=0 & Prefix18=1 & op8=0x05; indexed2_5; opr16a_16 +{ + opr16a_16 = indexed2_5; +} +@else +:MOVW indexed2_1, opr16a_16 is XGATE=0 & Prefix18=1 & op8=0x05; indexed2_1; opr16a_16 +{ + opr16a_16 = indexed2_1; +} +@endif + +@if defined(HCS12X) +:MOVW indexed2_5, op2_indexed2_5 is XGATE=0 & Prefix18=1 & op8=0x02; indexed2_5; op2_indexed2_5 +{ + # two operands share a lower level subconstructor + # MUST do the builds and store the value, or the first operands results will be overwritten + build indexed2_5; + local tmp = indexed2_5; + build op2_indexed2_5; + op2_indexed2_5 = tmp; +} +@else +:MOVW indexed2_1, op2_indexed2_1 is XGATE=0 & Prefix18=1 & op8=0x02; indexed2_1; op2_indexed2_1 +{ + # two operands share a lower level subconstructor + # MUST do the builds and store the value, or the first operands results will be overwritten + build indexed2_1; + local tmp = indexed2_1; + build op2_indexed2_1; + op2_indexed2_1 = tmp; +} +@endif + + +:MUL is XGATE=0 & Prefix18=0 & op8=0x12 +{ + D = zext(A) * zext(B); + $(C) = B[7,1]; +} + +:NEG opr16a_8 is XGATE=0 & Prefix18=0 & (op8=0x70); opr16a_8 +{ + tmp:1 = opr16a_8; + result:1 = -tmp; + opr16a_8 = result; + $(C) = (result != 0); + $(Z) = (result == 0); + $(N) = (result s< 0); + V_NEG_flag(tmp); +} + +:NEG indexed1_5 is XGATE=0 & Prefix18=0 & (op8=0x60); indexed1_5 +{ + tmp:1 = indexed1_5; + result:1 = -tmp; + indexed1_5 = result; + $(C) = (result != 0); + $(Z) = (result == 0); + $(N) = (result s< 0); + V_NEG_flag(tmp); +} + +:NEGA is XGATE=0 & Prefix18=0 & op8=0x40 +{ + tmp:1 = A; + A = -tmp; + $(C) = (A != 0); + $(Z) = (A == 0); + $(N) = (A s< 0); + V_NEG_flag(tmp); +} + +:NEGB is XGATE=0 & Prefix18=0 & op8=0x50 +{ + tmp:1 = B; + B = -tmp; + $(C) = (B != 0); + $(Z) = (B == 0); + $(N) = (B s< 0); + V_NEG_flag(tmp); +} + +@if defined(HCS12X) +:NEGW opr16a_16 is XGATE=0 & Prefix18=1 & (op8=0x70); opr16a_16 +{ + tmp:2 = opr16a_16; + result:2 = -tmp; + opr16a_16 = result; + $(C) = (result != 0); + $(Z) = (result == 0); + $(N) = (result s< 0); + V_NEG_flag2(tmp); +} + +@if defined(HCS12X) +:NEGW indexed2_5 is XGATE=0 & Prefix18=1 & (op8=0x60); indexed2_5 +{ + tmp:2 = indexed2_5; + result:2 = -tmp; + indexed2_5 = result; + $(C) = (result != 0); + $(Z) = (result == 0); + $(N) = (result s< 0); + V_NEG_flag2(tmp); +} +@endif + +@if defined(HCS12X) +:NEGX is XGATE=0 & Prefix18=1 & op8=0x40 +{ + tmp:2 = IX; + IX = -tmp; + $(C) = (IX != 0); + $(Z) = (IX == 0); + $(N) = (IX s< 0); + V_NEG_flag2(tmp); +} +@endif + +:NEGY is XGATE=0 & Prefix18=1 & op8=0x50 +{ + tmp:2 = IY; + IY = -tmp; + $(C) = (IY != 0); + $(Z) = (IY == 0); + $(N) = (IY s< 0); + V_NEG_flag2(tmp); +} +@endif + +:NOP is XGATE=0 & Prefix18=0 & op8=0xA7 +{ +} + +:ORAA iopr8i is XGATE=0 & Prefix18=0 & (op8=0x8A); iopr8i +{ + A = A | iopr8i; + $(Z) = (A == 0); + $(N) = (A s< 0); + V_equals_0(); +} + +:ORAA opr8a_8 is XGATE=0 & Prefix18=0 & (op8=0x9A); opr8a_8 +{ + A = A | opr8a_8; + $(Z) = (A == 0); + $(N) = (A s< 0); + V_equals_0(); +} + +:ORAA opr16a_8 is XGATE=0 & Prefix18=0 & (op8=0xBA); opr16a_8 +{ + A = A | opr16a_8; + $(Z) = (A == 0); + $(N) = (A s< 0); + V_equals_0(); +} + +:ORAA indexed1_5 is XGATE=0 & Prefix18=0 & (op8=0xAA); indexed1_5 +{ + A = A | indexed1_5; + $(Z) = (A == 0); + $(N) = (A s< 0); + V_equals_0(); +} + +:ORAB iopr8i is XGATE=0 & Prefix18=0 & (op8=0xCA); iopr8i +{ + B = B | iopr8i; + $(Z) = (B == 0); + $(N) = (B s< 0); + V_equals_0(); +} + +:ORAB opr8a_8 is XGATE=0 & Prefix18=0 & (op8=0xDA); opr8a_8 +{ + B = B | opr8a_8; + $(Z) = (B == 0); + $(N) = (B s< 0); + V_equals_0(); +} + +:ORAB opr16a_8 is XGATE=0 & Prefix18=0 & (op8=0xFA); opr16a_8 +{ + B = B | opr16a_8; + $(Z) = (B == 0); + $(N) = (B s< 0); + V_equals_0(); +} + +:ORAB indexed1_5 is XGATE=0 & Prefix18=0 & (op8=0xEA); indexed1_5 +{ + B = B | indexed1_5; + $(Z) = (B == 0); + $(N) = (B s< 0); + V_equals_0(); +} + +:ORCC iopr8i is XGATE=0 & Prefix18=0 & (op8=0x14); iopr8i +{ + CCR = CCR | (iopr8i & 0b10111111); +} + +@if defined(HCS12X) +:ORX iopr16i is XGATE=0 & Prefix18=1 & (op8=0x8A); iopr16i +{ + IX = IX | iopr16i; + V_equals_0(); + $(Z) = (IX == 0); + $(N) = (IX s< 0); +} +@endif + +@if defined(HCS12X) +:ORX opr8a_16 is XGATE=0 & Prefix18=1 & (op8=0x9A); opr8a_16 +{ + IX = IX | opr8a_16; + V_equals_0(); + $(Z) = (IX == 0); + $(N) = (IX s< 0); +} +@endif + +@if defined(HCS12X) +:ORX opr16a_16 is XGATE=0 & Prefix18=1 & (op8=0xBA); opr16a_16 +{ + IX = IX | opr16a_16; + V_equals_0(); + $(Z) = (IX == 0); + $(N) = (IX s< 0); +} +@endif + +@if defined(HCS12X) +:ORX indexed2_5 is XGATE=0 & Prefix18=1 & (op8=0xAA); indexed2_5 +{ + IX = IX | indexed2_5; + V_equals_0(); + $(Z) = (IX == 0); + $(N) = (IX s< 0); +} +@endif + +@if defined(HCS12X) +:ORY iopr16i is XGATE=0 & Prefix18=1 & (op8=0xCA); iopr16i +{ + IY = IY | iopr16i; + V_equals_0(); + $(Z) = (IY == 0); + $(N) = (IY s< 0); +} +@endif + +@if defined(HCS12X) +:ORY opr8a_16 is XGATE=0 & Prefix18=1 & (op8=0xDA); opr8a_16 +{ + IY = IY | opr8a_16; + V_equals_0(); + $(Z) = (IY == 0); + $(N) = (IY s< 0); +} +@endif + +@if defined(HCS12X) +:ORY opr16a_16 is XGATE=0 & Prefix18=1 & (op8=0xFA); opr16a_16 +{ + IY = IY | opr16a_16; + V_equals_0(); + $(Z) = (IY == 0); + $(N) = (IY s< 0); +} +@endif + +@if defined(HCS12X) +:ORY indexed2_5 is XGATE=0 & Prefix18=1 & (op8=0xEA); indexed2_5 +{ + IY = IY | indexed2_5; + V_equals_0(); + $(Z) = (IY == 0); + $(N) = (IY s< 0); +} +@endif + +:PSHA is XGATE=0 & Prefix18=0 & op8=0x36 +{ + Push1( A ); +} + +:PSHB is XGATE=0 & Prefix18=0 & op8=0x37 +{ + Push1( B ); +} + +:PSHC is XGATE=0 & Prefix18=0 & op8=0x39 +{ + Push1( CCR ); +} + +@if defined(HCS12X) +:PSHCW is XGATE=0 & Prefix18=1 & op8=0x39 +{ + Push2( CCRW ); +} +@endif + +:PSHD is XGATE=0 & Prefix18=0 & op8=0x3B +{ + Push2( D ); +} + +:PSHX is XGATE=0 & Prefix18=0 & op8=0x34 +{ + Push2( IX ); +} + +:PSHY is XGATE=0 & Prefix18=0 & op8=0x35 +{ + Push2( IY ); +} + +:PULA is XGATE=0 & Prefix18=0 & op8=0x32 +{ + Pull1( A ); +} + +:PULB is XGATE=0 & Prefix18=0 & op8=0x33 +{ + Pull1( B ); +} + +:PULC is XGATE=0 & Prefix18=0 & op8=0x38 +{ + Pull1( CCR ); +} + +@if defined(HCS12X) +:PULCW is XGATE=0 & Prefix18=1 & op8=0x38 +{ + Pull2( CCRW ); +} +@endif + +:PULD is XGATE=0 & Prefix18=0 & op8=0x3A +{ + Pull2( D ); +} + +:PULX is XGATE=0 & Prefix18=0 & op8=0x30 +{ + Pull2( IX ); +} + +:PULY is XGATE=0 & Prefix18=0 & op8=0x31 +{ + Pull2( IY ); +} + +:REV is XGATE=0 & Prefix18=1 & op8=0x3A +{ + tempIX:2 = MinMaxRuleEvaluation(IX, IY, A, $(V)); + $(V) = MinMaxRuleEvaluationCorrect(IX, IY, A, $(V)); + + IX = tempIX; +} + +:REVW is XGATE=0 & Prefix18=1 & op8=0x3B +{ + tempIX:2 = MinMaxRuleEvaluationWeighted(IX, IY, A, $(V), $(C)); + tempIY:2 = MinMaxRuleEvaluationWeighted(IX, IY, A, $(V), $(C)); + $(V) = MinMaxRuleEvaluationWeightedCorrect(IX, IY, A, $(V), $(C)); + + IX = tempIX; + IY = tempIY; +} + +:ROL opr16a_8 is XGATE=0 & Prefix18=0 & (op8=0x75); opr16a_8 +{ + tmpC:1 = $(C); + op1:1 = opr16a_8; + $(C) = op1 >> 7; + result:1 = op1 << 1; + result = result | tmpC; + opr16a_8 = result; + $(Z) = (result == 0); + $(N) = (result s< 0); + V_equals_N_xor_C(); +} + +:ROL indexed1_5 is XGATE=0 & Prefix18=0 & (op8=0x65); indexed1_5 +{ + tmpC:1 = $(C); + op1:1 = indexed1_5; + $(C) = op1 >> 7; + result:1 = op1 << 1; + result = result | tmpC; + indexed1_5 = result; + $(Z) = (result == 0); + $(N) = (result s< 0); + V_equals_N_xor_C(); +} + +:ROLA is XGATE=0 & Prefix18=0 & op8=0x45 +{ + tmpC:1 = $(C) ; + $(C) = A >> 7; + A = A << 1; + A = A | tmpC; + $(Z) = (A == 0); + $(N) = (A s< 0); + V_equals_N_xor_C(); +} + +:ROLB is XGATE=0 & Prefix18=0 & op8=0x55 +{ + tmpC:1 = $(C) ; + $(C) = B >> 7; + B = B << 1; + B = B | tmpC; + $(Z) = (B == 0); + $(N) = (B s< 0); + V_equals_N_xor_C(); +} + +@if defined(HCS12X) +:ROLW opr16a_16 is XGATE=0 & Prefix18=1 & (op8=0x75); opr16a_16 +{ + local tmp = opr16a_16; + local tmpC = $(C); + $(C) = tmp[15,1]; + tmp = tmp << 1; + tmp = tmp | zext(tmpC); + opr16a_16 = tmp; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + V_equals_N_xor_C(); +} +@endif + +@if defined(HCS12X) +:ROLW indexed2_5 is XGATE=0 & Prefix18=1 & (op8=0x65); indexed2_5 +{ + local tmp = indexed2_5; + local tmpC = $(C); + $(C) = tmp[15,1]; + tmp = tmp << 1; + tmp = tmp | zext(tmpC); + indexed2_5 = tmp; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + V_equals_N_xor_C(); +} +@endif + +@if defined(HCS12X) +:ROLX is XGATE=0 & Prefix18=1 & op8=0x45 +{ + local tmpC = $(C); + $(C) = IX[15,1]; + IX = IX << 1; + IX = IX | zext(tmpC); + $(Z) = (IX == 0); + $(N) = (IX s< 0); + V_equals_N_xor_C(); +} +@endif + +@if defined(HCS12X) +:ROLY is XGATE=0 & Prefix18=1 & op8=0x55 +{ + local tmpC = $(C); + $(C) = IY[15,1]; + IY = IY << 1; + IY = IY | zext(tmpC); + $(Z) = (IY == 0); + $(N) = (IY s< 0); + V_equals_N_xor_C(); +} +@endif + +:ROR opr16a_8 is XGATE=0 & Prefix18=0 & (op8=0x76); opr16a_8 +{ + tmpC:1 = $(C) << 7; + tmp:1 = opr16a_8; + $(C) = tmp & 1; + tmp = tmp >> 1; + tmp = tmp | tmpC; + opr16a_8 = tmp; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + V_equals_N_xor_C(); +} + +:ROR indexed1_5 is XGATE=0 & Prefix18=0 & (op8=0x66); indexed1_5 +{ + tmpC:1 = $(C) << 7; + tmp:1 = indexed1_5; + $(C) = tmp & 1; + tmp = tmp >> 1; + tmp = tmp | tmpC; + indexed1_5 = tmp; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + V_equals_N_xor_C(); +} + +:RORA is XGATE=0 & Prefix18=0 & op8=0x46 +{ + tmpC:1 = $(C) << 7; + $(C) = A & 1; + A = A >> 1; + A = A | tmpC; + $(Z) = (A == 0); + $(N) = (A s< 0); + V_equals_N_xor_C(); +} + +:RORB is XGATE=0 & Prefix18=0 & op8=0x56 +{ + tmpC:1 = $(C) << 7; + $(C) = B & 1; + B = B >> 1; + B = B | tmpC; + $(Z) = (B == 0); + $(N) = (B s< 0); + V_equals_N_xor_C(); +} + +@if defined(HCS12X) +:RORW opr16a_16 is XGATE=0 & Prefix18=1 & (op8=0x76); opr16a_16 +{ + local tmp = opr16a_16; + local tmpC = $(C); + $(C) = tmp[0,1]; + tmp = tmp >> 1; + tmp = tmp | (zext(tmpC) << 15); + opr16a_16 = tmp; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + V_equals_N_xor_C(); +} +@endif + +@if defined(HCS12X) +:RORW indexed2_5 is XGATE=0 & Prefix18=1 & (op8=0x66); indexed2_5 +{ + local tmp = indexed2_5; + local tmpC = $(C); + $(C) = tmp[0,1]; + tmp = tmp >> 1; + tmp = tmp | (zext(tmpC) << 15); + indexed2_5 = tmp; + $(Z) = (tmp == 0); + $(N) = (tmp s< 0); + V_equals_N_xor_C(); +} +@endif + +@if defined(HCS12X) +:RORX is XGATE=0 & Prefix18=1 & op8=0x46 +{ + local tmpC = $(C); + $(C) = IX[0,1]; + IX = IX >> 1; + IX = IX | (zext(tmpC) << 15); + $(Z) = (IX == 0); + $(N) = (IX s< 0); + V_equals_N_xor_C(); +} +@endif + +@if defined(HCS12X) +:RORY is XGATE=0 & Prefix18=1 & op8=0x56 +{ + local tmpC = $(C); + $(C) = IY[0,1]; + IY = IY >> 1; + IY = IY | (zext(tmpC) << 15); + $(Z) = (IY == 0); + $(N) = (IY s< 0); + V_equals_N_xor_C(); +} +@endif + +:RTC is XGATE=0 & Prefix18=0 & op8=0x0A +{ + Pull1( PPAGE ); + + tmp:2 = 0; + Pull2( tmp ); + + return [tmp]; +} + +:RTI is XGATE=0 & Prefix18=0 & op8=0x0B +{ + tmp:2 = 0; + Pull1( CCR ); + Pull1( B ); + Pull1( A ); + Pull2( IX ); + Pull2( IY ); + Pull2( tmp ); # as ordered on page 289, not as documented in RTI description + + return [tmp]; +} + +:RTS is XGATE=0 & Prefix18=0 & op8=0x3D +{ + tmp:2 = 0; + Pull2( tmp ); + + return [tmp]; +} + +:SBA is XGATE=0 & Prefix18=1 & (op8=0x16) +{ + result:1 = A - B; + subtraction_flags1(A, B, result); + A = result; +} + +:SBCA iopr8i is XGATE=0 & Prefix18=0 & (op8=0x82); iopr8i +{ + op1:1 = iopr8i; + + result:1 = A - op1 - $(C); + subtraction_flags1(A, op1, result); + A = result; +} + +:SBCA opr8a_8 is XGATE=0 & Prefix18=0 & (op8=0x92); opr8a_8 +{ + op1:1 = opr8a_8; + + result:1 = A - op1 - $(C); + subtraction_flags1(A, op1, result); + A = result; +} + +:SBCA opr16a_8 is XGATE=0 & Prefix18=0 & (op8=0xB2); opr16a_8 +{ + op1:1 = opr16a_8; + + result:1 = A - op1 - $(C); + subtraction_flags1(A, op1, result); + A = result; +} + +:SBCA indexed1_5 is XGATE=0 & Prefix18=0 & (op8=0xA2); indexed1_5 +{ + op1:1 = indexed1_5; + + result:1 = A - op1 - $(C); + subtraction_flags1(A, op1, result); + A = result; +} + +:SBCB iopr8i is XGATE=0 & Prefix18=0 & (op8=0xC2); iopr8i +{ + op1:1 = iopr8i; + + result:1 = B - op1 - $(C); + subtraction_flags1(B, op1, result); + B = result; +} + +:SBCB opr8a_8 is XGATE=0 & Prefix18=0 & (op8=0xD2); opr8a_8 +{ + op1:1 = opr8a_8; + + result:1 = B - op1 - $(C); + subtraction_flags1(B, op1, result); + B = result; +} + +:SBCB opr16a_8 is XGATE=0 & Prefix18=0 & (op8=0xF2); opr16a_8 +{ + op1:1 = opr16a_8; + + result:1 = B - op1 - $(C); + subtraction_flags1(B, op1, result); + B = result; +} + +:SBCB indexed1_5 is XGATE=0 & Prefix18=0 & (op8=0xE2); indexed1_5 +{ + op1:1 = indexed1_5; + + result:1 = B - op1 - $(C); + subtraction_flags1(B, op1, result); + B = result; +} + +@if defined(HCS12X) +:SBED iopr16i is XGATE=0 & Prefix18=1 & (op8=0x83); iopr16i +{ + op1:2 = iopr16i; + + result:2 = D - op1 - zext($(C)); + subtraction_flags2(D, op1, result); + D = result; +} +@endif + +@if defined(HCS12X) +:SBED opr8a_16 is XGATE=0 & Prefix18=1 & (op8=0x93); opr8a_16 +{ + op1:2 = opr8a_16; + + result:2 = D - op1 - zext($(C)); + subtraction_flags2(D, op1, result); + D = result; +} +@endif + +@if defined(HCS12X) +:SBED opr16a_16 is XGATE=0 & Prefix18=1 & (op8=0xB3); opr16a_16 +{ + op1:2 = opr16a_16; + + result:2 = D - op1 - zext($(C)); + subtraction_flags2(D, op1, result); + D = result; +} +@endif + +@if defined(HCS12X) +:SBED indexed2_5 is XGATE=0 & Prefix18=1 & (op8=0xA3); indexed2_5 +{ + op1:2 = indexed2_5; + + result:2 = D - op1 - zext($(C)); + subtraction_flags2(D, op1, result); + D = result; +} +@endif + +@if defined(HCS12X) +:SBEX iopr16i is XGATE=0 & Prefix18=1 & (op8=0x82); iopr16i +{ + op1:2 = iopr16i; + + result:2 = IX - op1 - zext($(C)); + subtraction_flags2(IX, op1, result); + IX = result; +} +@endif + +@if defined(HCS12X) +:SBEX opr8a_16 is XGATE=0 & Prefix18=1 & (op8=0x92); opr8a_16 +{ + op1:2 = opr8a_16; + + result:2 = IX - op1 - zext($(C)); + subtraction_flags2(IX, op1, result); + IX = result; +} +@endif + +@if defined(HCS12X) +:SBEX opr16a_16 is XGATE=0 & Prefix18=1 & (op8=0xB2); opr16a_16 +{ + op1:2 = opr16a_16; + + result:2 = IX - op1 - zext($(C)); + subtraction_flags2(IX, op1, result); + IX = result; +} +@endif + +@if defined(HCS12X) +:SBEX indexed2_5 is XGATE=0 & Prefix18=1 & (op8=0xA2); indexed2_5 +{ + op1:2 = indexed2_5; + + result:2 = IX - op1 - zext($(C)); + subtraction_flags2(IX, op1, result); + IX = result; +} +@endif + +@if defined(HCS12X) +:SBEY iopr16i is XGATE=0 & Prefix18=1 & (op8=0xC2); iopr16i +{ + op1:2 = iopr16i; + + result:2 = IY - op1 - zext($(C)); + subtraction_flags2(IY, op1, result); + IY = result; +} +@endif + +@if defined(HCS12X) +:SBEY opr8a_16 is XGATE=0 & Prefix18=1 & (op8=0xD2); opr8a_16 +{ + op1:2 = opr8a_16; + + result:2 = IY - op1 - zext($(C)); + subtraction_flags2(IY, op1, result); + IY = result; +} +@endif + +@if defined(HCS12X) +:SBEY opr16a_16 is XGATE=0 & Prefix18=1 & (op8=0xF2); opr16a_16 +{ + op1:2 = opr16a_16; + + result:2 = IY - op1 - zext($(C)); + subtraction_flags2(IY, op1, result); + IY = result; +} +@endif + +@if defined(HCS12X) +:SBEY indexed2_5 is XGATE=0 & Prefix18=1 & (op8=0xE2); indexed2_5 +{ + op1:2 = indexed2_5; + + result:2 = IY - op1 - zext($(C)); + subtraction_flags2(IY, op1, result); + IY = result; +} +@endif + +:SEC is XGATE=0 & Prefix18=0 & op16=0x1401 +{ + $(C) = 1; +} + +:SEI is XGATE=0 & Prefix18=0 & op16=0x1410 +{ + $(I) = 1; +} + +:SEV is XGATE=0 & Prefix18=0 & op16=0x1402 +{ + $(V) = 1; +} + + + +@if defined(HCS12X) +:SEX A, D is XGATE=0 & Prefix18=0 & op8=0xB7; + ( + ( rows3_0=0xC & ( columns7_4=0x0 ) ) + ) & + A & D +{ + D = sext( A ); +} +@endif + +@if defined(HCS12X) +:SEX B, D is XGATE=0 & Prefix18=0 & op8=0xB7; + ( + ( rows3_0=0xC & ( columns7_4=0x1 ) ) + ) & + B & D +{ + D = sext( B ); +} +@endif + +@if defined(HCS12X) +:SEX D, IX is XGATE=0 & Prefix18=0 & op8=0xB7; + ( + ( rows3_0=0xD & ( columns7_4=0x4 ) ) + ) & + D & IX +{ + # generate the sign extension upper word and assign it to destination + local tmp:4 = sext( D ); + IX = tmp(2); +} +@endif + +@if defined(HCS12X) +:SEX D, IY is XGATE=0 & Prefix18=0 & op8=0xB7; + ( + ( rows3_0=0xE & ( columns7_4=0x4 ) ) + ) & + D & IY +{ + # generate the sign extension upper word and assign it to destination + local tmp:4 = sext( D ); + IY = tmp(2); +} +@endif + +:SEX abc5_4, dxys2_0 is XGATE=0 & Prefix18=0 & op8=0xB7; + ( + ( rows3_0=0x3 & ( columns7_4=0x0 | columns7_4=0x1 | columns7_4=0x2 ) ) | + ( rows3_0=0x4 & ( columns7_4=0x0 | columns7_4=0x1 | columns7_4=0x2 ) ) | + ( rows3_0=0x5 & ( columns7_4=0x0 | columns7_4=0x1 | columns7_4=0x2 ) ) | + ( rows3_0=0x6 & ( columns7_4=0x0 | columns7_4=0x1 | columns7_4=0x2 ) ) | + ( rows3_0=0x7 & ( columns7_4=0x0 | columns7_4=0x1 | columns7_4=0x2 ) ) + ) & + abc5_4 & dxys2_0 +{ + dxys2_0 = sext(abc5_4); +} + +:^GPaged^"STAA" opr8a_8 is XGATE=0 & GPaged & (op8=0x5A); opr8a_8 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + opr8a_8 = A; + $(Z) = (A == 0); + $(N) = (A s< 0); + V_equals_0(); +} + +:^GPaged^"STAA" opr16a_8 is XGATE=0 & GPaged & (op8=0x7A); opr16a_8 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + opr16a_8 = A; + $(Z) = (A == 0); + $(N) = (A s< 0); + V_equals_0(); +} + +:^GPaged^"STAA" indexed1_5 is XGATE=0 & GPaged & (op8=0x6A); indexed1_5 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + indexed1_5 = A; + $(Z) = (A == 0); + $(N) = (A s< 0); + V_equals_0(); +} + +:^GPaged^"STAB" opr8a_8 is XGATE=0 & GPaged & (op8=0x5B); opr8a_8 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + opr8a_8 = B; + $(Z) = (B == 0); + $(N) = (B s< 0); + V_equals_0(); +} + +:^GPaged^"STAB" opr16a_8 is XGATE=0 & GPaged & (op8=0x7B); opr16a_8 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + opr16a_8 = B; + $(Z) = (B == 0); + $(N) = (B s< 0); + V_equals_0(); +} + +:^GPaged^"STAB" indexed1_5 is XGATE=0 & GPaged & (op8=0x6B); indexed1_5 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + indexed1_5 = B; + $(Z) = (B == 0); + $(N) = (B s< 0); + V_equals_0(); +} + +:^GPaged^"STD" opr8a_16 is XGATE=0 & GPaged & (op8=0x5C); opr8a_16 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + opr8a_16 = D; + $(Z) = (D == 0); + $(N) = (D s< 0); + V_equals_0(); +} + +:^GPaged^"STD" opr16a_16 is XGATE=0 & GPaged & (op8=0x7C); opr16a_16 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + opr16a_16 = D; + $(Z) = (D == 0); + $(N) = (D s< 0); + V_equals_0(); +} + +:^GPaged^"STD" indexed2_5 is XGATE=0 & GPaged & (op8=0x6C); indexed2_5 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + indexed2_5 = D; + $(Z) = (D == 0); + $(N) = (D s< 0); + V_equals_0(); +} + +:STOP is XGATE=0 & Prefix18=1 & op8=0x3E +{ + if ($(S) == 0) goto ; + tmp:2 = inst_next; + Push2( tmp ); + Push2( IY ); + Push2( IX ); + Push1( A ); + Push1( B ); + Push1( CCR ); + stop(); + +} + +:^GPaged^"STS" opr8a_16 is XGATE=0 & GPaged & (op8=0x5F); opr8a_16 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + opr8a_16 = SP; + $(Z) = (SP == 0); + $(N) = (SP s< 0); + V_equals_0(); +} + +:^GPaged^"STS" opr16a_16 is XGATE=0 & GPaged & (op8=0x7F); opr16a_16 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + opr16a_16 = SP; + $(Z) = (SP == 0); + $(N) = (SP s< 0); + V_equals_0(); +} + +:^GPaged^"STS" indexed2_5 is XGATE=0 & GPaged & (op8=0x6F); indexed2_5 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + indexed2_5 = SP; + $(Z) = (SP == 0); + $(N) = (SP s< 0); + V_equals_0(); +} + +:^GPaged^"STX" opr8a_16 is XGATE=0 & GPaged & (op8=0x5E); opr8a_16 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + opr8a_16 = IX; + $(Z) = (IX == 0); + $(N) = (IX s< 0); + V_equals_0(); +} + +:^GPaged^"STX" opr16a_16 is XGATE=0 & GPaged & (op8=0x7E); opr16a_16 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + opr16a_16 = IX; + $(Z) = (IX == 0); + $(N) = (IX s< 0); + V_equals_0(); +} + +:^GPaged^"STX" indexed2_5 is XGATE=0 & GPaged & (op8=0x6E); indexed2_5 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + indexed2_5 = IX; + $(Z) = (IX == 0); + $(N) = (IX s< 0); + V_equals_0(); +} + +:^GPaged^"STY" opr8a_16 is XGATE=0 & GPaged & (op8=0x5D); opr8a_16 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + opr8a_16 = IY; + $(Z) = (IY == 0); + $(N) = (IY s< 0); + V_equals_0(); +} + +:^GPaged^"STY" opr16a_16 is XGATE=0 & GPaged & (op8=0x7D); opr16a_16 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + opr16a_16 = IY; + $(Z) = (IY == 0); + $(N) = (IY s< 0); + V_equals_0(); +} + +:^GPaged^"STY" indexed2_5 is XGATE=0 & GPaged & (op8=0x6D); indexed2_5 [ UseGPAGE=Prefix18; ] +{ + build GPaged; + indexed2_5 = IY; + $(Z) = (IY == 0); + $(N) = (IY s< 0); + V_equals_0(); +} + +:SUBA iopr8i is XGATE=0 & Prefix18=0 & (op8=0x80); iopr8i +{ + op1:1 = iopr8i; + + result:1 = A - op1; + subtraction_flags1(A, op1, result); + A = result; +} + +:SUBA opr8a_8 is XGATE=0 & Prefix18=0 & (op8=0x90); opr8a_8 +{ + op1:1 = opr8a_8; + + result:1 = A - op1; + subtraction_flags1(A, op1, result); + A = result; +} + +:SUBA opr16a_8 is XGATE=0 & Prefix18=0 & (op8=0xB0); opr16a_8 +{ + op1:1 = opr16a_8; + + result:1 = A - op1; + subtraction_flags1(A, op1, result); + A = result; +} + +:SUBA indexed1_5 is XGATE=0 & Prefix18=0 & (op8=0xA0); indexed1_5 +{ + op1:1 = indexed1_5; + + result:1 = A - op1; + subtraction_flags1(A, op1, result); + A = result; +} + +:SUBB iopr8i is XGATE=0 & Prefix18=0 & (op8=0xC0); iopr8i +{ + op1:1 = iopr8i; + + result:1 = B - op1; + subtraction_flags1(B, op1, result); + B = result; +} + +:SUBB opr8a_8 is XGATE=0 & Prefix18=0 & (op8=0xD0); opr8a_8 +{ + op1:1 = opr8a_8; + + result:1 = B - op1; + subtraction_flags1(B, op1, result); + B = result; +} + +:SUBB opr16a_8 is XGATE=0 & Prefix18=0 & (op8=0xF0); opr16a_8 +{ + op1:1 = opr16a_8; + + result:1 = B - op1; + subtraction_flags1(B, op1, result); + B = result; +} + +:SUBB indexed1_5 is XGATE=0 & Prefix18=0 & (op8=0xE0); indexed1_5 +{ + op1:1 = indexed1_5; + + result:1 = B - op1; + subtraction_flags1(B, op1, result); + B = result; +} + +:SUBD iopr16i is XGATE=0 & Prefix18=0 & (op8=0x83); iopr16i +{ + op1:2 = iopr16i; + + result:2 = D - op1; + subtraction_flags2(D, op1, result); + D = result; +} + +:SUBD opr8a_16 is XGATE=0 & Prefix18=0 & (op8=0x93); opr8a_16 +{ + op1:2 = opr8a_16; + + result:2 = D - op1; + subtraction_flags2(D, op1, result); + D = result; +} + +:SUBD opr16a_16 is XGATE=0 & Prefix18=0 & (op8=0xB3); opr16a_16 +{ + op1:2 = opr16a_16; + + result:2 = D - op1; + subtraction_flags2(D, op1, result); + D = result; +} + +:SUBD indexed2_5 is XGATE=0 & Prefix18=0 & (op8=0xA3); indexed2_5 +{ + op1:2 = indexed2_5; + + result:2 = D - op1; + subtraction_flags2(D, op1, result); + D = result; +} + +@if defined(HCS12X) +:SUBX iopr16i is XGATE=0 & Prefix18=1 & (op8=0x80); iopr16i +{ + op1:2 = iopr16i; + + result:2 = IX - op1; + subtraction_flags2(IX, op1, result); + IX = result; +} +@endif + +@if defined(HCS12X) +:SUBX opr8a_16 is XGATE=0 & Prefix18=1 & (op8=0x90); opr8a_16 +{ + op1:2 = opr8a_16; + + result:2 = IX - op1; + subtraction_flags2(IX, op1, result); + IX = result; +} +@endif + +@if defined(HCS12X) +:SUBX opr16a_16 is XGATE=0 & Prefix18=1 & (op8=0xB0); opr16a_16 +{ + op1:2 = opr16a_16; + + result:2 = IX - op1; + subtraction_flags2(IX, op1, result); + IX = result; +} +@endif + +@if defined(HCS12X) +:SUBX indexed2_5 is XGATE=0 & Prefix18=1 & (op8=0xA0); indexed2_5 +{ + op1:2 = indexed2_5; + + result:2 = IX - op1; + subtraction_flags2(IX, op1, result); + IX = result; +} + +@if defined(HCS12X) +:SUBY iopr16i is XGATE=0 & Prefix18=1 & (op8=0xC0); iopr16i +{ + op1:2 = iopr16i; + + result:2 = IY - op1; + subtraction_flags2(IY, op1, result); + IY = result; +} +@endif + +@if defined(HCS12X) +:SUBY opr8a_16 is XGATE=0 & Prefix18=1 & (op8=0xD0); opr8a_16 +{ + op1:2 = opr8a_16; + + result:2 = IY - op1; + subtraction_flags2(IY, op1, result); + IY = result; +} +@endif + +@if defined(HCS12X) +:SUBY opr16a_16 is XGATE=0 & Prefix18=1 & (op8=0xF0); opr16a_16 +{ + op1:2 = opr16a_16; + + result:2 = IY - op1; + subtraction_flags2(IY, op1, result); + IY = result; +} +@endif + +@if defined(HCS12X) +:SUBY indexed2_5 is XGATE=0 & Prefix18=1 & (op8=0xE0); indexed2_5 +{ + op1:2 = indexed2_5; + + result:2 = IY - op1; + subtraction_flags2(IY, op1, result); + IY = result; +} +@endif + +:SWI is XGATE=0 & Prefix18=0 & op8=0x3F +{ + tmp:2 = inst_next; + Push2( tmp ); + Push2( IY ); + Push2( IX ); + Push1( A ); + Push1( B ); + Push1( CCR ); + + $(I) = 1; + + addr:2 = $(VECTOR_SWI); + call [addr]; +} + +:TAB is XGATE=0 & Prefix18=1 & op8=0x0E +{ + B = A; + $(Z) = (B == 0); + $(N) = (B s< 0); + V_equals_0(); +} + +:TAP is XGATE=0 & Prefix18=0 & op16=0xB702 +{ + setCCR( A ); +} + +:TBA is XGATE=0 & Prefix18=1 & op8=0x0F +{ + A = B; + $(Z) = (A == 0); + $(N) = (A s< 0); + V_equals_0(); +} + +:TBEQ byte9_8, rel9 is XGATE=0 & Prefix18=0 & op8=0x04; op15_13=0x2 & size10_10=0 & byte9_8 & rel9 +{ + if (byte9_8 == 0) goto rel9; +} + +:TBEQ word9_8, rel9 is XGATE=0 & Prefix18=0 & op8=0x04; op15_13=0x2 & size10_10=1 & word9_8 & rel9 +{ + if (word9_8 == 0) goto rel9; +} + +:TBL indexed1_3 is XGATE=0 & Prefix18=1 & op8=0x3D; indexed1_3 +{ + A = TableLookupAndInterpolate(indexed1_3, B); + $(Z) = (A == 0); + $(N) = (A s< 0); +@if defined(HC12) + $(C) = TableLookupAndInterpolateRoundable(indexed1_3, B); +@endif +} + +:TBNE byte9_8, rel9 is XGATE=0 & Prefix18=0 & op8=0x04; op15_13=0x3 & size10_10=0 & byte9_8 & rel9 +{ + if (byte9_8 != 0) goto rel9; +} + +:TBNE word9_8, rel9 is XGATE=0 & Prefix18=0 & op8=0x04; op15_13=0x3 & size10_10=1 & word9_8 & rel9 +{ + if (word9_8 != 0) goto rel9; +} + +:TFR bytes_ABClT3lBXlYlSl_6_4, bytes_ABCl_2_0 is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( +# The case "20" is covered by TPA + ( rows3_0=0x0 & ( columns7_4=0x0 | columns7_4=0x1 | columns7_4=0x3 | columns7_4=0x4 | columns7_4=0x5 | columns7_4=0x6 | columns7_4=0x7 ) ) | + ( rows3_0=0x1 & ( columns7_4=0x0 | columns7_4=0x1 | columns7_4=0x2 | columns7_4=0x3 | columns7_4=0x4 | columns7_4=0x5 | columns7_4=0x6 | columns7_4=0x7 ) ) | + + ( rows3_0=0x8 & ( columns7_4=0x0 | columns7_4=0x1 | columns7_4=0x4 ) ) | + ( rows3_0=0x9 & ( columns7_4=0x0 | columns7_4=0x1 | columns7_4=0x2 | columns7_4=0x3 | columns7_4=0x4 | columns7_4=0x5 | columns7_4=0x6 | columns7_4=0x7 ) ) + ) & + bytes_ABClT3lBXlYlSl_6_4 & bytes_ABCl_2_0 +{ + bytes_ABCl_2_0 = bytes_ABClT3lBXlYlSl_6_4; +} + +:TFR bytes_ABClT3lBXlYlSl_6_4, CCR is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( +# The case "02" is covered by TAP + ( rows3_0=0x2 & ( columns7_4=0x1 | columns7_4=0x2 | columns7_4=0x3 | columns7_4=0x4 | columns7_4=0x5 | columns7_4=0x6 | columns7_4=0x7 ) ) | + + ( rows3_0=0xA & ( columns7_4=0x1 ) ) + ) & + bytes_ABClT3lBXlYlSl_6_4 & CCR +{ + setCCR( bytes_ABClT3lBXlYlSl_6_4 ); +} + +:TFR bytes_ABChT3hBXhYhSh_6_4, A is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( + ( rows3_0=0x8 & ( columns7_4=0x2 | columns7_4=0x3 | columns7_4=0x5 | columns7_4=0x6 | columns7_4=0x7 ) ) + ) & + bytes_ABChT3hBXhYhSh_6_4 & A +{ + A = bytes_ABChT3hBXhYhSh_6_4; +} + +:TFR A, CCRH is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( + ( rows3_0=0xA & ( columns7_4=0x0 ) ) + ) & + A & CCRH +{ + CCRH = A; +} + +:TFR words_CT3DXYS_6_4, CCRW is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( + ( rows3_0=0xA & ( columns7_4=0x2 | columns7_4=0x3 | columns7_4=0x4 | columns7_4=0x5 | columns7_4=0x6 | columns7_4=0x7 ) ) + ) & + words_CT3DXYS_6_4 & CCRW +{ + setCCRW( words_CT3DXYS_6_4 ); +} + +:TFR words_T3DXYS_6_4, words_T2DXYS_2_0 is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( +# The case "57" is covered by TXS +# The case "67" is covered by TYS +# The case "75" is covered by TSX +# The case "76" is covered by TSY + ( rows3_0=0x3 & ( columns7_4=0x3 | columns7_4=0x4 | columns7_4=0x5 | columns7_4=0x6 | columns7_4=0x7 ) ) | + ( rows3_0=0x4 & ( columns7_4=0x3 | columns7_4=0x4 | columns7_4=0x5 | columns7_4=0x6 | columns7_4=0x7 ) ) | + ( rows3_0=0x5 & ( columns7_4=0x3 | columns7_4=0x4 | columns7_4=0x5 | columns7_4=0x6 ) ) | + ( rows3_0=0x6 & ( columns7_4=0x3 | columns7_4=0x4 | columns7_4=0x5 | columns7_4=0x6 ) ) | + ( rows3_0=0x7 & ( columns7_4=0x3 | columns7_4=0x4 | columns7_4=0x7 ) ) | + + ( rows3_0=0xB & ( columns7_4=0x3 | columns7_4=0x5 | columns7_4=0x6 | columns7_4=0x7 ) ) | + ( rows3_0=0xC & ( columns7_4=0x4 | columns7_4=0x5 | columns7_4=0x6 | columns7_4=0x7 ) ) | + ( rows3_0=0xD & ( columns7_4=0x3 | columns7_4=0x5 | columns7_4=0x6 | columns7_4=0x7 ) ) | + ( rows3_0=0xE & ( columns7_4=0x3 | columns7_4=0x5 | columns7_4=0x6 | columns7_4=0x7 ) ) | + ( rows3_0=0xF & ( columns7_4=0x3 | columns7_4=0x4 | columns7_4=0x5 | columns7_4=0x6 | columns7_4=0x7 ) ) + ) & + words_T3DXYS_6_4 & words_T2DXYS_2_0 +{ + words_T2DXYS_2_0 = words_T3DXYS_6_4; +} + +:TFR D, TMP1 is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( + ( rows3_0=0xB & ( columns7_4=0x4 ) ) + ) & + D & TMP1 +{ + TMP1 = D; +} + +:TFR TMP1, D is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( + ( rows3_0=0xC & ( columns7_4=0x3 ) ) + ) & + TMP1 & D +{ + D = TMP1; +} + +:TFR CCRW, words_T2DXYS_2_0 is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( + ( rows3_0=0xB & ( columns7_4=0x2 ) ) | + ( rows3_0=0xC & ( columns7_4=0x2 ) ) | + ( rows3_0=0xD & ( columns7_4=0x2 ) ) | + ( rows3_0=0xE & ( columns7_4=0x2 ) ) | + ( rows3_0=0xF & ( columns7_4=0x2 ) ) + ) & + CCRW & words_T2DXYS_2_0 +{ + words_T2DXYS_2_0 = CCRW; +} + +:TFR A, bytes_T2h_XhYhSh_2_0 is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( + ( rows3_0=0xB & ( columns7_4=0x0 ) ) | + + ( rows3_0=0xD & ( columns7_4=0x0 ) ) | + ( rows3_0=0xE & ( columns7_4=0x0 ) ) | + ( rows3_0=0xF & ( columns7_4=0x0 ) ) + ) & + A & bytes_T2h_XhYhSh_2_0 +{ + bytes_T2h_XhYhSh_2_0 = A; +} + +:TFR A, bytes_T2l_XlYlSl_2_0 is XGATE=0 & Prefix18=0 & ( op8=0xB7 ); + ( + ( rows3_0=0xB & ( columns7_4=0x1 ) ) | + + ( rows3_0=0xD & ( columns7_4=0x1 ) ) | + ( rows3_0=0xE & ( columns7_4=0x1 ) ) | + ( rows3_0=0xF & ( columns7_4=0x1 ) ) + ) & + A & bytes_T2l_XlYlSl_2_0 +{ + bytes_T2l_XlYlSl_2_0 = A; +} + +:TPA is XGATE=0 & Prefix18=0 & op16=0xB720 +{ + A = CCR; +} + +# TODO Not working properly with context regis XGATE=0 & ter for Prefix18 +:TRAP trapnum is XGATE=0 & Prefix18=1 & op8=0x30 & trapnum +{ + tmp:2 = inst_next; + Push2( tmp ); + Push2( IY ); + Push2( IX ); + Push1( A ); + Push1( B ); + Push1( CCR ); + + $(I) = 1; + + addr:2 = $(VECTOR_TRAP); + call [addr]; +} + +:TST opr16a_8 is XGATE=0 & Prefix18=0 & (op8=0xF7); opr16a_8 +{ + op1:1 = opr16a_8; + $(Z) = (op1 == 0); + $(N) = (op1 s< 0); + V_equals_0(); + $(C) = 0; +} + +:TST indexed1_5 is XGATE=0 & Prefix18=0 & (op8=0xE7); indexed1_5 +{ + op1:1 = indexed1_5; + $(Z) = (op1 == 0); + $(N) = (op1 s< 0); + V_equals_0(); + $(C) = 0; +} + +:TSTA is XGATE=0 & Prefix18=0 & op8=0x97 +{ + $(Z) = (A == 0); + $(N) = (A s< 0); + V_equals_0(); +} + +:TSTB is XGATE=0 & Prefix18=0 & op8=0xD7 +{ + $(Z) = (B == 0); + $(N) = (B s< 0); + $(V) = 0; + $(C) = 0; +} + +@if defined(HCS12X) +:TSTW opr16a_16 is XGATE=0 & Prefix18=1 & (op8=0xF7); opr16a_16 +{ + op1:2 = opr16a_16; + $(Z) = (op1 == 0); + $(N) = (op1 s< 0); + V_equals_0(); + $(C) = 0; +} +@endif + +@if defined(HCS12X) +:TSTW indexed2_5 is XGATE=0 & Prefix18=1 & (op8=0xE7); indexed2_5 +{ + op1:2 = indexed2_5; + $(Z) = (op1 == 0); + $(N) = (op1 s< 0); + V_equals_0(); + $(C) = 0; +} +@endif + +:TSTX is XGATE=0 & Prefix18=1 & op8=0x97 +{ + $(Z) = (IX == 0); + $(N) = (IX s< 0); + V_equals_0(); +} + + +:TSTY is XGATE=0 & Prefix18=1 & op8=0xD7 +{ + $(Z) = (IY == 0); + $(N) = (IY s< 0); + V_equals_0(); +} + +:TSX is XGATE=0 & Prefix18=0 & op16=0xB775 +{ + IX = SP; +} + +:TSY is XGATE=0 & Prefix18=0 & op16=0xB776 +{ + IY = SP; +} + +:TXS is XGATE=0 & Prefix18=0 & op16=0xB757 +{ + SP = IX; +} + +:TYS is XGATE=0 & Prefix18=0 & op16=0xB767 +{ + SP = IY; +} + +:WAI is XGATE=0 & Prefix18=0 & op8=0x3E +{ + tmp:2 = inst_next; + Push2( tmp ); + Push2( IY ); + Push2( IX ); + Push1( A ); + Push1( B ); + Push1( CCR ); + + WaitForInterrupt(); +} + +:WAV is XGATE=0 & Prefix18=1 & op8=0x3C +{ + tempIY:2 = WeightedAverageSOPHigh(B, IY, IX); + tempD:2 = WeightedAverageSOPLow (B, IY, IX); + tempIX:2 = WeightedAverageSOW(B, IY, IX); + + B = 0; + + IY = tempIY; + D = tempD; + IX = tempIX; +} + +:WAVR is XGATE=0 & Prefix18=0 & op8=0x3C +{ + WeightedAverageResume(); +} + +:XGDX is XGATE=0 & Prefix18=0 & op16=0xB7C5 +{ + tmp:2 = IX; + IX = D; + D = tmp; +} + +:XGDY is XGATE=0 & Prefix18=0 & op16=0xB7C6 +{ + tmp:2 = IY; + IY = D; + D = tmp; +} diff --git a/Ghidra/Processors/HCS12/data/languages/XGATE.sinc b/Ghidra/Processors/HCS12/data/languages/XGATE.sinc new file mode 100644 index 0000000000..56c78c7d8d --- /dev/null +++ b/Ghidra/Processors/HCS12/data/languages/XGATE.sinc @@ -0,0 +1,993 @@ +# 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=0x100 size=1 [R0.H R0.L R1.H R1.L R2.H R2.L R3.H R3.L R4.H R4.L R5.H R5.L R6.H R6.L R7.H R7.L]; +define register offset=0x110 size=2 [XPC XCCR]; +define register offset=0x120 size=1 [XC XV XZ XN]; + +# 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]; + +attach variables [reg8_lo ] [R0.L R1.L R2.L R3.L R4.L R5.L R6.L R7.L]; +attach variables [reg8_hi ] [R0.H R1.H R2.H R3.H R4.H R5.H R6.H R7.H]; + +################################################################ +# Pseudo Instructions +################################################################ + +define pcodeop findFirstOne; +define pcodeop leftShiftCarry; +define pcodeop rightShiftCarry; +define pcodeop parity; +define pcodeop clearSemaphore; +define pcodeop setSemaphore; +define pcodeop setInterruptFlag; +define pcodeop TerminateThread; + +################################################################ +# Macros Instructions +################################################################ + +macro default_flags(result) +{ + $(XZ) = (result == 0); + $(XN) = (result s< 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; +} + +# +# computes a fake PPAGE page mapping based on the 16 bit input address +# The XGATE memory is mapped to the pages of physical memory +# Warning: This might not be the correct mapping on all XGATE processors +# +# 0000-07ff = 0x00_0000 - 0x00_07ff +# 0800-7fff = 0x78_0800 - XGFLASH_HIGH +# 8000-ffff = 0x0f_0800 - 0x0f_ffff +# +macro computePage(addr) { + local isReg:1 = addr < 0x800; + local isFlash:1 = addr >= 0x800 & addr < 0x7fff; + local isRam:1 = addr >= 0x8000; + physPage = (zext(isReg) * 0x0)+ (zext(isFlash) * (0x78 << 16)) + (zext(isRam) * (0xf<<16)); +} + +################################################################ +# Constructors +################################################################ + +#rel9 defined in HCS_HC12.sinc +# range -256 through +255 +with : XGATE=1 { +rel9: reloc is immrel8 [ reloc = inst_next + (immrel8 * 2); ] { export * reloc; } + +# range -512 through +512 +rel10: reloc is immrel9 [ reloc = 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; } + + +rd_lo: reg8 is reg8 & reg8_lo { export reg8_lo; } +rd_hi: reg8 is reg8 & reg8_hi { export reg8_hi; } + + + +# 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 +{ + rd = rs1 & rs2; + + default_flags(rd); +} + +# Logical AND immediate 8-bit constant (high byte) +:ANDH rd, ximm8 is opcode=0x11 & rd & ximm8 & rd_hi +{ + rd_hi = rd_hi & ximm8; + + default_flags(rd_hi); +} + +# Logical AND immediate 8-bit constant (low byte) +:ANDL rd, ximm8 is opcode=0x10 & rd & ximm8 & rd_lo +{ + rd_lo = rd_lo & ximm8; + + default_flags(rd_lo); +} + +# 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 & rd_hi +{ + local val = rd_hi & ximm8; + + default_flags(val); +} + +# Bit Test immediate 8-bit constant (low byte) +:BITL reg8, ximm8 is opcode=0x12 & reg8 & ximm8 & rd_lo +{ + local val = rd_lo & 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(rd); +} + +:CSEM imm3 is opcode=0x0 & imm3 & xop8=0xf1 +{ + local sem:1 = imm3; + clearSemaphore(sem); +} + + +# 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 = inst_next; + call [dest]; +} + +# Load byte from memory (low byte) +:LDB rd, (rs1, offs5) is opcode=0x8 & rd & rs1 & offs5 +{ + local addr = rs1 + offs5; + computePage(addr); + local dst:3 = segment(PPAGE,addr); + local val:1 = *:1 (dst); + rd = (rd & 0xff00) | zext(val); +} + +:LDB rd, (rs1, rs2) is opcode=0xc & rd & rs1 & rs2 & op2=0x0 +{ + local addr = rs1 + rs2; + computePage(addr); + local dst:3 = segment(PPAGE,addr); + local val:1 = *:1 (dst); + rd = (rd & 0xff00) | zext(val); +} + +:LDB rd, (rs1, rs2+) is opcode=0xc & rd & rs1 & rs2 & op2=0x1 +{ + local addr = rs1 + rs2; + computePage(addr); + local dst:3 = segment(PPAGE,addr); + 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; + local addr = rs1 + rs2; + computePage(addr); + local dst:3 = segment(PPAGE,addr); + 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_hi +{ + rd_hi = ximm8 << 8; +} + + +# Load Immediate 8-bit constant (low byte) +:LDL rd, ximm8 is opcode=0x1e & rd & ximm8 +{ + rd = ximm8; +} + +# Load Word from Memory +:LDW rd, (rs1, offs5) is opcode=0x9 & rd & rs1 & offs5 +{ + local addr = rs1 + offs5; + computePage(addr); + local dst:3 = segment(PPAGE,addr); + local val:2 = *:2 (dst); + rd = val; +} + +:LDW rd, (rs1, rs2) is opcode=0xd & rd & rs1 & rs2 & op2=0x0 +{ + local addr = rs1 + rs2; + computePage(addr); + local dst:3 = segment(PPAGE,addr); + local val:2 = *:2 (dst); + rd = val; +} + +:LDW rd, (rs1, rs2+) is opcode=0xd & rd & rs1 & rs2 & op2=0x1 +{ + local addr = rs1 + rs2; + computePage(addr); + local dst:3 = segment(PPAGE,addr); + 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; + local addr = rs1 + rs2; + computePage(addr); + local dst:3 = segment(PPAGE,addr); + 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 & rd_hi +{ + rd_hi = rd_hi | ximm8; + + default_flags(rd_hi); +} + +# Logical OR Immediate 8-bit Constant (low byte) +:ORL rd, ximm8 is opcode=0x14 & rd & ximm8 & rd_lo +{ + rd_lo = rd_lo | ximm8; + + default_flags(rd_lo); +} + +# 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 { + XPC = TerminateThread(); + return [XPC]; +} + +# 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 +{ + local sem:1 = imm3; + setSemaphore(sem); +} + +:SSEM rd is opcode=0x0 & rd & xop8=0xf3 +{ + setSemaphore(rd); +} + +# Store Byte to Memory (low byte) +:STB rd, (rs1, offs5) is opcode=0xa & rd & rs1 & offs5 +{ + local addr = rs1 + offs5; + computePage(addr); + local dst:3 = segment(PPAGE,addr); + local val:1 = rd:1; + *dst = val; +} + +:STB rd, (rs1, rs2) is opcode=0xe & rd & rs1 & rs2 & op2=0x0 +{ + local addr = rs1 + rs2; + computePage(addr); + local dst:3 = segment(PPAGE,addr); + local val:1 = rd:1; + *dst = val; +} + +:STB rd, (rs1, rs2+) is opcode=0xe & rd & rs1 & rs2 & op2=0x1 +{ + local addr = rs1 + rs2; + computePage(addr); + local dst:3 = segment(PPAGE,addr); + 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; + local addr = rs1 + rs2; + computePage(addr); + local dst:3 = segment(PPAGE,addr); + local val:1 = rd:1; + *dst = val; +} + +# Store Word to Memory +:STW rd, (rs1, offs5) is opcode=0xb & rd & rs1 & offs5 +{ + local addr = rs1 + offs5; + computePage(addr); + local dst:3 = segment(PPAGE,addr); + local val:2 = rd; + *dst = val; +} + +:STW rd, (rs1, rs2) is opcode=0xf & rd & rs1 & rs2 & op2=0x0 +{ + local addr = rs1 + rs2; + computePage(addr); + local dst:3 = segment(PPAGE,addr); + local val:2 = rd; + *dst = val; + rs2 = rs2 + 1; +} + +:STW rd, (rs1, rs2+) is opcode=0xf & rd & rs1 & rs2 & op2=0x1 +{ + local addr = rs1 + rs2; + computePage(addr); + local dst:3 = segment(PPAGE,addr); + local val:2 = rd; + *dst = val; + rs2 = rs2 + 2; +} + +:STW rd, (rs1, -rs2) is opcode=0xf & rd & rs1 & rs2 & op2=0x2 +{ + rs2 = rs2 - 2; + local addr = rs1 + rs2; + computePage(addr); + local dst:3 = segment(PPAGE,addr); + 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 = inst_next + 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 & rd_hi +{ + rd_hi = ~(rd_hi ^ ximm8); + + default_flags(rd_hi); +} + +# Logical Exclusive NOR Immediate 8-bit constant (low byte) +:XNORL rd, ximm8 is opcode=0x16 & rd & ximm8 & rd_lo +{ + rd_lo= ~(rd_lo^ ximm8); + + default_flags(rd_lo); +} + +} \ No newline at end of file diff --git a/Ghidra/Processors/HCS12/data/manuals/HCS12.idx b/Ghidra/Processors/HCS12/data/manuals/HCS12.idx new file mode 100644 index 0000000000..9e07ad6fc7 --- /dev/null +++ b/Ghidra/Processors/HCS12/data/manuals/HCS12.idx @@ -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 diff --git a/Ghidra/Processors/HCS12/src/main/java/ghidra/app/plugin/core/analysis/HCS12ConstantAnalyzer.java b/Ghidra/Processors/HCS12/src/main/java/ghidra/app/plugin/core/analysis/HCS12ConstantAnalyzer.java new file mode 100644 index 0000000000..f3220f56bd --- /dev/null +++ b/Ghidra/Processors/HCS12/src/main/java/ghidra/app/plugin/core/analysis/HCS12ConstantAnalyzer.java @@ -0,0 +1,165 @@ +/* ### + * 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.app.plugin.core.analysis; + +import ghidra.program.model.address.Address; +import ghidra.program.model.address.AddressSetView; +import ghidra.program.model.lang.Processor; +import ghidra.program.model.listing.Instruction; +import ghidra.program.model.listing.Program; +import ghidra.program.model.pcode.PcodeOp; +import ghidra.program.model.symbol.RefType; +import ghidra.program.model.symbol.SourceType; +import ghidra.program.util.ContextEvaluator; +import ghidra.program.util.SymbolicPropogator; +import ghidra.program.util.VarnodeContext; +import ghidra.util.exception.CancelledException; +import ghidra.util.task.TaskMonitor; + +public class HCS12ConstantAnalyzer extends ConstantPropagationAnalyzer { + + private final static String PROCESSOR_NAME = "HCS12"; + + public HCS12ConstantAnalyzer() { + super(PROCESSOR_NAME); + } + + @Override + public boolean canAnalyze(Program program) { + boolean canAnalyze = program.getLanguage().getProcessor() + .equals(Processor.findOrPossiblyCreateProcessor(PROCESSOR_NAME)); + + if (!canAnalyze) { + return false; + } + + return true; + } + + private long hcs12TranslatePagedAddress(long addrWordOffset) { + + long page = (addrWordOffset >> 16) & 0xff; + + long addr = addrWordOffset & 0xffff; + + // Register address + if ( (addr & 0xfC00) == 0x0) { + return addr; + } + + // EPage address + if ((addr & 0xfc00) ==0x800) { + return 0x100000 | ((page << 10) | (addr & 0x3ff)); + } + + // EPage FF fixed address + if ((addr & 0xfc00) ==0xC00) { + return (0x4FF << 10) | (addr & 0x3ff); + } + + // RPage address + if ((addr & 0xf000) ==0x1000) { + return (page << 12) | (addr & 0xfff); + } + + // RPage FE fixed address + if ((addr & 0xf000) ==0x2000) { + return (0xFE << 12) | (addr & 0xfff); + } + + // RPage FF fixed address + if ((addr & 0xf000) ==0x3000) { + return (0xFF << 12) | (addr & 0xfff); + } + + // PPage FD fixed address + if ((addr & 0xc000) ==0x4000) { + return 0x400000 | (0xFD << 14) | (addr & 0x3fff); + } + + // PPage address + if ((addr & 0xc000) ==0x8000) { + return 0x400000 | (page << 14) | (addr & 0x3fff); + } + + // PPage FF fixed address + if ((addr & 0xc000) ==0xC000) { + return 0x400000 | (0xFF << 14) | (addr & 0x3fff); + } + + return addr; + } + + @Override + public AddressSetView flowConstants(final Program program, Address flowStart, AddressSetView flowSet, + final SymbolicPropogator symEval, final TaskMonitor monitor) throws CancelledException { + + // follow all flows building up context + // use context to fill out addresses on certain instructions + ContextEvaluator eval = new ConstantPropagationContextEvaluator(trustWriteMemOption) { + + @Override + public boolean evaluateReference(VarnodeContext context, Instruction instr, int pcodeop, + Address address, int size, RefType refType) { + + if ((refType.isRead() || refType.isWrite()) && + adjustPagedAddress(instr, address, refType)) { + return false; + } + return super.evaluateReference(context, instr, pcodeop, address, size, refType); + } + + @Override + public Address evaluateConstant(VarnodeContext context, Instruction instr, int pcodeop, Address constant, + int size, RefType refType) { + // TODO Auto-generated method stub + return super.evaluateConstant(context, instr, pcodeop, constant, size, refType); + } + + private boolean adjustPagedAddress(Instruction instr, Address address, RefType refType) { + PcodeOp[] pcode = instr.getPcode(); + for (PcodeOp op : pcode) { + int numin = op.getNumInputs(); + if (numin < 1) { + continue; + } + if (op.getOpcode() != PcodeOp.CALLOTHER) { + continue; + } + String opName = instr.getProgram().getLanguage().getUserDefinedOpName( + (int) op.getInput(0).getOffset()); + if (opName != null && opName.equals("segment") && numin > 2) { + // assume this is a poorly created segment op addr + long high = address.getOffset() >> 16; + long low = address.getOffset() & 0xffff; + address = address.getNewAddress((high << 14) | (low & 0x3fff)); + makeReference(instr, address, refType); + return true; + } + } + return false; + } + + // handle the reference on the correct read or write operand + private void makeReference(Instruction instr, Address address, RefType refType) { + int index = (refType.isRead() ? 1 : 0); + instr.addOperandReference(index, address, refType, SourceType.ANALYSIS); + } + }; + + return symEval.flowConstants(flowStart, flowSet, eval, true, monitor); + } +} diff --git a/Ghidra/Processors/HCS12/src/main/java/ghidra/app/plugin/core/analysis/HCS12ConventionAnalyzer.java b/Ghidra/Processors/HCS12/src/main/java/ghidra/app/plugin/core/analysis/HCS12ConventionAnalyzer.java new file mode 100644 index 0000000000..b2c0f2f61a --- /dev/null +++ b/Ghidra/Processors/HCS12/src/main/java/ghidra/app/plugin/core/analysis/HCS12ConventionAnalyzer.java @@ -0,0 +1,133 @@ +/* ### + * 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.app.plugin.core.analysis; + +import java.math.BigInteger; + +import ghidra.app.services.AbstractAnalyzer; +import ghidra.app.services.AnalysisPriority; +import ghidra.app.services.AnalyzerType; +import ghidra.app.util.importer.MessageLog; +import ghidra.program.model.address.AddressSetView; +import ghidra.program.model.lang.Processor; +import ghidra.program.model.lang.Register; +import ghidra.program.model.lang.RegisterValue; +import ghidra.program.model.listing.Function; +import ghidra.program.model.listing.FunctionIterator; +import ghidra.program.model.listing.Instruction; +import ghidra.program.model.listing.InstructionIterator; +import ghidra.program.model.listing.Program; +import ghidra.program.model.symbol.SourceType; +import ghidra.util.Msg; +import ghidra.util.exception.CancelledException; +import ghidra.util.exception.InvalidInputException; +import ghidra.util.task.TaskMonitor; + +public class HCS12ConventionAnalyzer extends AbstractAnalyzer { + + private static final String NAME = "HCS12 Calling Convention"; + private static final String DESCRIPTION = "Analyzes HCS12 programs with paged memory access to identify a calling convention for each function. This analyzer looks at the type of return used for the function to identify the calling convention."; + + Register xgate = null; + + public HCS12ConventionAnalyzer() { + super(NAME, DESCRIPTION, AnalyzerType.FUNCTION_ANALYZER); + setPriority(AnalysisPriority.FUNCTION_ANALYSIS); + setDefaultEnablement(true); + } + + @Override + public boolean canAnalyze(Program program) { + // Only analyze HCS12 Programs + Processor processor = program.getLanguage().getProcessor(); + + boolean canDo = processor.equals(Processor.findOrPossiblyCreateProcessor("HCS12")); + if (canDo) { + xgate = program.getRegister("XGATE"); + } + + return canDo; + } + + void checkReturn(Program program, Instruction instr) { + String mnemonic = instr.getMnemonicString().toLowerCase(); + + if (instr == null || !instr.getFlowType().isTerminal()) { + return; + } + + // if XGATE set on instruction is XGATE + RegisterValue xgateValue = program.getProgramContext().getRegisterValue(xgate, instr.getMinAddress()); + if (xgateValue != null && xgateValue.hasValue() && xgateValue.getUnsignedValue().equals(BigInteger.ONE)) { + setPrototypeModel(program, instr, "__asm_xgate"); + return; + } + + // set the correct convention + if (mnemonic.equals("rtc")) { + setPrototypeModel(program, instr, "__asmA_longcall"); + return; + } + + if (mnemonic.equals("rts")) { + setPrototypeModel(program, instr, "__asmA"); + return; + } + + } + + private void setPrototypeModel(Program program, Instruction instr, String convention) { + if (convention == null) { + return; + } + + Function func = program.getFunctionManager().getFunctionContaining(instr.getMinAddress()); + if (func == null) { + return; + } + + if (func.getSignatureSource() != SourceType.DEFAULT) { + return; + } + + try { + func.setCallingConvention(convention); + } catch (InvalidInputException e) { + Msg.error(this, "Unexpected Exception: " + e.getMessage(), e); + } + } + + @Override + public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log) + throws CancelledException { + + // get all functions within the set + FunctionIterator functions = program.getFunctionManager().getFunctions(set, true); + for (Function function : functions) { + + // for each function body, search instructions + AddressSetView body = function.getBody(); + InstructionIterator instructions = program.getListing().getInstructions(body, true); + for (Instruction instr : instructions) { + if (instr.getFlowType().isTerminal()) { + checkReturn(program, instr); + } + } + } + return true; + } + +} diff --git a/Ghidra/Processors/HCS12/src/main/java/ghidra/app/util/bin/format/elf/extend/HCS12X_ElfExtension.java b/Ghidra/Processors/HCS12/src/main/java/ghidra/app/util/bin/format/elf/extend/HCS12X_ElfExtension.java new file mode 100644 index 0000000000..c87952dcc0 --- /dev/null +++ b/Ghidra/Processors/HCS12/src/main/java/ghidra/app/util/bin/format/elf/extend/HCS12X_ElfExtension.java @@ -0,0 +1,178 @@ +/* ### + * 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.app.util.bin.format.elf.extend; + +import ghidra.app.util.bin.format.elf.ElfConstants; +import ghidra.app.util.bin.format.elf.ElfHeader; +import ghidra.app.util.bin.format.elf.ElfLoadHelper; +import ghidra.app.util.bin.format.elf.ElfProgramHeader; +import ghidra.app.util.bin.format.elf.ElfProgramHeaderType; +import ghidra.app.util.bin.format.elf.ElfSectionHeader; +import ghidra.app.util.bin.format.elf.ElfSectionHeaderType; +import ghidra.app.util.bin.format.elf.ElfSymbol; +import ghidra.program.model.address.Address; +import ghidra.program.model.address.AddressSpace; +import ghidra.program.model.lang.Language; +import ghidra.program.model.listing.Program; + +public class HCS12X_ElfExtension extends ElfExtension { + + // Elf Program Header Extensions + public static final ElfProgramHeaderType PT_HCS12_ARCHEXT = + new ElfProgramHeaderType(0x70000000, "PT_HCS12X_ARCHEXT", "HCS12X extension"); + + // Elf Section Header Extensions + public static final ElfSectionHeaderType SHT_HCS12_ATTRIBUTES = + new ElfSectionHeaderType(0x70000003, "SHT_AHCS12_ATTRIBUTES", "Attribute section"); + + @Override + public boolean canHandle(ElfHeader elf) { + return elf.e_machine() == ElfConstants.EM_68HC12; + } + + @Override + public boolean canHandle(ElfLoadHelper elfLoadHelper) { + Language language = elfLoadHelper.getProgram().getLanguage(); + return canHandle(elfLoadHelper.getElfHeader()) && + "HCS12".equals(language.getProcessor().toString()); + } + + @Override + public String getDataTypeSuffix() { + return "_HCS12"; + } + + @Override + public Address getPreferredSegmentAddress(ElfLoadHelper elfLoadHelper, ElfProgramHeader elfProgramHeader) { + + AddressSpace space = + getPreferredSegmentAddressSpace(elfLoadHelper, elfProgramHeader); + + if (space.equals(AddressSpace.OTHER_SPACE)) { + return space.getAddress(elfProgramHeader.getVirtualAddress()); + } + + Program program = elfLoadHelper.getProgram(); + + long addrWordOffset = elfProgramHeader.getVirtualAddress(); + + if (space == program.getAddressFactory().getDefaultAddressSpace()) { + addrWordOffset += elfLoadHelper.getImageBaseWordAdjustmentOffset(); + } + + addrWordOffset = hcs12TranslatePagedAddress(addrWordOffset); + + return space.getTruncatedAddress(addrWordOffset, true); + } + + @Override + public Address getPreferredSectionAddress(ElfLoadHelper elfLoadHelper, + ElfSectionHeader elfSectionHeader) { + + // don't translate non-allocated sections + if (!elfSectionHeader.isAlloc()) { + return super.getPreferredSectionAddress(elfLoadHelper, elfSectionHeader); + } + + Program program = elfLoadHelper.getProgram(); + + AddressSpace space = getPreferredSectionAddressSpace(elfLoadHelper, elfSectionHeader); + + long addrWordOffset = elfSectionHeader.getAddress(); + + if (space == program.getAddressFactory().getDefaultAddressSpace()) { + addrWordOffset += elfLoadHelper.getImageBaseWordAdjustmentOffset(); + } + + addrWordOffset = hcs12TranslatePagedAddress(addrWordOffset); + + return space.getTruncatedAddress(addrWordOffset, true); + } + + private long hcs12TranslatePagedAddress(long addrWordOffset) { + + long page = (addrWordOffset >> 16) & 0xff; + + long addr = addrWordOffset & 0xffff; + + // Register address + if ( (addr & 0xfC00) == 0x0) { + return addr; + } + + // EPage address + if ((addr & 0xfc00) ==0x800) { + return 0x100000 | ((page << 10) | (addr & 0x3ff)); + } + + // EPage FF fixed address + if ((addr & 0xfc00) ==0xC00) { + return (0x4FF << 10) | (addr & 0x3ff); + } + + // RPage address + if ((addr & 0xf000) ==0x1000) { + return (page << 12) | (addr & 0xfff); + } + + // RPage FE fixed address + if ((addr & 0xf000) ==0x2000) { + return (0xFE << 12) | (addr & 0xfff); + } + + // RPage FF fixed address + if ((addr & 0xf000) ==0x3000) { + return (0xFF << 12) | (addr & 0xfff); + } + + // PPage FD fixed address + if ((addr & 0xc000) ==0x4000) { + return 0x400000 | (0xFD << 14) | (addr & 0x3fff); + } + + // PPage address + if ((addr & 0xc000) ==0x8000) { + return 0x400000 | (page << 14) | (addr & 0x3fff); + } + + // PPage FF fixed address + if ((addr & 0xc000) ==0xC000) { + return 0x400000 | (0xFF << 14) | (addr & 0x3fff); + } + + return addr; + } + + @Override + public Address evaluateElfSymbol(ElfLoadHelper elfLoadHelper, ElfSymbol elfSymbol, + Address address, boolean isExternal) { + + if (isExternal) { + return address; + } + + String symName = elfSymbol.getNameAsString(); + + long laddr = address.getOffset(); + + laddr = hcs12TranslatePagedAddress(laddr); + + Address mappedAddr = address.getNewAddress(laddr); + + return mappedAddr; + } + +}