jsonpiler 0.11.0

a Json syntax programming language for Windows
Documentation
use crate::prelude::*;
impl X64Assembler {
  fn sizeof_alias(&self, insts: &[X64Inst], offset: Option<u32>) -> ErrOR<u32> {
    let mut code_size = 0;
    for inst in insts {
      code_size += self.sizeof_inst(inst, offset.map(|off| off + code_size))?;
    }
    Ok(code_size)
  }
  pub(crate) fn sizeof_inst(&self, inst: &X64Inst, offset: Option<u32>) -> ErrOR<u32> {
    Ok(match inst {
      Repeat(reg_size, _, _) => 1 + u32::from(*reg_size == S8) + 1,
      ShiftR(_, _, operand) => 3 + len_u32(&operand.imm())?,
      IncR(_) | DecR(_) | IDivR(_) => 3,
      CMovCc(..) | IMulR2(..) => 4,
      BitTest(..) | CvtSi2Sd(..) | CvtTSd2Si(..) | Call(_) => 5,
      CallApi(_) => 6,
      JCc(_, id) => self.sizeof_jmp(*id, offset, 6)?,
      Jmp(id) => self.sizeof_jmp(*id, offset, 5)?,
      CallApiCheck(api) => {
        self.sizeof_alias(&[CallApi(*api), TestRR(S8, Rax), JCc(E, self.handlers.os)], offset)?
      }
      UComISd(xmm, xmm2) | ArithSd(_, xmm, xmm2) | SqrtSd(xmm, xmm2) => {
        1 + (xmm.rex_size() | xmm2.rex_size()) + 2 + 1
      }
      MovSxDRMd(_, addr) | LeaRM(_, addr) => 2 + addr.modrm_sib_disp(),
      MovSdO(xmm, operand) => 1 + operand.sizeof(xmm.rex_size(), 2)?,
      MovOSd(operand, xmm) => 1 + operand.sizeof(xmm.rex_size(), 2)?,
      IncMd(addr) | DecMd(addr) => 1 + addr.modrm_sib_disp(),
      Clear(reg) => reg.rex_size() + 2,
      Unary(reg_size, _, reg) => match reg_size {
        S8 => 3,
        S4 | S1 => reg.rex_size() + 2,
      },
      MovRI(..) => 1 + 1 + 8,
      MovMId(operand, _) => sizeof_mov_id(*operand)?,
      MovMIb(operand, _) => sizeof_mov_ib(*operand)?,
      MovRO(reg_size, dst, src) => {
        let operands = (Reg(*dst), *src);
        match reg_size {
          S1 => sizeof_mov_b(operands)?,
          S4 | S8 => sizeof_mov_dq(*reg_size, operands)?,
        }
      }
      MovOR(reg_size, dst, src) => {
        let operands = (*dst, Reg(*src));
        match reg_size {
          S1 => sizeof_mov_b(operands)?,
          S4 | S8 => sizeof_mov_dq(*reg_size, operands)?,
        }
      }
      RR(reg_size, _, dst, src) => {
        (u32::from(reg_size.rex_w()) | dst.rex_size() | src.rex_size()) + 2
      }
      MR(reg_size, _, operand, reg) | RM(reg_size, _, reg, operand) => {
        operand.sizeof(u32::from(reg_size.rex_w()) | reg.rex_size(), 1)?
      }
      TestRR(reg_size, reg) => (u32::from(reg_size.rex_w()) | reg.rex_size()) + 2,
      Pop(reg) | Push(reg) => reg.rex_size() + 1,
      SetCc(reg, _) => reg.rex_size() + 3,
      RetX | DF(_) => 1,
      Cqo => 2,
      MId(reg_size, _, operand, _) => {
        if *reg_size == S1 {
          return Err(InvalidInst(format!("OId S1 {operand:?}")).into());
        }
        operand.sizeof(u32::from(reg_size.rex_w()), 1)? + 4
      }
      LblX(_) => 0,
    })
  }
  pub(crate) fn sizeof_jmp(&self, id: LabelId, offset: Option<u32>, long: u32) -> ErrOR<u32> {
    if let Some((TextX, lbl_off)) = self.labels.get(&id)
      && let Some(off) = offset
      && i8::try_from(i32::try_from(*lbl_off)? - 2 - i32::try_from(off)?).is_ok()
    {
      Ok(2)
    } else {
      Ok(long)
    }
  }
}
pub(crate) fn sizeof_mov_id(operand: X64Operand) -> ErrOR<u32> {
  Ok(if let Reg(reg) = operand { reg.rb()?.rex_size() + 1 } else { operand.sizeof(0, 1)? } + 4)
}
pub(crate) fn sizeof_mov_ib(operand: X64Operand) -> ErrOR<u32> {
  Ok(if let Reg(reg) = operand { reg.rb()?.rex_size() + 1 } else { operand.sizeof(0, 1)? } + 1)
}
pub(crate) fn sizeof_mov_b(operands: (X64Operand, X64Operand)) -> ErrOR<u32> {
  Ok(match operands {
    (Reg(dst), src) => src.rb()?.sizeof(dst.rb()?.rex_size(), 1)?,
    (dst, Reg(src)) => dst.rb()?.sizeof(src.rb()?.rex_size(), 1)?,
    _ => return Err(InvalidInst(format!("MovBB{operands:?}")).into()),
  })
}
pub(crate) fn sizeof_mov_dq(reg_size: RegSize, operands: (X64Operand, X64Operand)) -> ErrOR<u32> {
  let rex_w = u32::from(reg_size.rex_w());
  Ok(match operands {
    (Reg(dst), src) => src.sizeof(rex_w | dst.rex_size(), 1)?,
    (dst, Reg(src)) => dst.sizeof(rex_w | src.rex_size(), 1)?,
    _ => return Err(InvalidInst(format!("MovDD{operands:?}")).into()),
  })
}