- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
template <typename T, typename OUT_T = uint8_t>
OUT_T subdecoder_nbt::extract_bits(T bits, uint8_t pos, uint8_t end)
{
auto invert_bytes = [](T bytes) -> T
{
auto *p = reinterpret_cast<uint8_t*>(&bytes),
*p_end = reinterpret_cast<uint8_t*>(&bytes) + sizeof(bytes) - 1;
for(; p < p_end; ++p, --p_end)
{
*p = *p ^ *p_end;
*p_end = *p ^ *p_end;
*p = *p ^ *p_end;
}
return bytes;
};
bits = invert_bytes(bits);
bits <<= pos;
bits >>= (sizeof(bits) * 8 - (end - pos) - 1);
return (OUT_T)bits;
}
Как правильно доставать биты из промежутка из стандартных типов C++ на x86.
Изучал эту проблему в сумме почти сутки.
А всё потому, что x86 хранит байты в Little-Endian, из-за чего при сдвиге биты окажутся не там, где ожидаешь.
YpaHeLI_ 23.10.2020 12:17 # 0
bormand 23.10.2020 12:19 # 0
bormand 23.10.2020 12:40 # 0
З.Ы. invert_bytes аля htons/htonl/bswap_64 обычно делают сразу после чтения, до любой работы с числом, а не посреди неё.
bormand 23.10.2020 12:53 # 0
pethu 23.10.2020 13:04 # 0
P.S. ты отредактировал комментарий, там был read
bormand 23.10.2020 13:05 # 0
pethu 23.10.2020 13:11 # 0
bormand 23.10.2020 13:13 # 0
pethu 23.10.2020 13:15 # 0
bormand 23.10.2020 13:19 # 0
j123123 23.10.2020 17:21 # 0
будет какое-то такое описание:
Можно потом из этого XML генерить протобуфную питушню какую-нибудь
bormand 23.10.2020 17:28 # 0
Дык у протобуфа парсер в принципе не пригоден для кастомных форматов. Ибо там что-то в духе тегированных полей. Или что-то изменилось?
Ну что-то своё можно сгенерить. На крестах в общем-то просто имён полей хватает для генерации, остальное в компайлтайме доступно.
bormand 23.10.2020 13:06 # 0
read() я убрал потому что я обосрался с проверкой его результата (signed-unsigned mismatch).
bormand 23.10.2020 13:01 # 0
YpaHeLI_ 23.10.2020 13:06 # 0
bormand 23.10.2020 13:11 # 0
YpaHeLI_ 23.10.2020 13:14 # +1
то окажется, что не инвертировав байты ты достанешь не оттуда.
там вообще в этот отрезок войдет еще один отрезок, который ему не должен принадлежать.
15 14 13 [12] 11 10 9 8 | [7] 6 5 4 3 2 1 0 | LE
~~~~~~~~ -------------------------- ~~~~~~~~~~~
[7] 6 5 4 3 2 1 0 | 15 14 13 [12] 11 10 9 8 | BE
--- ~~~~~~~~~~~~~~~~~~~~ --------------------
bormand 23.10.2020 12:23 # +2
Rooster 23.10.2020 12:37 # +1
pethu 23.10.2020 13:06 # +2
a ^= b ^= a ^= b;
Сейас прилетит питух, и скажет, что это UB
bormand 23.10.2020 16:12 # 0
Или не скажет, а потом у тебя это в продакшене навернётся.
Rooster 23.10.2020 12:39 # +2
YpaHeLI_ 23.10.2020 13:05 # 0
На самом деле я хз как устроен std::swap для стандартных типов.
Используется ли там xor-обмен.
bormand 23.10.2020 13:16 # 0
xor-обмен никто в здравом уме не юзает, разве что выебнуться. Впрочем, компиляторы его умеют оптимизировать в один xchg. Как и классическую перестановку через временную переменную, которая юзается в дефолтном std::swap.
j123123 23.10.2020 16:25 # 0
guest8 23.10.2020 16:27 # −999
j123123 23.10.2020 16:31 # 0
> Instructions with a LOCK prefix have a long latency that depends on cache organization and possibly RAM speed. If there are multiple processors or cores or direct memory access (DMA) devices, then all locked instructions will lock a cache line for exclusive access, which may involve RAM ac-cess. A LOCK prefix typically costs more than a hundred clock cycles, even on single-processor systems. This also applies to the XCHG instruction with a memory operand.
guest8 23.10.2020 16:34 # −999
bormand 23.10.2020 16:36 # 0
Ну это уже неправда вроде. Если нет реальной драки за кешлайн, то атомики относительно дешёвые.
bormand 23.10.2020 16:30 # +1
Зачем? Зачем? Даже при обычном xchg, а не lock xchg у которого гарантии?
З.Ы. Бля, и правда. If a memory operand is referenced, the processor’s locking protocol is automatically implemented for the duration of the exchange operation, regardless of the presence or absence of the LOCK prefix or of the value of the IOPL.
j123123 23.10.2020 16:33 # +2
MAPTbIwKA 23.10.2020 23:25 # +1
naHga 23.10.2020 23:26 # 0
MAPTbIwKA 23.10.2020 23:27 # 0
naHga 23.10.2020 23:30 # 0
guest8 24.10.2020 02:08 # −999
bormand 24.10.2020 02:09 # 0
gost 24.10.2020 02:10 # +2
guest8 24.10.2020 03:01 # −999
bormand 24.10.2020 01:46 # +1
И какой-нибудь флажок smp-aware в eflags, который отключает все автоблокировки.
guest8 24.10.2020 02:34 # −999
bormand 24.10.2020 02:46 # +1
Лол, в доке по оригинальному 8086 уже есть глава про Multiprocessing Features! И там xchg ещё не брал lock автоматически.
The 8086 and 8088 are designed for the multiprocessing environment. They have built-in features that help solve the coordination problems that have discouraged multiprocessing system development in the past.
LOCK may be used in multiprocessing systems to coordinate access to a common resource.
It is possible for another processor to obtain the bus between these two cycles and to gain access to the partially-updated semaphore. This can be prevented by preceding the XCHG instruction with a LOCK prefix.
bormand 24.10.2020 02:54 # +1
Видимо какие-то лалки уже успели обосраться за 4 года.
guest8 24.10.2020 02:58 # −999
bormand 24.10.2020 03:04 # +1
LOCK на двойке был привилегированной инструкцией! А мутексов в юзермоде то хотелось. Вот и прикрутили автолочку к XCHG.
80386 перестал проверять привилегии на LOCK. Но уже было поздно.
Такой вот очередной плевок в вечность.
guest8 24.10.2020 03:08 # −999
bormand 24.10.2020 03:12 # 0
bormand 24.10.2020 03:19 # 0
guest8 24.10.2020 03:21 # −999
bormand 24.10.2020 03:23 # 0
The 80386 defines new exceptions that can occur even in systems designed for the 80286.
Exception #6 - invalid opcode
This exception can result from improper use of the LOCK instruction.
bormand 24.10.2020 03:25 # 0
Т.е. совместимость - это святое, но иногда можно и забить )))
guest8 24.10.2020 03:26 # −999
bormand 24.10.2020 05:01 # +1
Despite the fact that Pentium 4, Intel Xeon, and P6 family processors support processor ordering, Intel does not guarantee that future processors will support this model.
Какой дисклеймер )))
Т.е. интел внезапно может дропнуть гарантии про реордеринг. Но что-то мне намекает, что юзеры после этого дропнут интел.
guest8 24.10.2020 05:14 # −999
bormand 24.10.2020 05:28 # 0
Насколько я помню, на x86 только read вперёд write может проскочить (если они в разные места, само собой). Всё остальное идёт строго как написано в коде. Ну смёржиться разве что могут если WB или WC режим.
guest8 24.10.2020 05:29 # −999
bormand 24.10.2020 05:37 # 0
naHga 23.10.2020 23:33 # 0
guest8 24.10.2020 03:00 # −999
naHga 24.10.2020 03:22 # 0
11.2.2 Automatic Locking
In several instances, the processor itself initiates activity on the data
bus. To help ensure that such activities function correctly in
multiprocessor configurations, the processor automatically asserts the LOCK#
signal. These instances include:
• Acknowledging interrupts.
• Setting busy bit of TSS descriptor.
• Loading of descriptors.
• Updating page-table A and D bits.
• Executing XCHG instruction.
guest8 24.10.2020 03:25 # −999
naHga 24.10.2020 03:31 # 0
14.7 Differences From 8086
...
4. Value written by PUSH SP.
The 80386 pushes a different value on the stack for PUSH SP than the
8086/8088. The 80386 pushes the value of SP before SP is incremented
as part of the push operation; the 8086/8088 pushes the value of SP
after it is incremented. If the value pushed is important, replace
PUSH SP instructions with the following three instructions:
This code functions as the 8086/8088 PUSH SP instruction on the 80386.
Видимо, поэтому инструкцию PUSH SP почти нигде не встретишь: SP сначала кладут в какой-нибудь регистр, потом пушат.
guest8 24.10.2020 03:40 # −999
naHga 24.10.2020 03:45 # 0
Хак для определения процессора (когда-то не было CPUID):
guest8 24.10.2020 03:47 # −999
bormand 24.10.2020 03:52 # 0
CPUID can be executed at any privilege level to serialize instruction execution. Serializing instruction execution guarantees that any modifications to flags, registers, and memory for previous instructions are completed before the next instruction is fetched and executed.
guest8 24.10.2020 03:56 # −999
bormand 24.10.2020 03:58 # 0
Х.з., на самом деле это единственная инструкция, которая сериализует исполнение в юзермоде.
Формально ещё можно iret дёрнуть, но ты же не будешь это делать посреди кода.
guest8 24.10.2020 04:00 # −999
bormand 24.10.2020 04:00 # 0
cpuid - самый сильный из заборов, доступных юзермоду. Остальные заборы что-то да разрешают переставлять.
guest8 24.10.2020 04:02 # −999
bormand 24.10.2020 04:05 # 0
guest8 24.10.2020 04:10 # −999
bormand 24.10.2020 04:16 # 0
По-моему это только для замера пирфоманса может пригодиться.
guest8 24.10.2020 04:22 # −999
bormand 24.10.2020 04:24 # 0
guest8 24.10.2020 04:27 # −999
bormand 24.10.2020 04:34 # +1
Я сейчас открыл доку по первому пню, где она изначально появилась. И она там уже сериализует исполнение.
The CPUID instruction can be executed at any privilege level to serialize instruction execution.
guest8 24.10.2020 04:39 # −999
naHga 24.10.2020 04:43 # 0
guest8 24.10.2020 04:46 # −999
naHga 24.10.2020 04:52 # 0
486 мог быть от 25 МГц до 80(2×40) МГц или 100(3×33) МГц.
386 мог быть от 16 МГц до 40 МГц.
Т. е. можно было нарваться и на 40-мегагерцовую «трёшку», и на 25-мегагерцовую «четвёрку».
guest8 24.10.2020 05:00 # −999
guest8 24.10.2020 12:36 # −999
bormand 24.10.2020 03:43 # 0
naHga 24.10.2020 03:47 # +1
bormand 24.10.2020 03:28 # 0
guest8 24.10.2020 03:30 # −999
bormand 24.10.2020 03:31 # 0
mov ss, ...
mov sp, ...
И наебнуться от прерывания между ними.
guest8 24.10.2020 03:36 # −999
bormand 24.10.2020 03:39 # 0
guest8 24.10.2020 03:44 # −999
guest8 24.10.2020 03:50 # −999
bormand 24.10.2020 03:56 # 0
naHga 24.10.2020 04:07 # 0
guest8 24.10.2020 04:12 # −999
naHga 24.10.2020 04:16 # 0
Это расширение «Проводника», чтобы файл можно было мышкой кинуть на окошко, в котором отображается FTP. Почему они упомянули «Exchange», я не понял.
guest8 24.10.2020 04:19 # −999
naHga 24.10.2020 04:21 # 0
Где-то там были и патчи ОС под кривые прикладные программы.
guest8 24.10.2020 04:24 # −999
naHga 24.10.2020 04:28 # 0
guest8 24.10.2020 04:40 # −999
bormand 24.10.2020 04:54 # +1
Да иногда просто не везёт. На той версии мастера, которая была перед мержом твоих изменений и запуском тестов всё было норм. Но за это время кто-то уже пролез в мастер. И всё сломалось.
Полную сериализацию коммитов никто в здравом уме делать не будет. Поэтому иногда shit happens.
guest8 24.10.2020 04:59 # −999
bormand 24.10.2020 05:07 # 0
Придётся тесты очень сильно поджимать по времени и вбрасывать кучу железа на их распараллеливание.
По-моему это не особо пригодно для большой команды.
И 100% багов это всё равно не поймает. Ну не сможешь ты всё-всё-всё протестировать в такой сериализованной модели.
guest8 24.10.2020 05:11 # −999
bormand 24.10.2020 05:14 # 0
Ну вопрос в том, насколько полная сериализация коммитов ловит больше багов, чем более слабая но оптимистичная. И насколько она дороже обходится по железу и усилиям программистов.
Если была пара поломок мастера в месяц, то может и хуй с ними?
З.Ы. Я не против прекоммит тестов, я против их полной сериализации.
guest8 24.10.2020 05:19 # −999
guest8 24.10.2020 12:36 # −999
rotoeb 24.10.2020 13:24 # 0
guest8 23.10.2020 13:20 # −999
bormand 23.10.2020 15:43 # +1
З.Ы. Беру свои слова обратно. gcc -O2 не осилило xor-swap оптимизнуть. А вот с std::swap весь твой extract_bits<uint32_t, uint32_t>(n, 0, 31) свернулся в одну ассемблерную инструкцию bswap.
guest8 23.10.2020 15:54 # −999
bormand 23.10.2020 15:56 # +1
Ну и с наивным конпелятором, который не умеет в эту идиому, превращается в сраное говнище, которое не даёт процу распараллелить выполнение (в обычном swap'е по сути просто регистры заренеймятся).
guest8 23.10.2020 15:59 # −999
j123123 23.10.2020 16:14 # 0
Скастовать в тип подходящего размера который ксорить можно, и потом поксорить (точнее, сделать указатель на такой-то тип с поддержкой xor, и присвоить в такие указатели адреса на переменные с неподходящим для перексориванием типы, и потом уже поксорить). Обменять float-ы так вполне можно.
guest8 23.10.2020 16:15 # −999
bormand 23.10.2020 16:17 # 0
bormand 23.10.2020 16:16 # +1
Сможешь это написать без ub'ов и короче наивного свапа?
j123123 23.10.2020 16:19 # 0
bormand 23.10.2020 16:21 # 0
Прощайте, оптимизации, мне будет вас не хватать. Хотя с char * в общем-то так же.
j123123 24.10.2020 06:54 # +1
Впрочем, xor swap вообще говоря говно, https://godbolt.org/z/9rT6ax оптимизируется он плохо. Компилятор не может в принципе породить точно такой же код 1 в 1 как при обмене переменных через третью, т.к. если мы меняем переменную саму с собой, xor-swap ее занулит
gost 24.10.2020 07:08 # +2
Ну вот это и есть самое большое говнище в xor-swap. Всё прекрасно работает, а потом кто-нибудь передаёт туда уко-ко-козатели на одинаковые пельменные — и пиздец.
bormand 24.10.2020 13:29 # +1
naHga 24.10.2020 17:09 # 0
bormand 23.10.2020 16:18 # 0
Ну можно, только strict aliasing не забудь отключить.
guest8 23.10.2020 16:25 # −999
j123123 23.10.2020 16:27 # 0
Это ты про Эльбрус?
guest8 23.10.2020 16:30 # −999
bormand 23.10.2020 16:28 # 0
j123123 23.10.2020 13:07 # 0
uint16_t __builtin_bswap16 (uint16_t x)
uint32_t __builtin_bswap32 (uint32_t x)
uint64_t __builtin_bswap64 (uint64_t x)
uint128_t __builtin_bswap128 (uint128_t x)
из GCC, но Clang их вроде тоже умеет.
У MSVC есть под это своя елда:
Еще есть интелевые интринсики:
https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_bswap
И более-менее стандартный htonl() ntohl() (В стандарте Си нет, но в POSIX есть).
В крестоговно почему-то не завезли никакой специальной хуйни для разворота байтиков, но зато там можно функцию Бесселя считать.
bormand 23.10.2020 13:10 # 0
bormand 23.10.2020 14:04 # 0
j123123 23.10.2020 14:17 # 0
Ну это не совсем так, в последнем стандарте C++ описывается, что представление signed чисел может быть только в "two's complement" (дополнительный код). http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0907r4.html
И если это не описываеся, почему б это не описать тогда?
bormand 23.10.2020 14:19 # 0
С другой стороны, функции которые ты привёл - это такая же чистая математика как и функции бесселя. Можно и добавить, даже если на какой-нибудь платформе в духе PDP они не имеют никакого смысла.
З.Ы. А потом захочется вращения чисел и поиска старшего бита.
j123123 23.10.2020 14:21 # 0
Нет, пожалуй это ближе к области байтоебства, чем к математике. Зачем математикам разворачивать байтики?
bormand 23.10.2020 14:22 # 0
j123123 23.10.2020 14:26 # 0
bormand 23.10.2020 14:31 # 0
j123123 23.10.2020 15:47 # +1
bormand 23.10.2020 15:53 # 0
Rooster 23.10.2020 12:38 # +1
YpaHeLI_ 23.10.2020 13:22 # 0
j123123 23.10.2020 15:34 # 0
bormand 23.10.2020 16:11 # 0
bormand 23.10.2020 16:12 # 0