; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=csky -verify-machineinstrs -csky-no-aliases -no-integrated-as < %s \
; RUN:   | FileCheck -check-prefix=CSKY %s

@gi = external global i32
@mi = external global i64

define i32 @constraint_r(i32 %a) nounwind {
; CSKY-LABEL: constraint_r:
; CSKY:       # %bb.0:
; CSKY-NEXT:    subi16 sp, sp, 4
; CSKY-NEXT:    lrw32 a1, [.LCPI0_0]
; CSKY-NEXT:    ld16.w a1, (a1, 0)
; CSKY-NEXT:    #APP
; CSKY-NEXT:    add a0, a0, a1
; CSKY-NEXT:    #NO_APP
; CSKY-NEXT:    addi16 sp, sp, 4
; CSKY-NEXT:    rts16
; CSKY-NEXT:    .p2align 1
; CSKY-NEXT:  # %bb.1:
; CSKY-NEXT:    .p2align 2
; CSKY-NEXT:  .LCPI0_0:
; CSKY-NEXT:    .long gi
  %1 = load i32, i32* @gi
  %2 = tail call i32 asm "add $0, $1, $2", "=r,r,r"(i32 %a, i32 %1)
  ret i32 %2
}

define i64 @constraint_r_i64(i32 %a) nounwind {
; CSKY-LABEL: constraint_r_i64:
; CSKY:       # %bb.0:
; CSKY-NEXT:    subi16 sp, sp, 4
; CSKY-NEXT:    lrw32 a3, [.LCPI1_0]
; CSKY-NEXT:    ld16.w a1, (a3, 0)
; CSKY-NEXT:    ld16.w a2, (a3, 4)
; CSKY-NEXT:    #APP
; CSKY-NEXT:    mula.s32 a1, a0, a0
; CSKY-NEXT:    #NO_APP
; CSKY-NEXT:    mov16 a0, a1
; CSKY-NEXT:    mov16 a1, a2
; CSKY-NEXT:    addi16 sp, sp, 4
; CSKY-NEXT:    rts16
; CSKY-NEXT:    .p2align 1
; CSKY-NEXT:  # %bb.1:
; CSKY-NEXT:    .p2align 2
; CSKY-NEXT:  .LCPI1_0:
; CSKY-NEXT:    .long mi
  %1 = load i64, i64* @mi
  %2 = call i64 asm "mula.s32 $0, $1, $2", "=r,r,r,0"(i32 %a, i32 %a, i64 %1)
  ret i64 %2
}

define i32 @constraint_a(i32 %a) nounwind {
; CSKY-LABEL: constraint_a:
; CSKY:       # %bb.0:
; CSKY-NEXT:    subi16 sp, sp, 4
; CSKY-NEXT:    lrw32 a1, [.LCPI2_0]
; CSKY-NEXT:    ld16.w a1, (a1, 0)
; CSKY-NEXT:    #APP
; CSKY-NEXT:    add a0, a0, a1
; CSKY-NEXT:    #NO_APP
; CSKY-NEXT:    addi16 sp, sp, 4
; CSKY-NEXT:    rts16
; CSKY-NEXT:    .p2align 1
; CSKY-NEXT:  # %bb.1:
; CSKY-NEXT:    .p2align 2
; CSKY-NEXT:  .LCPI2_0:
; CSKY-NEXT:    .long gi
  %1 = load i32, i32* @gi
  %2 = tail call i32 asm "add $0, $1, $2", "=a,a,a"(i32 %a, i32 %1)
  ret i32 %2
}

define i32 @constraint_b(i32 %a) nounwind {
; CSKY-LABEL: constraint_b:
; CSKY:       # %bb.0:
; CSKY-NEXT:    subi16 sp, sp, 4
; CSKY-NEXT:    lrw32 a1, [.LCPI3_0]
; CSKY-NEXT:    ld16.w a1, (a1, 0)
; CSKY-NEXT:    #APP
; CSKY-NEXT:    add a0, a0, a1
; CSKY-NEXT:    #NO_APP
; CSKY-NEXT:    addi16 sp, sp, 4
; CSKY-NEXT:    rts16
; CSKY-NEXT:    .p2align 1
; CSKY-NEXT:  # %bb.1:
; CSKY-NEXT:    .p2align 2
; CSKY-NEXT:  .LCPI3_0:
; CSKY-NEXT:    .long gi
  %1 = load i32, i32* @gi
  %2 = tail call i32 asm "add $0, $1, $2", "=b,b,b"(i32 %a, i32 %1)
  ret i32 %2
}

define i32 @constraint_z(i32 %a) nounwind {
; CSKY-LABEL: constraint_z:
; CSKY:       # %bb.0:
; CSKY-NEXT:    subi16 sp, sp, 4
; CSKY-NEXT:    mov16 sp, a0
; CSKY-NEXT:    lrw32 a0, [.LCPI4_0]
; CSKY-NEXT:    ld16.w a0, (a0, 0)
; CSKY-NEXT:    #APP
; CSKY-NEXT:    add a0, sp, a0
; CSKY-NEXT:    #NO_APP
; CSKY-NEXT:    addi16 sp, sp, 4
; CSKY-NEXT:    rts16
; CSKY-NEXT:    .p2align 1
; CSKY-NEXT:  # %bb.1:
; CSKY-NEXT:    .p2align 2
; CSKY-NEXT:  .LCPI4_0:
; CSKY-NEXT:    .long gi
  %1 = load i32, i32* @gi
  %2 = tail call i32 asm "add $0, $1, $2", "=r,z,r"(i32 %a, i32 %1)
  ret i32 %2
}

define i32 @constraint_c(i32 %a, i32 %b) nounwind {
; CSKY-LABEL: constraint_c:
; CSKY:       # %bb.0:
; CSKY-NEXT:    subi16 sp, sp, 4
; CSKY-NEXT:    lrw32 a1, [.LCPI5_0]
; CSKY-NEXT:    ld16.w a1, (a1, 0)
; CSKY-NEXT:    #APP
; CSKY-NEXT:    addc a0, a0, a1
; CSKY-NEXT:    #NO_APP
; CSKY-NEXT:    addi16 sp, sp, 4
; CSKY-NEXT:    rts16
; CSKY-NEXT:    .p2align 1
; CSKY-NEXT:  # %bb.1:
; CSKY-NEXT:    .p2align 2
; CSKY-NEXT:  .LCPI5_0:
; CSKY-NEXT:    .long gi
  %1 = load i32, i32* @gi
  %2 = tail call i32 asm "addc $0, $1, $2", "=r,r,r,~{c}"(i32 %a, i32 %1)
  ret i32 %2
}

define i32 @constraint_i(i32 %a) nounwind {
; CSKY-LABEL: constraint_i:
; CSKY:       # %bb.0:
; CSKY-NEXT:    subi16 sp, sp, 4
; CSKY-NEXT:    #APP
; CSKY-NEXT:    addi a0, a0, 113
; CSKY-NEXT:    #NO_APP
; CSKY-NEXT:    addi16 sp, sp, 4
; CSKY-NEXT:    rts16

  %1 = load i32, i32* @gi
  %2 = tail call i32 asm "addi $0, $1, $2", "=r,r,i"(i32 %a, i32 113)
  ret i32 %2
}

define void @constraint_m(i32* %a) nounwind {
; CSKY-LABEL: constraint_m:
; CSKY:       # %bb.0:
; CSKY-NEXT:    subi16 sp, sp, 4
; CSKY-NEXT:    #APP
; CSKY-NEXT:    #NO_APP
; CSKY-NEXT:    addi16 sp, sp, 4
; CSKY-NEXT:    rts16

  call void asm sideeffect "", "=*m"(i32* elementtype(i32) %a)
  ret void
}

define i32 @constraint_m2(i32* %a) nounwind {
; CSKY-LABEL: constraint_m2:
; CSKY:       # %bb.0:
; CSKY-NEXT:    subi16 sp, sp, 4
; CSKY-NEXT:    #APP
; CSKY-NEXT:    ld.w a0, (a0, 0)
; CSKY-NEXT:    #NO_APP
; CSKY-NEXT:    addi16 sp, sp, 4
; CSKY-NEXT:    rts16

  %1 = tail call i32 asm "ld.w $0, $1", "=r,*m"(i32* elementtype(i32) %a)
  ret i32 %1
}

define i32 @modifier_i_imm(i32 %a) nounwind {
; CSKY-LABEL: modifier_i_imm:
; CSKY:       # %bb.0:
; CSKY-NEXT:    subi16 sp, sp, 4
; CSKY-NEXT:    #APP
; CSKY-NEXT:    addi a0, a0, 1
; CSKY-NEXT:    #NO_APP
; CSKY-NEXT:    addi16 sp, sp, 4
; CSKY-NEXT:    rts16
  %1 = tail call i32 asm "addi $0, $1, $2", "=r,r,ri"(i32 %a, i32 1)
  ret i32 %1
}

define void @operand_global() nounwind {
; CSKY-LABEL: operand_global:
; CSKY:       # %bb.0:
; CSKY-NEXT:    subi16 sp, sp, 4
; CSKY-NEXT:    #APP
; CSKY-NEXT:    .4byte gi
; CSKY-NEXT:    #NO_APP
; CSKY-NEXT:    addi16 sp, sp, 4
; CSKY-NEXT:    rts16

  tail call void asm sideeffect ".4byte $0", "i"(i32* @gi)
  ret void
}

define void @operand_block_address() nounwind {
; CSKY-LABEL: operand_block_address:
; CSKY:       # %bb.0:
; CSKY-NEXT:    subi16 sp, sp, 4
; CSKY-NEXT:    #APP
; CSKY-NEXT:    br32 .Ltmp0
; CSKY-NEXT:    #NO_APP
; CSKY-NEXT:  .Ltmp0: # Block address taken
; CSKY-NEXT:  # %bb.1: # %bb
; CSKY-NEXT:    addi16 sp, sp, 4
; CSKY-NEXT:    rts16

  call void asm sideeffect "br32 $0", "i"(i8* blockaddress(@operand_block_address, %bb))
  br label %bb
bb:
  ret void
}

; TODO: expand tests for more complex constraints, out of range immediates etc
