from ... import platforms
from .. import state
from . import cpu


class LoongArch(cpu.CPU):
    """Abstract CPU state object for all LoongArch targets"""

    def __init__(self, wordsize: int) -> None:
        super().__init__()
        # Program counter (not a real register)
        self.pc = state.Register("pc", size=wordsize)
        self.add(self.pc)
        # Zero register
        self.r0 = state.Register("r0", size=wordsize)
        self.add(self.r0)
        self.zero = state.RegisterAlias("zero", self.r0, size=wordsize, offset=0)
        self.add(self.zero)
        # Return address
        self.r1 = state.Register("r1", size=wordsize)
        self.add(self.r1)
        self.ra = state.RegisterAlias("ra", self.r1, size=wordsize, offset=0)
        self.add(self.ra)
        # TLS pointer
        self.r2 = state.Register("r2", size=wordsize)
        self.add(self.r2)
        self.tp = state.RegisterAlias("tp", self.r2, size=wordsize, offset=0)
        self.add(self.tp)
        # Stack pointer
        self.r3 = state.Register("r3", size=wordsize)
        self.add(self.r3)
        self.sp = state.RegisterAlias("sp", self.r3, size=wordsize, offset=0)
        self.add(self.sp)
        # Arguments.
        # a0 and a1 are also the return registers
        self.r4 = state.Register("r4", size=wordsize)
        self.add(self.r4)
        self.a0 = state.RegisterAlias("a0", self.r4, size=wordsize, offset=0)
        self.add(self.a0)
        self.v0 = state.RegisterAlias("v0", self.r4, size=wordsize, offset=0)
        self.add(self.v0)
        self.r5 = state.Register("r5", size=wordsize)
        self.add(self.r5)
        self.a1 = state.RegisterAlias("a1", self.r5, size=wordsize, offset=0)
        self.add(self.a1)
        self.v1 = state.RegisterAlias("v1", self.r5, size=wordsize, offset=0)
        self.add(self.v1)
        self.r6 = state.Register("r6", size=wordsize)
        self.add(self.r6)
        self.a2 = state.RegisterAlias("a2", self.r6, size=wordsize, offset=0)
        self.add(self.a2)
        self.r7 = state.Register("r7", size=wordsize)
        self.add(self.r7)
        self.a3 = state.RegisterAlias("a3", self.r7, size=wordsize, offset=0)
        self.add(self.a3)
        self.r8 = state.Register("r8", size=wordsize)
        self.add(self.r8)
        self.a4 = state.RegisterAlias("a4", self.r8, size=wordsize, offset=0)
        self.add(self.a4)
        self.r9 = state.Register("r9", size=wordsize)
        self.add(self.r9)
        self.a5 = state.RegisterAlias("a5", self.r9, size=wordsize, offset=0)
        self.add(self.a5)
        self.r10 = state.Register("r10", size=wordsize)
        self.add(self.r10)
        self.a6 = state.RegisterAlias("a6", self.r10, size=wordsize, offset=0)
        self.add(self.a6)
        self.r11 = state.Register("r11", size=wordsize)
        self.add(self.r11)
        self.a7 = state.RegisterAlias("a7", self.r11, size=wordsize, offset=0)
        self.add(self.a7)
        # Temporary registers
        self.r12 = state.Register("r12", size=wordsize)
        self.add(self.r12)
        self.t0 = state.RegisterAlias("t0", self.r12, size=wordsize, offset=0)
        self.add(self.t0)
        self.r13 = state.Register("r13", size=wordsize)
        self.add(self.r13)
        self.t1 = state.RegisterAlias("t1", self.r13, size=wordsize, offset=0)
        self.add(self.t1)
        self.r14 = state.Register("r14", size=wordsize)
        self.add(self.r14)
        self.t2 = state.RegisterAlias("t2", self.r14, size=wordsize, offset=0)
        self.add(self.t2)
        self.r15 = state.Register("r15", size=wordsize)
        self.add(self.r15)
        self.t3 = state.RegisterAlias("t3", self.r15, size=wordsize, offset=0)
        self.add(self.t3)
        self.r16 = state.Register("r16", size=wordsize)
        self.add(self.r16)
        self.t4 = state.RegisterAlias("t4", self.r16, size=wordsize, offset=0)
        self.add(self.t4)
        self.r17 = state.Register("r17", size=wordsize)
        self.add(self.r17)
        self.t5 = state.RegisterAlias("t5", self.r17, size=wordsize, offset=0)
        self.add(self.t5)
        self.r18 = state.Register("r18", size=wordsize)
        self.add(self.r18)
        self.t6 = state.RegisterAlias("t6", self.r18, size=wordsize, offset=0)
        self.add(self.t6)
        self.r19 = state.Register("r19", size=wordsize)
        self.add(self.r19)
        self.t7 = state.RegisterAlias("t7", self.r19, size=wordsize, offset=0)
        self.add(self.t7)
        self.r20 = state.Register("r20", size=wordsize)
        self.add(self.r20)
        self.t8 = state.RegisterAlias("t8", self.r20, size=wordsize, offset=0)
        self.add(self.t8)
        # Per-CPU Base Address
        self.r21 = state.Register("r21", size=wordsize)
        self.add(self.r21)
        self.u0 = state.RegisterAlias("u0", self.r21, size=wordsize, offset=0)
        self.add(self.u0)
        # Frame Pointer
        self.r22 = state.Register("r22", size=wordsize)
        self.add(self.r22)
        self.fp = state.RegisterAlias("fp", self.r22, size=wordsize, offset=0)
        self.add(self.fp)
        # Static registers
        self.r23 = state.Register("r23", size=wordsize)
        self.add(self.r23)
        self.s0 = state.RegisterAlias("s0", self.r23, size=wordsize, offset=0)
        self.add(self.s0)
        self.r24 = state.Register("r24", size=wordsize)
        self.add(self.r24)
        self.s1 = state.RegisterAlias("s1", self.r24, size=wordsize, offset=0)
        self.add(self.s1)
        self.r25 = state.Register("r25", size=wordsize)
        self.add(self.r25)
        self.s2 = state.RegisterAlias("s2", self.r25, size=wordsize, offset=0)
        self.add(self.s2)
        self.r26 = state.Register("r26", size=wordsize)
        self.add(self.r26)
        self.s3 = state.RegisterAlias("s3", self.r26, size=wordsize, offset=0)
        self.add(self.s3)
        self.r27 = state.Register("r27", size=wordsize)
        self.add(self.r27)
        self.s4 = state.RegisterAlias("s4", self.r27, size=wordsize, offset=0)
        self.add(self.s4)
        self.r28 = state.Register("r28", size=wordsize)
        self.add(self.r28)
        self.s5 = state.RegisterAlias("s5", self.r28, size=wordsize, offset=0)
        self.add(self.s5)
        self.r29 = state.Register("r29", size=wordsize)
        self.add(self.r29)
        self.s6 = state.RegisterAlias("s6", self.r29, size=wordsize, offset=0)
        self.add(self.s6)
        self.r30 = state.Register("r30", size=wordsize)
        self.add(self.r30)
        self.s7 = state.RegisterAlias("s7", self.r30, size=wordsize, offset=0)
        self.add(self.s7)
        self.r31 = state.Register("r31", size=wordsize)
        self.add(self.r31)
        self.s8 = state.RegisterAlias("s8", self.r31, size=wordsize, offset=0)
        self.add(self.s8)
        # Floating-point arguments.
        # fa0 and fa1 are also return values
        self.f0 = state.Register("f0", size=8)
        self.add(self.f0)
        self.fa0 = state.RegisterAlias("fa0", self.f0, size=8, offset=0)
        self.add(self.fa0)
        self.f1 = state.Register("f1", size=8)
        self.add(self.f1)
        self.fa1 = state.RegisterAlias("fa1", self.f1, size=8, offset=0)
        self.add(self.fa1)
        self.f2 = state.Register("f2", size=8)
        self.add(self.f2)
        self.fa2 = state.RegisterAlias("fa2", self.f2, size=8, offset=0)
        self.add(self.fa2)
        self.f3 = state.Register("f3", size=8)
        self.add(self.f3)
        self.fa3 = state.RegisterAlias("fa3", self.f3, size=8, offset=0)
        self.add(self.fa3)
        self.f4 = state.Register("f4", size=8)
        self.add(self.f4)
        self.fa4 = state.RegisterAlias("fa4", self.f4, size=8, offset=0)
        self.add(self.fa4)
        self.f5 = state.Register("f5", size=8)
        self.add(self.f5)
        self.fa5 = state.RegisterAlias("fa5", self.f5, size=8, offset=0)
        self.add(self.fa5)
        self.f6 = state.Register("f6", size=8)
        self.add(self.f6)
        self.fa6 = state.RegisterAlias("fa6", self.f6, size=8, offset=0)
        self.add(self.fa6)
        self.f7 = state.Register("f7", size=8)
        self.add(self.f7)
        self.fa7 = state.RegisterAlias("fa7", self.f7, size=8, offset=0)
        self.add(self.fa7)
        # Floating-point temporary registers
        self.f8 = state.Register("f8", size=8)
        self.add(self.f8)
        self.ft0 = state.RegisterAlias("ft0", self.f8, size=8, offset=0)
        self.add(self.ft0)
        self.f9 = state.Register("f9", size=8)
        self.add(self.f9)
        self.ft1 = state.RegisterAlias("ft1", self.f9, size=8, offset=0)
        self.add(self.ft1)
        self.f10 = state.Register("f10", size=8)
        self.add(self.f10)
        self.ft2 = state.RegisterAlias("ft2", self.f10, size=8, offset=0)
        self.add(self.ft2)
        self.f11 = state.Register("f11", size=8)
        self.add(self.f11)
        self.ft3 = state.RegisterAlias("ft3", self.f11, size=8, offset=0)
        self.add(self.ft3)
        self.f12 = state.Register("f12", size=8)
        self.add(self.f12)
        self.ft4 = state.RegisterAlias("ft4", self.f12, size=8, offset=0)
        self.add(self.ft4)
        self.f13 = state.Register("f13", size=8)
        self.add(self.f13)
        self.ft5 = state.RegisterAlias("ft5", self.f13, size=8, offset=0)
        self.add(self.ft5)
        self.f14 = state.Register("f14", size=8)
        self.add(self.f14)
        self.ft6 = state.RegisterAlias("ft6", self.f14, size=8, offset=0)
        self.add(self.ft6)
        self.f15 = state.Register("f15", size=8)
        self.add(self.f15)
        self.ft7 = state.RegisterAlias("ft7", self.f15, size=8, offset=0)
        self.add(self.ft7)
        self.f16 = state.Register("f16", size=8)
        self.add(self.f16)
        self.ft8 = state.RegisterAlias("ft8", self.f16, size=8, offset=0)
        self.add(self.ft8)
        self.f17 = state.Register("f17", size=8)
        self.add(self.f17)
        self.ft9 = state.RegisterAlias("ft9", self.f17, size=8, offset=0)
        self.add(self.ft9)
        self.f18 = state.Register("f18", size=8)
        self.add(self.f18)
        self.ft10 = state.RegisterAlias("ft10", self.f18, size=8, offset=0)
        self.add(self.ft10)
        self.f19 = state.Register("f19", size=8)
        self.add(self.f19)
        self.ft11 = state.RegisterAlias("ft11", self.f19, size=8, offset=0)
        self.add(self.ft11)
        self.f20 = state.Register("f20", size=8)
        self.add(self.f20)
        self.ft12 = state.RegisterAlias("ft12", self.f20, size=8, offset=0)
        self.add(self.ft12)
        self.f21 = state.Register("f21", size=8)
        self.add(self.f21)
        self.ft13 = state.RegisterAlias("ft13", self.f21, size=8, offset=0)
        self.add(self.ft13)
        self.f22 = state.Register("f22", size=8)
        self.add(self.f22)
        self.ft14 = state.RegisterAlias("ft14", self.f22, size=8, offset=0)
        self.add(self.ft14)
        self.f23 = state.Register("f23", size=8)
        self.add(self.f23)
        self.ft15 = state.RegisterAlias("ft15", self.f23, size=8, offset=0)
        self.add(self.ft15)
        # Floating-point static registers
        self.f24 = state.Register("f24", size=8)
        self.add(self.f24)
        self.fs0 = state.RegisterAlias("fs0", self.f24, size=8, offset=0)
        self.add(self.fs0)
        self.f25 = state.Register("f25", size=8)
        self.add(self.f25)
        self.fs1 = state.RegisterAlias("fs1", self.f25, size=8, offset=0)
        self.add(self.fs1)
        self.f26 = state.Register("f26", size=8)
        self.add(self.f26)
        self.fs2 = state.RegisterAlias("fs2", self.f26, size=8, offset=0)
        self.add(self.fs2)
        self.f27 = state.Register("f27", size=8)
        self.add(self.f27)
        self.fs3 = state.RegisterAlias("fs3", self.f27, size=8, offset=0)
        self.add(self.fs3)
        self.f28 = state.Register("f28", size=8)
        self.add(self.f28)
        self.fs4 = state.RegisterAlias("fs4", self.f28, size=8, offset=0)
        self.add(self.fs4)
        self.f29 = state.Register("f29", size=8)
        self.add(self.f29)
        self.fs5 = state.RegisterAlias("fs5", self.f29, size=8, offset=0)
        self.add(self.fs5)
        self.f30 = state.Register("f30", size=8)
        self.add(self.f30)
        self.fs6 = state.RegisterAlias("fs6", self.f30, size=8, offset=0)
        self.add(self.fs6)
        self.f31 = state.Register("f31", size=8)
        self.add(self.f31)
        self.fs7 = state.RegisterAlias("fs7", self.f31, size=8, offset=0)
        self.add(self.fs7)


class LoongArch64(LoongArch):
    platform = platforms.Platform(
        platforms.Architecture.LOONGARCH64, platforms.Byteorder.LITTLE
    )

    def __init__(self):
        super().__init__(8)


__all__ = ["LoongArch64"]
