UNPKG

m68kdecode

Version:

Port of deplinenoise/m68kdecode to Typescript

399 lines 17.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const types_1 = require("./types"); const lib_1 = require("./lib"); class CodeStream { constructor(bytes) { this.bytes = bytes; this.pos = 0; } hasWords(count) { return this.pos + count * 2 <= this.bytes.length; } peekWord(offset) { const p = this.pos + offset; if (p + 2 > this.bytes.length) { throw new Error("OutOfSpace"); } return (this.bytes[p] << 8) | this.bytes[p + 1]; } skipWords(count) { this.pos += 2 * count; } pull16() { const result = this.peekWord(0); this.pos += 2; return result; } pull32() { const a = this.pull16(); const b = this.pull16(); return (a << 16) | b; } ea(srcReg, srcMod, size) { switch (srcMod) { case 0b000: return (0, types_1.DR)(srcReg); case 0b001: return (0, types_1.AR)(srcReg); case 0b010: return (0, types_1.ARIND)(srcReg); case 0b011: return (0, types_1.ARINC)(srcReg); case 0b100: return (0, types_1.ARDEC)(srcReg); case 0b101: return (0, types_1.ARDISP)(srcReg, (0, lib_1.simpleDisp)((0, lib_1.i16)(this.pull16()))); case 0b110: return this.decodeExtendedEa(srcReg); case 0b111: { switch (srcReg) { case 0b000: return (0, types_1.ABS16)((0, lib_1.i16)(this.pull16())); case 0b001: return (0, types_1.ABS32)(this.pull32()); case 0b010: return (0, types_1.PCDISP)((0, lib_1.i8)(this.pos), (0, lib_1.simpleDisp)((0, lib_1.i16)(this.pull16()))); case 0b011: return this.decodeExtendedEa(null); case 0b100: { switch (size) { case 1: return (0, types_1.IMM8)((0, lib_1.u8)(this.pull16())); case 2: return (0, types_1.IMM16)(this.pull16()); case 4: return (0, types_1.IMM32)(this.pull32()); default: { throw new Error("BadSize"); } } } } } } throw new Error("NotImplemented"); } decodeExtendedEa(srcReg) { const pcOff = (0, lib_1.u8)(this.pos); const ext = this.pull16(); const scale = (0, lib_1.u8)((0, lib_1.getBits)(ext, 9, 2)); const idx = (0, lib_1.getBits)(ext, 12, 3); const idxIsA = (0, lib_1.getBits)(ext, 15, 1) === 1; if (0 !== (ext & (1 << 8))) { // Handle full extension word. const bd = (0, lib_1.getBits)(ext, 4, 2); const od = (0, lib_1.getBits)(ext, 0, 2); let baseDisplacement; switch (bd) { case 0: throw new Error("Reserved"); case 1: baseDisplacement = 0; break; case 2: baseDisplacement = (0, lib_1.i16)(this.pull16()); break; case 3: baseDisplacement = this.pull32(); break; default: throw new Error("NotImplemented"); } let outerDisplacement; switch (od) { case 0: outerDisplacement = 0; break; case 1: outerDisplacement = 0; break; case 2: outerDisplacement = (0, lib_1.i16)(this.pull16()); break; case 3: outerDisplacement = this.pull32(); break; default: throw new Error("NotImplemented"); } const suppressBase = (0, lib_1.getBits)(ext, 7, 1) === 1; const suppressIndexer = (0, lib_1.getBits)(ext, 6, 1) === 1; let indirection; if (!suppressIndexer) { switch ((0, lib_1.getBits)(ext, 0, 3)) { case 0b000: indirection = null; break; case 0b001: indirection = "IndirectPreIndexed"; break; case 0b010: indirection = "IndirectPreIndexed"; break; case 0b011: indirection = "IndirectPreIndexed"; break; case 0b100: throw new Error("Reserved"); case 0b101: indirection = "IndirectPostIndexed"; break; case 0b110: indirection = "IndirectPostIndexed"; break; case 0b111: indirection = "IndirectPostIndexed"; break; default: throw new Error("NotImplemented"); } } else { switch ((0, lib_1.getBits)(ext, 0, 3)) { case 0b000: indirection = null; break; case 0b001: indirection = "Indirect"; break; case 0b010: indirection = "Indirect"; break; case 0b011: indirection = "Indirect"; break; default: throw new Error("Reserved"); } } let indexer = null; if (!suppressIndexer) { indexer = idxIsA ? (0, types_1.ARIndexer)(idx, scale) : (0, types_1.DRIndexer)(idx, scale); } if (suppressBase) { return (0, types_1.DISP)({ baseDisplacement, outerDisplacement, indexer, indirection, }); } else { return srcReg !== null ? (0, types_1.ARDISP)(srcReg, { baseDisplacement, outerDisplacement, indexer, indirection, }) : (0, types_1.PCDISP)(pcOff, { baseDisplacement, outerDisplacement, indexer, indirection, }); } } else { // Handle brief extension word const disp = (0, lib_1.i8)(ext & 0xff); const indexer = idxIsA ? (0, types_1.ARIndexer)(idx, scale) : (0, types_1.DRIndexer)(idx, scale); const displacement = { baseDisplacement: disp, outerDisplacement: 0, indexer, indirection: null, }; return srcReg !== null ? (0, types_1.ARDISP)(srcReg, displacement) : (0, types_1.PCDISP)(pcOff, displacement); } } imm8() { return (0, types_1.IMM8)((0, lib_1.u8)(this.pull16())); } imm16() { return (0, types_1.IMM16)(this.pull16()); } imm32() { return (0, types_1.IMM32)(this.pull32()); } dar(dOrA, regno) { return dOrA === 0 ? (0, types_1.DR)(regno) : (0, types_1.AR)(regno); } bitfield(dynOff, off, dynWidth, width) { const bfOffset = dynOff === 0 ? (0, types_1.STATIC)((off & 31) === 0 ? 32 : (0, lib_1.u8)(off & 31)) : (0, types_1.DYNAMIC)(off); const bfWidth = dynWidth === 0 ? (0, types_1.STATIC)((width & 31) === 0 ? 32 : (0, lib_1.u8)(width & 31)) : (0, types_1.DYNAMIC)(width); return (0, types_1.Bitfield)(bfOffset, bfWidth); } cc(c) { switch (c) { case 0b0000: return (0, types_1.Condition)(types_1.ConditionCode.CC_T); // Always True case 0b0001: return (0, types_1.Condition)(types_1.ConditionCode.CC_F); // Always False case 0b0010: return (0, types_1.Condition)(types_1.ConditionCode.CC_HI); // High case 0b0011: return (0, types_1.Condition)(types_1.ConditionCode.CC_LS); // Low or Same case 0b0100: return (0, types_1.Condition)(types_1.ConditionCode.CC_CC); // Carry Clear case 0b0101: return (0, types_1.Condition)(types_1.ConditionCode.CC_CS); // Carry Set case 0b0110: return (0, types_1.Condition)(types_1.ConditionCode.CC_NE); // Not Equal case 0b0111: return (0, types_1.Condition)(types_1.ConditionCode.CC_EQ); // Equal case 0b1000: return (0, types_1.Condition)(types_1.ConditionCode.CC_VC); // Overflow Clear case 0b1001: return (0, types_1.Condition)(types_1.ConditionCode.CC_VS); // Overflow Set case 0b1010: return (0, types_1.Condition)(types_1.ConditionCode.CC_PL); // Plus case 0b1011: return (0, types_1.Condition)(types_1.ConditionCode.CC_MI); // Negative case 0b1100: return (0, types_1.Condition)(types_1.ConditionCode.CC_GE); // Greater or Equal case 0b1101: return (0, types_1.Condition)(types_1.ConditionCode.CC_LT); // Less case 0b1110: return (0, types_1.Condition)(types_1.ConditionCode.CC_GT); // Greater default: return (0, types_1.Condition)(types_1.ConditionCode.CC_LE); // Less or Equal } } quickConst(i) { return (0, types_1.IMM8)(i === 0 ? 8 : (0, lib_1.u8)(i)); } decodeFp(rg, md, m_r, s, d, k) { if (m_r === 1) { let sz; let fpform; switch (s) { case 0b000: sz = 4; fpform = (0, types_1.FPF_LONG_INT)(); break; case 0b001: sz = 4; fpform = (0, types_1.FPF_SINGLE)(); break; case 0b010: sz = 10; fpform = (0, types_1.FPF_EXTENDED_REAL)(); break; case 0b011: sz = 12; fpform = (0, types_1.FPF_PACKED_DECIMAL_REAL_STATIC)((0, lib_1.i8)(k << 1) >> 1); break; case 0b100: sz = 2; fpform = (0, types_1.FPF_WORD_INT)(); break; case 0b101: sz = 8; fpform = (0, types_1.FPF_DOUBLE)(); break; case 0b110: sz = 1; fpform = (0, types_1.FPF_BYTE_INT)(); break; case 0b111: sz = 12; fpform = (0, types_1.FPF_PACKED_DECIMAL_REAL_DYNAMIC)(k >> 4); break; default: throw new Error("Reserved"); } return [sz, this.ea(rg, md, sz), (0, types_1.FR)(d), (0, types_1.FloatFormat)(fpform)]; } else { return [10, (0, types_1.FR)(s), (0, types_1.FR)(d), (0, types_1.FloatFormat)((0, types_1.FPF_EXTENDED_REAL)())]; } } fpcc(c) { switch (c) { case 0b000000: return (0, types_1.FPCondition)(types_1.FPConditionCode.FPCC_F); // False case 0b000001: return (0, types_1.FPCondition)(types_1.FPConditionCode.FPCC_EQ); // Equal case 0b000010: return (0, types_1.FPCondition)(types_1.FPConditionCode.FPCC_OGT); // Ordered Greater Than case 0b000011: return (0, types_1.FPCondition)(types_1.FPConditionCode.FPCC_OGE); // Ordered Greater Than or Equal case 0b000100: return (0, types_1.FPCondition)(types_1.FPConditionCode.FPCC_OLT); // Ordered Less Than case 0b000101: return (0, types_1.FPCondition)(types_1.FPConditionCode.FPCC_OLE); // Ordered Less Than or Equal case 0b000110: return (0, types_1.FPCondition)(types_1.FPConditionCode.FPCC_OGL); // Ordered Greater Than or Less Than case 0b000111: return (0, types_1.FPCondition)(types_1.FPConditionCode.FPCC_OR); // Ordered case 0b001000: return (0, types_1.FPCondition)(types_1.FPConditionCode.FPCC_UN); // Unordered case 0b001001: return (0, types_1.FPCondition)(types_1.FPConditionCode.FPCC_UEQ); // Unordered or Equal case 0b001010: return (0, types_1.FPCondition)(types_1.FPConditionCode.FPCC_UGT); // Unordered or Greater Than case 0b001011: return (0, types_1.FPCondition)(types_1.FPConditionCode.FPCC_UGE); // Unordered or Greater Than or Equal case 0b001100: return (0, types_1.FPCondition)(types_1.FPConditionCode.FPCC_ULT); // Unordered or Less Than case 0b001101: return (0, types_1.FPCondition)(types_1.FPConditionCode.FPCC_ULE); // Unordered or Less Than or Equal case 0b001110: return (0, types_1.FPCondition)(types_1.FPConditionCode.FPCC_NE); // Not Equal case 0b001111: return (0, types_1.FPCondition)(types_1.FPConditionCode.FPCC_T); // True case 0b010000: return (0, types_1.FPCondition)(types_1.FPConditionCode.FPCC_SF); // Signaling False case 0b010001: return (0, types_1.FPCondition)(types_1.FPConditionCode.FPCC_SEQ); // Signaling Equal case 0b010010: return (0, types_1.FPCondition)(types_1.FPConditionCode.FPCC_GT); // Greater Than case 0b010011: return (0, types_1.FPCondition)(types_1.FPConditionCode.FPCC_GE); // Greater Than or Equal case 0b010100: return (0, types_1.FPCondition)(types_1.FPConditionCode.FPCC_LT); // Less Than case 0b010101: return (0, types_1.FPCondition)(types_1.FPConditionCode.FPCC_LE); // Less Than or Equal case 0b010110: return (0, types_1.FPCondition)(types_1.FPConditionCode.FPCC_GL); // Greater Than or Less Than case 0b010111: return (0, types_1.FPCondition)(types_1.FPConditionCode.FPCC_GLE); // Greater Than or Less Than or Equal case 0b011000: return (0, types_1.FPCondition)(types_1.FPConditionCode.FPCC_NGLE); // Not (Greater Than or Less Than or Equal) case 0b011001: return (0, types_1.FPCondition)(types_1.FPConditionCode.FPCC_NGL); // Not (Greater Than or Less Than) case 0b011010: return (0, types_1.FPCondition)(types_1.FPConditionCode.FPCC_NLE); // Not (Less Than or Equal) case 0b011011: return (0, types_1.FPCondition)(types_1.FPConditionCode.FPCC_NLT); // Not (Less Than) case 0b011100: return (0, types_1.FPCondition)(types_1.FPConditionCode.FPCC_NGE); // Not (Greater Than or Equal) case 0b011101: return (0, types_1.FPCondition)(types_1.FPConditionCode.FPCC_NGT); // Not (Greater Than) case 0b011110: return (0, types_1.FPCondition)(types_1.FPConditionCode.FPCC_SNE); // Signaling Not Equal default: return (0, types_1.FPCondition)(types_1.FPConditionCode.FPCC_ST); // Signaling True } } decodeFpMovem(r, m, direction, mask, mode) { const ea = this.ea(r, m, 10); const regs = (mode & 1) === 0 ? (0, types_1.REGLIST)(mask) : (0, types_1.DR)(mask >> 4); const extra = (0, types_1.FloatFormat)((0, types_1.FPF_EXTENDED_REAL)()); return direction === 0 ? [10, ea, regs, extra] // move from memory to float registers : [10, regs, ea, extra]; // move from registers to memory } } exports.default = CodeStream; //# sourceMappingURL=codestream.js.map