%default { "isrange":"0" }
%verify "executed"
%verify "unimplemented array type"
    /*
     * Create a new array with elements filled from registers.
     *
     * for: filled-new-array, filled-new-array/range
     */
    # op vB, {vD, vE, vF, vG, vA}, class   /* CCCC */
    # op {vCCCC..v(CCCC+AA-1)}, type       /* BBBB */
    LOAD_rSELF_methodClassDex(a3)          #  a3 <- pDvmDex
    FETCH(a1, 1)                           #  a1 <- BBBB
    LOAD_base_offDvmDex_pResClasses(a3, a3) #  a3 <- pDvmDex->pResClasses
    EXPORT_PC()                            #  need for resolve and alloc
    LOAD_eas2(a0, a3, a1)                  #  a0 <- resolved class
    GET_OPA(rOBJ)                          #  rOBJ <- AA or BA
    # already resolved?
    bnez      a0, .L${opcode}_continue     #  yes, continue on
    LOAD_rSELF_method(a3)                  #  a3 <- self->method
    li        a2, 0                        #  a2 <- false
    LOAD_base_offMethod_clazz(a0, a3)      #  a0 <- method->clazz
    JAL(dvmResolveClass)                   #  v0 <- call(clazz, ref)
    move      a0, v0
    # got null?
    beqz      v0, common_exceptionThrown   #  yes, handle exception
    b         .L${opcode}_continue
%break

    /*
     * On entry:
     *  a0 holds array class
     *  rOBJ holds AA or BA
     */
.L${opcode}_continue:
    LOAD_base_offClassObject_descriptor(a3, a0) #  a3 <- arrayClass->descriptor
    li        a2, ALLOC_DONT_TRACK         #  a2 <- alloc flags
    lbu       rINST, 1(a3)                 #  rINST <- descriptor[1]
    .if $isrange
    move      a1, rOBJ                     #  a1 <- AA (length)
    .else
    srl       a1, rOBJ, 4                  #  rOBJ <- B (length)
    .endif
    seq       t0, rINST, 'I'               #  array of ints?
    seq       t1, rINST, 'L'               #  array of objects?
    or        t0, t1
    seq       t1, rINST, '['               #  array of arrays?
    or        t0, t1
    move      rBIX, a1                     #  save length in rBIX
    beqz      t0, .L${opcode}_notimpl      #  no, not handled yet
    JAL(dvmAllocArrayByClass)              #  v0 <- call(arClass, length, flags)
    # null return?
    beqz      v0, common_exceptionThrown   #  alloc failed, handle exception

    FETCH(a1, 2)                           #  a1 <- FEDC or CCCC
    sw        v0, offThread_retval(rSELF)  #  retval.l <- new array
    sw        rINST, (offThread_retval+4)(rSELF) #  retval.h <- type
    addu      a0, v0, offArrayObject_contents #  a0 <- newArray->contents
    subu      rBIX, rBIX, 1                #  length--, check for neg
    FETCH_ADVANCE_INST(3)                  #  advance to next instr, load rINST
    bltz      rBIX, 2f                     #  was zero, bail

    # copy values from registers into the array
    # a0=array, a1=CCCC/FEDC, t0=length (from AA or B), rOBJ=AA/BA
    move      t0, rBIX
    .if $isrange
    EAS2(a2, rFP, a1)                      #  a2 <- &fp[CCCC]
1:
    lw        a3, 0(a2)                    #  a3 <- *a2++
    addu      a2, 4
    subu      t0, t0, 1                    #  count--
    sw        a3, (a0)                     #  *contents++ = vX
    addu      a0, 4
    bgez      t0, 1b

    # continue at 2
    .else
    slt       t1, t0, 4                    #  length was initially 5?
    and       a2, rOBJ, 15                 #  a2 <- A
    bnez      t1, 1f                       #  <= 4 args, branch
    GET_VREG(a3, a2)                       #  a3 <- vA
    subu      t0, t0, 1                    #  count--
    sw        a3, 16(a0)                   #  contents[4] = vA
1:
    and       a2, a1, 15                   #  a2 <- F/E/D/C
    GET_VREG(a3, a2)                       #  a3 <- vF/vE/vD/vC
    srl       a1, a1, 4                    #  a1 <- next reg in low 4
    subu      t0, t0, 1                    #  count--
    sw        a3, 0(a0)                    #  *contents++ = vX
    addu      a0, a0, 4
    bgez      t0, 1b
    # continue at 2
    .endif

2:
    lw        a0, offThread_retval(rSELF)  #  a0 <- object
    lw        a1, (offThread_retval+4)(rSELF) #  a1 <- type
    seq       t1, a1, 'I'                  #  Is int array?
    bnez      t1, 3f
    lw        a2, offThread_cardTable(rSELF) #  a2 <- card table base
    srl       t3, a0, GC_CARD_SHIFT
    addu      t2, a2, t3
    sb        a2, (t2)
3:
    GET_INST_OPCODE(t0)                    #  ip <- opcode from rINST
    GOTO_OPCODE(t0)                        #  execute it


    /*
     * Throw an exception indicating that we have not implemented this
     * mode of filled-new-array.
     */
.L${opcode}_notimpl:
    la        a0, .LstrFilledNewArrayNotImpl
    JAL(dvmThrowInternalError)
    b         common_exceptionThrown

    /*
     * Ideally we'd only define this once, but depending on layout we can
     * exceed the range of the load above.
     */