1200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung/*
2200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung * ===========================================================================
3200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung *  Common subroutines and data
4200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung * ===========================================================================
5200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung */
6200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung
7200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    .text
8200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    .align 2
9200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung
10200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung/*
11200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung * We've detected a condition that will result in an exception, but the exception
12200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung * has not yet been thrown.  Just bail out to the reference interpreter to deal with it.
13200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung * TUNING: for consistency, we may want to just go ahead and handle these here.
14200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung */
15200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leungcommon_errDivideByZero:
16200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    EXPORT_PC()
17200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung#if MTERP_LOGGING
18200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    move  a0, rSELF
19200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    addu  a1, rFP, OFF_FP_SHADOWFRAME
20200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    JAL(MterpLogDivideByZeroException)
21200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung#endif
22200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    b MterpCommonFallback
23200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung
24200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leungcommon_errArrayIndex:
25200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    EXPORT_PC()
26200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung#if MTERP_LOGGING
27200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    move  a0, rSELF
28200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    addu  a1, rFP, OFF_FP_SHADOWFRAME
29200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    JAL(MterpLogArrayIndexException)
30200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung#endif
31200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    b MterpCommonFallback
32200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung
33200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leungcommon_errNegativeArraySize:
34200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    EXPORT_PC()
35200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung#if MTERP_LOGGING
36200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    move  a0, rSELF
37200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    addu  a1, rFP, OFF_FP_SHADOWFRAME
38200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    JAL(MterpLogNegativeArraySizeException)
39200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung#endif
40200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    b MterpCommonFallback
41200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung
42200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leungcommon_errNoSuchMethod:
43200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    EXPORT_PC()
44200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung#if MTERP_LOGGING
45200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    move  a0, rSELF
46200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    addu  a1, rFP, OFF_FP_SHADOWFRAME
47200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    JAL(MterpLogNoSuchMethodException)
48200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung#endif
49200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    b MterpCommonFallback
50200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung
51200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leungcommon_errNullObject:
52200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    EXPORT_PC()
53200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung#if MTERP_LOGGING
54200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    move  a0, rSELF
55200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    addu  a1, rFP, OFF_FP_SHADOWFRAME
56200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    JAL(MterpLogNullObjectException)
57200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung#endif
58200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    b MterpCommonFallback
59200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung
60200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leungcommon_exceptionThrown:
61200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    EXPORT_PC()
62200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung#if MTERP_LOGGING
63200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    move  a0, rSELF
64200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    addu  a1, rFP, OFF_FP_SHADOWFRAME
65200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    JAL(MterpLogExceptionThrownException)
66200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung#endif
67200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    b MterpCommonFallback
68200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung
69200f040af3e4fe9e178cb63c90860d58d90ef665Douglas LeungMterpSuspendFallback:
70200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    EXPORT_PC()
71200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung#if MTERP_LOGGING
72200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    move  a0, rSELF
73200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    addu  a1, rFP, OFF_FP_SHADOWFRAME
74200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    lw    a2, THREAD_FLAGS_OFFSET(rSELF)
75200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    JAL(MterpLogSuspendFallback)
76200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung#endif
77200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    b MterpCommonFallback
78200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung
79200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung/*
80200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung * If we're here, something is out of the ordinary.  If there is a pending
81200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung * exception, handle it.  Otherwise, roll back and retry with the reference
82200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung * interpreter.
83200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung */
84200f040af3e4fe9e178cb63c90860d58d90ef665Douglas LeungMterpPossibleException:
85200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    lw      a0, THREAD_EXCEPTION_OFFSET(rSELF)
86200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    beqz    a0, MterpFallback          # If exception, fall back to reference interpreter.
87200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    /* intentional fallthrough - handle pending exception. */
88200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung/*
89200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung * On return from a runtime helper routine, we've found a pending exception.
90200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung * Can we handle it here - or need to bail out to caller?
91200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung *
92200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung */
93200f040af3e4fe9e178cb63c90860d58d90ef665Douglas LeungMterpException:
94200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    move    a0, rSELF
95200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    addu    a1, rFP, OFF_FP_SHADOWFRAME
96200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    JAL(MterpHandleException)                    # (self, shadow_frame)
97200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    beqz    v0, MterpExceptionReturn             # no local catch, back to caller.
98200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    lw      a0, OFF_FP_CODE_ITEM(rFP)
99200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    lw      a1, OFF_FP_DEX_PC(rFP)
100200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    lw      rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF)
101200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    addu    rPC, a0, CODEITEM_INSNS_OFFSET
102200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    sll     a1, a1, 1
103200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    addu    rPC, rPC, a1                         # generate new dex_pc_ptr
104200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    /* Do we need to switch interpreters? */
105200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    JAL(MterpShouldSwitchInterpreters)
106200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    bnez    v0, MterpFallback
107200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    /* resume execution at catch block */
108200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    EXPORT_PC()
109200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    FETCH_INST()
110200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    GET_INST_OPCODE(t0)
111200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    GOTO_OPCODE(t0)
112200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    /* NOTE: no fallthrough */
113200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung
114200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung/*
115200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung * Check for suspend check request.  Assumes rINST already loaded, rPC advanced and
116200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung * still needs to get the opcode and branch to it, and flags are in lr.
117200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung */
118200f040af3e4fe9e178cb63c90860d58d90ef665Douglas LeungMterpCheckSuspendAndContinue:
119200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    lw      rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF)  # refresh rIBASE
120200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    and     ra, (THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
121200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    bnez    ra, 1f
122200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    GET_INST_OPCODE(t0)                 # extract opcode from rINST
123200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    GOTO_OPCODE(t0)                     # jump to next instruction
124200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung1:
125200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    EXPORT_PC()
126200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    move    a0, rSELF
127200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    JAL(MterpSuspendCheck)              # (self)
128200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    bnez    v0, MterpFallback
129200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    GET_INST_OPCODE(t0)                 # extract opcode from rINST
130200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    GOTO_OPCODE(t0)                     # jump to next instruction
131200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung
132200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung/*
133200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung * On-stack replacement has happened, and now we've returned from the compiled method.
134200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung */
135200f040af3e4fe9e178cb63c90860d58d90ef665Douglas LeungMterpOnStackReplacement:
136200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung#if MTERP_LOGGING
137200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    move    a0, rSELF
138200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    addu    a1, rFP, OFF_FP_SHADOWFRAME
139200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    move    a2, rINST
140200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    JAL(MterpLogOSR)
141200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung#endif
142200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    li      v0, 1                       # Signal normal return
143200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    b       MterpDone
144200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung
145200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung/*
146200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung * Bail out to reference interpreter.
147200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung */
148200f040af3e4fe9e178cb63c90860d58d90ef665Douglas LeungMterpFallback:
149200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    EXPORT_PC()
150200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung#if MTERP_LOGGING
151200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    move  a0, rSELF
152200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    addu  a1, rFP, OFF_FP_SHADOWFRAME
153200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    JAL(MterpLogFallback)
154200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung#endif
155200f040af3e4fe9e178cb63c90860d58d90ef665Douglas LeungMterpCommonFallback:
156200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    move    v0, zero                    # signal retry with reference interpreter.
157200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    b       MterpDone
158200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung/*
159200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung * We pushed some registers on the stack in ExecuteMterpImpl, then saved
160200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung * SP and LR.  Here we restore SP, restore the registers, and then restore
161200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung * LR to PC.
162200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung *
163200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung * On entry:
164200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung *  uint32_t* rFP  (should still be live, pointer to base of vregs)
165200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung */
166200f040af3e4fe9e178cb63c90860d58d90ef665Douglas LeungMterpExceptionReturn:
167200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    li      v0, 1                       # signal return to caller.
168200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    b       MterpDone
169200f040af3e4fe9e178cb63c90860d58d90ef665Douglas LeungMterpReturn:
170200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    lw      a2, OFF_FP_RESULT_REGISTER(rFP)
171200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    sw      v0, 0(a2)
172200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    sw      v1, 4(a2)
173200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    li      v0, 1                       # signal return to caller.
174200f040af3e4fe9e178cb63c90860d58d90ef665Douglas LeungMterpDone:
175200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung/* Restore from the stack and return. Frame size = STACK_SIZE */
176200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    STACK_LOAD_FULL()
177200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    jalr    zero, ra
178200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung
179200f040af3e4fe9e178cb63c90860d58d90ef665Douglas Leung    .end ExecuteMterpImpl
180