왜 CPU 아키텍처가 플래그 레지스터 (이점)를 사용합니까?


15

일부 CPU에는 플래그 레지스터 (ARM, x86, ...)가 있고 다른 CPU에는 없습니다 (MIPS, ...). 부호, 오버플로 등을 검사하기 위해 제로 레지스터와 조건 분기를 사용하는 대신 플래그 레지스터 다음에 분기 명령어를 업데이트하는 CMP 명령어를 사용하면 어떤 이점이 있습니까?

답변:


11

레지스터 이름을 바꾸는 레지스터를 사용하는 최신 마이크로 아키텍처에서 플래그 구현 비용은 거의 비슷합니다. 내가 생각할 수있는 주요 차이점은 일부 플래그는 값의 특성을 나타냅니다 (값이 음수입니까? 값이 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 인디케이터 비트를 계산하는 방법을 알아 냈습니다. 주기. (이전 작업에서 캐리 플래그를 보는 것만으로도 정밀 정밀도 산술을 수행 할 수 없습니다.)


2
비 CC 설정 작업은 컴파일러 최적화 였습니다 ( 컴파일러 최적화 ). 컴파일러 는 후자의 명령에 의해 값을 방해하지 않고 컴파일러가 CC 설정 명령을 조기에 예약 할 수 있습니다. PowerPC750은 조건 레지스터 (8 4 비트 레지스터)를 프론트 엔드 근처에 배치하여 분기 된 분기가 분기 대상 명령 캐시에 도달하고 가능한 조기에 조건을 갖도록하여 가져온 분기를 페널티없이 해결할 수 있도록했습니다. (AT & T의 CRISP는 또한 초기 지점 해결을 활용했습니다.) CC의 소량 및 전문화는이를보다 실용적으로 만듭니다.
Paul A. Clayton 3

세부 사항 : 모든 플래그 계산이 동일하지 않습니다. CPU에 전통적인 NZVC 플래그가 있다고 가정하십시오. 모든 ALU 명령어가 플래그를 업데이트 할 수있는 경우, 가산기 / 감산기와 몇 개의 먹스 뒤에 플래그 생성을 배치해야합니다. 네거티브 플래그는 쉬우 며 MSB에 불과하지만 Zero 플래그는 비싸고 모든 비트에 따라 다릅니다. 이제 플래그를 비교 (및 비트 테스트) 명령어로 제한하면 빼기 결과를 기다리지 않고 소스 피연산자의 병렬 XOR을 사용하여 Zero 플래그를 계산할 수 있습니다. 추가 후 Z 플래그를 계산하는 것은 거의 쓸모가 없습니다.
TEMLIB

7

1 ISA 관점에서

  1. 플래그 만 설정하는 테스트 명령이있는 것은 레지스터가 부족한 아키텍처에서 레지스터 압력을 줄이는 방법입니다. 레지스터가 충분하면 그 중 하나를 수정하고 결과를 무시하십시오. 입력 값이 0 인 레지스터 0을 갖는 트릭은 레지스터 수를 늘리는 것이 명령 수를 늘리는 것보다 레지스터가 충분할 때 편리한 인코딩 트릭입니다. 그런 다음 대상으로 사용하는 것이 편리합니다 (잘못된 종속성의 수를 줄임).

  2. 다시 인코딩하십시오. 점프로 조건을 인코딩하면 피연산자 3 개 (비교할 2 개와 점프 목표)로 점프하며, 그 중 2 개는 즉시 값이되고 싶고 1 개는 큰 것입니다. 가능 (점프는 종종 대상이 가능한 한 많은 비트를 사용할 수 있도록 자체 인코딩 형식을 가짐). 아니면 가능성을 떨어 뜨립니다.

  3. 플래그를 사용하면 더 많은 기회를 설정할 수 있습니다. 플래그를 설정할 수있는 것은 단지 비교 연산이 아니라 원하는 것입니다. (플래그를 설정하는 작업이 많을수록 경고를 설정하면 플래그를 설정 한 마지막 작업이 원하는 작업인지 확인해야합니다.) 플래그가있는 경우 플래그 수를 설정할 수있는 명령어 수에 곱한 조건 수 (보통 16 개)를 테스트 할 수 있습니다 (플래그를 사용하지 않는 경우, 조건부 점프 수만큼) 테스트 할 것이 있거나 쉽게 테스트 할 수없는 것들이 있습니다 (예 : 운반 또는 오버플로).

2 구현 자 관점에서

  1. 테스트 플래그는 쉽고 빠르게 수행 할 수 있습니다. 테스트가 복잡할수록 사이클 시간 (또는 파이프 라인 인 경우 파이프 라인 구조)에 더 많은 영향을 미칩니다. 그것은 더 간단한 구현에 특히 해당됩니다. 책의 모든 트릭을 사용하여 고급 프로세서에 도달하면 그 효과는 거의 없습니다.

  2. 플래그가 있다는 것은 많은 명령어가 여러 결과 (자연적인 결과 및 수정 된 플래그 각각)를 가짐을 의미합니다. 그리고 마이크로 아키텍처 POV에서 여러 결과가 나쁩니다 (연결을 추적해야 함). 하나의 플래그 세트 만있는 경우 종속성을 도입하면 (플래그를 사용하지 않는 경우 필요하지 않음) 다른 방식으로 처리해야합니다. 이 책의 모든 트릭을 사용하여 고급 프로세서를 사용하면 나머지 프로세서가 추가 어려움을 겪을 수 있습니다.


2

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있었다면 실행 장치가 시간이 지남에 따라 사용하려고 시도한 경우에만 가능할 것입니다 플래그, 제로 플래그는 세 번째 명령에서 설정된 값을 보유하지만 캐리 플래그는 두 번째 명령에서 값을 보유합니다.


1
"명령어가 명령이 플래그 레지스터를 업데이트하는지 여부를 제어하는 ​​비트": 예를 들어 PowerPC, SPARC에서 사용 가능합니다.
TEMLIB

MIPS는 "r5 = r1 + r2; r6이 r1보다 작 으면 r6 설정; r7 = r3 + r4; r5 = R5 + R6;"을 사용합니다. 일부 SIMD 확장은 캐리를 적용하기 위해 캐리와 뺄셈을 찾기 위해 모든 비트를 0 또는 1로 설정하는 비교 (예를 들어, 0 또는 -1 2는 정수를 보완하는 정수)를 사용할 수 있습니다.
Paul A. Clayton

@ PaulA.Clayton : "r5가 r1보다 작은 경우"를 의미한다고 생각합니다. MIPS는 더 긴 수학을 어떻게 처리할까요? 단어 당 3 개, 3 개 또는 3 개 미만의 명령이 필요합니까?
supercat

@supercat 네, "r5가 r1보다 작 으면 r6으로 설정되었습니다"!
Paul A. Clayton

@ PaulA.Clayton : 32 비트 MIPS에 두 개의 64 워드 (2048 비트) 숫자를 추가하는 방법은 무엇입니까? 중간 단계에서 운반을 처리하는 효율적인 방법이 있습니까?
supercat

0

간단한 대답 ... 명령 자체를 제외하고 내부 버스 사용이 전혀 필요없는 빠르고 저렴한 메모리 작동. 메모리가없는 스택이나 프로세스 비트가없는 스택 부울로 사용할 수 있습니다.


1
이 답변은 다소 가볍습니다. 긴 답변이 반드시 필요한 것은 아니지만 좀 더 다듬어 진 것이 뚜렷한 개선이 될 것입니다.
David Richerby

플래그를 설정하거나 플래그 값을 비교하는 것은 어셈블리 코드에 포함될 인수 형식의 다른 정보가없는 단일 명령입니다. 플래그는 또한 uprocessor 작동 또는 테스트의 결과이며 효율적으로 분기 할 수 있습니다. 레지스터에서 두 값을 비교할 때 토글되거나 설정되는 실제 비트입니다.
SkipBerne
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.