pick a per-seed shuffled scratch from the volatile pool that doesn't collide with any caller-supplied register
| 263 | // pick a per-seed shuffled scratch from the volatile pool that doesn't |
| 264 | // collide with any caller-supplied register |
| 265 | static std::uint8_t pick_temp_reg(const VMConfig& vm, |
| 266 | std::uint64_t salt, |
| 267 | std::initializer_list<std::uint8_t> avoid) { |
| 268 | std::array<std::uint8_t, 7> pool{rx::rax, rx::rcx, rx::rdx, rx::r8, rx::r9, rx::r10, rx::r11}; |
| 269 | SeedRng local(vm.cipher_k1() ^ salt); |
| 270 | shuffle_in_place(pool, local); |
| 271 | |
| 272 | for (std::uint8_t r : pool) { |
| 273 | bool collide = false; |
| 274 | for (std::uint8_t a : avoid) if (a == r) { collide = true; break; } |
| 275 | if (!collide) return r; |
| 276 | } |
| 277 | |
| 278 | return rx::rdx; // unreachable: pool > avoid |
| 279 | } |
| 280 | |
| 281 | // mask reg to width_reg's width, stripping the high-byte flag |
| 282 | static void emit_mask_to_width(X64Emitter& e, const VMConfig& vm, |
no test coverage detected