Moved Condition-Code stuff to separate file, added reverse mapping function.
Reworked Instruction Documentation provider, now shows condition codes. Cosmetics: Removed MutableList information where unnecessary
This commit is contained in:
parent
5881dcdaf8
commit
6f99c2ffcc
@ -78,6 +78,7 @@ make it work with JUnit 5. Feel free to use the code (in package ```de.platon42.
|
|||||||
- Bugfix: Minor fix for `andi/eori/ori to ccr` which were not byte sized in ISA.
|
- Bugfix: Minor fix for `andi/eori/ori to ccr` which were not byte sized in ISA.
|
||||||
- Bugfix: Added alternate condition code tests `HS (=CC)` and `LO (=CS)`.
|
- Bugfix: Added alternate condition code tests `HS (=CC)` and `LO (=CS)`.
|
||||||
- Performance: Optimized mnemonic lookup.
|
- Performance: Optimized mnemonic lookup.
|
||||||
|
- Enhancement: Reworked Instruction Documentation provider, now shows condition codes.
|
||||||
|
|
||||||
### V0.4 (03-Aug-21)
|
### V0.4 (03-Aug-21)
|
||||||
|
|
||||||
|
@ -64,6 +64,7 @@ patchPluginXml {
|
|||||||
<li>Bugfix: Minor fix for `andi/eori/ori to ccr` which were not byte sized in ISA.
|
<li>Bugfix: Minor fix for `andi/eori/ori to ccr` which were not byte sized in ISA.
|
||||||
<li>Bugfix: Added alternate condition code tests HS (=CC) and LO (=CS).
|
<li>Bugfix: Added alternate condition code tests HS (=CC) and LO (=CS).
|
||||||
<li>Performance: Optimized mnemonic lookup.
|
<li>Performance: Optimized mnemonic lookup.
|
||||||
|
<li>Enhancement: Reworked Instruction Documentation provider, now shows condition codes.
|
||||||
</ul>
|
</ul>
|
||||||
<h4>V0.4 (03-Aug-21)</h4>
|
<h4>V0.4 (03-Aug-21)</h4>
|
||||||
<ul>
|
<ul>
|
||||||
|
@ -0,0 +1,198 @@
|
|||||||
|
package de.platon42.intellij.plugins.m68k.asm
|
||||||
|
|
||||||
|
const val CC_X_CLEAR = 0x10000
|
||||||
|
const val CC_X_SET = 0x20000
|
||||||
|
const val CC_X_UNDEF = 0x30000
|
||||||
|
const val CC_X_RES = 0x40000
|
||||||
|
const val CC_X_AND = 0x50000
|
||||||
|
const val CC_X_OR = 0x60000
|
||||||
|
const val CC_X_CARRY = 0x70000
|
||||||
|
const val CC_X_TST = 0xf0000
|
||||||
|
|
||||||
|
const val CC_N_CLEAR = 0x01000
|
||||||
|
const val CC_N_SET = 0x02000
|
||||||
|
const val CC_N_UNDEF = 0x03000
|
||||||
|
const val CC_N_RES = 0x04000
|
||||||
|
const val CC_N_AND = 0x05000
|
||||||
|
const val CC_N_OR = 0x06000
|
||||||
|
const val CC_N_TST = 0x0f000
|
||||||
|
|
||||||
|
const val CC_Z_CLEAR = 0x00100
|
||||||
|
const val CC_Z_SET = 0x00200
|
||||||
|
const val CC_Z_UNDEF = 0x00300
|
||||||
|
const val CC_Z_RES = 0x00400
|
||||||
|
const val CC_Z_AND = 0x00500
|
||||||
|
const val CC_Z_OR = 0x00600
|
||||||
|
const val CC_Z_TST = 0x00f00
|
||||||
|
|
||||||
|
const val CC_V_CLEAR = 0x00010
|
||||||
|
const val CC_V_SET = 0x00020
|
||||||
|
const val CC_V_UNDEF = 0x00030
|
||||||
|
const val CC_V_RES = 0x00040
|
||||||
|
const val CC_V_AND = 0x00050
|
||||||
|
const val CC_V_OR = 0x00060
|
||||||
|
const val CC_V_TST = 0x000f0
|
||||||
|
|
||||||
|
const val CC_C_CLEAR = 0x00001
|
||||||
|
const val CC_C_SET = 0x00002
|
||||||
|
const val CC_C_UNDEF = 0x00003
|
||||||
|
const val CC_C_RES = 0x00004
|
||||||
|
const val CC_C_AND = 0x00005
|
||||||
|
const val CC_C_OR = 0x00006
|
||||||
|
const val CC_C_TST = 0x0000f
|
||||||
|
|
||||||
|
private const val CC_NOT_AFFECTED_STR = "Not affected"
|
||||||
|
private const val CC_ALWAYS_CLEAR_STR = "Always cleared"
|
||||||
|
private const val CC_ALWAYS_SET_STR = "Always set"
|
||||||
|
private const val CC_UNDEFINED_STR = "Undefined"
|
||||||
|
private const val CC_RES_STR = "From result"
|
||||||
|
private const val CC_AND_STR = "And'ed: Only cleared for zero bit"
|
||||||
|
private const val CC_OR_STR = "Or'ed: Only set for one bit"
|
||||||
|
|
||||||
|
fun getCcInfo(cc: Int): Map<String, Pair<String, String>> {
|
||||||
|
val xnzvcMap = LinkedHashMap<String, Pair<String, String>>(5)
|
||||||
|
xnzvcMap["X"] = when (cc and CC_X_TST) {
|
||||||
|
0 -> "-" to CC_NOT_AFFECTED_STR
|
||||||
|
CC_X_SET -> "1" to CC_ALWAYS_SET_STR
|
||||||
|
CC_X_CLEAR -> "0" to CC_ALWAYS_CLEAR_STR
|
||||||
|
CC_X_UNDEF -> "U" to CC_UNDEFINED_STR
|
||||||
|
CC_X_AND -> "*" to CC_AND_STR
|
||||||
|
CC_X_OR -> "*" to CC_OR_STR
|
||||||
|
CC_X_CARRY -> "*" to "Set the same as the carry bit"
|
||||||
|
else -> "*" to "$CC_RES_STR (usually the bit shifted out)"
|
||||||
|
}
|
||||||
|
xnzvcMap["N"] = when (cc and CC_N_TST) {
|
||||||
|
0 -> "-" to CC_NOT_AFFECTED_STR
|
||||||
|
CC_N_SET -> "1" to CC_ALWAYS_SET_STR
|
||||||
|
CC_N_CLEAR -> "0" to CC_ALWAYS_CLEAR_STR
|
||||||
|
CC_N_UNDEF -> "U" to CC_UNDEFINED_STR
|
||||||
|
CC_N_AND -> "*" to CC_AND_STR
|
||||||
|
CC_N_OR -> "*" to CC_OR_STR
|
||||||
|
else -> "*" to "$CC_RES_STR (usually if negative)"
|
||||||
|
}
|
||||||
|
xnzvcMap["Z"] = when (cc and CC_Z_TST) {
|
||||||
|
0 -> "-" to CC_NOT_AFFECTED_STR
|
||||||
|
CC_Z_SET -> "1" to CC_ALWAYS_SET_STR
|
||||||
|
CC_Z_CLEAR -> "0" to CC_ALWAYS_CLEAR_STR
|
||||||
|
CC_Z_UNDEF -> "U" to CC_UNDEFINED_STR
|
||||||
|
CC_Z_AND -> "*" to CC_AND_STR
|
||||||
|
CC_Z_OR -> "*" to CC_OR_STR
|
||||||
|
else -> "*" to "$CC_RES_STR (usually if zero)"
|
||||||
|
}
|
||||||
|
xnzvcMap["V"] = when (cc and CC_V_TST) {
|
||||||
|
0 -> "-" to CC_NOT_AFFECTED_STR
|
||||||
|
CC_V_SET -> "1" to CC_ALWAYS_SET_STR
|
||||||
|
CC_V_CLEAR -> "0" to CC_ALWAYS_CLEAR_STR
|
||||||
|
CC_V_UNDEF -> "U" to CC_UNDEFINED_STR
|
||||||
|
CC_V_AND -> "*" to CC_AND_STR
|
||||||
|
CC_V_OR -> "*" to CC_OR_STR
|
||||||
|
else -> "*" to "$CC_RES_STR (usually for overflows)"
|
||||||
|
}
|
||||||
|
xnzvcMap["C"] = when (cc and CC_V_TST) {
|
||||||
|
0 -> "-" to CC_NOT_AFFECTED_STR
|
||||||
|
CC_V_SET -> "1" to CC_ALWAYS_SET_STR
|
||||||
|
CC_V_CLEAR -> "0" to CC_ALWAYS_CLEAR_STR
|
||||||
|
CC_V_UNDEF -> "U" to CC_UNDEFINED_STR
|
||||||
|
CC_V_AND -> "*" to CC_AND_STR
|
||||||
|
CC_V_OR -> "*" to CC_OR_STR
|
||||||
|
else -> "*" to "$CC_RES_STR (usually carry/borrow)"
|
||||||
|
}
|
||||||
|
|
||||||
|
return xnzvcMap
|
||||||
|
}
|
||||||
|
|
||||||
|
fun cc(xnzvc: String): Int {
|
||||||
|
var result = 0
|
||||||
|
result += when (xnzvc[0]) {
|
||||||
|
'-' -> 0
|
||||||
|
'0' -> CC_X_CLEAR
|
||||||
|
'1' -> CC_X_SET
|
||||||
|
'U' -> CC_X_UNDEF
|
||||||
|
'*' -> CC_X_RES
|
||||||
|
'A' -> CC_X_AND
|
||||||
|
'O' -> CC_X_OR
|
||||||
|
'C' -> CC_X_CARRY
|
||||||
|
'?' -> CC_X_TST
|
||||||
|
else -> throw IllegalArgumentException("Syntax Error")
|
||||||
|
}
|
||||||
|
result += when (xnzvc[1]) {
|
||||||
|
'-' -> 0
|
||||||
|
'0' -> CC_N_CLEAR
|
||||||
|
'1' -> CC_N_SET
|
||||||
|
'U' -> CC_N_UNDEF
|
||||||
|
'*' -> CC_N_RES
|
||||||
|
'A' -> CC_N_AND
|
||||||
|
'O' -> CC_N_OR
|
||||||
|
'?' -> CC_N_TST
|
||||||
|
else -> throw IllegalArgumentException("Syntax Error")
|
||||||
|
}
|
||||||
|
result += when (xnzvc[2]) {
|
||||||
|
'-' -> 0
|
||||||
|
'0' -> CC_Z_CLEAR
|
||||||
|
'1' -> CC_Z_SET
|
||||||
|
'U' -> CC_Z_UNDEF
|
||||||
|
'*' -> CC_Z_RES
|
||||||
|
'A' -> CC_Z_AND
|
||||||
|
'O' -> CC_Z_OR
|
||||||
|
'?' -> CC_Z_TST
|
||||||
|
else -> throw IllegalArgumentException("Syntax Error")
|
||||||
|
}
|
||||||
|
result += when (xnzvc[3]) {
|
||||||
|
'-' -> 0
|
||||||
|
'0' -> CC_V_CLEAR
|
||||||
|
'1' -> CC_V_SET
|
||||||
|
'U' -> CC_V_UNDEF
|
||||||
|
'*' -> CC_V_RES
|
||||||
|
'A' -> CC_V_AND
|
||||||
|
'O' -> CC_V_OR
|
||||||
|
'?' -> CC_V_TST
|
||||||
|
else -> throw IllegalArgumentException("Syntax Error")
|
||||||
|
}
|
||||||
|
result += when (xnzvc[4]) {
|
||||||
|
'-' -> 0
|
||||||
|
'0' -> CC_C_CLEAR
|
||||||
|
'1' -> CC_C_SET
|
||||||
|
'U' -> CC_C_UNDEF
|
||||||
|
'*' -> CC_C_RES
|
||||||
|
'A' -> CC_C_AND
|
||||||
|
'O' -> CC_C_OR
|
||||||
|
'?' -> CC_C_TST
|
||||||
|
else -> throw IllegalArgumentException("Syntax Error")
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class ConditionCode(val cc: String, val testedCc: Int) {
|
||||||
|
TRUE("t", cc("-----")),
|
||||||
|
FALSE("f", cc("-----")),
|
||||||
|
HI("hi", cc("--?-?")),
|
||||||
|
LS("ls", cc("--?-?")),
|
||||||
|
CC("cc", cc("----?")),
|
||||||
|
HS("hs", cc("----?")), // same as CC
|
||||||
|
CS("cs", cc("----?")),
|
||||||
|
LO("lo", cc("----?")), // same as CS
|
||||||
|
NE("ne", cc("--?--")),
|
||||||
|
EQ("eq", cc("--?--")),
|
||||||
|
VC("vc", cc("---?-")),
|
||||||
|
VS("vs", cc("---?-")),
|
||||||
|
PL("pl", cc("-?---")),
|
||||||
|
MI("mi", cc("-?---")),
|
||||||
|
GE("ge", cc("-?-?-")),
|
||||||
|
LT("lt", cc("-?-?-")),
|
||||||
|
GT("gt", cc("-???-")),
|
||||||
|
LE("le", cc("-???-"));
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val NAME_TO_CC_MAP = values().associateBy { it.cc }
|
||||||
|
|
||||||
|
fun getCcFromName(cc: String) = NAME_TO_CC_MAP[cc.lowercase()]!!
|
||||||
|
|
||||||
|
fun getCcFromMnemonic(mnemonic: String) =
|
||||||
|
// handle special case for dbra
|
||||||
|
if (mnemonic.equals("dbra", ignoreCase = true)) {
|
||||||
|
FALSE
|
||||||
|
} else {
|
||||||
|
NAME_TO_CC_MAP[mnemonic.substring(mnemonic.length - 2).lowercase()]!!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -113,108 +113,6 @@ const val RWM_SET_OP2_L = RWM_SET_L shl RWM_OP2_SHIFT
|
|||||||
|
|
||||||
const val RWM_MODIFY_STACK = 0x1000000
|
const val RWM_MODIFY_STACK = 0x1000000
|
||||||
|
|
||||||
const val CC_X_CLEAR = 0x10000
|
|
||||||
const val CC_X_SET = 0x20000
|
|
||||||
const val CC_X_UNDEF = 0x30000
|
|
||||||
const val CC_X_RES = 0x40000
|
|
||||||
const val CC_X_AND = 0x50000
|
|
||||||
const val CC_X_OR = 0x60000
|
|
||||||
const val CC_X_CARRY = 0x70000
|
|
||||||
const val CC_X_TST = 0xf0000
|
|
||||||
|
|
||||||
const val CC_N_CLEAR = 0x01000
|
|
||||||
const val CC_N_SET = 0x02000
|
|
||||||
const val CC_N_UNDEF = 0x03000
|
|
||||||
const val CC_N_RES = 0x04000
|
|
||||||
const val CC_N_AND = 0x05000
|
|
||||||
const val CC_N_OR = 0x06000
|
|
||||||
const val CC_N_TST = 0x0f000
|
|
||||||
|
|
||||||
const val CC_Z_CLEAR = 0x00100
|
|
||||||
const val CC_Z_SET = 0x00200
|
|
||||||
const val CC_Z_UNDEF = 0x00300
|
|
||||||
const val CC_Z_RES = 0x00400
|
|
||||||
const val CC_Z_AND = 0x00500
|
|
||||||
const val CC_Z_OR = 0x00600
|
|
||||||
const val CC_Z_TST = 0x00f00
|
|
||||||
|
|
||||||
const val CC_V_CLEAR = 0x00010
|
|
||||||
const val CC_V_SET = 0x00020
|
|
||||||
const val CC_V_UNDEF = 0x00030
|
|
||||||
const val CC_V_RES = 0x00040
|
|
||||||
const val CC_V_AND = 0x00050
|
|
||||||
const val CC_V_OR = 0x00060
|
|
||||||
const val CC_V_TST = 0x000f0
|
|
||||||
|
|
||||||
const val CC_C_CLEAR = 0x00001
|
|
||||||
const val CC_C_SET = 0x00002
|
|
||||||
const val CC_C_UNDEF = 0x00003
|
|
||||||
const val CC_C_RES = 0x00004
|
|
||||||
const val CC_C_AND = 0x00005
|
|
||||||
const val CC_C_OR = 0x00006
|
|
||||||
const val CC_C_TST = 0x0000f
|
|
||||||
|
|
||||||
private fun cc(xnzvc: String): Int {
|
|
||||||
var result = 0
|
|
||||||
result += when (xnzvc[0]) {
|
|
||||||
'-' -> 0
|
|
||||||
'0' -> CC_X_CLEAR
|
|
||||||
'1' -> CC_X_SET
|
|
||||||
'U' -> CC_X_UNDEF
|
|
||||||
'*' -> CC_X_RES
|
|
||||||
'A' -> CC_X_AND
|
|
||||||
'O' -> CC_X_OR
|
|
||||||
'C' -> CC_X_CARRY
|
|
||||||
'?' -> CC_X_TST
|
|
||||||
else -> throw IllegalArgumentException("Syntax Error")
|
|
||||||
}
|
|
||||||
result += when (xnzvc[1]) {
|
|
||||||
'-' -> 0
|
|
||||||
'0' -> CC_N_CLEAR
|
|
||||||
'1' -> CC_N_SET
|
|
||||||
'U' -> CC_N_UNDEF
|
|
||||||
'*' -> CC_N_RES
|
|
||||||
'A' -> CC_N_AND
|
|
||||||
'O' -> CC_N_OR
|
|
||||||
'?' -> CC_N_TST
|
|
||||||
else -> throw IllegalArgumentException("Syntax Error")
|
|
||||||
}
|
|
||||||
result += when (xnzvc[2]) {
|
|
||||||
'-' -> 0
|
|
||||||
'0' -> CC_Z_CLEAR
|
|
||||||
'1' -> CC_Z_SET
|
|
||||||
'U' -> CC_Z_UNDEF
|
|
||||||
'*' -> CC_Z_RES
|
|
||||||
'A' -> CC_Z_AND
|
|
||||||
'O' -> CC_Z_OR
|
|
||||||
'?' -> CC_Z_TST
|
|
||||||
else -> throw IllegalArgumentException("Syntax Error")
|
|
||||||
}
|
|
||||||
result += when (xnzvc[3]) {
|
|
||||||
'-' -> 0
|
|
||||||
'0' -> CC_V_CLEAR
|
|
||||||
'1' -> CC_V_SET
|
|
||||||
'U' -> CC_V_UNDEF
|
|
||||||
'*' -> CC_V_RES
|
|
||||||
'A' -> CC_V_AND
|
|
||||||
'O' -> CC_V_OR
|
|
||||||
'?' -> CC_V_TST
|
|
||||||
else -> throw IllegalArgumentException("Syntax Error")
|
|
||||||
}
|
|
||||||
result += when (xnzvc[4]) {
|
|
||||||
'-' -> 0
|
|
||||||
'0' -> CC_C_CLEAR
|
|
||||||
'1' -> CC_C_SET
|
|
||||||
'U' -> CC_C_UNDEF
|
|
||||||
'*' -> CC_C_RES
|
|
||||||
'A' -> CC_C_AND
|
|
||||||
'O' -> CC_C_OR
|
|
||||||
'?' -> CC_C_TST
|
|
||||||
else -> throw IllegalArgumentException("Syntax Error")
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
data class AllowedAdrMode(
|
data class AllowedAdrMode(
|
||||||
val op1: Set<AddressMode>? = null,
|
val op1: Set<AddressMode>? = null,
|
||||||
val op2: Set<AddressMode>? = null,
|
val op2: Set<AddressMode>? = null,
|
||||||
@ -237,27 +135,6 @@ data class IsaData(
|
|||||||
val modes: List<AllowedAdrMode> = listOf(AllowedAdrMode()),
|
val modes: List<AllowedAdrMode> = listOf(AllowedAdrMode()),
|
||||||
)
|
)
|
||||||
|
|
||||||
enum class ConditionCode(val cc: String, val testedCc: Int) {
|
|
||||||
TRUE("t", cc("-----")),
|
|
||||||
FALSE("f", cc("-----")),
|
|
||||||
HI("hi", cc("--?-?")),
|
|
||||||
LS("ls", cc("--?-?")),
|
|
||||||
CC("cc", cc("----?")),
|
|
||||||
HS("hs", cc("----?")), // same as CC
|
|
||||||
CS("cs", cc("----?")),
|
|
||||||
LO("lo", cc("----?")), // same as CS
|
|
||||||
NE("ne", cc("--?--")),
|
|
||||||
EQ("eq", cc("--?--")),
|
|
||||||
VC("vc", cc("---?-")),
|
|
||||||
VS("vs", cc("---?-")),
|
|
||||||
PL("pl", cc("-?---")),
|
|
||||||
MI("mi", cc("-?---")),
|
|
||||||
GE("ge", cc("-?-?-")),
|
|
||||||
LT("lt", cc("-?-?-")),
|
|
||||||
GT("gt", cc("-???-")),
|
|
||||||
LE("le", cc("-???-"))
|
|
||||||
}
|
|
||||||
|
|
||||||
object M68kIsa {
|
object M68kIsa {
|
||||||
|
|
||||||
private val NO_OPS_UNSIZED = listOf(AllowedAdrMode(size = OP_UNSIZED))
|
private val NO_OPS_UNSIZED = listOf(AllowedAdrMode(size = OP_UNSIZED))
|
||||||
|
@ -10,6 +10,7 @@ import com.intellij.psi.PsiFile
|
|||||||
import de.platon42.intellij.plugins.m68k.asm.AddressMode
|
import de.platon42.intellij.plugins.m68k.asm.AddressMode
|
||||||
import de.platon42.intellij.plugins.m68k.asm.IsaData
|
import de.platon42.intellij.plugins.m68k.asm.IsaData
|
||||||
import de.platon42.intellij.plugins.m68k.asm.M68kIsa
|
import de.platon42.intellij.plugins.m68k.asm.M68kIsa
|
||||||
|
import de.platon42.intellij.plugins.m68k.asm.getCcInfo
|
||||||
import de.platon42.intellij.plugins.m68k.psi.M68kAsmInstruction
|
import de.platon42.intellij.plugins.m68k.psi.M68kAsmInstruction
|
||||||
import de.platon42.intellij.plugins.m68k.psi.M68kAsmOp
|
import de.platon42.intellij.plugins.m68k.psi.M68kAsmOp
|
||||||
import de.platon42.intellij.plugins.m68k.psi.M68kOperandSize
|
import de.platon42.intellij.plugins.m68k.psi.M68kOperandSize
|
||||||
@ -36,24 +37,67 @@ 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 hasSameCcsForEverything = isaData.modes.map { it.affectedCc }.distinct().count() == 1
|
||||||
|
var alreadyShownCcsOnce = false
|
||||||
val mnemonicInfoRows = HtmlBuilder()
|
val mnemonicInfoRows = HtmlBuilder()
|
||||||
val headerCells = listOf(
|
mnemonicInfoRows.appendWithSeparators(HtmlChunk.tag("tr").child(HtmlChunk.hr().wrapWith(DocumentationMarkup.SECTION_CONTENT_CELL).attr("colspan", "3")),
|
||||||
HtmlChunk.text("Mnemonic").wrapWith(DocumentationMarkup.SECTION_HEADER_CELL),
|
isaData.modes.map { allowedAdrMode ->
|
||||||
HtmlChunk.text("Op1").wrapWith(DocumentationMarkup.SECTION_HEADER_CELL),
|
val addressModeInfoRows = HtmlBuilder()
|
||||||
HtmlChunk.text("Op2").wrapWith(DocumentationMarkup.SECTION_HEADER_CELL)
|
val headerCells = if (allowedAdrMode.op2 != null) {
|
||||||
)
|
listOf(
|
||||||
mnemonicInfoRows.append(HtmlChunk.tag("tr").children(headerCells))
|
HtmlChunk.text("Mnemonic / CCs").wrapWith(DocumentationMarkup.SECTION_HEADER_CELL),
|
||||||
isaData.modes.forEach { allowedAdrMode ->
|
HtmlChunk.text("Operand 1").wrapWith(DocumentationMarkup.SECTION_HEADER_CELL),
|
||||||
val mnemonics = findOpSizeDescriptions(allowedAdrMode.size)
|
HtmlChunk.text("Operand 2").wrapWith(DocumentationMarkup.SECTION_HEADER_CELL)
|
||||||
.map { HtmlChunk.text(isaData.mnemonic + it).wrapWith(HtmlChunk.div()) }
|
)
|
||||||
mnemonicInfoRows.append(
|
} else if (allowedAdrMode.op1 != null) {
|
||||||
HtmlChunk.tag("tr").children(
|
listOf(
|
||||||
DocumentationMarkup.SECTION_CONTENT_CELL.children(mnemonics),
|
HtmlChunk.text("Mnemonic / CCs").wrapWith(DocumentationMarkup.SECTION_HEADER_CELL),
|
||||||
DocumentationMarkup.SECTION_CONTENT_CELL.child(collectAddressModes(allowedAdrMode.op1)),
|
HtmlChunk.text("Operand").wrapWith(DocumentationMarkup.SECTION_HEADER_CELL)
|
||||||
DocumentationMarkup.SECTION_CONTENT_CELL.child(collectAddressModes(allowedAdrMode.op2))
|
)
|
||||||
)
|
} else {
|
||||||
)
|
listOf(HtmlChunk.text("Mnemonic / CCs").wrapWith(DocumentationMarkup.SECTION_HEADER_CELL))
|
||||||
}
|
}
|
||||||
|
addressModeInfoRows.append(HtmlChunk.tag("tr").children(headerCells))
|
||||||
|
|
||||||
|
val contentBuilder = HtmlBuilder()
|
||||||
|
val mnemonics = findOpSizeDescriptions(allowedAdrMode.size)
|
||||||
|
.map { HtmlChunk.text(isaData.mnemonic + it) }
|
||||||
|
contentBuilder.appendWithSeparators(HtmlChunk.br(), mnemonics)
|
||||||
|
contentBuilder.append(HtmlChunk.hr())
|
||||||
|
if (alreadyShownCcsOnce && hasSameCcsForEverything) {
|
||||||
|
contentBuilder.append(HtmlChunk.text("Condition Codes: Same as above"))
|
||||||
|
} else {
|
||||||
|
alreadyShownCcsOnce = true
|
||||||
|
contentBuilder.append(HtmlChunk.text("Condition Codes: "))
|
||||||
|
contentBuilder.append(HtmlChunk.br())
|
||||||
|
if (allowedAdrMode.affectedCc == 0) {
|
||||||
|
contentBuilder.append(HtmlChunk.text("Not affected."))
|
||||||
|
} else {
|
||||||
|
val ccMap = getCcInfo(allowedAdrMode.affectedCc)
|
||||||
|
val ccShortTableRows = HtmlBuilder()
|
||||||
|
ccShortTableRows.append(
|
||||||
|
HtmlChunk.tag("tr").children(ccMap.keys.map { HtmlChunk.text(it).wrapWith(DocumentationMarkup.SECTION_HEADER_CELL) })
|
||||||
|
)
|
||||||
|
ccShortTableRows.append(
|
||||||
|
HtmlChunk.tag("tr").children(ccMap.values.map {
|
||||||
|
HtmlChunk.text(it.first).wrapWith(DocumentationMarkup.SECTION_CONTENT_CELL)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
contentBuilder.append(ccShortTableRows.wrapWith(DocumentationMarkup.SECTIONS_TABLE))
|
||||||
|
contentBuilder.appendWithSeparators(HtmlChunk.br(), ccMap.map {
|
||||||
|
HtmlChunk.text(it.key + " - " + it.value.second)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val cellsPerRow = ArrayList<HtmlChunk>(3)
|
||||||
|
cellsPerRow.add(contentBuilder.toFragment())
|
||||||
|
|
||||||
|
if (allowedAdrMode.op1 != null) cellsPerRow.add(collectAddressModes(allowedAdrMode.op1))
|
||||||
|
if (allowedAdrMode.op1 != null) cellsPerRow.add(collectAddressModes(allowedAdrMode.op2))
|
||||||
|
|
||||||
|
addressModeInfoRows.append(HtmlChunk.tag("tr").children(cellsPerRow.map { it.wrapWith(DocumentationMarkup.SECTION_CONTENT_CELL) }))
|
||||||
|
addressModeInfoRows.toFragment()
|
||||||
|
})
|
||||||
|
|
||||||
val contentBuilder = HtmlBuilder()
|
val contentBuilder = HtmlBuilder()
|
||||||
contentBuilder.append(mnemonicInfoRows.wrapWith(DocumentationMarkup.SECTIONS_TABLE))
|
contentBuilder.append(mnemonicInfoRows.wrapWith(DocumentationMarkup.SECTIONS_TABLE))
|
||||||
|
@ -52,7 +52,7 @@ class M68kRegisterFlowDocumentationProvider : AbstractDocumentationProvider() {
|
|||||||
|
|
||||||
val firstOp = asmInstruction.addressingModeList[0] == addressingMode
|
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 cursorRwm = modifyRwmWithOpsize((adrMode.modInfo ushr if (firstOp) RWM_OP1_SHIFT else RWM_OP2_SHIFT) and RWM_OP_MASK, opSize)
|
||||||
val backtrace: MutableList<HtmlChunk> = ArrayList()
|
val backtrace = ArrayList<HtmlChunk>()
|
||||||
val missingBits = if (cursorRwm and RWM_SET_L != 0) {
|
val missingBits = if (cursorRwm and RWM_SET_L != 0) {
|
||||||
if (totalRwm and RWM_SET_L == RWM_SET_L) {
|
if (totalRwm and RWM_SET_L == RWM_SET_L) {
|
||||||
backtrace.add(
|
backtrace.add(
|
||||||
@ -108,10 +108,10 @@ class M68kRegisterFlowDocumentationProvider : AbstractDocumentationProvider() {
|
|||||||
startingStatement: M68kStatement,
|
startingStatement: M68kStatement,
|
||||||
linesLimit: Int,
|
linesLimit: Int,
|
||||||
direction: (statement: M68kStatement) -> M68kStatement?
|
direction: (statement: M68kStatement) -> M68kStatement?
|
||||||
): MutableList<HtmlChunk> {
|
): List<HtmlChunk> {
|
||||||
var missingBits = rwmBits
|
var missingBits = rwmBits
|
||||||
var currStatement = startingStatement
|
var currStatement = startingStatement
|
||||||
val statementLines: MutableList<HtmlChunk> = ArrayList()
|
val statementLines = ArrayList<HtmlChunk>()
|
||||||
val rn = register.regname
|
val rn = register.regname
|
||||||
var addAbrevDots = false
|
var addAbrevDots = false
|
||||||
var lines = 0
|
var lines = 0
|
||||||
|
@ -11,7 +11,7 @@ import de.platon42.intellij.plugins.m68k.stubs.M68kSymbolDefinitionStubIndex
|
|||||||
object M68kLookupUtil {
|
object M68kLookupUtil {
|
||||||
|
|
||||||
fun findAllGlobalLabels(project: Project): List<M68kGlobalLabel> {
|
fun findAllGlobalLabels(project: Project): List<M68kGlobalLabel> {
|
||||||
val results: MutableList<M68kGlobalLabel> = ArrayList()
|
val results = ArrayList<M68kGlobalLabel>()
|
||||||
StubIndex.getInstance().processAllKeys(M68kGlobalLabelStubIndex.KEY, project)
|
StubIndex.getInstance().processAllKeys(M68kGlobalLabelStubIndex.KEY, project)
|
||||||
{
|
{
|
||||||
results.addAll(StubIndex.getElements(M68kGlobalLabelStubIndex.KEY, it, project, GlobalSearchScope.allScope(project), M68kGlobalLabel::class.java))
|
results.addAll(StubIndex.getElements(M68kGlobalLabelStubIndex.KEY, it, project, GlobalSearchScope.allScope(project), M68kGlobalLabel::class.java))
|
||||||
@ -21,7 +21,7 @@ object M68kLookupUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun findAllGlobalLabels(file: M68kFile): List<M68kGlobalLabel> {
|
fun findAllGlobalLabels(file: M68kFile): List<M68kGlobalLabel> {
|
||||||
val results: MutableList<M68kGlobalLabel> = ArrayList()
|
val results = ArrayList<M68kGlobalLabel>()
|
||||||
StubIndex.getInstance().processAllKeys(
|
StubIndex.getInstance().processAllKeys(
|
||||||
M68kGlobalLabelStubIndex.KEY,
|
M68kGlobalLabelStubIndex.KEY,
|
||||||
{
|
{
|
||||||
@ -44,7 +44,7 @@ object M68kLookupUtil {
|
|||||||
|
|
||||||
fun findAllLocalLabels(globalLabel: M68kGlobalLabel): List<M68kLocalLabel> {
|
fun findAllLocalLabels(globalLabel: M68kGlobalLabel): List<M68kLocalLabel> {
|
||||||
val statement = PsiTreeUtil.getStubOrPsiParentOfType(globalLabel, M68kStatement::class.java)!!
|
val statement = PsiTreeUtil.getStubOrPsiParentOfType(globalLabel, M68kStatement::class.java)!!
|
||||||
val results: MutableList<M68kLocalLabel> = ArrayList()
|
val results = ArrayList<M68kLocalLabel>()
|
||||||
var currentStatement = PsiTreeUtil.getNextSiblingOfType(statement, M68kStatement::class.java)
|
var currentStatement = PsiTreeUtil.getNextSiblingOfType(statement, M68kStatement::class.java)
|
||||||
while (currentStatement != null) {
|
while (currentStatement != null) {
|
||||||
val child = currentStatement.firstChild
|
val child = currentStatement.firstChild
|
||||||
@ -56,7 +56,7 @@ object M68kLookupUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun findAllSymbolDefinitions(project: Project): List<M68kSymbolDefinition> {
|
fun findAllSymbolDefinitions(project: Project): List<M68kSymbolDefinition> {
|
||||||
val results: MutableList<M68kSymbolDefinition> = ArrayList()
|
val results = ArrayList<M68kSymbolDefinition>()
|
||||||
StubIndex.getInstance().processAllKeys(M68kSymbolDefinitionStubIndex.KEY, project)
|
StubIndex.getInstance().processAllKeys(M68kSymbolDefinitionStubIndex.KEY, project)
|
||||||
{
|
{
|
||||||
results.addAll(
|
results.addAll(
|
||||||
@ -74,7 +74,7 @@ object M68kLookupUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun findAllSymbolDefinitions(file: M68kFile): List<M68kSymbolDefinition> {
|
fun findAllSymbolDefinitions(file: M68kFile): List<M68kSymbolDefinition> {
|
||||||
val results: MutableList<M68kSymbolDefinition> = ArrayList()
|
val results = ArrayList<M68kSymbolDefinition>()
|
||||||
StubIndex.getInstance().processAllKeys(
|
StubIndex.getInstance().processAllKeys(
|
||||||
M68kSymbolDefinitionStubIndex.KEY,
|
M68kSymbolDefinitionStubIndex.KEY,
|
||||||
{
|
{
|
||||||
@ -97,7 +97,7 @@ object M68kLookupUtil {
|
|||||||
|
|
||||||
|
|
||||||
fun findAllMacroDefinitions(project: Project): List<M68kMacroDefinition> {
|
fun findAllMacroDefinitions(project: Project): List<M68kMacroDefinition> {
|
||||||
val results: MutableList<M68kMacroDefinition> = ArrayList()
|
val results = ArrayList<M68kMacroDefinition>()
|
||||||
StubIndex.getInstance().processAllKeys(M68kMacroDefinitionStubIndex.KEY, project)
|
StubIndex.getInstance().processAllKeys(M68kMacroDefinitionStubIndex.KEY, project)
|
||||||
{
|
{
|
||||||
results.addAll(
|
results.addAll(
|
||||||
@ -115,7 +115,7 @@ object M68kLookupUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun findAllMacroDefinitions(file: M68kFile): List<M68kMacroDefinition> {
|
fun findAllMacroDefinitions(file: M68kFile): List<M68kMacroDefinition> {
|
||||||
val results: MutableList<M68kMacroDefinition> = ArrayList()
|
val results = ArrayList<M68kMacroDefinition>()
|
||||||
StubIndex.getInstance().processAllKeys(
|
StubIndex.getInstance().processAllKeys(
|
||||||
M68kMacroDefinitionStubIndex.KEY,
|
M68kMacroDefinitionStubIndex.KEY,
|
||||||
{
|
{
|
||||||
@ -135,6 +135,4 @@ object M68kLookupUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun findAllMacroDefinitionNames(project: Project): Collection<String> = StubIndex.getInstance().getAllKeys(M68kMacroDefinitionStubIndex.KEY, project)
|
fun findAllMacroDefinitionNames(project: Project): Collection<String> = StubIndex.getInstance().getAllKeys(M68kMacroDefinitionStubIndex.KEY, project)
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -117,7 +117,7 @@ object M68kPsiImplUtil {
|
|||||||
// RegisterListAddressingMode
|
// RegisterListAddressingMode
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getRegisters(element: M68kRegisterListAddressingMode): Set<Register> {
|
fun getRegisters(element: M68kRegisterListAddressingMode): Set<Register> {
|
||||||
val registers: MutableSet<Register> = HashSet()
|
val registers = HashSet<Register>()
|
||||||
element.registerList.forEach { registers.add(Register.getRegFromName(it.text)) }
|
element.registerList.forEach { registers.add(Register.getRegFromName(it.text)) }
|
||||||
element.registerRangeList.forEach {
|
element.registerRangeList.forEach {
|
||||||
var startReg = Register.getRegFromName(it.startRegister.text)
|
var startReg = Register.getRegFromName(it.startRegister.text)
|
||||||
|
@ -19,7 +19,7 @@ class M68kChooseByNameContributor : ChooseByNameContributorEx {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// override fun getItemsByName(name: String, pattern: String, project: Project, includeNonProjectItems: Boolean): Array<NavigationItem> {
|
// override fun getItemsByName(name: String, pattern: String, project: Project, includeNonProjectItems: Boolean): Array<NavigationItem> {
|
||||||
// val result: MutableList<NavigationItem> = ArrayList()
|
// val result = ArrayList<NavigationItem>()
|
||||||
// processElementsWithName(name, result::add, FindSymbolParameters.wrap(pattern, project, includeNonProjectItems))
|
// processElementsWithName(name, result::add, FindSymbolParameters.wrap(pattern, project, includeNonProjectItems))
|
||||||
// return result.toTypedArray()
|
// return result.toTypedArray()
|
||||||
// }
|
// }
|
||||||
|
@ -28,7 +28,7 @@ class M68kGlobalLabelSymbolReference(element: M68kSymbolReference) :
|
|||||||
val refName = ref.element.symbolName
|
val refName = ref.element.symbolName
|
||||||
val project = ref.element.project
|
val project = ref.element.project
|
||||||
|
|
||||||
val targets: MutableList<M68kNamedElement> = SmartList()
|
val targets = SmartList<M68kNamedElement>()
|
||||||
StubIndex.getInstance()
|
StubIndex.getInstance()
|
||||||
.processElements(M68kGlobalLabelStubIndex.KEY, refName, project, GlobalSearchScope.allScope(project), M68kGlobalLabel::class.java)
|
.processElements(M68kGlobalLabelStubIndex.KEY, refName, project, GlobalSearchScope.allScope(project), M68kGlobalLabel::class.java)
|
||||||
{
|
{
|
||||||
|
@ -21,7 +21,7 @@ class M68kLocalLabelReference(element: M68kSymbolReference) : PsiPolyVariantRefe
|
|||||||
|
|
||||||
fun findLocalLabels(element: M68kSymbolReference, predicate: (M68kLocalLabel) -> Boolean): List<M68kLocalLabel> {
|
fun findLocalLabels(element: M68kSymbolReference, predicate: (M68kLocalLabel) -> Boolean): List<M68kLocalLabel> {
|
||||||
val statement = PsiTreeUtil.getStubOrPsiParentOfType(element, M68kStatement::class.java)!!
|
val statement = PsiTreeUtil.getStubOrPsiParentOfType(element, M68kStatement::class.java)!!
|
||||||
val results: MutableList<M68kLocalLabel> = SmartList()
|
val results = SmartList<M68kLocalLabel>()
|
||||||
// go backward
|
// go backward
|
||||||
var currentStatement = PsiTreeUtil.getPrevSiblingOfType(statement, M68kStatement::class.java)
|
var currentStatement = PsiTreeUtil.getPrevSiblingOfType(statement, M68kStatement::class.java)
|
||||||
while (currentStatement != null) {
|
while (currentStatement != null) {
|
||||||
|
@ -25,7 +25,7 @@ class M68kMacroReference(element: M68kMacroCall) :
|
|||||||
val macroName = ref.element.macroName
|
val macroName = ref.element.macroName
|
||||||
val project = ref.element.project
|
val project = ref.element.project
|
||||||
|
|
||||||
val targets: MutableList<M68kMacroDefinition> = SmartList()
|
val targets = SmartList<M68kMacroDefinition>()
|
||||||
StubIndex.getInstance()
|
StubIndex.getInstance()
|
||||||
.processElements(M68kMacroDefinitionStubIndex.KEY, macroName, project, GlobalSearchScope.allScope(project), M68kMacroDefinition::class.java)
|
.processElements(M68kMacroDefinitionStubIndex.KEY, macroName, project, GlobalSearchScope.allScope(project), M68kMacroDefinition::class.java)
|
||||||
{
|
{
|
||||||
|
@ -19,7 +19,47 @@ internal class M68kInstructionDocumentationProviderTest : AbstractDocumentationP
|
|||||||
)
|
)
|
||||||
assertThat(generateDocumentation(myFixture)).isEqualToIgnoringWhitespace(
|
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>
|
<div class="definition">
|
||||||
|
<pre><b>Move Quick</b></pre>
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<table class="sections">
|
||||||
|
<tr>
|
||||||
|
<td class="section" valign="top">Mnemonic / CCs</td>
|
||||||
|
<td class="section" valign="top">Operand 1</td>
|
||||||
|
<td class="section" valign="top">Operand 2</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top">moveq.l
|
||||||
|
<hr/>
|
||||||
|
Condition Codes: <br/>
|
||||||
|
<table class="sections">
|
||||||
|
<tr>
|
||||||
|
<td class="section" valign="top">X</td>
|
||||||
|
<td class="section" valign="top">N</td>
|
||||||
|
<td class="section" valign="top">Z</td>
|
||||||
|
<td class="section" valign="top">V</td>
|
||||||
|
<td class="section" valign="top">C</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top">-</td>
|
||||||
|
<td valign="top">*</td>
|
||||||
|
<td valign="top">*</td>
|
||||||
|
<td valign="top">0</td>
|
||||||
|
<td valign="top">0</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
X - Not affected<br/>N - From result (usually if negative)<br/>Z - From result (usually if zero)<br/>V - Always cleared<br/>C - Always cleared
|
||||||
|
</td>
|
||||||
|
<td valign="top">
|
||||||
|
<div>#<xxx></div>
|
||||||
|
</td>
|
||||||
|
<td valign="top">
|
||||||
|
<div>Dn</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -39,15 +79,13 @@ internal class M68kInstructionDocumentationProviderTest : AbstractDocumentationP
|
|||||||
<div class="content">
|
<div class="content">
|
||||||
<table class="sections">
|
<table class="sections">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="section" valign="top">Mnemonic</td>
|
<td class="section" valign="top">Mnemonic / CCs</td>
|
||||||
<td class="section" valign="top">Op1</td>
|
<td class="section" valign="top">Operand</td>
|
||||||
<td class="section" valign="top">Op2</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td valign="top">
|
<td valign="top">bra.s<br/>bra.b<br/>bra.w
|
||||||
<div>bra.s</div>
|
<hr/>
|
||||||
<div>bra.b</div>
|
Condition Codes: <br/>Not affected.
|
||||||
<div>bra.w</div>
|
|
||||||
</td>
|
</td>
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
<div>(xxx).w|l</div>
|
<div>(xxx).w|l</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user