@jalf의 답변은 대부분의 이유를 다루지 만 언급하지 않은 흥미로운 세부 사항이 하나 있습니다. 내부 RISC와 유사한 코어는 ARM / PPC / MIPS와 같은 명령어 세트를 실행하도록 설계되지 않았습니다. x86 세는 전력이 많이 소모되는 디코더뿐만 아니라 코어 전체에 걸쳐 어느 정도 지불됩니다. 즉, 단지 x86 명령어 인코딩이 아닙니다. 이상한 의미를 가진 모든 명령어입니다.
Intel이 명령 스트림이 x86이 아닌 작동 모드를 생성했다고 가정 해 보겠습니다. 명령은 uop에 더 직접적으로 매핑됩니다. 또한 각 CPU 모델에이 모드에 대한 자체 ISA가 있다고 가정 해 보겠습니다. 따라서 원하는 경우 내부를 자유롭게 변경할 수 있으며이 대체 형식의 명령 디코딩을 위해 최소한의 트랜지스터로 노출 할 수 있습니다.
아마도 x86 아키텍처 상태에 매핑 된 동일한 수의 레지스터 만 가질 수 있으므로 x86 OS는 CPU 별 명령 세트를 사용하지 않고도 컨텍스트 스위치에서이를 저장 / 복원 할 수 있습니다. 그러나 실제적인 제한을 버리면 일반적으로 마이크로 코드 1에 예약 된 숨겨진 임시 레지스터를 사용할 수 있기 때문에 레지스터를 몇 개 더 가질 수 있습니다 .
이후 파이프 라인 단계 (실행 단위)를 변경하지 않고 대체 디코더 만 있으면 이 ISA에는 여전히 많은 x86 편심이 있습니다. 아주 좋은 RISC 아키텍처는 아닐 것입니다. 단일 명령이 매우 복잡하지는 않지만 x86의 다른 광기 중 일부는 여전히 존재합니다.
예를 들어 : 왼쪽 / 오른쪽 시프트는 시프트 카운트가 1이 아니면 오버플로 플래그를 정의되지 않은 상태로 둡니다.이 경우 OF = 일반적인 부호있는 오버플로 감지입니다. 회전에 대한 유사한 광기. 그러나 노출 된 RISC 명령어는 플래그없는 시프트 등을 제공 할 수 있습니다 (일반적으로 복잡한 x86 명령어로 들어가는 여러 uop 중 하나 또는 두 개만 사용할 수 있음). 따라서 이것은 실제로 주요 반론으로 유지되지 않습니다.
RISC ISA를위한 완전히 새로운 디코더를 만들려는 경우 RISC 명령으로 노출 될 x86 명령의 일부를 선택하고 선택할 수 있습니다. 이것은 코어의 x86 전문화를 다소 완화합니다.
단일 uop이 많은 데이터를 보유 할 수 있기 때문에 명령어 인코딩은 고정 크기가 아닐 것입니다. 모든 여관의 크기가 같으면 말이되는 것보다 훨씬 많은 데이터. 단일 마이크로 퓨즈 uop은 2 개의 레지스터와 32 비트 변위가있는 주소 지정 모드를 사용하는 32 비트 즉시 및 메모리 피연산자를 추가 할 수 있습니다. (SnB 이상에서는 단일 레지스터 주소 지정 모드 만 ALU 작업과 마이크로 융합 할 수 있습니다.)
uop은 매우 크고 고정 너비 ARM 명령어와 매우 유사하지 않습니다. 고정 너비 32 비트 명령어 세트는 한 번에 16 비트 즉시 만로드 할 수 있으므로 32 비트 주소를로드하려면로드 즉시 하위 절반 /로드 상위 즉시 쌍이 필요합니다. x86은 그렇게 할 필요가 없습니다. 따라서 레지스터에서 상수를 유지하는 기능을 제한하는 15 개의 GP 레지스터만으로는 끔찍하지 않습니다. (15 개는 7 개 레지스터에 비해 큰 도움이되지만 31 개로 다시 두 배로 늘리면 훨씬 덜 도움이된다고 생각합니다. 일부 시뮬레이션이 발견 된 것 같습니다. RSP는 일반적으로 범용이 아니므로 15 개의 GP 레지스터와 스택에 가깝습니다.)
요약 :
어쨌든,이 대답은 "x86 명령 세트는 아마도 x86 명령을 빠르게 실행할 수 있어야하는 CPU를 프로그래밍하는 가장 좋은 방법 일 것입니다"로 요약되지만, 그 이유에 대해 약간의 빛을 비추 길 바랍니다.
프런트 엔드 대 백 엔드의 내부 uop 형식
Intel CPU에서 프런트 엔드 대 백엔드 uop 형식이 나타낼 수있는 차이점의 한 가지 사례 는 마이크로 퓨전 및 주소 지정 모드 를 참조하십시오 .
각주 1 : 마이크로 코드에 의해 임시로 사용되는 "숨겨진"레지스터가 있습니다. 이러한 레지스터는 x86 아키텍처 레지스터와 마찬가지로 이름이 바뀌므로 다중 uop 명령어는 순서가 맞지 않게 실행할 수 있습니다.
예 xchg eax, ecx
를 들어 Intel CPU에서 3 uops로 디코딩합니다 ( 왜? ). 우리의 최선의 추측은 이것들이 tmp = eax; ecx=eax ; eax=tmp;
. 그 순서대로 dst-> src 방향의 지연 시간을 ~ 1 사이클에서 측정하고 다른 방법으로는 2 사이클을 측정하기 때문입니다. 그리고 이러한 움직임 uops는 일반 mov
지침 과 같지 않습니다 . 지연 시간이없는 이동 제거의 후보가 아닌 것 같습니다.
PRF 크기를 실험적으로 측정하려고 시도하고 숨겨진 레지스터를 포함하여 아키텍처 상태를 유지하는 데 사용되는 물리적 레지스터를 고려해야한다는 언급은 http://blog.stuffedcow.net/2013/05/measuring-rob-capacity/ 를 참조하십시오 .
디코더 이후의 프런트 엔드에서 레지스터 이름을 물리 레지스터 파일로 변경하는 발급 / 이름 변경 단계 이전에 내부 uop 형식은 x86 reg 번호와 유사한 레지스터 번호를 사용하지만 이러한 숨겨진 레지스터를 처리 할 공간이 있습니다.
uop 형식은 비 순차적 코어 (ROB 및 RS), 일명 백엔드 (발급 / 이름 변경 단계 이후) 내에서 약간 다릅니다. int / FP 물리 레지스터 파일은 각각 Haswell에 168 개의 항목이 있으므로 uop의 각 레지스터 필드는 그 개수를 처리 할 수있을만큼 충분히 넓어야합니다.
이름 변경자는 HW에 있으므로 정적으로 예약 된 지침을 백엔드에 직접 제공하는 대신 사용하는 것이 더 나을 것입니다. 따라서 우리는 x86 아키텍처 레지스터 + 마이크로 코드 임시만큼 큰 레지스터 세트로 작업하게됩니다.
백엔드는 WAW / WAR 위험을 피하는 프런트 엔드 이름 변경자와 함께 작동하도록 설계되었으므로 원하는 경우에도 순차 CPU처럼 사용할 수 없었습니다. 이러한 종속성을 감지하는 인터록이 없습니다. 문제 / 이름 변경으로 처리됩니다.
문제 / 이름 변경 단계의 병목 현상없이 백엔드에 uop를 공급할 수 있다면 깔끔 할 수 있습니다 (예 : Skylake의 4 와이드 대 4 개의 ALU + 2 개의로드 + 1 개의 저장소 포트). 백엔드). 하지만 그렇게했다면 레지스터 재사용을 피하기 위해 코드를 정적으로 예약하고 캐시 미스가 오랫동안로드를 지연시킬 경우 여전히 필요한 결과를 밟을 수 없다고 생각합니다.
따라서 우리는 uop을 이슈 / 이름 변경 단계에 제공해야합니다. 아마도 uop 캐시 나 IDQ가 아닌 디코딩 만 우회 할 것입니다. 그런 다음 정상적인 위험 감지와 함께 정상적인 OoO exec를 얻습니다. 레지스터 할당 테이블은 16 개 + 몇 개의 정수 레지스터의 이름을 168 개 항목 정수 PRF로 변경하도록 설계되었습니다. 우리는 HW가 더 큰 논리적 레지스터 세트의 이름을 같은 수의 물리적 레지스터로 바꾸는 것을 기대할 수 없었습니다. 더 큰 RAT가 필요합니다.