rk86 2.0.13 → 2.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/rk86.js +448 -20
package/package.json
CHANGED
package/rk86.js
CHANGED
|
@@ -1588,12 +1588,400 @@ var init_catalog_data = __esm(() => {
|
|
|
1588
1588
|
];
|
|
1589
1589
|
});
|
|
1590
1590
|
|
|
1591
|
+
// node_modules/asm8080/dist/asm8.js
|
|
1592
|
+
var REG8 = {
|
|
1593
|
+
B: 0,
|
|
1594
|
+
C: 1,
|
|
1595
|
+
D: 2,
|
|
1596
|
+
E: 3,
|
|
1597
|
+
H: 4,
|
|
1598
|
+
L: 5,
|
|
1599
|
+
M: 6,
|
|
1600
|
+
A: 7
|
|
1601
|
+
};
|
|
1602
|
+
var REG_PAIR = {
|
|
1603
|
+
B: 0,
|
|
1604
|
+
D: 1,
|
|
1605
|
+
H: 2,
|
|
1606
|
+
SP: 3
|
|
1607
|
+
};
|
|
1608
|
+
var REG_PAIR_PUSH = {
|
|
1609
|
+
B: 0,
|
|
1610
|
+
D: 1,
|
|
1611
|
+
H: 2,
|
|
1612
|
+
PSW: 3
|
|
1613
|
+
};
|
|
1614
|
+
var IMPLIED = {
|
|
1615
|
+
NOP: 0,
|
|
1616
|
+
HLT: 118,
|
|
1617
|
+
RET: 201,
|
|
1618
|
+
XCHG: 235,
|
|
1619
|
+
EI: 251,
|
|
1620
|
+
DI: 243,
|
|
1621
|
+
CMA: 47,
|
|
1622
|
+
STC: 55,
|
|
1623
|
+
CMC: 63,
|
|
1624
|
+
DAA: 39,
|
|
1625
|
+
RLC: 7,
|
|
1626
|
+
RRC: 15,
|
|
1627
|
+
RAL: 23,
|
|
1628
|
+
RAR: 31,
|
|
1629
|
+
PCHL: 233,
|
|
1630
|
+
SPHL: 249,
|
|
1631
|
+
XTHL: 227,
|
|
1632
|
+
RNZ: 192,
|
|
1633
|
+
RZ: 200,
|
|
1634
|
+
RNC: 208,
|
|
1635
|
+
RC: 216,
|
|
1636
|
+
RPO: 224,
|
|
1637
|
+
RPE: 232,
|
|
1638
|
+
RP: 240,
|
|
1639
|
+
RM: 248
|
|
1640
|
+
};
|
|
1641
|
+
var ALU_REG = {
|
|
1642
|
+
ADD: 128,
|
|
1643
|
+
ADC: 136,
|
|
1644
|
+
SUB: 144,
|
|
1645
|
+
SBB: 152,
|
|
1646
|
+
ANA: 160,
|
|
1647
|
+
XRA: 168,
|
|
1648
|
+
ORA: 176,
|
|
1649
|
+
CMP: 184
|
|
1650
|
+
};
|
|
1651
|
+
var ALU_IMM = {
|
|
1652
|
+
ADI: 198,
|
|
1653
|
+
ACI: 206,
|
|
1654
|
+
SUI: 214,
|
|
1655
|
+
SBI: 222,
|
|
1656
|
+
ANI: 230,
|
|
1657
|
+
XRI: 238,
|
|
1658
|
+
ORI: 246,
|
|
1659
|
+
CPI: 254
|
|
1660
|
+
};
|
|
1661
|
+
var ADDR16 = {
|
|
1662
|
+
JMP: 195,
|
|
1663
|
+
JNZ: 194,
|
|
1664
|
+
JZ: 202,
|
|
1665
|
+
JNC: 210,
|
|
1666
|
+
JC: 218,
|
|
1667
|
+
JPO: 226,
|
|
1668
|
+
JPE: 234,
|
|
1669
|
+
JP: 242,
|
|
1670
|
+
JM: 250,
|
|
1671
|
+
CALL: 205,
|
|
1672
|
+
CNZ: 196,
|
|
1673
|
+
CZ: 204,
|
|
1674
|
+
CNC: 212,
|
|
1675
|
+
CC: 220,
|
|
1676
|
+
CPO: 228,
|
|
1677
|
+
CPE: 236,
|
|
1678
|
+
CP: 244,
|
|
1679
|
+
CM: 252,
|
|
1680
|
+
LDA: 58,
|
|
1681
|
+
STA: 50,
|
|
1682
|
+
LHLD: 42,
|
|
1683
|
+
SHLD: 34
|
|
1684
|
+
};
|
|
1685
|
+
function instrSize(m) {
|
|
1686
|
+
if (m in IMPLIED)
|
|
1687
|
+
return 1;
|
|
1688
|
+
if (m in ALU_REG)
|
|
1689
|
+
return 1;
|
|
1690
|
+
if (m === "MOV" || m === "INR" || m === "DCR")
|
|
1691
|
+
return 1;
|
|
1692
|
+
if (m === "PUSH" || m === "POP")
|
|
1693
|
+
return 1;
|
|
1694
|
+
if (m === "DAD" || m === "INX" || m === "DCX")
|
|
1695
|
+
return 1;
|
|
1696
|
+
if (m === "LDAX" || m === "STAX")
|
|
1697
|
+
return 1;
|
|
1698
|
+
if (m === "RST")
|
|
1699
|
+
return 1;
|
|
1700
|
+
if (m === "MVI")
|
|
1701
|
+
return 2;
|
|
1702
|
+
if (m in ALU_IMM)
|
|
1703
|
+
return 2;
|
|
1704
|
+
if (m === "IN" || m === "OUT")
|
|
1705
|
+
return 2;
|
|
1706
|
+
if (m === "LXI")
|
|
1707
|
+
return 3;
|
|
1708
|
+
if (m in ADDR16)
|
|
1709
|
+
return 3;
|
|
1710
|
+
throw new Error(`unknown mnemonic: ${m}`);
|
|
1711
|
+
}
|
|
1712
|
+
function stripComment(line) {
|
|
1713
|
+
let inQ = false;
|
|
1714
|
+
let qc = "";
|
|
1715
|
+
for (let i = 0;i < line.length; i++) {
|
|
1716
|
+
const c = line[i];
|
|
1717
|
+
if (inQ) {
|
|
1718
|
+
if (c === qc)
|
|
1719
|
+
inQ = false;
|
|
1720
|
+
} else if (c === '"' || c === "'") {
|
|
1721
|
+
inQ = true;
|
|
1722
|
+
qc = c;
|
|
1723
|
+
} else if (c === ";")
|
|
1724
|
+
return line.slice(0, i);
|
|
1725
|
+
}
|
|
1726
|
+
return line;
|
|
1727
|
+
}
|
|
1728
|
+
function splitOperands(s) {
|
|
1729
|
+
const r = [];
|
|
1730
|
+
let current = "";
|
|
1731
|
+
let inQ = false;
|
|
1732
|
+
let qc = "";
|
|
1733
|
+
for (const c of s) {
|
|
1734
|
+
if (inQ) {
|
|
1735
|
+
current += c;
|
|
1736
|
+
if (c === qc)
|
|
1737
|
+
inQ = false;
|
|
1738
|
+
} else if (c === '"' || c === "'") {
|
|
1739
|
+
inQ = true;
|
|
1740
|
+
qc = c;
|
|
1741
|
+
current += c;
|
|
1742
|
+
} else if (c === ",") {
|
|
1743
|
+
r.push(current.trim());
|
|
1744
|
+
current = "";
|
|
1745
|
+
} else
|
|
1746
|
+
current += c;
|
|
1747
|
+
}
|
|
1748
|
+
if (current.trim())
|
|
1749
|
+
r.push(current.trim());
|
|
1750
|
+
return r;
|
|
1751
|
+
}
|
|
1752
|
+
function parseLine(line) {
|
|
1753
|
+
let s = stripComment(line).trim();
|
|
1754
|
+
if (!s)
|
|
1755
|
+
return { operands: [] };
|
|
1756
|
+
let label;
|
|
1757
|
+
const ci = s.indexOf(":");
|
|
1758
|
+
if (ci > 0 && /^[A-Za-z_]\w*$/.test(s.slice(0, ci).trim())) {
|
|
1759
|
+
label = s.slice(0, ci).trim();
|
|
1760
|
+
s = s.slice(ci + 1).trim();
|
|
1761
|
+
}
|
|
1762
|
+
if (!s)
|
|
1763
|
+
return { label, operands: [] };
|
|
1764
|
+
const si = s.search(/\s/);
|
|
1765
|
+
const first = si < 0 ? s : s.slice(0, si);
|
|
1766
|
+
const rest = si < 0 ? "" : s.slice(si).trim();
|
|
1767
|
+
if (!label && rest) {
|
|
1768
|
+
const parts = rest.split(/\s+/);
|
|
1769
|
+
if (parts[0].toUpperCase() === "EQU") {
|
|
1770
|
+
return {
|
|
1771
|
+
label: first,
|
|
1772
|
+
mnemonic: "EQU",
|
|
1773
|
+
operands: [parts.slice(1).join(" ")],
|
|
1774
|
+
isEqu: true
|
|
1775
|
+
};
|
|
1776
|
+
}
|
|
1777
|
+
}
|
|
1778
|
+
return { label, mnemonic: first, operands: rest ? splitOperands(rest) : [] };
|
|
1779
|
+
}
|
|
1780
|
+
function evalAtom(s, symbols) {
|
|
1781
|
+
s = s.trim();
|
|
1782
|
+
if (s.length === 3 && s[0] === "'" && s[2] === "'")
|
|
1783
|
+
return s.charCodeAt(1);
|
|
1784
|
+
if (/^[0-9][0-9A-Fa-f]*[hH]$/.test(s))
|
|
1785
|
+
return parseInt(s.slice(0, -1), 16);
|
|
1786
|
+
if (/^[0-9]+$/.test(s))
|
|
1787
|
+
return parseInt(s, 10);
|
|
1788
|
+
const k = s.toUpperCase();
|
|
1789
|
+
if (symbols.has(k))
|
|
1790
|
+
return symbols.get(k);
|
|
1791
|
+
throw new Error(`unknown symbol: ${s}`);
|
|
1792
|
+
}
|
|
1793
|
+
function evalExpr(expr, symbols) {
|
|
1794
|
+
expr = expr.trim();
|
|
1795
|
+
const tokens = [];
|
|
1796
|
+
const ops = ["+"];
|
|
1797
|
+
let current = "";
|
|
1798
|
+
for (const c of expr) {
|
|
1799
|
+
if ((c === "+" || c === "-") && current.trim()) {
|
|
1800
|
+
tokens.push(current.trim());
|
|
1801
|
+
ops.push(c);
|
|
1802
|
+
current = "";
|
|
1803
|
+
} else {
|
|
1804
|
+
current += c;
|
|
1805
|
+
}
|
|
1806
|
+
}
|
|
1807
|
+
if (current.trim())
|
|
1808
|
+
tokens.push(current.trim());
|
|
1809
|
+
let r = 0;
|
|
1810
|
+
for (let i = 0;i < tokens.length; i++) {
|
|
1811
|
+
const v = evalAtom(tokens[i], symbols);
|
|
1812
|
+
r = ops[i] === "+" ? r + v : r - v;
|
|
1813
|
+
}
|
|
1814
|
+
return r & 65535;
|
|
1815
|
+
}
|
|
1816
|
+
function encode(m, ops, symbols) {
|
|
1817
|
+
if (m in IMPLIED)
|
|
1818
|
+
return [IMPLIED[m]];
|
|
1819
|
+
if (m in ALU_REG)
|
|
1820
|
+
return [ALU_REG[m] | REG8[ops[0].toUpperCase()]];
|
|
1821
|
+
if (m in ALU_IMM)
|
|
1822
|
+
return [ALU_IMM[m], evalExpr(ops[0], symbols) & 255];
|
|
1823
|
+
if (m in ADDR16) {
|
|
1824
|
+
const v = evalExpr(ops[0], symbols);
|
|
1825
|
+
return [ADDR16[m], v & 255, v >> 8 & 255];
|
|
1826
|
+
}
|
|
1827
|
+
if (m === "MOV")
|
|
1828
|
+
return [64 | REG8[ops[0].toUpperCase()] << 3 | REG8[ops[1].toUpperCase()]];
|
|
1829
|
+
if (m === "MVI") {
|
|
1830
|
+
const v = evalExpr(ops[1], symbols);
|
|
1831
|
+
return [6 | REG8[ops[0].toUpperCase()] << 3, v & 255];
|
|
1832
|
+
}
|
|
1833
|
+
if (m === "INR")
|
|
1834
|
+
return [4 | REG8[ops[0].toUpperCase()] << 3];
|
|
1835
|
+
if (m === "DCR")
|
|
1836
|
+
return [5 | REG8[ops[0].toUpperCase()] << 3];
|
|
1837
|
+
if (m === "LXI") {
|
|
1838
|
+
const v = evalExpr(ops[1], symbols);
|
|
1839
|
+
return [1 | REG_PAIR[ops[0].toUpperCase()] << 4, v & 255, v >> 8 & 255];
|
|
1840
|
+
}
|
|
1841
|
+
if (m === "DAD")
|
|
1842
|
+
return [9 | REG_PAIR[ops[0].toUpperCase()] << 4];
|
|
1843
|
+
if (m === "INX")
|
|
1844
|
+
return [3 | REG_PAIR[ops[0].toUpperCase()] << 4];
|
|
1845
|
+
if (m === "DCX")
|
|
1846
|
+
return [11 | REG_PAIR[ops[0].toUpperCase()] << 4];
|
|
1847
|
+
if (m === "PUSH")
|
|
1848
|
+
return [197 | REG_PAIR_PUSH[ops[0].toUpperCase()] << 4];
|
|
1849
|
+
if (m === "POP")
|
|
1850
|
+
return [193 | REG_PAIR_PUSH[ops[0].toUpperCase()] << 4];
|
|
1851
|
+
if (m === "LDAX")
|
|
1852
|
+
return [10 | REG_PAIR[ops[0].toUpperCase()] << 4];
|
|
1853
|
+
if (m === "STAX")
|
|
1854
|
+
return [2 | REG_PAIR[ops[0].toUpperCase()] << 4];
|
|
1855
|
+
if (m === "IN")
|
|
1856
|
+
return [219, evalExpr(ops[0], symbols) & 255];
|
|
1857
|
+
if (m === "OUT")
|
|
1858
|
+
return [211, evalExpr(ops[0], symbols) & 255];
|
|
1859
|
+
if (m === "RST") {
|
|
1860
|
+
const n = evalExpr(ops[0], symbols);
|
|
1861
|
+
return [199 | n << 3];
|
|
1862
|
+
}
|
|
1863
|
+
throw new Error(`cannot encode: ${m} ${ops.join(", ")}`);
|
|
1864
|
+
}
|
|
1865
|
+
function dbBytes(operands, symbols) {
|
|
1866
|
+
const out = [];
|
|
1867
|
+
for (const op of operands) {
|
|
1868
|
+
if (op.startsWith('"') && op.endsWith('"') || op.startsWith("'") && op.endsWith("'")) {
|
|
1869
|
+
for (const ch of op.slice(1, -1))
|
|
1870
|
+
out.push(ch.charCodeAt(0));
|
|
1871
|
+
} else {
|
|
1872
|
+
out.push(evalExpr(op, symbols) & 255);
|
|
1873
|
+
}
|
|
1874
|
+
}
|
|
1875
|
+
return out;
|
|
1876
|
+
}
|
|
1877
|
+
function dwBytes(operands, symbols) {
|
|
1878
|
+
const out = [];
|
|
1879
|
+
for (const op of operands) {
|
|
1880
|
+
const v = evalExpr(op, symbols) & 65535;
|
|
1881
|
+
out.push(v & 255, v >> 8 & 255);
|
|
1882
|
+
}
|
|
1883
|
+
return out;
|
|
1884
|
+
}
|
|
1885
|
+
function countDb(operands) {
|
|
1886
|
+
let n = 0;
|
|
1887
|
+
for (const op of operands) {
|
|
1888
|
+
if (op.startsWith('"') && op.endsWith('"') || op.startsWith("'") && op.endsWith("'"))
|
|
1889
|
+
n += op.length - 2;
|
|
1890
|
+
else
|
|
1891
|
+
n++;
|
|
1892
|
+
}
|
|
1893
|
+
return n;
|
|
1894
|
+
}
|
|
1895
|
+
function asm(source) {
|
|
1896
|
+
const lines = source.split(`
|
|
1897
|
+
`);
|
|
1898
|
+
const symbols = new Map;
|
|
1899
|
+
let pc = 0;
|
|
1900
|
+
for (const line of lines) {
|
|
1901
|
+
const parts = parseLine(line);
|
|
1902
|
+
if (parts.label) {
|
|
1903
|
+
if (parts.isEqu) {
|
|
1904
|
+
symbols.set(parts.label.toUpperCase(), evalExpr(parts.operands[0], symbols));
|
|
1905
|
+
continue;
|
|
1906
|
+
}
|
|
1907
|
+
symbols.set(parts.label.toUpperCase(), pc);
|
|
1908
|
+
}
|
|
1909
|
+
if (!parts.mnemonic)
|
|
1910
|
+
continue;
|
|
1911
|
+
const m = parts.mnemonic.toUpperCase();
|
|
1912
|
+
if (m === "EQU")
|
|
1913
|
+
continue;
|
|
1914
|
+
if (m === "ORG") {
|
|
1915
|
+
pc = evalExpr(parts.operands[0], symbols);
|
|
1916
|
+
continue;
|
|
1917
|
+
}
|
|
1918
|
+
if (m === "SECTION")
|
|
1919
|
+
continue;
|
|
1920
|
+
if (m === "END")
|
|
1921
|
+
break;
|
|
1922
|
+
if (m === "DB") {
|
|
1923
|
+
pc += countDb(parts.operands);
|
|
1924
|
+
continue;
|
|
1925
|
+
}
|
|
1926
|
+
if (m === "DW") {
|
|
1927
|
+
pc += parts.operands.length * 2;
|
|
1928
|
+
continue;
|
|
1929
|
+
}
|
|
1930
|
+
pc += instrSize(m);
|
|
1931
|
+
}
|
|
1932
|
+
const sections = [];
|
|
1933
|
+
let current = null;
|
|
1934
|
+
const sectionNames = new Set;
|
|
1935
|
+
for (const line of lines) {
|
|
1936
|
+
const parts = parseLine(line);
|
|
1937
|
+
if (parts.isEqu || !parts.mnemonic)
|
|
1938
|
+
continue;
|
|
1939
|
+
const m = parts.mnemonic.toUpperCase();
|
|
1940
|
+
if (m === "EQU")
|
|
1941
|
+
continue;
|
|
1942
|
+
if (m === "ORG") {
|
|
1943
|
+
if (current && current.data.length) {
|
|
1944
|
+
current.end = current.start + current.data.length - 1;
|
|
1945
|
+
sections.push(current);
|
|
1946
|
+
}
|
|
1947
|
+
const addr = evalExpr(parts.operands[0], symbols);
|
|
1948
|
+
current = { start: addr, end: addr, data: [] };
|
|
1949
|
+
continue;
|
|
1950
|
+
}
|
|
1951
|
+
if (m === "SECTION") {
|
|
1952
|
+
if (!current)
|
|
1953
|
+
throw new Error("SECTION before ORG");
|
|
1954
|
+
const name = parts.operands[0];
|
|
1955
|
+
if (!name)
|
|
1956
|
+
throw new Error("SECTION requires a name");
|
|
1957
|
+
if (sectionNames.has(name.toUpperCase()))
|
|
1958
|
+
throw new Error(`duplicate section name: ${name}`);
|
|
1959
|
+
sectionNames.add(name.toUpperCase());
|
|
1960
|
+
current.name = name;
|
|
1961
|
+
continue;
|
|
1962
|
+
}
|
|
1963
|
+
if (m === "END")
|
|
1964
|
+
break;
|
|
1965
|
+
if (!current)
|
|
1966
|
+
throw new Error("code before ORG");
|
|
1967
|
+
const bytes = m === "DB" ? dbBytes(parts.operands, symbols) : m === "DW" ? dwBytes(parts.operands, symbols) : encode(m, parts.operands, symbols);
|
|
1968
|
+
current.data.push(...bytes);
|
|
1969
|
+
}
|
|
1970
|
+
if (current && current.data.length) {
|
|
1971
|
+
current.end = current.start + current.data.length - 1;
|
|
1972
|
+
sections.push(current);
|
|
1973
|
+
}
|
|
1974
|
+
return sections;
|
|
1975
|
+
}
|
|
1976
|
+
if (false) {}
|
|
1977
|
+
|
|
1591
1978
|
// src/lib/terminal/rk86_terminal.ts
|
|
1592
1979
|
import { existsSync } from "fs";
|
|
1980
|
+
import { readFile } from "fs/promises";
|
|
1593
1981
|
// packages/rk86/package.json
|
|
1594
1982
|
var package_default = {
|
|
1595
1983
|
name: "rk86",
|
|
1596
|
-
version: "2.0.
|
|
1984
|
+
version: "2.0.14",
|
|
1597
1985
|
description: "\u042D\u043C\u0443\u043B\u044F\u0442\u043E\u0440 \u0420\u0430\u0434\u0438\u043E-86\u0420\u041A (Intel 8080) \u0434\u043B\u044F \u0442\u0435\u0440\u043C\u0438\u043D\u0430\u043B\u0430",
|
|
1598
1986
|
bin: {
|
|
1599
1987
|
rk86: "rk86.js"
|
|
@@ -1615,9 +2003,6 @@ var package_default = {
|
|
|
1615
2003
|
}
|
|
1616
2004
|
};
|
|
1617
2005
|
|
|
1618
|
-
// src/lib/terminal/rk86_terminal.ts
|
|
1619
|
-
import { readFile } from "fs/promises";
|
|
1620
|
-
|
|
1621
2006
|
// src/lib/core/hex.ts
|
|
1622
2007
|
function hex(v, prefix) {
|
|
1623
2008
|
return v.toString(16).toUpperCase();
|
|
@@ -3033,7 +3418,7 @@ class Runner {
|
|
|
3033
3418
|
}
|
|
3034
3419
|
}
|
|
3035
3420
|
execute(options = {}) {
|
|
3036
|
-
const { terminate_address, on_terminate, exit_on_halt } = options;
|
|
3421
|
+
const { terminate_address, on_terminate, exit_on_halt, armed } = options;
|
|
3037
3422
|
clearTimeout(this.execute_timer);
|
|
3038
3423
|
if (!this.paused) {
|
|
3039
3424
|
let batch_ticks = 0;
|
|
@@ -3061,6 +3446,8 @@ class Runner {
|
|
|
3061
3446
|
this.machine.ui.on_visualizer_hit(this.machine.memory.read_raw(this.machine.cpu.pc));
|
|
3062
3447
|
}
|
|
3063
3448
|
batch_instructions += 1;
|
|
3449
|
+
if (armed?.value === false)
|
|
3450
|
+
continue;
|
|
3064
3451
|
if (terminate_address !== undefined && this.machine.cpu.pc === terminate_address) {
|
|
3065
3452
|
on_terminate?.();
|
|
3066
3453
|
return;
|
|
@@ -3655,6 +4042,7 @@ function printHelp() {
|
|
|
3655
4042
|
-l \u0441\u043F\u0438\u0441\u043E\u043A \u0444\u0430\u0439\u043B\u043E\u0432 \u0438\u0437 \u043A\u0430\u0442\u0430\u043B\u043E\u0433\u0430
|
|
3656
4043
|
-m <\u0444\u0430\u0439\u043B> \u043C\u043E\u043D\u0438\u0442\u043E\u0440 (\u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E: \u0432\u0441\u0442\u0440\u043E\u0435\u043D\u043D\u044B\u0439 mon32.bin)
|
|
3657
4044
|
-p \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C \u0444\u0430\u0439\u043B \u0431\u0435\u0437 \u0437\u0430\u043F\u0443\u0441\u043A\u0430
|
|
4045
|
+
-g <\u0430\u0434\u0440\u0435\u0441> \u0430\u0434\u0440\u0435\u0441 \u0437\u0430\u043F\u0443\u0441\u043A\u0430 (\u043D\u0435\u0441\u043E\u0432\u043C\u0435\u0441\u0442\u0438\u043C \u0441 -p)
|
|
3658
4046
|
--exit-halt \u0432\u044B\u0445\u043E\u0434 \u043F\u0440\u0438 \u0432\u044B\u043F\u043E\u043B\u043D\u0435\u043D\u0438\u0438 HLT
|
|
3659
4047
|
--exit-address [\u0430\u0434\u0440\u0435\u0441] \u0432\u044B\u0445\u043E\u0434 \u043F\u0440\u0438 \u043F\u0435\u0440\u0435\u0445\u043E\u0434\u0435 \u043D\u0430 \u0430\u0434\u0440\u0435\u0441 (\u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E: 0xFFFE)
|
|
3660
4048
|
|
|
@@ -3666,6 +4054,8 @@ function printHelp() {
|
|
|
3666
4054
|
bunx rk86 --exit-halt prog.bin \u0432\u044B\u0445\u043E\u0434 \u043F\u0440\u0438 HLT
|
|
3667
4055
|
bunx rk86 --exit-address prog.bin \u0432\u044B\u0445\u043E\u0434 \u043F\u0440\u0438 JMP FFFEh
|
|
3668
4056
|
bunx rk86 -l \u0441\u043F\u0438\u0441\u043E\u043A \u0438\u0437\u0432\u0435\u0441\u0442\u043D\u044B\u0445 \u0444\u0430\u0439\u043B\u043E\u0432
|
|
4057
|
+
bunx rk86 --exit-halt prog.asm \u0441\u043E\u0431\u0440\u0430\u0442\u044C \u0438 \u0437\u0430\u043F\u0443\u0441\u0442\u0438\u0442\u044C .asm \u0444\u0430\u0439\u043B
|
|
4058
|
+
bunx rk86 -g 0x100 prog.bin \u0437\u0430\u043F\u0443\u0441\u043A \u0441 \u0430\u0434\u0440\u0435\u0441\u0430 100h
|
|
3669
4059
|
|
|
3670
4060
|
\u0423\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u0438\u0435:
|
|
3671
4061
|
Ctrl+C \u0432\u044B\u0445\u043E\u0434`);
|
|
@@ -3716,6 +4106,11 @@ async function main() {
|
|
|
3716
4106
|
process.exit(0);
|
|
3717
4107
|
}
|
|
3718
4108
|
const loadOnly = flag(args, "-p");
|
|
4109
|
+
const goAddr = arg(args, "-g", undefined, /^0x[0-9a-fA-F]+$/i, (v) => parseInt(v, 16));
|
|
4110
|
+
if (loadOnly && goAddr !== undefined) {
|
|
4111
|
+
console.error("\u043E\u0448\u0438\u0431\u043A\u0430: -p \u0438 -g \u043D\u0435\u0441\u043E\u0432\u043C\u0435\u0441\u0442\u0438\u043C\u044B");
|
|
4112
|
+
process.exit(1);
|
|
4113
|
+
}
|
|
3719
4114
|
const exitOnHalt = flag(args, "--exit-halt");
|
|
3720
4115
|
const exitAddrValue = arg(args, "--exit-address", "0xFFFE", /^0x[0-9a-fA-F]+$/i, (v) => parseInt(v, 16));
|
|
3721
4116
|
const exitAddr = exitAddrValue !== undefined;
|
|
@@ -3742,18 +4137,44 @@ async function main() {
|
|
|
3742
4137
|
let entryPoint;
|
|
3743
4138
|
let loadInfo = "";
|
|
3744
4139
|
if (programFile) {
|
|
3745
|
-
const
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
4140
|
+
const ext = file_ext(programFile).toLowerCase();
|
|
4141
|
+
if (ext === "asm") {
|
|
4142
|
+
const source = await readFile(programFile, "utf-8");
|
|
4143
|
+
const sections = asm(source);
|
|
4144
|
+
if (sections.length === 0) {
|
|
4145
|
+
console.error("\u043E\u0448\u0438\u0431\u043A\u0430: \u0430\u0441\u0441\u0435\u043C\u0431\u043B\u0435\u0440 \u043D\u0435 \u0432\u0435\u0440\u043D\u0443\u043B \u0441\u0435\u043A\u0446\u0438\u0439");
|
|
4146
|
+
process.exit(1);
|
|
4147
|
+
}
|
|
4148
|
+
const lines = [];
|
|
4149
|
+
for (const section of sections) {
|
|
4150
|
+
const data = section.data;
|
|
4151
|
+
for (let i = 0;i < data.length; i++) {
|
|
4152
|
+
machine.memory.write(section.start + i, data[i]);
|
|
4153
|
+
}
|
|
4154
|
+
const name = section.name ? ` [${section.name}]` : "";
|
|
4155
|
+
lines.push(`${hex16(section.start)}-${hex16(section.end)}${name} (${data.length} \u0431\u0430\u0439\u0442)`);
|
|
4156
|
+
}
|
|
4157
|
+
entryPoint = goAddr ?? sections[0].start;
|
|
4158
|
+
loadInfo = `\u0441\u043E\u0431\u0440\u0430\u043D: ${programFile}
|
|
4159
|
+
` + lines.join(`
|
|
4160
|
+
`) + `
|
|
4161
|
+
\u0437\u0430\u043F\u0443\u0441\u043A: G${hex16(entryPoint)}`;
|
|
3751
4162
|
} else {
|
|
3752
|
-
const
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
4163
|
+
const content = await fetchFile(programFile);
|
|
4164
|
+
const { ok, json } = parse(content);
|
|
4165
|
+
if (ok) {
|
|
4166
|
+
rk86_snapshot_restore(json, machine);
|
|
4167
|
+
entryPoint = parseInt(json.cpu.pc);
|
|
4168
|
+
loadInfo = `\u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043D: ${programFile} (PC=${hex16(entryPoint)})`;
|
|
4169
|
+
} else {
|
|
4170
|
+
const file = parse_rk86_binary(programFile, content);
|
|
4171
|
+
machine.memory.load_file(file);
|
|
4172
|
+
entryPoint = file.entry;
|
|
4173
|
+
loadInfo = `\u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043D: ${programFile} (${hex16(file.start)}-${hex16(file.end)}, G${hex16(file.entry)})`;
|
|
4174
|
+
}
|
|
3756
4175
|
}
|
|
4176
|
+
if (goAddr !== undefined)
|
|
4177
|
+
entryPoint = goAddr;
|
|
3757
4178
|
}
|
|
3758
4179
|
process.stdout.write("\x1B[?25l");
|
|
3759
4180
|
process.stdout.write("\x1B[2J");
|
|
@@ -3763,17 +4184,24 @@ async function main() {
|
|
|
3763
4184
|
machine.screen.start(renderer);
|
|
3764
4185
|
const onTerminate = exitOnHalt || exitAddr ? () => {
|
|
3765
4186
|
renderer.update();
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
4187
|
+
setTimeout(() => {
|
|
4188
|
+
console.log();
|
|
4189
|
+
console.log("\u043F\u0440\u043E\u0433\u0440\u0430\u043C\u043C\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043B\u0430 \u0440\u0430\u0431\u043E\u0442\u0443 \u043D\u0430", hex16(machine.cpu.pc));
|
|
4190
|
+
process.exit(0);
|
|
4191
|
+
}, 1000);
|
|
3769
4192
|
} : undefined;
|
|
4193
|
+
const armed = { value: entryPoint === undefined };
|
|
3770
4194
|
machine.runner.execute({
|
|
3771
4195
|
terminate_address: exitAddr ? exitAddrValue : undefined,
|
|
3772
4196
|
exit_on_halt: exitOnHalt,
|
|
3773
|
-
on_terminate: onTerminate
|
|
4197
|
+
on_terminate: onTerminate,
|
|
4198
|
+
armed
|
|
3774
4199
|
});
|
|
3775
4200
|
if (entryPoint !== undefined && !loadOnly) {
|
|
3776
|
-
setTimeout(() =>
|
|
4201
|
+
setTimeout(() => {
|
|
4202
|
+
machine.cpu.jump(entryPoint);
|
|
4203
|
+
armed.value = true;
|
|
4204
|
+
}, 500);
|
|
3777
4205
|
}
|
|
3778
4206
|
process.on("exit", () => {
|
|
3779
4207
|
process.stdout.write("\x1B[?25h");
|