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:
Chris Hodges 2021-08-02 20:54:30 +02:00
parent 55403f89a6
commit 94001c8b87
35 changed files with 619 additions and 254 deletions

View File

@ -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 symbol definitions (shows assigned declaration).
- New: Added Documentation Provider for mnemonics (simple version, generated out of ISA information). - 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). - 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) ### V0.3 (28-Jul-21)

View File

@ -68,6 +68,7 @@ patchPluginXml {
<li>New: Added Documentation Provider for symbol definitions (shows assigned declaration). <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>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>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> </ul>
<h4>V0.3 (28-Jul-21)</h4> <h4>V0.3 (28-Jul-21)</h4>
<ul> <ul>

View File

@ -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) { public static boolean AddressRegisterIndirectWithIndexNewAddressingMode(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "AddressRegisterIndirectWithIndexNewAddressingMode")) return false; if (!recursion_guard_(b, l, "AddressRegisterIndirectWithIndexNewAddressingMode")) return false;
if (!nextTokenIsFast(b, ROUND_L)) 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 && AddressRegisterIndirectWithIndexNewAddressingMode_1(b, l + 1);
r = r && AddressRegister(b, l + 1); r = r && AddressRegister(b, l + 1);
r = r && consumeToken(b, SEPARATOR); r = r && consumeToken(b, SEPARATOR);
r = r && DataOrAddressRegister(b, l + 1); r = r && IndexRegister(b, l + 1);
r = r && AddressRegisterIndirectWithIndexNewAddressingMode_5(b, l + 1);
r = r && consumeToken(b, ROUND_R); r = r && consumeToken(b, ROUND_R);
exit_section_(b, l, m, r, false, null); exit_section_(b, l, m, r, false, null);
return r; return r;
@ -246,15 +245,8 @@ public class M68kParser implements PsiParser, LightPsiParser {
return r; 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) { public static boolean AddressRegisterIndirectWithIndexOldAddressingMode(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "AddressRegisterIndirectWithIndexOldAddressingMode")) return false; if (!recursion_guard_(b, l, "AddressRegisterIndirectWithIndexOldAddressingMode")) return false;
boolean r; boolean r;
@ -263,8 +255,7 @@ public class M68kParser implements PsiParser, LightPsiParser {
r = r && consumeToken(b, ROUND_L); r = r && consumeToken(b, ROUND_L);
r = r && AddressRegister(b, l + 1); r = r && AddressRegister(b, l + 1);
r = r && consumeToken(b, SEPARATOR); r = r && consumeToken(b, SEPARATOR);
r = r && DataOrAddressRegister(b, l + 1); r = r && IndexRegister(b, l + 1);
r = r && AddressRegisterIndirectWithIndexOldAddressingMode_5(b, l + 1);
r = r && consumeToken(b, ROUND_R); r = r && consumeToken(b, ROUND_R);
exit_section_(b, l, m, r, false, null); exit_section_(b, l, m, r, false, null);
return r; return r;
@ -277,13 +268,6 @@ public class M68kParser implements PsiParser, LightPsiParser {
return true; 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 // OPSIZE_W|OPSIZE_L
public static boolean AddressSize(PsiBuilder b, int l) { public static boolean AddressSize(PsiBuilder b, int l) {
@ -547,6 +531,25 @@ public class M68kParser implements PsiParser, LightPsiParser {
return r; 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 // AsmInstruction | MacroCall
static boolean Instruction(PsiBuilder b, int l) { 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) { public static boolean ProgramCounterIndirectWithIndexNewAddressingMode(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "ProgramCounterIndirectWithIndexNewAddressingMode")) return false; if (!recursion_guard_(b, l, "ProgramCounterIndirectWithIndexNewAddressingMode")) return false;
if (!nextTokenIsFast(b, ROUND_L)) 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 = consumeTokenFast(b, ROUND_L);
r = r && ProgramCounterIndirectWithIndexNewAddressingMode_1(b, l + 1); r = r && ProgramCounterIndirectWithIndexNewAddressingMode_1(b, l + 1);
r = r && consumeTokens(b, 0, PC, SEPARATOR); r = r && consumeTokens(b, 0, PC, SEPARATOR);
r = r && DataOrAddressRegister(b, l + 1); r = r && IndexRegister(b, l + 1);
r = r && ProgramCounterIndirectWithIndexNewAddressingMode_5(b, l + 1);
r = r && consumeToken(b, ROUND_R); r = r && consumeToken(b, ROUND_R);
exit_section_(b, l, m, r, false, null); exit_section_(b, l, m, r, false, null);
return r; return r;
@ -972,23 +974,15 @@ public class M68kParser implements PsiParser, LightPsiParser {
return r; 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) { public static boolean ProgramCounterIndirectWithIndexOldAddressingMode(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "ProgramCounterIndirectWithIndexOldAddressingMode")) return false; if (!recursion_guard_(b, l, "ProgramCounterIndirectWithIndexOldAddressingMode")) return false;
boolean r; boolean r;
Marker m = enter_section_(b, l, _NONE_, PROGRAM_COUNTER_INDIRECT_WITH_INDEX_OLD_ADDRESSING_MODE, "<AddressingMode>"); Marker m = enter_section_(b, l, _NONE_, PROGRAM_COUNTER_INDIRECT_WITH_INDEX_OLD_ADDRESSING_MODE, "<AddressingMode>");
r = ProgramCounterIndirectWithIndexOldAddressingMode_0(b, l + 1); r = ProgramCounterIndirectWithIndexOldAddressingMode_0(b, l + 1);
r = r && consumeTokens(b, 0, ROUND_L, PC, SEPARATOR); r = r && consumeTokens(b, 0, ROUND_L, PC, SEPARATOR);
r = r && DataOrAddressRegister(b, l + 1); r = r && IndexRegister(b, l + 1);
r = r && ProgramCounterIndirectWithIndexOldAddressingMode_5(b, l + 1);
r = r && consumeToken(b, ROUND_R); r = r && consumeToken(b, ROUND_R);
exit_section_(b, l, m, r, false, null); exit_section_(b, l, m, r, false, null);
return r; return r;
@ -1001,13 +995,6 @@ public class M68kParser implements PsiParser, LightPsiParser {
return true; 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 // CURRENT_PC_SYMBOL
public static boolean ProgramCounterReference(PsiBuilder b, int l) { public static boolean ProgramCounterReference(PsiBuilder b, int l) {

View File

@ -9,13 +9,10 @@ public interface M68kAddressRegisterIndirectWithIndexNewAddressingMode extends M
@NotNull @NotNull
M68kAddressRegister getAddressRegister(); M68kAddressRegister getAddressRegister();
@NotNull
M68kIndexRegister getIndexRegister();
@Nullable @Nullable
M68kExpr getDisplacement(); M68kExpr getDisplacement();
@NotNull
M68kRegister getIndexRegister();
@Nullable
M68kDataWidth getIndexWidth();
} }

View File

@ -9,13 +9,10 @@ public interface M68kAddressRegisterIndirectWithIndexOldAddressingMode extends M
@NotNull @NotNull
M68kAddressRegister getAddressRegister(); M68kAddressRegister getAddressRegister();
@NotNull
M68kIndexRegister getIndexRegister();
@Nullable @Nullable
M68kExpr getDisplacement(); M68kExpr getDisplacement();
@NotNull
M68kRegister getIndexRegister();
@Nullable
M68kDataWidth getIndexWidth();
} }

View File

@ -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();
}

View File

@ -6,13 +6,10 @@ import org.jetbrains.annotations.Nullable;
public interface M68kProgramCounterIndirectWithIndexNewAddressingMode extends M68kAddressingMode, M68kWithDisplacement, M68kWithIndexRegister { public interface M68kProgramCounterIndirectWithIndexNewAddressingMode extends M68kAddressingMode, M68kWithDisplacement, M68kWithIndexRegister {
@NotNull
M68kIndexRegister getIndexRegister();
@Nullable @Nullable
M68kExpr getDisplacement(); M68kExpr getDisplacement();
@NotNull
M68kRegister getIndexRegister();
@Nullable
M68kDataWidth getIndexWidth();
} }

View File

@ -6,13 +6,10 @@ import org.jetbrains.annotations.Nullable;
public interface M68kProgramCounterIndirectWithIndexOldAddressingMode extends M68kAddressingMode, M68kWithDisplacement, M68kWithIndexRegister { public interface M68kProgramCounterIndirectWithIndexOldAddressingMode extends M68kAddressingMode, M68kWithDisplacement, M68kWithIndexRegister {
@NotNull
M68kIndexRegister getIndexRegister();
@Nullable @Nullable
M68kExpr getDisplacement(); M68kExpr getDisplacement();
@NotNull
M68kRegister getIndexRegister();
@Nullable
M68kDataWidth getIndexWidth();
} }

View File

@ -48,6 +48,7 @@ public interface M68kTypes {
IElementType EXPR = new M68kElementType("EXPR"); IElementType EXPR = new M68kElementType("EXPR");
IElementType GLOBAL_LABEL = M68kStubElementTypeFactory.stubFactory("GLOBAL_LABEL"); IElementType GLOBAL_LABEL = M68kStubElementTypeFactory.stubFactory("GLOBAL_LABEL");
IElementType IMMEDIATE_DATA = new M68kElementType("IMMEDIATE_DATA"); IElementType IMMEDIATE_DATA = new M68kElementType("IMMEDIATE_DATA");
IElementType INDEX_REGISTER = new M68kElementType("INDEX_REGISTER");
IElementType LITERAL_EXPR = new M68kElementType("LITERAL_EXPR"); IElementType LITERAL_EXPR = new M68kElementType("LITERAL_EXPR");
IElementType LOCAL_LABEL = new M68kElementType("LOCAL_LABEL"); IElementType LOCAL_LABEL = new M68kElementType("LOCAL_LABEL");
IElementType MACRO_CALL = new M68kElementType("MACRO_CALL"); IElementType MACRO_CALL = new M68kElementType("MACRO_CALL");
@ -212,6 +213,8 @@ public interface M68kTypes {
return new M68kGlobalLabelImpl(node); return new M68kGlobalLabelImpl(node);
} else if (type == IMMEDIATE_DATA) { } else if (type == IMMEDIATE_DATA) {
return new M68kImmediateDataImpl(node); return new M68kImmediateDataImpl(node);
} else if (type == INDEX_REGISTER) {
return new M68kIndexRegisterImpl(node);
} else if (type == LITERAL_EXPR) { } else if (type == LITERAL_EXPR) {
return new M68kLiteralExprImpl(node); return new M68kLiteralExprImpl(node);
} else if (type == LOCAL_LABEL) { } else if (type == LOCAL_LABEL) {

View File

@ -99,6 +99,10 @@ public class M68kVisitor extends PsiElementVisitor {
visitAddressingMode(o); visitAddressingMode(o);
} }
public void visitIndexRegister(@NotNull M68kIndexRegister o) {
visitPsiElement(o);
}
public void visitLocalLabel(@NotNull M68kLocalLabel o) { public void visitLocalLabel(@NotNull M68kLocalLabel o) {
visitNamedElement(o); visitNamedElement(o);
} }

View File

@ -31,22 +31,16 @@ public class M68kAddressRegisterIndirectWithIndexNewAddressingModeImpl extends M
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kAddressRegister.class)); return notNullChild(PsiTreeUtil.getChildOfType(this, M68kAddressRegister.class));
} }
@Override
@NotNull
public M68kIndexRegister getIndexRegister() {
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kIndexRegister.class));
}
@Override @Override
@Nullable @Nullable
public M68kExpr getDisplacement() { public M68kExpr getDisplacement() {
return PsiTreeUtil.getChildOfType(this, M68kExpr.class); 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);
}
} }

View File

@ -31,22 +31,16 @@ public class M68kAddressRegisterIndirectWithIndexOldAddressingModeImpl extends M
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kAddressRegister.class)); return notNullChild(PsiTreeUtil.getChildOfType(this, M68kAddressRegister.class));
} }
@Override
@NotNull
public M68kIndexRegister getIndexRegister() {
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kIndexRegister.class));
}
@Override @Override
@Nullable @Nullable
public M68kExpr getDisplacement() { public M68kExpr getDisplacement() {
return PsiTreeUtil.getChildOfType(this, M68kExpr.class); 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);
}
} }

View File

@ -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);
}
}

View File

@ -4,7 +4,10 @@ package de.platon42.intellij.plugins.m68k.psi.impl;
import com.intellij.lang.ASTNode; import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.util.PsiTreeUtil; 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.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -25,22 +28,16 @@ public class M68kProgramCounterIndirectWithIndexNewAddressingModeImpl extends M6
else super.accept(visitor); else super.accept(visitor);
} }
@Override
@NotNull
public M68kIndexRegister getIndexRegister() {
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kIndexRegister.class));
}
@Override @Override
@Nullable @Nullable
public M68kExpr getDisplacement() { public M68kExpr getDisplacement() {
return PsiTreeUtil.getChildOfType(this, M68kExpr.class); 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);
}
} }

View File

@ -4,7 +4,10 @@ package de.platon42.intellij.plugins.m68k.psi.impl;
import com.intellij.lang.ASTNode; import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.util.PsiTreeUtil; 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.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -25,22 +28,16 @@ public class M68kProgramCounterIndirectWithIndexOldAddressingModeImpl extends M6
else super.accept(visitor); else super.accept(visitor);
} }
@Override
@NotNull
public M68kIndexRegister getIndexRegister() {
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kIndexRegister.class));
}
@Override @Override
@Nullable @Nullable
public M68kExpr getDisplacement() { public M68kExpr getDisplacement() {
return PsiTreeUtil.getChildOfType(this, M68kExpr.class); 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);
}
} }

View File

@ -10,7 +10,7 @@ class M68kFileElementType private constructor() : ILightStubFileElementType<PsiF
@JvmField @JvmField
val INSTANCE = M68kFileElementType() val INSTANCE = M68kFileElementType()
const val STUB_VERSION = 4 const val STUB_VERSION = 5
const val STUB_EXTERNAL_ID_PREFIX = "MC68000." const val STUB_EXTERNAL_ID_PREFIX = "MC68000."
const val EXTERNAL_ID = STUB_EXTERNAL_ID_PREFIX + "FILE" const val EXTERNAL_ID = STUB_EXTERNAL_ID_PREFIX + "FILE"
} }

View File

@ -28,7 +28,7 @@ enum class Register(val regname: String, val num: Int) {
A7("a7", 7); A7("a7", 7);
companion object { 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()]!! 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_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 OP_SIZE_SBW = (OP_SIZE_B or OP_SIZE_S or OP_SIZE_W)
const val RWM_READ_OPSIZE = 0x10 const val RWM_OP_MASK = 0xfff
const val RWM_READ_B = 0x11 const val RWM_SIZE_MASK = 0x00e
const val RWM_READ_W = 0x12
const val RWM_READ_L = 0x13
const val RWM_SET_OPSIZE = 0x20 const val RWM_SET_OPSIZE = 0x008
const val RWM_SET_B = 0x21 const val RWM_SET_B = 0x009
const val RWM_SET_W = 0x22 const val RWM_SET_W = 0x00b
const val RWM_SET_L = 0x23 const val RWM_SET_L = 0x00f
const val RWM_MODIFY_OPSIZE = 0x30 const val RWM_READ_OPSIZE = 0x800
const val RWM_MODIFY_B = 0x31 const val RWM_READ_B = 0x900
const val RWM_MODIFY_W = 0x32 const val RWM_READ_W = 0xb00
const val RWM_MODIFY_L = 0x33 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_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_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_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_W = RWM_READ_W shl RWM_OP1_SHIFT
const val RWM_READ_OP1_L = RWM_READ_L 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_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_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_W = RWM_MODIFY_W shl RWM_OP1_SHIFT
const val RWM_MODIFY_OP1_L = RWM_MODIFY_L 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_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_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_W = RWM_READ_W shl RWM_OP2_SHIFT
const val RWM_READ_OP2_L = RWM_READ_L 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_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_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_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_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( data class AllowedAdrMode(
val op1: Set<AddressMode>? = null, val op1: Set<AddressMode>? = null,

View File

@ -36,17 +36,17 @@ class M68kInstructionDocumentationProvider : AbstractDocumentationProvider() {
val defBuilder = createDefinition(isaData) val defBuilder = createDefinition(isaData)
builder.append(defBuilder.wrapWith(DocumentationMarkup.DEFINITION_ELEMENT)) builder.append(defBuilder.wrapWith(DocumentationMarkup.DEFINITION_ELEMENT))
val bindingRows = HtmlBuilder() val mnemonicInfoRows = HtmlBuilder()
val headerCells = listOf( val headerCells = listOf(
HtmlChunk.text("Mnemonic").wrapWith(DocumentationMarkup.SECTION_HEADER_CELL), HtmlChunk.text("Mnemonic").wrapWith(DocumentationMarkup.SECTION_HEADER_CELL),
HtmlChunk.text("Op1").wrapWith(DocumentationMarkup.SECTION_HEADER_CELL), HtmlChunk.text("Op1").wrapWith(DocumentationMarkup.SECTION_HEADER_CELL),
HtmlChunk.text("Op2").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 -> isaData.modes.forEach { allowedAdrMode ->
val mnemonics = findOpSizeDescriptions(allowedAdrMode.size) val mnemonics = findOpSizeDescriptions(allowedAdrMode.size)
.map { HtmlChunk.text(isaData.mnemonic + it).wrapWith(HtmlChunk.p()) } .map { HtmlChunk.text(isaData.mnemonic + it).wrapWith(HtmlChunk.div()) }
bindingRows.append( mnemonicInfoRows.append(
HtmlChunk.tag("tr").children( HtmlChunk.tag("tr").children(
DocumentationMarkup.SECTION_CONTENT_CELL.children(mnemonics), DocumentationMarkup.SECTION_CONTENT_CELL.children(mnemonics),
DocumentationMarkup.SECTION_CONTENT_CELL.child(collectAddressModes(allowedAdrMode.op1)), DocumentationMarkup.SECTION_CONTENT_CELL.child(collectAddressModes(allowedAdrMode.op1)),
@ -56,7 +56,7 @@ class M68kInstructionDocumentationProvider : AbstractDocumentationProvider() {
} }
val contentBuilder = HtmlBuilder() 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)) builder.append(contentBuilder.wrapWith(DocumentationMarkup.CONTENT_ELEMENT))
} }
@ -77,7 +77,7 @@ class M68kInstructionDocumentationProvider : AbstractDocumentationProvider() {
val defBuilder = HtmlBuilder() val defBuilder = HtmlBuilder()
defBuilder.append(HtmlChunk.text(isaData.description).bold().wrapWith("pre")) defBuilder.append(HtmlChunk.text(isaData.description).bold().wrapWith("pre"))
if (isaData.isPrivileged) { if (isaData.isPrivileged) {
defBuilder.append(HtmlChunk.font("red").addText("(privileged)").wrapWith("p")) defBuilder.append(HtmlChunk.font("red").addText("(privileged)").wrapWith(HtmlChunk.p()))
} }
return defBuilder return defBuilder
} }
@ -86,7 +86,7 @@ class M68kInstructionDocumentationProvider : AbstractDocumentationProvider() {
if (addressModes == null) return HtmlChunk.text("") if (addressModes == null) return HtmlChunk.text("")
val modes = HtmlBuilder() val modes = HtmlBuilder()
addressModes.sortedBy(AddressMode::ordinal) 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() return modes.toFragment()
} }

View File

@ -1,34 +1,209 @@
package de.platon42.intellij.plugins.m68k.documentation package de.platon42.intellij.plugins.m68k.documentation
import com.intellij.lang.documentation.AbstractDocumentationProvider import com.intellij.lang.documentation.AbstractDocumentationProvider
import com.intellij.lang.documentation.DocumentationMarkup
import com.intellij.openapi.editor.Editor 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.PsiElement
import com.intellij.psi.PsiFile import com.intellij.psi.PsiFile
import com.intellij.psi.util.PsiTreeUtil import com.intellij.psi.util.PsiTreeUtil
import de.platon42.intellij.plugins.m68k.asm.RWM_OP1_SHIFT import de.platon42.intellij.plugins.m68k.asm.*
import de.platon42.intellij.plugins.m68k.asm.RWM_OP2_SHIFT
import de.platon42.intellij.plugins.m68k.asm.Register.Companion.getRegFromName 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.*
import de.platon42.intellij.plugins.m68k.psi.M68kAddressingMode import de.platon42.intellij.plugins.m68k.psi.M68kAddressModeUtil.getOtherReadWriteModifyRegisters
import de.platon42.intellij.plugins.m68k.psi.M68kAsmInstruction import de.platon42.intellij.plugins.m68k.psi.M68kAddressModeUtil.getReadWriteModifyRegisters
import de.platon42.intellij.plugins.m68k.psi.M68kDataRegister
import de.platon42.intellij.plugins.m68k.utils.M68kIsaUtil.findExactIsaDataAndAllowedAdrModeForInstruction 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() { class M68kRegisterFlowDocumentationProvider : AbstractDocumentationProvider() {
override fun generateDoc(element: PsiElement, originalElement: PsiElement?): String? { override fun generateDoc(element: PsiElement, originalElement: PsiElement?): String? {
if (element is M68kDataRegister || element is M68kAddressRegister) { if (element is M68kDataRegister || element is M68kAddressRegister) {
val register = getRegFromName(element.text) val register = getRegFromName(element.text)
val addressingMode = PsiTreeUtil.getParentOfType(element, M68kAddressingMode::class.java) ?: return null val addressingMode = PsiTreeUtil.getParentOfType(element, M68kAddressingMode::class.java) ?: return null
val asmInstruction = PsiTreeUtil.getParentOfType(addressingMode, M68kAsmInstruction::class.java) ?: return null val asmInstruction = PsiTreeUtil.getParentOfType(addressingMode, M68kAsmInstruction::class.java) ?: return null
val (isaData, adrMode) = findExactIsaDataAndAllowedAdrModeForInstruction(asmInstruction) ?: return "unknown instruction" 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 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? { override fun getCustomDocumentationElement(editor: Editor, file: PsiFile, contextElement: PsiElement?, targetOffset: Int): PsiElement? {
if (contextElement == null) return null if (contextElement == null) return null
if (contextElement is M68kDataRegister || contextElement is M68kAddressRegister) return contextElement if (contextElement is M68kDataRegister || contextElement is M68kAddressRegister) return contextElement

View File

@ -234,6 +234,14 @@ Register ::= DataRegister | AddressRegister | SpecialRegister
private DataOrAddressRegister ::= DataRegister | AddressRegister { name = "data or address register"} private DataOrAddressRegister ::= DataRegister | AddressRegister { name = "data or address register"}
IndexRegister ::= DataOrAddressRegister DataWidth?
{
name = "index register"
methods = [
isLongWidth
]
}
AddressingMode ::= ImmediateData AddressingMode ::= ImmediateData
| AddressRegisterIndirectPreDecAddressingMode | AddressRegisterIndirectPreDecAddressingMode
| AddressRegisterIndirectPostIncAddressingMode | 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 = [ implements = [
"de.platon42.intellij.plugins.m68k.psi.M68kWithAddressRegisterIndirect" "de.platon42.intellij.plugins.m68k.psi.M68kWithAddressRegisterIndirect"
@ -288,12 +296,10 @@ AddressRegisterIndirectWithIndexOldAddressingMode ::= expr? ROUND_L AddressRegis
] ]
methods = [ methods = [
displacement = "expr" 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 = [ implements = [
"de.platon42.intellij.plugins.m68k.psi.M68kWithAddressRegisterIndirect" "de.platon42.intellij.plugins.m68k.psi.M68kWithAddressRegisterIndirect"
@ -302,8 +308,6 @@ AddressRegisterIndirectWithIndexNewAddressingMode ::= ROUND_L (expr SEPARATOR)?
] ]
methods = [ methods = [
displacement = "expr" 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 = [ implements = [
"de.platon42.intellij.plugins.m68k.psi.M68kWithDisplacement" "de.platon42.intellij.plugins.m68k.psi.M68kWithDisplacement"
@ -331,12 +335,10 @@ ProgramCounterIndirectWithIndexOldAddressingMode ::= expr? ROUND_L PC SEPARATOR
] ]
methods = [ methods = [
displacement = "expr" 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 = [ implements = [
"de.platon42.intellij.plugins.m68k.psi.M68kWithDisplacement" "de.platon42.intellij.plugins.m68k.psi.M68kWithDisplacement"
@ -344,8 +346,6 @@ ProgramCounterIndirectWithIndexNewAddressingMode ::= ROUND_L (expr SEPARATOR)? P
] ]
methods = [ methods = [
displacement = "expr" displacement = "expr"
indexRegister = "Register"
indexWidth = "DataWidth"
] ]
} }

View File

@ -27,31 +27,46 @@ object M68kAddressModeUtil {
} }
} }
fun getReadWriteModifyRegisters(addressingMode: M68kAddressingMode?, rwm: Int): Set<Pair<Register, Int>> { fun getOtherReadWriteModifyRegisters(rwm: Int): List<Pair<Register, Int>> {
if (addressingMode == null) return emptySet() 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) { return when (addressingMode) {
is M68kImmediateData -> emptySet() is M68kImmediateData,
is M68kAddressRegisterIndirectPostIncAddressingMode -> setOf(Register.getRegFromName(addressingMode.addressRegister.text) to RWM_MODIFY_OP1_L) is M68kSpecialRegisterDirectAddressingMode,
is M68kAddressRegisterIndirectPreDecAddressingMode -> setOf(Register.getRegFromName(addressingMode.addressRegister.text) to RWM_MODIFY_OP1_L) 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 -> { is M68kWithAddressRegisterIndirect -> {
if (addressingMode is M68kWithIndexRegister) { if (addressingMode is M68kWithIndexRegister) {
setOf( listOf(
Register.getRegFromName(addressingMode.addressRegister.text) to RWM_READ_OP1_L, Register.getRegFromName(addressingMode.addressRegister.text) to RWM_READ_L,
Register.getRegFromName(addressingMode.indexRegister.text) to if (addressingMode.hasLongWidth()) RWM_READ_OP1_L else RWM_READ_OP1_W Register.getRegFromName(addressingMode.indexRegister.register.text) to if (addressingMode.indexRegister.isLongWidth) RWM_READ_L else RWM_READ_W
) )
} else { } 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 M68kWithIndexRegister -> listOf(Register.getRegFromName(addressingMode.indexRegister.register.text) to if (addressingMode.indexRegister.isLongWidth) RWM_READ_L else RWM_READ_W)
is M68kProgramCounterIndirectWithDisplacementNewAddressingMode -> emptySet() is M68kDataRegisterDirectAddressingMode -> listOf(Register.getRegFromName(addressingMode.dataRegister.text) to rwm)
is M68kProgramCounterIndirectWithDisplacementOldAddressingMode -> emptySet() is M68kAddressRegisterDirectAddressingMode -> listOf(Register.getRegFromName(addressingMode.addressRegister.text) to rwm)
is M68kSpecialRegisterDirectAddressingMode -> emptySet() is M68kRegisterListAddressingMode -> addressingMode.registers.map { it to rwm }
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()
else -> throw IllegalArgumentException("Unknown addressing mode $addressingMode") 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()
}
} }

View File

@ -134,4 +134,10 @@ object M68kPsiImplUtil {
} }
return registers return registers
} }
// IndexRegister
@JvmStatic
fun isLongWidth(element: M68kIndexRegister): Boolean {
return element.dataWidth?.text.equals(".l", ignoreCase = true)
}
} }

View File

@ -1,6 +1,6 @@
package de.platon42.intellij.plugins.m68k.psi package de.platon42.intellij.plugins.m68k.psi
interface M68kWithAddressRegisterIndirect { interface M68kWithAddressRegisterIndirect : M68kAddressingMode {
val addressRegister: M68kAddressRegister val addressRegister: M68kAddressRegister
} }

View File

@ -1,6 +1,6 @@
package de.platon42.intellij.plugins.m68k.psi package de.platon42.intellij.plugins.m68k.psi
interface M68kWithDisplacement { interface M68kWithDisplacement : M68kAddressingMode {
val displacement: M68kExpr? val displacement: M68kExpr?
} }

View File

@ -1,12 +1,6 @@
package de.platon42.intellij.plugins.m68k.psi package de.platon42.intellij.plugins.m68k.psi
interface M68kWithIndexRegister { interface M68kWithIndexRegister : M68kAddressingMode {
val indexRegister: M68kRegister val indexRegister: M68kIndexRegister
val indexWidth: M68kDataWidth?
fun hasLongWidth(): Boolean {
return indexWidth?.text.equals(".l", ignoreCase = true)
}
} }

View File

@ -34,6 +34,42 @@ object M68kIsaUtil {
return matchedIsaData.map { it to M68kIsa.findMatchingAddressMode(it.modes, op1, op2, opSize, specialReg) } 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 { fun findOpSizeDescription(opSize: Int): String {
return when (opSize) { return when (opSize) {
OP_UNSIZED -> "" OP_UNSIZED -> ""
@ -48,17 +84,17 @@ object M68kIsaUtil {
} }
} }
fun findOpSizeDescriptions(opSize: Int): Set<String> { fun findOpSizeDescriptions(opSize: Int): List<String> {
return when (opSize) { return when (opSize) {
OP_UNSIZED -> setOf("") OP_UNSIZED -> listOf("")
OP_SIZE_B -> setOf(".b") OP_SIZE_B -> listOf(".b")
OP_SIZE_W -> setOf(".w") OP_SIZE_W -> listOf(".w")
OP_SIZE_L -> setOf(".l") OP_SIZE_L -> listOf(".l")
OP_SIZE_S -> setOf(".s") OP_SIZE_S -> listOf(".s")
OP_SIZE_BWL -> setOf(".b", ".w", ".l") OP_SIZE_BWL -> listOf(".b", ".w", ".l")
OP_SIZE_WL -> setOf(".w", ".l") OP_SIZE_WL -> listOf(".w", ".l")
OP_SIZE_SBW -> setOf(".s", ".b", ".w") OP_SIZE_SBW -> listOf(".s", ".b", ".w")
else -> setOf("?") else -> listOf("?")
} }
} }
} }

View File

@ -17,8 +17,10 @@ internal class M68kInstructionDocumentationProviderTest : AbstractDocumentationP
mo<caret>veq.l #40,d0 mo<caret>veq.l #40,d0
""" """
) )
assertThat(generateDocumentation(myFixture)).isEqualTo( 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"><p>moveq.l</p></td><td valign="top"><p>#&lt;xxx&gt;</p></td><td valign="top"><p>Dn</p></td></tr><br/></table></div>""" """
<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>#&lt;xxx&gt;</div></td><td valign="top"><div>Dn</div></td></tr></table></div>
"""
) )
} }
@ -29,8 +31,32 @@ internal class M68kInstructionDocumentationProviderTest : AbstractDocumentationP
bra.<caret>s label bra.<caret>s label
""" """
) )
assertThat(generateDocumentation(myFixture)).isEqualTo( 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"><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>""" """
<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 <caret>reset
""" """
) )
assertThat(generateDocumentation(myFixture)).isEqualTo( assertThat(generateDocumentation(myFixture)).contains("Reset External Devices", "(privileged)")
"""<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>"""
)
} }
@Test @Test

View File

@ -11,21 +11,93 @@ import org.junit.jupiter.api.extension.ExtendWith
internal class M68kRegisterFlowDocumentationProviderTest : AbstractDocumentationProviderTest() { internal class M68kRegisterFlowDocumentationProviderTest : AbstractDocumentationProviderTest() {
@Test @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( myFixture.configureByText(
"documentme.asm", """ "documentme.asm", """
label label
moveq.l #0,d0 moveq.l #0,d0
add.w #1,d0 add.w #1,d0
move.l d1,-(sp)
move.w d0,d1 move.w d0,d1
move.b d2,d0 move.b d2,d0
addq.b #1,d0 addq.b #1,d0
move.w d<caret>0,d1 move.w d<caret>0,d1
move.l d0,d2 move.l d0,d2
move.w d1,d2 move.w d1,d2
clr.b d0
moveq.l #0,d0
move.l (sp)+,d1
rts 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">&nbsp;</td>
<td valign="top">
<div class="grayed">[...]</div>
</td>
<td valign="top">&nbsp;</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"> ; &lt;--</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">&nbsp;</td>
<td valign="top">
<div class="grayed">[...]</div>
</td>
<td valign="top">&nbsp;</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()
)
} }
} }

View File

@ -177,9 +177,10 @@ Assembly File: a.asm
M68kAddressRegisterImpl(ADDRESS_REGISTER) M68kAddressRegisterImpl(ADDRESS_REGISTER)
PsiElement(M68kTokenType.AREG)('a0') PsiElement(M68kTokenType.AREG)('a0')
PsiElement(M68kTokenType.SEPARATOR)(',') PsiElement(M68kTokenType.SEPARATOR)(',')
M68kDataRegisterImpl(DATA_REGISTER) M68kIndexRegisterImpl(INDEX_REGISTER)
PsiElement(M68kTokenType.DREG)('d0') M68kDataRegisterImpl(DATA_REGISTER)
M68kDataWidthImpl(DATA_WIDTH) PsiElement(M68kTokenType.DREG)('d0')
PsiElement(M68kTokenType.OPSIZE_L)('.l') M68kDataWidthImpl(DATA_WIDTH)
PsiElement(M68kTokenType.OPSIZE_L)('.l')
PsiElement(M68kTokenType.ROUND_R)(')') PsiElement(M68kTokenType.ROUND_R)(')')
PsiElement(M68kTokenType.EOL)('\n') PsiElement(M68kTokenType.EOL)('\n')

View File

@ -21,8 +21,9 @@ Assembly File: a.asm
PsiElement(M68kTokenType.SEPARATOR)(',') PsiElement(M68kTokenType.SEPARATOR)(',')
PsiElement(M68kTokenType.PC)('pc') PsiElement(M68kTokenType.PC)('pc')
PsiElement(M68kTokenType.SEPARATOR)(',') PsiElement(M68kTokenType.SEPARATOR)(',')
M68kAddressRegisterImpl(ADDRESS_REGISTER) M68kIndexRegisterImpl(INDEX_REGISTER)
PsiElement(M68kTokenType.AREG)('a0') M68kAddressRegisterImpl(ADDRESS_REGISTER)
PsiElement(M68kTokenType.AREG)('a0')
PsiElement(M68kTokenType.ROUND_R)(')') PsiElement(M68kTokenType.ROUND_R)(')')
PsiElement(M68kTokenType.SEPARATOR)(',') PsiElement(M68kTokenType.SEPARATOR)(',')
M68kProgramCounterIndirectWithIndexNewAddressingModeImpl(PROGRAM_COUNTER_INDIRECT_WITH_INDEX_NEW_ADDRESSING_MODE) M68kProgramCounterIndirectWithIndexNewAddressingModeImpl(PROGRAM_COUNTER_INDIRECT_WITH_INDEX_NEW_ADDRESSING_MODE)
@ -43,9 +44,10 @@ Assembly File: a.asm
PsiElement(M68kTokenType.SEPARATOR)(',') PsiElement(M68kTokenType.SEPARATOR)(',')
PsiElement(M68kTokenType.PC)('pc') PsiElement(M68kTokenType.PC)('pc')
PsiElement(M68kTokenType.SEPARATOR)(',') PsiElement(M68kTokenType.SEPARATOR)(',')
M68kDataRegisterImpl(DATA_REGISTER) M68kIndexRegisterImpl(INDEX_REGISTER)
PsiElement(M68kTokenType.DREG)('d5') M68kDataRegisterImpl(DATA_REGISTER)
M68kDataWidthImpl(DATA_WIDTH) PsiElement(M68kTokenType.DREG)('d5')
PsiElement(M68kTokenType.OPSIZE_L)('.l') M68kDataWidthImpl(DATA_WIDTH)
PsiElement(M68kTokenType.OPSIZE_L)('.l')
PsiElement(M68kTokenType.ROUND_R)(')') PsiElement(M68kTokenType.ROUND_R)(')')
PsiElement(M68kTokenType.EOL)('\n') PsiElement(M68kTokenType.EOL)('\n')

View File

@ -20,10 +20,11 @@ Assembly File: a.asm
PsiElement(M68kTokenType.ROUND_L)('(') PsiElement(M68kTokenType.ROUND_L)('(')
PsiElement(M68kTokenType.PC)('pc') PsiElement(M68kTokenType.PC)('pc')
PsiElement(M68kTokenType.SEPARATOR)(',') PsiElement(M68kTokenType.SEPARATOR)(',')
M68kDataRegisterImpl(DATA_REGISTER) M68kIndexRegisterImpl(INDEX_REGISTER)
PsiElement(M68kTokenType.DREG)('d0') M68kDataRegisterImpl(DATA_REGISTER)
M68kDataWidthImpl(DATA_WIDTH) PsiElement(M68kTokenType.DREG)('d0')
PsiElement(M68kTokenType.OPSIZE_W)('.w') M68kDataWidthImpl(DATA_WIDTH)
PsiElement(M68kTokenType.OPSIZE_W)('.w')
PsiElement(M68kTokenType.ROUND_R)(')') PsiElement(M68kTokenType.ROUND_R)(')')
PsiElement(M68kTokenType.SEPARATOR)(',') PsiElement(M68kTokenType.SEPARATOR)(',')
M68kProgramCounterIndirectWithIndexOldAddressingModeImpl(PROGRAM_COUNTER_INDIRECT_WITH_INDEX_OLD_ADDRESSING_MODE) M68kProgramCounterIndirectWithIndexOldAddressingModeImpl(PROGRAM_COUNTER_INDIRECT_WITH_INDEX_OLD_ADDRESSING_MODE)
@ -43,7 +44,8 @@ Assembly File: a.asm
PsiElement(M68kTokenType.ROUND_L)('(') PsiElement(M68kTokenType.ROUND_L)('(')
PsiElement(M68kTokenType.PC)('pc') PsiElement(M68kTokenType.PC)('pc')
PsiElement(M68kTokenType.SEPARATOR)(',') PsiElement(M68kTokenType.SEPARATOR)(',')
M68kAddressRegisterImpl(ADDRESS_REGISTER) M68kIndexRegisterImpl(INDEX_REGISTER)
PsiElement(M68kTokenType.AREG)('a3') M68kAddressRegisterImpl(ADDRESS_REGISTER)
PsiElement(M68kTokenType.AREG)('a3')
PsiElement(M68kTokenType.ROUND_R)(')') PsiElement(M68kTokenType.ROUND_R)(')')
PsiElement(M68kTokenType.EOL)('\n') PsiElement(M68kTokenType.EOL)('\n')

View File

@ -11,17 +11,19 @@ Assembly File: a.asm
PsiElement(M68kTokenType.ROUND_L)('(') PsiElement(M68kTokenType.ROUND_L)('(')
PsiElement(M68kTokenType.PC)('pc') PsiElement(M68kTokenType.PC)('pc')
PsiElement(M68kTokenType.SEPARATOR)(',') PsiElement(M68kTokenType.SEPARATOR)(',')
M68kDataRegisterImpl(DATA_REGISTER) M68kIndexRegisterImpl(INDEX_REGISTER)
PsiElement(M68kTokenType.DREG)('d0') M68kDataRegisterImpl(DATA_REGISTER)
M68kDataWidthImpl(DATA_WIDTH) PsiElement(M68kTokenType.DREG)('d0')
PsiElement(M68kTokenType.OPSIZE_W)('.w') M68kDataWidthImpl(DATA_WIDTH)
PsiElement(M68kTokenType.OPSIZE_W)('.w')
PsiElement(M68kTokenType.ROUND_R)(')') PsiElement(M68kTokenType.ROUND_R)(')')
PsiElement(M68kTokenType.SEPARATOR)(',') PsiElement(M68kTokenType.SEPARATOR)(',')
M68kProgramCounterIndirectWithIndexNewAddressingModeImpl(PROGRAM_COUNTER_INDIRECT_WITH_INDEX_NEW_ADDRESSING_MODE) M68kProgramCounterIndirectWithIndexNewAddressingModeImpl(PROGRAM_COUNTER_INDIRECT_WITH_INDEX_NEW_ADDRESSING_MODE)
PsiElement(M68kTokenType.ROUND_L)('(') PsiElement(M68kTokenType.ROUND_L)('(')
PsiElement(M68kTokenType.PC)('pc') PsiElement(M68kTokenType.PC)('pc')
PsiElement(M68kTokenType.SEPARATOR)(',') PsiElement(M68kTokenType.SEPARATOR)(',')
M68kAddressRegisterImpl(ADDRESS_REGISTER) M68kIndexRegisterImpl(INDEX_REGISTER)
PsiElement(M68kTokenType.AREG)('a3') M68kAddressRegisterImpl(ADDRESS_REGISTER)
PsiElement(M68kTokenType.AREG)('a3')
PsiElement(M68kTokenType.ROUND_R)(')') PsiElement(M68kTokenType.ROUND_R)(')')
PsiElement(M68kTokenType.EOL)('\n') PsiElement(M68kTokenType.EOL)('\n')

View File

@ -22,8 +22,9 @@ Assembly File: a.asm
M68kAddressRegisterImpl(ADDRESS_REGISTER) M68kAddressRegisterImpl(ADDRESS_REGISTER)
PsiElement(M68kTokenType.REG_SP)('sp') PsiElement(M68kTokenType.REG_SP)('sp')
PsiElement(M68kTokenType.SEPARATOR)(',') PsiElement(M68kTokenType.SEPARATOR)(',')
M68kAddressRegisterImpl(ADDRESS_REGISTER) M68kIndexRegisterImpl(INDEX_REGISTER)
PsiElement(M68kTokenType.AREG)('a0') M68kAddressRegisterImpl(ADDRESS_REGISTER)
PsiElement(M68kTokenType.AREG)('a0')
PsiElement(M68kTokenType.ROUND_R)(')') PsiElement(M68kTokenType.ROUND_R)(')')
PsiElement(M68kTokenType.SEPARATOR)(',') PsiElement(M68kTokenType.SEPARATOR)(',')
M68kAddressRegisterIndirectWithIndexNewAddressingModeImpl(ADDRESS_REGISTER_INDIRECT_WITH_INDEX_NEW_ADDRESSING_MODE) M68kAddressRegisterIndirectWithIndexNewAddressingModeImpl(ADDRESS_REGISTER_INDIRECT_WITH_INDEX_NEW_ADDRESSING_MODE)
@ -45,9 +46,10 @@ Assembly File: a.asm
M68kAddressRegisterImpl(ADDRESS_REGISTER) M68kAddressRegisterImpl(ADDRESS_REGISTER)
PsiElement(M68kTokenType.AREG)('a1') PsiElement(M68kTokenType.AREG)('a1')
PsiElement(M68kTokenType.SEPARATOR)(',') PsiElement(M68kTokenType.SEPARATOR)(',')
M68kDataRegisterImpl(DATA_REGISTER) M68kIndexRegisterImpl(INDEX_REGISTER)
PsiElement(M68kTokenType.DREG)('d5') M68kDataRegisterImpl(DATA_REGISTER)
M68kDataWidthImpl(DATA_WIDTH) PsiElement(M68kTokenType.DREG)('d5')
PsiElement(M68kTokenType.OPSIZE_L)('.l') M68kDataWidthImpl(DATA_WIDTH)
PsiElement(M68kTokenType.OPSIZE_L)('.l')
PsiElement(M68kTokenType.ROUND_R)(')') PsiElement(M68kTokenType.ROUND_R)(')')
PsiElement(M68kTokenType.EOL)('\n') PsiElement(M68kTokenType.EOL)('\n')

View File

@ -21,10 +21,11 @@ Assembly File: a.asm
M68kAddressRegisterImpl(ADDRESS_REGISTER) M68kAddressRegisterImpl(ADDRESS_REGISTER)
PsiElement(M68kTokenType.REG_SP)('sp') PsiElement(M68kTokenType.REG_SP)('sp')
PsiElement(M68kTokenType.SEPARATOR)(',') PsiElement(M68kTokenType.SEPARATOR)(',')
M68kDataRegisterImpl(DATA_REGISTER) M68kIndexRegisterImpl(INDEX_REGISTER)
PsiElement(M68kTokenType.DREG)('d0') M68kDataRegisterImpl(DATA_REGISTER)
M68kDataWidthImpl(DATA_WIDTH) PsiElement(M68kTokenType.DREG)('d0')
PsiElement(M68kTokenType.OPSIZE_W)('.w') M68kDataWidthImpl(DATA_WIDTH)
PsiElement(M68kTokenType.OPSIZE_W)('.w')
PsiElement(M68kTokenType.ROUND_R)(')') PsiElement(M68kTokenType.ROUND_R)(')')
PsiElement(M68kTokenType.SEPARATOR)(',') PsiElement(M68kTokenType.SEPARATOR)(',')
M68kAddressRegisterIndirectWithIndexOldAddressingModeImpl(ADDRESS_REGISTER_INDIRECT_WITH_INDEX_OLD_ADDRESSING_MODE) M68kAddressRegisterIndirectWithIndexOldAddressingModeImpl(ADDRESS_REGISTER_INDIRECT_WITH_INDEX_OLD_ADDRESSING_MODE)
@ -45,7 +46,8 @@ Assembly File: a.asm
M68kAddressRegisterImpl(ADDRESS_REGISTER) M68kAddressRegisterImpl(ADDRESS_REGISTER)
PsiElement(M68kTokenType.AREG)('a1') PsiElement(M68kTokenType.AREG)('a1')
PsiElement(M68kTokenType.SEPARATOR)(',') PsiElement(M68kTokenType.SEPARATOR)(',')
M68kAddressRegisterImpl(ADDRESS_REGISTER) M68kIndexRegisterImpl(INDEX_REGISTER)
PsiElement(M68kTokenType.AREG)('a3') M68kAddressRegisterImpl(ADDRESS_REGISTER)
PsiElement(M68kTokenType.AREG)('a3')
PsiElement(M68kTokenType.ROUND_R)(')') PsiElement(M68kTokenType.ROUND_R)(')')
PsiElement(M68kTokenType.EOL)('\n') PsiElement(M68kTokenType.EOL)('\n')

View File

@ -12,10 +12,11 @@ Assembly File: a.asm
M68kAddressRegisterImpl(ADDRESS_REGISTER) M68kAddressRegisterImpl(ADDRESS_REGISTER)
PsiElement(M68kTokenType.REG_SP)('sp') PsiElement(M68kTokenType.REG_SP)('sp')
PsiElement(M68kTokenType.SEPARATOR)(',') PsiElement(M68kTokenType.SEPARATOR)(',')
M68kDataRegisterImpl(DATA_REGISTER) M68kIndexRegisterImpl(INDEX_REGISTER)
PsiElement(M68kTokenType.DREG)('d0') M68kDataRegisterImpl(DATA_REGISTER)
M68kDataWidthImpl(DATA_WIDTH) PsiElement(M68kTokenType.DREG)('d0')
PsiElement(M68kTokenType.OPSIZE_W)('.w') M68kDataWidthImpl(DATA_WIDTH)
PsiElement(M68kTokenType.OPSIZE_W)('.w')
PsiElement(M68kTokenType.ROUND_R)(')') PsiElement(M68kTokenType.ROUND_R)(')')
PsiElement(M68kTokenType.SEPARATOR)(',') PsiElement(M68kTokenType.SEPARATOR)(',')
M68kAddressRegisterIndirectWithIndexNewAddressingModeImpl(ADDRESS_REGISTER_INDIRECT_WITH_INDEX_NEW_ADDRESSING_MODE) M68kAddressRegisterIndirectWithIndexNewAddressingModeImpl(ADDRESS_REGISTER_INDIRECT_WITH_INDEX_NEW_ADDRESSING_MODE)
@ -23,7 +24,8 @@ Assembly File: a.asm
M68kAddressRegisterImpl(ADDRESS_REGISTER) M68kAddressRegisterImpl(ADDRESS_REGISTER)
PsiElement(M68kTokenType.AREG)('a1') PsiElement(M68kTokenType.AREG)('a1')
PsiElement(M68kTokenType.SEPARATOR)(',') PsiElement(M68kTokenType.SEPARATOR)(',')
M68kAddressRegisterImpl(ADDRESS_REGISTER) M68kIndexRegisterImpl(INDEX_REGISTER)
PsiElement(M68kTokenType.AREG)('a3') M68kAddressRegisterImpl(ADDRESS_REGISTER)
PsiElement(M68kTokenType.AREG)('a3')
PsiElement(M68kTokenType.ROUND_R)(')') PsiElement(M68kTokenType.ROUND_R)(')')
PsiElement(M68kTokenType.EOL)('\n') PsiElement(M68kTokenType.EOL)('\n')