Bu eğitimin hedefleri şunlardır:
- İkili program biçimi açıklama dosyasının yapısını ve söz dizimini öğrenin.
- İkili program biçimi açıklamasının ISA açıklamasıyla nasıl eşleştiğini öğrenin.
- RiscV RV32I talimat alt kümesi için ikili açıklamaları yazın.
Genel Bakış
RiscV ikili talimatı kodlaması
İkili talimat kodlaması, görevlerdeki talimatları kodlamanın standart yoludur. çalıştırmayı öğreteceğim. Bu dosyalar, normalde yürütülebilir bir dosyada biçiminde girin. Talimatlar sabit genişlikli veya değişken olabilir dokunun.
Talimatlarda genellikle her biçimi içeren küçük bir kodlama biçimi kullanılır. kodlanan talimatların türü için özelleştirilmiş olması gerekir. Örneğin, register-register talimatlarda, kullanılabilir işlem kodu sayısını en üst düzeye çıkaran bir biçim kullanılabilir. hemen kayıt talimatlarında ise bir işlem yapmadan önce kodlanabilir anlık öğenin boyutunu artırmak için kullanılabilir. Dal ve atlama talimatlarında hemen hemen her zaman dalları desteklemek için hızlı bir şekilde bulmalıdır.
RiscV'mizde kodunu çözmek istediğimiz talimatlar tarafından kullanılan talimat biçimleri şunlardır:
Kayıt talimatları için kullanılan R-Type biçimi:
| 31..25 | 24...20 | 19...15 | 14..12 | 11..7 | 6..0 |
|---|---|---|---|---|---|
| 7 | 5 | 5 | 3 | 5 | 7 |
| func7 | rs2 | rs1 | func3 | . | işlem kodu |
Anında kayıt talimatları, yükleme talimatları ve yükleme talimatları için kullanılan I-Type biçimi
jalr talimatı, 12 bit anında.
| 31...20 | 19...15 | 14..12 | 11..7 | 6..0 |
|---|---|---|---|---|
| 12 | 5 | 3 | 5 | 7 |
| imm12 | rs1 | func3 | . | işlem kodu |
Hızlı talimatlarla kaydırma için kullanılan, 5 bit'lik özel I-Type biçimi anında:
| 31..25 | 24...20 | 19...15 | 14..12 | 11..7 | 6..0 |
|---|---|---|---|---|---|
| 7 | 5 | 5 | 3 | 5 | 7 |
| func7 | uimm5 | rs1 | func3 | . | işlem kodu |
Hızlı ve anında talimatlar için kullanılan U Türü biçimi (lui, auipc), 20 bit
anında:
| 31...12 | 11..7 | 6..0 |
|---|---|---|
| 20 | 5 | 7 |
| uimm20 | . | işlem kodu |
Koşullu dallar için kullanılan, 12 bit anında kullanılan B Türü biçimi.
| 31 | 30..25 | 24...20 | 19...15 | 14..12 | 11..8 | 7 | 6..0 |
|---|---|---|---|---|---|---|---|
| 1 | 6 | 5 | 5 | 3 | 4 | 1 | 7 |
| imm | imm | rs2 | rs1 | func3 | imm | imm | işlem kodu |
jal talimatı için kullanılan J Türü biçimi, 20 bit anında.
| 31 | 30...21 | 20 | 19...12 | 11..7 | 6..0 |
|---|---|---|---|---|---|
| 1 | 10 | 1 | 8 | 5 | 7 |
| imm | imm | imm | imm | . | işlem kodu |
Mağaza talimatları için kullanılan, 12 bit anında kullanılan S-Type biçimi.
| 31..25 | 24...20 | 19...15 | 14..12 | 11..7 | 6..0 |
|---|---|---|---|---|---|
| 7 | 5 | 5 | 3 | 5 | 7 |
| imm | rs2 | rs1 | func3 | imm | işlem kodu |
Bu biçimlerden görebileceğiniz gibi, tüm bu talimatlar 32 bit uzunluğunda ve her biçimdeki küçük 7 bit ise işlem kodu alanıdır. Ayrıca, birçok biçim aynı boyuta sahip olsa da bitleri kaynak bazı bölümleri kapsıyor. Göreceğimiz gibi, ikili kod çözücü bunu ifade edebiliyor.
İkili kodlama açıklaması
Talimatın ikili kodlaması, ikili biçimde ifade edilir.
(.bin_fmt) açıklama dosyasına kaydedin. Bu şema,
talimatlarının tutarlı bir şekilde çalıştırılabilmesini sağlar. Böylece,
elde edilir. Oluşturulan kod çözücü, işlem kodunu belirler,
işlem gören ve anında görüntülenen alanlara (ISA'nın ihtiyaç duyduğu bilgileri sağlamak için)
önceki eğiticide açıklandığı gibi kodlamadan bağımsız kod çözücüye uygundur.
Bu eğiticide, bir alt küme için bir ikili kodlama açıklama dosyası yazacağız RiscV32I talimatlarının büyük bir kısmı, küçük "Hello World" çok önemli. RiscV ISA hakkında daha fazla bilgi için bkz. Risc-V Teknik Özellikleri{.external}.
İlk olarak dosyayı açın:
riscv_bin_decoder/riscv32i.bin_fmt
Dosya içeriği birkaç bölüme ayrılmıştır.
Birincisi, decoder tanımıdır.
decoder RiscV32I {
// The namespace in which code will be generated.
namespace mpact::sim::codelab;
// The name (including any namespace qualifiers) of the opcode enum type.
opcode_enum = "OpcodeEnum";
// Include files specific to this decoder.
includes {
#include "riscv_isa_decoder/solution/riscv32i_decoder.h"
}
// Instruction groups for which to generate decode functions.
RiscVInst32;
};
Kod çözücü tanımımız, RiscV32I kod çözücüümüzün adını ve
ek iş çıkarmanızı sağlar. Bunlardan ilki, namespace
oluşturulan kodun yerleştirileceği ad alanıdır. İkinci olarak,
opcode_enum, işlem kodu numaralandırma türünün nasıl oluşturulduğunu belirtir.
oluşturulan kodda ISA kod çözücüsünün referans noktası bulunmalıdır. Üçüncüsü,
includes {}, şunlar için oluşturulan kod için gerekli dosyaları içereceğini belirtir:
kod çözücüyüm.
Örneğimizde bu, ISA kod çözücü tarafından
önceki eğiticide bulabilirsiniz.
Genel kapsamlı bir includes {} içinde ek dahil etme dosyaları belirtilebilir
belirler. Bu, birden fazla kod çözücü tanımlanmışsa ve bunların hepsinin
eklemeniz gerekebilir. Dördüncüsünde ise
kod çözücünün oluşturulduğu talimatları oluşturan gruplar. Şurada:
yalnızca bir tane vardır: RiscVInst32.
Ardından üç biçim tanımı vardır. Bunlar farklı talimatları önceden tanımlanmış talimatlar tarafından kullanılan 32 bitlik talimat kelimesinin biçimleri dosyadır.
// The generic RiscV 32 bit instruction format.
format Inst32Format[32] {
fields:
unsigned bits[25];
unsigned opcode[7];
};
// RiscV 32 bit instruction format used by a number of instructions
// needing a 12 bit immediate, including CSR instructions.
format IType[32] : Inst32Format {
fields:
signed imm12[12];
unsigned rs1[5];
unsigned func3[3];
unsigned rd[5];
unsigned opcode[7];
};
// RiscV instruction format used by fence instructions.
format Fence[32] : Inst32Format {
fields:
unsigned fm[4];
unsigned pred[4];
unsigned succ[4];
unsigned rs1[5];
unsigned func3[3];
unsigned rd[5];
unsigned opcode[7];
};
İlki, 32 bit genişliğinde ve 32 bit genişliğe sahip Inst32Format adlı,
iki alan: bits (25 bit genişliğinde) ve opcode (7 bit genişliğinde). Her alan
unsigned: Çıkarıldığında değer sıfır olarak genişletilir
ve C++ tam sayı türüne yerleştirilir. Bit alanlarının genişliklerinin toplamı,
biçimin genişliğine eşittir. Bir hata varsa araç
düşünülebilir. Bu biçim başka herhangi bir biçimden türetilmediği için
üst düzey bir biçim olarak değerlendirilir.
İkincisi ise IType adında, 32 bit genişliğinde bir talimat biçimi tanımlar ve
Bu iki biçimi alakalı hale getiriyor.Inst32Format Biçim 5 değerini içerir
alanlar: imm12, rs1, func3, rd ve opcode. imm12 alanı
signed (Bu, değer şu olduğunda değerin işaretleneceği anlamına gelir:
çıkarılıp C++ tam sayı türüne yerleştirilir. Her ikisinde de IType.opcode
aynı imzalı/imzasız özelliğe sahiptir ve aynı talimat kelime bitlerine işaret eder
Inst32Format.opcode olarak.
Üçüncü biçim, yalnızca fence tarafından kullanılan özel bir biçimdir.
Bu, halihazırda belirtilmiş bir talimattır ve elimizde henüz
bazı önemli hususlara değineceğiz.
Önemli nokta: Geçerli olduğu sürece, alan adlarını farklı ilgili biçimlerde yeniden kullanın aynı bitleri temsil eder ve aynı imzalı/imzasız özelliğe sahiptir.
riscv32i.bin_fmt içindeki biçim tanımlarından sonra bir talimat grubu gelir
belirler. Bir talimat grubundaki tüm talimatlar aynı olmalıdır
bit uzunluğunda olmalıdır ve aynı öğeden (dolaylı olarak) türetilen bir biçim
üst düzey talimat formatıdır. ISA, ne zaman farklı
her uzunluk için farklı bir talimat grubu kullanılır. Ayrıca,
Hedef ISA kodu çözme işlemi, Kol ve Küçük Resim gibi bir yürütme moduna bağlıysa
her mod için ayrı bir talimat grubu gerekir. İlgili içeriği oluşturmak için kullanılan
bin_fmt ayrıştırıcısı, her bir talimat grubu için bir ikili kod çözücü oluşturur.
instruction group RiscV32I[32] "OpcodeEnum" : Inst32Format {
fence : Fence : func3 == 0b000, opcode == 0b000'1111;
csrs : IType : func3 == 0b010, rs1 != 0, opcode == 0b111'0011;
csrw_nr : IType : func3 == 0b001, rd == 0, opcode == 0b111'0011;
csrs_nw : IType : func3 == 0b010, rs1 == 0, opcode == 0b111'0011;
};
Talimat grubu, RiscV32I adını, genişlik [32],
"OpcodeEnum" kullanılacak işlem kodu numaralandırma türü ve bir temel talimat
biçimindedir. opcode numaralandırma türü,
ISA konulu eğiticide ele alınan bağımsız talimat kod çözücü biçimi
kod çözücü.
Her talimat kodlama açıklaması 3 bölümden oluşur:
- Talimatta kullanılanla aynı olması gereken işlem kodu adı kod çözücü açıklaması verebilirsiniz.
- İşletim kodu için kullanılacak talimat biçimi. Bu biçim, son bölümdeki bit alanlarına yapılan referansları karşılamak için kullanılır.
- Bit alanı kısıtlamalarının virgülle ayrılmış listesi,
==,!=,<,<=,>, işlem kodunun başarılı bir şekilde eşleşmesi için tümünün doğru olması gereken>=talimat kelimesi.
.bin_fmt ayrıştırıcısı, tüm bu bilgileri kullanarak aşağıdaki özelliklere sahip bir kod çözücü oluşturur:
- Her bit için uygun olan ayıklama işlevlerini (imzalı/imzasız) sağlar
her biçimde olması gerekir. Ayıklayıcı işlevleri ad alanlarına yerleştirilir.
biçim adının yılan şeklinde büyük harf içeren sürümüne göre adlandırılmıştır. Örneğin,
ITypebiçimine ait ayıklayıcı işlevlerii_typead alanına yerleştirilmiş. Her ayıklayıcı işleviinlineolarak tanımlanır ve en daruint_tdeğerini alır biçimin genişliğini barındıran ve en darint_tdeğerini döndüren tür (imzalanmış için), çıkarılan alanı barındıranuint_t(imzasız için) türü dokunun. Örneğin:
inline uint8_t ExtractOpcode(uint32_t value) {
return value & 0x7f;
}
- Her bir talimat grubu için bir kod çözme işlevi. Şu tür bir değer döndürür:
OpcodeEnumveuint_ttalimat grubu biçimindedir.
İlk derlemeyi gerçekleştir
Dizini riscv_bin_decoder olarak değiştirin ve projeyi
şu komutu kullanın:
$ cd riscv_bin_decoder
$ bazel build :all
Şimdi dizininizi depo köküyle değiştirin ve bir bakalım.
oluşturulan kaynaklarda
gösterilir. Bunun için, dizini
bazel-out/k8-fastbuild/bin/riscv_bin_decoder (x86 kullandığınız varsayılır)
ana makine - diğer ana makineler için k8-Fastbuild, başka bir dize olacaktır).
$ cd ..
$ cd bazel-out/k8-fastbuild/bin/riscv_bin_decoder
riscv32i_bin_decoder.hriscv32i_bin_decoder.cc
Oluşturulan başlık dosyası (.h)
riscv32i_bin_decoder.h uygulamasını açın. Dosyanın ilk bölümünde standart
ortak metin korumaları, dosyalar ve ad alanı beyanları içermelidir. Ardından
internal ad alanında şablonlu bir yardımcı işlev bulunuyor. Bu işlev
64 bit C++ sürümüne sığmayacak kadar uzun biçimlerden bit alanlarını ayıklamak için kullanılır
Tam sayı.
#ifndef RISCV32I_BIN_DECODER_H
#define RISCV32I_BIN_DECODER_H
#include <iostream>
#include <cstdint>
#include "third_party/absl/functional/any_invocable.h"
#include "learning/brain/research/mpact/sim/codelab/riscv_isa_decoder/solution/riscv32i_decoder.h"
namespace mpact {
namespace sim {
namespace codelab {
namespace internal {
template <typename T>
static inline T ExtractBits(const uint8_t *data, int data_size,
int bit_index, int width) {
if (width == 0) return 0;
int byte_pos = bit_index >> 3;
int end_byte = (bit_index + width - 1) >> 3;
int start_bit = bit_index & 0x7;
// If it is only from one byte, extract and return.
if (byte_pos == end_byte) {
uint8_t mask = 0xff >> start_bit;
return (mask & data[byte_pos]) >> (8 - start_bit - width);
}
// Extract from the first byte.
T val = 0;
val = data[byte_pos++] & 0xff >> start_bit;
int remainder = width - (8 - start_bit);
while (remainder >= 8) {
val = (val << 8) | data[byte_pos++];
remainder -= 8;
}
// Extract any remaining bits.
if (remainder > 0) {
val <<= remainder;
int shift = 8 - remainder;
uint8_t mask = 0b1111'1111 << shift;
val |= (data[byte_pos] & mask) >> shift;
}
return val;
}
} // namespace internal
İlk bölümün ardından, her biri için bir tane olmak üzere üç ad alanından oluşan bir grup bulunur.
riscv32i.bin_fmt dosyasındaki format beyandan:
namespace fence {
...
} // namespace fence
namespace i_type {
...
} // namespace i_type
namespace inst32_format {
...
} // namespace inst32_format
Bu ad alanlarının her birinde inline bit alanı ayıklama işlevi
her bit alanının tanımıdır. Buna ek olarak, temel biçim
alt biçimlerden çıkarma fonksiyonlarını kopyalar
1) alan adları yalnızca tek bir alan adında bulunuyor veya 2) alan adının
alan adları aynı tür alanına (imzalı/imzasız ve bit konumları) başvuruda bulunuyor
bulunabilir. Bu, aynı
bit değerleri (en üst düzey biçim ad alanındaki işlevler kullanılarak ayıklanır).
i_type ad alanındaki işlevler aşağıda gösterilmiştir:
namespace i_type {
inline uint8_t ExtractFunc3(uint32_t value) {
return (value >> 12) & 0x7;
}
inline int16_t ExtractImm12(uint32_t value) {
int16_t result = ( (value >> 20) & 0xfff) << 4;
result = result >> 4;
return result;
}
inline uint8_t ExtractOpcode(uint32_t value) {
return value & 0x7f;
}
inline uint8_t ExtractRd(uint32_t value) {
return (value >> 7) & 0x1f;
}
inline uint8_t ExtractRs1(uint32_t value) {
return (value >> 15) & 0x1f;
}
} // namespace i_type
Son olarak, talimat için kod çözücü işlevinin işlev bildirimi
RiscVInst32 grubu bildirildi. Belgenin değeri olarak 32 bit
talimat kelimesini ekler ve OpcodeEnum numaralandırma sınıfı üyesini döndürür
veya eşleşme yoksa OpcodeEnum::kNone yazın.
OpcodeEnum DecodeRiscVInst32(uint32_t inst_word);
Oluşturulan Kaynak Dosya (.cc)
Şimdi riscv32i_bin_decoder.cc uygulamasını açın. Dosyanın ilk bölümünde
#include ve ad alanı beyanları, ardından kod çözücü işlevi
beyanlar:
#include "riscv32i_bin_decoder.h"
namespace mpact {
namespace sim {
namespace codelab {
OpcodeEnum DecodeRiscVInst32None(uint32_t);
OpcodeEnum DecodeRiscVInst32_0(uint32_t inst_word);
OpcodeEnum DecodeRiscVInst32_0_3(uint32_t inst_word);
OpcodeEnum DecodeRiscVInst32_0_3c(uint32_t inst_word);
OpcodeEnum DecodeRiscVInst32_0_5c(uint32_t inst_word);
DecodeRiscVInst32None, boş kod çözme işlemleri (yani
OpcodeEnum::kNone sonucu döndürür. Diğer üç fonksiyon
kod çözücü oluşturuldu. Genel kod çözücü hiyerarşik bir şekilde çalışır. Bir grup
Talimattaki bit sayısı, büyük/küçük harfe duyarlı değil
üst düzey talimatlar veya talimat grupları içerir. Bitlerin
kesintisiz olmalıdır. Bit sayısı, bitmek üzere gösterilen arama tablosunun
ikinci düzey kod çözücü işlevleriyle doldurulur. Bu, daha sonra
bölümüne ekleyin:
absl::AnyInvocable<OpcodeEnum(uint32_t)> parse_group_RiscVInst32_0[kParseGroupRiscVInst32_0_Size] = {
&DecodeRiscVInst32None, &DecodeRiscVInst32None,
&DecodeRiscVInst32None, &DecodeRiscVInst32_0_3,
&DecodeRiscVInst32None, &DecodeRiscVInst32None,
...
&DecodeRiscVInst32None, &DecodeRiscVInst32None,
&DecodeRiscVInst32None, &DecodeRiscVInst32None,
&DecodeRiscVInst32_0_3c, &DecodeRiscVInst32None,
...
};
Son olarak, kod çözücü işlevleri tanımlanır:
OpcodeEnum DecodeRiscVInst32None(uint32_t) {
return OpcodeEnum::kNone;
}
OpcodeEnum DecodeRiscVInst32_0(uint32_t inst_word) {
if ((inst_word & 0x4003) != 0x3) return OpcodeEnum::kNone;
uint32_t index;
index = (inst_word >> 2) & 0x1f;
index |= (inst_word >> 7) & 0x60;
return parse_group_RiscVInst32_0[index](inst_word);
}
OpcodeEnum DecodeRiscVInst32_0_3(uint32_t inst_word) {
return OpcodeEnum::kFence;
}
OpcodeEnum DecodeRiscVInst32_0_3c(uint32_t inst_word) {
if ((inst_word & 0xf80) != 0x0) return OpcodeEnum::kNone;
return OpcodeEnum::kCsrwNr;
}
OpcodeEnum DecodeRiscVInst32_0_5c(uint32_t inst_word) {
uint32_t rs1_value = (inst_word >> 15) & 0x1f;
if (rs1_value != 0x0)
return OpcodeEnum::kCsrs;
if (rs1_value == 0x0)
return OpcodeEnum::kCsrsNw;
return OpcodeEnum::kNone;
}
OpcodeEnum DecodeRiscVInst32(uint32_t inst_word) {
OpcodeEnum opcode;
opcode = DecodeRiscVInst32_0(inst_word);
return opcode;
}
Bu örnekte, yalnızca 4 talimat tanımlanmışsa yalnızca bir tek bir kod çözme düzeyi ve çok seyrek bir arama tablosu bulunur. Talimatlar kod çözücünün yapısı değişir ve kod çözücü tablosu hiyerarşisi artabilir.
Kayıt-kayıt ALU talimatları ekleme
Şimdi riscv32i.bin_fmt dosyasına bazı yeni talimatlar eklemenin zamanı geldi. İlgili içeriği oluşturmak için kullanılan
ilk talimat grubu,
add, and vb. RiscV32'de bunların tümü R tipi ikili talimatını kullanır
biçim:
| 31..25 | 24...20 | 19...15 | 14..12 | 11..7 | 6..0 |
|---|---|---|---|---|---|
| 7 | 5 | 5 | 3 | 5 | 7 |
| func7 | rs2 | rs1 | func3 | . | işlem kodu |
Yapmamız gereken ilk şey biçimi eklemektir. Devam edin ve şunu açın:
riscv32i.bin_fmt favori düzenleyicinizde. Inst32Format uygulamasından hemen sonra
Inst32Format değişkeninden türetilen RType adlı bir biçim ekleyin. Tüm bit alanları
RType bölgesinde unsigned. Adları, bit genişliğini ve sırayı (soldan sağa) kullanın
aşağıdaki tablodan seçin. İpucuna ihtiyacınız olursa veya
tam çözüm
burayı tıklayın.
Ardından talimatları eklememiz gerekir. Talimatlar şunlardır:
add- tam sayı toplama.and- bit tabanlı ve.or- bit tabanlı veya.sll- sola kaydırma mantıksal.sltu- "Küçüktür" olarak ayarla, imzasız.sub: Tamsayı çıkarma işlemi.xor- bit tabanlı xor.
Kodlamaları şu şekildedir:
| 31..25 | 24...20 | 19...15 | 14..12 | 11..7 | 6..0 | işlem kodu adı |
|---|---|---|---|---|---|---|
| 000.000 | rs2 | rs1 | 000 | . | 011 0011 | add |
| 000.000 | rs2 | rs1 | 111 | . | 011 0011 | ve |
| 000.000 | rs2 | rs1 | 110 | . | 011 0011 | veya |
| 000.000 | rs2 | rs1 | 001 | . | 011 0011 | Sl |
| 000.000 | rs2 | rs1 | 011 | . | 011 0011 | Sltu |
| 010 0.000 | rs2 | rs1 | 000 | . | 011 0011 | yerine girdi |
| 000.000 | rs2 | rs1 | 100 | . | 011 0011 | Xor |
| func7 | func3 | işlem kodu |
Bu talimat tanımlarını
RiscVInst32 talimat grubu. İkili dizeler başında bir
0b öneki (onaltılık sayılar için 0x ile benzer). Ekibiniz ve sizin için
ikili basamaklı uzun dizeleri okurken tek tırnak işaretini de '
bir rakam ayırıcısıdır.
Bu talimat tanımlarının her biri üç kısıtlamaya sahip olacaktır.
func7, func3 ve opcode. sub hariç tümü için func7 kısıtlaması
şöyle olmalıdır:
func7 == 0b000'0000
func3 kısıtlaması, talimatların çoğunda değişiklik gösterir. add ve
sub:
func3 == 0b000
opcode kısıtlaması bu talimatların her biri için aynıdır:
opcode == 0b011'0011
Her satırı noktalı virgül ; ile sonlandırmayı unutmayın.
Bitmiş çözüm, burada bulabilirsiniz.
Şimdi projenizi önceki gibi derleyin ve oluşturulan
riscv32i_bin_decoder.cc dosyası yükleyin. Ek kod çözücü işlevlerinin
yeni talimatların işlenmesi için oluşturuldu. Çoğunlukla
Bunlar daha önce oluşturulan raporlara benzer ancak
add/sub kod çözme işlemi için kullanılan DecodeRiscVInst32_0_c:
OpcodeEnum DecodeRiscVInst32_0_c(uint32_t inst_word) {
static constexpr OpcodeEnum opcodes[2] = {
OpcodeEnum::kAdd,
OpcodeEnum::kSub,
};
if ((inst_word & 0xbe000000) != 0x0) return OpcodeEnum::kNone;
uint32_t index;
index = (inst_word >> 30) & 0x1;
return opcodes[index];
}
Bu fonksiyonda, oluşturulmuş statik bir kod çözme tablosu vardır ve bir arama değeri ayıklanır. Bu işlem, ikinci katmanında yer alabilir, ancak işlem kodu başka karşılaştırma yapılmadan doğrudan bir tabloda bakıldığında, bu satıra işlevini kullanın.
Anlık içeren ALU talimatları ekleme
Ekleyeceğimiz bir sonraki talimat grubu, kayıtlardan biri yerine anında değer katar. Bu üç grup talimatlar (bir sonraki alana göre): I-Type hızlı talimatları hemen 12 bit imzalı, özel I-Type hızlı talimatları ve U Türü için 20 bitlik imzasız bir anlık değer gösterilir. Biçimler aşağıda gösterilmiştir:
I-Type'ın anlık biçimi:
| 31...20 | 19...15 | 14..12 | 11..7 | 6..0 |
|---|---|---|---|---|
| 12 | 5 | 3 | 5 | 7 |
| imm12 | rs1 | func3 | . | işlem kodu |
Özel I-Type hızlı biçimi:
| 31..25 | 24...20 | 19...15 | 14..12 | 11..7 | 6..0 |
|---|---|---|---|---|---|
| 7 | 5 | 5 | 3 | 5 | 7 |
| func7 | uimm5 | rs1 | func3 | . | işlem kodu |
U-Type hızlı biçimi:
| 31...12 | 11..7 | 6..0 |
|---|---|---|
| 20 | 5 | 7 |
| uimm20 | . | işlem kodu |
I-Type biçimi riscv32i.bin_fmt içinde zaten mevcuttur, dolayısıyla
bu biçimi eklemeniz gerekir.
Özel I-Type biçimini, burada tanımladığımız R-Type biçimiyle karşılaştırırsak
gördüğünüz gibi, tek farkın rs2 alanları
, uimm5 olarak yeniden adlandırıldı. Tamamen yeni bir biçim eklemek yerine,
R-Type biçimi. Genişliği artacağı için başka bir alan ekleyemiyoruz
ama bir yer paylaşımı ekleyebiliriz. Yer paylaşımı,
bitleri haline getirilir ve bu alanın birden çok sonraki tekrarlarını birleştirmek için
farklı bir adlandırılmış varlığa dönüştürür. Bunun yan etkisi, oluşturulan kodun
artık yer paylaşımı için bir ayıklama işlevi de
açıklayacağım. Bu durumda, hem rs2 hem de uimm5 imzalanmadığında
alanın kullanıldığını açıkça belirtmek dışında pek fark yaratmaz
ele alacağız. R-Type biçimine uimm5 adlı bir yer paylaşımı eklemek için
şunu ekleyin:
overlays:
unsigned uimm5[5] = rs2;
Eklememiz gereken tek yeni biçim U Türü biçimidir. Ekleme işleminden önce
biçimi varsa bu biçimi kullanan iki talimata bakalım: auipc ve
lui. Bunların her ikisi de, 20 bitlik anında değeri, kullanmadan önce 12'lik bir tarihe kaydırır
veya doğrudan bir kasaya yazarakauipc
(lui). Yer paylaşımı kullanarak anında, önceden kaydırılmış sürümünü sağlayabiliriz.
Daha küçük bir hesaplama işleminin talimatı yürütmeden öğretime kaydırması
çözer. Önce, tabloda belirtilen alanlara göre biçimi ekleyin
bölümünü ziyaret edin. Daha sonra, aşağıdaki yer paylaşımını ekleyebiliriz:
overlays:
unsigned uimm32[32] = uimm20, 0b0000'0000'0000;
Yer paylaşımı söz dizimi, yalnızca alanları değil, aynı zamanda dizeleri olur. Bu örnekte, 12 tane sıfır ile birleştiririz ve sonuç olarak, sola kaydırırız. 12 tarihine kadar.
Eklememiz gereken I-Type talimatları şunlardır:
addi- Hemen ekleyin.andi- Bit tabanlı ve anında.ori- Bit tabanlı veya anında.xori- Bit tabanlı Xor ve anında.
Kodlamaları şu şekildedir:
| 31...20 | 19...15 | 14..12 | 11..7 | 6..0 | opcode_name |
|---|---|---|---|---|---|
| imm12 | rs1 | 000 | . | 001 0011 | Addi |
| imm12 | rs1 | 111 | . | 001 0011 | Andi |
| imm12 | rs1 | 110 | . | 001 0011 | Ori |
| imm12 | rs1 | 100 | . | 001 0011 | sori |
| func3 | işlem kodu |
Eklememiz gereken R-Type (özel I-Type) talimatları şunlardır:
slli- Hemen sola mantıksal olarak kaydırır.srai- Hemen aritmetiği sağa kaydır.srli- Hemen sağa kaydırır.
Kodlamaları şu şekildedir:
| 31..25 | 24...20 | 19...15 | 14..12 | 11..7 | 6..0 | işlem kodu adı |
|---|---|---|---|---|---|---|
| 000.000 | uimm5 | rs1 | 001 | . | 001 0011 | Slli |
| 010 0.000 | uimm5 | rs1 | 101 | . | 001 0011 | Sarai |
| 000.000 | uimm5 | rs1 | 101 | . | 001 0011 | srli |
| func7 | func3 | işlem kodu |
Eklememiz gereken U-Type talimatları şunlardır:
auipc- Hemen pc'ye ekle.lui- Hemen üst öğeyi yükle.
Kodlamaları şu şekildedir:
| 31...12 | 11..7 | 6..0 | işlem kodu adı |
|---|---|---|---|
| uimm20 | . | 001 0111 | auipc |
| uimm20 | . | 011 0111 | Lui |
| işlem kodu |
Değişiklikleri yapın ve sonra oluşturun. Oluşturulan çıkışı kontrol edin. Adil önceki gibi çalışmanızı riscv32i.bin_fmt adresine gidin.
Dal ve atlama ve bağlantı talimatları ekleme
Tanımlanması gereken bir sonraki talimat grubu, talimatlar, atlama ve bağlantı talimatı, ve bağlantı ekleme teşekkür ederiz.
Eklediğimiz koşullu dallar, B-Type kodlamasını kullanmaktadır.
| 31..25 | 24...20 | 19...15 | 14..12 | 11..7 | 6..0 |
|---|---|---|---|---|---|
| 7 | 5 | 5 | 3 | 5 | 7 |
| imm7 | rs2 | rs1 | func3 | imm5 | işlem kodu |
B-Tipi kodlaması, düzen açısından R-Type kodlamasıyla özdeş olsa da,
RiscV dokümanlarıyla uyumlu olması için yeni bir biçim türü kullanmayı tercih etmeniz gerekir.
Ancak uygun dal almak için bir yer paylaşımı da
R-Type'ın func7 ve rd alanlarını kullanarak yer değiştirme
kullanır.
Yukarıda belirtilen alanları içeren bir BType biçiminin eklenmesi gerekir ancak bu zorunlu değildir
yeterli olacaktır. Gördüğünüz gibi, hemen iki talimat alanına bölünmüştür.
Ayrıca, şube talimatlarında bu durum,
gireceğiz. Bunun yerine, her alan daha fazla bölümlendirilir ve bu bölümler
farklı bir sırada sıralar. Son olarak, bu değer
için bir değer bulunmalıdır.
Anı oluşturmak için kullanılan talimat kelimesinde bit dizisi şu şekildedir: 31,
7, 30..25, 11..8. Bu, aşağıdaki alt alan referanslarına karşılık gelir ve
dizin veya aralık, alandaki bitleri belirtir; sağdan sola doğru (yani
imm7[6], imm7 öğesinin msb'sini, imm5[0] ise lsb değerini ifade eder
imm5.
imm7[6], imm5[0], imm7[5..0], imm5[4..1]
Bu küçük manipülasyonun dal talimatlarının bir parçası haline getirmek için
dezavantajları var. İlk olarak, anlamsal fonksiyonun uygulamasını
ikili talimat gösterimindeki ayrıntılara yer verir. İkinci olarak, reklamların
yardımcı olabilir. Bunun yanıtı, BType biçimine bir yer paylaşımı eklemektir. Örneğin,
sonda '0' hesaba katacağım.
overlays:
signed b_imm[13] = imm7[6], imm5[0], imm7[5..0], imm5[4..1], 0b0;
Yer paylaşımı imzalandığı için otomatik olarak genişletilir anahtar kelimeden ayıklandığında ne olur?
Jump-and-link (hemen) talimatı J-Type kodlamasını kullanır:
| 31...12 | 11..7 | 6..0 |
|---|---|---|
| 20 | 5 | 7 |
| imm20 | . | işlem kodu |
Bu da eklenmesi kolay bir biçimdir, ancak kullanıcı tarafından kullanılan anlık göründüğü kadar kolay değil. Kullanılan bit dizileri 31, 19..12, 20, 30..21 ve son hemen hemen yarım kelime hizalama için bir sola kaydırılır. Çözüm, tablodaki şu biçime sahiptir: (sol kayma için 21 bit):
overlays:
signed j_imm[21] = imm20[19, 7..0, 8, 18..9], 0b0;
Gördüğünüz gibi bindirmelerin söz dizimi, bir kullanabilirsiniz. Buna ek olarak, hiçbir alan adı kullanılmazsa sayılar talimat kelimesinin kendisine işaret ettiği için yukarıdakiler de aynı şekilde şu şekilde yazıldı:
signed j_imm[21] = [31, 19..12, 20, 30..21], 0b0;
Son olarak, atlama ve bağlantı (kaydet) işlevi, öğrendi.
I-Type'ın anlık biçimi:
| 31...20 | 19...15 | 14..12 | 11..7 | 6..0 |
|---|---|---|---|---|
| 12 | 5 | 3 | 5 | 7 |
| imm12 | rs1 | func3 | . | işlem kodu |
Bu kez, biçimde herhangi bir değişiklik yapılması gerekmez.
Eklememiz gereken dal talimatları şunlardır:
beq- Eşitse dal.bge- Büyükse veya eşitse dal.bgeu- Büyüktür veya eşittir imzalanmamışsa şube.blt- Küçükse şubelere ayırın.bltu- İmzalanmamışsa şubelerden yararlanın.bne- Eşit değilse dal.
Bunlar şu şekilde kodlanır:
| 31..25 | 24...20 | 19...15 | 14..12 | 11..7 | 6..0 | işlem kodu adı |
|---|---|---|---|---|---|---|
| imm7 | rs2 | rs1 | 000 | imm5 | 110.0011 | beq |
| imm7 | rs2 | rs1 | 101 | imm5 | 110.0011 | Bge |
| imm7 | rs2 | rs1 | 111 | imm5 | 110.0011 | Bgeu |
| imm7 | rs2 | rs1 | 100 | imm5 | 110.0011 | blt |
| imm7 | rs2 | rs1 | 110 | imm5 | 110.0011 | bltu |
| imm7 | rs2 | rs1 | 001 | imm5 | 110.0011 | Bne |
| func3 | işlem kodu |
jal talimatı şu şekilde kodlanır:
| 31...12 | 11..7 | 6..0 | işlem kodu adı |
|---|---|---|---|
| imm20 | . | 110 1111 | Jal |
| işlem kodu |
jalr talimatı şu şekilde kodlanır:
| 31...20 | 19...15 | 14..12 | 11..7 | 6..0 | opcode_name |
|---|---|---|---|---|---|
| imm12 | rs1 | 000 | . | 110 0111 | Jalr |
| func3 | işlem kodu |
Değişiklikleri yapın ve sonra oluşturun. Oluşturulan çıkışı kontrol edin. Adil önceki gibi çalışmanızı riscv32i.bin_fmt adresine gidin.
Mağaza talimatları ekleyin
Mağaza talimatlarında, B-Tipi ile bire bir aynı olan S-Type kodlaması kullanılır.
parçasının bileşenleri hariç olmak üzere, dal talimatları tarafından kullanılan kodlama
hemen öğrenebilirsiniz. RiscV ile uyumlu kalmak için SType biçimini eklemeyi tercih ediyoruz
belgelerinden faydalanabilirsiniz.
| 31..25 | 24...20 | 19...15 | 14..12 | 11..7 | 6..0 |
|---|---|---|---|---|---|
| 7 | 5 | 5 | 3 | 5 | 7 |
| imm7 | rs2 | rs1 | func3 | imm5 | işlem kodu |
SType biçiminde, neyse ki hemen
iki yakın alanın ileriye doğru birleştirilmesi için yer paylaşımı spesifikasyonu
şu basitçe ifade edilir:
overlays:
signed s_imm[12] = imm7, imm5;
Tüm alanları birleştirirken bit aralığı tanımlayıcısına gerek olmadığını unutmayın.
Mağaza talimatları şu şekilde kodlanmıştır:
| 31..25 | 24...20 | 19...15 | 14..12 | 11..7 | 6..0 | işlem kodu adı |
|---|---|---|---|---|---|---|
| imm7 | rs2 | rs1 | 000 | imm5 | 010 0011 | sb |
| imm7 | rs2 | rs1 | 001 | imm5 | 010 0011 | sh |
| imm7 | rs2 | rs1 | 010 | imm5 | 010 0011 | sw |
| func3 | işlem kodu |
Değişiklikleri yapın ve sonra oluşturun. Oluşturulan çıkışı kontrol edin. Adil önceki gibi çalışmanızı riscv32i.bin_fmt adresine gidin.
Yükleme talimatlarını ekleyin
Yükleme talimatlarında I-Type biçimi kullanılır. Orada herhangi bir değişiklik yapılması gerekmez.
Kodlamalar şunlardır:
| 31...20 | 19...15 | 14..12 | 11..7 | 6..0 | opcode_name |
|---|---|---|---|---|---|
| imm12 | rs1 | 000 | . | 000 0011 | lb |
| imm12 | rs1 | 100 | . | 000 0011 | Lbu |
| imm12 | rs1 | 001 | . | 000 0011 | h |
| imm12 | rs1 | 101 | . | 000 0011 | lhu |
| imm12 | rs1 | 010 | . | 000 0011 | lw |
| func3 | işlem kodu |
Değişiklikleri yapın ve sonra oluşturun. Oluşturulan çıkışı kontrol edin. Adil önceki gibi çalışmanızı riscv32i.bin_fmt adresine gidin.
Eğiticiyi sonlandırıyor. Yararlı olduğunu umuyoruz.