@aptre/v86 0.5.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.
Files changed (111) hide show
  1. package/LICENSE +22 -0
  2. package/LICENSE.MIT +22 -0
  3. package/Readme.md +237 -0
  4. package/dist/v86.browser.js +26666 -0
  5. package/dist/v86.browser.js.map +7 -0
  6. package/dist/v86.js +26632 -0
  7. package/dist/v86.js.map +7 -0
  8. package/gen/generate_analyzer.ts +512 -0
  9. package/gen/generate_interpreter.ts +522 -0
  10. package/gen/generate_jit.ts +624 -0
  11. package/gen/rust_ast.ts +107 -0
  12. package/gen/util.ts +35 -0
  13. package/gen/x86_table.ts +1836 -0
  14. package/lib/9p.ts +1547 -0
  15. package/lib/filesystem.ts +1879 -0
  16. package/lib/marshall.ts +168 -0
  17. package/lib/softfloat/softfloat.c +32501 -0
  18. package/lib/zstd/zstddeclib.c +13520 -0
  19. package/package.json +75 -0
  20. package/src/acpi.ts +267 -0
  21. package/src/browser/dummy_screen.ts +106 -0
  22. package/src/browser/fake_network.ts +1771 -0
  23. package/src/browser/fetch_network.ts +361 -0
  24. package/src/browser/filestorage.ts +124 -0
  25. package/src/browser/inbrowser_network.ts +57 -0
  26. package/src/browser/keyboard.ts +564 -0
  27. package/src/browser/main.ts +3415 -0
  28. package/src/browser/mouse.ts +255 -0
  29. package/src/browser/network.ts +142 -0
  30. package/src/browser/print_stats.ts +336 -0
  31. package/src/browser/screen.ts +978 -0
  32. package/src/browser/serial.ts +316 -0
  33. package/src/browser/speaker.ts +1223 -0
  34. package/src/browser/starter.ts +1688 -0
  35. package/src/browser/wisp_network.ts +332 -0
  36. package/src/browser/worker_bus.ts +64 -0
  37. package/src/buffer.ts +652 -0
  38. package/src/bus.ts +78 -0
  39. package/src/const.ts +128 -0
  40. package/src/cpu.ts +2891 -0
  41. package/src/dma.ts +474 -0
  42. package/src/elf.ts +251 -0
  43. package/src/floppy.ts +1778 -0
  44. package/src/ide.ts +3455 -0
  45. package/src/io.ts +504 -0
  46. package/src/iso9660.ts +317 -0
  47. package/src/kernel.ts +250 -0
  48. package/src/lib.ts +645 -0
  49. package/src/log.ts +149 -0
  50. package/src/main.ts +199 -0
  51. package/src/ne2k.ts +1589 -0
  52. package/src/pci.ts +815 -0
  53. package/src/pit.ts +406 -0
  54. package/src/ps2.ts +820 -0
  55. package/src/rtc.ts +537 -0
  56. package/src/rust/analysis.rs +101 -0
  57. package/src/rust/codegen.rs +2660 -0
  58. package/src/rust/config.rs +3 -0
  59. package/src/rust/control_flow.rs +425 -0
  60. package/src/rust/cpu/apic.rs +658 -0
  61. package/src/rust/cpu/arith.rs +1207 -0
  62. package/src/rust/cpu/call_indirect.rs +2 -0
  63. package/src/rust/cpu/cpu.rs +4501 -0
  64. package/src/rust/cpu/fpu.rs +923 -0
  65. package/src/rust/cpu/global_pointers.rs +112 -0
  66. package/src/rust/cpu/instructions.rs +2486 -0
  67. package/src/rust/cpu/instructions_0f.rs +5261 -0
  68. package/src/rust/cpu/ioapic.rs +316 -0
  69. package/src/rust/cpu/memory.rs +351 -0
  70. package/src/rust/cpu/misc_instr.rs +613 -0
  71. package/src/rust/cpu/mod.rs +16 -0
  72. package/src/rust/cpu/modrm.rs +133 -0
  73. package/src/rust/cpu/pic.rs +402 -0
  74. package/src/rust/cpu/sse_instr.rs +361 -0
  75. package/src/rust/cpu/string.rs +701 -0
  76. package/src/rust/cpu/vga.rs +175 -0
  77. package/src/rust/cpu_context.rs +69 -0
  78. package/src/rust/dbg.rs +98 -0
  79. package/src/rust/gen/analyzer.rs +3807 -0
  80. package/src/rust/gen/analyzer0f.rs +3992 -0
  81. package/src/rust/gen/interpreter.rs +4447 -0
  82. package/src/rust/gen/interpreter0f.rs +5404 -0
  83. package/src/rust/gen/jit.rs +5080 -0
  84. package/src/rust/gen/jit0f.rs +5547 -0
  85. package/src/rust/gen/mod.rs +14 -0
  86. package/src/rust/jit.rs +2443 -0
  87. package/src/rust/jit_instructions.rs +7881 -0
  88. package/src/rust/js_api.rs +6 -0
  89. package/src/rust/leb.rs +46 -0
  90. package/src/rust/lib.rs +29 -0
  91. package/src/rust/modrm.rs +330 -0
  92. package/src/rust/opstats.rs +249 -0
  93. package/src/rust/page.rs +15 -0
  94. package/src/rust/paging.rs +25 -0
  95. package/src/rust/prefix.rs +15 -0
  96. package/src/rust/profiler.rs +155 -0
  97. package/src/rust/regs.rs +38 -0
  98. package/src/rust/softfloat.rs +286 -0
  99. package/src/rust/state_flags.rs +27 -0
  100. package/src/rust/wasmgen/mod.rs +2 -0
  101. package/src/rust/wasmgen/wasm_builder.rs +1047 -0
  102. package/src/rust/wasmgen/wasm_opcodes.rs +221 -0
  103. package/src/rust/zstd.rs +105 -0
  104. package/src/sb16.ts +1928 -0
  105. package/src/state.ts +359 -0
  106. package/src/uart.ts +472 -0
  107. package/src/vga.ts +2791 -0
  108. package/src/virtio.ts +1756 -0
  109. package/src/virtio_balloon.ts +273 -0
  110. package/src/virtio_console.ts +372 -0
  111. package/src/virtio_net.ts +326 -0
package/src/elf.ts ADDED
@@ -0,0 +1,251 @@
1
+ declare let DEBUG: boolean
2
+
3
+ import { dbg_log, LOG_LEVEL } from './log.js'
4
+
5
+ // A minimal elf parser for loading 32 bit, x86, little endian, executable elf files
6
+
7
+ const ELF_MAGIC = 0x464c457f
8
+
9
+ interface FieldType {
10
+ size: number
11
+ get: (offset: number, littleEndian?: boolean) => number
12
+ set?: (offset: number, value: number, littleEndian?: boolean) => void
13
+ }
14
+
15
+ interface StructEntry {
16
+ name: string
17
+ type: FieldType
18
+ size: number
19
+ get: (offset: number, littleEndian?: boolean) => number
20
+ set:
21
+ | ((offset: number, value: number, littleEndian?: boolean) => void)
22
+ | undefined
23
+ }
24
+
25
+ type StructRecord = Record<string, number>
26
+
27
+ export interface ElfResult {
28
+ header: StructRecord
29
+ program_headers: StructRecord[]
30
+ sections_headers: StructRecord[]
31
+ }
32
+
33
+ const types = DataView.prototype
34
+ const U8: FieldType = { size: 1, get: types.getUint8, set: types.setUint8 }
35
+ const U16: FieldType = { size: 2, get: types.getUint16, set: types.setUint16 }
36
+ const U32: FieldType = { size: 4, get: types.getUint32, set: types.setUint32 }
37
+ const pad = function (size: number): FieldType {
38
+ return {
39
+ size,
40
+ get: (_offset: number): number => -1,
41
+ }
42
+ }
43
+
44
+ const Header: StructEntry[] = create_struct([
45
+ { magic: U32 },
46
+
47
+ { class: U8 },
48
+ { data: U8 },
49
+ { version0: U8 },
50
+ { osabi: U8 },
51
+
52
+ { abiversion: U8 },
53
+ { pad0: pad(7) },
54
+
55
+ { type: U16 },
56
+ { machine: U16 },
57
+
58
+ { version1: U32 },
59
+ { entry: U32 },
60
+ { phoff: U32 },
61
+ { shoff: U32 },
62
+ { flags: U32 },
63
+
64
+ { ehsize: U16 },
65
+ { phentsize: U16 },
66
+ { phnum: U16 },
67
+ { shentsize: U16 },
68
+ { shnum: U16 },
69
+ { shstrndx: U16 },
70
+ ])
71
+ console.assert(
72
+ Header.reduce((a: number, entry: StructEntry) => a + entry.size, 0) === 52,
73
+ )
74
+
75
+ const ProgramHeader: StructEntry[] = create_struct([
76
+ { type: U32 },
77
+ { offset: U32 },
78
+ { vaddr: U32 },
79
+ { paddr: U32 },
80
+ { filesz: U32 },
81
+ { memsz: U32 },
82
+ { flags: U32 },
83
+ { align: U32 },
84
+ ])
85
+ console.assert(
86
+ ProgramHeader.reduce(
87
+ (a: number, entry: StructEntry) => a + entry.size,
88
+ 0,
89
+ ) === 32,
90
+ )
91
+
92
+ const SectionHeader: StructEntry[] = create_struct([
93
+ { name: U32 },
94
+ { type: U32 },
95
+ { flags: U32 },
96
+ { addr: U32 },
97
+ { offset: U32 },
98
+ { size: U32 },
99
+ { link: U32 },
100
+ { info: U32 },
101
+ { addralign: U32 },
102
+ { entsize: U32 },
103
+ ])
104
+ console.assert(
105
+ SectionHeader.reduce(
106
+ (a: number, entry: StructEntry) => a + entry.size,
107
+ 0,
108
+ ) === 40,
109
+ )
110
+
111
+ // From [{ name: type }, ...] to [{ name, type, size, get, set }, ...]
112
+ function create_struct(struct: Record<string, FieldType>[]): StructEntry[] {
113
+ return struct.map(function (entry: Record<string, FieldType>): StructEntry {
114
+ const keys = Object.keys(entry)
115
+ console.assert(keys.length === 1)
116
+ const name = keys[0]
117
+ const type = entry[name]
118
+
119
+ console.assert(type.size > 0)
120
+
121
+ return {
122
+ name,
123
+ type,
124
+ size: type.size,
125
+ get: type.get,
126
+ set: type.set,
127
+ }
128
+ })
129
+ }
130
+
131
+ export function read_elf(buffer: ArrayBuffer): ElfResult {
132
+ const view = new DataView(buffer)
133
+
134
+ const [header, offset] = read_struct(view, Header)
135
+ console.assert(offset === 52)
136
+
137
+ if (DEBUG) {
138
+ for (const key of Object.keys(header)) {
139
+ dbg_log(key + ': 0x' + (Number(header[key].toString(16)) >>> 0))
140
+ }
141
+ }
142
+
143
+ console.assert(header.magic === ELF_MAGIC, 'Bad magic')
144
+ console.assert(header.class === 1, 'Unimplemented: 64 bit elf')
145
+ console.assert(header.data === 1, 'Unimplemented: big endian')
146
+ console.assert(header.version0 === 1, 'Bad version0')
147
+
148
+ // 1, 2, 3, 4 specify whether the object is relocatable, executable,
149
+ // shared, or core, respectively.
150
+ console.assert(header.type === 2, 'Unimplemented type')
151
+
152
+ console.assert(header.version1 === 1, 'Bad version1')
153
+
154
+ // these are different in 64 bit
155
+ console.assert(header.ehsize === 52, 'Bad header size')
156
+ console.assert(header.phentsize === 32, 'Bad program header size')
157
+ console.assert(header.shentsize === 40, 'Bad section header size')
158
+
159
+ const [program_headers, _ph_offset] = read_structs(
160
+ view_slice(view, header.phoff, header.phentsize * header.phnum),
161
+ ProgramHeader,
162
+ header.phnum,
163
+ )
164
+
165
+ const [sections_headers, _sh_offset] = read_structs(
166
+ view_slice(view, header.shoff, header.shentsize * header.shnum),
167
+ SectionHeader,
168
+ header.shnum,
169
+ )
170
+
171
+ if (DEBUG && LOG_LEVEL) {
172
+ console.log('%d program headers:', program_headers.length)
173
+ for (const program of program_headers) {
174
+ console.log(
175
+ 'type=%s offset=%s vaddr=%s paddr=%s ' +
176
+ 'filesz=%s memsz=%s flags=%s align=%s',
177
+ program.type.toString(16),
178
+ program.offset.toString(16),
179
+ program.vaddr.toString(16),
180
+ program.paddr.toString(16),
181
+ program.filesz.toString(16),
182
+ program.memsz.toString(16),
183
+ program.flags.toString(16),
184
+ program.align.toString(16),
185
+ )
186
+ }
187
+
188
+ console.log('%d section headers:', sections_headers.length)
189
+ for (const section of sections_headers) {
190
+ console.log(
191
+ 'name=%s type=%s flags=%s addr=%s offset=%s ' +
192
+ 'size=%s link=%s info=%s addralign=%s entsize=%s',
193
+ section.name.toString(16),
194
+ section.type.toString(16),
195
+ section.flags.toString(16),
196
+ section.addr.toString(16),
197
+ section.offset.toString(16),
198
+ section.size.toString(16),
199
+ section.link.toString(16),
200
+ section.info.toString(16),
201
+ section.addralign.toString(16),
202
+ section.entsize.toString(16),
203
+ )
204
+ }
205
+ }
206
+
207
+ return {
208
+ header,
209
+ program_headers,
210
+ sections_headers,
211
+ }
212
+ }
213
+
214
+ function read_struct(
215
+ view: DataView,
216
+ Struct: StructEntry[],
217
+ ): [StructRecord, number] {
218
+ const result: StructRecord = {}
219
+ let offset = 0
220
+ const LITTLE_ENDIAN = true // big endian not supported yet
221
+
222
+ for (const entry of Struct) {
223
+ const value = entry.get.call(view, offset, LITTLE_ENDIAN)
224
+ console.assert(result[entry.name] === undefined)
225
+ result[entry.name] = value
226
+ offset += entry.size
227
+ }
228
+
229
+ return [result, offset]
230
+ }
231
+
232
+ function read_structs(
233
+ view: DataView,
234
+ Struct: StructEntry[],
235
+ count: number,
236
+ ): [StructRecord[], number] {
237
+ const result: StructRecord[] = []
238
+ let offset = 0
239
+
240
+ for (let i = 0; i < count; i++) {
241
+ const [s, size] = read_struct(view_slice(view, offset), Struct)
242
+ result.push(s)
243
+ offset += size
244
+ }
245
+
246
+ return [result, offset]
247
+ }
248
+
249
+ function view_slice(view: DataView, offset: number, length?: number): DataView {
250
+ return new DataView(view.buffer, view.byteOffset + offset, length)
251
+ }