///|
/// Architecture Configuration
pub(all) struct ArchConfig {
  arch_name : String
  // The Number of Total Physical Registers
  // max_num_reg should be = num_arg_regs + num_temp_regs + num_saved_regs
  // not include special registers like zero, ra, sp
  max_num_reg : Int
  // The Number of Total Physical Floating Point Registers
  // max_num_freg should be = num_arg_fregs + num_temp_fregs + num_saved_fregs
  max_num_freg : Int
  // The Number of Physicial Argument Registers
  num_arg_regs : Int
  // The Number of Physical Argument Floating Point Registers
  num_arg_fregs : Int
  // The Number of Physical Temporary Registers
  num_temp_regs : Int
  // The Number of Physical Temporary Floating Point Registers
  num_temp_fregs : Int
  // The Number of Physical Saved Registers
  num_saved_regs : Int
  // The Number of Physical Saved Floating Point Registers
  num_saved_fregs : Int
  // Whether to support select instruction
  // If false, will lower to branches
  support_select : Bool
}

///|
/// Check if an immediate value is valid for arithmetic instructions
pub fn ArchConfig::is_valid_imm(self : ArchConfig, imm : Int64) -> Bool {
  match self.arch_name {
    "riscv64" =>
      // RISC-V arithmetic immediates are 12-bit signed (-2048 to 2047)
      imm >= -2048L && imm <= 2047L
    "aarch64" =>
      // AArch64 arithmetic immediates are 12-bit unsigned (0 to 4095)
      // or 12-bit unsigned shifted left by 12
      (imm >= 0L && imm <= 4095L) ||
      (imm >= 0L && imm <= 16773120L && imm % 4096L == 0L)
    _ => true // Unknown architecture, assume all immediates are valid
  }
}

///|
pub fn ArchConfig::riscv64() -> ArchConfig {
  ArchConfig::{
    arch_name: "riscv64",
    max_num_reg: 17,
    max_num_freg: 17,
    num_arg_regs: 8,
    num_arg_fregs: 8,
    num_temp_regs: 6,
    num_temp_fregs: 6,
    num_saved_regs: 11,
    num_saved_fregs: 11,
    support_select: false,
  }
}

///|
pub fn ArchConfig::aarch64() -> ArchConfig {
  ArchConfig::{
    arch_name: "aarch64",
    max_num_reg: 19, // X0-X30 minus reserved (SP, X18)
    max_num_freg: 32, // D0-D31
    num_arg_regs: 8, // X0-X7
    num_arg_fregs: 8, // D0-D7
    num_temp_regs: 7, // X9-X15
    num_temp_fregs: 6, // D16-D21
    num_saved_regs: 11, // X19-X28, X8 (can be saved), X29
    num_saved_fregs: 8, // D8-D15
    support_select: false,
  }
}

///|
pub fn ArchConfig::debug() -> ArchConfig {
  ArchConfig::{
    arch_name: "demo",
    max_num_reg: 8,
    max_num_freg: 8,
    num_arg_regs: 4,
    num_arg_fregs: 4,
    num_temp_regs: 2,
    num_temp_fregs: 2,
    num_saved_regs: 2,
    num_saved_fregs: 2,
    support_select: false,
  }
}