build: the libavr pin advances past the audit sweep, and the extents get counted

The pin crosses libavr's phase-6 close and the guideline sweep behind it;
the example is byte-identical on both chips in both modes.

The port's own sweep found rule 36 in seven places, and the fix had to be
measured rather than applied. Sakamoto's month offsets as a `std::to_array`
local cost **+348 bytes** on a 1480-byte image - an automatic class-type
constant inside a `constexpr` function is given an address and built per
call, which outlined `weekday()` whole and pulled in `__do_copy_data` and
`__udivmodhi4`; `static constexpr` is what folds it, and emits no symbol at
all. The six register buffers cost +4 as `to_array`, which materialises its
argument array before copying where an aggregate initialiser stores each
element as it is computed - so those take CTAD, which counts the extent and
keeps the direct initialisation. Both spellings are rule 36; only one is
free.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-12 14:40:20 +02:00
parent bea81c97e0
commit 572d38feef
2 changed files with 23 additions and 27 deletions

View File

@@ -81,7 +81,7 @@ constexpr std::uint8_t hours_from_reg(std::uint8_t reg)
// this maps Sunday to 1. // this maps Sunday to 1.
constexpr std::uint8_t weekday(std::uint16_t year, std::uint8_t month, std::uint8_t day) constexpr std::uint8_t weekday(std::uint16_t year, std::uint8_t month, std::uint8_t day)
{ {
constexpr std::uint8_t offsets[]{0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4}; static constexpr auto offsets = std::to_array<std::uint8_t>({0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4});
if (month < 3) { if (month < 3) {
--year; --year;
} }
@@ -151,34 +151,32 @@ class device {
[[nodiscard]] static status write_clock(const date_time &now) [[nodiscard]] static status write_clock(const date_time &now)
{ {
std::array<std::uint8_t, 7> raw{detail::to_bcd(now.second), std::array raw{detail::to_bcd(now.second),
detail::to_bcd(now.minute), detail::to_bcd(now.minute),
detail::to_bcd(now.hour), detail::to_bcd(now.hour),
SetWeekday ? detail::weekday(now.year, now.month, now.day) : std::uint8_t{1}, SetWeekday ? detail::weekday(now.year, now.month, now.day) : std::uint8_t{1},
detail::to_bcd(now.day), detail::to_bcd(now.day),
detail::to_bcd(now.month), detail::to_bcd(now.month),
detail::to_bcd(static_cast<std::uint8_t>(now.year % 100))}; detail::to_bcd(static_cast<std::uint8_t>(now.year % 100))};
return dev::write_regs(reg_clock, raw); return dev::write_regs(reg_clock, raw);
} }
[[nodiscard]] static status write_date(const date &value) [[nodiscard]] static status write_date(const date &value)
{ {
if constexpr (SetWeekday) { if constexpr (SetWeekday) {
std::array<std::uint8_t, 4> raw{detail::weekday(value.year, value.month, value.day), std::array raw{detail::weekday(value.year, value.month, value.day), detail::to_bcd(value.day),
detail::to_bcd(value.day), detail::to_bcd(value.month), detail::to_bcd(value.month), detail::to_bcd(static_cast<std::uint8_t>(value.year % 100))};
detail::to_bcd(static_cast<std::uint8_t>(value.year % 100))};
return dev::write_regs(reg_clock + 3, raw); return dev::write_regs(reg_clock + 3, raw);
} else { } else {
std::array<std::uint8_t, 3> raw{detail::to_bcd(value.day), detail::to_bcd(value.month), std::array raw{detail::to_bcd(value.day), detail::to_bcd(value.month),
detail::to_bcd(static_cast<std::uint8_t>(value.year % 100))}; detail::to_bcd(static_cast<std::uint8_t>(value.year % 100))};
return dev::write_regs(reg_clock + 4, raw); return dev::write_regs(reg_clock + 4, raw);
} }
} }
[[nodiscard]] static status write_time(const time_of_day &value) [[nodiscard]] static status write_time(const time_of_day &value)
{ {
std::array<std::uint8_t, 3> raw{detail::to_bcd(value.second), detail::to_bcd(value.minute), std::array raw{detail::to_bcd(value.second), detail::to_bcd(value.minute), detail::to_bcd(value.hour)};
detail::to_bcd(value.hour)};
return dev::write_regs(reg_clock, raw); return dev::write_regs(reg_clock, raw);
} }
@@ -187,12 +185,11 @@ class device {
[[nodiscard]] static status set_alarm1(const date_time &at, alarm1_rate rate, bool enable_interrupt = true) [[nodiscard]] static status set_alarm1(const date_time &at, alarm1_rate rate, bool enable_interrupt = true)
{ {
auto m = static_cast<std::uint8_t>(rate); auto m = static_cast<std::uint8_t>(rate);
std::array<std::uint8_t, 4> raw{ std::array raw{static_cast<std::uint8_t>(detail::to_bcd(at.second) | ((m & 1) << 7)),
static_cast<std::uint8_t>(detail::to_bcd(at.second) | ((m & 1) << 7)), static_cast<std::uint8_t>(detail::to_bcd(at.minute) | (((m >> 1) & 1) << 7)),
static_cast<std::uint8_t>(detail::to_bcd(at.minute) | (((m >> 1) & 1) << 7)), static_cast<std::uint8_t>(detail::to_bcd(at.hour) | (((m >> 2) & 1) << 7)),
static_cast<std::uint8_t>(detail::to_bcd(at.hour) | (((m >> 2) & 1) << 7)), static_cast<std::uint8_t>(day_date(at.day, rate == alarm1_rate::weekday_time_match) |
static_cast<std::uint8_t>(day_date(at.day, rate == alarm1_rate::weekday_time_match) | (((m >> 3) & 1) << 7))};
(((m >> 3) & 1) << 7))};
if (auto s = dev::write_regs(reg_alarm1, raw); !s) { if (auto s = dev::write_regs(reg_alarm1, raw); !s) {
return s; return s;
} }
@@ -202,11 +199,10 @@ class device {
[[nodiscard]] static status set_alarm2(const date_time &at, alarm2_rate rate, bool enable_interrupt = true) [[nodiscard]] static status set_alarm2(const date_time &at, alarm2_rate rate, bool enable_interrupt = true)
{ {
auto m = static_cast<std::uint8_t>(rate); auto m = static_cast<std::uint8_t>(rate);
std::array<std::uint8_t, 3> raw{ std::array raw{static_cast<std::uint8_t>(detail::to_bcd(at.minute) | ((m & 1) << 7)),
static_cast<std::uint8_t>(detail::to_bcd(at.minute) | ((m & 1) << 7)), static_cast<std::uint8_t>(detail::to_bcd(at.hour) | (((m >> 1) & 1) << 7)),
static_cast<std::uint8_t>(detail::to_bcd(at.hour) | (((m >> 1) & 1) << 7)), static_cast<std::uint8_t>(day_date(at.day, rate == alarm2_rate::weekday_time_match) |
static_cast<std::uint8_t>(day_date(at.day, rate == alarm2_rate::weekday_time_match) | (((m >> 2) & 1) << 7))};
(((m >> 2) & 1) << 7))};
if (auto s = dev::write_regs(reg_alarm2, raw); !s) { if (auto s = dev::write_regs(reg_alarm2, raw); !s) {
return s; return s;
} }

2
libavr

Submodule libavr updated: 07a0c40235...4c7d4d6ff3