답변:
레지스터 이름을 바꾸는 레지스터를 사용하는 최신 마이크로 아키텍처에서 플래그 구현 비용은 거의 비슷합니다. 내가 생각할 수있는 주요 차이점은 일부 플래그는 값의 특성을 나타냅니다 (값이 음수입니까? 값이 0입니까? 값이 짝수 또는 홀수 패리티를 가지고 있습니까?). 일부 플래그는 이전 작업 중에 발생한 이벤트를 나타냅니다 (추가 명령에 수행 또는 오버 플로우가 있었습니까?) 이로 인해 32 비트 아키텍처에서 64 비트 추가 (또는 128 비트 추가)를 시뮬레이션하려는 경우 MIPS에서 상황 이 덜 열악 했습니다. 캐리 플래그가있는 대부분의 아키텍처에는 특별한 기능이 있습니다.add-with-carry
이전 add 명령어의 carry 플래그를 포함하는 명령어입니다. 이것은 플래그 레지스터를 가진 많은 아키텍처에서 다중 정밀도 산술 시뮬레이션을 비교적 저렴하게 만듭니다.
반대로, 0 비트 또는 0이 아닌 N 비트 레지스터를 테스트하는 것은 실제로 놀랍도록 비싸다. N 비트 레지스터를 0으로 테스트하려면 계산 하려면 레벨의 로직 이 필요한 N 비트 NOR 연산을 수행해야합니다 . 플래그가 등록 된 아키텍처에서 ALU 단계의 끝에서 0/0이 아닌 계산을위한 추가 로직으로 인해 클럭이 느려질 수 있습니다 (또는 ALU가 두 번의주기 작업을하게 할 수 있음). SPARC와 같은 아키텍처에는 각 산술 연산의 두 가지 버전이 있습니다. 하나는 플래그를 설정하고 다른 하나는 설정하지 않았습니다.
그러나 MIPS는 여기에 아무것도 저장하지 않습니다. 그들은 문제를 다른 곳으로 옮겼습니다. MIPS에는 branch-on-equal
지침이 있습니다. 이것은 분기 명령이 실제로 분기가 진행되는 방식을 결정하기 전에 실제로 ALU 단계 (비트 단위 xor
연산 과 같은 것을 포함 nor
하여 단일 동등 / 비 동일 비트로 축소하기 포함)를 가져야 함을 의미합니다 .
DEC Alpha 아키텍처는 트릭을 사용하여 차이를 나누려고했습니다. DEC Alpha에는 플래그 레지스터가 없었지만 branch-on-equal
명령 도 없었습니다 . 대신 분기 명령어는 모두 단일 범용 레지스터의 상태를 확인합니다. 거기에 branch-on-zero
, branch-on-not-zero
, branch-on-less-than-zero
, 등 그 트릭은 당신이 다른 64 비트가 모두 0인지 아닌지 모든 일반적인 목적을 설명 추가 65 비트를 등록 줄 수 있다는 것입니다. 이것은 플래그 레지스터를 갖는 것과 비슷합니다. 모든 분기 명령은 단일 비트 (이미 계산 된)를보고 결정을 내리지 만 이제는 정상적인 ALU 동안 여분의 0 인디케이터 비트를 계산하는 방법을 알아 냈습니다. 주기. (이전 작업에서 캐리 플래그를 보는 것만으로도 정밀 정밀도 산술을 수행 할 수 없습니다.)
플래그 만 설정하는 테스트 명령이있는 것은 레지스터가 부족한 아키텍처에서 레지스터 압력을 줄이는 방법입니다. 레지스터가 충분하면 그 중 하나를 수정하고 결과를 무시하십시오. 입력 값이 0 인 레지스터 0을 갖는 트릭은 레지스터 수를 늘리는 것이 명령 수를 늘리는 것보다 레지스터가 충분할 때 편리한 인코딩 트릭입니다. 그런 다음 대상으로 사용하는 것이 편리합니다 (잘못된 종속성의 수를 줄임).
다시 인코딩하십시오. 점프로 조건을 인코딩하면 피연산자 3 개 (비교할 2 개와 점프 목표)로 점프하며, 그 중 2 개는 즉시 값이되고 싶고 1 개는 큰 것입니다. 가능 (점프는 종종 대상이 가능한 한 많은 비트를 사용할 수 있도록 자체 인코딩 형식을 가짐). 아니면 가능성을 떨어 뜨립니다.
플래그를 사용하면 더 많은 기회를 설정할 수 있습니다. 플래그를 설정할 수있는 것은 단지 비교 연산이 아니라 원하는 것입니다. (플래그를 설정하는 작업이 많을수록 경고를 설정하면 플래그를 설정 한 마지막 작업이 원하는 작업인지 확인해야합니다.) 플래그가있는 경우 플래그 수를 설정할 수있는 명령어 수에 곱한 조건 수 (보통 16 개)를 테스트 할 수 있습니다 (플래그를 사용하지 않는 경우, 조건부 점프 수만큼) 테스트 할 것이 있거나 쉽게 테스트 할 수없는 것들이 있습니다 (예 : 운반 또는 오버플로).
테스트 플래그는 쉽고 빠르게 수행 할 수 있습니다. 테스트가 복잡할수록 사이클 시간 (또는 파이프 라인 인 경우 파이프 라인 구조)에 더 많은 영향을 미칩니다. 그것은 더 간단한 구현에 특히 해당됩니다. 책의 모든 트릭을 사용하여 고급 프로세서에 도달하면 그 효과는 거의 없습니다.
플래그가 있다는 것은 많은 명령어가 여러 결과 (자연적인 결과 및 수정 된 플래그 각각)를 가짐을 의미합니다. 그리고 마이크로 아키텍처 POV에서 여러 결과가 나쁩니다 (연결을 추적해야 함). 하나의 플래그 세트 만있는 경우 종속성을 도입하면 (플래그를 사용하지 않는 경우 필요하지 않음) 다른 방식으로 처리해야합니다. 이 책의 모든 트릭을 사용하여 고급 프로세서를 사용하면 나머지 프로세서가 추가 어려움을 겪을 수 있습니다.
32 비트 시스템에서 다중 정밀도 덧셈 시퀀스의 일부로 사용되는 "반입 추가"명령어는 65 비트의 피연산자를 수용하고 33 비트 합계를 계산해야합니다. 소스 레지스터 스펙은 64 개의 피연산자 비트가 어디에서 왔는지, 목적지 레지스터 스펙은 결과의 하위 32 비트가 어디로 가야하는지 알려줄 것입니다. 결과의? 여분의 피연산자가 와야하는 곳과 여분의 결과 비트가가는 곳을 지시의 일부로 지정할 수 있으면 적당히 유용하지만 일반적으로 opcode에서 여분의 필드를 정당화하는 것만 큼 유용하지는 않습니다. 캐리 플래그를 처리 할 고정 된 "위치"를 갖는 것은 명령 스케줄링 관점에서 약간 어색 할 수 있지만
다중 정밀도 산술을 허용하도록 명령어 세트를 설계하려고했지만 각 명령어가 2 개의 32 비트 피연산자와 1 개의 32 비트 대상 피연산자로 제한된 경우 4 개의 명령어에서 64 비트 "add"를 구현할 수 있습니다. "set r0 + r2가 수행하지 않으면 r5 ~ 1, 그렇지 않으면 0; r4 = r1 + r3 계산; r5 = r4 + r5 계산; r4 = r0 + r2 계산 "을 초과하지만 각 추가 단어에 대해 세 개의 명령이 필요합니다. 보충 소스 및 대상으로 캐리 플래그를 사용할 수 있으면 단어 당 하나의 명령으로 비용이 절감됩니다.
플래그 비트를 사용 또는 수정하는 명령은 서로에 대해 시퀀스를 유지해야하지만, 명령 비트가 명령 레지스터를 업데이트하는지의 여부를 명령 비트를 갖는 것은 명령이 비 순차적 실행을 용이하게 할 수 있다는 것에 유의해야한다. 자유롭게 재 배열하십시오. 주어진 순서 :
ldr r0,[r1]
add r0,r0,r2
eors r4,r5,r6
실행 장치는 데이터를 읽을 때까지 기다릴 필요없이 세 번째 명령이 실행될 수 있다는 것을 쉽게 알 수 [r1]
있지만, 두 번째 명령이 adds r0,r0,r2
있었다면 실행 장치가 시간이 지남에 따라 사용하려고 시도한 경우에만 가능할 것입니다 플래그, 제로 플래그는 세 번째 명령에서 설정된 값을 보유하지만 캐리 플래그는 두 번째 명령에서 값을 보유합니다.
간단한 대답 ... 명령 자체를 제외하고 내부 버스 사용이 전혀 필요없는 빠르고 저렴한 메모리 작동. 메모리가없는 스택이나 프로세스 비트가없는 스택 부울로 사용할 수 있습니다.