@specy/risc-v 3.6.2 → 3.7.0

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/README.md CHANGED
@@ -13,6 +13,16 @@ First, create an instance of the simulator with `makeRiscVFromFiles`. Supply a v
13
13
 
14
14
  Before running the simulator, you must assemble and initialize it. You can then step through the program, simulate with breakpoints, or simulate with a limit.
15
15
 
16
+ The optional third factory argument selects the assembly profile:
17
+
18
+ ```typescript
19
+ const core = makeRiscVFromFiles(files, 'main.s', { assemblerProfile: 'gnu-compiler-v1' });
20
+ ```
21
+
22
+ Omission selects `rars`. `RISCV.assemblerProfiles` lists supported profiles; every present invalid profile throws. GNU compiler v1 provides independent named sections, explicit data alignment, exact eight-byte data, byte-valued string escapes, bounded expressions/aliases, numeric labels, and absolute/PC-relative address fixups. It uses fixed instruction expansions and rejects unsupported directives, ISA attributes, relocations and unresolved runtime helpers. Units link with ld semantics: global and weak symbols (an undefined weak reference is zero), COMDAT groups (the first copy is kept), and `.init_array`/`.fini_array` with ld-provided `__init_array_start`/`__init_array_end` bounds. Global labels enter the global symbol table, so the start label finds them. It does not load or link ELF, compressed/vector instructions, TLS or a standard library. RARS retains its existing educational syntax and macros.
23
+
24
+ `getAddressOfLabel(name)` returns a defined label/alias address after successful assembly, or `-1` when absent. Profile state is per program; width, memory and execution state retain the existing single-instance constraint.
25
+
16
26
  ⚠️**WARNING**⚠️ You must have only one instance of the simulator at a time. Memory, registers, and other state may be shared or behave unpredictably with multiple instances.
17
27
 
18
28
  ```typescript
package/dist/index.d.mts CHANGED
@@ -1,3 +1,43 @@
1
+ type AssemblerProfile = 'rars' | 'gnu-compiler-v1';
2
+ /**
3
+ * GNU compiler assembly members and the index naming the member that defines each global. A Build
4
+ * pulls a member only to resolve a global the program uses and does not define, as ld pulls members
5
+ * out of an archive, and keeps pulling for the globals those members use in turn. Members are always
6
+ * assembled with the `gnu-compiler-v1` profile, whatever profile the program uses, and their paths
7
+ * never meet the program's Files.
8
+ */
9
+ type RuntimeLibrary = {
10
+ /** Canonical member path to its source. */
11
+ members: Record<string, string>;
12
+ /** Global symbol to the path of the member defining it. */
13
+ index: Record<string, string>;
14
+ /**
15
+ * Globals the library supplies even to a weak reference, which otherwise pulls no member: GCC
16
+ * refers to `__cxa_pure_virtual` weakly from every abstract class's vtable.
17
+ */
18
+ resolveWeak?: string[];
19
+ };
20
+ type AssemblyOptions = {
21
+ assemblerProfile?: AssemblerProfile;
22
+ /**
23
+ * The global execution starts at instead of `main`. The link must define it, and with a library
24
+ * it pulls its own member, as ld's entry symbol does: `_start` brings in a library's startup code.
25
+ */
26
+ entrySymbol?: string;
27
+ /** Libraries searched in order: the first one whose index names a symbol supplies it. */
28
+ libraries?: RuntimeLibrary[];
29
+ };
30
+ /** The globals one GNU compiler unit defines and the ones it uses without defining. */
31
+ type GnuUnitSymbols = {
32
+ /** Globals the unit defines, strong or weak. */
33
+ defined: string[];
34
+ /** The defined globals that are weak. */
35
+ weak: string[];
36
+ /** Globals the unit uses without defining, other than weak references, which pull nothing. */
37
+ references: string[];
38
+ /** Why the unit could not be parsed; empty when it parsed. */
39
+ errors: string[];
40
+ };
1
41
  type JsInstructionToken = {
2
42
  /** One-based column in the processed source line. */
3
43
  sourceColumn: number;
@@ -135,9 +175,22 @@ type HandlerMap = {
135
175
  in: [];
136
176
  out: number;
137
177
  };
178
+ /**
179
+ * A read of standard input (descriptor 0): answer with the bytes left over from the current
180
+ * line or else one new line, at most `length` of them, as `[count, bytes]`. A count of 0 is end
181
+ * of input and -1 a failed read. Return a promise to wait for the user.
182
+ */
138
183
  stdIn: {
139
184
  in: [buffer: number[], length: number];
140
- out: void;
185
+ out: [count: number, buffer: number[]];
186
+ };
187
+ /**
188
+ * Syscall 62 (lseek): move an open file's position. `whence` is 0 from the start, 1 from the
189
+ * current position, 2 from the end. Answer with the new position, or -1 when the seek fails.
190
+ */
191
+ seekFile: {
192
+ in: [fileDescriptor: number, offset: number, whence: number];
193
+ out: number;
141
194
  };
142
195
  stdOut: {
143
196
  in: [buffer: number[]];
@@ -211,8 +264,14 @@ type RISCVAssembleResult = {
211
264
  hasWarnings: boolean;
212
265
  };
213
266
  declare class RISCV {
267
+ static readonly assemblerProfiles: readonly AssemblerProfile[];
214
268
  static makeRiscVFromFiles: typeof makeRiscVFromFiles;
215
269
  static initializeRISCV: typeof initializeRISCV;
270
+ /**
271
+ * The globals one `gnu-compiler-v1` unit defines and uses, without laying it out or touching
272
+ * memory, for building a library index. Uses the current width, so call `setIs64Bit` first.
273
+ */
274
+ static analyzeGnuUnit(path: string, source: string): GnuUnitSymbols;
216
275
  static getInstructionSet(): JsInstruction[];
217
276
  static setIs64Bit(is64Bit: boolean): void;
218
277
  static is64Bit(): boolean;
@@ -556,6 +615,8 @@ interface JsRiscV {
556
615
  * @returns The label at the given address, or null if no label is found.
557
616
  */
558
617
  getLabelAtAddress(address: number): string | null;
618
+ /** Address of a defined label/alias, or -1 if absent. Requires successful assembly. */
619
+ getAddressOfLabel(label: string): number;
559
620
  /**
560
621
  * Sets whether the undo feature is enabled.
561
622
  * @param enabled True to enable the undo feature, false to disable it.
@@ -692,6 +753,15 @@ interface JsRiscV {
692
753
  * carries what it changed, with the old and the new value of each write.
693
754
  */
694
755
  getUndoGroups(): JsUndoGroup[];
756
+ /**
757
+ * The newest `max` entries of `getUndoGroups`, read from the top of the history without
758
+ * grouping the rest of it: what a panel showing the latest steps of a large history wants.
759
+ */
760
+ getUndoGroupsUpTo(max: number): JsUndoGroup[];
761
+ /** `max` entries of `getUndoGroups` after the newest `skip`, which are counted but never built. */
762
+ getUndoGroupsRange(skip: number, max: number): JsUndoGroup[];
763
+ /** How many entries `undo()` can still pop, counted the way `getUndoGroups` groups them. */
764
+ getUndoDepth(): number;
695
765
  /**
696
766
  * Opens a Poke: a register or memory value changed by the host between two instructions,
697
767
  * recorded in this history as a step of its own.
@@ -814,9 +884,10 @@ interface JsRiscV {
814
884
  * snapshotted by this call; only the entry file and files reached through `.include` are assembled.
815
885
  * @param files Source text keyed by canonical source path.
816
886
  * @param entryFile Canonical path of the file from which include expansion starts.
887
+ * @param options The assembler profile, the entry symbol and the libraries to link; see `AssemblyOptions`.
817
888
  * @returns A new `JsRiscV` object.
818
889
  */
819
- declare function makeRiscVFromFiles(files: RISCVSourceSet, entryFile: string): JsRiscV;
890
+ declare function makeRiscVFromFiles(files: RISCVSourceSet, entryFile: string, options?: AssemblyOptions): JsRiscV;
820
891
  /**
821
892
  * Initializes the RISCV simulator.
822
893
  */
@@ -829,4 +900,4 @@ declare function bigintToHighLow(value: bigint): [high: number, low: number];
829
900
  */
830
901
  declare function highLowToBigint(high: number, low: number): bigint;
831
902
 
832
- export { BackStepAction, ConfirmResult, type CsrRegisterName, DialogType, type FloatingPointRegisterName, type HandlerMap, type HandlerMapFns, type JsBackStep, type JsInstruction, type JsInstructionToken, type JsInstructionUndoGroup, type JsPokeMemoryWrite, type JsPokeRegisterWrite, type JsPokeUndoGroup, type JsPokeWrite, type JsProgramStatement, type JsRiscV, type JsRiscVStackFrame, type JsUndoGroup, type MemoryAccessObserver, type MemoryObserverHandle, type MemoryWriteObserver, RISCV, type RISCVAssembleError, type RISCVAssembleResult, RISCVRegisters, type RISCVSourceLocation, type RISCVSourceSet, RISCV_CSR_REGISTERS, RISCV_FLOATING_POINT_REGISTERS, RISCV_REGISTERS, type RegisterName, type RiscvTokenizedLine, StopReason, bigintToHighLow, highLowToBigint, makeRiscVFromFiles, registerHandlers, unimplementedHandler };
903
+ export { type AssemblerProfile, type AssemblyOptions, BackStepAction, ConfirmResult, type CsrRegisterName, DialogType, type FloatingPointRegisterName, type GnuUnitSymbols, type HandlerMap, type HandlerMapFns, type JsBackStep, type JsInstruction, type JsInstructionToken, type JsInstructionUndoGroup, type JsPokeMemoryWrite, type JsPokeRegisterWrite, type JsPokeUndoGroup, type JsPokeWrite, type JsProgramStatement, type JsRiscV, type JsRiscVStackFrame, type JsUndoGroup, type MemoryAccessObserver, type MemoryObserverHandle, type MemoryWriteObserver, RISCV, type RISCVAssembleError, type RISCVAssembleResult, RISCVRegisters, type RISCVSourceLocation, type RISCVSourceSet, RISCV_CSR_REGISTERS, RISCV_FLOATING_POINT_REGISTERS, RISCV_REGISTERS, type RegisterName, type RiscvTokenizedLine, type RuntimeLibrary, StopReason, bigintToHighLow, highLowToBigint, makeRiscVFromFiles, registerHandlers, unimplementedHandler };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,43 @@
1
+ type AssemblerProfile = 'rars' | 'gnu-compiler-v1';
2
+ /**
3
+ * GNU compiler assembly members and the index naming the member that defines each global. A Build
4
+ * pulls a member only to resolve a global the program uses and does not define, as ld pulls members
5
+ * out of an archive, and keeps pulling for the globals those members use in turn. Members are always
6
+ * assembled with the `gnu-compiler-v1` profile, whatever profile the program uses, and their paths
7
+ * never meet the program's Files.
8
+ */
9
+ type RuntimeLibrary = {
10
+ /** Canonical member path to its source. */
11
+ members: Record<string, string>;
12
+ /** Global symbol to the path of the member defining it. */
13
+ index: Record<string, string>;
14
+ /**
15
+ * Globals the library supplies even to a weak reference, which otherwise pulls no member: GCC
16
+ * refers to `__cxa_pure_virtual` weakly from every abstract class's vtable.
17
+ */
18
+ resolveWeak?: string[];
19
+ };
20
+ type AssemblyOptions = {
21
+ assemblerProfile?: AssemblerProfile;
22
+ /**
23
+ * The global execution starts at instead of `main`. The link must define it, and with a library
24
+ * it pulls its own member, as ld's entry symbol does: `_start` brings in a library's startup code.
25
+ */
26
+ entrySymbol?: string;
27
+ /** Libraries searched in order: the first one whose index names a symbol supplies it. */
28
+ libraries?: RuntimeLibrary[];
29
+ };
30
+ /** The globals one GNU compiler unit defines and the ones it uses without defining. */
31
+ type GnuUnitSymbols = {
32
+ /** Globals the unit defines, strong or weak. */
33
+ defined: string[];
34
+ /** The defined globals that are weak. */
35
+ weak: string[];
36
+ /** Globals the unit uses without defining, other than weak references, which pull nothing. */
37
+ references: string[];
38
+ /** Why the unit could not be parsed; empty when it parsed. */
39
+ errors: string[];
40
+ };
1
41
  type JsInstructionToken = {
2
42
  /** One-based column in the processed source line. */
3
43
  sourceColumn: number;
@@ -135,9 +175,22 @@ type HandlerMap = {
135
175
  in: [];
136
176
  out: number;
137
177
  };
178
+ /**
179
+ * A read of standard input (descriptor 0): answer with the bytes left over from the current
180
+ * line or else one new line, at most `length` of them, as `[count, bytes]`. A count of 0 is end
181
+ * of input and -1 a failed read. Return a promise to wait for the user.
182
+ */
138
183
  stdIn: {
139
184
  in: [buffer: number[], length: number];
140
- out: void;
185
+ out: [count: number, buffer: number[]];
186
+ };
187
+ /**
188
+ * Syscall 62 (lseek): move an open file's position. `whence` is 0 from the start, 1 from the
189
+ * current position, 2 from the end. Answer with the new position, or -1 when the seek fails.
190
+ */
191
+ seekFile: {
192
+ in: [fileDescriptor: number, offset: number, whence: number];
193
+ out: number;
141
194
  };
142
195
  stdOut: {
143
196
  in: [buffer: number[]];
@@ -211,8 +264,14 @@ type RISCVAssembleResult = {
211
264
  hasWarnings: boolean;
212
265
  };
213
266
  declare class RISCV {
267
+ static readonly assemblerProfiles: readonly AssemblerProfile[];
214
268
  static makeRiscVFromFiles: typeof makeRiscVFromFiles;
215
269
  static initializeRISCV: typeof initializeRISCV;
270
+ /**
271
+ * The globals one `gnu-compiler-v1` unit defines and uses, without laying it out or touching
272
+ * memory, for building a library index. Uses the current width, so call `setIs64Bit` first.
273
+ */
274
+ static analyzeGnuUnit(path: string, source: string): GnuUnitSymbols;
216
275
  static getInstructionSet(): JsInstruction[];
217
276
  static setIs64Bit(is64Bit: boolean): void;
218
277
  static is64Bit(): boolean;
@@ -556,6 +615,8 @@ interface JsRiscV {
556
615
  * @returns The label at the given address, or null if no label is found.
557
616
  */
558
617
  getLabelAtAddress(address: number): string | null;
618
+ /** Address of a defined label/alias, or -1 if absent. Requires successful assembly. */
619
+ getAddressOfLabel(label: string): number;
559
620
  /**
560
621
  * Sets whether the undo feature is enabled.
561
622
  * @param enabled True to enable the undo feature, false to disable it.
@@ -692,6 +753,15 @@ interface JsRiscV {
692
753
  * carries what it changed, with the old and the new value of each write.
693
754
  */
694
755
  getUndoGroups(): JsUndoGroup[];
756
+ /**
757
+ * The newest `max` entries of `getUndoGroups`, read from the top of the history without
758
+ * grouping the rest of it: what a panel showing the latest steps of a large history wants.
759
+ */
760
+ getUndoGroupsUpTo(max: number): JsUndoGroup[];
761
+ /** `max` entries of `getUndoGroups` after the newest `skip`, which are counted but never built. */
762
+ getUndoGroupsRange(skip: number, max: number): JsUndoGroup[];
763
+ /** How many entries `undo()` can still pop, counted the way `getUndoGroups` groups them. */
764
+ getUndoDepth(): number;
695
765
  /**
696
766
  * Opens a Poke: a register or memory value changed by the host between two instructions,
697
767
  * recorded in this history as a step of its own.
@@ -814,9 +884,10 @@ interface JsRiscV {
814
884
  * snapshotted by this call; only the entry file and files reached through `.include` are assembled.
815
885
  * @param files Source text keyed by canonical source path.
816
886
  * @param entryFile Canonical path of the file from which include expansion starts.
887
+ * @param options The assembler profile, the entry symbol and the libraries to link; see `AssemblyOptions`.
817
888
  * @returns A new `JsRiscV` object.
818
889
  */
819
- declare function makeRiscVFromFiles(files: RISCVSourceSet, entryFile: string): JsRiscV;
890
+ declare function makeRiscVFromFiles(files: RISCVSourceSet, entryFile: string, options?: AssemblyOptions): JsRiscV;
820
891
  /**
821
892
  * Initializes the RISCV simulator.
822
893
  */
@@ -829,4 +900,4 @@ declare function bigintToHighLow(value: bigint): [high: number, low: number];
829
900
  */
830
901
  declare function highLowToBigint(high: number, low: number): bigint;
831
902
 
832
- export { BackStepAction, ConfirmResult, type CsrRegisterName, DialogType, type FloatingPointRegisterName, type HandlerMap, type HandlerMapFns, type JsBackStep, type JsInstruction, type JsInstructionToken, type JsInstructionUndoGroup, type JsPokeMemoryWrite, type JsPokeRegisterWrite, type JsPokeUndoGroup, type JsPokeWrite, type JsProgramStatement, type JsRiscV, type JsRiscVStackFrame, type JsUndoGroup, type MemoryAccessObserver, type MemoryObserverHandle, type MemoryWriteObserver, RISCV, type RISCVAssembleError, type RISCVAssembleResult, RISCVRegisters, type RISCVSourceLocation, type RISCVSourceSet, RISCV_CSR_REGISTERS, RISCV_FLOATING_POINT_REGISTERS, RISCV_REGISTERS, type RegisterName, type RiscvTokenizedLine, StopReason, bigintToHighLow, highLowToBigint, makeRiscVFromFiles, registerHandlers, unimplementedHandler };
903
+ export { type AssemblerProfile, type AssemblyOptions, BackStepAction, ConfirmResult, type CsrRegisterName, DialogType, type FloatingPointRegisterName, type GnuUnitSymbols, type HandlerMap, type HandlerMapFns, type JsBackStep, type JsInstruction, type JsInstructionToken, type JsInstructionUndoGroup, type JsPokeMemoryWrite, type JsPokeRegisterWrite, type JsPokeUndoGroup, type JsPokeWrite, type JsProgramStatement, type JsRiscV, type JsRiscVStackFrame, type JsUndoGroup, type MemoryAccessObserver, type MemoryObserverHandle, type MemoryWriteObserver, RISCV, type RISCVAssembleError, type RISCVAssembleResult, RISCVRegisters, type RISCVSourceLocation, type RISCVSourceSet, RISCV_CSR_REGISTERS, RISCV_FLOATING_POINT_REGISTERS, RISCV_REGISTERS, type RegisterName, type RiscvTokenizedLine, type RuntimeLibrary, StopReason, bigintToHighLow, highLowToBigint, makeRiscVFromFiles, registerHandlers, unimplementedHandler };