psyq-asm 0.0.1

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.
Files changed (117) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/LICENSE +56 -0
  3. package/README.md +220 -0
  4. package/bin/psyq-asm.mjs +149 -0
  5. package/dist/asm/assemble.d.ts +10 -0
  6. package/dist/asm/assemble.d.ts.map +1 -0
  7. package/dist/asm/assemble.js +42 -0
  8. package/dist/asm/assemble.js.map +1 -0
  9. package/dist/asm/diagnostics.d.ts +22 -0
  10. package/dist/asm/diagnostics.d.ts.map +1 -0
  11. package/dist/asm/diagnostics.js +40 -0
  12. package/dist/asm/diagnostics.js.map +1 -0
  13. package/dist/asm/directives.d.ts +67 -0
  14. package/dist/asm/directives.d.ts.map +1 -0
  15. package/dist/asm/directives.js +254 -0
  16. package/dist/asm/directives.js.map +1 -0
  17. package/dist/asm/expand.d.ts +21 -0
  18. package/dist/asm/expand.d.ts.map +1 -0
  19. package/dist/asm/expand.js +540 -0
  20. package/dist/asm/expand.js.map +1 -0
  21. package/dist/asm/hazards.d.ts +10 -0
  22. package/dist/asm/hazards.d.ts.map +1 -0
  23. package/dist/asm/hazards.js +196 -0
  24. package/dist/asm/hazards.js.map +1 -0
  25. package/dist/asm/layout.d.ts +17 -0
  26. package/dist/asm/layout.d.ts.map +1 -0
  27. package/dist/asm/layout.js +257 -0
  28. package/dist/asm/layout.js.map +1 -0
  29. package/dist/asm/lexer.d.ts +23 -0
  30. package/dist/asm/lexer.d.ts.map +1 -0
  31. package/dist/asm/lexer.js +81 -0
  32. package/dist/asm/lexer.js.map +1 -0
  33. package/dist/asm/object.d.ts +6 -0
  34. package/dist/asm/object.d.ts.map +1 -0
  35. package/dist/asm/object.js +46 -0
  36. package/dist/asm/object.js.map +1 -0
  37. package/dist/asm/operands.d.ts +49 -0
  38. package/dist/asm/operands.d.ts.map +1 -0
  39. package/dist/asm/operands.js +114 -0
  40. package/dist/asm/operands.js.map +1 -0
  41. package/dist/asm/parser.d.ts +28 -0
  42. package/dist/asm/parser.d.ts.map +1 -0
  43. package/dist/asm/parser.js +60 -0
  44. package/dist/asm/parser.js.map +1 -0
  45. package/dist/asm/relocations.d.ts +42 -0
  46. package/dist/asm/relocations.d.ts.map +1 -0
  47. package/dist/asm/relocations.js +214 -0
  48. package/dist/asm/relocations.js.map +1 -0
  49. package/dist/asm/sections.d.ts +23 -0
  50. package/dist/asm/sections.d.ts.map +1 -0
  51. package/dist/asm/sections.js +81 -0
  52. package/dist/asm/sections.js.map +1 -0
  53. package/dist/asm/stream.d.ts +77 -0
  54. package/dist/asm/stream.d.ts.map +1 -0
  55. package/dist/asm/stream.js +2 -0
  56. package/dist/asm/stream.js.map +1 -0
  57. package/dist/asm/symbols.d.ts +42 -0
  58. package/dist/asm/symbols.d.ts.map +1 -0
  59. package/dist/asm/symbols.js +122 -0
  60. package/dist/asm/symbols.js.map +1 -0
  61. package/dist/errors.d.ts +27 -0
  62. package/dist/errors.d.ts.map +1 -0
  63. package/dist/errors.js +34 -0
  64. package/dist/errors.js.map +1 -0
  65. package/dist/index.d.ts +14 -0
  66. package/dist/index.d.ts.map +1 -0
  67. package/dist/index.js +10 -0
  68. package/dist/index.js.map +1 -0
  69. package/dist/isa/decode.d.ts +8 -0
  70. package/dist/isa/decode.d.ts.map +1 -0
  71. package/dist/isa/decode.js +92 -0
  72. package/dist/isa/decode.js.map +1 -0
  73. package/dist/isa/encode.d.ts +9 -0
  74. package/dist/isa/encode.d.ts.map +1 -0
  75. package/dist/isa/encode.js +124 -0
  76. package/dist/isa/encode.js.map +1 -0
  77. package/dist/isa/fields.d.ts +27 -0
  78. package/dist/isa/fields.d.ts.map +1 -0
  79. package/dist/isa/fields.js +49 -0
  80. package/dist/isa/fields.js.map +1 -0
  81. package/dist/isa/format.d.ts +14 -0
  82. package/dist/isa/format.d.ts.map +1 -0
  83. package/dist/isa/format.js +98 -0
  84. package/dist/isa/format.js.map +1 -0
  85. package/dist/isa/instruction.d.ts +15 -0
  86. package/dist/isa/instruction.d.ts.map +1 -0
  87. package/dist/isa/instruction.js +47 -0
  88. package/dist/isa/instruction.js.map +1 -0
  89. package/dist/isa/registers.d.ts +8 -0
  90. package/dist/isa/registers.d.ts.map +1 -0
  91. package/dist/isa/registers.js +55 -0
  92. package/dist/isa/registers.js.map +1 -0
  93. package/dist/isa/table.d.ts +179 -0
  94. package/dist/isa/table.d.ts.map +1 -0
  95. package/dist/isa/table.js +128 -0
  96. package/dist/isa/table.js.map +1 -0
  97. package/dist/options.d.ts +29 -0
  98. package/dist/options.d.ts.map +1 -0
  99. package/dist/options.js +0 -0
  100. package/dist/options.js.map +1 -0
  101. package/dist/program/decode-words.d.ts +9 -0
  102. package/dist/program/decode-words.d.ts.map +1 -0
  103. package/dist/program/decode-words.js +87 -0
  104. package/dist/program/decode-words.js.map +1 -0
  105. package/dist/program/format-program.d.ts +12 -0
  106. package/dist/program/format-program.d.ts.map +1 -0
  107. package/dist/program/format-program.js +37 -0
  108. package/dist/program/format-program.js.map +1 -0
  109. package/dist/public-types.d.ts +253 -0
  110. package/dist/public-types.d.ts.map +1 -0
  111. package/dist/public-types.js +2 -0
  112. package/dist/public-types.js.map +1 -0
  113. package/dist/util.d.ts +3 -0
  114. package/dist/util.d.ts.map +1 -0
  115. package/dist/util.js +11 -0
  116. package/dist/util.js.map +1 -0
  117. package/package.json +82 -0
@@ -0,0 +1,124 @@
1
+ // SPDX-License-Identifier: MIT
2
+ import { InvalidInstructionError } from '../errors.js';
3
+ import { isRecord } from '../options.js';
4
+ import { COP_SLOTS } from './fields.js';
5
+ import { rowFor } from './table.js';
6
+ const EXPECTED_KIND = {
7
+ rd: 'gpr',
8
+ rs: 'gpr',
9
+ rt: 'gpr',
10
+ sa: 'shamt',
11
+ imm16s: 'imm',
12
+ imm16u: 'imm',
13
+ mem: 'mem',
14
+ branch: 'branch',
15
+ target: 'target',
16
+ code20: 'imm',
17
+ code10hi: 'imm',
18
+ code10: 'imm',
19
+ imm25: 'imm',
20
+ cop0: 'cop',
21
+ cop2d: 'cop',
22
+ cop2c: 'cop',
23
+ cop2dRt: 'cop',
24
+ };
25
+ function fieldReader(operand, position) {
26
+ return (key, min, max, what) => {
27
+ const value = operand[key];
28
+ if (typeof value !== 'number' || !Number.isInteger(value) || value < min || value > max) {
29
+ throw new InvalidInstructionError(`${position}: ${what} must be an integer from ${String(min)} to ${String(max)}, not ${String(value)}.`);
30
+ }
31
+ return value;
32
+ };
33
+ }
34
+ /** The bits one operand contributes to the word. */
35
+ function fieldBits(slot, field, operand, position) {
36
+ switch (slot) {
37
+ case 'rd':
38
+ return field('number', 0, 31, 'register') << 11;
39
+ case 'rs':
40
+ return field('number', 0, 31, 'register') << 21;
41
+ case 'rt':
42
+ return field('number', 0, 31, 'register') << 16;
43
+ case 'sa':
44
+ return field('value', 0, 31, 'shift amount') << 6;
45
+ case 'imm16s':
46
+ return field('value', -0x8000, 0x7fff, 'signed 16-bit immediate') & 0xffff;
47
+ case 'imm16u':
48
+ return field('value', 0, 0xffff, 'unsigned 16-bit immediate');
49
+ case 'mem':
50
+ return ((field('base', 0, 31, 'base register') << 21) |
51
+ (field('offset', -0x8000, 0x7fff, 'offset') & 0xffff));
52
+ case 'branch':
53
+ return field('displacement', -0x8000, 0x7fff, 'branch displacement') & 0xffff;
54
+ case 'target':
55
+ return field('index', 0, 0x03ffffff, 'jump index');
56
+ case 'code20':
57
+ return field('value', 0, 0xfffff, 'code') << 6;
58
+ case 'code10hi':
59
+ return field('value', 0, 0x3ff, 'code') << 16;
60
+ case 'code10':
61
+ return field('value', 0, 0x3ff, 'code') << 6;
62
+ case 'imm25':
63
+ return field('value', 0, 0x01ffffff, 'coprocessor command');
64
+ case 'cop0':
65
+ case 'cop2d':
66
+ case 'cop2c':
67
+ case 'cop2dRt': {
68
+ const n = field('number', 0, 31, 'coprocessor register');
69
+ const { unit, space, shift } = COP_SLOTS[slot];
70
+ if (operand['unit'] !== unit || operand['space'] !== space) {
71
+ throw new InvalidInstructionError(`${position} must be a coprocessor ${String(unit)} ${space} register.`);
72
+ }
73
+ return n << shift;
74
+ }
75
+ }
76
+ }
77
+ /** Fill omitted optional operands so the list matches the row's syntax. */
78
+ function canonicalOperands(row, operands) {
79
+ if (row.optional === 'trailing-zero' && operands.length < row.syntax.length) {
80
+ const missing = row.syntax.length - operands.length;
81
+ return [...operands, ...Array(missing).fill({ kind: 'imm', value: 0 })];
82
+ }
83
+ if (row.optional === 'leading-ra' && operands.length === row.syntax.length - 1) {
84
+ return [{ kind: 'gpr', number: 31 }, ...operands];
85
+ }
86
+ return operands;
87
+ }
88
+ /**
89
+ * Encode one instruction. The operands are in assembly order, as `decode`
90
+ * produces them; `jalr rs` may omit the link register and `syscall`, `break`,
91
+ * and `tge` may omit their code. Throws `InvalidInstructionError` for an
92
+ * unknown mnemonic or an operand that does not fit.
93
+ */
94
+ export function encode(instruction) {
95
+ const candidate = instruction;
96
+ if (!isRecord(candidate) ||
97
+ typeof candidate['mnemonic'] !== 'string' ||
98
+ !Array.isArray(candidate['operands'])) {
99
+ throw new InvalidInstructionError('instruction must be an object with a mnemonic and an operands array.');
100
+ }
101
+ const mnemonic = candidate['mnemonic'];
102
+ const given = candidate['operands'];
103
+ const row = rowFor(mnemonic);
104
+ if (row === undefined) {
105
+ throw new InvalidInstructionError(`unknown mnemonic ${JSON.stringify(mnemonic)}.`);
106
+ }
107
+ const operands = canonicalOperands(row, given);
108
+ if (operands.length !== row.syntax.length) {
109
+ throw new InvalidInstructionError(`${mnemonic} takes ${String(row.syntax.length)} operands, not ${String(given.length)}.`);
110
+ }
111
+ let word = row.value;
112
+ row.syntax.forEach((slot, index) => {
113
+ const operand = operands[index];
114
+ const position = `${mnemonic} operand ${String(index + 1)}`;
115
+ const expected = EXPECTED_KIND[slot];
116
+ if (!isRecord(operand) || operand['kind'] !== expected) {
117
+ const kind = isRecord(operand) ? String(operand['kind']) : typeof operand;
118
+ throw new InvalidInstructionError(`${position} must be of kind ${expected}, not ${kind}.`);
119
+ }
120
+ word |= fieldBits(slot, fieldReader(operand, position), operand, position);
121
+ });
122
+ return word >>> 0;
123
+ }
124
+ //# sourceMappingURL=encode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encode.js","sourceRoot":"","sources":["../../src/isa/encode.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Operand slots and the bit fields they occupy in an R3000 word.
3
+ *
4
+ * Bit layout: op[31:26] rs[25:21] rt[20:16] rd[15:11] sa[10:6] fn[5:0],
5
+ * imm[15:0], target[25:0].
6
+ */
7
+ /** Where an operand lives in the word and how it is written in assembly. */
8
+ export type Slot = 'rd' | 'rs' | 'rt' | 'sa' | 'imm16s' | 'imm16u' | 'mem' | 'branch' | 'target' | 'code20' | 'code10hi' | 'code10' | 'imm25' | CopSlot;
9
+ /** Coprocessor register slots: which unit, which register space, which field. */
10
+ export type CopSlot = 'cop0' | 'cop2d' | 'cop2c' | 'cop2dRt';
11
+ export declare const COP_SLOTS: Readonly<Record<CopSlot, {
12
+ readonly unit: 0 | 2;
13
+ readonly space: 'data' | 'control';
14
+ readonly shift: 11 | 16;
15
+ }>>;
16
+ /** The bits of the word each slot owns. */
17
+ export declare const SLOT_BITS: Readonly<Record<Slot, number>>;
18
+ /** Sign-extend the low 16 bits of `value`. */
19
+ export declare function signExtend16(value: number): number;
20
+ /**
21
+ * The `%hi` half of a 32-bit value: the upper 16 bits, adjusted so that adding
22
+ * the sign-extended `%lo` half reconstructs the value.
23
+ */
24
+ export declare function hi16(value: number): number;
25
+ /** The `%lo` half of a 32-bit value, as a field (0 to 0xFFFF). */
26
+ export declare function lo16(value: number): number;
27
+ //# sourceMappingURL=fields.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fields.d.ts","sourceRoot":"","sources":["../../src/isa/fields.ts"],"names":[],"mappings":"AACA;;;;;GAKG;AAEH,4EAA4E;AAC5E,MAAM,MAAM,IAAI,GACZ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,QAAQ,GACR,QAAQ,GACR,KAAK,GACL,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,UAAU,GACV,QAAQ,GACR,OAAO,GACP,OAAO,CAAC;AAEZ,iFAAiF;AACjF,MAAM,MAAM,OAAO,GACf,MAAM,GACN,OAAO,GACP,OAAO,GACP,SAAS,CAAC;AAEd,eAAO,MAAM,SAAS,EAAE,QAAQ,CAC9B,MAAM,CACJ,OAAO,EACP;IAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,GAAG,EAAE,CAAA;CAAE,CACtF,CAMD,CAAC;AAEH,2CAA2C;AAC3C,eAAO,MAAM,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAkBnD,CAAC;AAEH,8CAA8C;AAC9C,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;;GAGG;AACH,wBAAgB,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1C;AAED,kEAAkE;AAClE,wBAAgB,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1C"}
@@ -0,0 +1,49 @@
1
+ // SPDX-License-Identifier: MIT
2
+ /**
3
+ * Operand slots and the bit fields they occupy in an R3000 word.
4
+ *
5
+ * Bit layout: op[31:26] rs[25:21] rt[20:16] rd[15:11] sa[10:6] fn[5:0],
6
+ * imm[15:0], target[25:0].
7
+ */
8
+ export const COP_SLOTS = Object.freeze({
9
+ cop0: { unit: 0, space: 'data', shift: 11 },
10
+ cop2d: { unit: 2, space: 'data', shift: 11 },
11
+ cop2c: { unit: 2, space: 'control', shift: 11 },
12
+ cop2dRt: { unit: 2, space: 'data', shift: 16 },
13
+ });
14
+ /** The bits of the word each slot owns. */
15
+ export const SLOT_BITS = Object.freeze({
16
+ rd: 0x0000f800,
17
+ rs: 0x03e00000,
18
+ rt: 0x001f0000,
19
+ sa: 0x000007c0,
20
+ imm16s: 0x0000ffff,
21
+ imm16u: 0x0000ffff,
22
+ mem: 0x03e0ffff,
23
+ branch: 0x0000ffff,
24
+ target: 0x03ffffff,
25
+ code20: 0x03ffffc0,
26
+ code10hi: 0x03ff0000,
27
+ code10: 0x0000ffc0,
28
+ imm25: 0x01ffffff,
29
+ cop0: 0x0000f800,
30
+ cop2d: 0x0000f800,
31
+ cop2c: 0x0000f800,
32
+ cop2dRt: 0x001f0000,
33
+ });
34
+ /** Sign-extend the low 16 bits of `value`. */
35
+ export function signExtend16(value) {
36
+ return (value << 16) >> 16;
37
+ }
38
+ /**
39
+ * The `%hi` half of a 32-bit value: the upper 16 bits, adjusted so that adding
40
+ * the sign-extended `%lo` half reconstructs the value.
41
+ */
42
+ export function hi16(value) {
43
+ return ((value + 0x8000) >>> 16) & 0xffff;
44
+ }
45
+ /** The `%lo` half of a 32-bit value, as a field (0 to 0xFFFF). */
46
+ export function lo16(value) {
47
+ return value & 0xffff;
48
+ }
49
+ //# sourceMappingURL=fields.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fields.js","sourceRoot":"","sources":["../../src/isa/fields.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B;;;;;GAKG;AA0BH,MAAM,CAAC,MAAM,SAAS,GAKlB,MAAM,CAAC,MAAM,CAAC;IAChB,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE;IAC3C,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE;IAC5C,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,EAAE;IAC/C,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE;CAC/C,CAAC,CAAC;AAEH,2CAA2C;AAC3C,MAAM,CAAC,MAAM,SAAS,GAAmC,MAAM,CAAC,MAAM,CAAC;IACrE,EAAE,EAAE,UAAU;IACd,EAAE,EAAE,UAAU;IACd,EAAE,EAAE,UAAU;IACd,EAAE,EAAE,UAAU;IACd,MAAM,EAAE,UAAU;IAClB,MAAM,EAAE,UAAU;IAClB,GAAG,EAAE,UAAU;IACf,MAAM,EAAE,UAAU;IAClB,MAAM,EAAE,UAAU;IAClB,MAAM,EAAE,UAAU;IAClB,QAAQ,EAAE,UAAU;IACpB,MAAM,EAAE,UAAU;IAClB,KAAK,EAAE,UAAU;IACjB,IAAI,EAAE,UAAU;IAChB,KAAK,EAAE,UAAU;IACjB,KAAK,EAAE,UAAU;IACjB,OAAO,EAAE,UAAU;CACpB,CAAC,CAAC;AAEH,8CAA8C;AAC9C,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;AAC7B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,IAAI,CAAC,KAAa;IAChC,OAAO,CAAC,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC,GAAG,MAAM,CAAC;AAC5C,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,IAAI,CAAC,KAAa;IAChC,OAAO,KAAK,GAAG,MAAM,CAAC;AACxB,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { FormatStyle, Instruction, Operand, UnknownInstruction } from '../public-types.js';
2
+ import { type NormalizedFormatStyle } from '../options.js';
3
+ /** A number in the chosen radix; hexadecimal digits are upper case. */
4
+ export declare function formatNumber(value: number, hex: boolean): string;
5
+ /** A branch target relative to the branch itself: `.+12` is two instructions past the delay slot. */
6
+ export declare function formatDisplacement(displacement: number): string;
7
+ export declare function formatOperand(operand: Operand, style: NormalizedFormatStyle): string;
8
+ /**
9
+ * Render one instruction as assembly text: `lw $v0,0x20($s0)`,
10
+ * `cop2 0x180001`, `.word 0xFFFFFFFF` for an unknown word. Branch targets are
11
+ * written relative to the branch (`.+12`); `formatProgram` writes labels.
12
+ */
13
+ export declare function format(instruction: Instruction | UnknownInstruction, style?: FormatStyle): string;
14
+ //# sourceMappingURL=format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/isa/format.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAChG,OAAO,EAAuB,KAAK,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAOhF,uEAAuE;AACvE,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,MAAM,CAIhE;AAED,qGAAqG;AACrG,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAG/D;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,qBAAqB,GAAG,MAAM,CAkBpF;AA4DD;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,WAAW,EAAE,WAAW,GAAG,kBAAkB,EAAE,KAAK,CAAC,EAAE,WAAW,GAAG,MAAM,CAQjG"}
@@ -0,0 +1,98 @@
1
+ import { validateFormatStyle } from '../options.js';
2
+ import { REGISTER_NAMES } from './registers.js';
3
+ function register(n, style) {
4
+ return style.registers === 'numeric' ? `$${String(n)}` : `$${REGISTER_NAMES[n] ?? String(n)}`;
5
+ }
6
+ /** A number in the chosen radix; hexadecimal digits are upper case. */
7
+ export function formatNumber(value, hex) {
8
+ if (!hex)
9
+ return String(value);
10
+ const digits = Math.abs(value).toString(16).toUpperCase();
11
+ return value < 0 ? `-0x${digits}` : `0x${digits}`;
12
+ }
13
+ /** A branch target relative to the branch itself: `.+12` is two instructions past the delay slot. */
14
+ export function formatDisplacement(displacement) {
15
+ const bytes = 4 + displacement * 4;
16
+ return bytes < 0 ? `.-${String(-bytes)}` : `.+${String(bytes)}`;
17
+ }
18
+ export function formatOperand(operand, style) {
19
+ switch (operand.kind) {
20
+ case 'gpr':
21
+ return register(operand.number, style);
22
+ case 'cop':
23
+ return `$${String(operand.number)}`;
24
+ case 'imm':
25
+ // Trap and syscall codes read naturally in decimal (`break 7`).
26
+ return formatNumber(operand.value, style.hex && (operand.bits === 16 || operand.bits === 25));
27
+ case 'shamt':
28
+ return String(operand.value);
29
+ case 'mem':
30
+ return `${formatNumber(operand.offset, style.hex)}(${register(operand.base, style)})`;
31
+ case 'branch':
32
+ return formatDisplacement(operand.displacement);
33
+ case 'target':
34
+ return formatNumber(operand.index * 4, style.hex);
35
+ }
36
+ }
37
+ function isZeroRegister(operand) {
38
+ return operand?.kind === 'gpr' && operand.number === 0;
39
+ }
40
+ /** Apply the pseudo-instruction spellings, and drop optional operands at their defaults. */
41
+ function spelling(instruction, pseudo) {
42
+ const { mnemonic, operands } = instruction;
43
+ const [first, second, third] = operands;
44
+ if (pseudo) {
45
+ if (mnemonic === 'sll' &&
46
+ operands.length === 3 &&
47
+ isZeroRegister(first) &&
48
+ isZeroRegister(second)) {
49
+ if (third?.kind === 'shamt' && third.value === 0)
50
+ return { name: 'nop', operands: [] };
51
+ }
52
+ if (mnemonic === 'addu' && operands.length === 3 && isZeroRegister(third)) {
53
+ return { name: 'move', operands: [first, second].filter((o) => o !== undefined) };
54
+ }
55
+ if ((mnemonic === 'beq' || mnemonic === 'bne') &&
56
+ operands.length === 3 &&
57
+ isZeroRegister(second)) {
58
+ return {
59
+ name: mnemonic === 'beq' ? 'beqz' : 'bnez',
60
+ operands: [first, third].filter((o) => o !== undefined),
61
+ };
62
+ }
63
+ }
64
+ if (mnemonic === 'jalr' &&
65
+ operands.length === 2 &&
66
+ first?.kind === 'gpr' &&
67
+ first.number === 31) {
68
+ return { name: mnemonic, operands: operands.slice(1) };
69
+ }
70
+ // A break keeps both codes unless both are zero: `break n` alone would be
71
+ // split into two codes when re-assembled.
72
+ if (mnemonic === 'break' && operands.every(isZeroCode))
73
+ return { name: mnemonic, operands: [] };
74
+ if ((mnemonic === 'syscall' || (mnemonic === 'tge' && operands.length === 3)) &&
75
+ isZeroCode(operands.at(-1))) {
76
+ return { name: mnemonic, operands: operands.slice(0, -1) };
77
+ }
78
+ return { name: mnemonic, operands };
79
+ }
80
+ function isZeroCode(operand) {
81
+ return operand?.kind === 'imm' && operand.value === 0;
82
+ }
83
+ /**
84
+ * Render one instruction as assembly text: `lw $v0,0x20($s0)`,
85
+ * `cop2 0x180001`, `.word 0xFFFFFFFF` for an unknown word. Branch targets are
86
+ * written relative to the branch (`.+12`); `formatProgram` writes labels.
87
+ */
88
+ export function format(instruction, style) {
89
+ const normalized = validateFormatStyle(style);
90
+ if (instruction.mnemonic === '.word') {
91
+ return `.word 0x${instruction.word.toString(16).toUpperCase().padStart(8, '0')}`;
92
+ }
93
+ const { name, operands } = spelling(instruction, normalized.pseudo);
94
+ if (operands.length === 0)
95
+ return name;
96
+ return `${name} ${operands.map((o) => formatOperand(o, normalized)).join(',')}`;
97
+ }
98
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/isa/format.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /** Derivations shared by the encoder and decoder: reserved bits and register use. */
2
+ import type { Instruction, Operand } from '../public-types.js';
3
+ import type { IsaRow, RegisterRef } from './table.js';
4
+ /** Bits that must be zero in a word of this row: neither selector nor operand. */
5
+ export declare function reservedBits(row: IsaRow): number;
6
+ /**
7
+ * Resolve register references against an encoded word. `$0` is hard-wired to
8
+ * zero, so it is never reported as read or written.
9
+ */
10
+ export declare function registersOf(refs: readonly RegisterRef[], word: number): number[];
11
+ /** Registers that count as read for the load-delay rule. */
12
+ export declare function hazardReadsOf(row: IsaRow, word: number): number[];
13
+ /** Assemble the public `Instruction` for a row, its canonical operands, and its word. */
14
+ export declare function buildInstruction(row: IsaRow, operands: readonly Operand[], word: number): Instruction;
15
+ //# sourceMappingURL=instruction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instruction.d.ts","sourceRoot":"","sources":["../../src/isa/instruction.ts"],"names":[],"mappings":"AACA,qFAAqF;AACrF,OAAO,KAAK,EAAE,WAAW,EAAY,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAEzE,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEtD,kFAAkF;AAClF,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGhD;AAeD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,WAAW,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAOhF;AAED,4DAA4D;AAC5D,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAEjE;AAED,yFAAyF;AACzF,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,SAAS,OAAO,EAAE,EAC5B,IAAI,EAAE,MAAM,GACX,WAAW,CASb"}
@@ -0,0 +1,47 @@
1
+ import { SLOT_BITS } from './fields.js';
2
+ /** Bits that must be zero in a word of this row: neither selector nor operand. */
3
+ export function reservedBits(row) {
4
+ const owned = row.syntax.reduce((bits, slot) => bits | SLOT_BITS[slot], row.mask);
5
+ return ~owned >>> 0;
6
+ }
7
+ function registerOf(ref, word) {
8
+ switch (ref) {
9
+ case 'rs':
10
+ return (word >>> 21) & 31;
11
+ case 'rt':
12
+ return (word >>> 16) & 31;
13
+ case 'rd':
14
+ return (word >>> 11) & 31;
15
+ case 31:
16
+ return 31;
17
+ }
18
+ }
19
+ /**
20
+ * Resolve register references against an encoded word. `$0` is hard-wired to
21
+ * zero, so it is never reported as read or written.
22
+ */
23
+ export function registersOf(refs, word) {
24
+ const out = [];
25
+ for (const ref of refs) {
26
+ const n = registerOf(ref, word);
27
+ if (n !== 0 && !out.includes(n))
28
+ out.push(n);
29
+ }
30
+ return out;
31
+ }
32
+ /** Registers that count as read for the load-delay rule. */
33
+ export function hazardReadsOf(row, word) {
34
+ return registersOf(row.hazardReads ?? row.reads, word);
35
+ }
36
+ /** Assemble the public `Instruction` for a row, its canonical operands, and its word. */
37
+ export function buildInstruction(row, operands, word) {
38
+ return {
39
+ mnemonic: row.mnemonic,
40
+ format: row.format,
41
+ operands,
42
+ reads: registersOf(row.reads, word),
43
+ writes: registersOf(row.writes, word),
44
+ hazardClass: row.hazard,
45
+ };
46
+ }
47
+ //# sourceMappingURL=instruction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instruction.js","sourceRoot":"","sources":["../../src/isa/instruction.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGxC,kFAAkF;AAClF,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;IAClF,OAAO,CAAC,KAAK,KAAK,CAAC,CAAC;AACtB,CAAC;AAED,SAAS,UAAU,CAAC,GAAgB,EAAE,IAAY;IAChD,QAAQ,GAAG,EAAE,CAAC;QACZ,KAAK,IAAI;YACP,OAAO,CAAC,IAAI,KAAK,EAAE,CAAC,GAAG,EAAE,CAAC;QAC5B,KAAK,IAAI;YACP,OAAO,CAAC,IAAI,KAAK,EAAE,CAAC,GAAG,EAAE,CAAC;QAC5B,KAAK,IAAI;YACP,OAAO,CAAC,IAAI,KAAK,EAAE,CAAC,GAAG,EAAE,CAAC;QAC5B,KAAK,EAAE;YACL,OAAO,EAAE,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,IAA4B,EAAE,IAAY;IACpE,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAChC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;YAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,aAAa,CAAC,GAAW,EAAE,IAAY;IACrD,OAAO,WAAW,CAAC,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AACzD,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,gBAAgB,CAC9B,GAAW,EACX,QAA4B,EAC5B,IAAY;IAEZ,OAAO;QACL,QAAQ,EAAE,GAAG,CAAC,QAAoB;QAClC,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,QAAQ;QACR,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC;QACnC,MAAM,EAAE,WAAW,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC;QACrC,WAAW,EAAE,GAAG,CAAC,MAAM;KACxB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ /** General-purpose register names, by number, in the o32 ABI spelling ASPSX accepts. */
2
+ export declare const REGISTER_NAMES: readonly string[];
3
+ /**
4
+ * Parse a register spelled `$n` (0 to 31) or `$name` (`$zero`, `$v0`, `$s8`,
5
+ * `$fp`, ...). Returns `undefined` for anything else.
6
+ */
7
+ export declare function parseRegister(text: string): number | undefined;
8
+ //# sourceMappingURL=registers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registers.d.ts","sourceRoot":"","sources":["../../src/isa/registers.ts"],"names":[],"mappings":"AACA,wFAAwF;AACxF,eAAO,MAAM,cAAc,EAAE,SAAS,MAAM,EAiC1C,CAAC;AAOH;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAQ9D"}
@@ -0,0 +1,55 @@
1
+ // SPDX-License-Identifier: MIT
2
+ /** General-purpose register names, by number, in the o32 ABI spelling ASPSX accepts. */
3
+ export const REGISTER_NAMES = Object.freeze([
4
+ 'zero',
5
+ 'at',
6
+ 'v0',
7
+ 'v1',
8
+ 'a0',
9
+ 'a1',
10
+ 'a2',
11
+ 'a3',
12
+ 't0',
13
+ 't1',
14
+ 't2',
15
+ 't3',
16
+ 't4',
17
+ 't5',
18
+ 't6',
19
+ 't7',
20
+ 's0',
21
+ 's1',
22
+ 's2',
23
+ 's3',
24
+ 's4',
25
+ 's5',
26
+ 's6',
27
+ 's7',
28
+ 't8',
29
+ 't9',
30
+ 'k0',
31
+ 'k1',
32
+ 'gp',
33
+ 'sp',
34
+ 'fp',
35
+ 'ra',
36
+ ]);
37
+ const BY_NAME = new Map([
38
+ ...REGISTER_NAMES.map((name, index) => [name, index]),
39
+ ['s8', 30],
40
+ ]);
41
+ /**
42
+ * Parse a register spelled `$n` (0 to 31) or `$name` (`$zero`, `$v0`, `$s8`,
43
+ * `$fp`, ...). Returns `undefined` for anything else.
44
+ */
45
+ export function parseRegister(text) {
46
+ if (!text.startsWith('$'))
47
+ return undefined;
48
+ const body = text.slice(1);
49
+ if (/^(0|[1-9]\d?)$/.test(body)) {
50
+ const n = Number(body);
51
+ return n <= 31 ? n : undefined;
52
+ }
53
+ return BY_NAME.get(body);
54
+ }
55
+ //# sourceMappingURL=registers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registers.js","sourceRoot":"","sources":["../../src/isa/registers.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,wFAAwF;AACxF,MAAM,CAAC,MAAM,cAAc,GAAsB,MAAM,CAAC,MAAM,CAAC;IAC7D,MAAM;IACN,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;CACL,CAAC,CAAC;AAEH,MAAM,OAAO,GAAgC,IAAI,GAAG,CAAC;IACnD,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,CAAU,CAAC;IAC9D,CAAC,IAAI,EAAE,EAAE,CAAC;CACX,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC3B,IAAI,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAChC,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QACvB,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACjC,CAAC;IACD,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC"}