summaryrefslogtreecommitdiff
path: root/vm/mterp/x86/OP_FILLED_NEW_ARRAY.S
blob: 55b1f848a796194de3b76a40971dad8f567cf376 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
%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 */
    GET_GLUE(%eax)
    movzbl  rINST_HI,rINST_FULL               # rINST_FULL<- AA or BA
    movl    offGlue_methodClassDex(%eax),%eax # eax<- pDvmDex
    movzwl  2(rPC),%ecx                       # ecx<- BBBB
    movl    offDvmDex_pResClasses(%eax),%eax  # eax<- pDvmDex->pResClasses
    SPILL(rPC)
    movl    (%eax,%ecx,4),%eax                # eax<- resolved class
    EXPORT_PC()
    testl   %eax,%eax                         # already resolved?
    jne     .L${opcode}_continue              # yes, continue
    # less frequent path, so we'll redo some work
    GET_GLUE(%eax)
    movl    $$0,OUT_ARG2(%esp)                # arg2<- false
    movl    %ecx,OUT_ARG1(%esp)               # arg1<- BBBB
    movl    offGlue_method(%eax),%eax         # eax<- glue->method
    jmp     .L${opcode}_more
%break

.L${opcode}_more:
    movl    offMethod_clazz(%eax),%eax        # eax<- method->clazz
    movl    %eax,OUT_ARG0(%esp)               # arg0<- clazz
    call    dvmResolveClass                   # eax<- call(clazz,ref,flag)
    UNSPILL(rPC)
    testl   %eax,%eax                         # null?
    je      common_exceptionThrown            # yes, handle it

       # note: fall through to .L${opcode}_continue

    /*
     * On entry:
     *    eax holds array class [r0]
     *    rINST_FULL holds AA or BB [r10]
     *    ecx is scratch
     *    rPC is valid, but has been spilled
     */
.L${opcode}_continue:
    movl    offClassObject_descriptor(%eax),%ecx  # ecx<- arrayClass->descriptor
    movl    $$ALLOC_DONT_TRACK,OUT_ARG2(%esp)     # arg2<- flags
    movzbl  1(%ecx),%ecx                          # ecx<- descriptor[1]
    movl    %eax,OUT_ARG0(%esp)                   # arg0<- arrayClass
    GET_GLUE(%eax)
    cmpb    $$'I',%cl                             # supported?
    je      1f
    cmpb    $$'L',%cl
    je      1f
    cmpb    $$'[',%cl
    jne      .L${opcode}_notimpl                  # no, not handled yet
1:
    movl    %ecx,offGlue_retval+4(%eax)           # save type
    .if      (!$isrange)
    SPILL_TMP(rINST_FULL)                         # save copy, need "B" later
    sarl    $$4,rINST_FULL
    .endif
    movl    rINST_FULL,OUT_ARG1(%esp)             # arg1<- A or AA (length)
    call    dvmAllocArrayByClass                  # eax<- call(arrayClass, length, flags)
    UNSPILL(rPC)
    GET_GLUE(%ecx)
    testl   %eax,%eax                             # alloc successful?
    je      common_exceptionThrown                # no, handle exception
    movl    %eax,offGlue_retval(%ecx)             # retval.l<- new array
    movzwl  4(rPC),%ecx                           # ecx<- FEDC or CCCC
    leal    offArrayObject_contents(%eax),%eax    # eax<- newArray->contents

/* at this point:
 *     eax is pointer to tgt
 *     rINST_FULL is length
 *     ecx is FEDC or CCCC
 *     TMP_SPILL is BA
 *     rPC is valid, but spilled
 *  We now need to copy values from registers into the array
 */

    .if $isrange
    # set up src pointer
    SPILL(rFP)     # esi
    SPILL(rIBASE)   # edi
    movl    %eax,%edi         # set up dst ptr
    leal    (rFP,%ecx,4),%esi # set up src ptr
    movl    rINST_FULL,%ecx   # load count register
    FETCH_INST_WORD(3)
    rep
    movsd
    GET_GLUE(%ecx)
    UNSPILL(rIBASE)
    movl    offGlue_retval+4(%ecx),%eax      # eax<- type
    UNSPILL(rFP)
    .else
    testl  rINST_FULL,rINST_FULL
    je     4f
    UNSPILL_TMP(rPC)
    andl   $$0x0f,rPC            # rPC<- 0000000A
    sall   $$16,rPC              # rPC<- 000A0000
    orl    %ecx,rPC              # rpc<- 000AFEDC
3:
    movl   $$0xf,%ecx
    andl   rPC,%ecx           # ecx<- next reg to load
    GET_VREG(%ecx,%ecx)
    shrl   $$4,rPC
    leal   4(%eax),%eax
    movl   %ecx,-4(%eax)
    sub    $$1,rINST_FULL
    jne    3b
4:
    GET_GLUE(%ecx)
    UNSPILL(rPC)
    movl    offGlue_retval+4(%ecx),%eax      # eax<- type
    FETCH_INST_WORD(3)
    .endif

    cmpb    $$'I',%al                        # Int array?
    je      5f                               # skip card mark if so
    movl    offGlue_retval(%ecx),%eax        # eax<- object head
    movl    offGlue_cardTable(%ecx),%ecx     # card table base
    shrl    $$GC_CARD_SHIFT,%eax             # convert to card num
    movb    %cl,(%ecx,%eax)                  # mark card based on object head
5:
    ADVANCE_PC(3)
    GOTO_NEXT


    /*
     * Throw an exception indicating that we have not implemented this
     * mode of filled-new-array.
     */
.L${opcode}_notimpl:
    movl    $$.LstrInternalError,%eax
    movl    %eax,OUT_ARG0(%esp)
    movl    $$.LstrFilledNewArrayNotImpl,%eax
    movl    %eax,OUT_ARG1(%esp)
    call    dvmThrowException
    UNSPILL(rPC)
    jmp     common_exceptionThrown