scr_x: байтовая таблица x/7 вместо словарной — 1 такт быстрее, -1152 Б

Гипотеза «двухбайтная индексация съест выигрыш от сложения» не
подтвердилась.  Собраны ОБА варианта, такты посчитаны по сгенерированному
asm (хвост после проверки границ):

  int16_t готовое: add hl,hl / add hl,de / ld e,(hl) / inc hl / ld d,(hl)
                   = 132 такта, 2 304 байта
  int8_t  x/7:     add hl,bc / ld a,(hl) / ld l,a / rlca / sbc a,a /
                   ld h,a / add hl,de  = 131 такт, 1 152 байта

Расширение знака плюс 16-битное сложение стоят ровно столько же, сколько
лишний add hl,hl при двухбайтном индексе, а обращений к памяти на одно
меньше — под wait-state'ами Sprinter (2,4x номинала именно на обращениях
к ОЗУ) байтовый вариант ещё чуть выгоднее номинала.

Банк 4: 9 394 -> 8 243 из 16 384 (свободно 8 141 вместо 6 990) — запас под
рост pop_cdraw, о котором и был вопрос.

Тест переименован в geom_mul8div7_table_rules и проверяет ОБА правила
генерации таблицы: тождество 8x/7 == x + x/7 и усечение к нулю.
tests-host: [geom] 1992 -> 3144, все 5 наборов прошли.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-10 20:43:27 +03:00
parent 8175121d25
commit fc0ede91e1
3 changed files with 115 additions and 132 deletions
+12 -9
View File
@@ -72,20 +72,23 @@ TC_TEST(geom_y_to_row_matches_formula)
}
}
/* calc_screen_x_coord (seg008:2602) считается в pop_cdraw.c ГОТОВОЙ таблицей
* SCRX (банк 4, сюда не линкуется). Таблица сгенерирована питоном по правилу
* «усечение К НУЛЮ»: значение = знак(x) * (|x|*8 / 7). Проверяем ИМЕННО это
* правило на целевом компиляторе: если бы __divsint у SDCC округлял иначе
* (к минус бесконечности), вся отрицательная половина таблицы уехала бы на
* пиксель, а поймалось бы это только глазами на левой кромке комнаты. */
TC_TEST(geom_mul8div7_trunc_to_zero)
/* calc_screen_x_coord (seg008:2602) считается в pop_cdraw.c таблицей SCRX7
* (банк 4, сюда не линкуется): хранится x/7 байтом, результат = x + SCRX7[..].
* Таблица сгенерирована питоном, поэтому проверяем два правила, на которых
* держится генерация — ИМЕННО на целевом компиляторе:
* 1) тождество 8x/7 == x + x/7 (7x делится нацело);
* 2) усечение К НУЛЮ, а не к минус бесконечности.
* Округляй SDCC иначе — вся отрицательная половина уехала бы на пиксель, и
* поймалось бы это только глазами на левой кромке комнаты. */
TC_TEST(geom_mul8div7_table_rules)
{
int16_t x;
/* Полный диапазон obj_x по данным кадров: −416..695 (см. шапку scr_x). */
for (x = -448; x <= 703; x++) {
int16_t want = (int16_t)(((x < 0) ? -x : x) * 8 / 7);
if (x < 0) want = (int16_t)-want;
TC_EQ((int16_t)(x * 8 / 7), want);
TC_EQ((int16_t)(x * 8 / 7), want); /* усечение к нулю */
TC_EQ((int16_t)(x * 8 / 7), (int16_t)(x + x / 7)); /* тождество */
}
}
@@ -171,7 +174,7 @@ int main(void)
TC_RUN(geom_yland_rows);
TC_RUN(geom_y_to_row);
TC_RUN(geom_y_to_row_matches_formula);
TC_RUN(geom_mul8div7_trunc_to_zero);
TC_RUN(geom_mul8div7_table_rules);
#if POP_PRANDOM_EXACT
TC_RUN(geom_lcg_matches_reference);
TC_RUN(geom_lcg_seed_zero);