1use std::{
2 collections::{BTreeMap, HashMap, HashSet},
3 fmt::{Display, Write as _},
4 path::PathBuf,
5 str::FromStr,
6};
7
8use bincode::{BorrowDecode, Encode};
9use compile_commands::{CompilationDatabase, SourceFile};
10use log::{info, warn};
11use lsp_textdocument::TextDocuments;
12use lsp_types::{CompletionItem, Uri};
13use schemars::JsonSchema;
14use serde::{Deserialize, Serialize};
15use strum_macros::{AsRefStr, Display, EnumString};
16use tree_sitter::{Parser, Tree};
17
18use crate::{
19 UriConversion, populate_name_to_directive_map, populate_name_to_instruction_map,
20 populate_name_to_register_map, process_uri,
21};
22
23pub const BINCODE_CFG: bincode::config::Configuration = bincode::config::standard().with_no_limit();
24
25#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, Encode, BorrowDecode)]
27pub struct Instruction {
28 pub name: String,
29 pub summary: String,
30 pub forms: Vec<InstructionForm>,
31 pub asm_templates: Vec<String>,
32 pub aliases: Vec<InstructionAlias>,
33 pub url: Option<String>,
34 pub arch: Arch,
35}
36
37impl Hoverable for Instruction {}
38impl Completable for Instruction {}
39
40impl Default for Instruction {
41 fn default() -> Self {
42 let name = String::new();
43 let summary = String::new();
44 let forms = vec![];
45 let asm_templates = vec![];
46 let aliases = vec![];
47 let url = None;
48 let arch = Arch::None;
49
50 Self {
51 name,
52 summary,
53 forms,
54 asm_templates,
55 aliases,
56 url,
57 arch,
58 }
59 }
60}
61
62impl std::fmt::Display for Instruction {
63 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64 let header = format!("{} [{}]", &self.name, self.arch.as_ref());
66
67 let mut v: Vec<&str> = vec![&header, &self.summary, "\n"];
69
70 if !self.forms.is_empty() {
71 v.append(&mut vec!["## Forms", "\n"]);
72 }
73
74 let instruction_form_strs: Vec<String> =
76 self.forms.iter().map(|f| format!("{f}")).collect();
77 for item in &instruction_form_strs {
78 v.push(item.as_str());
79 }
80
81 if !self.asm_templates.is_empty() {
82 v.append(&mut vec!["## Templates", "\n"]);
83 }
84 let instruction_template_strs: Vec<String> = self
86 .asm_templates
87 .iter()
88 .map(|f| format!(" + `{}`", f.as_str()))
89 .collect();
90 for item in &instruction_template_strs {
91 v.push(item.as_str());
92 }
93
94 if !self.aliases.is_empty() {
95 v.append(&mut vec!["## Aliases", "\n"]);
96 }
97
98 let instruction_alias_strs: Vec<String> =
100 self.aliases.iter().map(|f| format!("{f}\n")).collect();
101 for item in &instruction_alias_strs {
102 v.push(item.as_str());
103 }
104
105 let more_info: String;
107 if let Some(url) = &self.url {
108 more_info = format!("\nMore info: {url}");
109 v.push(&more_info);
110 }
111
112 let s = v.join("\n");
113 write!(f, "{s}")?;
114 Ok(())
115 }
116}
117
118impl<'own> Instruction {
119 pub fn push_form(&mut self, form: InstructionForm) {
121 self.forms.push(form);
122 }
123
124 pub fn push_alias(&mut self, form: InstructionAlias) {
126 self.aliases.push(form);
127 }
128
129 #[must_use]
131 pub fn get_primary_names(&'own self) -> Vec<&'own str> {
132 let names = vec![self.name.as_ref()];
133
134 names
135 }
136
137 #[must_use]
139 pub fn get_associated_names(&'own self) -> Vec<&'own str> {
140 let mut names = Vec::<&'own str>::new();
141
142 for f in &self.forms {
143 for name in [&f.gas_name, &f.go_name, &f.z80_name]
144 .iter()
145 .copied()
146 .flatten()
147 {
148 names.push(name);
149 }
150 }
151
152 names
153 }
154}
155
156#[derive(
159 Default, Eq, PartialEq, Hash, Debug, Clone, Serialize, Deserialize, Encode, BorrowDecode,
160)]
161pub struct InstructionForm {
162 pub gas_name: Option<String>,
164 pub go_name: Option<String>,
165 pub mmx_mode: Option<MMXMode>,
166 pub xmm_mode: Option<XMMMode>,
167 pub cancelling_inputs: Option<bool>,
168 pub nacl_version: Option<u8>,
169 pub nacl_zero_extends_outputs: Option<bool>,
170 pub z80_name: Option<String>,
172 pub z80_form: Option<String>,
173 pub z80_opcode: Option<String>,
174 pub z80_timing: Option<Z80Timing>,
175 pub avr_mneumonic: Option<String>,
177 pub avr_summary: Option<String>,
178 pub avr_version: Option<String>,
179 pub avr_timing: Option<AvrTiming>,
180 pub avr_status_register: Option<AvrStatusRegister>,
181 pub isa: Option<ISA>,
183 pub operands: Vec<Operand>,
184 pub urls: Vec<String>,
185}
186
187impl std::fmt::Display for InstructionForm {
188 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
189 let mut s = String::new();
190 if let Some(val) = &self.gas_name {
191 write!(s, "*GAS*: {val} | ")?;
192 }
193 if let Some(val) = &self.go_name {
194 write!(s, "*GO*: {val} | ")?;
195 }
196 if let Some(val) = &self.z80_form {
197 write!(s, "*Z80*: {val} | ")?;
198 }
199 if let Some(val) = &self.avr_mneumonic {
200 let version_str = self
201 .avr_version
202 .as_ref()
203 .map_or_else(String::new, |version| format!(" ({version})"));
204 write!(s, "*AVR*: {val}{version_str} | ")?;
205 }
206
207 if let Some(val) = &self.mmx_mode {
208 write!(s, "*MMX*: {} | ", val.as_ref())?;
209 }
210 if let Some(val) = &self.xmm_mode {
211 write!(s, "*XMM*: {} | ", val.as_ref())?;
212 }
213 if let Some(val) = &self.z80_opcode {
214 if val.contains(',') {
215 write!(s, "*Opcodes*: {val} | ")?;
216 } else {
217 write!(s, "*Opcode*: {val} | ")?;
218 }
219 }
220
221 if let Some(val) = &self.isa {
227 write!(s, "*ISA*: {} | ", val.as_ref())?;
228 }
229
230 if !s.is_empty() {
231 s = format!("- {}\n\n", &s[..s.len() - 3]);
232 }
233
234 let operands_str: String = if self.operands.is_empty() {
236 String::new()
237 } else {
238 self.operands
239 .iter()
240 .map(|op| {
241 let mut s = format!(" + {:<8}", format!("[{}]", op.type_.as_ref()));
242 if let Some(input) = op.input {
243 write!(s, " input = {input:<5} ").unwrap();
244 }
245 if let Some(output) = op.output {
246 write!(s, " output = {output:<5}").unwrap();
247 }
248 if let Some(extended_size) = op.extended_size {
249 write!(s, " extended-size = {extended_size}").unwrap();
250 }
251
252 s.trim_end().to_owned()
253 })
254 .collect::<Vec<String>>()
255 .join("\n")
256 };
257
258 s += &operands_str;
259
260 if let Some(ref timing) = self.z80_timing {
261 write!(s, "\n + {timing}")?;
262 }
263
264 if let Some(summary) = &self.avr_summary {
265 write!(s, "\n\n{summary}")?;
266 }
267 if let Some(sreg) = &self.avr_status_register {
268 write!(s, "\n\n{sreg}")?;
269 }
270 if let Some(ref timing) = self.avr_timing {
271 writeln!(s, "\n\n{timing}")?;
272 }
273
274 for url in &self.urls {
275 writeln!(s, "\n + More info: {url}")?;
276 }
277
278 write!(f, "{s}")?;
279 Ok(())
280 }
281}
282
283#[derive(
285 Default, Eq, PartialEq, Hash, Debug, Clone, Serialize, Deserialize, Encode, BorrowDecode,
286)]
287pub struct InstructionAlias {
288 pub title: String,
289 pub summary: String,
290 pub asm_templates: Vec<String>,
291}
292
293impl std::fmt::Display for InstructionAlias {
294 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
295 let mut s = self.title.clone();
296
297 if !self.summary.is_empty() {
298 write!(s, "\n {}", self.summary)?;
299 }
300
301 for template in &self.asm_templates {
302 write!(s, "\n + `{template}`")?;
303 }
304
305 write!(f, "{s}")?;
306 Ok(())
307 }
308}
309
310#[derive(
311 Debug, Default, PartialEq, Eq, Hash, Clone, Copy, Serialize, Deserialize, Encode, BorrowDecode,
312)]
313pub enum Z80TimingValue {
314 #[default]
315 Unknown,
316 Val(u8),
317}
318
319impl Display for Z80TimingValue {
320 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
321 match self {
322 Self::Unknown => {
323 write!(f, "?")?;
324 }
325 Self::Val(val) => {
326 write!(f, "{val}")?;
327 }
328 }
329
330 Ok(())
331 }
332}
333
334impl FromStr for Z80TimingValue {
335 type Err = std::num::ParseIntError;
336 fn from_str(s: &str) -> Result<Self, Self::Err> {
337 if s.eq("?") {
338 Ok(Self::Unknown)
339 } else {
340 match s.parse::<u8>() {
341 Ok(val) => Ok(Self::Val(val)),
342 Err(e) => Err(e),
343 }
344 }
345 }
346}
347
348#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy, Serialize, Deserialize, Encode, BorrowDecode)]
349pub enum Z80TimingInfo {
350 OneNum(Z80TimingValue), TwoNum((Z80TimingValue, Z80TimingValue)),
352 ThreeNum((Z80TimingValue, Z80TimingValue, Z80TimingValue)),
353}
354
355impl Default for Z80TimingInfo {
356 fn default() -> Self {
357 Self::OneNum(Z80TimingValue::Unknown)
358 }
359}
360
361impl Display for Z80TimingInfo {
362 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
363 match self {
364 Self::OneNum(num) => {
365 write!(f, "{num}")?;
366 }
367 Self::TwoNum((num1, num2)) => {
368 write!(f, "{num1}/{num2}")?;
369 }
370 Self::ThreeNum((num1, num2, num3)) => {
371 write!(f, "{num1}/{num2}/{num3}")?;
372 }
373 }
374 Ok(())
375 }
376}
377
378impl FromStr for Z80TimingInfo {
379 type Err = String;
380 fn from_str(s: &str) -> Result<Self, Self::Err> {
381 if s.starts_with('/') || s.ends_with('/') {
382 return Err(String::from("Cannot have an empty num value"));
383 }
384
385 let pieces: Vec<Result<Z80TimingValue, std::num::ParseIntError>> =
386 s.split('/').map(str::parse).collect();
387
388 match pieces.len() {
389 1 => pieces[0].as_ref().map_or_else(
390 |_| Err(String::from("Failed to parse one timing value")),
391 |num| Ok(Self::OneNum(*num)),
392 ),
393 2 => match (&pieces[0], &pieces[1]) {
394 (Ok(num1), Ok(num2)) => Ok(Self::TwoNum((*num1, *num2))),
395 _ => Err(String::from("Failed to parse one or more timing values")),
396 },
397 3 => match (&pieces[0], &pieces[1], &pieces[2]) {
398 (Ok(num1), Ok(num2), Ok(num3)) => Ok(Self::ThreeNum((*num1, *num2, *num3))),
399 _ => Err(String::from("Failed to parse one or more timing values")),
400 },
401 n => Err(format!("Expected 1-3 timing values, got {n}")),
402 }
403 }
404}
405
406#[derive(
407 Default, Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize, Encode, BorrowDecode,
408)]
409pub struct Z80Timing {
410 pub z80: Z80TimingInfo,
411 pub z80_plus_m1: Z80TimingInfo,
412 pub r800: Z80TimingInfo,
413 pub r800_plus_wait: Z80TimingInfo,
414}
415
416impl Display for Z80Timing {
417 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
418 write!(
419 f,
420 "Z80: {}, Z80 + M1: {}, R800: {}, R800 + Wait: {}",
421 self.z80, self.z80_plus_m1, self.r800, self.z80_plus_m1
422 )?;
423 Ok(())
424 }
425}
426
427#[derive(
428 Default, Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize, Encode, BorrowDecode,
429)]
430pub struct AvrTiming {
431 pub avre: Option<String>,
432 pub avrxm: Option<String>,
433 pub avrxt: Option<String>,
434 pub avrrc: Option<String>,
435}
436
437impl Display for AvrTiming {
438 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
439 write!(f, "Timing: ")?;
440 let mut has_prev = false;
441 if let Some(ref cycles) = self.avre {
442 write!(f, "AVRE: {cycles}")?;
443 has_prev = true;
444 }
445 if let Some(ref cycles) = self.avrxm {
446 if has_prev {
447 write!(f, " | ")?;
448 }
449 write!(f, "AVRXM: {cycles}")?;
450 has_prev = true;
451 }
452 if let Some(ref cycles) = self.avrxt {
453 if has_prev {
454 write!(f, " | ")?;
455 }
456 write!(f, "AVRXT: {cycles}")?;
457 has_prev = true;
458 }
459 if let Some(ref cycles) = self.avrrc {
460 if has_prev {
461 write!(f, " | ")?;
462 }
463 write!(f, "AVRRC: {cycles}")?;
464 }
465
466 Ok(())
467 }
468}
469
470#[derive(
471 Default, Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize, Encode, BorrowDecode,
472)]
473pub struct AvrStatusRegister {
474 pub i: char,
475 pub t: char,
476 pub h: char,
477 pub s: char,
478 pub v: char,
479 pub n: char,
480 pub c: char,
481 pub z: char,
482}
483
484impl std::fmt::Display for AvrStatusRegister {
485 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
486 writeln!(f, "I T H S V N Z C")?;
487 writeln!(
488 f,
489 "{} {} {} {} {} {} {} {}",
490 self.i, self.t, self.h, self.s, self.v, self.n, self.c, self.z
491 )?;
492 Ok(())
493 }
494}
495
496#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Encode, BorrowDecode)]
498pub struct Directive {
499 pub name: String,
500 pub signatures: Vec<String>,
501 pub description: String,
502 pub deprecated: bool,
503 pub url: Option<String>,
504 pub assembler: Assembler,
505}
506
507impl Hoverable for Directive {}
508impl Completable for Directive {}
509
510impl Default for Directive {
511 fn default() -> Self {
512 let name = String::new();
513 let signatures = vec![];
514 let description = String::new();
515 let deprecated = false;
516 let url = None;
517 let assembler = Assembler::None;
518
519 Self {
520 name,
521 signatures,
522 description,
523 deprecated,
524 url,
525 assembler,
526 }
527 }
528}
529
530impl std::fmt::Display for Directive {
531 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
532 let header = format!(
535 "{} [{}]{}",
536 &self.name,
537 self.assembler,
538 if self.deprecated {
539 "\n**DEPRECATED**"
540 } else {
541 ""
542 }
543 );
544
545 let mut v: Vec<&str> = vec![&header, &self.description, "\n"];
546
547 let mut sigs = String::new();
549 for sig in &self.signatures {
550 writeln!(sigs, "- {sig}")?;
551 }
552 v.push(&sigs);
553
554 let more_info: String;
556 match &self.url {
557 None => {}
558 Some(url_) => {
559 more_info = format!("\nMore info: {url_}");
560 v.push(&more_info);
561 }
562 }
563
564 let s = v.join("\n");
565 write!(f, "{}", s.trim())?;
566 Ok(())
567 }
568}
569
570#[derive(Default, Debug, Clone)]
571pub enum Z80Register8Bit {
572 #[default]
573 A,
574 AShadow,
575 F,
576 FShadow,
577 B,
578 BShadow,
579 C,
580 CShadow,
581 D,
582 DShadow,
583 E,
584 EShadow,
585 H,
586 HShadow,
587 L,
588 LShadow,
589}
590
591#[derive(Default, Debug, Clone)]
592pub enum Z80Register16Bit {
593 AF,
594 AFShadow,
595 BC,
596 BCShadow,
597 DE,
598 DEShadow,
599 #[default]
600 HL,
601 HLShadow,
602}
603
604impl<'own> Directive {
605 #[must_use]
607 pub fn get_associated_names(&'own self) -> Vec<&'own str> {
608 let names = vec![self.name.as_ref()];
609
610 names
611 }
612}
613
614#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Encode, BorrowDecode)]
616pub struct Register {
617 pub name: String,
618 pub description: Option<String>,
619 pub reg_type: Option<RegisterType>,
620 pub width: Option<RegisterWidth>,
621 pub flag_info: Vec<RegisterBitInfo>,
622 pub arch: Arch,
623 pub url: Option<String>,
624}
625
626impl Hoverable for Register {}
627impl Completable for Register {}
628
629impl Default for Register {
630 fn default() -> Self {
631 let name = String::new();
632 let description = None;
633 let reg_type = None;
634 let width = None;
635 let flag_info = vec![];
636 let arch = Arch::None;
637 let url = None;
638
639 Self {
640 name,
641 description,
642 reg_type,
643 width,
644 flag_info,
645 arch,
646 url,
647 }
648 }
649}
650
651impl std::fmt::Display for Register {
652 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
653 let header = format!("{} [{}]", &self.name.to_uppercase(), self.arch.as_ref());
655
656 let mut v: Vec<String> = if let Some(description_) = &self.description {
657 vec![header, description_.clone(), String::from("\n")]
658 } else {
659 vec![header, String::from("\n")]
660 };
661
662 if let Some(reg_type_) = &self.reg_type {
664 let reg_type = format!("Type: {reg_type_}");
665 v.push(reg_type);
666 }
667
668 if let Some(reg_width_) = self.width {
670 let reg_width = format!("Width: {reg_width_}");
671 v.push(reg_width);
672 }
673
674 if !self.flag_info.is_empty() {
676 let flag_heading = String::from("\n## Flags:");
677 v.push(flag_heading);
678
679 let flags: Vec<String> = self
680 .flag_info
681 .iter()
682 .map(|flag| format!("{flag}"))
683 .collect();
684 for flag in &flags {
685 v.push(flag.clone());
686 }
687 }
688
689 if let Some(url_) = &self.url {
691 let more_info = format!("\nMore info: {url_}");
692 v.push(more_info);
693 }
694
695 let s = v.join("\n");
696 write!(f, "{s}")?;
697 Ok(())
698 }
699}
700
701impl<'own> Register {
702 pub fn push_flag(&mut self, flag: RegisterBitInfo) {
704 self.flag_info.push(flag);
705 }
706
707 #[must_use]
709 pub fn get_associated_names(&'own self) -> Vec<&'own str> {
710 let names = vec![self.name.as_ref()];
711
712 names
713 }
714}
715
716#[derive(Debug, Clone, Default)]
718pub struct NameToInfoMaps {
719 pub instructions: NameToInstructionMap,
720 pub registers: NameToRegisterMap,
721 pub directives: NameToDirectiveMap,
722}
723
724pub type NameToInstructionMap = HashMap<(Arch, String), Instruction>;
725
726pub type NameToRegisterMap = HashMap<(Arch, String), Register>;
727
728pub type NameToDirectiveMap = HashMap<(Assembler, String), Directive>;
729
730pub trait Hoverable: Display + Clone {}
731pub trait Completable: Display {}
732pub trait ArchOrAssembler: Clone + Copy {}
733
734#[derive(
735 Debug,
736 Clone,
737 PartialEq,
738 Eq,
739 Hash,
740 EnumString,
741 AsRefStr,
742 Serialize,
743 Deserialize,
744 Encode,
745 BorrowDecode,
746)]
747pub enum XMMMode {
748 SSE,
749 AVX,
750}
751
752#[derive(
753 Debug,
754 Clone,
755 Eq,
756 PartialEq,
757 Hash,
758 EnumString,
759 AsRefStr,
760 Serialize,
761 Deserialize,
762 Encode,
763 BorrowDecode,
764)]
765pub enum MMXMode {
766 FPU,
767 MMX,
768}
769
770#[allow(non_camel_case_types)]
771#[derive(
772 Debug,
773 Hash,
774 PartialEq,
775 Eq,
776 Clone,
777 Copy,
778 EnumString,
779 AsRefStr,
780 Serialize,
781 Deserialize,
782 Encode,
783 BorrowDecode,
784 JsonSchema,
785)]
786pub enum Arch {
787 #[strum(serialize = "x86")]
788 #[serde(rename = "x86")]
789 X86,
790 #[strum(serialize = "x86-64")]
791 #[serde(rename = "x86-64")]
792 X86_64,
793 #[strum(serialize = "x86/x86-64")]
795 #[serde(rename = "x86/x86-64")]
796 X86_AND_X86_64,
797 #[strum(serialize = "arm")]
798 #[serde(rename = "arm")]
799 ARM,
800 #[strum(serialize = "arm64")]
801 #[serde(rename = "arm64")]
802 ARM64,
803 #[strum(serialize = "riscv")]
804 #[serde(rename = "riscv")]
805 RISCV,
806 #[strum(serialize = "z80")]
807 #[serde(rename = "z80")]
808 Z80,
809 #[strum(serialize = "6502")]
810 #[serde(rename = "6502")]
811 MOS6502,
812 #[strum(serialize = "power-isa")]
813 #[serde(rename = "power-isa")]
814 PowerISA,
815 #[strum(serialize = "AVR")]
816 #[serde(rename = "AVR")] Avr,
818 #[strum(serialize = "mips")]
819 #[serde(rename = "mips")]
820 Mips,
821 #[serde(skip)]
823 None,
824}
825
826impl ArchOrAssembler for Arch {}
827
828impl Arch {
829 pub fn setup_registers(self, names_to_registers: &mut HashMap<(Self, String), Register>) {
835 macro_rules! load_registers_with_path {
836 ($arch:expr, $path:literal) => {{
837 let start = std::time::Instant::now();
838 let serialized_regs = include_bytes!($path);
839 let registers = bincode::borrow_decode_from_slice::<Vec<Register>, _>(serialized_regs, BINCODE_CFG)
840 .unwrap_or_else(|e| panic!("Error deserializing {} registers -- {}\nRegenerate serialized data with regenerate.sh", $arch, e)).0;
841
842 info!(
843 "{} register set loaded in {}ms",
844 $arch,
845 start.elapsed().as_millis()
846 );
847
848 populate_name_to_register_map($arch, ®isters, names_to_registers);
849 }};
850 }
851
852 match self {
853 Self::ARM => load_registers_with_path!(Self::ARM, "serialized/registers/arm"),
854 Self::ARM64 => load_registers_with_path!(Self::ARM64, "serialized/registers/arm"),
855 Self::Avr => load_registers_with_path!(Self::Avr, "serialized/registers/avr"),
856 Self::Mips => load_registers_with_path!(Self::Mips, "serialized/registers/mips"),
857 Self::MOS6502 => load_registers_with_path!(Self::MOS6502, "serialized/registers/6502"),
858 Self::PowerISA => {
859 load_registers_with_path!(Self::PowerISA, "serialized/registers/power-isa");
860 }
861 Self::RISCV => load_registers_with_path!(Self::RISCV, "serialized/registers/riscv"),
862 Self::X86 => load_registers_with_path!(Self::X86, "serialized/registers/x86"),
863 Self::X86_64 => load_registers_with_path!(Self::X86_64, "serialized/registers/x86_64"),
864 Self::X86_AND_X86_64 => {
865 load_registers_with_path!(Self::X86, "serialized/registers/x86");
866 load_registers_with_path!(Self::X86_64, "serialized/registers/x86_64");
867 }
868 Self::Z80 => load_registers_with_path!(Self::Z80, "serialized/registers/z80"),
869 Self::None => unreachable!(),
870 }
871 }
872
873 pub fn setup_instructions(
879 self,
880 assembler: Option<Assembler>,
881 names_to_instructions: &mut HashMap<(Self, String), Instruction>,
882 ) {
883 macro_rules! load_instructions_with_path {
884 ($arch:expr, $path:literal) => {{
885 let start = std::time::Instant::now();
886 let serialized_instrs = include_bytes!($path);
887 let instructions = bincode::borrow_decode_from_slice::<Vec<Instruction>, _>(serialized_instrs, BINCODE_CFG)
888 .unwrap_or_else(|e| panic!("Error deserializing {} instructions -- {}\nRegenerate serialized data with regenerate.sh", $arch, e))
889 .0;
890
891 info!(
892 "{} instruction set loaded in {}ms",
893 $arch,
894 start.elapsed().as_millis()
895 );
896
897 populate_name_to_instruction_map($arch, &instructions, names_to_instructions);
898 }};
899 }
900
901 match self {
902 Self::ARM => load_instructions_with_path!(Self::ARM, "serialized/opcodes/arm"),
903 Self::ARM64 => load_instructions_with_path!(Self::ARM64, "serialized/opcodes/arm"),
906 Self::Avr => load_instructions_with_path!(Self::Avr, "serialized/opcodes/avr"),
907 Self::MOS6502 => load_instructions_with_path!(Self::MOS6502, "serialized/opcodes/6502"),
908 Self::Mips => {
909 load_instructions_with_path!(Self::Mips, "serialized/opcodes/mips");
910 if Some(Assembler::Mars) == assembler {
911 load_instructions_with_path!(Self::Mips, "serialized/opcodes/mars");
912 }
913 }
914 Self::PowerISA => {
915 load_instructions_with_path!(Self::PowerISA, "serialized/opcodes/power-isa");
916 }
917 Self::RISCV => load_instructions_with_path!(Self::RISCV, "serialized/opcodes/riscv"),
918 Self::X86 => load_instructions_with_path!(Self::X86, "serialized/opcodes/x86"),
919 Self::X86_64 => load_instructions_with_path!(Self::X86_64, "serialized/opcodes/x86_64"),
920 Self::X86_AND_X86_64 => {
921 load_instructions_with_path!(Self::X86, "serialized/opcodes/x86");
922 load_instructions_with_path!(Self::X86_64, "serialized/opcodes/x86_64");
923 }
924 Self::Z80 => load_instructions_with_path!(Self::Z80, "serialized/opcodes/z80"),
925 Self::None => unreachable!(),
926 }
927 }
928}
929
930impl Default for Arch {
931 fn default() -> Self {
932 match () {
933 () if cfg!(target_arch = "x86") => {
934 info!("Detected host arch as x86");
935 Self::X86
936 }
937 () if cfg!(target_arch = "arm") => {
938 info!("Detected host arch as arm");
939 Self::ARM
940 }
941 () if cfg!(target_arch = "aarch64") => {
942 info!("Detected host arch as aarch64");
943 Self::ARM64
944 }
945 () if cfg!(target_arch = "riscv32") => {
946 info!("Detected host arch as riscv32");
947 Self::RISCV
948 }
949 () if cfg!(target_arch = "riscv64") => {
950 info!("Detected host arch as riscv64");
951 Self::RISCV
952 }
953 () => {
954 if cfg!(target_arch = "x86_64") {
955 info!("Detected host arch as x86-64");
956 } else {
957 info!("Failed to detect host arch, defaulting to x86-64");
958 }
959 Self::X86_64 }
961 }
962 }
963}
964
965impl std::fmt::Display for Arch {
966 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
967 match self {
968 Self::ARM => write!(f, "arm")?,
969 Self::ARM64 => write!(f, "arm64")?,
970 Self::Avr => write!(f, "avr")?,
971 Self::Mips => write!(f, "mips")?,
972 Self::MOS6502 => write!(f, "6502")?,
973 Self::PowerISA => write!(f, "power-isa")?,
974 Self::RISCV => write!(f, "riscv")?,
975 Self::X86 => write!(f, "x86")?,
976 Self::X86_64 => write!(f, "x86-64")?,
977 Self::X86_AND_X86_64 => write!(f, "x86/x86-64")?,
978 Self::Z80 => write!(f, "z80")?,
979 Self::None => write!(f, "None")?,
980 }
981 Ok(())
982 }
983}
984
985#[derive(
986 Debug,
987 Display,
988 Default,
989 Hash,
990 PartialEq,
991 Eq,
992 Clone,
993 Copy,
994 EnumString,
995 AsRefStr,
996 Serialize,
997 Deserialize,
998 Encode,
999 BorrowDecode,
1000 JsonSchema,
1001)]
1002pub enum Assembler {
1003 #[strum(serialize = "avr")]
1004 #[serde(rename = "avr")]
1005 Avr,
1006 #[strum(serialize = "ca65")]
1007 #[serde(rename = "ca65")]
1008 Ca65,
1009 #[strum(serialize = "fasm")]
1010 #[serde(rename = "fasm")]
1011 Fasm,
1012 #[default]
1013 #[strum(serialize = "gas")]
1014 #[serde(rename = "gas")]
1015 Gas,
1016 #[strum(serialize = "go")]
1017 #[serde(rename = "go")]
1018 Go,
1019 #[strum(serialize = "mars")]
1020 #[serde(rename = "mars")]
1021 Mars,
1022 #[strum(serialize = "masm")]
1023 #[serde(rename = "masm")]
1024 Masm,
1025 #[strum(serialize = "nasm")]
1026 #[serde(rename = "nasm")]
1027 Nasm,
1028 #[serde(skip)]
1029 None,
1030}
1031
1032impl ArchOrAssembler for Assembler {}
1033
1034impl Assembler {
1035 pub fn setup_directives(self, names_to_directives: &mut HashMap<(Self, String), Directive>) {
1041 macro_rules! load_directives_with_path {
1042 ($assembler:expr, $path:literal) => {{
1043 let start = std::time::Instant::now();
1044 let serialized_dirs = include_bytes!($path);
1045 let directives = bincode::borrow_decode_from_slice::<Vec<Directive>, _>(serialized_dirs, BINCODE_CFG)
1046 .unwrap_or_else(|e| panic!("Error deserializing {} directives -- {}\nRegenerate serialized data with regenerate.sh", $assembler, e))
1047 .0;
1048
1049 info!(
1050 "{} directive set loaded in {}ms",
1051 $assembler,
1052 start.elapsed().as_millis()
1053 );
1054
1055 populate_name_to_directive_map($assembler, &directives, names_to_directives);
1056 }};
1057 }
1058
1059 match self {
1060 Self::Avr => load_directives_with_path!(Self::Avr, "serialized/directives/avr"),
1061 Self::Ca65 => load_directives_with_path!(Self::Ca65, "serialized/directives/ca65"),
1062 Self::Fasm => load_directives_with_path!(Self::Fasm, "serialized/directives/fasm"),
1063 Self::Gas => load_directives_with_path!(Self::Gas, "serialized/directives/gas"),
1064 Self::Go => warn!("There is currently no Go-specific assembler documentation"),
1065 Self::Mars => load_directives_with_path!(Self::Mars, "serialized/directives/mars"),
1066 Self::Masm => load_directives_with_path!(Self::Masm, "serialized/directives/masm"),
1067 Self::Nasm => load_directives_with_path!(Self::Nasm, "serialized/directives/nasm"),
1068 Self::None => unreachable!(),
1069 }
1070 }
1071}
1072
1073#[derive(
1074 Debug,
1075 Hash,
1076 PartialEq,
1077 Eq,
1078 Clone,
1079 Copy,
1080 EnumString,
1081 AsRefStr,
1082 Display,
1083 Serialize,
1084 Deserialize,
1085 Encode,
1086 BorrowDecode,
1087)]
1088pub enum RegisterType {
1089 #[strum(serialize = "General Purpose Register")]
1090 GeneralPurpose,
1091 #[strum(serialize = "Special Purpose Register")]
1092 SpecialPurpose,
1093 #[strum(serialize = "Pointer Register")]
1094 Pointer,
1095 #[strum(serialize = "Segment Register")]
1096 Segment,
1097 #[strum(serialize = "Flag Register")]
1098 Flag,
1099 #[strum(serialize = "Control Register")]
1100 Control,
1101 #[strum(serialize = "Extended Control Register")]
1102 ExtendedControl,
1103 #[strum(serialize = "Machine State Register")]
1104 MSR,
1105 #[strum(serialize = "Debug Register")]
1106 Debug,
1107 #[strum(serialize = "Test Register")]
1108 Test,
1109 #[strum(serialize = "Protected Mode Register")]
1110 ProtectedMode,
1111 #[strum(serialize = "Floating Point Register")]
1112 FloatingPoint,
1113}
1114
1115#[derive(
1116 Debug,
1117 Hash,
1118 PartialEq,
1119 Eq,
1120 Clone,
1121 Copy,
1122 EnumString,
1123 AsRefStr,
1124 Display,
1125 Serialize,
1126 Deserialize,
1127 Encode,
1128 BorrowDecode,
1129)]
1130pub enum RegisterWidth {
1131 #[strum(serialize = "512 bits")]
1132 Bits512,
1133 #[strum(serialize = "256 bits")]
1134 Bits256,
1135 #[strum(serialize = "128 bits")]
1136 Bits128,
1137 #[strum(serialize = "32(64) bits")]
1138 Bits32Or64,
1139 #[strum(serialize = "64 bits")]
1140 Bits64,
1141 #[strum(serialize = "48 bits")]
1142 Bits48,
1143 #[strum(serialize = "32 bits")]
1144 Bits32,
1145 #[strum(serialize = "16 bits")]
1146 Bits16,
1147 #[strum(serialize = "8 bits")]
1148 Bits8,
1149 #[strum(serialize = "8 high bits of lower 16 bits")]
1150 Upper8Lower16,
1151 #[strum(serialize = "8 lower bits")]
1152 Lower8Lower16,
1153}
1154
1155#[derive(
1156 Debug, Clone, PartialEq, Eq, Hash, Serialize, Default, Deserialize, Encode, BorrowDecode,
1157)]
1158pub struct RegisterBitInfo {
1159 pub bit: u32,
1160 pub label: String,
1161 pub description: String,
1162 pub pae: String,
1163 pub long_mode: String,
1164}
1165
1166impl std::fmt::Display for RegisterBitInfo {
1167 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1168 let mut s = if self.label.is_empty() {
1169 format!("{:2}: {}", self.bit, self.description)
1170 } else {
1171 format!("{:2}: {} - {}", self.bit, self.label, self.description)
1172 };
1173 if !self.pae.is_empty() {
1174 write!(s, ", PAE: {}", self.pae)?;
1175 }
1176 if !self.long_mode.is_empty() {
1177 write!(s, " , Long Mode: {}", self.long_mode)?;
1178 }
1179
1180 write!(f, "{s}")?;
1181 Ok(())
1182 }
1183}
1184
1185#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
1186pub struct RootConfig {
1187 pub default_config: Option<Config>,
1188 #[serde(rename = "project")]
1189 pub projects: Option<Vec<ProjectConfig>>,
1190}
1191
1192impl Default for RootConfig {
1193 fn default() -> Self {
1194 Self {
1195 default_config: Some(Config::default()),
1196 projects: None,
1197 }
1198 }
1199}
1200
1201impl RootConfig {
1202 #[must_use]
1208 pub fn get_project<'a>(&'a self, request_path: &PathBuf) -> Option<&'a ProjectConfig> {
1209 if let Some(projects) = &self.projects {
1210 for project in projects {
1211 if (project.path.is_dir() && request_path.starts_with(&project.path))
1212 || (project.path.is_file() && request_path.eq(&project.path))
1213 {
1214 return Some(project);
1215 }
1216 }
1217 }
1218
1219 None
1220 }
1221
1222 pub fn get_config<'a>(&'a self, req_uri: &'a Uri) -> &'a Config {
1230 let request_path = match process_uri(req_uri) {
1231 UriConversion::Canonicalized(p) => p,
1232 UriConversion::Unchecked(p) => {
1233 warn!(
1234 "Failed to canonicalize request path {}, using {}",
1235 req_uri.path().as_str(),
1236 p.display()
1237 );
1238 p
1239 }
1240 };
1241 if let Some(project) = self.get_project(&request_path) {
1242 info!(
1243 "Selected project config with path \"{}\"",
1244 project.path.display()
1245 );
1246 return &project.config;
1247 }
1248 if let Some(root) = &self.default_config {
1249 info!("Selected root config");
1250 return root;
1251 }
1252
1253 panic!(
1254 "Invalid configuration for \"{}\" -- Must contain a per-project configuration or default",
1255 req_uri.path()
1256 );
1257 }
1258
1259 #[must_use]
1263 pub fn effective_arches(&self) -> Vec<Arch> {
1264 let mut arch_set = HashSet::new();
1265
1266 assert!(self.default_config.is_some());
1269 arch_set.insert(self.default_config.as_ref().unwrap().instruction_set);
1270 if let Some(ref projects) = self.projects {
1271 for project in projects {
1272 arch_set.insert(project.config.instruction_set);
1273 }
1274 }
1275
1276 arch_set.into_iter().collect()
1277 }
1278
1279 #[must_use]
1283 pub fn effective_assemblers(&self) -> Vec<Assembler> {
1284 let mut assembler_set = HashSet::new();
1285
1286 assert!(self.default_config.is_some());
1289 assembler_set.insert(self.default_config.as_ref().unwrap().assembler);
1290 if let Some(ref projects) = self.projects {
1291 for project in projects {
1292 assembler_set.insert(project.config.assembler);
1293 }
1294 }
1295
1296 assembler_set.into_iter().collect()
1297 }
1298
1299 #[must_use]
1300 pub fn is_isa_enabled(&self, isa: Arch) -> bool {
1301 if let Some(ref root) = self.default_config
1302 && root.is_isa_enabled(isa)
1303 {
1304 return true;
1305 }
1306
1307 if let Some(ref projects) = self.projects {
1308 for project in projects {
1309 if project.config.is_isa_enabled(isa) {
1310 return true;
1311 }
1312 }
1313 }
1314
1315 false
1316 }
1317
1318 #[must_use]
1319 pub fn is_assembler_enabled(&self, assembler: Assembler) -> bool {
1320 if let Some(ref root) = self.default_config
1321 && root.is_assembler_enabled(assembler)
1322 {
1323 return true;
1324 }
1325
1326 if let Some(ref projects) = self.projects {
1327 for project in projects {
1328 if project.config.is_assembler_enabled(assembler) {
1329 return true;
1330 }
1331 }
1332 }
1333
1334 false
1335 }
1336}
1337
1338#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
1339pub struct ProjectConfig {
1340 pub path: PathBuf,
1343 #[serde(flatten)]
1346 pub config: Config,
1347}
1348
1349#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
1350pub struct Config {
1351 pub version: Option<String>,
1352 pub assembler: Assembler,
1353 pub instruction_set: Arch,
1354 pub opts: Option<ConfigOptions>,
1355}
1356
1357impl Default for Config {
1358 fn default() -> Self {
1359 Self {
1360 version: None,
1361 assembler: Assembler::default(),
1362 instruction_set: Arch::default(),
1363 opts: Some(ConfigOptions::default()),
1364 }
1365 }
1366}
1367
1368impl Config {
1369 #[allow(clippy::missing_const_for_fn)]
1370 #[must_use]
1371 pub fn get_compiler(&self) -> Option<&str> {
1372 match self.opts {
1373 Some(ConfigOptions {
1374 compiler: Some(ref compiler),
1375 ..
1376 }) => Some(compiler),
1377 _ => None,
1378 }
1379 }
1380
1381 #[must_use]
1382 pub const fn get_compile_flags_txt(&self) -> Option<&Vec<String>> {
1383 match self.opts {
1384 Some(ConfigOptions {
1385 compile_flags_txt: Some(ref flags),
1386 ..
1387 }) => Some(flags),
1388 _ => None,
1389 }
1390 }
1391
1392 #[must_use]
1393 pub fn is_isa_enabled(&self, isa: Arch) -> bool {
1394 match self.instruction_set {
1395 Arch::X86_AND_X86_64 => {
1396 isa == Arch::X86 || isa == Arch::X86_64 || isa == Arch::X86_AND_X86_64
1397 }
1398 arch => isa == arch,
1400 }
1401 }
1402
1403 #[must_use]
1404 pub fn is_assembler_enabled(&self, assembler: Assembler) -> bool {
1405 self.assembler == assembler
1406 }
1407}
1408
1409#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
1410pub struct ConfigOptions {
1411 pub compiler: Option<String>,
1413 pub compile_flags_txt: Option<Vec<String>>,
1417 pub diagnostics: Option<bool>,
1419 pub default_diagnostics: Option<bool>,
1421}
1422
1423impl Default for ConfigOptions {
1424 fn default() -> Self {
1425 Self {
1426 compiler: None,
1427 compile_flags_txt: None,
1428 diagnostics: Some(true),
1429 default_diagnostics: Some(true),
1430 }
1431 }
1432}
1433
1434#[derive(
1436 Debug,
1437 Copy,
1438 Clone,
1439 PartialEq,
1440 Eq,
1441 Hash,
1442 EnumString,
1443 AsRefStr,
1444 Serialize,
1445 Deserialize,
1446 Encode,
1447 BorrowDecode,
1448)]
1449pub enum ISA {
1450 #[strum(serialize = "RAO-INT")]
1451 RAOINT,
1452 GFNI,
1453 VAES,
1454 VPCLMULQDQ,
1455 RDTSC,
1456 RDTSCP,
1457 CPUID,
1458 CMOV,
1459 CMPCCXADD,
1460 CMPXCHG8B,
1461 CMPXCHG16B,
1462 #[strum(serialize = "CET-IBT")]
1463 CETIBT,
1464 MMX,
1465 #[strum(serialize = "MMX+")]
1466 MMXPlus,
1467 FEMMS,
1468 #[strum(serialize = "3dnow!")]
1469 _3DNow,
1470 #[strum(serialize = "3dnow!+")]
1471 _3DNowPlus,
1472 #[strum(serialize = "3dnow! Geode")]
1473 _3DNowGeode,
1474 SM3,
1475 SM4,
1476 SSE,
1477 SSE2,
1478 SSE3,
1479 SSSE3,
1480 #[strum(serialize = "SSE4.1")]
1481 SSE4_1, #[strum(serialize = "SSE4.2")]
1483 SSE4_2, SSE4A,
1485 #[strum(serialize = "AMX-TILE")]
1486 AMXTILE,
1487 #[strum(serialize = "AMX-COMPLEX")]
1488 AMXCOMPLEX,
1489 #[strum(serialize = "AMX-INT8")]
1490 AMXINT8,
1491 #[strum(serialize = "AMX-BF16")]
1492 AMXBF16,
1493 #[strum(serialize = "AMX-FP16")]
1494 AMXFP16,
1495 AVX,
1496 AVX2,
1497 XOP,
1498 FMA3,
1499 FMA4,
1500 F16C,
1501 PCLMULQDQ,
1502 AES,
1503 SHA,
1504 SHA512,
1505 RDRAND,
1506 RDSEED,
1507 RDPID,
1508 RDPMC,
1509 RDPRU,
1510 MOVBE,
1511 MOVDIRI,
1512 MOVDIR64B,
1513 POPCNT,
1514 LZCNT,
1515 BMI,
1516 BMI2,
1517 TBM,
1518 ADX,
1519 CLDEMOTE,
1520 CLFLUSH,
1521 CLFLUSHOPT,
1522 CLWB,
1523 LAHFSAHF,
1524 FSGSBASE,
1525 MCOMMIT,
1526 CLZERO,
1527 PREFETCH,
1528 PREFETCHI,
1529 PREFETCHW,
1530 PREFETCHWT1,
1531 MONITOR,
1532 MONITORX,
1533 SERIALIZE,
1534 WAITPKG,
1535 AVX512F,
1536 AVX512BW,
1537 AVX512DQ,
1538 AVX512VL,
1539 AVX512PF,
1540 AVX512ER,
1541 AVX512CD,
1542 #[strum(serialize = "AVX512-IFMA")]
1543 AVX512IFMA,
1544 #[strum(serialize = "AVX512-VPOPCNTDQ")]
1545 AVX512VPOPCNTDQ,
1546 #[strum(serialize = "AVX512-BF16")]
1547 AVX512BF16,
1548 #[strum(serialize = "AVX512-FP16")]
1549 AVX512FP16,
1550 #[strum(serialize = "AVX512-BITALG")]
1551 AVX512BITALG,
1552 #[strum(serialize = "AVX512-VBMI")]
1553 AVX512VBMI,
1554 #[strum(serialize = "AVX512-VBMI2")]
1555 AVX512VBMI2,
1556 #[strum(serialize = "AVX512-VNNI")]
1557 AVX512VNNI,
1558 #[strum(serialize = "AVX-VNNI")]
1559 AVXVNNI,
1560 #[strum(serialize = "AVX-VNNI-INT8")]
1561 AVXVNNIINT8,
1562 #[strum(serialize = "AVX-VNNI-INT16")]
1563 AVXVNNIINT16,
1564 #[strum(serialize = "AVX-NE-CONVERT")]
1565 AVXNECONVERT,
1566 #[strum(serialize = "AVX-IFMA")]
1567 AVXIFMA,
1568 A64,
1570}
1571
1572#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize, Encode, BorrowDecode)]
1574pub struct Operand {
1575 pub type_: OperandType,
1576 pub input: Option<bool>,
1577 pub output: Option<bool>,
1578 pub extended_size: Option<usize>,
1579}
1580
1581#[allow(non_camel_case_types)]
1582#[derive(
1583 Debug,
1584 Clone,
1585 PartialEq,
1586 Eq,
1587 Hash,
1588 EnumString,
1589 AsRefStr,
1590 Serialize,
1591 Deserialize,
1592 Encode,
1593 BorrowDecode,
1594)]
1595pub enum OperandType {
1596 #[strum(serialize = "1")]
1597 _1,
1598 #[strum(serialize = "3")]
1599 _3,
1600 imm4,
1601 imm8,
1602 imm16,
1603 imm32,
1604 imm64,
1605 al,
1606 cl,
1607 r8,
1608 r8l,
1609 ax,
1610 r16,
1611 r16l,
1612 eax,
1613 r32,
1614 r32l,
1615 rax,
1616 r64,
1617 mm,
1618 xmm0,
1619 xmm,
1620 #[strum(serialize = "xmm{k}")]
1621 xmm_k,
1622 #[strum(serialize = "xmm{k}{z}")]
1623 xmm_k_z,
1624 ymm,
1625 #[strum(serialize = "ymm{k}")]
1626 ymm_k,
1627 #[strum(serialize = "ymm{k}{z}")]
1628 ymm_k_z,
1629 zmm,
1630 #[strum(serialize = "zmm{k}")]
1631 zmm_k,
1632 #[strum(serialize = "zmm{k}{z}")]
1633 zmm_k_z,
1634 k,
1635 #[strum(serialize = "k{k}")]
1636 k_k,
1637 moffs32,
1638 moffs64,
1639 m,
1640 m8,
1641 m16,
1642 #[strum(serialize = "m16{k}")]
1643 m16_k,
1644 #[strum(serialize = "m16{k}{z}")]
1645 m16_k_z,
1646 m32,
1647 #[strum(serialize = "m32{k}")]
1648 m32_k,
1649 #[strum(serialize = "m32{k}{z}")]
1650 m32_k_z,
1651 #[strum(serialize = "m32/m16bcst")]
1652 m32_m16bcst,
1653 m64,
1654 #[strum(serialize = "m64{k}")]
1655 m64_k,
1656 #[strum(serialize = "m64{k}{z}")]
1657 m64_k_z,
1658 #[strum(serialize = "m64/m16bcst")]
1659 m64_m16bcst,
1660 m128,
1661 #[strum(serialize = "m128{k}")]
1662 m128_k,
1663 #[strum(serialize = "m128{k}{z}")]
1664 m128_k_z,
1665 m256,
1666 #[strum(serialize = "m256{k}")]
1667 m256_k,
1668 #[strum(serialize = "m256{k}{z}")]
1669 m256_k_z,
1670 m512,
1671 #[strum(serialize = "m512{k}")]
1672 m512_k,
1673 #[strum(serialize = "m512{k}{z}")]
1674 m512_k_z,
1675 #[strum(serialize = "m64/m32bcst")]
1676 m64_m32bcst,
1677 #[strum(serialize = "m128/m32bcst")]
1678 m128_m32bcst,
1679 #[strum(serialize = "m256/m32bcst")]
1680 m256_m32bcst,
1681 #[strum(serialize = "m512/m32bcst")]
1682 m512_m32bcst,
1683 #[strum(serialize = "m128/m16bcst")]
1684 m128_m16bcst,
1685 #[strum(serialize = "m128/m64bcst")]
1686 m128_m64bcst,
1687 #[strum(serialize = "m256/m16bcst")]
1688 m256_m16bcst,
1689 #[strum(serialize = "m256/m64bcst")]
1690 m256_m64bcst,
1691 #[strum(serialize = "m512/m16bcst")]
1692 m512_m16bcst,
1693 #[strum(serialize = "m512/m64bcst")]
1694 m512_m64bcst,
1695 vm32x,
1696 #[strum(serialize = "vm32x{k}")]
1697 vm32x_k,
1698 vm64x,
1699 #[strum(serialize = "vm64x{k}")]
1700 vm64xk,
1701 vm32y,
1702 #[strum(serialize = "vm32y{k}")]
1703 vm32yk_,
1704 vm64y,
1705 #[strum(serialize = "vm64y{k}")]
1706 vm64y_k,
1707 vm32z,
1708 #[strum(serialize = "vm32z{k}")]
1709 vm32z_k,
1710 vm64z,
1711 #[strum(serialize = "vm64z{k}")]
1712 vm64z_k,
1713 rel8,
1714 rel32,
1715 rel32m,
1716 #[strum(serialize = "{er}")]
1717 er,
1718 #[strum(serialize = "{sae}")]
1719 sae,
1720 sibmem,
1721 tmm,
1722
1723 Rd,
1725 Rr,
1726 X,
1727 Y,
1728 Z,
1729 #[strum(serialize = "-X")]
1730 NegX,
1731 #[strum(serialize = "-Y")]
1732 NegY,
1733 #[strum(serialize = "-Z")]
1734 NegZ,
1735 #[strum(serialize = "X+")]
1736 XPlus,
1737 #[strum(serialize = "Y+")]
1738 YPlus,
1739 #[strum(serialize = "Z+")]
1740 ZPlus,
1741 #[strum(serialize = "Y+q")]
1742 YPlusQ,
1743 #[strum(serialize = "Z+q")]
1744 ZPlusQ,
1745 A,
1746 K,
1747 s,
1749 b,
1750}
1751
1752pub type Column = usize;
1756
1757pub struct TreeEntry {
1759 pub tree: Option<Tree>,
1760 pub parser: Parser,
1761}
1762
1763pub type TreeStore = BTreeMap<Uri, TreeEntry>;
1765
1766#[derive(Default)]
1767pub struct DocumentStore {
1768 pub tree_store: TreeStore,
1769 pub text_store: TextDocuments,
1770}
1771
1772impl DocumentStore {
1773 #[must_use]
1774 pub fn new() -> Self {
1775 Self {
1776 tree_store: TreeStore::new(),
1777 text_store: TextDocuments::new(),
1778 }
1779 }
1780}
1781
1782#[derive(Debug, Clone, Default)]
1783pub struct CompletionItems {
1784 pub instructions: Vec<(Arch, CompletionItem)>,
1785 pub registers: Vec<(Arch, CompletionItem)>,
1786 pub directives: Vec<(Assembler, CompletionItem)>,
1787}
1788
1789impl CompletionItems {
1790 #[must_use]
1791 pub const fn new() -> Self {
1792 Self {
1793 instructions: Vec::new(),
1794 registers: Vec::new(),
1795 directives: Vec::new(),
1796 }
1797 }
1798}
1799
1800#[derive(Default, Debug)]
1802pub struct ServerStore {
1803 pub names_to_info: NameToInfoMaps,
1805 pub completion_items: CompletionItems,
1807 pub compile_commands: CompilationDatabase,
1809 pub include_dirs: HashMap<SourceFile, Vec<PathBuf>>,
1811}