Added explicit IndexRegister-PSI-Element. Major rework to support new DocumentationProvider on registers.
When asking for documentation on registers, a code flow analysis is done.
This commit is contained in:
parent
55403f89a6
commit
94001c8b87
@ -81,6 +81,7 @@ make it work with JUnit 5. Feel free to use the code (in package ```de.platon42.
|
||||
- New: Added Documentation Provider for symbol definitions (shows assigned declaration).
|
||||
- New: Added Documentation Provider for mnemonics (simple version, generated out of ISA information).
|
||||
- Bugfix: Macro definitions with colons and without space supported (as found in P61a source).
|
||||
- New: When asking for documentation on registers, a code flow analysis is done. Cool stuff!
|
||||
|
||||
### V0.3 (28-Jul-21)
|
||||
|
||||
|
@ -68,6 +68,7 @@ patchPluginXml {
|
||||
<li>New: Added Documentation Provider for symbol definitions (shows assigned declaration).
|
||||
<li>New: Added Documentation Provider for mnemonics (simple version, generated out of ISA information).
|
||||
<li>Bugfix: Macro definitions with colons and without space supported (as found in P61a source).
|
||||
<li>New: When asking for documentation on registers, a code flow analysis is done. Cool stuff!
|
||||
</ul>
|
||||
<h4>V0.3 (28-Jul-21)</h4>
|
||||
<ul>
|
||||
|
@ -211,7 +211,7 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// ROUND_L (expr SEPARATOR)? AddressRegister SEPARATOR DataOrAddressRegister DataWidth? ROUND_R
|
||||
// ROUND_L (expr SEPARATOR)? AddressRegister SEPARATOR IndexRegister ROUND_R
|
||||
public static boolean AddressRegisterIndirectWithIndexNewAddressingMode(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "AddressRegisterIndirectWithIndexNewAddressingMode")) return false;
|
||||
if (!nextTokenIsFast(b, ROUND_L)) return false;
|
||||
@ -221,8 +221,7 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
||||
r = r && AddressRegisterIndirectWithIndexNewAddressingMode_1(b, l + 1);
|
||||
r = r && AddressRegister(b, l + 1);
|
||||
r = r && consumeToken(b, SEPARATOR);
|
||||
r = r && DataOrAddressRegister(b, l + 1);
|
||||
r = r && AddressRegisterIndirectWithIndexNewAddressingMode_5(b, l + 1);
|
||||
r = r && IndexRegister(b, l + 1);
|
||||
r = r && consumeToken(b, ROUND_R);
|
||||
exit_section_(b, l, m, r, false, null);
|
||||
return r;
|
||||
@ -246,15 +245,8 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
||||
return r;
|
||||
}
|
||||
|
||||
// DataWidth?
|
||||
private static boolean AddressRegisterIndirectWithIndexNewAddressingMode_5(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "AddressRegisterIndirectWithIndexNewAddressingMode_5")) return false;
|
||||
DataWidth(b, l + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// expr? ROUND_L AddressRegister SEPARATOR DataOrAddressRegister DataWidth? ROUND_R
|
||||
// expr? ROUND_L AddressRegister SEPARATOR IndexRegister ROUND_R
|
||||
public static boolean AddressRegisterIndirectWithIndexOldAddressingMode(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "AddressRegisterIndirectWithIndexOldAddressingMode")) return false;
|
||||
boolean r;
|
||||
@ -263,8 +255,7 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
||||
r = r && consumeToken(b, ROUND_L);
|
||||
r = r && AddressRegister(b, l + 1);
|
||||
r = r && consumeToken(b, SEPARATOR);
|
||||
r = r && DataOrAddressRegister(b, l + 1);
|
||||
r = r && AddressRegisterIndirectWithIndexOldAddressingMode_5(b, l + 1);
|
||||
r = r && IndexRegister(b, l + 1);
|
||||
r = r && consumeToken(b, ROUND_R);
|
||||
exit_section_(b, l, m, r, false, null);
|
||||
return r;
|
||||
@ -277,13 +268,6 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
||||
return true;
|
||||
}
|
||||
|
||||
// DataWidth?
|
||||
private static boolean AddressRegisterIndirectWithIndexOldAddressingMode_5(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "AddressRegisterIndirectWithIndexOldAddressingMode_5")) return false;
|
||||
DataWidth(b, l + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// OPSIZE_W|OPSIZE_L
|
||||
public static boolean AddressSize(PsiBuilder b, int l) {
|
||||
@ -547,6 +531,25 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
||||
return r;
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// DataOrAddressRegister DataWidth?
|
||||
public static boolean IndexRegister(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "IndexRegister")) return false;
|
||||
boolean r;
|
||||
Marker m = enter_section_(b, l, _NONE_, INDEX_REGISTER, "<index register>");
|
||||
r = DataOrAddressRegister(b, l + 1);
|
||||
r = r && IndexRegister_1(b, l + 1);
|
||||
exit_section_(b, l, m, r, false, null);
|
||||
return r;
|
||||
}
|
||||
|
||||
// DataWidth?
|
||||
private static boolean IndexRegister_1(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "IndexRegister_1")) return false;
|
||||
DataWidth(b, l + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// AsmInstruction | MacroCall
|
||||
static boolean Instruction(PsiBuilder b, int l) {
|
||||
@ -938,7 +941,7 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// ROUND_L (expr SEPARATOR)? PC SEPARATOR DataOrAddressRegister DataWidth? ROUND_R
|
||||
// ROUND_L (expr SEPARATOR)? PC SEPARATOR IndexRegister ROUND_R
|
||||
public static boolean ProgramCounterIndirectWithIndexNewAddressingMode(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "ProgramCounterIndirectWithIndexNewAddressingMode")) return false;
|
||||
if (!nextTokenIsFast(b, ROUND_L)) return false;
|
||||
@ -947,8 +950,7 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
||||
r = consumeTokenFast(b, ROUND_L);
|
||||
r = r && ProgramCounterIndirectWithIndexNewAddressingMode_1(b, l + 1);
|
||||
r = r && consumeTokens(b, 0, PC, SEPARATOR);
|
||||
r = r && DataOrAddressRegister(b, l + 1);
|
||||
r = r && ProgramCounterIndirectWithIndexNewAddressingMode_5(b, l + 1);
|
||||
r = r && IndexRegister(b, l + 1);
|
||||
r = r && consumeToken(b, ROUND_R);
|
||||
exit_section_(b, l, m, r, false, null);
|
||||
return r;
|
||||
@ -972,23 +974,15 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
||||
return r;
|
||||
}
|
||||
|
||||
// DataWidth?
|
||||
private static boolean ProgramCounterIndirectWithIndexNewAddressingMode_5(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "ProgramCounterIndirectWithIndexNewAddressingMode_5")) return false;
|
||||
DataWidth(b, l + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// expr? ROUND_L PC SEPARATOR DataOrAddressRegister DataWidth? ROUND_R
|
||||
// expr? ROUND_L PC SEPARATOR IndexRegister ROUND_R
|
||||
public static boolean ProgramCounterIndirectWithIndexOldAddressingMode(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "ProgramCounterIndirectWithIndexOldAddressingMode")) return false;
|
||||
boolean r;
|
||||
Marker m = enter_section_(b, l, _NONE_, PROGRAM_COUNTER_INDIRECT_WITH_INDEX_OLD_ADDRESSING_MODE, "<AddressingMode>");
|
||||
r = ProgramCounterIndirectWithIndexOldAddressingMode_0(b, l + 1);
|
||||
r = r && consumeTokens(b, 0, ROUND_L, PC, SEPARATOR);
|
||||
r = r && DataOrAddressRegister(b, l + 1);
|
||||
r = r && ProgramCounterIndirectWithIndexOldAddressingMode_5(b, l + 1);
|
||||
r = r && IndexRegister(b, l + 1);
|
||||
r = r && consumeToken(b, ROUND_R);
|
||||
exit_section_(b, l, m, r, false, null);
|
||||
return r;
|
||||
@ -1001,13 +995,6 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
||||
return true;
|
||||
}
|
||||
|
||||
// DataWidth?
|
||||
private static boolean ProgramCounterIndirectWithIndexOldAddressingMode_5(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "ProgramCounterIndirectWithIndexOldAddressingMode_5")) return false;
|
||||
DataWidth(b, l + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// CURRENT_PC_SYMBOL
|
||||
public static boolean ProgramCounterReference(PsiBuilder b, int l) {
|
||||
|
@ -9,13 +9,10 @@ public interface M68kAddressRegisterIndirectWithIndexNewAddressingMode extends M
|
||||
@NotNull
|
||||
M68kAddressRegister getAddressRegister();
|
||||
|
||||
@NotNull
|
||||
M68kIndexRegister getIndexRegister();
|
||||
|
||||
@Nullable
|
||||
M68kExpr getDisplacement();
|
||||
|
||||
@NotNull
|
||||
M68kRegister getIndexRegister();
|
||||
|
||||
@Nullable
|
||||
M68kDataWidth getIndexWidth();
|
||||
|
||||
}
|
||||
|
@ -9,13 +9,10 @@ public interface M68kAddressRegisterIndirectWithIndexOldAddressingMode extends M
|
||||
@NotNull
|
||||
M68kAddressRegister getAddressRegister();
|
||||
|
||||
@NotNull
|
||||
M68kIndexRegister getIndexRegister();
|
||||
|
||||
@Nullable
|
||||
M68kExpr getDisplacement();
|
||||
|
||||
@NotNull
|
||||
M68kRegister getIndexRegister();
|
||||
|
||||
@Nullable
|
||||
M68kDataWidth getIndexWidth();
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,17 @@
|
||||
// This is a generated file. Not intended for manual editing.
|
||||
package de.platon42.intellij.plugins.m68k.psi;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface M68kIndexRegister extends M68kPsiElement {
|
||||
|
||||
@Nullable
|
||||
M68kDataWidth getDataWidth();
|
||||
|
||||
@NotNull
|
||||
M68kRegister getRegister();
|
||||
|
||||
boolean isLongWidth();
|
||||
|
||||
}
|
@ -6,13 +6,10 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface M68kProgramCounterIndirectWithIndexNewAddressingMode extends M68kAddressingMode, M68kWithDisplacement, M68kWithIndexRegister {
|
||||
|
||||
@NotNull
|
||||
M68kIndexRegister getIndexRegister();
|
||||
|
||||
@Nullable
|
||||
M68kExpr getDisplacement();
|
||||
|
||||
@NotNull
|
||||
M68kRegister getIndexRegister();
|
||||
|
||||
@Nullable
|
||||
M68kDataWidth getIndexWidth();
|
||||
|
||||
}
|
||||
|
@ -6,13 +6,10 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface M68kProgramCounterIndirectWithIndexOldAddressingMode extends M68kAddressingMode, M68kWithDisplacement, M68kWithIndexRegister {
|
||||
|
||||
@NotNull
|
||||
M68kIndexRegister getIndexRegister();
|
||||
|
||||
@Nullable
|
||||
M68kExpr getDisplacement();
|
||||
|
||||
@NotNull
|
||||
M68kRegister getIndexRegister();
|
||||
|
||||
@Nullable
|
||||
M68kDataWidth getIndexWidth();
|
||||
|
||||
}
|
||||
|
@ -48,6 +48,7 @@ public interface M68kTypes {
|
||||
IElementType EXPR = new M68kElementType("EXPR");
|
||||
IElementType GLOBAL_LABEL = M68kStubElementTypeFactory.stubFactory("GLOBAL_LABEL");
|
||||
IElementType IMMEDIATE_DATA = new M68kElementType("IMMEDIATE_DATA");
|
||||
IElementType INDEX_REGISTER = new M68kElementType("INDEX_REGISTER");
|
||||
IElementType LITERAL_EXPR = new M68kElementType("LITERAL_EXPR");
|
||||
IElementType LOCAL_LABEL = new M68kElementType("LOCAL_LABEL");
|
||||
IElementType MACRO_CALL = new M68kElementType("MACRO_CALL");
|
||||
@ -212,6 +213,8 @@ public interface M68kTypes {
|
||||
return new M68kGlobalLabelImpl(node);
|
||||
} else if (type == IMMEDIATE_DATA) {
|
||||
return new M68kImmediateDataImpl(node);
|
||||
} else if (type == INDEX_REGISTER) {
|
||||
return new M68kIndexRegisterImpl(node);
|
||||
} else if (type == LITERAL_EXPR) {
|
||||
return new M68kLiteralExprImpl(node);
|
||||
} else if (type == LOCAL_LABEL) {
|
||||
|
@ -99,6 +99,10 @@ public class M68kVisitor extends PsiElementVisitor {
|
||||
visitAddressingMode(o);
|
||||
}
|
||||
|
||||
public void visitIndexRegister(@NotNull M68kIndexRegister o) {
|
||||
visitPsiElement(o);
|
||||
}
|
||||
|
||||
public void visitLocalLabel(@NotNull M68kLocalLabel o) {
|
||||
visitNamedElement(o);
|
||||
}
|
||||
|
@ -31,22 +31,16 @@ public class M68kAddressRegisterIndirectWithIndexNewAddressingModeImpl extends M
|
||||
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kAddressRegister.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public M68kIndexRegister getIndexRegister() {
|
||||
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kIndexRegister.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public M68kExpr getDisplacement() {
|
||||
return PsiTreeUtil.getChildOfType(this, M68kExpr.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public M68kRegister getIndexRegister() {
|
||||
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kRegister.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public M68kDataWidth getIndexWidth() {
|
||||
return PsiTreeUtil.getChildOfType(this, M68kDataWidth.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -31,22 +31,16 @@ public class M68kAddressRegisterIndirectWithIndexOldAddressingModeImpl extends M
|
||||
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kAddressRegister.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public M68kIndexRegister getIndexRegister() {
|
||||
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kIndexRegister.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public M68kExpr getDisplacement() {
|
||||
return PsiTreeUtil.getChildOfType(this, M68kExpr.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public M68kRegister getIndexRegister() {
|
||||
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kRegister.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public M68kDataWidth getIndexWidth() {
|
||||
return PsiTreeUtil.getChildOfType(this, M68kDataWidth.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,45 @@
|
||||
// This is a generated file. Not intended for manual editing.
|
||||
package de.platon42.intellij.plugins.m68k.psi.impl;
|
||||
|
||||
import com.intellij.extapi.psi.ASTWrapperPsiElement;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import de.platon42.intellij.plugins.m68k.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class M68kIndexRegisterImpl extends ASTWrapperPsiElement implements M68kIndexRegister {
|
||||
|
||||
public M68kIndexRegisterImpl(@NotNull ASTNode node) {
|
||||
super(node);
|
||||
}
|
||||
|
||||
public void accept(@NotNull M68kVisitor visitor) {
|
||||
visitor.visitIndexRegister(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(@NotNull PsiElementVisitor visitor) {
|
||||
if (visitor instanceof M68kVisitor) accept((M68kVisitor) visitor);
|
||||
else super.accept(visitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public M68kDataWidth getDataWidth() {
|
||||
return PsiTreeUtil.getChildOfType(this, M68kDataWidth.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public M68kRegister getRegister() {
|
||||
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kRegister.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLongWidth() {
|
||||
return M68kPsiImplUtil.isLongWidth(this);
|
||||
}
|
||||
|
||||
}
|
@ -4,7 +4,10 @@ package de.platon42.intellij.plugins.m68k.psi.impl;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import de.platon42.intellij.plugins.m68k.psi.*;
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kExpr;
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kIndexRegister;
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kProgramCounterIndirectWithIndexNewAddressingMode;
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kVisitor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@ -25,22 +28,16 @@ public class M68kProgramCounterIndirectWithIndexNewAddressingModeImpl extends M6
|
||||
else super.accept(visitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public M68kIndexRegister getIndexRegister() {
|
||||
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kIndexRegister.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public M68kExpr getDisplacement() {
|
||||
return PsiTreeUtil.getChildOfType(this, M68kExpr.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public M68kRegister getIndexRegister() {
|
||||
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kRegister.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public M68kDataWidth getIndexWidth() {
|
||||
return PsiTreeUtil.getChildOfType(this, M68kDataWidth.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,7 +4,10 @@ package de.platon42.intellij.plugins.m68k.psi.impl;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import de.platon42.intellij.plugins.m68k.psi.*;
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kExpr;
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kIndexRegister;
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kProgramCounterIndirectWithIndexOldAddressingMode;
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kVisitor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@ -25,22 +28,16 @@ public class M68kProgramCounterIndirectWithIndexOldAddressingModeImpl extends M6
|
||||
else super.accept(visitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public M68kIndexRegister getIndexRegister() {
|
||||
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kIndexRegister.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public M68kExpr getDisplacement() {
|
||||
return PsiTreeUtil.getChildOfType(this, M68kExpr.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public M68kRegister getIndexRegister() {
|
||||
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kRegister.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public M68kDataWidth getIndexWidth() {
|
||||
return PsiTreeUtil.getChildOfType(this, M68kDataWidth.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ class M68kFileElementType private constructor() : ILightStubFileElementType<PsiF
|
||||
@JvmField
|
||||
val INSTANCE = M68kFileElementType()
|
||||
|
||||
const val STUB_VERSION = 4
|
||||
const val STUB_VERSION = 5
|
||||
const val STUB_EXTERNAL_ID_PREFIX = "MC68000."
|
||||
const val EXTERNAL_ID = STUB_EXTERNAL_ID_PREFIX + "FILE"
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ enum class Register(val regname: String, val num: Int) {
|
||||
A7("a7", 7);
|
||||
|
||||
companion object {
|
||||
private val NAME_TO_REG_MAP = values().associateBy { it.regname }
|
||||
private val NAME_TO_REG_MAP = values().associateBy { it.regname }.plus("sp" to A7)
|
||||
|
||||
fun getRegFromName(regname: String) = NAME_TO_REG_MAP[regname.lowercase()]!!
|
||||
}
|
||||
@ -60,56 +60,58 @@ const val OP_SIZE_BWL = (OP_SIZE_B or OP_SIZE_W or OP_SIZE_L)
|
||||
const val OP_SIZE_WL = (OP_SIZE_W or OP_SIZE_L)
|
||||
const val OP_SIZE_SBW = (OP_SIZE_B or OP_SIZE_S or OP_SIZE_W)
|
||||
|
||||
const val RWM_READ_OPSIZE = 0x10
|
||||
const val RWM_READ_B = 0x11
|
||||
const val RWM_READ_W = 0x12
|
||||
const val RWM_READ_L = 0x13
|
||||
const val RWM_OP_MASK = 0xfff
|
||||
const val RWM_SIZE_MASK = 0x00e
|
||||
|
||||
const val RWM_SET_OPSIZE = 0x20
|
||||
const val RWM_SET_B = 0x21
|
||||
const val RWM_SET_W = 0x22
|
||||
const val RWM_SET_L = 0x23
|
||||
const val RWM_SET_OPSIZE = 0x008
|
||||
const val RWM_SET_B = 0x009
|
||||
const val RWM_SET_W = 0x00b
|
||||
const val RWM_SET_L = 0x00f
|
||||
|
||||
const val RWM_MODIFY_OPSIZE = 0x30
|
||||
const val RWM_MODIFY_B = 0x31
|
||||
const val RWM_MODIFY_W = 0x32
|
||||
const val RWM_MODIFY_L = 0x33
|
||||
const val RWM_READ_OPSIZE = 0x800
|
||||
const val RWM_READ_B = 0x900
|
||||
const val RWM_READ_W = 0xb00
|
||||
const val RWM_READ_L = 0xf00
|
||||
|
||||
const val RWM_MODIFY_OPSIZE = 0x880
|
||||
const val RWM_MODIFY_B = 0x990
|
||||
const val RWM_MODIFY_W = 0xbb0
|
||||
const val RWM_MODIFY_L = 0xff0
|
||||
|
||||
const val RWM_OP_MASK = 0xff
|
||||
const val RWM_OP1_SHIFT = 0
|
||||
const val RWM_OP2_SHIFT = 8
|
||||
const val RWM_OP2_SHIFT = 12
|
||||
|
||||
const val RWM_READ_OP1_OPSIZE = RWM_READ_OPSIZE shl RWM_OP1_SHIFT
|
||||
const val RWM_READ_OP1_B = RWM_READ_B shl RWM_OP1_SHIFT
|
||||
const val RWM_READ_OP1_W = RWM_READ_W shl RWM_OP1_SHIFT
|
||||
const val RWM_READ_OP1_L = RWM_READ_L shl RWM_OP1_SHIFT
|
||||
|
||||
const val RWM_SET_OP1_OPSIZE = RWM_SET_OPSIZE shl RWM_OP1_SHIFT
|
||||
const val RWM_SET_OP1_B = RWM_SET_B shl RWM_OP1_SHIFT
|
||||
const val RWM_SET_OP1_W = RWM_SET_W shl RWM_OP1_SHIFT
|
||||
const val RWM_SET_OP1_L = RWM_SET_L shl RWM_OP1_SHIFT
|
||||
|
||||
const val RWM_MODIFY_OP1_OPSIZE = RWM_MODIFY_OPSIZE shl RWM_OP1_SHIFT
|
||||
const val RWM_MODIFY_OP1_B = RWM_MODIFY_B shl RWM_OP1_SHIFT
|
||||
const val RWM_MODIFY_OP1_W = RWM_MODIFY_W shl RWM_OP1_SHIFT
|
||||
const val RWM_MODIFY_OP1_L = RWM_MODIFY_L shl RWM_OP1_SHIFT
|
||||
|
||||
const val RWM_SET_OP1_OPSIZE = RWM_SET_OPSIZE shl RWM_OP1_SHIFT
|
||||
const val RWM_SET_OP1_B = RWM_SET_B shl RWM_OP1_SHIFT
|
||||
const val RWM_SET_OP1_W = RWM_SET_W shl RWM_OP1_SHIFT
|
||||
const val RWM_SET_OP1_L = RWM_SET_L shl RWM_OP1_SHIFT
|
||||
|
||||
const val RWM_READ_OP2_OPSIZE = RWM_READ_OPSIZE shl RWM_OP2_SHIFT
|
||||
const val RWM_READ_OP2_B = RWM_READ_B shl RWM_OP2_SHIFT
|
||||
const val RWM_READ_OP2_W = RWM_READ_W shl RWM_OP2_SHIFT
|
||||
const val RWM_READ_OP2_L = RWM_READ_L shl RWM_OP2_SHIFT
|
||||
|
||||
const val RWM_SET_OP2_OPSIZE = RWM_SET_OPSIZE shl RWM_OP2_SHIFT
|
||||
const val RWM_SET_OP2_B = RWM_SET_B shl RWM_OP2_SHIFT
|
||||
const val RWM_SET_OP2_W = RWM_SET_W shl RWM_OP2_SHIFT
|
||||
const val RWM_SET_OP2_L = RWM_SET_L shl RWM_OP2_SHIFT
|
||||
|
||||
const val RWM_MODIFY_OP2_OPSIZE = RWM_MODIFY_OPSIZE shl RWM_OP2_SHIFT
|
||||
const val RWM_MODIFY_OP2_B = RWM_MODIFY_B shl RWM_OP2_SHIFT
|
||||
const val RWM_MODIFY_OP2_W = RWM_MODIFY_W shl RWM_OP2_SHIFT
|
||||
const val RWM_MODIFY_OP2_L = RWM_MODIFY_L shl RWM_OP2_SHIFT
|
||||
|
||||
const val RWM_MODIFY_STACK = 0x10000
|
||||
const val RWM_SET_OP2_OPSIZE = RWM_SET_OPSIZE shl RWM_OP2_SHIFT
|
||||
const val RWM_SET_OP2_B = RWM_SET_B shl RWM_OP2_SHIFT
|
||||
const val RWM_SET_OP2_W = RWM_SET_W shl RWM_OP2_SHIFT
|
||||
const val RWM_SET_OP2_L = RWM_SET_L shl RWM_OP2_SHIFT
|
||||
|
||||
const val RWM_MODIFY_STACK = 0x1000000
|
||||
|
||||
data class AllowedAdrMode(
|
||||
val op1: Set<AddressMode>? = null,
|
||||
|
@ -36,17 +36,17 @@ class M68kInstructionDocumentationProvider : AbstractDocumentationProvider() {
|
||||
val defBuilder = createDefinition(isaData)
|
||||
builder.append(defBuilder.wrapWith(DocumentationMarkup.DEFINITION_ELEMENT))
|
||||
|
||||
val bindingRows = HtmlBuilder()
|
||||
val mnemonicInfoRows = HtmlBuilder()
|
||||
val headerCells = listOf(
|
||||
HtmlChunk.text("Mnemonic").wrapWith(DocumentationMarkup.SECTION_HEADER_CELL),
|
||||
HtmlChunk.text("Op1").wrapWith(DocumentationMarkup.SECTION_HEADER_CELL),
|
||||
HtmlChunk.text("Op2").wrapWith(DocumentationMarkup.SECTION_HEADER_CELL)
|
||||
)
|
||||
bindingRows.append(HtmlChunk.tag("tr").children(headerCells))
|
||||
mnemonicInfoRows.append(HtmlChunk.tag("tr").children(headerCells))
|
||||
isaData.modes.forEach { allowedAdrMode ->
|
||||
val mnemonics = findOpSizeDescriptions(allowedAdrMode.size)
|
||||
.map { HtmlChunk.text(isaData.mnemonic + it).wrapWith(HtmlChunk.p()) }
|
||||
bindingRows.append(
|
||||
.map { HtmlChunk.text(isaData.mnemonic + it).wrapWith(HtmlChunk.div()) }
|
||||
mnemonicInfoRows.append(
|
||||
HtmlChunk.tag("tr").children(
|
||||
DocumentationMarkup.SECTION_CONTENT_CELL.children(mnemonics),
|
||||
DocumentationMarkup.SECTION_CONTENT_CELL.child(collectAddressModes(allowedAdrMode.op1)),
|
||||
@ -56,7 +56,7 @@ class M68kInstructionDocumentationProvider : AbstractDocumentationProvider() {
|
||||
}
|
||||
|
||||
val contentBuilder = HtmlBuilder()
|
||||
contentBuilder.append(bindingRows.br().wrapWith(DocumentationMarkup.SECTIONS_TABLE))
|
||||
contentBuilder.append(mnemonicInfoRows.wrapWith(DocumentationMarkup.SECTIONS_TABLE))
|
||||
|
||||
builder.append(contentBuilder.wrapWith(DocumentationMarkup.CONTENT_ELEMENT))
|
||||
}
|
||||
@ -77,7 +77,7 @@ class M68kInstructionDocumentationProvider : AbstractDocumentationProvider() {
|
||||
val defBuilder = HtmlBuilder()
|
||||
defBuilder.append(HtmlChunk.text(isaData.description).bold().wrapWith("pre"))
|
||||
if (isaData.isPrivileged) {
|
||||
defBuilder.append(HtmlChunk.font("red").addText("(privileged)").wrapWith("p"))
|
||||
defBuilder.append(HtmlChunk.font("red").addText("(privileged)").wrapWith(HtmlChunk.p()))
|
||||
}
|
||||
return defBuilder
|
||||
}
|
||||
@ -86,7 +86,7 @@ class M68kInstructionDocumentationProvider : AbstractDocumentationProvider() {
|
||||
if (addressModes == null) return HtmlChunk.text("")
|
||||
val modes = HtmlBuilder()
|
||||
addressModes.sortedBy(AddressMode::ordinal)
|
||||
.forEach { modes.append(HtmlChunk.text(it.syntax).wrapWith(HtmlChunk.p())) }
|
||||
.forEach { modes.append(HtmlChunk.text(it.syntax).wrapWith(HtmlChunk.div())) }
|
||||
return modes.toFragment()
|
||||
}
|
||||
|
||||
|
@ -1,34 +1,209 @@
|
||||
package de.platon42.intellij.plugins.m68k.documentation
|
||||
|
||||
import com.intellij.lang.documentation.AbstractDocumentationProvider
|
||||
import com.intellij.lang.documentation.DocumentationMarkup
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.util.text.HtmlBuilder
|
||||
import com.intellij.openapi.util.text.HtmlChunk
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import de.platon42.intellij.plugins.m68k.asm.RWM_OP1_SHIFT
|
||||
import de.platon42.intellij.plugins.m68k.asm.RWM_OP2_SHIFT
|
||||
import de.platon42.intellij.plugins.m68k.asm.*
|
||||
import de.platon42.intellij.plugins.m68k.asm.Register.Companion.getRegFromName
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kAddressRegister
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kAddressingMode
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kAsmInstruction
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kDataRegister
|
||||
import de.platon42.intellij.plugins.m68k.psi.*
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kAddressModeUtil.getOtherReadWriteModifyRegisters
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kAddressModeUtil.getReadWriteModifyRegisters
|
||||
import de.platon42.intellij.plugins.m68k.utils.M68kIsaUtil.findExactIsaDataAndAllowedAdrModeForInstruction
|
||||
import de.platon42.intellij.plugins.m68k.utils.M68kIsaUtil.getOpSizeOrDefault
|
||||
import de.platon42.intellij.plugins.m68k.utils.M68kIsaUtil.modifyRwmWithOpsize
|
||||
|
||||
class M68kRegisterFlowDocumentationProvider : AbstractDocumentationProvider() {
|
||||
|
||||
override fun generateDoc(element: PsiElement, originalElement: PsiElement?): String? {
|
||||
if (element is M68kDataRegister || element is M68kAddressRegister) {
|
||||
val register = getRegFromName(element.text)
|
||||
val addressingMode = PsiTreeUtil.getParentOfType(element, M68kAddressingMode::class.java) ?: return null
|
||||
val asmInstruction = PsiTreeUtil.getParentOfType(addressingMode, M68kAsmInstruction::class.java) ?: return null
|
||||
|
||||
val (isaData, adrMode) = findExactIsaDataAndAllowedAdrModeForInstruction(asmInstruction) ?: return "unknown instruction"
|
||||
|
||||
val opShift = if (asmInstruction.addressingModeList[0] == addressingMode) RWM_OP1_SHIFT else RWM_OP2_SHIFT
|
||||
val cursorInstRwmRegs = evaluateRegisterUse(asmInstruction, adrMode, register)
|
||||
val opSize = getOpSizeOrDefault(asmInstruction.asmOp.opSize, adrMode)
|
||||
|
||||
return register.regname
|
||||
val rn = register.regname
|
||||
val thisInfo = cursorInstRwmRegs
|
||||
.joinToString(separator = ", ", prefix = "${isaData.mnemonic} instruction ") {
|
||||
rwmToDisplayText(it, rn)
|
||||
}
|
||||
val totalRwm = cursorInstRwmRegs.reduce(Int::or)
|
||||
|
||||
val firstOp = asmInstruction.addressingModeList[0] == addressingMode
|
||||
val cursorRwm = modifyRwmWithOpsize((adrMode.modInfo ushr if (firstOp) RWM_OP1_SHIFT else RWM_OP2_SHIFT) and RWM_OP_MASK, opSize)
|
||||
val analysisBuilder = HtmlBuilder()
|
||||
val missingBits = if (cursorRwm and RWM_SET_L != 0) {
|
||||
if (totalRwm and RWM_SET_L == RWM_SET_L) {
|
||||
analysisBuilder.append(HtmlChunk.text("Register result is fully defined by this instruction."))
|
||||
0
|
||||
} else {
|
||||
(RWM_SET_L and RWM_SIZE_MASK) and totalRwm.inv()
|
||||
}
|
||||
} else {
|
||||
(RWM_SET_L and RWM_SIZE_MASK) and ((cursorRwm and RWM_MODIFY_L) ushr 8)
|
||||
}
|
||||
val backtrace: MutableList<HtmlChunk> = ArrayList()
|
||||
val initialStatement: M68kStatement = asmInstruction.parent as M68kStatement
|
||||
if (missingBits > 0) {
|
||||
val localLabelName = PsiTreeUtil.findChildOfType(initialStatement, M68kLocalLabel::class.java)?.name ?: ""
|
||||
backtrace.add(
|
||||
HtmlChunk.tag("tr")
|
||||
.children(DocumentationMarkup.SECTION_CONTENT_CELL.child(HtmlChunk.text(localLabelName)))
|
||||
.children(highlightRegister(asmInstruction, register).bold().wrapWith(DocumentationMarkup.SECTION_CONTENT_CELL))
|
||||
.children(DocumentationMarkup.SECTION_CONTENT_CELL.child(HtmlChunk.text(" ; <--")))
|
||||
)
|
||||
}
|
||||
|
||||
backtrace.addAll(analyseFlow(register, missingBits, true, initialStatement) { PsiTreeUtil.getPrevSiblingOfType(it, M68kStatement::class.java) })
|
||||
backtrace.reverse()
|
||||
val traceBits = (cursorRwm or (cursorRwm ushr 8)) and RWM_SIZE_MASK
|
||||
backtrace.addAll(analyseFlow(register, traceBits, false, initialStatement) { PsiTreeUtil.getNextSiblingOfType(it, M68kStatement::class.java) })
|
||||
|
||||
val statementRows = HtmlBuilder()
|
||||
backtrace.forEach(statementRows::append)
|
||||
val builder = HtmlBuilder()
|
||||
builder.append(HtmlChunk.text(thisInfo).wrapWith(DocumentationMarkup.DEFINITION_ELEMENT))
|
||||
builder.append(statementRows.wrapWith(DocumentationMarkup.SECTIONS_TABLE.style("padding-left: 8pt; padding-right: 8pt")))
|
||||
builder.append(analysisBuilder.wrapWith(DocumentationMarkup.CONTENT_ELEMENT))
|
||||
return builder.toString()
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun analyseFlow(
|
||||
register: Register,
|
||||
rwmBits: Int,
|
||||
globalLabelBreaksOnInitialStatement: Boolean,
|
||||
startingStatement: M68kStatement,
|
||||
direction: (statement: M68kStatement) -> M68kStatement?
|
||||
): MutableList<HtmlChunk> {
|
||||
var missingBits = rwmBits
|
||||
var currStatement = startingStatement
|
||||
val backtrace: MutableList<HtmlChunk> = ArrayList()
|
||||
val rn = register.regname
|
||||
var addAbrevDots = false
|
||||
while (missingBits > 0) {
|
||||
val globalLabel = PsiTreeUtil.findChildOfType(currStatement, M68kGlobalLabel::class.java)
|
||||
if ((globalLabel != null) && (globalLabelBreaksOnInitialStatement || (currStatement !== startingStatement))) {
|
||||
backtrace.add(
|
||||
HtmlChunk.tag("tr")
|
||||
.children(DocumentationMarkup.SECTION_CONTENT_CELL.child(HtmlChunk.text(globalLabel.name!!).bold()))
|
||||
.children(DocumentationMarkup.SECTION_CONTENT_CELL.child(HtmlChunk.nbsp()))
|
||||
.children(DocumentationMarkup.SECTION_CONTENT_CELL.child(HtmlChunk.nbsp()))
|
||||
)
|
||||
break
|
||||
}
|
||||
currStatement = direction.invoke(currStatement) ?: break
|
||||
val currAsmInstruction = PsiTreeUtil.getChildOfType(currStatement, M68kAsmInstruction::class.java) ?: continue
|
||||
if (checkIfInstructionUsesRegister(currAsmInstruction, register)) {
|
||||
if (addAbrevDots) {
|
||||
backtrace.add(
|
||||
HtmlChunk.tag("tr")
|
||||
.children(DocumentationMarkup.SECTION_CONTENT_CELL.child(HtmlChunk.nbsp()))
|
||||
.children(
|
||||
DocumentationMarkup.SECTION_CONTENT_CELL.child(
|
||||
HtmlChunk.text("[...]").wrapWith(HtmlChunk.div().attr("class", "grayed"))
|
||||
)
|
||||
)
|
||||
.children(DocumentationMarkup.SECTION_CONTENT_CELL.child(HtmlChunk.nbsp()))
|
||||
)
|
||||
}
|
||||
addAbrevDots = false
|
||||
val (_, currAdrMode) = findExactIsaDataAndAllowedAdrModeForInstruction(currAsmInstruction) ?: continue
|
||||
|
||||
val localLabelName = PsiTreeUtil.findChildOfType(currStatement, M68kLocalLabel::class.java)?.name ?: ""
|
||||
val currRwms = evaluateRegisterUse(currAsmInstruction, currAdrMode, register)
|
||||
val currTotalRwm = currRwms.reduce(Int::or)
|
||||
if ((currTotalRwm and RWM_SET_L) > 0) {
|
||||
missingBits = missingBits and currTotalRwm.inv()
|
||||
}
|
||||
val lineInfo = currRwms
|
||||
.map {
|
||||
val text = HtmlChunk.text(rwmToDisplayText(it, rn))
|
||||
if ((missingBits and it) > 0) text.bold() else text.italic()
|
||||
}
|
||||
val lineBuilder = HtmlBuilder()
|
||||
lineBuilder.append(" ; ")
|
||||
lineBuilder.appendWithSeparators(HtmlChunk.text(", "), lineInfo)
|
||||
.wrapWith(HtmlChunk.div())
|
||||
|
||||
backtrace.add(
|
||||
HtmlChunk.tag("tr")
|
||||
.children(DocumentationMarkup.SECTION_CONTENT_CELL.child(HtmlChunk.text(localLabelName)))
|
||||
.children(highlightRegister(currAsmInstruction, register).wrapWith(DocumentationMarkup.SECTION_CONTENT_CELL))
|
||||
.children(lineBuilder.wrapWith(DocumentationMarkup.SECTION_CONTENT_CELL))
|
||||
)
|
||||
} else {
|
||||
addAbrevDots = true
|
||||
}
|
||||
}
|
||||
return backtrace
|
||||
}
|
||||
|
||||
private fun highlightRegister(currAsmInstruction: M68kAsmInstruction, register: Register): HtmlChunk {
|
||||
val builder = HtmlBuilder()
|
||||
val plainText = currAsmInstruction.text
|
||||
var startPos = 0
|
||||
val rn = if (register == Register.A7) listOf(register.regname, "sp") else listOf(register.regname)
|
||||
do {
|
||||
val indexPos = plainText.indexOfAny(rn, startPos, ignoreCase = true)
|
||||
if (indexPos >= 0) {
|
||||
builder.append(HtmlChunk.text(plainText.substring(startPos until indexPos)))
|
||||
startPos = indexPos + register.regname.length
|
||||
builder.append(HtmlChunk.text(plainText.substring(indexPos until startPos)).wrapWith(HtmlChunk.font("red")))
|
||||
} else {
|
||||
builder.append(HtmlChunk.text(plainText.substring(startPos)))
|
||||
}
|
||||
} while (indexPos >= 0)
|
||||
return builder.toFragment().code()
|
||||
}
|
||||
|
||||
private fun rwmToDisplayText(rwm: Int, rn: String) =
|
||||
when (rwm) {
|
||||
RWM_READ_B -> "reads $rn.b"
|
||||
RWM_READ_W -> "reads $rn.w"
|
||||
RWM_READ_L -> "reads $rn.l"
|
||||
RWM_MODIFY_B -> "modifies $rn.b"
|
||||
RWM_MODIFY_W -> "modifies $rn.w"
|
||||
RWM_MODIFY_L -> "modifies $rn.l"
|
||||
RWM_SET_B -> "sets $rn.b"
|
||||
RWM_SET_W -> "sets $rn.w"
|
||||
RWM_SET_L -> "sets $rn.l"
|
||||
else -> "uhm?"
|
||||
}
|
||||
|
||||
private fun evaluateRegisterUse(
|
||||
asmInstruction: M68kAsmInstruction,
|
||||
adrMode: AllowedAdrMode,
|
||||
register: Register
|
||||
): List<Int> {
|
||||
val opSize = getOpSizeOrDefault(asmInstruction.asmOp.opSize, adrMode)
|
||||
|
||||
val rwm1 = modifyRwmWithOpsize((adrMode.modInfo ushr RWM_OP1_SHIFT) and RWM_OP_MASK, opSize)
|
||||
val rwm2 = if (asmInstruction.addressingModeList.size > 1) modifyRwmWithOpsize((adrMode.modInfo ushr RWM_OP2_SHIFT) and RWM_OP_MASK, opSize) else 0
|
||||
return getReadWriteModifyRegisters(asmInstruction.addressingModeList[0], rwm1).asSequence()
|
||||
.plus(getReadWriteModifyRegisters(asmInstruction.addressingModeList.getOrNull(1), rwm2))
|
||||
.plus(getOtherReadWriteModifyRegisters(adrMode.modInfo))
|
||||
.filter { it.first == register }
|
||||
.map { it.second }
|
||||
.toList()
|
||||
}
|
||||
|
||||
private fun checkIfInstructionUsesRegister(instruction: M68kAsmInstruction, register: Register): Boolean {
|
||||
if (instruction.addressingModeList.isEmpty()) {
|
||||
return false
|
||||
}
|
||||
return instruction.addressingModeList.any { aml -> getReadWriteModifyRegisters(aml, 0).any { it.first == register } }
|
||||
}
|
||||
|
||||
override fun getCustomDocumentationElement(editor: Editor, file: PsiFile, contextElement: PsiElement?, targetOffset: Int): PsiElement? {
|
||||
if (contextElement == null) return null
|
||||
if (contextElement is M68kDataRegister || contextElement is M68kAddressRegister) return contextElement
|
||||
|
@ -234,6 +234,14 @@ Register ::= DataRegister | AddressRegister | SpecialRegister
|
||||
|
||||
private DataOrAddressRegister ::= DataRegister | AddressRegister { name = "data or address register"}
|
||||
|
||||
IndexRegister ::= DataOrAddressRegister DataWidth?
|
||||
{
|
||||
name = "index register"
|
||||
methods = [
|
||||
isLongWidth
|
||||
]
|
||||
}
|
||||
|
||||
AddressingMode ::= ImmediateData
|
||||
| AddressRegisterIndirectPreDecAddressingMode
|
||||
| AddressRegisterIndirectPostIncAddressingMode
|
||||
@ -279,7 +287,7 @@ AddressRegisterIndirectWithDisplacementNewAddressingMode ::= ROUND_L expr SEPARA
|
||||
]
|
||||
}
|
||||
|
||||
AddressRegisterIndirectWithIndexOldAddressingMode ::= expr? ROUND_L AddressRegister SEPARATOR DataOrAddressRegister DataWidth? ROUND_R
|
||||
AddressRegisterIndirectWithIndexOldAddressingMode ::= expr? ROUND_L AddressRegister SEPARATOR IndexRegister ROUND_R
|
||||
{
|
||||
implements = [
|
||||
"de.platon42.intellij.plugins.m68k.psi.M68kWithAddressRegisterIndirect"
|
||||
@ -288,12 +296,10 @@ AddressRegisterIndirectWithIndexOldAddressingMode ::= expr? ROUND_L AddressRegis
|
||||
]
|
||||
methods = [
|
||||
displacement = "expr"
|
||||
indexRegister = "Register"
|
||||
indexWidth = "DataWidth"
|
||||
]
|
||||
}
|
||||
|
||||
AddressRegisterIndirectWithIndexNewAddressingMode ::= ROUND_L (expr SEPARATOR)? AddressRegister SEPARATOR DataOrAddressRegister DataWidth? ROUND_R
|
||||
AddressRegisterIndirectWithIndexNewAddressingMode ::= ROUND_L (expr SEPARATOR)? AddressRegister SEPARATOR IndexRegister ROUND_R
|
||||
{
|
||||
implements = [
|
||||
"de.platon42.intellij.plugins.m68k.psi.M68kWithAddressRegisterIndirect"
|
||||
@ -302,8 +308,6 @@ AddressRegisterIndirectWithIndexNewAddressingMode ::= ROUND_L (expr SEPARATOR)?
|
||||
]
|
||||
methods = [
|
||||
displacement = "expr"
|
||||
indexRegister = "Register"
|
||||
indexWidth = "DataWidth"
|
||||
]
|
||||
}
|
||||
|
||||
@ -323,7 +327,7 @@ ProgramCounterIndirectWithDisplacementNewAddressingMode ::= ROUND_L expr SEPARAT
|
||||
]
|
||||
}
|
||||
|
||||
ProgramCounterIndirectWithIndexOldAddressingMode ::= expr? ROUND_L PC SEPARATOR DataOrAddressRegister DataWidth? ROUND_R
|
||||
ProgramCounterIndirectWithIndexOldAddressingMode ::= expr? ROUND_L PC SEPARATOR IndexRegister ROUND_R
|
||||
{
|
||||
implements = [
|
||||
"de.platon42.intellij.plugins.m68k.psi.M68kWithDisplacement"
|
||||
@ -331,12 +335,10 @@ ProgramCounterIndirectWithIndexOldAddressingMode ::= expr? ROUND_L PC SEPARATOR
|
||||
]
|
||||
methods = [
|
||||
displacement = "expr"
|
||||
indexRegister = "Register"
|
||||
indexWidth = "DataWidth"
|
||||
]
|
||||
}
|
||||
|
||||
ProgramCounterIndirectWithIndexNewAddressingMode ::= ROUND_L (expr SEPARATOR)? PC SEPARATOR DataOrAddressRegister DataWidth? ROUND_R
|
||||
ProgramCounterIndirectWithIndexNewAddressingMode ::= ROUND_L (expr SEPARATOR)? PC SEPARATOR IndexRegister ROUND_R
|
||||
{
|
||||
implements = [
|
||||
"de.platon42.intellij.plugins.m68k.psi.M68kWithDisplacement"
|
||||
@ -344,8 +346,6 @@ ProgramCounterIndirectWithIndexNewAddressingMode ::= ROUND_L (expr SEPARATOR)? P
|
||||
]
|
||||
methods = [
|
||||
displacement = "expr"
|
||||
indexRegister = "Register"
|
||||
indexWidth = "DataWidth"
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -27,31 +27,46 @@ object M68kAddressModeUtil {
|
||||
}
|
||||
}
|
||||
|
||||
fun getReadWriteModifyRegisters(addressingMode: M68kAddressingMode?, rwm: Int): Set<Pair<Register, Int>> {
|
||||
if (addressingMode == null) return emptySet()
|
||||
fun getOtherReadWriteModifyRegisters(rwm: Int): List<Pair<Register, Int>> {
|
||||
if (rwm and RWM_MODIFY_STACK > 0) {
|
||||
return listOf(Register.A7 to RWM_MODIFY_L)
|
||||
}
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
fun getReadWriteModifyRegisters(addressingMode: M68kAddressingMode?, rwm: Int): List<Pair<Register, Int>> {
|
||||
if (addressingMode == null) return emptyList()
|
||||
return when (addressingMode) {
|
||||
is M68kImmediateData -> emptySet()
|
||||
is M68kAddressRegisterIndirectPostIncAddressingMode -> setOf(Register.getRegFromName(addressingMode.addressRegister.text) to RWM_MODIFY_OP1_L)
|
||||
is M68kAddressRegisterIndirectPreDecAddressingMode -> setOf(Register.getRegFromName(addressingMode.addressRegister.text) to RWM_MODIFY_OP1_L)
|
||||
is M68kImmediateData,
|
||||
is M68kSpecialRegisterDirectAddressingMode,
|
||||
is M68kProgramCounterIndirectWithDisplacementNewAddressingMode,
|
||||
is M68kProgramCounterIndirectWithDisplacementOldAddressingMode,
|
||||
is M68kAbsoluteAddressAddressingMode -> emptyList()
|
||||
|
||||
is M68kAddressRegisterIndirectPostIncAddressingMode -> listOf(Register.getRegFromName(addressingMode.addressRegister.text) to RWM_MODIFY_L)
|
||||
is M68kAddressRegisterIndirectPreDecAddressingMode -> listOf(Register.getRegFromName(addressingMode.addressRegister.text) to RWM_MODIFY_L)
|
||||
is M68kWithAddressRegisterIndirect -> {
|
||||
if (addressingMode is M68kWithIndexRegister) {
|
||||
setOf(
|
||||
Register.getRegFromName(addressingMode.addressRegister.text) to RWM_READ_OP1_L,
|
||||
Register.getRegFromName(addressingMode.indexRegister.text) to if (addressingMode.hasLongWidth()) RWM_READ_OP1_L else RWM_READ_OP1_W
|
||||
listOf(
|
||||
Register.getRegFromName(addressingMode.addressRegister.text) to RWM_READ_L,
|
||||
Register.getRegFromName(addressingMode.indexRegister.register.text) to if (addressingMode.indexRegister.isLongWidth) RWM_READ_L else RWM_READ_W
|
||||
)
|
||||
} else {
|
||||
setOf(Register.getRegFromName(addressingMode.addressRegister.text) to RWM_READ_OP1_L)
|
||||
listOf(Register.getRegFromName(addressingMode.addressRegister.text) to RWM_READ_L)
|
||||
}
|
||||
}
|
||||
is M68kWithIndexRegister -> setOf(Register.getRegFromName(addressingMode.indexRegister.text) to if (addressingMode.hasLongWidth()) RWM_READ_OP1_L else RWM_READ_OP1_W)
|
||||
is M68kProgramCounterIndirectWithDisplacementNewAddressingMode -> emptySet()
|
||||
is M68kProgramCounterIndirectWithDisplacementOldAddressingMode -> emptySet()
|
||||
is M68kSpecialRegisterDirectAddressingMode -> emptySet()
|
||||
is M68kDataRegisterDirectAddressingMode -> setOf(Register.getRegFromName(addressingMode.dataRegister.text) to rwm)
|
||||
is M68kAddressRegisterDirectAddressingMode -> setOf(Register.getRegFromName(addressingMode.addressRegister.text) to rwm)
|
||||
is M68kRegisterListAddressingMode -> addressingMode.registers.map { it to rwm }.toSet()
|
||||
is M68kAbsoluteAddressAddressingMode -> emptySet()
|
||||
is M68kWithIndexRegister -> listOf(Register.getRegFromName(addressingMode.indexRegister.register.text) to if (addressingMode.indexRegister.isLongWidth) RWM_READ_L else RWM_READ_W)
|
||||
is M68kDataRegisterDirectAddressingMode -> listOf(Register.getRegFromName(addressingMode.dataRegister.text) to rwm)
|
||||
is M68kAddressRegisterDirectAddressingMode -> listOf(Register.getRegFromName(addressingMode.addressRegister.text) to rwm)
|
||||
is M68kRegisterListAddressingMode -> addressingMode.registers.map { it to rwm }
|
||||
else -> throw IllegalArgumentException("Unknown addressing mode $addressingMode")
|
||||
}
|
||||
}
|
||||
|
||||
fun mergeReadWriteModifyRegisters(regset: Set<Pair<Register, Int>>): Set<Pair<Register, Int>> {
|
||||
if (regset.size <= 1) return regset
|
||||
return regset.groupBy({ it.first }) { it.second }
|
||||
.map { it.key to if (it.value.size == 1) it.value.single() else it.value.reduce(Int::or) }
|
||||
.toSet()
|
||||
}
|
||||
}
|
@ -134,4 +134,10 @@ object M68kPsiImplUtil {
|
||||
}
|
||||
return registers
|
||||
}
|
||||
|
||||
// IndexRegister
|
||||
@JvmStatic
|
||||
fun isLongWidth(element: M68kIndexRegister): Boolean {
|
||||
return element.dataWidth?.text.equals(".l", ignoreCase = true)
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
package de.platon42.intellij.plugins.m68k.psi
|
||||
|
||||
interface M68kWithAddressRegisterIndirect {
|
||||
interface M68kWithAddressRegisterIndirect : M68kAddressingMode {
|
||||
|
||||
val addressRegister: M68kAddressRegister
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
package de.platon42.intellij.plugins.m68k.psi
|
||||
|
||||
interface M68kWithDisplacement {
|
||||
interface M68kWithDisplacement : M68kAddressingMode {
|
||||
|
||||
val displacement: M68kExpr?
|
||||
}
|
@ -1,12 +1,6 @@
|
||||
package de.platon42.intellij.plugins.m68k.psi
|
||||
|
||||
interface M68kWithIndexRegister {
|
||||
interface M68kWithIndexRegister : M68kAddressingMode {
|
||||
|
||||
val indexRegister: M68kRegister
|
||||
|
||||
val indexWidth: M68kDataWidth?
|
||||
|
||||
fun hasLongWidth(): Boolean {
|
||||
return indexWidth?.text.equals(".l", ignoreCase = true)
|
||||
}
|
||||
val indexRegister: M68kIndexRegister
|
||||
}
|
@ -34,6 +34,42 @@ object M68kIsaUtil {
|
||||
return matchedIsaData.map { it to M68kIsa.findMatchingAddressMode(it.modes, op1, op2, opSize, specialReg) }
|
||||
}
|
||||
|
||||
fun getOpSizeOrDefault(opSize: Int, adrMode: AllowedAdrMode): Int {
|
||||
if (opSize == OP_UNSIZED && (adrMode.size != OP_UNSIZED)) {
|
||||
return if ((adrMode.size and OP_SIZE_W) == OP_SIZE_W) {
|
||||
OP_SIZE_W
|
||||
} else {
|
||||
adrMode.size
|
||||
}
|
||||
}
|
||||
return opSize
|
||||
}
|
||||
|
||||
fun modifyRwmWithOpsize(rwm: Int, opSize: Int): Int {
|
||||
if (opSize == OP_UNSIZED) return rwm
|
||||
return when (rwm) {
|
||||
RWM_READ_OPSIZE -> when (opSize) {
|
||||
OP_SIZE_B -> RWM_READ_B
|
||||
OP_SIZE_W -> RWM_READ_W
|
||||
OP_SIZE_L -> RWM_READ_L
|
||||
else -> rwm
|
||||
}
|
||||
RWM_MODIFY_OPSIZE -> when (opSize) {
|
||||
OP_SIZE_B -> RWM_MODIFY_B
|
||||
OP_SIZE_W -> RWM_MODIFY_W
|
||||
OP_SIZE_L -> RWM_MODIFY_L
|
||||
else -> rwm
|
||||
}
|
||||
RWM_SET_OPSIZE -> when (opSize) {
|
||||
OP_SIZE_B -> RWM_SET_B
|
||||
OP_SIZE_W -> RWM_SET_W
|
||||
OP_SIZE_L -> RWM_SET_L
|
||||
else -> rwm
|
||||
}
|
||||
else -> rwm
|
||||
}
|
||||
}
|
||||
|
||||
fun findOpSizeDescription(opSize: Int): String {
|
||||
return when (opSize) {
|
||||
OP_UNSIZED -> ""
|
||||
@ -48,17 +84,17 @@ object M68kIsaUtil {
|
||||
}
|
||||
}
|
||||
|
||||
fun findOpSizeDescriptions(opSize: Int): Set<String> {
|
||||
fun findOpSizeDescriptions(opSize: Int): List<String> {
|
||||
return when (opSize) {
|
||||
OP_UNSIZED -> setOf("")
|
||||
OP_SIZE_B -> setOf(".b")
|
||||
OP_SIZE_W -> setOf(".w")
|
||||
OP_SIZE_L -> setOf(".l")
|
||||
OP_SIZE_S -> setOf(".s")
|
||||
OP_SIZE_BWL -> setOf(".b", ".w", ".l")
|
||||
OP_SIZE_WL -> setOf(".w", ".l")
|
||||
OP_SIZE_SBW -> setOf(".s", ".b", ".w")
|
||||
else -> setOf("?")
|
||||
OP_UNSIZED -> listOf("")
|
||||
OP_SIZE_B -> listOf(".b")
|
||||
OP_SIZE_W -> listOf(".w")
|
||||
OP_SIZE_L -> listOf(".l")
|
||||
OP_SIZE_S -> listOf(".s")
|
||||
OP_SIZE_BWL -> listOf(".b", ".w", ".l")
|
||||
OP_SIZE_WL -> listOf(".w", ".l")
|
||||
OP_SIZE_SBW -> listOf(".s", ".b", ".w")
|
||||
else -> listOf("?")
|
||||
}
|
||||
}
|
||||
}
|
@ -17,8 +17,10 @@ internal class M68kInstructionDocumentationProviderTest : AbstractDocumentationP
|
||||
mo<caret>veq.l #40,d0
|
||||
"""
|
||||
)
|
||||
assertThat(generateDocumentation(myFixture)).isEqualTo(
|
||||
"""<div class="definition"><pre><b>Move Quick</b></pre></div><div class="content"><table class="sections"><tr><td class="section" valign="top">Mnemonic</td><td class="section" valign="top">Op1</td><td class="section" valign="top">Op2</td></tr><tr><td valign="top"><p>moveq.l</p></td><td valign="top"><p>#<xxx></p></td><td valign="top"><p>Dn</p></td></tr><br/></table></div>"""
|
||||
assertThat(generateDocumentation(myFixture)).isEqualToIgnoringWhitespace(
|
||||
"""
|
||||
<div class="definition"><pre><b>Move Quick</b></pre></div><div class="content"><table class="sections"><tr><td class="section" valign="top">Mnemonic</td><td class="section" valign="top">Op1</td><td class="section" valign="top">Op2</td></tr><tr><td valign="top"><div>moveq.l</div></td><td valign="top"><div>#<xxx></div></td><td valign="top"><div>Dn</div></td></tr></table></div>
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
@ -29,8 +31,32 @@ internal class M68kInstructionDocumentationProviderTest : AbstractDocumentationP
|
||||
bra.<caret>s label
|
||||
"""
|
||||
)
|
||||
assertThat(generateDocumentation(myFixture)).isEqualTo(
|
||||
"""<div class="definition"><pre><b>Branch</b></pre></div><div class="content"><table class="sections"><tr><td class="section" valign="top">Mnemonic</td><td class="section" valign="top">Op1</td><td class="section" valign="top">Op2</td></tr><tr><td valign="top"><p>bra.s</p><p>bra.b</p><p>bra.w</p></td><td valign="top"><p>(xxx).w|l</p></td><td valign="top"></td></tr><br/></table></div>"""
|
||||
assertThat(generateDocumentation(myFixture)).isEqualToIgnoringWhitespace(
|
||||
"""
|
||||
<div class="definition">
|
||||
<pre><b>Branch</b></pre>
|
||||
</div>
|
||||
<div class="content">
|
||||
<table class="sections">
|
||||
<tr>
|
||||
<td class="section" valign="top">Mnemonic</td>
|
||||
<td class="section" valign="top">Op1</td>
|
||||
<td class="section" valign="top">Op2</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
<div>bra.s</div>
|
||||
<div>bra.b</div>
|
||||
<div>bra.w</div>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<div>(xxx).w|l</div>
|
||||
</td>
|
||||
<td valign="top"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
@ -41,9 +67,7 @@ internal class M68kInstructionDocumentationProviderTest : AbstractDocumentationP
|
||||
<caret>reset
|
||||
"""
|
||||
)
|
||||
assertThat(generateDocumentation(myFixture)).isEqualTo(
|
||||
"""<div class="definition"><pre><b>Reset External Devices</b></pre><p><font color="red">(privileged)</font></p></div><div class="content"><table class="sections"><tr><td class="section" valign="top">Mnemonic</td><td class="section" valign="top">Op1</td><td class="section" valign="top">Op2</td></tr><tr><td valign="top"><p>reset</p></td><td valign="top"></td><td valign="top"></td></tr><br/></table></div>"""
|
||||
)
|
||||
assertThat(generateDocumentation(myFixture)).contains("Reset External Devices", "(privileged)")
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -11,21 +11,93 @@ import org.junit.jupiter.api.extension.ExtendWith
|
||||
internal class M68kRegisterFlowDocumentationProviderTest : AbstractDocumentationProviderTest() {
|
||||
|
||||
@Test
|
||||
internal fun check_documentation_for_a_symbol_definition(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||
internal fun check_documentation_for_a_register_in_code_flow(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||
myFixture.configureByText(
|
||||
"documentme.asm", """
|
||||
label
|
||||
moveq.l #0,d0
|
||||
add.w #1,d0
|
||||
move.l d1,-(sp)
|
||||
move.w d0,d1
|
||||
move.b d2,d0
|
||||
addq.b #1,d0
|
||||
move.w d<caret>0,d1
|
||||
move.l d0,d2
|
||||
move.w d1,d2
|
||||
clr.b d0
|
||||
moveq.l #0,d0
|
||||
move.l (sp)+,d1
|
||||
rts
|
||||
nextlabel
|
||||
"""
|
||||
)
|
||||
assertThat(generateDocumentation(myFixture)).isEqualTo("d0")
|
||||
assertThat(generateDocumentation(myFixture))
|
||||
.isEqualToIgnoringWhitespace(
|
||||
"""
|
||||
<div class="definition">move instruction reads d0.w</div>
|
||||
<table class="sections" style="padding-left: 8pt; padding-right: 8pt">
|
||||
<tr>
|
||||
<td valign="top"></td>
|
||||
<td valign="top"><code>moveq.l #0,<font color="red">d0</font></code></td>
|
||||
<td valign="top"> ; <i>sets d0.l</i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"></td>
|
||||
<td valign="top"><code>add.w #1,<font color="red">d0</font></code></td>
|
||||
<td valign="top"> ; <i>modifies d0.w</i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"> </td>
|
||||
<td valign="top">
|
||||
<div class="grayed">[...]</div>
|
||||
</td>
|
||||
<td valign="top"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"></td>
|
||||
<td valign="top"><code>move.w <font color="red">d0</font>,d1</code></td>
|
||||
<td valign="top"> ; <i>reads d0.w</i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"></td>
|
||||
<td valign="top"><code>move.b d2,<font color="red">d0</font></code></td>
|
||||
<td valign="top"> ; <i>sets d0.b</i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"></td>
|
||||
<td valign="top"><code>addq.b #1,<font color="red">d0</font></code></td>
|
||||
<td valign="top"> ; <i>modifies d0.b</i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"></td>
|
||||
<td valign="top"><b><code>move.w <font color="red">d0</font>,d1</code></b></td>
|
||||
<td valign="top"> ; <--</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"></td>
|
||||
<td valign="top"><code>move.l <font color="red">d0</font>,d2</code></td>
|
||||
<td valign="top"> ; <i>reads d0.l</i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"> </td>
|
||||
<td valign="top">
|
||||
<div class="grayed">[...]</div>
|
||||
</td>
|
||||
<td valign="top"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"></td>
|
||||
<td valign="top"><code>clr.b <font color="red">d0</font></code></td>
|
||||
<td valign="top"> ; <i>sets d0.b</i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"></td>
|
||||
<td valign="top"><code>moveq.l #0,<font color="red">d0</font></code></td>
|
||||
<td valign="top"> ; <i>sets d0.l</i></td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="content"/>
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
}
|
@ -177,9 +177,10 @@ Assembly File: a.asm
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a0')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d0')
|
||||
M68kDataWidthImpl(DATA_WIDTH)
|
||||
PsiElement(M68kTokenType.OPSIZE_L)('.l')
|
||||
M68kIndexRegisterImpl(INDEX_REGISTER)
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d0')
|
||||
M68kDataWidthImpl(DATA_WIDTH)
|
||||
PsiElement(M68kTokenType.OPSIZE_L)('.l')
|
||||
PsiElement(M68kTokenType.ROUND_R)(')')
|
||||
PsiElement(M68kTokenType.EOL)('\n')
|
@ -21,8 +21,9 @@ Assembly File: a.asm
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
PsiElement(M68kTokenType.PC)('pc')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a0')
|
||||
M68kIndexRegisterImpl(INDEX_REGISTER)
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a0')
|
||||
PsiElement(M68kTokenType.ROUND_R)(')')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kProgramCounterIndirectWithIndexNewAddressingModeImpl(PROGRAM_COUNTER_INDIRECT_WITH_INDEX_NEW_ADDRESSING_MODE)
|
||||
@ -43,9 +44,10 @@ Assembly File: a.asm
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
PsiElement(M68kTokenType.PC)('pc')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d5')
|
||||
M68kDataWidthImpl(DATA_WIDTH)
|
||||
PsiElement(M68kTokenType.OPSIZE_L)('.l')
|
||||
M68kIndexRegisterImpl(INDEX_REGISTER)
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d5')
|
||||
M68kDataWidthImpl(DATA_WIDTH)
|
||||
PsiElement(M68kTokenType.OPSIZE_L)('.l')
|
||||
PsiElement(M68kTokenType.ROUND_R)(')')
|
||||
PsiElement(M68kTokenType.EOL)('\n')
|
@ -20,10 +20,11 @@ Assembly File: a.asm
|
||||
PsiElement(M68kTokenType.ROUND_L)('(')
|
||||
PsiElement(M68kTokenType.PC)('pc')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d0')
|
||||
M68kDataWidthImpl(DATA_WIDTH)
|
||||
PsiElement(M68kTokenType.OPSIZE_W)('.w')
|
||||
M68kIndexRegisterImpl(INDEX_REGISTER)
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d0')
|
||||
M68kDataWidthImpl(DATA_WIDTH)
|
||||
PsiElement(M68kTokenType.OPSIZE_W)('.w')
|
||||
PsiElement(M68kTokenType.ROUND_R)(')')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kProgramCounterIndirectWithIndexOldAddressingModeImpl(PROGRAM_COUNTER_INDIRECT_WITH_INDEX_OLD_ADDRESSING_MODE)
|
||||
@ -43,7 +44,8 @@ Assembly File: a.asm
|
||||
PsiElement(M68kTokenType.ROUND_L)('(')
|
||||
PsiElement(M68kTokenType.PC)('pc')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a3')
|
||||
M68kIndexRegisterImpl(INDEX_REGISTER)
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a3')
|
||||
PsiElement(M68kTokenType.ROUND_R)(')')
|
||||
PsiElement(M68kTokenType.EOL)('\n')
|
@ -11,17 +11,19 @@ Assembly File: a.asm
|
||||
PsiElement(M68kTokenType.ROUND_L)('(')
|
||||
PsiElement(M68kTokenType.PC)('pc')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d0')
|
||||
M68kDataWidthImpl(DATA_WIDTH)
|
||||
PsiElement(M68kTokenType.OPSIZE_W)('.w')
|
||||
M68kIndexRegisterImpl(INDEX_REGISTER)
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d0')
|
||||
M68kDataWidthImpl(DATA_WIDTH)
|
||||
PsiElement(M68kTokenType.OPSIZE_W)('.w')
|
||||
PsiElement(M68kTokenType.ROUND_R)(')')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kProgramCounterIndirectWithIndexNewAddressingModeImpl(PROGRAM_COUNTER_INDIRECT_WITH_INDEX_NEW_ADDRESSING_MODE)
|
||||
PsiElement(M68kTokenType.ROUND_L)('(')
|
||||
PsiElement(M68kTokenType.PC)('pc')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a3')
|
||||
M68kIndexRegisterImpl(INDEX_REGISTER)
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a3')
|
||||
PsiElement(M68kTokenType.ROUND_R)(')')
|
||||
PsiElement(M68kTokenType.EOL)('\n')
|
@ -22,8 +22,9 @@ Assembly File: a.asm
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.REG_SP)('sp')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a0')
|
||||
M68kIndexRegisterImpl(INDEX_REGISTER)
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a0')
|
||||
PsiElement(M68kTokenType.ROUND_R)(')')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kAddressRegisterIndirectWithIndexNewAddressingModeImpl(ADDRESS_REGISTER_INDIRECT_WITH_INDEX_NEW_ADDRESSING_MODE)
|
||||
@ -45,9 +46,10 @@ Assembly File: a.asm
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a1')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d5')
|
||||
M68kDataWidthImpl(DATA_WIDTH)
|
||||
PsiElement(M68kTokenType.OPSIZE_L)('.l')
|
||||
M68kIndexRegisterImpl(INDEX_REGISTER)
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d5')
|
||||
M68kDataWidthImpl(DATA_WIDTH)
|
||||
PsiElement(M68kTokenType.OPSIZE_L)('.l')
|
||||
PsiElement(M68kTokenType.ROUND_R)(')')
|
||||
PsiElement(M68kTokenType.EOL)('\n')
|
@ -21,10 +21,11 @@ Assembly File: a.asm
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.REG_SP)('sp')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d0')
|
||||
M68kDataWidthImpl(DATA_WIDTH)
|
||||
PsiElement(M68kTokenType.OPSIZE_W)('.w')
|
||||
M68kIndexRegisterImpl(INDEX_REGISTER)
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d0')
|
||||
M68kDataWidthImpl(DATA_WIDTH)
|
||||
PsiElement(M68kTokenType.OPSIZE_W)('.w')
|
||||
PsiElement(M68kTokenType.ROUND_R)(')')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kAddressRegisterIndirectWithIndexOldAddressingModeImpl(ADDRESS_REGISTER_INDIRECT_WITH_INDEX_OLD_ADDRESSING_MODE)
|
||||
@ -45,7 +46,8 @@ Assembly File: a.asm
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a1')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a3')
|
||||
M68kIndexRegisterImpl(INDEX_REGISTER)
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a3')
|
||||
PsiElement(M68kTokenType.ROUND_R)(')')
|
||||
PsiElement(M68kTokenType.EOL)('\n')
|
@ -12,10 +12,11 @@ Assembly File: a.asm
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.REG_SP)('sp')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d0')
|
||||
M68kDataWidthImpl(DATA_WIDTH)
|
||||
PsiElement(M68kTokenType.OPSIZE_W)('.w')
|
||||
M68kIndexRegisterImpl(INDEX_REGISTER)
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d0')
|
||||
M68kDataWidthImpl(DATA_WIDTH)
|
||||
PsiElement(M68kTokenType.OPSIZE_W)('.w')
|
||||
PsiElement(M68kTokenType.ROUND_R)(')')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kAddressRegisterIndirectWithIndexNewAddressingModeImpl(ADDRESS_REGISTER_INDIRECT_WITH_INDEX_NEW_ADDRESSING_MODE)
|
||||
@ -23,7 +24,8 @@ Assembly File: a.asm
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a1')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a3')
|
||||
M68kIndexRegisterImpl(INDEX_REGISTER)
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a3')
|
||||
PsiElement(M68kTokenType.ROUND_R)(')')
|
||||
PsiElement(M68kTokenType.EOL)('\n')
|
Loading…
Reference in New Issue
Block a user