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.
- codecin/__init__.py +27 -0
- codecin/aot.py +229 -0
- codecin/assembler.py +548 -0
- codecin/cache.py +71 -0
- codecin/cin.py +2558 -0
- codecin/cli.py +282 -0
- codecin/config.py +58 -0
- codecin/console.py +183 -0
- codecin/cpu.py +1654 -0
- codecin/crom.py +222 -0
- codecin/debugger.py +659 -0
- codecin/disasm.py +86 -0
- codecin/errors.py +58 -0
- codecin/isa.py +457 -0
- codecin/jit.py +270 -0
- codecin/libcodecin_native.so +0 -0
- codecin/logger.py +145 -0
- codecin/memory.py +348 -0
- codecin/native/aot/aot.go +70 -0
- codecin/native/aot/build.go +219 -0
- codecin/native/aot/stub_main.go.txt +22 -0
- codecin/native/build.ps1 +33 -0
- codecin/native/build.sh +48 -0
- codecin/native/cmd/codecin/main.go +287 -0
- codecin/native/compiler/codegen.go +1938 -0
- codecin/native/compiler/compile_test.go +164 -0
- codecin/native/compiler/parser.go +1071 -0
- codecin/native/compiler/syscalls.go +86 -0
- codecin/native/compiler/tokenizer.go +336 -0
- codecin/native/compiler/types.go +213 -0
- codecin/native/engine/audio.go +152 -0
- codecin/native/engine/audio_other.go +46 -0
- codecin/native/engine/audio_windows.go +43 -0
- codecin/native/engine/canvas.go +271 -0
- codecin/native/engine/crom.go +86 -0
- codecin/native/engine/encode.go +93 -0
- codecin/native/engine/engine_test.go +198 -0
- codecin/native/engine/isa_gen.go +445 -0
- codecin/native/engine/system.go +190 -0
- codecin/native/engine/termux.go +113 -0
- codecin/native/engine/version_gen.go +7 -0
- codecin/native/engine/vm.go +1157 -0
- codecin/native/go.mod +3 -0
- codecin/native/ir/ir.go +48 -0
- codecin/native/main.go +225 -0
- codecin/native.py +336 -0
- codecin/registers.py +130 -0
- codecin/stats.py +235 -0
- codecin-5.4.2.dist-info/METADATA +985 -0
- codecin-5.4.2.dist-info/RECORD +54 -0
- codecin-5.4.2.dist-info/WHEEL +5 -0
- codecin-5.4.2.dist-info/entry_points.txt +2 -0
- codecin-5.4.2.dist-info/licenses/LICENSE +7 -0
- codecin-5.4.2.dist-info/top_level.txt +1 -0
codecin/disasm.py
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""UCBC 字节码反汇编 (A3): .bin -> .asm 风格文本清单。
|
|
2
|
+
|
|
3
|
+
支持两种输入:
|
|
4
|
+
- CPUSA 容器 (.bin, `--compile-only` 产物): 头 + 内存镜像 + UCBC 段
|
|
5
|
+
- 裸 UCBC 段 (magic 'UCBC')
|
|
6
|
+
|
|
7
|
+
CLI: python cpu.py --disasm prog.bin
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
import struct
|
|
12
|
+
from typing import Any, List, Tuple
|
|
13
|
+
|
|
14
|
+
from .debugger import fmt_operand
|
|
15
|
+
from .errors import CPUSimulatorError
|
|
16
|
+
from .isa import Constants
|
|
17
|
+
|
|
18
|
+
Operand = Tuple[Any, ...]
|
|
19
|
+
Instruction = Tuple[str, List[Operand]]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _format_instruction(index: int, opcode: str, args: List[Operand]) -> str:
|
|
23
|
+
# 条件后缀形式: cond 操作数作为指令 mnemonic.cond 前缀
|
|
24
|
+
if args and args[0][0] == 'cond':
|
|
25
|
+
cond = args[0][1]
|
|
26
|
+
rest = " ".join(fmt_operand(op) for op in args[1:])
|
|
27
|
+
return f"{index:04x}: {opcode}.{cond} {rest}".rstrip()
|
|
28
|
+
parts = [f"{index:04x}:", opcode]
|
|
29
|
+
parts.extend(fmt_operand(op) for op in args)
|
|
30
|
+
return " ".join(parts)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _decode_ucbc_segment(bytecode: bytes) -> Tuple[List[Instruction], int]:
|
|
34
|
+
from .native import decode_program
|
|
35
|
+
return decode_program(bytecode)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _extract_from_cpusa(data: bytes):
|
|
39
|
+
"""解析 CPUSA 容器, 返回 (bytecode, mem_size, entry, sp)。"""
|
|
40
|
+
if data[:5] != Constants.MAGIC_NUMBER:
|
|
41
|
+
return None
|
|
42
|
+
version = data[5]
|
|
43
|
+
if version != Constants.BIN_VERSION:
|
|
44
|
+
raise CPUSimulatorError(
|
|
45
|
+
f"--disasm: unsupported binary version {version}")
|
|
46
|
+
mem_size = struct.unpack('<I', data[6:10])[0]
|
|
47
|
+
entry = struct.unpack('<I', data[10:14])[0]
|
|
48
|
+
sp = struct.unpack('<Q', data[14:22])[0]
|
|
49
|
+
bc_len = struct.unpack('<I', data[22:26])[0]
|
|
50
|
+
off = 34
|
|
51
|
+
return data[off + mem_size: off + mem_size + bc_len], mem_size, entry, sp
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def disassemble_bytes(data: bytes) -> List[str]:
|
|
55
|
+
# CPUSA 容器
|
|
56
|
+
cpusa = _extract_from_cpusa(data)
|
|
57
|
+
if cpusa is not None:
|
|
58
|
+
bytecode, mem_size, entry, sp = cpusa
|
|
59
|
+
instructions, _ = _decode_ucbc_segment(bytecode)
|
|
60
|
+
out = [f"; CPUSA binary: {len(instructions)} instructions, "
|
|
61
|
+
f"mem={mem_size} bytes, entry=0x{entry:x}, sp=0x{sp:x}", ";"]
|
|
62
|
+
for idx, (opcode, args) in enumerate(instructions):
|
|
63
|
+
out.append(_format_instruction(idx, opcode, args))
|
|
64
|
+
out.append("")
|
|
65
|
+
return out
|
|
66
|
+
|
|
67
|
+
# 裸 UCBC
|
|
68
|
+
if data[:4] != b'UCBC':
|
|
69
|
+
raise CPUSimulatorError(
|
|
70
|
+
"--disasm 需要 .bin (CPUSA 容器) 或 UCBC 字节码; "
|
|
71
|
+
"先用 `python cpu.py src.cin --compile-only -o out.bin` 生成")
|
|
72
|
+
instructions, entry = _decode_ucbc_segment(data)
|
|
73
|
+
out = [f"; UCBC disassembly: {len(instructions)} instructions, "
|
|
74
|
+
f"entry=0x{entry:x}", ";"]
|
|
75
|
+
for idx, (opcode, args) in enumerate(instructions):
|
|
76
|
+
out.append(_format_instruction(idx, opcode, args))
|
|
77
|
+
out.append("")
|
|
78
|
+
return out
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def disassemble_file(path: str) -> List[str]:
|
|
82
|
+
if not os.path.exists(path):
|
|
83
|
+
raise CPUSimulatorError(f"File '{path}' not found")
|
|
84
|
+
with open(path, 'rb') as f:
|
|
85
|
+
data = f.read()
|
|
86
|
+
return disassemble_bytes(data)
|
codecin/errors.py
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
from typing import Any, Optional
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class CPUSimulatorError(Exception):
|
|
5
|
+
"""所有 Code CIN 错误的基类。"""
|
|
6
|
+
|
|
7
|
+
def __init__(self, message: str, detail: Optional[Any] = None):
|
|
8
|
+
self.message = message
|
|
9
|
+
self.detail = detail
|
|
10
|
+
super().__init__(message)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class AssemblerError(CPUSimulatorError):
|
|
14
|
+
"""汇编阶段错误 (.pl / .asm)。"""
|
|
15
|
+
|
|
16
|
+
def __init__(self, line: str, detail: str, line_num: Optional[int] = None,
|
|
17
|
+
filename: Optional[str] = None):
|
|
18
|
+
self.line = line
|
|
19
|
+
self.line_num = line_num
|
|
20
|
+
self.filename = filename
|
|
21
|
+
location = ""
|
|
22
|
+
if filename and line_num:
|
|
23
|
+
location = f"{filename}:{line_num}: "
|
|
24
|
+
elif line_num:
|
|
25
|
+
location = f"Line {line_num}: "
|
|
26
|
+
super().__init__(f"{location}Assembler error: {line.strip()} -- {detail}",
|
|
27
|
+
detail=detail)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class CompilerError(CPUSimulatorError):
|
|
31
|
+
"""CIN 编译阶段错误。"""
|
|
32
|
+
|
|
33
|
+
def __init__(self, message: str, line_num: Optional[int] = None,
|
|
34
|
+
filename: Optional[str] = None):
|
|
35
|
+
self.line_num = line_num
|
|
36
|
+
self.filename = filename
|
|
37
|
+
location = ""
|
|
38
|
+
if filename and line_num:
|
|
39
|
+
location = f"{filename}:{line_num}: "
|
|
40
|
+
elif line_num:
|
|
41
|
+
location = f"Line {line_num}: "
|
|
42
|
+
super().__init__(f"{location}Compiler error: {message}")
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class ExecutionError(CPUSimulatorError):
|
|
46
|
+
"""指令执行阶段错误 (除零、未实现指令、栈错误等)。"""
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class MemoryAccessError(CPUSimulatorError):
|
|
50
|
+
"""内存访问错误 (越界 / 保护违例)。"""
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class PageFaultError(MemoryAccessError):
|
|
54
|
+
"""MMU 缺页/物理越界 (B1 分页)。"""
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
# 向后兼容别名 (旧代码引用 MemoryError)
|
|
58
|
+
MemoryError = MemoryAccessError
|
codecin/isa.py
ADDED
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
from enum import Enum, IntEnum
|
|
2
|
+
from typing import Dict, Set
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Opcode(Enum):
|
|
6
|
+
MOV = 0
|
|
7
|
+
LOAD = 1
|
|
8
|
+
STORE = 2
|
|
9
|
+
ADD = 3
|
|
10
|
+
SUB = 4
|
|
11
|
+
MUL = 5
|
|
12
|
+
DIV = 6
|
|
13
|
+
AND = 7
|
|
14
|
+
OR = 8
|
|
15
|
+
XOR = 9
|
|
16
|
+
SHL = 10
|
|
17
|
+
SHR = 11
|
|
18
|
+
INC = 12
|
|
19
|
+
DEC = 13
|
|
20
|
+
CMP = 14
|
|
21
|
+
JMP = 15
|
|
22
|
+
JZ = 16
|
|
23
|
+
JNZ = 17
|
|
24
|
+
JE = 18
|
|
25
|
+
JL = 19
|
|
26
|
+
JG = 20
|
|
27
|
+
PUSH = 21
|
|
28
|
+
POP = 22
|
|
29
|
+
CALL = 23
|
|
30
|
+
RET = 24
|
|
31
|
+
IN = 25
|
|
32
|
+
OUT = 26
|
|
33
|
+
HALT = 27
|
|
34
|
+
ADDS = 28
|
|
35
|
+
SUBS = 29
|
|
36
|
+
ADDC = 30
|
|
37
|
+
SUBC = 31
|
|
38
|
+
LSL = 32
|
|
39
|
+
LSR = 33
|
|
40
|
+
ASR = 34
|
|
41
|
+
ROR = 35
|
|
42
|
+
MVN = 36
|
|
43
|
+
EOR = 37
|
|
44
|
+
BIC = 38
|
|
45
|
+
ORN = 39
|
|
46
|
+
LDR = 40
|
|
47
|
+
STR = 41
|
|
48
|
+
LDP = 42
|
|
49
|
+
STP = 43
|
|
50
|
+
CBZ = 44
|
|
51
|
+
CBNZ = 45
|
|
52
|
+
TBZ = 46
|
|
53
|
+
TBNZ = 47
|
|
54
|
+
B = 48
|
|
55
|
+
BL = 49
|
|
56
|
+
BR = 50
|
|
57
|
+
NOP = 51
|
|
58
|
+
WFE = 52
|
|
59
|
+
WFI = 53
|
|
60
|
+
SEV = 54
|
|
61
|
+
CSEL = 55
|
|
62
|
+
CSINC = 56
|
|
63
|
+
CSINV = 57
|
|
64
|
+
CSNEG = 58
|
|
65
|
+
SXTB = 59
|
|
66
|
+
SXTH = 60
|
|
67
|
+
SXTW = 61
|
|
68
|
+
UXTB = 62
|
|
69
|
+
UXTH = 63
|
|
70
|
+
CLZ = 64
|
|
71
|
+
CLS = 65
|
|
72
|
+
RBIT = 66
|
|
73
|
+
REV = 67
|
|
74
|
+
FADD = 68
|
|
75
|
+
FSUB = 69
|
|
76
|
+
FMUL = 70
|
|
77
|
+
FDIV = 71
|
|
78
|
+
FCMP = 72
|
|
79
|
+
FCVT = 73
|
|
80
|
+
FABS = 74
|
|
81
|
+
FNEG = 75
|
|
82
|
+
LDRS = 76
|
|
83
|
+
STRS = 77
|
|
84
|
+
VADD = 78
|
|
85
|
+
VSUB = 79
|
|
86
|
+
VMUL = 80
|
|
87
|
+
VDIV = 81
|
|
88
|
+
VLD1 = 82
|
|
89
|
+
VST1 = 83
|
|
90
|
+
LB = 84
|
|
91
|
+
LH = 85
|
|
92
|
+
LW = 86
|
|
93
|
+
LD = 87
|
|
94
|
+
SB = 88
|
|
95
|
+
SH = 89
|
|
96
|
+
SW = 90
|
|
97
|
+
SD = 91
|
|
98
|
+
ADDI = 92
|
|
99
|
+
SLTI = 93
|
|
100
|
+
SLTIU = 94
|
|
101
|
+
XORI = 95
|
|
102
|
+
ORI = 96
|
|
103
|
+
ANDI = 97
|
|
104
|
+
SLLI = 98
|
|
105
|
+
SRLI = 99
|
|
106
|
+
SRAI = 100
|
|
107
|
+
BEQ = 101
|
|
108
|
+
BNE = 102
|
|
109
|
+
BLT = 103
|
|
110
|
+
BGE = 104
|
|
111
|
+
BLTU = 105
|
|
112
|
+
BGEU = 106
|
|
113
|
+
JALR = 107
|
|
114
|
+
JAL = 108
|
|
115
|
+
LUI = 109
|
|
116
|
+
AUIPC = 110
|
|
117
|
+
# Code CIN 扩展: 宿主系统调用 (CIN 内建函数 / 浮点运算支撑)
|
|
118
|
+
SYS = 111
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class Syscall(IntEnum):
|
|
122
|
+
"""SYS 指令的功能号。参数通过 X0-X2 (整数) 传递,
|
|
123
|
+
浮点参数/结果以 float64 位模式存于 X0/X1。返回值写入 X0。"""
|
|
124
|
+
SQRT = 0 # float sqrt(x0 bits) -> x0 bits
|
|
125
|
+
POW = 1 # float pow(x0, x1) -> x0 bits
|
|
126
|
+
ABS = 2 # int abs(x0)
|
|
127
|
+
SIN = 3
|
|
128
|
+
COS = 4
|
|
129
|
+
TAN = 5
|
|
130
|
+
FADD = 6 # float x0 + x1
|
|
131
|
+
FSUB = 7
|
|
132
|
+
FMUL = 8
|
|
133
|
+
FDIV = 9
|
|
134
|
+
FCMP = 10 # float cmp(x0,x1) -> -1/0/1
|
|
135
|
+
FTOI = 11 # float -> int
|
|
136
|
+
ITOF = 12 # int -> float bits
|
|
137
|
+
RAND = 13 # -> 非负随机整数
|
|
138
|
+
SRAND = 14 # srand(x0)
|
|
139
|
+
TIME = 15 # -> unix 时间戳
|
|
140
|
+
STRLEN = 16 # strlen(x0=ptr)
|
|
141
|
+
STRCMP = 17 # strcmp(x0, x1)
|
|
142
|
+
STRCPY = 18 # strcpy(x0=dst, x1=src) -> dst
|
|
143
|
+
STRCAT = 19 # strcat(x0=dst, x1=src) -> dst
|
|
144
|
+
MALLOC = 20 # malloc(x0=bytes) -> ptr
|
|
145
|
+
PRINT_FLOAT = 21 # 打印 float(x0 bits)
|
|
146
|
+
ITOA = 22 # itoa(x0) -> 静态缓冲 ptr
|
|
147
|
+
FTOA = 23 # ftoa(x0 bits) -> 静态缓冲 ptr
|
|
148
|
+
PRINT_STR = 24 # 打印 x0 指向的字符串 (OUT str 的系统调用形式)
|
|
149
|
+
STR_CONCAT = 25 # strcat_alloc(x0=a, x1=b) -> 新堆块 ptr (NUL 结尾)
|
|
150
|
+
BOOL_STR = 26 # bool_str(x0) -> "true"/"false" 静态缓冲 ptr
|
|
151
|
+
ABORT = 27 # abort(x0=消息指针): 抛 ExecutionError (assert/边界检查)
|
|
152
|
+
SUBSTR = 28 # substr(x0=s, x1=start, x2=len) -> 新堆字符串 (越界裁剪)
|
|
153
|
+
INDEXOF = 29 # indexof(x0=hay, x1=needle) -> 首位置或 -1
|
|
154
|
+
TOUPPER = 30 # upper(x0=s) -> 新堆字符串 (ASCII 大写)
|
|
155
|
+
TOLOWER = 31 # lower(x0=s) -> 新堆字符串 (ASCII 小写)
|
|
156
|
+
FLOOR = 32 # float floor(x0 bits) -> float bits (向 -inf 取整)
|
|
157
|
+
CEIL = 33 # float ceil(x0 bits) -> float bits (向 +inf 取整)
|
|
158
|
+
ROUND = 34 # float round(x0 bits) -> float bits (floor(x+0.5), 半值向 +inf)
|
|
159
|
+
ATOI = 35 # int atoi(x0=string ptr) -> 十进制整数 (失败为 0)
|
|
160
|
+
TRIM = 36 # string trim(x0=s) -> 去首尾空白的新堆字符串
|
|
161
|
+
LTRIM = 37 # string ltrim(x0=s) -> 去前导空白的新堆字符串
|
|
162
|
+
RTRIM = 38 # string rtrim(x0=s) -> 去尾部空白的新堆字符串
|
|
163
|
+
# ---- 宿主能力: 联网音频 (Go 原生实现; 无原生库时报错) ----
|
|
164
|
+
AUDIOPLAY = 39 # audio_play(x0=url/文件路径) -> 0 成功 / -1 失败 (同步下载+播放)
|
|
165
|
+
AUDIOSTOP = 40 # audio_stop(): 停止当前播放
|
|
166
|
+
AUDIOVOL = 41 # audio_volume(x0=0..100): 设置音量 (支持则生效, 否则忽略)
|
|
167
|
+
AUDIOWAIT = 42 # audio_wait(): 阻塞到当前播放结束 (按 WAV 头时长估算)
|
|
168
|
+
# ---- 宿主能力: 2D 绘图画布 (Go 标准库 image/png 实现, 导出 PNG) ----
|
|
169
|
+
CANVASNEW = 43 # canvas(w=x0, h=x1): 新建 w*h 画布 (当前画布)
|
|
170
|
+
CANVASSET = 44 # set_color(rgb=x0): 设置画笔颜色 (0xRRGGBB)
|
|
171
|
+
CANVASRECT = 45 # rect(x=x0, y=x1, w=x2, h=x3): 填充矩形
|
|
172
|
+
CANVASCIRC = 46 # circle(x=x0, y=x1, r=x2): 填充圆
|
|
173
|
+
CANVASTEXT = 47 # text(x=x0, y=x1, s=x2 指针): 绘制文本 (内置 8x8 点阵字库)
|
|
174
|
+
CANVASLINE = 48 # line(x0,y0,x1,y1): 画线 (x0,x1,y0=x1? 见参数说明)
|
|
175
|
+
CANVASSAVE = 49 # save(x0=路径) -> 0 成功 / -1 失败 (PNG 编码写盘)
|
|
176
|
+
CANVASSHOW = 50 # show_canvas(): 保存当前画布到临时 PNG 并用系统查看器打开 (窗口)
|
|
177
|
+
# ---- 宿主能力: 系统原生交互 (跨平台文件/进程/环境/系统信息; Go 实现) ----
|
|
178
|
+
FILEREAD = 51 # file_read(x0=path) -> 新堆字符串 (文件内容; 失败为空串)
|
|
179
|
+
FILEWRITE = 52 # file_write(x0=path, x1=内容) -> 0 成功 / -1 失败 (覆盖写)
|
|
180
|
+
FILEAPPEND = 53 # file_append(x0=path, x1=内容) -> 0 成功 / -1 失败 (追加)
|
|
181
|
+
FILEEXISTS = 54 # file_exists(x0=path) -> 1 存在 / 0 不存在
|
|
182
|
+
FILEDELETE = 55 # file_delete(x0=path) -> 0 成功 / -1 失败 (文件或空目录)
|
|
183
|
+
FILESIZE = 56 # file_size(x0=path) -> 字节数 / -1 失败
|
|
184
|
+
MKDIR = 57 # mkdir(x0=path) -> 0 成功 / -1 失败 (递归创建)
|
|
185
|
+
DIRLIST = 58 # dir_list(x0=path) -> 换行分隔条目 (新堆字符串; 失败为空串)
|
|
186
|
+
EXEC = 59 # exec(x0=shell 命令) -> 退出码 (同步; 平台默认 shell)
|
|
187
|
+
EXECOUTPUT = 60 # exec_output(x0=shell 命令) -> stdout 新堆字符串 (退出码非 0 也返回输出)
|
|
188
|
+
GETENV = 61 # getenv(x0=变量名) -> 新堆字符串 (未设置为空串)
|
|
189
|
+
SETENV = 62 # setenv(x0=变量名, x1=值) -> 0 成功 / -1 失败
|
|
190
|
+
OSNAME = 63 # os_name() -> "windows" / "darwin" / "linux" / ...
|
|
191
|
+
HOSTNAME = 64 # hostname() -> 新堆字符串
|
|
192
|
+
USERNAME = 65 # username() -> 新堆字符串
|
|
193
|
+
CWD = 66 # cwd() -> 当前工作目录 (新堆字符串)
|
|
194
|
+
HOMEDIR = 67 # home_dir() -> 用户主目录 (新堆字符串)
|
|
195
|
+
# ---- 宿主能力: Termux API 交互 (Android/Termux; 经 termux-* 命令) ----
|
|
196
|
+
TERMUXAVAIL = 68 # termux_available() -> 1 Termux API 可用 / 0 不可用
|
|
197
|
+
TERMUXNOTIFY = 69 # termux_notify(x0=标题, x1=内容) -> 0 / -1
|
|
198
|
+
TERMUXTOAST = 70 # termux_toast(x0=消息) -> 0 / -1
|
|
199
|
+
TERMUXCLIPGET = 71 # termux_clipboard_get() -> 剪贴板内容 (新堆字符串)
|
|
200
|
+
TERMUXCLIPSET = 72 # termux_clipboard_set(x0=文本) -> 0 / -1
|
|
201
|
+
TERMUXBATTERY = 73 # termux_battery() -> JSON (新堆字符串)
|
|
202
|
+
TERMUXVIBRATE = 74 # termux_vibrate(x0=毫秒) -> 0 / -1
|
|
203
|
+
TERMUXTTS = 75 # termux_tts(x0=文本) -> 0 / -1 (文字转语音)
|
|
204
|
+
TERMUXLOCATION = 76 # termux_location() -> JSON (新堆字符串)
|
|
205
|
+
TERMUXWIFI = 77 # termux_wifi_info() -> JSON (新堆字符串)
|
|
206
|
+
TERMUXDIALOG = 78 # termux_dialog(x0=标题) -> JSON (新堆字符串)
|
|
207
|
+
TERMUXSMS = 79 # termux_sms_send(x0=号码, x1=内容) -> 0 / -1
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
class Cond:
|
|
211
|
+
"""条件码编号 (与 Go 端一致)。"""
|
|
212
|
+
EQ = 0
|
|
213
|
+
NE = 1
|
|
214
|
+
CS = 2
|
|
215
|
+
CC = 3
|
|
216
|
+
MI = 4
|
|
217
|
+
PL = 5
|
|
218
|
+
VS = 6
|
|
219
|
+
VC = 7
|
|
220
|
+
HI = 8
|
|
221
|
+
LS = 9
|
|
222
|
+
GE = 10
|
|
223
|
+
LT = 11
|
|
224
|
+
GT = 12
|
|
225
|
+
LE = 13
|
|
226
|
+
AL = 14
|
|
227
|
+
NV = 15
|
|
228
|
+
|
|
229
|
+
NAMES = ('EQ', 'NE', 'CS', 'CC', 'MI', 'PL', 'VS', 'VC',
|
|
230
|
+
'HI', 'LS', 'GE', 'LT', 'GT', 'LE', 'AL', 'NV')
|
|
231
|
+
|
|
232
|
+
@classmethod
|
|
233
|
+
def code(cls, name: str) -> int:
|
|
234
|
+
return cls.NAMES.index(name.upper())
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
# 字节码操作数类型码 (与 Go native 库共享)
|
|
238
|
+
KIND_REG = 0
|
|
239
|
+
KIND_IMM = 1
|
|
240
|
+
KIND_VEC = 2
|
|
241
|
+
KIND_VECLANE = 3
|
|
242
|
+
KIND_MEM = 4
|
|
243
|
+
KIND_COND = 5
|
|
244
|
+
KIND_FLOAT = 6
|
|
245
|
+
KIND_STR = 7
|
|
246
|
+
|
|
247
|
+
BC_MAGIC = b'UCBC'
|
|
248
|
+
BC_VERSION = 1
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
class Constants:
|
|
252
|
+
NUM_REGISTERS = 32
|
|
253
|
+
SP_REG = 32 # 伪寄存器: 栈指针
|
|
254
|
+
NUM_REGS_TOTAL = 33 # 0-31 通用 + 32 SP
|
|
255
|
+
NUM_VECTOR_REGISTERS = 32
|
|
256
|
+
VECTOR_LANES = 4
|
|
257
|
+
INSTR_SIZE = 16
|
|
258
|
+
DEFAULT_MEM_SIZE = 1024 * 64
|
|
259
|
+
MAGIC_NUMBER = b'CPUSA'
|
|
260
|
+
CROM_MAGIC = b'CROM'
|
|
261
|
+
CROM_VERSION = 3
|
|
262
|
+
BIN_VERSION = 2
|
|
263
|
+
MAX_INSTRUCTIONS = 100_000_000
|
|
264
|
+
STACK_SLOT = 8 # 栈槽位大小 (qword)
|
|
265
|
+
|
|
266
|
+
OPCODE_NAMES: Dict['Opcode', str] = {
|
|
267
|
+
Opcode.MOV: 'MOV', Opcode.LOAD: 'LOAD', Opcode.STORE: 'STORE',
|
|
268
|
+
Opcode.ADD: 'ADD', Opcode.SUB: 'SUB', Opcode.MUL: 'MUL',
|
|
269
|
+
Opcode.DIV: 'DIV', Opcode.AND: 'AND', Opcode.OR: 'OR',
|
|
270
|
+
Opcode.XOR: 'XOR', Opcode.SHL: 'SHL', Opcode.SHR: 'SHR',
|
|
271
|
+
Opcode.INC: 'INC', Opcode.DEC: 'DEC', Opcode.CMP: 'CMP',
|
|
272
|
+
Opcode.JMP: 'JMP', Opcode.JZ: 'JZ', Opcode.JNZ: 'JNZ',
|
|
273
|
+
Opcode.JE: 'JE', Opcode.JL: 'JL', Opcode.JG: 'JG',
|
|
274
|
+
Opcode.PUSH: 'PUSH', Opcode.POP: 'POP', Opcode.CALL: 'CALL',
|
|
275
|
+
Opcode.RET: 'RET', Opcode.IN: 'IN', Opcode.OUT: 'OUT',
|
|
276
|
+
Opcode.HALT: 'HALT',
|
|
277
|
+
Opcode.ADDS: 'ADDS', Opcode.SUBS: 'SUBS',
|
|
278
|
+
Opcode.ADDC: 'ADDC', Opcode.SUBC: 'SUBC',
|
|
279
|
+
Opcode.LSL: 'LSL', Opcode.LSR: 'LSR',
|
|
280
|
+
Opcode.ASR: 'ASR', Opcode.ROR: 'ROR',
|
|
281
|
+
Opcode.MVN: 'MVN', Opcode.EOR: 'EOR',
|
|
282
|
+
Opcode.BIC: 'BIC', Opcode.ORN: 'ORN',
|
|
283
|
+
Opcode.LDR: 'LDR', Opcode.STR: 'STR',
|
|
284
|
+
Opcode.LDP: 'LDP', Opcode.STP: 'STP',
|
|
285
|
+
Opcode.CBZ: 'CBZ', Opcode.CBNZ: 'CBNZ',
|
|
286
|
+
Opcode.TBZ: 'TBZ', Opcode.TBNZ: 'TBNZ',
|
|
287
|
+
Opcode.B: 'B', Opcode.BL: 'BL', Opcode.BR: 'BR',
|
|
288
|
+
Opcode.NOP: 'NOP', Opcode.WFE: 'WFE',
|
|
289
|
+
Opcode.WFI: 'WFI', Opcode.SEV: 'SEV',
|
|
290
|
+
Opcode.CSEL: 'CSEL', Opcode.CSINC: 'CSINC',
|
|
291
|
+
Opcode.CSINV: 'CSINV', Opcode.CSNEG: 'CSNEG',
|
|
292
|
+
Opcode.SXTB: 'SXTB', Opcode.SXTH: 'SXTH',
|
|
293
|
+
Opcode.SXTW: 'SXTW', Opcode.UXTB: 'UXTB',
|
|
294
|
+
Opcode.UXTH: 'UXTH',
|
|
295
|
+
Opcode.CLZ: 'CLZ', Opcode.CLS: 'CLS',
|
|
296
|
+
Opcode.RBIT: 'RBIT', Opcode.REV: 'REV',
|
|
297
|
+
Opcode.FADD: 'FADD', Opcode.FSUB: 'FSUB',
|
|
298
|
+
Opcode.FMUL: 'FMUL', Opcode.FDIV: 'FDIV',
|
|
299
|
+
Opcode.FCMP: 'FCMP', Opcode.FCVT: 'FCVT',
|
|
300
|
+
Opcode.FABS: 'FABS', Opcode.FNEG: 'FNEG',
|
|
301
|
+
Opcode.LDRS: 'LDRS', Opcode.STRS: 'STRS',
|
|
302
|
+
Opcode.VADD: 'VADD', Opcode.VSUB: 'VSUB',
|
|
303
|
+
Opcode.VMUL: 'VMUL', Opcode.VDIV: 'VDIV',
|
|
304
|
+
Opcode.VLD1: 'VLD1', Opcode.VST1: 'VST1',
|
|
305
|
+
Opcode.LB: 'LB', Opcode.LH: 'LH', Opcode.LW: 'LW',
|
|
306
|
+
Opcode.LD: 'LD', Opcode.SB: 'SB', Opcode.SH: 'SH',
|
|
307
|
+
Opcode.SW: 'SW', Opcode.SD: 'SD',
|
|
308
|
+
Opcode.ADDI: 'ADDI', Opcode.SLTI: 'SLTI',
|
|
309
|
+
Opcode.SLTIU: 'SLTIU', Opcode.XORI: 'XORI',
|
|
310
|
+
Opcode.ORI: 'ORI', Opcode.ANDI: 'ANDI',
|
|
311
|
+
Opcode.SLLI: 'SLLI', Opcode.SRLI: 'SRLI',
|
|
312
|
+
Opcode.SRAI: 'SRAI',
|
|
313
|
+
Opcode.BEQ: 'BEQ', Opcode.BNE: 'BNE',
|
|
314
|
+
Opcode.BLT: 'BLT', Opcode.BGE: 'BGE',
|
|
315
|
+
Opcode.BLTU: 'BLTU', Opcode.BGEU: 'BGEU',
|
|
316
|
+
Opcode.JALR: 'JALR', Opcode.JAL: 'JAL',
|
|
317
|
+
Opcode.LUI: 'LUI', Opcode.AUIPC: 'AUIPC',
|
|
318
|
+
Opcode.SYS: 'SYS',
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
OPCODE_NAME_TO_ENUM: Dict[str, 'Opcode'] = {v: k for k, v in OPCODE_NAMES.items()}
|
|
322
|
+
|
|
323
|
+
# 参数个数; -1 表示不检查 (变长)
|
|
324
|
+
ARG_COUNTS: Dict['Opcode', int] = {
|
|
325
|
+
Opcode.MOV: 2, Opcode.LOAD: 2, Opcode.STORE: 2,
|
|
326
|
+
Opcode.ADD: 2, Opcode.SUB: 2, Opcode.MUL: 2,
|
|
327
|
+
Opcode.DIV: 2, Opcode.AND: 2, Opcode.OR: 2,
|
|
328
|
+
Opcode.XOR: 2, Opcode.SHL: 2, Opcode.SHR: 2,
|
|
329
|
+
Opcode.INC: 1, Opcode.DEC: 1, Opcode.CMP: 2,
|
|
330
|
+
Opcode.JMP: 1, Opcode.JZ: 1, Opcode.JNZ: 1,
|
|
331
|
+
Opcode.JE: 1, Opcode.JL: 1, Opcode.JG: 1,
|
|
332
|
+
Opcode.PUSH: 1, Opcode.POP: 1, Opcode.CALL: 1,
|
|
333
|
+
Opcode.RET: 0, Opcode.IN: 1, Opcode.OUT: 1,
|
|
334
|
+
Opcode.HALT: 0,
|
|
335
|
+
Opcode.ADDS: 3, Opcode.SUBS: 3,
|
|
336
|
+
Opcode.ADDC: 3, Opcode.SUBC: 3,
|
|
337
|
+
Opcode.LSL: 3, Opcode.LSR: 3,
|
|
338
|
+
Opcode.ASR: 3, Opcode.ROR: 3,
|
|
339
|
+
Opcode.MVN: 2, Opcode.EOR: 3,
|
|
340
|
+
Opcode.BIC: 3, Opcode.ORN: 3,
|
|
341
|
+
Opcode.LDR: 2, Opcode.STR: 2,
|
|
342
|
+
Opcode.LDP: 3, Opcode.STP: 3,
|
|
343
|
+
Opcode.CBZ: 2, Opcode.CBNZ: 2,
|
|
344
|
+
Opcode.TBZ: 3, Opcode.TBNZ: 3,
|
|
345
|
+
Opcode.B: -1, Opcode.BL: 1, Opcode.BR: 1,
|
|
346
|
+
Opcode.NOP: 0, Opcode.WFE: 0,
|
|
347
|
+
Opcode.WFI: 0, Opcode.SEV: 0,
|
|
348
|
+
Opcode.CSEL: 4, Opcode.CSINC: 4,
|
|
349
|
+
Opcode.CSINV: 4, Opcode.CSNEG: 4,
|
|
350
|
+
Opcode.SXTB: 2, Opcode.SXTH: 2,
|
|
351
|
+
Opcode.SXTW: 2,
|
|
352
|
+
Opcode.UXTB: 2, Opcode.UXTH: 2,
|
|
353
|
+
Opcode.CLZ: 2, Opcode.CLS: 2,
|
|
354
|
+
Opcode.RBIT: 2, Opcode.REV: 2,
|
|
355
|
+
Opcode.FADD: 3, Opcode.FSUB: 3,
|
|
356
|
+
Opcode.FMUL: 3, Opcode.FDIV: 3,
|
|
357
|
+
Opcode.FCMP: 2, Opcode.FCVT: 2,
|
|
358
|
+
Opcode.FABS: 2, Opcode.FNEG: 2,
|
|
359
|
+
Opcode.LDRS: 2, Opcode.STRS: 2,
|
|
360
|
+
Opcode.VADD: 3, Opcode.VSUB: 3,
|
|
361
|
+
Opcode.VMUL: 3, Opcode.VDIV: 3,
|
|
362
|
+
Opcode.VLD1: 2, Opcode.VST1: 2,
|
|
363
|
+
Opcode.LB: 2, Opcode.LH: 2, Opcode.LW: 2,
|
|
364
|
+
Opcode.LD: 2, Opcode.SB: 2, Opcode.SH: 2,
|
|
365
|
+
Opcode.SW: 2, Opcode.SD: 2,
|
|
366
|
+
Opcode.ADDI: 3, Opcode.SLTI: 3,
|
|
367
|
+
Opcode.SLTIU: 3, Opcode.XORI: 3,
|
|
368
|
+
Opcode.ORI: 3, Opcode.ANDI: 3,
|
|
369
|
+
Opcode.SLLI: 3, Opcode.SRLI: 3,
|
|
370
|
+
Opcode.SRAI: 3,
|
|
371
|
+
Opcode.BEQ: 3, Opcode.BNE: 3,
|
|
372
|
+
Opcode.BLT: 3, Opcode.BGE: 3,
|
|
373
|
+
Opcode.BLTU: 3, Opcode.BGEU: 3,
|
|
374
|
+
Opcode.JALR: -1, Opcode.JAL: 2,
|
|
375
|
+
Opcode.LUI: 2, Opcode.AUIPC: 2,
|
|
376
|
+
Opcode.SYS: -1,
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
CONDITIONS: Set[str] = {
|
|
380
|
+
'EQ', 'NE', 'CS', 'CC', 'MI', 'PL', 'VS', 'VC',
|
|
381
|
+
'HI', 'LS', 'GE', 'LT', 'GT', 'LE', 'AL', 'NV'
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
DATA_DIRECTIVES: Set[str] = {
|
|
385
|
+
'DB', 'DW', 'DD', 'DQ', 'BYTE', 'WORD', 'DWORD', 'QWORD',
|
|
386
|
+
'ASCII', 'ASCIZ', 'STRING'
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
PL_KEYWORDS: Dict[str, str] = {
|
|
390
|
+
'set': 'MOV', 'load': 'LOAD', 'store': 'STORE',
|
|
391
|
+
'add': 'ADD', 'subtract': 'SUB', 'multiply': 'MUL', 'divide': 'DIV',
|
|
392
|
+
'and': 'AND', 'or': 'OR', 'xor': 'XOR',
|
|
393
|
+
'shift_left': 'SHL', 'shift_right': 'SHR',
|
|
394
|
+
'increment': 'INC', 'decrement': 'DEC',
|
|
395
|
+
'compare': 'CMP', 'jump': 'JMP', 'jump_zero': 'JZ',
|
|
396
|
+
'jump_not_zero': 'JNZ', 'jump_equal': 'JE',
|
|
397
|
+
'jump_less': 'JL', 'jump_greater': 'JG',
|
|
398
|
+
'push': 'PUSH', 'pop': 'POP', 'call': 'CALL',
|
|
399
|
+
'return': 'RET', 'input': 'IN', 'output': 'OUT', 'stop': 'HALT',
|
|
400
|
+
'add_set': 'ADDS', 'subtract_set': 'SUBS',
|
|
401
|
+
'add_carry': 'ADDC', 'subtract_carry': 'SUBC',
|
|
402
|
+
'logical_shift_left': 'LSL', 'logical_shift_right': 'LSR',
|
|
403
|
+
'arithmetic_shift_right': 'ASR', 'rotate_right': 'ROR',
|
|
404
|
+
'move_not': 'MVN', 'exclusive_or': 'EOR',
|
|
405
|
+
'bit_clear': 'BIC', 'or_not': 'ORN',
|
|
406
|
+
'load_register': 'LDR', 'store_register': 'STR',
|
|
407
|
+
'load_pair': 'LDP', 'store_pair': 'STP',
|
|
408
|
+
'compare_branch_zero': 'CBZ', 'compare_branch_not_zero': 'CBNZ',
|
|
409
|
+
'test_branch_zero': 'TBZ', 'test_branch_not_zero': 'TBNZ',
|
|
410
|
+
'branch': 'B', 'branch_link': 'BL', 'branch_register': 'BR',
|
|
411
|
+
'nop': 'NOP', 'wait_event': 'WFE', 'wait_interrupt': 'WFI',
|
|
412
|
+
'send_event': 'SEV',
|
|
413
|
+
'select': 'CSEL', 'select_increment': 'CSINC',
|
|
414
|
+
'select_invert': 'CSINV', 'select_negate': 'CSNEG',
|
|
415
|
+
'sign_extend_byte': 'SXTB', 'sign_extend_half': 'SXTH',
|
|
416
|
+
'sign_extend_word': 'SXTW', 'zero_extend_byte': 'UXTB',
|
|
417
|
+
'zero_extend_half': 'UXTH', 'count_leading_zeros': 'CLZ',
|
|
418
|
+
'count_leading_sign': 'CLS', 'reverse_bits': 'RBIT',
|
|
419
|
+
'reverse_bytes': 'REV',
|
|
420
|
+
'float_add': 'FADD', 'float_subtract': 'FSUB',
|
|
421
|
+
'float_multiply': 'FMUL', 'float_divide': 'FDIV',
|
|
422
|
+
'float_compare': 'FCMP', 'float_convert': 'FCVT',
|
|
423
|
+
'float_abs': 'FABS', 'float_negate': 'FNEG',
|
|
424
|
+
'load_float': 'LDRS', 'store_float': 'STRS',
|
|
425
|
+
'vec_add': 'VADD', 'vec_subtract': 'VSUB',
|
|
426
|
+
'vec_multiply': 'VMUL', 'vec_divide': 'VDIV',
|
|
427
|
+
'vec_load': 'VLD1', 'vec_store': 'VST1',
|
|
428
|
+
'load_byte': 'LB', 'load_half': 'LH', 'load_word': 'LW',
|
|
429
|
+
'load_double': 'LD',
|
|
430
|
+
'store_byte': 'SB', 'store_half': 'SH', 'store_word': 'SW',
|
|
431
|
+
'store_double': 'SD',
|
|
432
|
+
'add_imm': 'ADDI', 'set_less_than_imm': 'SLTI',
|
|
433
|
+
'set_less_than_imm_unsigned': 'SLTIU',
|
|
434
|
+
'xor_imm': 'XORI', 'or_imm': 'ORI', 'and_imm': 'ANDI',
|
|
435
|
+
'shift_left_logical_imm': 'SLLI',
|
|
436
|
+
'shift_right_logical_imm': 'SRLI',
|
|
437
|
+
'shift_right_arithmetic_imm': 'SRAI',
|
|
438
|
+
'branch_equal': 'BEQ', 'branch_not_equal': 'BNE',
|
|
439
|
+
'branch_less_than': 'BLT', 'branch_greater_equal': 'BGE',
|
|
440
|
+
'branch_less_than_unsigned': 'BLTU',
|
|
441
|
+
'branch_greater_equal_unsigned': 'BGEU',
|
|
442
|
+
'jump_and_link_register': 'JALR',
|
|
443
|
+
'jump_and_link': 'JAL',
|
|
444
|
+
'load_upper_imm': 'LUI', 'add_upper_imm_pc': 'AUIPC',
|
|
445
|
+
'syscall': 'SYS',
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
# 分支类指令 (统计用)
|
|
449
|
+
BRANCH_OPS = frozenset({
|
|
450
|
+
'JMP', 'JZ', 'JNZ', 'JE', 'JL', 'JG', 'B', 'BL', 'BR',
|
|
451
|
+
'BEQ', 'BNE', 'BLT', 'BGE', 'BLTU', 'BGEU',
|
|
452
|
+
'CBZ', 'CBNZ', 'TBZ', 'TBNZ', 'JAL', 'JALR', 'CALL', 'RET',
|
|
453
|
+
})
|
|
454
|
+
|
|
455
|
+
FP_OPS = frozenset({
|
|
456
|
+
'FADD', 'FSUB', 'FMUL', 'FDIV', 'VADD', 'VSUB', 'VMUL', 'VDIV',
|
|
457
|
+
})
|