Added new trace infrastructure
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
import ch.qos.logback.classic.LoggerContext
|
||||
import com.thequux.mcpdp.core.CPU
|
||||
import com.thequux.mcpdp.debug.LoggingCollector
|
||||
import com.thequux.mcpdp.debug.NullTracer
|
||||
import com.thequux.mcpdp.debug.Tracer
|
||||
import com.thequux.mcpdp.loadAbs
|
||||
import com.thequux.mcpdp.peripheral.DL11
|
||||
import com.thequux.mcpdp.peripheral.MemBus
|
||||
@@ -10,10 +13,14 @@ fun main(args: Array<String>) {
|
||||
|
||||
val tb = org.jline.terminal.TerminalBuilder.terminal()
|
||||
var mbus = MemBus(32768)
|
||||
var cpu = CPU(mbus)
|
||||
val tracer = Tracer()
|
||||
val loggingCollector = LoggingCollector()
|
||||
tracer.addCollector(loggingCollector)
|
||||
var cpu = CPU(mbus, if (CPU.debugMode) tracer else NullTracer())
|
||||
val console = DL11(mbus.unibus, tb.input(), tb.output()).apply { mount(mbus.unibus) }
|
||||
try {
|
||||
|
||||
|
||||
tb.enterRawMode()
|
||||
console.start()
|
||||
|
||||
@@ -21,7 +28,7 @@ fun main(args: Array<String>) {
|
||||
cpu.runState = CPU.RunState.RUNNING
|
||||
cpu.pc = 0x80u
|
||||
val start = System.nanoTime()
|
||||
val ninsn = cpu.run(200000000)
|
||||
val ninsn = cpu.run(600000000)
|
||||
val end = System.nanoTime()
|
||||
|
||||
System.err.println("Halted at 0${cpu.pc.toString(8)}")
|
||||
|
@@ -2,7 +2,9 @@ package com.thequux.mcpdp.core
|
||||
|
||||
import com.thequux.mcpdp.ext.bit.*
|
||||
import com.thequux.mcpdp.peripheral.MemBus
|
||||
import com.thequux.mcpdp.util.Disassembler
|
||||
import com.thequux.mcpdp.debug.Disassembler
|
||||
import com.thequux.mcpdp.debug.ITracer
|
||||
import com.thequux.mcpdp.debug.NullTracer
|
||||
import com.thequux.mcpdp.util.ProgrammerError
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
@@ -15,9 +17,14 @@ import java.lang.StringBuilder
|
||||
/// Exxx: ROM
|
||||
/// xxxx: rest
|
||||
@OptIn(ExperimentalUnsignedTypes::class)
|
||||
class CPU(val mbus: MemBus) {
|
||||
class CPU(val mbus: MemBus, val tracer: ITracer = NullTracer()) {
|
||||
|
||||
companion object {
|
||||
val PADDR_REG_BIT: Int = 23
|
||||
val PADDR_ISPACE_BIT: Int = 22
|
||||
val PADDR_DST_BIT: Int = 24
|
||||
val PADDR_ARG_BIT: Int = 25
|
||||
|
||||
val debugMode = System.getProperty("jdp11.itrace").toBoolean()
|
||||
|
||||
private val insnTable: Array<CPU.(Int) -> Unit> = Array(256) {{throw InvalidOpcodeException()}}
|
||||
@@ -536,9 +543,9 @@ class CPU(val mbus: MemBus) {
|
||||
for (i in 0x90..0x9F) insnTable[i] = { opcode -> // MOVB
|
||||
val src = opc_srcb(opcode)
|
||||
val dst = opc_dstb(opcode)
|
||||
var dstv = op_loadb(src)
|
||||
val dstv = op_loadb(src)
|
||||
|
||||
var dstw = if (is_paddr_reg(dst)) {
|
||||
if (is_paddr_reg(dst)) {
|
||||
op_storw(dst, dstv.toUShort() sex 8)
|
||||
dstv.toUShort() sex 8
|
||||
} else {
|
||||
@@ -595,14 +602,13 @@ class CPU(val mbus: MemBus) {
|
||||
N = res < 0
|
||||
Z = res == 0
|
||||
V = ((srcv bit 31) xor (dstv bit 15)) and ((srcv bit 15) == (res bit 31))
|
||||
C = (dst.toInt() + src.inv().inc().toInt()) >= 0x1_0000
|
||||
C = (dst.toInt() + src.inv().inc().toInt()) < 0x1_0000
|
||||
} // SUB
|
||||
// insnTable[0x0E] = // TODO: check this
|
||||
// insnTable[0x0F] = // TODO: check this
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private var control_reg: UShort = 0u
|
||||
val logger: Logger = LoggerFactory.getLogger(this.javaClass)
|
||||
private val flagStr: String
|
||||
@@ -618,7 +624,6 @@ class CPU(val mbus: MemBus) {
|
||||
private val general_registers = Array<UShortArray>(2) { UShortArray(6) }
|
||||
private val shadow_r6 = UShortArray(4) //
|
||||
val core = PagingUnit(mbus)
|
||||
private val dasm = Disassembler(core)
|
||||
|
||||
var runState: RunState = RunState.HALTED
|
||||
var psw: UShort
|
||||
@@ -662,7 +667,7 @@ class CPU(val mbus: MemBus) {
|
||||
set(value) {
|
||||
registers[7] = value
|
||||
}
|
||||
private var sp: UShort
|
||||
var sp: UShort
|
||||
get() = registers[6]
|
||||
set(value) {
|
||||
registers[6] = value
|
||||
@@ -708,8 +713,6 @@ class CPU(val mbus: MemBus) {
|
||||
private var Z: Boolean = false
|
||||
private var V: Boolean = false
|
||||
private var T: Boolean = false
|
||||
private val PADDR_REG_BIT: Int = 23
|
||||
private val PADDR_ISPACE_BIT: Int = 22
|
||||
|
||||
init {
|
||||
val regs = Registers()
|
||||
@@ -724,21 +727,23 @@ class CPU(val mbus: MemBus) {
|
||||
|
||||
private fun is_paddr_reg(addr: UInt): Boolean = addr bit PADDR_REG_BIT
|
||||
private fun is_paddr_ispace(addr: UInt): Boolean = addr bit PADDR_ISPACE_BIT
|
||||
private fun op_resolve(operand: Int, byte_mode: Boolean = false): UInt {
|
||||
private fun op_resolve(operand: Int, src: Boolean, byte_mode: Boolean = false): UInt {
|
||||
val mode = operand shr 3
|
||||
val reg = operand and 0x7
|
||||
val is_pc = reg == 7
|
||||
val increment = if (byte_mode && !is_pc) 1U else 2U
|
||||
return 0x80_FFFFu and when (mode and 0x7) {
|
||||
val decoded = 0x80_FFFFu and when (mode and 0x7) {
|
||||
0 -> reg.toUInt() bis PADDR_REG_BIT
|
||||
1 -> registers[reg].toUInt()
|
||||
2 -> {
|
||||
val addr = registers[reg]
|
||||
if (reg == 7) tracer.noteArgument(op_loadw(addr.toUInt() bis PADDR_ISPACE_BIT, false))
|
||||
registers[reg] = (addr + increment).toUShort()
|
||||
addr.toUInt().bit(PADDR_ISPACE_BIT, is_pc)
|
||||
}
|
||||
3 -> {
|
||||
val addr = registers[reg]
|
||||
if (reg == 7) tracer.noteArgument(op_loadw(addr.toUInt() bis PADDR_ISPACE_BIT, false))
|
||||
registers[reg] = (addr + 2U).toUShort()
|
||||
core.getw(addr, dspace = !is_pc).toUInt()
|
||||
}
|
||||
@@ -752,16 +757,19 @@ class CPU(val mbus: MemBus) {
|
||||
}
|
||||
6 -> {
|
||||
val idx = core.getw(pc, dspace = false)
|
||||
tracer.noteArgument(idx)
|
||||
pc = (pc + 2u).toUShort()
|
||||
(idx + registers[reg]) and 0xFFFFu
|
||||
}
|
||||
7 -> {
|
||||
val idx = core.getw(pc, dspace = false)
|
||||
tracer.noteArgument(idx)
|
||||
pc = (pc+2u).toUShort()
|
||||
core.getw((idx+registers[reg]).toUShort()).toUInt()
|
||||
}
|
||||
else -> throw InvalidOpcodeException() // unreachable
|
||||
}
|
||||
return decoded.bit(PADDR_DST_BIT, !src) bis PADDR_ARG_BIT
|
||||
}
|
||||
|
||||
private fun op_storb(spec: UInt, value: UByte) {
|
||||
@@ -776,11 +784,13 @@ class CPU(val mbus: MemBus) {
|
||||
|
||||
private fun op_loadb(spec: UInt): UByte {
|
||||
val addr = (spec and 0xFFFFu).toUShort()
|
||||
return if (is_paddr_reg(spec)) {
|
||||
val value = if (is_paddr_reg(spec)) {
|
||||
(registers[addr.toInt()] and 0xFFu).toUByte()
|
||||
} else {
|
||||
core.getb(addr)
|
||||
}
|
||||
tracer.noteReference(spec, value.toUShort())
|
||||
return value
|
||||
}
|
||||
|
||||
private fun op_storw(spec: UInt, value: UShort, dspace: Boolean = true) {
|
||||
@@ -795,17 +805,20 @@ class CPU(val mbus: MemBus) {
|
||||
|
||||
private fun op_loadw(spec: UInt, dspace: Boolean=true): UShort {
|
||||
val addr = (spec and 0xFFFFu).toUShort()
|
||||
return if (is_paddr_reg(spec)) {
|
||||
val value = if (is_paddr_reg(spec)) {
|
||||
registers[addr.toInt()]
|
||||
} else {
|
||||
core.getw(addr, dspace)
|
||||
}
|
||||
if (spec bit PADDR_ARG_BIT)
|
||||
tracer.noteReference(spec, value)
|
||||
return value
|
||||
}
|
||||
|
||||
private fun opc_dst(opcode: Int): UInt = op_resolve(opcode and 0x3F)
|
||||
private fun opc_dstb(opcode: Int): UInt = op_resolve(opcode and 0x3F, byte_mode = true)
|
||||
private fun opc_src(opcode: Int): UInt = op_resolve(opcode shr 6 and 0x3F)
|
||||
private fun opc_srcb(opcode: Int): UInt = op_resolve(opcode shr 6 and 0x3F, byte_mode = true)
|
||||
private fun opc_dst(opcode: Int): UInt = op_resolve(opcode and 0x3F, false)
|
||||
private fun opc_dstb(opcode: Int): UInt = op_resolve(opcode and 0x3F, false, byte_mode = true)
|
||||
private fun opc_src(opcode: Int): UInt = op_resolve(opcode shr 6 and 0x3F, true)
|
||||
private fun opc_srcb(opcode: Int): UInt = op_resolve(opcode shr 6 and 0x3F, true, byte_mode = true)
|
||||
|
||||
private fun stack_pop(): UShort = core.getw(sp).also { sp = (sp + 2u).toUShort() }
|
||||
private fun stack_push(value: UShort) {
|
||||
@@ -821,12 +834,15 @@ class CPU(val mbus: MemBus) {
|
||||
|
||||
/// Internal step; evaluates one opcode, but does not handle errors, interrupts, or updating system registers
|
||||
fun step_int() {
|
||||
if (debugMode) {
|
||||
logger.debug("${pc.toString(8).padStart(6, '0')}: ${dasm.dasm_at(pc)}")
|
||||
try {
|
||||
tracer.noteBegin(this)
|
||||
val opcode = core.getw(pc).toInt()
|
||||
tracer.noteOpcode(opcode.toUShort())
|
||||
pc = (pc + 2u).toUShort()
|
||||
this.(insnTable[opcode shr 8])(opcode)
|
||||
} finally {
|
||||
tracer.noteEnd()
|
||||
}
|
||||
val opcode = core.getw(pc).toInt()
|
||||
pc = (pc + 2u).toUShort()
|
||||
this.(insnTable[opcode shr 8])(opcode)
|
||||
}
|
||||
|
||||
private fun debugFlags() {
|
||||
@@ -907,7 +923,7 @@ class CPU(val mbus: MemBus) {
|
||||
}
|
||||
|
||||
fun trap(vector: UShort) {
|
||||
logger.info("Trap to {}", vector.toString(8))
|
||||
// logger.info("Trap to {}", vector.toString(8))
|
||||
val old_psw = psw
|
||||
// update PSW first so that this gets pushed to the
|
||||
psw = core.getw((vector + 2u).toUShort())
|
||||
|
@@ -1,37 +1,28 @@
|
||||
package com.thequux.mcpdp.util
|
||||
package com.thequux.mcpdp.debug
|
||||
|
||||
import com.thequux.mcpdp.core.CPU
|
||||
import com.thequux.mcpdp.core.InvalidOpcodeException
|
||||
import com.thequux.mcpdp.core.VAddressSpace
|
||||
import com.thequux.mcpdp.ext.bit.*
|
||||
import com.thequux.mcpdp.ext.bit.bit
|
||||
|
||||
object DebugTools {
|
||||
@OptIn(ExperimentalUnsignedTypes::class)
|
||||
class Disassembler {
|
||||
|
||||
|
||||
}
|
||||
|
||||
class NullDisassembler() {
|
||||
fun dasm_at(loc: UShort): String = ""
|
||||
}
|
||||
class Disassembler(val core: VAddressSpace) {
|
||||
|
||||
var vpc: UShort = 0u
|
||||
var istream: UShortArray = UShortArray(0)
|
||||
var vpc: Int = 0
|
||||
var opc: UShort = 0u
|
||||
var opcode: Int = 0
|
||||
|
||||
private fun fmt(opcode: String, vararg args: String): String {
|
||||
val res = StringBuilder()
|
||||
|
||||
var tpc = opc
|
||||
var bytes = 0
|
||||
while (tpc != vpc) {
|
||||
for (word in istream) {
|
||||
if (bytes != 0)
|
||||
res.append('.')
|
||||
bytes += 2
|
||||
res.append(core.getw(tpc, dspace = false).toString(16).padStart(4, '0'))
|
||||
res.append('.')
|
||||
tpc = tpc.inc().inc()
|
||||
res.append(word.toString(8).padStart(6, '0'))
|
||||
}
|
||||
while (bytes < 6) {
|
||||
res.append("----.")
|
||||
res.append(".------")
|
||||
bytes += 2
|
||||
}
|
||||
res.append('\t')
|
||||
@@ -56,11 +47,7 @@ class Disassembler(val core: VAddressSpace) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun getw(): UShort {
|
||||
val ret = core.getw(vpc, dspace = false)
|
||||
vpc = vpc.inc().inc()
|
||||
return ret
|
||||
}
|
||||
private fun getw(): UShort = istream[vpc++]
|
||||
private fun arg_at(offset: Int): String {
|
||||
val rv = opcode shr offset and 0x3F
|
||||
val reg = rv and 0x7
|
||||
@@ -72,7 +59,7 @@ class Disassembler(val core: VAddressSpace) {
|
||||
2 -> if (reg == 7) "$ind#${getw().toString(8)}" else "$ind($rn)+"
|
||||
4 -> "$ind-($rn)"
|
||||
6 -> if (reg == 7) {
|
||||
ind + (getw() + vpc).toShort().toString(8)
|
||||
ind + (getw() + opc + (vpc * 2).toUInt()).toShort().toString(8)
|
||||
} else {
|
||||
"$ind${getw().toString(8)}($rn)"
|
||||
}
|
||||
@@ -86,22 +73,22 @@ class Disassembler(val core: VAddressSpace) {
|
||||
|
||||
private fun br_rel(opc: String): String {
|
||||
val rel = (opcode and 0xFF) - (opcode and 0x80 shl 1)
|
||||
val dst = (vpc.toInt() + rel.shl(1)).toUShort()
|
||||
val dst = (this.opc.toInt() + (vpc * 2) + rel.shl(1)).toUShort()
|
||||
return fmt(opc, dst.toString(8))
|
||||
}
|
||||
|
||||
private fun rel6(): String {
|
||||
val rel = (opcode and 0x3F) - (opcode and 0x20 shl 1)
|
||||
val dst = vpc.toInt() + rel
|
||||
val dst = opc.toInt() + vpc*2 + rel
|
||||
return dst.toUShort().toString(8)
|
||||
}
|
||||
|
||||
fun dasm_at(loc: UShort): String {
|
||||
vpc = loc
|
||||
fun dasm_at(loc: UShort, istream: UShortArray): String {
|
||||
opc = loc
|
||||
this.istream = istream
|
||||
opcode = istream[0].toInt()
|
||||
|
||||
opcode = core.getw(vpc, dspace = false).toInt()
|
||||
vpc = (vpc + 2u).toUShort()
|
||||
vpc = 1
|
||||
try {
|
||||
return when (opcode and 0xF000) {
|
||||
0x0, 0x8000 -> when (opcode and 0xFF00) {
|
||||
@@ -225,7 +212,8 @@ class Disassembler(val core: VAddressSpace) {
|
||||
2 -> {
|
||||
throw InvalidOpcodeException()
|
||||
} // MTPD // TODO
|
||||
else -> throw InvalidOpcodeException()// Reserved
|
||||
else -> throw InvalidOpcodeException()
|
||||
// Reserved
|
||||
}
|
||||
|
||||
else -> throw InvalidOpcodeException()
|
15
src/main/kotlin/com/thequux/mcpdp/debug/LoggingCollector.kt
Normal file
15
src/main/kotlin/com/thequux/mcpdp/debug/LoggingCollector.kt
Normal file
@@ -0,0 +1,15 @@
|
||||
package com.thequux.mcpdp.debug
|
||||
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
class LoggingCollector(val logger: Logger = LoggerFactory.getLogger("ITrace")): Collector {
|
||||
|
||||
init {
|
||||
logger.debug("PC SP PSW |SRC DST |ISTREAM INSN")
|
||||
}
|
||||
private val disassembler = Disassembler()
|
||||
override fun invoke(record: TraceRecord) {
|
||||
logger.debug(record.report(disassembler))
|
||||
}
|
||||
}
|
36
src/main/kotlin/com/thequux/mcpdp/debug/TraceRecord.kt
Normal file
36
src/main/kotlin/com/thequux/mcpdp/debug/TraceRecord.kt
Normal file
@@ -0,0 +1,36 @@
|
||||
@file:OptIn(ExperimentalUnsignedTypes::class)
|
||||
|
||||
package com.thequux.mcpdp.debug
|
||||
|
||||
import com.thequux.mcpdp.ext.bit.toOctal
|
||||
|
||||
data class TraceRecord(
|
||||
val pc: UShort,
|
||||
val sp: UShort,
|
||||
val psw: UShort,
|
||||
val opc: UShort,
|
||||
val args: UShortArray,
|
||||
val src: Pair<UInt, UShort>? = null,
|
||||
val dst: Pair<UInt, UShort>? = null,
|
||||
) {
|
||||
|
||||
@OptIn(ExperimentalUnsignedTypes::class)
|
||||
companion object {
|
||||
fun default(): TraceRecord = TraceRecord(0u, 0u, 0u, 0u, UShortArray(0))
|
||||
}
|
||||
|
||||
private fun formatRef(ref: Pair<UInt, UShort>?): String {
|
||||
return if (ref == null) {
|
||||
" ".repeat(15)
|
||||
} else {
|
||||
"${ref.second.toOctal()}@${ref.first.toOctal(8)}"
|
||||
}
|
||||
}
|
||||
|
||||
fun report(disassembler: Disassembler = Disassembler()): String {
|
||||
return "${pc.toOctal()} ${sp.toOctal()} ${psw.toOctal()}|" +
|
||||
"${formatRef(src)} ${formatRef(dst)}|" +
|
||||
disassembler.dasm_at(pc, args)
|
||||
}
|
||||
}
|
||||
|
101
src/main/kotlin/com/thequux/mcpdp/debug/Tracer.kt
Normal file
101
src/main/kotlin/com/thequux/mcpdp/debug/Tracer.kt
Normal file
@@ -0,0 +1,101 @@
|
||||
@file:OptIn(ExperimentalUnsignedTypes::class)
|
||||
|
||||
package com.thequux.mcpdp.debug
|
||||
|
||||
import ch.qos.logback.classic.LoggerContext
|
||||
import com.thequux.mcpdp.core.CPU
|
||||
import com.thequux.mcpdp.ext.bit.bit
|
||||
import com.thequux.mcpdp.ext.bit.toOctal
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.util.Arrays
|
||||
|
||||
typealias Collector = (TraceRecord) -> Unit
|
||||
|
||||
interface ITracer {
|
||||
fun noteBegin(cpu: CPU)
|
||||
fun noteOpcode(opcode: UShort)
|
||||
fun noteArgument(arg: UShort)
|
||||
fun noteEnd()
|
||||
abstract fun noteReference(spec: UInt, value: UShort)
|
||||
}
|
||||
|
||||
/// An implementation of Tracer that does nothing, without need for a null check.
|
||||
/// This should get JITed out, so should have no runtime overhead
|
||||
class NullTracer: ITracer {
|
||||
override fun noteBegin(cpu: CPU) {}
|
||||
|
||||
override fun noteOpcode(opcode: UShort) {}
|
||||
|
||||
override fun noteArgument(arg: UShort) {}
|
||||
|
||||
override fun noteReference(spec: UInt, value: UShort) {}
|
||||
|
||||
override fun noteEnd() {}
|
||||
}
|
||||
class Tracer : ITracer {
|
||||
private val logger = LoggerFactory.getLogger(this.javaClass)
|
||||
private var src: Pair<UInt, UShort>? = null
|
||||
private var dst: Pair<UInt, UShort>? = null
|
||||
private var inInsn: Boolean = false
|
||||
|
||||
private var pc: UShort = 0u
|
||||
private var psw: UShort = 0u
|
||||
private var sp: UShort = 0u
|
||||
private var opcode: UShort = 0u
|
||||
private var opargs: UShortArray = UShortArray(3)
|
||||
private var oparg_ct: Int = 0
|
||||
|
||||
private val collectors: HashSet<(TraceRecord) -> Unit> = HashSet()
|
||||
|
||||
override fun noteBegin(cpu: CPU) {
|
||||
if (inInsn) {
|
||||
logger.warn("Began collection a new insn before committing the previous one. PC=${pc.toOctal()}")
|
||||
}
|
||||
pc = cpu.pc
|
||||
psw = cpu.psw
|
||||
sp = cpu.sp
|
||||
src = null
|
||||
dst = null
|
||||
oparg_ct = 0
|
||||
inInsn = true
|
||||
}
|
||||
|
||||
override fun noteOpcode(opcode: UShort) {
|
||||
this.opcode = opcode
|
||||
noteArgument(opcode)
|
||||
}
|
||||
|
||||
override fun noteArgument(arg: UShort) {
|
||||
opargs[oparg_ct++] = arg
|
||||
}
|
||||
|
||||
override fun noteReference(spec: UInt, value: UShort) {
|
||||
val ref = (spec and 0xFFFFu) to value
|
||||
if (spec bit CPU.PADDR_DST_BIT) {
|
||||
dst = ref
|
||||
} else {
|
||||
src = ref
|
||||
}
|
||||
}
|
||||
|
||||
override fun noteEnd() {
|
||||
val args = UShortArray(oparg_ct) {opargs[it]}
|
||||
oparg_ct = 0
|
||||
val record = TraceRecord(
|
||||
pc, sp, psw, opcode, args,
|
||||
src, dst,
|
||||
)
|
||||
for (coll in collectors) {
|
||||
coll(record)
|
||||
}
|
||||
inInsn = false
|
||||
}
|
||||
|
||||
fun addCollector(c: Collector) {
|
||||
collectors.add(c)
|
||||
}
|
||||
|
||||
fun removeCollector(c: Collector) {
|
||||
collectors.remove(c)
|
||||
}
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
@file:Suppress("NOTHING_TO_INLINE")
|
||||
@file:Suppress("NOTHING_TO_/*inline*/")
|
||||
|
||||
package com.thequux.mcpdp.ext.bit
|
||||
|
||||
@@ -6,82 +6,82 @@ import kotlin.experimental.and
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
inline infix fun Byte.shr(qty: Int): Byte = this.toInt().shr(min(qty, 7)).toByte()
|
||||
inline infix fun Byte.shl(qty: Int): Byte = if (qty > 7) 0 else this.toInt().shl(qty).toByte()
|
||||
inline infix fun Byte.bit(n: Int): Boolean = this.toInt() shr n and 1 != 0
|
||||
inline fun Byte.bit(n: Int, v: Boolean): Byte = if (v) this bis n else this bic n
|
||||
inline infix fun Byte.bis(n: Int): Byte = this.toInt().or(1 shl n).toByte()
|
||||
inline infix fun Byte.bic(n: Int): Byte = this.toInt().and(1.shl(n).inv()).toByte()
|
||||
inline infix fun Byte.sex(n: Int): Byte {
|
||||
/*inline*/ infix fun Byte.shr(qty: Int): Byte = this.toInt().shr(min(qty, 7)).toByte()
|
||||
/*inline*/ infix fun Byte.shl(qty: Int): Byte = if (qty > 7) 0 else this.toInt().shl(qty).toByte()
|
||||
/*inline*/ infix fun Byte.bit(n: Int): Boolean = this.toInt() shr n and 1 != 0
|
||||
/*inline*/ fun Byte.bit(n: Int, v: Boolean): Byte = if (v) this bis n else this bic n
|
||||
/*inline*/ infix fun Byte.bis(n: Int): Byte = this.toInt().or(1 shl n).toByte()
|
||||
/*inline*/ infix fun Byte.bic(n: Int): Byte = this.toInt().and(1.shl(n).inv()).toByte()
|
||||
/*inline*/ infix fun Byte.sex(n: Int): Byte {
|
||||
val sign = 1.toByte() shl n+1
|
||||
return ((this and sign.dec()) - (this and sign)).toByte()
|
||||
}
|
||||
|
||||
inline infix fun UByte.shr(qty: Int): UByte = this.toUInt().shr(min(qty, 7)).toUByte()
|
||||
inline infix fun UByte.shl(qty: Int): UByte = if (qty > 7) 0U else this.toInt().shl(qty).toUByte()
|
||||
inline infix fun UByte.bit(n: Int): Boolean = this.toUInt() shr n and 1U != 0U
|
||||
inline fun UByte.bit(n: Int, v: Boolean): UByte = if (v) this bis n else this bic n
|
||||
inline infix fun UByte.bis(n: Int): UByte = this.toUInt().or(1U shl n).toUByte()
|
||||
inline infix fun UByte.bic(n: Int): UByte = this.toUInt().and(1U.shl(n).inv()).toUByte()
|
||||
inline infix fun UByte.sex(n: Int): UByte {
|
||||
/*inline*/ infix fun UByte.shr(qty: Int): UByte = this.toUInt().shr(min(qty, 7)).toUByte()
|
||||
/*inline*/ infix fun UByte.shl(qty: Int): UByte = if (qty > 7) 0U else this.toInt().shl(qty).toUByte()
|
||||
/*inline*/ infix fun UByte.bit(n: Int): Boolean = this.toUInt() shr n and 1U != 0U
|
||||
/*inline*/ fun UByte.bit(n: Int, v: Boolean): UByte = if (v) this bis n else this bic n
|
||||
/*inline*/ infix fun UByte.bis(n: Int): UByte = this.toUInt().or(1U shl n).toUByte()
|
||||
/*inline*/ infix fun UByte.bic(n: Int): UByte = this.toUInt().and(1U.shl(n).inv()).toUByte()
|
||||
/*inline*/ infix fun UByte.sex(n: Int): UByte {
|
||||
val sign = 1.toUByte() shl n+1
|
||||
return ((this and sign.dec()) - (this and sign)).toUByte()
|
||||
}
|
||||
|
||||
inline infix fun Short.shr(qty: Int): Short = this.toInt().shr(min(qty, 15)).toShort()
|
||||
inline infix fun Short.shl(qty: Int): Short = if (qty > 15) 0 else this.toInt().shl(qty).toShort()
|
||||
inline infix fun Short.bit(n: Int): Boolean = this.toInt() shr n and 1 != 0
|
||||
inline fun Short.bit(n: Int, v: Boolean): Short = if (v) this bis n else this bic n
|
||||
inline infix fun Short.bis(n: Int): Short = this.toInt().or(1 shl n).toShort()
|
||||
inline infix fun Short.bic(n: Int): Short = this.toInt().and(1.shl(n).inv()).toShort()
|
||||
inline infix fun Short.sex(n: Int): Short {
|
||||
/*inline*/ infix fun Short.shr(qty: Int): Short = this.toInt().shr(min(qty, 15)).toShort()
|
||||
/*inline*/ infix fun Short.shl(qty: Int): Short = if (qty > 15) 0 else this.toInt().shl(qty).toShort()
|
||||
/*inline*/ infix fun Short.bit(n: Int): Boolean = this.toInt() shr n and 1 != 0
|
||||
/*inline*/ fun Short.bit(n: Int, v: Boolean): Short = if (v) this bis n else this bic n
|
||||
/*inline*/ infix fun Short.bis(n: Int): Short = this.toInt().or(1 shl n).toShort()
|
||||
/*inline*/ infix fun Short.bic(n: Int): Short = this.toInt().and(1.shl(n).inv()).toShort()
|
||||
/*inline*/ infix fun Short.sex(n: Int): Short {
|
||||
val sign = 1.toShort() shl n+1
|
||||
return ((this and sign.dec()) - (this and sign)).toShort()
|
||||
}
|
||||
|
||||
inline infix fun UShort.shr(qty: Int): UShort = this.toUInt().shr(min(qty, 15)).toUShort()
|
||||
inline infix fun UShort.shl(qty: Int): UShort = if (qty > 15) 0U else this.toInt().shl(qty).toUShort()
|
||||
inline infix fun UShort.bit(n: Int): Boolean = this.toUInt() shr n and 1U != 0U
|
||||
inline fun UShort.bit(n: Int, v: Boolean): UShort = if (v) this bis n else this bic n
|
||||
inline infix fun UShort.bis(n: Int): UShort = this.toUInt().or(1U shl n).toUShort()
|
||||
inline infix fun UShort.bic(n: Int): UShort = this.toUInt().and(1U.shl(n).inv()).toUShort()
|
||||
inline infix fun UShort.sex(n: Int): UShort {
|
||||
/*inline*/ infix fun UShort.shr(qty: Int): UShort = this.toUInt().shr(min(qty, 15)).toUShort()
|
||||
/*inline*/ infix fun UShort.shl(qty: Int): UShort = if (qty > 15) 0U else this.toInt().shl(qty).toUShort()
|
||||
/*inline*/ infix fun UShort.bit(n: Int): Boolean = this.toUInt() shr n and 1U != 0U
|
||||
/*inline*/ fun UShort.bit(n: Int, v: Boolean): UShort = if (v) this bis n else this bic n
|
||||
/*inline*/ infix fun UShort.bis(n: Int): UShort = this.toUInt().or(1U shl n).toUShort()
|
||||
/*inline*/ infix fun UShort.bic(n: Int): UShort = this.toUInt().and(1U.shl(n).inv()).toUShort()
|
||||
/*inline*/ infix fun UShort.sex(n: Int): UShort {
|
||||
val sign = 1.toUShort() shl (n-1)
|
||||
return (this - (this and sign shl 1)).toUShort()
|
||||
}
|
||||
|
||||
inline fun UShort.maskSet(v: UShort, mask: UShort) = this and mask.inv() or (v and mask)
|
||||
/*inline*/ fun UShort.maskSet(v: UShort, mask: UShort) = this and mask.inv() or (v and mask)
|
||||
|
||||
inline infix fun Int.bit(n: Int): Boolean = this shr n and 1 != 0
|
||||
inline fun Int.bit(n: Int, v: Boolean): Int = if (v) this bis n else this bic n
|
||||
inline infix fun Int.bis(n: Int): Int = this.or(1 shl n)
|
||||
inline infix fun Int.bic(n: Int): Int = this and (1 shl n).inv()
|
||||
inline infix fun Int.sex(n: Int): Int {
|
||||
/*inline*/ infix fun Int.bit(n: Int): Boolean = this shr n and 1 != 0
|
||||
/*inline*/ fun Int.bit(n: Int, v: Boolean): Int = if (v) this bis n else this bic n
|
||||
/*inline*/ infix fun Int.bis(n: Int): Int = this.or(1 shl n)
|
||||
/*inline*/ infix fun Int.bic(n: Int): Int = this and (1 shl n).inv()
|
||||
/*inline*/ infix fun Int.sex(n: Int): Int {
|
||||
val sign = 1 shl n+1
|
||||
return ((this and sign.dec()) - (this and sign))
|
||||
}
|
||||
inline infix fun UInt.bit(n: Int): Boolean = this shr n and 1U != 0U
|
||||
inline fun UInt.bit(n: Int, v: Boolean): UInt = if (v) this bis n else this bic n
|
||||
inline infix fun UInt.bis(n: Int): UInt = this.or(1U shl n)
|
||||
inline infix fun UInt.bic(n: Int): UInt = this.and(1U.shl(n).inv())
|
||||
inline infix fun UInt.sex(n: Int): UInt {
|
||||
/*inline*/ infix fun UInt.bit(n: Int): Boolean = this shr n and 1U != 0U
|
||||
/*inline*/ fun UInt.bit(n: Int, v: Boolean): UInt = if (v) this bis n else this bic n
|
||||
/*inline*/ infix fun UInt.bis(n: Int): UInt = this.or(1U shl n)
|
||||
/*inline*/ infix fun UInt.bic(n: Int): UInt = this.and(1U.shl(n).inv())
|
||||
/*inline*/ infix fun UInt.sex(n: Int): UInt {
|
||||
val sign = 1U shl n+1
|
||||
return ((this and sign.dec()) - (this and sign))
|
||||
}
|
||||
|
||||
inline infix fun Long.bit(n: Int): Boolean = this shr n and 1L != 0L
|
||||
inline fun Long.bit(n: Int, v: Boolean): Long = if (v) this bis n else this bic n
|
||||
inline infix fun Long.bis(n: Int): Long = this.or(1L shl n)
|
||||
inline infix fun Long.bic(n: Int): Long = this and (1L shl n).inv()
|
||||
inline infix fun Long.sex(n: Int): Long {
|
||||
/*inline*/ infix fun Long.bit(n: Int): Boolean = this shr n and 1L != 0L
|
||||
/*inline*/ fun Long.bit(n: Int, v: Boolean): Long = if (v) this bis n else this bic n
|
||||
/*inline*/ infix fun Long.bis(n: Int): Long = this.or(1L shl n)
|
||||
/*inline*/ infix fun Long.bic(n: Int): Long = this and (1L shl n).inv()
|
||||
/*inline*/ infix fun Long.sex(n: Int): Long {
|
||||
val sign = 1.toLong() shl n+1
|
||||
return (this and sign.dec()) - (this and sign)
|
||||
}
|
||||
inline infix fun ULong.bit(n: Int): Boolean = this shr n and 1UL != 0UL
|
||||
inline fun ULong.bit(n: Int, v: Boolean): ULong = if (v) this bis n else this bic n
|
||||
inline infix fun ULong.bis(n: Int): ULong = this.or(1UL shl n)
|
||||
inline infix fun ULong.bic(n: Int): ULong = this.and(1UL.shl(n).inv())
|
||||
inline infix fun ULong.sex(n: Int): ULong {
|
||||
/*inline*/ infix fun ULong.bit(n: Int): Boolean = this shr n and 1UL != 0UL
|
||||
/*inline*/ fun ULong.bit(n: Int, v: Boolean): ULong = if (v) this bis n else this bic n
|
||||
/*inline*/ infix fun ULong.bis(n: Int): ULong = this.or(1UL shl n)
|
||||
/*inline*/ infix fun ULong.bic(n: Int): ULong = this.and(1UL.shl(n).inv())
|
||||
/*inline*/ infix fun ULong.sex(n: Int): ULong {
|
||||
val sign = 1UL shl n+1
|
||||
return ((this and (sign.dec())) - (this and sign))
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
package com.thequux.mcpdp.ext.bit
|
||||
|
||||
fun UShort.toOctal(): String = this.toString(8).padStart(6,'0')
|
||||
fun UByte.toOctal(): String = this.toString(8).padStart(3, '0')
|
||||
fun UInt.toOctal(): String = this.toString(8).padStart(11, '0')
|
||||
fun UShort.toOctal(len: Int = 6): String = this.toString(8).padStart(len,'0')
|
||||
fun UByte.toOctal(len: Int = 3): String = this.toString(8).padStart(len, '0')
|
||||
fun UInt.toOctal(len: Int = 11): String = this.toString(8).padStart(len, '0')
|
||||
|
Reference in New Issue
Block a user