Как 15-байтовая инструкция переносится из памяти формы в ЦП? - PullRequest
0 голосов
/ 28 февраля 2019

Предполагая, что мы используем компьютер x86-64, это означает, что его общие регистры имеют длину 64 бита, его шина данных может обрабатывать 64 бита за раз, его ALU может обрабатывать до 64-битного числа (верно?).

Имея простую инструкцию, такую ​​как

MOV $5, %eax

, перемещает 32-битное число через 64-битную шину данных в регистр ЦП.

Я прочитал следующее:

An x86-64 instruction may be at most 15 bytes in length.

Мой вопрос: как это возможно, если шина данных имеет максимальные 64 бита?как это может обработать инструкцию с 120 битами.Процессор извлекает его за несколько циклов?

Мой второй вопрос: существуют ли специальные регистры большей длины для хранения всех этих 120 битов?

Ответы [ 2 ]

0 голосов
/ 28 февраля 2019

Выборка инструкций - это отдельный путь к данным из выборки кода.Это не сделано с использованием 64-битных mov инструкций.Существует специальная логика, которая обрабатывает выборку и декодирование невыровненных x86-команд переменной длины.

Одна команда может занимать границу страницы 4 КБ, поэтому ее байты находятся на двух смежных физических страницах!Внешний интерфейс должен иметь возможность извлекать байты команд и собирать их в буфере.

Даже 8086 имел небольшой буфер предварительной выборки команд, хотя это не обязательно было необходимо для декодирования, поскольку на 8088 он был меньше, чемсамая длинная инструкция (не включая префиксы)).Также Справочник по микроарху Агнера Фога .См. https://en.wikichip.org/wiki/amd/microarchitectures/zen#Decode для получения дополнительной информации о внешнем интерфейсе в последних AMD.

На процессорах Intel семейства P6 и SnB выбор кода и предварительный код (для нахождения границ insn) происходит в 16-байтовых блоках,поиск длин до 6 инструкций за цикл и использование до 16 байт машинного кода x86 за цикл.Если инструкция выполняется после конца блока, предварительный кодер сохраняет эти байты до следующего цикла.Microarch pdf от Agner Fog содержит некоторые сведения об оптимизации, чтобы избежать узких мест перед предварительным декодированием;Декодирование x86 hard .например, префикс размера операнда изменяет длину rest инструкции в некоторых случаях.Например, префикс 66 является единственной разницей между add eax, imm32 (5 байтов) и add ax, imm16 (66 + 3 байта).В этом случае прекодеры в процессорах Intel останавливаются, что требует дополнительных циклов обработки.(В ответе Алексиса утверждается, что определение длины легко. Скорее всего, не легко со всеми расширениями ISA, накопленными за эти годы, где префикс VEX, например, является недопустимым кодированием другой инструкции.И это становится намного сложнее, когда вы пытаетесь выполнять несколько инструкций параллельно, потому что вы должны учитывать несколько начальных точек для всех инструкций после первой.Простые процессоры раньше медленно обрабатывали префиксы, например, занимая дополнительный цикл напрефикс или даже экранирующий байт. Но современный основной Intel (не с низким энергопотреблением) может обрабатывать любое количество префиксов без штрафа.)

Инструкции подаются на декодеры до 4 одновременно (или 5 или 6).с макро-синтезом).Или Skylake имеет 5 декодеров, которые обрабатывают до 7 инструкций, если есть 2 пары dec / jcc или другие макроплавкие пары.В зависимости от уарха это может привести к 7 микрооперациям (мопам) (4-1-1-1 на Core2 / Nehalem), 4 (семейство SnB до Skylake) или 5 (Skylake).

enter image description here

Параллельное декодирование инструкций x86 является таким узким местом, что современные процессоры (Intel, начиная с семейства SnB, AMD, начиная с Zen), декодируют кэш-операции для быстрого вызова горячих порций.кода.Кэш трассировки Pentium 4 был ранним экспериментом в этом направлении, который работал плохо (и у него не было пропускной способности декодера для поддержания приемлемой производительности при пропаданиях кэша трассировки).

См. Также Какова связь междуМикропроцессор Pentium начала 90-х годов и современные разработки Intel? о ретро-вычислениях, где мой ответ рассказывает о том, почему P4 был тупиком архитектуры CPU, и как семейство P6 (PPro / PIII) превратилось в нынешнее семейство Intel Sandybridge.


Все процессоры x86-64 достаточно новые для обеспечения высокой производительности с широкими внутренними путями передачи данных, но 16 и 32-разрядные процессоры имеют одинаковую максимальную длину в 15 байтов (включая избыточные префиксы) .Вероятно, они будут использовать буфер, по крайней мере, достаточно большой, чтобы содержать инструкции, не содержащие префиксы, если они будут декодировать их по отдельности, прежде чем смотреть на код операции, modrm + дополнительные байты режима адресации и / или немедленно.

За исключением оригинального 8086, где сегмент кода 64k, полный префиксов REP для одной инструкции , является действительным.На тот момент Intel не определила никаких ограничений по длине команды, и 8086 декодировал префиксы отдельно от остальной части инструкции.

0 голосов
/ 28 февраля 2019

Кодировка инструкции

Современная инструкция X86 построена из следующих элементов:

  • Префиксы (0, 1, 2, 3, 4)
  • VEX (0, 2, 3)
  • OPCODE (1)
  • ModR / M (1)
  • SIB (0,1)
  • DISP (0,1, 2, 4)
  • IMM (0, 1, 2, 4)

Префикс от 0 до 4 байтов:

Группа 1: LOCK илиREP
Группа 2: Сегменты (CS, SS, DS, ES, FS, GS - не все доступны в 64 битах) и подсказки ветвления (т. Е. Ветвление с большей вероятностью будет принято или нет?)
Группа 3: Размер операнда (66H, обязателен для некоторых инструкций!)
Группа 4: Размер адреса

VEX

VEX для расширения AVX (в основном)

OPCODE

OPCODE - фактическая инструкция, только 8 бит , если вы не учитываете VEX и некоторые другие префиксы / специальные байты , такие какзнаменитый 0F.(В старые времена это был способ доступа к сопроцессорам x86.)

ModR / M определяет режим

Он сообщает нам, какой режим регистра и / или памяти используется в соответствии с этими инструкциями,Некоторые инструкции не поддерживают все доступные режимы.

Масштаб, Индекс, База

SIB является расширением ModR / M.

Смещение

DISP - это смещение, незамедлительно добавляемое в регистр адресов (как в [ESP + 13]). Это также может быть прямой адрес в ячейке памяти.

Немедленно

IMM немедленное значение(в MOV EBX, $8 - 8 - это значение, загруженное в EBX, непосредственное значение.)

Обратите внимание, что IMM обычно ограничен 32 битами.REX может использоваться для получения 64 битов, но он доступен не со всеми инструкциями (поскольку общее количество байтов для любой одной инструкции составляет 15 байтов).Чтобы загрузить 64 бита в регистр, вы всегда загружаете его из памяти.Один из способов сделать это - использовать IP-адрес.(Примерно так: MOV R8, [RIP, -42]) Также я заметил, что в прошлом компиляторы, такие как gcc, не использовали эту инструкцию.Однако для 64-битных процессоров доступно 32-битное смещение, поэтому значение может быть практически любым (± 2 ГБ).

Загрузка инструкций

64-битные процессоры загружают инструкции в инструкциикэш.Он загружает 16 байтов за раз (это может варьироваться в зависимости от процессора).Затем процессор интерпретирует эти байты.В зависимости от процессора он может преобразовать эти байты в набор инструкций RISC или просто выполнить инструкции напрямую .

Например, инструкции LOOP label на самом деле почти эквивалентныкак минимум две инструкции:

SUB ECX, 1
JNZ label

Некоторым процессорам в прошлом было трудно с такими, поэтому LOOP был очень медленным.Одна из причин заключается в том, что SUB меняет многие из EFLAGS, когда LOOP не меняет ничего.

Интерпретатор не загружает инструкции в регистр.Он загружает его в CPU и обрабатывает его в соответствующем модуле (ALU, ACU, FPU и т. Д.). Однако есть регистр RIP, который указывает на текущую инструкцию.Насколько вам известно, RIP всегда указывает либо на начало текущей инструкции, либо на начало следующей инструкции.

Как это на самом деле реализовано, я не знаю.Они, вероятно, очень быстро (мгновенно) определяют, к какой единице это относится, и помещают туда инструкцию.Размер не так уж сложно определить, поэтому они могут быстро получить все байты и поместить их в соответствующий блок FIFO, вероятно, в виде значения 15 или 16 байтов (т.е. один элемент в FIFO, скорее всего, всегда 16 байтов, один байт можетигнорировать, что означает, что аппаратное обеспечение даже не имеет строк для его чтения!) Эти байты будут каждый раз размещаться в одном и том же месте.Поэтому, если у входа нет LOCK или REP, в этот байт FIFO будет добавлено, скажем, 00h.

Обратите внимание, что перемещение 16 байтов в FIFO между единицами - ничто.Графические процессоры годами перемещают гораздо большие объемы данных в своих FIFO.

Можно сказать, что эти FIFO являются дополнительными регистрами.Файл реестра - это то же самое, что FIFO, только он имеет произвольный доступ вместо механизма типа «PUSH / POP».Оба используют одинаковые технологии, то есть память, для хранения данных в FIFO и в реестре.

Документация

Я бы предложил первый документ, который в настоящее время называется:

Руководства разработчика программного обеспечения для архитектуры Intel® 64 и IA-32 объединены тома: 1, 2A, 2B, 2C, 2D, 3A, 3B, 3C, 3D и 4

От Intel, как хорошо читать о доступных инструкциях (не совсем все, но более чем достаточно, чтобы начать!)

...