1   /* Copyright (C) 2008 The Android Open Source Project
2    *
3    * Licensed under the Apache License, Version 2.0 (the "License");
4    * you may not use this file except in compliance with the License.
5    * You may obtain a copy of the License at
6    *
7    * http://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10    * distributed under the License is distributed on an "AS IS" BASIS,
11    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12    * See the License for the specific language governing permissions and
13    * limitations under the License.
14    */
15
16   /*
17    * File: OP_FILLED_NEW_ARRAY.S
18    *
19    * Code: Constructs and fills an array with the given data. Provides
20    *
21    * For: float-to-int
22    *
23    * Description: Construct an array of the given type and size,
24    *              filling it with the supplied contents. The type
25    *              must be an array type. The array's contents
26    *              must be single-word. The constructed instance
27    *              is stored as a result in the same way that the
28    *              method invocation instructions store their results,
29    *              so the constructed instance must be moved to a
30    *              register with a subsequent move-result-object
31    *              instruction.
32    *
33    * Format: B|A|op CCCC G|F|E|D (35c)
34    *         AA|op BBBB CCCC (3rc) (range)
35    *
36    * Syntax: [B=5] op {vD, vE, vF, vG, vA}, vtaboff@CCCC
37    *         [B=4] op {vD, vE, vF, vG}, vtaboff@CCCC
38    *         [B=3] op {vD, vE, vF}, vtaboff@CCCC
39    *         [B=2] op {vD, vE}, vtaboff@CCCC
40    *         [B=1] op {vD}, vtaboff@CCCC
41    *
42    *         op {vCCCC .. vNNNN}, meth@BBBB
43    *         op {vCCCC .. vNNNN}, type@BBBB
44    */
45
46%default { "isrange":"0" }
47
48    movl        rGLUE, %edx             # %edx<- MterpGlue pointer
49    movl        offGlue_methodClassDex(%edx), %edx # %edx<- glue->methodClassDex
50    movl        offDvmDex_pResClasses(%edx), %edx # %edx<- glue->methodClassDex->pResClasses
51    FETCH       1, %ecx                 # %ecx<- BBBB
52    EXPORT_PC
53    movl (%edx, %ecx, 4), %eax # %eax<- possibly resolved class
54    cmp         $$0, %eax               # %eax<- check if already resolved
55    jne         .L${opcode}_continue
56    jmp         .L${opcode}_break
57%break
58
59.L${opcode}_break:
60    movl        $$0, -8(%esp)           # push parameter false
61    movl        %ecx, -12(%esp)         # push parameter BBBB
62    movl        rGLUE, %edx             # %edx<- MterpGlue pointer
63    movl        offGlue_method(%edx), %edx # %edx<- glue->method
64    movl        offMethod_clazz(%edx), %edx # %edx<- glue->method->clazz
65    movl        %edx, -16(%esp)         # push parameter glue->method->clazz
66    lea         -16(%esp), %esp
67    call        dvmResolveClass         # call: (const ClassObject* referrer, u4 classIdx,
68                                        #        bool fromUnverifiedConstant)
69                                        # return: ClassObject*
70    lea         16(%esp), %esp
71    cmp         $$0, %eax               # check for null return
72    je          common_exceptionThrown  # handle exception
73
74   /*
75    * On entry:
76    *  %eax holds array class
77    *  rINST holds BA or AA
78    */
79
80.L${opcode}_continue:
81    movl        offClassObject_descriptor(%eax), %eax # %eax<- arrayClass->descriptor
82    movzbl      1(%eax), %eax           # %eax<- descriptor[1]
83    cmpb        $$'I', %al             # check if array of ints
84    je          1f
85    cmpb        $$'L', %al
86    je          1f
87    cmpb        $$'[', %al
88    jne         .L${opcode}_notimpl     # jump to not implemented
891:
90    movl        %eax, sReg0             # save type
91    movl        rINST, -12(%esp)        # push parameter length
92    movl        %eax, -16(%esp)         # push parameter descriptor[1]
93    movl        $$ALLOC_DONT_TRACK, -8(%esp) # push parameter to allocate flags
94    .if         (!$isrange)
95    shrl        $$4, -12(%esp)          # parameter length is B
96    .endif
97    lea         -16(%esp), %esp
98    call        dvmAllocPrimitiveArray  # call: (char type, size_t length, int allocFlags)
99                                        # return: ArrayObject*
100    lea         16(%esp), %esp
101    cmp         $$0, %eax               # check for null return
102    je          common_exceptionThrown  # handle exception
103
104    FETCH       2, %edx                 # %edx<- FEDC or CCCC
105    movl        rGLUE, %ecx             # %ecx<- MterpGlue pointer
106    movl        %eax, offGlue_retval(%ecx) # retval<- new array
107    lea         offArrayObject_contents(%eax), %eax # %eax<- newArray->contents
108    subl        $$1, -12(%esp)          # length--; check for negative
109    js          2f                      # if length was zero, finish
110
111   /*
112    * copy values from registers into the array
113    * %eax=array, %edx=CCCC/FEDC, -12(%esp)=length (from AA or B), rINST=AA/BA
114    */
115
116    .if         $isrange
117    lea         (rFP, %edx, 4), %ecx    # %ecx<- &fpp[CCCC]
1181:
119    movl        (%ecx), %edx            # %edx<- %ecx++
120    lea         4(%ecx), %ecx           # %ecx++
121    movl        %edx, (%eax)            # *contents<- vX
122    lea         4(%eax), %eax           # %eax++; contents++
123    subl        $$1, -12(%esp)          # length--
124    jns         1b                      # or continue at 2
125    .else
126    cmp         $$4, -12(%esp)          # check length
127    jne         1f                      # has four args
128    and         $$15, rINST             # rINST<- A
129    GET_VREG    rINST                   # rINST<- vA
130    subl        $$1, -12(%esp)          # count--
131    movl        rINST, 16(%eax)         # contents[4]<- vA
1321:
133    movl        %edx, %ecx              # %ecx<- %edx; ecx for temp
134    andl        $$15, %ecx              # %ecx<- G/F/E/D
135    GET_VREG    %ecx                    # %ecx<- vG/vF/vE/vD
136    shr         $$4, %edx               # %edx<- put next reg in low 4
137    subl        $$1, -12(%esp)          # count--
138    movl        %ecx, (%eax)            # *contents<- vX
139    lea         4(%eax), %eax           # %eax++; contents++
140    jns         1b                      # or continue at 2
141    .endif
1422:
143    cmpb        $$'I', sReg0            # check for int array
144    je          3f
145    movl        rGLUE, %ecx             # %ecx<- MterpGlue pointer
146    movl        offGlue_retval(%ecx), %eax # Object head
147    movl        offGlue_cardTable(%ecx), %ecx # card table base
148    shrl        $$GC_CARD_SHIFT, %eax   # convert to card num
149    movb        %cl,(%ecx, %eax)        # mark card based on object head
1503:
151    FINISH      3                       # jump to next instruction
152
153   /*
154    * Throw an exception to indicate this mode of filled-new-array
155    * has not been implemented.
156    */
157
158.L${opcode}_notimpl:
159    movl        $$.LstrInternalError, -8(%esp)
160    movl        $$.LstrFilledNewArrayNotImpl, -4(%esp)
161    lea         -8(%esp), %esp
162    call        dvmThrowException # call: (const char* exceptionDescriptor,
163                                  #        const char* msg)
164                                  # return: void
165    lea         8(%esp), %esp
166    jmp         common_exceptionThrown
167
168.if         (!$isrange)                 # define in one or the other, not both
169.LstrFilledNewArrayNotImpl:
170.asciz      "filled-new-array only implemented for 'int'"
171.LstrInternalError:
172.asciz  "Ljava/lang/InternalError;"
173.endif
174