Parse a trimmed instruction line and push typed `AsmToken`s into `out`. May push more than one token (e.g. `li` expands to up to two real instructions). Unrecognised mnemonics are emitted as `AsmToken::Comment` so nothing is silently lost.
(line: &str, out: &mut Vec<AsmToken>)
| 150 | Directive::Space(n) => out.push(AsmToken::Space(n)), |
| 151 | Directive::Equ(_, _) | Directive::Unknown(_) => {} |
| 152 | } |
| 153 | } |
| 154 | |
| 155 | // --- Parsing raw instruction lines --- |
| 156 | |
| 157 | // May push more than one token (e.g. `li` expands to up to two real instructions). |
| 158 | // Unrecognised mnemonics are emitted as `AsmToken::Comment` so nothing is silently lost. |
| 159 | fn parse_instruction_line(line: &str, out: &mut Vec<AsmToken>) { |
| 160 | // Strip inline `;` or `#` comments before any operand parsing. |
| 161 | let line = match line.find([';', '#']) { |
| 162 | Some(i) => line[..i].trim_end(), |
| 163 | None => line, |
| 164 | }; |
| 165 | if line.is_empty() { |
| 166 | return; |
| 167 | } |
| 168 | let (mnemonic, rest) = split_mnemonic(line); |
| 169 | |
| 170 | // --- Dispatch by mnemonic --- |
| 171 | |
| 172 | // Branch instructions (`bne`, `beq`, `blt`, `bge`, `bltu`, `bgeu`) |
| 173 | if let Some(kind) = BranchKind::from_mnemonic(mnemonic) { |
| 174 | if let Some(tok) = parse_branch(kind, rest) { |
| 175 | out.push(tok); |
| 176 | } |
| 177 | return; |
| 178 | } |
| 179 | |
| 180 | match mnemonic { |
| 181 | // --- Symbol-bearing pseudos --- |
| 182 | "call" => { |
| 183 | let sym = rest.trim().to_owned(); |
| 184 | if !sym.is_empty() { |
| 185 | out.push(AsmToken::Call { symbol: sym }); |
| 186 | } |
| 187 | } |
| 188 | "tail" => { |
| 189 | let sym = rest.trim().to_owned(); |
| 190 | if !sym.is_empty() { |
| 191 | out.push(AsmToken::Tail { symbol: sym }); |
| 192 | } |
| 193 | } |
| 194 | "j" => { |
| 195 | let target = rest.trim().to_owned(); |
| 196 | if !target.is_empty() { |
| 197 | out.push(AsmToken::Jal { rd: 0, target }); |
| 198 | } |
| 199 | } |
| 200 | "jal" => try_parse_or_warn!(out, line, "jal", parse_jal(rest)), |
| 201 | "la" => try_parse_or_warn!(out, line, "la", parse_la(rest)), |
| 202 | "jalr" => { |
| 203 | if let Some((rd, rs1, imm)) = parse_load_mem(rest) { |
| 204 | out.push(AsmToken::Real(RealInstruction::Jalr(Jalr::new( |
| 205 | rd, rs1, imm, |
| 206 | )))); |
| 207 | } else { |
| 208 | asm_warn!(out, "unrecognised jalr: {line}"); |
| 209 | } |
no test coverage detected