instruction.rs 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932
  1. use {
  2. crate::{errors::SBPFError, opcode::Opcode, syscall::SYSCALLS},
  3. core::{fmt, ops::Range},
  4. serde::{Deserialize, Serialize},
  5. };
  6. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
  7. pub struct Register {
  8. pub n: u8,
  9. }
  10. impl fmt::Display for Register {
  11. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  12. write!(f, "r{}", self.n)
  13. }
  14. }
  15. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
  16. pub enum Number {
  17. Int(i64),
  18. Addr(i64),
  19. }
  20. impl fmt::Display for Number {
  21. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  22. match self {
  23. Number::Int(i) => write!(f, "{}", i),
  24. Number::Addr(a) => write!(f, "{}", a),
  25. }
  26. }
  27. }
  28. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
  29. pub struct Instruction {
  30. pub opcode: Opcode,
  31. pub dst: Option<Register>,
  32. pub src: Option<Register>,
  33. pub off: Option<i16>,
  34. pub imm: Option<Number>,
  35. pub span: Range<usize>,
  36. }
  37. impl Instruction {
  38. pub fn get_size(&self) -> u64 {
  39. match self.opcode {
  40. Opcode::Lddw => 16,
  41. _ => 8,
  42. }
  43. }
  44. pub fn is_jump(&self) -> bool {
  45. matches!(
  46. self.opcode,
  47. Opcode::Ja
  48. | Opcode::JeqImm
  49. | Opcode::JgtImm
  50. | Opcode::JgeImm
  51. | Opcode::JltImm
  52. | Opcode::JleImm
  53. | Opcode::JsetImm
  54. | Opcode::JneImm
  55. | Opcode::JsgtImm
  56. | Opcode::JsgeImm
  57. | Opcode::JsltImm
  58. | Opcode::JsleImm
  59. | Opcode::JeqReg
  60. | Opcode::JgtReg
  61. | Opcode::JgeReg
  62. | Opcode::JltReg
  63. | Opcode::JleReg
  64. | Opcode::JsetReg
  65. | Opcode::JneReg
  66. | Opcode::JsgtReg
  67. | Opcode::JsgeReg
  68. | Opcode::JsltReg
  69. | Opcode::JsleReg
  70. )
  71. }
  72. pub fn off_str(&self) -> String {
  73. match self.off {
  74. Some(off) => {
  75. if off.is_negative() {
  76. off.to_string()
  77. } else {
  78. format!("+{}", off)
  79. }
  80. }
  81. None => "0".to_string(),
  82. }
  83. }
  84. pub fn dst_off(&self) -> String {
  85. match &self.dst {
  86. Some(dst) => format!("[r{}{}]", dst.n, self.off_str()),
  87. None => format!("[r0{}]", self.off_str()),
  88. }
  89. }
  90. pub fn src_off(&self) -> String {
  91. match &self.src {
  92. Some(src) => format!("[r{}{}]", src.n, self.off_str()),
  93. None => format!("[r0{}]", self.off_str()),
  94. }
  95. }
  96. pub fn op_imm_bits(&self) -> Result<String, SBPFError> {
  97. match &self.imm {
  98. Some(Number::Int(imm)) => match *imm {
  99. 16 => Ok(format!("{}16", self.opcode)),
  100. 32 => Ok(format!("{}32", self.opcode)),
  101. 64 => Ok(format!("{}64", self.opcode)),
  102. _ => Err(SBPFError::BytecodeError {
  103. error: format!(
  104. "Invalid immediate value: {:?} for opcode: {:?}",
  105. self.imm, self.opcode
  106. ),
  107. span: self.span.clone(),
  108. custom_label: None,
  109. }),
  110. },
  111. _ => Err(SBPFError::BytecodeError {
  112. error: format!("Expected immediate value for opcode: {:?}", self.opcode),
  113. span: self.span.clone(),
  114. custom_label: None,
  115. }),
  116. }
  117. }
  118. pub fn from_bytes(bytes: &[u8]) -> Result<Self, SBPFError> {
  119. let span = 0..bytes.len();
  120. let opcode = Opcode::from_u8(bytes[0]).ok_or(SBPFError::BytecodeError {
  121. error: format!("Invalid opcode: {:?}", bytes[0]),
  122. span: span.clone(),
  123. custom_label: None,
  124. })?;
  125. let reg = bytes[1];
  126. let src = reg >> 4;
  127. let dst = reg & 0x0f;
  128. let off = i16::from_le_bytes([bytes[2], bytes[3]]);
  129. let imm = match opcode {
  130. Opcode::Lddw => {
  131. let imm_low = i32::from_le_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]);
  132. let imm_high = i32::from_le_bytes([bytes[12], bytes[13], bytes[14], bytes[15]]);
  133. ((imm_high as i64) << 32) | (imm_low as u32 as i64)
  134. }
  135. _ => i32::from_le_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]) as i64,
  136. };
  137. let mut out_dst: Option<Register> = None;
  138. let mut out_src: Option<Register> = None;
  139. let mut out_off: Option<i16> = None;
  140. let mut out_imm: Option<Number> = None;
  141. match opcode {
  142. Opcode::Lddw => {
  143. if src != 0 || off != 0 {
  144. return Err(SBPFError::BytecodeError {
  145. error: format!(
  146. "Lddw instruction expects src and off to be 0, but got src: {}, off: \
  147. {}",
  148. src, off
  149. ),
  150. span: span.clone(),
  151. custom_label: None,
  152. });
  153. }
  154. out_dst = Some(Register { n: dst });
  155. out_imm = Some(Number::Int(imm));
  156. }
  157. Opcode::Call => {
  158. if SYSCALLS.get(&(imm as u32)).is_some() {
  159. if reg != 0 || off != 0 {
  160. return Err(SBPFError::BytecodeError {
  161. error: format!(
  162. "Call instruction with syscall expects reg and off to be 0, but \
  163. got reg: {}, off: {}",
  164. reg, off
  165. ),
  166. span: span.clone(),
  167. custom_label: None,
  168. });
  169. }
  170. out_imm = Some(Number::Int(imm));
  171. } else {
  172. if reg != 16 || off != 0 {
  173. return Err(SBPFError::BytecodeError {
  174. error: format!(
  175. "Call instruction with immediate expects reg to be 16 and off to \
  176. be 0, but got reg: {}, off: {}",
  177. reg, off
  178. ),
  179. span: span.clone(),
  180. custom_label: None,
  181. });
  182. }
  183. out_imm = Some(Number::Int(imm));
  184. }
  185. }
  186. Opcode::Callx => {
  187. if src != 0 || off != 0 || imm != 0 {
  188. return Err(SBPFError::BytecodeError {
  189. error: format!(
  190. "Callx instruction expects src, off, and imm to be 0, but got src: \
  191. {}, off: {}, imm: {}",
  192. src, off, imm
  193. ),
  194. span: span.clone(),
  195. custom_label: None,
  196. });
  197. }
  198. // callx destination register is encoded in the dst field
  199. out_dst = Some(Register { n: dst });
  200. }
  201. Opcode::Ja => {
  202. if reg != 0 || imm != 0 {
  203. return Err(SBPFError::BytecodeError {
  204. error: format!(
  205. "Ja instruction expects reg and imm to be 0, but got reg: {}, imm: {}",
  206. reg, imm
  207. ),
  208. span: span.clone(),
  209. custom_label: None,
  210. });
  211. }
  212. out_off = Some(off);
  213. }
  214. Opcode::JeqImm
  215. | Opcode::JgtImm
  216. | Opcode::JgeImm
  217. | Opcode::JltImm
  218. | Opcode::JleImm
  219. | Opcode::JsetImm
  220. | Opcode::JneImm
  221. | Opcode::JsgtImm
  222. | Opcode::JsgeImm
  223. | Opcode::JsltImm
  224. | Opcode::JsleImm => {
  225. if src != 0 {
  226. return Err(SBPFError::BytecodeError {
  227. error: format!(
  228. "Jump instruction with immediate expects src to be 0, but got src: {}",
  229. src
  230. ),
  231. span: span.clone(),
  232. custom_label: None,
  233. });
  234. }
  235. out_dst = Some(Register { n: dst });
  236. out_imm = Some(Number::Int(imm));
  237. out_off = Some(off);
  238. }
  239. Opcode::JeqReg
  240. | Opcode::JgtReg
  241. | Opcode::JgeReg
  242. | Opcode::JltReg
  243. | Opcode::JleReg
  244. | Opcode::JsetReg
  245. | Opcode::JneReg
  246. | Opcode::JsgtReg
  247. | Opcode::JsgeReg
  248. | Opcode::JsltReg
  249. | Opcode::JsleReg => {
  250. if imm != 0 {
  251. return Err(SBPFError::BytecodeError {
  252. error: format!(
  253. "Jump instruction with register expects imm to be 0, but got imm: {}",
  254. imm
  255. ),
  256. span: span.clone(),
  257. custom_label: None,
  258. });
  259. }
  260. out_dst = Some(Register { n: dst });
  261. out_src = Some(Register { n: src });
  262. out_off = Some(off);
  263. }
  264. // Arithmetic instructions with immediate values
  265. Opcode::Add32Imm
  266. | Opcode::Sub32Imm
  267. | Opcode::Mul32Imm
  268. | Opcode::Div32Imm
  269. | Opcode::Or32Imm
  270. | Opcode::And32Imm
  271. | Opcode::Lsh32Imm
  272. | Opcode::Rsh32Imm
  273. | Opcode::Mod32Imm
  274. | Opcode::Xor32Imm
  275. | Opcode::Mov32Imm
  276. | Opcode::Arsh32Imm
  277. | Opcode::Lmul32Imm
  278. | Opcode::Udiv32Imm
  279. | Opcode::Urem32Imm
  280. | Opcode::Sdiv32Imm
  281. | Opcode::Srem32Imm
  282. | Opcode::Add64Imm
  283. | Opcode::Sub64Imm
  284. | Opcode::Mul64Imm
  285. | Opcode::Div64Imm
  286. | Opcode::Or64Imm
  287. | Opcode::And64Imm
  288. | Opcode::Lsh64Imm
  289. | Opcode::Rsh64Imm
  290. | Opcode::Mod64Imm
  291. | Opcode::Xor64Imm
  292. | Opcode::Mov64Imm
  293. | Opcode::Arsh64Imm
  294. | Opcode::Hor64Imm
  295. | Opcode::Lmul64Imm
  296. | Opcode::Uhmul64Imm
  297. | Opcode::Udiv64Imm
  298. | Opcode::Urem64Imm
  299. | Opcode::Shmul64Imm
  300. | Opcode::Sdiv64Imm
  301. | Opcode::Srem64Imm
  302. | Opcode::Be
  303. | Opcode::Le => {
  304. if src != 0 || off != 0 {
  305. return Err(SBPFError::BytecodeError {
  306. error: format!(
  307. "Arithmetic instruction with immediate expects src and off to be 0, \
  308. but got src: {}, off: {}",
  309. src, off
  310. ),
  311. span: span.clone(),
  312. custom_label: None,
  313. });
  314. }
  315. out_dst = Some(Register { n: dst });
  316. out_imm = Some(Number::Int(imm));
  317. }
  318. // Arithmetic instructions with register operands
  319. Opcode::Add32Reg
  320. | Opcode::Sub32Reg
  321. | Opcode::Mul32Reg
  322. | Opcode::Div32Reg
  323. | Opcode::Or32Reg
  324. | Opcode::And32Reg
  325. | Opcode::Lsh32Reg
  326. | Opcode::Rsh32Reg
  327. | Opcode::Mod32Reg
  328. | Opcode::Xor32Reg
  329. | Opcode::Mov32Reg
  330. | Opcode::Arsh32Reg
  331. | Opcode::Lmul32Reg
  332. | Opcode::Udiv32Reg
  333. | Opcode::Urem32Reg
  334. | Opcode::Sdiv32Reg
  335. | Opcode::Srem32Reg
  336. | Opcode::Add64Reg
  337. | Opcode::Sub64Reg
  338. | Opcode::Mul64Reg
  339. | Opcode::Div64Reg
  340. | Opcode::Or64Reg
  341. | Opcode::And64Reg
  342. | Opcode::Lsh64Reg
  343. | Opcode::Rsh64Reg
  344. | Opcode::Mod64Reg
  345. | Opcode::Xor64Reg
  346. | Opcode::Mov64Reg
  347. | Opcode::Arsh64Reg
  348. | Opcode::Lmul64Reg
  349. | Opcode::Uhmul64Reg
  350. | Opcode::Udiv64Reg
  351. | Opcode::Urem64Reg
  352. | Opcode::Shmul64Reg
  353. | Opcode::Sdiv64Reg
  354. | Opcode::Srem64Reg => {
  355. if off != 0 || imm != 0 {
  356. return Err(SBPFError::BytecodeError {
  357. error: format!(
  358. "Arithmetic instruction with register expects off and imm to be 0, \
  359. but got off: {}, imm: {}",
  360. off, imm
  361. ),
  362. span: span.clone(),
  363. custom_label: None,
  364. });
  365. }
  366. out_dst = Some(Register { n: dst });
  367. out_src = Some(Register { n: src });
  368. }
  369. Opcode::Ldxw | Opcode::Ldxh | Opcode::Ldxb | Opcode::Ldxdw => {
  370. if imm != 0 {
  371. return Err(SBPFError::BytecodeError {
  372. error: format!(
  373. "Load instruction expects imm to be 0, but got imm: {}",
  374. imm
  375. ),
  376. span: span.clone(),
  377. custom_label: None,
  378. });
  379. }
  380. out_dst = Some(Register { n: dst });
  381. out_src = Some(Register { n: src });
  382. out_off = Some(off);
  383. }
  384. Opcode::Stw | Opcode::Sth | Opcode::Stb | Opcode::Stdw => {
  385. if src != 0 {
  386. return Err(SBPFError::BytecodeError {
  387. error: format!(
  388. "Store instruction expects src to be 0, but got src: {}",
  389. src
  390. ),
  391. span: span.clone(),
  392. custom_label: None,
  393. });
  394. }
  395. out_dst = Some(Register { n: dst });
  396. out_off = Some(off);
  397. out_imm = Some(Number::Int(imm));
  398. }
  399. Opcode::Stxb | Opcode::Stxh | Opcode::Stxw | Opcode::Stxdw => {
  400. if imm != 0 {
  401. return Err(SBPFError::BytecodeError {
  402. error: format!(
  403. "Store instruction with register expects imm to be 0, but got imm: {}",
  404. imm
  405. ),
  406. span: span.clone(),
  407. custom_label: None,
  408. });
  409. }
  410. out_dst = Some(Register { n: dst });
  411. out_src = Some(Register { n: src });
  412. out_off = Some(off);
  413. }
  414. // Unary operations
  415. Opcode::Neg32 | Opcode::Neg64 | Opcode::Exit => {
  416. if src != 0 || off != 0 || imm != 0 {
  417. return Err(SBPFError::BytecodeError {
  418. error: format!(
  419. "Unary operation expects src, off, and imm to be 0, but got src: {}, \
  420. off: {}, imm: {}",
  421. src, off, imm
  422. ),
  423. span: span.clone(),
  424. custom_label: None,
  425. });
  426. }
  427. out_dst = Some(Register { n: dst });
  428. }
  429. _ => {
  430. return Err(SBPFError::BytecodeError {
  431. error: format!("Unsupported opcode: {:?}", opcode),
  432. span: span.clone(),
  433. custom_label: None,
  434. });
  435. }
  436. }
  437. Ok(Instruction {
  438. opcode,
  439. dst: out_dst,
  440. src: out_src,
  441. off: out_off,
  442. imm: out_imm,
  443. span,
  444. })
  445. }
  446. pub fn to_bytes(&self) -> Vec<u8> {
  447. let src_val = self.src.as_ref().map(|r| r.n).unwrap_or(0);
  448. let dst_val = self.dst.as_ref().map(|r| r.n).unwrap_or(0);
  449. let off_val = self.off.unwrap_or(0);
  450. let imm_val = match &self.imm {
  451. Some(Number::Int(imm)) | Some(Number::Addr(imm)) => *imm,
  452. None => 0,
  453. };
  454. let mut b = vec![self.opcode.to_bytecode(), src_val << 4 | dst_val];
  455. b.extend_from_slice(&off_val.to_le_bytes());
  456. b.extend_from_slice(&(imm_val as i32).to_le_bytes());
  457. if self.opcode == Opcode::Lddw {
  458. b.extend_from_slice(&[0; 4]);
  459. b.extend_from_slice(&((imm_val >> 32) as i32).to_le_bytes());
  460. }
  461. b
  462. }
  463. pub fn to_asm(&self) -> Result<String, SBPFError> {
  464. Ok(match self.opcode {
  465. // lddw - (load double word) takes up two instructions. The 64 bit value
  466. // is made up of two halves with the upper half being the immediate
  467. // of the lddw value and the lower half being the immediate of the
  468. // following instruction
  469. Opcode::Lddw => {
  470. match (&self.dst, &self.imm) {
  471. (Some(dst), Some(imm)) => format!("{} r{}, {}", self.opcode, dst.n, imm),
  472. _ => return Err(SBPFError::BytecodeError {
  473. error: "Lddw instruction missing destination register or immediate value".to_string(),
  474. span: self.span.clone(),
  475. custom_label: None,
  476. }),
  477. }
  478. },
  479. // ldx - (load x) store a 8/16/32/64 bit (byte/half/word/double word)
  480. // value in a register
  481. Opcode::Ldxb |
  482. Opcode::Ldxh |
  483. Opcode::Ldxw |
  484. Opcode::Ldxdw => {
  485. match &self.dst {
  486. Some(dst) => format!("{} r{}, {}", self.opcode, dst.n, self.src_off()),
  487. None => return Err(SBPFError::BytecodeError {
  488. error: format!("{} instruction missing destination register", self.opcode),
  489. span: self.span.clone(),
  490. custom_label: None,
  491. }),
  492. }
  493. },
  494. // stb - these instructions are deprecated
  495. Opcode::Stb |
  496. Opcode::Sth |
  497. Opcode::Stw |
  498. Opcode::Stdw => {
  499. match &self.imm {
  500. Some(imm) => format!("{} {}, {}", self.opcode, self.dst_off(), imm),
  501. None => return Err(SBPFError::BytecodeError {
  502. error: format!("{} instruction missing immediate value", self.opcode),
  503. span: self.span.clone(),
  504. custom_label: None,
  505. }),
  506. }
  507. },
  508. // stx - store a 8/16/32/64 bit value from a source register into the offset
  509. // of the destination register
  510. Opcode::Stxb |
  511. Opcode::Stxh |
  512. Opcode::Stxw |
  513. Opcode::Stxdw => {
  514. match &self.src {
  515. Some(src) => format!("{} {}, r{}", self.opcode, self.dst_off(), src.n),
  516. None => return Err(SBPFError::BytecodeError {
  517. error: format!("{} instruction missing source register", self.opcode),
  518. span: self.span.clone(),
  519. custom_label: None,
  520. }),
  521. }
  522. },
  523. // Math
  524. Opcode::Neg32 | // Deprecated in SBFv2
  525. Opcode::Neg64 => {
  526. match &self.dst {
  527. Some(dst) => format!("{} r{}", self.opcode, dst.n),
  528. None => return Err(SBPFError::BytecodeError {
  529. error: format!("{} instruction missing destination register", self.opcode),
  530. span: self.span.clone(),
  531. custom_label: None,
  532. }),
  533. }
  534. },
  535. // LE and BE OpCodes act a little differently to others. In assembly form, they are
  536. // notated as be16, be32 and b64. In byte form, the bit length of the operation is
  537. // determined by the immedate value of its parent instruction, 0x10, 0x20 and 0x40
  538. // accordingly (the hex of 16/32/64)
  539. Opcode::Le |
  540. Opcode::Be => {
  541. match &self.dst {
  542. Some(dst) => format!("{}{}", self.op_imm_bits()?, dst.n),
  543. None => return Err(SBPFError::BytecodeError {
  544. error: format!("{} instruction missing destination register", self.opcode),
  545. span: self.span.clone(),
  546. custom_label: None,
  547. }),
  548. }
  549. }, // Docs for this seem wrong //DC01000010000000 DC01000020000000 DC01000040000000
  550. // Immedate
  551. Opcode::Add32Imm |
  552. Opcode::Sub32Imm |
  553. Opcode::Mul32Imm |
  554. Opcode::Div32Imm |
  555. Opcode::Or32Imm |
  556. Opcode::And32Imm |
  557. Opcode::Lsh32Imm |
  558. Opcode::Rsh32Imm |
  559. Opcode::Mod32Imm |
  560. Opcode::Xor32Imm |
  561. Opcode::Arsh32Imm |
  562. Opcode::Mov32Imm |
  563. Opcode::Lmul32Imm |
  564. Opcode::Udiv32Imm |
  565. Opcode::Urem32Imm |
  566. Opcode::Sdiv32Imm |
  567. Opcode::Srem32Imm |
  568. Opcode::Add64Imm |
  569. Opcode::Sub64Imm |
  570. Opcode::Mul64Imm |
  571. Opcode::Div64Imm |
  572. Opcode::Or64Imm |
  573. Opcode::And64Imm |
  574. Opcode::Lsh64Imm |
  575. Opcode::Rsh64Imm |
  576. Opcode::Mod64Imm |
  577. Opcode::Xor64Imm |
  578. Opcode::Mov64Imm |
  579. Opcode::Arsh64Imm |
  580. Opcode::Hor64Imm |
  581. Opcode::Lmul64Imm |
  582. Opcode::Uhmul64Imm |
  583. Opcode::Udiv64Imm |
  584. Opcode::Urem64Imm |
  585. Opcode::Shmul64Imm |
  586. Opcode::Sdiv64Imm |
  587. Opcode::Srem64Imm => {
  588. match (&self.dst, &self.imm) {
  589. (Some(dst), Some(imm)) => format!("{} r{}, {}", self.opcode, dst.n, imm),
  590. _ => return Err(SBPFError::BytecodeError {
  591. error: format!("{} instruction missing destination register or immediate value", self.opcode),
  592. span: self.span.clone(),
  593. custom_label: None,
  594. }),
  595. }
  596. },
  597. // Register
  598. Opcode::Add32Reg |
  599. Opcode::Sub32Reg |
  600. Opcode::Mul32Reg |
  601. Opcode::Div32Reg |
  602. Opcode::Or32Reg |
  603. Opcode::And32Reg |
  604. Opcode::Lsh32Reg |
  605. Opcode::Rsh32Reg |
  606. Opcode::Mod32Reg |
  607. Opcode::Xor32Reg |
  608. Opcode::Mov32Reg |
  609. Opcode::Arsh32Reg |
  610. Opcode::Lmul32Reg |
  611. Opcode::Udiv32Reg |
  612. Opcode::Urem32Reg |
  613. Opcode::Sdiv32Reg |
  614. Opcode::Srem32Reg |
  615. Opcode::Add64Reg |
  616. Opcode::Sub64Reg |
  617. Opcode::Mul64Reg |
  618. Opcode::Div64Reg |
  619. Opcode::Or64Reg |
  620. Opcode::And64Reg |
  621. Opcode::Lsh64Reg |
  622. Opcode::Rsh64Reg |
  623. Opcode::Mod64Reg |
  624. Opcode::Xor64Reg |
  625. Opcode::Mov64Reg |
  626. Opcode::Arsh64Reg |
  627. Opcode::Lmul64Reg |
  628. Opcode::Uhmul64Reg |
  629. Opcode::Udiv64Reg |
  630. Opcode::Urem64Reg |
  631. Opcode::Shmul64Reg |
  632. Opcode::Sdiv64Reg |
  633. Opcode::Srem64Reg => {
  634. match (&self.dst, &self.src) {
  635. (Some(dst), Some(src)) => format!("{} r{}, r{}", self.opcode, dst.n, src.n),
  636. _ => return Err(SBPFError::BytecodeError {
  637. error: format!("{} instruction missing destination or source register", self.opcode),
  638. span: self.span.clone(),
  639. custom_label: None,
  640. }),
  641. }
  642. },
  643. // Jumps
  644. Opcode::Ja => format!("{} {}", self.opcode, self.off_str()),
  645. // Immediates
  646. Opcode::JeqImm |
  647. Opcode::JgtImm |
  648. Opcode::JgeImm |
  649. Opcode::JltImm |
  650. Opcode::JleImm |
  651. Opcode::JsetImm |
  652. Opcode::JneImm |
  653. Opcode::JsgtImm |
  654. Opcode::JsgeImm |
  655. Opcode::JsltImm |
  656. Opcode::JsleImm => {
  657. match (&self.dst, &self.imm) {
  658. (Some(dst), Some(imm)) => format!("{} r{}, {}, {}", self.opcode, dst.n, imm, self.off_str()),
  659. _ => return Err(SBPFError::BytecodeError {
  660. error: format!("{} instruction missing destination register or immediate value", self.opcode),
  661. span: self.span.clone(),
  662. custom_label: None,
  663. }),
  664. }
  665. },
  666. // Registers
  667. Opcode::JeqReg |
  668. Opcode::JgtReg |
  669. Opcode::JgeReg |
  670. Opcode::JltReg |
  671. Opcode::JleReg |
  672. Opcode::JsetReg |
  673. Opcode::JneReg |
  674. Opcode::JsgtReg |
  675. Opcode::JsgeReg |
  676. Opcode::JsltReg |
  677. Opcode::JsleReg => {
  678. match (&self.dst, &self.src) {
  679. (Some(dst), Some(src)) => format!("{} r{}, r{}, {}", self.opcode, dst.n, src.n, self.off_str()),
  680. _ => return Err(SBPFError::BytecodeError {
  681. error: format!("{} instruction missing destination or source register", self.opcode),
  682. span: self.span.clone(),
  683. custom_label: None,
  684. }),
  685. }
  686. },
  687. // Calls
  688. Opcode::Call => {
  689. match &self.imm {
  690. Some(imm) => format!("call {}", imm),
  691. None => return Err(SBPFError::BytecodeError {
  692. error: "Call instruction missing immediate value".to_string(),
  693. span: self.span.clone(),
  694. custom_label: None,
  695. }),
  696. }
  697. },
  698. Opcode::Callx => {
  699. match &self.src {
  700. Some(src) => format!("call r{}", src.n),
  701. None => return Err(SBPFError::BytecodeError {
  702. error: "Callx instruction missing source register".to_string(),
  703. span: self.span.clone(),
  704. custom_label: None,
  705. }),
  706. }
  707. },
  708. Opcode::Exit => format!("{}", self.opcode),
  709. _ => return Err(SBPFError::BytecodeError {
  710. error: format!("Unsupported opcode: {:?}", self.opcode),
  711. span: self.span.clone(),
  712. custom_label: None,
  713. })
  714. })
  715. }
  716. }
  717. #[cfg(test)]
  718. mod test {
  719. use {
  720. crate::{
  721. instruction::{Instruction, Register},
  722. opcode::Opcode,
  723. },
  724. hex_literal::hex,
  725. };
  726. #[test]
  727. fn serialize_e2e() {
  728. let b = hex!("9700000000000000");
  729. let i = Instruction::from_bytes(&b).unwrap();
  730. assert_eq!(i.to_bytes(), &b);
  731. assert_eq!(i.to_asm().unwrap(), "mod64 r0, 0");
  732. }
  733. #[test]
  734. fn serialize_e2e_lddw() {
  735. let b = hex!("18010000000000000000000000000000");
  736. let i = Instruction::from_bytes(&b).unwrap();
  737. assert_eq!(i.to_bytes(), &b);
  738. assert_eq!(i.to_asm().unwrap(), "lddw r1, 0");
  739. }
  740. #[test]
  741. fn serialize_e2e_add64_imm() {
  742. let b = hex!("0701000000000000");
  743. let i = Instruction::from_bytes(&b).unwrap();
  744. assert_eq!(i.to_bytes(), &b);
  745. assert_eq!(i.to_asm().unwrap(), "add64 r1, 0");
  746. }
  747. #[test]
  748. fn serialize_e2e_add64_reg() {
  749. let b = hex!("0f12000000000000");
  750. let i = Instruction::from_bytes(&b).unwrap();
  751. assert_eq!(i.to_bytes(), &b);
  752. assert_eq!(i.to_asm().unwrap(), "add64 r2, r1");
  753. }
  754. #[test]
  755. fn serialize_e2e_ja() {
  756. let b = hex!("05000a0000000000");
  757. let i = Instruction::from_bytes(&b).unwrap();
  758. assert_eq!(i.to_bytes(), &b);
  759. assert_eq!(i.to_asm().unwrap(), "jeq +10");
  760. }
  761. #[test]
  762. fn serialize_e2e_jeq_imm() {
  763. let b = hex!("15030a0001000000");
  764. let i = Instruction::from_bytes(&b).unwrap();
  765. assert_eq!(i.to_bytes(), &b);
  766. assert_eq!(i.to_asm().unwrap(), "jeq r3, 1, +10");
  767. }
  768. #[test]
  769. fn serialize_e2e_jeq_reg() {
  770. let b = hex!("1d210a0000000000");
  771. let i = Instruction::from_bytes(&b).unwrap();
  772. assert_eq!(i.to_bytes(), &b);
  773. assert_eq!(i.to_asm().unwrap(), "jeq r1, r2, +10");
  774. }
  775. #[test]
  776. fn serialize_e2e_ldxw() {
  777. let b = hex!("6112000000000000");
  778. let i = Instruction::from_bytes(&b).unwrap();
  779. assert_eq!(i.to_bytes(), &b);
  780. assert_eq!(i.to_asm().unwrap(), "ldxw r2, [r1+0]");
  781. }
  782. #[test]
  783. fn serialize_e2e_stxw() {
  784. let b = hex!("6312000000000000");
  785. let i = Instruction::from_bytes(&b).unwrap();
  786. assert_eq!(i.to_bytes(), &b);
  787. assert_eq!(i.to_asm().unwrap(), "stxw [r2+0], r1");
  788. }
  789. #[test]
  790. fn serialize_e2e_neg64() {
  791. let b = hex!("8700000000000000");
  792. let i = Instruction::from_bytes(&b).unwrap();
  793. assert_eq!(i.to_bytes(), &b);
  794. assert_eq!(i.to_asm().unwrap(), "neg64 r0");
  795. }
  796. #[test]
  797. fn test_instruction_size() {
  798. let exit = Instruction::from_bytes(&hex!("9500000000000000")).unwrap();
  799. assert_eq!(exit.get_size(), 8);
  800. let lddw = Instruction::from_bytes(&hex!("18010000000000000000000000000000")).unwrap();
  801. assert_eq!(lddw.get_size(), 16);
  802. }
  803. #[test]
  804. fn test_is_jump() {
  805. let ja = Instruction::from_bytes(&hex!("0500000000000000")).unwrap();
  806. assert!(ja.is_jump());
  807. let jeq_imm = Instruction::from_bytes(&hex!("1502000000000000")).unwrap();
  808. assert!(jeq_imm.is_jump());
  809. let jeq_reg = Instruction::from_bytes(&hex!("1d12000000000000")).unwrap();
  810. assert!(jeq_reg.is_jump());
  811. let exit = Instruction::from_bytes(&hex!("9500000000000000")).unwrap();
  812. assert!(!exit.is_jump());
  813. let add64 = Instruction::from_bytes(&hex!("0701000000000000")).unwrap();
  814. assert!(!add64.is_jump());
  815. }
  816. #[test]
  817. fn test_off_str() {
  818. let pos_off = Instruction {
  819. opcode: Opcode::Ja,
  820. dst: None,
  821. src: None,
  822. off: Some(10),
  823. imm: None,
  824. span: 0..8,
  825. };
  826. assert_eq!(pos_off.off_str(), "+10");
  827. let neg_off = Instruction {
  828. opcode: Opcode::Ja,
  829. dst: None,
  830. src: None,
  831. off: Some(-10),
  832. imm: None,
  833. span: 0..8,
  834. };
  835. assert_eq!(neg_off.off_str(), "-10");
  836. }
  837. #[test]
  838. fn test_dst_off() {
  839. let inst = Instruction {
  840. opcode: Opcode::Ldxw,
  841. dst: Some(Register { n: 1 }),
  842. src: Some(Register { n: 2 }),
  843. off: Some(10),
  844. imm: None,
  845. span: 0..8,
  846. };
  847. assert_eq!(inst.dst_off(), "[r1+10]");
  848. }
  849. #[test]
  850. fn test_src_off() {
  851. let inst = Instruction {
  852. opcode: Opcode::Ldxw,
  853. dst: Some(Register { n: 1 }),
  854. src: Some(Register { n: 2 }),
  855. off: Some(-5),
  856. imm: None,
  857. span: 0..8,
  858. };
  859. assert_eq!(inst.src_off(), "[r2-5]");
  860. }
  861. #[test]
  862. fn test_invalid_opcode() {
  863. let result = Instruction::from_bytes(&hex!("ff00000000000000"));
  864. assert!(result.is_err());
  865. }
  866. #[test]
  867. fn test_unsupported_opcode() {
  868. let add32 = Instruction::from_bytes(&hex!("1300000000000000"));
  869. assert!(add32.is_err());
  870. }
  871. }