compiler/
lib/
examples/
std/
arch/
rv64/
asm/
image/
shared/
asm.rad
24.8 KiB
atomicTests.rad
5.0 KiB
atomics.rad
3.6 KiB
bounds.rad
33.4 KiB
decode.rad
15.2 KiB
emit.rad
33.2 KiB
encode.rad
22.0 KiB
image.rad
4.5 KiB
isel.rad
52.6 KiB
printer.rad
13.9 KiB
shared.rad
16.8 KiB
tests.rad
17.2 KiB
rv64.rad
17.5 KiB
char/
collections/
graph/
lang/
sys/
arch.rad
68 B
char.rad
855 B
collections.rad
39 B
fmt.rad
8.3 KiB
graph.rad
4.3 KiB
intrinsics.rad
467 B
io.rad
1.7 KiB
lang.rad
276 B
mem.rad
2.3 KiB
sys.rad
179 B
testing.rad
2.4 KiB
tests.rad
15.7 KiB
vec.rad
3.2 KiB
std.rad
299 B
scripts/
seed/
sublime/
test/
vim/
.gitignore
336 B
.gitsigners
112 B
CELL_PERMISSIONS
6.8 KiB
CONTRIBUTING
2.1 KiB
LICENSE
1.1 KiB
Makefile
5.4 KiB
README
2.5 KiB
STYLE
2.5 KiB
std.lib
1.5 KiB
std.lib.test
808 B
lib/std/arch/rv64/atomics.rad
raw
| 1 | //! RV64 atomic instruction fields and canonical assembly names. |
| 2 | |
| 3 | use std::mem; |
| 4 | use std::lang::gen; |
| 5 | |
| 6 | /// Atomic operation, width, and ordering fields. |
| 7 | export record Format: Copy { |
| 8 | /// Five-bit operation code from the A extension. |
| 9 | operation: u32, |
| 10 | /// Memory width encoding: 2 for a word, 3 for a doubleword. |
| 11 | width: u32, |
| 12 | /// Ordering bits: 2 for acquire, 1 for release, 3 for both. |
| 13 | order: u32, |
| 14 | } |
| 15 | |
| 16 | /// Decoded atomic instruction operands. |
| 17 | export record Instruction: Copy { |
| 18 | /// Operation and ordering fields. |
| 19 | format: Format, |
| 20 | /// Destination register. |
| 21 | rd: gen::Reg, |
| 22 | /// Address register. |
| 23 | rs1: gen::Reg, |
| 24 | /// Source value; zero for load-reserved. |
| 25 | rs2: gen::Reg, |
| 26 | } |
| 27 | |
| 28 | /// An architectural operation and its mnemonic stem. |
| 29 | record Operation: Copy { |
| 30 | /// Mnemonic without width or ordering suffixes. |
| 31 | name: *[u8], |
| 32 | /// Five-bit instruction field. |
| 33 | code: u32, |
| 34 | } |
| 35 | |
| 36 | /// Operations shared by the 32-bit and 64-bit forms. |
| 37 | constant OPERATIONS: [Operation; 11] = [ |
| 38 | { name: "amoadd", code: 0 }, { name: "amoswap", code: 1 }, |
| 39 | { name: "lr", code: 2 }, { name: "sc", code: 3 }, |
| 40 | { name: "amoxor", code: 4 }, { name: "amoor", code: 8 }, |
| 41 | { name: "amoand", code: 12 }, { name: "amomin", code: 16 }, |
| 42 | { name: "amomax", code: 20 }, { name: "amominu", code: 24 }, |
| 43 | { name: "amomaxu", code: 28 }, |
| 44 | ]; |
| 45 | |
| 46 | /// Look up an operation's canonical mnemonic stem. |
| 47 | export fn name(code: u32) -> ?*[u8] { |
| 48 | for operation in &OPERATIONS[..] { |
| 49 | if operation.code == code { |
| 50 | return operation.name; |
| 51 | } |
| 52 | } |
| 53 | return nil; |
| 54 | } |
| 55 | |
| 56 | /// Parse an atomic mnemonic with mandatory width and optional ordering suffix. |
| 57 | export fn parse(text: *[u8]) -> ?Format { |
| 58 | for operation in &OPERATIONS[..] { |
| 59 | let n = operation.name.len; |
| 60 | if text.len < n + 2 or not mem::eq(&text[..n], operation.name) or text[n] <> '.' { |
| 61 | continue; |
| 62 | } |
| 63 | let mut width: u32 = 2; |
| 64 | if text[n + 1] == 'd' { |
| 65 | set width = 3; |
| 66 | } |
| 67 | else if text[n + 1] <> 'w' { |
| 68 | return nil; |
| 69 | } |
| 70 | let suffix = &text[n + 2..]; |
| 71 | let mut order: u32 = 0; |
| 72 | if mem::eq(suffix, ".aq") { |
| 73 | set order = 2; |
| 74 | } |
| 75 | else if mem::eq(suffix, ".rl") { |
| 76 | set order = 1; |
| 77 | } |
| 78 | else if mem::eq(suffix, ".aqrl") { |
| 79 | set order = 3; |
| 80 | } |
| 81 | else if suffix.len <> 0 { |
| 82 | return nil; |
| 83 | } |
| 84 | return Format { operation: operation.code, width, order }; |
| 85 | } |
| 86 | return nil; |
| 87 | } |
| 88 | |
| 89 | /// Encode a validated atomic operation and register operands. |
| 90 | export fn encode(instruction: Instruction) -> u32 { |
| 91 | let format = instruction.format; |
| 92 | assert name(format.operation) <> nil and (format.width == 2 or format.width == 3) and format.order <= 3; |
| 93 | assert format.operation <> 2 or instruction.rs2 == super::ZERO; |
| 94 | return 0x2f | (*instruction.rd as u32 << 7) | (format.width << 12) |
| 95 | | (*instruction.rs1 as u32 << 15) | (*instruction.rs2 as u32 << 20) |
| 96 | | (format.order << 25) | (format.operation << 27); |
| 97 | } |
| 98 | |
| 99 | /// Decode a supported atomic word and reject reserved width and LR fields. |
| 100 | export fn decode(word: u32) -> ?Instruction { |
| 101 | let operation = word >> 27; |
| 102 | let width = (word >> 12) & 7; |
| 103 | let rs2 = super::reg(((word >> 20) & 31) as u8); |
| 104 | if (word & 127) <> 0x2f or name(operation) == nil or (width <> 2 and width <> 3) { |
| 105 | return nil; |
| 106 | } |
| 107 | if operation == 2 and rs2 <> super::ZERO { |
| 108 | return nil; |
| 109 | } |
| 110 | return Instruction { |
| 111 | format: Format { operation, width, order: (word >> 25) & 3 }, |
| 112 | rd: super::reg(((word >> 7) & 31) as u8), rs1: super::reg(((word >> 15) & 31) as u8), rs2, |
| 113 | }; |
| 114 | } |