package xiangshan.backend.decode.isa

import chisel3._
import chisel3.util._
import xiangshan.{FuType, HasXSParameter}
import xiangshan.backend.decode._
import xiangshan.backend.MDUOpType

object RV32MInstr extends HasInstrType with HasXSParameter {
  def MUL     = BitPat("b0000001_?????_?????_000_?????_0110011")
  def MULH    = BitPat("b0000001_?????_?????_001_?????_0110011")
  def MULHSU  = BitPat("b0000001_?????_?????_010_?????_0110011")
  def MULHU   = BitPat("b0000001_?????_?????_011_?????_0110011")
  def DIV     = BitPat("b0000001_?????_?????_100_?????_0110011")
  def DIVU    = BitPat("b0000001_?????_?????_101_?????_0110011")
  def REM     = BitPat("b0000001_?????_?????_110_?????_0110011")
  def REMU    = BitPat("b0000001_?????_?????_111_?????_0110011")
  def MULW    = BitPat("b0000001_?????_?????_000_?????_0111011")
  def DIVW    = BitPat("b0000001_?????_?????_100_?????_0111011")
  def DIVUW   = BitPat("b0000001_?????_?????_101_?????_0111011")
  def REMW    = BitPat("b0000001_?????_?????_110_?????_0111011")
  def REMUW   = BitPat("b0000001_?????_?????_111_?????_0111011")

  val mulTable = Array(
    MUL            -> List(InstrR, FuType.mul, MDUOpType.mul),
    MULH           -> List(InstrR, FuType.mul, MDUOpType.mulh),
    MULHSU         -> List(InstrR, FuType.mul, MDUOpType.mulhsu),
    MULHU          -> List(InstrR, FuType.mul, MDUOpType.mulhu)
  )
  val divTable = Array(
    DIV            -> List(InstrR, FuType.div, MDUOpType.div),
    DIVU           -> List(InstrR, FuType.div, MDUOpType.divu),
    REM            -> List(InstrR, FuType.div, MDUOpType.rem),
    REMU           -> List(InstrR, FuType.div, MDUOpType.remu)
  )
  val table = mulTable ++ (if (HasDiv) divTable else Nil)
}

object RV64MInstr extends HasInstrType with HasXSParameter {
  def MULW    = BitPat("b0000001_?????_?????_000_?????_0111011")
  def DIVW    = BitPat("b0000001_?????_?????_100_?????_0111011")
  def DIVUW   = BitPat("b0000001_?????_?????_101_?????_0111011")
  def REMW    = BitPat("b0000001_?????_?????_110_?????_0111011")
  def REMUW   = BitPat("b0000001_?????_?????_111_?????_0111011")

  val mulTable = Array(
    MULW           -> List(InstrR, FuType.mul, MDUOpType.mulw)
  )
  val divTable = Array(
    DIVW           -> List(InstrR, FuType.div, MDUOpType.divw),
    DIVUW          -> List(InstrR, FuType.div, MDUOpType.divuw),
    REMW           -> List(InstrR, FuType.div, MDUOpType.remw),
    REMUW          -> List(InstrR, FuType.div, MDUOpType.remuw)
  )
  val table = mulTable ++ (if (HasDiv) divTable else Nil)
}

object RVMInstr extends HasXSParameter {
  val table = RV32MInstr.table ++ (if (XLEN == 64) RV64MInstr.table else Nil)
}
