| %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 */ |
| ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex |
| FETCH(r1, 1) @ r1<- BBBB |
| ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses |
| EXPORT_PC() @ need for resolve and alloc |
| ldr r0, [r3, r1, lsl #2] @ r0<- resolved class |
| mov r10, rINST, lsr #8 @ r10<- AA or BA |
| cmp r0, #0 @ already resolved? |
| bne .L${opcode}_continue @ yes, continue on |
| 8: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method |
| mov r2, #0 @ r2<- false |
| ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz |
| bl dvmResolveClass @ r0<- call(clazz, ref) |
| cmp r0, #0 @ got null? |
| beq common_exceptionThrown @ yes, handle exception |
| b .L${opcode}_continue |
| %break |
| |
| /* |
| * On entry: |
| * r0 holds array class |
| * r10 holds AA or BA |
| */ |
| .L${opcode}_continue: |
| ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor |
| mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags |
| ldrb r3, [r3, #1] @ r3<- descriptor[1] |
| .if $isrange |
| mov r1, r10 @ r1<- AA (length) |
| .else |
| mov r1, r10, lsr #4 @ r1<- B (length) |
| .endif |
| cmp r3, #'I' @ array of ints? |
| cmpne r3, #'L' @ array of objects? |
| cmpne r3, #'[' @ array of arrays? |
| mov r9, r1 @ save length in r9 |
| bne .L${opcode}_notimpl @ no, not handled yet |
| bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) |
| cmp r0, #0 @ null return? |
| beq common_exceptionThrown @ alloc failed, handle exception |
| |
| FETCH(r1, 2) @ r1<- FEDC or CCCC |
| str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array |
| add r0, r0, #offArrayObject_contents @ r0<- newArray->contents |
| subs r9, r9, #1 @ length--, check for neg |
| FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST |
| bmi 2f @ was zero, bail |
| |
| @ copy values from registers into the array |
| @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA |
| .if $isrange |
| add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] |
| 1: ldr r3, [r2], #4 @ r3<- *r2++ |
| subs r9, r9, #1 @ count-- |
| str r3, [r0], #4 @ *contents++ = vX |
| bpl 1b |
| @ continue at 2 |
| .else |
| cmp r9, #4 @ length was initially 5? |
| and r2, r10, #15 @ r2<- A |
| bne 1f @ <= 4 args, branch |
| GET_VREG(r3, r2) @ r3<- vA |
| sub r9, r9, #1 @ count-- |
| str r3, [r0, #16] @ contents[4] = vA |
| 1: and r2, r1, #15 @ r2<- F/E/D/C |
| GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC |
| mov r1, r1, lsr #4 @ r1<- next reg in low 4 |
| subs r9, r9, #1 @ count-- |
| str r3, [r0], #4 @ *contents++ = vX |
| bpl 1b |
| @ continue at 2 |
| .endif |
| |
| 2: |
| GET_INST_OPCODE(ip) @ ip<- opcode from rINST |
| GOTO_OPCODE(ip) @ execute it |
| |
| /* |
| * Throw an exception indicating that we have not implemented this |
| * mode of filled-new-array. |
| */ |
| .L${opcode}_notimpl: |
| ldr r0, .L_strInternalError |
| ldr r1, .L_strFilledNewArrayNotImpl |
| bl dvmThrowException |
| b common_exceptionThrown |
| |
| .if (!$isrange) @ define in one or the other, not both |
| .L_strFilledNewArrayNotImpl: |
| .word .LstrFilledNewArrayNotImpl |
| .L_strInternalError: |
| .word .LstrInternalError |
| .endif |