Skip to content

Commit

Permalink
feat: support AVR opcodes
Browse files Browse the repository at this point in the history
  • Loading branch information
WillLillis committed Feb 1, 2025
1 parent b74fc0f commit 0091f61
Show file tree
Hide file tree
Showing 25 changed files with 684 additions and 11 deletions.
446 changes: 445 additions & 1 deletion asm-lsp/parser.rs

Large diffs are not rendered by default.

Binary file modified asm-lsp/serialized/directives/avr
Binary file not shown.
Binary file modified asm-lsp/serialized/directives/gas
Binary file not shown.
Binary file modified asm-lsp/serialized/directives/masm
Binary file not shown.
Binary file modified asm-lsp/serialized/directives/nasm
Binary file not shown.
Binary file modified asm-lsp/serialized/opcodes/arm
Binary file not shown.
Binary file modified asm-lsp/serialized/opcodes/arm64
Binary file not shown.
Binary file added asm-lsp/serialized/opcodes/avr
Binary file not shown.
Binary file modified asm-lsp/serialized/opcodes/riscv
Binary file not shown.
Binary file modified asm-lsp/serialized/opcodes/x86
Binary file not shown.
Binary file modified asm-lsp/serialized/opcodes/x86_64
Binary file not shown.
Binary file modified asm-lsp/serialized/opcodes/z80
Binary file not shown.
Binary file modified asm-lsp/serialized/registers/6502
Binary file not shown.
Binary file modified asm-lsp/serialized/registers/arm
Binary file not shown.
Binary file modified asm-lsp/serialized/registers/arm64
Binary file not shown.
Binary file modified asm-lsp/serialized/registers/avr
Binary file not shown.
Binary file modified asm-lsp/serialized/registers/power-isa
Binary file not shown.
Binary file modified asm-lsp/serialized/registers/x86
Binary file not shown.
Binary file modified asm-lsp/serialized/registers/x86_64
Binary file not shown.
Binary file modified asm-lsp/serialized/registers/z80
Binary file not shown.
113 changes: 110 additions & 3 deletions asm-lsp/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ mod tests {
z80_registers: Vec<Register>,
mos6502_registers: Vec<Register>,
power_isa_registers: Vec<Register>,
avr_instructions: Vec<Instruction>,
avr_registers: Vec<Register>,
gas_directives: Vec<Directive>,
masm_directives: Vec<Directive>,
Expand Down Expand Up @@ -212,6 +213,7 @@ mod tests {
z80_registers: Vec::new(),
mos6502_instructions: Vec::new(),
mos6502_registers: Vec::new(),
avr_instructions: Vec::new(),
avr_registers: Vec::new(),
gas_directives: Vec::new(),
masm_directives: Vec::new(),
Expand Down Expand Up @@ -295,6 +297,13 @@ mod tests {
Vec::new()
};

info.avr_instructions = if config.is_isa_enabled(Arch::Avr) {
let avr_instrs = include_bytes!("serialized/opcodes/avr");
bincode::deserialize::<Vec<Instruction>>(avr_instrs)?
} else {
Vec::new()
};

info.x86_registers = if config.is_isa_enabled(Arch::X86) {
let regs_x86 = include_bytes!("serialized/registers/x86");
bincode::deserialize(regs_x86)?
Expand Down Expand Up @@ -447,6 +456,12 @@ mod tests {
&mut store.names_to_info.instructions,
);

populate_name_to_instruction_map(
Arch::Avr,
&info.avr_instructions,
&mut store.names_to_info.instructions,
);

populate_name_to_register_map(
Arch::X86,
&info.x86_registers,
Expand Down Expand Up @@ -781,7 +796,7 @@ mod tests {
fn handle_hover_avr_arch_it_provides_reg_info_1() {
test_hover(
"ldi r1<cursor>6,0xC0",
"R16 [avr]
"R16 [AVR]
General purpose register 16. Mapped to address 0x10.
Type: General Purpose Register
Expand All @@ -793,7 +808,7 @@ Width: 8 bits",
fn handle_hover_avr_arch_it_provides_reg_info_2() {
test_hover(
"clr r<cursor>17",
"R17 [avr]
"R17 [AVR]
General purpose register 17. Mapped to address 0x11.
Type: General Purpose Register
Expand All @@ -805,7 +820,7 @@ Width: 8 bits",
fn handle_hover_avr_arch_it_provides_reg_info_3() {
test_hover(
"x<cursor>",
"X [avr]
"X [AVR]
General purpose X-register. Low byte is r26 and high byte is r27.
Type: General Purpose Register
Expand All @@ -814,6 +829,71 @@ Width: 16 bits",
);
}
#[test]
fn handle_hover_avr_arch_it_provides_instr_info_1() {
test_hover(
"ld<cursor>i r16,0xC0",
"ldi [AVR]
## Forms
- *AVR*: LDI (All)
Load Immediate
+ [Rd]
+ [K]
I T H S V N Z C
- - - - - - - -
Timing: AVRE: 1 | AVRXM: 1 | AVRXT: 1 | AVRRC: 1
",
&avr_arch_test_config(),
);
}
#[test]
fn handle_hover_avr_arch_it_provides_instr_info_2() {
test_hover(
"c<cursor>lr r17",
"clr [AVR]
## Forms
- *AVR*: CLR (All)
Clear Register
+ [Rd]
I T H S V N Z C
- - - 0 0 0 - 1
Timing: AVRE: 1 | AVRXM: 1 | AVRXT: 1 | AVRRC: 1
",
&avr_arch_test_config(),
);
}
#[test]
fn handle_hover_avr_arch_it_provides_instr_info_3() {
test_hover(
" ou<cursor>t 0x25,r16",
"out [AVR]
## Forms
- *AVR*: OUT (All)
Out To I/O Location
+ [A]
+ [Rr]
I T H S V N Z C
- - - - - - - -
Timing: AVRE: 1 | AVRXM: 1 | AVRXT: 1 | AVRRC: 1
",
&avr_arch_test_config(),
);
}
#[test]
fn handle_autocomplete_avr_arch_it_provides_reg_comps_1() {
test_register_autocomplete(
"ldi r<cursor>",
Expand Down Expand Up @@ -841,6 +921,33 @@ Width: 16 bits",
);
}
#[test]
fn handle_autocomplete_avr_arch_it_provides_instr_comps_1() {
test_instruction_autocomplete(
"l<cursor> r1",
&avr_arch_test_config(),
CompletionTriggerKind::INVOKED,
None,
);
}
#[test]
fn handle_autocomplete_avr_arch_it_provides_instr_comps_2() {
test_instruction_autocomplete(
"ld<cursor> r1,0xC0",
&avr_arch_test_config(),
CompletionTriggerKind::INVOKED,
None,
);
}
#[test]
fn handle_autocomplete_avr_arch_it_provides_instr_comps_3() {
test_instruction_autocomplete(
"f<cursor> r16,r1",
&avr_arch_test_config(),
CompletionTriggerKind::INVOKED,
None,
);
}
#[test]
fn handle_autocomplete_avr_assembler_it_provides_dir_comps_no_args() {
test_directive_autocomplete(
".und<cursor>",
Expand Down
126 changes: 122 additions & 4 deletions asm-lsp/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ impl<'own> Instruction {
}
}

// TODO: Rework this to use a tagged union...
// InstructionForm
#[derive(Default, Eq, PartialEq, Hash, Debug, Clone, Serialize, Deserialize)]
pub struct InstructionForm {
Expand All @@ -160,14 +161,20 @@ pub struct InstructionForm {
pub cancelling_inputs: Option<bool>,
pub nacl_version: Option<u8>,
pub nacl_zero_extends_outputs: Option<bool>,
pub operands: Vec<Operand>,
// --- Z80-Specific Information ---
pub z80_name: Option<String>,
pub z80_form: Option<String>,
pub z80_opcode: Option<String>,
pub z80_timing: Option<Z80Timing>,
// --- Avr-Specific Information ---
pub avr_mneumonic: Option<String>,
pub avr_summary: Option<String>,
pub avr_version: Option<String>,
pub avr_timing: Option<AvrTiming>,
pub avr_status_register: Option<AvrStatusRegister>,
// --- Assembler/Architecture Agnostic Info ---
pub isa: Option<ISA>,
pub operands: Vec<Operand>,
pub urls: Vec<String>,
}

Expand All @@ -183,6 +190,13 @@ impl std::fmt::Display for InstructionForm {
if let Some(val) = &self.z80_form {
s += &format!("*Z80*: {val} | ");
}
if let Some(val) = &self.avr_mneumonic {
let version_str = self
.avr_version
.as_ref()
.map_or_else(String::new, |version| format!(" ({version})"));
s += &format!("*AVR*: {val}{version_str} | ",);
}

if let Some(val) = &self.mmx_mode {
s += &(format!("*MMX*: {} | ", val.as_ref()));
Expand Down Expand Up @@ -211,6 +225,10 @@ impl std::fmt::Display for InstructionForm {
s = format!("- {}\n\n", &s[..s.len() - 3]);
}

if let Some(summary) = &self.avr_summary {
s += &format!("\n{summary}\n");
}

// Operands
let operands_str: String = if self.operands.is_empty() {
String::new()
Expand Down Expand Up @@ -241,6 +259,13 @@ impl std::fmt::Display for InstructionForm {
s += &format!("\n + {timing}");
}

if let Some(sreg) = &self.avr_status_register {
s += &format!("\n\n{sreg}\n");
}
if let Some(ref timing) = self.avr_timing {
s += &format!("\n\n{timing}\n");
}

for url in &self.urls {
s += &format!("\n + More info: {url}\n");
}
Expand Down Expand Up @@ -388,6 +413,71 @@ impl Display for Z80Timing {
}
}

#[derive(Default, Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize)]
pub struct AvrTiming {
pub avre: Option<String>,
pub avrxm: Option<String>,
pub avrxt: Option<String>,
pub avrrc: Option<String>,
}

impl Display for AvrTiming {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Timing: ")?;
let mut has_prev = false;
if let Some(ref cycles) = self.avre {
write!(f, "AVRE: {cycles}")?;
has_prev = true;
}
if let Some(ref cycles) = self.avrxm {
if has_prev {
write!(f, " | ")?;
}
write!(f, "AVRXM: {cycles}")?;
has_prev = true;
}
if let Some(ref cycles) = self.avrxt {
if has_prev {
write!(f, " | ")?;
}
write!(f, "AVRXT: {cycles}")?;
has_prev = true;
}
if let Some(ref cycles) = self.avrrc {
if has_prev {
write!(f, " | ")?;
}
write!(f, "AVRRC: {cycles}")?;
}

Ok(())
}
}

#[derive(Default, Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize)]
pub struct AvrStatusRegister {
pub i: char,
pub t: char,
pub h: char,
pub s: char,
pub v: char,
pub n: char,
pub c: char,
pub z: char,
}

impl std::fmt::Display for AvrStatusRegister {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "I T H S V N Z C")?;
writeln!(
f,
"{} {} {} {} {} {} {} {}",
self.i, self.t, self.h, self.s, self.v, self.n, self.c, self.z
)?;
Ok(())
}
}

// Directive
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Directive {
Expand Down Expand Up @@ -669,8 +759,8 @@ pub enum Arch {
#[strum(serialize = "power-isa")]
#[serde(rename = "power-isa")]
PowerISA,
#[strum(serialize = "avr")]
#[serde(rename = "avr")]
#[strum(serialize = "AVR")]
#[serde(rename = "AVR")] // TODO: lower-case this in the generation code
Avr,
/// For testing purposes *only*. This is not a valid config option
#[serde(skip)]
Expand Down Expand Up @@ -766,7 +856,7 @@ impl Arch {
Self::PowerISA => {
load_instructions_with_path!(Self::PowerISA, "serialized/opcodes/power-isa");
}
Self::Avr => warn!("AVR opcodes are not supported"),
Self::Avr => load_instructions_with_path!(Self::Avr, "serialized/opcodes/avr"),
Self::None => unreachable!(),
}
}
Expand Down Expand Up @@ -1520,6 +1610,34 @@ pub enum OperandType {
sae,
sibmem,
tmm,

// Avr operand types
Rd,
Rr,
X,
Y,
Z,
#[strum(serialize = "-X")]
NegX,
#[strum(serialize = "-Y")]
NegY,
#[strum(serialize = "-Z")]
NegZ,
#[strum(serialize = "X+")]
XPlus,
#[strum(serialize = "Y+")]
YPlus,
#[strum(serialize = "Z+")]
ZPlus,
#[strum(serialize = "Y+q")]
YPlusQ,
#[strum(serialize = "Z+q")]
ZPlusQ,
A,
K,
// `k` is already covered
s,
b,
}

// lsp types
Expand Down
3 changes: 2 additions & 1 deletion asm_docs_parsing/regenerate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ cargo build --release
../target/release/asm_docs_parsing ../docs_store/opcodes/z80.xml -o ../asm-lsp/serialized/opcodes/z80 --doc-type instruction
../target/release/asm_docs_parsing ../docs_store/opcodes/6502.html -o ../asm-lsp/serialized/opcodes/6502 --doc-type instruction --arch 6502
../target/release/asm_docs_parsing ../docs_store/opcodes/power-isa.json -o ../asm-lsp/serialized/opcodes/power-isa --doc-type instruction --arch power-isa
../target/release/asm_docs_parsing ../docs_store/opcodes/avr.xml -o ../asm-lsp/serialized/opcodes/avr --doc-type instruction --arch AVR

# register binaries
../target/release/asm_docs_parsing ../docs_store/registers/x86.xml -o ../asm-lsp/serialized/registers/x86 --doc-type register --arch x86
Expand All @@ -27,7 +28,7 @@ cargo build --release
../target/release/asm_docs_parsing ../docs_store/registers/z80.xml -o ../asm-lsp/serialized/registers/z80 --doc-type register --arch z80
../target/release/asm_docs_parsing ../docs_store/registers/6502.xml -o ../asm-lsp/serialized/registers/6502 --doc-type register --arch 6502
../target/release/asm_docs_parsing ../docs_store/registers/power-isa.xml -o ../asm-lsp/serialized/registers/power-isa --doc-type register --arch power-isa
../target/release/asm_docs_parsing ../docs_store/registers/avr.xml -o ../asm-lsp/serialized/registers/avr --doc-type register --arch avr
../target/release/asm_docs_parsing ../docs_store/registers/avr.xml -o ../asm-lsp/serialized/registers/avr --doc-type register --arch AVR

# directive binaries
../target/release/asm_docs_parsing ../docs_store/directives/gas.xml -o ../asm-lsp/serialized/directives/gas --doc-type directive --assembler gas
Expand Down
Loading

0 comments on commit 0091f61

Please sign in to comment.