phase-36: T5 CLOSE — the GTE consolidation and the dead-macro sweep: include/gte_inline.h (50 canonical macros for 9,102 definitions), 8,951 per-TU definitions deleted, 629 clobber variants freed byte-identical and 70 kept as marked levers, 575 direct statements → Sony-named calls, 274 dead launder macros swept; the census learns cross-file macro names (10 launders surfaced in two shared headers, 6 removed); per-TU asm macro definitions 9,540 → 314 with 0 canonical duplicates; THE NUMBER 34,091 sites (incl. 462 GTE levers) in 12,712 bodies, all marked, 0 orphans — lever_census --check OK; R22 218/218; SETUP rows; kit corpus; the 🛑 block for T6

This commit is contained in:
Drew T
2026-09-09 07:12:06 -06:00
parent 4bc987426c
commit d025e67e71
16 changed files with 1005 additions and 331 deletions
+476
View File
@@ -0,0 +1,476 @@
clean: removed build/, expected/, and the regenerated splat tree (asm/, assets/, undefined_*_auto.txt).
disc-extract: up to date — extracted/retail/ matches the committed manifest (sha1 e5c6019249dec3c71bb2cf40658a78439dddb037)
splat 0.41.0 (powered by spimdisasm 1.41.0)
0%| | 0/1096 [00:00<?, ?it/s]
Loading symbols (symbols.us): 0%| | 0/1096 [00:00<?, ?it/s]
Loading symbols (symbols.us): 100%|██████████| 1096/1096 [00:00<00:00, 194769.82it/s]
0%| | 0/47 [00:00<?, ?it/s]
Loading symbols (symbols.us.ram): 0%| | 0/47 [00:00<?, ?it/s]
Loading symbols (symbols.us.ram): 100%|██████████| 47/47 [00:00<00:00, 642124.72it/s]
0%| | 0/2 [00:00<?, ?it/s]
Scanning header: 0%| | 0/2 [00:00<?, ?it/s]
Scanning main: 0%| | 0/2 [00:00<?, ?it/s]
Rodata segment '800' may belong to the text segment '800'
Based on the usage from the function LzssDecodeSector to the symbol jtbl_80072A38
The rodata segment '800' has jumptables that are not aligned properly file-wise, indicating one or more likely file split.
File split suggestions for this segment will follow in config yaml format:
- [0x6324C, .rodata]
- [0x63388, .rodata]
- [0x633FC, .rodata]
Rodata segment '800_b' may belong to the text segment '800_b'
Based on the usage from the function func_8002B0B4 to the symbol jtbl_80072E44
Rodata segment '800_b_2' may belong to the text segment '800_b_2'
Based on the usage from the function func_8002DC68 to the symbol jtbl_80072F3C
The rodata segment '800_b_2' has jumptables that are not aligned properly file-wise, indicating one or more likely file split.
File split suggestions for this segment will follow in config yaml format:
- [0x63920, .rodata]
Rodata segment '800_c' may belong to the text segment '800_c'
Based on the usage from the function func_80035270 to the symbol jtbl_800732A0
Scanning main: 100%|██████████| 2/2 [00:01<00:00, 1.29it/s]
Scanning main: 100%|██████████| 2/2 [00:01<00:00, 1.29it/s]
0%| | 0/2 [00:00<?, ?it/s]
Splitting header: 0%| | 0/2 [00:00<?, ?it/s]
Splitting main: 0%| | 0/2 [00:00<?, ?it/s]
Splitting main: 100%|██████████| 2/2 [00:00<00:00, 2.19it/s]
Splitting main: 100%|██████████| 2/2 [00:00<00:00, 2.19it/s]
0%| | 0/2 [00:00<?, ?it/s]
Linker script header: 0%| | 0/2 [00:00<?, ?it/s]
Linker script main: 0%| | 0/2 [00:00<?, ?it/s]
Linker script main: 100%|██████████| 2/2 [00:00<00:00, 82.37it/s]
Split 340 KB (82.28%) in defined segments
header: 2 KB (0.50%) 1 split, 0 cached
c: 338 KB (81.78%) 85 split, 0 cached
unknown: 0 B (0.00%) from unknown bin files
ld_interleave --order: .main island = 8 pieces [53198.data.o, 800.o, 63470.data.o, 800_b.o, 800_b_2.o, 63940.data.o, 800_c.o, 63C4C.data.o]; pre=0 text=85 empties=166 bss=85
[ OK ] resident
[ OK ] ov_SC05_000
[ OK ] ov_SC04_000
[ OK ] ov_SC06_000
[ OK ] ov_SC01_000
[ OK ] ov_SC01_005
[ OK ] ov_SC01_077
[ OK ] ov_SC02_003
[ OK ] ov_SC01_006
[ OK ] ov_SC04_018
[ OK ] ov_SC04_019
[ OK ] ov_SC03_002
[ OK ] ov_SC02_000
[ OK ] ov_SC03_006
[ OK ] ov_SC03_001
[ OK ] ov_SC01_001
[ OK ] ov_SC01_004
[ OK ] ov_SC01_074
[ OK ] ov_SC01_008
[ OK ] ov_SC07_000
[ OK ] ov_SC02_004
[ OK ] ov_SC02_015
[ OK ] ov_SC02_021
[ OK ] ov_SC01_080
[ OK ] ov_SC01_009
[ OK ] ov_SC01_084
[ OK ] ov_SC02_016
[ OK ] ov_SC02_039
[ OK ] ov_SC02_011
[ OK ] ov_SC02_026
[ OK ] ov_SC02_031
[ OK ] ov_SC02_005
[ OK ] ov_SC03_003
[ OK ] ov_SC02_028
[ OK ] ov_SC02_035
[ OK ] ov_SC02_027
[ OK ] ov_SC02_017
[ OK ] ov_SC02_041
[ OK ] ov_SC03_010
[ OK ] ov_SC03_012
[ OK ] ov_SC03_011
[ OK ] ov_SC03_023
[ OK ] ov_SC03_007
[ OK ] ov_SC03_013
[ OK ] ov_SC03_024
[ OK ] ov_SC03_031
[ OK ] ov_SC03_089
[ OK ] ov_SC03_092
[ OK ] ov_SC03_029
[ OK ] ov_SC03_015
[ OK ] ov_SC03_090
[ OK ] ov_SC03_030
[ OK ] ov_SC03_028
[ OK ] ov_SC03_091
[ OK ] ov_SC03_014
[ OK ] ov_SC03_093
[ OK ] ov_SC03_095
[ OK ] ov_SC03_096
[ OK ] ov_SC03_094
[ OK ] ov_SC03_097
[ OK ] ov_SC03_098
[ OK ] ov_SC03_101
[ OK ] ov_SC03_109
[ OK ] ov_SC03_108
[ OK ] ov_SC03_110
[ OK ] ov_SC03_102
[ OK ] ov_SC03_099
[ OK ] ov_SC03_103
[ OK ] ov_SC03_105
[ OK ] ov_SC03_112
[ OK ] ov_SC03_104
[ OK ] ov_SC03_100
[ OK ] ov_SC03_113
[ OK ] ov_SC03_111
[ OK ] ov_SC03_114
[ OK ] ov_SC03_115
[ OK ] ov_SC03_116
[ OK ] ov_SC03_126
[ OK ] ov_SC04_008
[ OK ] ov_SC03_121
[ OK ] ov_SC04_003
[ OK ] ov_SC03_117
[ OK ] ov_SC04_006
[ OK ] ov_SC03_118
[ OK ] ov_SC04_004
[ OK ] ov_SC03_119
[ OK ] ov_SC04_007
[ OK ] ov_SC04_002
[ OK ] ov_SC03_125
[ OK ] ov_SC04_010
[ OK ] ov_SC04_005
[ OK ] ov_SC03_124
[ OK ] ov_SC04_009
[ OK ] ov_SC04_012
[ OK ] ov_SC04_021
[ OK ] ov_SC04_016
[ OK ] ov_SC05_006
[ OK ] ov_SC04_020
[ OK ] ov_SC05_002
[ OK ] ov_SC05_004
[ OK ] ov_SC05_009
[ OK ] ov_SC05_007
[ OK ] ov_SC05_001
[ OK ] ov_SC05_003
[ OK ] ov_SC05_005
[ OK ] ov_SC04_015
[ OK ] ov_SC05_008
[ OK ] ov_SC04_011
[ OK ] ov_SC05_011
[ OK ] ov_SC05_019
[ OK ] ov_SC05_010
[ OK ] ov_SC06_013
[ OK ] ov_SC06_015
[ OK ] ov_SC06_008
[ OK ] ov_SC06_010
[ OK ] ov_SC06_011
[ OK ] ov_SC06_014
[ OK ] ov_SC06_016
[ OK ] ov_SC05_017
[ OK ] ov_SC05_018
[ OK ] ov_SC06_020
[ OK ] ov_SC06_006
[ OK ] ov_SC06_022
[ OK ] ov_SC06_018
[ OK ] ov_SC06_024
[ OK ] ov_SC06_025
[ OK ] ov_SC07_008
[ OK ] md_MAIN_013
[ OK ] ov_SC07_002
[ OK ] ov_SC07_001
[ OK ] ov_SC06_030
[ OK ] md_MAIN_014
[ OK ] md_MAIN_016
[ OK ] md_MAIN_015
[ OK ] md_MAIN_017
[ OK ] md_MAIN_018
[ OK ] ov_SC07_009
[ OK ] md_MAIN_019
[ OK ] ov_SC06_027
[ OK ] md_MAIN_020
[ OK ] md_MAIN_021
[ OK ] md_MAIN_022
[ OK ] md_MAIN_023
[ OK ] md_MAIN_024
[ OK ] ov_SC06_033
[ OK ] md_MAIN_025
[ OK ] md_MAIN_027
[ OK ] md_MAIN_028
[ OK ] md_MAIN_026
[ OK ] md_MAIN_029
[ OK ] md_MAIN_030
[ OK ] ov_SC06_032
[ OK ] md_MAIN_031
[ OK ] md_MAIN_032
[ OK ] md_MAIN_033
[ OK ] md_MAIN_035
[ OK ] ov_SC06_029
[ OK ] md_MAIN_034
[ OK ] md_MAIN_036
[ OK ] md_MAIN_037
[ OK ] ov_MAIN_012
[ OK ] md_MAIN_039
[ OK ] md_MAIN_040
[ OK ] md_MAIN_041
[ OK ] md_MAIN_042
[ OK ] md_MAIN_038
[ OK ] md_MAIN_043
[ OK ] md_MAIN_044
[ OK ] md_MAIN_045
[ OK ] md_MAIN_046
[ OK ] md_MAIN_047
[ OK ] ov_SC07_011
[ OK ] md_MAIN_008
[ OK ] md_MAIN_011
[ OK ] md_MAIN_001
[ OK ] ov_SC07_010
[ OK ] md_SC03_078
[ OK ] md_SC03_073
[ OK ] md_SC03_074
[ OK ] md_SC03_075
[ OK ] md_SC03_077
[ OK ] md_SC03_132
[ OK ] md_SC03_076
[ OK ] md_SC03_079
[ OK ] md_SC03_133
[ OK ] md_SC03_137
[ OK ] ov_SC07_007
[ OK ] md_SC03_134
[ OK ] md_SC03_136
[ OK ] md_SC03_135
[ OK ] md_MAIN_003
[ OK ] md_SC03_138
[ OK ] md_SC04_024
[ OK ] ov_SC03_107
[ OK ] md_SC04_026
[ OK ] md_SC04_029
[ OK ] ov_SC07_006
[ OK ] md_SC04_028
[ OK ] md_SC05_023
[ OK ] md_SC04_025
[ OK ] md_SC04_030
[ OK ] md_SC04_027
[ OK ] md_SC05_025
[ OK ] md_SC05_028
[ OK ] md_MAIN_007
[ OK ] md_SC05_024
[ OK ] md_SC05_027
[ OK ] md_SC05_026
[ OK ] md_MAIN_009
[ OK ] md_SC03_053
[ OK ] md_SC05_029
[ OK ] md_SC03_054
[ OK ] md_SC03_056
[ OK ] ov_SC02_037
[ OK ] md_SC02_009
[ OK ] md_SC07_004
[ OK ] md_SC07_003
extract-all: 217 extracted, 0 failed of 217 (+ main, serial)
[ OK ] resident
[ OK ] ov_SC04_000
[ OK ] ov_SC01_006
[ OK ] ov_SC01_000
[ OK ] ov_SC03_006
[ OK ] ov_SC01_001
[ OK ] ov_SC05_000
[ OK ] ov_SC03_002
[ OK ] ov_SC01_077
[ OK ] ov_SC04_018
[ OK ] ov_SC01_005
[ OK ] ov_SC06_000
[ OK ] ov_SC04_019
[ OK ] ov_SC02_000
[ OK ] ov_SC02_003
[ OK ] ov_SC03_001
[ OK ] ov_SC01_008
[ OK ] ov_SC01_004
[ OK ] ov_SC07_000
[ OK ] ov_SC02_004
[ OK ] ov_SC01_074
[ OK ] ov_SC02_015
[ OK ] ov_SC01_009
[ OK ] ov_SC02_016
[ OK ] ov_SC01_080
[ OK ] ov_SC02_021
[ OK ] ov_SC02_011
[ OK ] ov_SC02_026
[ OK ] ov_SC02_017
[ OK ] ov_SC01_084
[ OK ] ov_SC02_005
[ OK ] ov_SC02_031
[ OK ] ov_SC02_039
[ OK ] ov_SC02_028
[ OK ] ov_SC02_041
[ OK ] ov_SC02_027
[ OK ] ov_SC02_035
[ OK ] ov_SC03_003
[ OK ] ov_SC03_012
[ OK ] ov_SC03_011
[ OK ] ov_SC03_013
[ OK ] ov_SC03_010
[ OK ] ov_SC03_007
[ OK ] ov_SC03_023
[ OK ] ov_SC03_014
[ OK ] ov_SC03_015
[ OK ] ov_SC03_024
[ OK ] ov_SC03_030
[ OK ] ov_SC03_031
[ OK ] ov_SC03_090
[ OK ] ov_SC03_029
[ OK ] ov_SC03_089
[ OK ] ov_SC03_028
[ OK ] ov_SC03_092
[ OK ] ov_SC03_093
[ OK ] ov_SC03_091
[ OK ] ov_SC03_094
[ OK ] ov_SC03_096
[ OK ] ov_SC03_095
[ OK ] main
[ OK ] ov_SC03_097
[ OK ] ov_SC03_098
[ OK ] ov_SC03_099
[ OK ] ov_SC03_100
[ OK ] ov_SC03_101
[ OK ] ov_SC03_102
[ OK ] ov_SC03_109
[ OK ] ov_SC03_103
[ OK ] ov_SC03_108
[ OK ] ov_SC03_110
[ OK ] ov_SC03_104
[ OK ] ov_SC03_111
[ OK ] ov_SC03_105
[ OK ] ov_SC03_113
[ OK ] ov_SC03_112
[ OK ] ov_SC03_114
[ OK ] ov_SC03_115
[ OK ] ov_SC03_116
[ OK ] ov_SC03_117
[ OK ] ov_SC03_121
[ OK ] ov_SC03_126
[ OK ] ov_SC03_118
[ OK ] ov_SC03_125
[ OK ] ov_SC03_119
[ OK ] ov_SC04_003
[ OK ] ov_SC04_002
[ OK ] ov_SC03_124
[ OK ] ov_SC04_004
[ OK ] ov_SC04_008
[ OK ] ov_SC04_005
[ OK ] ov_SC04_006
[ OK ] ov_SC04_007
[ OK ] ov_SC04_010
[ OK ] ov_SC04_009
[ OK ] ov_SC04_012
[ OK ] ov_SC04_011
[ OK ] ov_SC04_016
[ OK ] ov_SC04_021
[ OK ] ov_SC04_015
[ OK ] ov_SC04_020
[ OK ] ov_SC05_002
[ OK ] ov_SC05_004
[ OK ] ov_SC05_003
[ OK ] ov_SC05_001
[ OK ] ov_SC05_006
[ OK ] ov_SC05_007
[ OK ] ov_SC05_005
[ OK ] ov_SC05_009
[ OK ] ov_SC05_008
[ OK ] ov_SC05_010
[ OK ] ov_SC05_011
[ OK ] ov_SC05_019
[ OK ] ov_SC06_011
[ OK ] ov_SC06_008
[ OK ] ov_SC05_018
[ OK ] ov_SC06_010
[ OK ] ov_SC06_013
[ OK ] ov_SC06_006
[ OK ] ov_SC06_015
[ OK ] ov_SC06_014
[ OK ] ov_SC05_017
[ OK ] ov_SC06_020
[ OK ] ov_SC06_016
[ OK ] ov_SC06_018
[ OK ] ov_SC06_022
[ OK ] ov_SC06_024
[ OK ] ov_SC06_027
[ OK ] ov_SC06_025
[ OK ] md_MAIN_013
[ OK ] md_MAIN_014
[ OK ] md_MAIN_015
[ OK ] md_MAIN_016
[ OK ] ov_SC06_030
[ OK ] md_MAIN_017
[ OK ] ov_SC07_001
[ OK ] md_MAIN_018
[ OK ] md_MAIN_019
[ OK ] ov_SC07_008
[ OK ] md_MAIN_021
[ OK ] md_MAIN_020
[ OK ] ov_SC07_002
[ OK ] md_MAIN_023
[ OK ] md_MAIN_022
[ OK ] md_MAIN_024
[ OK ] md_MAIN_025
[ OK ] ov_SC07_009
[ OK ] ov_SC06_029
[ OK ] md_MAIN_026
[ OK ] md_MAIN_028
[ OK ] md_MAIN_029
[ OK ] md_MAIN_027
[ OK ] md_MAIN_031
[ OK ] md_MAIN_030
[ OK ] md_MAIN_033
[ OK ] md_MAIN_034
[ OK ] md_MAIN_035
[ OK ] md_MAIN_032
[ OK ] md_MAIN_037
[ OK ] md_MAIN_036
[ OK ] md_MAIN_038
[ OK ] md_MAIN_042
[ OK ] md_MAIN_039
[ OK ] md_MAIN_041
[ OK ] md_MAIN_043
[ OK ] md_MAIN_040
[ OK ] md_MAIN_045
[ OK ] md_MAIN_044
[ OK ] ov_SC07_006
[ OK ] md_MAIN_001
[ OK ] md_MAIN_008
[ OK ] md_MAIN_047
[ OK ] md_MAIN_046
[ OK ] md_MAIN_011
[ OK ] ov_SC07_010
[ OK ] md_SC03_074
[ OK ] ov_SC06_032
[ OK ] md_SC03_073
[ OK ] md_SC03_075
[ OK ] md_SC03_078
[ OK ] ov_SC07_011
[ OK ] ov_SC06_033
[ OK ] md_SC03_132
[ OK ] md_SC03_133
[ OK ] md_SC03_077
[ OK ] md_SC03_079
[ OK ] md_SC03_134
[ OK ] md_SC03_076
[ OK ] md_SC07_003
[ OK ] ov_SC07_007
[ OK ] md_SC03_135
[ OK ] md_SC03_137
[ OK ] md_SC04_025
[ OK ] md_SC03_136
[ OK ] md_SC04_024
[ OK ] md_SC03_138
[ OK ] md_SC04_026
[ OK ] md_SC04_029
[ OK ] md_MAIN_003
[ OK ] md_SC04_030
[ OK ] md_SC07_004
[ OK ] md_SC04_028
+55 -32
View File
@@ -3,13 +3,36 @@
"gte_header": "include/gte_inline.h",
"gte_header_sites": 0,
"gte_mnemonics": {
"cfc2": 1,
"gte_rt": 3,
"lw": 24,
"lwc2": 159,
"mfc2": 1,
"nop": 1,
"swc2": 14
"gte_SetRotMatrix": 246,
"gte_SetTransMatrix": 226,
"gte_dpcl": 134,
"gte_ldIR0z": 134,
"gte_ldIRGB": 134,
"gte_ldclmv": 72,
"gte_ldrgb": 164,
"gte_ldv0": 757,
"gte_ldv3": 177,
"gte_ldv3c": 184,
"gte_nclip": 108,
"gte_rtir": 75,
"gte_rtps": 437,
"gte_rtpt": 352,
"gte_rtv0tr": 228,
"gte_stORGB": 134,
"gte_stclmv": 108,
"gte_stflg": 415,
"gte_stlvnl": 593,
"gte_stopz": 108,
"gte_stsv": 161,
"gte_stsxy": 447,
"gte_stsxy3": 236,
"gte_stsxy3_f3": 111,
"gte_stsxy3_ft3": 79,
"gte_stsxy3c": 108,
"gte_stsz3": 147,
"gte_stsz4": 149,
"gte_stszotz": 134,
"lwc2": 159
},
"instruction_mnemonics": {
".section": 7,
@@ -37,12 +60,12 @@
"gte-lever/via-macro": 100,
"gte-unsigned/direct": 3,
"gte/direct": 200,
"gte/via-macro": 3,
"gte/via-macro": 6658,
"instruction/direct": 1690,
"instruction/via-macro": 22,
"keepalive/direct": 2000,
"launder/direct": 4236,
"launder/via-macro": 440,
"launder/via-macro": 444,
"verbatim-body/direct": 2682
}
},
@@ -62,25 +85,25 @@
"unmarked": 0
},
"B": {
"bodies": 9435,
"distinct_bodies": 905,
"bodies": 9766,
"distinct_bodies": 1063,
"file_scope": 13,
"in_bodies": 16316,
"in_bodies": 22975,
"kinds": {
"asm-body": 13,
"barrier": 4578,
"gte": 203,
"gte": 6858,
"gte-lever": 462,
"gte-unsigned": 3,
"instruction": 1712,
"keepalive": 2000,
"launder": 4676,
"launder": 4680,
"verbatim-body": 2682
},
"marked": 13443,
"sites": 16329,
"tus": 2279,
"unmarked": 2886
"marked": 13711,
"sites": 22988,
"tus": 2297,
"unmarked": 9277
},
"C": {
"bodies": 628,
@@ -214,7 +237,7 @@
}
},
"coverage_ok": true,
"elapsed_s": 33.0,
"elapsed_s": 40.8,
"generated": "2026-09-09",
"gte_levers": {
"direct": 362,
@@ -225,15 +248,15 @@
"via_macro": 100,
"what": "GTE ops whose clobbers exceed the canonical macro's (a scheduling steer): class-B levers INSIDE the headline number since T5 (2026-09-09), marked, 0 at the close"
},
"head": "3b2c5178b",
"head": "4bc987426",
"headers": 3181,
"levers_AB": {
"asm": 13441,
"asm": 13445,
"bodies": 12712,
"distinct_bodies": 1759,
"marked": 34087,
"marked": 34091,
"pins": 20646,
"sites": 34087,
"sites": 34091,
"unmarked": 0,
"what": "register pins + asm statements excluding GTE ops: the classes the phase drives to 0"
},
@@ -410,21 +433,21 @@
"volatile_qualified": 134,
"zero": 1321
},
"src_stamp": "a667519a38753e8f",
"src_stamp": "3b72bfb04cfd5830",
"tus": 4121,
"unclassified": 0,
"union_AD": {
"bodies": 15659,
"bodies": 15961,
"by_kind": {
"main": 159,
"md": 167,
"ov": 14998,
"main": 180,
"md": 182,
"ov": 15258,
"resident": 12,
"shared": 323
"shared": 329
},
"copies_in_multi": 14142,
"distinct_bodies": 1895,
"multi_copy_classes": 378
"copies_in_multi": 14331,
"distinct_bodies": 2031,
"multi_copy_classes": 401
},
"verbatim_excluded": {
"functions": 13,
+6 -6
View File
@@ -6,26 +6,26 @@ lever_census: 218 binaries · 4,121 TUs + 3,181 headers · coverage OK · unclas
coverage attribute raw 76 = live 76 + macro-block 0 + comment/dead 0
class sites in-bodies file-scope bodies distinct TUs marked unmarked kinds
A pins 20646 20646 0 10329 1331 2580 20646 0 {'pin': 20646}
B asm 16329 16316 13 9435 905 2279 13443 2886 {'gte': 203, 'barrier': 4578, 'gte-lever': 462, 'gte-unsigned': 3, 'launder': 4676, 'instruction': 1712, 'keepalive': 2000, 'asm-body': 13, 'verbatim-body': 2682}
B asm 22988 22975 13 9766 1063 2297 13711 9277 {'gte': 6858, 'barrier': 4578, 'gte-lever': 462, 'gte-unsigned': 3, 'launder': 4680, 'instruction': 1712, 'keepalive': 2000, 'asm-body': 13, 'verbatim-body': 2682}
C volatile 1722 1570 152 628 97 612 14 1708 {'decl-body': 58, 'decl-file': 152, 'cast': 1510, 'param': 2}
D register 50 50 0 47 47 6 0 50 {'register': 50}
E asm-label 7428 1005 6423 737 117 2080 0 7428 {'asm-label': 7428}
F builtin 445 445 0 428 27 302 0 445 {'builtin': 445}
G attribute 76 1 75 1 1 40 0 76 {'attribute': 76}
UNION A–D: 15,659 bodies · 1,895 distinct (addresses normalized) · 378 multi-copy classes holding 14,142 bodies · by kind {'ov': 14998, 'main': 159, 'shared': 323, 'md': 167, 'resident': 12}
THE PHASE'S NUMBER (pins + asm statements, GTE excluded): 34,087 sites in 12,712 bodies (1,759 distinct) · marked !FAKE 34,087 · UNMARKED 0
UNION A–D: 15,961 bodies · 2,031 distinct (addresses normalized) · 401 multi-copy classes holding 14,331 bodies · by kind {'ov': 15258, 'md': 182, 'main': 180, 'shared': 329, 'resident': 12}
THE PHASE'S NUMBER (pins + asm statements, GTE excluded): 34,091 sites in 12,712 bodies (1,759 distinct) · marked !FAKE 34,091 · UNMARKED 0
orphan !FAKE markers (no pin/asm site on the line nor below): 0
GTE levers (clobbers beyond the canonical macro's): 462 sites (100 via a variant macro, 362 direct) · marked 462 · UNMARKED 0 · unsigned GTE statements 3
per-TU asm macro definitions outside the GTE header: 314 {'gte': 150, 'launder': 154, 'instruction': 9, 'barrier': 1} (GTE variants 64)
pins: 20,646 · $0 1,321 · $sp 13 · with initializer 2,776 · volatile-qualified 134 · bare-name 25 · spellings {'__asm__': 20544, 'asm': 102}
whole-body asm routines in C shells, manifest PERMANENT (hand asm, NOT levers): 22 routines · 2,682 sites (2,660 private copies + 22 shared headers); asm-bodies NOT permanent (levers): 13 site(s) ['func_8001E378:DECOMPILE-NOW', 'func_80020F34:DECOMPILE-NOW', 'func_800249F0:DECOMPILE-NOW', 'func_80025CBC:DECOMPILE-NOW', 'func_80026514:UNCERTAIN', 'func_800268D0:UNCERTAIN', 'func_80027058:DECOMPILE-NOW', 'func_80027200:DECOMPILE-NOW', 'func_800CBA44:DECOMPILE-NOW', 'func_8017D810:DECOMPILE-NOW', 'func_8017E26C:UNCERTAIN', 'func_80184440:DECOMPILE-NOW', 'func_801A3BCC:DECOMPILE-NOW']
asm kinds: {'asm-body/direct': 13, 'barrier/direct': 4576, 'barrier/via-macro': 2, 'gte/direct': 200, 'gte/via-macro': 3, 'gte-lever/direct': 362, 'gte-lever/via-macro': 100, 'gte-unsigned/direct': 3, 'instruction/direct': 1690, 'instruction/via-macro': 22, 'keepalive/direct': 2000, 'launder/direct': 4236, 'launder/via-macro': 440, 'verbatim-body/direct': 2682}
asm kinds: {'asm-body/direct': 13, 'barrier/direct': 4576, 'barrier/via-macro': 2, 'gte/direct': 200, 'gte/via-macro': 6658, 'gte-lever/direct': 362, 'gte-lever/via-macro': 100, 'gte-unsigned/direct': 3, 'instruction/direct': 1690, 'instruction/via-macro': 22, 'keepalive/direct': 2000, 'launder/direct': 4236, 'launder/via-macro': 444, 'verbatim-body/direct': 2682}
instruction mnemonics: {'addu': 966, 'move': 406, 'la': 142, 'lh': 134, 'addiu': 22, 'RTP_SND': 22, '.section': 7, 'lui': 4, 'and': 2, 'mult': 1, 'mfhi': 1, 'sll': 1, 'li': 1, 'lw': 1, 'nop': 1, 'srl': 1}
gte mnemonics: {'lwc2': 159, 'lw': 24, 'swc2': 14, 'gte_rt': 3, 'nop': 1, 'cfc2': 1, 'mfc2': 1}
gte mnemonics: {'gte_ldv0': 757, 'gte_stlvnl': 593, 'gte_stsxy': 447, 'gte_rtps': 437, 'gte_stflg': 415, 'gte_rtpt': 352, 'gte_SetRotMatrix': 246, 'gte_stsxy3': 236, 'gte_rtv0tr': 228, 'gte_SetTransMatrix': 226, 'gte_ldv3c': 184, 'gte_ldv3': 177, 'gte_ldrgb': 164, 'gte_stsv': 161, 'lwc2': 159, 'gte_stsz4': 149, 'gte_stsz3': 147, 'gte_stszotz': 134, 'gte_ldIR0z': 134, 'gte_ldIRGB': 134, 'gte_dpcl': 134, 'gte_stORGB': 134, 'gte_stsxy3_f3': 111, 'gte_stclmv': 108, 'gte_nclip': 108, 'gte_stopz': 108, 'gte_stsxy3c': 108, 'gte_stsxy3_ft3': 79, 'gte_rtir': 75, 'gte_ldclmv': 72}
asm-bearing macro definitions: 314 (20 names, 3 with >1 text) kinds {'gte': 150, 'launder': 154, 'instruction': 9, 'barrier': 1}
controls (R39):
src/800.c func_800226C0 pins got 14 expected 45 N-A
src/shared/ov/func_80178004.h pins got 8 expected 26 N-A
ov_SC03_006 func_80184034 bare-name pins got 0 expected 3 N-A
engine_prelude.h asm sites (a macro definition only) got 0 expected 0 OK
elapsed 33.0 s
elapsed 40.8 s
+4
View File
@@ -0,0 +1,4 @@
07:06:03 apply t5_xfile: 2 files, control src/shared/ov/func_80165CA0.h IDENTICAL (0.61 s), calibration 4bc987426, census a667519a38753e8f
07:06:07 src/shared/ov/func_80165CA0.h:func_80165CA0 A=DIFFERS B: removed 6 needed 2 compiles 9
07:06:25 src/shared/ov/func_80166F58__3728db8a.h:func_80166F58 A=DIFFERS B: removed 0 needed 2 compiles 3
07:06:25 delever: batch t5_xfile — 2 files (headers; 2 drawable) · 2 bodies: 0 lever-free, 2 residue, 0 refused · sites removed 6 / needed 4 / refused 3 / deferred 0 · replays 0 (0 disagreed) · compiles 297 in 22 s wall · final 2/2 identical · written 2 files
+54
View File
@@ -0,0 +1,54 @@
{
"label": "t5_xfile",
"generated": "2026-09-09 07:06",
"headers": true,
"batch": 300,
"only": [
"src/shared/ov/func_80165CA0.h",
"src/shared/ov/func_80166F58__3728db8a.h"
],
"files": 2,
"drawable_files": 2,
"wall_s": 22.4,
"calib": {
"head": "4bc987426",
"stamp": "b44c5a8a3423"
},
"bodies": 2,
"compiles": 297,
"sites_removed": 6,
"sites_needed": 4,
"sites_refused": 3,
"sites_deferred": 0,
"lever_free": 0,
"residue": 2,
"refused_bodies": 0,
"replays": 0,
"disagreed": 0,
"written": 2,
"seconds": 132.78877711296082,
"final_ok": 2,
"final_bad": 0,
"per_file": [
{
"tu": "src/shared/ov/func_80165CA0.h",
"bodies": 1,
"final": "IDENTICAL",
"written": true,
"removed": 6,
"needed": 2,
"refused": 0,
"compiles": 291
},
{
"tu": "src/shared/ov/func_80166F58__3728db8a.h",
"bodies": 1,
"final": "IDENTICAL",
"written": true,
"removed": 0,
"needed": 2,
"refused": 3,
"compiles": 6
}
]
}
+187 -187
View File
@@ -1,7 +1,7 @@
{
"head": "3b2c5178b",
"head": "4bc987426",
"stamp": "b44c5a8a3423",
"generated": "2026-09-09 06:39",
"generated": "2026-09-09 07:05",
"aliases": [
"main",
"ov_SC03_014",
@@ -21,207 +21,207 @@
"main": {
"objects": 85,
"identical": 85,
"seconds": 10.379000000000003,
"mean_s": 0.122
"seconds": 9.508000000000003,
"mean_s": 0.112
},
"ov_SC03_014": {
"objects": 32,
"identical": 32,
"seconds": 6.51,
"mean_s": 0.203
"seconds": 5.9910000000000005,
"mean_s": 0.187
},
"ov_SC03_015": {
"objects": 32,
"identical": 32,
"seconds": 6.227999999999999,
"mean_s": 0.195
"seconds": 6.171000000000001,
"mean_s": 0.193
},
"ov_SC04_011": {
"objects": 28,
"identical": 28,
"seconds": 5.250000000000001,
"mean_s": 0.188
"seconds": 4.969000000000001,
"mean_s": 0.177
}
},
"per_object_seconds": {
"build/src/800.o": 0.798,
"build/src/800_b.o": 0.122,
"build/src/800_b_2.o": 0.331,
"build/src/800_b_o0a.o": 0.143,
"build/src/800_c.o": 0.423,
"build/src/800b2.o": 0.124,
"build/src/apicard1.o": 0.143,
"build/src/apicard2.o": 0.121,
"build/src/apicard3.o": 0.177,
"build/src/apicard4.o": 0.112,
"build/src/apicard5.o": 0.119,
"build/src/apicard6.o": 0.207,
"build/src/apicard7.o": 0.177,
"build/src/boot.o": 0.166,
"build/src/gap.o": 0.141,
"build/src/libapi1.o": 0.117,
"build/src/libapi2.o": 0.071,
"build/src/libc2_1.o": 0.084,
"build/src/libc2_2.o": 0.077,
"build/src/libcd1.o": 0.093,
"build/src/libcd2.o": 0.174,
"build/src/libetc.o": 0.081,
"build/src/libgpu.o": 0.094,
"build/src/libgpu2.o": 0.18,
"build/src/libgs1.o": 0.08,
"build/src/libgs2.o": 0.096,
"build/src/libgs3.o": 0.188,
"build/src/libgs4.o": 0.096,
"build/src/libgs5.o": 0.086,
"build/src/libgs6.o": 0.124,
"build/src/libgs7.o": 0.075,
"build/src/libgs8.o": 0.098,
"build/src/libgte1.o": 0.092,
"build/src/libgte10.o": 0.093,
"build/src/libgte11.o": 0.205,
"build/src/libgte12.o": 0.079,
"build/src/libgte13.o": 0.082,
"build/src/libgte14.o": 0.081,
"build/src/libgte15.o": 0.24,
"build/src/libgte16.o": 0.086,
"build/src/libgte17.o": 0.09,
"build/src/libgte18.o": 0.073,
"build/src/libgte19.o": 0.062,
"build/src/libgte2.o": 0.081,
"build/src/libgte20.o": 0.084,
"build/src/libgte21.o": 0.109,
"build/src/libgte22.o": 0.074,
"build/src/libgte23.o": 0.096,
"build/src/libgte24.o": 0.067,
"build/src/libgte25.o": 0.176,
"build/src/libgte26.o": 0.064,
"build/src/libgte27.o": 0.078,
"build/src/libgte28.o": 0.095,
"build/src/libgte29.o": 0.067,
"build/src/libgte3.o": 0.076,
"build/src/libgte30.o": 0.089,
"build/src/libgte4.o": 0.071,
"build/src/libgte5.o": 0.089,
"build/src/libgte6.o": 0.065,
"build/src/libgte7.o": 0.094,
"build/src/libgte8.o": 0.142,
"build/src/libgte9.o": 0.098,
"build/src/libmcrd1.o": 0.128,
"build/src/libmcrd2.o": 0.086,
"build/src/libpad1.o": 0.135,
"build/src/libpad2.o": 0.083,
"build/src/sgap.o": 0.104,
"build/src/sgap_2.o": 0.102,
"build/src/sgap_3.o": 0.089,
"build/src/sgap_4.o": 0.2,
"build/src/sgap_5.o": 0.098,
"build/src/sgap_6.o": 0.1,
"build/src/sgap_8.o": 0.111,
"build/src/snd1.o": 0.103,
"build/src/snd10.o": 0.094,
"build/src/snd11.o": 0.095,
"build/src/snd12.o": 0.084,
"build/src/snd2.o": 0.087,
"build/src/snd3.o": 0.096,
"build/src/snd4.o": 0.099,
"build/src/snd5.o": 0.064,
"build/src/snd6.o": 0.168,
"build/src/snd7.o": 0.075,
"build/src/snd8.o": 0.089,
"build/src/snd9.o": 0.073,
"build/src/ov_SC03_014/ov_SC03_014.o": 0.213,
"build/src/ov_SC03_014/ov_SC03_014_after.o": 0.572,
"build/src/ov_SC03_014/ov_SC03_014_jr_8012ACE0.o": 0.513,
"build/src/ov_SC03_014/ov_SC03_014_jr_80135888.o": 0.111,
"build/src/ov_SC03_014/ov_SC03_014_jr_80135A4C.o": 0.067,
"build/src/ov_SC03_014/ov_SC03_014_jr_80135D20.o": 0.192,
"build/src/ov_SC03_014/ov_SC03_014_jr_801380E0.o": 0.289,
"build/src/ov_SC03_014/ov_SC03_014_jr_8013C98C.o": 0.146,
"build/src/ov_SC03_014/ov_SC03_014_jr_8013F350.o": 0.089,
"build/src/ov_SC03_014/ov_SC03_014_jr_8013FFD8.o": 0.172,
"build/src/ov_SC03_014/ov_SC03_014_jr_80140608.o": 0.227,
"build/src/ov_SC03_014/ov_SC03_014_jr_8015444C.o": 0.104,
"build/src/ov_SC03_014/ov_SC03_014_jr_80154C24.o": 0.185,
"build/src/ov_SC03_014/ov_SC03_014_jr_801588CC.o": 0.116,
"build/src/ov_SC03_014/ov_SC03_014_jr_80159C84.o": 0.109,
"build/src/ov_SC03_014/ov_SC03_014_jr_8015A3C8.o": 0.089,
"build/src/ov_SC03_014/ov_SC03_014_jr_8015AE2C.o": 0.181,
"build/src/ov_SC03_014/ov_SC03_014_jr_8015C32C.o": 0.59,
"build/src/ov_SC03_014/ov_SC03_014_jr_8016AB6C.o": 0.563,
"build/src/ov_SC03_014/ov_SC03_014_jr_80171B4C.o": 0.118,
"build/src/ov_SC03_014/ov_SC03_014_jr_801734BC.o": 0.257,
"build/src/ov_SC03_014/ov_SC03_014_jr_801789AC.o": 0.079,
"build/src/800.o": 0.869,
"build/src/800_b.o": 0.085,
"build/src/800_b_2.o": 0.329,
"build/src/800_b_o0a.o": 0.155,
"build/src/800_c.o": 0.237,
"build/src/800b2.o": 0.132,
"build/src/apicard1.o": 0.158,
"build/src/apicard2.o": 0.092,
"build/src/apicard3.o": 0.202,
"build/src/apicard4.o": 0.073,
"build/src/apicard5.o": 0.083,
"build/src/apicard6.o": 0.147,
"build/src/apicard7.o": 0.065,
"build/src/boot.o": 0.117,
"build/src/gap.o": 0.078,
"build/src/libapi1.o": 0.087,
"build/src/libapi2.o": 0.093,
"build/src/libc2_1.o": 0.109,
"build/src/libc2_2.o": 0.137,
"build/src/libcd1.o": 0.12,
"build/src/libcd2.o": 0.075,
"build/src/libetc.o": 0.075,
"build/src/libgpu.o": 0.077,
"build/src/libgpu2.o": 0.155,
"build/src/libgs1.o": 0.159,
"build/src/libgs2.o": 0.113,
"build/src/libgs3.o": 0.118,
"build/src/libgs4.o": 0.128,
"build/src/libgs5.o": 0.081,
"build/src/libgs6.o": 0.1,
"build/src/libgs7.o": 0.165,
"build/src/libgs8.o": 0.088,
"build/src/libgte1.o": 0.107,
"build/src/libgte10.o": 0.081,
"build/src/libgte11.o": 0.07,
"build/src/libgte12.o": 0.12,
"build/src/libgte13.o": 0.085,
"build/src/libgte14.o": 0.068,
"build/src/libgte15.o": 0.068,
"build/src/libgte16.o": 0.077,
"build/src/libgte17.o": 0.062,
"build/src/libgte18.o": 0.076,
"build/src/libgte19.o": 0.12,
"build/src/libgte2.o": 0.113,
"build/src/libgte20.o": 0.066,
"build/src/libgte21.o": 0.064,
"build/src/libgte22.o": 0.168,
"build/src/libgte23.o": 0.098,
"build/src/libgte24.o": 0.066,
"build/src/libgte25.o": 0.07,
"build/src/libgte26.o": 0.068,
"build/src/libgte27.o": 0.067,
"build/src/libgte28.o": 0.086,
"build/src/libgte29.o": 0.071,
"build/src/libgte3.o": 0.14,
"build/src/libgte30.o": 0.079,
"build/src/libgte4.o": 0.131,
"build/src/libgte5.o": 0.065,
"build/src/libgte6.o": 0.177,
"build/src/libgte7.o": 0.071,
"build/src/libgte8.o": 0.066,
"build/src/libgte9.o": 0.142,
"build/src/libmcrd1.o": 0.139,
"build/src/libmcrd2.o": 0.069,
"build/src/libpad1.o": 0.071,
"build/src/libpad2.o": 0.065,
"build/src/sgap.o": 0.065,
"build/src/sgap_2.o": 0.163,
"build/src/sgap_3.o": 0.068,
"build/src/sgap_4.o": 0.08,
"build/src/sgap_5.o": 0.081,
"build/src/sgap_6.o": 0.072,
"build/src/sgap_8.o": 0.083,
"build/src/snd1.o": 0.073,
"build/src/snd10.o": 0.078,
"build/src/snd11.o": 0.072,
"build/src/snd12.o": 0.111,
"build/src/snd2.o": 0.079,
"build/src/snd3.o": 0.101,
"build/src/snd4.o": 0.073,
"build/src/snd5.o": 0.106,
"build/src/snd6.o": 0.172,
"build/src/snd7.o": 0.07,
"build/src/snd8.o": 0.07,
"build/src/snd9.o": 0.103,
"build/src/ov_SC03_014/ov_SC03_014.o": 0.136,
"build/src/ov_SC03_014/ov_SC03_014_after.o": 0.6,
"build/src/ov_SC03_014/ov_SC03_014_jr_8012ACE0.o": 0.438,
"build/src/ov_SC03_014/ov_SC03_014_jr_80135888.o": 0.074,
"build/src/ov_SC03_014/ov_SC03_014_jr_80135A4C.o": 0.134,
"build/src/ov_SC03_014/ov_SC03_014_jr_80135D20.o": 0.179,
"build/src/ov_SC03_014/ov_SC03_014_jr_801380E0.o": 0.224,
"build/src/ov_SC03_014/ov_SC03_014_jr_8013C98C.o": 0.161,
"build/src/ov_SC03_014/ov_SC03_014_jr_8013F350.o": 0.155,
"build/src/ov_SC03_014/ov_SC03_014_jr_8013FFD8.o": 0.068,
"build/src/ov_SC03_014/ov_SC03_014_jr_80140608.o": 0.256,
"build/src/ov_SC03_014/ov_SC03_014_jr_8015444C.o": 0.078,
"build/src/ov_SC03_014/ov_SC03_014_jr_80154C24.o": 0.201,
"build/src/ov_SC03_014/ov_SC03_014_jr_801588CC.o": 0.103,
"build/src/ov_SC03_014/ov_SC03_014_jr_80159C84.o": 0.133,
"build/src/ov_SC03_014/ov_SC03_014_jr_8015A3C8.o": 0.084,
"build/src/ov_SC03_014/ov_SC03_014_jr_8015AE2C.o": 0.107,
"build/src/ov_SC03_014/ov_SC03_014_jr_8015C32C.o": 0.556,
"build/src/ov_SC03_014/ov_SC03_014_jr_8016AB6C.o": 0.318,
"build/src/ov_SC03_014/ov_SC03_014_jr_80171B4C.o": 0.17,
"build/src/ov_SC03_014/ov_SC03_014_jr_801734BC.o": 0.327,
"build/src/ov_SC03_014/ov_SC03_014_jr_801789AC.o": 0.088,
"build/src/ov_SC03_014/ov_SC03_014_jr_80178D40.o": 0.123,
"build/src/ov_SC03_014/ov_SC03_014_jr_8017A4AC.o": 0.154,
"build/src/ov_SC03_014/ov_SC03_014_jr_8017AE2C.o": 0.209,
"build/src/ov_SC03_014/ov_SC03_014_jr_8017EB7C.o": 0.23,
"build/src/ov_SC03_014/ov_SC03_014_jr_80184440.o": 0.09,
"build/src/ov_SC03_014/ov_SC03_014_jr_801848E4.o": 0.323,
"build/src/ov_SC03_014/ov_SC03_014_o0b.o": 0.067,
"build/src/ov_SC03_014/ov_SC03_014_o0c.o": 0.098,
"build/src/ov_SC03_014/ov_SC03_014_o0d.o": 0.092,
"build/src/ov_SC03_014/ov_SC03_014_o0e.o": 0.142,
"build/src/ov_SC03_015/ov_SC03_015.o": 0.175,
"build/src/ov_SC03_015/ov_SC03_015_after.o": 0.564,
"build/src/ov_SC03_015/ov_SC03_015_jr_8012ACE0.o": 0.541,
"build/src/ov_SC03_015/ov_SC03_015_jr_80135888.o": 0.079,
"build/src/ov_SC03_015/ov_SC03_015_jr_80135A4C.o": 0.068,
"build/src/ov_SC03_015/ov_SC03_015_jr_80135D20.o": 0.17,
"build/src/ov_SC03_015/ov_SC03_015_jr_801380E0.o": 0.245,
"build/src/ov_SC03_015/ov_SC03_015_jr_8013C98C.o": 0.131,
"build/src/ov_SC03_015/ov_SC03_015_jr_8013F350.o": 0.112,
"build/src/ov_SC03_015/ov_SC03_015_jr_8013FFD8.o": 0.109,
"build/src/ov_SC03_015/ov_SC03_015_jr_80140608.o": 0.313,
"build/src/ov_SC03_015/ov_SC03_015_jr_8015444C.o": 0.079,
"build/src/ov_SC03_015/ov_SC03_015_jr_80154C24.o": 0.204,
"build/src/ov_SC03_015/ov_SC03_015_jr_801588CC.o": 0.102,
"build/src/ov_SC03_015/ov_SC03_015_jr_80159C84.o": 0.082,
"build/src/ov_SC03_015/ov_SC03_015_jr_8015A3C8.o": 0.076,
"build/src/ov_SC03_015/ov_SC03_015_jr_8015AE2C.o": 0.17,
"build/src/ov_SC03_015/ov_SC03_015_jr_8015C32C.o": 0.602,
"build/src/ov_SC03_015/ov_SC03_015_jr_8016AB6C.o": 0.442,
"build/src/ov_SC03_015/ov_SC03_015_jr_80171B4C.o": 0.109,
"build/src/ov_SC03_015/ov_SC03_015_jr_801734BC.o": 0.227,
"build/src/ov_SC03_015/ov_SC03_015_jr_801789AC.o": 0.082,
"build/src/ov_SC03_015/ov_SC03_015_jr_80178D40.o": 0.121,
"build/src/ov_SC03_015/ov_SC03_015_jr_8017A4AC.o": 0.077,
"build/src/ov_SC03_015/ov_SC03_015_jr_8017AE2C.o": 0.252,
"build/src/ov_SC03_015/ov_SC03_015_jr_8017EB7C.o": 0.24,
"build/src/ov_SC03_015/ov_SC03_015_jr_80184440.o": 0.057,
"build/src/ov_SC03_015/ov_SC03_015_jr_801848E4.o": 0.414,
"build/src/ov_SC03_015/ov_SC03_015_o0b.o": 0.134,
"build/src/ov_SC03_015/ov_SC03_015_o0c.o": 0.076,
"build/src/ov_SC03_015/ov_SC03_015_o0d.o": 0.082,
"build/src/ov_SC03_015/ov_SC03_015_o0e.o": 0.093,
"build/src/ov_SC04_011/ov_SC04_011.o": 0.144,
"build/src/ov_SC04_011/ov_SC04_011_after.o": 0.591,
"build/src/ov_SC04_011/ov_SC04_011_jr_8012ACE0.o": 0.407,
"build/src/ov_SC04_011/ov_SC04_011_jr_80135888.o": 0.057,
"build/src/ov_SC04_011/ov_SC04_011_jr_80135A4C.o": 0.058,
"build/src/ov_SC04_011/ov_SC04_011_jr_80135D20.o": 0.165,
"build/src/ov_SC04_011/ov_SC04_011_jr_801380E0.o": 0.216,
"build/src/ov_SC04_011/ov_SC04_011_jr_8013C98C.o": 0.173,
"build/src/ov_SC04_011/ov_SC04_011_jr_8013F350.o": 0.083,
"build/src/ov_SC04_011/ov_SC04_011_jr_8013FFD8.o": 0.096,
"build/src/ov_SC04_011/ov_SC04_011_jr_80140608.o": 0.215,
"build/src/ov_SC04_011/ov_SC04_011_jr_8015444C.o": 0.078,
"build/src/ov_SC04_011/ov_SC04_011_jr_80154C24.o": 0.268,
"build/src/ov_SC04_011/ov_SC04_011_jr_801588CC.o": 0.115,
"build/src/ov_SC04_011/ov_SC04_011_jr_80159C84.o": 0.083,
"build/src/ov_SC04_011/ov_SC04_011_jr_8015A3C8.o": 0.083,
"build/src/ov_SC04_011/ov_SC04_011_jr_8015AE2C.o": 0.182,
"build/src/ov_SC04_011/ov_SC04_011_jr_8015C32C.o": 0.459,
"build/src/ov_SC04_011/ov_SC04_011_jr_8016AB6C.o": 0.338,
"build/src/ov_SC04_011/ov_SC04_011_jr_80171B4C.o": 0.11,
"build/src/ov_SC04_011/ov_SC04_011_jr_801734BC.o": 0.201,
"build/src/ov_SC04_011/ov_SC04_011_jr_801789AC.o": 0.1,
"build/src/ov_SC04_011/ov_SC04_011_jr_80178D40.o": 0.114,
"build/src/ov_SC04_011/ov_SC04_011_jr_8017A4AC.o": 0.078,
"build/src/ov_SC04_011/ov_SC04_011_jr_8017AE2C.o": 0.151,
"build/src/ov_SC04_011/ov_SC04_011_jr_8017D494.o": 0.546,
"build/src/ov_SC04_011/ov_SC04_011_o0b.o": 0.07,
"build/src/ov_SC04_011/ov_SC04_011_o0c.o": 0.069
"build/src/ov_SC03_014/ov_SC03_014_jr_8017A4AC.o": 0.072,
"build/src/ov_SC03_014/ov_SC03_014_jr_8017AE2C.o": 0.204,
"build/src/ov_SC03_014/ov_SC03_014_jr_8017EB7C.o": 0.314,
"build/src/ov_SC03_014/ov_SC03_014_jr_80184440.o": 0.057,
"build/src/ov_SC03_014/ov_SC03_014_jr_801848E4.o": 0.313,
"build/src/ov_SC03_014/ov_SC03_014_o0b.o": 0.097,
"build/src/ov_SC03_014/ov_SC03_014_o0c.o": 0.074,
"build/src/ov_SC03_014/ov_SC03_014_o0d.o": 0.066,
"build/src/ov_SC03_014/ov_SC03_014_o0e.o": 0.081,
"build/src/ov_SC03_015/ov_SC03_015.o": 0.144,
"build/src/ov_SC03_015/ov_SC03_015_after.o": 0.546,
"build/src/ov_SC03_015/ov_SC03_015_jr_8012ACE0.o": 0.433,
"build/src/ov_SC03_015/ov_SC03_015_jr_80135888.o": 0.063,
"build/src/ov_SC03_015/ov_SC03_015_jr_80135A4C.o": 0.059,
"build/src/ov_SC03_015/ov_SC03_015_jr_80135D20.o": 0.127,
"build/src/ov_SC03_015/ov_SC03_015_jr_801380E0.o": 0.164,
"build/src/ov_SC03_015/ov_SC03_015_jr_8013C98C.o": 0.181,
"build/src/ov_SC03_015/ov_SC03_015_jr_8013F350.o": 0.08,
"build/src/ov_SC03_015/ov_SC03_015_jr_8013FFD8.o": 0.099,
"build/src/ov_SC03_015/ov_SC03_015_jr_80140608.o": 0.258,
"build/src/ov_SC03_015/ov_SC03_015_jr_8015444C.o": 0.088,
"build/src/ov_SC03_015/ov_SC03_015_jr_80154C24.o": 0.199,
"build/src/ov_SC03_015/ov_SC03_015_jr_801588CC.o": 0.101,
"build/src/ov_SC03_015/ov_SC03_015_jr_80159C84.o": 0.094,
"build/src/ov_SC03_015/ov_SC03_015_jr_8015A3C8.o": 0.1,
"build/src/ov_SC03_015/ov_SC03_015_jr_8015AE2C.o": 0.111,
"build/src/ov_SC03_015/ov_SC03_015_jr_8015C32C.o": 0.689,
"build/src/ov_SC03_015/ov_SC03_015_jr_8016AB6C.o": 0.524,
"build/src/ov_SC03_015/ov_SC03_015_jr_80171B4C.o": 0.118,
"build/src/ov_SC03_015/ov_SC03_015_jr_801734BC.o": 0.353,
"build/src/ov_SC03_015/ov_SC03_015_jr_801789AC.o": 0.109,
"build/src/ov_SC03_015/ov_SC03_015_jr_80178D40.o": 0.118,
"build/src/ov_SC03_015/ov_SC03_015_jr_8017A4AC.o": 0.149,
"build/src/ov_SC03_015/ov_SC03_015_jr_8017AE2C.o": 0.179,
"build/src/ov_SC03_015/ov_SC03_015_jr_8017EB7C.o": 0.258,
"build/src/ov_SC03_015/ov_SC03_015_jr_80184440.o": 0.112,
"build/src/ov_SC03_015/ov_SC03_015_jr_801848E4.o": 0.302,
"build/src/ov_SC03_015/ov_SC03_015_o0b.o": 0.113,
"build/src/ov_SC03_015/ov_SC03_015_o0c.o": 0.111,
"build/src/ov_SC03_015/ov_SC03_015_o0d.o": 0.11,
"build/src/ov_SC03_015/ov_SC03_015_o0e.o": 0.079,
"build/src/ov_SC04_011/ov_SC04_011.o": 0.152,
"build/src/ov_SC04_011/ov_SC04_011_after.o": 0.496,
"build/src/ov_SC04_011/ov_SC04_011_jr_8012ACE0.o": 0.401,
"build/src/ov_SC04_011/ov_SC04_011_jr_80135888.o": 0.063,
"build/src/ov_SC04_011/ov_SC04_011_jr_80135A4C.o": 0.061,
"build/src/ov_SC04_011/ov_SC04_011_jr_80135D20.o": 0.126,
"build/src/ov_SC04_011/ov_SC04_011_jr_801380E0.o": 0.175,
"build/src/ov_SC04_011/ov_SC04_011_jr_8013C98C.o": 0.156,
"build/src/ov_SC04_011/ov_SC04_011_jr_8013F350.o": 0.108,
"build/src/ov_SC04_011/ov_SC04_011_jr_8013FFD8.o": 0.072,
"build/src/ov_SC04_011/ov_SC04_011_jr_80140608.o": 0.217,
"build/src/ov_SC04_011/ov_SC04_011_jr_8015444C.o": 0.086,
"build/src/ov_SC04_011/ov_SC04_011_jr_80154C24.o": 0.231,
"build/src/ov_SC04_011/ov_SC04_011_jr_801588CC.o": 0.111,
"build/src/ov_SC04_011/ov_SC04_011_jr_80159C84.o": 0.075,
"build/src/ov_SC04_011/ov_SC04_011_jr_8015A3C8.o": 0.138,
"build/src/ov_SC04_011/ov_SC04_011_jr_8015AE2C.o": 0.1,
"build/src/ov_SC04_011/ov_SC04_011_jr_8015C32C.o": 0.486,
"build/src/ov_SC04_011/ov_SC04_011_jr_8016AB6C.o": 0.279,
"build/src/ov_SC04_011/ov_SC04_011_jr_80171B4C.o": 0.154,
"build/src/ov_SC04_011/ov_SC04_011_jr_801734BC.o": 0.238,
"build/src/ov_SC04_011/ov_SC04_011_jr_801789AC.o": 0.071,
"build/src/ov_SC04_011/ov_SC04_011_jr_80178D40.o": 0.118,
"build/src/ov_SC04_011/ov_SC04_011_jr_8017A4AC.o": 0.072,
"build/src/ov_SC04_011/ov_SC04_011_jr_8017AE2C.o": 0.115,
"build/src/ov_SC04_011/ov_SC04_011_jr_8017D494.o": 0.532,
"build/src/ov_SC04_011/ov_SC04_011_o0b.o": 0.064,
"build/src/ov_SC04_011/ov_SC04_011_o0c.o": 0.072
},
"ok": true,
"seconds": 3.1
"seconds": 3.0
}
+2
View File
@@ -17546,3 +17546,5 @@
{"ts": "2026-09-09 06:46:40", "label": "sweep3", "rung": "sweep", "calib": {"head": "3b2c5178b", "stamp": "b44c5a8a3423"}, "tu": "src/ov_SC07_010/ov_SC07_010_jr_8015C32C.c", "fn": null, "addr": null, "aliases": null, "header": false, "verdict": "SWEPT-all", "dead": ["SHB", "SHB", "SHB"], "inner_dropped": [], "sites": [], "compiles": 1}
{"ts": "2026-09-09 06:46:40", "label": "sweep3", "rung": "sweep", "calib": {"head": "3b2c5178b", "stamp": "b44c5a8a3423"}, "tu": "src/ov_SC07_011/ov_SC07_011_jr_8015C32C.c", "fn": null, "addr": null, "aliases": null, "header": false, "verdict": "SWEPT-all", "dead": ["SHB", "SHB", "SHB"], "inner_dropped": [], "sites": [], "compiles": 1}
{"ts": "2026-09-09 06:55:47", "label": "sweep3", "rung": "sweep", "calib": {"head": "3b2c5178b", "stamp": "b44c5a8a3423"}, "tu": "src/shared/engine_prelude.h", "fn": null, "addr": null, "aliases": null, "header": true, "verdict": "REFUSED", "dead": ["ENGINE_SHB"], "inner_dropped": [], "sites": [], "compiles": 3975}
{"ts": "2026-09-09 07:06:16", "label": "t5_xfile", "rung": "B", "calib": {"head": "4bc987426", "stamp": "b44c5a8a3423"}, "tu": "src/shared/ov/func_80165CA0.h", "fn": "func_80165CA0", "addr": 2148949152, "aliases": ["ov_MAIN_012", "ov_SC01_000", "ov_SC01_001", "ov_SC01_004", "ov_SC01_005", "ov_SC01_006", "ov_SC01_008", "ov_SC01_009", "ov_SC01_074", "ov_SC01_077", "ov_SC01_080", "ov_SC01_084", "ov_SC02_000", "ov_SC02_003", "ov_SC02_004", "ov_SC02_005", "ov_SC02_011", "ov_SC02_015", "ov_SC02_016", "ov_SC02_017", "ov_SC02_021", "ov_SC02_026", "ov_SC02_027", "ov_SC02_028", "ov_SC02_031", "ov_SC02_035", "ov_SC02_037", "ov_SC02_039", "ov_SC02_041", "ov_SC03_001", "ov_SC03_002", "ov_SC03_003", "ov_SC03_006", "ov_SC03_007", "ov_SC03_010", "ov_SC03_011", "ov_SC03_012", "ov_SC03_013", "ov_SC03_014", "ov_SC03_015", "ov_SC03_023", "ov_SC03_024", "ov_SC03_028", "ov_SC03_029", "ov_SC03_030", "ov_SC03_031", "ov_SC03_089", "ov_SC03_090", "ov_SC03_091", "ov_SC03_092", "ov_SC03_093", "ov_SC03_094", "ov_SC03_095", "ov_SC03_096", "ov_SC03_097", "ov_SC03_098", "ov_SC03_099", "ov_SC03_100", "ov_SC03_101", "ov_SC03_102", "ov_SC03_103", "ov_SC03_104", "ov_SC03_105", "ov_SC03_107", "ov_SC03_108", "ov_SC03_109", "ov_SC03_110", "ov_SC03_111", "ov_SC03_112", "ov_SC03_113", "ov_SC03_114", "ov_SC03_115", "ov_SC03_116", "ov_SC03_117", "ov_SC03_118", "ov_SC03_119", "ov_SC03_121", "ov_SC03_124", "ov_SC03_125", "ov_SC03_126", "ov_SC04_000", "ov_SC04_002", "ov_SC04_003", "ov_SC04_004", "ov_SC04_005", "ov_SC04_006", "ov_SC04_007", "ov_SC04_008", "ov_SC04_009", "ov_SC04_010", "ov_SC04_011", "ov_SC04_012", "ov_SC04_015", "ov_SC04_016", "ov_SC04_018", "ov_SC04_019", "ov_SC04_020", "ov_SC04_021", "ov_SC05_000", "ov_SC05_001", "ov_SC05_002", "ov_SC05_003", "ov_SC05_004", "ov_SC05_005", "ov_SC05_006", "ov_SC05_007", "ov_SC05_008", "ov_SC05_009", "ov_SC05_010", "ov_SC05_011", "ov_SC05_017", "ov_SC05_018", "ov_SC05_019", "ov_SC06_000", "ov_SC06_006", "ov_SC06_008", "ov_SC06_010", "ov_SC06_011", "ov_SC06_013", "ov_SC06_014", "ov_SC06_015", "ov_SC06_016", "ov_SC06_018", "ov_SC06_020", "ov_SC06_022", "ov_SC06_024", "ov_SC06_025", "ov_SC06_027", "ov_SC06_029", "ov_SC06_030", "ov_SC06_032", "ov_SC06_033", "ov_SC07_000", "ov_SC07_001", "ov_SC07_002", "ov_SC07_006", "ov_SC07_007", "ov_SC07_008", "ov_SC07_009", "ov_SC07_010", "ov_SC07_011"], "header": true, "includers": 136, "o0": false, "nhash_before": "b10fd3c5f43d53867bbc37ab4c872f244f1e7ad7", "nhash_after": "df8ff08ceb0ac5972fad10d4d662f9046e889098", "exemplar": null, "verdict": "RESIDUE", "replay_disagreed": false, "sites": [{"ord": 0, "kind": "pin", "cls": "A", "detail": "$3", "via": "", "line": 12, "verdict": "NEEDED", "why": "", "oracle": "DIFFERS"}, {"ord": 1, "kind": "launder", "cls": "B", "detail": "ENGINE_SHB", "via": "ENGINE_SHB", "line": 20, "verdict": "REMOVED", "why": "", "oracle": "IDENTICAL"}, {"ord": 2, "kind": "launder", "cls": "B", "detail": "ENGINE_SHB", "via": "ENGINE_SHB", "line": 26, "verdict": "REMOVED", "why": "", "oracle": "IDENTICAL"}, {"ord": 3, "kind": "launder", "cls": "B", "detail": "ENGINE_SHB", "via": "ENGINE_SHB", "line": 27, "verdict": "REMOVED", "why": "", "oracle": "IDENTICAL"}, {"ord": 4, "kind": "launder", "cls": "B", "detail": "ENGINE_SHB", "via": "ENGINE_SHB", "line": 28, "verdict": "REMOVED", "why": "", "oracle": "IDENTICAL"}, {"ord": 5, "kind": "launder", "cls": "B", "detail": "ENGINE_SHB", "via": "ENGINE_SHB", "line": 30, "verdict": "REMOVED", "why": "", "oracle": "IDENTICAL"}, {"ord": 6, "kind": "launder", "cls": "B", "detail": "ENGINE_SHB", "via": "ENGINE_SHB", "line": 31, "verdict": "REMOVED", "why": "", "oracle": "IDENTICAL"}, {"ord": 7, "kind": "launder", "cls": "B", "detail": "ENGINE_SHB", "via": "ENGINE_SHB", "line": 32, "verdict": "NEEDED", "why": "", "oracle": "DIFFERS"}], "compiles": 150, "seconds": 67.253}
{"ts": "2026-09-09 07:06:25", "label": "t5_xfile", "rung": "B", "calib": {"head": "4bc987426", "stamp": "b44c5a8a3423"}, "tu": "src/shared/ov/func_80166F58__3728db8a.h", "fn": "func_80166F58", "addr": 2148953944, "aliases": ["ov_SC03_126", "ov_SC04_021", "ov_SC05_019"], "header": true, "includers": 3, "o0": false, "nhash_before": "85b4f6b26d2215ec2d3a4ecbdcac77301329e035", "nhash_after": "85b4f6b26d2215ec2d3a4ecbdcac77301329e035", "exemplar": null, "verdict": "RESIDUE", "replay_disagreed": false, "sites": [{"ord": 0, "kind": "pin", "cls": "A", "detail": "$20", "via": "", "line": 11, "verdict": "NEEDED", "why": "", "oracle": "DIFFERS"}, {"ord": 1, "kind": "pin", "cls": "A", "detail": "$5", "via": "", "line": 13, "verdict": "NEEDED", "why": "", "oracle": "DIFFERS"}, {"ord": 2, "kind": "launder", "cls": "B", "detail": "SHB", "via": "SHB", "line": 21, "verdict": "REFUSED", "why": "macro `SHB` is not defined in this file", "oracle": ""}, {"ord": 3, "kind": "launder", "cls": "B", "detail": "SHB", "via": "SHB", "line": 21, "verdict": "REFUSED", "why": "macro `SHB` is not defined in this file", "oracle": ""}, {"ord": 4, "kind": "launder", "cls": "B", "detail": "SHB", "via": "SHB", "line": 22, "verdict": "REFUSED", "why": "macro `SHB` is not defined in this file", "oracle": ""}], "compiles": 3, "seconds": 1.433}
+2
View File
@@ -0,0 +1,2 @@
src/shared/ov/func_80165CA0.h
src/shared/ov/func_80166F58__3728db8a.h
@@ -300,7 +300,9 @@ def inventory(jobs=12, quiet=False):
# ----------------------------------------------------------------------------------------------------------------------
# the canonical table
# ----------------------------------------------------------------------------------------------------------------------
def canonical_table(inv, quiet=False):
def canonical_table(inv, quiet=False, write=True):
"""write=False for fixtures: the selftest once overwrote the real table with its two-signature fixture (the census then classified
every direct statement against a fixture and 362 levers vanished twice) — a selftest never writes an instrument's real state."""
sony = sony_table()
incn = inc_names()
groups = collections.defaultdict(list)
@@ -380,7 +382,8 @@ def canonical_table(inv, quiet=False):
variants[f"{key}|{'|'.join(cs)}"] = dict(name=vname, of=name, key=key, clob=list(cs), extra=extra, fewer=fewer, defs=cnt,
files=len({d["tu"] for d in ds if tuple(d["sig"]["clob"]) == cs}))
out = dict(generated=time.strftime("%Y-%m-%d %H:%M"), canonical=table, variants=variants, unsigned=[dict(tu=d["tu"], name=d["name"], l0=d["l0"]) for d in unsigned])
CANON.write_text(json.dumps(out, indent=1))
if write:
CANON.write_text(json.dumps(out, indent=1))
if not quiet:
print(f"gte_consolidate: canonical table — {len(table)} signatures ({sum(1 for t in table.values() if t['sony'])} with Sony's name), "
f"{sum(t['defs'] for t in table.values())} canonical definitions; {len(variants)} lever variants holding {sum(v['defs'] for v in variants.values())} definitions; "
@@ -806,14 +809,37 @@ def sweep(a):
def_spans = collections.defaultdict(list)
for (l0, l1, name, body) in lc.define_blocks(raw):
def_spans[name].append((ls[l0 - 1], ls[l1] if l1 < len(ls) else len(raw)))
def mentions(name):
def mentions(name, l0=None, next_l0=None):
text = m
for s0, e0 in def_spans.get(name, ()):
text = text[:s0] + " " * (e0 - s0) + text[e0:]
if l0 is not None:
a = ls[l0 - 1]
b = ls[next_l0 - 1] if next_l0 else len(text)
text = text[a:b]
return re.search(r"\b%s\b" % re.escape(name), text) is not None
# uses per DEFINITION: a use (a census site via the name, or an #include of a header that uses the name) is governed by the last
# definition of that name above it; a definition with no governed use is dead even when a sibling definition is used
use_lines = collections.defaultdict(list)
for s in sites:
if s["tu"] == rel and s.get("via"):
use_lines[s["via"]].append(s["line"])
inc_lines = []
for mm in sc.INCLUDE_LINE.finditer(m):
h = os.path.normpath(os.path.join(os.path.dirname(rel), mm.group(1)))
inc_lines.append((m.count("\n", 0, mm.start()) + 1, hdr_uses.get(h, collections.Counter())))
def governed_uses(name, l0, next_l0):
n = sum(1 for ln in use_lines.get(name, []) if l0 < ln and (next_l0 is None or ln < next_l0))
n += sum(1 for ln, hu in inc_lines if hu.get(name, 0) and l0 < ln and (next_l0 is None or ln < next_l0))
return n
same_name = collections.defaultdict(list)
for (l0, l1, name, body) in lc.define_blocks(raw):
same_name[name].append(l0)
for (l0, l1, name, body) in blocks:
start, end = ls[l0 - 1], ls[l1] if l1 < len(ls) else len(raw)
if used.get(name, 0) == 0 and not mentions(name):
later = sorted(x for x in same_name[name] if x > l0)
next_l0 = later[0] if later else None
if governed_uses(name, l0, next_l0) == 0 and not mentions(name, l0, next_l0):
edits.append((start, end, ""))
dead.append(name)
continue
@@ -971,7 +997,7 @@ def selftest():
dict(tu="c.c", l0=1, l1=2, name="LDV0_DA34", params="( r0 )", body='__asm__ volatile ("lwc2 $0, 0( %0 );lwc2 $1, 4( %0 )" : : "r"( r0 ))', kind="gte", sig=s4),
dict(tu="a.c", l0=3, l1=3, name="gte_rtps", params="()", body='__asm__ volatile ("nop;nop;rtps")', kind="gte", sig=s1),
], direct=[], uses={})
canon = canonical_table(inv, quiet=True)
canon = canonical_table(inv, quiet=True, write=False)
t = canon["canonical"].get(sig_key(s4))
if not t or t["name"] != "gte_ldv0" or t["clob"] != [] or t["defs"] != 2:
fail(f"canonical ldv0: {t}")
@@ -1003,7 +1029,7 @@ def selftest():
fo = fm.find("(", fpos)
finner = fm[fo + 1:lc._paren_span(fm, fo)]
inv2 = dict(definitions=defs, direct=[dict(tu="fx.c", line=7, col=5, fn="f", inner=finner, sig=signature(finner))], uses={})
canon2 = canonical_table(inv2, quiet=True)
canon2 = canonical_table(inv2, quiet=True, write=False)
plan = plan_files(inv2, canon2, bound={})
edits, rec = file_edits("fx.c", fx, plan["fx.c"], canon2, "self")
out = dl.apply_edits(fx, edits)
@@ -1017,7 +1043,7 @@ def selftest():
for (l0, l1, name, body) in lc.define_blocks(fxo):
defso.append(dict(tu="fo.c", l0=l0, l1=l1, name=name, params=define_params(fxo, l0), body=body, kind="gte", sig=signature(asm_inner(body))))
invo = dict(definitions=defso + [dict(tu="fa.c", l0=1, l1=1, name="gte_rtps", params="()", body='__asm__ volatile ("nop;nop;rtps")', kind="gte", sig=signature('"nop;nop;rtps"'))], direct=[], uses={})
canono = canonical_table(invo, quiet=True)
canono = canonical_table(invo, quiet=True, write=False)
plano = plan_files(invo, canono, bound={})
editso, reco = file_edits("fo.c", fxo, plano["fo.c"], canono, "self")
outo = dl.apply_edits(fxo, editso)
@@ -1040,7 +1066,7 @@ def selftest():
for (l0, l1, name, body) in lc.define_blocks(fx2):
defs2.append(dict(tu="fy.c", l0=l0, l1=l1, name=name, params=define_params(fx2, l0), body=body, kind="gte", sig=signature(asm_inner(body))))
inv3 = dict(definitions=defs2, direct=[], uses={})
canon3 = canonical_table(inv3, quiet=True)
canon3 = canonical_table(inv3, quiet=True, write=False)
names3 = sorted(t_["name"] for t_ in canon3["canonical"].values())
plan3 = plan_files(inv3, canon3, bound={})
edits3, rec3 = file_edits("fy.c", fx2, plan3["fy.c"], canon3, "self")
@@ -394,7 +394,30 @@ def _paren_depth_at(masked, start, pos):
return depth
def walk_file(raw, rel, is_header):
def global_asm_macros(files):
"""name -> kind for every asm-bearing #define in the tree plus the GTE header and the prelude: a USE of a macro defined in another
file (the prelude's ENGINE_SHB in a shared header; a unit's SHB in a header it includes) was invisible to the census, which only
knew a file's own definitions — 7 launder levers uncounted, three live SHB definitions judged dead (the oracle refused). Kinds
disagreeing across definitions resolve to the majority."""
kinds = collections.defaultdict(collections.Counter)
for rel in list(files) + [GTE_HEADER_DEFAULT, PRELUDE]:
p = REPO / rel
if not p.exists():
continue
raw = p.read_text(errors="surrogateescape")
if "#define" not in raw:
continue
for (l0, l1, name, body) in define_blocks(raw):
k = macro_kind(body)
if k:
kinds[name][k] += 1
return {n: c.most_common(1)[0][0] for n, c in kinds.items()}
PRELUDE = "src/shared/engine_prelude.h"
def walk_file(raw, rel, is_header, global_names=None):
"""One file. Returns dict(sites=[...], defs=[...], macro_defs=[...], tokens=dict(raw, live, macro_block, comment_dead, unclassified),
unclassified=[...])."""
masked = sc.mask_text(raw)
@@ -426,7 +449,8 @@ def walk_file(raw, rel, is_header):
mdefs.append(dict(name=name, kind=kind, line=l0, end=l1, nlines=l1 - l0 + 1, text_hash=hashlib.sha1(re.sub(r"\s+", " ", body).encode()).hexdigest()[:12]))
if l1 > l0:
macro_block_lines.update(range(l0, l1 + 1))
asm_macro_names = {m["name"]: m["kind"] for m in mdefs}
asm_macro_names = dict(global_names or {}) # names defined elsewhere in the tree (kind by the majority definition)
asm_macro_names.update({m["name"]: m["kind"] for m in mdefs}) # the file's own definitions win
# single-line #define lines stay in the masked text: their tokens are roled 'macro-def'
define_single_lines = {l0 for (l0, l1, _, _) in define_blocks(raw) if l0 == l1}
sites, roles, claimed = [], {}, set()
@@ -676,9 +700,9 @@ def walk_file(raw, rel, is_header):
def _walk_worker(args):
rel, is_header = args
rel, is_header, global_names = args
raw = (REPO / rel).read_text(errors="surrogateescape")
return walk_file(raw, rel, is_header)
return walk_file(raw, rel, is_header, global_names)
# ----------------------------------------------------------------------------------------------------------------------
@@ -755,11 +779,13 @@ def run_census(jobs, use_cache=True, out_dir=OUT_DIR_DEFAULT, want_sites=False,
cache = {}
work, keys = [], {}
files = [(rel, False) for rel in sorted(tu_aliases)] + [(h, True) for h in headers]
gnames = global_asm_macros([rel for rel, _ in files])
gstamp = hashlib.sha1(json.dumps(sorted(gnames.items())).encode()).hexdigest()[:8] # the cross-file name table is part of the key
for rel, is_h in files:
st = (REPO / rel).stat()
keys[rel] = f"{rel}|{int(st.st_mtime)}|{st.st_size}|{TOOL_STAMP}" # a tool change invalidates every cached walk (R35)
keys[rel] = f"{rel}|{int(st.st_mtime)}|{st.st_size}|{TOOL_STAMP}|{gstamp}" # a tool change invalidates every cached walk (R35)
if keys[rel] not in cache:
work.append((rel, is_h))
work.append((rel, is_h, gnames))
results = {}
if work:
with ProcessPoolExecutor(max_workers=jobs) as ex:
@@ -1036,6 +1062,7 @@ s32 func_80128218(s32 a0, register s32 a1) {
__asm__("addu %0,%1,$zero" : "=r"(v) : "r"(s));
__asm__("la %0, D_800A5E94" : "=r"(p));
SHB(v);
ENGINE_SHB(v);
GTE_LDV0(p);
q = (u8 *)__builtin_memcpy((void *)a0, (void *)a1, 8);
return v + zr + plain + buf[0] + (s32)q;
@@ -1051,10 +1078,10 @@ void func_80128500(void) {
def selftest():
r = walk_file(FIXTURE, "src/fx/x.c", False)
r = walk_file(FIXTURE, "src/fx/x.c", False, global_names={"ENGINE_SHB": "launder"})
got = collections.Counter((s["cls"], s["kind"]) for s in r["sites"])
want = collections.Counter({("A", "pin"): 5, ("D", "register"): 2, ("C", "decl-file"): 1, ("C", "decl-body"): 1, ("C", "cast"): 1,
("B", "barrier"): 3, ("B", "launder"): 2, ("B", "keepalive"): 1, ("B", "instruction"): 2,
("B", "barrier"): 3, ("B", "launder"): 3, ("B", "keepalive"): 1, ("B", "instruction"): 2,
# the fixture's GTE_LDV0 carries a "memory" clobber Sony's gte_ldv0 lacks: a gte-lever once the T5 tables
# (.run/P36/gte/canonical.json + sig_cache.json, tracked) exist — they do in every checkout
("B", GTE_LEVER_KIND if _gte_lookup()[1] else "gte"): 1,
@@ -1077,7 +1104,7 @@ def selftest():
if len(r["orphan_markers"]) != 1:
print(f"selftest: orphan markers {r['orphan_markers']} (want exactly the stale line)"); ok = False
via = sorted(s["detail"] for s in r["sites"] if s.get("via"))
if via != ["GTE_LDV0", "SHB"]:
if via != ["ENGINE_SHB", "GTE_LDV0", "SHB"]:
print(f"selftest: macro uses {via}"); ok = False
mk = sorted((m["name"], m["kind"]) for m in r["macro_defs"])
if mk != [("GTE_LDV0", "gte"), ("SHB", "launder")]:
+2 -2
View File
@@ -782,10 +782,10 @@ Every script under `tools/` (plus the two report make-targets), grouped by purpo
| | `tools/kit_lint.py [--selftest] [--paths …]` | **(P33.5 task 11)** The day-one decomp kit (`decomp-architect/`) stays de-specialised: (1) LEAK — no line outside a ```` ```calibration ```` fence and off a `provenance:` line matches `SLUS|Musashi|BFM|Druthulu|func_80|ov_SC|/home/musashi|/mnt/z|172\.17\.|\bR[0-9]{1,2}\b|§[0-9]+` (fence-aware: `grep -v calibration` would drop only lines containing the word); (2) PLACEHOLDERS — the `{{NAME}}` set used under the package equals the backticked set in `templates/PLACEHOLDERS.md` (the contract); (3) SYNTAX — `bash -n` / `py_compile` (no bytecode written) / JSON+YAML parse; (4) the gitignore template diff (delegated); (5) `TODO(platform)` / `TODO(phase-N)` counts; (6) coverage — zero files is a failure. rc 1 findings, rc 2 package absent (R43). `--selftest` = the R39 control (a planted leak line + a planted unlisted placeholder must be caught, fenced and provenance lines must not). In `tools-health` (selftest, then the real run). |
| | `tools/tool_census.py [--check | --manifest | --corpus | --all | --consumers FILE]` | **(P33.5 task 13.5)** The tools audit as a derived instrument: two independent enumerations of every tool file under `tools/` (`find` vs `git ls-files`, submodules/vendored/downloaded excluded — they must agree, R34); per tool the docstring line, its SETUP row, its CONSUMERS (Makefile/`.mk` targets, CI, the wave playbook, other tools by import or by name) and hence its class (LIVE · REFERENCED · ORPHAN); the AUTHORED facts live in `config/tool_dictionary.tsv` (phase · portability · the NEED the tool answers · what · what it hard-codes · the retirement verdict with its successor or product) with coverage asserted BOTH ways (R32 — a new tool without a row fails `--check`). Generates `docs/tool-index.md` (the need-keyed dictionary; KEEP-GEN), the kit's `tools/MANIFEST.md` (`--manifest`) and the three verbatim corpora `decomp-architect/corpus/tools/<phase>/` + `corpus/cookbook/` + `corpus/record/` (the how-to, the decision log, the accelerators, the retrospective, the story, the playbook, the effort map, the gen3 docs, the digest, every PhaseEnd — task 14.5) (`--corpus`; superseded tools as pointer files; sha1-equal to their sources). `--check` in `tools-health`; `make kit-corpus` = `--all`. `--consumers FILE` is the referrer census before any `git mv` of a tool. |
| | `tools/share_census.py` | **(P35 T1)** The fleet-wide census of byte-identical function classes and the S1 "one source per unique function" checker (`--check`, `--selftest`, `--scope`, `--strict-macros`, `--strict-text`); its ledger is `config/dedup_exceptions.tsv`; details in the P35 T1 section below. |
| | `tools/lever_census.py` | **(P36 T1)** The census of every compiler-forcing construct ("lever") in the fleet's C — register pins, asm statements by kind (barrier / launder / keepalive / instruction / GTE / verbatim-body), volatile levers, bare `register`, plus the deferred asm-label aliases, builtins and attributes — derived from `share_census`'s scanner with a per-token coverage assertion against the raw text, four known-true controls, the `// !FAKE:` marker split, `--check` (0 unmarked pins/asm AND 0 orphan markers — a `// !FAKE:` line with no pin/asm site on it nor on the line below) and `--check --strict` (0 pins, 0 asm outside the GTE header) gates, the JSON's `head` + stat-based `src_stamp` (delever refuses a census that does not describe the tree) and a per-file walk cache keyed on the walker's own hash (a tool change invalidates it, R35), `--sites` (every site to `.run/P36/census/lever_sites.jsonl`, the delever ledger's input), `--selftest`. Evidence: `.run/P36/census/lever_census.{json,txt}`; `progress.py` publishes the `levers` block and a README sentence from it. |
| | `tools/lever_census.py` | **(P36 T1)** The census of every compiler-forcing construct ("lever") in the fleet's C — register pins, asm statements by kind (barrier / launder / keepalive / instruction / GTE / verbatim-body), volatile levers, bare `register`, plus the deferred asm-label aliases, builtins and attributes — derived from `share_census`'s scanner with a per-token coverage assertion against the raw text, four known-true controls, the `// !FAKE:` marker split, `--check` (0 unmarked pins/asm AND 0 orphan markers — a `// !FAKE:` line with no pin/asm site on it nor on the line below) and `--check --strict` (0 pins, 0 asm outside the GTE header) gates, cross-file macro names (a use of a macro defined in another file — the prelude's `ENGINE_SHB`, a unit's `SHB` inside an included header, the GTE header's names — is classed by the majority definition's kind; it was invisible before), the JSON's `head` + stat-based `src_stamp` (delever refuses a census that does not describe the tree) and a per-file walk cache keyed on the walker's own hash (a tool change invalidates it, R35), `--sites` (every site to `.run/P36/census/lever_sites.jsonl`, the delever ledger's input), `--selftest`. Evidence: `.run/P36/census/lever_census.{json,txt}`; `progress.py` publishes the `levers` block and a README sentence from it. |
| | `tools/delever_oracle.py` | **(P36 T2)** The fast byte oracle for a single-translation-unit edit: `--recipes` captures every object's exact build command through `make -n -W <src> <obj> BINARY=<alias>` (the Makefile's own pipeline — the jump-table pad stage, the per-object `-O0` overrides, the twin rule — into `.run/P36/delever/recipes.json`, regenerable in ~15 s); a candidate is compiled IN PLACE with `-o`/`-MF` redirected to scratch and its bytes compared with `build/`'s object from the fleet run (build/ is never written); `--calibrate <aliases>` proves 100 % equality untouched + twin == primary + a positive control (a nop injected at the end of a real body → DIFFERS) and writes `calibration.json` (HEAD, config stamp, per-object seconds); `--status`. Measured at T2: main 0.08–0.77 s per object, overlays ~0.14 s. |
| | `tools/delever.py` | **(P36 T2/T3)** The de-lever engine AND the campaign tool. Rewrites per lever class on the raw text at the census's positions (a token mismatch REFUSES, never guesses): pin → plain declaration (type/qualifiers/initializer kept; the `$0` zero-register variable's uses → 0, refused if it is ever assigned), barrier / keep-alive → deleted, launder → deleted when it launders a value into itself, **an ASSIGNMENT `out = in;` when its output and input differ** (deleting those made cc1 2.7.2 abort — the T2 probe counted them NEEDED), a hand-placed instruction → its C (addu-$zero/move/la/lh/lw/addiu/sll/srl/and/andi/lui/li and the lui+addiu / lui+ori pairs), a macro-carried site → deleted for a pure launder statement macro (`SHB`), its value `((T)(p))` for a launder statement-expression, REFUSED for a compound macro (XFER/DRAW/RTP_SND: the lever is in the `#define`, T5), volatile / register → dropped. Per body: replay (a ledger exemplar with the same normalized text: 1 compile) → rung A strip-all → rung B greedy, through `delever_oracle` (verdicts IDENTICAL / DIFFERS / COMPILE-ERROR / COMPILE-CRASH). **The file is the write unit and its final compile the proof**: every body's accepted edits + the file-scope volatile edits + the `// !FAKE:` markers spliced once, compiled through every recipe of the file (a twin's object; every includer of a header, in parallel) — IDENTICAL or the file-scope edits are dropped, or the file is restored and REFUSED (COMBINATION-FAILED). `--plan` / `--apply --batch N --label L [--headers] [--only …] [-j 12]` (TUs in parallel, exemplar files before their copies; headers serial; the tree must be clean, the calibration current, the census's src stamp the tree's — it reruns the census itself), `--redraw REFUSED NOTHING-USABLE` (draw again the bodies whose latest ledger verdict is one of these — after a tool fix), `--restore` (from `inflight.json`, the only restore — R102; it also drops the in-flight batch's ledger rows into an ignored `ledger.jsonl.killed_<label>`, so a killed batch leaves no trace and its bodies are drawn again), `--status`, `--scrub [--only …]` (remove the census's ORPHAN markers — a `// !FAKE:` whose site is gone — each file judged through every recipe; a removed or rewritten site consumes its own trailing marker, so orphans arise only from older tool versions), `--apply-body TU FN FILE --label L [--rung E]` (T6/T7: a reshaped body judged on the bytes, refused if a class A/B lever remains), `--selftest` (the fixture through the census's own parser: every rewrite, the ladder against a stub oracle with a crashing site, the markers, a replay and a disagreeing replay, the ledger index, the oracle's crash forms), `--probe` (T2). The ledger `.run/P36/delever/ledger.jsonl`: one row per (tu, fn, addr, aliases) per judgement with every site's verdict REMOVED / REWRITTEN / NEEDED(oracle word) / REFUSED(why) / DEFERRED, the rung, the calibration id, the body's nhash BEFORE and AFTER — "done" = the current nhash is some row's after-hash; a body with a row's before-hash replays it. Class C/D survivors are never marked (decision 3); class A/B survivors carry `// !FAKE: <kind> <detail> — <verdict> (P36 <rung> <label>)` at the end of their line. Evidence: `apply_<label>.log`, `batch_<label>.json`. Per-batch setup: the per-file include lists are cached in the ignored `includers_cache.json` on (mtime, size) — 29 s → 1.3 s, proven equal to the uncached map. |
| | `tools/gte_consolidate.py` | **(P36 T5)** The GTE consolidation. `--inventory`: every asm-bearing `#define` and every direct GTE statement signed by the build's own tail (`maspsx --aspsx-version=2.56` → `mipsel-linux-gnu-as` with `include/macro.inc` + `gte_macros.inc`, where `rtps`/`mvmva`/`sqr 0` are GAS macros): signature = (bytes with %k bound to $4–$7 / $2–$3, #outputs, #inputs); `nop;nop;rtps`, `.word 0x4a180001` and `cop2 0x0180001` are one signature. The canonical table (`.run/P36/gte/canonical.json`): one text per signature (the majority body — byte-proven in the fleet), Sony's name when the operand counts agree with `inline_c.h` (Sony's converted header is unreliable for opcode words: `gte_rtps` there is `.word 0x0000007f`), Sony's clobber set canonical even when every definition carries the steer (the body is synthesized with Sony's clobbers); a definition with the canonical bytes and OTHER clobbers is a lever variant `<name>_m` / `<name>_v<hash>`. `--header` writes `include/gte_inline.h` (50 macros at T5) and the include in `common.h`. `--apply --batch N --label L`: per file, canonical duplicates deleted, private names renamed to the canonical, each variant TRIED as canonical (the clobber dropped, judged) and kept as a marked `_m` lever only when the object differs, direct statements rewritten into canonical calls (a concatenation of two canonical macros included; a direct statement with extra clobbers is marked as a lever; an unmatched sequence is counted); the file judged through every recipe, the definition edits alone retried when the direct rewrites differ. `--sweep`: dead asm-bearing macros (0 uses in the TU and its included headers) deleted; a compound macro's inner asm dropped when byte-neutral. `tools/delever_cycle.sh … gte` runs the apply batches. The census classes a variant's uses and a direct statement with clobbers beyond the canonical's as `gte-lever` — a class-B lever INSIDE the phase's number from T5 on (2026-09-09; the headline's definition gained the clause), marked, 0 at the close — and counts per-TU asm macro definitions. |
| | `tools/gte_consolidate.py` | **(P36 T5)** The GTE consolidation. `--inventory`: every asm-bearing `#define` and every direct GTE statement signed by the build's own tail (`maspsx --aspsx-version=2.56` → `mipsel-linux-gnu-as` with `include/macro.inc` + `gte_macros.inc`, where `rtps`/`mvmva`/`sqr 0` are GAS macros): signature = (bytes with %k bound to $4–$7 / $2–$3, #outputs, #inputs); `nop;nop;rtps`, `.word 0x4a180001` and `cop2 0x0180001` are one signature. The canonical table (`.run/P36/gte/canonical.json`): one text per signature (the majority body — byte-proven in the fleet), Sony's name when the operand counts agree with `inline_c.h` (Sony's converted header is unreliable for opcode words: `gte_rtps` there is `.word 0x0000007f`), Sony's clobber set canonical even when every definition carries the steer (the body is synthesized with Sony's clobbers); a definition with the canonical bytes and OTHER clobbers is a lever variant `<name>_m` / `<name>_v<hash>`. `--header` writes `include/gte_inline.h` (50 macros at T5) and the include in `common.h`. `--apply --batch N --label L`: per file, canonical duplicates deleted, private names renamed to the canonical, each variant TRIED as canonical (the clobber dropped, judged) and kept as a marked `_m` lever only when the object differs, direct statements rewritten into canonical calls (a concatenation of two canonical macros included; a direct statement with extra clobbers is marked as a lever; an unmatched sequence is counted); the file judged through every recipe, the definition edits alone retried when the direct rewrites differ. `--sweep`: dead asm-bearing macros deleted — a use (or an `#include` of a header using the name) is counted for the GOVERNING definition, the last one above it, so a used sibling definition keeps no dead one alive; a compound macro's inner asm dropped when byte-neutral. `--remark [--dirty-ok]`: the census's UNMARKED gte-lever sites marked on their own (first) lines after a `delever --scrub`. The selftest never writes the real table (`canonical_table(write=False)`) — it once did, and the census then classified against a fixture. `tools/delever_cycle.sh … gte` runs the apply batches. The census classes a variant's uses and a direct statement with clobbers beyond the canonical's as `gte-lever` — a class-B lever INSIDE the phase's number from T5 on (2026-09-09; the headline's definition gained the clause), marked, 0 at the close — and counts per-TU asm macro definitions. |
| | `tools/delever_cycle.sh` | **(P36 T3)** The unattended batch cycle: `[LABEL_PREFIX=…] [TASK=T4] [REDRAW="REFUSED NOTHING-USABLE"] tools/delever_cycle.sh START END [BATCH=300] [tus|headers] [ONLY="alias …"]` — per batch: the tree must be clean (a dotfile under `src/` refuses), the oracle recalibrated when stale (2–3 s; every commit stales it), `delever --apply` (exit code + its `final X/X identical` — an empty verify line is a failure, R32), the CLEAN fleet run as the outer gate (`218 passed, 0 failed of 218`, R22 — it also refreshes `build/`, the oracle's baselines), the census rerun on the new tree, the phase-log entry + the 🛑 headline (R101), one commit of `src/` + the ledger/batch record/logs + the census + the log (R42). Stops on the first red with the batch's files in place (inspect, then `delever --restore`); stops cleanly when nothing is drawable. Size a call so a batch stays under ~10 min. |
| | `tools/kit_coverage.py` | **(P33.5 task 14.5)** The kit's DISTILLATION coverage: derives the rule population (every `- **R<n>` of DIGEST §3, asserted contiguous) and the hindsight population (every `## ` heading of `docs/accelerators.md` at numbered-item granularity — 58 at S92) and asserts each is cited by a `provenance:` line of the registry seed / the kernels OR dispositioned in `config/kit_coverage_map.tsv` (`G<id>` / `DK-<n>` / `FOLDED:G<id>` / `ENV` / `PA` / `SEED:<file>` / `KIT:<path>` / `RECORD` / `COOKBOOK` / `NOT-PORTABLE`; unknown ids refused, R43); counts with denominators (R41); rc 1 on any gap. In `tools-health` after `tool_census --check`. Its first run found 26 uncited rules and 21 uncited entries → three new kernels (DK-66–DK-68) and 41 authored dispositions. |
| | `decomp-architect/` (the day-one decomp kit) | **(P33.5 tasks 9–14)** The package a new matching-decomp project installs as Phase 0.5 on ProjectArchitect 2.0: `README.md` (the three steps), `intake.decomp.md` (ProjectArchitect's twelve items pre-answered + the phase ladder + the six readability inversions), `SETUP.md` (the installer, Step 0 contract … Step 10 verify + hard stop; `answers: <path>` for unattended runs), `decomp-architect.md` (the methodology), `templates/` (the firewall pack — `gitignore.decomp`, `firewall.txt`, `audit_public.template.py`, the planted fixture, `no-rom.template.yml` —, the READMEs, `pa-overlays.md`, `registry-E.decomp.md` G1–G67, the skeletons, `PLACEHOLDERS.md`, `layout-contract.md`), `corpus/decomp-kernels.md` (DK-1 … DK-80), the three dictionaries `corpus/tools/<phase>/` + `corpus/cookbook/` + `corpus/record/` (generated by `make kit-corpus`), `memory-seed/` (18), `tools/MANIFEST.md` (generated). **How it is checked:** `tools/kit_lint.py` (de-specialisation, placeholders, syntax, the gitignore-template diff) + `tools/tool_census.py --check` (the corpora equal their sources) + `tools/gitignore_template_check.py`, all in `tools-health`; the dry-run harness under `.run/P33.5/kit-dryrun/` (`answers.md`, `expected-manifest.txt`, `judge.py`, the install logs and verdicts of runs 1–5 — a kit change is re-verified by a resume on the last throwaway `repo/`, a fresh full run only when SETUP's steps change; the judge compares the real tree's dirty PATH SETS before/after). Wiki page: `docs/wiki/Start-a-new-decomp-project.md`. Split into its own repository after the flip. |
+65 -58
View File
@@ -496,73 +496,80 @@ accumulate here as the phase produces them.**
real `canonical.json` (the census then classified every direct GTE statement against a fixture — 362 levers vanished twice); a selftest
never writes an instrument's real state (`write=False`).
## 🛑 SESSION CHECKPOINT — S98 (2026-09-09): T0 ☑ T1 ☑ T1b ☑ T2 ☑ T3 ☑ T4 ☑ — all committed (T4 = 13 batch commits `a605e1dba`…`f087282a3` + the tool commits; this close); NEXT = T5 the GTE consolidation + the dead lever-macro sweep | the number: 33,625 sites in 12,501 bodies (1,728 distinct) · marked 33,625 · UNMARKED 0 · orphans 0 — `lever_census --check` OK | last batch `gte2` on 145ab7719: THE PHASE'S NUMBER (pins + asm statements, GTE excluded): 34,085 sites in 12,710 bodies (1,757 distinct) · marked !FAKE 33,741 · UNMARKED 344
- **S98 — T5 CLOSE.** The census's cross-file blind spot fixed (a name defined in another file is classed by the majority definition's kind;
selftest 24 sites): 10 launder sites appeared in two shared headers → `delever --apply --headers --rejudge`: `func_80165CA0.h A=DIFFERS
B: removed 6 needed 2` (6 of the prelude's 7 `ENGINE_SHB` launders came off), `func_80166F58__3728db8a.h … needed 2 / refused 3` (its
three `SHB` uses bind to each includer's own definition — header-bound, marked); R22 **`check-all: 218 passed, 0 failed of 218`**
(`.run/P36/baseline/r22_t5_xfile.log`). **T5's verify line:** `lever_census`: **per-TU asm macro definitions outside the GTE header:
9,540 → 314** {gte 150 = 64 lever variants (`_m`/`_v`, their uses marked) + 85 header-bound homonyms (an includer's name with another
signature's bytes, used by an `h_text` header — the names phase's parameterized form) + 1 unsigned two-statement macro; launder 154 = 142
`SHB` definitions each governing a marked NEEDED use + the 12 compound/private launders whose inner asm is a real steer; instruction 9
(`RTP_SND`); barrier 1 (`COPY_TO_FAAC`)} — **0 canonical duplicates remain**; every remaining definition is tied to a surviving marked
lever or to a homonym, and dies with it (T6/T7/names). `include/gte_inline.h`: 50 macros for what were 9,102 definitions; 575 direct
statements now Sony-named calls; the GTE levers (462: 100 via a variant macro, 362 direct) are inside the number. **THE NUMBER: 34,091
sites in 12,712 bodies (1,759 distinct) · marked 34,091 · UNMARKED 0 · orphans 0** — `lever_census --check: … 0 UNMARKED — OK`. T5's
instrument findings for the record (nine, each fixed at its cause and selftested): the signature engine must be the build's own tail;
Sony's header is names-only; scoped renames; header-bound homonyms; object-like macros; the marker on the first line; the stable
canonical table (the header in the inventory); the census cache keyed on the tables; the selftest that wrote the real table; the
cross-file names; the sweep's per-definition uses. Commits: `0bd784c64` (header), `145ab7719`/`666d4b5ae`/`02810debd` (batches),
`5b6e1a2fe` (repair), `3b2c5178b`, `4bc987426` (sweep), this close. **T5 ☑.**
## 🛑 SESSION CHECKPOINT — S98 (2026-09-09): T0 ☑ T1 ☑ T1b ☑ T2 ☑ T3 ☑ T4 ☑ T5 ☑ — all committed (this close on top of `4bc987426`); NEXT = T6 rung R (mechanical shape recipes) + rung D (the permuter on the residue exemplars) | the number: 34,091 sites in 12,712 bodies (1,759 distinct) · marked 34,091 · UNMARKED 0 · orphans 0 · GTE levers 462 · per-TU asm macro definitions 314 (0 canonical duplicates) — `lever_census --check` OK
### 0. How to use this block
A fresh session reads CLAUDE.md's load order, replays this block verbatim, confirms the effort (T5/T6/T8/T9 xHigh per the plan; S98 ran
at Max — Drew toggles, R27) and executes §2. The tree is clean at HEAD = this close commit. The headless Ghidra MCP is unused this phase.
Drew pushes (R6). **T7 (the Ultracode reshaping waves) starts ONLY on Drew's direct approval in the session that would run them** (his
words, 2026-09-09, decisions) — the toggle is necessary, not sufficient. **Never run a long job as a harness background task** — the
harness's low-memory guard kills them with 22 GB free; run cycles DETACHED (`setsid nohup … &`, the usage line in the cycle script) and
watch the log with a `Monitor`; a killed batch: `tools/delever.py --restore` (drops its ledger rows); a batch whose apply + fleet run
were green but whose census/commit failed: `FINISH=<label> tools/delever_cycle.sh k k …`.
A fresh session reads CLAUDE.md's load order, replays this block verbatim, confirms the effort (T6/T8/T9 xHigh per the plan; S98 ran at Max —
Drew toggles, R27) and executes §2. The tree is clean at HEAD = this close commit. **T7 (the Ultracode reshaping waves) starts ONLY on
Drew's direct approval in the session that would run them** (his words, 2026-09-09, decisions). **Never run a long job as a harness
background task** (its low-memory guard kills them with 22 GB free; it also killed a 10-minute foreground chain that was moved to the
background — keep foreground chains under ~8 min, run cycles DETACHED with `setsid nohup … &` and a `Monitor` on the log). A killed
batch: `tools/delever.py --restore` (drops its ledger rows). The calibration is keyed to HEAD: EVERY commit stales it — recalibrate
(`tools/delever_oracle.py --calibrate ov_SC04_011 ov_SC03_015 ov_SC03_014 main -j 16`, 3 s) before any judging.
### 1. Where things stand
- **T4 done:** every drawable body judged (`delever --plan` and `--plan --headers`: `0 of 0 drawable files`); the totals are in the T4
close entry above. THE NUMBER: **53,234 → 33,625 sites (−36.8 %) in 12,501 bodies (1,728 distinct); 33,625 marked, 0 UNMARKED, 0
orphans**; the residue = 12,967 bodies in 1,803 distinct classes (pins-only 6,018 · pins+asm 4,310 · asm-only 2,141 · C/D-only 498).
Re-derive: `.venv/bin/python tools/lever_census.py --check -j 16` (≈35 s; must print `… 0 UNMARKED — OK` and no ORPHAN line at every
commit from now on) · `tools/delever.py --status` (the ledger's totals) · `docs/progress.json` `counts.levers` + README line 30 are
generated by `make report BINARY=main` (285 s; rewrites `docs/story-timeline.*` too — commit them together, R75).
- **The ledger** `.run/P36/delever/ledger.jsonl` (tracked): one row per body per judgement (verdict, rung, sites with REMOVED / REWRITTEN /
NEEDED(oracle word) / REFUSED(why) / DEFERRED, `nhash_before`/`nhash_after`, the calibration id); "done" = (tu, fn, after-hash); a body
reshaped by T6/T7 gets a new hash and is drawn again; `--redraw REFUSED NOTHING-USABLE` after a tool fix; `--apply-body TU FN FILE
--label L --rung D|E` banks a reshaped body (refused if a class A/B lever remains).
- **Instruments (SETUP + dictionary rows current, kit corpus regenerated, `tool_census --check: OK`):** `tools/delever.py` (`--plan`,
`--apply`, `--restore`, `--scrub`, `--status`, `--apply-body`, `--redraw`, `--selftest`, `--probe`), `tools/delever_cycle.sh` (`[TASK=…]
[FINISH=label] [REDRAW=…] START END [BATCH] [tus|headers] [ONLY]`), `tools/delever_oracle.py` (`--calibrate ov_SC04_011 ov_SC03_015
ov_SC03_014 main -j 16`, keyed to HEAD — every commit stales it), `tools/lever_census.py` (`--sites`, `--check [--strict]`, the controls
keyed on T1 hashes → N-A once a control body is edited, the walk cache keyed on the tool's hash, `orphan_markers`). Selftests:
`delever --selftest: OK — 15 sites in the exemplar, 1 refused rewrite(s), ladder RESIDUE (15 compiles), replay replay (1 compile),
markers 5`; `lever_census --selftest: OK — 23 sites, 2 defs, 2 asm macros`.
- **Environment:** WSL2, `~/bfm-decomp`, `.venv`; R22 clean fleet run 90–150 s; the census ≈35 s; `make report BINARY=main` ≈285 s; `make
kit-corpus` ≈25 s (a NEW tool must be `git add`ed first); 16 cores; 31 GB RAM; ~30 GB disk free; the harness's foreground cap is 10 min;
two `make` invocations in one tree are a race.
- **Done:** T0–T5. T4's campaign judged every body (16,334; 3,341 lever-free; 21,063 of 56,445 sites removed; the T4 close entry has the
tables). T5 consolidated the GTE coprocessor asm: `include/gte_inline.h` (50 canonical macros, Sony's names for 41, included from
`include/common.h`), 8,951 per-TU definitions deleted, 629 clobber variants byte-identical without the clobber, 575 direct statements
turned into calls, 274 dead launder macros swept; the census gained the `gte-lever` class (INSIDE the number), per-TU definition
counts, cross-file macro names, orphan markers, the controls keyed on their T1 hashes.
- **THE NUMBER: 34,091 sites (33,625 pins/asm + 462 GTE levers + 4 launders the cross-file fix surfaced) in 12,712 bodies (1,759
distinct); 34,091 marked; 0 UNMARKED; 0 orphans.** The residue for T6/T7 = every marked site: pins ≈ 20,600, barriers ≈ 4,570,
launders ≈ 4,640, keep-alives 2,000, instructions ≈ 1,670, refused/deferred ≈ 100, GTE levers 462. Re-derive: `.venv/bin/python
tools/lever_census.py --check -j 16` (must print `… 0 UNMARKED — OK`, no ORPHAN line); `tools/delever.py --status`;
`tools/gte_consolidate.py --status` (645 consolidated, 6 unchanged, 0 refused).
- **Instruments (SETUP + dictionary rows, kit corpus, `tool_census --check: OK`):** `tools/delever.py` (`--plan`, `--apply`, `--restore`,
`--scrub [--dirty-ok]`, `--status`, `--apply-body TU FN FILE --label L --rung D|E`, `--redraw`, `--rejudge`, `--selftest`, `--probe`);
`tools/delever_cycle.sh` (`[TASK] [FINISH=label] [REDRAW] START END [BATCH] [tus|headers|gte] [ONLY]`); `tools/delever_oracle.py`;
`tools/lever_census.py`; `tools/gte_consolidate.py` (`--inventory`, `--header`, `--apply`, `--sweep`, `--remark`, `--status`,
`--selftest`). The ledger `.run/P36/delever/ledger.jsonl` (tracked): body rows (rung A/B/replay), gte rows, sweep/scrub/remark rows.
- **Environment:** WSL2, `~/bfm-decomp`, `.venv`; R22 clean fleet run ≈ 115 s; the census ≈ 35 s (a full rewalk when a tool or a table
changes); `make report BINARY=main` ≈ 285 s; `make kit-corpus` ≈ 25 s; 16 cores; 31 GB RAM; ~30 GB disk free.
### 2. T5 — the GTE consolidation and the dead lever-macro sweep (xHigh; design first, X1)
The facts from T1's census (`.run/P36/census/lever_census.json` `macro_definitions`): 9,540 asm-bearing macro definitions under 338
names, 32 names with more than one text — gte 9,102 (`gte_ldv0` 839 defs / 9 texts; a 171-definition variant carries a byte-relevant
`"memory"` clobber; plus address-suffixed private copies like `LDV0_DA34`, `RTPS221A8`), launder 428 (`SHB` 416 defs / 2 texts — `__asm__
__volatile__("" : "=r"(x) : "0"(x))` ×145 and the non-volatile ×271; `ENGINE_SHB` in `src/shared/engine_prelude.h`; `LAUNDER_8018A180`),
instruction 9 (`RTP_SND`), barrier 1 (`COPY_TO_FAAC`), the compound `XFER`/`XFERLAST`/`XFER_1919A0`/`DRAW` (real code around a launder).
The GTE uses: 6,891 sites (`gte_ldv0` 653 uses, `gte_rtps` 356, `gte_stsxy` 361, `gte_stflg` 319, `gte_rtpt` 289 … and raw `lwc2`/`swc2`/
`mfc2` 945 spelled inline). Build order: (1) an inventory tool pass (extend `lever_census` or a small `tools/gte_consolidate.py`): every
GTE macro definition's name → normalized text → the PsyQ canonical name (the SDK's `inline_c.h`/`gtemac.h` spellings under
`include/psyq/` if present, else the majority text per name); group the address-suffixed private names by text; list the `"memory"`-
clobber variants apart (they are levers: the clobber is the steer — their USES become class-B `gte`+clobber sites for T7, not a second
spelling in the header). (2) `include/gte_inline.h` (the census's `GTE_HEADER_DEFAULT`) with one canonical macro per PsyQ name, included
from `src/shared/engine_prelude.h` (every overlay/module TU) and from main's/resident's common include; (3) per TU, delete the local
definitions whose text equals the canonical one, rename the private-name USES to the canonical name — every TU judged by the oracle
(`delever_oracle.judge_all`: a macro that expands to the same text gives the same object, but the oracle says so, not the argument), the
fleet gated by R22; (4) the dead-macro sweep: every `#define` with an asm inside and NO remaining use in its TU (`SHB` where T4 removed
every use; the census's macro list vs the sites' `via` counts — `SHB` may be used by an included header: `src/shared/ov/func_80166F58__3728db8a.h`
uses the INCLUDER's `SHB`, count cross-file uses before deleting) → deleted; `ENGINE_SHB` if unused fleet-wide; (5) the compound macros
(XFER/DRAW/RTP_SND/COPY_TO_FAAC/XFERLAST/…; 88 refused use sites): edit the DEFINITION (drop the launder/barrier statement inside), judge
the TU — IDENTICAL → the uses are no longer sites, their markers become orphans → `delever --scrub`; DIFFERS → the definition keeps
its asm and the use markers stay (T7). (6) `lever_census`: 0 per-TU asm macro definitions outside the GTE header (the T5 verify line);
R22 green; the log entry; SETUP/dictionary rows for any new tool; kit corpus; commit. Effort xHigh; one session.
### 2. T6 — rung R (mechanical shape recipes) + rung D (the permuter on the residue exemplars) (xHigh; design first, X1)
The plan's two yield lines: `recipes: <k> of <r> NEEDED sites removed` and `permuter: <k> of <r> exemplars matched lever-free in <t> h`.
(a) **Rung R** = byte-neutral shape recipes applied mechanically per NEEDED site, each negative-controlled on a body it must not change:
the cookbook's §501-P (a fresh single-set temp at the use), §501-R (the inline-expression-thrice / `u16` accumulator), §76 (declaration-scope
moves), T4 (branch-polarity flip), §17a (the explicit temp before a call), the `zr` → `0` copy-arm rewrite for the `$0` class (1,318 needed
`$0` pins), and for the 462 GTE levers "drop the clobber" (already tried per definition in T5 — the 70 kept ARE needed there) — read
`docs/matching-cookbook.md` by § (grep `^## §501`) and `docs/cookbook-index.md` by symptom; measure each recipe on a stratified sample of
its class before the sweep (R37). Implement as `tools/delever.py --recipes` (or a `tools/delever_recipes.py` that delever imports):
per body, per NEEDED site, the recipe's rewrite → the same oracle → REMOVED/NEEDED; the ledger row's site verdict gains `rule`.
(b) **Rung D** = `tools/permuter/run_masked.py` + `permuter_ils.py` on the residue EXEMPLARS (one per distinct after-hash class, ≈1,759;
largest copy count first), seeded with the lever-free body (every A/B site stripped — the target bytes from `build/`'s object of the fleet
run), `permuter_weights.py`'s class profile, a time budget per body, 16 workers, DETACHED; a score-0 candidate → `tools/delever.py
--apply-body TU FN FILE --label d<k> --rung D` (refused if a class A/B lever remains) → the copies replay through the ledger's exemplar
rows → the cycle's R22 + commit. Read `docs/SETUP.md` §permuter and cookbook §3/§5a/§12 for the harness (`.run/permuter/<fn>/`, `base.c`
self-contained, `target.o` from the object, `settings.toml`); `tools/verbatim_target_s.py` for the target listing. Report both yield lines
with denominators (R41), then the T6 log entry + checkpoint.
### 3. Numbers to re-derive, never trust
The gate-1 table (grep) → T1's census → T4's ledger; the T2 probe's percentages → T4's measured 37.3 % of sites / 20.5 % of bodies. Any
number in a published document is regenerated by `make report BINARY=main` (R75). The census after T5 will show FEWER macro definitions
and the same 33,625 pin/asm sites unless T5's definition edits remove use sites (the compound macros).
The T2 probe's rates → T4's measured rates → T5 changed the population (the number went UP by the 462 GTE levers and 4 surfaced
launders, DOWN by 6). Published numbers: `make report BINARY=main` (R75) — last run at the T4 close; run it at the T6 close.
### 4. Gotchas known before any work
The oracle must not write `build/`; objects embed the source path (compile in place, restore from the in-memory snapshot, the mtime
restored); the calibration is keyed to HEAD + the Makefile/config stamp; the census's src stamp is stat-based (a written file = rerun,
≈35 s); `compile_only.py` is not faithful; a dotfile under `src/` refuses the cycle; a shared header's edit reaches up to 136 binaries; never
`git checkout` to restore (R102); `tool_census --check` refuses an UNTRACKED tool; never two `make`s at once; never edit a running
bash script; a marker on a removed site is consumed by the rewrite and an orphan is a `--check` failure (`--scrub`).
Everything in the T3/T4 lists, plus T5's: a macro name is redefined between functions (scope every use to the definition above it); a
shared header's macro use binds to the INCLUDER's definition (the 20 `h_text` headers; a homonym is kept, not deleted); an object-like
macro's uses carry no parentheses; a marker goes at the end of a statement's FIRST line; a tool's selftest must never write the tool's
real tables; a census cache is keyed on every table it classifies with; never two `make`s at once; never edit a running bash script.
## Approved plan (verbatim, gate 1 — 2026-09-09)
+8 -8
View File
@@ -9,7 +9,7 @@ void func_80165CA0(void) {
s32 a1, base;
short *p;
short v;
register short w __asm__("$3"); // !FAKE: pin $3 — NEEDED DIFFERS (P36 rung B headers1)
register short w __asm__("$3"); // !FAKE: pin $3 — NEEDED DIFFERS (P36 rung B t5_xfile)
i = 0; q = &D_8011D030;
do {
if (*q != 0) (*(void (**)(u16 *))((u32)*q * 4 + D_80126728))(q);
@@ -17,19 +17,19 @@ void func_80165CA0(void) {
} while (i < 0x1e);
i = 0; off = 0;
do {
base = (s32)&D_8011D030; ENGINE_SHB(base);
base = (s32)&D_8011D030;
a1 = off + base;
p = *(short **)(a1 + 0x20);
if (p != 0) {
s32 q2;
if ((u16)*p == 1) {
v = *(short *)(a1 + 6); p[4] = v; ENGINE_SHB(v); *(int *)(p + 0x24) = v;
v = *(short *)(a1 + 0xa); p[5] = v; ENGINE_SHB(v); *(int *)(p + 0x26) = v;
w = *(short *)(a1 + 0xe); p[6] = w; v = p[0x16] | 1; ENGINE_SHB(w); p[0x16] = v; *(int *)(p + 0x28) = w;
v = *(short *)(a1 + 6); p[4] = v; *(int *)(p + 0x24) = v;
v = *(short *)(a1 + 0xa); p[5] = v; *(int *)(p + 0x26) = v;
w = *(short *)(a1 + 0xe); p[6] = w; v = p[0x16] | 1; p[0x16] = v; *(int *)(p + 0x28) = w;
} else if ((q2 = *(int *)(p + 0x1a)) != 0) {
v = *(short *)(a1 + 6); p[4] = v; ENGINE_SHB(v); *(int *)(q2 + 0x14) = v;
v = *(short *)(a1 + 0xa); p[5] = v; q2 = *(int *)(p + 0x1a); ENGINE_SHB(v); *(int *)(q2 + 0x18) = v;
v = *(short *)(a1 + 0xe); p[6] = v; q2 = *(int *)(p + 0x1a); ENGINE_SHB(v); *(int *)(q2 + 0x1c) = v;
v = *(short *)(a1 + 6); p[4] = v; *(int *)(q2 + 0x14) = v;
v = *(short *)(a1 + 0xa); p[5] = v; q2 = *(int *)(p + 0x1a); *(int *)(q2 + 0x18) = v;
v = *(short *)(a1 + 0xe); p[6] = v; q2 = *(int *)(p + 0x1a); ENGINE_SHB(v); *(int *)(q2 + 0x1c) = v; // !FAKE: launder via ENGINE_SHB — NEEDED DIFFERS (P36 rung B t5_xfile)
} else {
p[4] = *(short *)(a1 + 6); p[5] = *(short *)(a1 + 0xa); p[6] = *(short *)(a1 + 0xe);
}
+4 -4
View File
@@ -8,9 +8,9 @@ s32 func_80166F58(s32 param_1, s32 param_2, s32 param_3, s32 param_4)
extern s32 D_8011D030;
extern unsigned char D_8018E9E0[];
register int p2 __asm__("$20"); /* $s4 */ // !FAKE: pin $20 — NEEDED DIFFERS (P36 rung B headers2)
register int p2 __asm__("$20"); /* $s4 */ // !FAKE: pin $20 — NEEDED DIFFERS (P36 rung B t5_xfile)
int p3; /* $s1 */
register int t2 __asm__("$5"); /* a1 */ // !FAKE: pin $5 — NEEDED DIFFERS (P36 rung B headers2)
register int t2 __asm__("$5"); /* a1 */ // !FAKE: pin $5 — NEEDED DIFFERS (P36 rung B t5_xfile)
int t3; /* a2 */
unsigned short *puVar1;
short iVar2;
@@ -18,8 +18,8 @@ s32 func_80166F58(s32 param_1, s32 param_2, s32 param_3, s32 param_4)
iVar2 = 0;
puVar1 = ((unsigned short *)&D_8011D030);
t2 = ((short)param_2); SHB(t2); p2 = t2; SHB(p2);
t3 = ((short)param_3); SHB(t3); p3 = t3;
t2 = ((short)param_2); SHB(t2); p2 = t2; SHB(p2); // !FAKE: launder via SHB — REFUSED macro `SHB` is not defined in this file; launder via SHB — REFUSED macro `SHB` is not defined in this file (P36 rung B t5_xfile)
t3 = ((short)param_3); SHB(t3); p3 = t3; // !FAKE: launder via SHB — REFUSED macro `SHB` is not defined in this file (P36 rung B t5_xfile)
eq = (p2 == p3);
do {
if ((puVar1 != ((unsigned short *)param_1)) &&
+34 -8
View File
@@ -300,7 +300,9 @@ def inventory(jobs=12, quiet=False):
# ----------------------------------------------------------------------------------------------------------------------
# the canonical table
# ----------------------------------------------------------------------------------------------------------------------
def canonical_table(inv, quiet=False):
def canonical_table(inv, quiet=False, write=True):
"""write=False for fixtures: the selftest once overwrote the real table with its two-signature fixture (the census then classified
every direct statement against a fixture and 362 levers vanished twice) — a selftest never writes an instrument's real state."""
sony = sony_table()
incn = inc_names()
groups = collections.defaultdict(list)
@@ -380,7 +382,8 @@ def canonical_table(inv, quiet=False):
variants[f"{key}|{'|'.join(cs)}"] = dict(name=vname, of=name, key=key, clob=list(cs), extra=extra, fewer=fewer, defs=cnt,
files=len({d["tu"] for d in ds if tuple(d["sig"]["clob"]) == cs}))
out = dict(generated=time.strftime("%Y-%m-%d %H:%M"), canonical=table, variants=variants, unsigned=[dict(tu=d["tu"], name=d["name"], l0=d["l0"]) for d in unsigned])
CANON.write_text(json.dumps(out, indent=1))
if write:
CANON.write_text(json.dumps(out, indent=1))
if not quiet:
print(f"gte_consolidate: canonical table — {len(table)} signatures ({sum(1 for t in table.values() if t['sony'])} with Sony's name), "
f"{sum(t['defs'] for t in table.values())} canonical definitions; {len(variants)} lever variants holding {sum(v['defs'] for v in variants.values())} definitions; "
@@ -806,14 +809,37 @@ def sweep(a):
def_spans = collections.defaultdict(list)
for (l0, l1, name, body) in lc.define_blocks(raw):
def_spans[name].append((ls[l0 - 1], ls[l1] if l1 < len(ls) else len(raw)))
def mentions(name):
def mentions(name, l0=None, next_l0=None):
text = m
for s0, e0 in def_spans.get(name, ()):
text = text[:s0] + " " * (e0 - s0) + text[e0:]
if l0 is not None:
a = ls[l0 - 1]
b = ls[next_l0 - 1] if next_l0 else len(text)
text = text[a:b]
return re.search(r"\b%s\b" % re.escape(name), text) is not None
# uses per DEFINITION: a use (a census site via the name, or an #include of a header that uses the name) is governed by the last
# definition of that name above it; a definition with no governed use is dead even when a sibling definition is used
use_lines = collections.defaultdict(list)
for s in sites:
if s["tu"] == rel and s.get("via"):
use_lines[s["via"]].append(s["line"])
inc_lines = []
for mm in sc.INCLUDE_LINE.finditer(m):
h = os.path.normpath(os.path.join(os.path.dirname(rel), mm.group(1)))
inc_lines.append((m.count("\n", 0, mm.start()) + 1, hdr_uses.get(h, collections.Counter())))
def governed_uses(name, l0, next_l0):
n = sum(1 for ln in use_lines.get(name, []) if l0 < ln and (next_l0 is None or ln < next_l0))
n += sum(1 for ln, hu in inc_lines if hu.get(name, 0) and l0 < ln and (next_l0 is None or ln < next_l0))
return n
same_name = collections.defaultdict(list)
for (l0, l1, name, body) in lc.define_blocks(raw):
same_name[name].append(l0)
for (l0, l1, name, body) in blocks:
start, end = ls[l0 - 1], ls[l1] if l1 < len(ls) else len(raw)
if used.get(name, 0) == 0 and not mentions(name):
later = sorted(x for x in same_name[name] if x > l0)
next_l0 = later[0] if later else None
if governed_uses(name, l0, next_l0) == 0 and not mentions(name, l0, next_l0):
edits.append((start, end, ""))
dead.append(name)
continue
@@ -971,7 +997,7 @@ def selftest():
dict(tu="c.c", l0=1, l1=2, name="LDV0_DA34", params="( r0 )", body='__asm__ volatile ("lwc2 $0, 0( %0 );lwc2 $1, 4( %0 )" : : "r"( r0 ))', kind="gte", sig=s4),
dict(tu="a.c", l0=3, l1=3, name="gte_rtps", params="()", body='__asm__ volatile ("nop;nop;rtps")', kind="gte", sig=s1),
], direct=[], uses={})
canon = canonical_table(inv, quiet=True)
canon = canonical_table(inv, quiet=True, write=False)
t = canon["canonical"].get(sig_key(s4))
if not t or t["name"] != "gte_ldv0" or t["clob"] != [] or t["defs"] != 2:
fail(f"canonical ldv0: {t}")
@@ -1003,7 +1029,7 @@ def selftest():
fo = fm.find("(", fpos)
finner = fm[fo + 1:lc._paren_span(fm, fo)]
inv2 = dict(definitions=defs, direct=[dict(tu="fx.c", line=7, col=5, fn="f", inner=finner, sig=signature(finner))], uses={})
canon2 = canonical_table(inv2, quiet=True)
canon2 = canonical_table(inv2, quiet=True, write=False)
plan = plan_files(inv2, canon2, bound={})
edits, rec = file_edits("fx.c", fx, plan["fx.c"], canon2, "self")
out = dl.apply_edits(fx, edits)
@@ -1017,7 +1043,7 @@ def selftest():
for (l0, l1, name, body) in lc.define_blocks(fxo):
defso.append(dict(tu="fo.c", l0=l0, l1=l1, name=name, params=define_params(fxo, l0), body=body, kind="gte", sig=signature(asm_inner(body))))
invo = dict(definitions=defso + [dict(tu="fa.c", l0=1, l1=1, name="gte_rtps", params="()", body='__asm__ volatile ("nop;nop;rtps")', kind="gte", sig=signature('"nop;nop;rtps"'))], direct=[], uses={})
canono = canonical_table(invo, quiet=True)
canono = canonical_table(invo, quiet=True, write=False)
plano = plan_files(invo, canono, bound={})
editso, reco = file_edits("fo.c", fxo, plano["fo.c"], canono, "self")
outo = dl.apply_edits(fxo, editso)
@@ -1040,7 +1066,7 @@ def selftest():
for (l0, l1, name, body) in lc.define_blocks(fx2):
defs2.append(dict(tu="fy.c", l0=l0, l1=l1, name=name, params=define_params(fx2, l0), body=body, kind="gte", sig=signature(asm_inner(body))))
inv3 = dict(definitions=defs2, direct=[], uses={})
canon3 = canonical_table(inv3, quiet=True)
canon3 = canonical_table(inv3, quiet=True, write=False)
names3 = sorted(t_["name"] for t_ in canon3["canonical"].values())
plan3 = plan_files(inv3, canon3, bound={})
edits3, rec3 = file_edits("fy.c", fx2, plan3["fy.c"], canon3, "self")
+36 -9
View File
@@ -394,7 +394,30 @@ def _paren_depth_at(masked, start, pos):
return depth
def walk_file(raw, rel, is_header):
def global_asm_macros(files):
"""name -> kind for every asm-bearing #define in the tree plus the GTE header and the prelude: a USE of a macro defined in another
file (the prelude's ENGINE_SHB in a shared header; a unit's SHB in a header it includes) was invisible to the census, which only
knew a file's own definitions — 7 launder levers uncounted, three live SHB definitions judged dead (the oracle refused). Kinds
disagreeing across definitions resolve to the majority."""
kinds = collections.defaultdict(collections.Counter)
for rel in list(files) + [GTE_HEADER_DEFAULT, PRELUDE]:
p = REPO / rel
if not p.exists():
continue
raw = p.read_text(errors="surrogateescape")
if "#define" not in raw:
continue
for (l0, l1, name, body) in define_blocks(raw):
k = macro_kind(body)
if k:
kinds[name][k] += 1
return {n: c.most_common(1)[0][0] for n, c in kinds.items()}
PRELUDE = "src/shared/engine_prelude.h"
def walk_file(raw, rel, is_header, global_names=None):
"""One file. Returns dict(sites=[...], defs=[...], macro_defs=[...], tokens=dict(raw, live, macro_block, comment_dead, unclassified),
unclassified=[...])."""
masked = sc.mask_text(raw)
@@ -426,7 +449,8 @@ def walk_file(raw, rel, is_header):
mdefs.append(dict(name=name, kind=kind, line=l0, end=l1, nlines=l1 - l0 + 1, text_hash=hashlib.sha1(re.sub(r"\s+", " ", body).encode()).hexdigest()[:12]))
if l1 > l0:
macro_block_lines.update(range(l0, l1 + 1))
asm_macro_names = {m["name"]: m["kind"] for m in mdefs}
asm_macro_names = dict(global_names or {}) # names defined elsewhere in the tree (kind by the majority definition)
asm_macro_names.update({m["name"]: m["kind"] for m in mdefs}) # the file's own definitions win
# single-line #define lines stay in the masked text: their tokens are roled 'macro-def'
define_single_lines = {l0 for (l0, l1, _, _) in define_blocks(raw) if l0 == l1}
sites, roles, claimed = [], {}, set()
@@ -676,9 +700,9 @@ def walk_file(raw, rel, is_header):
def _walk_worker(args):
rel, is_header = args
rel, is_header, global_names = args
raw = (REPO / rel).read_text(errors="surrogateescape")
return walk_file(raw, rel, is_header)
return walk_file(raw, rel, is_header, global_names)
# ----------------------------------------------------------------------------------------------------------------------
@@ -755,11 +779,13 @@ def run_census(jobs, use_cache=True, out_dir=OUT_DIR_DEFAULT, want_sites=False,
cache = {}
work, keys = [], {}
files = [(rel, False) for rel in sorted(tu_aliases)] + [(h, True) for h in headers]
gnames = global_asm_macros([rel for rel, _ in files])
gstamp = hashlib.sha1(json.dumps(sorted(gnames.items())).encode()).hexdigest()[:8] # the cross-file name table is part of the key
for rel, is_h in files:
st = (REPO / rel).stat()
keys[rel] = f"{rel}|{int(st.st_mtime)}|{st.st_size}|{TOOL_STAMP}" # a tool change invalidates every cached walk (R35)
keys[rel] = f"{rel}|{int(st.st_mtime)}|{st.st_size}|{TOOL_STAMP}|{gstamp}" # a tool change invalidates every cached walk (R35)
if keys[rel] not in cache:
work.append((rel, is_h))
work.append((rel, is_h, gnames))
results = {}
if work:
with ProcessPoolExecutor(max_workers=jobs) as ex:
@@ -1036,6 +1062,7 @@ s32 func_80128218(s32 a0, register s32 a1) {
__asm__("addu %0,%1,$zero" : "=r"(v) : "r"(s));
__asm__("la %0, D_800A5E94" : "=r"(p));
SHB(v);
ENGINE_SHB(v);
GTE_LDV0(p);
q = (u8 *)__builtin_memcpy((void *)a0, (void *)a1, 8);
return v + zr + plain + buf[0] + (s32)q;
@@ -1051,10 +1078,10 @@ void func_80128500(void) {
def selftest():
r = walk_file(FIXTURE, "src/fx/x.c", False)
r = walk_file(FIXTURE, "src/fx/x.c", False, global_names={"ENGINE_SHB": "launder"})
got = collections.Counter((s["cls"], s["kind"]) for s in r["sites"])
want = collections.Counter({("A", "pin"): 5, ("D", "register"): 2, ("C", "decl-file"): 1, ("C", "decl-body"): 1, ("C", "cast"): 1,
("B", "barrier"): 3, ("B", "launder"): 2, ("B", "keepalive"): 1, ("B", "instruction"): 2,
("B", "barrier"): 3, ("B", "launder"): 3, ("B", "keepalive"): 1, ("B", "instruction"): 2,
# the fixture's GTE_LDV0 carries a "memory" clobber Sony's gte_ldv0 lacks: a gte-lever once the T5 tables
# (.run/P36/gte/canonical.json + sig_cache.json, tracked) exist — they do in every checkout
("B", GTE_LEVER_KIND if _gte_lookup()[1] else "gte"): 1,
@@ -1077,7 +1104,7 @@ def selftest():
if len(r["orphan_markers"]) != 1:
print(f"selftest: orphan markers {r['orphan_markers']} (want exactly the stale line)"); ok = False
via = sorted(s["detail"] for s in r["sites"] if s.get("via"))
if via != ["GTE_LDV0", "SHB"]:
if via != ["ENGINE_SHB", "GTE_LDV0", "SHB"]:
print(f"selftest: macro uses {via}"); ok = False
mk = sorted((m["name"], m["kind"]) for m in r["macro_defs"])
if mk != [("GTE_LDV0", "gte"), ("SHB", "launder")]: