Skip to content

Commit 472fd65

Browse files
committed
Refactor handling of new instructions in the assembler
1 parent 72ef585 commit 472fd65

File tree

1 file changed

+41
-107
lines changed

1 file changed

+41
-107
lines changed

crates/polkavm-common/src/assembler.rs

Lines changed: 41 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::program::{Instruction, Reg};
1+
use crate::program::{Instruction, RawReg, Reg};
22
use crate::utils::{parse_imm, parse_immediate, parse_reg, ParsedImmediate};
33
use alloc::borrow::ToOwned;
44
use alloc::collections::BTreeMap;
@@ -437,69 +437,29 @@ pub fn assemble(code: &str) -> Result<Vec<u8>, String> {
437437
}
438438
}
439439

440-
if let Some(index) = rhs.find("cpop ") {
441-
if let Some(src) = parse_reg(rhs[index + 5..].trim()) {
442-
match op_marker {
443-
OpMarker::I32 => {
444-
emit_and_continue!(Instruction::count_set_bits_32(dst.into(), src.into()));
445-
}
446-
OpMarker::NONE => {
447-
emit_and_continue!(Instruction::count_set_bits_64(dst.into(), src.into()));
448-
}
449-
}
450-
}
451-
}
452-
453-
if let Some(index) = rhs.find("clz ") {
454-
if let Some(src) = parse_reg(rhs[index + 4..].trim()) {
455-
match op_marker {
456-
OpMarker::I32 => {
457-
emit_and_continue!(Instruction::count_leading_zero_bits_32(dst.into(), src.into()));
458-
}
459-
OpMarker::NONE => {
460-
emit_and_continue!(Instruction::count_leading_zero_bits_64(dst.into(), src.into()));
461-
}
462-
}
463-
}
464-
}
465-
466-
if let Some(index) = rhs.find("ctz ") {
467-
if let Some(src) = parse_reg(rhs[index + 4..].trim()) {
468-
match op_marker {
469-
OpMarker::I32 => {
470-
emit_and_continue!(Instruction::count_trailing_zero_bits_32(dst.into(), src.into()));
471-
}
472-
OpMarker::NONE => {
473-
emit_and_continue!(Instruction::count_trailing_zero_bits_64(dst.into(), src.into()));
474-
}
440+
if let Some((name, rhs)) = split(rhs, " ") {
441+
if let Some(src) = parse_reg(rhs) {
442+
type F = fn(RawReg, RawReg) -> Instruction;
443+
let ctor = match (name, op_marker) {
444+
("cpop", OpMarker::I32) => Some(Instruction::count_set_bits_32 as F),
445+
("cpop", OpMarker::NONE) => Some(Instruction::count_set_bits_64 as F),
446+
("clz", OpMarker::I32) => Some(Instruction::count_leading_zero_bits_32 as F),
447+
("clz", OpMarker::NONE) => Some(Instruction::count_leading_zero_bits_64 as F),
448+
("ctz", OpMarker::I32) => Some(Instruction::count_trailing_zero_bits_32 as F),
449+
("ctz", OpMarker::NONE) => Some(Instruction::count_trailing_zero_bits_64 as F),
450+
("sext.b", _) => Some(Instruction::sign_extend_8 as F),
451+
("sext.h", _) => Some(Instruction::sign_extend_16 as F),
452+
("zext.h", _) => Some(Instruction::zero_extend_16 as F),
453+
("reverse", _) => Some(Instruction::reverse_byte as F),
454+
_ => None,
455+
};
456+
457+
if let Some(ctor) = ctor {
458+
emit_and_continue!(ctor(dst.into(), src.into()));
475459
}
476460
}
477461
}
478462

479-
if let Some(index) = rhs.find("sext.b ") {
480-
if let Some(src) = parse_reg(rhs[index + 7..].trim()) {
481-
emit_and_continue!(Instruction::sign_extend_8(dst.into(), src.into()));
482-
}
483-
}
484-
485-
if let Some(index) = rhs.find("sext.h ") {
486-
if let Some(src) = parse_reg(rhs[index + 7..].trim()) {
487-
emit_and_continue!(Instruction::sign_extend_16(dst.into(), src.into()));
488-
}
489-
}
490-
491-
if let Some(index) = rhs.find("zext.h ") {
492-
if let Some(src) = parse_reg(rhs[index + 7..].trim()) {
493-
emit_and_continue!(Instruction::zero_extend_16(dst.into(), src.into()));
494-
}
495-
}
496-
497-
if let Some(index) = rhs.find("reverse ") {
498-
if let Some(src) = parse_reg(rhs[index + 8..].trim()) {
499-
emit_and_continue!(Instruction::reverse_byte(dst.into(), src.into()));
500-
}
501-
}
502-
503463
if let Some(src) = parse_reg(rhs) {
504464
emit_and_continue!(Instruction::move_reg(dst.into(), src.into()));
505465
}
@@ -519,14 +479,9 @@ pub fn assemble(code: &str) -> Result<Vec<u8>, String> {
519479
emit_and_continue!(MaybeInstruction::LoadLabelAddress(dst, label.to_owned()));
520480
}
521481

522-
if let Some(index) = rhs.find("~(") {
523-
let rhs = rhs[index + 2..].trim();
524-
if let Some(index) = rhs.find(')') {
525-
let rhs = rhs[..index].trim();
526-
if let Some(index) = rhs.find('^') {
527-
let src1 = rhs[..index].trim();
528-
let src2 = rhs[index + 1..].trim();
529-
482+
if let Some(rhs) = rhs.strip_prefix("~(") {
483+
if let Some(rhs) = rhs.strip_suffix(')') {
484+
if let Some((src1, src2)) = split(rhs.trim(), "^") {
530485
if let Some(src1) = parse_reg(src1) {
531486
if let Some(src2) = parse_reg(src2) {
532487
let dst = dst.into();
@@ -884,45 +839,24 @@ pub fn assemble(code: &str) -> Result<Vec<u8>, String> {
884839
}
885840
}
886841

887-
enum MaxMinOp {
888-
Max,
889-
MaxUnsigned,
890-
Min,
891-
MinUnsigned,
892-
}
893-
894-
#[allow(clippy::manual_map)]
895-
let min_max_op = if let Some(index) = rhs.find("maxs(") {
896-
Some((index, 5, MaxMinOp::Max))
897-
} else if let Some(index) = rhs.find("maxu(") {
898-
Some((index, 5, MaxMinOp::MaxUnsigned))
899-
} else if let Some(index) = rhs.find("mins(") {
900-
Some((index, 5, MaxMinOp::Min))
901-
} else if let Some(index) = rhs.find("minu(") {
902-
Some((index, 5, MaxMinOp::MinUnsigned))
903-
} else {
904-
None
905-
};
906-
907-
if let Some((index, op_len, op)) = min_max_op {
908-
let rhs = rhs[index + op_len..].trim();
909-
if let Some(index) = rhs.find(')') {
910-
let rhs = rhs[..index].trim();
911-
if let Some(index) = rhs.find(',') {
912-
let src1 = rhs[..index].trim();
913-
let src2 = rhs[index + 1..].trim();
914-
915-
if let Some(src1) = parse_reg(src1) {
916-
if let Some(src2) = parse_reg(src2) {
917-
let dst = dst.into();
918-
let src1 = src1.into();
919-
let src2 = src2.into();
920-
emit_and_continue!(match op {
921-
MaxMinOp::Max => Instruction::maximum(dst, src1, src2),
922-
MaxMinOp::MaxUnsigned => Instruction::maximum_unsigned(dst, src1, src2),
923-
MaxMinOp::Min => Instruction::minimum(dst, src1, src2),
924-
MaxMinOp::MinUnsigned => Instruction::minimum_unsigned(dst, src1, src2),
925-
});
842+
if let Some(rhs) = rhs.strip_suffix(')') {
843+
let rhs = rhs.trim();
844+
if let Some((name, rhs)) = split(rhs, "(") {
845+
type F = fn(RawReg, RawReg, RawReg) -> Instruction;
846+
let ctor = match name {
847+
"maxs" => Some(Instruction::maximum as F),
848+
"maxu" => Some(Instruction::maximum_unsigned as F),
849+
"mins" => Some(Instruction::minimum as F),
850+
"minu" => Some(Instruction::minimum_unsigned as F),
851+
_ => None,
852+
};
853+
854+
if let Some(ctor) = ctor {
855+
if let Some((src1, src2)) = split(rhs, ",") {
856+
if let Some(src1) = parse_reg(src1) {
857+
if let Some(src2) = parse_reg(src2) {
858+
emit_and_continue!(ctor(dst.into(), src1.into(), src2.into()));
859+
}
926860
}
927861
}
928862
}

0 commit comments

Comments
 (0)