Skip to content

Commit 34a1c27

Browse files
committed
refactor label optimizer again (closes #383)
1 parent f18681b commit 34a1c27

3 files changed

Lines changed: 96 additions & 45 deletions

File tree

src/asar/assembleblock.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -761,14 +761,17 @@ static void resolve_pinned_freespaces() {
761761
fs.pin_target_id = get_freespace_pin_target(value.freespace_id);
762762
fs.len = 0;
763763
}
764+
for(int i = 1; i < freespaces.count; i++) {
765+
freespace_data& fs = freespaces[i];
766+
// just in case the pin target changed again or something
767+
fs.pin_target_id = get_freespace_pin_target(fs.pin_target_id);
768+
}
764769
}
765770

766771
static void allocate_freespaces() {
767772
// compute real size of all pinned freespace blocks
768773
for(int i = 1; i < freespaces.count; i++) {
769774
freespace_data& fs = freespaces[i];
770-
// just in case the pin target changed again or something
771-
fs.pin_target_id = get_freespace_pin_target(fs.pin_target_id);
772775
freespace_data& target = freespaces[fs.pin_target_id];
773776
target.total_len += fs.len;
774777
target.search_start = std::max(fs.search_start, target.search_start);

src/asar/main.cpp

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -357,31 +357,40 @@ virtual_file_error asar_get_last_io_error()
357357

358358
int getlenforlabel(int labelpos, int label_fs_id, bool exists)
359359
{
360-
unsigned int bank = labelpos>>16;
360+
int bank = labelpos>>16;
361361
unsigned int word = labelpos&0xFFFF;
362-
bool lblfreespace = label_fs_id > 0;
362+
bool lbl_is_freespace = label_fs_id > 0;
363+
// bank number for mirroring considerations.
364+
// this is the number of a bank which has the same "layout" as the current bank.
363365
unsigned int relaxed_bank;
366+
// nonnegative if we know that DBR is pointing at a certain bank
367+
int cur_effective_bank = -1;
364368
if(optimizeforbank >= 0) {
365-
relaxed_bank = optimizeforbank;
369+
cur_effective_bank = relaxed_bank = optimizeforbank;
366370
} else {
367371
if(freespaceid == 0) {
368-
relaxed_bank = snespos >> 16;
372+
cur_effective_bank = relaxed_bank = snespos >> 16;
369373
} else {
370374
int target_bank = freespaces[freespaceid].bank;
371375
if(target_bank == -2) relaxed_bank = 0;
372376
else if(target_bank == -1) relaxed_bank = 0x40;
373-
else relaxed_bank = target_bank;
377+
else cur_effective_bank = relaxed_bank = target_bank;
374378
}
375379
}
380+
381+
if(lbl_is_freespace) {
382+
bank = freespaces[label_fs_id].bank;
383+
}
384+
376385
if (!exists)
377386
{
378387
return 2;
379388
}
380-
else if((optimize_dp == optimize_dp_flag::RAM) && bank == 0x7E && (word-dp_base < 0x100) && !lblfreespace)
389+
else if((optimize_dp == optimize_dp_flag::RAM) && bank == 0x7E && (word-dp_base < 0x100) && !lbl_is_freespace)
381390
{
382391
return 1;
383392
}
384-
else if(optimize_dp == optimize_dp_flag::ALWAYS && (bank == 0x7E || !(bank & 0x40)) && (word-dp_base < 0x100) && !lblfreespace)
393+
else if(optimize_dp == optimize_dp_flag::ALWAYS && (bank == 0x7E || !(bank & 0x40)) && (word-dp_base < 0x100) && !lbl_is_freespace)
385394
{
386395
return 1;
387396
}
@@ -391,7 +400,7 @@ int getlenforlabel(int labelpos, int label_fs_id, bool exists)
391400
// and we're in a bank with ram mirrors... (optimizeforbank=0x7E is checked later)
392401
&& !(relaxed_bank & 0x40)
393402
// and the label is in low RAM
394-
&& bank == 0x7E && word < 0x2000 && !lblfreespace)
403+
&& bank == 0x7E && word < 0x2000 && !lbl_is_freespace)
395404
{
396405
return 2;
397406
}
@@ -401,27 +410,33 @@ int getlenforlabel(int labelpos, int label_fs_id, bool exists)
401410
// we're in a bank with ram mirrors...
402411
&& !(relaxed_bank & 0x40)
403412
// and the label is in a mirrored section
404-
&& !(bank & 0x40) && word < 0x8000 && !lblfreespace)
413+
&& !(bank & 0x40) && word < 0x8000 && !lbl_is_freespace)
405414
{
406415
return 2;
407416
}
408417
else if (optimizeforbank>=0)
409418
{
410419
// if optimizing for a specific bank:
411-
// if the label is in freespace, never optimize
412-
if (lblfreespace) return 3;
413-
else if (bank==(unsigned int)optimizeforbank) return 2;
420+
// if the label is in freespace, then bank is the freespace's bank, and
421+
// if that's non-negative, then the freespace is forced to that bank.
422+
// if the freespace isn't forced to a specific bank, then bank is
423+
// negative, so this equality will never hold.
424+
if (bank == optimizeforbank) return 2;
414425
else return 3;
415426
}
416-
else if (lblfreespace || freespaceid > 0)
417-
{
418-
// optimize only if the label is in the same freespace
419-
// TODO: check whether they're pinned to the same bank
420-
if (label_fs_id != freespaceid) return 3;
421-
else return 2;
427+
428+
// check if the label is pinned to the current freespace.
429+
// can only be checked after pass 0, as freespace pin targets aren't
430+
// computed before then.
431+
// This codepath also handles the case of labels that are in the current freespace.
432+
if(pass > 0 && lbl_is_freespace && freespaceid > 0) {
433+
int fs_pin_1 = freespaces[label_fs_id].pin_target_id;
434+
int fs_pin_2 = freespaces[freespaceid].pin_target_id;
435+
if(fs_pin_1 == fs_pin_2) return 2;
422436
}
423-
else if ((int)bank != snespos >> 16){ return 3; }
424-
else { return 2;}
437+
438+
if (bank >= 0 && bank == cur_effective_bank) return 2;
439+
else return 3;
425440
}
426441
int getlenforlabel(snes_label thislabel, bool exists) {
427442
return getlenforlabel(thislabel.pos, thislabel.freespace_id, exists);

tests/optimizer.asm

Lines changed: 56 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,4 @@
11
;`+
2-
;`AD 00 00 AF 00 00 7E
3-
;`AD 00 00 A5 00
4-
;`A5 00
5-
;`AD 00 00 A5 00
6-
;`AF 00 10 01 AD 00 10
7-
;`AD 00 10
8-
;`AF 1D 80 00
9-
;`AF 1D 80 00
10-
;`AD 1D 80
11-
;`AD 00 80 AF 00 80 01
12-
;`
13-
;`80000 53 54 41 52 26 00 D9 FF
14-
;` AD 08 80 AF 00 00 00 AF 00 60 02
15-
;` AD 00 00 AF 00 10 01 AF 00 60 02
16-
;` AD 00 00 AD 00 10 AD 00 60 AF 00 80 00
17-
;` AF 37 80 90
18-
;`53 54 41 52 16 00 E9 FF
19-
;` AF 08 80 90 AD 37 80 AF 00 00 00
20-
;` AF 00 00 7E
21-
;` AF 00 00 7E AF 00 60 02
22-
;`FFFFF 00
23-
24-
;1 line above = 1 block of code below
252
;namespace optimize_dp_flag {
263
; enum : int {
274
; NONE, //don't optimize
@@ -78,75 +55,131 @@ base off
7855
optimize address default
7956
optimize dp none
8057
;test default asar optimization (bank only)
58+
;`AD 00 00 AF 00 00 7E
8159
lda test_00.test
8260
lda test_7E.test
8361

8462
;test optimizations of dp on with dp base as default 0000 in bank 7E only
8563
;optimize dp ram
8664
optimize dp ram
8765
dpbase $0000
66+
;`AD 00 00 A5 00
8867
lda test_00.test
8968
lda test_7E.test
9069

9170
optimize dp always
71+
;`A5 00
9272
lda test_00.test
9373

9474
dpbase $0100
75+
;`AD 00 00 A5 00
9576
lda test_00.test
9677
lda test_00.test_0100
9778

9879
optimize dp none
9980
optimize address ram
81+
;`AF 00 10 01 AD 00 10
10082
lda test_word.up
10183
lda test_7E.word
10284

10385
optimize address mirrors
86+
;`AD 00 10
10487
lda test_word.up
10588

10689
bank noassume
10790
asdf:
91+
;`AF 1D 80 00
10892
lda asdf
10993
bank $10
94+
;`AF 1D 80 00
11095
lda asdf
11196
bank auto
97+
;`AD 1D 80
11298
lda asdf
11399

100+
;`AD 00 80 AF 00 80 01
114101
lda nonmirror
115102
lda nonmirror01
116103

117104
assert pc() <= $009000
118105

106+
bank80label = $808080
107+
segment bank=$80
108+
;`AD 80 80
109+
lda bank80label
110+
banksegmentlabel:
111+
112+
segment bank=$80
113+
;`AD 32 80
114+
lda banksegmentlabel
115+
;`AF 00 80 81
116+
lda bank1segmentlabel
117+
118+
segment bank=$81
119+
bank1segmentlabel:
120+
;`08000 EA
121+
nop
122+
123+
;`80000 53 54 41 52 26 00 D9 FF
119124
freecode cleaned
120125
optimize dp none
121126
optimize address default
122127
freec:
128+
;` AD 08 80 AF 00 00 00 AF 00 60 02
123129
lda freec
124130
lda test_00.test
125131
lda mirror
126132

127133
optimize address ram
134+
;` AD 00 00 AF 00 10 01 AF 00 60 02
128135
lda test_7E.test
129136
lda test_word.up
130137
lda mirror
131138

132139
optimize address mirrors
140+
;` AD 00 00 AD 00 10 AD 00 60 AF 00 80 00
133141
lda test_7E.test
134142
lda test_word.up
135143
lda mirror
136144
lda nonmirror
137145

146+
;` AF 37 80 90
138147
lda freed
139148

149+
;`53 54 41 52 16 00 E9 FF
140150
freedata cleaned
141151
freed:
142152
optimize address default
153+
;` AF 08 80 90 AD 37 80 AF 00 00 00
143154
lda freec
144155
lda freed
145156
lda test_00.test
146157

147158
optimize address ram
159+
;` AF 00 00 7E
148160
lda test_7E.test
149161

150162
optimize address mirrors
163+
;` AF 00 00 7E AF 00 60 02
151164
lda test_7E.test
152165
lda mirror
166+
167+
segment
168+
pinnedseg:
169+
;`EA
170+
nop
171+
172+
segment pin=pinnedseg
173+
;`AD 4E 80
174+
lda pinnedseg
175+
;`AF 5A 80 90
176+
lda unpinnedseg
177+
;`AF 00 80 81
178+
lda bank1segmentlabel
179+
180+
segment
181+
unpinnedseg:
182+
;`EA
183+
nop
184+
185+
;`FFFFF 00

0 commit comments

Comments
 (0)