codecin 5.4.2__py3-none-any.whl

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 (54) hide show
  1. codecin/__init__.py +27 -0
  2. codecin/aot.py +229 -0
  3. codecin/assembler.py +548 -0
  4. codecin/cache.py +71 -0
  5. codecin/cin.py +2558 -0
  6. codecin/cli.py +282 -0
  7. codecin/config.py +58 -0
  8. codecin/console.py +183 -0
  9. codecin/cpu.py +1654 -0
  10. codecin/crom.py +222 -0
  11. codecin/debugger.py +659 -0
  12. codecin/disasm.py +86 -0
  13. codecin/errors.py +58 -0
  14. codecin/isa.py +457 -0
  15. codecin/jit.py +270 -0
  16. codecin/libcodecin_native.so +0 -0
  17. codecin/logger.py +145 -0
  18. codecin/memory.py +348 -0
  19. codecin/native/aot/aot.go +70 -0
  20. codecin/native/aot/build.go +219 -0
  21. codecin/native/aot/stub_main.go.txt +22 -0
  22. codecin/native/build.ps1 +33 -0
  23. codecin/native/build.sh +48 -0
  24. codecin/native/cmd/codecin/main.go +287 -0
  25. codecin/native/compiler/codegen.go +1938 -0
  26. codecin/native/compiler/compile_test.go +164 -0
  27. codecin/native/compiler/parser.go +1071 -0
  28. codecin/native/compiler/syscalls.go +86 -0
  29. codecin/native/compiler/tokenizer.go +336 -0
  30. codecin/native/compiler/types.go +213 -0
  31. codecin/native/engine/audio.go +152 -0
  32. codecin/native/engine/audio_other.go +46 -0
  33. codecin/native/engine/audio_windows.go +43 -0
  34. codecin/native/engine/canvas.go +271 -0
  35. codecin/native/engine/crom.go +86 -0
  36. codecin/native/engine/encode.go +93 -0
  37. codecin/native/engine/engine_test.go +198 -0
  38. codecin/native/engine/isa_gen.go +445 -0
  39. codecin/native/engine/system.go +190 -0
  40. codecin/native/engine/termux.go +113 -0
  41. codecin/native/engine/version_gen.go +7 -0
  42. codecin/native/engine/vm.go +1157 -0
  43. codecin/native/go.mod +3 -0
  44. codecin/native/ir/ir.go +48 -0
  45. codecin/native/main.go +225 -0
  46. codecin/native.py +336 -0
  47. codecin/registers.py +130 -0
  48. codecin/stats.py +235 -0
  49. codecin-5.4.2.dist-info/METADATA +985 -0
  50. codecin-5.4.2.dist-info/RECORD +54 -0
  51. codecin-5.4.2.dist-info/WHEEL +5 -0
  52. codecin-5.4.2.dist-info/entry_points.txt +2 -0
  53. codecin-5.4.2.dist-info/licenses/LICENSE +7 -0
  54. codecin-5.4.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,1157 @@
1
+ // Package engine 是 Code CIN 的原生字节码 VM (Go 实现)。
2
+ //
3
+ // 语义与 codecin/cpu.py 解释器严格一致:
4
+ // - PC 语义: 取指后先 pc++ 再执行; CALL/BL 压入的是已自增的 pc
5
+ // - 栈: 8 字节 qword, 自顶向下; sp 初值由调用方传入
6
+ // - 寄存器: 33 个槽, R[31]=XZR 只读, R[32]=SP
7
+ // - 遇到不支持的指令立即返回 StatusUnsupported, pc 指向该指令, 供 Python 回退
8
+ //
9
+ // 字节码格式 (UCBC v1):
10
+ //
11
+ // magic[4] version u8 entry u32 count u32
12
+ // 指令: opcode u8 argc u8 ; 操作数: kind u8 value i64 extra i64 (小端)
13
+ package engine
14
+
15
+ import (
16
+ "encoding/binary"
17
+ "fmt"
18
+ "math"
19
+ "math/rand"
20
+ "strconv"
21
+ "strings"
22
+ "time"
23
+ )
24
+
25
+ // 执行状态码 (与 c-shared 桥接层 / Python native.py 一致)。
26
+ const (
27
+ StatusOK = 0
28
+ StatusDone = 1
29
+ StatusUnsupported = 2
30
+ StatusError = 3
31
+ )
32
+
33
+ // 操作数种类/操作码/SYS 功能号常量由 isa_gen.go 提供 (单一事实来源:
34
+ // python script/gen_native_isa.py 自 codecin/isa.py 生成, 请勿在此重复定义)。
35
+
36
+ const mask64 = uint64(0xFFFFFFFFFFFFFFFF)
37
+
38
+ type operand struct {
39
+ kind uint8
40
+ value int64
41
+ extra int64
42
+ }
43
+
44
+ type instruction struct {
45
+ opcode uint8
46
+ args []operand
47
+ }
48
+
49
+ type vmState struct {
50
+ prog []instruction
51
+ entry int
52
+ mem []byte
53
+ regs [33]uint64
54
+ sp uint64
55
+ pc int
56
+ heapPtr uint64
57
+ steps uint64
58
+ flags struct{ N, Z, C, V bool }
59
+ out strings.Builder
60
+ outOver bool // 输出超过 maxOutputBytes (截断并置错误)
61
+ sysIdx int
62
+ rng *rand.Rand
63
+ inData []byte
64
+ inPos int
65
+ emptyStr uint64 // 预留空串地址 (宿主调用返回失败时的安全空串)
66
+ }
67
+
68
+ // maxOutputBytes 限制单次运行的输出总量: 程序用无限打印不能把宿主 OOM。
69
+ const maxOutputBytes = 16 << 20 // 16 MiB
70
+
71
+ // outWrite 追加输出; 超过上限则截断并标记 outOver。
72
+ func (vm *vmState) outWrite(s string) {
73
+ if vm.outOver {
74
+ return
75
+ }
76
+ remaining := maxOutputBytes - vm.out.Len()
77
+ if remaining <= 0 {
78
+ vm.outOver = true
79
+ return
80
+ }
81
+ if len(s) > remaining {
82
+ s = s[:remaining]
83
+ vm.outOver = true
84
+ }
85
+ vm.out.WriteString(s)
86
+ }
87
+
88
+ // outByte 追加单字节输出 (同上限)。
89
+ func (vm *vmState) outByte(b byte) {
90
+ if vm.outOver {
91
+ return
92
+ }
93
+ if vm.out.Len() >= maxOutputBytes {
94
+ vm.outOver = true
95
+ return
96
+ }
97
+ vm.out.WriteByte(b)
98
+ }
99
+
100
+ // Result 是 Run 的执行结果。
101
+ type Result struct {
102
+ Status int
103
+ Pc int
104
+ Sp uint64
105
+ HeapPtr uint64
106
+ Steps uint64
107
+ Regs [33]uint64
108
+ Output string
109
+ ErrMsg string
110
+ }
111
+
112
+ func decodeBytecode(bc []byte) ([]instruction, int, bool) {
113
+ if len(bc) < 13 || string(bc[:4]) != "UCBC" {
114
+ return nil, 0, false
115
+ }
116
+ if bc[4] != bcVersion {
117
+ // 版本字节此前从不校验: 未知格式会被按当前布局强行解释
118
+ return nil, 0, false
119
+ }
120
+ entry := binary.LittleEndian.Uint32(bc[5:9])
121
+ count := binary.LittleEndian.Uint32(bc[9:13])
122
+ // count 来自不可信输入: 先按"每条指令至少 2 字节头部"夹取。
123
+ // 旧实现直接把它当 make 容量 (count=0xFFFFFFFF → 137GB 预分配),
124
+ // 一个 13 字节的文件就能让宿主 OOM。
125
+ if maxCount := uint32((len(bc) - 13) / 2); count > maxCount {
126
+ return nil, 0, false
127
+ }
128
+ pos := 13
129
+ prog := make([]instruction, 0, count)
130
+ for i := uint32(0); i < count; i++ {
131
+ if pos+2 > len(bc) {
132
+ return nil, 0, false
133
+ }
134
+ opcode := bc[pos]
135
+ argc := int(bc[pos+1])
136
+ pos += 2
137
+ if int(opcode) >= len(argCounts) {
138
+ return nil, 0, false
139
+ }
140
+ // 参数个数必须与操作码匹配: 否则 execute 中的 args[i] 会越界 panic。
141
+ // -1 表示变长 (B / JALR / SYS), 只设一个合理上限。
142
+ if want := int(argCounts[opcode]); want >= 0 {
143
+ if argc != want {
144
+ return nil, 0, false
145
+ }
146
+ } else if argc > 6 {
147
+ return nil, 0, false
148
+ }
149
+ ins := instruction{opcode: opcode}
150
+ for j := 0; j < argc; j++ {
151
+ if pos+17 > len(bc) {
152
+ return nil, 0, false
153
+ }
154
+ op := operand{
155
+ kind: bc[pos],
156
+ value: int64(binary.LittleEndian.Uint64(bc[pos+1 : pos+9])),
157
+ extra: int64(binary.LittleEndian.Uint64(bc[pos+9 : pos+17])),
158
+ }
159
+ pos += 17
160
+ ins.args = append(ins.args, op)
161
+ }
162
+ prog = append(prog, ins)
163
+ }
164
+ return prog, int(entry), true
165
+ }
166
+
167
+ // Run 执行程序字节码, 返回结果快照。mem 会被原地修改 (数据段/堆/栈写入)。
168
+ func Run(bc []byte, mem []byte, entry, sp, heapBase int64, inData []byte,
169
+ maxSteps int64) *Result {
170
+
171
+ prog, ent, ok := decodeBytecode(bc)
172
+ if !ok {
173
+ return &Result{Status: StatusError, ErrMsg: "bad bytecode"}
174
+ }
175
+ if entry >= 0 {
176
+ ent = int(entry)
177
+ }
178
+ vm := &vmState{
179
+ prog: prog,
180
+ entry: ent,
181
+ mem: mem,
182
+ sp: uint64(sp),
183
+ pc: ent,
184
+ heapPtr: uint64(heapBase),
185
+ rng: rand.New(rand.NewSource(time.Now().UnixNano())),
186
+ inData: inData,
187
+ }
188
+
189
+ finish := func(status int, errMsg string) *Result {
190
+ // 输出超限一并报错: 不能把"被截断的输出"当成正常结果
191
+ if vm.outOver && status != StatusError {
192
+ status = StatusError
193
+ if errMsg == "" {
194
+ errMsg = "output limit exceeded (16 MiB)"
195
+ }
196
+ }
197
+ return &Result{
198
+ Status: status,
199
+ Pc: vm.pc,
200
+ Sp: vm.sp,
201
+ HeapPtr: vm.heapPtr,
202
+ Steps: vm.steps,
203
+ Regs: vm.regs,
204
+ Output: vm.out.String(),
205
+ ErrMsg: errMsg,
206
+ }
207
+ }
208
+
209
+ for {
210
+ if maxSteps > 0 && int64(vm.steps) >= maxSteps {
211
+ // 步数用尽不等于正常停机: 旧实现返回 StatusDone, 与 HALT 无法区分,
212
+ // 于是被截断的程序在 Python 侧被当成 halted=true 正常结束。
213
+ return finish(StatusError,
214
+ fmt.Sprintf("instruction limit reached (%d steps)", maxSteps))
215
+ }
216
+ if vm.pc < 0 || vm.pc >= len(vm.prog) {
217
+ return finish(StatusDone, "")
218
+ }
219
+ ins := vm.prog[vm.pc]
220
+ if !opcodeSupported(ins.opcode) {
221
+ return finish(StatusUnsupported, "")
222
+ }
223
+ // 未知 SYS 功能号: 交给解释器 (pc 不自增)
224
+ if ins.opcode == opSYS {
225
+ if len(ins.args) == 0 || ins.args[0].kind != kindImm ||
226
+ !syscallSupported(uint64(ins.args[0].value)) {
227
+ return finish(StatusUnsupported, "")
228
+ }
229
+ }
230
+ // 与解释器一致: 先自增 pc
231
+ vm.pc++
232
+ vm.steps++
233
+ halt, err := vm.execute(ins)
234
+ if err != "" {
235
+ return finish(StatusError, err)
236
+ }
237
+ if halt {
238
+ return finish(StatusOK, "")
239
+ }
240
+ }
241
+ }
242
+
243
+ func opcodeSupported(op uint8) bool {
244
+ switch op {
245
+ case opMOV, opLOAD, opSTORE, opADD, opSUB, opMUL, opDIV, opAND, opOR, opXOR,
246
+ opSHL, opSHR, opINC, opDEC, opCMP, opJMP, opJZ, opJNZ, opJE, opJL, opJG,
247
+ opPUSH, opPOP, opCALL, opRET, opIN, opOUT, opHALT, opLSL, opLSR, opASR,
248
+ opMVN, opB, opBL, opNOP, opLB, opLH, opLW, opLD, opSB, opSH, opSW, opSD,
249
+ opADDI, opXORI, opORI, opANDI, opSYS:
250
+ return true
251
+ }
252
+ return false
253
+ }
254
+
255
+ // syscallSupported: 原生 VM 已实现的 SYS 功能号。
256
+ // 现已在 Go 侧实现全部宿主调用 (0..sysTERMUXSMS), 供独立 Go CLI 使用。
257
+ func syscallSupported(id uint64) bool {
258
+ return id <= sysTERMUXSMS
259
+ }
260
+
261
+ // ---------------- 操作数/寄存器/内存 ----------------
262
+
263
+ func (vm *vmState) reg(n int) uint64 {
264
+ if n == 32 {
265
+ return vm.sp
266
+ }
267
+ if n == 31 || n < 0 || n > 32 {
268
+ return 0
269
+ }
270
+ return vm.regs[n]
271
+ }
272
+
273
+ func (vm *vmState) setReg(n int, v uint64) {
274
+ if n == 32 {
275
+ vm.sp = v
276
+ } else if n == 31 || n < 0 || n > 32 {
277
+ // XZR 只读
278
+ } else {
279
+ vm.regs[n] = v
280
+ }
281
+ }
282
+
283
+ func (vm *vmState) memAddr(op operand) (uint64, bool) {
284
+ base := op.value
285
+ off := uint64(op.extra)
286
+ if base >= 0 {
287
+ return (vm.reg(int(base)) + off) & mask64, true
288
+ }
289
+ return off & mask64, true
290
+ }
291
+
292
+ func (vm *vmState) val(op operand) (uint64, bool) {
293
+ switch op.kind {
294
+ case kindReg:
295
+ return vm.reg(int(op.value)), true
296
+ case kindImm:
297
+ return uint64(op.value), true
298
+ case kindFloat:
299
+ return uint64(op.value), true
300
+ case kindStr:
301
+ return uint64(op.value), true
302
+ case kindMem:
303
+ addr, ok := vm.memAddr(op)
304
+ if !ok {
305
+ return 0, false
306
+ }
307
+ v, e := vm.readQ(addr)
308
+ return v, e == ""
309
+ case kindCond:
310
+ if vm.condition(uint8(op.value)) {
311
+ return 1, true
312
+ }
313
+ return 0, true
314
+ case kindVec, kindVecLane:
315
+ // CIN 不生成向量操作数; 向量指令整体不支持
316
+ return 0, false
317
+ }
318
+ return 0, false
319
+ }
320
+
321
+ func (vm *vmState) checkAddr(addr uint64, width int) string {
322
+ if uint64(len(vm.mem)) < uint64(width) || addr > uint64(len(vm.mem))-uint64(width) {
323
+ return "address " + strconv.FormatUint(addr, 16) + " out of bounds"
324
+ }
325
+ return ""
326
+ }
327
+
328
+ func (vm *vmState) readQ(addr uint64) (uint64, string) {
329
+ if e := vm.checkAddr(addr, 8); e != "" {
330
+ return 0, e
331
+ }
332
+ return binary.LittleEndian.Uint64(vm.mem[addr : addr+8]), ""
333
+ }
334
+
335
+ func (vm *vmState) writeQ(addr, v uint64) string {
336
+ if e := vm.checkAddr(addr, 8); e != "" {
337
+ return e
338
+ }
339
+ binary.LittleEndian.PutUint64(vm.mem[addr:addr+8], v)
340
+ return ""
341
+ }
342
+
343
+ func toSigned(v uint64) int64 { return int64(v) }
344
+
345
+ // ---------------- 条件标志 ----------------
346
+
347
+ func (vm *vmState) condition(code uint8) bool {
348
+ n, z, c, v := vm.flags.N, vm.flags.Z, vm.flags.C, vm.flags.V
349
+ switch code {
350
+ case 0: // EQ
351
+ return z
352
+ case 1: // NE
353
+ return !z
354
+ case 2: // CS
355
+ return c
356
+ case 3: // CC
357
+ return !c
358
+ case 4: // MI
359
+ return n
360
+ case 5: // PL
361
+ return !n
362
+ case 6: // VS
363
+ return v
364
+ case 7: // VC
365
+ return !v
366
+ case 8: // HI
367
+ return c && !z
368
+ case 9: // LS
369
+ return !c || z
370
+ case 10: // GE
371
+ return n == v
372
+ case 11: // LT
373
+ return n != v
374
+ case 12: // GT
375
+ return !z && (n == v)
376
+ case 13: // LE
377
+ return z || (n != v)
378
+ case 14: // AL
379
+ return true
380
+ default: // NV
381
+ return false
382
+ }
383
+ }
384
+
385
+ func (vm *vmState) setFlagsSub(a, b uint64) {
386
+ res := (a - b) & mask64
387
+ sa := int64(a)
388
+ sb := int64(b)
389
+ sr := sa - sb
390
+ vm.flags.Z = res == 0
391
+ vm.flags.N = res&(1<<63) != 0
392
+ vm.flags.C = a >= b
393
+ vm.flags.V = sr > math.MaxInt64 || sr < math.MinInt64
394
+ }
395
+
396
+ // ---------------- 栈 ----------------
397
+
398
+ func (vm *vmState) push(v uint64) string {
399
+ vm.sp = (vm.sp - 8) & mask64
400
+ if vm.sp < vm.heapPtr+4096 {
401
+ return "Stack overflow (collides with heap)"
402
+ }
403
+ return vm.writeQ(vm.sp, v)
404
+ }
405
+
406
+ func (vm *vmState) pop() (uint64, string) {
407
+ if vm.sp >= uint64(len(vm.mem))-8 {
408
+ return 0, "Stack underflow"
409
+ }
410
+ v, e := vm.readQ(vm.sp)
411
+ if e != "" {
412
+ return 0, e
413
+ }
414
+ vm.sp = (vm.sp + 8) & mask64
415
+ return v, ""
416
+ }
417
+
418
+ // ---------------- 浮点辅助 ----------------
419
+
420
+ func bitsToF(b uint64) float64 { return math.Float64frombits(b) }
421
+ func fToBits(f float64) uint64 { return math.Float64bits(f) }
422
+
423
+ // formatFloat 与 Python _format_float 对齐 (repr 最短表示 + 去尾零)
424
+ func formatFloat(f float64) string {
425
+ if math.IsNaN(f) {
426
+ return "NaN"
427
+ }
428
+ if math.IsInf(f, 1) {
429
+ return "+Inf"
430
+ }
431
+ if math.IsInf(f, -1) {
432
+ return "-Inf"
433
+ }
434
+ return strconv.FormatFloat(f, 'g', -1, 64)
435
+ }
436
+
437
+ func (vm *vmState) readCString(addr uint64) string {
438
+ var sb strings.Builder
439
+ for addr < uint64(len(vm.mem)) {
440
+ ch := vm.mem[addr]
441
+ if ch == 0 {
442
+ break
443
+ }
444
+ sb.WriteByte(ch)
445
+ addr++
446
+ }
447
+ return sb.String()
448
+ }
449
+
450
+ func (vm *vmState) writeString(addr uint64, s string) string {
451
+ if e := vm.checkAddr(addr, len(s)+1); e != "" {
452
+ return e
453
+ }
454
+ copy(vm.mem[addr:addr+uint64(len(s))], s)
455
+ vm.mem[addr+uint64(len(s))] = 0
456
+ return ""
457
+ }
458
+
459
+ // sysBuffer 轮转静态缓冲 (与 Python 一致: heap+2048+idx*64)
460
+ func (vm *vmState) sysBuffer() uint64 {
461
+ idx := vm.sysIdx % 8
462
+ vm.sysIdx++
463
+ return vm.heapPtr + 2048 + uint64(idx)*64
464
+ }
465
+
466
+ // ---------------- 指令执行 ----------------
467
+
468
+ func (vm *vmState) execute(ins instruction) (bool, string) {
469
+ args := ins.args
470
+ switch ins.opcode {
471
+ case opMOV:
472
+ v, ok := vm.val(args[1])
473
+ if !ok {
474
+ return false, "bad MOV operand"
475
+ }
476
+ vm.setReg(int(args[0].value), v)
477
+ case opADD:
478
+ rd := int(args[0].value)
479
+ v, ok := vm.val(args[1])
480
+ if !ok {
481
+ return false, "bad ADD operand"
482
+ }
483
+ vm.setReg(rd, (vm.reg(rd)+v)&mask64)
484
+ case opSUB:
485
+ rd := int(args[0].value)
486
+ v, ok := vm.val(args[1])
487
+ if !ok {
488
+ return false, "bad SUB operand"
489
+ }
490
+ vm.setReg(rd, (vm.reg(rd)-v)&mask64)
491
+ case opMUL:
492
+ rd := int(args[0].value)
493
+ v, ok := vm.val(args[1])
494
+ if !ok {
495
+ return false, "bad MUL operand"
496
+ }
497
+ vm.setReg(rd, (vm.reg(rd)*v)&mask64)
498
+ case opDIV:
499
+ rd := int(args[0].value)
500
+ d, ok := vm.val(args[1])
501
+ if !ok {
502
+ return false, "bad DIV operand"
503
+ }
504
+ if d == 0 {
505
+ return false, "Division by zero"
506
+ }
507
+ vm.setReg(rd, sdiv(vm.reg(rd), d))
508
+ case opAND:
509
+ rd := int(args[0].value)
510
+ v, _ := vm.val(args[1])
511
+ vm.setReg(rd, vm.reg(rd)&v)
512
+ case opOR:
513
+ rd := int(args[0].value)
514
+ v, _ := vm.val(args[1])
515
+ vm.setReg(rd, vm.reg(rd)|v)
516
+ case opXOR:
517
+ rd := int(args[0].value)
518
+ v, _ := vm.val(args[1])
519
+ vm.setReg(rd, vm.reg(rd)^v)
520
+ case opSHL:
521
+ rd := int(args[0].value)
522
+ v, _ := vm.val(args[1])
523
+ vm.setReg(rd, (vm.reg(rd)<<(v&63))&mask64)
524
+ case opSHR:
525
+ rd := int(args[0].value)
526
+ v, _ := vm.val(args[1])
527
+ vm.setReg(rd, vm.reg(rd)>>(v&63))
528
+ case opINC:
529
+ rd := int(args[0].value)
530
+ vm.setReg(rd, (vm.reg(rd)+1)&mask64)
531
+ case opDEC:
532
+ rd := int(args[0].value)
533
+ vm.setReg(rd, (vm.reg(rd)-1)&mask64)
534
+ case opMVN:
535
+ rd := int(args[0].value)
536
+ v, _ := vm.val(args[1])
537
+ vm.setReg(rd, ^v&mask64)
538
+ case opCMP:
539
+ a, _ := vm.val(args[0])
540
+ b, _ := vm.val(args[1])
541
+ vm.setFlagsSub(a, b)
542
+ case opJMP:
543
+ t, _ := vm.val(args[0])
544
+ vm.pc = int(t)
545
+ case opJZ, opJE:
546
+ if vm.flags.Z {
547
+ t, _ := vm.val(args[0])
548
+ vm.pc = int(t)
549
+ }
550
+ case opJNZ:
551
+ if !vm.flags.Z {
552
+ t, _ := vm.val(args[0])
553
+ vm.pc = int(t)
554
+ }
555
+ case opJL:
556
+ if vm.flags.N != vm.flags.V {
557
+ t, _ := vm.val(args[0])
558
+ vm.pc = int(t)
559
+ }
560
+ case opJG:
561
+ if !vm.flags.Z && vm.flags.N == vm.flags.V {
562
+ t, _ := vm.val(args[0])
563
+ vm.pc = int(t)
564
+ }
565
+ case opPUSH:
566
+ v, _ := vm.val(args[0])
567
+ if e := vm.push(v); e != "" {
568
+ return false, e
569
+ }
570
+ case opPOP:
571
+ v, e := vm.pop()
572
+ if e != "" {
573
+ return false, e
574
+ }
575
+ vm.setReg(int(args[0].value), v)
576
+ case opCALL, opBL:
577
+ if e := vm.push(uint64(vm.pc)); e != "" {
578
+ return false, e
579
+ }
580
+ t, _ := vm.val(args[0])
581
+ vm.pc = int(t)
582
+ case opRET:
583
+ v, e := vm.pop()
584
+ if e != "" {
585
+ return false, e
586
+ }
587
+ vm.pc = int(v)
588
+ case opNOP:
589
+ // nothing
590
+ case opB:
591
+ cond := -1
592
+ target := uint64(0)
593
+ for _, a := range args {
594
+ if a.kind == kindCond {
595
+ cond = int(a.value)
596
+ } else {
597
+ t, ok := vm.val(a)
598
+ if ok {
599
+ target = t
600
+ }
601
+ }
602
+ }
603
+ if cond >= 0 && !vm.condition(uint8(cond)) {
604
+ break
605
+ }
606
+ vm.pc = int(target)
607
+ case opIN:
608
+ vm.setReg(int(args[0].value), vm.readLineInt())
609
+ case opOUT:
610
+ if e := vm.doOut(args[0]); e != "" {
611
+ return false, e
612
+ }
613
+ case opHALT:
614
+ return true, ""
615
+ // load/store
616
+ case opLOAD:
617
+ addr, e := vm.loadStoreAddr(args[1])
618
+ if e != "" {
619
+ return false, e
620
+ }
621
+ if e := vm.checkAddr(addr, 4); e != "" {
622
+ return false, e
623
+ }
624
+ v := uint64(binary.LittleEndian.Uint32(vm.mem[addr : addr+4]))
625
+ vm.setReg(int(args[0].value), v)
626
+ case opLW:
627
+ addr, e := vm.loadStoreAddr(args[1])
628
+ if e != "" {
629
+ return false, e
630
+ }
631
+ if e := vm.checkAddr(addr, 4); e != "" {
632
+ return false, e
633
+ }
634
+ v := int64(binary.LittleEndian.Uint32(vm.mem[addr : addr+4]))
635
+ if v&0x80000000 != 0 {
636
+ v -= 1 << 32
637
+ }
638
+ vm.setReg(int(args[0].value), uint64(v)&mask64)
639
+ case opSTORE, opSW:
640
+ addr, e := vm.loadStoreAddr(args[1])
641
+ if e != "" {
642
+ return false, e
643
+ }
644
+ if e := vm.checkAddr(addr, 4); e != "" {
645
+ return false, e
646
+ }
647
+ rs := vm.reg(int(args[0].value))
648
+ binary.LittleEndian.PutUint32(vm.mem[addr:addr+4], uint32(rs))
649
+ case opLD:
650
+ addr, e := vm.loadStoreAddr(args[1])
651
+ if e != "" {
652
+ return false, e
653
+ }
654
+ v, e := vm.readQ(addr)
655
+ if e != "" {
656
+ return false, e
657
+ }
658
+ vm.setReg(int(args[0].value), v)
659
+ case opSD:
660
+ addr, e := vm.loadStoreAddr(args[1])
661
+ if e != "" {
662
+ return false, e
663
+ }
664
+ rs := vm.reg(int(args[0].value))
665
+ if e := vm.writeQ(addr, rs); e != "" {
666
+ return false, e
667
+ }
668
+ case opLB:
669
+ addr, e := vm.loadStoreAddr(args[1])
670
+ if e != "" {
671
+ return false, e
672
+ }
673
+ if e := vm.checkAddr(addr, 1); e != "" {
674
+ return false, e
675
+ }
676
+ v := int64(vm.mem[addr])
677
+ if v&0x80 != 0 {
678
+ v -= 256
679
+ }
680
+ vm.setReg(int(args[0].value), uint64(v)&mask64)
681
+ case opLH:
682
+ addr, e := vm.loadStoreAddr(args[1])
683
+ if e != "" {
684
+ return false, e
685
+ }
686
+ if e := vm.checkAddr(addr, 2); e != "" {
687
+ return false, e
688
+ }
689
+ v := int64(binary.LittleEndian.Uint16(vm.mem[addr : addr+2]))
690
+ if v&0x8000 != 0 {
691
+ v -= 65536
692
+ }
693
+ vm.setReg(int(args[0].value), uint64(v)&mask64)
694
+ case opSB:
695
+ addr, e := vm.loadStoreAddr(args[1])
696
+ if e != "" {
697
+ return false, e
698
+ }
699
+ if e := vm.checkAddr(addr, 1); e != "" {
700
+ return false, e
701
+ }
702
+ vm.mem[addr] = byte(vm.reg(int(args[0].value)) & 0xFF)
703
+ case opSH:
704
+ addr, e := vm.loadStoreAddr(args[1])
705
+ if e != "" {
706
+ return false, e
707
+ }
708
+ if e := vm.checkAddr(addr, 2); e != "" {
709
+ return false, e
710
+ }
711
+ binary.LittleEndian.PutUint16(vm.mem[addr:addr+2], uint16(vm.reg(int(args[0].value))&0xFFFF))
712
+ // 立即数算术
713
+ case opADDI:
714
+ rd, rs := int(args[0].value), int(args[1].value)
715
+ v, _ := vm.val(args[2])
716
+ vm.setReg(rd, (vm.reg(rs)+v)&mask64)
717
+ case opXORI:
718
+ rd, rs := int(args[0].value), int(args[1].value)
719
+ v, _ := vm.val(args[2])
720
+ vm.setReg(rd, vm.reg(rs)^v)
721
+ case opORI:
722
+ rd, rs := int(args[0].value), int(args[1].value)
723
+ v, _ := vm.val(args[2])
724
+ vm.setReg(rd, vm.reg(rs)|v)
725
+ case opANDI:
726
+ rd, rs := int(args[0].value), int(args[1].value)
727
+ v, _ := vm.val(args[2])
728
+ vm.setReg(rd, vm.reg(rs)&v)
729
+ case opLSL:
730
+ rd, rn := int(args[0].value), int(args[1].value)
731
+ v, _ := vm.val(args[2])
732
+ vm.setReg(rd, (vm.reg(rn)<<(v&63))&mask64)
733
+ case opLSR:
734
+ rd, rn := int(args[0].value), int(args[1].value)
735
+ v, _ := vm.val(args[2])
736
+ vm.setReg(rd, vm.reg(rn)>>(v&63))
737
+ case opASR:
738
+ // 算术右移 (保留符号), 与 Python _op_asr 一致
739
+ rd, rn := int(args[0].value), int(args[1].value)
740
+ amt, _ := vm.val(args[2])
741
+ sv := int64(vm.reg(rn))
742
+ vm.setReg(rd, uint64(sv>>(amt&63))&mask64)
743
+ case opSYS:
744
+ if len(args) == 0 || args[0].kind != kindImm {
745
+ return false, "SYS requires an immediate call id"
746
+ }
747
+ if e := vm.doSyscall(uint64(args[0].value)); e != "" {
748
+ return false, e
749
+ }
750
+ }
751
+ return false, ""
752
+ }
753
+
754
+ func (vm *vmState) loadStoreAddr(op operand) (uint64, string) {
755
+ if op.kind == kindMem {
756
+ addr, _ := vm.memAddr(op)
757
+ return addr, ""
758
+ }
759
+ v, ok := vm.val(op)
760
+ if !ok {
761
+ return 0, "bad memory operand"
762
+ }
763
+ return v, ""
764
+ }
765
+
766
+ // sdiv: 有符号 64 位除法, 向零截断
767
+ func sdiv(a, b uint64) uint64 {
768
+ sa := int64(a)
769
+ sb := int64(b)
770
+ q := sa / sb // Go 整数除法即向零截断
771
+ return uint64(q) & mask64
772
+ }
773
+
774
+ func (vm *vmState) doOut(op operand) string {
775
+ if op.kind == kindStr {
776
+ vm.outWrite(vm.readCString(uint64(op.value)))
777
+ return ""
778
+ }
779
+ v, ok := vm.val(op)
780
+ if !ok {
781
+ return "bad OUT operand"
782
+ }
783
+ if op.kind == kindFloat || op.kind == kindVec || op.kind == kindVecLane {
784
+ vm.outWrite(formatFloat(bitsToF(v)))
785
+ return ""
786
+ }
787
+ if v == 10 {
788
+ vm.outByte('\n')
789
+ } else {
790
+ vm.outWrite(strconv.FormatUint(v, 10))
791
+ }
792
+ return ""
793
+ }
794
+
795
+ func (vm *vmState) readLineInt() uint64 {
796
+ for vm.inPos < len(vm.inData) {
797
+ end := vm.inPos
798
+ for end < len(vm.inData) && vm.inData[end] != '\n' {
799
+ end++
800
+ }
801
+ line := strings.TrimSpace(string(vm.inData[vm.inPos:end]))
802
+ if end < len(vm.inData) {
803
+ vm.inPos = end + 1
804
+ } else {
805
+ vm.inPos = end
806
+ }
807
+ n, err := strconv.ParseInt(line, 10, 64)
808
+ if err == nil {
809
+ return uint64(n) & mask64
810
+ }
811
+ return 0
812
+ }
813
+ return 0
814
+ }
815
+
816
+ // ---------------- SYS ----------------
817
+
818
+ func (vm *vmState) doSyscall(id uint64) string {
819
+ x0 := vm.reg(0)
820
+ x1 := vm.reg(1)
821
+ x2 := vm.reg(2)
822
+
823
+ switch id {
824
+ case sysABS:
825
+ vm.setReg(0, uint64(abs64(toSigned(x0)))&mask64)
826
+ case sysSQRT:
827
+ vm.setReg(0, fToBits(math.Sqrt(bitsToF(x0))))
828
+ case sysPOW:
829
+ vm.setReg(0, fToBits(math.Pow(bitsToF(x0), bitsToF(x1))))
830
+ case sysSIN:
831
+ vm.setReg(0, fToBits(math.Sin(bitsToF(x0))))
832
+ case sysCOS:
833
+ vm.setReg(0, fToBits(math.Cos(bitsToF(x0))))
834
+ case sysTAN:
835
+ vm.setReg(0, fToBits(math.Tan(bitsToF(x0))))
836
+ case sysFADD:
837
+ vm.setReg(0, fToBits(bitsToF(x0)+bitsToF(x1)))
838
+ case sysFSUB:
839
+ vm.setReg(0, fToBits(bitsToF(x0)-bitsToF(x1)))
840
+ case sysFMUL:
841
+ vm.setReg(0, fToBits(bitsToF(x0)*bitsToF(x1)))
842
+ case sysFDIV:
843
+ b := bitsToF(x1)
844
+ if b == 0 {
845
+ return "Float division by zero (SYS)"
846
+ }
847
+ vm.setReg(0, fToBits(bitsToF(x0)/b))
848
+ case sysFCMP:
849
+ a, b := bitsToF(x0), bitsToF(x1)
850
+ r := uint64(0)
851
+ if a < b {
852
+ r = mask64 // -1 的无符号表示
853
+ } else if a > b {
854
+ r = 1
855
+ }
856
+ vm.setReg(0, r)
857
+ case sysFTOI:
858
+ vm.setReg(0, uint64(int64(bitsToF(x0)))&mask64)
859
+ case sysITOF:
860
+ vm.setReg(0, fToBits(float64(toSigned(x0))))
861
+ case sysRAND:
862
+ vm.setReg(0, uint64(vm.rng.Int63n(1<<31))&mask64)
863
+ case sysSRAND:
864
+ vm.rng.Seed(int64(x0))
865
+ case sysTIME:
866
+ vm.setReg(0, uint64(time.Now().Unix())&mask64)
867
+ case sysSTRLEN:
868
+ n := uint64(0)
869
+ for x0+n < uint64(len(vm.mem)) && vm.mem[x0+n] != 0 {
870
+ n++
871
+ }
872
+ vm.setReg(0, n)
873
+ case sysSTRCMP:
874
+ i := uint64(0)
875
+ for {
876
+ var ca, cb byte
877
+ if x0+i < uint64(len(vm.mem)) {
878
+ ca = vm.mem[x0+i]
879
+ }
880
+ if x1+i < uint64(len(vm.mem)) {
881
+ cb = vm.mem[x1+i]
882
+ }
883
+ if ca != cb || ca == 0 {
884
+ vm.setReg(0, uint64(int64(ca)-int64(cb))&mask64)
885
+ break
886
+ }
887
+ i++
888
+ }
889
+ case sysSTRCPY, sysSTRCAT:
890
+ dst := x0
891
+ if id == sysSTRCAT {
892
+ for dst < uint64(len(vm.mem)) && vm.mem[dst] != 0 {
893
+ dst++
894
+ }
895
+ }
896
+ src := x1
897
+ i := uint64(0)
898
+ for {
899
+ var ch byte
900
+ if src+i < uint64(len(vm.mem)) {
901
+ ch = vm.mem[src+i]
902
+ }
903
+ if e := vm.checkAddr(dst+i, 1); e != "" {
904
+ return e
905
+ }
906
+ vm.mem[dst+i] = ch
907
+ i++
908
+ if ch == 0 {
909
+ break
910
+ }
911
+ }
912
+ vm.setReg(0, x0)
913
+ case sysMALLOC:
914
+ size := (x0 + 15) &^ uint64(15)
915
+ ptr := vm.heapPtr
916
+ vm.heapPtr += size
917
+ if vm.heapPtr > vm.sp {
918
+ return "Heap exhausted"
919
+ }
920
+ vm.setReg(0, ptr)
921
+ case sysPRINTFLO:
922
+ vm.outWrite(formatFloat(bitsToF(x0)))
923
+ case sysITOA:
924
+ addr := vm.sysBuffer()
925
+ s := strconv.FormatInt(toSigned(x0), 10)
926
+ if e := vm.writeString(addr, s); e != "" {
927
+ return e
928
+ }
929
+ vm.setReg(0, addr)
930
+ case sysFTOA:
931
+ addr := vm.sysBuffer()
932
+ s := formatFloat(bitsToF(x0))
933
+ if e := vm.writeString(addr, s); e != "" {
934
+ return e
935
+ }
936
+ vm.setReg(0, addr)
937
+ case sysPRINTSTR:
938
+ vm.outWrite(vm.readCString(x0))
939
+ case sysSTRCONCAT:
940
+ sa := vm.readCString(x0)
941
+ sb := vm.readCString(x1)
942
+ data := []byte(sa + sb + "\x00")
943
+ size := uint64(len(data)+15) &^ uint64(15)
944
+ ptr := vm.heapPtr
945
+ vm.heapPtr += size
946
+ if vm.heapPtr > vm.sp {
947
+ return "Heap exhausted (string concat)"
948
+ }
949
+ if e := vm.checkAddr(ptr, len(data)); e != "" {
950
+ return e
951
+ }
952
+ copy(vm.mem[ptr:ptr+uint64(len(data))], data)
953
+ vm.setReg(0, ptr)
954
+ case sysBOOLSTR:
955
+ addr := vm.sysBuffer()
956
+ s := "false"
957
+ if x0 != 0 {
958
+ s = "true"
959
+ }
960
+ if e := vm.writeString(addr, s); e != "" {
961
+ return e
962
+ }
963
+ vm.setReg(0, addr)
964
+ case sysSUBSTR:
965
+ // substr(s, start, len): 按字符索引, 越界自动裁剪
966
+ runes := []rune(vm.readCString(x0))
967
+ n := int64(len(runes))
968
+ start := int64(0)
969
+ if int64(x1) > n {
970
+ start = n
971
+ } else if int64(x1) > 0 {
972
+ start = int64(x1)
973
+ }
974
+ length := int64(0)
975
+ if int64(x2) > 0 {
976
+ length = int64(x2)
977
+ }
978
+ end := start + length
979
+ if end > n {
980
+ end = n
981
+ }
982
+ p, e := vm.heapDupString(string(runes[start:end]))
983
+ if e != "" {
984
+ return e
985
+ }
986
+ vm.setReg(0, p)
987
+ case sysINDEXOF:
988
+ hay := vm.readCString(x0)
989
+ needle := vm.readCString(x1)
990
+ bi := strings.Index(hay, needle)
991
+ idx := int64(-1)
992
+ if bi >= 0 {
993
+ idx = int64(len([]rune(hay[:bi])))
994
+ }
995
+ vm.setReg(0, uint64(idx)&mask64)
996
+ case sysTOUPPER:
997
+ p, e := vm.heapDupString(strings.ToUpper(vm.readCString(x0)))
998
+ if e != "" {
999
+ return e
1000
+ }
1001
+ vm.setReg(0, p)
1002
+ case sysTOLOWER:
1003
+ p, e := vm.heapDupString(strings.ToLower(vm.readCString(x0)))
1004
+ if e != "" {
1005
+ return e
1006
+ }
1007
+ vm.setReg(0, p)
1008
+ case sysABORT:
1009
+ msg := vm.readCString(x0)
1010
+ if msg != "" {
1011
+ return "Runtime abort: " + msg
1012
+ }
1013
+ return "Runtime abort"
1014
+ case sysFLOOR:
1015
+ vm.setReg(0, fToBits(math.Floor(bitsToF(x0))))
1016
+ case sysCEIL:
1017
+ vm.setReg(0, fToBits(math.Ceil(bitsToF(x0))))
1018
+ case sysROUND:
1019
+ vm.setReg(0, fToBits(math.Floor(bitsToF(x0)+0.5)))
1020
+ case sysATOI:
1021
+ s := strings.TrimSpace(vm.readCString(x0))
1022
+ n, err := strconv.ParseInt(s, 10, 64)
1023
+ if err != nil {
1024
+ vm.setReg(0, 0)
1025
+ } else {
1026
+ vm.setReg(0, uint64(n)&mask64)
1027
+ }
1028
+ case sysTRIM:
1029
+ p, e := vm.heapDupString(strings.TrimSpace(vm.readCString(x0)))
1030
+ if e != "" {
1031
+ return e
1032
+ }
1033
+ vm.setReg(0, p)
1034
+ case sysLTRIM:
1035
+ p, e := vm.heapDupString(strings.TrimLeft(vm.readCString(x0), " \t\n\r\v\f"))
1036
+ if e != "" {
1037
+ return e
1038
+ }
1039
+ vm.setReg(0, p)
1040
+ case sysRTRIM:
1041
+ p, e := vm.heapDupString(strings.TrimRight(vm.readCString(x0), " \t\n\r\v\f"))
1042
+ if e != "" {
1043
+ return e
1044
+ }
1045
+ vm.setReg(0, p)
1046
+ case sysAUDIOPLAY:
1047
+ vm.setReg(0, vm.audioPlay(vm.readCString(x0)))
1048
+ case sysAUDIOSTOP:
1049
+ vm.audioStop()
1050
+ case sysAUDIOVOL:
1051
+ vm.audioVolume(x0)
1052
+ case sysAUDIOWAIT:
1053
+ vm.audioWait()
1054
+ case sysCANVASNEW:
1055
+ vm.canvasNew(x0, x1)
1056
+ case sysCANVASSET:
1057
+ vm.canvasSetColor(x0)
1058
+ case sysCANVASRECT:
1059
+ vm.canvasRect(x0, x1, vm.reg(2), vm.reg(3))
1060
+ case sysCANVASCIRC:
1061
+ vm.canvasCircle(x0, x1, vm.reg(2))
1062
+ case sysCANVASTEXT:
1063
+ vm.canvasText(x0, x1, vm.readCString(vm.reg(2)))
1064
+ case sysCANVASLINE:
1065
+ vm.canvasLine(x0, x1, vm.reg(2), vm.reg(3))
1066
+ case sysCANVASSAVE:
1067
+ vm.setReg(0, vm.canvasSave(vm.readCString(x0)))
1068
+ case sysCANVASSHOW:
1069
+ vm.setReg(0, vm.canvasShow())
1070
+ // 系统原生交互 (文件/进程/环境/系统信息)
1071
+ case sysFILEREAD:
1072
+ vm.setReg(0, vm.fileRead(vm.readCString(x0)))
1073
+ case sysFILEWRITE:
1074
+ vm.setReg(0, vm.fileWrite(vm.readCString(x0), vm.readCString(x1)))
1075
+ case sysFILEAPPEND:
1076
+ vm.setReg(0, vm.fileAppend(vm.readCString(x0), vm.readCString(x1)))
1077
+ case sysFILEEXISTS:
1078
+ vm.setReg(0, vm.fileExists(vm.readCString(x0)))
1079
+ case sysFILEDELETE:
1080
+ vm.setReg(0, vm.fileDelete(vm.readCString(x0)))
1081
+ case sysFILESIZE:
1082
+ vm.setReg(0, vm.fileSize(vm.readCString(x0)))
1083
+ case sysMKDIR:
1084
+ vm.setReg(0, vm.mkdir(vm.readCString(x0)))
1085
+ case sysDIRLIST:
1086
+ vm.setReg(0, vm.dirList(vm.readCString(x0)))
1087
+ case sysEXEC:
1088
+ vm.setReg(0, vm.execCmd(vm.readCString(x0)))
1089
+ case sysEXECOUTPUT:
1090
+ vm.setReg(0, vm.execOutput(vm.readCString(x0)))
1091
+ case sysGETENV:
1092
+ vm.setReg(0, vm.getenv(vm.readCString(x0)))
1093
+ case sysSETENV:
1094
+ vm.setReg(0, vm.setenv(vm.readCString(x0), vm.readCString(x1)))
1095
+ case sysOSNAME:
1096
+ vm.setReg(0, vm.osName())
1097
+ case sysHOSTNAME:
1098
+ vm.setReg(0, vm.hostname())
1099
+ case sysUSERNAME:
1100
+ vm.setReg(0, vm.username())
1101
+ case sysCWD:
1102
+ vm.setReg(0, vm.cwd())
1103
+ case sysHOMEDIR:
1104
+ vm.setReg(0, vm.homeDir())
1105
+ // Termux API
1106
+ case sysTERMUXAVAIL:
1107
+ vm.setReg(0, vm.termuxAvailable())
1108
+ case sysTERMUXNOTIFY:
1109
+ vm.setReg(0, vm.termuxNotify(vm.readCString(x0), vm.readCString(x1)))
1110
+ case sysTERMUXTOAST:
1111
+ vm.setReg(0, vm.termuxToast(vm.readCString(x0)))
1112
+ case sysTERMUXCLIPGET:
1113
+ vm.setReg(0, vm.termuxClipboardGet())
1114
+ case sysTERMUXCLIPSET:
1115
+ vm.setReg(0, vm.termuxClipboardSet(vm.readCString(x0)))
1116
+ case sysTERMUXBATTERY:
1117
+ vm.setReg(0, vm.termuxBattery())
1118
+ case sysTERMUXVIBRATE:
1119
+ vm.setReg(0, vm.termuxVibrate(x0))
1120
+ case sysTERMUXTTS:
1121
+ vm.setReg(0, vm.termuxTTS(vm.readCString(x0)))
1122
+ case sysTERMUXLOCATION:
1123
+ vm.setReg(0, vm.termuxLocation())
1124
+ case sysTERMUXWIFI:
1125
+ vm.setReg(0, vm.termuxWifiInfo())
1126
+ case sysTERMUXDIALOG:
1127
+ vm.setReg(0, vm.termuxDialog(vm.readCString(x0)))
1128
+ case sysTERMUXSMS:
1129
+ vm.setReg(0, vm.termuxSmsSend(vm.readCString(x0), vm.readCString(x1)))
1130
+ default:
1131
+ return "Unknown SYS call id"
1132
+ }
1133
+ return ""
1134
+ }
1135
+
1136
+ // heapDupString 在堆上分配 NUL 结尾字符串副本, 返回 (指针, 错误)。
1137
+ func (vm *vmState) heapDupString(s string) (uint64, string) {
1138
+ data := []byte(s + "\x00")
1139
+ size := (uint64(len(data)) + 15) &^ uint64(15)
1140
+ ptr := vm.heapPtr
1141
+ vm.heapPtr += size
1142
+ if vm.heapPtr > vm.sp {
1143
+ return 0, "Heap exhausted (string operation)"
1144
+ }
1145
+ if e := vm.checkAddr(ptr, len(data)); e != "" {
1146
+ return 0, e
1147
+ }
1148
+ copy(vm.mem[ptr:ptr+uint64(len(data))], data)
1149
+ return ptr, ""
1150
+ }
1151
+
1152
+ func abs64(v int64) int64 {
1153
+ if v < 0 {
1154
+ return -v
1155
+ }
1156
+ return v
1157
+ }