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
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
+ })