Jawaban @ jalf mencakup sebagian besar alasan, tetapi ada satu detail menarik yang tidak disebutkan: Inti seperti RISC internal tidak dirancang untuk menjalankan set instruksi seperti ARM / PPC / MIPS. Pajak x86 tidak hanya dibayarkan pada decoder yang haus daya, tetapi juga di seluruh inti. yaitu bukan hanya pengkodean instruksi x86; itu setiap instruksi dengan semantik aneh.
Anggaplah Intel membuat mode operasi dengan aliran instruksi selain x86, dengan instruksi yang dipetakan lebih langsung ke uops. Mari kita juga menganggap bahwa setiap model CPU memiliki ISA sendiri untuk mode ini, jadi mereka masih bebas untuk mengubah internal ketika mereka suka, dan mengeksposnya dengan jumlah transistor minimal untuk instruksi-dekode format alternatif ini.
Agaknya Anda masih hanya memiliki jumlah register yang sama, dipetakan ke status arsitektur x86, sehingga x86 OS dapat menyimpan / memulihkannya pada sakelar konteks tanpa menggunakan set instruksi khusus CPU. Tetapi jika kita membuang batasan praktis itu, ya kita dapat memiliki beberapa register lagi karena kita dapat menggunakan register temp tersembunyi yang biasanya disediakan untuk microcode 1 .
Jika kita hanya memiliki dekoder alternatif tanpa perubahan ke tahap pipeline selanjutnya (unit eksekusi), ISA ini masih memiliki banyak eksentrisitas x86. Ini bukan arsitektur RISC yang bagus. Tidak ada instruksi tunggal yang akan menjadi sangat kompleks, tetapi beberapa kegilaan x86 lainnya akan tetap ada.
Misalnya: pergeseran kiri / kanan membiarkan bendera Overflow tidak ditentukan, kecuali hitungan shift adalah satu, dalam hal ini OF = deteksi luapan bertanda biasa. Kegilaan serupa untuk rotasi. Namun, instruksi RISC yang terekspos dapat memberikan pergeseran tanpa flag dan seterusnya (mengizinkan penggunaan hanya satu atau dua dari beberapa uops yang biasanya masuk ke beberapa instruksi x86 yang kompleks). Jadi ini tidak benar-benar berlaku sebagai argumen tandingan utama.
Jika Anda akan membuat decoder yang benar-benar baru untuk ISA RISC, Anda dapat memilihnya dan memilih bagian dari instruksi x86 untuk diekspos sebagai instruksi RISC. Ini agak mengurangi spesialisasi x86 dari inti.
Pengkodean instruksi mungkin tidak berukuran tetap, karena uops tunggal dapat menampung banyak data. Lebih banyak data daripada yang masuk akal jika semua insns berukuran sama. UOP mikro-fusi tunggal dapat menambahkan 32bit segera dan operan memori yang menggunakan mode pengalamatan dengan 2 register dan perpindahan 32bit. (Di SnB dan yang lebih baru, hanya mode pengalamatan register tunggal yang dapat melakukan sekering mikro dengan operasi ALU).
uops sangat besar, dan tidak terlalu mirip dengan instruksi ARM dengan lebar tetap. Set instruksi 32-bit dengan lebar tetap hanya dapat memuat 16-bit segera pada satu waktu, jadi memuat alamat 32-bit membutuhkan pasangan beban-langsung-rendah-setengah /-tinggi-langsung. x86 tidak harus melakukan itu, yang membantunya tidak menjadi buruk dengan hanya 15 register GP yang membatasi kemampuan untuk menyimpan konstanta di register. (15 adalah bantuan besar dari 7 register, tetapi menggandakan lagi menjadi 31 membantu jauh lebih sedikit, saya pikir beberapa simulasi ditemukan. RSP biasanya bukan tujuan umum, jadi lebih seperti 15 register GP dan tumpukan.)
Ringkasan TL; DR:
Bagaimanapun, jawaban ini bermuara pada "set instruksi x86 mungkin adalah cara terbaik untuk memprogram CPU yang harus dapat menjalankan instruksi x86 dengan cepat", tetapi mudah-mudahan dapat menjelaskan alasannya.
Format uop internal di front-end vs. back-end
Lihat juga mode fusi mikro dan pengalamatan untuk satu kasus perbedaan dalam apa yang dapat diwakili oleh format uop front-end vs. back-end pada CPU Intel.
Catatan kaki 1 : Ada beberapa register "tersembunyi" untuk digunakan sebagai sementara oleh microcode. Register ini diganti namanya seperti register arsitektural x86, sehingga instruksi multi-uop dapat dieksekusi out-of-order.
misalnya xchg eax, ecx
pada CPU Intel mendekode sebagai 3 uops ( mengapa? ), dan tebakan terbaik kami adalah bahwa ini adalah uops mirip MOV yang melakukannya tmp = eax; ecx=eax ; eax=tmp;
. Dalam urutan itu, karena saya mengukur latensi dari arah dst-> src pada ~ 1 siklus, vs. 2 untuk sebaliknya. Dan gerakan ini tidak seperti mov
instruksi biasa ; mereka tampaknya bukan calon eliminasi perpindahan latensi-nol.
Lihat juga http://blog.stuffedcow.net/2013/05/measuring-rob-capacity/ untuk penyebutan mencoba mengukur ukuran PRF secara eksperimental, dan harus memperhitungkan register fisik yang digunakan untuk menyimpan status arsitektural, termasuk register tersembunyi.
Di front-end setelah decoder, tetapi sebelum masalah / rename stage yang mengganti nama register ke file register fisik, format uop internal menggunakan nomor register yang mirip dengan nomor reg x86, tetapi dengan ruang untuk mengatasi register tersembunyi ini.
Format uop agak berbeda di dalam inti out-of-order (ROB dan RS), alias back-end (setelah tahap penerbitan / ganti nama). File register fisik int / FP masing-masing memiliki 168 entri di Haswell , jadi setiap bidang register dalam uop harus cukup lebar untuk menangani sebanyak itu.
Karena penggantian nama ada di HW, kami mungkin lebih baik menggunakannya, daripada memasukkan instruksi yang dijadwalkan secara statis langsung ke back-end. Jadi kita akan mulai bekerja dengan satu set register sebesar register arsitektur x86 + temporaries microcode, tidak lebih dari itu.
Bagian belakang dirancang untuk bekerja dengan pengubah nama bagian depan yang menghindari bahaya WAW / WAR, jadi kami tidak dapat menggunakannya seperti CPU dalam urutan meskipun kami menginginkannya. Itu tidak memiliki interlock untuk mendeteksi dependensi tersebut; yang ditangani oleh masalah / ganti nama.
Mungkin rapi jika kita dapat memasukkan uops ke back-end tanpa hambatan pada tahap masalah / ganti nama (titik tersempit dalam pipeline Intel modern, misalnya 4-lebar pada Skylake vs. 4 ALU + 2 beban + 1 port penyimpanan di bagian belakang). Tetapi jika Anda melakukan itu, saya rasa Anda tidak dapat menjadwalkan kode secara statis untuk menghindari penggunaan kembali register dan menginjak hasil yang masih diperlukan jika cache-miss menghentikan pemuatan untuk waktu yang lama.
Jadi kita cukup banyak memberi makan uops ke tahap masalah / ganti nama, mungkin hanya melewati decode, bukan cache uop atau IDQ. Kemudian kita mendapatkan OoO exec normal dengan deteksi bahaya yang waras. Tabel alokasi register hanya dirancang untuk mengganti nama 16 + beberapa register integer ke PRF integer 168-entri. Kami tidak dapat mengharapkan HW untuk mengganti nama set register logis yang lebih besar ke jumlah register fisik yang sama; itu akan membutuhkan RAT yang lebih besar.