명령어: LD F0, 0(R2)
진짜 의미: "R2에 있는 값과 0을 더해서 메모리 주소(Address)를 구한 다음, 그 주소의 메모리(RAM)로 직접 찾아가서, 그 안에 들어있는 '데이터'를 꺼내와서 F0 방에 넣어라!"
즉, LD 명령어는 두 번의 작업을 거쳐야 합니다.
EX stage: R2 + 0을 계산해서 "어느 메모리 주소로 갈지" 타겟 주소를 찾습니다. (이때까진 데이터가 없습니다. 주소만 안 겁니다!)
MEM stage: 계산된 주소를 들고 진짜 데이터 메모리(D-Cache/RAM)에 접근(Access)해서, 그 안에 들어있는 데이터를 쏙 뽑아옵니다.
결론: MEM stage가 끝나야만 비로소 쓸 수 있는 진짜 '데이터'가 튀어나옵니다! 그래서 뒤따라오는 MULD가 데이터를 넘겨받으려면(Forwarding) 무조건 MEM이 끝날 때까지 기다려야 하는 겁니다.
명령어: SD F0, 0(R2) (Store Double-precision)
진짜 의미: "R2에 있는 값과 0을 더해서 메모리 주소를 구한 다음, 이미 F0 방에 예쁘게 들어있는 '데이터'를 그 메모리 주소에 갖다 버려라(저장해라)!"
결정적 차이: Store는 데이터를 '쓰는(Write)' 명령어입니다. 레지스터(F0)가 목적지가 아니라, 메모리(RAM)가 목적지입니다.
따라서 Store는 자기가 쓴 값을 남한테 줘서 해저드를 일으키는 일이 거의 없습니다. (오히려 남이 계산해 줄 데이터를 기다렸다가 메모리에 예쁘게 묻어버리고 끝나는 조연 역할입니다.)
Store 명령어는 뒤따라오는 다른 명령어에게 데이터를 포워딩(Forwarding) 해주는 일 자체가 아예 성립하지 않습니다!
보이시나요? Store는 레지스터에 새로운 값을 쓰는(Write) 명령어가 아닙니다. 레지스터에 있던 값을 메모리라는 거대한 창고에 갖다 버리고(저장하고) 끝나는 명령어입니다.
자기가 새롭게 업데이트하는 Destination Register가 아예 없기 때문에, 뒤따라오는 명령어에게 "야, 내가 방금 쓴 최신값 받아!" 하고 던져줄 데이터 자체가 존재하지 않는 겁니다.
D에서 어디로 뛸지 주소가 결정나고
X에서 뛸지 안뛸지 여부가 결정이난다.
이걸 바탕으로 flush, taken, not taken이 생기는 것
taken 은 D 다음 에서 바로 다음 거 실행, 어차피 뛸거라 예상해서 X안기다려도 됨

그런데 안뛰면(예측실패) -> 버림

not taken 은 원래 파이프라인대로, F 다음, 다음거 실행, 왜? 어차피 안뛰니까 그냥 순차대로 진행.

그런데 뛰면(예측 실패) -> 버림

flush 는 X 결과 나올때 까지 그냥 스톨해 버리자 이거임
