aarchmrs_parser/
instructions.rs

1/* Copyright (C) 2025 Ivan Boldyrev
2 *
3 * This document is licensed under the BSD 3-clause license.
4 */
5
6//! Simple AARCHMRS parser for `Instructions.json`.
7//!
8//! It extracts ARM instruction info (`Instructions.json`) from the ARM's AARCHMRS open source archive.
9//! It extracts only minimal information required for the code generation of the `aarchmrs-instructions` crate.
10
11use serde::Deserialize;
12
13#[derive(Debug, Deserialize)]
14pub struct Instructions {
15    pub instructions: Vec<InstructionSet>,
16    pub _meta: Meta,
17}
18
19#[derive(Debug, Deserialize)]
20pub struct Meta {
21    pub license: License,
22}
23
24#[derive(Debug, Deserialize)]
25pub struct License {
26    pub copyright: String,
27    pub info: String,
28}
29
30#[derive(Debug, Deserialize)]
31pub struct InstructionSet {
32    pub children: Vec<InstructionGroupOrInstruction>,
33    pub encoding: Encodeset,
34    pub name: String,
35}
36
37#[derive(Debug, Deserialize)]
38pub struct InstructionGroup {
39    pub children: Vec<InstructionGroupOrInstruction>,
40    pub encoding: Encodeset,
41    pub name: String,
42}
43
44#[derive(Debug, Deserialize)]
45#[serde(tag = "_type")]
46pub enum InstructionGroupOrInstruction {
47    #[serde(rename = "Instruction.InstructionGroup")]
48    InstructionGroup(InstructionGroup),
49    #[serde(rename = "Instruction.Instruction")]
50    Instruction(Instruction),
51    #[serde(rename = "Instruction.InstructionAlias")]
52    InstructionAlias(InstructionAlias),
53}
54
55#[derive(Debug, Deserialize)]
56pub struct Encodeset {
57    pub values: Vec<Encode>,
58}
59
60impl<'a> IntoIterator for &'a Encodeset {
61    type Item = &'a Encode;
62
63    type IntoIter = std::slice::Iter<'a, Encode>;
64
65    fn into_iter(self) -> Self::IntoIter {
66        self.values.iter()
67    }
68}
69
70#[derive(Debug, Deserialize)]
71#[serde(tag = "_type")]
72pub enum Encode {
73    #[serde(rename = "Instruction.Encodeset.Field")]
74    Field(Field),
75    #[serde(rename = "Instruction.Encodeset.Bits")]
76    Bits(Bits),
77}
78
79#[derive(Debug, Deserialize)]
80pub struct Field {
81    pub name: String,
82    pub range: Range,
83    pub should_be_mask: Value,
84    pub value: Value,
85}
86
87#[derive(Debug, Deserialize)]
88pub struct Bits {
89    pub range: Range,
90    pub should_be_mask: Value,
91    pub value: Value,
92}
93
94#[derive(Copy, Clone, Debug, Deserialize)]
95pub struct Range {
96    pub start: u32,
97    pub width: u32,
98}
99
100impl IntoIterator for Range {
101    type Item = u32;
102
103    type IntoIter = std::ops::Range<u32>;
104
105    fn into_iter(self) -> Self::IntoIter {
106        self.start..(self.start + self.width)
107    }
108}
109
110#[derive(Debug, Deserialize)]
111pub struct Value {
112    pub value: String,
113    // there is also a "meaning" field, but it is always null.
114}
115
116impl Value {
117    pub fn as_str(&self) -> Option<&str> {
118        if self.value.starts_with('\'') && self.value.ends_with('\'') {
119            let val = self.value.as_str();
120            Some(val.split_at(val.len() - 1).0.split_at(1).1)
121        } else {
122            None
123        }
124    }
125}
126
127#[derive(Debug, Deserialize)]
128pub struct Instruction {
129    pub encoding: Encodeset,
130    pub name: String,
131    pub operation_id: String,
132    #[serde(default)]
133    pub children: Vec<InstructionGroupOrInstruction>,
134}
135
136#[derive(Debug, Deserialize)]
137pub struct InstructionAlias {
138    // TODO what are the real fields?
139    pub name: String,
140    pub operation_id: String,
141    #[serde(default)]
142    pub children: Vec<InstructionGroupOrInstruction>,
143}
144
145#[cfg(test)]
146mod tests {
147    use super::*;
148
149    #[test]
150    fn test_value_as_str_empty() {
151        assert_eq!(Value { value: "''".into() }.as_str(), Some(""));
152    }
153
154    #[test]
155    fn test_value_as_str() {
156        assert_eq!(
157            Value {
158                value: "'000'".into()
159            }
160            .as_str(),
161            Some("000")
162        );
163    }
164}